9oHigh / usKet.TID

Who am I? Let's get to know me by defining the things around us.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Today I Define ( TID ) ๐Ÿง

โœจ์ถœ์‹œ์™„๋ฃŒโœจ

์ฃผ์š” ๊ธฐ์ˆ  ์Šคํƒ

Realm AutoLayout Snapkit Alamofire SwiftyJSON MVC Github Action

โœ” ํ•™์Šต ๋ฐ ์ ์šฉ ๐Ÿƒ๐Ÿปโ€โ™‚๏ธ

1. AutoLayout

  • ์•ฝ 1์ฃผ์ผ ~ 2์ฃผ์ผ ๋™์•ˆ ๊พธ์ค€ํžˆ ๋ ˆ์ด์•„์›ƒ์„ ์กฐ์ •ํ•ด๋ดค์Šต๋‹ˆ๋‹ค. ์ƒ์ˆ˜๊ฐ’์ด ์•„๋‹Œ ๋น„์œจ์„ ๊ธฐ์ค€์œผ๋กœ ์กฐ์ •ํ•˜๋Š” ๊ฒƒ์ด ์‹œ๊ฐ์ ์ธ ์ธก๋ฉด, ๊ฐœ๋ฐœ ์†๋„ ์ธก๋ฉด์—์„œ ๋” ํšจ์œจ์ด ์ข‹์•˜๊ณ  ํ›„๋ฐ˜๋ถ€ ์ž‘์—…์—์„œ๋Š” ๋Œ€๋ถ€๋ถ„ ๋น„์œจ์„ ์ด์šฉํ•ด ๋ ˆ์ด์•„์›ƒ์„ ๋งŒ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค.
๋ ˆ์ด์•„์›ƒ ํŽผ์ณ๋ณด๊ธฐ


แ„‰แ…ณแ„แ…ณแ„…แ…ตแ†ซแ„‰แ…ฃแ†บ 2022-02-14 แ„‹แ…ฉแ„Œแ…ฅแ†ซ 4 07 40

2. Realm

  • ์œ ์ €๊ฐ€ ์ €์žฅํ•œ ๋‹จ์–ด๋ฅผ ๊ธฐ๋กํ•˜๊ธฐ ์œ„ํ•ด Realm์„ ์„ ํƒํ–ˆ์Šต๋‹ˆ๋‹ค.

  • ๊ฐœ๋ฐœ์ด์Šˆ: ๊ธฐ์กด์˜ ์Šคํ‚ค๋งˆ์—์„œ ๋‚ ์งœ ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•  ์‹œ์— ์ž„์‹œ๋กœ ๋„ฃ์–ด๋’€๋˜ Date()๊ฐ’์„ ์ƒˆ๋กœ์šด Object๋กœ ๋ณ€ํ™˜ํ•ด์•ผํ–ˆ์Šต๋‹ˆ๋‹ค. Realm์˜ ์Šคํ‚ค๋งˆ๋ฅผ ๋ณ€๊ฒฝํ•ด์•ผ ๋œ๋‹ค๋Š” ๊ฒƒ ์ฆ‰, ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜์„ ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ์•˜๊ณ  ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ ์šฉํ•จ์œผ๋กœ์จ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

    //Realm migration
    let config = Realm.Configuration(
        schemaVersion: 2,
        migrationBlock: { migration,oldSchemaVersion in
            if (oldSchemaVersion < 2){
                migration.enumerateObjects(ofType: DefineWordModel.className()) { oldObject, newObject in
                    //๊ธฐ์กด์˜ ๋‚ ์งœ๋“ค์„ ๋ณ€ํ™˜ํ•˜๊ณ  storedDate์— ๊ฐ’์„ ๋‚จ๊ธด๋‹ค.
                    let format = DateFormatter()
                    format.dateFormat = "yyyy๋…„ MM์›” dd์ผ"
                    let value = format.string(from: oldObject?["date"] as! Date)
    
                    newObject?["storedDate"] = value
                }
            }
    
        }
    )

3. Alamofire + SwiftyJson

  • API ํ†ต์‹ ์„ ์œ„ํ•ด Alamofire๋ฅผ, ๋ฐ›์•„์˜จ Json ํ˜•ํƒœ์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด SwiftyJSON์„ ํ•™์Šต ๋ฐ ์ ์šฉํ•˜์—ฌ ๋žœ๋ค์œผ๋กœ ๋‚˜์˜จ ๋‹จ์–ด์˜ ์ •์˜๋ฅผ ๋ณด์—ฌ์ค„ ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

