<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>개발 세발</title>
    <link>https://developthreefeet.tistory.com/</link>
    <description></description>
    <language>ko</language>
    <pubDate>Sun, 19 Jul 2026 01:21:21 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>yunzema</managingEditor>
    <image>
      <title>개발 세발</title>
      <url>https://tistory1.daumcdn.net/tistory/3336400/attach/86e67eaaf7804b26812c7a77a8c07749</url>
      <link>https://developthreefeet.tistory.com</link>
    </image>
    <item>
      <title>Android Audio Focus 관련</title>
      <link>https://developthreefeet.tistory.com/15</link>
      <description>&lt;p id=&quot;SE-6df6c735-70cc-4e4f-b5ac-b98eb0014dc5&quot;&gt;&lt;span&gt;구급대원 폭행방지 어플을 어느정도 마무리하고 테스트하는 중간에 발생한 에러로,&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-1546ae1d-4ac5-4594-bedf-033660c06eca&quot;&gt;&lt;span&gt;잘만 실행되던 오디오가 다른 앱(예: Youtube같은 미디어플레이어를 사용하는 어플)을 사용하고나면 경고안내방송을 요청해도 소리가 나지 않는 문제가 발생했다.&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-79e30ab0-7864-4617-af6a-8d84e14d0ff0&quot;&gt;&lt;span&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-a08d057e-35a2-45bb-89a4-c5e20bf0d8e5&quot;&gt;&lt;span&gt;Audio Focus를 관리해줬어야하는데, 우선 개념부터 확인하자면&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-03d633d1-7955-4034-bc4d-e10286c9ce97&quot;&gt;&lt;span&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-792ee33a-1930-4b2c-830a-23376bbfac90&quot;&gt;&lt;span&gt;만약 Audio Focus가 없다면 사용자가 음악앱으로 음악을 듣고 있다가 알람이 울리면 두소리가 같이 송출되어 듣기 거부감이 드는 상황이 생긴다. 그래서 음악앱이 실행되는 중에 알람이 울린다면 음악앱을 중지할 수있게 나온 것이 Audio Focus이다. &lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-9564739a-d643-4690-9632-5512811ce931&quot;&gt;&lt;span&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-e8b0c6f3-7255-4f7e-9654-d1cc7832bdfc&quot;&gt;&lt;span&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Audio Focus에는 획득이나 상실되는 상황이 생기는데 아래와같다.&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td colspan=&quot;1&quot; rowspan=&quot;1&quot;&gt;
