<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>Jutole's programming</title>
    <link>https://jutole.tistory.com/</link>
    <description></description>
    <language>ko</language>
    <pubDate>Sat, 9 May 2026 02:33:50 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>주톨</managingEditor>
    <image>
      <title>Jutole's programming</title>
      <url>https://tistory1.daumcdn.net/tistory/5423831/attach/16640316111f4c94bf354ce49f36821b</url>
      <link>https://jutole.tistory.com</link>
    </image>
    <item>
      <title>[Flutter] Migrate to applying Gradle plugins with the declarative plugins block</title>
      <link>https://jutole.tistory.com/165</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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;937&quot; data-origin-height=&quot;165&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/zJMZp/btsMw5ahLeP/xKESKplf5W7Uq5K08H4Yn1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/zJMZp/btsMw5ahLeP/xKESKplf5W7Uq5K08H4Yn1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/zJMZp/btsMw5ahLeP/xKESKplf5W7Uq5K08H4Yn1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FzJMZp%2FbtsMw5ahLeP%2FxKESKplf5W7Uq5K08H4Yn1%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;937&quot; height=&quot;165&quot; data-origin-width=&quot;937&quot; data-origin-height=&quot;165&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;Flutter 버전 업그레이드 하니 Gradle 관련 수정하라고 나옵니다.&amp;nbsp;&lt;br /&gt;&lt;a href=&quot;https://flutter.dev/to/flutter-gradle-plugin-apply&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://flutter.dev/to/flutter-gradle-plugin-apply&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1740647012997&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Deprecated imperative apply of Flutter's Gradle plugins&quot; data-og-description=&quot;How to migrate your Flutter app's Android Gradle build files to the new, declarative format.&quot; data-og-host=&quot;docs.flutter.dev&quot; data-og-source-url=&quot;https://flutter.dev/to/flutter-gradle-plugin-apply&quot; data-og-url=&quot;https://docs.flutter.dev/release/breaking-changes/flutter-gradle-plugin-apply&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/SVe32/hyYjvA057l/XOwWkz3RGQeSr1CAEOdxA1/img.png?width=937&amp;amp;height=461&amp;amp;face=0_0_937_461&quot;&gt;&lt;a href=&quot;https://flutter.dev/to/flutter-gradle-plugin-apply&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://flutter.dev/to/flutter-gradle-plugin-apply&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/SVe32/hyYjvA057l/XOwWkz3RGQeSr1CAEOdxA1/img.png?width=937&amp;amp;height=461&amp;amp;face=0_0_937_461');&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;Deprecated imperative apply of Flutter's Gradle plugins&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;How to migrate your Flutter app's Android Gradle build files to the new, declarative format.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;docs.flutter.dev&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&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;- Migrate&lt;/h3&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;1.&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1036&quot; data-origin-height=&quot;400&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ovHwa/btsMyEipm2e/ga0Pl3jKTPxHBEb5FfbNt0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ovHwa/btsMyEipm2e/ga0Pl3jKTPxHBEb5FfbNt0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ovHwa/btsMyEipm2e/ga0Pl3jKTPxHBEb5FfbNt0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FovHwa%2FbtsMyEipm2e%2Fga0Pl3jKTPxHBEb5FfbNt0%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;1036&quot; height=&quot;400&quot; data-origin-width=&quot;1036&quot; data-origin-height=&quot;400&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;android -&amp;gt; build.gradle 파일에서 AGP버전과 Kotlin버전을 찾아내야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AGP버전 : com.android.tools.build:gradle 뒤에 나온 버전&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Kotlin버전 : ext.kotlin_version 뒤에 나온 버전&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;2.&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;android -&amp;gt; settings.gradle 파일의 기존 내용을 전부 지우고 아래 코드를 복사해서 넣어줍니다.&lt;/p&gt;
&lt;pre id=&quot;code_1740701773221&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;pluginManagement {
    def flutterSdkPath = {
        def properties = new Properties()
        file(&quot;local.properties&quot;).withInputStream { properties.load(it) }
        def flutterSdkPath = properties.getProperty(&quot;flutter.sdk&quot;)
        assert flutterSdkPath != null, &quot;flutter.sdk not set in local.properties&quot;
        return flutterSdkPath
    }()

    includeBuild(&quot;$flutterSdkPath/packages/flutter_tools/gradle&quot;)

    repositories {
        google()
        mavenCentral()
        gradlePluginPortal()
    }
}

plugins {
    id &quot;dev.flutter.flutter-plugin-loader&quot; version &quot;1.0.0&quot;
    id &quot;com.android.application&quot; version &quot;{agpVersion}&quot; apply false
    id &quot;org.jetbrains.kotlin.android&quot; version &quot;{kotlinVersion}&quot; apply false
}

include &quot;:app&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;그리고 &quot;{agpVersion}&quot;과 &quot;{kotlinVersion}&quot;에 이전에 알아온 버전을 넣어줍니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1041&quot; data-origin-height=&quot;597&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bguVBJ/btsMyumVNfr/ffmRrBPXJXl9IcFlJE49Ok/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bguVBJ/btsMyumVNfr/ffmRrBPXJXl9IcFlJE49Ok/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bguVBJ/btsMyumVNfr/ffmRrBPXJXl9IcFlJE49Ok/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbguVBJ%2FbtsMyumVNfr%2FffmRrBPXJXl9IcFlJE49Ok%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;1041&quot; height=&quot;597&quot; data-origin-width=&quot;1041&quot; data-origin-height=&quot;597&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;3.&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1041&quot; data-origin-height=&quot;464&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nKfKr/btsMzriHzJY/hFkq1ocVjkZ0rOHYv0qlhk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nKfKr/btsMzriHzJY/hFkq1ocVjkZ0rOHYv0qlhk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nKfKr/btsMzriHzJY/hFkq1ocVjkZ0rOHYv0qlhk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FnKfKr%2FbtsMzriHzJY%2FhFkq1ocVjkZ0rOHYv0qlhk%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;1041&quot; height=&quot;464&quot; data-origin-width=&quot;1041&quot; data-origin-height=&quot;464&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;android -&amp;gt; build.gradle 파일에 buildScript내용을 전부 지워줍니다.&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;4.&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1355&quot; data-origin-height=&quot;514&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/pV4bV/btsMAj5xK4R/TDPYvic08pMbvn1Y7wpnL0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/pV4bV/btsMAj5xK4R/TDPYvic08pMbvn1Y7wpnL0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/pV4bV/btsMAj5xK4R/TDPYvic08pMbvn1Y7wpnL0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FpV4bV%2FbtsMAj5xK4R%2FTDPYvic08pMbvn1Y7wpnL0%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;1355&quot; height=&quot;514&quot; data-origin-width=&quot;1355&quot; data-origin-height=&quot;514&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;android -&amp;gt; app -&amp;gt; build.gradle 파일에 저 부분이 있다면 지워주세요.&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;5.&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1027&quot; data-origin-height=&quot;376&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/uzEuH/btsMxrdm3Kl/ZcGLmfVlwKDZOvEOVKVGR0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/uzEuH/btsMxrdm3Kl/ZcGLmfVlwKDZOvEOVKVGR0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/uzEuH/btsMxrdm3Kl/ZcGLmfVlwKDZOvEOVKVGR0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FuzEuH%2FbtsMxrdm3Kl%2FZcGLmfVlwKDZOvEOVKVGR0%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;1027&quot; height=&quot;376&quot; data-origin-width=&quot;1027&quot; data-origin-height=&quot;376&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;android -&amp;gt; app -&amp;gt; build.gradle 파일에 저 부분을 아래와 같이 바꾸어 주시고 해당 코드를 맨 위라인으로 이동시켜 주세요.&lt;/p&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-origin-width=&quot;697&quot; data-origin-height=&quot;433&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cOPQkE/btsMzOLACEo/Ws98hgAeYKmLFTIFquUC90/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cOPQkE/btsMzOLACEo/Ws98hgAeYKmLFTIFquUC90/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cOPQkE/btsMzOLACEo/Ws98hgAeYKmLFTIFquUC90/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcOPQkE%2FbtsMzOLACEo%2FWs98hgAeYKmLFTIFquUC90%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;697&quot; height=&quot;433&quot; data-origin-width=&quot;697&quot; data-origin-height=&quot;433&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;gms.google-service와 firebase.crashlytics는 사용하시는 분만 있으실 겁니다. 없는 분들은 나머지 부분만 바꿔주시면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1740704113599&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;plugins {
    id &quot;com.android.application&quot;
    id &quot;kotlin-android&quot;
    id &quot;dev.flutter.flutter-gradle-plugin&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;6.&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1067&quot; data-origin-height=&quot;577&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bgN1YM/btsMz8iMqv2/ZYB2DLKcFzqfj3U6KKQwak/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bgN1YM/btsMz8iMqv2/ZYB2DLKcFzqfj3U6KKQwak/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bgN1YM/btsMz8iMqv2/ZYB2DLKcFzqfj3U6KKQwak/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbgN1YM%2FbtsMz8iMqv2%2FZYB2DLKcFzqfj3U6KKQwak%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;1067&quot; height=&quot;577&quot; data-origin-width=&quot;1067&quot; data-origin-height=&quot;577&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;android -&amp;gt; app -&amp;gt; build.gradle 파일에 dependencies에 해당 코드가 있다면 지워줍니다.&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;7.&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5번에서 gms.google-serviced와 firebase.crashlytics를 사용했다면 android -&amp;gt; settings.gradle에 해당 부분을 추가해줍니다.&lt;/p&gt;
&lt;p 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-origin-width=&quot;947&quot; data-origin-height=&quot;585&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/br4UJN/btsMzriH7dd/qRglsh1PK2vxPemkkn3zY0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/br4UJN/btsMzriH7dd/qRglsh1PK2vxPemkkn3zY0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/br4UJN/btsMzriH7dd/qRglsh1PK2vxPemkkn3zY0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbr4UJN%2FbtsMzriH7dd%2FqRglsh1PK2vxPemkkn3zY0%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;947&quot; height=&quot;585&quot; data-origin-width=&quot;947&quot; data-origin-height=&quot;585&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Flutter/기본</category>
      <category>flutter</category>
      <category>gradle</category>
      <author>주톨</author>
      <guid isPermaLink="true">https://jutole.tistory.com/165</guid>
      <comments>https://jutole.tistory.com/165#entry165comment</comments>
      <pubDate>Fri, 28 Feb 2025 10:12:16 +0900</pubDate>
    </item>
    <item>
      <title>[Flutter] List Builder: 효율적으로 사용하는 방법</title>
      <link>https://jutole.tistory.com/164</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;Flutter를 사용하면서 리스트(List Builder)를 많이 활용하고 계시죠? 하지만 여러분은 이 리스트 빌더를 정말 제대로 사용하고 계신가요? 이번 글에서는 Flutter에서 리스트 빌더를 올바르게 사용하는 방법과, 최적화가 부족한 부분은 무엇인지에 대해 알아보겠습니다.&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;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;- Why&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;List&amp;nbsp;Builder를&amp;nbsp;왜&amp;nbsp;사용하시나요?&amp;nbsp;리스트&amp;nbsp;안에&amp;nbsp;담긴&amp;nbsp;아이템들을&amp;nbsp;쉽게&amp;nbsp;보여주기&amp;nbsp;위해서인가요?&amp;nbsp;코드가&amp;nbsp;짧아져서&amp;nbsp;편리하다고&amp;nbsp;느끼시나요?&amp;nbsp;이러한&amp;nbsp;이유들도&amp;nbsp;있지만,&amp;nbsp;가장&amp;nbsp;중요한&amp;nbsp;점은&amp;nbsp;성능&amp;nbsp;향상에&amp;nbsp;큰&amp;nbsp;도움이&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;&lt;u&gt;&lt;b&gt;This&amp;nbsp;constructor&amp;nbsp;is&amp;nbsp;appropriate&amp;nbsp;for&amp;nbsp;list&amp;nbsp;views&amp;nbsp;with&amp;nbsp;a&amp;nbsp;large&amp;nbsp;(or&amp;nbsp;infinite)&amp;nbsp;number&amp;nbsp;of&amp;nbsp;children&amp;nbsp;because&amp;nbsp;the&amp;nbsp;builder&amp;nbsp;is&amp;nbsp;called&amp;nbsp;only&amp;nbsp;for&amp;nbsp;those&amp;nbsp;children&amp;nbsp;that&amp;nbsp;are&amp;nbsp;actually&amp;nbsp;visible.&lt;/b&gt;&lt;/u&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;Flutter 공식문서 ListView Builder에 관한 설명입니다. 해석하면 실제로 표시되는 위젯에 한해서만 빌드가 되기 때문에 많은 양의 리스트를 보여주기에 적합하다고 볼 수 있습니다. 비슷한 것으로 안드로이드에 RecyclerView라는 게 있습니다. 이것을 증명하기 위해 아래 코드를 실행해 보겠습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1740148410347&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class ListPage extends StatelessWidget {
  const ListPage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: ListView.builder(
        itemBuilder: (context, index) {
          print('빌드: $index');
          return _buildItem();
        },
        itemCount: 30,
      ),
    );
  }

  Widget _buildItem() {
    return Container(
      width: double.infinity,
      height: 150,
      margin: const EdgeInsets.only(bottom: 10),
      color: Colors.deepOrangeAccent,
      alignment: Alignment.center,
      child: const Text('Hello, World!'),
    );
  }
}

