-
properties 불변 객체로 주입하기프로젝트/잡스캐너 2022. 9. 8. 21:23
로그인시 발급하는 JWT를 생성할 때 secret 값과 expiry 값, 소셜 로그인할 때 url, client-id, client-secret 값 등을 application.yml에 설정하고 클래스에서는 @Value를 통해 주입했다.
auth: client: kakao: token-url: https://kauth.kakao.com/oauth/token redirect-url: https://dev.jobscanner.app/oauth/callback/kakao client-id: client-secret: google: token-url: https://oauth2.googleapis.com/token redirect-url: https://dev.jobscanner.app/oauth/callback/google client-id: client-secret: github: token-url: https://github.com/login/oauth/access_token redirect-url: https://dev.jobscanner.app/oauth/callback/github client-id: client-secret: jwt: app-token-secret: refresh-token-secret: app-token-expiry: refresh-token-expiry:@Value("${auth.jwt.app-token-expiry}") private String appTokenExpiry; @Value("${auth.jwt.refresh-token-expiry}") private String refreshTokenExpiry; private final Key appKey; private final Key refreshKey; private static final String AUTHORITIES_KEY = "role"; public AuthTokenProvider( @Value("${auth.jwt.app-token-secret}") String appSecretKey, @Value("${auth.jwt.refresh-token-secret}") String refreshSecretKey) { this.appKey = Keys.hmacShaKeyFor(appSecretKey.getBytes()); this.refreshKey = Keys.hmacShaKeyFor(refreshSecretKey.getBytes()); }@Value("${auth.client.kakao.token-url}") private String tokenUrl; @Value("${auth.client.kakao.redirect-url}") private String redirectUrl; @Value("${auth.client.kakao.client-id}") private String clientId; // JavaScript 키 @Value("${auth.client.kakao.client-secret}") private String clientSecret;하지만 @Value를 통해 주입하는 방법은 클래스가 생성된 이후에 Setter를 통해 주입해서 값을 주입 받은 객체를 final한 객체로 생성할 수 없다. 프로그램 관점에서 언제든지 값을 변경할 수 있는 변수는 에러와 버그를 만들어내는 주된 원인이다. 그래서 가능한 불변 객체를 생성하는 것이 좋다. 그런 이유에서 함수형 프로그래밍에서는 변수 변경을 아예 허용하지 않고 자바8 람다에서 변수를 변경할 수 없다.
따라서 @Value를 통해 값을 주입하는 방법 말고 값을 불변 객체로 주입할 수 있는 방법을 찾아보고 적용했다. 바로 @ConstructorBinding을 사용하여 final 필드에 값을 주입하는 것이다. @ConfigurationProperties(prefix = )와@ConstructorBinding을 통해 .yml과 값을 매칭하고 @EnableConfigurationProperties 사용해 Spring Bean으로 등록하고 @Configuration해주는 것이다.@ConfigurationProperties(prefix = )와 @ConstructorBinding을 통해 .yml과 값을 매칭한다.
@ConstructorBinding @ConfigurationProperties(prefix = "auth") public record AuthProperties( Client client, Jwt jwt ) { public record Client( Kakao kakao, Google google, Github github ) { public record Kakao( String tokenUrl, String redirectUrl, String clientId, String clientSecret ) { } public record Google( String tokenUrl, String redirectUrl, String clientId, String clientSecret ) { } public record Github( String tokenUrl, String redirectUrl, String clientId, String clientSecret ) { } } public record Jwt( String appTokenSecret, String refreshTokenSecret, String appTokenExpiry, String refreshTokenExpiry ) { } }
@EnableConfigurationProperties를 Spring Bean으로 등록하고 @Configruation한다.@Configuration @EnableConfigurationProperties(value = {AuthProperties.class}) public class PropertiesConfig { }
이렇게 설정하면 properties 값을 객체 생성시에 주입해서 불변 객체로 값을 주입할 수 있다.private final String tokenUrl; private final String redirectUrl; private final String clientId; private final String clientSecret; public KakaoTokenValidator(AuthProperties authProperties) { AuthProperties.Client.Kakao kakaoClient = authProperties.client().kakao(); this.tokenUrl = kakaoClient.tokenUrl(); this.redirectUrl = kakaoClient.redirectUrl(); this.clientId = kakaoClient.clientId(); this.clientSecret = kakaoClient.clientSecret(); }Setter로 주입하는 @Value 대신 불변 객체로 값을 주입할 수 있는 @ConstructorBinding을 사용하자!
참고
https://tecoble.techcourse.co.kr/post/2020-09-29-spring-properties-binding/'프로젝트 > 잡스캐너' 카테고리의 다른 글
Optional 활용하기, 람다식에서 지역변수 변경하기 (0) 2022.09.08 클래스다이어그램 - 의존성 그려보기 (0) 2022.09.08 불변 객체 생성 방법 - 정적 팩토리 메서드와 빌더 패턴 (0) 2022.09.08 자바 16 레코드 클래스 (0) 2022.09.08 채용 공고 수집하기 (0) 2022.08.28