&lt;p id=&quot;SE-0b9f40c2-ee0a-4193-9536-0d282aa01fba&quot;&gt;획득하는 상황&lt;/p&gt;
&lt;/td&gt;
&lt;td colspan=&quot;1&quot; rowspan=&quot;1&quot;&gt;
&lt;p id=&quot;SE-583b9b4a-28ee-46db-ab94-cb16bb3f6001&quot;&gt;상실하는 상황&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td colspan=&quot;1&quot; rowspan=&quot;1&quot;&gt;
&lt;p id=&quot;SE-74eff3fa-999f-4917-8f3f-4d88e91b0658&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;AUDIOFOCUS_GAIN&lt;/span&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;td colspan=&quot;1&quot; rowspan=&quot;1&quot;&gt;
&lt;p id=&quot;SE-ce4c0c8c-dc65-4455-b24e-62f7366fa7ac&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;AUDIOFOCUS_LOSS&lt;/span&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td colspan=&quot;1&quot; rowspan=&quot;1&quot;&gt;
&lt;p id=&quot;SE-58f14045-38c2-41b4-b754-d5e08072881f&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;AUDIOFOCUS_GAIN_TRANSIENT&lt;/span&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;td colspan=&quot;1&quot; rowspan=&quot;1&quot;&gt;
&lt;p id=&quot;SE-1cbd0efd-1258-40b4-9057-f3ab8b385c4a&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;AUDIOFOCUS_LOSS_TRANSIENT&lt;/span&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td colspan=&quot;1&quot; rowspan=&quot;1&quot;&gt;
&lt;p id=&quot;SE-b0ccc6b8-1fff-4d47-bce0-354d707af643&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK&lt;/span&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;td colspan=&quot;1&quot; rowspan=&quot;1&quot;&gt;
&lt;p id=&quot;SE-f5b2c5b0-5f7f-40b3-acfd-20b135d3a457&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK&lt;/span&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 668px;&quot; border=&quot;1&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 54px;&quot;&gt;
&lt;td style=&quot;height: 54px;&quot; colspan=&quot;1&quot; rowspan=&quot;1&quot;&gt;
&lt;p id=&quot;SE-54c73ef9-19e0-468a-b6ad-78257fdf745e&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;포커스 변경 종류&lt;/span&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;td style=&quot;height: 54px;&quot; colspan=&quot;1&quot; rowspan=&quot;1&quot;&gt;
&lt;p id=&quot;SE-da7d17a8-a2cb-4af5-8f30-213b778ce50b&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;적절한 행동&lt;/span&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 151px;&quot;&gt;
&lt;td style=&quot;height: 151px;&quot; colspan=&quot;1&quot; rowspan=&quot;1&quot;&gt;
&lt;p id=&quot;SE-21980b77-dfe2-4dff-b84f-c333f3a46712&quot;&gt;&lt;span&gt;&lt;a href=&quot;http://developer.android.com/reference/android/media/AudioManager.html#AUDIOFOCUS_GAIN&quot;&gt;AUDIOFOCUS_GAIN&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;td style=&quot;height: 151px;&quot; colspan=&quot;1&quot; rowspan=&quot;1&quot;&gt;
&lt;p id=&quot;SE-d0f6f693-17fa-4d50-a86c-85d7805895c5&quot;&gt;&lt;span&gt;&lt;b&gt;상실 이벤트 후 획득 이벤트. &lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-d16305cc-22a4-45ac-a07f-fab98afc4e9a&quot;&gt;&lt;span&gt;애플리케이션에 의해 설정된 다른 상태가 없다면 재생을 재개한다.&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-1eae8099-0c91-41ff-84ee-97818a5a792a&quot;&gt;&lt;span&gt;예를 들어 상실 이베트 이전에 사용자가 명시적으로 일시 정지한 경우.&lt;/span&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 54px;&quot;&gt;
&lt;td style=&quot;height: 54px;&quot; colspan=&quot;1&quot; rowspan=&quot;1&quot;&gt;
&lt;p id=&quot;SE-2ba0e3c2-eb90-4943-af7d-28402452f732&quot;&gt;&lt;span&gt;&lt;a href=&quot;http://developer.android.com/reference/android/media/AudioManager.html#AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK&quot;&gt;AUDIOFOCUS_&lt;/a&gt;&lt;/span&gt;&lt;span&gt;GAIN_TRANSIENT&lt;/span&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;td style=&quot;height: 54px;&quot; colspan=&quot;1&quot; rowspan=&quot;1&quot;&gt;
&lt;p id=&quot;SE-dbb18dc8-7ddd-4cdf-adb3-3fc0237cfc87&quot;&gt;&lt;span&gt;짧은 시간 포커스 확보 필요시 사용&lt;/span&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 102px;&quot;&gt;
&lt;td style=&quot;height: 102px;&quot; colspan=&quot;1&quot; rowspan=&quot;1&quot;&gt;
&lt;p id=&quot;SE-aa62840a-8f06-472f-b3d2-04a8ef029dc6&quot;&gt;&lt;span&gt;&lt;a href=&quot;http://developer.android.com/reference/android/media/AudioManager.html#AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK&quot;&gt;AUDIOFOCUS_&lt;/a&gt;&lt;/span&gt;&lt;span&gt;GAIN_TRANSIENT_MAY_DUCK&lt;/span&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;td style=&quot;height: 102px;&quot; colspan=&quot;1&quot; rowspan=&quot;1&quot;&gt;
&lt;p id=&quot;SE-3c57077d-4f51-4606-8636-999b208f08a2&quot;&gt;&lt;span&gt;해당플래그로 포커스 확보 시 포커스가 확보된 앱을 제외한 현재 미디어 재생 중인 앱의 볼륨이 줄어든다. - 기존에 재생중인 미디어의 볼륨만 줄이고싶을 때 사용&lt;/span&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 54px;&quot;&gt;
&lt;td style=&quot;height: 54px;&quot; colspan=&quot;1&quot; rowspan=&quot;1&quot;&gt;
&lt;p id=&quot;SE-b76f3d93-dc19-4bd8-b5be-84f9528cac6c&quot;&gt;&lt;span&gt;&lt;a href=&quot;http://developer.android.com/reference/android/media/AudioManager.htmCUS_LOSS&quot;&gt;AUDIOFOCUS_LOSS&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;td style=&quot;height: 54px;&quot; colspan=&quot;1&quot; rowspan=&quot;1&quot;&gt;
&lt;p id=&quot;SE-2fd5f1e6-3397-49d8-b1f6-61f9718612f9&quot;&gt;&lt;span&gt;재생을 정지한다. 에셋을 해제한다.&lt;/span&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 151px;&quot;&gt;
&lt;td style=&quot;height: 151px;&quot; colspan=&quot;1&quot; rowspan=&quot;1&quot;&gt;
&lt;p id=&quot;SE-295800cd-c2ad-48af-9b0d-3e9be5c19591&quot;&gt;&lt;span&gt;&lt;a href=&quot;http://developer.android.com/reference/android/media/AudioManager.html#AUDIOFOCUS_LOSS_TRANSIENT&quot;&gt;AUDIOFOCUS_LOSS_TRANSIENT&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;td style=&quot;height: 151px;&quot; colspan=&quot;1&quot; rowspan=&quot;1&quot;&gt;
&lt;p id=&quot;SE-cae11587-2b80-460d-85d8-b3df6e3b7b21&quot;&gt;&lt;span&gt;재생을 일시정지하고 상실이 일시적이란 것의 상태를 유지한다. &lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-d0d2ca1a-78e9-49bb-b56a-89c119fea7dd&quot;&gt;&lt;span&gt;AUDIOFOCUS_GAIN 이벤트가 나타나면 적절히 재생을 재개할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-507130fa-c1a6-4169-a4b9-64af8e4c08b2&quot;&gt;&lt;span&gt;에셋을 해제하지 마라.&lt;/span&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 102px;&quot;&gt;
&lt;td style=&quot;height: 102px;&quot; colspan=&quot;1&quot; rowspan=&quot;1&quot;&gt;
&lt;p id=&quot;SE-945684bf-d572-4ad6-8d61-2bb99ba34c57&quot;&gt;&lt;span&gt;&lt;a href=&quot;http://developer.android.com/reference/android/media/AudioManager.html#AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK&quot;&gt;AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;td style=&quot;height: 102px;&quot; colspan=&quot;1&quot; rowspan=&quot;1&quot;&gt;
&lt;p id=&quot;SE-685ed9b4-c95d-46e8-baf1-eb90995ee5c1&quot;&gt;&lt;span&gt;볼륨을 줄이거나 재생을 일시정지한다.&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-8dbe2536-9f48-45d0-9c26-b89a22f4a105&quot;&gt;&lt;span&gt;AUDIOFOCUS_LOSS_TRANSIENT의 상태를 저장한다. 애셋을 해제하지 마라.&lt;/span&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p id=&quot;SE-6a2453f4-8538-4469-a4ce-84b391620901&quot;&gt;&lt;span&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-90a0f01d-35e1-4f9e-9df1-0737a40a3a1e&quot;&gt;&lt;span&gt;요청할 때는 위의 [GAIN]에 정의된 것 중에 하나를 사용해서 요청하고, 앱의 AudioFocus를 잃었을 때는 [LOSS]에 정의한 것이 리스너에게 전달되니 거기에 맞춰서 동작해야한다.&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-3869b756-366f-409e-a9fb-e774639322c3&quot;&gt;&lt;span&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-ac35d837-d758-439e-8c46-a8eb068c7a56&quot;&gt;&lt;span&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-d35bcfde-f673-4d79-b8d5-ab084530dc71&quot;&gt;&lt;span&gt;중요한 부분만 정리해놓은 것이니 자세히 알고싶다면 아래의 참고자로를 보셈.&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-d5790698-b96d-46b3-804d-2272a1729405&quot;&gt;&lt;span&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-9a7afdd0-8393-4b04-8545-74395f327c68&quot;&gt;&lt;span&gt;참고자료&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-52d398bf-11d6-480b-8079-7ea5b5005acb&quot;&gt;&lt;span&gt;&lt;a href=&quot;http://blog.daum.net/creazier/15310433&quot;&gt;http://blog.daum.net/creazier/15310433&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;</description>
      <category>개발/Android</category>
      <author>알 수 없는 사용자</author>
      <guid isPermaLink="true">https://developthreefeet.tistory.com/15</guid>
      <comments>https://developthreefeet.tistory.com/15#entry15comment</comments>
      <pubDate>Mon, 17 Feb 2020 12:27:19 +0900</pubDate>
    </item>
    <item>
      <title>웹뷰(webview) https 에러, ERR_CLEARTEXT_NOT_PERMITTED</title>
      <link>https://developthreefeet.tistory.com/14</link>
      <description>&lt;p&gt;안드로이드 웹뷰에서 'https://blrablra' 형태의 url이 http로 이동되어, https 만 이동 가능한 안드로이드 OS 9 이상 버전의 기기에서 흰 페이지와 함께 'ERR_CLEARTEXT_NOT_PERMITTED' 가 발생하는 에러입니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;매니페스트 application 태그에&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;android:usesCleartextTraffic=&quot;true&quot; 를 추가하면 해결됩니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;amp;fname=https%3A%2F%2Fk.kakaocdn.net%2Fdn%2FbCE3ua%2FbtqBDbrrMxo%2F7pVstEQ2hpSCkvCoVdgSxk%2Fimg.jpg&quot; data-origin-width=&quot;540&quot; data-origin-height=&quot;960&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/13yUD/btqBE1b5wRR/KpbIK3kCeZn3X550pxgugk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/13yUD/btqBE1b5wRR/KpbIK3kCeZn3X550pxgugk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/13yUD/btqBE1b5wRR/KpbIK3kCeZn3X550pxgugk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fk.kakaocdn.net%2Fdn%2FbCE3ua%2FbtqBDbrrMxo%2F7pVstEQ2hpSCkvCoVdgSxk%2Fimg.jpg&quot; data-origin-width=&quot;540&quot; data-origin-height=&quot;960&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&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>개발/Android</category>
      <author>책 읽는 개발자_테드</author>
      <guid isPermaLink="true">https://developthreefeet.tistory.com/14</guid>
      <comments>https://developthreefeet.tistory.com/14#entry14comment</comments>
      <pubDate>Sun, 2 Feb 2020 11:18:22 +0900</pubDate>
    </item>
    <item>
      <title>Firebase FCM 에러, AndroidRuntimeException: Calling Activity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag.</title>
      <link>https://developthreefeet.tistory.com/13</link>
      <description>&lt;p&gt;android 9 이상버전에서 FCM 메세지를 받고, Service에서 새로운 Activity를 생성할때 제목의 메세지와 함께 액티비티가 강제 종료되는 오류가 발생했다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Activity를 생성할때 아래와 같이 intent에 addFlags 메소드를 실행해주면 해결된다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;intent.addFlags(&lt;span&gt;FLAG_ACTIVITY_NEW_TASK&lt;/span&gt;);&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;amp;fname=https%3A%2F%2Fk.kakaocdn.net%2Fdn%2FbqEOuP%2FbtqBFL61Aod%2FLlPMlQiGT2xKKdNtkiIP81%2Fimg.jpg&quot; data-origin-width=&quot;540&quot; data-origin-height=&quot;960&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c3Q8tT/btqBGZYqJYj/kXlSlteKT7gZX8nOhdYgGK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c3Q8tT/btqBGZYqJYj/kXlSlteKT7gZX8nOhdYgGK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c3Q8tT/btqBGZYqJYj/kXlSlteKT7gZX8nOhdYgGK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fk.kakaocdn.net%2Fdn%2FbqEOuP%2FbtqBFL61Aod%2FLlPMlQiGT2xKKdNtkiIP81%2Fimg.jpg&quot; data-origin-width=&quot;540&quot; data-origin-height=&quot;960&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&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>개발/Android</category>
      <author>책 읽는 개발자_테드</author>
      <guid isPermaLink="true">https://developthreefeet.tistory.com/13</guid>
      <comments>https://developthreefeet.tistory.com/13#entry13comment</comments>
      <pubDate>Sun, 2 Feb 2020 11:17:34 +0900</pubDate>
    </item>
    <item>
      <title>스프링 관련 용어 - Ioc/DI</title>
      <link>https://developthreefeet.tistory.com/12</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Ioc(Inversion of control)란?&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;span style=&quot;color: #000000;&quot;&gt;-IoC(제어의 역전)이란&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;프로그램의 제어 흐름 구조가 뒤바뀌는 것&lt;/b&gt;이다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;일반적으로 프로그램의 흐름은 main() 메소드와 같이 프로그램이 시작되는 지점에서 다음에 사용할 오브젝트를 결정하고, 결정한 오브젝트를 생성하고, 만들어진오브젝트에 있는 메소드를 호출하고, 그 오브젝트 메소드 안에서 다음에 사용할 것을 결정하고 호출하는 식의 작업이 반복된다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;제어의 역전이란 이런 제어 흐름의 개념을 거꾸로 뒤집는 것이다.&lt;b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;오브젝트가 자신이 사용할 오브젝트를 스스로 선택하지 않는다. 당연히 생성하지도 않는다. 또 자신도 어떻게 만들어지고 어디서 사용되는지를 알 수 없다. 모든 제어 권한을 자신이 아닌 다른 대상에게 위임하기 때문이다.&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;스프링에서는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;application context라고하는 IoC 컨테이너&lt;/b&gt;를 통해 IoC를 관리한다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #000000;&quot;&gt;-스프링은 IoC를 모든 기능의 기초가 되는 기반기술로 삼고 있으며, IoC를 극한까지 적용하고 있는 프레임워크다. 스프링의&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;대표적인 IoC 동작원리로 DI(dependency Injection)이 있다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;408&quot; data-origin-height=&quot;217&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bhw7nd/btqBlzyLEcW/cAXmFlyVTNdUkUcJGVOCk1/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bhw7nd/btqBlzyLEcW/cAXmFlyVTNdUkUcJGVOCk1/img.gif&quot; data-alt=&quot;출처:http://www.ytechie.com/2008/06/i-finally-get-the-point-of-inversion-of-control/&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bhw7nd/btqBlzyLEcW/cAXmFlyVTNdUkUcJGVOCk1/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/bhw7nd/btqBlzyLEcW/cAXmFlyVTNdUkUcJGVOCk1/img.gif&quot; data-origin-width=&quot;408&quot; data-origin-height=&quot;217&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;figcaption&gt;출처:http://www.ytechie.com/2008/06/i-finally-get-the-point-of-inversion-of-control/&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #000000;&quot;&gt;-&lt;b&gt;프레임워크는 제어의 역전 개념이 적용된 대표적인 기술&lt;/b&gt;이다. 프레임워크는 단지 미리 만들어둔 반제품이나 확장해서 사용할 수있도록 준비된 추상 라이브러리의 집합이 아니다. 라이브러리를 사용하는 애플리케이션 코드는 애플리케이션 흐름을 직접 제어한다. 반면에&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;프레임워크는 거꾸로 애플리케이션 코드가 프레임워크에 의해 사용된다&lt;/b&gt;. 보통 프레임워크 위에 개발된 클래스를 등록해두고, 프레임워크가 흐름을 주도하는 중에 개발자가 만들 애플리케이션 코드를 사용하도록 만드는 방식이다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;419&quot; height=&quot;178&quot; data-origin-width=&quot;640&quot; data-origin-height=&quot;272&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/UBG9p/btqBlAj8UD9/96TIP1D0XVEoV0q1sBaArk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/UBG9p/btqBlAj8UD9/96TIP1D0XVEoV0q1sBaArk/img.png&quot; data-alt=&quot;출처:https://www.programcreek.com/2011/09/what-is-the-difference-between-a-java-library-and-a-framework/&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/UBG9p/btqBlAj8UD9/96TIP1D0XVEoV0q1sBaArk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FUBG9p%2FbtqBlAj8UD9%2F96TIP1D0XVEoV0q1sBaArk%2Fimg.png&quot; width=&quot;419&quot; height=&quot;178&quot; data-origin-width=&quot;640&quot; data-origin-height=&quot;272&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;figcaption&gt;출처:https://www.programcreek.com/2011/09/what-is-the-difference-between-a-java-library-and-a-framework/&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;-IoC를 사용하는 이유: 작성중&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;DI(Dependency Injection) 란?&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #000000;&quot;&gt;-의존관계 주입, 의존관계 설정이라는 의미이다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #000000;&quot;&gt;-스프링 IoC 기능의 대표적인 동작원리이다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #000000;&quot;&gt;-&lt;b&gt;DI는 오브젝트 레퍼런스를 외부로부터 제공(주입)받고 이를 통해 여타 오브젝트와 다이나믹하게 의존관계가 만들어지는 것이다&lt;/b&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;487&quot; data-origin-height=&quot;264&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xZyQb/btqBly0Vw6r/sWx9WO3vLcHyq9Cbv8YUw0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xZyQb/btqBly0Vw6r/sWx9WO3vLcHyq9Cbv8YUw0/img.jpg&quot; data-alt=&quot;출처:https://www.codeproject.com/Articles/592372/Dependency-Injection-DI-vs-Inversion-of-Control-IO&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xZyQb/btqBly0Vw6r/sWx9WO3vLcHyq9Cbv8YUw0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxZyQb%2FbtqBly0Vw6r%2FsWx9WO3vLcHyq9Cbv8YUw0%2Fimg.jpg&quot; data-origin-width=&quot;487&quot; data-origin-height=&quot;264&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;figcaption&gt;출처:https://www.codeproject.com/Articles/592372/Dependency-Injection-DI-vs-Inversion-of-Control-IO&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;의존관계란?&lt;/span&gt;&lt;/b&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;span style=&quot;color: #000000;&quot;&gt;-의존 관계란 한쪽의 변화가 다른 쪽에 영향을 주는 것이다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #000000;&quot;&gt;-인터페이스를 통해 의존관계를 제한해주면 그만큼 변경에서 자유로워질 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Application Context란?&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;span style=&quot;color: #000000;&quot;&gt;-스프링 애플리케이션 전반에 걸쳐 모든 구성요소의 제어 작업을 담당하는&lt;b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;IoC 엔진&lt;/b&gt;이다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;-IoC 방식을 따라 만들어진 일종의 빈 팩토리이다. 빈 팩토리라고 말할 때는 빈을 생성하고 관계를 설정하는 IoC의 기본 기능에 초점을 맞춘 것이고, 애플리케이션 컨텍스트는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;별도의 정보를 참고해서 빈의 생성, 관계설정 등의 제어를 총괄&lt;/b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;한다.&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #000000;&quot;&gt;-싱글톤을 저장하고 관리하는&lt;b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;싱글톤 레지스트리&lt;/b&gt;이다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;스프링은 기본적으로 별다른 설정을 하지 않으면 내부에서 생성하는 빈 오브젝트를 모두 싱글톤으로 만든다&lt;/b&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;매번 클라이언트에서 요청이 올 때마다 각 로직을 담당하는 오브젝트를 새로 만들어서 사용한다고 생각해보자 요청 한 번에 5개의 오브젝트가 새로 만들어지고 초당 500개의 요청이 들어오면, 초당 2500개의 새로운 오브젝트가 생성된다. 서버가 감당하기 힘들다. 그래서 필요한 것이 싱글톤이다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Bean Factory란?&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;span style=&quot;color: #000000;&quot;&gt;-빈의 생성과 관계설정 같은 제어를 담당하는 IoC 오브젝트이다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Bean&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이란?&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;span style=&quot;color: #000000;&quot;&gt;-스프링에서는 스프링이 제어권을 가지고 직접 만들고 관계를 부여하는 오브젝트를 Bean이라고 부른다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #000000;&quot;&gt;-스프링에서 빈 등록은 XML, 자바 코드(애너테이션)를 통해 할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;출처:토비의 스프링&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>개발/Spring</category>
      <category>application context</category>
      <category>bean</category>
      <category>bean factory</category>
      <category>DI</category>
      <category>IOC</category>
      <category>spring</category>
      <author>책 읽는 개발자_테드</author>
      <guid isPermaLink="true">https://developthreefeet.tistory.com/12</guid>
      <comments>https://developthreefeet.tistory.com/12#entry12comment</comments>
      <pubDate>Sun, 19 Jan 2020 01:17:36 +0900</pubDate>
    </item>
    <item>
      <title>서블릿 컨테이너(Servlet Container)란?</title>
      <link>https://developthreefeet.tistory.com/11</link>
      <description>&lt;p&gt;잘 정리된 글이 있어 의역해봅니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;출처입니다.&lt;a href=&quot;https://www.programcreek.com/2013/04/what-is-servlet-container/&quot;&gt;https://www.programcreek.com/2013/04/what-is-servlet-container/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;이 글에서는 웹 서버, 서블릿 컨테이너 그리고 이것들과 JVM과의 관계를 일반적인 생각을 적습니다. 서블릿 컨테이너는 자바 프로그램에 불과하다는 걸 보여주고 싶었습니다.&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;1. 웹서버란? - &lt;span style=&quot;color: #333333;&quot;&gt;웹페이지를 사용자에게 전송&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;서블릿 컨테이너를 알기전에 웹서버에 대한 이해가 먼저 필요합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;535&quot; height=&quot;211&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/sHi3g/btqA2VYbgS8/qIrev9LZiF551XJ0usBAZ0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/sHi3g/btqA2VYbgS8/qIrev9LZiF551XJ0usBAZ0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/sHi3g/btqA2VYbgS8/qIrev9LZiF551XJ0usBAZ0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FsHi3g%2FbtqA2VYbgS8%2FqIrev9LZiF551XJ0usBAZ0%2Fimg.jpg&quot; width=&quot;535&quot; height=&quot;211&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&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&gt;웹서버는 데이터를 전송하기 위해 HTTP 프로토콜을 사용합니다. 일반적인 상황에서 사용자는 브라우저에 URL&lt;span style=&quot;color: #333333;&quot;&gt;(e.g.&lt;/span&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;a href=&quot;http://www.programcreek.com/static.html)&quot;&gt;www.programcreek.com/static.html)&lt;/a&gt;&lt;span style=&quot;color: #333333;&quot;&gt; 을 입력하고 웹페이지를 얻게 됩니다. 웹서버가 하는 일은 웹페이지를 사용자에게 전송하는 것입니다. 변화하는 것은 HTTP 프로토콜에서 형식이 지정되는 요청과 반응 메세지입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;1. 서블릿 컨테이너란? - &lt;b&gt;서블릿 컨테이너는 서블릿들의 생성, 실행, 파괴를 담당&lt;/b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;여기서 볼 수 있듯이, 사용자는 서버에서 오직 정적인 웹페이지만 요청할 수 있습니다. 만약 사용자가 본인의 입력을 기초로한 웹 페이지를 보고 싶다면 이 방법은 충분하지 않습니다. 서블릿 컨테이너의 일반적인 아이디어는 서버 사이드에서 동적으로 웹 페이지를 생성하기 위해 자바를 사용하는 겁니다. 때문에 웹서버와 서블릿들이 상호작용할 때 서블릿 컨테이너는 필수적인 부분입니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;535&quot; height=&quot;211&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b3P5Aq/btqA4z8dKlc/cgrUQm7UCstEvzPV8jajlK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b3P5Aq/btqA4z8dKlc/cgrUQm7UCstEvzPV8jajlK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b3P5Aq/btqA4z8dKlc/cgrUQm7UCstEvzPV8jajlK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb3P5Aq%2FbtqA4z8dKlc%2FcgrUQm7UCstEvzPV8jajlK%2Fimg.jpg&quot; width=&quot;535&quot; height=&quot;211&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&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&gt;서블릿 컨테이너는 서블릿들을 위한 상자(Container) 입니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;3. 서블릿이란? - &lt;b&gt;javax.servlet package에 정의된 인터페이스, 요청을 처리함&lt;/b&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;b&gt;서블릿이란 javax.servlet package에 정의된 인터페이스&lt;/b&gt;입니다. 이것은 &lt;b&gt;서블릿의 라이프 사이클을 위한 세 가지 필수적인 메소드&lt;/b&gt;들을 정의합니다 -&lt;b&gt;init(), service(), destroy()&lt;/b&gt;. 이 메소드들은 모든 서블릿(SDK에서 정의 되거나, 자체적으로 정의된)에 의해 구현되고, 특정 시간에 서버에 의해 호출됩니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;1. init() - 해당 메소드는 서블릿 생명 주기중 &lt;b&gt;초기화 단계&lt;/b&gt;에 호출됩니다. &lt;span&gt;&lt;b&gt;javax.servlet.ServletConfig 인터페이스를 구현하는 오브젝트가 전달&lt;/b&gt;되며, 이를 통해 &lt;b&gt;서블릿이 웹 애플리케이션에서 초기화 매개변수(parameter)에 접근&lt;/b&gt;할 수 있도록 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;2. service() - 해당 메소드는 초기화 이후 각각의 &lt;b&gt;요청들이 들어오면 호출&lt;/b&gt;됩니다. 각각의 요청들은 별도로 나누어진 스레드에서 처리됩니다.&lt;/p&gt;
