<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>Memory of Dreaming</title>
    <link>https://memohg.tistory.com/</link>
    <description>개발 일상과 내용 정리를 위해 개설된 블로그입니다</description>
    <language>ko</language>
    <pubDate>Sun, 23 Aug 2026 08:52:29 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>HyeonGyu IM</managingEditor>
    <image>
      <title>Memory of Dreaming</title>
      <url>https://tistory1.daumcdn.net/tistory/4011276/attach/e2d1939d93b34d1aa9a611d9ca484b79</url>
      <link>https://memohg.tistory.com</link>
    </image>
    <item>
      <title>Swift Package Manager 생성 방법</title>
      <link>https://memohg.tistory.com/147</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;1_t03UYVwsi1ufOT9Uy1E9JQ@2x.png&quot; data-origin-width=&quot;1200&quot; data-origin-height=&quot;408&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bvoAd1/btszy5HkeDg/EWt86keY4EWa7r98o005DK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bvoAd1/btszy5HkeDg/EWt86keY4EWa7r98o005DK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bvoAd1/btszy5HkeDg/EWt86keY4EWa7r98o005DK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbvoAd1%2Fbtszy5HkeDg%2FEWt86keY4EWa7r98o005DK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1200&quot; height=&quot;408&quot; data-filename=&quot;1_t03UYVwsi1ufOT9Uy1E9JQ@2x.png&quot; data-origin-width=&quot;1200&quot; data-origin-height=&quot;408&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;안녕하세요 오늘은 제가 자주쓰는 익스텐션을 저장하고 개인프로젝트에 활용하려고 SPM을 만들어 보게 되었습니다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 빠르게! 살펴보겠습니다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;### 1. Package 생성&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-10-31 오후 10.53.12.png&quot; data-origin-width=&quot;1458&quot; data-origin-height=&quot;686&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b97KiR/btszChtffT9/zYudMRkVqjOAzpv6Lj2gA0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b97KiR/btszChtffT9/zYudMRkVqjOAzpv6Lj2gA0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b97KiR/btszChtffT9/zYudMRkVqjOAzpv6Lj2gA0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb97KiR%2FbtszChtffT9%2FzYudMRkVqjOAzpv6Lj2gA0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1458&quot; height=&quot;686&quot; data-filename=&quot;스크린샷 2023-10-31 오후 10.53.12.png&quot; data-origin-width=&quot;1458&quot; data-origin-height=&quot;686&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 xcode를 실행하고&amp;nbsp;&lt;br /&gt;File -&amp;gt; New -&amp;gt; Package 를 선택해줍니다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;b&gt;###&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;2. Package 이름 정하기&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-10-31 오후 10.53.35.png&quot; data-origin-width=&quot;1478&quot; data-origin-height=&quot;1068&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bELuvu/btszCtttzsC/lWGrdnSskkIWpgVBHrjINK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bELuvu/btszCtttzsC/lWGrdnSskkIWpgVBHrjINK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bELuvu/btszCtttzsC/lWGrdnSskkIWpgVBHrjINK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbELuvu%2FbtszCtttzsC%2FlWGrdnSskkIWpgVBHrjINK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1478&quot; height=&quot;1068&quot; data-filename=&quot;스크린샷 2023-10-31 오후 10.53.35.png&quot; data-origin-width=&quot;1478&quot; data-origin-height=&quot;1068&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 패키지 이름을 정해야하는데 이름은 다른 라이브러리와 겹치지 않게 미리 검색해보시고 정하시는걸 추천드립니다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;b&gt;###&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;3. 패키지 파일 정리 및 Package.swift 수정&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-10-31 오후 11.18.37.png&quot; data-origin-width=&quot;1878&quot; data-origin-height=&quot;986&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ZwYi9/btszCKBJNu2/DxXhiAkoNXPDFB1DcZNya0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ZwYi9/btszCKBJNu2/DxXhiAkoNXPDFB1DcZNya0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ZwYi9/btszCKBJNu2/DxXhiAkoNXPDFB1DcZNya0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FZwYi9%2FbtszCKBJNu2%2FDxXhiAkoNXPDFB1DcZNya0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1878&quot; height=&quot;986&quot; data-filename=&quot;스크린샷 2023-10-31 오후 11.18.37.png&quot; data-origin-width=&quot;1878&quot; data-origin-height=&quot;986&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저는 패키지 테스트코드는 작성할 생각이없어서 Test관련된 부분은 모두 정리했습니다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;b&gt;###&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;4. 정리된 Package.swift 사진&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-11-01 오후 9.00.42.png&quot; data-origin-width=&quot;1732&quot; data-origin-height=&quot;1252&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cpfBvm/btszCu6YCLy/wK1naqhX2S69mf4MtzRhnk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cpfBvm/btszCu6YCLy/wK1naqhX2S69mf4MtzRhnk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cpfBvm/btszCu6YCLy/wK1naqhX2S69mf4MtzRhnk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcpfBvm%2FbtszCu6YCLy%2FwK1naqhX2S69mf4MtzRhnk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;642&quot; height=&quot;464&quot; data-filename=&quot;스크린샷 2023-11-01 오후 9.00.42.png&quot; data-origin-width=&quot;1732&quot; data-origin-height=&quot;1252&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지원하는 플랫폼과 버전을 명시해 줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;폴더를 Foundation과 UIKit 두가지로 구분해서 추가해 두었습니다.(단순히 폴더만 구분해주면 분리됩니다)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게하면 UIKit, Foundation 둘중에 하나만 골라서 추가할수 있습니다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;b&gt;###&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;5. 깃허브에 업로드&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mrSUW/btszCnmwM5Y/VSKqBCcuBuCtleDK6A2Te1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mrSUW/btszCnmwM5Y/VSKqBCcuBuCtleDK6A2Te1/img.png&quot; data-is-animation=&quot;false&quot; data-origin-width=&quot;774&quot; data-origin-height=&quot;806&quot; data-filename=&quot;스크린샷 2023-11-01 오후 9.11.57.png&quot; width=&quot;338&quot; height=&quot;352&quot; style=&quot;width: 38.3061%; margin-right: 10px;&quot; data-widthpercent=&quot;38.76&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mrSUW/btszCnmwM5Y/VSKqBCcuBuCtleDK6A2Te1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmrSUW%2FbtszCnmwM5Y%2FVSKqBCcuBuCtleDK6A2Te1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;774&quot; height=&quot;806&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bkuwEZ/btszDZ6fWk1/zCmb4iWVHRF2ahUaBUpdv1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bkuwEZ/btszDZ6fWk1/zCmb4iWVHRF2ahUaBUpdv1/img.png&quot; data-is-animation=&quot;false&quot; data-origin-width=&quot;1912&quot; data-origin-height=&quot;1260&quot; data-filename=&quot;스크린샷 2023-11-01 오후 9.07.03.png&quot; data-widthpercent=&quot;61.24&quot; style=&quot;width: 60.5311%;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bkuwEZ/btszDZ6fWk1/zCmb4iWVHRF2ahUaBUpdv1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbkuwEZ%2FbtszDZ6fWk1%2FzCmb4iWVHRF2ahUaBUpdv1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1912&quot; height=&quot;1260&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;깃허브 로그인이 안되어있다면 토큰을 생성해서 연결해주시고 진행해야 합니다. 위와같이 나오고 Create를 누르면 깃허브에 레포가 생성됩니다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;b&gt;###&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;6. 커밋 메시지 작성 및 푸시&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-11-01 오후 9.08.56.png&quot; data-origin-width=&quot;922&quot; data-origin-height=&quot;304&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dx5NDw/btszCmHUsPY/6XQk2CHYlMFDh7gzlWoiD0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dx5NDw/btszCmHUsPY/6XQk2CHYlMFDh7gzlWoiD0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dx5NDw/btszCmHUsPY/6XQk2CHYlMFDh7gzlWoiD0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdx5NDw%2FbtszCmHUsPY%2F6XQk2CHYlMFDh7gzlWoiD0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;922&quot; height=&quot;304&quot; data-filename=&quot;스크린샷 2023-11-01 오후 9.08.56.png&quot; data-origin-width=&quot;922&quot; data-origin-height=&quot;304&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-11-01 오후 9.09.07.png&quot; data-origin-width=&quot;4182&quot; data-origin-height=&quot;984&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/zyvDd/btszy4hqDUp/Onp6lKCW50nLGnqHtjqGkk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/zyvDd/btszy4hqDUp/Onp6lKCW50nLGnqHtjqGkk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/zyvDd/btszy4hqDUp/Onp6lKCW50nLGnqHtjqGkk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FzyvDd%2Fbtszy4hqDUp%2FOnp6lKCW50nLGnqHtjqGkk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;4182&quot; height=&quot;984&quot; data-filename=&quot;스크린샷 2023-11-01 오후 9.09.07.png&quot; data-origin-width=&quot;4182&quot; data-origin-height=&quot;984&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-11-01 오후 9.09.41.png&quot; data-origin-width=&quot;4180&quot; data-origin-height=&quot;1004&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/yyaqG/btszAYgtHIW/ZfscD3WZbXLfJdtYrKrkKK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/yyaqG/btszAYgtHIW/ZfscD3WZbXLfJdtYrKrkKK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/yyaqG/btszAYgtHIW/ZfscD3WZbXLfJdtYrKrkKK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FyyaqG%2FbtszAYgtHIW%2FZfscD3WZbXLfJdtYrKrkKK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;4180&quot; height=&quot;1004&quot; data-filename=&quot;스크린샷 2023-11-01 오후 9.09.41.png&quot; data-origin-width=&quot;4180&quot; data-origin-height=&quot;1004&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;순서대로 탭에가셔서 Uncommitted Changes를 누르시고 다음사진에 오른쪽 위에있는 Stage All을 누르시고 Commit Message 작성후에 3번째 사진 오른쪽 위에있는 Push를 누르시면 작성한 코드가 모두 업로드 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;b&gt;###&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;7. 버전관리&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-11-01 오후 9.17.01.png&quot; data-origin-width=&quot;1236&quot; data-origin-height=&quot;257&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/l1xCs/btszzKwgAlf/95QGhLZfpx5S7pIKCqwghK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/l1xCs/btszzKwgAlf/95QGhLZfpx5S7pIKCqwghK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/l1xCs/btszzKwgAlf/95QGhLZfpx5S7pIKCqwghK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fl1xCs%2FbtszzKwgAlf%2F95QGhLZfpx5S7pIKCqwghK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1236&quot; height=&quot;257&quot; data-filename=&quot;스크린샷 2023-11-01 오후 9.17.01.png&quot; data-origin-width=&quot;1236&quot; data-origin-height=&quot;257&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SPM의 버전관리는 Tags로 이루어지기 때문에 업로드를 완료하시고 꼭 Tag를 등록해주셔야합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;b&gt;###&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;8. 실제 프로젝트 적용확인&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-11-01 오후 9.18.59.png&quot; data-origin-width=&quot;784&quot; data-origin-height=&quot;248&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/n1mY9/btszA1jYWkf/hQ0r8RfacJm2cFrTvuGlE1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/n1mY9/btszA1jYWkf/hQ0r8RfacJm2cFrTvuGlE1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/n1mY9/btszA1jYWkf/hQ0r8RfacJm2cFrTvuGlE1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fn1mY9%2FbtszA1jYWkf%2FhQ0r8RfacJm2cFrTvuGlE1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;670&quot; height=&quot;212&quot; data-filename=&quot;스크린샷 2023-11-01 오후 9.18.59.png&quot; data-origin-width=&quot;784&quot; data-origin-height=&quot;248&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-11-01 오후 9.19.23.png&quot; data-origin-width=&quot;920&quot; data-origin-height=&quot;1000&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bZbsNg/btszCEO408K/Z64fZVd3HpzYcPxqNwxIo0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bZbsNg/btszCEO408K/Z64fZVd3HpzYcPxqNwxIo0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bZbsNg/btszCEO408K/Z64fZVd3HpzYcPxqNwxIo0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbZbsNg%2FbtszCEO408K%2FZ64fZVd3HpzYcPxqNwxIo0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;566&quot; height=&quot;615&quot; data-filename=&quot;스크린샷 2023-11-01 오후 9.19.23.png&quot; data-origin-width=&quot;920&quot; data-origin-height=&quot;1000&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-11-01 오후 9.20.02.png&quot; data-origin-width=&quot;1344&quot; data-origin-height=&quot;630&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/YfLzV/btszDBq0RyM/UnJcHIqkZoky1ZTOjPkr60/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/YfLzV/btszDBq0RyM/UnJcHIqkZoky1ZTOjPkr60/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/YfLzV/btszDBq0RyM/UnJcHIqkZoky1ZTOjPkr60/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FYfLzV%2FbtszDBq0RyM%2FUnJcHIqkZoky1ZTOjPkr60%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;681&quot; height=&quot;319&quot; data-filename=&quot;스크린샷 2023-11-01 오후 9.20.02.png&quot; data-origin-width=&quot;1344&quot; data-origin-height=&quot;630&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;새로운 프로젝트를 생성하고 다음의 사진과같이 추가과정을 진행합니다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;주의하실점은 3번째 사진에서 패키지를 적용하실 타겟을 지정해주셔야합니다. 기본값은 None이기 때문에 꼭 선택해주셔야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;b&gt;###&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;9. 동작확인&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-11-01 오후 9.29.16.png&quot; data-origin-width=&quot;1560&quot; data-origin-height=&quot;706&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/JvtaI/btszzHTPNQS/JASL0GnszhKztrgSCmSYo0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/JvtaI/btszzHTPNQS/JASL0GnszhKztrgSCmSYo0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/JvtaI/btszzHTPNQS/JASL0GnszhKztrgSCmSYo0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FJvtaI%2FbtszzHTPNQS%2FJASL0GnszhKztrgSCmSYo0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1560&quot; height=&quot;706&quot; data-filename=&quot;스크린샷 2023-11-01 오후 9.29.16.png&quot; data-origin-width=&quot;1560&quot; data-origin-height=&quot;706&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;import 패키지 네임을 써주신후 코드가 잘 불러와지는지 확인하시면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약 코드가 잘 동작하지 않는다면 접근제한자를 &lt;b&gt;public&lt;/b&gt; 또는 &lt;b&gt;open&lt;/b&gt;으로 잘 설정하셨는지 확인해 보시길 바랍니다&lt;/p&gt;</description>
      <category>IOS/iOS</category>
      <author>HyeonGyu IM</author>
      <guid isPermaLink="true">https://memohg.tistory.com/147</guid>
      <comments>https://memohg.tistory.com/147#entry147comment</comments>
      <pubDate>Wed, 1 Nov 2023 21:35:06 +0900</pubDate>
    </item>
    <item>
      <title>WKWebView를 아라보자</title>
      <link>https://memohg.tistory.com/146</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;예전부터 WKWebView에 대해서는 관심을 가지고 있었는데, 잘(?) 다루는 방법에 대해서 자료가 좀 적기도하고 네이티브에서는 궂이? 잘쓰려고 하지않기에 등한시 했던 부분이 있습니다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 카카오같은 곳에서 세션을 발표할때 웹뷰의 비동기 동작이나 통신을 어떻게 하는지 꿀팁을 소개해 주셔서 능력이 닿는한 파해쳐 보려고 합니다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://tech.kakaopay.com/post/ifkakao2022-ios-webview/&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://tech.kakaopay.com/post/ifkakao2022-ios-webview/&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1698677812179&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[if kakao 2022] 카카오페이 iOS 웹뷰 소개, 그리고 세션에서 못다한 이야기 | 카카오페이 기술 블로그&quot; data-og-description=&quot;if(kakao)2022 카카오페이 iOS 웹뷰 소개 및 리팩토링 이야기 세션에서 못다한 이야기를 공유합니다.&quot; data-og-host=&quot;tech.kakaopay.com&quot; data-og-source-url=&quot;https://tech.kakaopay.com/post/ifkakao2022-ios-webview/&quot; data-og-url=&quot;https://tech.kakaopay.com/post/ifkakao2022-ios-webview/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/0fDk4/hyUkize67K/tGNiWAAzPqlFUMZ4WJdfhk/img.png?width=480&amp;amp;height=319&amp;amp;face=0_0_480_319,https://scrap.kakaocdn.net/dn/d51U73/hyUkhtxa6S/kvxqBXUr8e7L0ktCmpeuOK/img.png?width=480&amp;amp;height=319&amp;amp;face=0_0_480_319,https://scrap.kakaocdn.net/dn/WaZXi/hyUkb1aNv3/kjVT99hffV1KYQ2EOhk730/img.jpg?width=234&amp;amp;height=234&amp;amp;face=73_58_137_128&quot;&gt;&lt;a href=&quot;https://tech.kakaopay.com/post/ifkakao2022-ios-webview/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://tech.kakaopay.com/post/ifkakao2022-ios-webview/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/0fDk4/hyUkize67K/tGNiWAAzPqlFUMZ4WJdfhk/img.png?width=480&amp;amp;height=319&amp;amp;face=0_0_480_319,https://scrap.kakaocdn.net/dn/d51U73/hyUkhtxa6S/kvxqBXUr8e7L0ktCmpeuOK/img.png?width=480&amp;amp;height=319&amp;amp;face=0_0_480_319,https://scrap.kakaocdn.net/dn/WaZXi/hyUkb1aNv3/kjVT99hffV1KYQ2EOhk730/img.jpg?width=234&amp;amp;height=234&amp;amp;face=73_58_137_128');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[if kakao 2022] 카카오페이 iOS 웹뷰 소개, 그리고 세션에서 못다한 이야기 | 카카오페이 기술 블로그&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;if(kakao)2022 카카오페이 iOS 웹뷰 소개 및 리팩토링 이야기 세션에서 못다한 이야기를 공유합니다.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;tech.kakaopay.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span&gt;###&lt;/span&gt; Script&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;- &lt;/span&gt;Native에서 web에게 일방적으로 정보를 보낼 때 사용&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;- &lt;/span&gt;Event(라이프 사이클 등 ) 또는 Button Action과 같이 간단한 정보를 전송&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2023-02-19_%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB_1.14.56.png&quot; data-origin-width=&quot;895&quot; data-origin-height=&quot;142&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lpM3s/btszweJr1vY/9fllI3eKi2WtPjL5Fxsx9K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lpM3s/btszweJr1vY/9fllI3eKi2WtPjL5Fxsx9K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lpM3s/btszweJr1vY/9fllI3eKi2WtPjL5Fxsx9K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlpM3s%2FbtszweJr1vY%2F9fllI3eKi2WtPjL5Fxsx9K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;895&quot; height=&quot;142&quot; data-filename=&quot;%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2023-02-19_%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB_1.14.56.png&quot; data-origin-width=&quot;895&quot; data-origin-height=&quot;142&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span&gt;###&lt;/span&gt; JSAPI(JavaScript API)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;- &lt;/span&gt;Web에서 Native&lt;span&gt;&amp;nbsp; &lt;/span&gt;로직이 필요한 모든 경우에 사용&lt;br /&gt;&lt;span&gt;- &lt;/span&gt;Web에서 정보를 받은 후, Native의 결과 값 전달&lt;br /&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span&gt;- &lt;/span&gt;정보는 &lt;span&gt;*&lt;/span&gt;&lt;i&gt;postMessage() 로 전송하게 됩니다&lt;/i&gt;&lt;span&gt;*&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2023-03-05_%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE_10.34.24.png&quot; data-origin-width=&quot;1020&quot; data-origin-height=&quot;498&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/skGTq/btszw7i0TxO/kfOxTaVSRimHUO1K065SEK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/skGTq/btszw7i0TxO/kfOxTaVSRimHUO1K065SEK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/skGTq/btszw7i0TxO/kfOxTaVSRimHUO1K065SEK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FskGTq%2Fbtszw7i0TxO%2FkfOxTaVSRimHUO1K065SEK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;659&quot; height=&quot;322&quot; data-filename=&quot;%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2023-03-05_%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE_10.34.24.png&quot; data-origin-width=&quot;1020&quot; data-origin-height=&quot;498&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2023-02-19_%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB_1.16.55.png&quot; data-origin-width=&quot;844&quot; data-origin-height=&quot;449&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bckgyH/btszpAfVGRt/trfHT6HBH2t8bXXIgVKKG1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bckgyH/btszpAfVGRt/trfHT6HBH2t8bXXIgVKKG1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bckgyH/btszpAfVGRt/trfHT6HBH2t8bXXIgVKKG1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbckgyH%2FbtszpAfVGRt%2FtrfHT6HBH2t8bXXIgVKKG1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;701&quot; height=&quot;373&quot; data-filename=&quot;%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2023-02-19_%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB_1.16.55.png&quot; data-origin-width=&quot;844&quot; data-origin-height=&quot;449&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span&gt;- &lt;/span&gt;command, parameter를 통해 Web에서 Native에게 전달하고자하는 값을 전달 받습니다&lt;br /&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span&gt;- &lt;/span&gt;extra: id 값으로 동일한 commandd의 비동기 처리를 구분하고, 디버깅도 id에 따라온 값을 보고 처리할수 있습니다. 이 id는 JSapi별로 다른 id값을 갖습니다&lt;br /&gt;&lt;span&gt;- &lt;/span&gt;이 예시는 open이라는 commnad값을 받고 파라미터로 url을 받아 여는 함수입니다&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2023-02-19_%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB_1.22.16.png&quot; data-origin-width=&quot;1745&quot; data-origin-height=&quot;1016&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/zmF74/btsznB0t5XM/KgYdkMtmeMfSFC6Ll9S87K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/zmF74/btsznB0t5XM/KgYdkMtmeMfSFC6Ll9S87K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/zmF74/btsznB0t5XM/KgYdkMtmeMfSFC6Ll9S87K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FzmF74%2FbtsznB0t5XM%2FKgYdkMtmeMfSFC6Ll9S87K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;603&quot; height=&quot;351&quot; data-filename=&quot;%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2023-02-19_%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB_1.22.16.png&quot; data-origin-width=&quot;1745&quot; data-origin-height=&quot;1016&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span&gt;###&lt;/span&gt; Configuration&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;- &lt;/span&gt;Native처럼 사용자에게 이질감 없는 interaction, UI를 제공하기 위해 웹뷰를 구성할 때 사전에 약속된 값으로 UI핸들링&lt;br /&gt;&lt;span&gt;- &lt;/span&gt;타이밍상 Native에서 더 자연스러운 기능은 Native에서 구현하고 Configuration으로 구분&lt;br /&gt;&lt;span&gt;- &lt;/span&gt;웹뷰 UI 설정 값을 Configuration으로 받아 WebViewController객체 생성&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2023-02-19_%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB_1.25.34.png&quot; data-origin-width=&quot;1695&quot; data-origin-height=&quot;385&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Rf1eW/btszltBR0lA/otqdQByzVrkoKdVsKyikx0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Rf1eW/btszltBR0lA/otqdQByzVrkoKdVsKyikx0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Rf1eW/btszltBR0lA/otqdQByzVrkoKdVsKyikx0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FRf1eW%2FbtszltBR0lA%2FotqdQByzVrkoKdVsKyikx0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1695&quot; height=&quot;385&quot; data-filename=&quot;%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2023-02-19_%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB_1.25.34.png&quot; data-origin-width=&quot;1695&quot; data-origin-height=&quot;385&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span&gt;###&lt;/span&gt;Transparent&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2023-02-19_%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB_1.26.25.png&quot; data-origin-width=&quot;1823&quot; data-origin-height=&quot;895&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bUL1mz/btszwgf74pl/3kAJb60sHHZSAyjk3oKUH1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bUL1mz/btszwgf74pl/3kAJb60sHHZSAyjk3oKUH1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bUL1mz/btszwgf74pl/3kAJb60sHHZSAyjk3oKUH1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbUL1mz%2Fbtszwgf74pl%2F3kAJb60sHHZSAyjk3oKUH1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1823&quot; height=&quot;895&quot; data-filename=&quot;%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2023-02-19_%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB_1.26.25.png&quot; data-origin-width=&quot;1823&quot; data-origin-height=&quot;895&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;---&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span&gt;###&lt;/span&gt; 실제 서비스에서 호출되는 형태&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 웹뷰 컨트롤러 생성&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2023-02-19_%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB_1.34.24.png&quot; data-origin-width=&quot;1240&quot; data-origin-height=&quot;717&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/BUibc/btszwh7cpy3/f1stw8iqr4xcGpE8tUixfk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/BUibc/btszwh7cpy3/f1stw8iqr4xcGpE8tUixfk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/BUibc/btszwh7cpy3/f1stw8iqr4xcGpE8tUixfk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FBUibc%2Fbtszwh7cpy3%2Ff1stw8iqr4xcGpE8tUixfk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;652&quot; height=&quot;377&quot; data-filename=&quot;%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2023-02-19_%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB_1.34.24.png&quot; data-origin-width=&quot;1240&quot; data-origin-height=&quot;717&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 이벤트 처리&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2023-02-19_%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB_1.33.55.png&quot; data-origin-width=&quot;1111&quot; data-origin-height=&quot;721&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cuNOLc/btszvhGDrqf/0fXVQYOOz90qtnquZTb030/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cuNOLc/btszvhGDrqf/0fXVQYOOz90qtnquZTb030/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cuNOLc/btszvhGDrqf/0fXVQYOOz90qtnquZTb030/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcuNOLc%2FbtszvhGDrqf%2F0fXVQYOOz90qtnquZTb030%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;546&quot; height=&quot;354&quot; data-filename=&quot;%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2023-02-19_%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB_1.33.55.png&quot; data-origin-width=&quot;1111&quot; data-origin-height=&quot;721&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;- 이미 핸들되었는지 체크하고 이값이 `false` 일때 처리를 시작합니다&lt;br /&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;- 처리를 체크하는 함수는 아래와 같습니다&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2023-02-19_%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB_1.37.42.png&quot; data-origin-width=&quot;1680&quot; data-origin-height=&quot;733&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rUT2I/btszsAmmPJm/oOqQaTkmCSnYFOO0w6LXX1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rUT2I/btszsAmmPJm/oOqQaTkmCSnYFOO0w6LXX1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rUT2I/btszsAmmPJm/oOqQaTkmCSnYFOO0w6LXX1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FrUT2I%2FbtszsAmmPJm%2FoOqQaTkmCSnYFOO0w6LXX1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;670&quot; height=&quot;292&quot; data-filename=&quot;%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2023-02-19_%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB_1.37.42.png&quot; data-origin-width=&quot;1680&quot; data-origin-height=&quot;733&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;### 헤더세팅방법&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1698678298226&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;private var headers: [String: String] {

	let bundleVersion = Bundle.main.infoDictionary?[&quot;CFBundleShortVersionString&quot;] as? String ?? &quot;&quot;

	var header = [&quot;Content-Type&quot;: &quot;application/json&quot;]

	header[&quot;app-device-uuid&quot;] = UUID().uuidString

	header[&quot;app-device-os-version&quot;] = UIDevice.current.systemVersion

	header[&quot;app-device-device-manufacturer&quot;] = &quot;apple&quot;

	header[&quot;app-version&quot;] = bundleVersion

	return header

}

