이전포스트의 문제해결을 다른 관점으로 해결해 보았다.
해당 부분을 yml을 이용해서 @Value 애너테이션 을 이용하여서 숨길려고 시도해 보았지만 spotifyAPI.clientCredentials().build() 부분에서 로그상에 정상적으로 토큰이 존재하는데도 불구하고 옳지 않은 키 값으로 나왔다. 아무래도 스프링이로 등록될때 절차상에 제가 놓친부분이 있는거 같았다 !
@Slf4j
@Component
public class SpotifyConfig {
private static String CLIENT\_ID;
private static String CLIENT\_SECRET;
@Value("${spotify.registration.client-id}")
public void setClientId(String clientId) {
CLIENT\_ID=clientId;
}
@Value("${spotify.registration.client-secret}")
public void setClientSecret(String clientSecret) {
CLIENT\_SECRET=clientSecret;
}
private SpotifyApi spotifyApi = new SpotifyApi.Builder().setClientId(CLIENT\_ID).setClientSecret(CLIENT\_SECRET).build();
private String accessToken;
private Instant accessTokenExpiration;
public String getAccessToken(){
if (accessToken == null || Instant.now().isAfter(accessTokenExpiration)) {
refreshAccessToken();
}
return accessToken;
}
private void refreshAccessToken() {
ClientCredentialsRequest clientCredentialsRequest = spotifyApi.clientCredentials().build();
log.info("새로운 리프레쉬 토큰 발급을 위한 과정 시작");
log.info("현재 정의된 Client-id : "+CLIENT\_ID);
log.info("현재 정의된 Client-secret : "+CLIENT\_SECRET);
try {
final ClientCredentials clientCredentials = clientCredentialsRequest.execute();
log.info("0");
accessToken = clientCredentials.getAccessToken();
log.info("현재 발급된 토큰 : "+accessToken);
// 토큰의 유효 시간을 계산하여 저장합니다.
accessTokenExpiration = Instant.now().plusSeconds(clientCredentials.getExpiresIn());
log.info("2");
spotifyApi.setAccessToken(accessToken);
log.info("3");
} catch (IOException | SpotifyWebApiException | org.apache.hc.core5.http.ParseException e) {
System.out.println("Error: " + e.getMessage());
accessToken = "error";
}
}
}
다시 @Value
애너테이션의 변수 주입시점을 스프링 빈 등록 과정에서 어떤 곳에서 이루어지는지 파악을 해본 결과 문제의 원인은 생성자에서 SpotifyApi
객체를 초기화할 때 CLIENT_ID
와 CLIENT_SECRET
의 값이 초기에 할당되지 않아 null
로 들어가게 되는 것이였다. Spring의 라이프사이클에서 @Value
를 사용한 주입은 빈이 생성될 때 수행되므로, SpotifyApi
를 초기화하는 생성자에서는 해당 값들이 초기화되지 않은 상태였다.
이것을 해결하기 위해서 SpotifyApi
의 초기화를 위한 작업을 @PostConstruct
메서드나 InitializingBean
인터페이스를 구현한 afterPropertiesSet()
메서드 등을 사용하여 빈이 생성된 후에 수행하도록 변경하였습니다. 이렇게 하면 CLIENT_ID
와 CLIENT_SECRET
이 이미 주입된 상태에서 SpotifyApi
를 초기화할 수 있었고, 테스트 결과 Client-id가 잘못되었다는 위의 오류가 더이상 나오지 않았다.
아래는 위의 두가지 해결방법중에 @PostConstruct
을 이용하여서 빈이 생성될때 @Value
주입이 수행되고 난 뒤에 Spotifyapi를 초기화 하도록 수정하였다.
import javax.annotation.PostConstruct;
@Component
@Slf4j
public class SpotifyConfig {
@Value("${spotify.registration.client-id}")
private String CLIENT_ID;
@Value("${spotify.registration.client-secret}")
private String CLIENT_SECRET;
private SpotifyApi spotifyApi;
private static String accessToken;
private static Instant accessTokenExpiration;
@PostConstruct
public void initialize() {
log.info("CLIENT_ID = {}", CLIENT_ID);
log.info("CLIENT_SECRET = {}", CLIENT_SECRET);
this.spotifyApi = new SpotifyApi.Builder().setClientId(CLIENT_ID).setClientSecret(CLIENT_SECRET).build();
refreshAccessToken();
}
}
이렇게 하면 SpotifyApi
객체 초기화는 @PostConstruct
어노테이션이 붙은 메서드에서 수행되며, 이 메서드는 스프링 빈이 생성된 후에 호출된다. 따라서 CLIENT_ID
와 CLIENT_SECRET
값이 이미 주입된 상태에서 SpotifyApi
를 초기화할 수 있다. 해당 코드대로 수정하였고, 정상적으로 동작되었다.
해당 과정을 논의하고 해결한 과정이 담긴 PR
https://github.com/Playlist-pack/Server/pull/66
♻️ [refactor] : spotify API 성능 개선 by ulsandonghun · Pull Request #66 · Playlist-pack/Server
기존의 순수 자바코드로 동작하던 AccessToken을 받는 과정이 담긴SpotifyConfig를 스프링 빈 컨테이너로 등록하여 싱글톤으로 관리되게 하였습니다. 매번 SpotifyApi의 기능을 사용할때마다 반복 호출
github.com
'기록 > Spring framework' 카테고리의 다른 글
JPA의 영속성 컨텍스트와 플러시 이해하기(2024-01-26) (0) | 2024.01.26 |
---|---|
@Value 애너테이션 static 필드에 적용하기. (0) | 2024.01.25 |
스프링 시큐리티 필터 동작 과정(2024-01-22) (0) | 2024.01.22 |
JWT 와 Session 적용기 (2024-01-22) (0) | 2024.01.22 |
@NotNull 비활성화 이슈 (2024-01-15) (0) | 2024.01.15 |