트러블 슈팅 & 불편함을 해소한 기록 - jinkshower/galmanhae GitHub Wiki
프로젝트를 진행하며 발생한 트러블 슈팅, 불편함을 스스로 해결한 기록입니다
@PostConstruct와 외부 API 호출
WireMock을 @PostConstruct와 함께 적용해 테스트를 작성할때 객체 모킹이 애플리케이션 빈 로드보다 늦게 이루어져 테스트를 할 수 없는 이슈가 발생했음. 해당 부분을 해결하기 위해 여러 방법을 찾아보았고.아예 PostConstruct로 데이터를 fetch하는 단계를 운영환경에서만 사용하는 방법을 떠올리게 됨.
운영환경에서만 빈을 만들면 테스트가 불가능해져 히스토리 관리가 불가능해질 거라 판단했고 애플리케이션 시작시 메서드를 실행하는 책임을 다른 객체가 가지게 하면 원하는 대로 커스텀해서 테스트할 수 있고 테스트도 가능할 거라 생각함.
'DataInitializer' 클래스를 빈으로 등록하여 해당 객체에 @PostConstruct를 하는 책임을 주고 외부 API 호출을 하는 객체는 호출을 받게 만들어 빈 로딩보다 빠른 모킹 등 복잡한 테스트를 만드는 과정 없이 테스트 가능한 코드로 만들어냄.
@Configuration
@Profile("prod")
@RequiredArgsConstructor
public class DataProcessInitializer {
private final PlaceInfoDataProcessor placeInfoDataProcessor;
@PostConstruct
public void init() {
placeInfoDataProcessor.process();
}
}
장소 상세 정보가 없으면 지도 렌더링을 하지 말아야 할까?
전체 장소 조회시 한 장소의 데이터라도 없다면 요청자체가 예외가 나는 이슈가 발생. 습관적으로 DB 조회시 결과가 없으면 예외를 던지던 코딩 습관 때문이었음.
@Override
public Congestion findMostRecentByPlaceId(final Long placeId) {
return congestionJpaRepository.findMostRecentByPlaceId(placeId)
.map(CongestionEntity::toDomain)
.orElseThrow(() -> new NotFoundCongestionException(placeId));
}
-> 서비스적인 측면에서 한 장소의 데이터가 없다고 해도 사용자는 다른 장소들의 데이터는 보고 싶어할 것이라고 판단했음.
@Override
public Congestion findMostRecentByPlaceId(final Long placeId) {
return congestionJpaRepository.findMostRecentByPlaceId(placeId)
.map(CongestionEntity::toDomain)
.orElse(Congestion.of(0, "NONE"));
}
따라서 찾을 수 없다면 invalid한 객체를 orElse로 반환하고 외출 점수를 계산하는 로직에서 해당 부분이 알려질 수 있게 변경함.
일정 시간에서 스케쥴러가 동작하지 않는 오류
DB에 일정 시간(이 경우에는 2024-08-30 06시) 이후의 데이터가 적재되지 않고 있음을 발견했음.
로깅된 서버시간을 체크하니 현재 시간과 맞지 않았음. 서버의 timezone을 Asia/Seoul로 설정하고 jvm옵션
"-Duser.timezone=Asia/Seoul"
를 추가하여 서버와 현재 시간대 sync를 맞춤
매번 formatter를 손수 적용해야 할까?
갈만해 프로젝트는 Code of Conduct에 따라 매 PR마다 포맷터를 적용해 통일성과 코드 가독성을 지키려고 노력하고 있음. 매번 커밋하기전 변경이 있는 파일을 선택하거나 수동으로 reformat code를 해주는 것이 반복적이고 비효율적이라 생각되었음.
오픈 소스 컨트리뷰션 경험을 통해 포맷터를 자동화할 수 있는 방법을 배워, 프로젝트에 적용하려 했지만 intellij에서 자체적으로 Actions on save(저장시 자동으로 포맷터 적용)을 제공하고 있는 것을 발견, 포맷터 적용을 자동화함.
assertThat()을 매번 import해야 할까?
테스트 작성시 AssertJ의 문법이 가독성이 훨씬 좋다고 여겨 사용하고 있었지만, Junit5의 경우 기본적으로 jupiter의 Assertions를 스태틱 임포트하고 있어 매번 import를 해줘야 했음.
해당 부분이 귀찮고 비효율적이라 느껴져 intellij에서 테스트 클래스를 만들 때마다 자동으로 AssertJ의 Assertions를 임포트 하는 템플릿 설정.