--- 결과 ---
flutter: 빌드: 0
flutter: 빌드: 1
flutter: 빌드: 2
flutter: 빌드: 3
flutter: 빌드: 4
flutter: 빌드: 5
flutter: 빌드: 6&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;itemCount가 30개지만 빌드되는 것은 7번째 아이템까지만 빌드가 되는 것을 확인할 수 있습니다. 드래그를 하면 화면에서 사라진 위젯은 정리가 되고 화면에 나타난 위젯이 다시 그려지면서 Print가 계속 찍히는 것을 보실 수 있으실 겁니다. 그래서 뭐가 문제야?라고 할 수 있습니다. 우리가 UI를 개발할 때 저렇게 리스트만 있는 페이지로 개발을 할까요? 있을 수도 있습니다. 하지만 대부분 그렇지 않죠. 아래에 잘 사용한 예제와 그렇지 못한 예제를 보도록 하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&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;- Good&lt;/b&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1740150364292&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class ListPage extends StatelessWidget {
  const ListPage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child: Column(
          children: [
            Text(
              '이것은 Hello, World! 리스트 입니다.',
            ),
            Expanded(
              child: ListView.builder(
                itemBuilder: (context, index) {
                  print('빌드: $index');
                  return _buildItem();
                },
                itemCount: 30,
              ),
            ),
          ],
        ),
      ),
    );
  }

  Widget _buildItem() {
    return Container(
      width: double.infinity,
      height: 150,
      margin: const EdgeInsets.only(bottom: 10),
      color: Colors.deepOrangeAccent,
      alignment: Alignment.center,
      child: const Text('Hello, World!'),
    );
  }
}&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;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;- Bad&lt;/b&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1740150503634&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class ListPage extends StatelessWidget {
  const ListPage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child: SingleChildScrollView(
          child: Column(
            children: [
              Text(
                '이것은 Hello, World! 리스트 입니다.',
              ),
              ListView.builder(
                physics: const NeverScrollableScrollPhysics(),
                shrinkWrap: true,
                itemBuilder: (context, index) {
                  print('빌드: $index');
                  return _buildItem();
                },
                itemCount: 30,
              ),
            ],
          ),
        ),
      ),
    );
  }

  Widget _buildItem() {
    return Container(
      width: double.infinity,
      height: 150,
      margin: const EdgeInsets.only(bottom: 10),
      color: Colors.deepOrangeAccent,
      alignment: Alignment.center,
      child: const Text('Hello, World!'),
    );
  }
}&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;Good의 코드는 타이틀이 고정되어 있고 리스트를 보여주는 영역이 Expanded로 감싸져 있어 리스트를 보여줄 영역이 정확히 지정되어 있습니다.&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;Bad의 코드는 타이틀이 고정되어 있지 않고 스크롤 시 같이 올라가고 그로 인해 리스트를 보여줄 영역을 지정하지 않아서 shrinkWrap 속성을 사용해서 자식 Widget의 크기만큼 알아서 영역을 잡아라! 이렇게 만들어둔 코드입니다.&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;뭐가 문제야? Bad의 코드를 실행하면 아래와 같은 결과가 실행하자마자 나타납니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1740150869177&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;--- 결과 ---
flutter: 빌드: 0
flutter: 빌드: 1
flutter: 빌드: 2
 ...
flutter: 빌드: 27
flutter: 빌드: 28
flutter: 빌드: 29&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;결과로 보면 실행하자마자 모든 위젯을 빌드시키는 것을 확인할 수 있습니다. 이것은 ListView Builder의 &lt;span style=&quot;text-align: start;&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;size16&quot;&gt;물론&amp;nbsp;위의&amp;nbsp;코드처럼&amp;nbsp;Container에&amp;nbsp;Text&amp;nbsp;정도만&amp;nbsp;보여주는&amp;nbsp;경우라면&amp;nbsp;크리티컬 한 문제가 아닐 수 있습니다. 하지만 만약 이미지를 표시해야 한다면, 모바일 기기가 이미지를 그리는 데 필요한 CPU 자원을 감당하지 못해 튕겨버리는 경우가 발생할 수 있습니다.&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;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;- Why?&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇다면 왜 Bad의 코드는 저런 현상이 나타나는 것 일 까요?&amp;nbsp; Good의 코드와 같이 리스트를 그리는 영역이 고정적일 경우 ListView.builder는 정상적으로 동작합니다. 반면, Bad의 코드와 같이 shrinkWrap 속성을 사용하면 리스트의 크기가 동적으로 조정됩니다. 이 경우, 리스트의 전체 높이를 계산하기 위해 모든 아이템을 한 번에 빌드합니다.&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;성능을 신경 쓴다면 shrinkWrap의 사용은 자제하는 것이 좋습니다.&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;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;- Solution&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇다면 Bad코드와 같이 리스트 영역 위에 따로 보여줄 영역이 있어야 하고, 스크롤 시에 같이 위로 올라가야 하는 상황에서는 어떻게 해야 하는지 많은 방법 중에 제일 간단한 방법을 설명하겠습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1740152077657&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class ListPage extends StatelessWidget {
  const ListPage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child: ListView.builder(
          itemBuilder: (context, index) {
            print('빌드: $index');

            if (index == 0) {
              return Column(
                children: [
                  Text(
                    '이것은 Hello, World! 리스트 입니다.',
                  ),
                  _buildItem()
                ],
              );
            }

            return _buildItem();
          },
          itemCount: 30,
        ),
      ),
    );
  }

  Widget _buildItem() {
    return Container(
      width: double.infinity,
      height: 150,
      margin: const EdgeInsets.only(bottom: 10),
      color: Colors.deepOrangeAccent,
      alignment: Alignment.center,
      child: const Text('Hello, World!'),
    );
  }
}&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;위의 코드처럼 0번째 인덱스에서 타이틀을 함께 반환하는 방식으로 사용하면 ListView.builder는 정상적으로 동작합니다. 하지만 이러한 방법은 시각적으로 매력적이지 않으며, 만약 위에 보여줄 위젯들이 많아진다면 더욱 어색해질 수 있습니다. 이러한 문제를 해결하기 위해, 다음 포스트에서는 CustomScrollView를 사용해 해당 문제를 해결해 보겠습니다.&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;그리고 추가적으로 본인 프로젝트에서 ListView Builder는 제 역할을 하는지 한번 점검해 보시고 효율적으로 사용하시길 바라겠습니다.&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>Flutter/기본</category>
      <category>flutter</category>
      <category>listviewbuilder</category>
      <author>주톨</author>
      <guid isPermaLink="true">https://jutole.tistory.com/164</guid>
      <comments>https://jutole.tistory.com/164#entry164comment</comments>
      <pubDate>Sat, 22 Feb 2025 00:39:35 +0900</pubDate>
    </item>
    <item>
      <title>[Flutter] Cursor로 간단하게 개발하기</title>
      <link>https://jutole.tistory.com/163</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;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://jutole.tistory.com/162&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://jutole.tistory.com/162&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1738193600014&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;[Flutter] Cursor로 프로젝트 세팅하기&quot; data-og-description=&quot;안녕하세요. 이번에는 현재 매우 각광받고 있는 Cursor를 사용해서 Flutter 프로젝트를 세팅 해보도록 하겠습니다.&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Cursor?Cursor는&amp;nbsp;AI와&amp;nbsp;협업을&amp;nbsp;중심으로&amp;nbsp;설계된&amp;nbsp;통합&amp;nbsp;개발&amp;nbsp;환경(IDE)으로,&amp;nbsp;&quot; data-og-host=&quot;jutole.tistory.com&quot; data-og-source-url=&quot;https://jutole.tistory.com/162&quot; data-og-url=&quot;https://jutole.tistory.com/162&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/u9dv1/hyX73X3vaC/KU4atFhas1sclbcMbbK3O1/img.png?width=299&amp;amp;height=168&amp;amp;face=0_0_299_168,https://scrap.kakaocdn.net/dn/2hpXx/hyX7Wq5BW9/jZb3M8sVggJDIErVMK5qM0/img.png?width=299&amp;amp;height=168&amp;amp;face=0_0_299_168,https://scrap.kakaocdn.net/dn/b5sSIJ/hyX7RXAP2l/796ZQOxkqUGY2CAfE7lifK/img.png?width=384&amp;amp;height=925&amp;amp;face=0_0_384_925&quot;&gt;&lt;a href=&quot;https://jutole.tistory.com/162&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://jutole.tistory.com/162&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/u9dv1/hyX73X3vaC/KU4atFhas1sclbcMbbK3O1/img.png?width=299&amp;amp;height=168&amp;amp;face=0_0_299_168,https://scrap.kakaocdn.net/dn/2hpXx/hyX7Wq5BW9/jZb3M8sVggJDIErVMK5qM0/img.png?width=299&amp;amp;height=168&amp;amp;face=0_0_299_168,https://scrap.kakaocdn.net/dn/b5sSIJ/hyX7RXAP2l/796ZQOxkqUGY2CAfE7lifK/img.png?width=384&amp;amp;height=925&amp;amp;face=0_0_384_925');&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;[Flutter] Cursor로 프로젝트 세팅하기&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;안녕하세요. 이번에는 현재 매우 각광받고 있는 Cursor를 사용해서 Flutter 프로젝트를 세팅 해보도록 하겠습니다.&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Cursor?Cursor는&amp;nbsp;AI와&amp;nbsp;협업을&amp;nbsp;중심으로&amp;nbsp;설계된&amp;nbsp;통합&amp;nbsp;개발&amp;nbsp;환경(IDE)으로,&amp;nbsp;&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;jutole.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;
