<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>CORE DATA</title>
    <link>https://doh-an.tistory.com/</link>
    <description>iOS Dev.

</description>
    <language>ko</language>
    <pubDate>Wed, 15 Jul 2026 05:16:54 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>D0HAN.</managingEditor>
    <image>
      <title>CORE DATA</title>
      <url>https://tistory1.daumcdn.net/tistory/3169882/attach/ff87441cecf04da9b15e0d119bbb50a1</url>
      <link>https://doh-an.tistory.com</link>
    </image>
    <item>
      <title>SwiftUI View Lifecycle - 뷰 생명주기 완벽 이해하기</title>
      <link>https://doh-an.tistory.com/43</link>
      <description>&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;오늘은!&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;SwiftUI 의 &lt;b&gt;View lifecycle&lt;/b&gt; 을 한번 정리해보겠습니다;)&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;UIKit 에 비해 훨씬 간단해서 한 번 읽고 넘겼었는데,&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;정확히 어떤 시점을 기준으로 상태가 변하는지 눈으로 확인해보면서 정리해 볼게요&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;SwiftUI View liifecycle 핵심 원칙&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;1. 뷰는 Value 타입&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;View 는 struct 이며, 상태가 바뀔 때마다 새로운 인스턴스 생성&lt;/li&gt;
&lt;li&gt;View의 상태변화가 생명주기의 핵심!!!&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 상태 기반 렌더링&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;@State, @ObservedObject, @EnvironmentObject 등의 상태 변경되면&lt;br /&gt;-&amp;gt; body 재평가 -&amp;gt; 새로운 뷰로 업데이트&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;background-color: #a6bc00;&quot;&gt;&lt;b&gt;View Lifecycle&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #dddddd;&quot;&gt;1)&amp;nbsp; &amp;nbsp;init()&lt;/span&gt;&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;뷰 인스턴스가 생성될 때 호출됨&lt;/li&gt;
&lt;li&gt;프로퍼티 초기화, 로그 출력에 사용가능&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #dddddd;&quot;&gt;2)&amp;nbsp; &amp;nbsp;.onAppear&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;뷰가 화면에 나타나기 &lt;b&gt;직전&lt;/b&gt; 호출&lt;/li&gt;
&lt;li&gt;네트워크 요청, 초기 데이터로딩 등 사용&lt;/li&gt;
&lt;li&gt;뷰가 재조합 되어 다시 나타날 때도 호출 될 수 있음! 주의&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #dddddd;&quot;&gt;3)&amp;nbsp; &amp;nbsp;.onDisappear&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;뷰가 화면에서 사라질 때 호출됨&lt;/li&gt;
&lt;li&gt;일부 컨테이너(NavigationLink, TabView, LazyVStack등) 에서는 실제로 메모리에서 해제되지 않아 호출 되지 않을 수도 있다고 한다....&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #dddddd;&quot;&gt;4)&amp;nbsp; &amp;nbsp;.Task (iOS15+)&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;비동기 작업을 위한 modifier!!&lt;/li&gt;
&lt;li&gt;뷰가 나타날 때 자동 실행되고, 사라질 때 cancel 호출&lt;/li&gt;
&lt;li&gt;네트워크 요청에 사용&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개념은 대충 알겠으니 한번 직접 눈으로 확인해 봅시다!-!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;&lt;b&gt;Test 코드&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1746894059509&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import SwiftUI

struct test: View {
    @State private var isToggled = false
    
    init(){
        print(&quot;❤️init() called&quot;)
    }
    var body: some View {
        
        VStack(spacing: 20) {
            Text(&quot;SwiftUI View Lifecycle&quot;)
                .font(.title)
            
            Button(action: {
                self.isToggled.toggle()
            }) {
                Text(&quot;Show Subview&quot;)
            }.sheet(isPresented: $isToggled, content: {
                Subview()
                    .presentationDetents([.medium])
            })
            
        }
        .onAppear {
            print(&quot;❤️onAppear() called&quot;)
        }
        .onDisappear{
            print(&quot;❤️onDisappear() called&quot;)
        }
    }
}


struct Subview: View {
    
    init() {
        print(&quot; SubView init() called&quot;)
    }
    
    var body: some View {
        VStack{
            Text(&quot;Subview&quot;)
        }
        .onAppear{
            print(&quot; SubView onAppear() called&quot;)
        }
        .onDisappear {
            print(&quot; SubView onDisappear() called&quot;)
        }
        .task {
            print(&quot; Start task ---&quot;)
            sleep(3)
            print(&quot;--- End task &quot;)
        }
        
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Screenshot 2025-05-10 at 12.14.48 PM.png&quot; data-origin-width=&quot;984&quot; data-origin-height=&quot;348&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cUg2ug/btsNSztkMig/eU0lIWB77imK2g4zbuRVs1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cUg2ug/btsNSztkMig/eU0lIWB77imK2g4zbuRVs1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cUg2ug/btsNSztkMig/eU0lIWB77imK2g4zbuRVs1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcUg2ug%2FbtsNSztkMig%2FeU0lIWB77imK2g4zbuRVs1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;984&quot; height=&quot;348&quot; data-filename=&quot;Screenshot 2025-05-10 at 12.14.48 PM.png&quot; data-origin-width=&quot;984&quot; data-origin-height=&quot;348&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;문제:&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 테스트를 통해 확인해본 결과,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;sleep() 으로 3초 지연을 준 task에서, 뷰를 닫기 전에 닫기 버튼을 눌러도 뷰가 즉시 사라지지 않았습니다....왜일까요???&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;✅ &lt;b&gt;정답&lt;/b&gt;:&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;sleep() 이라는 함수는 동기함수로 메인 스레드를 블락하기 때문에, 뷰가 사라지는 시점조차 대기 상태가 되어버립니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SwiftUI의 UI 업데이트는 메인스레드에서 진행되므로 치명적인 실수가 될 수 있겠죠&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;  해결 방법&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비동기적 대기를 위해서는 Task.sleep() 을 사용하면 됩니다 ^___^&lt;/p&gt;
&lt;pre id=&quot;code_1746991533321&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;    .task {
        print(&quot; Start task ---&quot;)
        try await Task.sleep(nanoseconds: 5_000_000_000) //5초
        print(&quot;--- End task &quot;)
    }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위에서는 sheet 을 통한 화면전환을 시도해 보았는데,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;NavigationLink 차이점도 궁금해서 코드 살짝 바꿔서 다시 테스트 해보았습니다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1746894579218&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;NavigationStack {
            NavigationLink(destination: Subview()){
                Text(&quot;Navigation Subview&quot;)
            }
        }
        
   (...)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Screenshot 2025-05-11 at 8.03.53 AM.png&quot; data-origin-width=&quot;836&quot; data-origin-height=&quot;312&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b18eZv/btsNSLmPKx5/pqAWNSKZUGRE9pKIvDwDAK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b18eZv/btsNSLmPKx5/pqAWNSKZUGRE9pKIvDwDAK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b18eZv/btsNSLmPKx5/pqAWNSKZUGRE9pKIvDwDAK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb18eZv%2FbtsNSLmPKx5%2FpqAWNSKZUGRE9pKIvDwDAK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;836&quot; height=&quot;312&quot; data-filename=&quot;Screenshot 2025-05-11 at 8.03.53 AM.png&quot; data-origin-width=&quot;836&quot; data-origin-height=&quot;312&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번엔 Task 가 종료되기 전에 Subview 를 닫아보았어요&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 sleep() 처럼 메인스레드를 막지 않아서 바로 onDisappear() 가 호출되긴 하지만, 여전히 endTask 로그가 프린트 되는 걸 확인했습니다 ㅇ0ㅇ 두둥.. 뷰가 사라지면 같이 종료되어야하는거 아냐?&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Screenshot 2025-05-11 at 2.44.26 PM.png&quot; data-origin-width=&quot;1712&quot; data-origin-height=&quot;1392&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bby1tC/btsNTaGNdGC/2IaywlBvPEkbIpZE0gui31/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bby1tC/btsNTaGNdGC/2IaywlBvPEkbIpZE0gui31/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bby1tC/btsNTaGNdGC/2IaywlBvPEkbIpZE0gui31/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbby1tC%2FbtsNTaGNdGC%2F2IaywlBvPEkbIpZE0gui31%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1712&quot; height=&quot;1392&quot; data-filename=&quot;Screenshot 2025-05-11 at 2.44.26 PM.png&quot; data-origin-width=&quot;1712&quot; data-origin-height=&quot;1392&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;공식문서에도 명확히 설명되진 않는 거 같지만...&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;알고보니 task는 뷰가 사라질때 cancel 요청을 하지만, 내부에서 cacel 처리를 명시적으로 처리해주어야 합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 코드의 경우 try await Task.sleep(nanoseconds: 5_000_000_000) 구문은 취소처리되기때문에 5초가 지나지 않아도 바로 취소되고, 다음 코드로 넘어간 거라고 보면 되겠네요 :)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;cancel 처리를 해주기 위해 이렇게 코드를 고쳐보았습니다&lt;/p&gt;
&lt;pre id=&quot;code_1746989497574&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;.task {
            print(&quot; Start task ---&quot;)
            do {
                try await Task.sleep(nanoseconds: 5_000_000_000)
                print(&quot;--- End task &quot;)
            } catch {
                print(&quot; task canceled&quot;)
            }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Screenshot 2025-05-11 at 2.52.45 PM.png&quot; data-origin-width=&quot;722&quot; data-origin-height=&quot;328&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c1TYSy/btsNTGSKTZM/X2jk5UFsqjlNKtgWA47yvK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c1TYSy/btsNTGSKTZM/X2jk5UFsqjlNKtgWA47yvK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c1TYSy/btsNTGSKTZM/X2jk5UFsqjlNKtgWA47yvK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc1TYSy%2FbtsNTGSKTZM%2FX2jk5UFsqjlNKtgWA47yvK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;722&quot; height=&quot;328&quot; data-filename=&quot;Screenshot 2025-05-11 at 2.52.45 PM.png&quot; data-origin-width=&quot;722&quot; data-origin-height=&quot;328&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 do-catch 로 감싸면 드디어! 캔슬 처리가 되는걸 볼 수 있습니다 하하&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;task 캔슬처리를 확실히 해야 할 때는 꼭 명시적으로 처리를 해주기&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;추가 발견&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;혹시 다른점을 눈치채셧나요...&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;sheet 으로 subView 를 띄우면, 버튼을 눌러야 Subview의 init()이 호출됩니다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Navigation Stack 을 사용할때는 링크의 destination 인 뷰까지 함께 평가하면서 init() 처리를 해주는것두 알 수 있네용&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;  NavigationLink는 뷰를 미리 평가하고 초기화 하기 때문&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;이렇게 SwiftUI 의 생명주기를 간단하게 알아보고, 로그도 찍어보았습니다&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;중간중간 사족때문에 생각보다 글이 길어졌는데, 그래도 쫌쫌따리 도움이 되셨길 바라며....&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;다른 의견이나 질문 있으시면 언제든 댓글 달아주세요 :)&lt;/p&gt;</description>
      <category>iOS/swiftUI</category>
      <category>SwiftUI</category>
      <category>swiftui .task</category>
      <category>swiftui lifecycle</category>
      <category>swiftui 뷰생명주기</category>
      <category>swiftui생명주기</category>
      <category>view lifecycle</category>
      <category>뷰 lifecycle</category>
      <category>뷰 생명주기</category>
      <author>D0HAN.</author>
      <guid isPermaLink="true">https://doh-an.tistory.com/43</guid>
      <comments>https://doh-an.tistory.com/43#entry43comment</comments>
      <pubDate>Mon, 12 May 2025 21:07:25 +0900</pubDate>
    </item>
    <item>
      <title>Cocoa touch framework 정리</title>
      <link>https://doh-an.tistory.com/42</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;코코아 터치 프레임워크(Cocoa touch framework)&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;UIKit: 아이폰, 아이패드, 애플워치 등에서 실행되는 애플리케이션의 유저인터페이스 제공&lt;br /&gt;터치, 지문인식, 각종 센서 등 사용자액션 처리 요소 구현&lt;/li&gt;
&lt;li&gt;Foundation :어플리케이션 핵심 객체와 네트워크, 문자열 처리 등 서비스 지원&lt;/li&gt;
&lt;li&gt;iOS,watchOS, tvOS 에 사용&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;코코아 프레임워크(Cocoa framework)&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;AppKit&lt;/li&gt;
&lt;li&gt;Foundation : 코코아터치에서 사용되는 파운데이션 프레임워크와 동일&lt;/li&gt;
&lt;li&gt;macOS에 사용&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;프레임워크 계층구조&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;프레임워크는 하위 프레임워크에 의존적이다.&lt;/li&gt;
&lt;li&gt;ex) Cocoa Touch (상위)&lt;br /&gt;Media&lt;br /&gt;Core Service&lt;br /&gt;Core OS (하위)&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;1. Core OS&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;커널, 파일 시스템, 네트워크, 보안, 전원관리, 디바이스 드라이버 등 포함되어있음.&lt;/li&gt;
&lt;li&gt;iOS가 운영체제로서 기능을 하기 위한 핵심적인 영역&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;2. Core Service&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;문자열 처리, 데이터 집합 관리, 네트워크 , 주소록 관리, 환경설정 등 핵심적 서비스 제공&lt;/li&gt;
&lt;li&gt;GPS, 나침반, 가속도 센서, 자이로스코프 센서 - 디바이스 하드웨어 특성에 기반한 서비스&lt;/li&gt;
&lt;li&gt;Core Foundation 프레임워크 속해있음(Foundation 프레임워크가 내부적으로 의존)&lt;/li&gt;
&lt;li&gt;Core Data 프레임워크 포함&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;3. Media&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;코코아 터치 계층에 그래픽 관련 서비스, 멀티미디어 관련 서비스 제공&lt;/li&gt;
&lt;li&gt;코어 그래픽스, 코어 텍스트, 코어 오디오, 코어 애니메이션, AV파운데이션 등&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;4. Cocoa Touch&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;애플리케이션 프레임워크 계층 이라고도 불림&lt;/li&gt;
&lt;li&gt;UIKit 프레임워크, Game Kit, Map Kit 등의 프레임워크 속해있음&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;프레임워크 접두어&lt;/b&gt;&lt;/h3&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 395px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style16&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;width: 25%; height: 19px;&quot;&gt;&lt;b&gt;프레임워크&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 12.5%; height: 19px;&quot;&gt;&lt;b&gt;접두어&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 37.5%;&quot; colspan=&quot;2&quot;&gt;&lt;b&gt;주요 객체&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 25%; height: 17px;&quot;&gt;Foundation Framework&lt;/td&gt;
&lt;td style=&quot;width: 12.5%; height: 17px;&quot;&gt;NS&lt;/td&gt;
&lt;td style=&quot;width: 37.5%;&quot; colspan=&quot;2&quot;&gt;NSDate, NSData, NSURL ...&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 35px;&quot;&gt;
&lt;td style=&quot;width: 25%; height: 35px;&quot;&gt;UIKit Framework&lt;/td&gt;
&lt;td style=&quot;width: 12.5%; height: 35px;&quot;&gt;UI&lt;/td&gt;
&lt;td style=&quot;width: 37.5%;&quot; colspan=&quot;2&quot;&gt;UIApplication, UIViewController, UIView, UIButton ...&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 35px;&quot;&gt;
&lt;td style=&quot;width: 25%; height: 35px;&quot;&gt;UserNotifications Framework&lt;/td&gt;
&lt;td style=&quot;width: 12.5%; height: 35px;&quot;&gt;UN&lt;/td&gt;
&lt;td style=&quot;width: 37.5%;&quot; colspan=&quot;2&quot;&gt;UNNotification, UNNotificationContent ...&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 25%; height: 17px;&quot;&gt;MapKit Framework&lt;/td&gt;
&lt;td style=&quot;width: 12.5%; height: 17px;&quot;&gt;MK&lt;/td&gt;
&lt;td style=&quot;width: 37.5%;&quot; colspan=&quot;2&quot;&gt;MKAnnotaionView, MKCircle ...&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 25%; height: 17px;&quot;&gt;Core Foundation&lt;/td&gt;
&lt;td style=&quot;width: 12.5%; height: 17px;&quot;&gt;CF&lt;/td&gt;
&lt;td style=&quot;width: 37.5%;&quot; colspan=&quot;2&quot;&gt;CFBundle, CFData, CFDate ...&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 25%; height: 17px;&quot;&gt;Core Graphics&lt;/td&gt;
&lt;td style=&quot;width: 12.5%; height: 17px;&quot;&gt;CG&lt;/td&gt;
&lt;td style=&quot;width: 37.5%;&quot; colspan=&quot;2&quot;&gt;CGColor, CGContext, CGImage, CGGradient, CGLayer, CGSize ...&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 25%; height: 17px;&quot;&gt;AVFoundation&lt;/td&gt;
&lt;td style=&quot;width: 12.5%; height: 17px;&quot;&gt;AV&lt;/td&gt;
&lt;td style=&quot;width: 12.5%;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 17px;&quot;&gt;AVAssetReader,AVAudioUnit ...&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>iOS</category>
      <category>Cocoa</category>
      <category>cocoa touch</category>
      <category>SWIFT</category>
      <category>UIKit</category>
      <category>코코아터치</category>
      <author>D0HAN.</author>
      <guid isPermaLink="true">https://doh-an.tistory.com/42</guid>
      <comments>https://doh-an.tistory.com/42#entry42comment</comments>
      <pubDate>Sun, 15 Jan 2023 19:43:30 +0900</pubDate>
    </item>
    <item>
      <title>[Swift] 프로퍼티(Property)- 프로퍼티의 정의, 종류</title>
      <link>https://doh-an.tistory.com/41</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;증말 기본적인 개념인데도&amp;nbsp;그냥 대애충 두루뭉술하게만 알고 넘어갔었더라고요  &lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;막상 구체적으로 문제가 나오니까 확실히 아는게 없는 것 같아서&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 기회에 한 번 정리해봅니다 &amp;gt;&amp;lt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div class=&quot;book-toc&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;목차&lt;/p&gt;
