OAuth2는 사용자 인증을 제3자 인증 제공자(Google, Kakao, GitHub 등)에 위임하여 간편하게 로그인할 수 있는 방식입니다.
Spring Boot에서는 spring-security-oauth2-client를 활용하여 소셜 로그인을 쉽게 구현할 수 있습니다.
OAuth2 소셜 로그인 흐름
- 클라이언트가 소셜 로그인 버튼 클릭
- Spring Security가 OAuth2 인증 서버로 리디렉션
- 사용자가 소셜 로그인 서비스(Google, Kakao, GitHub)에 로그인
- 소셜 서비스에서 인증 코드를 발급하여 콜백으로 전달
- 서버가 토큰 발급 및 사용자 정보 가져오기
- 로그인 완료 후 원하는 페이지로 리다이렉트
모든 과정은 Spring Security의 필터 체인과 OAuth2UserService에서 처리됩니다.
의존성 추가
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-oauth2-client'
}
application.yml 설정 (Google 예시)
spring:
security:
oauth2:
client:
registration:
google:
client-id: [발급받은 ID]
client-secret: [발급받은 Secret]
redirect-uri: "{baseUrl}/login/oauth2/code/{registrationId}"
scope: profile, email
provider:
google:
authorization-uri: https://accounts.google.com/o/oauth2/v2/auth
token-uri: https://oauth2.googleapis.com/token
user-info-uri: https://openidconnect.googleapis.com/v1/userinfo
Kakao, GitHub의 경우에도 registration + provider를 각각 지정해야 합니다.
Kakao 설정 예시
spring:
security:
oauth2:
client:
registration:
kakao:
client-id: [카카오 REST API 키]
client-secret: [카카오 Client Secret]
authorization-grant-type: authorization_code
redirect-uri: "{baseUrl}/login/oauth2/code/{registrationId}"
client-name: Kakao
scope: profile_nickname, account_email
provider:
kakao:
authorization-uri: https://kauth.kakao.com/oauth/authorize
token-uri: https://kauth.kakao.com/oauth/token
user-info-uri: https://kapi.kakao.com/v2/user/me
user-name-attribute: id
로그인 후 사용자 정보 매핑
@Service
public class CustomOAuth2UserService extends DefaultOAuth2UserService {
@Override
public OAuth2User loadUser(OAuth2UserRequest request) throws OAuth2AuthenticationException {
OAuth2User oAuth2User = super.loadUser(request);
String registrationId = request.getClientRegistration().getRegistrationId(); // google, kakao 등
String userNameAttr = request.getClientRegistration()
.getProviderDetails().getUserInfoEndpoint().getUserNameAttributeName();
Map<String, Object> attributes = oAuth2User.getAttributes();
// 소셜 서비스마다 attribute 구조가 다르므로 별도 파싱 필요
OAuthAttributes oauthAttributes = OAuthAttributes.of(registrationId, userNameAttr, attributes);
// 회원가입 or 로그인 처리 (DB 저장 로직 포함 가능)
return new DefaultOAuth2User(
Collections.singleton(new SimpleGrantedAuthority("ROLE_USER")),
oauthAttributes.getAttributes(),
oauthAttributes.getNameAttributeKey()
);
}
}
Security 설정에서 커스텀 OAuth2UserService 연결
@Configuration
@EnableWebSecurity
public class SecurityConfig {
private final CustomOAuth2UserService customOAuth2UserService;
public SecurityConfig(CustomOAuth2UserService customOAuth2UserService) {
this.customOAuth2UserService = customOAuth2UserService;
}
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.csrf(csrf -> csrf.disable())
.authorizeHttpRequests(auth -> auth
.requestMatchers("/", "/login", "/css/**").permitAll()
.anyRequest().authenticated())
.oauth2Login(oauth2 -> oauth2
.loginPage("/login") // 커스텀 로그인 페이지 사용 시
.userInfoEndpoint(userInfo -> userInfo
.userService(customOAuth2UserService)));
return http.build();
}
}
사용자 정보 파싱 클래스 예시
@Getter
public class OAuthAttributes {
private Map<String, Object> attributes;
private String nameAttributeKey;
private String name;
private String email;
public static OAuthAttributes of(String registrationId, String userNameAttr, Map<String, Object> attributes) {
if ("kakao".equals(registrationId)) {
return ofKakao(userNameAttr, attributes);
}
// github 등 확장 가능
return ofGoogle(userNameAttr, attributes);
}
private static OAuthAttributes ofGoogle(String userNameAttr, Map<String, Object> attributes) {
return new OAuthAttributes(
attributes,
userNameAttr,
(String) attributes.get("name"),
(String) attributes.get("email")
);
}
private static OAuthAttributes ofKakao(String userNameAttr, Map<String, Object> attributes) {
Map<String, Object> kakaoAccount = (Map<String, Object>) attributes.get("kakao_account");
Map<String, Object> profile = (Map<String, Object>) kakaoAccount.get("profile");
return new OAuthAttributes(
attributes,
userNameAttr,
(String) profile.get("nickname"),
(String) kakaoAccount.get("email")
);
}
public OAuthAttributes(Map<String, Object> attributes, String nameAttributeKey, String name, String email) {
this.attributes = attributes;
this.nameAttributeKey = nameAttributeKey;
this.name = name;
this.email = email;
}
}
실무 팁 및 주의사항
- 사용자 식별 키는 소셜 서비스마다
id또는sub등 다름 → 반드시 파싱 분기 처리 - Kakao는 이메일 제공이 필수가 아님 → 개발자센터 설정에서 동의 항목 확인
- GitHub는
user:emailscope 추가 필요 - 회원가입 처리는 최초 로그인 시 DB 저장, 이후 로그인은 조회만
Spring Boot에서는 OAuth2를 통해 어렵지 않게 소셜 로그인 기능을 구현할 수 있습니다.
Google, Kakao, GitHub 등의 플랫폼에 연동해 사용자 인증을 간단히 처리하고, 자체 회원 시스템과 연동하면 보안성과 사용자 편의성을 고려하여 개발할 수 있습니다.
'개발 > JAVA' 카테고리의 다른 글
| [JAVA] Spring AOP(관점 지향 프로그래밍) 기초 완전 정복 (0) | 2025.10.28 |
|---|---|
| [JAVA] Spring에서 세션 관리와 Redis 세션 클러스터링 (0) | 2025.10.27 |
| [JAVA] JWT 기반 인증/인가 구현하기 (Spring Boot 실전 가이드) (0) | 2025.10.25 |
| [JAVA] Spring Security 기본 개념 이해하기 (0) | 2025.10.24 |
| [JAVA] Spring Boot에서 이메일 발송 기능 구현하기 (JavaMailSender) (0) | 2025.10.23 |
