2025. 10. 10. 00:19ㆍDevelopers 공간 [Shorts]/Frontend
<분류>
A. 수단
- OS/Platform/Tool : Linux, Kubernetes(k8s), Docker, AWS
- Package Manager : node.js, yarn, brew,
- Compiler/Transpillar : React, Nvcc, gcc/g++, Babel, Flutter
- Module Bundler : React, Webpack, Parcel
B. 언어
- C/C++, python, Javacsript, Typescript, Go-Lang, CUDA, Dart, HTML/CSS
C. 라이브러리 및 프레임워크 및 SDK
- OpenCV, OpenCL, FastAPI, PyTorch, Tensorflow, Nsight
1. What? (현상)
OAuth(Open Authorization)이란 사용자가 다른 웹사이트나 어플리케이션을 사용해 다른 서비스에서 동일한 자격으로 로그인 가능하도록 하거나, 웹 & 모바일 서비스에서 API를 보호하기 위해서 사용하는 개방형 표준(Protocol)입니다.

OAuth는 현재(2025.10.12) 2.1이 최신이며 이번 글에서는 OAuth 2.0에 대해서만 먼저 살펴보겠습니다.
** OAuth 2.0과 다르게 OAuth 1.0은 구현이 복잡하고 Web & Application 지원이 부족했습니다. 또한 Access Token이 만료되지 않았으며, 아래 설명한 객체 종류 중 Service Provider가 Resource와 Authorization으로 나눠있지 않는 등 다양한 점이 다릅니다.
OAuth 2.0을 살펴보기에 앞서 먼저 용어를 정의해보겠습니다.
- 객체 종류
- 서비스 공급자(Service Provider) Resource Server : 자원을 호스팅하는 서버
- 서비스 공급자(Service Provider) Authorization Server : 권한을 부여하는 서버
- 클라이언트(Client) : Resource Server에서 제공하는 자원을 활용하는 Application
- 사용자(User) : Resource를 가지게 될 사용자
- Code 및 Token 종류
- Authorization Code : Access Token을 받기 위한 조건으로, 일회성입니다.
- 엑세스 토큰(Access Token) : 사용자 인증 혹은 API 호출 권한 부여
** 유효 기간 예시 : Android와 iOS(12시간), JavaScript(2시간), REST API(6시간) - 재발급 토큰(Refresh Token) : 엑세스 토큰을 재발급 하기 위한 토큰
** 유효 기간 예시 : 2달이며, 만료 1달 남은 시점부터 갱신 가능
이 프로토콜은 4가지의 방식으로 클라이언트에게 권한을 부여합니다. 그 중 가장 많이 쓰이는 한가지만 살펴보겠습니다.
1. Authorization Code Grant - 권한 부여 승인 코드 방식 (3-legged)
보통 간편 로그인 기능에서 사용하는 방식으로, Client가 User를 대신해서 특정 자원에 접근을 요청할 때 사용하는 방식으로, 아래와 같은 순서로 진행됩니다.
- Step 1~6 : User가 로그인을 요청하면 Client가 Authorization Server를 통해 Authorization Code를 받습니다.
- Step 7~8 : Client가 Authorization Code를 활용해 Authorization Server를 통해 Access Token을 받습니다.
- Step 11~12 : Client는 Access Token을 활용해 Resource Server에 정보를 요청가능합니다.
- Step 15~18 : Access Token 만료시 Client가 Refresh Token을 활용해 Authorization Server를 통해 새로운 Access Token을 받습니다.

Refresh Token을 활용가능하며, Access Token을 바로 클라이언트로 전달하지 않고 Authorization server가 Resource server를 중재하기 때문에 잠재적 유출을 방지할 수 있습니다.
또한 Web Application이나 "Server 측 Application"에서 활용하는 방식입니다.
** 나머지 권한 부여 방식에 대해 궁금하시면 아래 더보기를 참조하세요
-----------------------------------------------------------------------------------------
<다른 권한 부여 방식>
2. Implicit Grant - 암묵적 승인 방식 (3-legged) ▶ OAuth 2.1에서 삭제
위와 달리 Authorization Code 없이 바로 Access Token이 발급되는 방식으로, 아래와 같은 순서로 진행됩니다.
Refresh Token 사용이 불가능하며, 응답성과 효율성은 높아지지만 Access Token의 만료기간을 짧게 설정해 누출의 위험을 줄여야합니다.
따라서 자격증명을 안전하게 저장하기 힘든 Client(JavaScript 등을 사용한 브라우저)에게 최적화된 방식입니다.