4. Network Status

  • ์ถ”์ฒœ ๋‹จ์–ด ๊ธฐ๋Šฅ์„ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด ์šฐ๋ฆฌ๋ง์ƒ˜API๋ฅผ ์ด์šฉํ–ˆ์Šต๋‹ˆ๋‹ค.

  • ์ดˆ๊ธฐ, ์œ ์ €์˜ ๋„คํŠธ์›Œํฌ ์ƒํƒœ๋ฅผ ๊ณ ๋ คํ•˜์ง€ ์•Š๊ณ  ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ–ˆ๊ณ  ์ด๋ฅผ ๋ฐœ๊ฒฌํ•˜๊ณ  ์›ํ•˜๋Š” ViewController์— ์ง„์ž…์‹œ Network ์ƒํƒœ๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“ค์–ด ์‚ฌ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค.

     import Network
    //๋„คํŠธ์›Œํฌ ์ƒํƒœ ๋ชจ๋‹ˆํ„ฐ
    func monitorNetwork(){
    
        let monitor = NWPathMonitor()
    
        monitor.pathUpdateHandler = {
            path in
            if path.status == .satisfied {
                DispatchQueue.main.async {
                    return
                }
            } else {
                DispatchQueue.main.async {
    
                    self.showAlert(title: "๋„คํŠธ์›Œํฌ์— ์—ฐ๊ฒฐ๋˜์–ด ์žˆ์ง€ ์•Š์•„์š”.\n์„ค์ •ํ™”๋ฉด์œผ๋กœ ์ด๋™ํ•ฉ๋‹ˆ๋‹ค ๐Ÿฅฒ",connection: true)
                }
            }
        }
        let queue = DispatchQueue(label: "Network")
        monitor.start(queue: queue)
    }

5. ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ถœ์‹œ ๊ณผ์ •

  • ์„œ๋น„์Šค๋ฅผ ๊ฐœ๋ฐœํ•˜๊ณ  ๋ฐฐํฌํ•˜๋Š” ์ผ๋ จ์˜ ๊ณผ์ •์„ ๊ฒฝํ—˜ํ•  ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.
  • ์—…๋ฐ์ดํŠธ๋ฅผ ๊พธ์ค€ํžˆ ์ง„ํ–‰ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ( ๊ฐ€์žฅ ์ตœ๊ทผ ์—…๋ฐ์ดํŠธ : 2022.3.14 )

6. CI / CD ํ•™์Šต ๋ฐ ์ ์šฉ