let url = Bundle.main.url(forResource: &quot;index&quot;, withExtension: &quot;html&quot;)!

var urlRequest = URLRequest(url: url)

headers.forEach { urlRequest.setValue($0.value, forHTTPHeaderField: $0.key) }

//&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; webView.loadFileURL(url, allowingReadAccessTo: url)

webview.load(urlRequest)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;참고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[[iOS] WKWebView 정리 Swift](&lt;a href=&quot;https://thoonk.tistory.com/87)&quot;&gt;https://thoonk.tistory.com/87)&lt;/a&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;[&lt;a href=&quot;https://github.com/Lision/WKWebViewJavascriptBridge](https://github.com/Lision/WKWebViewJavascriptBridge)&quot;&gt;https://github.com/Lision/WKWebViewJavascriptBridge](https://github.com/Lision/WKWebViewJavascriptBridge)&lt;/a&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;[&lt;a href=&quot;https://github.com/bernikovich/WebViewWarmUper](https://github.com/bernikovich/WebViewWarmUper)&quot;&gt;https://github.com/bernikovich/WebViewWarmUper](https://github.com/bernikovich/WebViewWarmUper)&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[[iOS - swift] 1. WKWebView 개념 (UIWebView, AJAX, XHR, 캐시, 쿠키)](&lt;a href=&quot;https://ios-development.tistory.com/700)&quot;&gt;https://ios-development.tistory.com/700)&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;/span&gt;[[iOS - swift] 2. WKWebView 사용 방법 (웹뷰, 쿠키, WKScriptMessageHandler, WKNavigationDelegate, WKUIDelegate)](&lt;a href=&quot;https://ios-development.tistory.com/701)&quot;&gt;https://ios-development.tistory.com/701)&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;/span&gt;[[iOS - swift] RxWebKit, WKWebView, messageHandler 사용 방법 웹뷰 통신(native &amp;lt;-&amp;gt; javascript), 콜백](&lt;a href=&quot;https://ios-development.tistory.com/942)&quot;&gt;https://ios-development.tistory.com/942)&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;/span&gt;[[iOS - swift] 2. WKWebView - Header 설정, Cookie 설정, access token 전달, deeplink 수신 방법](&lt;a href=&quot;https://ios-development.tistory.com/751)&quot;&gt;https://ios-development.tistory.com/751)&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;/span&gt;[iOS WKWebView Communication Using Javascript and Swift](&lt;a href=&quot;https://medium.com/john-lewis-software-engineering/ios-wkwebview-communication-using-javascript-and-swift-ee077e0127eb)&quot;&gt;https://medium.com/john-lewis-software-engineering/ios-wkwebview-communication-using-javascript-and-swift-ee077e0127eb)&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;/span&gt;[How does the iOS 14 API WKScriptMessageHandlerWithReply work for communicating with JavaScript from iOS?](&lt;a href=&quot;https://stackoverflow.com/questions/65270083/how-does-the-ios-14-api-wkscriptmessagehandlerwithreply-work-for-communicating-w)&quot;&gt;https://stackoverflow.com/questions/65270083/how-does-the-ios-14-api-wkscriptmessagehandlerwithreply-work-for-communicating-w)&lt;/a&gt;&lt;/p&gt;</description>
      <category>IOS/WKWebView</category>
      <author>HyeonGyu IM</author>
      <guid isPermaLink="true">https://memohg.tistory.com/146</guid>
      <comments>https://memohg.tistory.com/146#entry146comment</comments>
      <pubDate>Tue, 31 Oct 2023 00:14:45 +0900</pubDate>
    </item>
    <item>
      <title>Const, Final 언제 사용하는 걸까?</title>
      <link>https://memohg.tistory.com/145</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;플러터 UI 그리는걸 따라해보고 있자니 const를 써야할때와 안써야할때가 궁금해서 찾아봤다&lt;/p&gt;
&lt;h2 id=&quot;공통점&quot; style=&quot;background-color: #ffffff; color: #404040; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;공통점&lt;/h2&gt;
&lt;p style=&quot;background-color: #ffffff; color: #404040; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;한번 할당한 변수는 재할당이 불가능하다&lt;/p&gt;
&lt;h2 id=&quot;차이점&quot; style=&quot;background-color: #ffffff; color: #404040; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;차이점&lt;/h2&gt;
&lt;p style=&quot;background-color: #ffffff; color: #404040; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;전제로&lt;span&gt;&amp;nbsp;&lt;/span&gt;컴파일 타임과&lt;span&gt;&amp;nbsp;&lt;/span&gt;런타임의 차이를 이해할 필요가 있다&lt;/p&gt;
&lt;h3 id=&quot;final&quot; style=&quot;background-color: #ffffff; color: #404040; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;final(런타임에 정하고 변화 x)&lt;/h3&gt;
&lt;p style=&quot;background-color: #ffffff; color: #404040; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;동적으로 메모리에 할당이라고 말한다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #404040; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;즉&lt;span&gt;&amp;nbsp;&lt;/span&gt;컴파일 타임에는 변수할당을 하지 않고&lt;span&gt;&amp;nbsp;&lt;/span&gt;런타임시에 변수할당을 한다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #404040; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;덕분에&lt;span&gt;&amp;nbsp;&lt;/span&gt;컴파일 타임에서 확인할 수 없는 값들을 변수에 할당할 수 가 있게된다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #404040; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;컴파일 타임에서 확인할 수 없는 값(런타임시 확인가능한것)으로는&lt;span&gt;&amp;nbsp;&lt;/span&gt;DateTime.now()가 있다.&lt;/p&gt;
&lt;div style=&quot;background-color: #ffffff; color: #404040; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;aspectj&quot; style=&quot;background-color: #f8f8f8; color: #333333;&quot;&gt;&lt;code&gt;void main(){
    final d = DateTime.now();
}
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 id=&quot;const&quot; style=&quot;background-color: #ffffff; color: #404040; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;const( 컴파일 타임에 한번 정하고 변화 x )&lt;/h3&gt;
&lt;p style=&quot;background-color: #ffffff; color: #404040; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;컴파일 타임에 변수선언이 이루어진다. 덕분에 런타임시 특별히 할것 없이 메모리에 할당되어 있는 값을 이용할 수 있어 효율적이다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #404040; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;padding값과 같이 재사용을 많이 하는 케이스라면 const가 유용하다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #404040; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;아래와 같이&lt;span&gt;&amp;nbsp;&lt;/span&gt;런타임시에만 확인가능한 값을 const에 대입하면 const는&lt;span&gt;&amp;nbsp;&lt;/span&gt;컴파일 타임에 변수할당을 하므로 에러가 발생한다.&lt;/p&gt;
&lt;div style=&quot;background-color: #ffffff; color: #404040; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;cpp&quot; style=&quot;background-color: #f8f8f8; color: #333333;&quot;&gt;&lt;code&gt;void main(){
    const d = DateTime.now(); //error
}
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h4 id=&quot;전체에러&quot; style=&quot;background-color: #ffffff; color: #404040; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;전체에러&lt;/h4&gt;
&lt;div style=&quot;background-color: #ffffff; color: #404040; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;smali&quot; style=&quot;background-color: #f8f8f8; color: #333333;&quot;&gt;&lt;code&gt;Error: Cannot invoke a non-'const' constructor where a const expression is expected.
Try using a constructor or factory that is 'const'.&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;</description>
      <category>Flutter</category>
      <category>flutter</category>
      <author>HyeonGyu IM</author>
      <guid isPermaLink="true">https://memohg.tistory.com/145</guid>
      <comments>https://memohg.tistory.com/145#entry145comment</comments>
      <pubDate>Mon, 30 Oct 2023 23:53:00 +0900</pubDate>
    </item>
    <item>
      <title>Tuist 프로젝트 Xcode Cloud 적용(feat. Environment Variable, Tuist, cocoaPods, dSYM upload, App Distribution)</title>
      <link>https://memohg.tistory.com/144</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;# 프로젝트 기본 구조&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;본론에 들어가기전에 레저에빠지다 프로젝트 구조에 대해서 간단히 말씀드리면, 현재 저희는 &lt;b&gt;Tuist&lt;/b&gt;를 이용해 프로젝트파일을 관리하고 있고, &lt;b&gt;SPM&lt;/b&gt;과 &lt;b&gt;Carthage&lt;/b&gt;를 쓰면 &lt;u&gt;module을 찾을수 없다는 에러&lt;/u&gt;를 계속 마주하게되어 온몸을 비틀고 에러를 해결해보다가 일단은 &lt;b&gt;cocoaPods&lt;/b&gt;를 이용해 외부의존성을 컨트롤 하고있습니다&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;따라서 프로젝트파일을 구성하게 되는 순서는&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;1. tuist generate -n&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;2. pod install&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;위와 같이 터미널에서 진행되고, &lt;/span&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;하나하나씩 기다렸다가 실행하기는 번거롭기 때문에 &lt;b&gt;makefile&lt;/b&gt;을 이용해서 &lt;/span&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;b&gt;make generate&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;라는 명령어를 통해&lt;/span&gt;&lt;span style=&quot;background-color: #fafafa; color: #333333; text-align: start;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #fafafa; color: #333333; text-align: start;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;tuist generate -n&lt;br /&gt;pod install&lt;br /&gt;open  appName.xcworkspace&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위와같이 실행하고 있습니다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;# Xcode Cloud Work Flow &amp;amp; Environment Variable&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재 사용중인 워크플로우는 두가지 입니다.&lt;br /&gt;심사전 TestFlight에 올릴용도 한개, 테스트 진행시 App Distribution으로 배포되는 용도로 한개&lt;br /&gt;Workflow생성시 환경변수를 설정하는 곳이 있는데 자료들을 찾아보면 firebase app distribution업로드시 token을 발급받아야 하기 때문에 거기에 &lt;b&gt;token&lt;/b&gt;을 &lt;b&gt;secret&lt;/b&gt;으로 설정해서 넣어라 하는데 저는 그렇게 하니까 script에서 &lt;b&gt;Warning Deprecate&lt;/b&gt; 메시지가 떠서 검색 후 다르게 진행했습니다.&lt;br /&gt;&lt;b&gt;Environment Variable&lt;/b&gt; 설정은 간단하기 때문에 사진과 함께 간단히 말씀드리고 넘어가겠습니다&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-06-06 오후 9.58.01.png&quot; data-origin-width=&quot;662&quot; data-origin-height=&quot;173&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bPpUrq/btsiO6BNeCq/Lclxh5buUPzkCFLIXJkdk1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bPpUrq/btsiO6BNeCq/Lclxh5buUPzkCFLIXJkdk1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bPpUrq/btsiO6BNeCq/Lclxh5buUPzkCFLIXJkdk1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbPpUrq%2FbtsiO6BNeCq%2FLclxh5buUPzkCFLIXJkdk1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;662&quot; height=&quot;173&quot; data-filename=&quot;스크린샷 2023-06-06 오후 9.58.01.png&quot; data-origin-width=&quot;662&quot; data-origin-height=&quot;173&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위와같이 원하는 변수를 넣고 로그에 노출되지 않아야 하는 값이면 Secret을 체크합니다&amp;nbsp;&lt;br /&gt;script에서 사용시 &lt;b&gt;$TESTER_GROUP&lt;/b&gt; 이런식으로 작성하면 해당값을 가져옵니다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;# Xcode Cloud Custom Script(ci_post_clone.sh, ci_post_xcodebuild.sh)&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 프로젝트 &lt;b&gt;root 디렉토리에 ci_scripts&lt;/b&gt; 폴더를 생성합니다&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-06-06 오후 10.08.28.png&quot; data-origin-width=&quot;904&quot; data-origin-height=&quot;392&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cn3cuq/btsiQj8x7hs/uT9iiIozEXKau51ISeFGTk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cn3cuq/btsiQj8x7hs/uT9iiIozEXKau51ISeFGTk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cn3cuq/btsiQj8x7hs/uT9iiIozEXKau51ISeFGTk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcn3cuq%2FbtsiQj8x7hs%2FuT9iiIozEXKau51ISeFGTk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;473&quot; height=&quot;205&quot; data-filename=&quot;스크린샷 2023-06-06 오후 10.08.28.png&quot; data-origin-width=&quot;904&quot; data-origin-height=&quot;392&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;# ci_post_clone.sh&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1686057025167&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#!/bin/sh

