최근 간편로그인을 리펙토링 하여 OAuth2.0 표준에 맞춰 작성했습니다.
하지만 이후 구글,네이버 를 추가하다보면 유지보수에 있어서 코드가 많이 복잡해지기 때문에 유지보수를 위해 다시 리펙토링을 결심했습니다.
먼저 기존 코드를 보겠습니다.
try {
// 카카오 인증 처리
if ("kakao".equals(oauthClientName)) {
userId = "kakao_" + oAuth2User.getAttributes().get("id");
// 데이터베이스에서 사용자 정보 조회
userEntity = userRepository.findByUId(userId);
if (userEntity == null) {
// 새로운 사용자 생성 및 저장
UserEntity newUser = new UserEntity();
newUser.setUMail((String) oAuth2User.getAttributes().getOrDefault("kakao_account.email", ""));
newUser.setUName((String) oAuth2User.getAttributes().getOrDefault("properties.nickname", "Unknown"));
newUser.setURegister(LocalDate.now());
newUser.setUPw(""); // 비밀번호는 빈 값으로 설정
newUser.setUPofile((String) oAuth2User.getAttributes().getOrDefault("properties.profile_image", ""));
newUser.setUBirth(""); // 생일 정보는 비워둠
newUser.setUTel(""); // 전화번호 정보도 비워둠
newUser.setUId(userId);
// 데이터베이스에 사용자 저장
userEntity = userRepository.save(newUser);
}
// 세션에 사용자 ID 저장
request.getSession().setAttribute("UId", userEntity.getUId());
}
} catch (Exception e) {
OAuth2Error error = new OAuth2Error("invalid_token", "Failed to process OAuth2 login", null);
throw new OAuth2AuthenticationException(error, e.getMessage());
}
기존 코드를 보면 우선 잘 정리는 되어있지만 다른 플랫폼(구글,네이버 등)의 추가가 어렵고 코드를 한 눈에 알아보기 어렵다. 또한 다른 플랫폼이 추가될 시, 코드가 길어질 가능성이 매우 높습니다.
우선 한 개의 서비스에서 동작하는 것을 두개로 나누고, 하나는 플랫폼만 판단하여 세션에 저장하는 기능과, 다른 하나는 실제 플랫폼에 맞는 로그인 로직을 실행하는 파일이다.
//
try {
switch (oauthClientName) {
case "kakao":
userId = "kakao_" + oAuth2User.getAttributes().get("id");
userEntity = oAuthLoginService.KakaoLogin(oAuth2User, userId);
session.getSession().setAttribute("UId", userEntity.getUId());
break;
}
} catch (
Exception e) {
OAuth2Error error = new OAuth2Error("invalid_token", "Failed to process OAuth2 login", null);
throw new OAuth2AuthenticationException(error, e.getMessage());
}
if문으로 조건문을 보기 보다는
switch문으로 플랫폼 이름으로 판별하면 코드 가독성을 높혔습니다.
로그인 로직은 서비스에서 관리하고 플랫폼 판별은 컨트롤러에서 작성해서 코드 가독성을 높혔습니다.
@Service
public class OAuthLoginService {
@Autowired
private UserRepository userRepository;
public UserEntity KakaoLogin(OAuth2User oAuth2User, String userId) {
UserEntity userEntity = new UserEntity();
userEntity = userRepository.findByUId(userId);
if (userEntity == null) {
UserEntity newUser = new UserEntity();
newUser.setUMail((String) oAuth2User.getAttributes().getOrDefault("kakao_account.email", ""));
newUser.setUName((String) oAuth2User.getAttributes().getOrDefault("properties.nickname", "Unknown"));
newUser.setURegister(LocalDate.now());
newUser.setUPw(""); // 비밀번호는 빈 값으로 설정
newUser.setUPofile((String) oAuth2User.getAttributes().getOrDefault("properties.profile_image", ""));
newUser.setUBirth(""); // 생일 정보는 비워둠
newUser.setUTel(""); // 전화번호도 비워둠
newUser.setUId(userId);
userEntity = userRepository.save(newUser);
}
return userEntity;
}
}
각 풀랫폼마다 불러오는 값의 이름이 다르기 때문에 해당하는 각각 따로 생성 합니다.
문제: 다른 플랫폼 추가 시, 코드 추가시 코드 복잡해진다.
해결: 플랫폼을 판별하고 세션에 저장하는 컨트롤러와, 실제 로그인 로직은 실행시키는서비스 로직을 분리하였다.