ํ•™์Šต ๋‚ด์šฉ ์ •๋ฆฌ
  • CI / CD Github Action
    • Github Action์ด๋ž€

      • Pull Request, Push ๋“ฑ์˜ ์ด๋ฒคํŠธ ๋ฐœ์ƒ์— ๋”ฐ๋ผ ์ž๋™ํ™”๋œ ์ž‘์—…์„ ์ง„ํ–‰ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๋Š” ๊ธฐ๋Šฅ
      • CI / CD
        • ๋กœ์ปฌ ๋ ˆํฌ์ง€ํ† ๋ฆฌ์—์„œ ์›๊ฒฉ ๋ ˆํฌ์ง€ํ† ๋ฆฌ๋กœ ํ‘ธ์‰ฌํ•˜๊ณ  ๋‚œ ํ›„, Github Actions์—์„œ๋Š” ์ด๋ฒคํŠธ ๋ฐœ์ƒ์— ๋”ฐ๋ผ ์ž๋™์œผ๋กœ ๋นŒ๋“œ ๋ฐ ๋ฐฐํฌํ•˜๋Š” ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์‹คํ–‰์‹œ์ผœ์ฃผ๋Š” ๊ฒƒ
      • Testing
        • Pull Request๋ฅผ ๋ณด๋‚ด๋ฉด ์ž๋™์œผ๋กœ ํ…Œ์ŠคํŠธ๋ฅผ ์ง„ํ–‰ํ•˜๋Š” ๊ฒƒ ๋˜ํ•œ ๊ตฌํ˜„ ๊ฐ€๋Šฅํ•˜๊ณ  ์ž๋™์œผ๋กœ Pull Request๋ฅผ open ๋ฐ closeํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋จ
      • Cron Job
        • ํŠน์ •ํ•œ ์‹œ๊ฐ„๋Œ€์— ์Šคํฌ๋ฆฝํŠธ๋ฅผ ๋ฐ˜๋ณต ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ์Œ
    • Github Action์˜ ๊ตฌ์„ฑ์š”์†Œ

      • Workflow

        • ๋ ˆํฌ์— ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ๋Š” ์ž๋™ํ™” ์ปค๋งจ๋“œ์˜ ์ง‘ํ•ฉ์œผ๋กœ ํ•˜๋‚˜ ์ด์ƒ์˜ Job์œผ๋กœ ๊ตฌ์„ฑ๋˜์–ด ์žˆ์œผ๋ฉฐ Push๋‚˜ PR๊ณผ ๊ฐ™์€ ์ด๋ฒคํŠธ์— ์˜ํ•ด ์‹คํ–‰๋  ์ˆ˜๋„ ์žˆ์œผ๋ฉฐ ํŠน์ • ์‹œ๊ฐ„๋Œ€์— ์‹คํ–‰๋  ์ˆ˜๋„ ์žˆ์Œ

          Untitled

      • Event

        • Workflow๋ฅผ ์‹คํ–‰์‹œํ‚ค๋Š” ํŠน์ • ํ–‰๋™ ( Push, Pull Request, Commit ๋“ฑ )์„ ์˜๋ฏธ ํ•จ
      • Job

        • Job์ด๋ž€ ๋™์ผํ•œ Runner์—์„œ ์ง„ํ–‰๋˜๋Š” Step์˜ ์ง‘ํ•ฉ
        • ํ•˜๋‚˜์˜ workflow ๋‚ด์˜ ์—ฌ๋Ÿฌ Job์€ ๋…๋ฆฝ์ ์œผ๋กœ ์‹คํ–‰๋˜๋‚˜ ํ•„์š”์— ๋”ฐ๋ผ ์˜์กด ๊ด€๊ณ„๋ฅผ ์„ค์ •ํ•˜์—ฌ ์ˆœ์„œ๋ฅผ ์ง€์ •ํ•  ์ˆ˜ ์žˆ์Œ
          • ๊ฐ€๋ น Test ์ž‘์—…๊ณผ Build ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋Š” Job๋“ค์ด ํ•˜๋‚˜์˜ workflow์— ์กด์žฌํ•œ๋‹ค๋ฉด Build ์ดํ›„์— Test๊ฐ€ ์ง„ํ–‰๋˜์–ด์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— Build Job์ด ๋งˆ๋ฌด๋ฆฌ ๋œ ํ›„ Test Job์„ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋„๋ก ์ง€์ •๊ฐ€๋Šฅ ( Build ์‹คํŒจ์‹œ Test๋Š” ์‹คํ–‰ํ•˜์ง€ ์•Š์Œ )
      • Step

        • ์ปค๋งจ๋“œ๋ฅผ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋Š” ๊ฐ๊ฐ์˜ Task๋ฅผ ์˜๋ฏธํ•˜๊ณ , Shell ์ปค๋งจ๋“œ๊ฐ€ ๋  ์ˆ˜๋„ ์žˆ๊ณ , ํ•˜๋‚˜์˜ Action์ด ๋  ์ˆ˜๋„ ์žˆ์Œ
        • ํ•˜๋‚˜์˜ Job ๋‚ด์—์„œ ๊ฐ๊ฐ์˜ Step์€ ๋‹ค์–‘ํ•œ Task๋กœ ์ธํ•ด ์ƒ์„ฑ๋œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ณต์œ ํ•  ์ˆ˜ ์žˆ์Œ
      • Action

        • Job์„ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด Step์„ ๊ฒฐํ•ฉํ•œ ์ปค๋งจ๋“œ๋กœ ์žฌ์‚ฌ์šฉ์ด ๊ฐ€๋Šฅํ•œ Workflow์˜ ๊ฐ€์žฅ ์ž‘์€ ๋‹จ์œ„
        • ์ง์ ‘ ๋งŒ๋“ค๊ฑฐ๋‚˜ Github Community์— ์˜ํ•ด ์ƒ์„ฑ๋œ Action์„ ๋ถˆ๋Ÿฌ์™€ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Œ
      • Runner

        • Runner๋ž€ Github Actions Workflow ๋‚ด์— ์žˆ๋Š” Job์„ ์‹คํ–‰์‹œํ‚ค๊ธฐ ์œ„ํ•œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜
        • Runner Application์€ Github์—์„œ ํ˜ธ์ŠคํŒ…ํ•˜๋Š” ๊ฐ€์ƒํ™˜๊ฒฝ ํ˜น์€ ์ง์ ‘ ํ˜ธ์ŠคํŒ…ํ•˜๋Š” ๊ฐ€์ƒ ํ™˜๊ฒฝ์—์„œ ์‹คํ–‰ ๊ฐ€๋Šฅํ•˜๋ฉฐ Github์—์„œ ํ˜ธ์ŠคํŒ…ํ•˜๋Š” ๊ฐ€์ƒ ์ธ์Šคํ„ด์Šค์˜ ๊ฒฝ์šฐ ๋ฉ”๋ชจ๋ฆฌ ๋ฐ ์šฉ๋Ÿ‰ ์ œํ•œ์ด ์กด์žฌ
    • Workflow ์ƒ์„ฑ ๋ฐ ํŒŒ์ผ ์„ค๋ช…

      • .github/workflows ๋””๋ ‰ํ† ๋ฆฌ ๋‚ด์— .yml ํŒŒ์ผ์„ ์ƒ์„ฑํ•ด๋„ ๋˜์ง€๋งŒ, Repository์˜ Actions ํƒญ์—์„œ ์ž๋™์œผ๋กœ template๋ฅผ ๋งŒ๋“ค์–ด์ฃผ๋Š” ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Œ

      • Github์—์„œ ์ œ๊ณตํ•˜๋Š” ๊ฐ€์žฅ ๊ธฐ๋ณธ์ ์ธ Template๋Š” set up a workflow yourself๋ฅผ ํด๋ฆญ

        แ„‰แ…ณแ„แ…ณแ„…แ…ตแ†ซแ„‰แ…ฃแ†บ 2022-05-20 แ„‹แ…ฉแ„’แ…ฎ 9 56 20

      • ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์–‘์‹์˜ .yml ํŒŒ์ผ์ด ์ƒ์„ฑ๋จ

        แ„‰แ…ณแ„แ…ณแ„…แ…ตแ†ซแ„‰แ…ฃแ†บ 2022-05-20 แ„‹แ…ฉแ„’แ…ฎ 9 58 50

      • ์„ค๋ช…

        # Actions ํƒญ์— ํ‘œ์‹œ๋  Workflow ์ด๋ฆ„
        name: CI
        
        # Workflow๋ฅผ ์‹คํ–‰์‹œํ‚ค๊ธฐ ์œ„ํ•œ Event ๋ชฉ๋ก
        on: # ํŠธ๋ฆฌ๊ฑฐ
          # ํ•˜๋‹จ ์ฝ”๋“œ์— ๋”ฐ๋ผ develop ๋ธŒ๋žœ์น˜์— Push ๋˜๋Š” Pull Request ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•œ ๊ฒฝ์šฐ์— Workflow๊ฐ€ ์‹คํ–‰
          push:
            branches: [main]
          # ํŠน์ •ํ•œ Branch์— ํ‘ธ์‰ฌ๋˜์—ˆ์„ ๋•Œ ์‚ฌ์šฉํ•˜๋ ค๋ฉด ๊ฐ€๋ น feature/*๋กœ ์ž‘์„ฑํ•˜๋ฉด ๋จ
          pull_request:
            branches: [main]
        
          # ํ•ด๋‹น ์˜ต์…˜์„ ํ†ตํ•ด Actions ํƒญ์—์„œ Workflow๋ฅผ ์‹คํ–‰
          workflow_dispatch:
        
        # Workflow์˜ ํ•˜๋‚˜ ์ด์ƒ์˜ Job 
        jobs:
          # Job ์ด๋ฆ„์œผ๋กœ, build๋ผ๋Š” ์ด๋ฆ„์œผ๋กœ Job์ด ํ‘œ์‹œ
          build:
            # Runner๊ฐ€ ์‹คํ–‰๋˜๋Š” ํ™˜๊ฒฝ์„ ์ •์˜
            runs-on: macos-latest
        
            # build Job ๋‚ด์˜ step ๋ชฉ๋ก
            steps:
              # uses ํ‚ค์›Œ๋“œ๋ฅผ ํ†ตํ•ด Action์„ ๋ถˆ๋Ÿฌ์˜ด
              # ์—ฌ๊ธฐ์—์„œ๋Š” ํ•ด๋‹น ๋ ˆํฌ์ง€ํ† ๋ฆฌ๋กœ check-out ๋ฐ ๋ ˆํฌ์ง€ํ† ๋ฆฌ์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋Š” Action์„ ๋ถˆ๋Ÿฌ์˜ด.
              - uses: actions/checkout@v2
              # ์‹คํ–‰๋˜๋Š” ์ปค๋งจ๋“œ์— ๋Œ€ํ•œ ์„ค๋ช…์œผ๋กœ, Workflow์— ํ‘œ์‹œ
              - name: Build
                run: echo Hello, world!
        
              # ํ•˜๋‚˜์˜ ์ปค๋งจ๋“œ๊ฐ€ ์•„๋‹Œ ์—ฌ๋Ÿฌ ์ปค๋งจ๋“œ๋„ ์‹คํ–‰ ๊ฐ€๋Šฅ
              - name: Run tests
                run: |
                  xcodebuild test -project "$XC_PROJECT" -scheme "$XC_SCHEME" -destination 'platform=iOS Simulator,name=iPhone 13'
      • Start Commit ํ›„ Action ํƒญ์„ ํ™•์ธํ•ด๋ณด๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ •์ƒ์ ์œผ๋กœ ์ž‘๋™ํ•œ ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Œ. แ„‰แ…ณแ„แ…ณแ„…แ…ตแ†ซแ„‰แ…ฃแ†บ 2022-05-23 แ„‹แ…ฉแ„’แ…ฎ 10 41 42

