Project/토이 프로젝트

[Refactoring] 여러 소셜 로그인을 위한 공통영역 분리

Lea Hwang 2023. 1. 31. 10:35

OAuth2.0 소셜 로그인

회원 정보 받는 곳을 한 패키지에서 관리합니다.

전 Google과 Naver만 구현했지만 트위터, 카카오 등 원하는 만큼 클래스를 생성해서 구현할 수 있습니다. 

 

 

 

 

OAuth2UserInfo

public interface OAuth2UserInfo {
    String getProviderId(); 
    String getProvider(); 
    String getEmail();
    String getName();
}

공통적으로 가져올 정보입니다.

 

 

 

GoogleUserInfo

public class GoogleUserInfo implements OAuth2UserInfo{

    private Map<String, Object> attributes; // oauth2User.getAttributes()

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

    @Override
    public String getProviderId() {
        return (String) attributes.get("sub");
    }

    @Override
    public String getProvider() {
        return "google";
    }

    @Override
    public String getEmail() {
        return (String) attributes.get("email");
    }

    @Override
    public String getName() {
        return (String) attributes.get("name");
    }
}
  • OAuth2UserInfo를 implements 합니다.
  • 소셜 로그인을 한 후 회원정보를 받을 필드 작성
    • private Map<String, Object> attributes;
  • 소셜로그인의 response에 맞게 return문을 작성합니다. 

 

 

 

Google 말고 다른 그리고 여러 개의 소셜로그인을 추가하고 싶다면

이제 provider패키지 안에 각각의 클래스를 만들어 사용할 수 있습니다.

구글

네이버

페이스북

트위터....

 

 

 

그럼 이런 의문이 들 수 있습니다.

일반 로그인 사용자 VS. 소셜 로그인 사용자는 DB에서 어떻게 구분할 수 있을까요?

해당 부분은 User모델에 OAuth2.0 전용 필드를 추가하는 것으로 해결할 수 있습니다.

 

User

...
@Entity
public class User extends BaseTimeEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;

    ...

    // OAuth2.0
    private String provider;
    private String providerId;

}

 

 

기존 유저인지 확인해볼 때는 UserRepository에 provider와 providerId를 체크하면됩니다.

public interface UserRepository extends JpaRepository<User, Integer> {

    User findByUsername(String username);

    // OAuth2.0 로그인
    User findByProviderAndProviderId(String provider, String providerId);
}

 

 

그리고 만약 해당 소셜 로그인으로 처음 접속했다면

// 이미 존재하는 유저인지 확인
User userEntity =
        userRepository.findByProviderAndProviderId(oAuth2UserInfo.getProvider(), oAuth2UserInfo.getProviderId());


if(userEntity != null) {
    return new CustomUserDetails(userEntity);
}else {
    User user = User.builder()
            .username(username)
            .email(email)
            .name(name)
            .password(password)
            .role("ROLE_USER")
            .provider(oAuth2UserInfo.getProvider())
            .providerId(oAuth2UserInfo.getProviderId())
            .build();
    return new CustomUserDetails(userRepository.save(user));
}

 

위에서 작업한 OAuth2UserInfo.getProvider, OAuth2UserInfo.getProviderId를 가져와서 provider와 providerId에 업데이트합니다. 

 

 

 

그럼 일반 사용자는 해당 필드에 null이 소셜 로그인 사용자는 값이 채워지는 것을 확인할 수 있습니다. 

 

 

 

 

 

 

 


 

 

관련 프로젝트 포스팅은 소셜 로그인 (구글, 네이버) 및 NFT 이미지 추가 - (14) 입니다.