한번더 코드를 갈아엎어야 한다.

지금 위와 같은 코드로 ApiCall 함수를 활용하여 데이터를 받아들이고 있다. 하지만 여기서 데이터를 파싱한 후 DB에 넣어야 하는데, 이걸 어떻게 해야 하지? 라는 고민이 생겼다.
Api 호출하는 코드, url로 만들어주는 코드, 호출하는 코드 여러개 등등 하나의 파일에 기능이 너무 많이들어있어서 너무 복잡하다는 것이다.
그래서 하고싶은 말은 뭐냐 하니
Mono, Flux로 데이터를 받아오는 코드를 각각의 새로운 파일로 만드는 것이다.
그러니 파일의 구조를 다음과 같이 개편한다는 것이다.

분명히 이런식으로 파일을 만들면 호출하는 곳 마다 파일이 생길 것이고, 적어도 8개 정도의 파일이 생길것이라 생각한다.
하지만 파일이 많아진다 하더라도, 기능을 정확하게 분리시켜야 된다고 생각했다. 이후 DB에 데이터도 집어넣어야 하기 때문이다.
다행히 기본 코드에서 WebClient 설정, env 데이터 받아오기 등등 기본적인것을 다 해놔서 형식만 맞춰주면 될것이다.
// API 호출 메서드
public Mono<String> makeApiCall(String baseUrlKey, String pathKey, String keyParam, String... queryParams) {
String baseUrl = env.getProperty(baseUrlKey);
String path = env.getProperty(pathKey);
String key = env.getProperty(keyParam);
String fullUrl = baseUrl + path + "?" + String.join("&", queryParams) + key;
기존 코드에서는 key를 env.getProperty를 통해 가져왔다.
하지만 다른 파일에서는 이를 할 수 없음으로 파라미터를 통해 받은 데이터를 활용할 것이다.
형식은 다음과 같다.
BaseURL + Path + "?" + Parameter + "ServiceKey" or "apiKey" + serviceKey
여기서 골때리는게 Parameter에서 Key를 부르는 형식이 제각각이다.
한전쪽은 apiKey라고 부르고, 공공데이터 쪽에서는 ServiceKey 라고 부른다.
따라서, 이것까지 싹다 Parameter로 받아버리려고 했다.
이렇게 되면 호출값은 다음과 같다.
makeApiCall("KCA_URL", "KCA_ProdPrice_Path","DATA_Key", "goodInspectDay=" + LF, "entpId=100", "ServiceKey="),
그리고 결합도 때문에 날짜 관련 함수를 그대로 쓸려고 했지만..
public class DateUtils {
// 오늘 이전의 날짜에서 가장 먼저 만나는 달의 첫번째 금요일을 계산하는 메서드
public static String calculateLastFridayBeforeToday() {
LocalDate today = LocalDate.now();
LocalDate FFM = today
.with(TemporalAdjusters.firstDayOfMonth()) // 이번 달의 첫 번째 날로 이동
.with(TemporalAdjusters.nextOrSame(DayOfWeek.FRIDAY)); // 이번 달 첫 번째 금요일로 이동
// 만약 첫 번째 금요일이 오늘 이후라면, 전달의 첫 번째 금요일로 이동
if (FFM.isAfter(today)) {
FFM = today.minusMonths(1)
.with(TemporalAdjusters.firstDayOfMonth()) // 이전 달의 첫 번째 날로 이동
.with(TemporalAdjusters.nextOrSame(DayOfWeek.FRIDAY)); // 이전 달의 첫 번째 금요일로 이동
}
return FFM.format(DateTimeFormatter.ofPattern("yyyyMMdd"));
}
}
너무나도 함수가 커져버리기 때문에 그냥 새로운 파일을 만들었다.
저 함수가 나온 배경을 설명하자면

또한 KCA_ProdPrice 파일을 작성하고 있다.
@Service
public class KCA_ProdPrice {
private final Public_service publicService;
private static final Logger logger = LoggerFactory.getLogger(KCA_ProdPrice.class);
private final String LF = DateUtils.calculateLastFridayBeforeToday();
public KCA_ProdPrice(Public_service publicService) {
this.publicService = publicService;
}
public void parseApiCall() {
// API 호출
Mono<String> apiCallResult = publicService.makeApiCall(
"KCA_URL",
"KCA_ProdPrice_Path",
"DATA_Key",
"goodInspectDay=" + LF,
"entpId=100",
"ServiceKey="
);
logger.info("result: {}", apiCallResult.block());
}
}
(생각보다 이거 만드는데 시간도 엄청 오래걸리고 이해도 잘 못해서 하루를 썼다..ㅠㅠ)
PublicService에 있는 URL 함수들을 하나하나 분리한 후, 각각 Parse 해야 한다.

logger를 통해 데이터가 잘 들어오고 있는것도 확인하였다.
이제 파싱을 하면 된다.
그리고 원래 있던 PublicService는
@Service
public class Public_service {
private static final Logger logger = LoggerFactory.getLogger(Public_service.class);
private final WebClient webClient;
private final Environment env;
@Autowired
public Public_service(Environment env, WebClient.Builder webClientBuilder) {
this.env = env;
this.webClient = webClientBuilder
.exchangeStrategies(ExchangeStrategies.builder()
.codecs(configurer -> configurer.defaultCodecs().maxInMemorySize(10 * 1024 * 1024)) // 10MB로 설정
.build())
.build();
}
public Mono<String> makeApiCall(String baseUrlKey, String pathKey, String keyParam, String... queryParams) {
String baseUrl = env.getProperty(baseUrlKey);
String path = env.getProperty(pathKey);
String key = env.getProperty(keyParam);
String fullUrl = baseUrl + path + "?" + String.join("&", queryParams) + key;
logger.info("Making request to URL: {}", fullUrl);
return webClient.get()
.uri(URI.create(fullUrl))
.retrieve()
.bodyToMono(String.class)
.doOnError(e -> logger.error("Error during API call", e));
}
}
엄청나게 줄어서 50줄이 되었다.
여기서 하나 말하고 싶은건 @Autowired 관련이다.
Public_service를 만들었고, 이를 @Autowired를 사용하지 않으면 의존성이 주입되지 않고, 다른 클래스에서 Public_service를 쓴다고 한들 새로운 생성자를 또 만들어서 집어넣어야 된다.
왜 이번글에 별로 한거없는 리팩토링인데도 불구하고 오래 걸렸느냐 하면
뭔소리냐 하면
리팩토링 한답시고 메서드 하나 새로운 파일로 리팩토링 시키니까 static 아닌곳에서 static을 호출을 했니 DI관련 오류(참고를 잘못함) 자꾸떴었고
여러개의 메서드 중에서 어떤거를 개별 파일로 빼내야 할지도 고민이고
결합도 관련해서 자꾸 늘어나니 고민이 되기도 했었다.
결국 여러가지 고민을 하다가 위와 같이 리팩토링 했는데,
나름 만족하는 결과를 낸거 같다.
내일 예비군이니까 빨리 씼고 자야겠다.