&lt;p data-ke-size=&quot;size16&quot;&gt;지난 글에서 Cursor Ide로 프로젝트 세팅을 끝냈습니다. 이번에는 Cursor의 기능을 이용해서 직접 개발을 해보겠습니다.&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;h3 data-ke-size=&quot;size23&quot;&gt;Accept a tab&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;main.dart의 모든 코드를 지우고 시작해 보겠습니다.&lt;/p&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-origin-width=&quot;265&quot; data-origin-height=&quot;164&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/pwIqc/btsL02Fm6wg/RnKhBEqvec920KRGLKb2GK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/pwIqc/btsL02Fm6wg/RnKhBEqvec920KRGLKb2GK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/pwIqc/btsL02Fm6wg/RnKhBEqvec920KRGLKb2GK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FpwIqc%2FbtsL02Fm6wg%2FRnKhBEqvec920KRGLKb2GK%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;265&quot; height=&quot;164&quot; data-origin-width=&quot;265&quot; data-origin-height=&quot;164&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;해당 파일에 Flutter 프로젝트의 시작 코드인 void main()을 작성하면, 옅은 회색으로 미리 완성된 코드가 보입니다. 이는 AI가 이전에 작성된 코드를 기반으로, 다음에 작성할 코드를 예측하여 보여주는 기능입니다. 만약 예측된 코드가 실제로 작성하려는 코드와 일치하면, 키보드에서 Tab 키를 눌러 자동완성을 할 수 있습니다.&lt;/p&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-origin-width=&quot;377&quot; data-origin-height=&quot;219&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cwsUuK/btsL2H7XO6Y/A7BpvltCvEABuqajCtVXLK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cwsUuK/btsL2H7XO6Y/A7BpvltCvEABuqajCtVXLK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cwsUuK/btsL2H7XO6Y/A7BpvltCvEABuqajCtVXLK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcwsUuK%2FbtsL2H7XO6Y%2FA7BpvltCvEABuqajCtVXLK%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;377&quot; height=&quot;219&quot; data-origin-width=&quot;377&quot; data-origin-height=&quot;219&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;&amp;nbsp;&lt;/p&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-origin-width=&quot;458&quot; data-origin-height=&quot;519&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bE0nXG/btsL12Eyazr/bXMh4VAvpBbU49RHUk81Vk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bE0nXG/btsL12Eyazr/bXMh4VAvpBbU49RHUk81Vk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bE0nXG/btsL12Eyazr/bXMh4VAvpBbU49RHUk81Vk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbE0nXG%2FbtsL12Eyazr%2FbXMh4VAvpBbU49RHUk81Vk%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;458&quot; height=&quot;519&quot; data-origin-width=&quot;458&quot; data-origin-height=&quot;519&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;엔터와 탭만 눌렀더니 5초 만에 flutter 기본 실행코드가 완성됐습니다.&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;h3 data-ke-size=&quot;size23&quot;&gt;Symbol&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아직 위의 코드는 실행이 되지는 않는 상태입니다. Flutter에서 Material 디자인 위젯을 사용하려면 기본적으로 material.dart를 임포트해야 하는데 아직 Cursor에 Flutter플러그인이 설치되어 있지 않은 것 같습니다.&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;자 막혔어요. 이제 어떡할까요? 저번 글에서 사용했던 채팅을 열어서 해결해 봅시다. &quot;Command + l&quot;을 눌러서 채팅창을 열어보겠습니다.&lt;/p&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-origin-width=&quot;415&quot; data-origin-height=&quot;402&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xYDuk/btsL242W7os/FOnRHyq6UyZjEvGgt1uYG0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xYDuk/btsL242W7os/FOnRHyq6UyZjEvGgt1uYG0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xYDuk/btsL242W7os/FOnRHyq6UyZjEvGgt1uYG0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxYDuk%2FbtsL242W7os%2FFOnRHyq6UyZjEvGgt1uYG0%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;415&quot; height=&quot;402&quot; data-origin-width=&quot;415&quot; data-origin-height=&quot;402&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;채팅창에 @(symbol)을 입력하면 여러 옵션들이 뜹니다. 저는 Files를 눌러서 main.dart를 지정해 보겠습니다.&lt;/p&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-origin-width=&quot;393&quot; data-origin-height=&quot;128&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bklWY1/btsL3hgFelj/MUZvv7PzPpMEkzhOjS8Wu1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bklWY1/btsL3hgFelj/MUZvv7PzPpMEkzhOjS8Wu1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bklWY1/btsL3hgFelj/MUZvv7PzPpMEkzhOjS8Wu1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbklWY1%2FbtsL3hgFelj%2FMUZvv7PzPpMEkzhOjS8Wu1%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;393&quot; height=&quot;128&quot; data-origin-width=&quot;393&quot; data-origin-height=&quot;128&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 이렇게 main.dart 파일이 지정됩니다. 이렇게 되면 ai에게 질문할 때 해당 파일의 코드를 기반으로 질문하기 때문에 더 확실한 정보를 얻을 수 있습니다.&lt;/p&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-origin-width=&quot;382&quot; data-origin-height=&quot;719&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dRm3hv/btsL22qv0zw/MaVI0yh86dkqMdlEv3xP51/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dRm3hv/btsL22qv0zw/MaVI0yh86dkqMdlEv3xP51/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dRm3hv/btsL22qv0zw/MaVI0yh86dkqMdlEv3xP51/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdRm3hv%2FbtsL22qv0zw%2FMaVI0yh86dkqMdlEv3xP51%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;382&quot; height=&quot;719&quot; data-origin-width=&quot;382&quot; data-origin-height=&quot;719&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;&amp;nbsp;&lt;/p&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-origin-width=&quot;508&quot; data-origin-height=&quot;538&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cbki05/btsL1kFMehh/FHGfW2krSk5d85HGexsnn1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cbki05/btsL1kFMehh/FHGfW2krSk5d85HGexsnn1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cbki05/btsL1kFMehh/FHGfW2krSk5d85HGexsnn1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcbki05%2FbtsL1kFMehh%2FFHGfW2krSk5d85HGexsnn1%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;508&quot; height=&quot;538&quot; data-origin-width=&quot;508&quot; data-origin-height=&quot;538&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;또 하라는 대로 했더니 드디어 Flutter가 인식된 거 같아요. import 해주고 실행해 보겠습니다.&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;433&quot; data-origin-height=&quot;941&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/oq5Oq/btsL2H1ds4q/IhBbstvD5r55otMGBarZiK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/oq5Oq/btsL2H1ds4q/IhBbstvD5r55otMGBarZiK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/oq5Oq/btsL2H1ds4q/IhBbstvD5r55otMGBarZiK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Foq5Oq%2FbtsL2H1ds4q%2FIhBbstvD5r55otMGBarZiK%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;333&quot; height=&quot;724&quot; data-origin-width=&quot;433&quot; data-origin-height=&quot;941&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;자 이렇게 Cursor가 제공한 코드들로 실행된 화면입니다.&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;h3 data-ke-size=&quot;size23&quot;&gt;Composer&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 Composer라는 기능을 사용해 보겠습니다. 이전 글에서 잠깐 설명드렸지만 Composer는 코드에 바로 적용시켜 줍니다. &quot;Command + i&quot;를 누르면 Composer를 열 수 있습니다. 여기서도 똑같이 위에 사용한 @(symbol) 기능을 이용해서 main.dart파일의 &quot;Hello, World!&quot; 텍스트의 색상을 빨간색으로 변경해 달라고 해보겠습니다.&lt;/p&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-origin-width=&quot;1843&quot; data-origin-height=&quot;690&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/tccFv/btsL3iGG8R1/vHlwyQWhIYmTAyzHuEWKwK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/tccFv/btsL3iGG8R1/vHlwyQWhIYmTAyzHuEWKwK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/tccFv/btsL3iGG8R1/vHlwyQWhIYmTAyzHuEWKwK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FtccFv%2FbtsL3iGG8R1%2FvHlwyQWhIYmTAyzHuEWKwK%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;1843&quot; height=&quot;690&quot; data-origin-width=&quot;1843&quot; data-origin-height=&quot;690&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;Composer는 바로 코드에 적용시켜 주기 때문에 코드 부분이 바로 변경되는 모습을 볼 수 있습니다. Git등에서 볼 수 있는 변경점 같이 빨간색으로 이전코드와 초록색으로 변경된 코드를 보여줍니다. 어떤 부분이 바뀌었는지 한눈에 볼 수 있습니다. 변경된 코드를 적용하려면 &quot;Command + y&quot; 적용하지 않으려면 &quot;Command + n&quot;를 누르면 됩니다.&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;169&quot; data-origin-height=&quot;125&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/66Dcc/btsL116LVT6/9KyV8jm1kFSIXKgx4V8ptK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/66Dcc/btsL116LVT6/9KyV8jm1kFSIXKgx4V8ptK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/66Dcc/btsL116LVT6/9KyV8jm1kFSIXKgx4V8ptK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F66Dcc%2FbtsL116LVT6%2F9KyV8jm1kFSIXKgx4V8ptK%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;169&quot; height=&quot;125&quot; data-origin-width=&quot;169&quot; data-origin-height=&quot;125&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;변경된 코드를 적용하고 확인해 보면 텍스트 색상이 빨간색으로 변경된 것을 확인할 수 있습니다. 이로써 우리는 Flutter를 하나도 모르는 상태였어도 화면에 텍스트를 뿌리고 색상을 변경하는 등 간단한 코드를 작성할 수 있게 되었습니다.&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;h3 data-ke-size=&quot;size23&quot;&gt;Prompt an edit&lt;/h3&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-origin-width=&quot;452&quot; data-origin-height=&quot;221&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lOKDL/btsL2eLBjxJ/NoLbRs617005ZukbmNhX80/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lOKDL/btsL2eLBjxJ/NoLbRs617005ZukbmNhX80/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lOKDL/btsL2eLBjxJ/NoLbRs617005ZukbmNhX80/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlOKDL%2FbtsL2eLBjxJ%2FNoLbRs617005ZukbmNhX80%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;452&quot; height=&quot;221&quot; data-origin-width=&quot;452&quot; data-origin-height=&quot;221&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코드를 이렇게 드래그해 보세요. 2가지 옵션이 뜹니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Chat&lt;/b&gt; : 드래그한 코드를 챗에 붙여 넣고 사용합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Edit&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;&quot;Command + K&quot;를 눌러서 바로 Edit을 사용해 보겠습니다.&lt;/p&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-origin-width=&quot;581&quot; data-origin-height=&quot;239&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bsfb1m/btsL3i7LJR9/pKzok1hOqXNuU8oJUuAD01/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bsfb1m/btsL3i7LJR9/pKzok1hOqXNuU8oJUuAD01/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bsfb1m/btsL3i7LJR9/pKzok1hOqXNuU8oJUuAD01/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbsfb1m%2FbtsL3i7LJR9%2FpKzok1hOqXNuU8oJUuAD01%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;581&quot; height=&quot;239&quot; data-origin-width=&quot;581&quot; data-origin-height=&quot;239&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 지정한 영역 위에 창이 뜨고 해당창에 원하는 동작을 입력하면 Composer처럼 동작합니다.&lt;/p&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-origin-width=&quot;617&quot; data-origin-height=&quot;375&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cY7Gkd/btsL37keorY/ktG4CXydKaksjdDlLdbu6K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cY7Gkd/btsL37keorY/ktG4CXydKaksjdDlLdbu6K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cY7Gkd/btsL37keorY/ktG4CXydKaksjdDlLdbu6K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcY7Gkd%2FbtsL37keorY%2FktG4CXydKaksjdDlLdbu6K%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;617&quot; height=&quot;375&quot; data-origin-width=&quot;617&quot; data-origin-height=&quot;375&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;바로 코드를 수정해 주고 이전코드와 변경된 코드를 한눈에 보여줍니다. 적용하려면 &quot;Command + enter&quot; 취소하려면 &quot;Command + Backspace&quot;를 누르라고 뜨네요.&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;이 외에도 글로 작성할 수 없을 만큼 많은 기능을 제공하고 있습니다. 저의 글로 Cursor에 흥미가 생기셨다면 다른 많은 기능도 찾아보시는 게 어떠신가요?&lt;/p&gt;</description>
      <category>Flutter/기본</category>
      <category>cursor</category>
      <category>flutter</category>
      <author>주톨</author>
      <guid isPermaLink="true">https://jutole.tistory.com/163</guid>
      <comments>https://jutole.tistory.com/163#entry163comment</comments>
      <pubDate>Thu, 30 Jan 2025 09:54:15 +0900</pubDate>
    </item>
    <item>
      <title>[Flutter] Cursor로 프로젝트 세팅하기</title>
      <link>https://jutole.tistory.com/162</link>
      <description>&lt;p data-ke-size=&quot;size16&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;안녕하세요. 이번에는 현재 매우 각광받고 있는 Cursor를 사용해서 Flutter 프로젝트를 세팅 해보도록 하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&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;1.png&quot; data-origin-width=&quot;299&quot; data-origin-height=&quot;168&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cDIiVs/btsL2KDxGb1/NKit1GImVbX7b5qVA6xxY1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cDIiVs/btsL2KDxGb1/NKit1GImVbX7b5qVA6xxY1/img.png&quot; data-alt=&quot;이 커서 아닙니다..&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cDIiVs/btsL2KDxGb1/NKit1GImVbX7b5qVA6xxY1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcDIiVs%2FbtsL2KDxGb1%2FNKit1GImVbX7b5qVA6xxY1%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;299&quot; height=&quot;168&quot; data-filename=&quot;1.png&quot; data-origin-width=&quot;299&quot; data-origin-height=&quot;168&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;이 커서 아닙니다..&lt;/figcaption&gt;
