# Kakao OAuth2 + JWT + Redis๋ฅผ ํ†ตํ•œ ์ธ์ฆ ๊ณผ์ • ๊ตฌํ˜„ (1) - ์นด์นด์˜ค ๋กœ๊ทธ์ธ
Study Repository

Kakao OAuth2 + JWT + Redis๋ฅผ ํ†ตํ•œ ์ธ์ฆ ๊ณผ์ • ๊ตฌํ˜„ (1) - ์นด์นด์˜ค ๋กœ๊ทธ์ธ

by rlaehddnd0422

DND ์‚ฌ์ด๋“œ ํ”„๋กœ์ ํŠธ์—์„œ ์ธ์ฆ์œผ๋กœ ์นด์นด์˜ค ๋กœ๊ทธ์ธ์„ ์ฑ„ํƒํ•˜์—ฌ ์ง„ํ–‰ํ•˜๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

Spring Security์™€ JWT, OAuth2 Client, Redis๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์นด์นด์˜ค ๋กœ๊ทธ์ธ์„ ํ”„๋กœ์ ํŠธ์— ์–ด๋–ป๊ฒŒ ์ ์šฉํ–ˆ๋Š”์ง€ ํ•œ ๋ฒˆ ์ •๋ฆฌํ•ด๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

 

๋จผ์ € ์นด์นด์˜ค ๋กœ๊ทธ์ธ ๊ณผ์ •์„ ์งš์–ด๋ด…์‹œ๋‹ค.


Step 1. ์ธ๊ฐ€ ์ฝ”๋“œ ๋ฐ›๊ธฐ 

1. ์ธ๊ฐ€ ์ฝ”๋“œ GET

1. ์นด์นด์˜ค ์ธ์ฆ ์„œ๋ฒ„๋กœ /oauth/authorize URI๋กœ GET ์š”์ฒญ์„ ๋ณด๋ƒ…๋‹ˆ๋‹ค.

2. ์นด์นด์˜ค ์ธ์ฆ ์„œ๋ฒ„์—์„œ ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ ์นด์นด์˜ค ๋กœ๊ทธ์ธ ํŽ˜์ด์ง€๋ฅผ ํ†ตํ•ด ๋กœ๊ทธ์ธ์„ ์š”์ฒญํ•ฉ๋‹ˆ๋‹ค.

3. ์‚ฌ์šฉ์ž๋Š” ์นด์นด์˜ค๊ณ„์ •์œผ๋กœ ๋กœ๊ทธ์ธ

4. ์นด์นด์˜ค๊ณ„์ •์ด ์œ ํšจํ•œ ๊ฒฝ์šฐ ์นด์นด์˜ค ์ธ์ฆ ์„œ๋ฒ„์—์„œ ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ ๋™์˜ ํ™”๋ฉด์„ ํ†ตํ•ด ์‚ฌ์šฉ์ž ์ •๋ณด ์ˆ˜์ง‘ ๋™์˜๋ฅผ ์š”์ฒญํ•ฉ๋‹ˆ๋‹ค.

5. ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋™์˜ํ•œ ํ•ญ๋ชฉ์„ ์นด์นด์˜ค ์ธ์ฆ ์„œ๋ฒ„์—๊ฒŒ ์š”์ฒญํ•ฉ๋‹ˆ๋‹ค.

6. ์นด์นด์˜ค ์ธ์ฆ ์„œ๋ฒ„์—์„œ๋Š” 302 Redirect URI๋กœ ์„œ๋น„์Šค ์„œ๋ฒ„์—๊ฒŒ ์ธ๊ฐ€ ์ฝ”๋“œ๋ฅผ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค.

 

* ์—ฌ๊ธฐ์„œ Redirect URI๋Š” Kakao Developers - ๋‚ด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ - ์นด์นด์˜ค ๋กœ๊ทธ์ธ์—์„œ ์ถ”๊ฐ€ํ•œ URI๋กœ ์„ค์ •๋ฉ๋‹ˆ๋‹ค.