&lt;p&gt;웹 컨테이너는 모든 요청에 대해 서블릿의 service() 메소드를 요청합니다. service() 메소드는 요청의 종류를 판별하고 요청을 처리할 적절한 메소드로 전달합니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;3. destroy() - 해당 메소드는 &lt;b&gt;서블릿 객체가 파괴되어야할 때 호출&lt;/b&gt;됩니다. 해당 서블릿이 가지고 있던 자원(메모리)을 풀어(release)줍니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;서블릿 객체의 생명 주기에서 서블릿 클래스가 클래스 로더에 의해 컨테이너에 동적으로 로드되는 것을 볼 수 있습니다. 각 요청은 자체적인 스레드에 있으며, 서블릿 객체는 동시에 여러개의 스레드를 제공할 수 있습니다(thread not safe). 더 이상 사용되지 않을 때는, JVM에 의해 가비지 컬렉팅 되어야합니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;다른 자바 프로그램처럼, 서블릿들은 JVM 내부에서 작동합니다. &lt;span style=&quot;color: #333333;&quot;&gt;HTTP 요청들의 복잡성을 처리하기 위해서 서블릿 컨테이너가 제공됩니다.&amp;nbsp; &lt;b&gt;서블릿 컨테이너는 서블릿들의 생성, 실행, 파괴를 담당합니다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;#&lt;b&gt;thread not safe&lt;/b&gt;란 &lt;span style=&quot;color: #333333;&quot;&gt;코드가 다른 스레드에 의해 상태가 변경될 수 있음을 의미합니다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;4. 서블릿 컨테이너와 웹서버는 어떻게 요청을 처리할까?&lt;/b&gt;&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;웹서버가 HTTP 요청을 받습니다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;웹서버는 요청을 서블릿 컨테이너로 전달합니다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;서블릿이 컨테이너에 없다면,&amp;nbsp; 서블릿을 동적으로 검색하여 컨테이너의 주소 공간에 로드합니다&lt;/li&gt;
&lt;li&gt;컨테이너가 서블릿의 init() 메소드를 호출하면, 서블릿이 초기화 됩니다(서블릿이 처음 로드됬을 때 한번만 호출됩니다).&lt;/li&gt;
&lt;li&gt;컨테이너가 서블릿의 service() 메소드를 호출하여 HTTP 요청을 처리합니다(예: 요청의 데이터를 읽고, 응답을 만들어냅니다.). 서블릿은 컨테이너 주소에 남아있고, 다른 HTTP 요청들을 처리할 수 있습니다.&lt;/li&gt;
&lt;li&gt;웹서버는 동적으로 생성된 결과를 올바른 위치에 반환합니다.&amp;nbsp;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;위의 여섯 단계는 다음에 보이는 다이어그램에 표시되어 있습니다:&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;471&quot; height=&quot;268&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/buuO0t/btqA6Em8ADL/oXojKgGBWWAlDfkbg27ofk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/buuO0t/btqA6Em8ADL/oXojKgGBWWAlDfkbg27ofk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/buuO0t/btqA6Em8ADL/oXojKgGBWWAlDfkbg27ofk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbuuO0t%2FbtqA6Em8ADL%2FoXojKgGBWWAlDfkbg27ofk%2Fimg.jpg&quot; width=&quot;471&quot; height=&quot;268&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&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 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;5. JVM의 역할은? - &lt;b&gt;각 요청을 분리된 자바 스레드 내부에서 처리&lt;/b&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;b&gt;서블릿을 사용하는 것은 JVM이 각 요청을 분리된 자바 스레드 내부에서 처리&lt;/b&gt;하도록 하며, 이는 서블릿 컨테이너의&amp;nbsp; 주요 장점 중 하나입니다. 각 서블릿은 HTTP 요청에 응답하는 특한 요소들이 있는 자바 클래스입니다. 서블릿 컨테이너의 가장 중요한 기능은 요청을 올바른 서블릿에&amp;nbsp; 전달해서 처리되도록 하고, JVM이 해당 요청을 처리한 후에는 생성된 결과를 올바른 장소에 동적으로 반환해주는 것입니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;대부분의 사례에 서블릿 컨테이너는 하나의 JVM에서 동작합니다. 하지만 컨테이너가 여러개의 JVM들을 필요로하는 문제들도 존재합니다.&lt;/p&gt;
&lt;p&gt;From&amp;nbsp;&lt;a href=&quot;http://www.programcreek.com/2013/04/what-is-servlet-container/&quot;&gt;Program Creek&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;출처&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.programcreek.com/2013/04/what-is-servlet-container/&quot;&gt;https://www.programcreek.com/2013/04/what-is-servlet-container/&lt;/a&gt;&lt;/p&gt;</description>
      <category>개발/Java</category>
      <author>책 읽는 개발자_테드</author>
      <guid isPermaLink="true">https://developthreefeet.tistory.com/11</guid>
      <comments>https://developthreefeet.tistory.com/11#entry11comment</comments>
      <pubDate>Sat, 11 Jan 2020 17:23:12 +0900</pubDate>
    </item>
    <item>
      <title>MySQL / MariaDB 서브 쿼리 내의 order by 안 되는 현상 + 해결법</title>
      <link>https://developthreefeet.tistory.com/10</link>
      <description>&lt;p&gt;작업을 하다 보면 다루어야 할 데이터도 많아지고, 테이블도 많아집니다.&lt;/p&gt;
&lt;p&gt;그에 따라서 사용하는 쿼리문이 길어지기도 합니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;쿼리가 길어지다 보면 과거 심플하던 시절에는 없던 문제가 생기기도 하는데, 이번에 제가 발견한 케이스가 있어 공유하고자 합니다.&lt;/p&gt;
&lt;p&gt;사용했던 쿼리의 형태는 아래와 같았습니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;3개의 테이블을 A 테이블의 m_id를 중심으로 join하고, 그 결과값을 원하는 기준으로 정렬한 후에 특정 컬럼을 기준으로 group하는 쿼리입니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1578220996848&quot; class=&quot;html xml&quot; style=&quot;margin: 20px auto 0px; display: block; overflow: auto; padding: 15px; color: #383a42; background: #f6f7f8; font-size: 14px; border-radius: 3px; font-family: Menlo, Consolas, Monaco, monospace; border: 1px solid #dddddd; 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-style: initial; text-decoration-color: initial;&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;SELECT * FROM 

(SELECT A.m_id, A.name, B.gender, C.items FROM A 

JOIN B ON A.m_id = B.m_id 

JOIN C ON A.m_id = C.m_id 

ORDER BY A.regdt DESC ) AS RESULT 