//코코아팟 설치를 진행합니다
echo &quot;&amp;gt;&amp;gt;&amp;gt; INSTALL DEPENDENCIES&quot;
brew install cocoapods
 
//상위폴더로 가는 명령어 입니다 빼먹으시면 에러납니다
cd ..

echo &quot;tuist... start&quot;
// 이 명령어는 xcode cloud에서 실행되기전에 사용자의 맥에서 tuist bundle명령어를 통해
// .tuist-bin 파일이 생성되고 깃에 올라가 있어야 사용가능합니다
// 이렇게하면 tuist install 없이 generate 명령어를 사용가능합니다
tuist bundle

echo &quot;tuist generate...&quot;
.tuist-bin/tuist generate

echo &quot;pod install...&quot;
pod install&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 스크립트에서 가장 중요한 부분은 &lt;u&gt;&lt;b&gt;로컬에서 tuist bundle 명령어를 실행&lt;/b&gt;&lt;/u&gt;하고 깃에 올려 ci에서 돌아갈때도 tuist install 없이 명령이 동작하도록 환경을 조성해주어야 한다는 부분입니다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;b&gt;&lt;span&gt;# &lt;/span&gt;&lt;/b&gt;ci_post_xcodebuild.sh&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1686057475283&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#!/bin/sh
//이 부분은 workflow 분기하는 부분입니다 주의할점은 ==이 아니라 = 이라는 점 입니다
if [ &quot;$CI_WORKFLOW&quot; = &quot;AutoAppDistribution&quot; ]; then
    echo &quot;Develop Version: #$CI_BUILD_NUMBER&quot;
    echo &quot;Uploading Firebase App Distribution&quot;
    //아래 세줄은 변수에 이름과 아이디를 담는 부분입니다 안담고 바로 사용하셔도 무방합니다
    appname=&quot;myAppName.ipa&quot;
    appid=&quot;myAppFirebaseAppID&quot;

	//이 부분은 따로 아래에서 설명하겠습니다
    unzip firebase-tools-macos.zip
    chmod +x ./firebase-tools-macos
    
    //아까 잠깐 Token Deprecate경고 메시지에서 이야기한게 이 부분입니다
    export GOOGLE_APPLICATION_CREDENTIALS=&quot;service-account-key.json&quot;  # 서비스 계정 키 파일 경로 설정

    chmod +x &quot;$CI_AD_HOC_SIGNED_APP_PATH/$appname&quot;
    ./firebase-tools-macos appdistribution:distribute &quot;$CI_AD_HOC_SIGNED_APP_PATH/$appname&quot; --app $appid --release-notes &quot;Develop Version: #$CI_BUILD_NUMBER&quot; --groups $TESTER_GROUP