Step 2. ํ† ํฐ ๋ฐ›๊ธฐ

2. ํ† ํฐ ๋ฐœ๊ธ‰

์ด์ œ ์„œ๋น„์Šค ์„œ๋ฒ„๋กœ ๋ฐ›์€ ์ธ๊ฐ€ ์ฝ”๋“œ๋ฅผ ๊ฐ€์ง€๊ณ  ์‚ฌ์šฉ์ž ์ •๋ณด์— ๋Œ€ํ•œ ํ† ํฐ์„ ๋ฐœ๊ธ‰๋ฐ›์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

1. ์„œ๋น„์Šค ์„œ๋ฒ„๊ฐ€ Redirect URI๋กœ ์ „๋‹ฌ๋ฐ›์€ ์ธ๊ฐ€ ์ฝ”๋“œ๋กœ ํ† ํฐ ๋ฐ›๊ธฐ๋ฅผ ์š”์ฒญํ•ฉ๋‹ˆ๋‹ค.

 

2. ์นด์นด์˜ค ์ธ์ฆ ์„œ๋ฒ„๊ฐ€ ํ† ํฐ์„ ๋ฐœ๊ธ‰ํ•ด์„œ ์„œ๋น„์Šค ์„œ๋ฒ„์— ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค.

 

* ์—ฌ๊ธฐ์„œ ํ—ท๊ฐˆ๋ฆด ์ˆ˜ ์žˆ๋Š”๋ฐ, ์ด ํ† ํฐ์€ ์„œ๋น„์Šค ์„œ๋ฒ„์—์„œ ์‚ฌ์šฉํ•  ์•ก์„ธ์Šค ํ† ํฐ์ด ์•„๋‹ˆ๋ผ๋Š” ์ ์— ์ฃผ์˜ํ•ฉ์‹œ๋‹ค.

 


Step 3. ์‚ฌ์šฉ์ž ๋กœ๊ทธ์ธ ์ฒ˜๋ฆฌ

 

์นด์นด์˜ค ์„œ๋ฒ„๊ฐ€ ํ•ด์ฃผ์–ด์•ผ ํ•  ์ผ์€ ๋ชจ๋‘ ๋๋‚ฌ์Šต๋‹ˆ๋‹ค. ์ด ๋ถ€๋ถ„์€ ์„œ๋น„์Šค ์„œ๋ฒ„์— ์ง์ ‘ ๊ตฌํ˜„ํ•ด์•ผ ํ•˜๋Š” ๋ถ€๋ถ„์œผ๋กœ Step2 ์—์„œ ํ† ํฐ์„ ํ†ตํ•ด ์‚ฌ์šฉ์ž ์ •๋ณด๋ฅผ ๋ฐ›์•˜์œผ๋‹ˆ ์ด ์ •๋ณด๋ฅผ ์–ด๋–ป๊ฒŒ ์ฒ˜๋ฆฌํ•  ์ง€ ์„œ๋ฒ„์— ๊ตฌํ˜„ํ•˜๋ฉด ๋˜๊ฒ ์Šต๋‹ˆ๋‹ค.

 

์„œ๋น„์Šค ์„œ๋ฒ„์— ๊ตฌํ˜„ํ•œ ์นด์นด์˜ค ๋กœ๊ทธ์ธ ๋กœ์ง ์ฝ”๋“œ๋ฅผ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.


0. ์„ค์ • ์ •๋ณด

