2025. 5. 23. 14:55ㆍProject
문제 정의: 다른 함수까지 Dto 내부 값이 따라오는 상황
현재 스마트제조 KPI 연계 시스템에 KPI 값을 보내주어야한다.
하나의 측정 수치를 통해 향상율을 계산하여 Lv.2에는 향상율에 대한 값, Lv3에는 측정 값을 보내주어야한다.
현재 스케쥴러에 의해 매달 마지막 날 해당 월의 생산량과 향상율을 계산하여 보내주는데,
이전 로직에서 오류가 생겨 보내지지 않은 것을 확인했다.
이러한 경우를 방지하기 위해 DB에 응답에 대한 메시지를 저장하는 방식으로 변경을 진행하였다.
같은 분류라도 다른 API로 보내야하기 때문에 각각의 결과가 생겨 DB에 따로 저장을 진행하였다.
하지만, 같은 Dto를 사용하여 계산을 하였기 때문에
Level2에서 설정한 응답값 값들이 Level3 전송에도 함께 따라가는 객체 참조에 대한 문제가 발생하였다.
원인 분석: Java는 객체를 '참조'로 전달한다
Java에서 객체를 변수에 할당하거나 메서드 인자로 넘기면, 값이 아니라 주소(참조) 가 전달된다.
하나의 dto 만든 후 각각의 service의 함수로 보내면 함수에서 설정한 값들은 해당 함수에서만 작동하고
밖에서는 다시 원상태의 dto를 다른 함수로 보내진다고 생각했던 점이 원인이였다.
KpiDataLevel2SND(kpiApiDataDto);
KpiDataLevel3SND(kpiApiDataDto);
하지만, 객체로 주소를 공유하는 것이기 때문에 해당 주소의 값이 변하면 그 값을 다른 함수에서 참고하게 된다.
트러블슈팅: 객체 분리 또는 복사로 해결
방법 1: 새 객체로 복사해서 사용
KpiApiDataDto dtoForLv3 = new KpiApiDataDto();
BeanUtils.copyProperties(dto, dtoForLv3);
sendLevel2(dto);
sendLevel3(dtoForLv3);
Spring의 BeanUtils.copyProperties()를 사용하면 DTO의 값만 복사한 새로운 인스턴스를 만들 수 있다.
방법 2: 값 수동 복사
수동으로 필요한 필드만 복사할 수도 있다:
KpiApiDataDto dtoForLv3 = new KpiApiDataDto();
dtoForLv3.setKpiCertKey(dto.getKpiCertKey());
dtoForLv3.setOcrDttm(dto.getOcrDttm()); // ... 필요한 필드만 복사
정리
문제 원인 | Java 객체는 참조형으로 전달되기 때문에 한 객체를 공유 |
발생 위치 | 같은 DTO를 재사용하면서 부작용 발생 |
해결 방법 | 새로운 객체 생성 후 복사하여 분리 처리 |
실무 팁 | API 전송이나 저장 로직이 여러 번 호출될 경우 DTO를 복제 |
마무리
Java 객체의 참조 방식이 어떻게 예상치 못한 데이터 전파를 만들 수 있는지를 확인했다.
단순한 구조에서는 문제 없지만, 트랜잭션 또는 API 통신이 중첩될수록 객체 복사 여부가 시스템 안정성에 중요한 요소가 될 거라고 예상된다.
'Project' 카테고리의 다른 글
[Spring RestTemplate]Discord Webhook으로 에러 알림 전송 (6) | 2025.06.12 |
---|---|
[jQuery] .val()로는 안 되는 Datepicker 값 복원 문제와 해결법 (0) | 2025.05.06 |
[Spring Validation] BindingResult로 에러 처리 깔끔하게 하기 (0) | 2025.04.06 |