fi

echo &quot;dSYM 파일 업로드&quot;
cd ..
./Pods/FirebaseCrashlytics/upload-symbols -gsp ./reference/GoogleService-Info-Develop.plist -p ios $CI_ARCHIVE_PATH/dSYMs&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;# &lt;/b&gt;&lt;/b&gt;firebase-tools-macos&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;하면서 가장 이해가 안됫던 부분입니다.&lt;/li&gt;
&lt;li&gt;여기서 --token관련해서 firebase cli를 통해 발급받는 부분이 원래 있는데 위에 언급한것처럼 다르게 해결해서 그냥 cli파일받고 압축하기만 하면 됩니다 &lt;b&gt;GOOGLE_APPLICATION_CREDENTIALS 부분을 참고해주세요&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;해당 부분은 &lt;a href=&quot;https://dy-yb.github.io/2023/AppDistribution/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://dy-yb.github.io/2023/AppDistribution/&lt;/a&gt;&amp;nbsp;이분의 글을 많이 참고했습니다&lt;/li&gt;
&lt;li&gt;압축하고 용량이 대략 40MB 50MB정되 되는데 위에서 보여드린 사진과 같이 압축하고 ci_scripts 폴더안에 넣어주시면 됩니다&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;#&lt;/b&gt;&lt;/b&gt;&amp;nbsp;&lt;b&gt;firebase appid &amp;amp; App Distribution &amp;amp; Tester 설정&lt;/b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;1. 녹색으로 표시된 부분 바로 아래에 나와있는 &lt;b&gt;앱 ID 부분이 ID 입니다&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-06-06 오후 10.28.34.png&quot; data-origin-width=&quot;2177&quot; data-origin-height=&quot;737&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bxR63J/btsiNuJ3klB/xW69YvujKAZv9UDlIGBE11/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bxR63J/btsiNuJ3klB/xW69YvujKAZv9UDlIGBE11/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bxR63J/btsiNuJ3klB/xW69YvujKAZv9UDlIGBE11/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbxR63J%2FbtsiNuJ3klB%2FxW69YvujKAZv9UDlIGBE11%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;638&quot; height=&quot;216&quot; data-filename=&quot;스크린샷 2023-06-06 오후 10.28.34.png&quot; data-origin-width=&quot;2177&quot; data-origin-height=&quot;737&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. &lt;b&gt;Distribution&lt;/b&gt;은 별거 없이 위에 코드를 잘 붙여넣으셨으면 잘 작동하게 되어있습니다&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;유의하실점은 ipa추출되고 앱 이름이 어떻게 되어있는지 꼭! 확인하시고 해야합니다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;그리고만약 ipa가 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;한글을 포함하고 있다면 upload가 되지 않으니 영어로 바꾸시고 진행해야합니다&lt;/b&gt;&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이거때문에 아스키코드변환 utf8인코딩 등등 시도해보았으나 결과적으로 시간만 날리고 실패했습니다&lt;/li&gt;
&lt;li&gt;저는 그래서 ipa추출을 &lt;b&gt;TargetName&lt;/b&gt;으로 전환하였고 info.plist에 &lt;b&gt;CFBundleDisplayName&lt;/b&gt;을 설정해서 한글이름이 앱설치시 적용되도록 하였습니다&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. &lt;b&gt;Tester&lt;/b&gt; 설정은 한가지 유의하실 점이 있는데 이미지에 나와있는데로 &lt;b&gt;물음표 옆에 나와있는 이름&lt;/b&gt;을 사용하셔야 오류가 나지 않습니다&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;--release-notes &lt;span&gt;&quot;Develop Version: #&lt;/span&gt;$CI_BUILD_NUMBER&lt;span&gt;&quot; 이부분은 출시노트에 추가되는 부분인데 자유롭게 수정하셔도 괜찮습니다&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;edited_스크린샷 2023-06-06 오후 10.58.56.png&quot; data-origin-width=&quot;1872&quot; data-origin-height=&quot;525&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/SAUWn/btsiJzkJVo3/XVIOZgqj2KM1oUs94fZmRk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/SAUWn/btsiJzkJVo3/XVIOZgqj2KM1oUs94fZmRk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/SAUWn/btsiJzkJVo3/XVIOZgqj2KM1oUs94fZmRk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FSAUWn%2FbtsiJzkJVo3%2FXVIOZgqj2KM1oUs94fZmRk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1872&quot; height=&quot;525&quot; data-filename=&quot;edited_스크린샷 2023-06-06 오후 10.58.56.png&quot; data-origin-width=&quot;1872&quot; data-origin-height=&quot;525&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;# GOOGLE_APPLICATION_CREDENTIALS&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이부분은 사진 여러장과 함께 말씀드리도록 하겠습니다 이거 자료도없고 찾느라 고생했네요 ㅠ&lt;/li&gt;
&lt;li&gt;일단 해당 링크로 이동합니다 &lt;a href=&quot;https://cloud.google.com/docs/authentication/application-default-credentials?hl=ko&quot;&gt;https://cloud.google.com/docs/authentication/application-default-credentials?hl=ko&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 링크 이동후에 오른쪽위에 &lt;b&gt;콘솔&lt;/b&gt; 버튼을 클릭합니다&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-06-06 오후 10.33.16.png&quot; data-origin-width=&quot;749&quot; data-origin-height=&quot;292&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cPvC2T/btsiOgrqDcJ/b0t7chy3ke3OExURpDfmA0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cPvC2T/btsiOgrqDcJ/b0t7chy3ke3OExURpDfmA0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cPvC2T/btsiOgrqDcJ/b0t7chy3ke3OExURpDfmA0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcPvC2T%2FbtsiOgrqDcJ%2Fb0t7chy3ke3OExURpDfmA0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;485&quot; height=&quot;189&quot; data-filename=&quot;스크린샷 2023-06-06 오후 10.33.16.png&quot; data-origin-width=&quot;749&quot; data-origin-height=&quot;292&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 이동하고 가운데 상단 검색을 활성화 시키면 3번째에 &lt;b&gt;IAM 및 관리자&lt;/b&gt;가 나옵니다 안나오면 검색하셔야 되요&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-06-06 오후 10.33.43.png&quot; data-origin-width=&quot;1061&quot; data-origin-height=&quot;456&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bh8S1b/btsiNc3Q0jb/KzguAzz4eE9qynQPjbTpe0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bh8S1b/btsiNc3Q0jb/KzguAzz4eE9qynQPjbTpe0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bh8S1b/btsiNc3Q0jb/KzguAzz4eE9qynQPjbTpe0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbh8S1b%2FbtsiNc3Q0jb%2FKzguAzz4eE9qynQPjbTpe0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;558&quot; height=&quot;240&quot; data-filename=&quot;스크린샷 2023-06-06 오후 10.33.43.png&quot; data-origin-width=&quot;1061&quot; data-origin-height=&quot;456&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 왼쪽 상단에서 &lt;b&gt;서비스 계정&lt;/b&gt;을 탭합니다&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-06-06 오후 10.34.26.png&quot; data-origin-width=&quot;381&quot; data-origin-height=&quot;542&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b7yjFH/btsiJ7n4nEj/vUmkWp2KsdWfE3IJLeR0N1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b7yjFH/btsiJ7n4nEj/vUmkWp2KsdWfE3IJLeR0N1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b7yjFH/btsiJ7n4nEj/vUmkWp2KsdWfE3IJLeR0N1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb7yjFH%2FbtsiJ7n4nEj%2FvUmkWp2KsdWfE3IJLeR0N1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;201&quot; height=&quot;286&quot; data-filename=&quot;스크린샷 2023-06-06 오후 10.34.26.png&quot; data-origin-width=&quot;381&quot; data-origin-height=&quot;542&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. &lt;b&gt;+ 서비스계정&lt;/b&gt; 만들기 버튼을 탭합니다&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;edited_스크린샷 2023-06-06 오후 10.34.43.png&quot; data-origin-width=&quot;857&quot; data-origin-height=&quot;168&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dBgJZT/btsiO445tDm/eUUhyq6ralMYte6Il2O24k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dBgJZT/btsiO445tDm/eUUhyq6ralMYte6Il2O24k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dBgJZT/btsiO445tDm/eUUhyq6ralMYte6Il2O24k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdBgJZT%2FbtsiO445tDm%2FeUUhyq6ralMYte6Il2O24k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;561&quot; height=&quot;110&quot; data-filename=&quot;edited_스크린샷 2023-06-06 오후 10.34.43.png&quot; data-origin-width=&quot;857&quot; data-origin-height=&quot;168&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5. 크게 의미 없기때문에 원하시는 걸로 아무렇게나 해도 상관없습니다&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-06-06 오후 10.36.09.png&quot; data-origin-width=&quot;861&quot; data-origin-height=&quot;557&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/q3Qnv/btsiOgY5sTT/Bv7y9gRovFeypBoTaqzAy0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/q3Qnv/btsiOgY5sTT/Bv7y9gRovFeypBoTaqzAy0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/q3Qnv/btsiOgY5sTT/Bv7y9gRovFeypBoTaqzAy0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fq3Qnv%2FbtsiOgY5sTT%2FBv7y9gRovFeypBoTaqzAy0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;317&quot; height=&quot;205&quot; data-filename=&quot;스크린샷 2023-06-06 오후 10.36.09.png&quot; data-origin-width=&quot;861&quot; data-origin-height=&quot;557&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;6. 역할에 다음의 역할을 추가하고 확인을 누릅니다 2개 모두 추가해주세요&lt;br /&gt;추가하시고 완료를 누르시면 됩니다&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-06-06 오후 10.37.15.png&quot; data-origin-width=&quot;623&quot; data-origin-height=&quot;242&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/x4dyc/btsiOeNS8fq/Wbn2N7fItrH8YU0lKr4Wdk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/x4dyc/btsiOeNS8fq/Wbn2N7fItrH8YU0lKr4Wdk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/x4dyc/btsiOeNS8fq/Wbn2N7fItrH8YU0lKr4Wdk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fx4dyc%2FbtsiOeNS8fq%2FWbn2N7fItrH8YU0lKr4Wdk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;566&quot; height=&quot;220&quot; data-filename=&quot;스크린샷 2023-06-06 오후 10.37.15.png&quot; data-origin-width=&quot;623&quot; data-origin-height=&quot;242&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;7. 생성된 계정 오른쪽을 보시면 작업항목을 누르시고 &lt;b&gt;키 관리&lt;/b&gt; 를 누르세요&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-06-06 오후 10.37.52.png&quot; data-origin-width=&quot;346&quot; data-origin-height=&quot;474&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/zaG0o/btsiNcv1WNL/PfyPx7fZ0Y0FOhjJtaEQg1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/zaG0o/btsiNcv1WNL/PfyPx7fZ0Y0FOhjJtaEQg1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/zaG0o/btsiNcv1WNL/PfyPx7fZ0Y0FOhjJtaEQg1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FzaG0o%2FbtsiNcv1WNL%2FPfyPx7fZ0Y0FOhjJtaEQg1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;160&quot; height=&quot;219&quot; data-filename=&quot;스크린샷 2023-06-06 오후 10.37.52.png&quot; data-origin-width=&quot;346&quot; data-origin-height=&quot;474&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;8. &lt;b&gt;키 추가 버튼&lt;/b&gt;을 활성화 시키면 &lt;b&gt;새 키 만들기&lt;/b&gt; 항목이 보이는데 탭하시면 됩니다&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-06-06 오후 10.38.13.png&quot; data-origin-width=&quot;525&quot; data-origin-height=&quot;551&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/d8H2ec/btsiWTabMLc/BwwUbsGpXr057CTbzbENDk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/d8H2ec/btsiWTabMLc/BwwUbsGpXr057CTbzbENDk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/d8H2ec/btsiWTabMLc/BwwUbsGpXr057CTbzbENDk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fd8H2ec%2FbtsiWTabMLc%2FBwwUbsGpXr057CTbzbENDk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;282&quot; height=&quot;296&quot; data-filename=&quot;스크린샷 2023-06-06 오후 10.38.13.png&quot; data-origin-width=&quot;525&quot; data-origin-height=&quot;551&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;9. &lt;b&gt;JSON&lt;/b&gt; 파일로 받으시면 됩니다&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-06-06 오후 10.38.23.png&quot; data-origin-width=&quot;824&quot; data-origin-height=&quot;307&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bZD18C/btsiQ53jTaW/XkEYnbfbRRgDg3QLGc8uxk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bZD18C/btsiQ53jTaW/XkEYnbfbRRgDg3QLGc8uxk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bZD18C/btsiQ53jTaW/XkEYnbfbRRgDg3QLGc8uxk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbZD18C%2FbtsiQ53jTaW%2FXkEYnbfbRRgDg3QLGc8uxk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;464&quot; height=&quot;173&quot; data-filename=&quot;스크린샷 2023-06-06 오후 10.38.23.png&quot; data-origin-width=&quot;824&quot; data-origin-height=&quot;307&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;10. 받으신 파일을 &lt;b&gt;ci_scripts&lt;/b&gt; 폴더에 넣으시고 파일이름을 &lt;b&gt;service-account-key.json&lt;/b&gt; 라고 설정하시면 됩니다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; text-align: left; font-family: 'Nanum Gothic';&quot;&gt;참고한 링크는 다음과 같습니다&lt;/span&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;- xcode cloud에서 프로젝트 의존성 구성&lt;br /&gt;&lt;a href=&quot;https://developer.apple.com/documentation/xcode/making-dependencies-available-to-xcode-cloud&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://developer.apple.com/documentation/xcode/making-dependencies-available-to-xcode-cloud&lt;/a&gt;&lt;/blockquote&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;- xcode cloud custom script에서 사용가능한 환경변수 목록 및 설명&lt;br /&gt;&lt;a href=&quot;https://developer.apple.com/documentation/xcode/environment-variable-reference&quot;&gt;https://developer.apple.com/documentation/xcode/environment-variable-reference&lt;/a&gt;&lt;/blockquote&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;- Custom Build Script를 작성하는 방법 소개&lt;br /&gt;&lt;a href=&quot;https://developer.apple.com/documentation/xcode/writing-custom-build-scripts&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://developer.apple.com/documentation/xcode/writing-custom-build-scripts&lt;/a&gt;&lt;/blockquote&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;- firebase cli 파일관련 참고&lt;br /&gt;&lt;a href=&quot;https://dy-yb.github.io/2023/AppDistribution/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://dy-yb.github.io/2023/AppDistribution/&lt;/a&gt;&lt;/blockquote&gt;</description>
      <category>IOS/iOS</category>
      <category>App Distribution</category>
      <category>dsym</category>
      <category>Firebase Crashlytics</category>
      <category>tuist</category>
      <category>xcode cloud</category>
      <author>HyeonGyu IM</author>
      <guid isPermaLink="true">https://memohg.tistory.com/144</guid>
      <comments>https://memohg.tistory.com/144#entry144comment</comments>
      <pubDate>Tue, 6 Jun 2023 23:07:31 +0900</pubDate>
    </item>
    <item>
      <title>응애개발자 -&amp;gt; 개발자</title>
      <link>https://memohg.tistory.com/143</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;keyboard-2436834_1920.jpg&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1280&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bMEVpz/btrCNNXzZ5X/skCpUlyKiv07WV5NlwRcs0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bMEVpz/btrCNNXzZ5X/skCpUlyKiv07WV5NlwRcs0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bMEVpz/btrCNNXzZ5X/skCpUlyKiv07WV5NlwRcs0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbMEVpz%2FbtrCNNXzZ5X%2FskCpUlyKiv07WV5NlwRcs0%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1280&quot; data-filename=&quot;keyboard-2436834_1920.jpg&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1280&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;응애개발자 -&amp;gt; 개발자&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개발 공부를 시작하고, 포트폴리오를 만들고, 취업에 성공해서 iOS개발자로 살게된지 1년이 약간 넘었습니다.&amp;nbsp;&lt;br /&gt;그동안 많은 어려움과 주변 분들의 감사한 도움과 함께 저만의 작품을 갖게 되는 시간이였습니다&lt;br /&gt;이번에 테스트코드를 처음으로 프로젝트에 추가하며 알게되었는데 소스코드가 어느새 4만줄이 넘더군요 ㅎㅎ&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그동안 많은 일들이 있었습니다. 수많은 리팩토링시도, 새로운 프로젝트, 데이터분석, UI 디자인 등등...&lt;br /&gt;이중 에서도 가장 흥미가 많이 느껴졌던 것은 리팩토링 시도 였습니다. 예전의 코드를 개선하고 개선하다보면 뭔가... 성장했다 라는 느낌이 뚜렷하게 느껴지는 것 같습니다. 제가 처음 리팩토링 시도할때 어렴풋이 분리를 이렇게 하는건가? 라고 생각하고 쓴것과 지금의 제가 분리는 이렇게 하자 라는 느낌은 정말 많이 다릅니다. 혼자 개발을 계속 했더라도, 분명 이럴때는 이렇게 하면 힘들고 저렇게 하면 좋다 라는게 점점 눈에 들어오기 시작하니까 어려움은 있어도 좋은 코드에 대한 인식은 계속 생겨나는것 같습니다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;제가 가장 잘했다고 생각하는 리팩토링은&amp;nbsp;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;API request를 Open Close 원칙에 따라 수정에는 닫혀있고 확장에는 열려있도록 한 것&lt;/li&gt;