&lt;/figure&gt;
&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;h3 data-ke-size=&quot;size23&quot;&gt;Cursor?&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;Cursor는&amp;nbsp;AI와&amp;nbsp;협업을&amp;nbsp;중심으로&amp;nbsp;설계된&amp;nbsp;통합&amp;nbsp;개발&amp;nbsp;환경(IDE)으로,&amp;nbsp;코드&amp;nbsp;작성,&amp;nbsp;디버깅,&amp;nbsp;수정&amp;nbsp;등&amp;nbsp;다양한&amp;nbsp;개발&amp;nbsp;작업을&amp;nbsp;AI의&amp;nbsp;도움으로&amp;nbsp;효율화할&amp;nbsp;수&amp;nbsp;있는&amp;nbsp;툴이다.&amp;nbsp;다양한&amp;nbsp;AI&amp;nbsp;모델을&amp;nbsp;지원하여&amp;nbsp;개발자들에게&amp;nbsp;혁신적인&amp;nbsp;개발&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;설치&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.cursor.com/&quot;&gt;https://www.cursor.com/&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1738186238663&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Cursor - The AI Code Editor&quot; data-og-description=&quot;Built to make you extraordinarily productive, Cursor is the best way to code with AI.&quot; data-og-host=&quot;www.cursor.com&quot; data-og-source-url=&quot;https://www.cursor.com/&quot; data-og-url=&quot;https://www.cursor.com/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/yNmAr/hyX74ijAHb/UZM9VXKx3RkAyP6QZp2YbK/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/brANU5/hyX74CCQfD/ycnL6KFIbZ1GWs6INGiMg1/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630&quot;&gt;&lt;a href=&quot;https://www.cursor.com/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.cursor.com/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/yNmAr/hyX74ijAHb/UZM9VXKx3RkAyP6QZp2YbK/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/brANU5/hyX74CCQfD/ycnL6KFIbZ1GWs6INGiMg1/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630');&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;Cursor - The AI Code Editor&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Built to make you extraordinarily productive, Cursor is the best way to code with AI.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.cursor.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;해당 사이트 접속 후 설치하시면 됩니다. 별다른 어려운 과정이 없습니다.&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;h3 data-ke-size=&quot;size23&quot;&gt;Cursor 간단 사용&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;697&quot; data-origin-height=&quot;533&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/txIvX/btsL19qkgnX/ShbrdrUrDOouFMstCKQWGk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/txIvX/btsL19qkgnX/ShbrdrUrDOouFMstCKQWGk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/txIvX/btsL19qkgnX/ShbrdrUrDOouFMstCKQWGk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FtxIvX%2FbtsL19qkgnX%2FShbrdrUrDOouFMstCKQWGk%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;522&quot; height=&quot;399&quot; data-origin-width=&quot;697&quot; data-origin-height=&quot;533&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;size18&quot;&gt;설치 후 Cursor를 실행하면 해당 화면처럼 뜹니다. 본인이 원하는 위치에 폴더하나를 만들고 해당 폴더를 열어주세요&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;660&quot; data-origin-height=&quot;485&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/wMJKY/btsL2BsYRnJ/RfpyPAkbUj20D8m5Mz8npk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/wMJKY/btsL2BsYRnJ/RfpyPAkbUj20D8m5Mz8npk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/wMJKY/btsL2BsYRnJ/RfpyPAkbUj20D8m5Mz8npk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FwMJKY%2FbtsL2BsYRnJ%2FRfpyPAkbUj20D8m5Mz8npk%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;552&quot; height=&quot;406&quot; data-origin-width=&quot;660&quot; data-origin-height=&quot;485&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&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;그러면 저처럼 이렇게 빈 화면이 뜨게 됩니다. 여기서 단축키 &quot;command + l&quot; 단축키를 눌러서 채팅창을 열어주세요.&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;391&quot; data-origin-height=&quot;760&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/clpA0d/btsL3mvxrZD/n4Irzg5P949J1R9GAuRVOK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/clpA0d/btsL3mvxrZD/n4Irzg5P949J1R9GAuRVOK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/clpA0d/btsL3mvxrZD/n4Irzg5P949J1R9GAuRVOK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FclpA0d%2FbtsL3mvxrZD%2Fn4Irzg5P949J1R9GAuRVOK%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;391&quot; height=&quot;760&quot; data-origin-width=&quot;391&quot; data-origin-height=&quot;760&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;size18&quot;&gt;채팅창을 열고 flutter 프로젝트를 생성하고 싶다고 채팅을 쳤더니 flutter 프로젝트를 생성하는 방법을 알려줍니다. 여기까지는 가장 유명한 Chatgpt도 가능한 부분입니다. 이제 Cursor가 빛을 발휘하는 개발자와 협업하는 기능 중 하나를 사용해 보겠습니다.&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;373&quot; data-origin-height=&quot;100&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bXietX/btsL3goxp43/zIkFHuCT31zySEUcC6Oox0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bXietX/btsL3goxp43/zIkFHuCT31zySEUcC6Oox0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bXietX/btsL3goxp43/zIkFHuCT31zySEUcC6Oox0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbXietX%2FbtsL3goxp43%2FzIkFHuCT31zySEUcC6Oox0%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;373&quot; height=&quot;100&quot; data-origin-width=&quot;373&quot; data-origin-height=&quot;100&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;size18&quot;&gt;채팅창에 있는 명령어에 마우스를 올려보면 &quot;Ask&quot;, &quot;Copy&quot;, &quot;Run&quot;라는 기능이 보입니다. 이 것 말고도 더 많지만 해당 코드에서는 저 3가지가 뜨네요.&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;b&gt;Ask&lt;/b&gt; : 해당 답변에 대해서 추가 질문을 할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Copy&lt;/b&gt; : 해당 코드를 복사합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Run&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;size18&quot;&gt;Run을 눌러서 프로젝트를 생성해 보세요. 그리고 추가로 2번과, 3번, 4번을 동일하게 Run을 눌러서 실행해 보세요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;465&quot; data-origin-height=&quot;124&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/y9dzh/btsL05WlKn0/8HsKSQWa6s9TduvTXPrXWK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/y9dzh/btsL05WlKn0/8HsKSQWa6s9TduvTXPrXWK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/y9dzh/btsL05WlKn0/8HsKSQWa6s9TduvTXPrXWK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fy9dzh%2FbtsL05WlKn0%2F8HsKSQWa6s9TduvTXPrXWK%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;465&quot; height=&quot;124&quot; data-origin-width=&quot;465&quot; data-origin-height=&quot;124&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;저는 4번 과정 Ios시뮬레이터로 실행하는 와중에 에러가 발생했습니다. 자 이렇게 터미널에서 에러가 발생할 경우 Cursor는 어떻게 우리와 협업을 할까요?&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;752&quot; data-origin-height=&quot;163&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cIWKXj/btsL3YOtQjj/tSCz779BT6D40oK1oABrP0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cIWKXj/btsL3YOtQjj/tSCz779BT6D40oK1oABrP0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cIWKXj/btsL3YOtQjj/tSCz779BT6D40oK1oABrP0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcIWKXj%2FbtsL3YOtQjj%2FtSCz779BT6D40oK1oABrP0%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;752&quot; height=&quot;163&quot; data-origin-width=&quot;752&quot; data-origin-height=&quot;163&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;size18&quot;&gt;에러가 발생한 문구를 클릭하면 오른쪽에 &quot;Add to Composer&quot;, &quot;Add to Chat&quot;이라는 버튼들이 뜨게 됩니다.&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;b&gt;Add to Composer&lt;/b&gt; : 발생한 오류의 해결 방법을 찾아 바로 적용한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Add to Chat&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;size18&quot;&gt;저는 Add to Chat을 눌러서 해결 방법을 찾아보겠습니다. 해당 버튼을 누르면 &quot;Command + l&quot; 단축키로 열었던 채팅창에 해당 에러가 자동으로 붙여 넣기가 됩니다. 이제 추가적인 요구사항과 함께 찾아보도록 합시다.&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;figure data-ke-type=&quot;image&quot; data-ke-style=&quot;alignCenter&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;
&lt;figcaption style=&quot;display: none;&quot;&gt;&lt;/figcaption&gt;
&lt;figcaption style=&quot;display: none;&quot;&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;384&quot; data-origin-height=&quot;925&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/o5ytm/btsL2x5eemj/tbDYpZibCF0zwbvi09SHik/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/o5ytm/btsL2x5eemj/tbDYpZibCF0zwbvi09SHik/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/o5ytm/btsL2x5eemj/tbDYpZibCF0zwbvi09SHik/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fo5ytm%2FbtsL2x5eemj%2FtbDYpZibCF0zwbvi09SHik%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;384&quot; height=&quot;925&quot; data-origin-width=&quot;384&quot; data-origin-height=&quot;925&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;제시해 준 방법대로 진행합니다. 저는 시뮬레이터를 실행한 다음 Flutter 앱을 실행했지만 계속 에러가 발생했습니다. 그래서 추가로 확인할 사항들에 있는 flutter doctor 명령어를 실행했습니다.&lt;/p&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-origin-width=&quot;755&quot; data-origin-height=&quot;324&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Q4hVE/btsL3fQH1lU/K6K4WIATtUXr8X5dy6AyNk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Q4hVE/btsL3fQH1lU/K6K4WIATtUXr8X5dy6AyNk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Q4hVE/btsL3fQH1lU/K6K4WIATtUXr8X5dy6AyNk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FQ4hVE%2FbtsL3fQH1lU%2FK6K4WIATtUXr8X5dy6AyNk%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;755&quot; height=&quot;324&quot; data-origin-width=&quot;755&quot; data-origin-height=&quot;324&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Xcode 몇몇 설정이 안 되어있어 문제 되는 거 같습니다. 해당 설정도 &quot;Add to Chat&quot;으로 물어보고 해결해 보겠습니다.&lt;/p&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-origin-width=&quot;375&quot; data-origin-height=&quot;1055&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dM6Nwv/btsL2aQlkDy/YVdu8EtF3KIcRkpLrkr3E0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dM6Nwv/btsL2aQlkDy/YVdu8EtF3KIcRkpLrkr3E0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dM6Nwv/btsL2aQlkDy/YVdu8EtF3KIcRkpLrkr3E0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdM6Nwv%2FbtsL2aQlkDy%2FYVdu8EtF3KIcRkpLrkr3E0%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;375&quot; height=&quot;1055&quot; data-origin-width=&quot;375&quot; data-origin-height=&quot;1055&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;계속 제시해 주는 방법으로 진행하고 에러 뜨면 물어보고 해결하고 반복하였습니다.&amp;nbsp;&lt;/p&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-origin-width=&quot;2540&quot; data-origin-height=&quot;1096&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bOhG31/btsL12Scbkx/v1eQ8DHe4RbnlQM97rkxHK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bOhG31/btsL12Scbkx/v1eQ8DHe4RbnlQM97rkxHK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bOhG31/btsL12Scbkx/v1eQ8DHe4RbnlQM97rkxHK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbOhG31%2FbtsL12Scbkx%2Fv1eQ8DHe4RbnlQM97rkxHK%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;709&quot; height=&quot;306&quot; data-origin-width=&quot;2540&quot; data-origin-height=&quot;1096&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;결국 Ios 시뮬레이터로 flutter 실행을 성공적으로 마무리했습니다!! 개인마다 뜨는 오류는 다양각색이지만 계속 물어보면서 제시하는 방법대로 하다 보면 실행될 것입니다. 다음 글에서는 Cursor를 사용해서 직접 개발해 보겠습니다.&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://jutole.tistory.com/163&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://jutole.tistory.com/163&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1738198485410&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;[Flutter] Cursor로 간단하게 개발하기&quot; data-og-description=&quot;https://jutole.tistory.com/162&amp;nbsp;[Flutter] Cursor로 프로젝트 세팅하기안녕하세요. 이번에는 현재 매우 각광받고 있는 Cursor를 사용해서 Flutter 프로젝트를 세팅 해보도록 하겠습니다.&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Cursor?Cursor는&amp;nbsp;AI&quot; data-og-host=&quot;jutole.tistory.com&quot; data-og-source-url=&quot;https://jutole.tistory.com/163&quot; data-og-url=&quot;https://jutole.tistory.com/163&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/cJKKJh/hyX71eRbXb/jopMvfP8ZJ3HPHtlPphWc0/img.png?width=265&amp;amp;height=164&amp;amp;face=0_0_265_164,https://scrap.kakaocdn.net/dn/7Zj3H/hyX7UUjLTJ/Pk15Ety9FbKrr9W1DKWBgk/img.png?width=265&amp;amp;height=164&amp;amp;face=0_0_265_164,https://scrap.kakaocdn.net/dn/XiztQ/hyX7R4nq2C/qsIKwnbPZKTvHjhKBCQLk1/img.png?width=1843&amp;amp;height=690&amp;amp;face=0_0_1843_690&quot;&gt;&lt;a href=&quot;https://jutole.tistory.com/163&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://jutole.tistory.com/163&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/cJKKJh/hyX71eRbXb/jopMvfP8ZJ3HPHtlPphWc0/img.png?width=265&amp;amp;height=164&amp;amp;face=0_0_265_164,https://scrap.kakaocdn.net/dn/7Zj3H/hyX7UUjLTJ/Pk15Ety9FbKrr9W1DKWBgk/img.png?width=265&amp;amp;height=164&amp;amp;face=0_0_265_164,https://scrap.kakaocdn.net/dn/XiztQ/hyX7R4nq2C/qsIKwnbPZKTvHjhKBCQLk1/img.png?width=1843&amp;amp;height=690&amp;amp;face=0_0_1843_690');&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;[Flutter] Cursor로 간단하게 개발하기&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;https://jutole.tistory.com/162&amp;nbsp;[Flutter] Cursor로 프로젝트 세팅하기안녕하세요. 이번에는 현재 매우 각광받고 있는 Cursor를 사용해서 Flutter 프로젝트를 세팅 해보도록 하겠습니다.&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Cursor?Cursor는&amp;nbsp;AI&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;jutole.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;
&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>Flutter/기본</category>
      <category>cursor</category>
      <category>flutter</category>
      <author>주톨</author>
      <guid isPermaLink="true">https://jutole.tistory.com/162</guid>
      <comments>https://jutole.tistory.com/162#entry162comment</comments>
      <pubDate>Thu, 30 Jan 2025 08:25:17 +0900</pubDate>
    </item>
    <item>
      <title>[Flutter] Web Image Cors 문제</title>
      <link>https://jutole.tistory.com/161</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;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;439&quot; data-origin-height=&quot;501&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Nb8EX/btsLGZ9vcS5/CaiTGo3ZzKO84LkCFhGx90/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Nb8EX/btsLGZ9vcS5/CaiTGo3ZzKO84LkCFhGx90/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Nb8EX/btsLGZ9vcS5/CaiTGo3ZzKO84LkCFhGx90/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FNb8EX%2FbtsLGZ9vcS5%2FCaiTGo3ZzKO84LkCFhGx90%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;439&quot; height=&quot;501&quot; data-origin-width=&quot;439&quot; data-origin-height=&quot;501&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;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;이런 식으로 web으로 빌드해서 실행해 보면 네트워크 이미지가 안 보이는 문제가 발생하는 경우가 있습니다. 이는 Cors문제로 브라우저에서 그리지 않는 문제입니다. 이를 강제로 해결하기 위한 방법으론&amp;nbsp;&lt;/b&gt;&lt;b&gt;Flutter Web은 기본적으로 두 가지 렌더링 엔진을 사용합니다: CanvasKit과 HTML 렌더러입니다. Flutter Web의 기본 렌더러는 CanvasKit입니다. CanvasKit은 WebAssembly 기반의 렌더러로, 더 나은 성능과 그래픽 효과를 제공하지만, 일부 경우 네트워크 리소스를 제대로 처리하지 못해 위와 같은 문제가 발생합니다.&lt;/b&gt;&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;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;기본 렌더러 설정을 HTML로&amp;nbsp;&lt;/b&gt;&lt;/h2&gt;
