{"id":83,"date":"2025-07-16T14:46:50","date_gmt":"2025-07-16T05:46:50","guid":{"rendered":"http:\/\/34.64.61.65\/?p=83"},"modified":"2025-07-16T14:50:18","modified_gmt":"2025-07-16T05:50:18","slug":"2-flutter%ec%95%b1-%ea%b0%9c%eb%b0%9c-%ec%b2%ab-%ec%82%bd-%eb%9c%a8%ea%b8%b0-%ec%a0%84-%ed%95%84%ec%88%98-%ed%99%95%ec%9d%b8-%ec%82%ac%ed%95%ad","status":"publish","type":"post","link":"https:\/\/hed-g.me\/?p=83","title":{"rendered":"2. [Flutter]\uc571 \uac1c\ubc1c, \uccab \uc0bd \ub728\uae30 \uc804 \ud544\uc218 \ud655\uc778 \uc0ac\ud56d!"},"content":{"rendered":"\n<h1 class=\"wp-block-heading\">Flutter \ud504\ub85c\uc81d\ud2b8 \uc2dc\uc791 \uc804 \ud544\uc218 \uccb4\ud06c\ub9ac\uc2a4\ud2b8 \ud83d\udccb<\/h1>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p><strong>\uc2e4\ubb34\uc5d0\uc11c \ubc14\ub85c \uc4f0\ub294 Flutter \ud504\ub85c\uc81d\ud2b8 \ucd08\uae30 \uc124\uc815 \uac00\uc774\ub4dc<\/strong><br>\n\ub354 \uc774\uc0c1 \ud504\ub85c\uc81d\ud2b8 \uc911\uac04\uc5d0 &#8220;\uc544, \uc774\uac78 \ucc98\uc74c\uc5d0 \uc124\uc815\ud588\uc5b4\uc57c \ud588\ub294\ub370&#8230;&#8221; \ud558\uc9c0 \ub9c8\uc138\uc694!<\/p>\n<\/blockquote>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<p>\uc548\ub155\ud558\uc138\uc694! \ubaa8\ubc14\uc77c \uac1c\ubc1c\uc758 \uc0c8\ub85c\uc6b4 \ud328\ub7ec\ub2e4\uc784\uc778 Flutter\ub85c \uccab \ud504\ub85c\uc81d\ud2b8\ub97c \uc2dc\uc791\ud558\ub824\uace0 \ud558\uc2dc\ub098\uc694? <\/p>\n\n\n\n<p>Android\/iOS \ub124\uc774\ud2f0\ube0c \uac1c\ubc1c\uc744 \ud574\ubcf4\uc2e0 \ubd84\ub4e4\uc774\ub098 \uc6f9 \ud504\ub860\ud2b8\uc5d4\ub4dc\uc5d0\uc11c \ubaa8\ubc14\uc77c\ub85c \ud655\uc7a5\uc744 \uace0\ub824\ud558\uace0 \uacc4\uc2e0 \ubd84\ub4e4\uc5d0\uac8c <strong>&#8220;\ud504\ub85c\uc81d\ud2b8 \uc2dc\uc791 \uc804\uc5d0 \uc774\uac83\ub9cc\uc740 \uaf2d \ud655\uc778\ud558\uc790!&#8221;<\/strong>\ub294 \uc2e4\uc804 \uac00\uc774\ub4dc\ub97c \uc900\ube44\ud588\uc2b5\ub2c8\ub2e4.<\/p>\n\n\n\n<p>\uc81c\uac00 \uc5ec\ub7ec Flutter \ud504\ub85c\uc81d\ud2b8\ub97c \uc9c4\ud589\ud558\uba74\uc11c \uacaa\uc5c8\ub358 \uc2dc\ud589\ucc29\uc624\ub97c \ubc14\ud0d5\uc73c\ub85c, \ud504\ub85c\uc81d\ud2b8 \ucd08\uae30\uc5d0 \ub193\uce58\uae30 \uc26c\uc6b4 \ud575\uc2ec \uc124\uc815\ub4e4\uc744 \uc815\ub9ac\ud574\ubd24\uc2b5\ub2c8\ub2e4. \uc774 \uae00\uc744 \ub530\ub77c\ud558\uc2dc\uba74 \ub098\uc911\uc5d0 &#8220;\uc544, \ucc98\uc74c\uc5d0 \uc774\uac78 \uc124\uc815\ud588\uc5b4\uc57c \ud588\ub294\ub370&#8230;&#8221;\ub77c\ub294 \ud6c4\ud68c\ub97c \ud558\uc9c0 \uc54a\uc73c\uc2e4 \uac70\uc608\uc694! \ud83d\ude0a<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">\ud83c\udfaf \uc65c \ucd08\uae30 \uc124\uc815\uc774 \uc911\uc694\ud560\uae4c?<\/h2>\n\n\n\n<p>Flutter \ud504\ub85c\uc81d\ud2b8\uc5d0\uc11c \ucd08\uae30 \uc124\uc815\uc744 \uc81c\ub300\ub85c \ud558\uc9c0 \uc54a\uc73c\uba74:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>\ud83d\udd04 \uc911\uac04\uc5d0 \ud328\ud0a4\uc9c0 \uc758\uc874\uc131 \ucda9\ub3cc<\/strong>\ub85c \uba70\uce60\uc744 \uc0bd\uc9c8\ud558\uac8c \ub429\ub2c8\ub2e4<\/li>\n\n\n\n<li><strong>\ud83d\udcf1 \ud50c\ub7ab\ud3fc\ubcc4 \uc124\uc815 \ub204\ub77d<\/strong>\uc73c\ub85c \ubc30\ud3ec \uc9c1\uc804\uc5d0 \ub2f9\ud669\ud558\uac8c \ub429\ub2c8\ub2e4  <\/li>\n\n\n\n<li><strong>\ud83d\udd10 \uad8c\ud55c \uc124\uc815 \uc2e4\uc218<\/strong>\ub85c \uc571\uc2a4\ud1a0\uc5b4 \ub9ac\uc81d\uc744 \ub2f9\ud558\uac8c \ub429\ub2c8\ub2e4<\/li>\n\n\n\n<li><strong>\u26a1 \uc131\ub2a5 \ucd5c\uc801\ud654<\/strong>\ub97c \ub098\uc911\uc5d0 \ud558\ub824\uace0 \ud558\uba74 \ub9ac\ud329\ud1a0\ub9c1 \uc9c0\uc625\uc5d0 \ube60\uc9d1\ub2c8\ub2e4<\/li>\n<\/ul>\n\n\n\n<p>\ud2b9\ud788 \uc548\ub4dc\ub85c\uc774\ub4dc\ub098 iOS\uc5d0\uc11c \ub118\uc5b4\uc624\uc2e0 \ubd84\ub4e4\uc740 &#8220;Flutter\ub294 \ud06c\ub85c\uc2a4 \ud50c\ub7ab\ud3fc\uc774\ub2c8\uae4c \uc124\uc815\uc774 \uac04\ub2e8\ud558\uaca0\uc9c0?&#8221;\ub77c\uace0 \uc0dd\uac01\ud558\uc2dc\ub294\ub370, \uc624\ud788\ub824 <strong>\ub450 \ud50c\ub7ab\ud3fc\uc744 \ubaa8\ub450 \uace0\ub824\ud574\uc57c \ud558\uae30 \ub54c\ubb38\uc5d0<\/strong> \ub354 \uc2e0\uacbd \uc368\uc57c \ud560 \ubd80\ubd84\uc774 \ub9ce\uc2b5\ub2c8\ub2e4.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">\ud83d\udccb \uccb4\ud06c\ub9ac\uc2a4\ud2b8 \uac1c\uc694<\/h2>\n\n\n\n<p>\uc774 \uae00\uc5d0\uc11c \ub2e4\ub8f0 \ud575\uc2ec \uccb4\ud06c \ud3ec\uc778\ud2b8\ub4e4\uc785\ub2c8\ub2e4:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Android \uc124\uc815<\/strong> &#8211; Manifest\uc640 Gradle \uc124\uc815<\/li>\n\n\n\n<li><strong>iOS \uc124\uc815<\/strong> &#8211; info.plist\uc640 Xcode \ud504\ub85c\uc81d\ud2b8 \uc124\uc815  <\/li>\n\n\n\n<li><strong>pubspec.yaml \uc644\ubcbd \uc124\uc815<\/strong> &#8211; \uc758\uc874\uc131\ubd80\ud130 \ub9ac\uc18c\uc2a4\uae4c\uc9c0<\/li>\n\n\n\n<li><strong>\ud544\uc218 \ud328\ud0a4\uc9c0 \ubbf8\ub9ac \uc138\ud305<\/strong> &#8211; \ub098\uc911\uc5d0 \ud6c4\ud68c\ud558\uc9c0 \uc54a\uc744 \ud328\ud0a4\uc9c0\ub4e4<\/li>\n\n\n\n<li><strong>\uad8c\ud55c \ubc0f \ubcf4\uc548 \uc124\uc815<\/strong> &#8211; \uc571\uc2a4\ud1a0\uc5b4 \uc2b9\uc778\uc744 \uc704\ud55c \ud544\uc218 \uc0ac\ud56d\ub4e4<\/li>\n<\/ol>\n\n\n\n<p>\uac01 \ub2e8\uacc4\ubcc4\ub85c <strong>\uc65c \ud544\uc694\ud55c\uc9c0<\/strong>, <strong>\uc5b4\ub5bb\uac8c \uc124\uc815\ud558\ub294\uc9c0<\/strong>, <strong>\uc8fc\uc758\uc0ac\ud56d\uc740 \ubb34\uc5c7\uc778\uc9c0<\/strong> \uc0c1\uc138\ud788 \uc54c\uc544\ubcf4\uaca0\uc2b5\ub2c8\ub2e4.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">1\ufe0f\u20e3 Android \uc124\uc815: \ud0c4\ud0c4\ud55c \uae30\ubc18 \ub2e4\uc9c0\uae30<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udcf1 Android Manifest \uc124\uc815<\/h3>\n\n\n\n<p>Android Manifest\ub294 \uc571\uc758 \uc2e0\ubd84\uc99d \uac19\uc740 \uc5ed\ud560\uc744 \ud569\ub2c8\ub2e4. <code>android\/app\/src\/main\/AndroidManifest.xml<\/code> \ud30c\uc77c\uc5d0\uc11c \ud575\uc2ec \uc124\uc815\ub4e4\uc744 \ud655\uc778\ud574\ubd05\uc2dc\ub2e4.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;manifest xmlns:android=\"http:\/\/schemas.android.com\/apk\/res\/android\"\n    package=\"com.example.your_app\"&gt;\n\n    &lt;!-- \uc778\ud130\ub137 \uad8c\ud55c (API \ud1b5\uc2e0 \ud544\uc218) --&gt;\n    &lt;uses-permission android:name=\"android.permission.INTERNET\" \/&gt;\n\n    &lt;!-- \uce74\uba54\ub77c \uad8c\ud55c (\uce74\uba54\ub77c \uae30\ub2a5 \uc0ac\uc6a9 \uc2dc) --&gt;\n    &lt;uses-permission android:name=\"android.permission.CAMERA\" \/&gt;\n\n    &lt;!-- \uc800\uc7a5\uc18c \uad8c\ud55c (\ud30c\uc77c \uc5c5\ub85c\ub4dc\/\ub2e4\uc6b4\ub85c\ub4dc \uc2dc) --&gt;\n    &lt;uses-permission android:name=\"android.permission.READ_EXTERNAL_STORAGE\" \/&gt;\n    &lt;uses-permission android:name=\"android.permission.WRITE_EXTERNAL_STORAGE\" \/&gt;\n\n    &lt;!-- \uc704\uce58 \uad8c\ud55c (\uc9c0\ub3c4 \uae30\ub2a5 \uc0ac\uc6a9 \uc2dc) --&gt;\n    &lt;uses-permission android:name=\"android.permission.ACCESS_FINE_LOCATION\" \/&gt;\n    &lt;uses-permission android:name=\"android.permission.ACCESS_COARSE_LOCATION\" \/&gt;\n\n    &lt;application\n        android:label=\"Your App Name\"  &lt;!-- \uc571 \uc774\ub984 --&gt;\n        android:name=\"${applicationName}\"\n        android:icon=\"@mipmap\/ic_launcher\"  &lt;!-- \uc571 \uc544\uc774\ucf58 --&gt;\n        android:usesCleartextTraffic=\"true\"&gt; &lt;!-- HTTP \ud1b5\uc2e0 \ud5c8\uc6a9 (\uac1c\ubc1c \uc2dc\uc5d0\ub9cc) --&gt;\n\n        &lt;activity\n            android:name=\".MainActivity\"\n            android:exported=\"true\"\n            android:launchMode=\"singleTop\"\n            android:theme=\"@style\/LaunchTheme\"\n            android:configChanges=\"orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode\"\n            android:hardwareAccelerated=\"true\"\n            android:windowSoftInputMode=\"adjustResize\"&gt;\n\n            &lt;!-- \ub525\ub9c1\ud06c \uc124\uc815 --&gt;\n            &lt;intent-filter android:autoVerify=\"true\"&gt;\n                &lt;action android:name=\"android.intent.action.VIEW\" \/&gt;\n                &lt;category android:name=\"android.intent.category.DEFAULT\" \/&gt;\n                &lt;category android:name=\"android.intent.category.BROWSABLE\" \/&gt;\n                &lt;data android:scheme=\"https\"\n                      android:host=\"yourapp.com\" \/&gt;\n            &lt;\/intent-filter&gt;\n\n            &lt;meta-data\n              android:name=\"io.flutter.embedding.android.NormalTheme\"\n              android:resource=\"@style\/NormalTheme\" \/&gt;\n        &lt;\/activity&gt;\n\n        &lt;!-- Firebase \uc124\uc815 (\ud478\uc2dc \uc54c\ub9bc \uc0ac\uc6a9 \uc2dc) --&gt;\n        &lt;service\n            android:name=\".java.MyFirebaseMessagingService\"\n            android:exported=\"false\"&gt;\n            &lt;intent-filter&gt;\n                &lt;action android:name=\"com.google.firebase.MESSAGING_EVENT\" \/&gt;\n            &lt;\/intent-filter&gt;\n        &lt;\/service&gt;\n    &lt;\/application&gt;\n&lt;\/manifest&gt;<\/code><\/pre>\n\n\n\n<p><strong>\ud83d\udca1 Pro Tip<\/strong>: \uad8c\ud55c\uc740 \ucc98\uc74c\ubd80\ud130 \ub2e4 \ucd94\uac00\ud558\uc9c0 \ub9c8\uc138\uc694! \ud544\uc694\ud55c \uae30\ub2a5\uc774 \uc0dd\uae38 \ub54c\ub9c8\ub2e4 \ucd94\uac00\ud558\ub294 \uac83\uc774 \uc88b\uc2b5\ub2c8\ub2e4. Google Play Store\uc5d0\uc11c\ub294 \ubd88\ud544\uc694\ud55c \uad8c\ud55c\uc744 \uc694\uccad\ud558\ub294 \uc571\uc744 \uc88b\uc9c0 \uc54a\uac8c \ubd05\ub2c8\ub2e4.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udd27 build.gradle \uc124\uc815<\/h3>\n\n\n\n<p><code>android\/app\/build.gradle<\/code> \ud30c\uc77c\uc740 \uc571\uc758 \ube4c\ub4dc \uc124\uc815\uc744 \ub2f4\ub2f9\ud569\ub2c8\ub2e4.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>def localProperties = new Properties()\ndef localPropertiesFile = rootProject.file('local.properties')\nif (localPropertiesFile.exists()) {\n    localPropertiesFile.withReader('UTF-8') { reader -&gt;\n        localProperties.load(reader)\n    }\n}\n\ndef flutterRoot = localProperties.getProperty('flutter.sdk')\nif (flutterRoot == null) {\n    throw new GradleException(\"Flutter SDK not found. Define location with flutter.sdk in the local.properties file.\")\n}\n\ndef flutterVersionCode = localProperties.getProperty('flutter.versionCode')\nif (flutterVersionCode == null) {\n    flutterVersionCode = '1'\n}\n\ndef flutterVersionName = localProperties.getProperty('flutter.versionName')\nif (flutterVersionName == null) {\n    flutterVersionName = '1.0'\n}\n\napply plugin: 'com.android.application'\napply plugin: 'kotlin-android'\napply from: \"$flutterRoot\/packages\/flutter_tools\/gradle\/flutter.gradle\"\n\n\/\/ Firebase \uc0ac\uc6a9 \uc2dc \ucd94\uac00\napply plugin: 'com.google.gms.google-services'\n\nandroid {\n    compileSdkVersion 34  \/\/ \ucd5c\uc2e0 SDK \ubc84\uc804 \uc0ac\uc6a9\n    ndkVersion flutter.ndkVersion\n\n    compileOptions {\n        sourceCompatibility JavaVersion.VERSION_1_8\n        targetCompatibility JavaVersion.VERSION_1_8\n    }\n\n    kotlinOptions {\n        jvmTarget = '1.8'\n    }\n\n    sourceSets {\n        main.java.srcDirs += 'src\/main\/kotlin'\n    }\n\n    defaultConfig {\n        applicationId \"com.example.your_app\"  \/\/ \uace0\uc720\ud55c \ud328\ud0a4\uc9c0\uba85\n        minSdkVersion 21  \/\/ Android 5.0 \uc774\uc0c1 \uc9c0\uc6d0\n        targetSdkVersion 34  \/\/ \ucd5c\uc2e0 \ud0c0\uac9f SDK\n        versionCode flutterVersionCode.toInteger()\n        versionName flutterVersionName\n\n        \/\/ MultiDex \ud65c\uc131\ud654 (\ud328\ud0a4\uc9c0\uac00 \ub9ce\uc744 \ub54c \ud544\uc694)\n        multiDexEnabled true\n\n        \/\/ \ud504\ub85c\uac00\ub4dc \uc124\uc815\n        proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'\n    }\n\n    signingConfigs {\n        release {\n            \/\/ \ub9b4\ub9ac\uc988 \ube4c\ub4dc\ub97c \uc704\ud55c \ud0a4\uc2a4\ud1a0\uc5b4 \uc124\uc815\n            keyAlias localProperties.getProperty('keyAlias')\n            keyPassword localProperties.getProperty('keyPassword')\n            storeFile localProperties.getProperty('storeFile') ? file(localProperties.getProperty('storeFile')) : null\n            storePassword localProperties.getProperty('storePassword')\n        }\n    }\n\n    buildTypes {\n        release {\n            signingConfig signingConfigs.release\n            minifyEnabled true  \/\/ \ucf54\ub4dc \ub09c\ub3c5\ud654 \ud65c\uc131\ud654\n            shrinkResources true  \/\/ \ubd88\ud544\uc694\ud55c \ub9ac\uc18c\uc2a4 \uc81c\uac70\n            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'\n        }\n        debug {\n            applicationIdSuffix \".debug\"  \/\/ \ub514\ubc84\uadf8 \ubc84\uc804 \uad6c\ubd84\n            debuggable true\n        }\n    }\n}\n\nflutter {\n    source '..\/..'\n}\n\ndependencies {\n    implementation \"org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version\"\n\n    \/\/ Firebase \uc0ac\uc6a9 \uc2dc\n    implementation platform('com.google.firebase:firebase-bom:32.7.0')\n    implementation 'com.google.firebase:firebase-analytics'\n    implementation 'com.google.firebase:firebase-crashlytics'\n\n    \/\/ MultiDex \uc9c0\uc6d0\n    implementation 'com.android.support:multidex:1.0.3'\n}<\/code><\/pre>\n\n\n\n<p><strong>\u26a0\ufe0f \uc8fc\uc758\uc0ac\ud56d<\/strong>: <\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>minSdkVersion<\/code>\uc740 21 \uc774\uc0c1\uc73c\ub85c \uc124\uc815\ud558\uc138\uc694 (Android 5.0). \ub354 \ub0ae\uc73c\uba74 \ucd5c\uc2e0 Flutter \uae30\ub2a5\ub4e4\uc744 \uc0ac\uc6a9\ud560 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4.<\/li>\n\n\n\n<li><code>compileSdkVersion<\/code>\uacfc <code>targetSdkVersion<\/code>\uc740 \ucd5c\uc2e0 \ubc84\uc804\uc744 \uc0ac\uc6a9\ud558\uc138\uc694.<\/li>\n\n\n\n<li>\ud0a4\uc2a4\ud1a0\uc5b4 \uc815\ubcf4\ub294 \uc808\ub300 \ucf54\ub4dc\uc5d0 \ud558\ub4dc\ucf54\ub529\ud558\uc9c0 \ub9c8\uc138\uc694!<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udd11 \ud0a4\uc2a4\ud1a0\uc5b4 \uc124\uc815 (\ubc30\ud3ec \uc900\ube44)<\/h3>\n\n\n\n<p>\ubc30\ud3ec\ub97c \uc704\ud574\uc11c\ub294 \uc571 \uc11c\uba85\uc6a9 \ud0a4\uc2a4\ud1a0\uc5b4\uac00 \ud544\uc694\ud569\ub2c8\ub2e4.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># \ud0a4\uc2a4\ud1a0\uc5b4 \uc0dd\uc131\nkeytool -genkey -v -keystore ~\/upload-keystore.jks -keyalg RSA -keysize 2048 -validity 10000 -alias upload\n\n# android\/key.properties \ud30c\uc77c \uc0dd\uc131\nstorePassword=your_store_password\nkeyPassword=your_key_password\nkeyAlias=upload\nstoreFile=\/Users\/your_username\/upload-keystore.jks<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">2\ufe0f\u20e3 iOS \uc124\uc815: \uc560\ud50c \uc0dd\ud0dc\uacc4 \uc815\ubcf5\ud558\uae30<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83c\udf4e info.plist \uc124\uc815<\/h3>\n\n\n\n<p>iOS \uc124\uc815\uc758 \ud575\uc2ec\uc778 <code>ios\/Runner\/Info.plist<\/code> \ud30c\uc77c\uc744 \uc0b4\ud3b4\ubd05\uc2dc\ub2e4.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;?xml version=\"1.0\" encoding=\"UTF-8\"?&gt;\n&lt;!DOCTYPE plist PUBLIC \"-\/\/Apple\/\/DTD PLIST 1.0\/\/EN\" \"http:\/\/www.apple.com\/DTDs\/PropertyList-1.0.dtd\"&gt;\n&lt;plist version=\"1.0\"&gt;\n&lt;dict&gt;\n    &lt;!-- \uc571 \uae30\ubcf8 \uc815\ubcf4 --&gt;\n    &lt;key&gt;CFBundleDevelopmentRegion&lt;\/key&gt;\n    &lt;string&gt;$(DEVELOPMENT_LANGUAGE)&lt;\/string&gt;\n\n    &lt;key&gt;CFBundleDisplayName&lt;\/key&gt;\n    &lt;string&gt;Your App Name&lt;\/string&gt;  &lt;!-- \ud648 \ud654\uba74\uc5d0 \ud45c\uc2dc\ub420 \uc571 \uc774\ub984 --&gt;\n\n    &lt;key&gt;CFBundleExecutable&lt;\/key&gt;\n    &lt;string&gt;$(EXECUTABLE_NAME)&lt;\/string&gt;\n\n    &lt;key&gt;CFBundleIdentifier&lt;\/key&gt;\n    &lt;string&gt;$(PRODUCT_BUNDLE_IDENTIFIER)&lt;\/string&gt;\n\n    &lt;key&gt;CFBundleInfoDictionaryVersion&lt;\/key&gt;\n    &lt;string&gt;6.0&lt;\/string&gt;\n\n    &lt;key&gt;CFBundleName&lt;\/key&gt;\n    &lt;string&gt;your_app&lt;\/string&gt;\n\n    &lt;key&gt;CFBundlePackageType&lt;\/key&gt;\n    &lt;string&gt;APPL&lt;\/string&gt;\n\n    &lt;key&gt;CFBundleShortVersionString&lt;\/key&gt;\n    &lt;string&gt;$(FLUTTER_BUILD_NAME)&lt;\/string&gt;\n\n    &lt;key&gt;CFBundleSignature&lt;\/key&gt;\n    &lt;string&gt;????&lt;\/string&gt;\n\n    &lt;key&gt;CFBundleVersion&lt;\/key&gt;\n    &lt;string&gt;$(FLUTTER_BUILD_NUMBER)&lt;\/string&gt;\n\n    &lt;!-- \ucd5c\uc18c iOS \ubc84\uc804 --&gt;\n    &lt;key&gt;LSMinimumSystemVersion&lt;\/key&gt;\n    &lt;string&gt;12.0&lt;\/string&gt;\n\n    &lt;!-- UI \uc124\uc815 --&gt;\n    &lt;key&gt;LSRequiresIPhoneOS&lt;\/key&gt;\n    &lt;true\/&gt;\n\n    &lt;key&gt;UILaunchStoryboardName&lt;\/key&gt;\n    &lt;string&gt;LaunchScreen&lt;\/string&gt;\n\n    &lt;key&gt;UIMainStoryboardFile&lt;\/key&gt;\n    &lt;string&gt;Main&lt;\/string&gt;\n\n    &lt;!-- \uc9c0\uc6d0 \uae30\uae30 \ubc29\ud5a5 --&gt;\n    &lt;key&gt;UISupportedInterfaceOrientations&lt;\/key&gt;\n    &lt;array&gt;\n        &lt;string&gt;UIInterfaceOrientationPortrait&lt;\/string&gt;\n        &lt;string&gt;UIInterfaceOrientationLandscapeLeft&lt;\/string&gt;\n        &lt;string&gt;UIInterfaceOrientationLandscapeRight&lt;\/string&gt;\n    &lt;\/array&gt;\n\n    &lt;key&gt;UISupportedInterfaceOrientations~ipad&lt;\/key&gt;\n    &lt;array&gt;\n        &lt;string&gt;UIInterfaceOrientationPortrait&lt;\/string&gt;\n        &lt;string&gt;UIInterfaceOrientationPortraitUpsideDown&lt;\/string&gt;\n        &lt;string&gt;UIInterfaceOrientationLandscapeLeft&lt;\/string&gt;\n        &lt;string&gt;UIInterfaceOrientationLandscapeRight&lt;\/string&gt;\n    &lt;\/array&gt;\n\n    &lt;!-- \uad8c\ud55c \uc124\uba85 \uba54\uc2dc\uc9c0 (\ud544\uc218!) --&gt;\n    &lt;key&gt;NSCameraUsageDescription&lt;\/key&gt;\n    &lt;string&gt;\uc774 \uc571\uc740 \uc0ac\uc9c4 \ucd2c\uc601\uc744 \uc704\ud574 \uce74\uba54\ub77c\uc5d0 \uc811\uadfc\ud569\ub2c8\ub2e4.&lt;\/string&gt;\n\n    &lt;key&gt;NSPhotoLibraryUsageDescription&lt;\/key&gt;\n    &lt;string&gt;\uc774 \uc571\uc740 \uc0ac\uc9c4 \uc800\uc7a5\uc744 \uc704\ud574 \uc0ac\uc9c4 \ub77c\uc774\ube0c\ub7ec\ub9ac\uc5d0 \uc811\uadfc\ud569\ub2c8\ub2e4.&lt;\/string&gt;\n\n    &lt;key&gt;NSLocationWhenInUseUsageDescription&lt;\/key&gt;\n    &lt;string&gt;\uc774 \uc571\uc740 \uc704\uce58 \uae30\ubc18 \uc11c\ube44\uc2a4 \uc81c\uacf5\uc744 \uc704\ud574 \uc704\uce58 \uc815\ubcf4\ub97c \uc0ac\uc6a9\ud569\ub2c8\ub2e4.&lt;\/string&gt;\n\n    &lt;key&gt;NSLocationAlwaysAndWhenInUseUsageDescription&lt;\/key&gt;\n    &lt;string&gt;\uc774 \uc571\uc740 \ubc31\uadf8\ub77c\uc6b4\ub4dc\uc5d0\uc11c\ub3c4 \uc704\uce58 \uae30\ubc18 \uc11c\ube44\uc2a4\ub97c \uc81c\uacf5\ud558\uae30 \uc704\ud574 \uc704\uce58 \uc815\ubcf4\ub97c \uc0ac\uc6a9\ud569\ub2c8\ub2e4.&lt;\/string&gt;\n\n    &lt;key&gt;NSMicrophoneUsageDescription&lt;\/key&gt;\n    &lt;string&gt;\uc774 \uc571\uc740 \uc74c\uc131 \ub179\uc74c\uc744 \uc704\ud574 \ub9c8\uc774\ud06c\uc5d0 \uc811\uadfc\ud569\ub2c8\ub2e4.&lt;\/string&gt;\n\n    &lt;!-- App Transport Security --&gt;\n    &lt;key&gt;NSAppTransportSecurity&lt;\/key&gt;\n    &lt;dict&gt;\n        &lt;key&gt;NSAllowsArbitraryLoads&lt;\/key&gt;\n        &lt;false\/&gt;  &lt;!-- \ud504\ub85c\ub355\uc158\uc5d0\uc11c\ub294 false\ub85c \uc124\uc815 --&gt;\n        &lt;key&gt;NSExceptionDomains&lt;\/key&gt;\n        &lt;dict&gt;\n            &lt;key&gt;your-api-domain.com&lt;\/key&gt;\n            &lt;dict&gt;\n                &lt;key&gt;NSExceptionAllowsInsecureHTTPLoads&lt;\/key&gt;\n                &lt;true\/&gt;\n                &lt;key&gt;NSExceptionMinimumTLSVersion&lt;\/key&gt;\n                &lt;string&gt;TLSv1.0&lt;\/string&gt;\n            &lt;\/dict&gt;\n        &lt;\/dict&gt;\n    &lt;\/dict&gt;\n\n    &lt;!-- Deep Link \uc124\uc815 --&gt;\n    &lt;key&gt;CFBundleURLTypes&lt;\/key&gt;\n    &lt;array&gt;\n        &lt;dict&gt;\n            &lt;key&gt;CFBundleURLName&lt;\/key&gt;\n            &lt;string&gt;your-app-scheme&lt;\/string&gt;\n            &lt;key&gt;CFBundleURLSchemes&lt;\/key&gt;\n            &lt;array&gt;\n                &lt;string&gt;yourapp&lt;\/string&gt;\n            &lt;\/array&gt;\n        &lt;\/dict&gt;\n    &lt;\/array&gt;\n\n    &lt;!-- App Tracking Transparency (iOS 14.5+) --&gt;\n    &lt;key&gt;NSUserTrackingUsageDescription&lt;\/key&gt;\n    &lt;string&gt;\uc774 \uc571\uc740 \ub354 \ub098\uc740 \uad11\uace0 \uacbd\ud5d8\uc744 \uc81c\uacf5\ud558\uae30 \uc704\ud574 \ucd94\uc801 \uad8c\ud55c\uc744 \uc694\uccad\ud569\ub2c8\ub2e4.&lt;\/string&gt;\n&lt;\/dict&gt;\n&lt;\/plist&gt;<\/code><\/pre>\n\n\n\n<p><strong>\ud83d\udea8 \uc911\uc694<\/strong>: iOS\uc5d0\uc11c\ub294 \uad8c\ud55c \uc0ac\uc6a9 \uc774\uc720\ub97c \ubc18\ub4dc\uc2dc \uba85\uc2dc\ud574\uc57c \ud569\ub2c8\ub2e4. \uc560\ub9e4\ud55c \uc124\uba85\uc740 \uc571\uc2a4\ud1a0\uc5b4 \ub9ac\ubdf0\uc5d0\uc11c \ub9ac\uc81d\ub2f9\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4!<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udd28 Xcode \ud504\ub85c\uc81d\ud2b8 \uc124\uc815<\/h3>\n\n\n\n<p>Xcode\uc5d0\uc11c \uc9c1\uc811 \uc124\uc815\ud574\uc57c \ud560 \ud56d\ubaa9\ub4e4:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Bundle Identifier<\/strong>: \uace0\uc720\ud55c \uc2dd\ubcc4\uc790 \uc124\uc815<\/li>\n\n\n\n<li><strong>Deployment Target<\/strong>: \ucd5c\uc18c iOS \ubc84\uc804 (12.0 \uc774\uc0c1 \uad8c\uc7a5)<\/li>\n\n\n\n<li><strong>Signing &amp; Capabilities<\/strong>: \uac1c\ubc1c\uc790 \uacc4\uc815 \uc5f0\uacb0<\/li>\n\n\n\n<li><strong>App Transport Security<\/strong>: HTTPS \ubcf4\uc548 \uc124\uc815<\/li>\n\n\n\n<li><strong>Background Modes<\/strong>: \ubc31\uadf8\ub77c\uc6b4\ub4dc \uc2e4\ud589 \uad8c\ud55c<\/li>\n<\/ol>\n\n\n\n<pre class=\"wp-block-code\"><code># Xcode\uc5d0\uc11c \ud504\ub85c\uc81d\ud2b8 \uc5f4\uae30\nopen ios\/Runner.xcworkspace<\/code><\/pre>\n\n\n\n<p><strong>\ud83d\udca1 Pro Tip<\/strong>: Xcode\uc5d0\uc11c \uc124\uc815\ud558\ub294 \ub0b4\uc6a9\ub4e4\uc740 \uc790\ub3d9\uc73c\ub85c \uad00\ub828 \ud30c\uc77c\ub4e4\uc5d0 \ubc18\uc601\ub429\ub2c8\ub2e4. \uac00\ub2a5\ud558\uba74 Xcode GUI\ub97c \ud1b5\ud574 \uc124\uc815\ud558\uc138\uc694.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">3\ufe0f\u20e3 pubspec.yaml: Flutter \ud504\ub85c\uc81d\ud2b8\uc758 \uc2ec\uc7a5<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udce6 \uae30\ubcf8 \uc124\uc815<\/h3>\n\n\n\n<p><code>pubspec.yaml<\/code>\uc740 Flutter \ud504\ub85c\uc81d\ud2b8\uc758 \ubaa8\ub4e0 \uc758\uc874\uc131\uacfc \uc124\uc815\uc744 \uad00\ub9ac\ud558\ub294 \ud575\uc2ec \ud30c\uc77c\uc785\ub2c8\ub2e4.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>name: your_app\ndescription: A new Flutter project.\npublish_to: 'none' # \ud328\ud0a4\uc9c0\ub85c \ubc30\ud3ec\ud558\uc9c0 \uc54a\uc74c\n\n# \ubc84\uc804 \uc815\ubcf4\nversion: 1.0.0+1\n\n# \ud658\uacbd \uc124\uc815\nenvironment:\n  sdk: '&gt;=3.0.0 &lt;4.0.0'\n  flutter: \"&gt;=3.10.0\"\n\n# \uc758\uc874\uc131\ndependencies:\n  flutter:\n    sdk: flutter\n\n  # UI \ucef4\ud3ec\ub10c\ud2b8\n  cupertino_icons: ^1.0.6  # iOS \uc2a4\ud0c0\uc77c \uc544\uc774\ucf58\n\n  # \uc0c1\ud0dc \uad00\ub9ac (\uc120\ud0dd: riverpod OR bloc OR provider)\n  flutter_riverpod: ^2.4.9\n  # flutter_bloc: ^8.1.3\n  # provider: ^6.1.1\n\n  # \ub124\ud2b8\uc6cc\ud0b9\n  dio: ^5.4.0  # HTTP \ud074\ub77c\uc774\uc5b8\ud2b8 (http\ubcf4\ub2e4 \uae30\ub2a5\uc774 \ud48d\ubd80)\n  retrofit: ^4.0.3  # REST API \ud074\ub77c\uc774\uc5b8\ud2b8 \uc0dd\uc131\n\n  # \ub85c\uceec \uc800\uc7a5\uc18c\n  shared_preferences: ^2.2.2  # \uac04\ub2e8\ud55c \ud0a4-\uac12 \uc800\uc7a5\n  hive: ^2.2.3  # NoSQL \ub85c\uceec \ub370\uc774\ud130\ubca0\uc774\uc2a4\n  hive_flutter: ^1.1.0\n\n  # \uc720\ud2f8\ub9ac\ud2f0\n  get_it: ^7.6.7  # \uc758\uc874\uc131 \uc8fc\uc785\n  injectable: ^2.3.2  # \ucf54\ub4dc \uc0dd\uc131 \uae30\ubc18 DI\n  auto_route: ^7.9.2  # \uc790\ub3d9 \ub77c\uc6b0\ud305 \uc0dd\uc131\n\n  # JSON \uc9c1\ub82c\ud654\n  json_annotation: ^4.8.1\n  freezed_annotation: ^2.4.1\n\n  # \ud658\uacbd \ubcc0\uc218\n  flutter_dotenv: ^5.1.0\n\n  # \ub124\uc774\ud2f0\ube0c \uae30\ub2a5\n  permission_handler: ^11.2.0  # \uad8c\ud55c \uad00\ub9ac\n  device_info_plus: ^9.1.1  # \ub514\ubc14\uc774\uc2a4 \uc815\ubcf4\n  package_info_plus: ^4.2.0  # \uc571 \uc815\ubcf4\n  url_launcher: ^6.2.2  # \uc678\ubd80 \ub9c1\ud06c \uc5f4\uae30\n\n  # \uc774\ubbf8\uc9c0 &amp; \ubbf8\ub514\uc5b4\n  cached_network_image: ^3.3.0  # \uc774\ubbf8\uc9c0 \uce90\uc2f1\n  image_picker: ^1.0.5  # \uc774\ubbf8\uc9c0 \uc120\ud0dd\n  photo_view: ^0.14.0  # \uc774\ubbf8\uc9c0 \ud655\ub300\/\ucd95\uc18c\n  video_player: ^2.8.1  # \ube44\ub514\uc624 \uc7ac\uc0dd\n\n  # Firebase (\ud544\uc694\ud55c \uac83\ub9cc \uc120\ud0dd)\n  firebase_core: ^2.24.2\n  firebase_auth: ^4.15.3\n  cloud_firestore: ^4.13.6\n  firebase_storage: ^11.5.6\n  firebase_messaging: ^14.7.10\n  firebase_analytics: ^10.7.4\n  firebase_crashlytics: ^3.4.8\n\n  # \uc18c\uc15c \ub85c\uadf8\uc778\n  google_sign_in: ^6.1.6\n  sign_in_with_apple: ^5.0.0\n  # flutter_facebook_auth: ^6.0.3\n\n  # UI \ub77c\uc774\ube0c\ub7ec\ub9ac\n  flutter_svg: ^2.0.9  # SVG \uc774\ubbf8\uc9c0\n  lottie: ^2.7.0  # Lottie \uc560\ub2c8\uba54\uc774\uc158\n  shimmer: ^3.0.0  # \ub85c\ub529 \ud6a8\uacfc\n  flutter_staggered_grid_view: ^0.7.0  # \uadf8\ub9ac\ub4dc \ubdf0\n\n  # \uc720\ud2f8\ub9ac\ud2f0 \uc704\uc82f\n  gap: ^3.0.1  # \uac04\uaca9 \uc704\uc82f\n  flutter_screenutil: ^5.9.0  # \ubc18\uc751\ud615 UI\n\n  # \uae30\ud0c0\n  intl: ^0.19.0  # \uad6d\uc81c\ud654\n  equatable: ^2.0.5  # \uac12 \ube44\uad50 \uc720\ud2f8\ub9ac\ud2f0\n\n# \uac1c\ubc1c \uc758\uc874\uc131\ndev_dependencies:\n  flutter_test:\n    sdk: flutter\n\n  # \ub9b0\ud305\n  flutter_lints: ^3.0.1\n  very_good_analysis: ^5.1.0  # \ub354 \uc5c4\uaca9\ud55c \ub9b0\ud2b8 \uaddc\uce59\n\n  # \ucf54\ub4dc \uc0dd\uc131\n  build_runner: ^2.4.7\n  freezed: ^2.4.6\n  json_serializable: ^6.7.1\n  retrofit_generator: ^8.0.4\n  injectable_generator: ^2.4.1\n  auto_route_generator: ^7.3.2\n  hive_generator: ^2.0.1\n\n  # \ud14c\uc2a4\ud305\n  mockito: ^5.4.4\n  integration_test:\n    sdk: flutter\n\n# Flutter \uc124\uc815\nflutter:\n  uses-material-design: true\n\n  # \ub9ac\uc18c\uc2a4 \ud30c\uc77c\n  assets:\n    - assets\/images\/\n    - assets\/icons\/\n    - assets\/animations\/\n    - .env\n    - .env.dev\n    - .env.prod\n\n  # \ud3f0\ud2b8\n  fonts:\n    - family: Pretendard\n      fonts:\n        - asset: assets\/fonts\/Pretendard-Regular.ttf\n          weight: 400\n        - asset: assets\/fonts\/Pretendard-Medium.ttf\n          weight: 500\n        - asset: assets\/fonts\/Pretendard-SemiBold.ttf\n          weight: 600\n        - asset: assets\/fonts\/Pretendard-Bold.ttf\n          weight: 700<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83c\udfa8 \ub9ac\uc18c\uc2a4 \uad00\ub9ac \uc804\ub7b5<\/h3>\n\n\n\n<p>\ud504\ub85c\uc81d\ud2b8\uc5d0\uc11c \uc0ac\uc6a9\ud560 \ub9ac\uc18c\uc2a4\ub4e4\uc744 \uccb4\uacc4\uc801\uc73c\ub85c \uad00\ub9ac\ud558\uc138\uc694:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>assets\/\n\u251c\u2500\u2500 images\/\n\u2502   \u251c\u2500\u2500 logos\/\n\u2502   \u251c\u2500\u2500 icons\/\n\u2502   \u251c\u2500\u2500 illustrations\/\n\u2502   \u2514\u2500\u2500 backgrounds\/\n\u251c\u2500\u2500 animations\/\n\u2502   \u2514\u2500\u2500 loading.json\n\u251c\u2500\u2500 fonts\/\n\u2502   \u2514\u2500\u2500 Pretendard\/\n\u2514\u2500\u2500 configs\/\n    \u251c\u2500\u2500 .env\n    \u251c\u2500\u2500 .env.dev\n    \u2514\u2500\u2500 .env.prod<\/code><\/pre>\n\n\n\n<p><strong>\ud658\uacbd \ubcc0\uc218 \uad00\ub9ac (.env \ud30c\uc77c)<\/strong>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># .env.dev\nAPI_BASE_URL=https:\/\/dev-api.yourapp.com\nGOOGLE_MAPS_API_KEY=your_dev_api_key\nFIREBASE_PROJECT_ID=your-dev-project\n\n# .env.prod\nAPI_BASE_URL=https:\/\/api.yourapp.com\nGOOGLE_MAPS_API_KEY=your_prod_api_key\nFIREBASE_PROJECT_ID=your-prod-project<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">4\ufe0f\u20e3 \ud544\uc218 \ud328\ud0a4\uc9c0 \ubbf8\ub9ac \uc138\ud305: \ubbf8\ub798\uc758 \ub098\ub97c \uc704\ud55c \ud22c\uc790<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83c\udfaf \ud328\ud0a4\uc9c0 \uc120\ud0dd \uac00\uc774\ub4dc<\/h3>\n\n\n\n<p>\ud504\ub85c\uc81d\ud2b8 \uc720\ud615\ubcc4\ub85c \ud544\uc694\ud55c \ud328\ud0a4\uc9c0\ub4e4\uc744 \uc815\ub9ac\ud574\ubd24\uc2b5\ub2c8\ub2e4:<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udcf1 \ubaa8\ub4e0 \ud504\ub85c\uc81d\ud2b8 \uacf5\ud1b5 (\ud544\uc218)<\/h4>\n\n\n\n<pre class=\"wp-block-code\"><code># \uc0c1\ud0dc \uad00\ub9ac\nflutter_riverpod: ^2.4.9  # \ub610\ub294 bloc, provider \uc911 \uc120\ud0dd\n\n# \ub124\ud2b8\uc6cc\ud0b9\ndio: ^5.4.0\n\n# \ub85c\uceec \uc800\uc7a5\uc18c\nshared_preferences: ^2.2.2\n\n# \uad8c\ud55c \uad00\ub9ac\npermission_handler: ^11.2.0\n\n# \ud658\uacbd \ubcc0\uc218\nflutter_dotenv: ^5.1.0\n\n# JSON \ucc98\ub9ac\njson_annotation: ^4.8.1\nfreezed_annotation: ^2.4.1<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\uded2 E-\ucee4\uba38\uc2a4\/\uc18c\uc15c \uc571<\/h4>\n\n\n\n<pre class=\"wp-block-code\"><code># \uc778\uc99d\nfirebase_auth: ^4.15.3\ngoogle_sign_in: ^6.1.6\nsign_in_with_apple: ^5.0.0\n\n# \uc774\ubbf8\uc9c0 \ucc98\ub9ac\ncached_network_image: ^3.3.0\nimage_picker: ^1.0.5\n\n# \ud478\uc2dc \uc54c\ub9bc\nfirebase_messaging: ^14.7.10\n\n# \uacb0\uc81c\n# in_app_purchase: ^3.1.11<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udccd \uc704\uce58 \uae30\ubc18 \uc11c\ube44\uc2a4<\/h4>\n\n\n\n<pre class=\"wp-block-code\"><code># \uc704\uce58\ngeolocator: ^10.1.0\ngeocoding: ^2.1.1\n\n# \uc9c0\ub3c4\ngoogle_maps_flutter: ^2.5.0<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83c\udfb5 \ubbf8\ub514\uc5b4 \uc571<\/h4>\n\n\n\n<pre class=\"wp-block-code\"><code># \ubbf8\ub514\uc5b4\nvideo_player: ^2.8.1\naudio_players: ^5.2.1\ncamera: ^0.10.5+5\n\n# \ud30c\uc77c \ucc98\ub9ac\nfile_picker: ^6.1.1\npath_provider: ^2.1.2<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udcda \ud328\ud0a4\uc9c0 \uad00\ub9ac \ud301<\/h3>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>\ubc84\uc804 \ud638\ud658\uc131 \ud655\uc778<\/strong>: <code>flutter pub deps<\/code> \uba85\ub839\uc5b4\ub85c \uc758\uc874\uc131 \ud2b8\ub9ac \ud655\uc778<\/li>\n\n\n\n<li><strong>\uc815\uae30\uc801\uc778 \uc5c5\ub370\uc774\ud2b8<\/strong>: <code>flutter pub upgrade<\/code> \ud558\ub418 \uba54\uc774\uc800 \uc5c5\ub370\uc774\ud2b8\ub294 \uc2e0\uc911\ud788<\/li>\n\n\n\n<li><strong>\ubd88\ud544\uc694\ud55c \ud328\ud0a4\uc9c0 \uc81c\uac70<\/strong>: \uc0ac\uc6a9\ud558\uc9c0 \uc54a\ub294 \ud328\ud0a4\uc9c0\ub294 \uacfc\uac10\ud788 \uc81c\uac70<\/li>\n\n\n\n<li><strong>\ub77c\uc774\uc120\uc2a4 \ud655\uc778<\/strong>: \uc0c1\uc5c5\uc801 \uc0ac\uc6a9 \uac00\ub2a5\ud55c \ub77c\uc774\uc120\uc2a4\uc778\uc9c0 \ud655\uc778<\/li>\n<\/ol>\n\n\n\n<pre class=\"wp-block-code\"><code># \ud328\ud0a4\uc9c0 \ucd94\uac00\nflutter pub add package_name\n\n# \uac1c\ubc1c \uc758\uc874\uc131 \ucd94\uac00  \nflutter pub add --dev package_name\n\n# \ud2b9\uc815 \ubc84\uc804 \uc9c0\uc815\nflutter pub add package_name:^1.0.0\n\n# \uc758\uc874\uc131 \ud655\uc778\nflutter pub deps\n\n# \uc624\ub798\ub41c \ud328\ud0a4\uc9c0 \ud655\uc778\nflutter pub outdated<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">5\ufe0f\u20e3 \uad8c\ud55c \ubc0f \ubcf4\uc548 \uc124\uc815: \uc571\uc2a4\ud1a0\uc5b4 \uc2b9\uc778\uc758 \uc9c0\ub984\uae38<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udd10 iOS App Tracking Transparency (iOS 14.5+)<\/h3>\n\n\n\n<p>iOS 14.5\ubd80\ud130\ub294 \uc0ac\uc6a9\uc790 \ucd94\uc801\uc744 \uc704\ud55c \uba85\uc2dc\uc801 \uad8c\ud55c \uc694\uccad\uc774 \ud544\uc694\ud569\ub2c8\ub2e4:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import 'package:app_tracking_transparency\/app_tracking_transparency.dart';\nimport 'package:permission_handler\/permission_handler.dart';\n\nclass AppInitializer {\n  static Future&lt;void&gt; initialize() async {\n    WidgetsFlutterBinding.ensureInitialized();\n\n    \/\/ App Tracking Transparency \uad8c\ud55c \uc694\uccad\n    if (Platform.isIOS) {\n      await _requestTrackingPermission();\n    }\n\n    \/\/ \uc54c\ub9bc \uad8c\ud55c \uc694\uccad\n    await _requestNotificationPermission();\n\n    \/\/ \uae30\ud0c0 \ucd08\uae30\ud654 \uc791\uc5c5...\n  }\n\n  static Future&lt;void&gt; _requestTrackingPermission() async {\n    final status = await AppTrackingTransparency.trackingAuthorizationStatus;\n\n    if (status == TrackingStatus.notDetermined) {\n      \/\/ \ucee4\uc2a4\ud140 \ub2e4\uc774\uc5bc\ub85c\uadf8 \ud45c\uc2dc (\uc120\ud0dd\uc0ac\ud56d)\n      await _showTrackingDialog();\n\n      \/\/ \uc2dc\uc2a4\ud15c \uad8c\ud55c \uc694\uccad\n      await AppTrackingTransparency.requestTrackingAuthorization();\n    }\n  }\n\n  static Future&lt;void&gt; _showTrackingDialog() async {\n    \/\/ \uc0ac\uc6a9\uc790\uc5d0\uac8c \ucd94\uc801 \uad8c\ud55c\uc758 \ud544\uc694\uc131\uc744 \uc124\uba85\ud558\ub294 \ucee4\uc2a4\ud140 \ub2e4\uc774\uc5bc\ub85c\uadf8\n    return showDialog(\n      context: navigatorKey.currentContext!,\n      builder: (context) =&gt; AlertDialog(\n        title: Text('\uac1c\uc778\ud654\ub41c \uad11\uace0'),\n        content: Text(\n          '\ub354 \ub098\uc740 \uc571 \uacbd\ud5d8\uc744 \uc704\ud574 \ub2e4\ub978 \ud68c\uc0ac\uc758 \uc571\uacfc \uc6f9\uc0ac\uc774\ud2b8\uc5d0\uc11c \ud68c\uc6d0\ub2d8\uc758 \ud65c\ub3d9\uc744 \ucd94\uc801\ud558\ub3c4\ub85d \ud5c8\uc6a9\ud558\uc2dc\uaca0\uc2b5\ub2c8\uae4c?'\n        ),\n        actions: &#91;\n          TextButton(\n            onPressed: () =&gt; Navigator.pop(context),\n            child: Text('\uacc4\uc18d'),\n          ),\n        ],\n      ),\n    );\n  }\n\n  static Future&lt;void&gt; _requestNotificationPermission() async {\n    final status = await Permission.notification.status;\n\n    if (status.isDenied) {\n      await Permission.notification.request();\n    }\n  }\n}\n\n\/\/ main.dart\nvoid main() async {\n  await AppInitializer.initialize();\n  runApp(MyApp());\n}<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udee1\ufe0f \ub124\ud2b8\uc6cc\ud06c \ubcf4\uc548 \uc124\uc815<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">Android Network Security Config<\/h4>\n\n\n\n<p><code>android\/app\/src\/main\/res\/xml\/network_security_config.xml<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;?xml version=\"1.0\" encoding=\"utf-8\"?&gt;\n&lt;network-security-config&gt;\n    &lt;domain-config cleartextTrafficPermitted=\"false\"&gt;\n        &lt;domain includeSubdomains=\"true\"&gt;your-api-domain.com&lt;\/domain&gt;\n        &lt;pin-set expiration=\"2025-12-31\"&gt;\n            &lt;pin digest=\"SHA-256\"&gt;AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=&lt;\/pin&gt;\n            &lt;pin digest=\"SHA-256\"&gt;BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB=&lt;\/pin&gt;\n        &lt;\/pin-set&gt;\n    &lt;\/domain-config&gt;\n\n    &lt;!-- \uac1c\ubc1c \ud658\uacbd\uc5d0\uc11c\ub9cc \ud5c8\uc6a9 --&gt;\n    &lt;domain-config cleartextTrafficPermitted=\"true\"&gt;\n        &lt;domain includeSubdomains=\"true\"&gt;localhost&lt;\/domain&gt;\n        &lt;domain includeSubdomains=\"true\"&gt;10.0.2.2&lt;\/domain&gt;\n    &lt;\/domain-config&gt;\n&lt;\/network-security-config&gt;<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">iOS App Transport Security<\/h4>\n\n\n\n<p>\uac1c\ubc1c \ub2e8\uacc4\uc5d0\uc11c\ub294 \uc784\uc2dc\ub85c HTTP\ub97c \ud5c8\uc6a9\ud558\ub418, \ud504\ub85c\ub355\uc158\uc5d0\uc11c\ub294 \ubc18\ub4dc\uc2dc HTTPS\ub9cc \uc0ac\uc6a9:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;!-- \uac1c\ubc1c \uc2dc \uc784\uc2dc \uc124\uc815 --&gt;\n&lt;key&gt;NSAppTransportSecurity&lt;\/key&gt;\n&lt;dict&gt;\n    &lt;key&gt;NSAllowsArbitraryLoads&lt;\/key&gt;\n    &lt;true\/&gt;\n&lt;\/dict&gt;\n\n&lt;!-- \ud504\ub85c\ub355\uc158 \uad8c\uc7a5 \uc124\uc815 --&gt;\n&lt;key&gt;NSAppTransportSecurity&lt;\/key&gt;\n&lt;dict&gt;\n    &lt;key&gt;NSAllowsArbitraryLoads&lt;\/key&gt;\n    &lt;false\/&gt;\n    &lt;key&gt;NSExceptionDomains&lt;\/key&gt;\n    &lt;dict&gt;\n        &lt;key&gt;your-api-domain.com&lt;\/key&gt;\n        &lt;dict&gt;\n            &lt;key&gt;NSExceptionRequiresForwardSecrecy&lt;\/key&gt;\n            &lt;false\/&gt;\n            &lt;key&gt;NSExceptionMinimumTLSVersion&lt;\/key&gt;\n            &lt;string&gt;TLSv1.2&lt;\/string&gt;\n        &lt;\/dict&gt;\n    &lt;\/dict&gt;\n&lt;\/dict&gt;<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udd11 API \ud0a4 \ubcf4\uc548 \uad00\ub9ac<\/h3>\n\n\n\n<p>\uc808\ub300 API \ud0a4\ub97c \ucf54\ub4dc\uc5d0 \ud558\ub4dc\ucf54\ub529\ud558\uc9c0 \ub9c8\uc138\uc694!<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ \u274c \uc798\ubabb\ub41c \ubc29\ubc95\nconst String apiKey = \"AIzaSyB123456789\";\n\n\/\/ \u2705 \uc62c\ubc14\ub978 \ubc29\ubc95\nclass ApiConfig {\n  static String get googleMapsApiKey {\n    return dotenv.env&#91;'GOOGLE_MAPS_API_KEY'] ?? '';\n  }\n\n  static String get firebaseApiKey {\n    return dotenv.env&#91;'FIREBASE_API_KEY'] ?? '';\n  }\n}\n\n\/\/ \ud658\uacbd\ubcc4 \uc124\uc815 \ub85c\ub4dc\nFuture&lt;void&gt; loadEnvConfig() async {\n  const flavor = String.fromEnvironment('FLAVOR', defaultValue: 'dev');\n\n  switch (flavor) {\n    case 'prod':\n      await dotenv.load(fileName: '.env.prod');\n      break;\n    case 'staging':\n      await dotenv.load(fileName: '.env.staging');\n      break;\n    default:\n      await dotenv.load(fileName: '.env.dev');\n  }\n}<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">6\ufe0f\u20e3 \ud504\ub85c\uc81d\ud2b8 \uad6c\uc870 &amp; \uc544\ud0a4\ud14d\ucc98 \uc124\uc815<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udcc1 \ucd94\ucc9c \ud3f4\ub354 \uad6c\uc870<\/h3>\n\n\n\n<p>\ud655\uc7a5 \uac00\ub2a5\ud558\uace0 \uc720\uc9c0\ubcf4\uc218\ud558\uae30 \uc26c\uc6b4 \ud3f4\ub354 \uad6c\uc870\ub97c \uc124\uc815\ud558\uc138\uc694:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>lib\/\n\u251c\u2500\u2500 main.dart\n\u251c\u2500\u2500 app\/\n\u2502   \u251c\u2500\u2500 app.dart                 # \uc571 \uc9c4\uc785\uc810\n\u2502   \u251c\u2500\u2500 router\/                  # \ub77c\uc6b0\ud305 \uc124\uc815\n\u2502   \u251c\u2500\u2500 theme\/                   # \ud14c\ub9c8 \uc124\uc815\n\u2502   \u2514\u2500\u2500 constants\/               # \uc571 \uc0c1\uc218\n\u251c\u2500\u2500 core\/\n\u2502   \u251c\u2500\u2500 error\/                   # \uc5d0\ub7ec \ucc98\ub9ac\n\u2502   \u251c\u2500\u2500 network\/                 # \ub124\ud2b8\uc6cc\ud06c \uc124\uc815\n\u2502   \u251c\u2500\u2500 utils\/                   # \uc720\ud2f8\ub9ac\ud2f0 \ud568\uc218\n\u2502   \u2514\u2500\u2500 di\/                      # \uc758\uc874\uc131 \uc8fc\uc785\n\u251c\u2500\u2500 features\/\n\u2502   \u251c\u2500\u2500 auth\/\n\u2502   \u2502   \u251c\u2500\u2500 data\/               # \ub370\uc774\ud130 \ub808\uc774\uc5b4\n\u2502   \u2502   \u251c\u2500\u2500 domain\/             # \ube44\uc988\ub2c8\uc2a4 \ub85c\uc9c1\n\u2502   \u2502   \u2514\u2500\u2500 presentation\/       # UI \ub808\uc774\uc5b4\n\u2502   \u251c\u2500\u2500 home\/\n\u2502   \u2514\u2500\u2500 profile\/\n\u251c\u2500\u2500 shared\/\n\u2502   \u251c\u2500\u2500 widgets\/                # \uacf5\ud1b5 \uc704\uc82f\n\u2502   \u251c\u2500\u2500 models\/                 # \uacf5\ud1b5 \ubaa8\ub378\n\u2502   \u2514\u2500\u2500 services\/               # \uacf5\ud1b5 \uc11c\ube44\uc2a4\n\u2514\u2500\u2500 generated\/                  # \uc790\ub3d9 \uc0dd\uc131 \ud30c\uc77c<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83c\udfd7\ufe0f Clean Architecture \uae30\ubcf8 \uc124\uc815<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ core\/di\/injection.dart\n@InjectableInit()\nFuture&lt;void&gt; configureDependencies() async =&gt; getIt.init();\n\nfinal getIt = GetIt.instance;\n\n\/\/ main.dart\nvoid main() async {\n  WidgetsFlutterBinding.ensureInitialized();\n\n  \/\/ \ud658\uacbd \uc124\uc815 \ub85c\ub4dc\n  await loadEnvConfig();\n\n  \/\/ \uc758\uc874\uc131 \uc8fc\uc785 \uc124\uc815\n  await configureDependencies();\n\n  \/\/ Hive \ucd08\uae30\ud654\n  await Hive.initFlutter();\n\n  \/\/ Firebase \ucd08\uae30\ud654\n  if (Firebase.apps.isEmpty) {\n    await Firebase.initializeApp(\n      options: DefaultFirebaseOptions.currentPlatform,\n    );\n  }\n\n  runApp(\n    ProviderScope(\n      child: MyApp(),\n    ),\n  );\n}<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">7\ufe0f\u20e3 \ub514\ubc84\uae45 &amp; \uac1c\ubc1c \ub3c4\uad6c \uc124\uc815<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udd27 \uac1c\ubc1c \ud658\uacbd \ucd5c\uc801\ud654<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ core\/utils\/logger.dart\nimport 'package:logger\/logger.dart';\n\nclass AppLogger {\n  static final _logger = Logger(\n    printer: PrettyPrinter(\n      methodCount: 2,\n      errorMethodCount: 8,\n      lineLength: 120,\n      colors: true,\n      printEmojis: true,\n      printTime: true,\n    ),\n  );\n\n  static void d(String message) =&gt; _logger.d(message);\n  static void i(String message) =&gt; _logger.i(message);\n  static void w(String message) =&gt; _logger.w(message);\n  static void e(String message, &#91;dynamic error, StackTrace? stackTrace]) {\n    _logger.e(message, error, stackTrace);\n  }\n}\n\n\/\/ Firebase Crashlytics \uc5f0\ub3d9\nclass CrashReporter {\n  static Future&lt;void&gt; recordError(\n    dynamic exception,\n    StackTrace? stack, {\n    bool fatal = false,\n  }) async {\n    await FirebaseCrashlytics.instance.recordError(\n      exception,\n      stack,\n      fatal: fatal,\n    );\n  }\n\n  static Future&lt;void&gt; log(String message) async {\n    await FirebaseCrashlytics.instance.log(message);\n  }\n}<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udcca \uc571 \uc131\ub2a5 \ubaa8\ub2c8\ud130\ub9c1<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ core\/services\/performance_service.dart\nclass PerformanceService {\n  static Future&lt;void&gt; startTrace(String traceName) async {\n    final trace = FirebasePerformance.instance.newTrace(traceName);\n    await trace.start();\n  }\n\n  static Future&lt;void&gt; stopTrace(String traceName) async {\n    final trace = FirebasePerformance.instance.newTrace(traceName);\n    await trace.stop();\n  }\n\n  static Future&lt;void&gt; recordNetworkRequest(\n    String url,\n    String method,\n    int responseCode,\n    int responseSize,\n  ) async {\n    final metric = FirebasePerformance.instance.newHttpMetric(url, HttpMethod.Get);\n    await metric.start();\n\n    metric.responseCode = responseCode;\n    metric.responsePayloadSize = responseSize;\n\n    await metric.stop();\n  }\n}<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">8\ufe0f\u20e3 \ubc30\ud3ec \uc900\ube44: \ud55c \ubc88\uc5d0 \uc131\uacf5\ud558\ub294 \ubc30\ud3ec<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\ude80 \ubc30\ud3ec \uc804 \uccb4\ud06c\ub9ac\uc2a4\ud2b8<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>## Android \ubc30\ud3ec \uccb4\ud06c\ub9ac\uc2a4\ud2b8\n\n- &#91; ] \ud0a4\uc2a4\ud1a0\uc5b4 \uc0dd\uc131 \ubc0f \uc124\uc815 \uc644\ub8cc\n- &#91; ] \ud504\ub85c\uac00\ub4dc \uaddc\uce59 \uc124\uc815\n- &#91; ] \uc571 \uc11c\uba85 \ud655\uc778\n- &#91; ] \uad8c\ud55c \ucd5c\uc18c\ud654\n- &#91; ] APK\/AAB \ud06c\uae30 \ucd5c\uc801\ud654\n- &#91; ] 64\ube44\ud2b8 \uc544\ud0a4\ud14d\ucc98 \uc9c0\uc6d0 \ud655\uc778\n\n## iOS \ubc30\ud3ec \uccb4\ud06c\ub9ac\uc2a4\ud2b8\n\n- &#91; ] Apple Developer \uacc4\uc815 \ub4f1\ub85d\n- &#91; ] Bundle ID \ub4f1\ub85d\n- &#91; ] \uc778\uc99d\uc11c \ubc0f \ud504\ub85c\ube44\uc800\ub2dd \ud504\ub85c\ud30c\uc77c \uc0dd\uc131\n- &#91; ] App Store Connect \uc571 \ub4f1\ub85d\n- &#91; ] \uad8c\ud55c \uc0ac\uc6a9 \uc774\uc720 \uba85\uc2dc\n- &#91; ] ATS (App Transport Security) \uc124\uc815\n\n## \uacf5\ud1b5 \uccb4\ud06c\ub9ac\uc2a4\ud2b8\n\n- &#91; ] \uc571 \uc544\uc774\ucf58 \uc124\uc815 (\ubaa8\ub4e0 \uc0ac\uc774\uc988)\n- &#91; ] \uc2a4\ud50c\ub798\uc2dc \uc2a4\ud06c\ub9b0 \uc124\uc815\n- &#91; ] \uc571 \uc774\ub984 \ubc0f \uc124\uba85 \ub2e4\uad6d\uc5b4 \uc9c0\uc6d0\n- &#91; ] \uac1c\uc778\uc815\ubcf4 \ubcf4\ud638\uc815\ucc45 URL \uc124\uc815\n- &#91; ] \ud14c\uc2a4\ud2b8 \ub514\ubc14\uc774\uc2a4\uc5d0\uc11c \ucd5c\uc885 \ud655\uc778\n- &#91; ] \uc131\ub2a5 \ucd5c\uc801\ud654 \ud655\uc778\n- &#91; ] \ud06c\ub798\uc2dc \uc5c6\ub294\uc9c0 \ud655\uc778<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udd27 \ube4c\ub4dc \ucd5c\uc801\ud654 \uc124\uc815<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ \ub9b4\ub9ac\uc988 \ube4c\ub4dc \ucd5c\uc801\ud654\nflutter build apk --release --shrink --obfuscate --split-debug-info=build\/debug-info\n\nflutter build ios --release --obfuscate --split-debug-info=build\/debug-info<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">\ud83c\udf89 \ub9c8\ubb34\ub9ac: \uc131\uacf5\uc801\uc778 Flutter \ud504\ub85c\uc81d\ud2b8\uc758 \uc2dc\uc791<\/h2>\n\n\n\n<p>\ucd95\ud558\ud569\ub2c8\ub2e4! \ud83c\udf8a \uc774\uc81c \uc5ec\ub7ec\ubd84\uc740 Flutter \ud504\ub85c\uc81d\ud2b8\ub97c \uc2dc\uc791\ud558\uae30 \uc804\uc5d0 \ud655\uc778\ud574\uc57c \ud560 \ubaa8\ub4e0 \ud575\uc2ec \uc0ac\ud56d\ub4e4\uc744 \uc219\uc9c0\ud558\uc168\uc2b5\ub2c8\ub2e4.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udccb \ucd5c\uc885 \uc810\uac80 \uc694\uc57d<\/h3>\n\n\n\n<ol class=\"wp-block-list\">\n<li>\u2705 <strong>Android \uc124\uc815<\/strong>: Manifest, Gradle, \ud0a4\uc2a4\ud1a0\uc5b4<\/li>\n\n\n\n<li>\u2705 <strong>iOS \uc124\uc815<\/strong>: info.plist, Xcode \ud504\ub85c\uc81d\ud2b8, \uc778\uc99d\uc11c<\/li>\n\n\n\n<li>\u2705 <strong>pubspec.yaml<\/strong>: \uc758\uc874\uc131, \ub9ac\uc18c\uc2a4, \ud658\uacbd \uc124\uc815<\/li>\n\n\n\n<li>\u2705 <strong>\ud544\uc218 \ud328\ud0a4\uc9c0<\/strong>: \ud504\ub85c\uc81d\ud2b8 \uc720\ud615\ubcc4 \ud328\ud0a4\uc9c0 \uc120\ud0dd<\/li>\n\n\n\n<li>\u2705 <strong>\uad8c\ud55c \ubc0f \ubcf4\uc548<\/strong>: \ud50c\ub7ab\ud3fc\ubcc4 \uad8c\ud55c, API \ud0a4 \uad00\ub9ac<\/li>\n\n\n\n<li>\u2705 <strong>\ud504\ub85c\uc81d\ud2b8 \uad6c\uc870<\/strong>: Clean Architecture \uae30\ubc18 \ud3f4\ub354 \uad6c\uc870<\/li>\n\n\n\n<li>\u2705 <strong>\uac1c\ubc1c \ub3c4\uad6c<\/strong>: \ub514\ubc84\uae45, \ub85c\uae45, \uc131\ub2a5 \ubaa8\ub2c8\ud130\ub9c1<\/li>\n\n\n\n<li>\u2705 <strong>\ubc30\ud3ec \uc900\ube44<\/strong>: \ud50c\ub7ab\ud3fc\ubcc4 \ubc30\ud3ec \uccb4\ud06c\ub9ac\uc2a4\ud2b8<\/li>\n<\/ol>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\ude80 \ub2e4\uc74c \ub2e8\uacc4<\/h3>\n\n\n\n<p>\uc774\uc81c \ubcf8\uaca9\uc801\uc778 \uac1c\ubc1c\uc5d0 \uc9d1\uc911\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4! \ub2e4\uc74c \uae00\uc5d0\uc11c\ub294:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Dart \uc5b8\uc5b4 \ud575\uc2ec \uac1c\ub150 \ub9c8\uc2a4\ud130\ud558\uae30<\/strong><\/li>\n\n\n\n<li><strong>Flutter \uc704\uc82f \uc2dc\uc2a4\ud15c \uc644\uc804 \uc815\ubcf5<\/strong>  <\/li>\n\n\n\n<li><strong>\uc0c1\ud0dc \uad00\ub9ac \ud328\ud134 \ube44\uad50 \ubc0f \uc120\ud0dd \uac00\uc774\ub4dc<\/strong><\/li>\n\n\n\n<li><strong>\uc2e4\uc804 API \uc5f0\ub3d9 \ubc0f \uc5d0\ub7ec \ucc98\ub9ac<\/strong><\/li>\n<\/ul>\n\n\n\n<p>\ub4f1\uc758 \uc8fc\uc81c\ub85c \ub354 \uae4a\uc774 \uc788\ub294 \ub0b4\uc6a9\uc744 \ub2e4\ub8f0 \uc608\uc815\uc785\ub2c8\ub2e4.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udcac \ucee4\ubba4\ub2c8\ud2f0\uc640 \ud568\uaed8 \uc131\uc7a5\ud558\uae30<\/h3>\n\n\n\n<p>Flutter \uac1c\ubc1c \uc5ec\uc815\uc5d0\uc11c \ub9c9\ud788\ub294 \ubd80\ubd84\uc774 \uc788\ub2e4\uba74:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/flutter.dev\/docs\">Flutter \uacf5\uc2dd \ubb38\uc11c<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/flutter-korea.slack.com\">Flutter \ud55c\uad6d \uac1c\ubc1c\uc790 \ucee4\ubba4\ub2c8\ud2f0<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/stackoverflow.com\/questions\/tagged\/flutter\">Stack Overflow Flutter \ud0dc\uadf8<\/a><\/li>\n<\/ul>\n\n\n\n<p>\ud63c\uc790\uc11c\ub294 \uc5b4\ub824\uc6b4 \uae38\uc774\uc9c0\ub9cc, \ud568\uaed8\ub77c\uba74 \ub354 \uc990\uac81\uace0 \ube60\ub974\uac8c \uc131\uc7a5\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4! <\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<p><strong>\uc990\uac70\uc6b4 Flutter \uac1c\ubc1c \ub418\uc138\uc694! \ud83d\ude80<\/strong><\/p>\n\n\n\n<p><em>\uc774 \uae00\uc774 \ub3c4\uc6c0\uc774 \ub418\uc168\ub2e4\uba74 \uc88b\uc544\uc694 \ud83d\udc4d\uc640 \uacf5\uc720 \ud83d\udce4 \ubd80\ud0c1\ub4dc\ub9bd\ub2c8\ub2e4!<\/em><\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udcda \ucc38\uace0 \uc790\ub8cc<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/flutter.dev\/docs\">Flutter \uacf5\uc2dd \ubb38\uc11c<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/dart.dev\/guides\/language\">Dart \uc5b8\uc5b4 \uac00\uc774\ub4dc<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/firebase.flutter.dev\/\">Firebase Flutter \uc124\uc815 \uac00\uc774\ub4dc<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/developer.android.com\/guide\">Android \uac1c\ubc1c\uc790 \uac00\uc774\ub4dc<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/developer.apple.com\/documentation\/\">iOS \uac1c\ubc1c\uc790 \uac00\uc774\ub4dc<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Flutter \ud504\ub85c\uc81d\ud2b8 \uc2dc\uc791 \uc804 \ud544\uc218 \uccb4\ud06c\ub9ac\uc2a4\ud2b8 \ud83d\udccb \uc2e4\ubb34\uc5d0\uc11c \ubc14\ub85c \uc4f0\ub294 Flutter \ud504\ub85c\uc81d\ud2b8 \ucd08\uae30 \uc124\uc815 \uac00\uc774\ub4dc \ub354 \uc774\uc0c1 \ud504\ub85c\uc81d\ud2b8 \uc911\uac04\uc5d0 &#8220;\uc544, \uc774\uac78 \ucc98\uc74c\uc5d0 \uc124\uc815\ud588\uc5b4\uc57c \ud588\ub294\ub370&#8230;&#8221; \ud558\uc9c0 \ub9c8\uc138\uc694! \uc548\ub155\ud558\uc138\uc694! \ubaa8\ubc14\uc77c \uac1c\ubc1c\uc758 \uc0c8\ub85c\uc6b4 \ud328\ub7ec\ub2e4\uc784\uc778 Flutter\ub85c \uccab \ud504\ub85c\uc81d\ud2b8\ub97c \uc2dc\uc791\ud558\ub824\uace0 \ud558\uc2dc\ub098\uc694? Android\/iOS \ub124\uc774\ud2f0\ube0c \uac1c\ubc1c\uc744 \ud574\ubcf4\uc2e0 \ubd84\ub4e4\uc774\ub098 \uc6f9 \ud504\ub860\ud2b8\uc5d4\ub4dc\uc5d0\uc11c \ubaa8\ubc14\uc77c\ub85c \ud655\uc7a5\uc744 \uace0\ub824\ud558\uace0 \uacc4\uc2e0 \ubd84\ub4e4\uc5d0\uac8c &#8220;\ud504\ub85c\uc81d\ud2b8 \uc2dc\uc791 \uc804\uc5d0 \uc774\uac83\ub9cc\uc740 \uaf2d \ud655\uc778\ud558\uc790!&#8221;\ub294 \uc2e4\uc804 [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[43],"tags":[114,110,78,113,116,111,79,115,112,117,106],"class_list":["post-83","post","type-post","status-publish","format-standard","hentry","category-flutter","tag-android","tag-dart","tag-flutter","tag-ios","tag-116","tag-111","tag-79","tag-115","tag-112","tag-117","tag-106"],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/hed-g.me\/index.php?rest_route=\/wp\/v2\/posts\/83","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/hed-g.me\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/hed-g.me\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/hed-g.me\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/hed-g.me\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=83"}],"version-history":[{"count":2,"href":"https:\/\/hed-g.me\/index.php?rest_route=\/wp\/v2\/posts\/83\/revisions"}],"predecessor-version":[{"id":106,"href":"https:\/\/hed-g.me\/index.php?rest_route=\/wp\/v2\/posts\/83\/revisions\/106"}],"wp:attachment":[{"href":"https:\/\/hed-g.me\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=83"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/hed-g.me\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=83"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/hed-g.me\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=83"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}