3. Resource Owner Password Credentials Grant - 자원 소유자 자격증명 승인 방식 (2-legged) ▶ OAuth 2.1에서 삭제
첫 로그인 시에 Username과 Password를 같이 제공함으로써 Access Token을 제공 받는 방식으로, 아래와 같은 순서로 진행됩니다.
Refresh Token 사용이 가능하지만, 신뢰할 수 있는 Client일 때만 사용할 수 있습니다. 따라서 Client가 타사의 외부 프로그램일 경우에는 이 방식은 위험하며, Authorization Server & Resource Server가 Client와 같은 시스템에 있을 때 주로 사용합니다.

4. Client Credentials Grant - 클라이언트 자격증명 승인 방식 (2-legged)
Client의 자격증명만으로 Access Token을 획득하는 방식으로, OAuth 2.0 권한 부여 방식 중 가장 간단한 방식입니다.
Refresh Token을 사용할 수 없으며, 신뢰할 수 있는 Client일 때만 사용할 수 있습니다. 따라서Authorization Server & Resource Server가 Client의 관리영역에 포함된 시스템에 있을 때 주로 사용합니다.

5. Device Authorization Grant - 장치 권한 승인 방식 ▶ OAuth 2.1에서 추가
입력 & 조작이 불편한 Device들(스마트TV, 스마트워치 등)에서 OAuth인증을 하기 위해 OAuth 2.1에서 추가된 방식입니다.
Device가 Authorization Server에 로그인을 요청하면, Authorization Server가 반환할 때 Device 고유 코드인 Device Code, 사용자가 입력해야하는 User Code, 인증할 수 있는 URL인 Verification URI를 함께 돌려주고
이들을 활용해 User가 Device에서 User Code를 입력해 Access Token을 발급하는 방식으로 진행됩니다.
-----------------------------------------------------------------------------------------
어떤 방식으로 권한을 부여할지에 대해 권장되는 방법은 아래를 참고해 결정하시면 됩니다.
- Access Token owner (누가 자원에 접근하는가)
- 기계가 자체적으로 접근 → 4. Client Credentials Grant
- 사용자 동의가 필요한 경우 → 클라이언트 유형에 따라 다름.
- Client Type (클라이언트 유형별 권장)
- 서버가 있는 웹앱 → 1. Authorization Code Grant
- 프론트엔드(SPA)나 모바일앱 → 1. Authorization Code Grant + PKCE
** PKCE (Proof Key for Code Exchange) : 앱이 Authorization Code 등의 보안을 위해 암호화와 관련된 정보를 Authorization Server에 같이 보내 Access Token을 받는 방식입니다. - 서드파티 네이티브 앱 → 1. Authorization Code Grant (브라우저 통해 인증)
- First-party vs Third-party (신뢰 여부)
- 1st party client: 사용자의 인증 정보를 직접 다뤄도 될 만큼 신뢰할 수 있는 앱.
- 3rd party client: 신뢰할 수 없는 외부 앱.

이제 OAuth에 대해서 살펴보았으니, Flutter에 Kakao OAuth Social Login을 구현하는 과정을 살펴보겠습니다.
참고로 Kakao Login의 인증 흐름 방식은 Authorization Code Grant방식입니다.
2. Why? (원인)
- X
3. How? (해결책)
공식 페이지에 구분되어 있는 로그인 방식은 아래와 같습니다.
** https://developers.kakao.com/docs/latest/ko/kakaologin/flutter#login-with-kakao-talk

