본문 바로가기

Proj/Tripot

Trouble Shooting: @Value에 값이 불러와지지 않는 문제

1. 개요

카카오 로그인을 구현하다 발생한 문제이다. 프론트 측에서 코드를 받아 서버에 보내면, 서버에서 이를 Auth 서버와 Resource 서버를 통해 사용자 정보를 받아오고, 로그인을 진행하는 과정을 거치게 된다. 이렇게 개발하여 배포했을 때 카카오 측에서 401 에러를 발생시켰다. 그 원인과 해결책을 알아보고자 한다.

2. 원인?

로깅 레벨을 debug로 보고 관련 로그를 확인해보았다. 진행 로직에서 다음의 URL로 Auth Server에 요청을 보내는 것을 확인할 수 있었다.

https://kauth.kakao.com/oauth/token?grant_type=authorization_code&client_id&code=인증 코드&client_secret

이걸 보고 client_id와 secret key가 제대로 담기지 않은 것을 확인할 수 있었다. 그렇다고 yml 파일을 읽지 못한 것은 아니었다. 로그에서도 확인했고, yml 파일을 읽지 못했다면 실행 자체가 안될 수 있었기 때문이다. 

    @Value("${kakao.client-id}")
    private String clientId;
    @Value("${kakao.client-secret}")
    private String secretKey;

따라서 해당 부분에 문제가 있음을 추측하였다.

2-1. 왜 읽지 못하였는가?

이에 앞서 해당 코드는 다음과 같이 사용되었다.

    private OAuth2UserInfo generateOAuth2UserInfo(String code, OAuth2Provider provider) {
        //소셜 로그인 전략 설정
        if (provider == OAuth2Provider.KAKAO) {
            oAuth2UserGenerator.setOAuth2MemberStrategy(new KakaoOAuth2LoginStrategy());
        }

        //OAuth2 과정 진행 후 사용자 정보 받아오기
        OAuth2UserInfo userInfo = oAuth2UserGenerator.signUpOAuth2(code);
        return userInfo;
    }

OAuth2Service의 일부이다. 여러 소셜 로그인을 추가함이 예정됨에 따라, 전략 패턴을 사용하기로 하였고 위와 같이 코드를 작성했다. 

@Value 애노테이션은 애플리케이션 로딩 시점에 스프링 빈을 등록하면서 설정 파일의 값을 저장한다. 그런데 new 키워드를 사용하여 새로운 객체를 생성하게 되면 해당 객체는 런타임 시점에 새로 생성되는 객체이고, 당연히 스프링 빈으로 등록이 안되어 있으므로 null 값이 저장되게 되는 것이다. 

3. 해결 방안

    private final KakaoOAuth2LoginStrategy kakaoOAuth2LoginStrategy;
    
        private OAuth2UserInfo generateOAuth2UserInfo(String code, OAuth2Provider provider) {
        //소셜 로그인 전략 설정
        if (provider == OAuth2Provider.KAKAO) {
            oAuth2UserGenerator.setOAuth2MemberStrategy(kakaoOAuth2LoginStrategy);
        }

        //OAuth2 과정 진행 후 사용자 정보 받아오기
        OAuth2UserInfo userInfo = oAuth2UserGenerator.signUpOAuth2(code);
        return userInfo;
    }

이에 따라 로그인 전략에 대한 의존성을 추가하고, 위와 같이 수정하였다. 이후 로그인이 잘 되는 것을 프론트 측을 통해 확인할 수 있었다.

4. 여담

간단하게나마 해결은 하였으나 이렇게 코드가 구성되면 새로운 전략이 추가될 때 마다 해당 전략을 OAuth2Service가 의존해야 하는데, 별로 좋은 코드라는 생각이 들지는 않는다. 이에 대해서는 추후 리팩토링이 한번 필요할 것 같다.