Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: 카카오 로그인하기 #1 #18

Merged
merged 8 commits into from
Sep 25, 2024
Merged

feat: 카카오 로그인하기 #1 #18

merged 8 commits into from
Sep 25, 2024

Conversation

westzeroright
Copy link
Contributor

📌 관련 이슈

✨ PR 내용

카카오 로그인 간단 설명

  • 인가코드로부터 카카오톡 토큰 받기
  • 카카오톡 토큰을 가지고 회원 추출 후 조회 및 식별
  • 회원에게 서비스 토큰(jwt) 발급

⭐️ API 명세서 수정

기존:
image

  • 인가코드로부터 카카오톡 토큰 받기
  • 카카오톡 토큰으로부터 서비스 토큰 발급하기

변경안:
image

  • 인가코드 받기 - 로그인 - 서비스 토큰 발급


깃이 너무 꼬여서 파일이 와장창되어버려서 브랜치 이번만 날먹합니다..

Copy link
Contributor

@rbm0524 rbm0524 left a comment

Choose a reason for hiding this comment

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

코멘트 남겨놨습니당

import org.springframework.stereotype.Component;

@Component
public class JwtUtil {
Copy link
Contributor

Choose a reason for hiding this comment

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

카카오 로그인 API 사용하는데 JWT는 왜 작성하신건가요?

Copy link
Contributor

Choose a reason for hiding this comment

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

코드 읽으면서 작성하신 이유 이해했습니다!

Copy link
Contributor

Choose a reason for hiding this comment

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

이 클래스는 정적 필드와 메서드를 가지는 유틸리티 클래스로 보이는데요
빈으로 등록해서 사용하는 이유가 있을까요?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

현재 코드에는 없지만 로깅을 적용하기 위해 사용하였습니다.

.orElseGet(
() -> {
Member newMember = Member.createMember(email);
return memberRepository.saveAndFlush(newMember);
Copy link
Contributor

Choose a reason for hiding this comment

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

saveAndFlush를 사용하신 이유는 뭔가요?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

DB에 바로 적용되게 하기 위해서 사용했습니다.

Copy link
Contributor

Choose a reason for hiding this comment

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

왜 db에 바로 적용시키려고 했는지 궁금해요!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

디버깅 과정에서 데이터베이스에 대한 변경사항을 즉시 확인하고 싶었습니다!

KakaoUserInfo kakaoUserInfo = kakaoClient.getUserInfo((kakaoToken));
String userKakaoEmail = kakaoUserInfo.kakaoAccount().email();
memberService.findOrCreateMember(userKakaoEmail);
String serviceToken = JwtUtil.generateToken(userKakaoEmail);
Copy link
Contributor

Choose a reason for hiding this comment

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

카카오 API 호출로 이미 토큰을 받았기 때문에 email을 다시 추출해서 JWT를 만드는 것은 의미가 없는 것 같아요. 이게 JwtUtil 클래스를 작성한 이유겠네요. findOrCreateMember를 통해서 Member 엔티티에 이메일이 없으면 회원에 추가하는 것 같네요.
제가 이해한 영우님 로직은
카카오 토큰을 가져온다 -> 토큰에서 이메일을 추출해서 회원 여부 확인하고 회원이 아니면 가입시킨다 -> JWT 토큰을 만들어서 발급한다.
이건데 카카오 토큰도 토큰입니다!
https://developers.kakao.com/docs/latest/ko/kakaologin/rest-api#get-token-info
이 문서를 보시면 토큰 만료 여부나 갱신 기간을 알 수 있기 때문에 JWT로 다시 만들어서 관리할 필요는 없을 것 같아요

Copy link
Contributor

Choose a reason for hiding this comment

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

오...저도 많이 배워갑니다.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

반영했습니다!

Copy link
Contributor

Choose a reason for hiding this comment

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

엇 저는 영우님이 한 방식이 좀 더 적합해보였어요
카카오에서 발급 받은 토큰은 서버에서 발행한 토큰이 아니기 때문에 해당 토큰을 검증할 정보를 가지고 있지 않아서 그대로 사용할 수 없지 않을까요?
그리고 카카오 토큰을 그대로 사용하면 해당 토큰이 탈취되었을 때 카카오 서비스를 이용할 권한까지 같이 탈취당할 위험도 있을 것 같아요

Copy link
Contributor

Choose a reason for hiding this comment

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

탈취당했을 때를 대비해서 토큰 만료 시간을 짧게 하고 refresh 토큰으로 주기적으로 갱신하는 것으로 알고 있어요. 토큰 탈취는 토큰을 어디에 저장해도 발생할 수 있는 문제에요. 토큰이 탈취당했더라도 동의한 항목 외의 다른 기능들에 대해서는 접근이 불가한걸로 알고 있어요.
카카오 토큰에서 사용자의 이메일 추출해서 JWT로 다시 반환시킨다면 우리가 카카오 로그인을 사용할 이유가 없는 것 같아요. 똑같이 아이디,비밀번호 입력해서 로그인을 하는 것인데 굳이 OAuth를 사용할 필요가 있을까요?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

저도 제법님과 같은 의견이었습니다. 그래서 인증인가를 저희 서비스내에서 따로 두었던 것이었어요. 사실 저도 안 되는 거라고 생각하지만 저희 서비스가 간단하게 진행된다고 고려하고 반영하긴 했는데 카카오에서 주는 토큰을 굳이 저희가 조작해서 사용해야할까요? 그리고 주기를 짧게 한다해도 카카오 토큰으로부터 사용자 정보를 추출할 수 있는데 위험한 부분이라고 생각합니다.

key:
jwt:
secreat-key: ${JWT_SCREAT_KEY}
Copy link
Contributor

Choose a reason for hiding this comment

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

마지막에 빈줄 하나 넣으시면 이거 없어집니다!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

인텔리제이에 빈줄 자동으로 추가하는 옵션 미리 설정했는데 다시 보니 안 되어 있더라구요..! 확인 감사합니다 :)

import org.springframework.boot.context.properties.ConfigurationPropertiesScan;
import org.springframework.util.LinkedMultiValueMap;

@ConfigurationPropertiesScan
Copy link
Contributor

Choose a reason for hiding this comment

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

Team14BeApplication.java에서 이미 Scan하고 있어서 이 클래스에서는 불필요하지 않나요?

Copy link
Contributor

Choose a reason for hiding this comment

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

하하 저는 이게 뭔지 처음 알았네요

Copy link
Contributor Author

Choose a reason for hiding this comment

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

엇 맞습니다..! 확인 감사합니다 👍🏻

private final KakaoProperties kakaoProperties;

public KakaoClient(KakaoProperties kakaoProperties) {
this.restClient = RestClient.builder().build();
Copy link
Contributor

Choose a reason for hiding this comment

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

config 파일에서 RestClient도 Bean으로 등록해서 사용하는 것이 더 좋아보여요 그러면 Autowired도 사용할 수 있겠네요

Copy link
Contributor Author

Choose a reason for hiding this comment

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

오 좋은 거 알려주셔서 감사합니다! 반영했습니다~👍🏻👍🏻

Copy link
Contributor

@ajy9851 ajy9851 left a comment

Choose a reason for hiding this comment

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

이후 회의에서 나중에 엔티티 관계 관련해서 이야기 나눠봐유

build.gradle Outdated
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'io.jsonwebtoken:jjwt-api:0.11.5'
Copy link
Contributor

Choose a reason for hiding this comment

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

구체적인 버전은 따로 변수로 추출해서 한 곳에서 관리하면 좋을 것 같아요!

ext {
    jjwt_version = '0.11.5'
}

dependencies {
    implementation "io.jsonwebtoken:jjwt-api:${jjwt_version}"
    runtimeOnly "io.jsonwebtoken:jjwt-impl:${jjwt_version}"
    runtimeOnly "io.jsonwebtoken:jjwt-jackson:${jjwt_version}"
}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

반영했습니다! 예시 감사합니다!! 👍🏻


import com.fasterxml.jackson.annotation.JsonProperty;

public record KakaoAccount(@JsonProperty("email") String email) {}
Copy link
Contributor

Choose a reason for hiding this comment

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

Json 필드 이름과 KakaoAccount 객체의 필드 이름이 같은데 @JsonProperty는 제거해도 좋을 것 같아요!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

그렇네요! 반영했습니다~ 감사합니다👍🏻


public AuthController(AuthService authService) {
this.authService = authService;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Lombok의 @RequiredArgsConstructor 를 사용해보는 것도 좋을 것 같아요
왠지 어노테이션 무엇을 해줄지 알 것 같지 않나요?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

생성자 주입해주는 거 너무 쌈@뽕하네요.. 왼전 최고에요🥺 파일 전반적으로 모두 적용했습니다! 감사합니다~

this.email = email;
}

public static Member createMember(String email) {
Copy link
Contributor

@nove1080 nove1080 Sep 24, 2024

Choose a reason for hiding this comment

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

정적 팩토리 메서드의 이름을 지을 때 컨벤션을 지켜준다면 다른 개발자들이 보기 편할 것 같아요!

이 경우에는

public static Member from(String email)

이렇게 바꿀 수 있을 것 같네요

정적 팩토리 메서드 네이밍 컨벤션
https://velog.io/@saint6839/%EC%A0%95%EC%A0%81-%ED%8C%A9%ED%86%A0%EB%A6%AC-%EB%A9%94%EC%84%9C%EB%93%9C-%EB%84%A4%EC%9D%B4%EB%B0%8D-%EB%B0%A9%EC%8B%9D

Copy link
Contributor Author

Choose a reason for hiding this comment

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

덕분에 공부했습니다! 반영했습니다~

@westzeroright
Copy link
Contributor Author

westzeroright commented Sep 24, 2024

피드백 다들 너무 감사드립니다!! 확인 부탁드려요~~

@westzeroright westzeroright marked this pull request as draft September 25, 2024 10:22
@westzeroright westzeroright requested review from nove1080 and rbm0524 and removed request for nove1080 and rbm0524 September 25, 2024 10:22
@westzeroright westzeroright marked this pull request as ready for review September 25, 2024 10:36
@westzeroright westzeroright merged commit 64a258a into weekly_4 Sep 25, 2024
@westzeroright westzeroright self-assigned this Sep 26, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants