📌 소셜 로그인을 사용해야 하는 이유
사이드 프로젝트나 스타트업 서비스를 개발할 때 사용자 인증은 필수적인 기능입니다.
하지만 전통적인 회원가입/로그인 방식은 사용자에게 귀찮은 절차를 요구하고, 개발자에게는 보안 관련 부담을 줍니다.
소셜 로그인은 이러한 문제를 효과적으로 해결해주는 대안입니다.
- 사용자 경험 향상: 새로운 계정을 만들지 않고 기존 소셜 계정으로 간편하게 로그인
- 높은 보안성: 소셜 플랫폼의 검증된 보안 시스템 활용
- 개인정보 관리 부담 감소: 민감한 사용자 정보를 직접 저장하지 않아도 됨
- 빠른 구현 가능: OAuth2 프로토콜을 통한 표준화된 인증 방식
이 글에서는 Spring Boot 프로젝트에서 구글, 네이버, 카카오 소셜 로그인을 구현하는 방법을 단계별로 설명하겠습니다.
🛠️ 개발 환경 및 기술 스택
- Spring Boot 2.7.12
- Spring Security와 OAuth2 Client
- JWT 0.11.5
- Thymeleaf (프론트엔드)
- Java 17
- JPA & MySQL 8.0.34
- Lombok
- Gradle
📊 소셜 로그인 구현 전체 아키텍처
이 프로젝트는 다음과 같은 플로우로 소셜 로그인을 처리합니다:
- 사용자가 소셜 로그인 버튼 클릭
- 해당 플랫폼(구글/네이버/카카오)의 로그인 페이지로 리다이렉트
- 사용자 인증 후 지정된 콜백 URL로 인증 코드와 함께 리다이렉트
- 인증 코드로 액세스 토큰 요청
- 액세스 토큰으로 사용자 정보 요청
- 우리 서버에서 JWT 액세스 토큰 발급 및 클라이언트 쿠키에 저장
- 리프레시 토큰은 DB에 저장하여 액세스 토큰 만료 시 재발급 가능하도록 구현
🔍 소셜 로그인 API 구성하기
1️⃣ 데이터베이스 설정
MySQL 데이터베이스와 사용자 테이블을 생성합니다:
CREATE DATABASE notifycal CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'notifycal_user'@'localhost' IDENTIFIED BY '1234';
GRANT ALL PRIVILEGES ON notifycal.* TO 'notifycal_user'@'localhost';
FLUSH PRIVILEGES;
create table users (
id bigint not null auto_increment,
email varchar(255) not null,
password varchar(255),
name varchar(255),
image_url varchar(255),
provider varchar(255),
provider_id varchar(255),
unique_identifier varchar(255) not null,
refresh_token TEXT,
refreshTokenExpiryDate datetime(6),
created_at datetime(6),
updated_at datetime(6), primary key (id)
) engine=InnoDB;
alter table users add constraint UK_6dotkott2kjsp8vw4d0m25fb7 unique (email);
alter table users add constraint UK_1mh0m6c9yk2vkvm9wsnhnegb7 unique (unique_identifier);
2️⃣ 구글 OAuth 설정
- Google Cloud Console에 접속하여 새 프로젝트 생성
- API 및 서비스 > OAuth 동의화면으로 이동하여 External 유형 선택 및 필수 정보 입력
- 사용자 인증 정보 > OAuth 클라이언트 ID에서 웹 애플리케이션 선택
- 리디렉션 URI 설정: http://localhost:5050/login/oauth2/code/google
- 생성된 클라이언트 ID와 시크릿 저장
3️⃣ 네이버 OAuth 설정
- 네이버 개발자 센터에서 애플리케이션 등록
- 사용 API에서 '네이버 로그인' 선택
- 제공 정보 선택 및 PC웹으로 서비스 환경 설정
- 서비스 URL: http://localhost:5050
- 콜백 URL: http://localhost:5050/login/oauth2/code/naver
- 클라이언트 ID와 시크릿 저장
4️⃣ 카카오 OAuth 설정
- 카카오 개발자 센터에서 애플리케이션 추가
- '카카오 로그인' 활성화 및 동의 항목 설정
- 리다이렉트 URI 설정: http://localhost:5050/login/oauth2/code/kakao
- REST API 키(클라이언트 ID)와 보안 탭에서 생성한 클라이언트 시크릿 저장
💻 Spring Boot 애플리케이션 설정
1️⃣ application.yml 구성
API 키와 시크릿은 보안을 위해 Jasypt로 암호화하여 저장합니다:
spring:
security:
oauth2:
client:
registration:
google:
client-id: ENC(구글_클라이언트_ID_암호화값)
client-secret: ENC(구글_클라이언트_시크릿_암호화값)
scope: profile,email
naver:
client-id: ENC(네이버_클라이언트_ID_암호화값)
client-secret: ENC(네이버_클라이언트_시크릿_암호화값)
redirect-uri: "{baseUrl}/login/oauth2/code/{registrationId}"
authorization-grant-type: authorization_code
scope: name,email,profile_image
client-name: Naver
kakao:
client-id: ENC(카카오_REST_API_키_암호화값)
client-secret: ENC(카카오_클라이언트_시크릿_암호화값)
redirect-uri: "{baseUrl}/login/oauth2/code/{registrationId}"
client-authentication-method: client_secret_post
authorization-grant-type: authorization_code
scope: profile_nickname, profile_image, account_email
client-name: Kakao
2️⃣ Jasypt 설정
보안 키를 암호화하기 위해 Jasypt를 설정합니다:
- JasyptConfigTest.java를 이용해 각 API 키와 시크릿 암호화
- IntelliJ에서 Edit Configurations > VM Options에 암호화 키 설정:
-Djasypt.encryptor.password=키값입력
🚀 JWT 인증 구현
사용자 인증 후에는 서버에서 JWT 토큰을 발급합니다:
- 액세스 토큰: 클라이언트 쿠키에 저장하여 짧은 유효기간 설정
- 리프레시 토큰: 데이터베이스에 저장하고 액세스 토큰 만료 시 재발급에 활용
💡 성능 최적화 팁: 부하가 많은 서비스라면 리프레시 토큰 저장소를 MySQL에서 Redis로 변경하여 성능 향상 가능
🔄 전체 소셜 로그인 흐름 정리
- 사용자가 소셜 로그인 버튼 클릭
- OAuth Provider의 로그인 페이지로 리다이렉트
- 로그인 성공 시 지정된 콜백 URL로 인증 코드 전달
- 백엔드에서 인증 코드로 액세스 토큰 요청
- 액세스 토큰으로 사용자 정보 요청
- 사용자 정보를 DB에 저장하거나 업데이트
- JWT 토큰 발급 후 사용자 인증 완료
📝 마무리
Spring Boot와 OAuth2를 이용한 소셜 로그인 구현은 사용자 경험을 크게 향상시키는 중요한 기능입니다.
이 글에서 다룬 방법을 활용하면 구글, 네이버, 카카오 로그인을 손쉽게 구현할 수 있습니다.
전체 소스 코드는 GitHub 저장소에서 확인할 수 있습니다.
다양한 Spring Boot 버전별로 브랜치가 나뉘어 있으니 필요한 버전을 선택하여 사용하세요.
더 나은 보안과 성능을 위해 Jasypt 암호화와 리프레시 토큰 관리에 특히 주의하시길 바랍니다.
여러분의 프로젝트에 이 템플릿이 도움이 되길 바랍니다!
'Spring & Spring Boot 실무 가이드' 카테고리의 다른 글
🌱 Spring Retry 실무 가이드 – 트랜잭션과 API 호출에서 재시도 적용하기 (0) | 2025.02.26 |
---|---|
[Spring] Spring Boot에서 API 응답 속도를 높이는 5가지 방법 (2) | 2025.01.21 |
[Spring] Spring Batch로 사용자 활동 로그를 집계하여 실시간 보고서 자동화하기 (0) | 2025.01.20 |
[Spring]Spring 개발자를 위한 Annotation 원리와 커스텀 Annotation 실습 (0) | 2025.01.18 |
[spring] AOP(관점 지향 프로그래밍) 이해하기: 실용적인 예제로 배우는 AOP (1) | 2024.01.21 |