&lt;li&gt;흩어진 UserDefault를 관리할 객체를 만들어 모든 UserDefault는 해당 객체를 거쳐 저장되고 읽어올수 있도록 한것&lt;/li&gt;
&lt;li&gt;기존에 VC에서 작성하던 파라미터와 url request를 enum으로 정의해서 Route를 만들수 있도록 한것&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 3가지 라고 할수 있을것 같습니다. 기본적인 리팩토링이지만 가장 뿌듯했던? 그리고 가장 체감이 컷던 리팩토링 이였습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 이제 서비스 개발단계가 굵직굵직한 프로젝트들은 어느정도 완성이 되었고 코드한줄의 사이드 이펙트가 예상하기 힘들어진만큼 테스트 코드의 필요성이 점점 커지고있고, 테스트코드가 붙으면 CI/CD도 자연스레 붙이려고 했었기 때문에 요즘에는 Single Responsibility Principle과 Dependency Inversion을 지키며 Testable한 코드를 작성하는데 중점을 두고 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나름 열심히 하고있다고 생각하지만 배울게 쌓여있습니다. SwiftUI, Combine, RxSwift까지 넘어야할 산들이 많네요 ㅎㅎ;;&lt;br /&gt;혼자 개발을 하게 되니 맞는 방향으로 가고 있는 것인지 항상 의심스럽습니다. 내가 구현하는 이방법이 야매인건 아닐까. 시스템에서 제공하는게 있는데 내가 몰라서 이렇게 하는건 아닐까... 실제로 몰라서 돌아가면서 구현을 했다가 나중에 알게되서 몇번 고친 부분들이 있습니다.&amp;nbsp;&lt;br /&gt;구현을 하며 퍼포먼스도 생각을 해야되고 복잡한 UI를 구현하면 자연스럽게 만드는데 시간을 많이 보내게 됩니다 ㅜㅜ 다른 로직들이야 생각을 잘 하고 차례로 구현을 해나가면 상관없지만 이 UI에 대한 경험만큼은 사수가 정말 필요하다 라고 뼈저리게 느끼게 되는 부분인것 같습니다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;요즘은 그래도 유튜브와 Raywenderich, 패스트캠퍼스같은 강의매체가 잘 되어있어서 감사하게도 좋은 코드를 보고 잘 배울수 있는것 같습니다. 저 말고도 사수없이 혼자 고생하시는 분들이 많은 것으로 알고있는데 다들 화이팅 하셨으면 좋겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지치지 않고 앞으로도 어떻게 하면 더 좋은 코드를 쓸수있을까 항상 고민하는 개발자가 되고싶습니다. 화이팅 입니다.&lt;/p&gt;</description>
      <category>Dairy/Life Memo</category>
      <author>HyeonGyu IM</author>
      <guid isPermaLink="true">https://memohg.tistory.com/143</guid>
      <comments>https://memohg.tistory.com/143#entry143comment</comments>
      <pubDate>Mon, 23 May 2022 22:39:21 +0900</pubDate>
    </item>
    <item>
      <title>다형성(Polymorphism)과 추상화(Abstraction)의 관계</title>
      <link>https://memohg.tistory.com/142</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;최근 인터뷰를 몇번 보면서 부족한 점을 많이 느끼게 되는 것 같습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그중에 기억에 남은 질문이 오늘의 주제입니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서칭을 하며 언뜻 보기에는 두 개념이 같은 말을 하고있는게 아닌가 했었는데 같은 생각을 하셨던분이 정리해주신걸 보고 좀 명확해진 것 같아 공유하려고 글을 쓰게 되었습니다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://wlaxhrl.tistory.com/78&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://wlaxhrl.tistory.com/78&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1648386237200&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;OOP의 추상화(Abstraction)와 다형성(Polymorphism)의 관계&quot; data-og-description=&quot;최근에 OOP에 대해 공부를 하다 혼란에 빠졌었는데, 나름 결론이 나서 기록. '나름' 결론이기 때문에 주의해주세요. 의견은 자유롭게 코멘트로 달아주세요. 혼란을 불러일으킨 요소 - 존 호프만의&quot; data-og-host=&quot;wlaxhrl.tistory.com&quot; data-og-source-url=&quot;https://wlaxhrl.tistory.com/78&quot; data-og-url=&quot;https://wlaxhrl.tistory.com/78&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/blxHtm/hyNPK2CUnU/7rrkbpO8678tizEXJI9ywk/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/GBXiS/hyNPFfWnTz/ZC0UFg4xYujUUsKnavgR91/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800&quot;&gt;&lt;a href=&quot;https://wlaxhrl.tistory.com/78&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://wlaxhrl.tistory.com/78&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/blxHtm/hyNPK2CUnU/7rrkbpO8678tizEXJI9ywk/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/GBXiS/hyNPFfWnTz/ZC0UFg4xYujUUsKnavgR91/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;OOP의 추상화(Abstraction)와 다형성(Polymorphism)의 관계&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;최근에 OOP에 대해 공부를 하다 혼란에 빠졌었는데, 나름 결론이 나서 기록. '나름' 결론이기 때문에 주의해주세요. 의견은 자유롭게 코멘트로 달아주세요. 혼란을 불러일으킨 요소 - 존 호프만의&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;wlaxhrl.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>IOS/Swift</category>
      <author>HyeonGyu IM</author>
      <guid isPermaLink="true">https://memohg.tistory.com/142</guid>
      <comments>https://memohg.tistory.com/142#entry142comment</comments>
      <pubDate>Sun, 27 Mar 2022 22:04:14 +0900</pubDate>
    </item>
    <item>
      <title>UserDefault 깔끔하게 쓰는 법 공유합니다</title>
      <link>https://memohg.tistory.com/141</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://medium.com/better-programming/create-the-perfect-userdefaults-wrapper-using-property-wrapper-42ca76005ac8&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://medium.com/better-programming/create-the-perfect-userdefaults-wrapper-using-property-wrapper-42ca76005ac8&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1646817008622&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;Create the Perfect UserDefaults Wrapper Using Property Wrapper&quot; data-og-description=&quot;No more boilerplate code and increase reusability&quot; data-og-host=&quot;betterprogramming.pub&quot; data-og-source-url=&quot;https://medium.com/better-programming/create-the-perfect-userdefaults-wrapper-using-property-wrapper-42ca76005ac8&quot; data-og-url=&quot;https://betterprogramming.pub/create-the-perfect-userdefaults-wrapper-using-property-wrapper-42ca76005ac8&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/cnPsQM/hyNEqDsO3A/2rFHdkaamG6dhzdi7PvXz1/img.png?width=1200&amp;amp;height=380&amp;amp;face=0_0_1200_380,https://scrap.kakaocdn.net/dn/DdW94/hyNFKAkkme/FTftFw9NhvJgjuTGvCd4e0/img.png?width=1400&amp;amp;height=443&amp;amp;face=0_0_1400_443&quot;&gt;&lt;a href=&quot;https://medium.com/better-programming/create-the-perfect-userdefaults-wrapper-using-property-wrapper-42ca76005ac8&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://medium.com/better-programming/create-the-perfect-userdefaults-wrapper-using-property-wrapper-42ca76005ac8&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/cnPsQM/hyNEqDsO3A/2rFHdkaamG6dhzdi7PvXz1/img.png?width=1200&amp;amp;height=380&amp;amp;face=0_0_1200_380,https://scrap.kakaocdn.net/dn/DdW94/hyNFKAkkme/FTftFw9NhvJgjuTGvCd4e0/img.png?width=1400&amp;amp;height=443&amp;amp;face=0_0_1400_443');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Create the Perfect UserDefaults Wrapper Using Property Wrapper&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;No more boilerplate code and increase reusability&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;betterprogramming.pub&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;미디엄구독하세요! ㅎㅎ&lt;/p&gt;</description>
      <category>IOS/Swift</category>
      <author>HyeonGyu IM</author>
      <guid isPermaLink="true">https://memohg.tistory.com/141</guid>
      <comments>https://memohg.tistory.com/141#entry141comment</comments>
      <pubDate>Wed, 9 Mar 2022 18:10:56 +0900</pubDate>
    </item>
    <item>
      <title>[iOS] Xcode 13 UIButton</title>
      <link>https://memohg.tistory.com/139</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1280&quot; data-filename=&quot;keyboard-2436834_1920.jpg&quot; width=&quot;683&quot; height=&quot;456&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bKMGYM/btrgQAsoSQA/DkBgK5ZicIXF2SI3aX3ejk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bKMGYM/btrgQAsoSQA/DkBgK5ZicIXF2SI3aX3ejk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bKMGYM/btrgQAsoSQA/DkBgK5ZicIXF2SI3aX3ejk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbKMGYM%2FbtrgQAsoSQA%2FDkBgK5ZicIXF2SI3aX3ejk%2Fimg.jpg&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1280&quot; data-filename=&quot;keyboard-2436834_1920.jpg&quot; width=&quot;683&quot; height=&quot;456&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;요즘에 일을 하면서 버튼이 뭔가 많이 바뀌었다 라는걸 느끼고 있었는데 제드님이 정리를 너무 잘해주셔서 공유합니다 ㅎㅎ&lt;br /&gt;&lt;a href=&quot;https://zeddios.tistory.com/1291&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://zeddios.tistory.com/1291&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1633440133806&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;WWDC 21 ) Meet the UIKit  button system&quot; data-og-description=&quot;안녕하세요 :) Zedd입니다. 오늘은 iOS 15에서 굉장히 많이 업데이트가 된 UIButton들에 대해서 알아보겠습니다   Meet&amp;nbsp;the&amp;nbsp;UIKit&amp;nbsp;&amp;nbsp;button&amp;nbsp;system을 아주 빠르고 간단하게 요약해보겠습니다. # Deprecated p..&quot; data-og-host=&quot;zeddios.tistory.com&quot; data-og-source-url=&quot;https://zeddios.tistory.com/1291&quot; data-og-url=&quot;https://zeddios.tistory.com/1291&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/dYnEpT/hyLQ931coM/8w5ST1XGetRvOoD6KhcntK/img.png?width=382&amp;amp;height=390&amp;amp;face=0_0_382_390,https://scrap.kakaocdn.net/dn/dbTaaM/hyLRaaMI3o/fMHdYcYK4GD47I3CYlTEMK/img.png?width=382&amp;amp;height=390&amp;amp;face=0_0_382_390,https://scrap.kakaocdn.net/dn/b6i1ms/hyLQ5tLEXd/KzeS27iK2pdQxfR42jjkO1/img.png?width=1344&amp;amp;height=976&amp;amp;face=0_0_1344_976&quot;&gt;&lt;a href=&quot;https://zeddios.tistory.com/1291&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://zeddios.tistory.com/1291&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/dYnEpT/hyLQ931coM/8w5ST1XGetRvOoD6KhcntK/img.png?width=382&amp;amp;height=390&amp;amp;face=0_0_382_390,https://scrap.kakaocdn.net/dn/dbTaaM/hyLRaaMI3o/fMHdYcYK4GD47I3CYlTEMK/img.png?width=382&amp;amp;height=390&amp;amp;face=0_0_382_390,https://scrap.kakaocdn.net/dn/b6i1ms/hyLQ5tLEXd/KzeS27iK2pdQxfR42jjkO1/img.png?width=1344&amp;amp;height=976&amp;amp;face=0_0_1344_976');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;WWDC 21 ) Meet the UIKit button system&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;안녕하세요 :) Zedd입니다. 오늘은 iOS 15에서 굉장히 많이 업데이트가 된 UIButton들에 대해서 알아보겠습니다   Meet&amp;nbsp;the&amp;nbsp;UIKit&amp;nbsp;&amp;nbsp;button&amp;nbsp;system을 아주 빠르고 간단하게 요약해보겠습니다. # Deprecated p..&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;zeddios.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;전체적인 버튼 변경사항&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;버튼 스타일 4가지&lt;/li&gt;