application.yml

  • Redirect URI๋Š” ์นด์นด์˜ค ๋””๋ฒจ๋กœํผ์Šค์— ์„ค์ •ํ•œ URI์™€ ๋™์ผํ•˜๊ฒŒ ์ง€์ •ํ•ด์ค๋‹ˆ๋‹ค.
  • Client ID, Client Secret์€ ์นด์นด์˜ค ๋””๋ฒจ๋กœํผ์Šค์—์„œ ๋ฐœ๊ธ‰๋ฐ›์€ ๊ฐ’์œผ๋กœ ์ง€์ •ํ•ด์ค๋‹ˆ๋‹ค.
  • authorization-grant-type์€ ์ธ๊ฐ€ ์ฝ”๋“œ ๋ฐฉ์‹์„ ์‚ฌ์šฉํ•˜๋ฏ€๋กœ authorization_code ์ง€์ •ํ•ด์ฃผ๊ณ , client-authentication-method๋Š” ๋ฐ˜๋“œ์‹œ cllient_secret_post๋กœ ์ง€์ •ํ•ด์ฃผ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

gradle

implementation 'org.springframework.boot:spring-boot-starter-oauth2-client'
implementation 'org.springframework.boot:spring-boot-starter-security'
  • ์ธ์ฆ ํ•„ํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด Security๋ฅผ, ์นด์นด์˜ค ๋กœ๊ทธ์ธ์„ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด OAuth2๋ฅผ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

1. KakaoDetails

 

KakaoMemberDetails 

@RequiredArgsConstructor
public class KakaoMemberDetails implements OAuth2User {

    private final String email;
    private final List<? extends GrantedAuthority> authorities;
    private final Map<String, Object> attributes;

    @Override
    public String getName() {
        return email;
    }

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return authorities;
    }

    @Override
    public Map<String, Object> getAttributes() {
        return attributes;
    }
}

 

 

  • Step 3์˜ ๋กœ๊ทธ์ธ ์„ฑ๊ณต ํ›„์ฒ˜๋ฆฌ ์„œ๋น„์Šค๋ฅผ ๊ตฌํ˜„ํ•˜๊ธฐ์— ์•ž์„œ ํ›„์ฒ˜๋ฆฌ ์„œ๋น„์Šค์—์„œ ํ•„์š”ํ•œ ์ •๋ณด๋“ค์„ ๋จผ์ € ๊ตฌํ˜„ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.
  • ์ด ํด๋ž˜์Šค๋Š” ์ธ์ฆ ๊ฐ์ฒด์ธ Authentication ๊ฐ์ฒด์•ˆ์— ์‚ฌ์šฉ์ž ์ •๋ณด๋ฅผ ๋‹ด๊ธฐ ์œ„ํ•œ ํด๋ž˜์Šค๋กœ, ์ธ์Šคํ„ด์Šค๋Š” ์นด์นด์˜ค ๊ณ„์ •์˜ email๊ณผ ์‚ฌ์šฉ์ž์˜ ๊ถŒํ•œ์ธ authority๊ฐ€ ์ปฌ๋ ‰์…˜ ํ˜•ํƒœ๋กœ ํ•„๋“œ๋กœ ๊ฐ€์ง€๋Š”๋ฐ์š”. gradle์— ์ถ”๊ฐ€ํ•œ OAuth2 Client๊ฐ€ ์ œ๊ณตํ•˜๋Š” OAuth2User ์ธํ„ฐํŽ˜์ด์Šค์˜ ๊ตฌํ˜„์ฒด๋กœ ์ž‘์„ฑํ•ด์•ผ Authenticaiton ๊ฐ์ฒด ์•ˆ์— ๋‹ด์„ ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— OAuth2User๋ฅผ ๊ตฌํ˜„ํ•˜์—ฌ getter๋ฅผ ์˜ค๋ฒ„๋ผ์ด๋”ฉ ํ•˜์˜€์Šต๋‹ˆ๋‹ค.

 

KakaoUserInfo

public class KakaoUserInfo {

    public static final String KAKAO_ACCOUNT = "kakao_account";
    public static final String EMAIL = "email";

    private Map<String, Object> attributes;

    public KakaoUserInfo(Map<String, Object> attributes) {
        this.attributes = attributes;
    }

    public String getEmail() {
        ObjectMapper objectMapper = new ObjectMapper();
        TypeReference<Map<String, Object>> typeReferencer = new TypeReference<Map<String, Object>>() {
        };

        Object kakaoAccount = attributes.get(KAKAO_ACCOUNT);
        Map<String, Object> account = objectMapper.convertValue(kakaoAccount, typeReferencer);

        return (String) account.get(EMAIL);
    }
}

 