이번 글에서는 위 표시한 바와 같이 네이티브 앱을 타겟으로 구현할 것입니다.
즉, 카카오톡이 실행 가능한 환경에서는 카카오톡으로 로그인하고, 카카오톡에 연결된 계정이 없는 경우 카카오 계정으로 로그인하도록 할 예정입니다.
if (await isKakaoTalkInstalled()) {
try {
// 카카오톡으로 로그인 시도
} catch (error) {
// 카카오계정으로 로그인 시도
}
} else {
// 카카오계정으로 로그인 시도
}
0. Kakao 플랫폼 셋팅
시작하기에 앞서, Kakao Developer 홈페이지 들어가서 로그인 한 뒤 아래와 같이 콘솔 셋팅을 먼저 해주어야합니다.
** https://developers.kakao.com/

가장 먼저 앱을 생성해줍니다. 아래 보이는 모든 부분들을 기록합니다.

다음으로, Flutter에서 작업할 Android와 iOS 플랫폼의 정보들을 입력해보겠습니다.

Android 플랫폼은 아래 부분을 입력해주면 됩니다. 아래 빨간 부분은 android/app/build.gradle에서 아래와 같이 적혀 있는 부분의 applicationId 부분을 입력해줍니다.
** android/app/src/main/AndroidManifest.xml에서 입력하는 것으로 알 수도 있지만, 최근 (AGP 7+ / Flutter 템플릿)은 구조가 바뀌어서 설치 식별자는 build.gradle의 applicationId로 정하고, AndroidManifest.xml에 package=는 적지 않는 것이 일반적입니다.
android {
defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId = "com.example.my_project"
// You can update the following values to match your application needs.
// For more information, see: https://flutter.dev/to/review-gradle-config.
minSdk = flutter.minSdkVersion
targetSdk = flutter.targetSdkVersion
versionCode = flutter.versionCode
versionName = flutter.versionName
}
}
또한, 키 해시 부분은 아래 중 필요한 것을 적으면 됩니다.
- 디버그 키 Hash : 디버그할 때 안드로이드 스튜디오에서 개발 환경에 맞게 자동으로 생성되는 디버그 인증서에서 해시(hash)한 값
- 릴리즈 키 Hash : 앱 스토어에 앱을 배포하기 위해 생성한 릴리즈 인증서로부터 해시한 값
# Debug Key (Mac)
keytool -exportcert -alias androiddebugkey -keystore ~/.android/debug.keystore -storepass android -keypass android | openssl sha1 -binary | openssl base64
# Release Key (Mac)
keytool -exportcert -alias <RELEASE_KEY_ALIAS> -keystore <RELEASE_KEY_PATH> | openssl sha1 -binary | openssl base64

iOS 플랫폼은 아래 부분을 입력해주면 됩니다. 아래 빨간 부분은 ios/Runner.xcodeproj/project.pbxproj에서 PRODUCT_BUNDLE_IDENTIFIER 부분을 입력해주면 됩니다.
** PRODUCT_BUNDLE_IDENTIFIER가 아래와 같은 두가지 있을 수 있는데, "앱과 관련된" Runner 부분의 값을 넣어주면 됩니다.
----- Runner (실제 앱) - Debug / Profile / Release : 실제 배포 & 설치되는 앱 타깃으로 “진짜 앱”에 해당
----- RunnerTests / RunnerUITests (테스트용) - Debug / Profile / Release : 테스트 전용 타깃으로, 단위/UI 테스트 실행용이라 스토어/카카오 설정과 무관
{
IDEXAMPLEABC /* Profile */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = IDEXAMPLEABCDE /* Release.xcconfig */;
buildSettings = {
PRODUCT_BUNDLE_IDENTIFIER = com.example.myProject;
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Profile;
};
}

이번엔 카카오 로그인을 활성화 해주겠습니다.