&lt;pre id=&quot;code_1736325177860&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;script type=&quot;text/javascript&quot;&amp;gt;
    window.flutterWebRenderer = &quot;html&quot;;
&amp;lt;/script&amp;gt;&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;size18&quot;&gt;&lt;b&gt;해당 코드는 Flutter&amp;nbsp;Web에서&amp;nbsp;사용하는&amp;nbsp;렌더러를&amp;nbsp;CanvasKit에서&amp;nbsp;HTML로&amp;nbsp;강제로&amp;nbsp;변경하는&amp;nbsp;역할을&amp;nbsp;합니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;724&quot; data-origin-height=&quot;234&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/MDZNF/btsLGZuNYZB/sy4zu9FEgNkfdUsvIo1iQK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/MDZNF/btsLGZuNYZB/sy4zu9FEgNkfdUsvIo1iQK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/MDZNF/btsLGZuNYZB/sy4zu9FEgNkfdUsvIo1iQK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FMDZNF%2FbtsLGZuNYZB%2Fsy4zu9FEgNkfdUsvIo1iQK%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;724&quot; height=&quot;234&quot; data-origin-width=&quot;724&quot; data-origin-height=&quot;234&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;size18&quot;&gt;&lt;b&gt;index.html 파일 body태그 안에 붙여 넣고 확인해 보시면 이미지가 잘 나오는 것을 확인할 수 있습니다.&lt;br /&gt;&lt;/b&gt;&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;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;3.27이상 버전에서는 안됩니다.&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Flutter 3.27 이상 버전에서부터는 html 랜더링 방식이 deprecate가 되어서 더 이상 지원하지 않는 방법입니다. 해당 코드는 동작하지 않으니 지우셔도 됩니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Flutter/오류해결</category>
      <category>flutter</category>
      <author>주톨</author>
      <guid isPermaLink="true">https://jutole.tistory.com/161</guid>
      <comments>https://jutole.tistory.com/161#entry161comment</comments>
      <pubDate>Wed, 8 Jan 2025 17:36:48 +0900</pubDate>
    </item>
    <item>
      <title>[Flutter] Google Login 구현</title>
      <link>https://jutole.tistory.com/160</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;&lt;a href=&quot;https://jutole.tistory.com/159&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://jutole.tistory.com/159&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1728493751340&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;[Flutter] Google Login 설정 -  feat.Firebase&quot; data-og-description=&quot;시작에 앞서 Firebase 기본 설정은 맞추셔야 합니다.&amp;nbsp;&amp;nbsp;1. Firebase 로그인 제공업체 추가&amp;nbsp;Authentication -&amp;gt; 로그인 방법 -&amp;gt; 새 제공업체 추가 -&amp;gt; Google 선택&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;중요 메시지를 확인하고 사용 설정을 선택&quot; data-og-host=&quot;jutole.tistory.com&quot; data-og-source-url=&quot;https://jutole.tistory.com/159&quot; data-og-url=&quot;https://jutole.tistory.com/159&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bipvtY/hyXhJL4X3f/EBX8p5w1Wx6OtYPKR7UmO0/img.png?width=177&amp;amp;height=182&amp;amp;face=0_0_177_182,https://scrap.kakaocdn.net/dn/cLMItQ/hyXhK5h5r8/qeKuJAp5FVDOkhYaZygAd1/img.png?width=177&amp;amp;height=182&amp;amp;face=0_0_177_182,https://scrap.kakaocdn.net/dn/BbiiU/hyXhWSbNvp/1KuC4NaC04nGI3kBcquh5k/img.png?width=991&amp;amp;height=731&amp;amp;face=0_0_991_731&quot;&gt;&lt;a href=&quot;https://jutole.tistory.com/159&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://jutole.tistory.com/159&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bipvtY/hyXhJL4X3f/EBX8p5w1Wx6OtYPKR7UmO0/img.png?width=177&amp;amp;height=182&amp;amp;face=0_0_177_182,https://scrap.kakaocdn.net/dn/cLMItQ/hyXhK5h5r8/qeKuJAp5FVDOkhYaZygAd1/img.png?width=177&amp;amp;height=182&amp;amp;face=0_0_177_182,https://scrap.kakaocdn.net/dn/BbiiU/hyXhWSbNvp/1KuC4NaC04nGI3kBcquh5k/img.png?width=991&amp;amp;height=731&amp;amp;face=0_0_991_731');&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;[Flutter] Google Login 설정 - feat.Firebase&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;시작에 앞서 Firebase 기본 설정은 맞추셔야 합니다.&amp;nbsp;&amp;nbsp;1. Firebase 로그인 제공업체 추가&amp;nbsp;Authentication -&amp;gt; 로그인 방법 -&amp;gt; 새 제공업체 추가 -&amp;gt; Google 선택&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;중요 메시지를 확인하고 사용 설정을 선택&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;jutole.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;
&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;h3 data-ke-size=&quot;size23&quot;&gt;1. google_sign_in 패키지 설치&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://pub.dev/packages/google_sign_in&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://pub.dev/packages/google_sign_in&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1728493822208&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;google_sign_in | Flutter package&quot; data-og-description=&quot;Flutter plugin for Google Sign-In, a secure authentication system for signing in with a Google account.&quot; data-og-host=&quot;pub.dev&quot; data-og-source-url=&quot;https://pub.dev/packages/google_sign_in&quot; data-og-url=&quot;https://pub.dev/packages/google_sign_in&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/tmFWl/hyXhTVs1tB/sWoBVwpjYOkokt8uHwPXb0/img.png?width=1280&amp;amp;height=640&amp;amp;face=0_0_1280_640,https://scrap.kakaocdn.net/dn/cPaDvq/hyXeefWoz6/HLbM4Lj1G5B6vHpCaJP2mK/img.png?width=1280&amp;amp;height=640&amp;amp;face=0_0_1280_640&quot;&gt;&lt;a href=&quot;https://pub.dev/packages/google_sign_in&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://pub.dev/packages/google_sign_in&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/tmFWl/hyXhTVs1tB/sWoBVwpjYOkokt8uHwPXb0/img.png?width=1280&amp;amp;height=640&amp;amp;face=0_0_1280_640,https://scrap.kakaocdn.net/dn/cPaDvq/hyXeefWoz6/HLbM4Lj1G5B6vHpCaJP2mK/img.png?width=1280&amp;amp;height=640&amp;amp;face=0_0_1280_640');&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;google_sign_in | Flutter package&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Flutter plugin for Google Sign-In, a secure authentication system for signing in with a Google account.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;pub.dev&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2.&amp;nbsp; firebase_auth 패키지 설치&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://pub.dev/packages/firebase_auth&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://pub.dev/packages/firebase_auth&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1728499421974&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;firebase_auth | Flutter package&quot; data-og-description=&quot;Flutter plugin for Firebase Auth, enabling authentication using passwords, phone numbers and identity providers like Google, Facebook and Twitter.&quot; data-og-host=&quot;pub.dev&quot; data-og-source-url=&quot;https://pub.dev/packages/firebase_auth&quot; data-og-url=&quot;https://pub.dev/packages/firebase_auth&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/cmsgm7/hyXhRQSVjp/k4qQwYBlSbnotNETyDRtM0/img.png?width=1280&amp;amp;height=640&amp;amp;face=0_0_1280_640,https://scrap.kakaocdn.net/dn/h8UKO/hyXehKsIoI/2mXe0YBZ4epzppQBWa4RIK/img.png?width=1280&amp;amp;height=640&amp;amp;face=0_0_1280_640&quot;&gt;&lt;a href=&quot;https://pub.dev/packages/firebase_auth&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://pub.dev/packages/firebase_auth&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/cmsgm7/hyXhRQSVjp/k4qQwYBlSbnotNETyDRtM0/img.png?width=1280&amp;amp;height=640&amp;amp;face=0_0_1280_640,https://scrap.kakaocdn.net/dn/h8UKO/hyXehKsIoI/2mXe0YBZ4epzppQBWa4RIK/img.png?width=1280&amp;amp;height=640&amp;amp;face=0_0_1280_640');&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;firebase_auth | Flutter package&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Flutter plugin for Firebase Auth, enabling authentication using passwords, phone numbers and identity providers like Google, Facebook and Twitter.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;pub.dev&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. 구현&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Google Login을 하기 위한 준비가 끝났습니다.&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;span style=&quot;text-align: start;&quot;&gt;구현 예시 코드입니다.)&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1728499475672&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import 'package:google_sign_in/google_sign_in.dart';