๋กœ๊ทธ์ธ์— ์„ฑ๊ณตํ•˜๊ฒŒ ๋˜๋ฉด ํ›„์ฒ˜๋ฆฌ ์„œ๋น„์Šค์—์„œ ๋ฐ›์€ ์‚ฌ์šฉ์ž ์ •๋ณด๋“ค์„ KakaoMemberDetails๋กœ ์บ์ŠคํŒ…ํ•˜๊ธฐ์œ„ํ•œ ์ •๋ณด๋“ค์ž…๋‹ˆ๋‹ค. ์šฐ์„  ํ›„์ฒ˜๋ฆฌ ์„œ๋น„์Šค ์ฝ”๋“œ๋ฅผ ๋จผ์ € ๋ณด๋Š”๊ฒŒ ์ดํ•ด๊ฐ€ ๋” ๋น ๋ฅผ ์ˆ˜๋„ ์žˆ๊ฒ ๋„ค์š”. ํ›„์ฒ˜๋ฆฌ ์„œ๋น„์Šค ์ฝ”๋“œ๋ฅผ ๋จผ์ € ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

 

KakaoMemberDetailsService - ์นด์นด์˜ค ๋กœ๊ทธ์ธ ์„ฑ๊ณต ํ›„์ฒ˜๋ฆฌ ์„œ๋น„์Šค ๊ฐ์ฒด

 

Step2์—์„œ ํ† ํฐ์„ ํ†ตํ•ด ์‚ฌ์šฉ์ž ์ •๋ณด๋ฅผ ๋ฐ›๊ฒŒ ๋˜๋ฉด ์ด๋ ‡๊ฒŒ DefaultOAuth2UserService์˜ OAuth2UserRequest ๊ฐ์ฒด์— ์‚ฌ์šฉ์ž ์ •๋ณด๊ฐ€ ๋‹ด๊ธฐ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค!

public class DefaultOAuth2UserService implements OAuth2UserService<OAuth2UserRequest, OAuth2User> {
    ...
    private Converter<OAuth2UserRequest, RequestEntity<?>> requestEntityConverter = new OAuth2UserRequestEntityConverter();
    ...
}

 

ํ›„์ฒ˜๋ฆฌ ์„œ๋น„์Šค๋Š” ์‚ฌ์šฉ์ž๊ฐ€ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์— ๋งž๊ฒŒ ์ปค์Šคํ…€ํ•ด์„œ ๊ตฌํ˜„ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋•Œ๋ฌธ์— ์ด DefaultOAuth2UserService๋ฅผ ์ƒ์†๋ฐ›์•„ ์š”๊ตฌ์‚ฌํ•ญ์— ๋งž๊ฒŒ ์ปค์Šคํ„ฐ๋งˆ์ด์ง• ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

 

KakaoMemberDetailsService 

@Service
@RequiredArgsConstructor
public class KakaoMemberDetailsService extends DefaultOAuth2UserService {

    private static final String PREFIX = "๋‚ฏ์„  ";

    private final MemberRepository memberRepository;

    @Transactional
    @Override
    public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException {
        OAuth2User oAuth2User = super.loadUser(userRequest);
        KakaoUserInfo kakaoUserInfo = new KakaoUserInfo(oAuth2User.getAttributes());

        Member member = memberRepository.findByEmail(kakaoUserInfo.getEmail())
                .orElseGet(() ->
                        memberRepository.save(
                                Member.builder()
                                        .email(kakaoUserInfo.getEmail())
                                        .role(Role.USER)
                                        .nickName(PREFIX)
                                        .gender(Gender.NONE)
                                        .updateAgeCount(0)
                                        .updateGenderCount(0)
                                        .build()
                        )
                );

        SimpleGrantedAuthority authority = new SimpleGrantedAuthority(member.getRole().name());

        return new KakaoMemberDetails(String.valueOf(member.getEmail()),
                Collections.singletonList(authority),
                oAuth2User.getAttributes());
    }
}

 

