| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | 5 | 6 | 7 |
| 8 | 9 | 10 | 11 | 12 | 13 | 14 |
| 15 | 16 | 17 | 18 | 19 | 20 | 21 |
| 22 | 23 | 24 | 25 | 26 | 27 | 28 |
| 29 | 30 | 31 |
- Oracle
- Spring
- superBuilder
- docker
- IntelliJ
- 프로그래머스
- 알고리즘
- programmers
- CI
- builder-pattern
- Kubernetes
- 뷰
- Di
- CKA
- JPA
- ORM
- 자바
- dabase
- java
- DevOps
- 해시맵
- SpringMVC
- vuejs
- hibernate
- k8s
- cd
- map
- Vue
- 코딩테스트연습
- CI/CD
- Today
- Total
문홍의 공부장
카카오 소셜 로그인 구현기 본문
들어가며
이번 작업은 개인 프로젝트 앱에 카카오 소셜 로그인을 추가한 기록입니다. 기존 이메일/비밀번호 로그인 흐름은 유지하면서, 동일한 /api/v1/login 엔드포인트로 OAuth 로그인까지 처리하도록 서버와 클라이언트를 함께 확장했습니다.
OAuth 개념 정리
OAuth 2.0은 "인증"과 "인가"를 분리해주는 표준 프로토콜입니다. 사용자는 서비스에 비밀번호를 직접 제공하지 않고, 외부 인증 제공자(카카오 등)로부터 발급된 토큰을 통해 서비스 접근 권한을 위임합니다.
- 인증(Authentication): 사용자가 누구인지 확인
- 인가(Authorization): 해당 사용자에게 어떤 권한을 부여할지 결정
이번 구현에서는 "카카오로 로그인"을 통해 인가 코드를 받고, 서버가 카카오에 토큰을 요청해 사용자 정보를 얻는 흐름을 사용했습니다.
카카오 OAuth 인증/인가 플로우
아래는 카카오 OAuth에서 일반적으로 사용하는 Authorization Code 플로우를 개발중인 프로젝트를 기준으로 정리한 것입니다.

시퀀스 다이어그램
클라이언트와 서버, 카카오가 어떤 순서로 통신하는지 더 직관적으로 표현했습니다.

전체 플로우
- 클라이언트가 카카오 인가 코드 요청
- 카카오가 리다이렉트 URI로 인가 코드 전달
- 클라이언트가 서버 /api/v1/login 호출 (oauthType, authCode 전달)
- 서버가 카카오에 토큰 요청 → 사용자 정보 조회
- 사용자 저장/조회 후 JWT 발급 및 응답
클라이언트 구현
1) 인가 코드 획득
Expo 환경에서 expo-web-browser + expo-linking 조합으로 인가 코드를 받았습니다.
- openAuthSessionAsync()로 카카오 로그인 페이지 열기
- 리다이렉트 URL에서 code 파싱
관련 코드: client/utils/kakaoAuth.ts
const authUrl =
'https://kauth.kakao.com/oauth/authorize' +
`?client_id=${encodeURIComponent(REST_API_KEY)}` +
`&redirect_uri=${encodeURIComponent(REDIRECT_URI)}` +
'&response_type=code';
const result = await WebBrowser.openAuthSessionAsync(authUrl, REDIRECT_URI);
const { queryParams } = Linking.parse(result.url);
const code = queryParams?.code;
2) OAuth 로그인 요청
인가 코드를 서버에 전달하는 전용 함수 oauthLogin을 추가했습니다.
- POST /login
- oauthType: 'KAKAO', authCode 전달
관련 코드: client/api/auth.ts
export async function oauthLogin(data: OAuthLoginRequest): Promise<AuthResponse> {
const res = await apiFetch('/login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data),
});
return await handleAuthResponse(res);
}
3) UI
로그인 화면에 카카오 로그인 버튼을 추가했습니다. 관련 코드: client/screens/SignupScreen.tsx
<TouchableOpacity style={styles.kakaoButton} onPress={handleKakaoLogin}>
<Text style={styles.kakaoButtonText}>카카오로 로그인</Text>
</TouchableOpacity>
서버 구현
1) OAuth 타입 및 사용자 식별 컬럼 추가
소셜 로그인을 식별하기 위해 users 테이블에 oauth_type, oauth_provider_id 컬럼을 추가했습니다.
ALTER TABLE users ADD COLUMN oauth_type VARCHAR(20);
ALTER TABLE users ADD COLUMN oauth_provider_id VARCHAR(255);
2) Kakao OAuth Client 추가
카카오 토큰 발급 및 사용자 조회를 담당하는 KakaoOAuthClient를 구현했습니다.
핵심 포인트:
- 토큰/사용자 응답이 비어있으면 예외 처리
- 사용자 이메일 동의 여부 확인
3) 로그인 분기 처리
기존 AuthService.signIn에서 oauthType이 존재하면 OAuth 로그인으로 분기했습니다.
주요 로직:
- oauthType 유효성 검증 (현재는 KAKAO만 지원)
- 카카오 사용자 정보 획득
- 기존 계정과의 충돌 방지
- 동일 이메일이 존재하면 가입 차단
- 신규 계정이면 oauth_type, oauth_provider_id 저장
- JWT 발급 및 응답
환경 설정
서버
application.yml 에 카카오 설정을 추가했습니다.
- kakao.client-id
- kakao.client-secret
- kakao.redirect-uri
클라이언트
.env에 아래 값을 설정합니다.
- EXPO_PUBLIC_KAKAO_CLIENT_ID
- EXPO_PUBLIC_KAKAO_REDIRECT_URI
마무리
이번 작업으로 기존 이메일 로그인 흐름을 유지하면서 카카오 소셜 로그인을 자연스럽게 통합했습니다. 서버 측에서 사용자 중복 방지와 필수 동의 검증을 추가하면서 안전한 로그인 경험을 만들 수 있었습니다.
다음 단계로는 다른 OAuth 제공자(예: Google) 확장과, 기존 이메일 계정을 카카오 계정으로 연결하는 계정 연동 플로우를 고려해볼 수 있을 것 같습니다.
'개발 > Java' 카테고리의 다른 글
| [Java] 비동기 작업에 사용되는 CompletableFuture (0) | 2024.03.04 |
|---|---|
| [Java] Querydsl @QueryProjection, transform() 을 활용하여 효율적으로 Result Handling 하기 (0) | 2024.01.28 |
| [Java] EntityListeners 를 활용하여 엔티티의 생명 주기에 따른 이벤트 처리하기 (JPA Entity Lifecycle Events) (1) | 2024.01.28 |
| [Java] Shorten URL (단축 URL) 생성하기 (0) | 2023.07.19 |
| [Java] BigDecimal 사용하기 (1) | 2023.06.18 |