Future&amp;lt;UserCredential&amp;gt; signInWithGoogle() async {
  // Trigger the authentication flow
  final GoogleSignInAccount? googleUser = await GoogleSignIn().signIn();

  // Obtain the auth details from the request
  final GoogleSignInAuthentication? googleAuth = await googleUser?.authentication;

  // Create a new credential
  final credential = GoogleAuthProvider.credential(
    accessToken: googleAuth?.accessToken,
    idToken: googleAuth?.idToken,
  );

  // Once signed in, return the UserCredential
  return await FirebaseAuth.instance.signInWithCredential(credential);
}&lt;/code&gt;&lt;/pre&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;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;GoogleSignIn().signIn()&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;구글 로그인 화면을 열고 로그인을 진행합니다. 사용자가 로그인을 진행하지 않고 복귀 시에는 null을 반환합니다. 사용자가 로그인을 진행하였으면 아래와 같은 정보들을 가지고 옵니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;360&quot; data-origin-height=&quot;207&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/oplFt/btsJ0PePhpB/7s3PjRAkfzk0WxhZqNfUf1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/oplFt/btsJ0PePhpB/7s3PjRAkfzk0WxhZqNfUf1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/oplFt/btsJ0PePhpB/7s3PjRAkfzk0WxhZqNfUf1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FoplFt%2FbtsJ0PePhpB%2F7s3PjRAkfzk0WxhZqNfUf1%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;360&quot; height=&quot;207&quot; data-origin-width=&quot;360&quot; data-origin-height=&quot;207&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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;googleUser.authentication&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;로그인으로 얻은 정보를 가지고 *idToken과 accessToken*을 받아오기 위한 작업입니다. 해당 토큰으로 Google&amp;nbsp;서비스와&amp;nbsp;상호작용할&amp;nbsp;수&amp;nbsp;있도록&amp;nbsp;하는&amp;nbsp;중요한&amp;nbsp;단계입니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;GoogleAuthProvider.credential&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;Google에서 받은 토큰을 가지고 Firebase에서 사용할 수 있도록 변환하는 과정입니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;FirebaseAuth.instance.signInWithCredential&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;최종적으로 Firebase에서 사용자를 로그인 처리하고, 성공 시 해당 사용자의 정보를 가져옵니다.&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;h3 data-ke-size=&quot;size23&quot;&gt;4. 확인&lt;/h3&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-origin-width=&quot;1633&quot; data-origin-height=&quot;524&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cd4b35/btsJZTCfgCx/KIls0ufxxOhAQh5kw9Dfxk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cd4b35/btsJZTCfgCx/KIls0ufxxOhAQh5kw9Dfxk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cd4b35/btsJZTCfgCx/KIls0ufxxOhAQh5kw9Dfxk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcd4b35%2FbtsJZTCfgCx%2FKIls0ufxxOhAQh5kw9Dfxk%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;729&quot; height=&quot;234&quot; data-origin-width=&quot;1633&quot; data-origin-height=&quot;524&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;로그인을 성공하고 나면 Firebase에서 위에 사진처럼 SocialLogin 한 유저를 확인할 수 있습니다.&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>Flutter/SNS Login</category>
      <category>flutter</category>
      <category>googleLogin</category>
      <author>주톨</author>
      <guid isPermaLink="true">https://jutole.tistory.com/160</guid>
      <comments>https://jutole.tistory.com/160#entry160comment</comments>
      <pubDate>Thu, 10 Oct 2024 04:24:10 +0900</pubDate>
    </item>
    <item>
      <title>[Flutter] Google Login 설정 -  feat.Firebase</title>
      <link>https://jutole.tistory.com/159</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;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;시작에 앞서 Firebase 기본 설정은 맞추셔야 합니다.&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;h3 data-ke-size=&quot;size23&quot;&gt;1. Firebase 로그인 제공업체 추가&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1240&quot; data-origin-height=&quot;370&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/o6QAw/btsJZmSpL42/aqpjg7A1hMe5V0oAnRrskK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/o6QAw/btsJZmSpL42/aqpjg7A1hMe5V0oAnRrskK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/o6QAw/btsJZmSpL42/aqpjg7A1hMe5V0oAnRrskK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fo6QAw%2FbtsJZmSpL42%2Faqpjg7A1hMe5V0oAnRrskK%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;1240&quot; height=&quot;370&quot; data-origin-width=&quot;1240&quot; data-origin-height=&quot;370&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;Authentication -&amp;gt; 로그인 방법 -&amp;gt; 새 제공업체 추가 -&amp;gt; Google 선택&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1004&quot; data-origin-height=&quot;617&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/QYfAT/btsJZNI0v0z/P98s2iohaRwrd6rtZBlk90/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/QYfAT/btsJZNI0v0z/P98s2iohaRwrd6rtZBlk90/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/QYfAT/btsJZNI0v0z/P98s2iohaRwrd6rtZBlk90/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FQYfAT%2FbtsJZNI0v0z%2FP98s2iohaRwrd6rtZBlk90%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;1004&quot; height=&quot;617&quot; data-origin-width=&quot;1004&quot; data-origin-height=&quot;617&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;중요 메시지를 확인하고 사용 설정을 선택하시고 저장을 눌러주세요.&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;h3 data-ke-size=&quot;size23&quot;&gt;2.&amp;nbsp; SHA 인증서 지문 추가&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1번 과정에서 *중요* 작업을 해야 합니다.&lt;/p&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-origin-width=&quot;991&quot; data-origin-height=&quot;731&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bc177c/btsJYETSKjv/nARdpDLstxwrCT0RKBDdD1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bc177c/btsJYETSKjv/nARdpDLstxwrCT0RKBDdD1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bc177c/btsJYETSKjv/nARdpDLstxwrCT0RKBDdD1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbc177c%2FbtsJYETSKjv%2FnARdpDLstxwrCT0RKBDdD1%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;731&quot; data-origin-width=&quot;991&quot; data-origin-height=&quot;731&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;Firebase -&amp;gt; 프로젝트 설정 -&amp;gt; 내 앱 -&amp;gt; Android -&amp;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;a href=&quot;https://developers.google.com/android/guides/client-auth&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://developers.google.com/android/guides/client-auth&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1728486261612&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;클라이언트 인증 &amp;nbsp;|&amp;nbsp; Google Play services &amp;nbsp;|&amp;nbsp; Google for Developers&quot; data-og-description=&quot;이 페이지는 Cloud Translation API를 통해 번역되었습니다. 클라이언트 인증 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요. 특정 Google Play 서비스 (예: Google 로그&quot; data-og-host=&quot;developers.google.com&quot; data-og-source-url=&quot;https://developers.google.com/android/guides/client-auth&quot; data-og-url=&quot;https://developers.google.com/android/guides/client-auth?hl=ko&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/Xgr9W/hyXhWxSyHy/MzYmq7JSqxL76hnYqwIZ8K/img.png?width=1200&amp;amp;height=675&amp;amp;face=0_0_1200_675&quot;&gt;&lt;a href=&quot;https://developers.google.com/android/guides/client-auth&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://developers.google.com/android/guides/client-auth&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/Xgr9W/hyXhWxSyHy/MzYmq7JSqxL76hnYqwIZ8K/img.png?width=1200&amp;amp;height=675&amp;amp;face=0_0_1200_675');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;클라이언트 인증 &amp;nbsp;|&amp;nbsp; Google Play services &amp;nbsp;|&amp;nbsp; Google for Developers&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;이 페이지는 Cloud Translation API를 통해 번역되었습니다. 클라이언트 인증 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요. 특정 Google Play 서비스 (예: Google 로그&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;developers.google.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;디지털 지문을 찾는 방법은 위 사이트에 설명되어 있습니다.&lt;/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;SHA-1, SHA-256 둘 다 추가해 주시면 됩니다.&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;h3 data-ke-size=&quot;size23&quot;&gt;3.&amp;nbsp; IOS Client Id 추가&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;974&quot; data-origin-height=&quot;845&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c1fCe5/btsJZa5KdzY/oWyxtU3XRR31WqKfEpzJNK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c1fCe5/btsJZa5KdzY/oWyxtU3XRR31WqKfEpzJNK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c1fCe5/btsJZa5KdzY/oWyxtU3XRR31WqKfEpzJNK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc1fCe5%2FbtsJZa5KdzY%2FoWyxtU3XRR31WqKfEpzJNK%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;810&quot; height=&quot;703&quot; data-origin-width=&quot;974&quot; data-origin-height=&quot;845&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;Firebase -&amp;gt; 프로젝트 설정 -&amp;gt; 내 앱 -&amp;gt; iOS -&amp;gt; GoogleService-Info.plist 파일을 다운로드하여 줍니다.&lt;/p&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-origin-width=&quot;479&quot; data-origin-height=&quot;45&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/wOGed/btsJZ8lLcbv/v0V2rkyZM8G6pkJMovNO01/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/wOGed/btsJZ8lLcbv/v0V2rkyZM8G6pkJMovNO01/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/wOGed/btsJZ8lLcbv/v0V2rkyZM8G6pkJMovNO01/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FwOGed%2FbtsJZ8lLcbv%2Fv0V2rkyZM8G6pkJMovNO01%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;479&quot; height=&quot;45&quot; data-origin-width=&quot;479&quot; data-origin-height=&quot;45&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 파일을 열어서 CLIENT_ID를 복사하고 프로젝트 root폴더 -&amp;gt; ios -&amp;gt; Runner -&amp;gt; Info.plist에 아래처럼 추가해 줍니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;554&quot; data-origin-height=&quot;117&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/btA3Te/btsJYWmpr1z/AfPmVAphkahDn1mPMIdLKK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/btA3Te/btsJYWmpr1z/AfPmVAphkahDn1mPMIdLKK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/btA3Te/btsJYWmpr1z/AfPmVAphkahDn1mPMIdLKK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbtA3Te%2FbtsJYWmpr1z%2FAfPmVAphkahDn1mPMIdLKK%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;554&quot; height=&quot;117&quot; data-origin-width=&quot;554&quot; data-origin-height=&quot;117&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;pre id=&quot;code_1728492630997&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;key&amp;gt;GIDClientID&amp;lt;/key&amp;gt;
&amp;lt;string&amp;gt;2602rla9aje8.apps.googleusercontent.com&amp;lt;/string&amp;gt;&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;h3 data-ke-size=&quot;size23&quot;&gt;4. IOS URL Schemes 추가&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번에는 GoogleService-Info.plist 해당 파일에서 REVERSED_CLIENT_ID를 복사하고 3번과 똑같이 Info.plist에 추가해 줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1728493378307&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;key&amp;gt;CFBundleURLTypes&amp;lt;/key&amp;gt;
&amp;lt;array&amp;gt;
    &amp;lt;dict&amp;gt;
        &amp;lt;key&amp;gt;CFBundleTypeRole&amp;lt;/key&amp;gt;
        &amp;lt;string&amp;gt;Editor&amp;lt;/string&amp;gt;
        &amp;lt;key&amp;gt;CFBundleURLSchemes&amp;lt;/key&amp;gt;
        &amp;lt;array&amp;gt;
            &amp;lt;string&amp;gt;[Your REVERSED_CLIENT_ID]&amp;lt;/string&amp;gt;
        &amp;lt;/array&amp;gt;
    &amp;lt;/dict&amp;gt;
&amp;lt;/array&amp;gt;&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;전부 복사해서 REVERSED_CLIENT_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;h3 data-ke-size=&quot;size23&quot;&gt;5. 구현&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://jutole.tistory.com/160&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://jutole.tistory.com/160&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1728501880266&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;[Flutter] Google Login 구현&quot; data-og-description=&quot;https://jutole.tistory.com/159 로그인 방법 -&amp;gt; 새 제공업체 추가 -&amp;gt; Google 선택&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;중요 메시지를 확인하고 사용 설정을 선택&amp;quot; data-og-host=&amp;quot;jutole.tistory.com&amp;quot; data-og-source-url=&amp;quot;https://jutole.tistory.com/159&amp;quot; data-og-url=&amp;quot;&quot; data-og-host=&quot;jutole.tistory.com&quot; data-og-source-url=&quot;https://jutole.tistory.com/160&quot; data-og-url=&quot;https://jutole.tistory.com/160&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bhFY8Q/hyXhNAW2Tm/7zukSjcZwgtZEI38FhlKHk/img.png?width=177&amp;amp;height=182&amp;amp;face=0_0_177_182,https://scrap.kakaocdn.net/dn/bFYUyx/hyXhTuoNV6/eLkx2InyJFjvqvSB8EjIV0/img.png?width=177&amp;amp;height=182&amp;amp;face=0_0_177_182,https://scrap.kakaocdn.net/dn/3g63l/hyXd7VpO8R/5J6XS5pQW8G2CPSkPKCEiK/img.png?width=1633&amp;amp;height=524&amp;amp;face=0_0_1633_524&quot;&gt;&lt;a href=&quot;https://jutole.tistory.com/160&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://jutole.tistory.com/160&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bhFY8Q/hyXhNAW2Tm/7zukSjcZwgtZEI38FhlKHk/img.png?width=177&amp;amp;height=182&amp;amp;face=0_0_177_182,https://scrap.kakaocdn.net/dn/bFYUyx/hyXhTuoNV6/eLkx2InyJFjvqvSB8EjIV0/img.png?width=177&amp;amp;height=182&amp;amp;face=0_0_177_182,https://scrap.kakaocdn.net/dn/3g63l/hyXd7VpO8R/5J6XS5pQW8G2CPSkPKCEiK/img.png?width=1633&amp;amp;height=524&amp;amp;face=0_0_1633_524');&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;[Flutter] Google Login 구현&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;https://jutole.tistory.com/159 로그인 방법 -&amp;gt; 새 제공업체 추가 -&amp;gt; Google 선택&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;중요 메시지를 확인하고 사용 설정을 선택&quot; data-og-host=&quot;jutole.tistory.com&quot; data-og-source-url=&quot;https://jutole.tistory.com/159&quot; data-og-url=&quot;&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;jutole.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;
&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>Flutter/SNS Login</category>
      <category>firebasegooglelogin</category>
      <category>flutter</category>
      <category>googleLogin</category>
      <author>주톨</author>
      <guid isPermaLink="true">https://jutole.tistory.com/159</guid>
      <comments>https://jutole.tistory.com/159#entry159comment</comments>
      <pubDate>Thu, 10 Oct 2024 02:07:17 +0900</pubDate>
    </item>
    <item>
      <title>[Apple Login] 비공개 이메일로 메일 발송 안될 때</title>
      <link>https://jutole.tistory.com/158</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;Email Source 추가&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일반적으로 사용자의 이메일로 메일을 보내거나 하는 이벤트는 정상적으로 이루어집니다. 하지만 AppleLogin에서 사용자가 *이메일 가리기* 기능을 선택해 비공개 이메일로 설정되어 비공개 이메일로 메일을 보내면 정상적으로 메일이 가지 않습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일반 이메일 : &lt;a href=&quot;mailto:jutoleofficial@gmail.com&quot;&gt;jutoleofficial@gmail.com&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비공개 이메일 : &lt;a href=&quot;mailto:ABCDEFG@privaterelay.appleid.com&quot;&gt;ABCDEFG@privaterelay.appleid.com&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;&lt;a href=&quot;https://developer.apple.com/account/resources/services/list&quot;&gt;https://developer.apple.com/account/resources/services/list&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1727635349686&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;로그인 - Apple&quot; data-og-description=&quot;&quot; data-og-host=&quot;idmsa.apple.com&quot; data-og-source-url=&quot;https://developer.apple.com/account/resources/services/list&quot; data-og-url=&quot;https://idmsa.apple.com/IDMSWebAuth/signin?appIdKey=891bd3417a7776362562d2197f89480a8547b108fd934911bcbea0110d07f757&amp;amp;path=%2Faccount%2Fresources%2Fservices%2Flist&amp;amp;rv=1&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://developer.apple.com/account/resources/services/list&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://developer.apple.com/account/resources/services/list&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;로그인 - Apple&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;idmsa.apple.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 상황에서 해결 방법은 위에 사이트를 들어가서 *Sign in With Apple for Email Communication* -&amp;gt; *Configure* -&amp;gt; *Email Sources* 추가 버튼을 눌러줍니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;532&quot; data-origin-height=&quot;595&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cjjyHy/btsJQlsxNDo/D8C4JEG2mJA13CGh7EjCT1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cjjyHy/btsJQlsxNDo/D8C4JEG2mJA13CGh7EjCT1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cjjyHy/btsJQlsxNDo/D8C4JEG2mJA13CGh7EjCT1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcjjyHy%2FbtsJQlsxNDo%2FD8C4JEG2mJA13CGh7EjCT1%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;477&quot; height=&quot;533&quot; data-origin-width=&quot;532&quot; data-origin-height=&quot;595&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러면 위와 같은 창이 뜨는데 *Domains and Subdomains*에 메일을 보낼 domain을 입력하고 저장하면 됩니다.&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;* gmail.com 같은 도메인은 추가도 안되고 발송도 안 되는 것 같습니다.&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;</description>
      <category>자유로운 글</category>
      <author>주톨</author>
      <guid isPermaLink="true">https://jutole.tistory.com/158</guid>
      <comments>https://jutole.tistory.com/158#entry158comment</comments>
      <pubDate>Mon, 30 Sep 2024 03:42:42 +0900</pubDate>
    </item>
    <item>
      <title>[Flutter] Apple Login 심화 구현 - Ios App</title>
      <link>https://jutole.tistory.com/157</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://jutole.tistory.com/156&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://jutole.tistory.com/156&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1727630461832&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;[Flutter] Apple Login 구현 - Ios App&quot; data-og-description=&quot;설정이 안 된 분은 아래글을 통해 설정을 하고 와주세요.&amp;nbsp;https://jutole.tistory.com/154&amp;nbsp;[Flutter] Apple Login 설정 - Ios AppIos App 환경에서 apple 로그인을 하기 위한 설정 입니다.&amp;nbsp;&amp;nbsp;&amp;nbsp;1.&amp;nbsp; App IDs 등록&amp;nbsp;&amp;nbsp;&amp;nbsp;이러&quot; data-og-host=&quot;jutole.tistory.com&quot; data-og-source-url=&quot;https://jutole.tistory.com/156&quot; data-og-url=&quot;https://jutole.tistory.com/156&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/cktmU0/hyXaC1jcEI/osw4M3k61hbzP6xkZB9rn1/img.png?width=177&amp;amp;height=182&amp;amp;face=0_0_177_182,https://scrap.kakaocdn.net/dn/db57A1/hyXaBafrob/9LpKnJMoxAgvQ1PK80kQwk/img.png?width=177&amp;amp;height=182&amp;amp;face=0_0_177_182,https://scrap.kakaocdn.net/dn/bHhFTd/hyXaua6hwh/s5BghrRTx4u844RddoNkK1/img.png?width=687&amp;amp;height=919&amp;amp;face=0_0_687_919&quot;&gt;&lt;a href=&quot;https://jutole.tistory.com/156&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://jutole.tistory.com/156&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/cktmU0/hyXaC1jcEI/osw4M3k61hbzP6xkZB9rn1/img.png?width=177&amp;amp;height=182&amp;amp;face=0_0_177_182,https://scrap.kakaocdn.net/dn/db57A1/hyXaBafrob/9LpKnJMoxAgvQ1PK80kQwk/img.png?width=177&amp;amp;height=182&amp;amp;face=0_0_177_182,https://scrap.kakaocdn.net/dn/bHhFTd/hyXaua6hwh/s5BghrRTx4u844RddoNkK1/img.png?width=687&amp;amp;height=919&amp;amp;face=0_0_687_919');&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;[Flutter] Apple Login 구현 - Ios App&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;설정이 안 된 분은 아래글을 통해 설정을 하고 와주세요.&amp;nbsp;https://jutole.tistory.com/154&amp;nbsp;[Flutter] Apple Login 설정 - Ios AppIos App 환경에서 apple 로그인을 하기 위한 설정 입니다.&amp;nbsp;&amp;nbsp;&amp;nbsp;1.&amp;nbsp; App IDs 등록&amp;nbsp;&amp;nbsp;&amp;nbsp;이러&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;jutole.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;