또한 선택적으로 Open ID Connect도 활성화해줄 수 있습니다.
** https://developers.kakao.com/docs/latest/ko/kakaologin/prerequisite#kakao-login-oidc
OAuth 2.0이 리소스 접근을 위한 권한을 부여하는 표준이라면, OIDC(OpenID Connect)는 그 위에 얹은 사용자 인증(로그인) 표준입니다.
따라서 Kakao Login을 사용하면 순수한 OAuth를 사용해 앱이 카카오 API를 호출할 Access Token만 받는 것이고, OIDC를 활용하면 Access Token과 함께 ID Token(JWT)를 받아 "누가 로그인 했는지"도 토큰 자체로 검증이 가능한 "표준"을 따르게 됩니다.
그래서, 여러가지의 Social Login을 통합하거나 "누가 로그인 했는지"를 알기 위해 JWT토큰을 따로 요청하는 Query를 없애고 싶을 때 사용할 수 있습니다.

이번엔 카카오 로그인 인증할 때, 내가 만들 앱에서 인증된 사용자의 정보중 받고자 하는 정보를 사용자가 동의하도록 활성화해야합니다.

근데 만약 위 "권한 없음"으로 표시된 동의항목이 꼭 필요한 경우 아래와 같이 "비즈니스 인증"을 통해 검수를 통과해야하고, 비즈 앱으로 바꾸면 개발 단계에서 테스트 앱 형태도 사용할 수 있습니다.
** 앱 분류 : 기본 앱 / 비즈 앱/ 테스트 앱 (https://developers.kakao.com/docs/latest/ko/app-setting/app#app-status)

하지만 우리는 사업자 등록번호가 없는 개인이므로, 아래와 같은 순서로 임시로 비즈앱 전환하고 테스트 가능합니다.
- Step1. 프로필에서 본인인증하고
- Step2. 앱>일반 에서 앱 아이콘을 등록
- Step3. 아래와 같이 "카카오 비즈니스 통합 서비스 약관 동의" 진행
** https://developers.kakao.com/docs/latest/ko/app-setting/app#biz-app-for-individual

이제 개발을 시작해보겠습니다. 시작하기에 앞서 아래 앱키 중 "네이티브 앱 키"를 활용할 예정이니 미리 참고해둡니다.

1. 초기 셋팅
시작하기에 앞서 프로젝트에 셋팅해야되는 내용들을 살펴보겠습니다.
먼저, pubspec.yaml내에 kakao_flutter_sdk를 설치 & 추가해줍니다.
** https://pub.dev/packages/kakao_flutter_sdk
dependencies:
kakao_flutter_sdk: ^1.9.7+3
다음으로 Android 셋팅을 해주겠습니다.
** https://developers.kakao.com/docs/latest/ko/flutter/getting-started#project-scheme
- (선택) android/app/build.gradle 내에 android > defaultConfig 속성에 minSdkVersion 혹은 minSdk를 21로 설정하기도 합니다.
** 만약 minSdk = flutter.minSdkVersion으로 되어있다면 $FLUTTER_ROOT/packages/flutter_tools/gradle/flutter.gradle 혹은 $FLUTTER_ROOT/packages/flutter_tools/gradle/src/main/groovy/flutter.groovy에 설정되어있습니다. - (선택) android/app/src/AndroidManifest.xml 내에 <manifest> Element 하위에 아래와 같이 인터넷 권한을 직접 추가하기도 합니다.
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.INTERNET" />
</manifest>
- 카카오 로그인시 리다이렉트 URI 설정을 위해, android/app/src/AndroidManifest.xml 내에, <application> Element 하위에 아래와 같은 위 "네이티브 앱 키"를 포함한 <activity> Element를 추가해줍니다.
<application>
<!-- 카카오 로그인 커스텀 URL 스킴 설정 -->
<activity
android:name="com.kakao.sdk.flutter.AuthCodeCustomTabsActivity"
android:exported="true">
<intent-filter android:label="flutter_web_auth">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<!-- "kakao${YOUR_NATIVE_APP_KEY}://oauth" 형식의 앱 실행 스킴 설정 -->
<!-- 카카오 로그인 리다이렉트 URI -->
<data android:scheme="kakao${YOUR_NATIVE_APP_KEY}" android:host="oauth"/>
</intent-filter>
</activity>
</application>
이번엔 iOS 셋팅을 해주겠습니다.
** https://developers.kakao.com/docs/latest/ko/flutter/getting-started#project-scheme-ios
- ios/Runner/Info.plist 내 <Dict> 하위에, 사용할 "앱실행 허용 목록"을 아래와 같이 추가해줍니다.
(!) 혹은 아래 사진과 같이 open ios/Runner.xcodeproj 한 뒤, [Info] > [Custom iOS Target Properties]에 Array 타입 키(Key)인 "Queried URL Schemes"을 추가하고, 해당 키의 [Item]에 값으로 kakaokompassauth 추가해줍니다.
<key>LSApplicationQueriesSchemes</key>
<array>
<!-- 카카오톡으로 로그인 -->
<string>kakaokompassauth</string>
</array>

- ios/Runner/Info.plist 내 <Dict> 하위에, "네이티브 앱 키"를 포함한 아래와 같은 Element를 추가해줍니다.
(!) 혹은 아래 사진과 같이 open ios/Runner.xcodeproj 한 뒤, [Info] > [URL Types] > [URL Schemes]에 사용할 "URL Schemes"을 추가해줍니다.
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLSchemes</key>
<array>
<string>kakao${NATIVE_APP_KEY}</string>
</array>
</dict>
</array>

2. 초기화
이제 셋팅이 끝났으니 kakao_flutter_sdk를 활용하기 위해 lib/main.dart에서 초기화를 해주어야합니다. 네이티브 앱만 지원되도록 구현할것이라 javascript 앱 키는 적지 않았고, 네이티브 앱 키만 적어줍니다.
import 'package:kakao_flutter_sdk_common/kakao_flutter_sdk_common.dart';
void main() {
...
// 웹 환경에서 카카오 로그인을 정상적으로 완료하려면 runApp() 호출 전 아래 메서드 호출 필요
WidgetsFlutterBinding.ensureInitialized();
// runApp() 호출 전 Flutter SDK 초기화
KakaoSdk.init(
nativeAppKey: '${YOUR_NATIVE_APP_KEY}',
//javaScriptAppKey: '${YOUR_JAVASCRIPT_APP_KEY}',
);
runApp(MyApp());
...
}
3. 구현
이제 로그인을 구현해보면 아래와 같습니다.
** 패키지 정보 : https://developers.kakao.com/docs/latest/ko/flutter/getting-started#package
import 'package:kakao_flutter_sdk_user/kakao_flutter_sdk_user.dart';
import 'package:flutter/services.dart';
// 카카오톡 실행이 가능하면 카카오톡으로 로그인, 아니면 카카오계정으로 로그인
if (await isKakaoTalkInstalled()) {
try {
await UserApi.instance.loginWithKakaoTalk();
print('카카오톡으로 로그인 성공');
} catch (error) {
print('카카오톡으로 로그인 실패 $error');
// 사용자가 카카오톡 설치 후 디바이스 권한 요청 화면에서 로그인을 취소한 경우,
// 의도적인 로그인 취소로 보고 카카오계정으로 로그인 시도 없이 로그인 취소로 처리 (예: 뒤로 가기)
if (error is PlatformException && error.code == 'CANCELED') {
return;
}
// 카카오톡에 연결된 카카오계정이 없는 경우, 카카오계정으로 로그인
try {
await UserApi.instance.loginWithKakaoAccount();
print('카카오계정으로 로그인 성공');
} catch (error) {
print('카카오계정으로 로그인 실패 $error');
}
}
} else {
try {
await UserApi.instance.loginWithKakaoAccount();
print('카카오계정으로 로그인 성공');
} catch (error) {
print('카카오계정으로 로그인 실패 $error');
}
}
위에서는 await만 해주어서 실제 값을 받지는 않았지만, 아래와 같이 token을 받아 access 토큰과 ID 토큰(JWT)을 직접 확인할 수도 있습니다.
** ID 토큰은 openID 설정을 해주었을 때만 확인 가능합니다.
OAuthToken token =await UserApi.instance.loginWithKakaoTalk();
print('카카오톡으로 로그인 성공 ${token.accessToken},,,${token.idToken}');
OAuthToken token=await UserApi.instance.loginWithKakaoAccount();
print('카카오톡으로 로그인 성공 ${token.accessToken},,,${token.idToken}');
4. 토큰 존재 여부 조회
로그인을 이전에 했던 경우, 이미 발급받은 Access 토큰 또는 Refresh 토큰이 아직 존재할 수도 있으므로 이를 확인하고 바로 로그인을 할 수 있게 하는 방법도 알아두면 좋습니다.
if (await AuthApi.instance.hasToken()) {
try {
AccessTokenInfo tokenInfo =
await UserApi.instance.accessTokenInfo();
print('토큰 유효성 체크 성공 ${tokenInfo.id} ${tokenInfo.expiresIn}');
} catch (error) {
if (error is KakaoException && error.isInvalidTokenError()) {
print('토큰 만료 $error');
} else {
print('액세스 토큰 정보 조회 실패 $error');
}
// 로그인 시도
}
} else {
print('발급된 토큰 없음');
// 로그인 시도
}
5. 사용자 정보 조회
로그인을 완료한 경우, 현재 로그인한 유저의 정보를 얻으려면 아래와 같이 하면 됩니다.
try {
User user = await UserApi.instance.me();
print('사용자 정보 요청 성공'
'\n회원번호: ${user.id}'
'\n닉네임: ${user.kakaoAccount?.profile?.nickname}'
'\n이메일: ${user.kakaoAccount?.email}');
} catch (error) {
print('사용자 정보 요청 실패 $error');
}
6. 로그아웃
사용을 마친 경우 이제 토큰을 폐기하고 삭제하는 방법은 아래와 같습니다.
try {
await UserApi.instance.unlink();
print('연결 해제 성공, SDK에서 토큰 폐기');
} catch (error) {
print('연결 해제 실패 $error');
}
Kakao flutter 서류 : https://developers.kakao.com/docs/latest/ko/flutter/getting-started#project-scheme
Kakao Login 서류 : https://developers.kakao.com/docs/latest/ko/kakaologin/flutter
OAuth설명1 : https://velog.io/@hyg8702/OAuth%EB%9E%80-OAuth1-vs-OAuth2
OAuth 설명2-1** - 권한 방식구분 : https://blog.naver.com/mds_datasecurity/222182943542
OAuth 설명2-2 - 권한 방식 구분 : https://showerbugs.github.io/2017-11-16/OAuth-%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%BC%EA%B9%8C
Oauth 설명3** - 권한 방식 flow : https://velog.io/@alswp006/OAuth2-%EB%A1%9C%EA%B7%B8%EC%9D%B8-%EA%B5%AC%ED%98%84%EA%B8%B0-1-OAuth2%EC%99%80-%EC%B9%B4%EC%B9%B4%EC%98%A4-%EB%A1%9C%EA%B7%B8%EC%9D%B8
Oauth 설명3 - 권한 방식 flow코드 : https://louisus.tistory.com/224
Oauth 설명4 - 1.0, 2.0차이 : https://canada-coder.tistory.com/entry/%EC%9E%A1-%EC%9D%B8%ED%84%B0%EB%B7%B0-2-OAuth-10-%EA%B3%BC-OAuth-20%EC%9D%98-%EC%B0%A8%EC%9D%B4%EC%A0%90
OAuth Refresh Token : https://stateful.com/blog/oauth-refresh-token-best-practices
OAuth Device Authorization Grant : https://velog.io/@today-is-first/OAuth-2.02.1-OIDC
구현 참고2 : https://malangdidoo.tistory.com/257
'Developers 공간 [Shorts] > Frontend' 카테고리의 다른 글
| [Flutter] 앱 이름 변경하기 (0) | 2025.10.11 |
|---|---|
| [Flutter] Flutter에 안드로이드 폰을 연결해주기 (0) | 2025.10.10 |
| [Flutter] Switch 위젯 No Material Widget Found 에러 (1) | 2023.05.07 |
| [Flutter] Flutter에서 KakaoMap API 활용하기 (1) | 2023.05.06 |
| [Flutter] 앱의 이름, ID, 아이콘 변경하기 (1) | 2023.05.06 |