&lt;ul id=&quot;toc&quot; style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;&lt;/ul&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-08-07 오후 10.37.36.png&quot; data-origin-width=&quot;1244&quot; data-origin-height=&quot;256&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/LvjGm/btrI2xn4fFm/W5MsZyxmvchUtsIaNUDT8k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/LvjGm/btrI2xn4fFm/W5MsZyxmvchUtsIaNUDT8k/img.png&quot; data-alt=&quot;프로퍼티란, 클래스나 구조체 또는 열거형에 값을 할당합니다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/LvjGm/btrI2xn4fFm/W5MsZyxmvchUtsIaNUDT8k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FLvjGm%2FbtrI2xn4fFm%2FW5MsZyxmvchUtsIaNUDT8k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; alt=&quot;Properties associate values with a particular class&amp;amp;#44; structure&amp;amp;#44; or enumeration.&quot; loading=&quot;lazy&quot; width=&quot;600&quot; height=&quot;256&quot; data-filename=&quot;스크린샷 2022-08-07 오후 10.37.36.png&quot; data-origin-width=&quot;1244&quot; data-origin-height=&quot;256&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;프로퍼티란, 클래스나 구조체 또는 열거형에 값을 할당합니다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;프로퍼티란 어떤 대상(클래스,구조체,열거형etc.)에 값을 할당해주는 존재입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;프로퍼티는 크게 저장 프로퍼티,&amp;nbsp; 연산&amp;nbsp; 프로퍼티로 나눌 수 있습니다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;저장 프로퍼티 (Stored Properties)&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Stored Properties&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;► 이름에서 알 수 있듯 가장 단순하고 기본적인 개념의 프로퍼티로, 클래스 또는 구조체의 인스턴스와 연관된 값을 저장하는 프로퍼티&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;► 클래스 / 구조체에서만 사용 가능!! (열거형x)&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;- 변수 저장 프로퍼티 (variable stored properties) - var 키워드 사용&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;- 상수 저장 프로퍼티 (constant stored properties) - let 키워드 사용&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1660045240820&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;struct Point {
  var x: Int  // 변수 저장 프로퍼티
  let y: Int  // 상수 저장 프로퍼티 
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;정의에서 봤듯이 어떤 대상 - 이경우에는 &lt;b&gt;Point&lt;/b&gt;&amp;nbsp; 라는 구조체에 &lt;b&gt;x,y&lt;/b&gt;라는 값을 할당해주는 애들이 &lt;b&gt;프로퍼티&lt;/b&gt;&amp;nbsp; 입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Lazy Stored Properties&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;► lazy라는 키워드를 사용하는 지연 저장 프로퍼티는 호출이 있어야 값을 초기화 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;그 말은, 값이 처음으로 사용 되기 전에는 계산되지 않는다는 말이죠!&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;► 지연 저장 프로퍼티는 반드시! &lt;b&gt;var&lt;/b&gt;로 선언해야 합니다. &amp;nbsp;let 선언은 초기화가 되기 전에 항상 값을 갖는 프로퍼티이기 때문!!!&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;► 어떨 때 유용할까? 프로퍼티가 특정 요소에 의존적이어서, 그 요소가 끝나기 전에 값을 알 수 없는 경우.&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;혹은 복잡한 계산, 부하가 많이 걸리는 작업을 lazy로 선언하면 인스턴스 초기화 시점에 복잡한 계산을 피할 수 있읍니당.&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;► 지연 프로퍼티가 여러 스레드에서 사용되면? 한번만 실행된다는 보장이 x. Thread safe 하지 않음!!&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;► 단일 스레드에서 사용될 경우 초기화는 한 번!&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1660047497445&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class DataImporter {
    /*
        겁 나 오 래 걸 리 는 초기화 작업
    */
     
    var filename = &quot;data.txt&quot;
}

class DataManager {
    lazy var importer = DataImporter()
    var data = [String]()
    /*
       데이터를 관리하는 기능
    */
}

let manager = DataManager()
manager.data.append(&quot;Some data&quot;)
manager.data.append(&quot;Some more data&quot;)
// DataImporter 인스턴스는 이 시점에 생성돼 있지 x

//이렇게 직접 importer 인스턴스에 접근할때야 생성됨
print(manager.importer.filename)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;연산 프로퍼티 (Computed Properties)&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;► &lt;b&gt;클래스, 구조체, 열거형&lt;/b&gt;은 저장 프로퍼티 뿐만 아니라 연산 프로퍼티도 선언할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;► 저장 프로퍼티와 다르게 실제 값을 저장하고 있는 것이 아니라, 다른 프로퍼티와 간접적으로 값을 검색하고 세팅합니다&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp; &amp;nbsp; 그게 바로 &lt;b&gt;getter&lt;/b&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;와&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;setter&lt;/b&gt;(optional)라는 연산 프로퍼티!&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;► 계산값에 따라 값이 변할 수 있는 프로퍼티이기 때문에 항상 &lt;b&gt;var&lt;/b&gt; 으로 선언!!!&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;►set(newValue) { ... } 와 같은 구조에서 (newValue)라고 인자이름을 지정하지 않아도 기본 이름인 newValue를 사용할 수 있습니다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;like this&lt;/p&gt;
&lt;pre id=&quot;code_1660049555978&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;set {
            origin.x = newValue.x - (size.width / 2)
            origin.y = newValue.y - (size.height / 2)
        }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;► 예제 1&lt;/p&gt;
&lt;pre id=&quot;code_1660048815476&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class P {
	var x: Int {
    		get { return x }
        	set(newValue) { x = newValue * 2 }
    }
}

var p = Point()
p.x = 12 		// error!&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;이렇게 하면 에러가 납니다!!!!!&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;x값이 자기 자신을 리턴하고 자기 자신을 두배로 만들고 있기 때문에 이렇게 사용하면 오류가 납니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;그래서 getter setter에는 필수적으로 변수가 더 있어야하는데, 이처럼 내부에서 사용하는 변수용으로 사용하는 stored Property는 언더바를 붙인 형태로 구분합니다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1660049067658&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class Test {

    private var _myProperty: Int
    
    var myProperty: Int {
        get {
            return _myProperty
        }
        set {
            return _myProperty = newValue
        }
    }

}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;► 예제2&lt;/p&gt;
&lt;pre id=&quot;code_1660049202843&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;struct Point {
    var x = 0.0, y = 0.0
}
struct Size {
    var width = 0.0, height = 0.0
}


