배경
•
현재 QA 여부는 응시자 엔티티 내에 Enum으로 QA 필요 여부를 관리하는 필드가 존재
•
QA 적용되는 응시자에 대해 QA가 완료된 시점을 알고 싶다는 요구사항에 따라 해당 값을 저장할 필드 추가 필요
•
해당 필드를 어디에 어떻게 추가할 지에 따른 트레이드 오프를 따져보기 위해 문서 작성
방법과 예시, 장단점
장단점 고려사항
•
컬럼, 테이블 추가 여부
•
도메인 응집도
•
코드의 간결함과 일관성
•
각 특성에 따라 발생하는 장점과 단점
•
성능
❗️새로 추가될 QA 완료 시간에 대한 컬럼이 nullable인 것은 모든 케이스에 해당되기 때문에 단점에서 제외하였습니다.
1. 단순히 필드 하나를 추가하여 QA 완료 시점을 저장하는 방법
•
상황에 따른 예시
◦
QA가 필요없는 경우
▪
QA필요여부 = 불필요 / QA완료시각 = null
◦
QA가 필요한 경우
▪
QA필요여부 = 필요 / QA완료시각 = null
◦
QA가 완료된 경우
▪
QA필요여부 = 통과 / QA완료시각 = 2024-08-09'T'16:09:44
•
장점
◦
구현이 간단하고 직관적
◦
특정 조건에 따라 쿼리로만 필터링 수행 가능 (ex. QA 완료 응시자 필터링)
•
단점
◦
추가적인 컬럼을 사용해야함
◦
응시자 도메인의 로직이 뚱뚱해짐(현재도 충분히 뚱뚱하다)
2. JSON으로 저장
•
상황에 따른 예시
◦
QA가 필요없는 경우
▪
DB - "{"QA필요여부":"불필요"}"
▪
객체 - QA필요여부 = 불필요 / QA완료시각 = null
◦
QA가 필요한 경우
▪
DB - "{"QA필요여부":"필요"}"
▪
객체 - QA필요여부 = 필요 / QA완료시각 = null
◦
QA가 완료된 경우
▪
DB - "{"QA필요여부":"통과", "QA완료시각":"2024-08-09'T'16:09:44"}"
▪
객체 - QA필요여부 = 통과 / QA완료시각 = 2024-08-09'T'16:09:44
•
장점
◦
추가적인 컬럼을 사용하지 않아도 됨
◦
관련 있는 필드를 JSON으로 저장되는 객체에 집약했기 때문에 응집도 높은 도메인 작성 가능
•
단점
◦
DB의 데이터를 직접 열어 확인하는 경우 가독성이 좋지 않음
◦
QA 분석 여부를 확인하기 위해서는 JSON_EXTRACT를 사용하거나 메모리에 올려서 필터링 해야함
3. 새로운 테이블 추가 + 외래키 참조(ManyToOne)
추가되는 테이블은 CandidateQaStatus라고 가정하면,
1) 외래키 nullable
•
상황에 따른 예시
◦
QA가 필요없는 경우
▪
Candidate - null
▪
CandidateQaStatus - 레코드 없음
◦
QA가 필요한 경우
▪
Candidate - CandidateQaStatusId
▪
CandidateQaStatus - QA완료시각 = null
◦
QA가 완료된 경우
▪
Candidate - CandidateQaStatusId
▪
CandidateQaStatus - QA완료시각 = 2024-08-09'T'16:09:44
•
장점
◦
QA가 필요 없는 경우를 Join이나 추가 쿼리 없이 null 값으로 간단하게 확인 가능
◦
관련 필드를 하나의 테이블로 뽑아냈기 때문에 하나의 엔티티로 응집도 높은 도메인 작성 가능
◦
추후 응시자의 QA 관련 기능이 추가 되었을 때 확장이 용이
•
단점
◦
추가적인 테이블 사용
◦
이중 null check 필요(응시자 외래키 nullable + CandidateQaStatus의 QA완료시각 nullable)
◦
외래키 null로 인해 일관된 방식으로 처리 불가(stream 혹은 반복문에서 null check 후 로직 분기)
◦
필요에 따라 Join 쿼리 사용해야함
2) 외래키 not null
•
상황에 따른 예시
◦
QA가 필요없는 경우
▪
CandidateQaStatus - QA필요여부 = 불필요 / QA완료시각 = null
◦
QA가 필요한 경우
▪
CandidateQaStatus - QA필요여부 = 필요 / QA완료시각 = null
◦
QA가 완료된 경우
▪
CandidateQaStatus - QA필요여부 = 통과 / QA완료시각 = 2024-08-09'T'16:09:44
•
장점
◦
관련 필드를 하나의 테이블로 뽑아냈기 때문에 하나의 엔티티로 응집도 높은 도메인 작성 가능
◦
추후 응시자의 QA 관련 기능이 추가 되었을 때 확장이 용이
•
단점
◦
추가적인 테이블 사용
◦
QA 여부를 확인하려면 항상 Join 쿼리를 사용해야함
애플케이션 및 비즈니스 특성 고려사항
•
QA 상태에 따른 Candidate 수
◦
서버1
▪
필요 3896
▪
불필요 1344
▪
통과 989
◦
서버2
▪
필요 7373
▪
불필요 36784
▪
통과 0
•
QA 상태를 나타내는 Enum 필드 추가될 가능성 없음
•
글 작성 시점, Enum이 필요인 응시자들만 조회와 같이 QA 여부에 따른 조회 케이스 없음
•
QA 상태 Enum 값을 외부에 제공하는 API 있음
•
응시자 엔티티가 다양하고 많은 요청에서 사용됨
•
QA 여부는 서버2에서는 전혀 사용되지 않음
논의 결과 및 적용
•
애플리케이션 특성 중 QA 상태 Enum 값을 외부에 제공하는 API 있음 -> Enum을 사용하지 않는 3-1(외래키 + nullable) 사용 불가
•
JSON은 부분적으로 쪼개서 사용하지 않을 단일 값만 저장하는 것이 맞음(RDB를 사용하는 이유에 반하는 행동) + 추후 필터링 조건 추가 시 많은 비용을 지불해야함(JSON 데이터를 분리하거나 성능을 포기하거나) -> JSON 방식 권장 되지 않음
•
프리즘에서는 해당 속성을 전혀 사용하지 않기 때문에 사용하지 않을 외부 테이블 참조 -> 추가 테이블 방식은 섣부르다
⇒ 필드 추가 방식으로 결정
적용 사유
•
QA 여부는 응시자가 가지고 있어야할 특성이 맞음
•
가장 저렴한 비용으로 구현 가능
•
현재 시점에서는 많이 활용되지 않는 특성이고 추후 활용하는 곳이 많아진다면 그 때 테이블로 분리하는 것을 고려하는게 맞음