Skip to content

Conversation

@dmp100
Copy link
Collaborator

@dmp100 dmp100 commented Jan 10, 2026

카카오 로그인 구현

ISSUE


❗ WORK DESCRIPTION

0. 자세한 일기장

앙티클_카카오 왜이렇게 귀찮음 ?
local.properties

1. 카카오 SDK 초기화

  • KieroApplication에서 SDK 초기화
  • AndroidManifest.xmlAuthCodeHandlerActivity 등록
  • 키 해시 추출 및 카카오 디벨로퍼스 등록 완료

2. Data Layer (Clean Architecture)

Remote DataSource

  • AuthDataSource 인터페이스 정의
  • AuthDataSourceImpl 구현
    • 카카오톡 앱 로그인 / 웹 로그인 분기 처리
    • 공식 문서 기반 fallback 로직 (카카오톡 실패 → 웹 자동 전환)

Local DataSource

  • AuthLocalDataSource 인터페이스 정의
  • AuthLocalDataSourceImpl 구현
    • DataStore 사용 (EncryptedSharedPreferences는 deprecated)
    • Tink 암호화 적용 (AES-256-GCM)

Repository

  • AuthRepository 인터페이스 정의
  • AuthRepositoryImpl 구현
    • 카카오 로그인 → 서버 통신 → 토큰 저장 분리
    • suspendRunCatching, handleError 적용

3. DI 모듈

  • ServiceModule: AuthService 제공
  • DataSourceModule: AuthDataSource, AuthLocalDataSource 바인딩
  • RepositoryModule: AuthRepository 바인딩
  • UtilModule: TinkEncryption 제공

4. UI Layer (MVVM 패턴)

  • AuthContract: State, SideEffect 정의
  • AuthViewModel: 로그인 로직, 상태 관리
  • KakaoLoginButton: 재사용 가능한 컴포넌트
  • LoginScreen: 로그인 화면
  • AuthNavigation: 역할 선택 → 로그인 흐름 추가

5. 보안

  • Tink 암호화 유틸리티 구현 (TinkEncryption)
    • JSON 키셋 저장 방식
    • AES-256-GCM 알고리즘
  • 토큰 암호화 저장
    • 평문 → Tink 암호화 → DataStore 저장

6. CICD 대비 NATIVE_KEY GitSecret 저장

image

🔄 로그인 프로세스

[사용자] 
  ↓ "카카오 로그인" 버튼 클릭
[ViewModel::loginWithKakao()]
  ↓
[AuthRepository::loginWithKakao()]
  ↓
[AuthDataSource::getKakaoToken()] → 카카오 SDK 호출
  ↓
  ├─ 카카오톡 앱 있음 → 앱으로 로그인
  └─ 카카오톡 앱 없음 → 웹으로 로그인
  ↓
카카오 accessToken 획득
  ↓
[AuthDataSource::postAuthLogin()] → 서버 통신
  ↓
우리 서버 JWT 토큰 획득
  ↓
[AuthRepository::saveAuthTokens()]
  ↓
[AuthLocalDataSource::saveAccessToken()] → Tink 암호화 → DataStore 저장
  ↓
[ViewModel] LoginSuccess 이벤트 발행
  ↓
[UI] 메인 화면 이동

📢 TO REVIEWERS

1. 보안 구현

  • TinkEncryption 구현 방식 (현재는 Keystore 없이 Tink만 사용)
  • 프로덕션 환경에서는 Android Keystore 적용 필요할 수 있음

2. 에러 처리

  • suspendRunCatching + handleError 조합이 적절한지
  • 사용자 취소 vs 네트워크 에러 구분 로직

3. 아키텍처

  • Repository에서 로그인 + 토큰 저장 분리한 방식
  • ViewModel에서 loginWithKakao()saveAuthTokens() 별도 호출 필요

4. 네이밍

  • AuthDataSource (Remote)와 AuthLocalDataSource 구분이 명확한지

⚠️ 알려진 제약사항

토큰 갱신 로직 왜 안했냐는 나쁜말은 ㄴㄴ

  • Access Token 만료 시 Refresh Token으로 재발급하는 로직은 추후 구현 예정
  • 현재는 로그인 성공 시 토큰 저장까지만 처리

Tink 암호화 수준

  • 현재는 앱 내부 파일에 키 저장 (중간 보안)
  • 더 높은 보안이 필요하면 Android Keystore 통합 필요

💬 논의 필요한 부분

  • Entity/Mapper 분리 없이 DTO 직접 사용하는 방식 괜찮은지
  • Repository에서 토큰 저장까지 책임지는 게 맞는지 (vs ViewModel에서 처리)