DefaultOAuth2UserService์˜ loadUser ๋ฉ”์†Œ๋“œ๋Š” ๋กœ๊ทธ์ธ ์„ฑ๊ณต ํ›„ ๋™์ž‘ํ•˜๋Š” ๋ฉ”์†Œ๋“œ๋กœ ์‹ค์ œ์ ์œผ๋กœ ์‚ฌ์šฉ์ž ์ •๋ณด๋ฅผ ์–ด๋–ป๊ฒŒ ์ฒ˜๋ฆฌํ•  ์ง€ ์ž‘์„ฑํ•ด์•ผ ํ•˜๋Š” ๊ตฌํ˜„๋ถ€์ž…๋‹ˆ๋‹ค.

OAuth2User oAuth2User = super.loadUser(userRequest);

 

1. ๋จผ์ € request๋กœ๋ถ€ํ„ฐ ์‚ฌ์šฉ์ž ์ •๋ณด๊ฐ€ ๋‹ด๊ธด ๊ฐ์ฒด๋ฅผ ๊บผ๋‚ด์˜ต๋‹ˆ๋‹ค.

KakaoUserInfo kakaoUserInfo = new KakaoUserInfo(oAuth2User.getAttributes());

 

2. ์‚ฌ์šฉ์ž ์ •๋ณด๊ฐ€ ๋‹ด๊ธด ๊ฐ์ฒด์—์„œ ์‚ฌ์šฉ์ž ์ •๋ณด๋ฅผ ๊บผ๋‚ด์„œ KakaoUserInfo์— ๋‹ด์Šต๋‹ˆ๋‹ค.

 

์™œ ๊ตณ์ด KakaoUserInfo๊ฐ€ ํ•„์š”ํ• ๊นŒ? 

  • ์‚ฌ์šฉ์ž ์ •๋ณด๊ฐ€ ๋‹ด๊ธด OAuth2User ๊ฐ์ฒด์˜ attributes๋ฅผ ์ถœ๋ ฅํ•ด๋ณด๋ฉด, ๋กœ๊ทธ์ธ ์œ ์ € ์ •๋ณด๊ฐ€ ์•„๋ž˜์™€ ๊ฐ™์ด Map<String, Object> ํ˜•ํƒœ๋กœ ์ €์žฅ๋œ ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. 
  • ๊ทธ ์ค‘์—์„œ๋„ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์ €์žฅํ•˜๊ธฐ ์œ„ํ•ด ํ•„์š”ํ•œ ์ด๋ฉ”์ผ ์ •๋ณด๋Š” Map<String(key:kakao_account), Map<String,String>> ํ˜•ํƒœ๋กœ ์ €์žฅ๋˜์–ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์ด ์ •๋ณด๋“ค์„ ํŽธํ•˜๊ฒŒ ํŒŒ์‹ฑํ•ด์˜ค๊ธฐ ์œ„ํ•ด KakaoUserInfo ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค์–ด ์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค.
oauth2User.getAttributes() = {
                setPrivacyInfo=true, 
                id=3292176436,
                connected_at=2024-01-21T09:45:17Z,
                properties={nickname=๊น€๋™์›…}, 
                kakao_account = {profile_nickname_needs_agreement=false, profile={nickname=๊น€๋™์›…}, has_email=true, email_needs_agreement=false, is_email_valid=true, is_email_verified=true, email=kdo0422@nate.com}
}

 

KakaoUserInfo๋ฅผ ๋‹ค์‹œ ์‚ดํŽด๋ด…์‹œ๋‹ค.

public class KakaoUserInfo {

    public static final String KAKAO_ACCOUNT = "kakao_account";
    public static final String EMAIL = "email";

    private Map<String, Object> attributes;

