🐛이슈
- 발생한 오류 copy & paste
- 오류가 발생한 상황 간략히 설명
오늘 하루 예산을 조회하는 API와 오늘부터 말일까지의 날짜별 하루 예산을 조회하는 API에서 오류가 생겼었다.
- 구체적인 오류
- 8월 12일에 배포 서버의 swagger에서 테스트한 결과, 원래대로면 12일부터 31일까지의 하루 예산만 나와야 했지만, 10일과 11일의 하루 예산까지 조회되는 문제가 발생했다.
- 로컬 서버의 swagger 테스트 결과는 정상적으로 나오는 것까지 확인했다.
- 상황
- CICD 파이프라인이 돌아간 마지막 날짜는 8월 10일이었다. 날짜가 수상하게 들어맞는다는 생각이 들어서, DayBudgetService가 스프링 빈으로 등록될 때 or 배포가 진행될 때 날짜가 고정돼버려서 생긴 문제가 아닐지 의심하게 됐고, 해당 코드를 살펴봤다.
😓원인과 해결방안
- 오류가 발생한 원인 간략히 설명
- 해결방안 설명
아래 코드를 살펴보면 오늘 날짜와 말일을 구해 저장해둔 값이 DayBudgetService 객체의 필드로 되어 있다. 해당 값들은 DayBudgetService 객체가 생성될 때 함께 생성되기 때문에, 8월 10일에 배포가 진행되면서 오늘 날짜가 8월 10일로 고정돼서 하루 예산이 10일 것부터 조회된 것이었다.
@Service
@RequiredArgsConstructor
public class DayBudgetService {
...
LocalDate now = LocalDate.now();
int year = now.getYear();
int month = now.getMonthValue();
int day = now.getDayOfMonth();
int lastDay = now.lengthOfMonth();
...
}
따라서 API가 호출될 때마다 오늘 날짜와 말일을 다르게 구하기 위해, 아래 코드처럼 필드들을 지역 변수로 바꿔 메서드 안에 넣어서 해결했다.
@Service
@RequiredArgsConstructor
public class DayBudgetService {
...
public List<DayBudget> findAllBudget(Long memberId) {
LocalDate now = LocalDate.now();
int year = now.getYear();
int month = now.getMonthValue();
int day = now.getDayOfMonth();
int lastDay = now.lengthOfMonth();
...
}
}
참고로, 스프링은 빈을 등록할 때 싱글톤 방식을 사용한다. 객체 인스턴스를 하나만 생성해 공유하기 때문에, 여러 클라이언트가 하나의 같은 객체 인스턴스를 공유하게 된다. 따라서 특정 클라이언트에 의존적인 필드나 특정 클라이언트가 값을 변경할 수 있는 필드가 있으면 안 된다.
🪽참고자료
- 링크 기록