&lt;p data-ke-size=&quot;size16&quot;&gt;이전에 Apple Login 간단하게 구현해 보았습니다. 이번 글에서는 조금 더 심화 구현을 해보겠습니다.&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;h3 data-ke-size=&quot;size23&quot;&gt;1.&amp;nbsp; Nonce&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Nonce는 Apple 로그인 (Sign in with Apple) 과정에서 사용하는 중요한 보안 요소입니다. Apple 로그인의 Nonce는 암호화된 임의 문자열로, 요청을 보낼 때 이를 사용하여 인증 과정의 보안을 강화합니다. 주로 *replay attack(재전송 공격)*을 방지하는 용도로 사용됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1727631213196&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;return SignInWithAppleButton(
  onPressed: () async {
    final result = await SignInWithApple.getAppleIDCredential(
      scopes: [
        AppleIDAuthorizationScopes.email,
        AppleIDAuthorizationScopes.fullName,
      ],
      nonce: _getNonce(),
    );
  },
);

String _getNonce() {
  const charset =
      '0123456789ABCDEFGHIJKLMNOPQRSTUVXYZabcdefghijklmnopqrstuvwxyz-._';

  final random = List&amp;lt;int&amp;gt;.generate(
    32,
    (_) =&amp;gt; charset.codeUnitAt(
      (Random().nextDouble() * charset.length).floor(),
    ),
  );

  final bytes = utf8.encode(
    String.fromCharCodes(random),
  );

  /// import 'package:crypto/crypto.dart'; 패키지 추가 사용
  final sha256Nonce = sha256.convert(bytes).toString();

  return sha256Nonce;
}&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;이전 구현에서 했던 기본적인 AppleLogin 방법에서 nonce를 추가할 수 있습니다. 클라이언트가 임의로 생성한 무작위 값을 Apple로그인과 함께 보내고 Apple에서는 해당 값을 identityToken에 같이 실어서 보내줍니다.&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;h3 data-ke-size=&quot;size23&quot;&gt;2. IdentityToken&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Apple에서&amp;nbsp;발급하는&amp;nbsp;JWT&amp;nbsp;형식의&amp;nbsp;신원&amp;nbsp;확인&amp;nbsp;토큰.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1727632002636&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;result.identityToken&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-origin-width=&quot;976&quot; data-origin-height=&quot;519&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cesblk/btsJRBA1shE/jvPGzZvvSobjuWUWLvViV0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cesblk/btsJRBA1shE/jvPGzZvvSobjuWUWLvViV0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cesblk/btsJRBA1shE/jvPGzZvvSobjuWUWLvViV0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcesblk%2FbtsJRBA1shE%2FjvPGzZvvSobjuWUWLvViV0%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;976&quot; height=&quot;519&quot; data-origin-width=&quot;976&quot; data-origin-height=&quot;519&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;AppleLogin을 하고 받은 응답값에는 identityToken이 있습니다. 해당 토큰은 Apple에서 발급한 JWT 형식의 토큰이기 때문에 디코딩을 하면 해당 유저의 신원을 확인할 수 있습니다.&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://jwt.io/&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://jwt.io/&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1727632608823&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;JWT.IO&quot; data-og-description=&quot;JSON Web Tokens are an open, industry standard RFC 7519 method for representing claims securely between two parties.&quot; data-og-host=&quot;jwt.io&quot; data-og-source-url=&quot;https://jwt.io/&quot; data-og-url=&quot;http://jwt.io/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/cYw63C/hyW6JHI206/2fXaUzBdxkvJ8OzCi1zkXK/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/bL65KU/hyXat4hTs2/tXhdcirkYA6apKIPLzjSK1/img.png?width=1024&amp;amp;height=512&amp;amp;face=0_0_1024_512&quot;&gt;&lt;a href=&quot;https://jwt.io/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://jwt.io/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/cYw63C/hyW6JHI206/2fXaUzBdxkvJ8OzCi1zkXK/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/bL65KU/hyXat4hTs2/tXhdcirkYA6apKIPLzjSK1/img.png?width=1024&amp;amp;height=512&amp;amp;face=0_0_1024_512');&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;JWT.IO&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;JSON Web Tokens are an open, industry standard RFC 7519 method for representing claims securely between two parties.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;jwt.io&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&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;pre id=&quot;code_1727632748779&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;{
  /// 토큰 발급한 주체
  &quot;iss&quot;: &quot;https://appleid.apple.com&quot;,
  
  /// 토큰의 수신자
  &quot;aud&quot;: &quot;jutole.app.customer&quot;,
  
  /// 토큰 만료 시간
  &quot;exp&quot;: 1727718782,
  
  /// 토큰 발급 시간
  &quot;iat&quot;: 1727632382,
  
  /// userIdentifier 유저 고유 식별자
  &quot;sub&quot;: &quot;001381.71cebe533162466fd6229190b49d4329.0111&quot;,
  
  /// 보안 용도로 사용되는 고유한 문자열
  &quot;nonce&quot;: &quot;d6ead4b4e3cb70c1deeec1d2429a4ac5a0b4b819dab04b45f0cf5d403e52525a&quot;,
  
  /// 인증 코드가 안전하게 전송되었음을 검증하는 데 사용
  &quot;c_hash&quot;: &quot;PQiQDbxZCaTz1kuiHkjG5B&quot;,
  
  /// 사용자의 이메일 주소
  /// 용자의 실제 이메일을 보호하기 위해 Apple이 제공하는 사설 이메일 주소
  &quot;email&quot;: &quot;ABCDEFG@privaterelay.appleid.com&quot;,
  
  /// 사용자의 이메일 주소가 검증되었는지를 나타내는 불리언 값
  &quot;email_verified&quot;: true,
  
  /// 사용자가 개인 이메일 보호 기능을 사용하고 있는지 여부
  &quot;is_private_email&quot;: true,
  
  /// 사용자가 마지막으로 인증된 시간
  &quot;auth_time&quot;: 1727632382,
  
  /// Nonce 지원 여부
  &quot;nonce_supported&quot;: true,
  
  /// 사용자가 실제 사용자임을 나타내는 상태 코드
  /// 0 : 사용자에 대한 정보가 불확실하거나 제공되지 않음.
  /// 1 : 실제 사용자가 아니거나 테스트 계정
  /// 2 : 실제 사용자
  &quot;real_user_status&quot;: 2
}&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;identityToken을 디코딩하면 위와 같은 데이터를 알 수 있습니다. 1번에서 보낸 nonce가 응답값으로 오는 게 확인이 됩니다. 이것으로 클라이언트에서 보낼 때의 nonce와 응답으로 온 nonce값을 비교해서 중간에 위변조가 되었는지 여부를 알 수 있습니다.&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;identityToken에 userIdentifier도 포함하고 있어 해당 토큰만 서버에 전달하면 서버에서 해당 토큰을 디코딩해서 처리할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(identityToken에 사용자 이름은 포함되어 있지 않기 때문에 따로 보내야 합니다.)&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;h3 data-ke-size=&quot;size23&quot;&gt;3.&amp;nbsp; Email Source 추가&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일반적으로 사용자의 이메일로 메일을 보내거나 하는 이벤트는 정상적으로 이루어집니다. 하지만 AppleLogin에서 사용자가 *이메일 가리기* 기능을 선택해 비공개 이메일로 설정되어 비공개 이메일로 메일을 보내면 정상적으로 메일이 가지 않습니다.&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;일반 이메일 : jutoleofficial@gmail.com&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비공개 이메일 : ABCDEFG@privaterelay.appleid.com&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://developer.apple.com/account/resources/services/list&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://developer.apple.com/account/resources/services/list&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1727633800421&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;로그인 - Apple&quot; data-og-description=&quot;&quot; data-og-host=&quot;idmsa.apple.com&quot; data-og-source-url=&quot;https://developer.apple.com/account/resources/services/list&quot; data-og-url=&quot;https://idmsa.apple.com/IDMSWebAuth/signin?appIdKey=891bd3417a7776362562d2197f89480a8547b108fd934911bcbea0110d07f757&amp;amp;path=%2Faccount%2Fresources%2Fservices%2Flist&amp;amp;rv=1&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://developer.apple.com/account/resources/services/list&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://developer.apple.com/account/resources/services/list&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;로그인 - Apple&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;idmsa.apple.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 상황에서 해결 방법은 위에 사이트를 들어가서 *Sign in With Apple for Email Communication* -&amp;gt; *Configure* -&amp;gt; *Email Sources* 추가 버튼을 눌러줍니다.&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;532&quot; data-origin-height=&quot;595&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/wwoNA/btsJPGRPUW2/LkKYc1ktyPjU978vVtR6WK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/wwoNA/btsJPGRPUW2/LkKYc1ktyPjU978vVtR6WK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/wwoNA/btsJPGRPUW2/LkKYc1ktyPjU978vVtR6WK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FwwoNA%2FbtsJPGRPUW2%2FLkKYc1ktyPjU978vVtR6WK%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;477&quot; height=&quot;533&quot; data-origin-width=&quot;532&quot; data-origin-height=&quot;595&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;그러면 위와 같은 창이 뜨는데 *Domains and Subdomains*에 메일을 보낼 domain을 입력하고 저장하면 됩니다.&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;gmail.com&amp;nbsp;같은&amp;nbsp;도메인은&amp;nbsp;추가도&amp;nbsp;안되고&amp;nbsp;발송도&amp;nbsp;안&amp;nbsp;되는&amp;nbsp;것&amp;nbsp;같습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;*&amp;nbsp;되시는&amp;nbsp;분&amp;nbsp;있으면&amp;nbsp;알려주세요.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;*&amp;nbsp;회사&amp;nbsp;도메인&amp;nbsp;추가하면&amp;nbsp;회사&amp;nbsp;도메인으로&amp;nbsp;메일&amp;nbsp;발송시&amp;nbsp;정상적으로&amp;nbsp;발송됩니다.&lt;/p&gt;</description>
      <category>Flutter/SNS Login</category>
      <category>applelogin</category>
      <category>emailsource</category>
      <category>flutter</category>
      <author>주톨</author>
      <guid isPermaLink="true">https://jutole.tistory.com/157</guid>
      <comments>https://jutole.tistory.com/157#entry157comment</comments>
      <pubDate>Mon, 30 Sep 2024 03:39:12 +0900</pubDate>
    </item>
    <item>
      <title>[Flutter] Apple Login 구현 - Ios App</title>
      <link>https://jutole.tistory.com/156</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;설정이 안 된 분은 아래글을 통해 설정을 하고 와주세요.&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://jutole.tistory.com/154&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://jutole.tistory.com/154&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1727440311781&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;[Flutter] Apple Login 설정 - Ios App&quot; data-og-description=&quot;Ios App 환경에서 apple 로그인을 하기 위한 설정 입니다.&amp;nbsp;&amp;nbsp;&amp;nbsp;1.&amp;nbsp; App IDs 등록&amp;nbsp;&amp;nbsp;&amp;nbsp;이러한 페이지로 오게 됩니다. 여기서 2개의 Identifier를 등록해주어야 합니다.추가버튼을 누르면 여러 항목들이 쭉 &quot; data-og-host=&quot;jutole.tistory.com&quot; data-og-source-url=&quot;https://jutole.tistory.com/154&quot; data-og-url=&quot;https://jutole.tistory.com/154&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/NHh5f/hyXaAhLpiE/zAt5p6IrtLeTG04k0QldA1/img.png?width=177&amp;amp;height=182&amp;amp;face=0_0_177_182,https://scrap.kakaocdn.net/dn/beRakj/hyW6FLNJM6/3oCrfmQR0Kk8RKuklTh5ok/img.png?width=177&amp;amp;height=182&amp;amp;face=0_0_177_182,https://scrap.kakaocdn.net/dn/bX1orw/hyXazJWlrl/oOVYaUondtkp84kYoEI9d0/img.png?width=1920&amp;amp;height=1080&amp;amp;face=0_0_1920_1080&quot;&gt;&lt;a href=&quot;https://jutole.tistory.com/154&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://jutole.tistory.com/154&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/NHh5f/hyXaAhLpiE/zAt5p6IrtLeTG04k0QldA1/img.png?width=177&amp;amp;height=182&amp;amp;face=0_0_177_182,https://scrap.kakaocdn.net/dn/beRakj/hyW6FLNJM6/3oCrfmQR0Kk8RKuklTh5ok/img.png?width=177&amp;amp;height=182&amp;amp;face=0_0_177_182,https://scrap.kakaocdn.net/dn/bX1orw/hyXazJWlrl/oOVYaUondtkp84kYoEI9d0/img.png?width=1920&amp;amp;height=1080&amp;amp;face=0_0_1920_1080');&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;[Flutter] Apple Login 설정 - Ios App&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Ios App 환경에서 apple 로그인을 하기 위한 설정 입니다.&amp;nbsp;&amp;nbsp;&amp;nbsp;1.&amp;nbsp; App IDs 등록&amp;nbsp;&amp;nbsp;&amp;nbsp;이러한 페이지로 오게 됩니다. 여기서 2개의 Identifier를 등록해주어야 합니다.추가버튼을 누르면 여러 항목들이 쭉&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;jutole.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;