&lt;li&gt;멀티라인 지원&lt;/li&gt;
&lt;li&gt;다이나믹 타입 지원&lt;/li&gt;
&lt;li&gt;액티비티 인디케이터 속성추가&lt;/li&gt;
&lt;li&gt;서브타이틀 추가&lt;/li&gt;
&lt;li&gt;configuration을 통한 속성 설정&lt;/li&gt;
&lt;li&gt;configurationUpdateHandler를 통한 버튼 액션시 속성 제어&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;팝업 버튼도 생기고 이것저것 추가로 생겼는데 제드님이 너무 잘 설명해 주셨네요 ㅎㅎㅎ 제드님 블로그만 열심히 봐도 최신 개발공부 다될듯...&lt;/p&gt;</description>
      <category>IOS/iOS</category>
      <author>HyeonGyu IM</author>
      <guid isPermaLink="true">https://memohg.tistory.com/139</guid>
      <comments>https://memohg.tistory.com/139#entry139comment</comments>
      <pubDate>Tue, 5 Oct 2021 22:34:07 +0900</pubDate>
    </item>
    <item>
      <title>스타트업 신입 iOS 6개월차 회고</title>
      <link>https://memohg.tistory.com/138</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1439&quot; data-filename=&quot;love-1100255_1920.jpg&quot; width=&quot;675&quot; height=&quot;506&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lMbvL/btrgCG7sRR3/g5Fbi05SYumT12FIxEKxRK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lMbvL/btrgCG7sRR3/g5Fbi05SYumT12FIxEKxRK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lMbvL/btrgCG7sRR3/g5Fbi05SYumT12FIxEKxRK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlMbvL%2FbtrgCG7sRR3%2Fg5Fbi05SYumT12FIxEKxRK%2Fimg.jpg&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1439&quot; data-filename=&quot;love-1100255_1920.jpg&quot; width=&quot;675&quot; height=&quot;506&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 style=&quot;text-align: center;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;첫 개발자 취업&lt;/span&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1633439302343&quot; class=&quot;swift&quot; style=&quot;margin: 20px auto 0px; display: block; overflow: auto; padding: 20px; color: #383a42; background: #f8f8f8; font-size: 14px; font-family: 'SF Mono', Menlo, Consolas, Monaco, monospace; border: 1px solid #ebebeb; line-height: 1.71; cursor: default; z-index: 1; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;if HyeongyuIM == iOS Developer {
	workingStart(at: 2021.02.04)
} else {
	print(&quot;현규님은 아직 요리사입니다&quot;)
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;제가 처음으로 개발자의 삶에 뛰어든 날짜입니다.&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;제가 이전에 남겼던 글에 나와있지만 ㅎㅎ 외주받은 결과물로 혼자 iOS를 관리하며 Android 개발요청하는 것은 쉬운 일은 아니였습니다.&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;저도 여타의 신입 구직자들과 같은 마음이였습니다. 사수가 있었으면 했고 개발문화가 있으면 좋겠다 나도 여타의 개발자들과 같은 멋진 개발생활을 하고싶다 라고. 취업이후 이런 생각들은 접어두고 할것들이 신입인 제 눈에도 너무 많이 보여 정신없이 일했던것 같습니다&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;아래의 정리들은 제가 6개월간 개발자 로서 저의 업무와 앞으로의 목표를 정리하는 글 입니다.&lt;/span&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h3 style=&quot;text-align: center;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;SourceCode Refactoring&lt;/span&gt;&lt;/h3&gt;
&lt;figure id=&quot;og_1633332573962&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;&amp;lrm;레저에빠지다&quot; data-og-description=&quot;&amp;lrm;레저에빠지다를 통해 한층 더 가까워진 레저를 체험해 보세요! 레저에빠지다는 레저와 IT를 접목하여 다양한 레저정보를 제공하고 레저인들의 중고거래 및 레저시설 이용을 돕는 종합 레저 &quot; data-og-host=&quot;apps.apple.com&quot; data-og-source-url=&quot;https://apps.apple.com/kr/app/%EB%A0%88%EC%A0%80%EC%97%90%EB%B9%A0%EC%A7%80%EB%8B%A4/id1554261343&quot; data-og-url=&quot;https://apps.apple.com/kr/app/%EB%A0%88%EC%A0%80%EC%97%90%EB%B9%A0%EC%A7%80%EB%8B%A4/id1554261343&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/cwOtLX/hyLReC6Cyz/xaqeBzDzHkGRM5Hnt1SFz0/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/bexbfA/hyLRfvfxQi/bKeFKRDPgzH1CMsBWvQcKK/img.png?width=600&amp;amp;height=600&amp;amp;face=0_0_600_600&quot;&gt;&lt;a href=&quot;https://apps.apple.com/kr/app/%EB%A0%88%EC%A0%80%EC%97%90%EB%B9%A0%EC%A7%80%EB%8B%A4/id1554261343&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://apps.apple.com/kr/app/%EB%A0%88%EC%A0%80%EC%97%90%EB%B9%A0%EC%A7%80%EB%8B%A4/id1554261343&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/cwOtLX/hyLReC6Cyz/xaqeBzDzHkGRM5Hnt1SFz0/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/bexbfA/hyLRfvfxQi/bKeFKRDPgzH1CMsBWvQcKK/img.png?width=600&amp;amp;height=600&amp;amp;face=0_0_600_600');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;&amp;lrm;레저에빠지다&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;&amp;lrm;레저에빠지다를 통해 한층 더 가까워진 레저를 체험해 보세요! 레저에빠지다는 레저와 IT를 접목하여 다양한 레저정보를 제공하고 레저인들의 중고거래 및 레저시설 이용을 돕는 종합 레저&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;apps.apple.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;레저에빠지다 서비스는 현재 13.2 버전을 타겟으로 개발되었고 기존에 회원/사업자가 같이 있는 형태에서 현재는 사업자로 따로 떨어져서 관리하는 앱은 2개가 되었습니다. 페이지수는 대략 두 서비스 합쳐 100페이지를 넘어갑니다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기존 외주를 통해 받은 앱은 푸시알림, 모델조차 없는 프로젝트 코드였습니다.&lt;br /&gt;외주코드는 제가 상상했던것 보다... 날것의 형태였습니다. API호출 부분은 분리되어있었지만 하나의 페이지 즉 뷰컨트롤러에 모든 비즈니스 로직이 붙어있어 복잡한 페이지는 연관관계를 보는데 여러 사항을 고려해야했습니다...&lt;br /&gt;또한 모델이 없어 Json Parsing을 필요한 데이터마다 일일이 타입캐스팅 하여 사용하고 있었습니다. 해서 받고 나서 초반부는 크리티컬한 버그부터 수정하고 코드에 패턴과 Reference를 관리하기 위해 거의 2주간 밤낮으로 고생했던것 같습니다. 해당 시기 제가 집중적으로 구현한것은&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;BaseController Pattern -&amp;gt; MVVM Pattern&lt;/li&gt;
&lt;li&gt;URL, Parameter, HTTP Method -&amp;gt; Route with Generic Method&lt;/li&gt;
&lt;li&gt;API Model, ViewModel&lt;/li&gt;
&lt;li&gt;User LoginModule(UserDefault 관리 객체)&lt;/li&gt;
&lt;li&gt;Delegate -&amp;gt; CallBack Closure&lt;/li&gt;
&lt;li&gt;GitHub Branch 분리 - Main, Stage, Develop&lt;/li&gt;
&lt;li&gt;앱 Target분리 - Release,Debug / Develop( Test )&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 기존 컨트롤러에 모두 의존된 모델생성, 비즈니스 로직, 데이터 요청을 각각 분리 하였습니다&lt;br /&gt;- 데이터 요청의 레퍼런스값 String URL, Parameter를 Enum에 담아 정리하였습니다&lt;br /&gt;&amp;nbsp; &amp;nbsp;해당 Enum을 호출할때 Route를 만들고 Route로 API를 호출합니다&lt;br /&gt;&amp;nbsp; &amp;nbsp;레저에빠지다 어플은 수많은 작은 기능들 때문에 API만 120여개가 넘습니다. 각각의 호출 메서드를 최대한 간결하게 작성하기 위해&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; GET, POST는 같이 처리하고 멀티파트만 분리하여 처리합니다&lt;br /&gt;- API Model은 파싱할 Codable모델을 만들고, 뷰모델에 넘겨주면 뷰모델에서 데이터를 가공후 컨트롤러에 넘기도록 하였습니다&amp;nbsp;&lt;br /&gt;- 기존에 UserDefault를 페이지 별로 분산되어있어 관리가 어려웠는데 Key를 따로 관리하고 UserDefault를 관리하는 객체를 생성해 해당 클래스가 모든 UserDefault를 처리하도록 하였습니다&amp;nbsp;&lt;br /&gt;- Delegate패턴은 흐름을 파악하기 힘들어 페이지 하나의 이동같은경우 콜백 클로저를 통해 개선하였습니다&lt;br /&gt;- 기존에 하나의 메인 브랜치로만 관리되던 깃허브 브랜치를 3개로 나누어 관리하였습니다&lt;br /&gt;- Configuration 분리를 통해 앱 빌드시 Test API, Release API를 나누어 테스트 버전 앱 빌드를 만들었습니다&lt;span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;text-align: center;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;리팩토링 이후의 서비스 개발 : 마켓 서비스&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;기본적인 마켓 서비스 구현
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;채팅&lt;/li&gt;
&lt;li&gt;푸시알림&lt;/li&gt;
&lt;li&gt;공유하기&lt;/li&gt;
&lt;li&gt;상품등록&lt;/li&gt;
&lt;li&gt;상품조회&lt;/li&gt;
&lt;li&gt;Token&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대표적으로 보자면 위의 기능들이 있습니다. 위의 기능들을 구현할때 가장 애를 먹었던 기능은 채팅입니다. 저희 서비스가 소켓을 통해 할필요는 없을것 같아 2초의 주기를 가지고 업데이트를 하고, 푸시알림이 오면 업데이트를 하도록 구현하였습니다.&amp;nbsp;&lt;br /&gt;그리고 또 어려웠던것은 이미지를 다루는 것이 저한테는 너무 어려웠습니다. 그냥 띄워주면 알아서 해주는 건줄 알았는데 확대, 축소, 화면에 맞는 비율의 선정까지 모두 개발자가 일일이 구현해야 했습니다. 또한 사진을 올리면 그에맞는 이미지 압축도 해야하고... 아직까지 개선해야 할 것들이 많은것 같습니다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;text-align: center;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;Swift 5.5, RxSwift, MVVM, TDD, CI/CD, Snapkit, SwiftUI&lt;/span&gt;&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;요즘 관심을 가지고 배우고 있는 학습 목표? 레저에빠지다 서비스에 적용해볼 대상들 이랄까요?&amp;nbsp;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;요즘 개발을 계속하고 리팩토링을 하며 드는 생각은 새로운 기술의 도입보다는 제가 작성한 코드가 잘 쓴것인지 앱의 의존성 구조나 테스트하기는 어떤지를 생각해 보는것 같습니다. 클린코드에서 분명히 메서드는 파라미터가 하나도 없는것이 좋다! 라고해서 쭈욱 작성해높고 보니... 실질적으로 인풋이 없는 메서드는 테스트하기가 어렵다거나... Struct로 구현해도 되는데 Class를 쓴것이 많다거나... 하네요 ㅠㅠ&lt;br /&gt;해서 위의 5.5와 여러 기술들을 관심을 가지고 배우고 있는데 적용하는 시기는 아직 멀은것 같습니다.&amp;nbsp;&lt;br /&gt;&lt;br /&gt;일단 저의 목표는&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. MVVM을 완벽히 이해하고&lt;br /&gt;2. RxSwift를 통해 MVVM을 좀더 간결하게 표현한뒤에&lt;br /&gt;3. BDD또는 TDD를 통해 테스트 코드를 작성하고&lt;br /&gt;4. CI/CD를 붙여 배포의 자동화를 만드는 것입니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이외의 스냅킷, 스위프트UI는 제가 필수는 아니지만 알아두면 좋을 지식들이 되겠네요 ㅎㅎ&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;현재 6개월이 넘어 7개월 8개월차에 접어들고 있습니다. 그동안 많은 이슈들이 있었고 새로운 서버개발자, 안드로이드 개발자를 채용해서 이제는 개발팀같은 느낌으로? 돌아가서 이제는 개발자가 된게 실감나기도 하구요 ㅎㅎ&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;시간이 지나면서 개발 안정화가 조금씩 되고... 오픈톡방에서 지식을 나누는 사람들이 때때로 알수없는 지식의 교환이 이루어지고 제가 이해하기 어려울때마다 뒤처지고 있다는 느낌이 계속 들기 시작합니다&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;이런 뒤처지는 느낌은 저에게 동기부여가 되는 한편 저에게 제 코드에 대한 불신감을 주었습니다. 당연한 일이지만 사수가 없으니 제가 제대로 하고있는 것인지...&amp;nbsp; 주말에는 괜찮은 레포를 뒤지고 분석하고 부트캠프 졸업생의 코드를 살펴보고 배우고... 현재 나의 수준은 어디인가 깨닫게 되네요&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;취업을 하고, 첫 직장이지만... 인정받고 연봉이 짧은 기간 두번의 인상이 있었습니다. 저는 더 잘하고 싶고... 더욱 열심히 살아가야 겠습니다&lt;/span&gt;&lt;/p&gt;</description>
      <category>Dairy/Life Memo</category>
      <category>6개월 회고</category>
      <category>더 잘하고싶다!!!!</category>
      <category>신입 iOS개발자</category>
      <author>HyeonGyu IM</author>
      <guid isPermaLink="true">https://memohg.tistory.com/138</guid>
      <comments>https://memohg.tistory.com/138#entry138comment</comments>
      <pubDate>Mon, 4 Oct 2021 16:47:41 +0900</pubDate>
    </item>
    <item>
      <title>[iOS] URL Scheme 다루기, 호출 메서드 2개 처리 방법</title>
      <link>https://memohg.tistory.com/137</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://celsiusnotes.com/url-schemes-in-ios/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://celsiusnotes.com/url-schemes-in-ios/&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1632731277724&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;Custom URL Schemes in iOS&quot; data-og-description=&quot;URL schemes are essentially just specially formatted URLs linking to content within your app. You can use URL schemes in your iOS (and also macOS) apps to implement deep-linking and also to give third-party apps the ability to open your app. You could, for&quot; data-og-host=&quot;celsiusnotes.com&quot; data-og-source-url=&quot;https://celsiusnotes.com/url-schemes-in-ios/&quot; data-og-url=&quot;http://celsiusnotes.com/url-schemes-in-ios/&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://celsiusnotes.com/url-schemes-in-ios/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://celsiusnotes.com/url-schemes-in-ios/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Custom URL Schemes in iOS&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;URL schemes are essentially just specially formatted URLs linking to content within your app. You can use URL schemes in your iOS (and also macOS) apps to implement deep-linking and also to give third-party apps the ability to open your app. You could, for&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;celsiusnotes.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일반적인 URL Schemes핸들링의 경우 다수의 블로그에서 13버전 이상의 SceneDelegate에서 호출되는 메서드에 대해서 설명을 잘 안해주더라구요&lt;br /&gt;&lt;br /&gt;위의 글에서는 호출되는 메서드 두가지에 대해 설명하고 있으니 살펴보시면 아실수 있습니다 ㅎㅎ&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;- 앱이 작동중이지 않을 때 호출되는 메서드&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1632732382143&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions)&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;- 앱이 백그라운드 또는 포그라운드 상태에서 호출되는 메서드&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1632732450172&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;func scene(_ scene: UIScene, openURLContexts URLContexts: Set&amp;lt;UIOpenURLContext&amp;gt;)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>IOS/iOS</category>
      <author>HyeonGyu IM</author>
      <guid isPermaLink="true">https://memohg.tistory.com/137</guid>
      <comments>https://memohg.tistory.com/137#entry137comment</comments>
      <pubDate>Mon, 27 Sep 2021 17:48:04 +0900</pubDate>
    </item>
  </channel>
</rss>