Suwiki 버그일지 (@Transient)

정지원·2023년 4월 26일
0

서사 & 문제

운영중인 수원대학교 강의평가 플랫폼 Suwiki의 프로덕션 코드를 리팩토링 한 후,
최근 강의게시물을 보았는데 강의 평균평점데이터의 신뢰성이 깨져있었다.

A : 5점, B: 5점 이면 평균은 5점이어야 하는데, 0.3 이렇게 들어가 있었다.

Test를 했을때에는 문제가 없었는데, 왜 이런 문제가 발생할까?

문제를 구체화 해야할것 같다.

구체화

기존 강의평가데이터는 문제가 없었다.
가장 최근의 게시물에만 문제가 있던 상황으로 보아,
리팩토링 한 내용에서 문제를 찾아야겠다는 생각이 들었다.

리팩토링 PR

PR 에서 개선한 내용은 다음과 같다.

1. 강의 데이터중 현재 사용되지 않는 데이터들과, 평가 관련 점수 들을 각각 값객체로 분리하여 책임을 더 세부적으로 분리 하였습니다.
2. 평균값 연산을 위한 Value (총 점) 필드는 저장할 필요 없는 임시 필드이므로 Transient 를 통해 영속성 대상에서 제거 하였습니다.
3. Null 값을 받을 수 있는 참조 타입 같은 경우 굳이 Optional 을 사용하지 않고 Null check 하는 로직으로 변경하였습니다.

문제는 바로 2번에 있었다.

Suwiki 에서 평균값을 관리하는 방식

  • 우리 어플리케이션에서는 평균점수를 유연하게 구하기 위해서,
    평균점수, 점수 총합, 강의개수 이런 필드들로 구성되어있다.

  • 점수총합 또는 강의개수가 업데이트되면, 평균점수는 (점수총합/강의개수) 값으로 업데이트 된다.

왜 그런 문제가 발생했을까?

@Transient

메서드 또는 필드를 더이상 영속대상으로 관리하고 싶지 않을때 사용한다.

사용한 이유

점수 총합 필드는 평균값을 구하기 위한 임시 필드라고 생각했다.
총합을 직접적으로 응답해줄일도 없어서, 해당 필드는 영속성 관리를 할 필요가 없다고 생각.

문제 발생 이유

평균값을 영속성 관리를 해주지 않았기 때문에 일어난 문제였다.
기존 영속성 관리를 하던 점수총합이 영속대상에서 제거되면서
Application 이 처음 실행될때 0으로 초기화가 되었다.


기존데이터 - A:5 , B:5, 평균값 : 5, 총점 : 10, 개수 : 2
추가하려는 데이터 - C:5 평균값 : 1.6XX, 총점 : 5, 개수 : 3 (버그발생)

`

테스트에서 발견되지 않은 이유

언제 문제가 생길까? 에 대한 고민이 이와 연관되어있다고 생각한다.
결국 문제는 영속대상에서 제외되면서 서버가 새로 시작되면
기존 메모리에 가지고 있던 점수총합데이터가 초기화
된다는 점이다.
기존데이터가 있는 상태에서 서버가 초기화 되어야 이 문제가 발생 하게 된다.

이문제를 테스트 할 수 있는 방법

운영 DB 와 비슷한 테스트 DB 인스턴스를 하나 만드는 것도 좋은 방법 같다.


그게 아니라면, 운영 DB 와 비슷하게 데이터도 어느정도 넣어둔 테스트 전용
DB DDL, DML 을 관리
하는 것도 이 문제를 해결 할 수 있는 방법이 될 것 같다. 이부분은 팀원과 상의해서 적용 후 일지를 통해 공유 하겠다.

해결

  • 잘못 들어간 데이터는 직접 계산을 통해 복구를 해놓았다.

    테스트의 커버리지 중요성을 크게 깨닫는 경험이였다.

  • @Transient 를 모두 제거하였다.

그럼 언제 @Transient 를 사용해야할까?

  • 기본개념은 JPA에서 데이터베이스에 저장할 필요가 없는 엔티티의 필드나 속성에 사용된다.
  • 예를들어, 로그에 관한 필드나 꾸준히 값을 이용하는게 아닌 정말 Temp 저장소 같은 곳에 사용해야 한다.

마지막 복기 : @Transient 를 점수총합에 쓰면 안됐던 이유

점수총합은 우리가 응답으로 사용하진 않지만, 평균값을 위해 영속관리가 필요했던 대상이였다.
다음부터는 @Transient 를 적용할때에는 이런 사이드이팩트를 생각하고 적용해보아야겠다.

profile
지속적인 발전, 태도

0개의 댓글