    public KakaoUserInfo(Map<String, Object> attributes) {
        this.attributes = attributes;
    }

    public String getEmail() {
        ObjectMapper objectMapper = new ObjectMapper();
        TypeReference<Map<String, Object>> typeReferencer = new TypeReference<Map<String, Object>>() {
        };

        Object kakaoAccount = attributes.get(KAKAO_ACCOUNT);
        Map<String, Object> account = objectMapper.convertValue(kakaoAccount, typeReferencer);

        return (String) account.get(EMAIL);
    }
}

 

KakaoUserInfo๋ฅผ ์•„๋ž˜์ฒ˜๋Ÿผ oauth2User.getAttributes()๋กœ ์ƒ์„ฑํ•˜๋ฉด, 

KakaoUserInfo kakaoUserInfo = new KakaoUserInfo(oAuth2User.getAttributes());

 

 

์ด์ œ kakaoUserInfo.getEmail()์„ ํ†ตํ•ด

 

1. Map<String, Map<String,String>> attributes์— ๋‹ด๊ธด kakao_account key์˜ value๋ฅผ ๊ฐ€์ ธ์™€์„œ

2. kakao_account key์˜ value์ธ Map<String, String>์—์„œ email์„ ๊ฐ€์ ธ์˜ค๋„๋ก ํ•จ์œผ๋กœ์จ, ์‹ค์ œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— insertํ•  ํšŒ์› ์ •๋ณด ์ค‘ ํ•˜๋‚˜์ธ email์„ ํŽธํ•˜๊ฒŒ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

๋ณธ๋ก ์œผ๋กœ ๋Œ์•„์™€ ๋งˆ์ € ํ›„์ฒ˜๋ฆฌ ๋ฉ”์†Œ๋“œ์ธ loadUser()๋กœ ๋Œ์•„์˜ค๊ฒ ์Šต๋‹ˆ๋‹ค.

KakaoUserInfo kakaoUserInfo = new KakaoUserInfo(oAuth2User.getAttributes());

Member member = memberRepository.findByEmail(kakaoUserInfo.getEmail())
        .orElseGet(() ->
                memberRepository.save(
                        Member.builder()
                                .email(kakaoUserInfo.getEmail())
                                .role(Role.USER)
                                .nickName(PREFIX)
                                .gender(Gender.NONE)
                                .updateAgeCount(0)
                                .updateGenderCount(0)
                                .build()
                )
        );

 

  • ์‚ฌ์šฉ์ž ์ •๋ณด๋ฅผ ํ†ตํ•ด kakaoUserInfo๋ฅผ ์ƒ์„ฑํ•ด์ฃผ๊ณ , kakaoUserInfo๋กœ ํšŒ์› ๋ฆฌํฌ์ง€ํ† ๋ฆฌ์— ํ•ด๋‹น ํšŒ์›์ด ์กด์žฌํ•˜๋Š” ์ง€ ์กฐํšŒํ•˜์—ฌ ์—†์œผ๋ฉด ์ƒ์„ฑ ํ›„ ๋ฆฌํ„ดํ•˜๊ณ  ์žˆ์œผ๋ฉด ๋ฆฌํ„ดํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ๊ตฌํ˜„ํ•˜์˜€์Šต๋‹ˆ๋‹ค.
  • ์—ฌ๊ธฐ์„œ ๋ฆฌํฌ์ง€ํ† ๋ฆฌ์— ํšŒ์›์ด ์—†๋Š” ๊ฒฝ์šฐ์—๋Š” email ํ•„๋“œ๋งŒ ์นด์นด์˜ค ๋กœ๊ทธ์ธ ๊ณ„์ •์œผ๋กœ ๋“ฑ๋กํ•ด์ฃผ๊ณ , ๋‚˜๋จธ์ง€ ํ•„๋“œ๋“ค์€ ์š”๊ตฌ์‚ฌํ•ญ์— ๋งž๊ฒŒ ๊ธฐ๋ณธ์ ์ธ ์ •๋ณด๋“ค์„ Builder๋กœ ์ƒ์„ฑํ•˜์—ฌ ๋ฆฌํฌ์ง€ํ† ๋ฆฌ์— ์ €์žฅํ•ด์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค.