GROUP BY RESULT.regdt &lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;아시다시피 group by는 테이블 내의 row들을 중복제거해주는 효과가 있는데, 공통되는 row가 있을 경우 그 테이블에서 가장 위의 row만 남기는 특성이 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;1344&quot; data-origin-height=&quot;580&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/UMNpP/btqAUvqS3Cb/ATBiVJcMf7OUPjIaVVnshK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/UMNpP/btqAUvqS3Cb/ATBiVJcMf7OUPjIaVVnshK/img.png&quot; data-alt=&quot;group by 결과&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/UMNpP/btqAUvqS3Cb/ATBiVJcMf7OUPjIaVVnshK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FUMNpP%2FbtqAUvqS3Cb%2FATBiVJcMf7OUPjIaVVnshK%2Fimg.png&quot; data-origin-width=&quot;1344&quot; data-origin-height=&quot;580&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;figcaption&gt;group by 결과&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;이런 느낌이죠.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;그래서 예를 들어 group by 를 할 때 맨 위에 위치한 데이터가 아니라 가장 최신의 row를 남기고 싶다면, group by 이전에 데이터의 정렬이 필요합니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;그래서 관련해서 검색을 해보면 위와 같은 쿼리를 쓰라는 자료들이 많습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;근데 아무리 해도 group by의 결과가 원하는 대로 정렬되어 나오지 않고 항상 똑같이 나와서 뭐지 해서 찾아보니, 아래와 같은 문서가 있었습니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://mariadb.com/kb/en/why-is-order-by-in-a-from-subquery-ignored/&quot;&gt;https://mariadb.com/kb/en/why-is-order-by-in-a-from-subquery-ignored/&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1578220996849&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot;&gt;&lt;a href=&quot;https://mariadb.com/kb/en/why-is-order-by-in-a-from-subquery-ignored/&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; style=&quot;position: relative; flex-grow: 1; height: 130px; padding-left: 40px;&quot;&gt;
&lt;p class=&quot;og-title&quot; style=&quot;line-height: 1.6; color: #000000; font-size: 22px; padding-bottom: 10px; max-width: 467px; text-overflow: ellipsis; white-space: nowrap; margin: 0px; overflow: hidden; font-family: 'Noto Sans', 'Noto Sans KR';&quot;&gt;Why is ORDER BY in a FROM Subquery Ignored?&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; style=&quot;line-height: normal; margin: 0px; max-width: 467px; text-overflow: ellipsis; overflow: hidden; font-family: 'Noto Sans DemiLight', sans-serif; font-size: 14px; font-weight: 300; font-style: normal; font-stretch: normal; letter-spacing: normal; color: #909090; max-height: 42px; -webkit-line-clamp: 2; -webkit-box-orient: vertical; display: -webkit-box;&quot;&gt;Query with ORDER BY in a FROM subquery produces an unordered result.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; style=&quot;line-height: 1.6; margin: 0px; position: absolute; bottom: -8px; font-family: AvenirNext; font-size: 14px; color: #909090;&quot;&gt;mariadb.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p&gt;요약하면 서브쿼리 내의 order by를 설정해도 효과가 없는 것이 맞다는 의미였는데요.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;그 이유는 SQL standard에서 정한 DB 테이블의 정의에서는, 테이블을 채우고 있는 데이터의 order는 아무런 의미가 없기 때문이라고 합니다.&lt;/p&gt;
&lt;p&gt;우리가 작성한 서브쿼리 역시 어떻게 보면 한 종류의 테이블이라고 볼 수 있기 때문에(테이블이니까 최상위 절에서 SELECT가 다시 한번 가능한 것이죠), 위와 같이 서브쿼리 내의 order by 명령어가 제대로 동작하지 않았던 것입니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;해결법은 2가지입니다.&lt;/p&gt;
&lt;p&gt;1. 서브쿼리 내의 order by 뒤에 limit를 걸어준다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;==&amp;gt; 의외로 간단하고 약간은 어이없는 해결책입니다. 서브쿼리 내에 limit를 걸어줄 경우 order by가 먹히는 이유는, limit를 걸게 되면 데이터의 순서뿐만 아니라 갯수까지 제한되에 테이블의 본질적인 내용이 변화된다고 보기에 mysql, mariaDB에는 order by가 적용된다고 합니다. 그러니까...&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1578220996850&quot; class=&quot;html xml&quot; style=&quot;margin: 20px auto 0px; display: block; overflow: auto; padding: 15px; color: #383a42; background: #f6f7f8; font-size: 14px; border-radius: 3px; font-family: Menlo, Consolas, Monaco, monospace; border: 1px solid #dddddd; 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-style: initial; text-decoration-color: initial;&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;SELECT * FROM 

(SELECT A.m_id, A.name, B.gender, C.items FROM A 

JOIN B ON A.m_id = B.m_id 

JOIN C ON A.m_id = C.m_id 

ORDER BY A.regdt DESC LIMIT 1000000 ) AS RESULT 

