JPA
이번 미션에서는 JPA(Java Persistence API)에 대해 집중적으로 학습하기 위한 미션으로,
QnA 게시판의 백엔드 로직을 JPA 기반으로 구현하는 것이 목적이었다.
각 단계별로 엔티티 매핑, 연관 관계 매핑, 질문 삭제하기 리팩터링으로 구성되어 있었고,엔티티 매핑, 연관 관계 매핑 단계에선 각 단계의 제목대로 요구사항이 주어졌다.
QnA 서비스는 User, Question, Answer, DeleteHistory 총 4개의 도메인으로 이루어져 있었으며,
마지막 질문 삭제하기 리펙터링의 경우 ‘본인이 작성한 질문과 답글만 삭제할 수 있고, 이 이력을 DeleteHistory에
저장해야 한다.’ 라는 요구사항이었다.
하지만 삭제라고 해서 DB에서 row가 삭제되는 것이 아니라, 삭제 상태(deleted = true)로 만드는 것이라,
DB에서는 update가 되는 것이고, delete_history 테이블에는 insert가 되는것이므로 도메인의 비즈니스 로직에서 잘 처리해줘야 한다.
또한, 이전 단계에서 엔티티 매핑과 연관 관계 매핑을 잘 처리해놨어야 3단계에서 비교적 매끄럽게 진행이 가능하다.
3단계를 진행하면서 이전에 학습했던 TDD, Refactoring 방법등을 적극 활용하여
이번 미션을 무난하게 진행 할 수 있었다
회고
이번 미션에서 잘 한 점
엔티티 매핑 및 연관관계 매핑
QnA의 시스템 중에서 가장 중요한 연관관계 매핑을 간단히 그려보면 아래와 같다.
DeleteHistory라는 엔티티의 책임에 대한 고민이 많았다.
속성중에 content_id 라는 Question / Answer의 id를 가지고 있었으나,
이 엔티티의 역할로 보면 History라는 측면에선 연관 관계를 맺지 않았다.
이렇게 설계한 연관 관계가 3단계에서 꽤나 유연하게 설계할 수 있는 밑거름이 되었다.
엔티티 매핑과 연관관계 매핑 단계가 JPA를 잘 알았던 사람이라면 금방 끝낼 수 있는 미션이지만,
각 엔티티의 역할과 책임을 적절히 고려하여 연관관계 매핑을 해줘야 한다는 점 에서
꽤나 오랫동안 고민하며 설계했던 것이 도움이 많이 되었다.
어려웠던 점
엔티티 설계에 대한 깊은 고민
Question 엔티티
1 |
|
Answer 엔티티
1 |
|
두 엔티티를 보면 공통적으로 content, writer, id, deleted 라는 속성을 가지고 있다.
나는 처음에 중복 코드를 최대한 배제하자 라는 생각으로 공통된 속성을 하나의BaseContentEntity라는 @MappedSuperclass로 분리하여, 이를 상속받는 구조로 구현을 했다.
1 |
|
하지만, 리뷰어님의 피드백은 BaseContentEntity는 과도한 책임을 가지고 있는 슈퍼클래스가 되어 버렸고,
추가 확장에 유연하지 못할 것 같다는 의견을 주시며 내 생각이 어떠한지 물어보셨다.😅
각 속성에 대해 다시 한번 고민 해 본 결과
- id : 변경에 유연하지 못하고, MappedSuperclass 보다는 이를 상속받는 근본 Entity가 가지고 있는 것이 더 바람직하다.
- writer : Question / Answer의 writer는 나중에 다른 비즈니스 로직이 적용될 가능성이 높다.
- deleted : 이미 3단계 미션에서 요구사항이 다름(삭제에 필요한 비즈니스 로직이 다르게 전개됨).
따라서, 만약 공통 속성으로 뺀다면content만 남게 된다.
그렇다면 추가로 고민해볼 것이, content가 공통 속성으로 뺄만한 가치가 있는가?
–> 그렇지 않다는게 나의 결론이었다. content는 공통 속성으로 뺄만한 복잡한 비즈니스 로직이 없거니와,
만일 뺀다고 했을때 구현 복잡도가 오히려 증가한다는 결론을 내리고, BaseContentEntity를 아예 삭제하는 식으로 다시 원복했다..😭
이제와서 다시 생각해보면, 단일 책임의 원칙으로 고려해봤을 때BaseContentEntity는 content와 관련된 역할과 책임만 가지고 있어야 됐다.
느낀점
이번 미션을 진행하면서 가장 크게 느낀점은 JPA는 DataBase를 위한 기술이 아니라, 객체지향설계를 위한 기술 이라는 것이다.
- 각 속성을 어떻게 매핑하는지
- 연관 관계는 어디서 어떤 방향으로(DB의 관계에선 방향이 없다.) 매핑해야 하는지
- 시스템의 설계 상 어떤 임의의 도메인이 다른 도메인과 자주 사용되는지에 따라 변경이 예상되는 부분을 고려
하는 등등.. 여러 가지 측면에서 봤을 때, JPA도 결국은 객체지향을 위한 기술 이라는 것이었다.
이 부분을 크게 간과하고 이번 미션에 임했던 것이 많은 시행착오를 야기시켰다.
JPA 사용 시 엔티티 매핑, 연관 관계 매핑단계 에서는 반드시 객체지향적인 설계를 동반해야 한다!
생각해보자
이번 미션을 완료 한 시점에 ‘좋은 객체지향 설계란 무엇인가?’ 라는 의문이 생겼다.
이 질문에 대한 좋은 답을 내고 있는 책을 찾게 되었다.
바로 ‘객체지향의 사실과 오해 - 조영호 지음(위키북스)’ 이다.
개인적으론 이 책을 읽으며 책의 제목 그대로
내가 객체지향에 대해 잘못 알고 있는 부분이 많았다는 것이다.
위 책에 대한 독후감은 다른 포스트에서 좀 더 자세히 다뤄 볼 예정이다.
또한, 기술적으로 바로 도입해볼 수 있는 것들은..
적어도 어떤 개발이라도 객체지향의 5대 원칙(SOLID)를 체크리스트로 만들어서,
원칙을 잘 지키고 있는지를 체크하고 넘어가도 좋을 것 같다는 생각이 든다.🧐