SimpleGrantedAuthority authority = new SimpleGrantedAuthority(member.getRole().name());

 

3. OAuth2User ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•œ KakaoMemberDetails์— ํšŒ์›์˜ ๊ถŒํ•œ ์ •๋ณด๋ฅผ ๋‹ด๊ธฐ ์œ„ํ•ด ์ €์žฅ๋œ ํšŒ์›์œผ๋กœ๋ถ€ํ„ฐ ๊ถŒํ•œ ์ •๋ณด๋ฅผ ๊บผ๋‚ด์˜ค๊ณ , SimpleGrantedAuthority ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค์–ด ์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค.

 

return new KakaoMemberDetails(String.valueOf(member.getEmail()),
        Collections.singletonList(authority),
        oAuth2User.getAttributes());

 

4. KakaoMemberDetails๋Š” ๊ถŒํ•œ ์ •๋ณด๋ฅผ Collection ํ˜•ํƒœ์˜ ํ•„๋“œ๋กœ ๊ฐ–๊ธฐ ๋•Œ๋ฌธ์— 3์—์„œ ๋งŒ๋“  ๊ถŒํ•œ์„ ํ˜•ํƒœ์— ๋งž๊ฒŒ ๋ณ€๊ฒฝํ•˜์—ฌ KakaoMemberDetails๋ฅผ ์ƒ์„ฑ ํ›„ ๋ฆฌํ„ดํ•ฉ๋‹ˆ๋‹ค.

 

์–ด๋””์— ๋ฆฌํ„ด๋ ๊นŒ?

  • ์—ฌ๊ธฐ์„œ ๋ฆฌํ„ด๋œ UserDetails ๊ฐ์ฒด๋Š” ์‚ฌ์šฉ์ž ์ธ์ฆ ์ •๋ณด๋ฅผ ๋‚˜ํƒ€๋‚ด๊ธฐ ์œ„ํ•ด Authentication ๊ฐ์ฒด์— ๋‹ด๊ฒจ์ง€๊ณ , ์ด Authentication ๊ฐ์ฒด๋Š” ์‚ฌ์šฉ์ž์˜ ์ธ์ฆ ์ƒํƒœ๋ฅผ ๋‚˜ํƒ€๋‚ด๋ฉฐ, SecurityContext์— ์ €์žฅ๋œ๋‹ค๊ณ  ๋ณด์‹œ๋ฉด ๋˜๊ฒ ์Šต๋‹ˆ๋‹ค.

 

๋งˆ์ง€๋ง‰์œผ๋กœ ๊ตฌํ˜„ํ•œ ํ›„์ฒ˜๋ฆฌ ์„œ๋น„์Šค ํด๋ž˜์Šค๋ฅผ SecurityConfig์— ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋“ฑ๋กํ•ด์ฃผ๋ฉด ๋ !

.oauth2Login(oAuth2Login -> {
    oAuth2Login.userInfoEndpoint(userInfoEndpointConfig ->
            userInfoEndpointConfig.userService(kakaoMemberDetailsService));
});

 

์ด๋ ‡๊ฒŒ ์นด์นด์˜ค ๋กœ๊ทธ์ธ์€ ๊ตฌํ˜„์ด ๋๋‚ฌ์Šต๋‹ˆ๋‹ค. ์•„์ง JWT ์ ์šฉ์ด ๋‚จ์•˜๋Š”๋ฐ์š”. ๋‹ค์Œ ํฌ์ŠคํŒ…์œผ๋กœ ์ด์–ด๊ฐ€๊ฒ ์Šต๋‹ˆ๋‹ค.

๋ธ”๋กœ๊ทธ์˜ ์ •๋ณด

Study Repository

rlaehddnd0422

ํ™œ๋™ํ•˜๊ธฐ