GROUP BY RESULT.regdt &lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이렇게 하면 서브 쿼리 내의 order by가 적용된다는 것이죠. 저도 limit를 붙임으로써 원하는 쿼리 결과물을 얻을 수 있었습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;2. 문서에서 권하는 두 번째 방식은 order by를 최상위 절로 옮기라는 것입니다. 평소에 쓰는 것처럼 쓰면 됩니다. 다만 저같은 경우에는 group by를 반드시 사용해야 했는데, 최상위 절에서 group by 앞에 order by를 쓸 경우 SQL error가 발생하고, 뒤에 order by를 쓸 경우에는 사용한다 해도 원하는 쿼리 결과물이 아니라서 어쩔 수 없이 배제되었습니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;오랜만에 글을 쓰려니까 참 어렵네요. 머리가 잘 돌아가지 않는 것도 같고...&lt;/p&gt;
&lt;p&gt;그래도 올해 목표 중 하나가 일주일에 1포스팅이라, 앞으로도 열심히 써 보겠습니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;-끝-&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://chisu.tistory.com/4&quot;&gt;https://chisu.tistory.com/4&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1578221037830&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-og-type=&quot;article&quot; data-og-title=&quot;MySQL / MariaDB 서브 쿼리 내의 order by 안 되는 현상 + 해결법&quot; data-og-description=&quot;작업을 하다 보면 다루어야 할 데이터도 많아지고, 테이블도 많아집니다. 그에 따라서 사용하는 쿼리문이 길어지기도 합니다. 쿼리가 길어지다 보면 과거 심플하던 시절에는 없던 문제가 생기기도 하는데, 이번에..&quot; data-og-host=&quot;chisu.tistory.com&quot; data-og-source-url=&quot;https://chisu.tistory.com/4&quot; data-og-url=&quot;https://chisu.tistory.com/4&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/dHOdoF/hyEsU6JY3T/Cu0QpMbQzPCdkMwdlFkupk/img.png?width=800&amp;amp;height=345&amp;amp;face=0_0_800_345,https://scrap.kakaocdn.net/dn/fFUcL/hyEqXD2mMB/SViDKvtXHcXfyZYZwkCYek/img.png?width=800&amp;amp;height=345&amp;amp;face=0_0_800_345,https://scrap.kakaocdn.net/dn/l838a/hyEqSioPf0/Xh6F5YHHOTw0A2aLKfWdK0/img.png?width=1344&amp;amp;height=580&amp;amp;face=0_0_1344_580&quot;&gt;&lt;a href=&quot;https://chisu.tistory.com/4&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://chisu.tistory.com/4&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/dHOdoF/hyEsU6JY3T/Cu0QpMbQzPCdkMwdlFkupk/img.png?width=800&amp;amp;height=345&amp;amp;face=0_0_800_345,https://scrap.kakaocdn.net/dn/fFUcL/hyEqXD2mMB/SViDKvtXHcXfyZYZwkCYek/img.png?width=800&amp;amp;height=345&amp;amp;face=0_0_800_345,https://scrap.kakaocdn.net/dn/l838a/hyEqSioPf0/Xh6F5YHHOTw0A2aLKfWdK0/img.png?width=1344&amp;amp;height=580&amp;amp;face=0_0_1344_580');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot;&gt;MySQL / MariaDB 서브 쿼리 내의 order by 안 되는 현상 + 해결법&lt;/p&gt;
&lt;p class=&quot;og-desc&quot;&gt;작업을 하다 보면 다루어야 할 데이터도 많아지고, 테이블도 많아집니다. 그에 따라서 사용하는 쿼리문이 길어지기도 합니다. 쿼리가 길어지다 보면 과거 심플하던 시절에는 없던 문제가 생기기도 하는데, 이번에..&lt;/p&gt;
&lt;p class=&quot;og-host&quot;&gt;chisu.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>GROUP BY</category>
      <category>maiardb</category>
      <category>mysql</category>
      <category>order by</category>
      <category>Subquery</category>
      <author>SOOSIN</author>
      <guid isPermaLink="true">https://developthreefeet.tistory.com/10</guid>
      <comments>https://developthreefeet.tistory.com/10#entry10comment</comments>
      <pubDate>Sun, 5 Jan 2020 19:44:26 +0900</pubDate>
    </item>
    <item>
      <title>IOS에서 스토리보드를 통해 기본 화면 구성하기</title>
      <link>https://developthreefeet.tistory.com/9</link>
      <description>&lt;p&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Xcode에서 IOS 프로젝트를 생성하면 프로젝트 내부에 스토리 보드가 존재합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;스토리보드 (Stroryboard)란?&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;&lt;span style=&quot;color: #000000;&quot;&gt;스토리 보드는 IOS 앱의 사용자 인터페이스를 시각적으로 표현하여 컨텐츠 화면과 화면 간의 연결을 보여주는 도구입니다. 스토리보드는 일련의 장면들(scenes)로 구성되며, 각 scene은 뷰 컨트롤러와 해당 뷰를 나타냅니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;602&quot; height=&quot;351&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/RagDI/btqARyWesvY/bZZKMb0Mr7iCaRk4GKZF71/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/RagDI/btqARyWesvY/bZZKMb0Mr7iCaRk4GKZF71/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/RagDI/btqARyWesvY/bZZKMb0Mr7iCaRk4GKZF71/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FRagDI%2FbtqARyWesvY%2FbZZKMb0Mr7iCaRk4GKZF71%2Fimg.png&quot; width=&quot;602&quot; height=&quot;351&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&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&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;뷰(View)란?&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;span style=&quot;color: #000000;&quot;&gt;IOS 앱 사용자 인터페이스의 기본 구성 요소입니다. 이를 사용하여 앱의 컨텐츠를 화면에 그리거나 구성할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;&lt;br /&gt;&lt;br /&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;602&quot; height=&quot;353&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dVV3MY/btqARXIgYry/7k2K1dl6YKK7azkLjKlpFK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dVV3MY/btqARXIgYry/7k2K1dl6YKK7azkLjKlpFK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dVV3MY/btqARXIgYry/7k2K1dl6YKK7azkLjKlpFK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdVV3MY%2FbtqARXIgYry%2F7k2K1dl6YKK7azkLjKlpFK%2Fimg.png&quot; width=&quot;602&quot; height=&quot;353&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&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&gt;&lt;b&gt;&lt;br /&gt;&lt;br /&gt;&lt;/b&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;뷰 컨트롤러(View Controller)란?&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;span style=&quot;color: #000000;&quot;&gt;UIKit을 사용하는 앱의 인터페이스를 관리하기 위한 도구입니다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #000000;&quot;&gt;뷰 컨트롤러는 하나의 루트 뷰 만을 관리하고, 해당 루트 뷰가 여러개의 서브뷰들을 가지는 방식으로 한 화면을 여러개의 뷰로 구성할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;602&quot; height=&quot;351&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/NzsdW/btqAThsIFfJ/WEIiMCyZwjFx8kt8wFZ8MK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/NzsdW/btqAThsIFfJ/WEIiMCyZwjFx8kt8wFZ8MK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/NzsdW/btqAThsIFfJ/WEIiMCyZwjFx8kt8wFZ8MK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FNzsdW%2FbtqAThsIFfJ%2FWEIiMCyZwjFx8kt8wFZ8MK%2Fimg.png&quot; width=&quot;602&quot; height=&quot;351&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&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&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;UIKIT 이란?&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;span style=&quot;color: #000000;&quot;&gt;IOS 또는 tvOS 앱을 위한 그래픽 기반의 이벤트 중심 사용자 인터페이스를 구성하고 관리하는 프레임워크입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #000000;&quot;&gt;용어 정의가 끝났으니 스토리보드를 통해 화면을 구성하는 방법을 알아보겠습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #000000;&quot;&gt;xcode 상단의 &amp;lsquo;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;rsquo; &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;모양 버튼을 누르면&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; IOS의 화면을 구성하는 &amp;lsquo;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;오브젝트 라이브러리&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;rsquo;들을 확인할 수 있습니다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #000000;&quot;&gt;여기서&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; View Controller를 찾아 스토리보드로 드래그하면 새로운 화면이 생성&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;602&quot; height=&quot;344&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bAOy0C/btqARh8jnGw/vh0gVfLkVHFM4NHmfDIr1k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bAOy0C/btqARh8jnGw/vh0gVfLkVHFM4NHmfDIr1k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bAOy0C/btqARh8jnGw/vh0gVfLkVHFM4NHmfDIr1k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbAOy0C%2FbtqARh8jnGw%2Fvh0gVfLkVHFM4NHmfDIr1k%2Fimg.png&quot; width=&quot;602&quot; height=&quot;344&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&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&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이번에는 생성된 화면에 뷰 컨트롤러를 스위프트 언어를 통해 조작하기 위한 설정을 진행하겠습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #000000;&quot;&gt;먼저 스위프트 파일을 생성합니다. xcode 프로젝트의 현재 디렉토리를 우클릭하여 New File -&amp;gt; 스위프트 파일을 선택합니다. 파일이름은 testViewController로 하겠습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;602&quot; height=&quot;376&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/7pmfd/btqAQ4g0VmO/NwWIUV1P3dR8WpR8Nvdu01/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/7pmfd/btqAQ4g0VmO/NwWIUV1P3dR8WpR8Nvdu01/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/7pmfd/btqAQ4g0VmO/NwWIUV1P3dR8WpR8Nvdu01/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F7pmfd%2FbtqAQ4g0VmO%2FNwWIUV1P3dR8WpR8Nvdu01%2Fimg.png&quot; width=&quot;602&quot; height=&quot;376&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&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;figure class=&quot;imageblock alignCenter&quot; width=&quot;602&quot; height=&quot;376&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c0JyeJ/btqAU5ZFiZP/3YNAUwBpSjKIEgM6fdYp31/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c0JyeJ/btqAU5ZFiZP/3YNAUwBpSjKIEgM6fdYp31/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c0JyeJ/btqAU5ZFiZP/3YNAUwBpSjKIEgM6fdYp31/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc0JyeJ%2FbtqAU5ZFiZP%2F3YNAUwBpSjKIEgM6fdYp31%2Fimg.png&quot; width=&quot;602&quot; height=&quot;376&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&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&gt;&lt;b&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #000000;&quot;&gt;해당 파일에 UIKit을 import하고, testViewController 라는 이름의 ViewController 클래스를 생성합니다. 그리고 해당 클래스 내부에 viewDidLoad() 메소드를 오버라이드합니다. 추후 IOS 앱 화면 전환 예제에서 객체들을 조작할 때 활용됩니다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Xcode의 &amp;lsquo;Add Editor On Right&amp;rsquo; 버튼을 클릭해 화면을 여러 개로 나누어 스토리보드, swift 파일을 동시에 볼 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;602&quot; height=&quot;375&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/SrLCa/btqASy2BlwK/oRedeKZ35ShxMucfLWIUhK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/SrLCa/btqASy2BlwK/oRedeKZ35ShxMucfLWIUhK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/SrLCa/btqASy2BlwK/oRedeKZ35ShxMucfLWIUhK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FSrLCa%2FbtqASy2BlwK%2FoRedeKZ35ShxMucfLWIUhK%2Fimg.png&quot; width=&quot;602&quot; height=&quot;375&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&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&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;viewDidLoad() 란?&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;span style=&quot;color: #000000;&quot;&gt;IOS 앱의 생명 주기 중 뷰 컨트롤러의 루트 뷰가 스토리 보드에서 만들어 로드 될 때 호출되는 메소드입니다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #000000;&quot;&gt;생명 주기란 앱의 실행부터 종료하기 까지의 일련의 단계를 의미합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;308&quot; height=&quot;292&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mLhOq/btqARiMQEiW/Y3ANCcMHYoxGjvOXxI1UCk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mLhOq/btqARiMQEiW/Y3ANCcMHYoxGjvOXxI1UCk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mLhOq/btqARiMQEiW/Y3ANCcMHYoxGjvOXxI1UCk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmLhOq%2FbtqARiMQEiW%2FY3ANCcMHYoxGjvOXxI1UCk%2Fimg.png&quot; width=&quot;308&quot; height=&quot;292&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&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&gt;&lt;b&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이제 해당 스위프트 파일과 스토리보드 scene의 View Controller를 연결하겠습니다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #000000;&quot;&gt;연결을 원하는 scene을 클릭한 후 xcode의 인스펙터 영역의 &amp;lsquo;show the identity inspector&amp;rsquo; 버튼을 클릭합니다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #000000;&quot;&gt;class를 입력하는 란에 방금 생성한 &amp;lsquo;TestViewController&amp;rsquo;를 선택합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #000000;&quot;&gt;마지막으로 &amp;lsquo;Storyboard ID&amp;rsquo;에 &amp;lsquo;TestVC&amp;rsquo;를 입력합니다. Storyboard ID는 스위프트 파일에서 조작을 원하는 View Controller를 스토리보드로 부터 얻어 올 때 사용하는 아이디입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;602&quot; height=&quot;375&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/EQUWr/btqAUueg7O1/Je0ytgxKnMWtafbba65qoK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/EQUWr/btqAUueg7O1/Je0ytgxKnMWtafbba65qoK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/EQUWr/btqAUueg7O1/Je0ytgxKnMWtafbba65qoK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FEQUWr%2FbtqAUueg7O1%2FJe0ytgxKnMWtafbba65qoK%2Fimg.png&quot; width=&quot;602&quot; height=&quot;375&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&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&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이번에는 화면에 &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;버튼과 레이블(텍스트를 표시할 수 있는 객체)을 추가&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;하겠습니다. 그리고 &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;버튼을 누를 때마다 레이블에 쓰여진 숫자가 증가하도록 조작&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;하겠습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #000000;&quot;&gt;xcode 상단의 &amp;lsquo;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;rsquo; &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;모양 버튼을 눌러서&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &amp;lsquo;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;오브젝트 라이브러리&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;rsquo; 중 &amp;lsquo;Button&amp;rsquo;과 &amp;lsquo;Label&amp;rsquo;을 선택해서 화면으로 드래그합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;602&quot; height=&quot;371&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b7FI0B/btqAThlXL3v/wifQZ07vPX6evC0SooL4A0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b7FI0B/btqAThlXL3v/wifQZ07vPX6evC0SooL4A0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b7FI0B/btqAThlXL3v/wifQZ07vPX6evC0SooL4A0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb7FI0B%2FbtqAThlXL3v%2FwifQZ07vPX6evC0SooL4A0%2Fimg.png&quot; width=&quot;602&quot; height=&quot;371&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&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&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;602&quot; height=&quot;376&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kDb0U/btqARx34koe/EtvUEEwM6IOFlxtYkaEFO0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kDb0U/btqARx34koe/EtvUEEwM6IOFlxtYkaEFO0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kDb0U/btqARx34koe/EtvUEEwM6IOFlxtYkaEFO0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkDb0U%2FbtqARx34koe%2FEtvUEEwM6IOFlxtYkaEFO0%2Fimg.png&quot; width=&quot;602&quot; height=&quot;376&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&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&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;lsquo;Label&amp;rsquo;을 우클릭하여 viewDidLoad() 메소드 위로 드래그합니다. &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #000000;&quot;&gt;그러면 아래 화면처럼 &amp;lsquo;Label&amp;rsquo; 사용을 위한 선택란들이 나오는데 Connection에&amp;nbsp; Outlet, Name에 numLabel, Type에 UILabel을 입력하고, connect 버튼을 누르면 아웃렛 변수가 생성됩니다. &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;아웃렛 변수&lt;/span&gt;&lt;/b&gt;로 레이블 객체를 조정할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;544&quot; height=&quot;333&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/phmAF/btqAUv5l6MB/1avwd9mRrjhTql83ZkVKFk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/phmAF/btqAUv5l6MB/1avwd9mRrjhTql83ZkVKFk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/phmAF/btqAUv5l6MB/1avwd9mRrjhTql83ZkVKFk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FphmAF%2FbtqAUv5l6MB%2F1avwd9mRrjhTql83ZkVKFk%2Fimg.png&quot; width=&quot;544&quot; height=&quot;333&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&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&gt;&lt;b&gt;&lt;br /&gt;&lt;br /&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #000000;&quot;&gt;그 다음 &amp;lsquo;Button&amp;rsquo;을 우클릭하여&amp;nbsp; viewDidLoad() 메소드 아래로 드래그합니다. &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #000000;&quot;&gt;해당 선택란에서 Connection에 Action, Name에 numUp, Type에 UIButton를 입력하고 connect 버튼을 누르면 액션 메소드가 생성됩니다. &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;액션메소드&lt;/b&gt;를 통해 버튼 클릭시 발생할 이벤트를 정의할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Type은 기본적으로 Any로 선택되어 있을 겁니다. Any는 스위프트에서 모든 타입의 인스턴스를 나타낼 수 있습니다. &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #000000;&quot;&gt;때문에 해당 메소드의 속성을 알고 싶다면 Any를 사용하면 안됩니다. &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Type을 Any가 아닌 UIButton으로 설정해야 메소드가 버튼을 클릭해서 실행된 메소드인지 알 수 있으니까요.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;&lt;br /&gt;&lt;br /&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;551&quot; height=&quot;345&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/uG3uh/btqAQ2Q4doM/GM5DhNdRU5K16OGKFAUzRk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/uG3uh/btqAQ2Q4doM/GM5DhNdRU5K16OGKFAUzRk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/uG3uh/btqAQ2Q4doM/GM5DhNdRU5K16OGKFAUzRk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FuG3uh%2FbtqAQ2Q4doM%2FGM5DhNdRU5K16OGKFAUzRk%2Fimg.png&quot; width=&quot;551&quot; height=&quot;345&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&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&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이제 레이블에 입력될 숫자를 저장할 int형 변수 &amp;lsquo;num&amp;rsquo;의 값을 0으로 해서&amp;nbsp; &amp;lsquo;numLabel&amp;rsquo; 변수 밑에 저장합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #000000;&quot;&gt;그리고 방금 추가한 액션 메소드 내부에&lt;b&gt; 버튼 클릭시 num 변수의 값을 1씩 올린 후 레이블에 입력하는 코드를 아래와 같이 입력하면, &lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;버튼을 누를 때마다 레이블에 쓰여진 숫자가 증가&lt;/b&gt;하는 앱이 완성됩니다!&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;602&quot; height=&quot;340&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/9gxZA/btqASzAq8ep/wS7nGt5GdkmSG8kzyKgYyk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/9gxZA/btqASzAq8ep/wS7nGt5GdkmSG8kzyKgYyk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/9gxZA/btqASzAq8ep/wS7nGt5GdkmSG8kzyKgYyk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F9gxZA%2FbtqASzAq8ep%2FwS7nGt5GdkmSG8kzyKgYyk%2Fimg.png&quot; width=&quot;602&quot; height=&quot;340&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&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;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;출처&lt;/span&gt;&lt;/h2&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;서적&lt;/span&gt;&lt;/h4&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;꼼꼼한 재은 씨의 스위프트: 기본편&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;애플 공식 문서&lt;/span&gt;&lt;/h4&gt;
&lt;p&gt;&lt;span&gt;&lt;/span&gt;&lt;a href=&quot;https://developer.apple.com/library/archive/documentation/General/Conceptual/Devpedia-CocoaApp/Storyboard.html&quot;&gt;https://developer.apple.com/library/archive/documentation/General/Conceptual/Devpedia-CocoaApp/Storyboard.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;/span&gt;&lt;a href=&quot;https://developer.apple.com/documentation/uikit/uiview&quot;&gt;https://developer.apple.com/documentation/uikit/uiview&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;/span&gt;&lt;a href=&quot;https://developer.apple.com/documentation/uikit/view_controllers&quot;&gt;https://developer.apple.com/documentation/uikit/view_controllers&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;/span&gt;&lt;a href=&quot;https://developer.apple.com/documentation/uikit/uiview/1622621-frame&quot;&gt;https://developer.apple.com/documentation/uikit/uiview/1622621-frame&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;/span&gt;&lt;a href=&quot;https://developer.apple.com/documentation/uikit/views_and_controls&quot;&gt;https://developer.apple.com/documentation/uikit/views_and_controls&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;/span&gt;&lt;a href=&quot;https://developer.apple.com/library/archive/referencelibrary/GettingStarted/DevelopiOSAppsSwift/WorkWithViewControllers.html&quot;&gt;https://developer.apple.com/library/archive/referencelibrary/GettingStarted/DevelopiOSAppsSwift/WorkWithViewControllers.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>개발/IOS</category>
      <author>책 읽는 개발자_테드</author>
      <guid isPermaLink="true">https://developthreefeet.tistory.com/9</guid>
      <comments>https://developthreefeet.tistory.com/9#entry9comment</comments>
      <pubDate>Sun, 5 Jan 2020 11:42:32 +0900</pubDate>
    </item>
    <item>
      <title>HTTP 구조 (라인,헤더,공백,바디) / POST와 GET 구조 차이</title>
      <link>https://developthreefeet.tistory.com/8</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;http-request-8f877662b99b954756836e865f66928e.png&quot; data-origin-width=&quot;640&quot; data-origin-height=&quot;360&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/s5Ies/btqAtCKxHFj/cPZL1iEk9qxG1M8WL0LMWK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/s5Ies/btqAtCKxHFj/cPZL1iEk9qxG1M8WL0LMWK/img.png&quot; data-alt=&quot;그림 출처:https://richardimaoka.github.io/blog/akka-http-request-response-model/&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/s5Ies/btqAtCKxHFj/cPZL1iEk9qxG1M8WL0LMWK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fs5Ies%2FbtqAtCKxHFj%2FcPZL1iEk9qxG1M8WL0LMWK%2Fimg.png&quot; data-filename=&quot;http-request-8f877662b99b954756836e865f66928e.png&quot; data-origin-width=&quot;640&quot; data-origin-height=&quot;360&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;figcaption&gt;그림 출처:https://richardimaoka.github.io/blog/akka-http-request-response-model/&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;'꼼꼼한 재은 씨의 Swift:실전편' 이라는 책의 HTTP 구조 관련된 페이지를 보다 문득 평소에 가장 많이 사용하는 통신 프로토콜이 HTTP인데 구조도 모르고 사용했다는 생각이 들어 해당 내용을 정리합니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Request Line&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;1. 전송 메소드&lt;/p&gt;