struct Rect {
    var origin = Point()
    var size = Size()
    var center: Point {
        get {
            let centerX = origin.x + (size.width / 2)
            let centerY = origin.y + (size.height / 2)
            return Point(x: centerX, y: centerY)
        }
        set {
            origin.x = newValue.x - (size.width / 2)
            origin.y = newValue.y - (size.height / 2)
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;center라는 Point형 변수에 접근할 때는 origin, size라는 다른 프로퍼티를 이용하여 계산하고, center를 직접 설정할 때는 size를 이용해서 origin을 변경하고 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1660049334685&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;var square = Rect(origin: Point(x: 0.0, y: 0.0),
                  size: Size(width: 10.0, height: 10.0))
                  
let initialSquareCenter = square.center	//getter로 square의 center값 가져옴
square.center = Point(x: 15.0, y: 15.0) //setter로 center값 변경


print(&quot;square.origin is now at (\(square.origin.x), \(square.origin.y))&quot;)
// &quot;square.origin is now at (10.0, 10.0)&quot; 출력&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;background-color: #c0d1e7;&quot;&gt;&lt;b&gt;프로퍼티 옵저버 (Property Observers)&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;► 프로퍼티에 새 값이 설정(set)될 때마다 이벤트를 감지할 수 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;► 지연 저장 프로퍼티(lazy stored properties)에서는 사용할 수 없음!&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;► 연산 프로퍼티는 setter에서 값의 변화를 감지하므로 따로 옵저버를 정의할 필요가 없음!&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;► willSet : 값이 저장되기 바로 직전에 호출 (연산프로퍼티의 set에서와 마찬가지로 기본 값으로 newValue라는 파라미터명 사용)&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;didSet : 값이 저장되고 난 직후에 호출 (oldValue라는 파라미터 사용)&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;► 예제&lt;/p&gt;
&lt;pre id=&quot;code_1660050111483&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class StepCounter {
    var totalSteps: Int = 0 {
        willSet(newTotalSteps) {
            print(&quot;About to set totalSteps to \(newTotalSteps)&quot;)
        }
        didSet {
            if totalSteps &amp;gt; oldValue  {
                print(&quot;Added \(totalSteps - oldValue) steps&quot;)
            }
        }
    }
}
let stepCounter = StepCounter()
stepCounter.totalSteps = 200
// About to set totalSteps to 200
// Added 200 steps
stepCounter.totalSteps = 360
// About to set totalSteps to 360
// Added 160 steps
stepCounter.totalSteps = 896
// About to set totalSteps to 896
// Added 536 steps&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;참고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://jusung.gitbook.io/the-swift-language-guide/language-guide/10-properties&quot;&gt;https://jusung.gitbook.io/the-swift-language-guide/language-guide/10-properties&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://jinshine.github.io/2018/05/22/Swift/6.%ED%94%84%EB%A1%9C%ED%8D%BC%ED%8B%B0(Property)/&quot;&gt;https://jinshine.github.io/2018/05/22/Swift/6.%ED%94%84%EB%A1%9C%ED%8D%BC%ED%8B%B0(Property)/&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://ios-development.tistory.com/552&quot;&gt;https://ios-development.tistory.com/552&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>iOS</category>
      <category>getter</category>
      <category>lazy property</category>
      <category>observer</category>
      <category>property</category>
      <category>setter</category>
      <category>stored property</category>
      <category>SWIFT</category>
      <category>swift getter</category>
      <category>swift setter</category>
      <author>D0HAN.</author>
      <guid isPermaLink="true">https://doh-an.tistory.com/41</guid>
      <comments>https://doh-an.tistory.com/41#entry41comment</comments>
      <pubDate>Tue, 9 Aug 2022 22:05:27 +0900</pubDate>
    </item>
    <item>
      <title>iOS 소셜로그인 구현 - 구글 로그인 연동</title>
      <link>https://doh-an.tistory.com/40</link>
      <description>&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;안녕하세요 ! 도안입니당 :&amp;gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;티스토리가 다 쓴 글을 날려버렸어요... 분명 자동저장 열심히했는데 이자식.....&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;어쩌겠나요 다시써야지 ᵕ᷄≀ ̠˘᷅&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://doh-an.tistory.com/37&quot;&gt;&amp;gt;&amp;gt;카카오 로그인 하는 법 보러가기&amp;lt;&amp;lt;&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;암튼 지난번 카카오 로그인에 이어서!!&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;이번엔 구글 로그인 연동을 해보겠습니다~! (신난다~~)&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;그럼 목차 훑어주고 가실게요~~&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div class=&quot;book-toc&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;iOS 구글 로그인 연동&lt;/p&gt;
&lt;ul id=&quot;toc&quot; style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;&lt;/ul&gt;
&lt;/div&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;결국 자동목차 기능 넣음,, 편하네요&amp;gt;&amp;lt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;b&gt;1. Pod File 설치&lt;/b&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;pre id=&quot;code_1652550098858&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;pod 'GoogleSignIn'&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;pod file 에 추가해주기 ~ pod install ~~&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;2. 구글 클라우드 Client ID 받기&lt;/b&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;프로젝트 생성&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 &lt;a title=&quot;구글 클라우드 플랫폼&quot; href=&quot;https://console.cloud.google.com/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;구글 클라우드 플랫폼&lt;/a&gt;에 프로젝트를 생성하고, iOS용 클라이언트 ID를 만들어야 합니다 ^_^&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-04-28 오전 11.49.15.png&quot; data-origin-width=&quot;3360&quot; data-origin-height=&quot;1722&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/GVXkq/btrAD75kA4S/GMxZg2WS34ttqMZILuEa3K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/GVXkq/btrAD75kA4S/GMxZg2WS34ttqMZILuEa3K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/GVXkq/btrAD75kA4S/GMxZg2WS34ttqMZILuEa3K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FGVXkq%2FbtrAD75kA4S%2FGMxZg2WS34ttqMZILuEa3K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;3360&quot; height=&quot;1722&quot; data-filename=&quot;스크린샷 2022-04-28 오전 11.49.15.png&quot; data-origin-width=&quot;3360&quot; data-origin-height=&quot;1722&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;왼쪽 상단에 프로젝트 선택하는 박스에서 [새 프로젝트 생성]을 눌러 프로젝트를 만들어봅시다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로젝트를 만드셨으면 왼쪽 탭의 [API 및 서비스] &amp;gt;&amp;gt;[OAuth동의 화면] &amp;gt;&amp;gt; [User Type 외부] &amp;gt;&amp;gt; 앱 이름, 이메일,개발자 연락처 등록하고 저장!&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Client ID 발급 받기&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[API및 서비스] &amp;gt;&amp;gt; [사용자 인증 정보] &amp;gt;&amp;gt; [+ 사용자 인증 정보 만들기]&amp;nbsp; &amp;gt;&amp;gt; [OAuth 클라이언트 ID] &amp;gt;&amp;gt; [iOS] &amp;gt;&amp;gt; 번들ID, 앱스토어 ID(있는경우만) 입력&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;까지 하시면 클라이언트 아이디가 생성됩니다! &amp;gt;.&amp;lt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;깃에 클라이언트 ID 를 숨기기 위해서 저는 따로 파일을 분리해서 Struct를 만들어두고 gitignore에 포함시켰어요!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;3. 프로젝트 설정&lt;/b&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;URL Scheme 추가&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-05-13 오후 5.45.29.png&quot; data-origin-width=&quot;1268&quot; data-origin-height=&quot;1284&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bRyu54/btrB6jil7P5/FWMHrpn3ZeTxtqn2TAXDVK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bRyu54/btrB6jil7P5/FWMHrpn3ZeTxtqn2TAXDVK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bRyu54/btrB6jil7P5/FWMHrpn3ZeTxtqn2TAXDVK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbRyu54%2FbtrB6jil7P5%2FFWMHrpn3ZeTxtqn2TAXDVK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;600&quot; height=&quot;1284&quot; data-filename=&quot;스크린샷 2022-05-13 오후 5.45.29.png&quot; data-origin-width=&quot;1268&quot; data-origin-height=&quot;1284&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자 저기 URL Types 에 !&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아까 받았던 클라이언트 ID 를 &lt;i&gt;&lt;b&gt;역순&lt;/b&gt;&lt;/i&gt; 으로 등록해줍니다~~&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;클라이언트어쩌고&lt;/span&gt;.&lt;span style=&quot;color: #f89009;&quot;&gt;apps&lt;/span&gt;.&lt;span style=&quot;color: #009a87;&quot;&gt;googleusercontent&lt;/span&gt;.&lt;span style=&quot;color: #006dd7;&quot;&gt;com&lt;/span&gt;&amp;nbsp; (x)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;com&lt;/span&gt;.&lt;span style=&quot;color: #009a87;&quot;&gt;googleusercontent&lt;/span&gt;.&lt;span style=&quot;color: #f89009;&quot;&gt;apps&lt;/span&gt;.&lt;span style=&quot;color: #ee2323;&quot;&gt;클라이언트어쩌고&lt;/span&gt; (o)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;SceneDelegate / AppDelegate&amp;nbsp;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 프로젝트에 의존성을 주입하고 ! 프로젝트 세팅을 해봅시당&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다들 아시다시피, iOS13이후로는 프로젝트 생성시에 SceneDelegate 를 기본으로 채택하게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;근데 제가 못찾은건지 구글공식문서에는 AppDelegate에서 설정하는 법밖에 없더라고요!ㅜ.ㅜ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단 구글문서에 나온 방법 ▼&lt;/p&gt;
&lt;pre id=&quot;code_1652554017548&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import GoogleSignIn
...
func application(
  _ app: UIApplication,
  open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]
) -&amp;gt; Bool {
  var handled: Bool

  handled = GIDSignIn.sharedInstance.handle(url)
  if handled {
    return true
  }

  // Handle other custom URL types.

  // If not handled by this app, return false.
  return false
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SceneDelegate에서 관리하는 방법 ▼&lt;/p&gt;
&lt;pre id=&quot;code_1652688005599&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import GoogleSignIn
...
func scene(_ scene: UIScene, openURLContexts URLContexts: Set&amp;lt;UIOpenURLContext&amp;gt;) {
        if let url = URLContexts.first?.url {
            
            if ((url.scheme?.contains(&quot;com.googleusercontent.apps&quot;)) != nil) {  //구글 링크인지
                GIDSignIn.sharedInstance.handle(url)
            }
        }
    }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약 다른 url 도 같이 있다면? 요렇게 구분해줘야겠죠 ?!&amp;nbsp; ▼&lt;/p&gt;
&lt;pre id=&quot;code_1652688045241&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;func scene(_ scene: UIScene, openURLContexts URLContexts: Set&amp;lt;UIOpenURLContext&amp;gt;) {
        if let url = URLContexts.first?.url {
            
            if (AuthApi.isKakaoTalkLoginUrl(url)) { //카카오 링크인지
                _ = AuthController.handleOpenUrl(url: url)
            }else if ((url.scheme?.contains(&quot;com.googleusercontent.apps&quot;)) != nil) {  //구글 링크인지
                GIDSignIn.sharedInstance.handle(url)
            }
        }
    }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;4. 로그인 구현&lt;/b&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;GIDConfiguration 생성&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;로그인 기능을 할 VC에다가 또 GoogleSignIn 을 임포트 해주고, configuration 생성을 해줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1652697271015&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;let signInConfig = GIDConfiguration.init(clientID: &quot;YOUR_IOS_CLIENT_ID&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;로그인&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;생성한 configuration으로 로그인을 해봅시다-!&lt;/p&gt;
&lt;pre id=&quot;code_1652697902845&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@IBAction func signIn(sender: Any) {
	//전 여기서 생성했어요!
	let signInConfig = GIDConfiguration.init(clientID: &quot;YOUR_IOS_CLIENT_ID&quot;)
    
	GIDSignIn.sharedInstance.signIn(with: signInConfig, presenting: self) { user, error in
    	guard error == nil else { return }

    // If sign in succeeded, display the app's main content View.
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;유저 정보 받아오기&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 받아온 user로 유저 정보를 받아올 수 있어요!!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Like this&lt;/p&gt;
&lt;pre id=&quot;code_1652698137922&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;let email = user.profile?.email 
let fullName = user.profile?.name	// name = givenName + familyName
let given = user.profile?.givenName
let family = user.profile?.familyName
let profilePicUrl = user.profile?.imageURL(withDimension: 320)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;토큰은 어디갔냐구요? 요렇게 받아오시면 됩니다 :3&lt;/p&gt;
&lt;pre id=&quot;code_1652698207560&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;GIDSignIn.sharedInstance.signIn(with: signInConfig, presenting: self) { user, error in
    guard error == nil else { return }
    guard let user = user else { return }

    user.authentication.do { authentication, error in
        guard error == nil else { return }
        guard let authentication = authentication else { return }

        let idToken = authentication.idToken
        // Send ID token to backend (example below).
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;로그아웃&lt;/b&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1652699570355&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@IBAction func signOut(sender: Any) {
  GIDSignIn.sharedInstance.signOut()
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;까지 하면~!! 필수적인 기능은 끝입니다  &lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;5. 추가적인 이슈&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실 구현을 다 해놓고 로그인 에러가 뜨는 현상이 발생했었습니다 :(&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;토큰을 서버에 보냈는데 verify가 안된다는 응답만 오더라고요 이게 무슨일이냐!!!&amp;nbsp;암만 코드를 뜯어봐도 잘못된게없는데?! 해서 서버 파트랑 얘기를 해봤는데요&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;알고보니까 서버측에도 제가 가지고 있었던 ClientID를 알려줘야 했더라고요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;변경된 클라이언트ID를 서버측에 알려주지 않아서 생긴 문제였습니다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클라에서 토큰만 받아서 카카오측에 유효한 토큰인지 확인하는 카카오 로그인과 달리,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;구글이랑 애플은 추가적인 정보(클라이언트 아이디,key id, team id 등등...)를 한번 더 검증하더라고요~&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서버쪽에 클라이언트 아이디 잘 알려주니까 깨끗하게 해결 됐습니다 ^ㅡ^&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://developers.google.com/identity/sign-in/ios/sign-in&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;구글 공식 문서&lt;/a&gt;를 참고해서 작성했습니다 XD&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;혹시 틀린 부분이나 뭔가 개선할 부분은 댓글로 말씀해주시면 정말 감사하겠습니다!!!(제발료 저도 알고싶어요)&lt;/p&gt;</description>
      <category>iOS</category>
      <category>IOS</category>
      <category>ios 구글 로그인 연동</category>
      <category>ios 구글로그인</category>
      <category>ios 로그인</category>
      <category>ios 로그인 에러</category>
      <category>sign in google</category>
      <category>구글로그인</category>
      <category>구글로그인 구현</category>
      <category>소셜로그인</category>
      <author>D0HAN.</author>
      <guid isPermaLink="true">https://doh-an.tistory.com/40</guid>
      <comments>https://doh-an.tistory.com/40#entry40comment</comments>
      <pubDate>Mon, 16 May 2022 20:16:27 +0900</pubDate>
    </item>
    <item>
      <title>iOS 소셜 로그인 구현 - 카카오톡 로그인 연동</title>
      <link>https://doh-an.tistory.com/37</link>
      <description>&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;안녕하세요! 도안입니당.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;요 며칠 소셜 로그인때문에 애먹었는데 기록해두지 않으면 또 헤맬 것 같아서 기록해둡니다!&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;사실 애먹은 이유는 bundle id, certeficates 쪽이긴 한데, 이것두 나중에 포스팅하겠습니다~~&lt;/span&gt;&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1200&quot; data-origin-height=&quot;1460&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/odlrU/btrBzd38krQ/oDH6z8R7HdUHhnT89jKgl0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/odlrU/btrBzd38krQ/oDH6z8R7HdUHhnT89jKgl0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/odlrU/btrBzd38krQ/oDH6z8R7HdUHhnT89jKgl0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FodlrU%2FbtrBzd38krQ%2FoDH6z8R7HdUHhnT89jKgl0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;700&quot; height=&quot;852&quot; data-origin-width=&quot;1200&quot; data-origin-height=&quot;1460&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;카카오 문서에 나와있는 로그인 로직입니다!!&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;우리가 카카오 로그인 요청을 하면?&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;1. 카카오 계정 사용자의 자격정보로 인가 코드를 받아옴.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;2. 이 인가코드로 액세스 토큰과 리프레시 토큰을 얻음.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;간략하게 정리하면 이렇게 되겠네용.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;일단 순서부터 간략하게 훑고가자면,&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;1. Kakao 개발자 사이트에 앱 등록하기!&amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp; 1.1. 앱 추가&lt;br /&gt;&amp;nbsp; &amp;nbsp; 1.2. iOS 플랫폼 등록&lt;br /&gt;&amp;nbsp; &amp;nbsp; 1.3. 카카오 로그인 활성화&lt;br /&gt;&amp;nbsp; &amp;nbsp; 1.4. 동의 항목 설정&lt;br /&gt;&amp;nbsp; &amp;nbsp; 1.5 네이티브 앱 키 확인&lt;br /&gt;2. SDK설치!&lt;br /&gt;3. xcode 설정&lt;br /&gt;&amp;nbsp; &amp;nbsp; 3.1. info.plist 설정&lt;br /&gt;&amp;nbsp; &amp;nbsp; 3.2. URL Schemes 설정&amp;nbsp; &amp;nbsp;&lt;br /&gt;4. AppDelegate, SceneDelegate 설정&lt;br /&gt;&amp;nbsp; &amp;nbsp; 4.1. kakaoSDK 초기화&lt;br /&gt;&amp;nbsp; &amp;nbsp; 4.2. handleOpenUrl()추가&lt;br /&gt;5. 메소드 작성&lt;br /&gt;&amp;nbsp; &amp;nbsp; 5.1. 카카오톡 설치 돼 있나?&lt;br /&gt;&amp;nbsp; &amp;nbsp; 5.2. 앱으로/계정으로 로그인&lt;br /&gt;&amp;nbsp; &amp;nbsp; 5.3. 사용자 정보 가져오기&lt;br /&gt;&amp;nbsp; &amp;nbsp; 5.4. 로그아웃&lt;/blockquote&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;&lt;i&gt;&lt;s&gt;자동목차 기능을 넣어야겠어요......&lt;/s&gt;&lt;/i&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure contenteditable=&quot;false&quot; data-ke-type=&quot;emoticon&quot; data-ke-align=&quot;alignCenter&quot; data-emoticon-type=&quot;friends1&quot; data-emoticon-name=&quot;017&quot; data-emoticon-isanimation=&quot;false&quot; data-emoticon-src=&quot;https://t1.daumcdn.net/keditor/emoticon/friends1/large/017.gif&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/keditor/emoticon/friends1/large/017.gif&quot; width=&quot;150&quot; /&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;두근두근 카카오 로그인 연동 시작~&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;text-align: left;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 style=&quot;text-align: left;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;1.&amp;nbsp; Kakao 개발자 사이트에&amp;nbsp; 앱 등록하기!&lt;/b&gt;&lt;/h2&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;여기서는 앱을 등록하고, 동의 항목을 설정하고,&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;카톡 로그인 후 앱으로 리다이렉트될 때 쓰이는 네이티브 앱 키를 받을 겁니다!!&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a title=&quot;카카오 디벨로퍼&quot; href=&quot;https://developers.kakao.com/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;카카오 디벨로퍼 바로가기&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;내 어플리케이션 &amp;gt; 어플리케이션 추가하기에서 앱을 등록해줍니당&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1648&quot; data-origin-height=&quot;1602&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/zD4ix/btrBDmscEZJ/SP8HEfD8jrcDRpDXHOOhIK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/zD4ix/btrBDmscEZJ/SP8HEfD8jrcDRpDXHOOhIK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/zD4ix/btrBDmscEZJ/SP8HEfD8jrcDRpDXHOOhIK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FzD4ix%2FbtrBDmscEZJ%2FSP8HEfD8jrcDRpDXHOOhIK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;550&quot; height=&quot;1602&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1648&quot; data-origin-height=&quot;1602&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;앱 아이콘과 앱 이름, 사업자명은 나중에 이렇게 떠요!&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;물론 아이콘 이름 사업자명 모두 수정 가능하니까 부담없이 지어주시면 됩니다~~&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;IMG_AE6456216DF5-1.jpeg&quot; data-origin-width=&quot;828&quot; data-origin-height=&quot;972&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Ei167/btrBu5eTiXv/WBvvaySw66MaxVoVfnZfu1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Ei167/btrBu5eTiXv/WBvvaySw66MaxVoVfnZfu1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Ei167/btrBu5eTiXv/WBvvaySw66MaxVoVfnZfu1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FEi167%2FbtrBu5eTiXv%2FWBvvaySw66MaxVoVfnZfu1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;500&quot; height=&quot;972&quot; data-filename=&quot;IMG_AE6456216DF5-1.jpeg&quot; data-origin-width=&quot;828&quot; data-origin-height=&quot;972&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;앱이 등록이 됐다면! &lt;b&gt;좌측 메뉴 &amp;gt; 플랫폼 &amp;gt; iOS 플랫폼 등록&lt;/b&gt;을 해줍니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-05-09 오전 4.25.22.png&quot; data-origin-width=&quot;1328&quot; data-origin-height=&quot;1452&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cCLIuk/btrBxatdsXs/LbHC10YYKBHcuVq5kvFkz0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cCLIuk/btrBxatdsXs/LbHC10YYKBHcuVq5kvFkz0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cCLIuk/btrBxatdsXs/LbHC10YYKBHcuVq5kvFkz0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcCLIuk%2FbtrBxatdsXs%2FLbHC10YYKBHcuVq5kvFkz0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;500&quot; height=&quot;1452&quot; data-filename=&quot;스크린샷 2022-05-09 오전 4.25.22.png&quot; data-origin-width=&quot;1328&quot; data-origin-height=&quot;1452&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;번들 아이디를 넣어줘요~~ 어디서 확인하시는지 아시져?&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-05-09 오전 4.26.14.png&quot; data-origin-width=&quot;1302&quot; data-origin-height=&quot;588&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/GPi5I/btrBzeBVafe/iRrByYUddCggMpH5MeClz1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/GPi5I/btrBzeBVafe/iRrByYUddCggMpH5MeClz1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/GPi5I/btrBzeBVafe/iRrByYUddCggMpH5MeClz1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FGPi5I%2FbtrBzeBVafe%2FiRrByYUddCggMpH5MeClz1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;600&quot; height=&quot;588&quot; data-filename=&quot;스크린샷 2022-05-09 오전 4.26.14.png&quot; data-origin-width=&quot;1302&quot; data-origin-height=&quot;588&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;바로바로 여기!!! bundle Identifier 값을 넣어주면 됩니다.&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;주의 @ 고유한 값이어야해요!!!!! 주소같은 느낌인듯&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;앱스토어/마켓 정보는 있으면 넣어주시고 없다면 패스~&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-05-09 오전 5.10.51.png&quot; data-origin-width=&quot;1772&quot; data-origin-height=&quot;832&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/k4Gqk/btrBx2aGdDm/qXiKnDqG6U3Tu9t4F7ucDk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/k4Gqk/btrBx2aGdDm/qXiKnDqG6U3Tu9t4F7ucDk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/k4Gqk/btrBx2aGdDm/qXiKnDqG6U3Tu9t4F7ucDk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fk4Gqk%2FbtrBx2aGdDm%2FqXiKnDqG6U3Tu9t4F7ucDk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;600&quot; height=&quot;832&quot; data-filename=&quot;스크린샷 2022-05-09 오전 5.10.51.png&quot; data-origin-width=&quot;1772&quot; data-origin-height=&quot;832&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;플랫폼 등록을 했으면&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;좌측 메뉴에서 &lt;b&gt;제품설정 &amp;gt; 카카오 로그인 &amp;gt; 활성화 설정&lt;/b&gt;을 ON으로 바꿔주세요!&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;우리는 카카오 로그인 쓸거니까!! 당연함&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;다음은 동의항목 설정하러 가볼까요!&lt;/p&gt;
&lt;p&gt;&lt;img style=&quot;caret-color: transparent; font-family: -apple-system, BlinkMacSystemFont, AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; letter-spacing: 0px;&quot; src=&quot;https://blog.kakaocdn.net/dn/mekTX/btrBA0b8nGr/lgfKLCU8xl1XGoYFIF3Ujk/img.png&quot; width=&quot;700&quot; height=&quot;481&quot; data-is-animation=&quot;false&quot; data-origin-width=&quot;1832&quot; data-origin-height=&quot;1260&quot; data-filename=&quot;스크린샷 2022-05-09 오전 4.40.49.png&quot; /&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;제품 설정 &amp;gt; 카카오 로그인 &amp;gt; 동의항목&lt;/b&gt; 에 가시면 필요한 정보들을 받아올 수 있습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;저는 닉네임이랑 이메일만 필요해서 설정해줬어요&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;동의 목적은 사용자가 볼 수 있는 화면에는 나타나지 않고 검수에 필요한 부분이라고 합니다!!&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;+) ​이메일 필수 동의를 위해서는 비즈니스 앱으로 전환을 해야 합니다!&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;사업자 번호 없어도 간단하게 약관 동의만 하면 개인 개발자로 비즈 앱 전환 할 수 있으니까 곰방 하시면 돼요&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;그리고 &lt;b&gt;앱설정 &amp;gt; 앱 키 &lt;/b&gt;에서 네이티브 앱 키를 확인해줍니다!!&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;나중에 네이티브 앱 키 넣을때 여기서 확인해주셔야 해요~~&lt;/p&gt;
&lt;h2 style=&quot;text-align: left;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 style=&quot;text-align: left;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;2. SDK 설치&lt;/b&gt;&lt;/h2&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;자 이제 로그인에 필요한 모듈을 추가해줄 거예요@.@&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;카카오 디벨로퍼 문서를 보면&lt;/p&gt;
&lt;pre id=&quot;code_1652049170505&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 전체 추가
pod 'KakaoSDK'

# or

# 필요한 모듈 추가
pod 'KakaoSDKCommon'  # 필수 요소를 담은 공통 모듈
pod 'KakaoSDKAuth'  # 사용자 인증
pod 'KakaoSDKUser'  # 카카오 로그인, 사용자 관리
pod 'KakaoSDKTalk'  # 친구, 메시지(카카오톡)
pod 'KakaoSDKStory'  # 카카오스토리 
pod 'KakaoSDKLink'  # 메시지(카카오링크)
pod 'KakaoSDKTemplate'  # 메시지 템플릿 
pod 'KakaoSDKNavi'  # 카카오내비&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;친절하게 나와있는데용&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;당연히 다 설치 할 필요는 없고!!!! 저는 로그인만 할 거라서 이렇게▼ 설치했습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1652049803059&quot; class=&quot;nginx&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;  pod 'KakaoSDKAuth'
  pod 'KakaoSDKUser'
  pod 'KakaoSDKCommon'&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;그리고 pod install~~!&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;text-align: left;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;3.&amp;nbsp; xcode 설정&lt;/b&gt;&lt;/h2&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3.1. info.plist에서 앱 실행 목록에 등록!&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;다른 어플리케이션을 실행시키려면 실행 허용목록을 설정해야 합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-05-09 오후 9.52.33.png&quot; data-origin-width=&quot;2144&quot; data-origin-height=&quot;964&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/LjNHe/btrBEdjtaO6/FD0lcjtr44C6q3kf6YKpZ1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/LjNHe/btrBEdjtaO6/FD0lcjtr44C6q3kf6YKpZ1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/LjNHe/btrBEdjtaO6/FD0lcjtr44C6q3kf6YKpZ1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FLjNHe%2FbtrBEdjtaO6%2FFD0lcjtr44C6q3kf6YKpZ1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;650&quot; height=&quot;292&quot; data-filename=&quot;스크린샷 2022-05-09 오후 9.52.33.png&quot; data-origin-width=&quot;2144&quot; data-origin-height=&quot;964&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Info &amp;gt; Custom iOS Target Properties &amp;gt; Array 타입으로 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;LSApplicatioonQueriesSchemes&lt;/span&gt; 를 추가,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;키 내부의 Item 으로 &lt;span style=&quot;background-color: #99cefa;&quot;&gt;kakaokompassauth , kakaolink&lt;/span&gt; 를 추가합니다. (URL 스킴에 사용됩니다!)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;+) 코드로 추가하는 방법&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;info.plist 우클릭 &amp;gt; open as &amp;gt; source code 로 여신다음에&lt;/p&gt;
&lt;pre id=&quot;code_1652101134652&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;plist version=&quot;1.0&quot;&amp;gt;
&amp;lt;dict&amp;gt;
	//...
	&amp;lt;key&amp;gt;LSApplicationQueriesSchemes&amp;lt;/key&amp;gt;
	&amp;lt;array&amp;gt;
		&amp;lt;string&amp;gt;kakaokompassauth&amp;lt;/string&amp;gt;
		&amp;lt;string&amp;gt;kakaolink&amp;lt;/string&amp;gt;
	&amp;lt;/array&amp;gt;
    	// ...
&amp;lt;/dict&amp;gt;
&amp;lt;/plist&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 추가하면 끝!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3.2. URL Schemes 설정&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;카카오 로그인을 하려면 우리 앱이 카카오 앱을 실행할 수 있어야 하고,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;카카오 앱을 실행해서 로그인 한 뒤엔 다시 우리 앱으로 돌아올 수 있어야겠죠??&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이를 위해서 아까 받았던(1.5) 네이티브 앱 키를 이용합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Targets &amp;gt; Info 맨 아래보면 URL Type!&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-05-10 오전 11.36.37.png&quot; data-origin-width=&quot;986&quot; data-origin-height=&quot;640&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/tcZEg/btrBHk9NP3q/fJtmpYNmb76GpaAUsdWHbK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/tcZEg/btrBHk9NP3q/fJtmpYNmb76GpaAUsdWHbK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/tcZEg/btrBHk9NP3q/fJtmpYNmb76GpaAUsdWHbK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FtcZEg%2FbtrBHk9NP3q%2FfJtmpYNmb76GpaAUsdWHbK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;600&quot; height=&quot;640&quot; data-filename=&quot;스크린샷 2022-05-10 오전 11.36.37.png&quot; data-origin-width=&quot;986&quot; data-origin-height=&quot;640&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기 URL Schemes 에 kakao + 네이티브앱 키를 적어줍니다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;네이티브앱 키가 abcd1234였다면 -&amp;gt; kakaoabcd1234 적어주시면 됨!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;4. &lt;span style=&quot;background-color: #fcfcfc; color: #000000;&quot;&gt;AppDelegate, SceneDelegate 설정&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;4.1&amp;nbsp; SDK 초기화&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 우리의 iOS앱에서&amp;nbsp; SDK파일을 사용하려면 import를 해줘야겠죠?!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한 kakaoSDK를 우리 네이티브 앱 키를 사용해 초기화 하는 과정이 필요합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;AppDelegate.swift&lt;/b&gt; 파일에 다음과 같이 kakaoSDK 초기화 코드를 추가합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1652155585621&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import KakaoSDKCommon

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -&amp;gt; Bool {

  ...
  KakaoSDK.initSDK(appKey: &quot;${NATIVE_APP_KEY}&quot;)
  ...

}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;네이티브 앱 키에는 각자&lt;b&gt; 아까 받았던 네이티브 앱 키&lt;/b&gt;를 문자열 형태로 입력해주시면 됩니다!!!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;4.2 handleOpenURL()&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;카카오톡에서 앱으로 돌아왔을때 나머지 로그인 처리를 정상적으로 처리하기 위한 코드를 추가 할 건데요,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1) iOS 13 이상으로 생성된 프로젝트&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;iOS 13 이상에서는 SceneDelegate를 기본으로 사용하므로, SceneDelegate 파일에 다음과 같은 코드를 추가합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1652156167800&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import KakaoSDKAuth
...

class SceneDelegate: UIResponder, UIWindowSceneDelegate {
    ...
    func scene(_ scene: UIScene, openURLContexts URLContexts: Set&amp;lt;UIOpenURLContext&amp;gt;) {
        if let url = URLContexts.first?.url {
            if (AuthApi.isKakaoTalkLoginUrl(url)) {
                _ = AuthController.handleOpenUrl(url: url)
            }
        }
    }
    ...
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2) iOS 13이하&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;iOS13 이하 프로젝트라면 AppDelegate.swift 파일에 추가합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1652156210721&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import KakaoSDKAuth
...

class AppDelegate: UIResponder, UIApplicationDelegate {
    ...
    func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -&amp;gt; Bool {
        if (AuthApi.isKakaoTalkLoginUrl(url)) {
            return AuthController.handleOpenUrl(url: url)
        }

        return false
    }
    ...
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;와! 이제 카카오 로그인을 위한 &quot;준비&quot; 가 끝났습니다 &amp;gt;&amp;lt;&lt;/i&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;5. 메소드 작성&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;자 이제 드디어!! 로그인 메소드를 작성할 수 있습니다~~~~ &lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;로그인 기능을 할 뷰컨트롤러에&amp;nbsp; 코드를 작성하면 됩니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;카카오에서 제공하는 메소드들은 음청 다양하게 있는데요, 저는 거기서&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;① 카카오톡이 설치 되어 있는지 확인하는 메소드&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;② 카카오톡 앱으로 로그인 하는 메소드 &amp;amp; 카카오 계정 입력해서 로그인 하는 메소드&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;③ 현재 로그인 한 사용자 정보 가져오는 메소드&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;④ 로그아웃 메소드&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 사용했습니다 ^_^&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;더 다양한 메소드들은 (다들 아시겠지만) UserApi 따블 클릭 &amp;gt; Jump to definition 으로 가셔서 코드 뜯어보시면 편해요~!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1652157853908&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// isKakaoTalkLoginAvailable() : 카톡 설치 되어있으면 true
if (UserApi.isKakaoTalkLoginAvailable()) {		
    
    //카톡 설치되어있으면 -&amp;gt; 카톡으로 로그인
    UserApi.shared.loginWithKakaoTalk {(oauthToken, error) in
        if let error = error {
            print(error)
        } else {
            print(&quot;카카오 톡으로 로그인 성공&quot;)
            
            _ = oauthToken
            /// 로그인 관련 메소드 추가
        }
    }    
} else {

    // 카톡 없으면 -&amp;gt; 계정으로 로그인
    UserApi.shared.loginWithKakaoAccount { (oauthToken, error) in
        if let error = error {
            print(error)
        } else {
            print(&quot;카카오 계정으로 로그인 성공&quot;)
            
            _ = oauthToken
            // 관련 메소드 추가
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;간단~~&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저는 여기서 사용자 정보를 불러와서 토큰, 이메일, 닉네임을 서버에 보내주는 작업을 추가했습니다 :3&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;UserApi.shared.me&lt;/b&gt; 라는 메소드를 사용하면 불러올 수 있습니다 !&lt;/p&gt;
&lt;pre id=&quot;code_1652158101100&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt; //사용자 정보 불러옴
UserApi.shared.me { [self] user, error in
    if let error = error {
        print(error)
    } else {
        
        guard let token = oauthToken?.accessToken, let email = user?.kakaoAccount?.email,
              let name = user?.kakaoAccount?.profile?.nickname else{
                  print(&quot;token/email/name is nil&quot;)
                  return
              }

        self.email = email
        self.accessToken = token
        self.name = name
		
        //서버에 이메일/토큰/이름 보내주기
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 로그아웃까지!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;로그아웃 메소드를 호출하면, 사용자의 액세스 토큰과 리프레시 토큰을 모두 만료시킵니다.&lt;/p&gt;
&lt;pre id=&quot;code_1652158251003&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;UserApi.shared.logout {(error) in
    if let error = error {
        print(error)
    }
    else {
        print(&quot;logout() success.&quot;)
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하면 끝~!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;더 자세하고 친절한 설명은 카카오 디벨로퍼에 잘 나와있답니다.....한 번 스스로 정리해 본 것에 의의를 둠 :),....&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;읽어주셔서 감사합니다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음 포스팅은 구글/애플 소셜로그인으로 돌아오겠습니다~!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;구글 로그인 ▼&lt;/p&gt;
&lt;figure id=&quot;og_1652700383352&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;iOS 소셜로그인(2) - 구글 로그인 연동하기!&quot; data-og-description=&quot;안녕하세요 ! 도안입니당 :&amp;gt; 티스토리가 다 쓴 글을 날려버렸어요... 분명 자동저장 열심히했는데 이자식..... 어쩌겠나요 다시써야지 ᵕ᷄≀ ̠˘᷅ &amp;gt;&amp;gt;카카오 로그인 하는 법 보러가기&amp;lt;&amp;lt; 암튼 지난&quot; data-og-host=&quot;doh-an.tistory.com&quot; data-og-source-url=&quot;https://doh-an.tistory.com/40&quot; data-og-url=&quot;https://doh-an.tistory.com/40&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bIsCcX/hyOrkOl5ZP/LjyKZHy6WwBYs6Z5XRcW51/img.png?width=800&amp;amp;height=410&amp;amp;face=0_0_800_410,https://scrap.kakaocdn.net/dn/b5MBI0/hyOpQaiZF4/xwgCfszd9nRD1NoeY1hSqk/img.png?width=800&amp;amp;height=410&amp;amp;face=0_0_800_410,https://scrap.kakaocdn.net/dn/flxHM/hyOrpa3JXO/0JXzJOHAGHxoyXkbSEmJxK/img.png?width=3360&amp;amp;height=1722&amp;amp;face=0_0_3360_1722&quot;&gt;&lt;a href=&quot;https://doh-an.tistory.com/40&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://doh-an.tistory.com/40&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bIsCcX/hyOrkOl5ZP/LjyKZHy6WwBYs6Z5XRcW51/img.png?width=800&amp;amp;height=410&amp;amp;face=0_0_800_410,https://scrap.kakaocdn.net/dn/b5MBI0/hyOpQaiZF4/xwgCfszd9nRD1NoeY1hSqk/img.png?width=800&amp;amp;height=410&amp;amp;face=0_0_800_410,https://scrap.kakaocdn.net/dn/flxHM/hyOrpa3JXO/0JXzJOHAGHxoyXkbSEmJxK/img.png?width=3360&amp;amp;height=1722&amp;amp;face=0_0_3360_1722');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;iOS 소셜로그인(2) - 구글 로그인 연동하기!&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;안녕하세요 ! 도안입니당 :&amp;gt; 티스토리가 다 쓴 글을 날려버렸어요... 분명 자동저장 열심히했는데 이자식..... 어쩌겠나요 다시써야지 ᵕ᷄≀ ̠˘᷅ &amp;gt;&amp;gt;카카오 로그인 하는 법 보러가기&amp;lt;&amp;lt; 암튼 지난&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;doh-an.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>iOS</category>
      <category>IOS</category>
      <category>ios 카카오톡</category>
      <category>iOS소셜로그인</category>
      <category>소셜로그인</category>
      <category>카카오 로그인연동</category>
      <category>카카오 소셜로그인</category>
      <category>카카오로그인</category>
      <category>카카오톡 로그인</category>
      <author>D0HAN.</author>
      <guid isPermaLink="true">https://doh-an.tistory.com/37</guid>
      <comments>https://doh-an.tistory.com/37#entry37comment</comments>
      <pubDate>Tue, 10 May 2022 13:55:12 +0900</pubDate>
    </item>
    <item>
      <title>[iOS/Swift] 신입 면접 질문 정리 (22.05.04 업데이트)</title>
      <link>https://doh-an.tistory.com/36</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;ㅎㅎ 내가 보려고 만드는 면접질문 정리~&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;직접 들은 질문들 + 유명한 iOS 면접 질문들 섞어서 정리해봅니다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #24292f;&quot;&gt;1. ARC (Automatic Reference Counting)&lt;/span&gt;&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자동 레퍼런스 카운팅! 자동으로 메모리를 관리해주는 방식&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ARC는 메모리영역중 &lt;span style=&quot;color: #0593d3;&quot;&gt;&lt;b&gt;힙 영역&lt;/b&gt;&lt;/span&gt;을 관리함.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;런타임에 주기적으로 참조를 추적하여 사용하지 않는 인스턴스를 해제하는 GC(garbage collector)와 다르게 컴파일 타임 시점에 언제 참조/해제되는지 결정되어 런타임때 그대로 실행됨.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;근데... 순환참조시 메모리가 영구적으로 해제되지 않을 수 있음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모든 인스턴스는 자신의 RC값을 가지고있음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(몇번이나 참조되고있는지!! 참조 횟수!! 인스턴스 생성될때 힙에 같이 저장됨)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 RC값은 어떻게 세냐??&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;참조 횟수가 +1이 되는 순간은 &lt;span style=&quot;color: #ef5369;&quot;&gt;인스턴스의 주소값을 변수에 할당할때!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1) 인스턴스 새로 생성&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2) 기존 인스턴스 다른 변수에 대입할때&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;참조 횟수가 -1이 되는 순간은 &lt;br /&gt;1) 인스턴스 가리키던 변수가 메모리에서 해제되었을때!! &lt;br /&gt;2) nil이 지정되었을때?(해제나 마찬가지인가..) &lt;br /&gt;3) 다른거 지정되었을때(당연..)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 메모리(코드,데이터,힙,스택)&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;코드 영역&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;소스코드가 기계어 형태로 저장됨. 중간에 코드 변경되지 않도록 read-only&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;데이터 영역&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;전역변수, static 변수가 저장됨. 프로그램 시작과 동시에 할당되고, 종료되면 메모리 해제 됨. 실행 도중 변수 값 변경될 수 있어서 read-write로&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;힙 영역 -수동&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;프로그래머가 할당/해제하는 메모리 영역. malloc, calloc로 힙에 메모리를 할당(동적할당).그래서 사용하고 난 후에는 메모리 해제를 해줘야댐!! 안그러면 memory leak 발생.&lt;/li&gt;
&lt;li&gt;유일하게 런타임 시에 결정됨!!! 데이터의 크기가 확실하지 않을때 사용.&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;caret-color: auto; font-family: -apple-system, BlinkMacSystemFont, AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; letter-spacing: 0px;&quot;&gt;프로그램의 모든 함수에서 액세스 할수있음!&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;caret-color: auto; font-family: -apple-system, BlinkMacSystemFont, AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; letter-spacing: 0px;&quot;&gt;다만 할당/해제작업 &amp;rarr; 속도 저하&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;caret-color: auto; font-family: -apple-system, BlinkMacSystemFont, AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; letter-spacing: 0px;&quot;&gt;힙 경합(두개 이상 쓰레드가 동시접근하면 락걸림) &amp;rarr; 속도 저하&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;caret-color: auto; font-family: -apple-system, BlinkMacSystemFont, AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; letter-spacing: 0px;&quot;&gt;swift 에서 클래스 인스턴스, 클로저같은 &amp;ldquo;참조타입&quot;의 값!!!은 모두 힙에 자동할당됨 &amp;rarr; 메모리해제는????&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;caret-color: auto; font-family: -apple-system, BlinkMacSystemFont, AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; letter-spacing: 0px;&quot;&gt;더이상 참조되지 안흐면 &lt;/span&gt;&lt;a style=&quot;font-family: -apple-system, BlinkMacSystemFont, AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; letter-spacing: 0px;&quot; href=&quot;https://www.notion.so/iOS-7515cc2700914133bf210ba2cc5c56a4&quot;&gt;ARC&lt;/a&gt;&lt;span style=&quot;caret-color: auto; font-family: -apple-system, BlinkMacSystemFont, AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; letter-spacing: 0px;&quot;&gt;가 자동으로 해제~~!&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;스택 영역 -자동&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;함수 호출시! - 지역변수, 매개변수, 리턴값 등등 저장됨&lt;/li&gt;
&lt;li&gt;&lt;b&gt;함수 종료되면 저장된 메모리도 해제!!(반환)&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;caret-color: auto; font-family: -apple-system, BlinkMacSystemFont, AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; letter-spacing: 0px;&quot;&gt;빠름. 힙보다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;caret-color: auto; font-family: -apple-system, BlinkMacSystemFont, AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; letter-spacing: 0px;&quot;&gt;컴파일타임에 결정되기 때문에 무한히 할당할수는 x &amp;rarr; 너무 큰 메모리는 할당 안됨!! 너무 많은 메모리 할당하면 stack overflow 뜸&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;caret-color: auto; font-family: -apple-system, BlinkMacSystemFont, AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; letter-spacing: 0px;&quot;&gt;스레드로부터 안전함&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;caret-color: auto; font-family: -apple-system, BlinkMacSystemFont, AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; letter-spacing: 0px;&quot;&gt;프로그램이 자동으로 사용하는 임시 메모리영역. LIFO 속도 빠름. 지역변수만 액세스 할수있음.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;힙과 스택은 같은 메모리 영역 공유&lt;br /&gt;힙은 0x0000000&amp;rarr; 시작&lt;br /&gt;스택은 0xfffffff&amp;rarr;시작&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 참조(Strong, Weak, Unowned + 순환참조)&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;강한참조? Strong&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인스턴스의 주소값이 변수에 할당될 때, RC가 증가한다면? 강한참조&lt;br /&gt;인스턴스 생성, 사용했던거 다 strong~&lt;br /&gt;default 값이 strong임.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;순환참조?&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #fafafa;&quot;&gt;두개의 객체가 서로서로 참조하고 있는 형태&lt;/span&gt;&lt;br /&gt;서로가 서로를 참조하고있어서 RC가 0이 되지 못함. 근데 인스턴스를 둘다 해제해버리면 인스턴스에 접근할수있는 방법도 없어서 메모리 해제도 못함.&lt;br /&gt;이를 해결하기 위해서는??? &amp;rarr; weak 약한 참조!&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;약한 참조? Weak&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인스턴스 참조할때, RC를 증가시키지 않음!!! 엥?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;참조하던 인스턴스가 메모리에서 해제된 경우 자동으로 nil이 할당돼서 메모리 해제됨.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;순환참조되어있던 둘 중 한쪽을 weak로 선언해줌. (무조건 !옵셔널타입)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;근데 !!! 둘 중에 수명이 더 짧은 인스턴스를 가리키는애!!!&amp;lt;를 약한 참조로 선언. ( 수명이 더 긴쪽에서 선언 )&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ex) 철수/영희 중에 철수 인스턴스가 먼저 죽는다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rarr; 그럼 영희의 boyfriend가 Nil이 될 수 있다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rarr; 영희의 boyfriend를 weak로 선언!!!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;weak의 특징! 가리키던 인스턴스가 메모리에서 해제되면 nil이 할당된다.(strong은?이럴일이없을듯? 가리키는 인스턴스가있으면 RC가 0이되지 않으니까?)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클로저 내부에서 [weak self] 해주는것도 순환참조 문제때문!&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;unowned 미소유 참조?&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;weak랑 비슷함!! RC값을 증가시키지 않아 강한순환참조를 해결&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;근데? unowned는 인스턴스 참조하는 도중 메모리에서 사라질 일이 없다고 확신. (그래서 수명이 더 짧은 쪽에서 선언)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rArr; 뭐지?아직 좀 헷갈린다 왜 쓰는거지... 이제 옵셔널도 가능함! Weak는 무조건 옵셔널이어야 해서 옵셔널 값이 아닐때 쓰나?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;weak보다 에러날 확률이 높아보이는데..&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. SceneDelegate 와 AppDelegate&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;678&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/BPpBT/btrBhg7GHn3/D3L0B3ynnwWp2ulH2EDKU0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/BPpBT/btrBhg7GHn3/D3L0B3ynnwWp2ulH2EDKU0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/BPpBT/btrBhg7GHn3/D3L0B3ynnwWp2ulH2EDKU0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FBPpBT%2FbtrBhg7GHn3%2FD3L0B3ynnwWp2ulH2EDKU0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1280&quot; height=&quot;678&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;678&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Untitled.png&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;680&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/crxBgt/btrBiaSZJZx/o91BUMq7EK9CImlvK8jrIK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/crxBgt/btrBiaSZJZx/o91BUMq7EK9CImlvK8jrIK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/crxBgt/btrBiaSZJZx/o91BUMq7EK9CImlvK8jrIK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcrxBgt%2FbtrBiaSZJZx%2Fo91BUMq7EK9CImlvK8jrIK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1280&quot; height=&quot;680&quot; data-filename=&quot;Untitled.png&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;680&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #1b711d;&quot;&gt;&lt;b&gt;✅&amp;nbsp; iOS 13 기점으로 변한점!&lt;/b&gt;&lt;br /&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이전까지는 하나의 앱에 하나의 window였지만 window 의 개념이&lt;b&gt; Scene&lt;/b&gt;으로 대체 됨. 하나의 앱에서 여러개의 Scene을 가질 수 있게 됨.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Scene Delegate&lt;/b&gt;가 생김!! -&amp;gt; 이 SceneDelegate가 원래 AppDelegate가 가지고있던 &lt;b&gt;UI LifeCycle&lt;/b&gt; 가져감~&lt;/li&gt;
&lt;li&gt;AppDelegate에 &lt;b&gt;Session Lifecycle&lt;/b&gt;에 대한 역할이 추가됨!!&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;그래서 Scene이 뭐지?&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기존 앱은 window하나밖에 가지지 못했으나 멀티 뷰가 가능해지면서 Scene으로 바뀜!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;app switcher를 통해 여러 scene을 확인할 수 있음.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;scene에는 UI 하나의 인스턴스를 나타내는 windows와 view controllers가 들어있음.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각각의 Scene은 UIWindowSeceneDelegate를 가지고있음 ! -&amp;gt; 이걸로 UIKit과 app사이에서 인터랙션 함&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하나의 앱은 여러 Scene과 SceneDelegate객체를 동시에 활성화 할 수 있음.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Scene들은 같은 메모리와 앱 프로세스 공간을 공유하면서 동시에 실행 됨.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;Scene Session 은 또 뭐지?&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;유저나 개발자가 새로운 Scene을 만들었을때, 해당 Scene을 tracking 하기 위해 Session 객체를 생성함.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위에서 AppDelegate에 Session Lifecycle에 대한 역할이 추가 됐다고 했는데, 그게 그림에서 보이는 두가지 메소드다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SceneSession이 생성될 때와 삭제 될 때, AppDelegate에 알려주는 메소드가 추가 됨!!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5. Class 와 Struct 의 차이&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Class&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;참조 타입!! &amp;rarr; 같은 클래스 인스턴스를 여러 변수에 할당하고 값을 변경시키면 모든 변수에 영향을 줌&lt;/li&gt;
&lt;li&gt;ARC로 메모리 관리&lt;/li&gt;
&lt;li&gt;deinit으로 클래스 인스턴스의 메모리 할당해제 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Struct&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;값 타입&lt;/li&gt;
&lt;li&gt;구조체 변수 새롭게 할당할때마다 새로운 구조체가 할당됨&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;</description>
      <category>iOS</category>
      <category>IOS</category>
      <category>ios 면접질문</category>
      <category>ios면접</category>
      <category>ios신입면접</category>
      <category>swift 면접</category>
      <category>swift질문</category>
      <category>개발자 면접</category>
      <category>면접 질문</category>
      <category>면접 질문 정리</category>
      <category>신입면접</category>
      <author>D0HAN.</author>
      <guid isPermaLink="true">https://doh-an.tistory.com/36</guid>
      <comments>https://doh-an.tistory.com/36#entry36comment</comments>
      <pubDate>Wed, 4 May 2022 01:35:05 +0900</pubDate>
    </item>
    <item>
      <title>[xcode]Failed to register bundle identifier 오류 해결</title>
      <link>https://doh-an.tistory.com/35</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-04-27 오후 8.24.39.png&quot; data-origin-width=&quot;804&quot; data-origin-height=&quot;426&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Xu0Ps/btrAIPhxUuu/Hdp9DUuKOiNN3VKDRxF70K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Xu0Ps/btrAIPhxUuu/Hdp9DUuKOiNN3VKDRxF70K/img.png&quot; data-alt=&quot;이런 열받는 에러가 뜬다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Xu0Ps/btrAIPhxUuu/Hdp9DUuKOiNN3VKDRxF70K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FXu0Ps%2FbtrAIPhxUuu%2FHdp9DUuKOiNN3VKDRxF70K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;804&quot; height=&quot;426&quot; data-filename=&quot;스크린샷 2022-04-27 오후 8.24.39.png&quot; data-origin-width=&quot;804&quot; data-origin-height=&quot;426&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;이런 열받는 에러가 뜬다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Failed to register bundle identifier:&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;The&amp;nbsp;app&amp;nbsp;identifier&amp;nbsp;&quot;com.WeekFlex&quot;&amp;nbsp;cannot&amp;nbsp;be&amp;nbsp;registered&amp;nbsp;to&amp;nbsp;your&amp;nbsp;development&amp;nbsp;team&amp;nbsp;because&amp;nbsp;it&amp;nbsp;is&amp;nbsp;not&amp;nbsp;available.&amp;nbsp;Change&amp;nbsp;your&amp;nbsp;bundle&amp;nbsp;identifier&amp;nbsp;to&amp;nbsp;a&amp;nbsp;unique&amp;nbsp;string&amp;nbsp;to&amp;nbsp;try&amp;nbsp;again.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;No profiles for 'com.WeekFlex' were found:&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Xcode couldn't find any iOS App Development provisioning profiles matching 'com.WeekFlex'.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;폰에다가 빌드하려고 하니 이런 에러가 뜬다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단 bundle identifier가 고유하지 않아서 생기는 문젠데, 번들id를 변경하면 해결된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나의 경우 문제는 팀원과 함께 같은 번들 Id를 사용했던 것인데, 팀원과 함께 번들id를 쓰기 위해서는 프로비저닝 프로필 설정이 필요했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;certificates, identifier, provisioning prifile 에 대해 공부했는데 내용이 많아 추후 따로 포스팅 하도록 하겠음!!!&lt;/p&gt;</description>
      <category>iOS/error log</category>
      <category>apple 개발자계정</category>
      <category>bundle identifier</category>
      <category>Certificates</category>
      <category>error</category>
      <category>provisioning</category>
      <category>Xcode</category>
      <category>xcode error</category>
      <category>인증서</category>
      <category>해결</category>
      <author>D0HAN.</author>
      <guid isPermaLink="true">https://doh-an.tistory.com/35</guid>
      <comments>https://doh-an.tistory.com/35#entry35comment</comments>
      <pubDate>Thu, 28 Apr 2022 10:47:58 +0900</pubDate>
    </item>
    <item>
      <title>[OS] Interrupt 인터럽트란?</title>
      <link>https://doh-an.tistory.com/31</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;i&gt;&lt;b&gt;인터럽트란?&lt;/b&gt;&lt;/i&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;CPU가 프로그램을 실행하고 있을 때, 입출력 하드웨어 등의 장치에 예외상황이 발생하여 처리가 필요할 경우에 CPU에게 알려 처리할 수 있도록 하는 것&lt;/li&gt;
&lt;li&gt;우선적으로 처리해야할 일이 발생하였을 때 그것을 처리하고 원래 동작으로 돌아옴&lt;/li&gt;
&lt;li&gt;크게 하드웨어 인터럽트와 소프트웨어 인터럽트로 나눔&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;i&gt;&lt;b&gt;하드웨어 인터럽트&lt;/b&gt;&lt;/i&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;일반적으로 인터럽트를 이르는 말&lt;/li&gt;
&lt;li&gt;CPU외부로부터의 인터럽트 요구 신호에 의해 발생되는 인터럽트&lt;/li&gt;
&lt;li&gt;Maskable interrupt, Non-maskable interrupt 가 있다. (Interrunpt Mask가 가능)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Maskable interrupt&lt;br /&gt;- Interrupt Mask(인터럽트가 발생하였을 때 요구를 받아들일지 말지 지정하는 것)가 가능&amp;nbsp;&lt;br /&gt;- 인텔CPU 에서 &lt;b&gt;INTR pin&lt;/b&gt;으로 신호가 들어옴&lt;/li&gt;
&lt;li&gt;Non Maskable interrupt&amp;nbsp;&lt;br /&gt;- Interrupt Mask가 불가능&lt;br /&gt;- 거부, 무시할 수 없음 (매우 중요함)&lt;br /&gt;- 정전, 하드웨어 고장 등 어쩔수없는 오류&lt;br /&gt;- 인텔 CPU에서 &lt;b&gt;NMI pin&lt;/b&gt;으로 신호가 들어옴&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;i&gt;&lt;b&gt;하드웨어 인터럽트 종류&lt;/b&gt;&lt;/i&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;입출력 인터럽트 (I/O interrupt) - 입출력 작업의 종료나 입출력 오류에 의해 CPU의 기능이 요청됨&lt;/li&gt;
&lt;li&gt;정전,전원 이상 인터럽트(Power fail interrupt) - 전원 공급의 이상&lt;/li&gt;
&lt;li&gt;기계 착오 인터럽트(Machine check interrupt) - CPU의 기능적인 오류&lt;/li&gt;
&lt;li&gt;외부 신호 인터럽트(External interrupt) - I/O 장치가 아닌 오퍼레이터나 타이머에 의해 의도적으로 프로그램이 중단된 경우&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;i&gt;&lt;b&gt;소프트웨어 인터럽트&lt;/b&gt;&lt;/i&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;CPU내부에서 자신이 실행한 명령이나 CPU의 명령 실행에 관련된 모듈이 변화하는 경우 발생&lt;/li&gt;
&lt;li&gt;trap 또는 exception 이라고도 함&lt;/li&gt;
&lt;li&gt;프로그램의 오류에 의해 생기는 인터럽트&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;i&gt;&lt;b&gt;소프트웨어 인터럽트 종류&lt;/b&gt;&lt;/i&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;프로그램 검사 인터럽트 (Program check interrupt)&amp;nbsp;&lt;br /&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;0으로 나누는 경우&lt;/li&gt;
&lt;li&gt;OverFlow/UnderFlow&lt;/li&gt;
&lt;li&gt;페이지 부재&lt;/li&gt;
&lt;li&gt;부당한 기억장소의 참조&lt;/li&gt;
&lt;li&gt;등등...&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;SVC(Supervisor Call: 감시프로그램 호출)인터럽트
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;사용자가 프로그램을 실행시키거나 supervisior을 호출하는 동작을 수행하는 경우&lt;/li&gt;
&lt;li&gt;프로그래머에 의해 코드로 짜인 감시 프로그램을 호출하는 방식&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;i&gt;&lt;b&gt;인터럽트 우선순위&lt;/b&gt;&lt;/i&gt;&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-origin-width=&quot;826&quot; data-origin-height=&quot;1290&quot; data-filename=&quot;스크린샷 2021-08-17 오후 12.39.28.png&quot; width=&quot;600&quot; height=&quot;937&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bXN8JO/btrcrNOCdrX/p9yBaxaFeCQKL7VleUPKWk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bXN8JO/btrcrNOCdrX/p9yBaxaFeCQKL7VleUPKWk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bXN8JO/btrcrNOCdrX/p9yBaxaFeCQKL7VleUPKWk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbXN8JO%2FbtrcrNOCdrX%2Fp9yBaxaFeCQKL7VleUPKWk%2Fimg.png&quot; data-origin-width=&quot;826&quot; data-origin-height=&quot;1290&quot; data-filename=&quot;스크린샷 2021-08-17 오후 12.39.28.png&quot; width=&quot;600&quot; height=&quot;937&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;i&gt;&lt;b&gt;인터럽트 벡터&amp;nbsp; &amp;nbsp;Interrupt Vector&lt;/b&gt;&lt;/i&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;여러가지 인터럽트에 대해 해당 인터럽트 발생시 처리해야 할 루틴(ISR)의 주소를 보관하고 있는 공간&lt;/li&gt;
&lt;li&gt;대부분의 CPU들은 인터럽트 벡터 테이블을 가지고 있음&lt;/li&gt;
&lt;li&gt;인텔x86에서는 이를 IDT(Interrupt Descriptor Table)이라고 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;i&gt;&lt;b&gt;인터럽트 서비스 루틴&amp;nbsp; &amp;nbsp;Interrupt Service Routine(ISR)&lt;/b&gt;&lt;/i&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;인터럽트 핸들러 Interrupt handler 라고도 함&lt;/li&gt;
&lt;li&gt;인터럽트가 접수되면 각각의 인터럽트에 대응하여 특정 기능을 처리하는 기계어 코드 루틴(커널이 실행)&lt;/li&gt;
&lt;li&gt;ex) 키보드 자판을 눌러 키보드 인터럽트가 발생하면 이에 해당하는 인터럽트 서비스 루틴이 실행됨&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;i&gt;&lt;b&gt;인터럽트 과정&lt;/b&gt;&lt;/i&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;gt;&amp;gt; 프로세스 A 실행 중 디스크에서 어떤 데이터를 읽어오라는 명령을 받았을 때&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;프로세스 A는 system call을 통해 인터럽트를 발생시킴&lt;/li&gt;
&lt;li&gt;CPU는 현재 진행중인 기계어 코드를 완료&lt;/li&gt;
&lt;li&gt;현재까지 수행중이었던 상태를 해당 프로세스의&lt;b&gt; PCB(Process Control Block)&lt;/b&gt;에 저장&amp;nbsp;&lt;br /&gt;(수행중이던 메모리 주소, 레지스터 값 등등)&lt;/li&gt;
&lt;li&gt;PC(Program Counter, IP)에 다음 실행할 명령의 주소 저장&lt;/li&gt;
&lt;li&gt;인터럽트 벡터를 읽고 ISR 주소값을 얻어 ISR(interrupt Service Routine)으로 점프하여 루틴을 실행&lt;/li&gt;
&lt;li&gt;해당 코드 실행&lt;/li&gt;
&lt;li&gt;해당 일을 다 처리하면 저장했던 프로세스 상태 복구&lt;/li&gt;
&lt;li&gt;ISR의 끝에 IRET명령어에 의해 인터럽트가 해제&lt;/li&gt;
&lt;li&gt;IRET 명령어가 실행되면, 대피시킨 PC 값을 복원하여 이전 실행위치로 복원&lt;br /&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-origin-width=&quot;461&quot; data-origin-height=&quot;495&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/csOicV/btrcebCFFGo/JOr4V3M4umegWKsqdtSV8K/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/csOicV/btrcebCFFGo/JOr4V3M4umegWKsqdtSV8K/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/csOicV/btrcebCFFGo/JOr4V3M4umegWKsqdtSV8K/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcsOicV%2FbtrcebCFFGo%2FJOr4V3M4umegWKsqdtSV8K%2Fimg.jpg&quot; data-origin-width=&quot;461&quot; data-origin-height=&quot;495&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #456771;&quot;&gt;&lt;i&gt;* &lt;b&gt;IRET(Interrupt Return) 명령어&lt;/b&gt;: 이전 태스크로 다시 돌아가는 어셈블리 명령어. ISR의 마지막 명령어.&lt;/i&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;참고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://huistorage.tistory.com/111&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://huistorage.tistory.com/111&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://medium.com/@lazypanda43/%EC%9D%B8%ED%84%B0%EB%9F%BD%ED%8A%B8-%EC%A2%85%EB%A5%98%EC%99%80-%EC%B2%98%EB%A6%AC%EA%B3%BC%EC%A0%95%EA%B3%BC-%EC%9A%B0%EC%84%A0%EC%88%9C%EC%9C%84-c95c26909472&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://medium.com/@lazypanda43/%EC%9D%B8%ED%84%B0%EB%9F%BD%ED%8A%B8-%EC%A2%85%EB%A5%98%EC%99%80-%EC%B2%98%EB%A6%AC%EA%B3%BC%EC%A0%95%EA%B3%BC-%EC%9A%B0%EC%84%A0%EC%88%9C%EC%9C%84-c95c26909472&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://velog.io/@adam2/%EC%9D%B8%ED%84%B0%EB%9F%BD%ED%8A%B8&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://velog.io/@adam2/%EC%9D%B8%ED%84%B0%EB%9F%BD%ED%8A%B8&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://otakuking.tistory.com/70&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://otakuking.tistory.com/70&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://docs.oracle.com/cd/E19455-01/806-3773/instructionset-75/index.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://docs.oracle.com/cd/E19455-01/806-3773/instructionset-75/index.html&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>CS</category>
      <category>interrupt</category>
      <category>OS</category>
      <category>소프트웨어 인터럽트</category>
      <category>인터럽트</category>
      <category>하드웨어 인터럽트</category>
      <author>D0HAN.</author>
      <guid isPermaLink="true">https://doh-an.tistory.com/31</guid>
      <comments>https://doh-an.tistory.com/31#entry31comment</comments>
      <pubDate>Sun, 15 Aug 2021 23:45:53 +0900</pubDate>
    </item>
    <item>
      <title>[DB] SQL - JOIN문, JOIN 종류 (Inner Join,Natural Join,Outer Join,Cross Join)</title>
      <link>https://doh-an.tistory.com/30</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;background-color: #c0d1e7; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&lt;i&gt;1. Join이란?&lt;/i&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;두 개 이상의 테이블을 서로 연결하여 데이터를 검색할 때 사용하는 방법&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;두 개의 테이블을 마치 하나의 테이블인 것처럼 보여준다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;background-color: #c0d1e7; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;i&gt;&lt;b&gt;2. 기본 구조&lt;/b&gt;&lt;/i&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;pre id=&quot;code_1628409764067&quot; class=&quot;sql&quot; data-ke-language=&quot;sql&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;1) 일반
SELECT 테이블.컬럼, 테이블.컬럼
FROM 테이블1,테이블2           
WHERE 조건&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;background-color: #c0d1e7; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;i&gt;&lt;b&gt;3. Join 의 종류&lt;/b&gt;&lt;/i&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Inner Join&lt;/li&gt;
&lt;li&gt;Natural Join&lt;/li&gt;
&lt;li&gt;Outer Join
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;Left Join&lt;/li&gt;
&lt;li&gt;Right Join&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Cross Join&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;991&quot; data-origin-height=&quot;689&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b8YNAm/btrbCuoZPrI/lEIcImHWTIZs3nApw0Bqr0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b8YNAm/btrbCuoZPrI/lEIcImHWTIZs3nApw0Bqr0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b8YNAm/btrbCuoZPrI/lEIcImHWTIZs3nApw0Bqr0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb8YNAm%2FbtrbCuoZPrI%2FlEIcImHWTIZs3nApw0Bqr0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;991&quot; height=&quot;689&quot; data-origin-width=&quot;991&quot; data-origin-height=&quot;689&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;script async src=&quot;https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-8813018742152991&quot;
     crossorigin=&quot;anonymous&quot;&gt;&lt;/script&gt;
&lt;ins class=&quot;adsbygoogle&quot;
     style=&quot;display:block; text-align:center;&quot;
     data-ad-layout=&quot;in-article&quot;
     data-ad-format=&quot;fluid&quot;
     data-ad-client=&quot;ca-pub-8813018742152991&quot;
     data-ad-slot=&quot;1178361169&quot;&gt;&lt;/ins&gt;
&lt;script&gt;
     (adsbygoogle = window.adsbygoogle || []).push({});
&lt;/script&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #8a3db6;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;① &lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;내부 조인 (Inner Join)&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;pre id=&quot;code_1628452666534&quot; class=&quot;sql&quot; data-ke-language=&quot;sql&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;1)
SELECT 조회할 컬럼
FROM 테이블1, 테이블2
[WHERE 조건문]


2)
SELECT 조회할 컬럼
FROM 테이블1
(INNER) JOIN 테이블2
ON 테이블1.컬럼 = 테이블2.컬럼
[WHERE 추가조건]&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;기준 테이블과 조인 테이블 모두에 조인 컬럼 데이터가 존재해야 조회됨 (ON절)&lt;/li&gt;
&lt;li&gt;예시&lt;br /&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;463&quot; data-origin-height=&quot;305&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c7kLBI/btrbquYTQ0x/M4kso0nOk1n1kplQmyjHXk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c7kLBI/btrbquYTQ0x/M4kso0nOk1n1kplQmyjHXk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c7kLBI/btrbquYTQ0x/M4kso0nOk1n1kplQmyjHXk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc7kLBI%2FbtrbquYTQ0x%2FM4kso0nOk1n1kplQmyjHXk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;463&quot; height=&quot;305&quot; data-origin-width=&quot;463&quot; data-origin-height=&quot;305&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;span style=&quot;color: #859900;&quot;&gt;SELECT&lt;/span&gt; &lt;span&gt;Sales&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;Countries&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Country&lt;/span&gt; &lt;br /&gt;&lt;span style=&quot;color: #859900;&quot;&gt;FROM&lt;/span&gt; &lt;span&gt;Sales&lt;/span&gt; &lt;br /&gt;&lt;span style=&quot;color: #859900;&quot;&gt;JOIN&lt;/span&gt; &lt;span&gt;Countries&lt;/span&gt; &lt;br /&gt;&lt;span style=&quot;color: #859900;&quot;&gt;ON&lt;/span&gt; &lt;span&gt;Sales&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;CountryID&lt;/span&gt; &lt;span style=&quot;color: #000000;&quot;&gt;=&lt;/span&gt; &lt;span&gt;Countries&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;ID&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #8a3db6;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;②&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;자연 조인 (Natural Join)&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;pre id=&quot;code_1628452721836&quot; class=&quot;sql&quot; data-ke-language=&quot;sql&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;SELECT 조회할 컬럼
FROM 테이블1
NATURAL JOIN 테이블2
[WHERE 조건문]&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;내부 조인에 속함.&lt;/li&gt;
&lt;li&gt;두 테이블에서 동일한 컬럼명을 갖는 컬럼은 모두 조인이 된다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;두 테이블이 동시에 가지고 있는 컬럼의 값이 전부 같은 것만 골라냄 &lt;br /&gt;-&amp;gt; 반드시 두 테이블 간의 동일한 이름, 타입을 가진 컬럼이 필요함. 이름이 같지만 타입이 다른 컬럼이 있으면 에러&lt;/li&gt;
&lt;li&gt;기준 테이블과 조인 테이블 모두에 데이터가 존재해야 조회됨&lt;/li&gt;
&lt;li&gt;Inner Join에서 조건문 추가하여 같은 결과값을 얻을 수 있음&lt;/li&gt;
&lt;li&gt;예시&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;720&quot; data-origin-height=&quot;540&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/uzjOw/btrbENWaFvG/zrk95RtBpVu7iS0O4EtT2k/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/uzjOw/btrbENWaFvG/zrk95RtBpVu7iS0O4EtT2k/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/uzjOw/btrbENWaFvG/zrk95RtBpVu7iS0O4EtT2k/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FuzjOw%2FbtrbENWaFvG%2Fzrk95RtBpVu7iS0O4EtT2k%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;650&quot; height=&quot;488&quot; data-origin-width=&quot;720&quot; data-origin-height=&quot;540&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #859900;&quot;&gt;SELECT&lt;/span&gt; *&lt;br /&gt;&lt;span style=&quot;color: #859900;&quot;&gt;FROM&lt;/span&gt; R&lt;br /&gt;&lt;span style=&quot;color: #859900;&quot;&gt;NATURAL JOIN&lt;/span&gt; S&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;같은 컬럼이 두개일 경우&lt;br /&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;761&quot; data-origin-height=&quot;268&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/zrbt8/btrbuA491Ba/JILUt95KEqzCELUuBWY4H1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/zrbt8/btrbuA491Ba/JILUt95KEqzCELUuBWY4H1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/zrbt8/btrbuA491Ba/JILUt95KEqzCELUuBWY4H1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fzrbt8%2FbtrbuA491Ba%2FJILUt95KEqzCELUuBWY4H1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;500&quot; height=&quot;176&quot; data-origin-width=&quot;761&quot; data-origin-height=&quot;268&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;img src=&quot;https://blog.kakaocdn.net/dn/cf94LH/btrbEOAM3oN/K3eGtWkbzXDbeqObklKpM1/img.png&quot; width=&quot;500&quot; data-image-src=&quot;https://blog.kakaocdn.net/dn/cf94LH/btrbEOAM3oN/K3eGtWkbzXDbeqObklKpM1/img.png&quot; data-origin-width=&quot;1180&quot; data-origin-height=&quot;2360&quot; data-filename=&quot;스크린샷 2021-08-09 오전 3.22.36.png&quot; /&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #8a3db6;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;③&amp;nbsp; 전체 외부 조인 (Full Outer Join)&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: #8a3db6;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;pre id=&quot;code_1628447927123&quot; class=&quot;sql&quot; data-ke-language=&quot;sql&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;SELECT 조회할 컬럼
FROM 테이블1 
FULL OUTER JOIN 테이블2
ON 조건문
[WHERE 추가조건문]&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;공통된 부분만 골라 결합하는 Inner Join 과 다르게 공통되지 않은 행도 유지한다.&lt;/li&gt;
&lt;li&gt;이때 두 테이블 모두의 값을 유지하면 Full Outer Join&lt;br /&gt;왼쪽 테이블 값만 유지하면 Left Outer Join&lt;br /&gt;오른쪽 테이블 값만 유지하면 Right Outer Join&lt;/li&gt;
&lt;li&gt;MySQL에서는 FULL OUTER JOIN을 지원하지 않으므로 LEFT OUTER JOIN 결과와 RIGHT OUTER JOIN결과를 UNION 하여 사용해야 함&lt;/li&gt;
&lt;li&gt;예시&lt;br /&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2021-08-09 오전 4.04.17.png&quot; data-origin-width=&quot;1292&quot; data-origin-height=&quot;964&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/PNNRB/btrbCtcAR3w/oXmkrdq6IHzv6NggOR0kl0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/PNNRB/btrbCtcAR3w/oXmkrdq6IHzv6NggOR0kl0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/PNNRB/btrbCtcAR3w/oXmkrdq6IHzv6NggOR0kl0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FPNNRB%2FbtrbCtcAR3w%2FoXmkrdq6IHzv6NggOR0kl0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;600&quot; height=&quot;448&quot; data-filename=&quot;스크린샷 2021-08-09 오전 4.04.17.png&quot; data-origin-width=&quot;1292&quot; data-origin-height=&quot;964&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;span style=&quot;color: #859900;&quot;&gt;SELECT&lt;/span&gt;&amp;nbsp;*&lt;br /&gt;&lt;span style=&quot;color: #859900;&quot;&gt;FROM&lt;/span&gt; instructor&lt;br /&gt;&lt;span style=&quot;color: #859900;&quot;&gt;FULL OUTER JOIN&lt;/span&gt; teaches&amp;nbsp;&lt;br /&gt;&lt;span style=&quot;color: #859900;&quot;&gt;ON &lt;span style=&quot;color: #000000;&quot;&gt;instructor.id = teaches.id&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #8a3db6;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;④ Left Outer Join&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;pre id=&quot;code_1628449783072&quot; class=&quot;sql&quot; data-ke-language=&quot;sql&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;SELECT 조회할 컬럼
FROM 기준테이블1 
LEFT OUTER JOIN 테이블2
ON 조건문
[WHERE 추가조건문]&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Left Join = Left Outer Join&lt;/li&gt;
&lt;li&gt;왼쪽 테이블을 기준으로 일치하는 행만 결합되고, 일치하지 않는 부분은 null 값으로 채워짐.&lt;/li&gt;
&lt;li&gt;예시&lt;br /&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2021-08-09 오전 4.15.08.png&quot; data-origin-width=&quot;1222&quot; data-origin-height=&quot;848&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/x7aO7/btrbwg59qDG/CJu4asfXeRFAX7o0fm7NdK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/x7aO7/btrbwg59qDG/CJu4asfXeRFAX7o0fm7NdK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/x7aO7/btrbwg59qDG/CJu4asfXeRFAX7o0fm7NdK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fx7aO7%2Fbtrbwg59qDG%2FCJu4asfXeRFAX7o0fm7NdK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;600&quot; height=&quot;416&quot; data-filename=&quot;스크린샷 2021-08-09 오전 4.15.08.png&quot; data-origin-width=&quot;1222&quot; data-origin-height=&quot;848&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;span style=&quot;color: #859900;&quot;&gt;SELECT&lt;/span&gt;&amp;nbsp;*&lt;br /&gt;&lt;span style=&quot;color: #859900;&quot;&gt;FROM&lt;/span&gt;&amp;nbsp;instructor&lt;br /&gt;&lt;span style=&quot;color: #859900;&quot;&gt;LEFT OUTER JOIN&lt;/span&gt;&amp;nbsp;teaches&amp;nbsp;&lt;br /&gt;&lt;span style=&quot;color: #859900;&quot;&gt;ON &lt;span style=&quot;color: #000000;&quot;&gt;instructor.id = teaches.id&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #8a3db6;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;⑤ Right Join&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;pre id=&quot;code_1628452778369&quot; class=&quot;sql&quot; data-ke-language=&quot;sql&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;SELECT 조회할 컬럼
FROM 테이블1 
RIGHT OUTER JOIN 기준테이블2
ON 조건문
[WHERE 추가조건문]&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Right Join = Right Outer Join&lt;/li&gt;
&lt;li&gt;오른쪽 테이블을 기준으로 일치하는 행만 결합되고, 일치하지 않는 부분은 null 값으로 채워짐.&lt;/li&gt;
&lt;li&gt;예시&lt;br /&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;721&quot; data-origin-height=&quot;489&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kBoPJ/btrbpWOcIGj/ECN1TsGyFcMSOOVLE1C4ok/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kBoPJ/btrbpWOcIGj/ECN1TsGyFcMSOOVLE1C4ok/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kBoPJ/btrbpWOcIGj/ECN1TsGyFcMSOOVLE1C4ok/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkBoPJ%2FbtrbpWOcIGj%2FECN1TsGyFcMSOOVLE1C4ok%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;600&quot; height=&quot;407&quot; data-origin-width=&quot;721&quot; data-origin-height=&quot;489&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;br /&gt;&lt;span style=&quot;color: #859900;&quot;&gt;SELECT&lt;/span&gt;&amp;nbsp;*&lt;br /&gt;&lt;span style=&quot;color: #859900;&quot;&gt;FROM&lt;/span&gt;&amp;nbsp;instructor&lt;br /&gt;&lt;span style=&quot;color: #859900;&quot;&gt;RIGHT OUTER JOIN&lt;/span&gt;&amp;nbsp;teaches&amp;nbsp;&lt;br /&gt;&lt;span style=&quot;color: #859900;&quot;&gt;ON &lt;span style=&quot;color: #000000;&quot;&gt;instructor.id = teaches.id&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #8a3db6;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;⑥ Cross Join&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;pre id=&quot;code_1628572854342&quot; class=&quot;sql&quot; data-ke-language=&quot;sql&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;1)
SELECT 조회할컬럼
FROM 테이블1, 테이블2

2)
SELECT 조회할컬럼
FROM 테이블1
JOIN 테이블2

3)
SELECT 조회할컬럼
FROM 테이블1
CROSS JOIN 테이블2&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;곱집합&lt;/li&gt;
&lt;li&gt;두 테이블 데이터의 모든 조합&lt;/li&gt;
&lt;li&gt;테이블1의 row * 테이블2의 row 개수만큼의 row를 가진 테이블 생성&lt;br /&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2021-08-10 오후 2.23.16.png&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;934&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lBWZk/btrbHcvQ7lK/ziZIwcRD2XedQRGznmbmUk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lBWZk/btrbHcvQ7lK/ziZIwcRD2XedQRGznmbmUk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lBWZk/btrbHcvQ7lK/ziZIwcRD2XedQRGznmbmUk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlBWZk%2FbtrbHcvQ7lK%2FziZIwcRD2XedQRGznmbmUk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;600&quot; height=&quot;934&quot; data-filename=&quot;스크린샷 2021-08-10 오후 2.23.16.png&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;934&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;참고&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;http://egloos.zum.com/sweeper/v/3002220&quot;&gt;http://egloos.zum.com/sweeper/v/3002220&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://zetawiki.com/wiki/SQL_%EB%82%B4%EB%B6%80_%EC%A1%B0%EC%9D%B8&quot;&gt;https://zetawiki.com/wiki/SQL_%EB%82%B4%EB%B6%80_%EC%A1%B0%EC%9D%B8&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://the-underwater.tistory.com/26&quot;&gt;https://the-underwater.tistory.com/26&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://viewa.tistory.com/36&quot;&gt;https://viewa.tistory.com/36&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://yahwang.github.io/posts/33&quot;&gt;https://yahwang.github.io/posts/33&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>CS</category>
      <category>CROSS JOIN</category>
      <category>db</category>
      <category>INNER JOIN</category>
      <category>join</category>
      <category>OS</category>
      <category>OUTER JOIN</category>
      <category>SQL</category>
      <author>D0HAN.</author>
      <guid isPermaLink="true">https://doh-an.tistory.com/30</guid>
      <comments>https://doh-an.tistory.com/30#entry30comment</comments>
      <pubDate>Mon, 9 Aug 2021 04:33:29 +0900</pubDate>
    </item>
    <item>
      <title>[Network] TCP/IP 흐름제어 &amp;amp; 혼잡제어</title>
      <link>https://doh-an.tistory.com/29</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #c0d1e7; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&lt;a style=&quot;color: #c0d1e7;&quot; href=&quot;https://doh-an.tistory.com/26&quot;&gt;&lt;span style=&quot;color: #9d9d9d; background-color: #ffffff;&quot;&gt;&amp;gt;&amp;gt;TCP란?&lt;/span&gt;&lt;/a&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;☑️ &lt;/b&gt;&lt;i&gt;&lt;b&gt;흐름 제어? 혼잡 제어?&lt;/b&gt;&lt;/i&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;: 혼잡 상황이 발생하면 네트워크 자원이 낭비되므로 혼잡 상황을 최소화 하기 위한 기법&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;흐름 제어&lt;/b&gt;:&amp;nbsp; &lt;span style=&quot;background-color: #c0d1e7;&quot;&gt;&lt;b&gt;송신측&lt;/b&gt;&lt;/span&gt;과 &lt;span style=&quot;background-color: #c0d1e7;&quot;&gt;&lt;b&gt;수신측&lt;/b&gt;&lt;/span&gt;의 데이터 처리 속도 차이를 해결하기 위한 기법. &lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;송신측의 데이터 &lt;span style=&quot;color: #0593d3;&quot;&gt;&lt;b&gt;전송량&lt;/b&gt;&lt;/span&gt; 제어&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;혼잡 제어&lt;/b&gt;: &lt;span style=&quot;background-color: #ffc9af;&quot;&gt;&lt;b&gt;송신측의 데이터 전달&lt;/b&gt;&lt;/span&gt;과 &lt;span style=&quot;background-color: #ffc9af;&quot;&gt;&lt;b&gt;네트워크 상의 데이터 처리 속도&lt;/b&gt;&lt;/span&gt; 차이를 해결하기 위한 기법.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 송신측의 데이터 &lt;span style=&quot;color: #ef6f53;&quot;&gt;&lt;b&gt;전송 속도&lt;/b&gt;&lt;/span&gt; 제어&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;✅ 흐름 제어 Flow control&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; background-color: #cce3d4;&quot;&gt;&lt;b&gt;1. Stop and wait 방식&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;매번 전송한 패킷에 대해 확인 응답을 받아야만 그 다음 패킷을 전송하는 방법 (비효율적)&lt;/span&gt;&lt;br /&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-origin-width=&quot;228&quot; data-origin-height=&quot;306&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bc8Yh4/btraqSE5vPK/fqP4MYA63vWL66NJ17qfsk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bc8Yh4/btraqSE5vPK/fqP4MYA63vWL66NJ17qfsk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bc8Yh4/btraqSE5vPK/fqP4MYA63vWL66NJ17qfsk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbc8Yh4%2FbtraqSE5vPK%2FfqP4MYA63vWL66NJ17qfsk%2Fimg.png&quot; data-origin-width=&quot;228&quot; data-origin-height=&quot;306&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; background-color: #cce3d4;&quot;&gt;&lt;b&gt;2. Sliding window 슬라이딩 윈도우 기법&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;수신 측에서 설정한 윈도우 크기만큼은 송신 측에서 확인 응답ACK를 받기 전에 전송 가능.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;송신 버퍼의 범위는 수신 측의 여유 버퍼 공간을 반영하여 동적으로 바뀜.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-origin-width=&quot;580&quot; data-origin-height=&quot;322&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qAMcM/btraqTc8kgQ/sB075PwK3PBPj8d3kLHff1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qAMcM/btraqTc8kgQ/sB075PwK3PBPj8d3kLHff1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qAMcM/btraqTc8kgQ/sB075PwK3PBPj8d3kLHff1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqAMcM%2FbtraqTc8kgQ%2FsB075PwK3PBPj8d3kLHff1%2Fimg.png&quot; data-origin-width=&quot;580&quot; data-origin-height=&quot;322&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&amp;nbsp;윈도우에 포함되는 모든 패킷을 확인 응답 없이 전송하고, 그 패킷들의 전달이 확인되는 대로 윈도우를 옆으로 옮기며 그 다음 패킷들을 전송&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;TCP/IP를 사용하는 호스트들은 보내는 용과 받는 용의 2개의 윈도우를 가지고 있다. 실제 데이터를 보내기 전에 TCP-3way-handshaking을 통해 수신 컴퓨터의 receive window size에 자신의 윈도우 크기를 맞추게 된다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;* 호스트: 응용 프로그램을 사용하는 주체.&amp;nbsp;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;✅ &lt;b&gt;혼잡 제어 Congestion control&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;:데이터 전달과 네트워크의 데이터 처리 속도를 해결하기 위한 기법&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;: 송신측에서 보내는 데이터의전송 속도를 제어&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; background-color: #d8cce3;&quot;&gt;&lt;b&gt;1. AIMD (Additive Increase Multicative Decrease)&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;합 증가/ 곱 감소 알고리즘&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;처음에 패킷 하나를 보내는 것으로 시작, 전송한 패킷이 문제 없이 도착하면 윈도우 크기를 1씩 증가시키며 전송&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;패킷 전송을 실패하거나 타임아웃이 발생하면 윈도우 크기를 절반으로 감소시킴&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;여러 호스트가 한 네트워크를 공유하고 있으면 나중에 진입하는 쪽이 처음에는 불리하지만, 시간이 흐르면 평형 상태로 수렴&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;문제점&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;- 초기 네트워크의 높은 대역폭을 사용하지 못함&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;- 처음에 전송 속도를 올리는 데 시간이 너무 오래 걸림&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;- 네트워크가 혼잡해지는 상황을 미리 감지하지 못하여 혼잡해지고 나서야 대역폭을 줄임&lt;br /&gt;&lt;/span&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-origin-width=&quot;571&quot; data-origin-height=&quot;326&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kQXga/btrax8N0cGF/ioxrRAhaDUKTyXa1WRbvG1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kQXga/btrax8N0cGF/ioxrRAhaDUKTyXa1WRbvG1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kQXga/btrax8N0cGF/ioxrRAhaDUKTyXa1WRbvG1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkQXga%2Fbtrax8N0cGF%2FioxrRAhaDUKTyXa1WRbvG1%2Fimg.png&quot; data-origin-width=&quot;571&quot; data-origin-height=&quot;326&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; background-color: #d8cce3;&quot;&gt;&lt;b&gt;2. Slow start&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;AIMD와 같이 패킷을 하나씩 보냄&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;하나의 패킷이 문제없이 도착하여 ACK를 보낼 때마다 윈도우 크기를 1씩 늘림&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;한 주기가 지나면 윈도우 크기는 2배 -&amp;gt; 그래프의 모양이 지수함수 꼴&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;혼잡 현상이 발생하면 윈도우 크기를 1로 떨어트림&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;한 번 혼잡 현상이 발생하고 나면 이전에 혼잡 현상이 발생했던 윈도우 크기의 절반까지는 이전처럼 지수함수 꼴로 윈도우 크기를 증가시키고 그 이후부터는 완만하게 1씩 증가시킴&lt;/span&gt;&lt;br /&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-origin-width=&quot;720&quot; data-origin-height=&quot;540&quot; width=&quot;600&quot; height=&quot;450&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cOKT9U/btrasuEgFeI/YuwrPUWItyjURibCrpJ5Z1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cOKT9U/btrasuEgFeI/YuwrPUWItyjURibCrpJ5Z1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cOKT9U/btrasuEgFeI/YuwrPUWItyjURibCrpJ5Z1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcOKT9U%2FbtrasuEgFeI%2FYuwrPUWItyjURibCrpJ5Z1%2Fimg.png&quot; data-origin-width=&quot;720&quot; data-origin-height=&quot;540&quot; width=&quot;600&quot; height=&quot;450&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; background-color: #d8cce3;&quot;&gt;&lt;b&gt;3. Fast Recovery&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;혼잡 상태가 되면 윈도우 크기를 1로 줄이지 않고 반으로 줄인 후 선형증가.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;혼잡 상태를 한 번 겪고 나서부터는 AIMD 방식으로 동작&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; background-color: #d8cce3;&quot;&gt;&lt;b&gt;4. Fast Retransmit&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;먼저 도착해야 할 패킷이 도착하지 않고 다음 패킷이 도착한 경우에도 ACK패킷을 보냄&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;순서대로 잘 도착한 마지막 패킷의 다음 패킷 순번을 ACK패킷에 실어보내게 되므로 송신측에서는 순번이 중복된 것을 알게됨&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;이것을 감지하여 중복된 순번의 패킷을 3개 받으면 타임아웃 전에 문제가 되는 순번의 패킷을 즉시&amp;nbsp;재전송해줌&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;이런 현상이 일어나면 혼잡 현상이 발생한 것이므로 윈도우 크기를 줄임&lt;br /&gt;&lt;/span&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-origin-width=&quot;640&quot; data-origin-height=&quot;480&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/FuefQ/btraoP22nYp/lxqkWCEyKeYeEkiKVP7FX1/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/FuefQ/btraoP22nYp/lxqkWCEyKeYeEkiKVP7FX1/img.gif&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/FuefQ/btraoP22nYp/lxqkWCEyKeYeEkiKVP7FX1/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/FuefQ/btraoP22nYp/lxqkWCEyKeYeEkiKVP7FX1/img.gif&quot; data-origin-width=&quot;640&quot; data-origin-height=&quot;480&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;✅ 혼잡 제어 정책&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; background-color: #ebd7d5;&quot;&gt;&lt;b&gt;1. TCP Tahoe&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;처음에는 Slow Start 방식을 사용하다가 임계점에 도달하면 AIMD 방식 사용&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;그러다 3 ACK 순번 중복(중간패킷유실)이나 타임아웃이 발생하면 혼잡이라고 판단하여 임계점은 혼잡이 발생한 윈도우 크기의 절반으로, 윈도우 크기는 1로 줄임&lt;/span&gt;&lt;br /&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-origin-width=&quot;992&quot; data-origin-height=&quot;497&quot; width=&quot;620&quot; height=&quot;311&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bjMWqF/btrav6pm2iV/0n0KVz6GiugszGv0Qw9Htk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bjMWqF/btrav6pm2iV/0n0KVz6GiugszGv0Qw9Htk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bjMWqF/btrav6pm2iV/0n0KVz6GiugszGv0Qw9Htk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbjMWqF%2Fbtrav6pm2iV%2F0n0KVz6GiugszGv0Qw9Htk%2Fimg.png&quot; data-origin-width=&quot;992&quot; data-origin-height=&quot;497&quot; width=&quot;620&quot; height=&quot;311&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;단점: 혼잡 이후 Slow start 구간에서 윈도우 크기를 키울때 너무 오래걸림. -&amp;gt; TCP Reno&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; background-color: #ebd7d5;&quot;&gt;&lt;b&gt;2. TCP Reno&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;Tahoe와 마찬가지로 slow start로 시작하여 임계점 이후에는AIMD방식으로 변경.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;단, 3 ACK 중복과 타임아웃을 구분함&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;3 ACK 중복이 발생하면 Fast Recovery 방식을 사용&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;윈도우 크기를 1로 줄이는 것이 아니라 반으로 줄인 후 윈도우 크기를 선형적으로 증가시킴.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;임계점은 줄어든 윈도우 값으로 설정&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;타임아웃이 발생하면 Tahoe와 마찬가지로 윈도우 1로 줄이고 Slow start 진행.(임계점 변경하지 x)&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;참고&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;a href=&quot;https://rok93.tistory.com/entry/%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC-TCP-%ED%9D%90%EB%A6%84%EC%A0%9C%EC%96%B4%ED%98%BC%EC%9E%A1%EC%A0%9C%EC%96%B4&quot;&gt;TCP/IP 흐름제어, 혼잡제어&lt;/a&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;a href=&quot;https://gyoogle.dev/blog/computer-science/network/%ED%9D%90%EB%A6%84%EC%A0%9C%EC%96%B4%20&amp;amp;%20%ED%98%BC%EC%9E%A1%EC%A0%9C%EC%96%B4.html&quot;&gt;TCP/IP (흐름제어/혼잡제어)&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;a href=&quot;https://jwprogramming.tistory.com/36&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;TCP의 흐름제어, 혼잡제어&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;a href=&quot;https://ko.wikipedia.org/wiki/%ED%98%BC%EC%9E%A1_%EC%A0%9C%EC%96%B4#%EB%B9%A0%EB%A5%B8_%EC%9E%AC%EC%A0%84%EC%86%A1&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://ko.wikipedia.org/wiki/%ED%98%BC%EC%9E%A1_%EC%A0%9C%EC%96%B4#%EB%B9%A0%EB%A5%B8_%EC%9E%AC%EC%A0%84%EC%86%A1&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;a href=&quot;https://evan-moon.github.io/2019/11/26/tcp-congestion-control/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://evan-moon.github.io/2019/11/26/tcp-congestion-control/&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;a href=&quot;https://velog.io/@mu1616/TCPIP-%ED%98%BC%EC%9E%A1-%EC%A0%9C%EC%96%B4&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://velog.io/@mu1616/TCPIP-%ED%98%BC%EC%9E%A1-%EC%A0%9C%EC%96%B4&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>CS</category>
      <category>Congestion Control</category>
      <category>flow control</category>
      <category>network</category>
      <category>OS</category>
      <category>TCP/IP</category>
      <author>D0HAN.</author>
      <guid isPermaLink="true">https://doh-an.tistory.com/29</guid>
      <comments>https://doh-an.tistory.com/29#entry29comment</comments>
      <pubDate>Mon, 26 Jul 2021 06:29:29 +0900</pubDate>
    </item>
  </channel>
</rss>