📸 SCREENSHOT

전체 로그

image image image image

카카오톡 앱이 없을때 웹으로 넘어가는 모습

image
2026-01-10.14.56.19.mov

카카오로그인 성공

image
2026-01-10.15.51.37.mov

@dmp100 dmp100 added this to the [키어로] AppJam milestone Jan 10, 2026
@dmp100 dmp100 requested review from seungjae708, sonms and vvan2 January 10, 2026 07:09
@dmp100 dmp100 self-assigned this Jan 10, 2026
@dmp100 dmp100 added feature ✨ 신규 기능 구현 🌕규현 규현 전용 라벨 labels Jan 10, 2026
Copy link
Member

@sonms sonms left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

너무 고생많으셨습니다! Tink 까지 써보시다니 좋은데요? 우선은 이 정도 남기고 후추 추가적으로 더 남기겠습니다~!

Comment on lines 36 to 38
private val Context.dataStore: DataStore<Preferences> by preferencesDataStore(
name = DATASTORE_NAME
)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

p1: context.datastore는 파일의 최상단에 두는 게 공식권장 사항으로 알고 있어요
DataStore는 싱글톤으로 유지되어야합니다
근데 해당 AuthLocalDataSourceImpl 안에 선언하면 클래스가 여러 번 생성되거나 다른 컨텍스트로 호출되면
같은 파일명 DATASTORE_NAME에 대해 인스턴스 충돌이 발생할 수 있을 것 같습니다

또한 다른 인스턴스로 생성 시 값이 중간에 유실되는 일관성? 에도 문제가 생기고 race condition도 생길 거 같네용

Copy link
Collaborator

@seungjae708 seungjae708 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

고생하셨습니다!!
쉽지 않아보이는데 정리도 같이 하시면서 공부 열심히 하시고 적용하신게 느껴집니다.
저도 소셜로그인 처리를 안해봐서 코드랑 아티클 천천히 다시 보면서 공부해볼게요~

Comment on lines 5 to 8
interface AuthRepository {
suspend fun loginWithKakao(): Result<AuthLoginResponseDto>
suspend fun saveAuthTokens(accessToken: String, refreshToken: String)
} No newline at end of file
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

p3) AuthRepository가 Data Layer의 Dto를 직접 반환하고 있는데 Mapper를 넣는건 어떤가요?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

p3) 저희 첫.. 코리에 얘기해놓긴 했는데.. 전달이 안됐네요 하핫... Mapper 써도 되긴하는데, 확장함수 써서 좀 더 간편하게 변환 하기로 했습니다

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mapper 넣는거 생각도 해봤었는데, 저희가 프로필보여주는 화면도 없기도 하고 굳이 Token들을
매퍼로 변환할 이유가 없을 것 같아서 간편하게 변환했습니다 !

@vvan2 vvan2 changed the title [Feat/#8] kakao login [feat/#8] kakao login Jan 10, 2026
Copy link
Member

@vvan2 vvan2 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

고생하셨습니다~ 카카오 로그인 작업 잘해주셨네요 ㅎㅎ .
코드 리뷰는 이따 저녁에 더 달아볼게요
(규현쿤, 사실 나도 Tink 를 써본적 없어)

data object NavigateUp : SideEffect
data object LoginSuccess : SideEffect
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

p2) state 와 sideEffect 분리해서 놨었는데 다시 객체로 묶어준 이유가 있을까요!

Comment on lines 5 to 8
interface AuthRepository {
suspend fun loginWithKakao(): Result<AuthLoginResponseDto>
suspend fun saveAuthTokens(accessToken: String, refreshToken: String)
} No newline at end of file
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

p3) 저희 첫.. 코리에 얘기해놓긴 했는데.. 전달이 안됐네요 하핫... Mapper 써도 되긴하는데, 확장함수 써서 좀 더 간편하게 변환 하기로 했습니다

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

p2) DI 쪽은 제가 분리할 예정이긴 한데, (auth,kid,parent 각각 사용할 수 있게) 참고만 해주세용

Copy link
Member

@sonms sonms left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

고생많았습니다!!

Copy link
Member

@vvan2 vvan2 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

고생했다....

Copy link
Collaborator

@seungjae708 seungjae708 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

수고 많으셨습니다~!

@dmp100 dmp100 merged commit 3ef46ab into develop Jan 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature ✨ 신규 기능 구현 🌕규현 규현 전용 라벨

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[feat] 카카오 로그인 연동 및 토큰 인증

5 participants