&lt;p&gt;&amp;nbsp;위 그림의 Request Line에서 가장 좌측 'POST'가 여기에 해당합니다. GET/POST 등 어떤 전송 방식으로 구성되어 있는지를 나타냅니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;2.요청 내용에 대한 경로&lt;/p&gt;
&lt;p&gt;&amp;nbsp;위 그림의 Request Line에서 전송 메소드 오른쪽에 있는 내용입니다. '/path/to/what' 이렇게 요청 내용이 서버상의 어느 위치에 있는지를 나타냅니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;3.요청 형식에 대한 버전 정보&lt;/p&gt;
&lt;p&gt;&amp;nbsp;위 그림의 Request Line에서 '요청 내용에 대한 경로' 오른쪽에 있는 내용입니다.&amp;nbsp; HTTP는 통신을 위한 약속을 정의한 규약입니다. 이 내용은 어떤 버전의 HTTP 문법을 준수하고 있는가를 나타냅니다. 예를 들어 1.1, 2.0 , 3.0이 있겠네요.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Header&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;HTTP 헤더는 요청 라인 아래에 작성된 내용부터 한 줄 공백이 나오기 전까지 모두를 포함합니다. HTTP 헤더는 클라이언트와 서버가 요청 또는 응답으로 &lt;b&gt;부가적인 정보&lt;/b&gt;를 전송할 수 있도록 합니다. 헤더는 모두 키 : 값으로 이루어집니다.&amp;nbsp; 위 그림의 각각의 내용은 다음을 의미합니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #333333;&quot;&gt;#&lt;b&gt;host:&lt;/b&gt;서버의 도메인명과 서버가 리스닝중인 TCP 포트 번호를 명시합니다.&lt;/span&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #333333;&quot;&gt;#&lt;b&gt;Connection&lt;/b&gt;:현재 트랜잭션이 끝난후에 네트워크 연결을 열린 상태로 둘지 여부를 제어합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #333333;&quot;&gt;#&lt;b&gt;Accept&lt;/b&gt;:Return할 데이터 타입에 대해 서버에 알립니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #333333;&quot;&gt;#&lt;b&gt;User-Agent&lt;/b&gt;:네트워크 프로토콜 피어가 요청하는 사용자 에이전트의 애플리케이션 타입, 운영 체제, 소프트웨어 벤더 또는 소프트웨어 버전을 식별할 수 있는 문자열을 포함합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #333333;&quot;&gt;#&lt;b&gt;Accept-Encoding&lt;/b&gt;:인코딩 알고리즘에 대해 서버에 알립니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #333333;&quot;&gt;#&lt;b&gt;Accept-Langue&lt;/b&gt;:서버가 Return하기로 예상된 언어에 대해 서버에 알립니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Body&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;한 줄 공백 아래에 작성된 메시지 본문을 HTTP Body 라고 합니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;추가내용&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;지금까지 살펴본 HTTP 요청 메시지는 POST 방식일 경우입니다. 만약 전송 방식이 GET이라면 메시지 구조는 달라집니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;GET /userAccount/login?account=swift@swift.com&amp;amp;amp;passwd=1234&amp;amp;amp;grant_type=password HTTP/1.1&lt;br /&gt;Host: swiftapi.rubypaper.co.kr:2029&lt;br /&gt;cache-Control: no-cache&lt;b&gt;&lt;/b&gt;&lt;b&gt;&amp;nbsp;&amp;nbsp;&lt;/b&gt;&lt;/blockquote&gt;
&lt;p&gt;&amp;nbsp;GET 메소드를 사용할 경우 위 내용(꼼꼼한 재은씨의 Swift:실전편 출처)과 같이 메시지 본문(Body)이 사라지고, 본문에 있어야 할 값이 첫 번째 라인의 경로 뒤에 '?' 문자열과 함께 연결되었습니다. GET 방식에서는 파라미터를 모두 URL 뒤에 연결해서 전달하기 때문입니다. 이렇게 연결된 파라미터를 쿼리 스트링이라고 합니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;비교적 간결하게 정보를 전달할 수 있다는 장점이 있지만,&lt;b&gt; URL 경로는 1024 Byte까지만 허용&lt;/b&gt;되기 때문에, 긴 값을 GET 방식으로 전송할 수는 없습니다. 때문에 데이터를 전송하는 경우보다 &lt;b&gt;필요한 정보를 요청할 때 주로 GET 방식이 사용&lt;/b&gt;됩니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;글 출처&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;꼼꼼한 재은씨의 Swift:실전편 &amp;amp; &lt;a href=&quot;https://developer.mozilla.org/ko/docs/Web/HTTP/Headers&quot;&gt;https://developer.mozilla.org/ko/docs/Web/HTTP/Headers&lt;/a&gt;&lt;/p&gt;</description>
      <category>개발/프로토콜</category>
      <author>책 읽는 개발자_테드</author>
      <guid isPermaLink="true">https://developthreefeet.tistory.com/8</guid>
      <comments>https://developthreefeet.tistory.com/8#entry8comment</comments>
      <pubDate>Sun, 15 Dec 2019 00:42:43 +0900</pubDate>
    </item>
    <item>
      <title>윈도우에서 도커로 개발환경 구성하기</title>
      <link>https://developthreefeet.tistory.com/7</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/1njuo/btqAbmVPnvC/i4Y43GpHhyGxUSa1vbq8jk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/1njuo/btqAbmVPnvC/i4Y43GpHhyGxUSa1vbq8jk/img.jpg&quot; data-alt=&quot;도커!&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/1njuo/btqAbmVPnvC/i4Y43GpHhyGxUSa1vbq8jk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F1njuo%2FbtqAbmVPnvC%2Fi4Y43GpHhyGxUSa1vbq8jk%2Fimg.jpg&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&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;figcaption&gt;도커!&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;안녕하세요.&lt;/p&gt;
