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

#360 [refactor] 구글 로그인 구현 및 전략 패턴 적용 #371

Merged
merged 4 commits into from
Jun 11, 2024

Conversation

sohyundoh
Copy link
Member

✒️ 관련 이슈번호

Key Changes 🔑

  • 소셜 로그인의 추가적인 방식(ex. 구글 네이버) 도입했을 때 가독성과 유지보수가 좋게 하기 위한 방안을 고민하다 전략 패턴이라는 디자인 패턴을 알게 되었습니다.

전략 패턴

  • 전략 패턴은 런타임 중 알고리즘을 선택하여 반응해야하는 객체를 동적으로 실시간에 바뀌도록 하는 디자인 패턴입니다.

구현 방식

  • 원래 Abstract Class 였던 Social Service를 아래와 같이 Interface(알고리즘의 틀을 만들기 위해)로 변경해줍니다.

    public interface LoginStrategy {
    UserInfoResponse login(final String authorizationCode, final UserLoginRequest loginRequest);
    default UserInfoResponse getLoginDto(final SocialType socialType, final String clientId, final String email) {
    return UserInfoResponse.of(clientId, socialType, email);
    }
    SocialType getSocialType();
    }

  • 각 전략 클래스(Kakao, Google)를 빈으로 등록해주기 위해 Component 어노테이션을 추가합니다.

  • 이렇게 등록된 빈 클래스를 런타임에 따라 매칭해주는 매니저가 필요합니다. 저 같은 경우는 로그인 방법을 enum SocialType으로 구분했기 때문에 각 전략 클래스에(클래스가 담당하는 로그인 방법을 담기 위해 아래와 같이 Getter와 함께 정의해줍니다.

    @Getter
    private final SocialType socialType = SocialType.GOOGLE;

    Map으로 빈클래스들을 불러올 수 있게 도와주는 매니저 클래스를 정의합니다.
    @Component
    public class LoginStrategyManager {
    private final Map<SocialType, LoginStrategy> loginStrategies;
    public LoginStrategyManager(final List<LoginStrategy> strategies) {
    this.loginStrategies = strategies.stream().collect(Collectors.toMap(LoginStrategy::getSocialType, Function.identity()));
    }
    public LoginStrategy getLoginStrategy(final SocialType socialType) {
    return loginStrategies.get(socialType);
    }
    }

    위 코드에서 확인할 수 있듯이 생성자를 통해 의존성을 주입받고, 각 전략 클래스마다 정의되어 있는 Social Type을 키로 가지고 있습니다.

  • 실제 런타임에서는 switch, case 문으로 아래와 같이 LoginStrategy를 대응합니다.

    public UserInfoResponse getUserInfoResponse(
    final String authorizationCode,
    final UserLoginRequest loginRequest
    ) {
    return switch (loginRequest.socialType()) {
    case KAKAO ->
    loginStrategyManager.getLoginStrategy(SocialType.KAKAO).login(authorizationCode, loginRequest);
    case GOOGLE ->
    loginStrategyManager.getLoginStrategy(SocialType.GOOGLE).login(authorizationCode, loginRequest);
    };
    }

  • 확장하면서 기존에 social Id를 Long -> String을 해야한다는 것을 깨달았습니다(구글의 경우 많은 유저로 Long을 초과함), 이를 제 로컬에서는 변경했는데 머지하게 될 경우 dev, deploy 서버를 모두 수정해야 합니다.

To Reviewers 📢

  • 아직 Google Client Id와 Secret을 작성하지 않았기 때문에 CI에서 부터 에러가 날 것입니다! 일단 확인 후 적절히 변경해야하는 값 변경 후 머지해보도록합시다!

@sohyundoh sohyundoh self-assigned this Jun 3, 2024
Copy link
Contributor

@parkheeddong parkheeddong left a comment

Choose a reason for hiding this comment

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

멋쟁이... LGTM
id를 String으로 변경한 이유는 구글에서는 사용자 수가 많아 아이디를 String값으로 사용하기 때문에 기존에 우리가 쓰던 Id도 String으로 변경해야 한다 라는 의미가 맞나요??

@sohyundoh sohyundoh merged commit 4706e12 into develop Jun 11, 2024
1 check passed
@sohyundoh sohyundoh deleted the refactor/#360 branch June 11, 2024 09:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[refactor] 회원 가입 로직 리팩토링
2 participants