Github Action ๋ฐฉ๋ฒ• ๋ฐ ์ ์šฉ
  • ์ฐธ๊ณ : naljin๋‹˜์˜ ๋ธ”๋กœ๊ทธ

  • ์ ์šฉ๋ฐฉ๋ฒ•

    name: TID Automation release
    
    on:
      push:
        branches: [ main ]
      pull_request:
        branches: [ main ]
    
    jobs:
      build:
      
        runs-on: macos-latest
        env: 
    			   # ๊ฐ€์ƒํ™˜๊ฒฝ
    		   	# Xcode ๋ฒ„์ „ ๋ฐ ํ”„๋กœ์ ํŠธ์™€ ์Šคํ‚ค๋งˆ ์„ค์ • + ์‚ฌ์šฉํ•  ํ‚ค์ฒด์ธ ์„ค์ • ( ์Šคํฌ๋ฆฝํŠธ์—์„œ ๋งŒ๋“ค์–ด์„œ ๋„ฃ์„ ๋ณ€์ˆ˜ )
          XC_VERSION: ${{ '13.1' }}
          XC_PROJECT: ${{ 'usket_TID.xcodeproj' }}
          XC_SCHEME: ${{ 'usket_TID' }}
          KEYCHAIN: ${{ 'usket.keychain' }}
          # ๋ฃจํŠธ
          PROJECT_ROOT_PATH: ${{ 'usket_TID' }}
           
          ENCRYPTED_CERTS_FILE_PATH: ${{ '.github/secrets/GithubActionKey.p12.gpg' }}
    			   # ์–ด๋””์— ๋ณตํ˜ธํ™” ํ•  ๊ฒƒ์ธ์ง€ ๋ช…์‹œ
          DECRYPTED_CERTS_FILE_PATH: ${{ '.github/secrets/GithubActionKey.p12' }}
    
          ENCRYPTED_PROVISION_FILE_PATH: ${{ '.github/secrets/GithubAction.mobileprovision.gpg' }}
    		   	# ์–ด๋””์— ๋ณตํ˜ธํ™” ํ•  ๊ฒƒ์ธ์ง€ ๋ช…์‹œ
          DECRYPTED_PROVISION_FILE_PATH: ${{ '.github/secrets/GithubAction.mobileprovision' }} 
    			
    			   # ๊ธฐ์กด์— secrets๋ฅผ ๊ฐ€์ง€๊ณ ์™€์„œ ์ ์šฉ
          CERTS_EXPORT_PWD: ${{ secrets.CERTS_EXPORT_PWD }}
          CERTS_ENCRYPTION_PWD: ${{ secrets.CERTS_ENCRYPTO_PWD }}
          PROFILES_ENCRYPTO_PWD: ${{ secrets.PROFILES_ENCRYPTO_PWD }}
    			
    			   # ์•„์นด์ด๋ธŒ path ๋ฐ ์•ฑ์Šคํ† ์–ด์— ์˜ฌ๋ฆด artifacts path ์„ค์ • 
          XC_ARCHIVE_PATH: ${{ 'usket_TID.xcarchive' }}
          XC_EXPORT_PATH: ${{ './artifacts' }}
          
        steps:
          - name: Select Xcode Version
            run: "sudo xcode-select -s /Applications/Xcode_$XC_VERSION.app"
        
          - uses: actions/checkout@v3
    
          - name: Build
            run: echo Hello, world!
    			
    			   # ์œ„์—์„œ ๋งŒ๋“ค์–ด๋‘” ํ‚ค์ฒด์ธ ์ ์šฉ
          - name: Configure Keychain 
            run: | 
              security create-keychain -p "" "$KEYCHAIN" 
              security list-keychains -s "$KEYCHAIN" 
              security default-keychain -s "$KEYCHAIN" 
              security unlock-keychain -p "" "$KEYCHAIN"
              
    			   # Code Signing ์‹คํ–‰
          - name : Configure Code Signing
            run: | 
              gpg -d -o "$DECRYPTED_CERTS_FILE_PATH" --pinentry-mode=loopback --passphrase "$CERTS_ENCRYPTION_PWD" "$ENCRYPTED_CERTS_FILE_PATH"
              gpg -d -o "$DECRYPTED_PROVISION_FILE_PATH" --pinentry-mode=loopback --passphrase "$PROFILES_ENCRYPTO_PWD" "$ENCRYPTED_PROVISION_FILE_PATH"
              security import "$DECRYPTED_CERTS_FILE_PATH" -k "$KEYCHAIN" -P "$CERTS_EXPORT_PWD" -A
              security set-key-partition-list -S apple-tool:,apple: -s -k "" "$KEYCHAIN"
              mkdir -p "$HOME/Library/MobileDevice/Provisioning Profiles"
              echo `ls .github/secrets/*.mobileprovision`
              # ํ”„๋กœํŒŒ์ผ๋“ค์„ renameํ•˜๊ณ  ์ƒˆ๋กœ๋งŒ๋“  ๋””๋ ‰ํ† ๋ฆฌ์— ๋ณต์‚ฌ
              for PROVISION in `ls .github/secrets/*.mobileprovision`
                do
                  UUID=`/usr/libexec/PlistBuddy -c 'Print :UUID' /dev/stdin <<< $(security cms -D -i ./$PROVISION)`
                cp "./$PROVISION" "$HOME/Library/MobileDevice/Provisioning Profiles/$UUID.mobileprovision"
                done
    			   # ์•„์นด์ด๋ธŒ!
          - name: Archive
            working-directory: usket_TID
            run: | 
              mkdir artifacts
              xcodebuild archive -project "$XC_PROJECT" -scheme "$XC_SCHEME" -configuration release -archivePath "$XC_ARCHIVE_PATH"
    			   # App Store๋กœ ๋‚ด๋ณด๋‚ด๊ธฐ
          - name: Export for App Store
            run: | 
              xcodebuild -exportArchive -archivePath "$XC_ARCHIVE_PATH" -exportOptionsPlist ExportOptions.plist -exportPath "$XC_EXPORT_PATH"
    
    			   # ์—…๋กœ๋“œํ•˜๋ฉด ๋!
          - name: Upload Artifact
            uses: actions/upload-artifact@v3
            with:
              name: Artifacts
              path: ./artifacts
    
  • Artifact๊ฐ€ ์•„๋‹Œ TestFlight๋กœ ์ ์šฉ๋ฐฉ๋ฒ•

    • ๊ฒฝ๋กœ๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†๋‹ค๋Š” ์˜ค๋ฅ˜ ์˜ค๋ฅ˜

      • apple-actions/upload-testflight-build@v1๋ฅผ ์ด์šฉํ–ˆ์„ ๊ฒฝ์šฐ ๋ฐœ์ƒํ•จ.
      • ๋””๋ ‰ํ† ๋ฆฌ์™€ ํŒŒ์ผ์„ ์ƒ์„ฑํ•˜๋Š” ๋ฐฉ๋ฒ•์œผ๋กœ ๋ณ€๊ฒฝ
    • ์›๋ž˜ ์ ์šฉ ํ–ˆ์–ด์•ผํ•˜๋Š” ๋ฐฉ๋ฒ•

       name: Upload app to TestFlight 
       uses: apple-actions/upload-testflight-build@v1
        with:
            app-path: 'usket_TID.ipa'
            issuer-id: ${{ secrets.APPSTORE_ISSUER_ID }}
            api-key-id: ${{ secrets.APPSTORE_API_KEY_ID }}
            api-private-key: ${{ secrets.APPSTORE_API_PRIVATE_KEY }}
      
    • ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋””๋ ‰ํ† ๋ฆฌ๋ฅผ ์ƒ์„ฑ ๋ฐ base64๋กœ ์ธ์ฝ”๋”ฉ๋œ Private Key๋ฅผ decodingํ•˜์—ฌ ๋„ฃ์€ ํ›„ ์‹คํ–‰ ๊ทธ๋ฆฌ๊ณ  ์„ฑ๊ณต!

      name: TID Automation release
      
      on:
        push:
          branches: [ main ]
        pull_request:
          branches: [ main ]
      
      jobs:
        build:
          runs-on: macos-latest
          env: # ๊ฐ€์ƒํ™˜๊ฒฝ
            XC_VERSION: ${{ '13.1' }}
            XC_PROJECT: ${{ 'usket_TID.xcodeproj' }}
            XC_SCHEME: ${{ 'usket_TID' }}
            XC_ARCHIVE_PATH: ${{ 'usket_TID.xcarchive' }}
            KEYCHAIN: ${{ 'usket.keychain' }}
            
            ENCRYPTED_CERTS_FILE_PATH: ${{ '.github/secrets/GithubActionKey.p12.gpg' }}
            DECRYPTED_CERTS_FILE_PATH: ${{ '.github/secrets/GithubActionKey.p12' }} # ์–ด๋””์— ๋ณตํ˜ธํ™” ํ•  ๊ฒƒ์ธ์ง€ ๋ช…์‹œ
      
            ENCRYPTED_PROVISION_FILE_PATH: ${{ '.github/secrets/GithubAction.mobileprovision.gpg' }}
            DECRYPTED_PROVISION_FILE_PATH: ${{ '.github/secrets/GithubAction.mobileprovision' }} # ์–ด๋””์— ๋ณตํ˜ธํ™” ํ•  ๊ฒƒ์ธ์ง€ ๋ช…์‹œ
      
            CERTS_EXPORT_PWD: ${{ secrets.CERTS_EXPORT_PWD }}
            CERTS_ENCRYPTION_PWD: ${{ secrets.CERTS_ENCRYPTO_PWD }}
            PROFILES_ENCRYPTO_PWD: ${{ secrets.PROFILES_ENCRYPTO_PWD }}
      
          steps:
            - name: Setting checkout
              uses: actions/checkout@v3
                
            - name: Select Xcode Version
              run: "sudo xcode-select -s /Applications/Xcode_$XC_VERSION.app"
      
            - name: Configure Keychain 
              run: | 
                security create-keychain -p "" "$KEYCHAIN" 
                security list-keychains -s "$KEYCHAIN" 
                security default-keychain -s "$KEYCHAIN" 
                security unlock-keychain -p "" "$KEYCHAIN"
                security set-keychain-settings -lut 1200
                security list-keychains
                
            - name : Configure Code Signing
              run: | 
                gpg -d -o "$DECRYPTED_CERTS_FILE_PATH" --pinentry-mode=loopback --passphrase "$CERTS_ENCRYPTION_PWD" "$ENCRYPTED_CERTS_FILE_PATH"
                gpg -d -o "$DECRYPTED_PROVISION_FILE_PATH" --pinentry-mode=loopback --passphrase "$PROFILES_ENCRYPTO_PWD" "$ENCRYPTED_PROVISION_FILE_PATH"
                security import "$DECRYPTED_CERTS_FILE_PATH" -k "$KEYCHAIN" -P "$CERTS_EXPORT_PWD" -A
                security set-key-partition-list -S apple-tool:,apple: -s -k "" "$KEYCHAIN"
                mkdir -p "$HOME/Library/MobileDevice/Provisioning Profiles"
                echo `ls .github/secrets/*.mobileprovision`
                # ํ”„๋กœํŒŒ์ผ๋“ค์„ renameํ•˜๊ณ  ์ƒˆ๋กœ๋งŒ๋“  ๋””๋ ‰ํ† ๋ฆฌ์— ๋ณต์‚ฌ
                for PROVISION in `ls .github/secrets/*.mobileprovision`
                  do
                    UUID=`/usr/libexec/PlistBuddy -c 'Print :UUID' /dev/stdin <<< $(security cms -D -i ./$PROVISION)`
                  cp "./$PROVISION" "$HOME/Library/MobileDevice/Provisioning Profiles/$UUID.mobileprovision"
                  done
            - name: Archive App
              working-directory: usket_TID
              run: | 
                xcodebuild clean archive -project "$XC_PROJECT" -scheme "$XC_SCHEME" -configuration release -archivePath "$XC_ARCHIVE_PATH" 
                
            - name: Export App
              working-directory: usket_TID
              run:  |
                xcodebuild -exportArchive -archivePath "$XC_ARCHIVE_PATH" -exportOptionsPlist ExportOptions.plist -exportPath . -allowProvisioningUpdates
                ls
      			# Make Private API Key Path
            - name: Install private API key P8
              env:
                APPSTORE_API_PRIVATE_KEY: ${{ secrets.APPSTORE_API_PRIVATE_KEY }}
                APPSTORE_API_KEY_ID: ${{ secrets.APPSTORE_API_KEY_ID }}
      				# Decode Private Key
              run: | 
                mkdir -p ~/private_keys
                echo -n "$APPSTORE_API_PRIVATE_KEY" | base64 --decode --output ~/private_keys/AuthKey_$APPSTORE_API_KEY_ID.p8
                ls
                
            - name: Upload app to TestFlight
              env:
                APPSTORE_API_KEY_ID: ${{ secrets.APPSTORE_API_KEY_ID }}
              run: |
                cd usket_TID
                ls
                xcrun altool --output-format xml --upload-app -f usket_TID.ipa -t ios --apiKey $APPSTORE_API_KEY_ID --apiIssuer ${{ secrets.APPSTORE_ISSUER_ID }}
      

7. ์—…๋ฐ์ดํŠธ

๋ฒ„์ „ ์—…๋ฐ์ดํŠธ ๋‚ด์—ญ ์„ค๋ช…
v2.12 Localize ๋‹ค๊ตญ์–ด ์ฒ˜๋ฆฌ(English)
[ ๋‹ค๊ตญ์–ด์ฒ˜๋ฆฌ ๋ฐฉ๋ฒ• ๊ธฐ๋ก ]
v2.11 ์•Œ๋ฆผ ์„ค์ •์‹œ ์•Œ๋ฆผ์ด ์˜ค์ง€ ์•Š๋˜ ์˜ค๋ฅ˜ TimeZone ์ด์Šˆ๋กœ ์ธํ•œ ์•Œ๋ฆผ์ด ์ด์ „ ๋‚ ์งœ์— ๋“ฑ๋ก๋˜๋˜ ์ด์Šˆ๋ฅผ ํ•ด๊ฒฐํ–ˆ์Šต๋‹ˆ๋‹ค.
v2.10 Calendar์—์„œ ๋‹จ์–ด ํด๋ฆญ ์ด๋ฒคํŠธ ์ˆ˜์ • ํŽ˜์ด์ง€๋กœ ์ด๋™๊ฐ€๋Šฅํ•˜๊ฒŒ ๋ณ€๊ฒฝํ–ˆ์Šต๋‹ˆ๋‹ค.
v2.08 CI / CD
[ CI/CD ๊ธฐ๋ก(1) - ๋ธ”๋กœ๊ทธ ]
[ CI/CD ๊ธฐ๋ก(2) - ๋ธ”๋กœ๊ทธ ]
[ CI/CD ๊ธฐ๋ก(3) - ๋ธ”๋กœ๊ทธ ]
Github Action์„ ์ด์šฉํ•ด ์ž๋™๋ฐฐํฌ ํ™˜๊ฒฝ์„ ๊ตฌ์ถ•ํ–ˆ์Šต๋‹ˆ๋‹ค.
v2.07 ์ถ”๊ฐ€๋ฒ„ํŠผ ํด๋ฆญ์‹œ Navigation Bar๋Š” Ove lay View์— ๊ฐ์‹ธ์ง€์ง€ ์•Š๋˜ ์˜ค๋ฅ˜
[ ํŠธ๋Ÿฌ๋ธ” ์ŠˆํŒ… ๊ธฐ๋ก - ๋ธ”๋กœ๊ทธ ]
ํ•ด๋‹น ์˜ค๋ฅ˜๋ฅผ ํ•ด๊ฒฐํ–ˆ์Šต๋‹ˆ๋‹ค.
v2.06 ๊ฐœ๋ฐœ, ์•ฑ, ๋ฆฌ๋ทฐ๋ฅผ ์œ„ํ•œ ๋ฒ„ํŠผ ์ƒ์„ฑ ๊ฐ๊ฐ ๊นƒํ—ˆ๋ธŒ ๋งํฌ, ์•ฑ๊ด€๋ จ ๋ฌธ์˜๋ฅผ ์œ„ํ•œ ์ด๋ฉ”์ผ ๋”ฅ๋งํฌ, ๋ฆฌ๋ทฐํŽ˜์ด์ง€๋กœ ์ด๋™๊ฐ€๋Šฅํ•œ ๋ฒ„ํŠผ์„ ์ถ”๊ฐ€
v2.05 ๋กœ๊ณ  ๋””์ž์ด๋„ˆ ์ธ์Šคํƒ€๊ทธ๋žจ ๋งํฌ ์š”์ฒญ์œผ๋กœ ๋งํฌ๋ฅผ ์ฒจ๋ถ€ ๋ฐ ์ถ”๊ฐ€ ๋ฒ„ํŠผ ํด๋ฆญ์‹œ ๋ฐฑ๊ทธ๋ผ์šด๋“œ ์ปฌ๋Ÿฌ
v2.04 Firebase Crashlytics Firebase Crashlytics ์ ์šฉ ๋ฐ ๊ธฐํƒ€ ์˜ค๋ฅ˜์ˆ˜์ •
v2.03 Local Notification
[ ํŠธ๋Ÿฌ๋ธ” ์ŠˆํŒ… ๊ธฐ๋ก - ๋ธ”๋กœ๊ทธ ]
๋กœ์ปฌ์•Œ๋ฆผ์‹œ ํ•œ ๋‹จ์–ด๋งŒ ๋ฐ˜๋ณตํ•ด์„œ ์˜ค๋Š” ์ด์Šˆ๋ฅผ ์ˆ˜์ •ํ–ˆ์Šต๋‹ˆ๋‹ค.
v2.02 ๋ ˆ์ด์•„์›ƒ ๋ฒ„๊ทธ ์ˆ˜์ • ๋‹จ์–ด์˜ ๋œป์„ ๋ณด์—ฌ์ฃผ๋Š” TableView์—์„œ ๋ฐœ์ƒํ•œ ์˜ค๋ฅ˜๋ฅผ ํ•ด๊ฒฐํ–ˆ์Šต๋‹ˆ๋‹ค.
v2.01 ํ†ต๊ณ„ ๋ฒ„๊ทธ ์ˆ˜์ • ์›”์ด ๋ฐ”๋€Œ๊ฒŒ ๋  ๊ฒฝ์šฐ ๊ธฐ์กด์˜ ์ฝ”๋“œ์—์„œ nil ์ฒ˜๋ฆฌ๋กœ ์ธํ•œ ์˜ค๋ฅ˜๊ฐ€ ์กด์žฌ, ์ด๋ฅผ ํ•ด๊ฒฐํ–ˆ์Šต๋‹ˆ๋‹ค.
v2.0 ๋ ˆ์ด์•„์›ƒ ๋ฒ„๊ทธ ์ˆ˜์ •, ์ €์žฅ์‹œ ํ† ์ŠคํŠธ ์•Œ๋ฆผ ์ถ”๊ฐ€, ์ž‘์„ฑํŽ˜์ด์ง€ ์ง„์ž…์‹œ ์ œ์Šค์ฒ˜๋กœ ๋‚˜๊ฐ€๊ธฐ ์ถ”๊ฐ€, ์ˆ˜์ •์‹œ ๊ฐ์ •๊ณผ ์ •์˜ ๋ถ€๋ถ„๊นŒ์ง€ ๋ณด์ด๊ฒŒ ์ถ”๊ฐ€, ํ†ต๊ณ„์ˆ˜์น˜ ์ˆ˜์ •, ๋กœ์ปฌ ์•Œ๋ฆผ ์ œ๊ณต, ์บ˜๋ฆฐ๋” ์ œ๊ณต ์ถœ์‹œ ์ดํ›„ ๋ฐ›์€ ํ”ผ๋“œ๋ฐฑ ํ†ตํ•ด ์บ˜๋ฆฐ๋”์™€ ์•Œ๋ฆผ์„ ์ค‘์ ์œผ๋กœ ์—…๋ฐ์ดํŠธ๋ฅผ ์ง„ํ–‰ํ–ˆ์Šต๋‹ˆ๋‹ค.