&lt;p&gt;요즘 날이 엄청 춥네요.&lt;/p&gt;
&lt;p&gt;자취방이 너무 추워서 도저히 잠이 안 옵니다...&lt;/p&gt;
&lt;p&gt;그래서 보일러를 켰더니 온도가 오르는 속도가 너무 느리네요.&lt;/p&gt;
&lt;p&gt;따뜻해지기를 기다릴 겸사겸사,&lt;/p&gt;
&lt;p&gt;이번 글에서는 제 나름대로 도커를 이용해서 윈도우 컴퓨터에서 개발환경을 구성하는 과정에서 얻었던 나름의 미세팁들을 공유하고자 합니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;도커를 왜 쓰는지, 혹은 도커의 유용함 자체는 이미 많이 알려진 상태이고, 또한 많은 곳에서 사용중이기에 굳이 여기서까지 적을 필요는 없을 것 같습니다. 그런 걸 알고 싶으시면 구글에 도커를 검색하세요.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;다만 저는 개발환경을 구성하는 데 도커를 사용했기에, 개발환경 측면에서의 이점만 간단하게 말씀드리겠습니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot;&gt;
&lt;li&gt;&lt;b&gt;서버 컴퓨터를 구매할(혹은 대여할) 필요가 없다.&amp;nbsp;&lt;br /&gt;&lt;/b&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;예를 들어서 윈도우에서 도커를 사용해 우분투 컨테이너를 운영할 경우, 따로 리눅스 서버를 클라우드에서 빌리거나 하지 않고도 개발용 컴퓨터 안에서 서버 개발이 가능해집니다. 물론 VMware나 VirtualBox 등의 가상머신을 사용하는 방법도 있지만, 속도나 메모리 측면에서 상대가 되질 않습니다. 또한 도커 내부의 서버와 윈도우의 코드 디렉토리를 연결하면 윈도우의 코드 수정이 바로바로 도커 서버에 적용됨으로써 빠른 개발이 가능해집니다.&amp;nbsp;&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;윈도우와 리눅스의 차이로 인한 문제를 방지한다.&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;이 문제는 제가 직접 겪어본 문제는 아닙니다만, 윈도우와 리눅스는 OS를 구성하는 커널 자체가 다릅니다. 때문에 개발용 컴퓨터의 윈도우에서는 제대로 동작하던 소스 코드가 실제 서버 OS인 리눅스에서는 동작하지 않는 경우가 종종 있습니다. 이 때 개발용으로 도커를 사용하면 윈도우 내의 리눅스를 사용하게 되므로 위와 같은 문제는 일어날 일이 없게 됩니다. 처음부터 리눅스 환경을 사용하니까요.&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;서버 환경의 버전 관리가 가능해진다.&amp;nbsp;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;서비스를 운영하다 보면 운영중인 실제 서버에 무언가를 설치하는 것이 상당히 부담스럽습니다. 새로 설치한 패키지 혹은 파일이 서비스에 어떤 영향을 미칠 지 모르기 때문이죠. 하지만 도커를 사용하면 컨테이너의 현재 상태를 도커파일의 형태로 기록할 수 있습니다. 때문에 서버 컨테이너에 새로운 프로그램을 설치하기 전에 미리 도커파일로 만들어두고 작업을 하면, 문제가 발생하더라도 이전의 서버 구성 기록이 남아있기 때문에 쉽게 롤백할 수 있다는 장점이 있습니다. 이는 서버의 가장 중요 포인트 중 하나인 안정성에 큰 뒷받침을 하게 됩니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;이외에도 도커의 장점은 무궁무진합니다. 만.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;이제 제가 개발환경을 구성할 때 어떻게 사용했는지, 그리고 관련한 팁들을 두서없이 적어보겠습니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;(사실 구성한 지 한 달 좀 더 지나서 기억이 단편적으로 남아있습니다)&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot;&gt;
&lt;li&gt;&lt;b&gt;도커는 윈도우에서 사용하려면 Windows 10 Pro 이상의 버전이 필요합니다.&amp;nbsp;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;처음에 제 노트북이 Home 버전이었어서 제대로 동작하지 않는 사태가 시작하자마자 벌어졌었습니다. 때문에 윈도우 버전을 Pro로 새로 구매했습니다. 여러분은 Pro로 시작하시는 게 좋을 것 같습니다.&amp;nbsp;&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;윈도우에서 도커를 run하려면 커맨드를 쳐야 하는데, 이 때 커맨드툴은 cmd보다 PowerShell을 쓰는 게 좋습니다.&amp;nbsp;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;저는 CLI 환경을 리눅스에서 주로 사용해서 윈도우에서 새로운 명령어들을 또 따로 배우는 게 굉장한 스트레스였는데, PowerShell을 써보니 리눅스에서 사용가능한 명령어들을 상당히 많이 지원하고 있어서 굉장히 편했습니다. 사실상 대부분의 작업은 윈도우 안의 도커 컨테이너 안의 리눅스에서 작업을 하기 때문에, 따로 윈도우의 명령어들을 거의 공부하지 않고도 PowerShell에서는 원활하게 작업이 가능했습니다. 다른 선택으로 Git Bash, 혹은 Cygwin도 가능합니다만 저는 PowerShell이 가장 좋은 것 같습니다. (색깔이 좀 맘에 안 듭니다 ㅎ.ㅎ)&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;도커에 순정 우분투를 설치하게 되면 생각보다 안되는 게 많습니다.&amp;nbsp;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;처음에 도커에 순정 우분투를 설치했을 때(v18.04) 당황했던 것이 당연하다고 생각했던 기능들이 대부분 탑재가 안 되어 있다는 것이었습니다. (ex. netstat 등등) 물론 대부분이 apt-get 으로 설치 가능하지만 그 apt-get 이랑 ls 빼고는 없는 게 상당히 많다고 보시면 됩니다. 때문에 많은 문서에서 튜토리얼로 알려주는 ubuntu 16.04를 그대로 설치하기 보다는 다른 프로그램들이 동봉되어 있는 도커 이미지를 받아 사용하는 것이 불필요한 비용을 줄이는 데 도움이 될 것 같습니다.&amp;nbsp; &amp;nbsp;&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;다음은 제가 작업할 때 사용했던 도커 명령어들입니다.&amp;nbsp;&lt;/b&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;b&gt;도커 컨테이너 run 시 :&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;&lt;span&gt;docker run --name&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;chase&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;-i -t&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;-p&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;8888&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;8888&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;-v&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;C:\development\chase&lt;/span&gt;&lt;span&gt;:/home/ubuntu/chase&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;ubuntu:18.04&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;위 커맨드는 도커 컨테이너를 생성하고 (&lt;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;docker run&lt;/b&gt;)&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;해당 컨테이너의 별명은 chase, (&lt;b&gt;--name chase&lt;/b&gt;)&lt;/p&gt;
&lt;p&gt;해당 컨테이너가 사용자의 키보드 입력을 인식하게 하고 (&lt;b&gt;-i -t&lt;/b&gt;)&lt;/p&gt;
&lt;p&gt;윈도우 상의 포트와 도커 내부의 운영체제의 포트를 연결하고 (&lt;b&gt;-p 8888:8888&lt;/b&gt;)&lt;/p&gt;
&lt;p&gt;윈도우 상의 디렉토리와 도커 내부의 운영체제의 디렉토리를 연결해주고, (마운트라고도 합니다)&lt;/p&gt;
&lt;p&gt;(&lt;b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;-v&lt;/span&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #333333;&quot;&gt;C:\development\chase&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;:/home/ubuntu/chase&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;==&amp;gt; : (콜론)을 기준으로 왼쪽이 윈도우, 오른쪽이 리눅스)&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #333333;&quot;&gt;그리고 해당 컨테이너에 Ubuntu 18.04 를 설치하는 명령어입니다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;한 줄의 커맨드지만 상당히 많은 의미를 담고 있고, 사실상 한 대의 훌륭한 리눅스 서버를 만들 수도 있습니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;도커 컨테이너 전체 삭제 시&amp;nbsp; :&lt;/p&gt;
&lt;p&gt;&lt;b&gt;&lt;span&gt;docker rm $(docker ps -qa)&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;도커를 써보다 보면 시행착오를 거치면서 컨테이너를 생성했다 지웠다 하는 작업을 반복하게 됩니다. 저는 초반에는 도커를 하나하나 선택해서 지우기도 귀찮아서 전부 날려버리는 커맨드를 자주 쓰게 되더군요.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;span style=&quot;color: #333333;&quot;&gt;도커 컨테이너 조회&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;&lt;span&gt;&lt;span&gt;docker ps -a&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;span&gt;현재 존재하는 모든 도커 컨테이너들을 조회합니다.&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;span&gt;컨테이너 내부에서 작업하려고 할 때 컨테이너 시작 및 접속&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;docker chase start&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;(컨테이너 시작)&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;docker chase attach&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;(컨테이너 접속)&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;일반적으로 컴퓨터를 껐다가 켜면 도커 프로세스도 Exit된 상태가 많습니다. 때문에 작업을 하려면 우선 컨테이너를 켜주고 접속해야 하는데, 위 명령어를 연속으로 사용하면 됩니다(여기서 chase처럼 별칭을 붙여놓으면 편합니다)&lt;span style=&quot;color: #333333;&quot;&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;잘못된 점 알려주시면 수정 가능합니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;감사합니다.&lt;/p&gt;
&lt;p&gt;-끝-&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;출처 :&amp;nbsp;&lt;a href=&quot;https://chisu.tistory.com/3&quot;&gt;https://chisu.tistory.com/3&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1575395323652&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-og-type=&quot;article&quot; data-og-title=&quot;윈도우에서 도커로 개발환경 구성하기&quot; data-og-description=&quot;안녕하세요. 요즘 날이 엄청 춥네요. 자취방이 너무 추워서 도저히 잠이 안 옵니다... 그래서 보일러를 켰더니 온도가 오르는 속도가 너무 느리네요. 따뜻해지기를 기다릴 겸사겸사, 이번 글에서는 제 나름대로..&quot; data-og-host=&quot;chisu.tistory.com&quot; data-og-source-url=&quot;https://chisu.tistory.com/3&quot; data-og-url=&quot;https://chisu.tistory.com/3&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/cspqN8/hyDXXjtvjM/zxVUGiR7DgYvNMM1yRTgSK/img.jpg?width=800&amp;amp;height=418&amp;amp;face=0_0_800_418,https://scrap.kakaocdn.net/dn/QQGVq/hyDXPTitrY/9bA8Bl9kZufzeLy3dUguOK/img.jpg?width=800&amp;amp;height=418&amp;amp;face=0_0_800_418,https://scrap.kakaocdn.net/dn/6qGzJ/hyDXZBA8sn/Dn2pIWeWGVfkLjDzc3XOXk/img.jpg?width=1200&amp;amp;height=627&amp;amp;face=0_0_1200_627&quot;&gt;&lt;a href=&quot;https://chisu.tistory.com/3&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://chisu.tistory.com/3&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/cspqN8/hyDXXjtvjM/zxVUGiR7DgYvNMM1yRTgSK/img.jpg?width=800&amp;amp;height=418&amp;amp;face=0_0_800_418,https://scrap.kakaocdn.net/dn/QQGVq/hyDXPTitrY/9bA8Bl9kZufzeLy3dUguOK/img.jpg?width=800&amp;amp;height=418&amp;amp;face=0_0_800_418,https://scrap.kakaocdn.net/dn/6qGzJ/hyDXZBA8sn/Dn2pIWeWGVfkLjDzc3XOXk/img.jpg?width=1200&amp;amp;height=627&amp;amp;face=0_0_1200_627');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot;&gt;윈도우에서 도커로 개발환경 구성하기&lt;/p&gt;
&lt;p class=&quot;og-desc&quot;&gt;안녕하세요. 요즘 날이 엄청 춥네요. 자취방이 너무 추워서 도저히 잠이 안 옵니다... 그래서 보일러를 켰더니 온도가 오르는 속도가 너무 느리네요. 따뜻해지기를 기다릴 겸사겸사, 이번 글에서는 제 나름대로..&lt;/p&gt;
&lt;p class=&quot;og-host&quot;&gt;chisu.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Docker</category>
      <category>개발환경</category>
      <category>도커</category>
      <category>리눅스</category>
      <category>윈도우</category>
      <category>컨테이너</category>
      <author>SOOSIN</author>
      <guid isPermaLink="true">https://developthreefeet.tistory.com/7</guid>
      <comments>https://developthreefeet.tistory.com/7#entry7comment</comments>
      <pubDate>Wed, 4 Dec 2019 02:48:56 +0900</pubDate>
    </item>
    <item>
      <title>Spring 서버에서 사용할 APNS 인증서 준비</title>
      <link>https://developthreefeet.tistory.com/6</link>
      <description>&lt;p style=&quot;font-size: 1.25em;&quot;&gt;&amp;nbsp;APNS(apple Push Notification Service)는 Apple device에서 앱이 보안 연결을 통해 원격 서버에서 사용자에게 푸시 알림을 보낼 수 있게 하는 클라우드 서비스입니다. 간략한 로직은 아래와 같습니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;744&quot; data-origin-height=&quot;795&quot; width=&quot;573&quot; height=&quot;612&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cm8wxU/btqzYDwVIOg/OVC2XR6KdT1n6FRAzyoyfK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cm8wxU/btqzYDwVIOg/OVC2XR6KdT1n6FRAzyoyfK/img.jpg&quot; data-alt=&quot;출처:https://medium.com/@ufukatalca/generate-apns-certificate-for-ios-push-notifications-ada9234d4c09&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cm8wxU/btqzYDwVIOg/OVC2XR6KdT1n6FRAzyoyfK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcm8wxU%2FbtqzYDwVIOg%2FOVC2XR6KdT1n6FRAzyoyfK%2Fimg.jpg&quot; data-origin-width=&quot;744&quot; data-origin-height=&quot;795&quot; width=&quot;573&quot; height=&quot;612&quot; data-ke-mobilestyle=&quot;widthContent&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;figcaption&gt;출처:https://medium.com/@ufukatalca/generate-apns-certificate-for-ios-push-notifications-ada9234d4c09&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.25em;&quot;&gt;이 글은 위 프로그램의 Your Server 부분에 스프링을 통해 APNS를 사용하기 위한 파일을 생성하는 과정과 간단한 원리를 설명합니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;CSR(Certificate Signing Request)발급&lt;/h3&gt;
&lt;p&gt;맥의 spotlight 검색을 통해 키체인을 검색하고 해당 탭에서 다음과 같인 csr을 발급합니다.&lt;/p&gt;
&lt;p&gt;&lt;a&gt;&amp;nbsp;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;스크린샷 2020-10-08 오전 5.41.40.png&quot; data-origin-width=&quot;972&quot; data-origin-height=&quot;524&quot; width=&quot;427&quot; height=&quot;NaN&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bNY4Iv/btqKlUbJeTc/kBkxrsFYzGkkifkGBvl08k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bNY4Iv/btqKlUbJeTc/kBkxrsFYzGkkifkGBvl08k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bNY4Iv/btqKlUbJeTc/kBkxrsFYzGkkifkGBvl08k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbNY4Iv%2FbtqKlUbJeTc%2FkBkxrsFYzGkkifkGBvl08k%2Fimg.png&quot; data-filename=&quot;스크린샷 2020-10-08 오전 5.41.40.png&quot; data-origin-width=&quot;972&quot; data-origin-height=&quot;524&quot; width=&quot;427&quot; height=&quot;NaN&quot; data-ke-mobilestyle=&quot;widthContent&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;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; width=&quot;436&quot; height=&quot;NaN&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bTTaC4/btqKqy6BcBy/obA0pI1EsAwvI6nqsQxlYk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bTTaC4/btqKqy6BcBy/obA0pI1EsAwvI6nqsQxlYk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bTTaC4/btqKqy6BcBy/obA0pI1EsAwvI6nqsQxlYk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbTTaC4%2FbtqKqy6BcBy%2FobA0pI1EsAwvI6nqsQxlYk%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; width=&quot;436&quot; height=&quot;NaN&quot; data-ke-mobilestyle=&quot;widthContent&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&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;생성된 CSR 파일을 열어보면 다음과 같은 데이터가 보입니다. 이 데이터에는 공개키 정보, 인증서가 사용될 FQDN(Fully-qualified domain name), 본인이나 본인의 웹사이트 정보들이 저장됩니다. 공개키가 저장되므로 보안을 위해 비대칭키 알고리즘을 사용한다는 걸 알 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;1838&quot; data-origin-height=&quot;790&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/FUHNs/btqzXhH8sii/mofdsejk8DFYUJuVLM5UZ0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/FUHNs/btqzXhH8sii/mofdsejk8DFYUJuVLM5UZ0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/FUHNs/btqzXhH8sii/mofdsejk8DFYUJuVLM5UZ0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FFUHNs%2FbtqzXhH8sii%2Fmofdsejk8DFYUJuVLM5UZ0%2Fimg.png&quot; data-origin-width=&quot;1838&quot; data-origin-height=&quot;790&quot; data-ke-mobilestyle=&quot;widthContent&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&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;APNS(&lt;span style=&quot;color: #333333;&quot;&gt;Apple Push Notification Service&lt;/span&gt;) 인증서 발급&lt;/h3&gt;
&lt;p&gt;애플 개발자 사이트(&lt;a href=&quot;https://developer.apple.com/kr/&quot;&gt;https://developer.apple.com/kr/&lt;/a&gt;)에 접속한후 아래 이미지처럼 Identifiers 탭에 들어가 본인이 발급을 원하는 앱의&lt;/p&gt;
&lt;p&gt;identifier를 클릭해주세요.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;스크린샷 2019-11-24 오전 12.25.17.png&quot; data-origin-width=&quot;1800&quot; data-origin-height=&quot;1028&quot; width=&quot;522&quot; height=&quot;298&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/csm9zM/btqzYL9lz74/WmYyt1SyWbWzZsJ5rV48xK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/csm9zM/btqzYL9lz74/WmYyt1SyWbWzZsJ5rV48xK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/csm9zM/btqzYL9lz74/WmYyt1SyWbWzZsJ5rV48xK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcsm9zM%2FbtqzYL9lz74%2FWmYyt1SyWbWzZsJ5rV48xK%2Fimg.png&quot; data-filename=&quot;스크린샷 2019-11-24 오전 12.25.17.png&quot; data-origin-width=&quot;1800&quot; data-origin-height=&quot;1028&quot; width=&quot;522&quot; height=&quot;298&quot; data-ke-mobilestyle=&quot;widthContent&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&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #333333;&quot;&gt;identifier를 클릭해서 들어간 페이지에서 &lt;/span&gt;Push Notifications 오른쪽 Edit을 클릭하세요.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;스크린샷 2019-11-24 오전 12.22.22.png&quot; data-origin-width=&quot;1632&quot; data-origin-height=&quot;1290&quot; width=&quot;522&quot; height=&quot;413&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/tgwt2/btqzZdjZxVg/SUD7eCQ4eZzgEgHp6d8sX1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/tgwt2/btqzZdjZxVg/SUD7eCQ4eZzgEgHp6d8sX1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/tgwt2/btqzZdjZxVg/SUD7eCQ4eZzgEgHp6d8sX1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Ftgwt2%2FbtqzZdjZxVg%2FSUD7eCQ4eZzgEgHp6d8sX1%2Fimg.png&quot; data-filename=&quot;스크린샷 2019-11-24 오전 12.22.22.png&quot; data-origin-width=&quot;1632&quot; data-origin-height=&quot;1290&quot; width=&quot;522&quot; height=&quot;413&quot; data-ke-mobilestyle=&quot;widthContent&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&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #333333;&quot;&gt;Edit을 클릭해서 들어간 페이지에서 Create Certificat 버튼을 클릭하세요. Development SSL Certificate는 개발용, Production SSL Certificate는 출시용입니다. 용도에 맞는 걸 선택하시면 됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;1074&quot; data-origin-height=&quot;1224&quot; width=&quot;489&quot; height=&quot;557&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/d7hOI7/btqzXi72vxb/QhbOPyECmo6s5yvcUrnupK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/d7hOI7/btqzXi72vxb/QhbOPyECmo6s5yvcUrnupK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/d7hOI7/btqzXi72vxb/QhbOPyECmo6s5yvcUrnupK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fd7hOI7%2FbtqzXi72vxb%2FQhbOPyECmo6s5yvcUrnupK%2Fimg.png&quot; data-origin-width=&quot;1074&quot; data-origin-height=&quot;1224&quot; width=&quot;489&quot; height=&quot;557&quot; data-ke-mobilestyle=&quot;widthContent&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&gt;&lt;span style=&quot;color: #333333;&quot;&gt;Create Certificat 버튼을 클릭해서 들어간 페이지에서 Choose File을 클릭해서 앞서 생성한 CSR 파일을 입력해주세요. 입력후&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #333333;&quot;&gt;Continue 버튼을 누르면 &lt;span style=&quot;color: #333333;&quot;&gt;APNS SSL Certificate가&lt;/span&gt; 생성되며, Download 버튼을 눌러 다운로드 받을 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;스크린샷 2019-11-24 오전 12.22.46.png&quot; data-origin-width=&quot;1632&quot; data-origin-height=&quot;1290&quot; width=&quot;477&quot; height=&quot;377&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/TQyLn/btqzYTTEygs/zCCRedkd0ZKG82zPxUq2yk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/TQyLn/btqzYTTEygs/zCCRedkd0ZKG82zPxUq2yk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/TQyLn/btqzYTTEygs/zCCRedkd0ZKG82zPxUq2yk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FTQyLn%2FbtqzYTTEygs%2FzCCRedkd0ZKG82zPxUq2yk%2Fimg.png&quot; data-filename=&quot;스크린샷 2019-11-24 오전 12.22.46.png&quot; data-origin-width=&quot;1632&quot; data-origin-height=&quot;1290&quot; width=&quot;477&quot; height=&quot;377&quot; data-ke-mobilestyle=&quot;widthContent&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&gt;&lt;span style=&quot;color: #333333;&quot;&gt;다운로드 받은 인증서를 더블클릭하면 아래처럼 키체인에 &lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;Apple IOS Push Service&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;인증서와&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;개인키가&lt;/span&gt;&lt;/span&gt; 등록됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;a&gt;&amp;nbsp;&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;452&quot; data-origin-height=&quot;230&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bNKquh/btqzYMAo61P/urFXStfu7QjYlJv8W0wxXk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bNKquh/btqzYMAo61P/urFXStfu7QjYlJv8W0wxXk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bNKquh/btqzYMAo61P/urFXStfu7QjYlJv8W0wxXk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbNKquh%2FbtqzYMAo61P%2FurFXStfu7QjYlJv8W0wxXk%2Fimg.jpg&quot; data-origin-width=&quot;452&quot; data-origin-height=&quot;230&quot; data-ke-mobilestyle=&quot;widthContent&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 data-ke-size=&quot;size23&quot;&gt;p12 파일 생성&lt;/h3&gt;
&lt;p&gt;위에서 등록한&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;Apple IOS Push Service&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;인증서와&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;개인키를 함께 클릭한후 마우스 오른쪽을 눌러 '2개 항목 내보내기'를 클릭하여 .p12파일을 생성 합니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Pem 파일 생성&lt;/h3&gt;
&lt;p&gt;애플 개발자 홈페이지에서 다운로드 받은 인증서를 openssl을 이용해 다음과 같이 pem 파일을 만듭니다.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;openssl x509 -in 애플개발자홈에서받은.cer -inform DER -out 애개홈.pem -outform PEM&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;키체인에서 &lt;span style=&quot;color: #000000;&quot;&gt;2개 항목 내보내기'를 클릭해서 만든 .p12 파일을 openssl을 이용해 다음과 같이 pem 파일을 만듭니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;&lt;span&gt;openssl pkcs12 -nocerts -in &lt;/span&gt;&lt;span&gt;키체인에서만든&lt;/span&gt;&lt;span&gt;.p12 -out 키체인.pem&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;#&lt;b&gt;pem 파일&lt;/b&gt;이란 Privacy Enhanced Mail의 약자로 Base64 인코딩된 ASCII 파일입니다. 인증서, 개인키 등을 저장하는데 사용됩니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;해당 정보들을 Base64 방식으로 encoding하면 다음과 같이 ASCII Text형식으로 표시됩니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;#&lt;b&gt;openssl&lt;/b&gt;이란 TLS/SSL(전송계층보안) 프로토콜의 오픈 소스 구현판입니다. 소스 내에 여러 암호화 라이브러리가 구현되어 있습니다.&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;스크린샷 2019-11-24 오전 12.50.30.png&quot; data-origin-width=&quot;1552&quot; data-origin-height=&quot;1208&quot; width=&quot;584&quot; height=&quot;454&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lvet5/btqzYULLbU5/g7IEoaMvJG6jKzPtU4ay0K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lvet5/btqzYULLbU5/g7IEoaMvJG6jKzPtU4ay0K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lvet5/btqzYULLbU5/g7IEoaMvJG6jKzPtU4ay0K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Flvet5%2FbtqzYULLbU5%2Fg7IEoaMvJG6jKzPtU4ay0K%2Fimg.png&quot; data-filename=&quot;스크린샷 2019-11-24 오전 12.50.30.png&quot; data-origin-width=&quot;1552&quot; data-origin-height=&quot;1208&quot; width=&quot;584&quot; height=&quot;454&quot; data-ke-mobilestyle=&quot;widthContent&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 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;다시 p12 파일 생성&lt;/h3&gt;
&lt;p&gt;마지막으로 위에서 만든 2개의 pem 파일을 openssl을 통해 .p12 파일을 만듭니다.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;&lt;span&gt;openssl pkcs12 -export -inkey &lt;span style=&quot;color: #000000;&quot;&gt;키체인&lt;/span&gt;.pem -in &lt;span style=&quot;color: #333333;&quot;&gt;애개홈&lt;/span&gt;.pem -out &lt;/span&gt;&lt;span&gt;스프링서버에서사용할&lt;/span&gt;&lt;span&gt;.p12&lt;/span&gt;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.25em;&quot;&gt;&lt;b&gt;이렇게 생성한 &lt;span style=&quot;color: #333333;&quot;&gt;스프링서버에서사용할&lt;/span&gt;&lt;span style=&quot;color: #333333;&quot;&gt;.p12을 스프링 서버에 올려 사용하면 &lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.25em;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;APNS를 사용할 수 있습니다!&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.25em;&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;*추가개념정리&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;#x509&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;Public Key infrastructure에 대한 ITU-T의 표준으로 공개키 인증서의 포맷 revocation list(더이상 유효하지 않은 인증서들에 대한 정보), cerfication path validation 알고리즘 등을 정의한다. 보통 x509 인증서라고 하면 RFC 5290에 따라서 인코딩되거나 서명된 디지털 문서를 말합니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;#DER&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;RSA Public Key를 표시하는 포맷은 DER 포맷과 PEM 포맷이 있습니다. PKCS 표준에서는 RSA KEY를 ASN.1 방식으로 표현하라고 규정합니다. DER 포맷은 ASN.1 구조에 맞추어 DER 인코딩을 한 것입니다. binary 형태로 저장됩니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;#pkc12&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;public key Cryptography Standard 표준 중의 일부로 private key를 저장하는 문법에 관한 표준입니다. private key는 일반적으로 PEM 형식으로 인코딩됩니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;출처&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;a href=&quot;https://www.thesslstore.com/blog/what-is-a-csr/&quot;&gt;https://www.thesslstore.com/blog/what-is-a-csr/&lt;/a&gt;&lt;span&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;a href=&quot;https://www.letmecompile.com/certificate-file-format-extensions-comparison/&quot;&gt;https://www.letmecompile.com/certificate-file-format-extensions-comparison/&lt;/a&gt;&lt;span&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;a href=&quot;https://www.openssl.org/&quot;&gt;https://www.openssl.org/&lt;/a&gt;&lt;span&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;a href=&quot;https://ko.wikipedia.org/wiki/OpenSSL&quot;&gt;https://ko.wikipedia.org/wiki/OpenSSL&lt;/a&gt;&lt;span&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;a href=&quot;https://wiki.openssl.org/index.php/DER&quot;&gt;https://wiki.openssl.org/index.php/DER&lt;/a&gt;&lt;span&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;a href=&quot;https://cbsm.tistory.com/10&quot;&gt;https://cbsm.tistory.com/10&lt;/a&gt;&lt;span&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;a href=&quot;https://m.blog.naver.com/PostView.nhn?blogId=aepkoreanet&amp;amp;logNo=221089013217&amp;amp;proxyReferer=h&quot;&gt;https://m.blog.naver.com/PostView.nhn?blogId=aepkoreanet&amp;amp;logNo=221089013217&amp;amp;proxyReferer=h&lt;/a&gt;&lt;a href=&quot;https://m.blog.naver.com/PostView.nhn?blogId=aepkoreanet&amp;amp;logNo=221089013217&amp;amp;proxyReferer=https%3A%2F%2Fwww.google.com%2F&quot;&gt;&lt;span&gt;&lt;span&gt;ttps%3A%2F%2Fwww.google.com%2F&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://medium.com/@ufukatalca/generate-apns-certificate-for-ios-push-notifications-ada9234d4c09&quot;&gt;https://medium.com/@ufukatalca/generate-apns-certificate-for-ios-push-notifications-ada9234d4c09&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>개발/IOS</category>
      <author>책 읽는 개발자_테드</author>
      <guid isPermaLink="true">https://developthreefeet.tistory.com/6</guid>
      <comments>https://developthreefeet.tistory.com/6#entry6comment</comments>
      <pubDate>Sun, 17 Nov 2019 09:29:30 +0900</pubDate>
    </item>
  </channel>
</rss>