&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;h3 data-ke-size=&quot;size23&quot;&gt;1.&amp;nbsp; sign_in_with_apple 패키지 설치&lt;/h3&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://pub.dev/packages/sign_in_with_apple&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://pub.dev/packages/sign_in_with_apple&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1727440467537&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;sign_in_with_apple | Flutter package&quot; data-og-description=&quot;Flutter bridge to initiate Sign in with Apple (on iOS, macOS, and Android). Includes support for keychain entries as well as signing in with an Apple ID.&quot; data-og-host=&quot;pub.dev&quot; data-og-source-url=&quot;https://pub.dev/packages/sign_in_with_apple&quot; data-og-url=&quot;https://pub.dev/packages/sign_in_with_apple&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/dfr3KS/hyW6AjmKlq/8a6WiKka6EjnVnKtqzJx4K/img.png?width=1280&amp;amp;height=640&amp;amp;face=0_0_1280_640,https://scrap.kakaocdn.net/dn/XS4Nb/hyXayRNmN0/2PvQUYeZZLe0ibWypimlg1/img.png?width=1280&amp;amp;height=640&amp;amp;face=0_0_1280_640,https://scrap.kakaocdn.net/dn/z7cDA/hyXawGrweF/bpYsJgZK9nu2Fyyl3514X0/img.png?width=924&amp;amp;height=925&amp;amp;face=0_0_924_925&quot;&gt;&lt;a href=&quot;https://pub.dev/packages/sign_in_with_apple&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://pub.dev/packages/sign_in_with_apple&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/dfr3KS/hyW6AjmKlq/8a6WiKka6EjnVnKtqzJx4K/img.png?width=1280&amp;amp;height=640&amp;amp;face=0_0_1280_640,https://scrap.kakaocdn.net/dn/XS4Nb/hyXayRNmN0/2PvQUYeZZLe0ibWypimlg1/img.png?width=1280&amp;amp;height=640&amp;amp;face=0_0_1280_640,https://scrap.kakaocdn.net/dn/z7cDA/hyXawGrweF/bpYsJgZK9nu2Fyyl3514X0/img.png?width=924&amp;amp;height=925&amp;amp;face=0_0_924_925');&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;sign_in_with_apple | Flutter package&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Flutter bridge to initiate Sign in with Apple (on iOS, macOS, and Android). Includes support for keychain entries as well as signing in with an Apple ID.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;pub.dev&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&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;2. Apple Login Button 생성&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;457&quot; data-origin-height=&quot;107&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bFVdjX/btsJPEmbZcP/mKXUp6Nlp0Ef6F2m6bDG2K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bFVdjX/btsJPEmbZcP/mKXUp6Nlp0Ef6F2m6bDG2K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bFVdjX/btsJPEmbZcP/mKXUp6Nlp0Ef6F2m6bDG2K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbFVdjX%2FbtsJPEmbZcP%2FmKXUp6Nlp0Ef6F2m6bDG2K%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;457&quot; height=&quot;107&quot; data-origin-width=&quot;457&quot; data-origin-height=&quot;107&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre id=&quot;code_1727623910463&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class _AppleLoginButton extends StatelessWidget {
  const _AppleLoginButton();

  @override
  Widget build(BuildContext context) {
    return SignInWithAppleButton(
      onPressed: () {},
      style: SignInWithAppleButtonStyle.black, /// 색상 지정 가능
      height: 44, /// 버튼 높이 지정 가능
      borderRadius: BorderRadius.circular(8), /// 모서리 지정 가능
      iconAlignment: IconAlignment.center, /// 아이콘 위치 지정 가능
      text: 'Sign in with Apple', /// 텍스트 지정 가능
    );
  }
}&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;위 코드와 같이 sign_in_with_apple패키지에서 제공하는 SignInWithAppleButton을 사용하면 AppleLoginButton 디자인을 자동으로 생성해 줍니다. 버튼 디자인이 애플이 규정하는 디자인에 맞지 않으면 앱 심사에서 거절당하니 해당 기능으로 버튼을 만들어주는 게 좋습니다.&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;h3 data-ke-size=&quot;size23&quot;&gt;3. Login Event&lt;/h3&gt;
&lt;pre id=&quot;code_1727628751076&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;return SignInWithAppleButton(
  onPressed: () async {
    final result = await SignInWithApple.getAppleIDCredential(
      scopes: [
        AppleIDAuthorizationScopes.email,
        AppleIDAuthorizationScopes.fullName,
      ],
    );

    /// 사용자 이메일
    /// 사용자 설정에 따라서 비공개 이메일이 올 수 있음.
    /// 첫 로그인시에만 오고 그 후로는 null 반환.
    print(result.email ?? '');

    /// 사용자 이름 (성)
    /// 첫 로그인시에만 오고 그 후로는 null 반환.
    print(result.familyName ?? '');

    /// 사용자 이름 (이름)
    /// 첫 로그인시에만 오고 그 후로는 null 반환.
    print(result.givenName ?? '');

    /// Apple에서 발급하는 해당앱의 유저 고유 식별자.
    print(result.userIdentifier ?? '');

    /// Apple에서 발급하는 JWT 형식의 신원 확인 토큰.
    print(result.identityToken);

    /// 짧은 기간 유효한 인증 코드로, 서버에서 Apple과 통신해 사용자 인증을 확인할 때 사용됩니다. 
    print(result.authorizationCode);
  },
);&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;기본적으로 Apple Login 방법은 SignInWithApple.getAppleIDCredential()를 사용해 할 수 있습니다.&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;687&quot; data-origin-height=&quot;919&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/zC5dE/btsJRou8RSU/UPVnAQvygwVSClG3D8K4a0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/zC5dE/btsJRou8RSU/UPVnAQvygwVSClG3D8K4a0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/zC5dE/btsJRou8RSU/UPVnAQvygwVSClG3D8K4a0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FzC5dE%2FbtsJRou8RSU%2FUPVnAQvygwVSClG3D8K4a0%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;347&quot; height=&quot;464&quot; data-origin-width=&quot;687&quot; data-origin-height=&quot;919&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;&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;&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;h3 data-ke-size=&quot;size23&quot;&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;&lt;a href=&quot;https://jutole.tistory.com/157&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://jutole.tistory.com/157&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1727635179508&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;[Flutter] Apple Login 심화 구현 - Ios App&quot; data-og-description=&quot;https://jutole.tistory.com/156&amp;nbsp;[Flutter] Apple Login 구현 - Ios App설정이 안 된 분은 아래글을 통해 설정을 하고 와주세요.&amp;nbsp;https://jutole.tistory.com/154&amp;nbsp;[Flutter] Apple Login 설정 - Ios AppIos App 환경에서 apple 로그인을&quot; data-og-host=&quot;jutole.tistory.com&quot; data-og-source-url=&quot;https://jutole.tistory.com/157&quot; data-og-url=&quot;https://jutole.tistory.com/157&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bkbUdc/hyW6DAKeFi/0wsdgH788HHAj0RrFHCPd0/img.png?width=177&amp;amp;height=182&amp;amp;face=0_0_177_182,https://scrap.kakaocdn.net/dn/mcHKC/hyXatXzSgU/rAGkia11m4XJ2nzlmABpIK/img.png?width=177&amp;amp;height=182&amp;amp;face=0_0_177_182,https://scrap.kakaocdn.net/dn/dce2p3/hyW6DHwU59/isV6XWsG6QiJTkKqLx8g11/img.png?width=976&amp;amp;height=519&amp;amp;face=0_0_976_519&quot;&gt;&lt;a href=&quot;https://jutole.tistory.com/157&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://jutole.tistory.com/157&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bkbUdc/hyW6DAKeFi/0wsdgH788HHAj0RrFHCPd0/img.png?width=177&amp;amp;height=182&amp;amp;face=0_0_177_182,https://scrap.kakaocdn.net/dn/mcHKC/hyXatXzSgU/rAGkia11m4XJ2nzlmABpIK/img.png?width=177&amp;amp;height=182&amp;amp;face=0_0_177_182,https://scrap.kakaocdn.net/dn/dce2p3/hyW6DHwU59/isV6XWsG6QiJTkKqLx8g11/img.png?width=976&amp;amp;height=519&amp;amp;face=0_0_976_519');&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;[Flutter] Apple Login 심화 구현 - Ios App&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;https://jutole.tistory.com/156&amp;nbsp;[Flutter] Apple Login 구현 - Ios App설정이 안 된 분은 아래글을 통해 설정을 하고 와주세요.&amp;nbsp;https://jutole.tistory.com/154&amp;nbsp;[Flutter] Apple Login 설정 - Ios AppIos App 환경에서 apple 로그인을&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;jutole.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;
&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>Flutter/SNS Login</category>
      <category>applelogin</category>
      <category>flutter</category>
      <author>주톨</author>
      <guid isPermaLink="true">https://jutole.tistory.com/156</guid>
      <comments>https://jutole.tistory.com/156#entry156comment</comments>
      <pubDate>Mon, 30 Sep 2024 02:14:59 +0900</pubDate>
    </item>
  </channel>
</rss>