โœ” ๋ฐฐ์›Œ์•ผํ•  & ๋ฐฐ์šฐ๊ณ  ์‹ถ์€ ๊ธฐ์ˆ  ๐Ÿƒ๐Ÿปโ€โ™‚

  • SnapKit

    • ๋ ˆ์ด์•„์›ƒ์— ๊ด€ํ•ด ๊ฒ€์ƒ‰์„ ํ•˜๋‹ค๋ณด๋ฉด SnapKit์— ๋Œ€ํ•œ ๋‹ต๋ณ€๋“ค์ด ๋งŽ์ด ๋ณด์˜€์Šต๋‹ˆ๋‹ค. ์ฝ”๋“œ๋ฅผ ์ด์šฉํ•˜์—ฌ ๋ ˆ์ด์•„์›ƒ์„ ์žก์„ ์ˆ˜ ์žˆ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ธ ๊ฒƒ์„ ์•Œ๊ฒŒ ๋˜์—ˆ๊ณ  ๊ฐ„๋‹จํ•œ ๋ทฐ๋“ค ๊ฐ™์€ ๊ฒฝ์šฐ์—๋Š” ์ฝ”๋“œ๋ฅผ ํ™œ์šฉํ•ด ๋งŒ๋“ ๋‹ค๋ฉด ๊ฐœ๋ฐœ์‹œ๊ฐ„ ์ธก๋ฉด์—์„œ ๋†’์€ ํ™œ์šฉ๋„๊ฐ€ ์žˆ๋‹ค๊ณ  ์ƒ๊ฐ์ด ๋“ค์—ˆ๊ณ  ๋‹ค์Œ ํ”„๋กœ์ ํŠธ์—๋Š” ์ด๋ฅผ ์ ๊ทน์ ์œผ๋กœ ํ™œ์šฉํ•ด ๋ณด๊ณ  ์‹ถ์–ด์กŒ์Šต๋‹ˆ๋‹ค.
  • MVVM

    • ๊ธฐ์กด์˜ MVC ๋””์ž์ธ ํŒจํ„ด์„ ํ™œ์šฉํ•˜์—ฌ ๊ฐœ๋ฐœ์„ ํ–ˆ์ง€๋งŒ ViewController์— UI + ๊ธฐ๋Šฅ์„ ๋ชจ๋‘ ๋„ฃ์–ด์•ผํ–ˆ๊ธฐ์— ๊ฐ€๋…์„ฑ์ด ๋–จ์–ด์ง„๋‹ค๊ณ  ์ƒ๊ฐ์ด ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค. ๊ฐ€๋…์„ฑ์„ ๋†’์ด๊ณ  ํšจ์œจ์ ์ธ ๊ด€๋ฆฌ๋ฅผ ์œ„ํ•ด MVVM ๋””์ž์ธ ํŒจํ„ด์„ ํ•™์Šตํ•ด์•ผ ๊ฒ ๋‹ค๊ณ  ๋‹ค์งํ–ˆ์Šต๋‹ˆ๋‹ค.

About

Who am I? Let's get to know me by defining the things around us.


Languages

Language:Swift 100.0%