운영중인 수원대학교 강의평가 플랫폼 Suwiki의 프로덕션 코드를 리팩토링 한 후,
최근 강의게시물을 보았는데 강의 평균평점데이터의 신뢰성이 깨져있었다.
A : 5점, B: 5점 이면 평균은 5점이어야 하는데, 0.3 이렇게 들어가 있었다.
Test를 했을때에는 문제가 없었는데, 왜 이런 문제가 발생할까?
문제를 구체화 해야할것 같다.
기존 강의평가데이터는 문제가 없었다.
가장 최근의 게시물에만 문제가 있던 상황으로 보아,
리팩토링 한 내용에서 문제를 찾아야겠다는 생각이 들었다.
PR 에서 개선한 내용은 다음과 같다.
1. 강의 데이터중 현재 사용되지 않는 데이터들과, 평가 관련 점수 들을 각각 값객체로 분리하여 책임을 더 세부적으로 분리 하였습니다.
2. 평균값 연산을 위한 Value (총 점) 필드는 저장할 필요 없는 임시 필드이므로 Transient 를 통해 영속성 대상에서 제거 하였습니다.
3. Null 값을 받을 수 있는 참조 타입 같은 경우 굳이 Optional 을 사용하지 않고 Null check 하는 로직으로 변경하였습니다.
문제는 바로 2번에 있었다.
우리 어플리케이션에서는 평균점수를 유연하게 구하기 위해서,
평균점수, 점수 총합, 강의개수 이런 필드들로 구성되어있다.
점수총합 또는 강의개수가 업데이트되면, 평균점수는 (점수총합/강의개수) 값으로 업데이트 된다.
메서드 또는 필드를 더이상 영속대상으로 관리하고 싶지 않을때 사용한다.
점수 총합 필드는 평균값을 구하기 위한 임시 필드라고 생각했다.
총합을 직접적으로 응답해줄일도 없어서, 해당 필드는 영속성 관리를 할 필요가 없다고 생각.
평균값을 영속성 관리를 해주지 않았기 때문에 일어난 문제였다.
기존 영속성 관리를 하던 점수총합이 영속대상에서 제거되면서
Application 이 처음 실행될때 0으로 초기화가 되었다.
기존데이터 - A:5 , B:5, 평균값 : 5, 총점 : 10, 개수 : 2
추가하려는 데이터 - C:5 평균값 : 1.6XX, 총점 : 5, 개수 : 3 (버그발생)
`
언제 문제가 생길까? 에 대한 고민이 이와 연관되어있다고 생각한다.
결국 문제는 영속대상에서 제외되면서 서버가 새로 시작되면
기존 메모리에 가지고 있던 점수총합데이터가 초기화된다는 점이다.
기존데이터가 있는 상태에서 서버가 초기화 되어야 이 문제가 발생 하게 된다.
운영 DB 와 비슷한 테스트 DB 인스턴스를 하나 만드는 것도 좋은 방법 같다.
그게 아니라면, 운영 DB 와 비슷하게 데이터도 어느정도 넣어둔 테스트 전용
DB DDL, DML 을 관리 하는 것도 이 문제를 해결 할 수 있는 방법이 될 것 같다. 이부분은 팀원과 상의해서 적용 후 일지를 통해 공유 하겠다.
테스트의 커버리지 중요성을 크게 깨닫는 경험이였다.
점수총합은 우리가 응답으로 사용하진 않지만, 평균값을 위해 영속관리가 필요했던 대상이였다.
다음부터는 @Transient 를 적용할때에는 이런 사이드이팩트를 생각하고 적용해보아야겠다.