데이터베이스의 설계는 쉽지 않다. 데이터를 객체로 사용하는 spring에서도 고려를 하며 관계를 설계 해야한다. 일반적으로 데이터 베이스는 PK를 가진 테이블을 설계하고 PK키를 FK로 갖는 테이블을 나중에 설계한다. 하지만 JPA는 방향성을 결정하는 것조차 어렵다.
예를 들어 아래와 같은 테이블이 두개 존재한다고 가정하자.
회원 | |
id(PK) | Long |
name | varchar |
password | varchar |
created_at | DATETIME |
modified_at | DATETIME |
게시물 | |
id(PK) | Long |
title | varchar |
writer_id(FK) | Long |
contents | varchar |
created_at | DATETIME |
게시물은 작성자의 id를 FK로 가지고 있다. 그러면 회원 객체가 게시물을 참조하는 것일까? 아니면 게시물들이 회원을 참조하는 것일까?
연관 관계의 판단 기준을 결정할 때는 다음을 기억하자
- 연관 관계의 기준은 변화가 많은 쪽으로 결정
- ERD의 FK를 기준으로 결정
여기서는 게시물이 FK를 갖고 있으므로 게시물이 연관관계의 기준이 되는 것이다. 또한 회원 정보를 수정하는 변경하는 일보단 게시물의 수정이 빈번하게 일어날듯 하다. 앞서 말한 두가지를 잘 기억하자.
단방향과 양방향
참조를 결정할때는 A->B, B->A와 같은 양방향 참조가 가능하다. 반면 A->B와 같은 단방향 참조 또한 가능하다. 둘 중 뭐가 더 나은 방법일까?
먼저 방식의 각 특징을 알아보자
- 양방향 : 서로 참조를 유지하기 때문에 모든 관리를 양쪽 객체에 동일하게 적용해야만 하는 불편함이 있지만 JPA에서 필요한 데이터를 탐색하는 작업에서는 편리함을 제공.
- 단방향 : 구현이 단순하고 에러 발생의 여지를 많이 줄일 수 있지만, 데이터베이스 상에서 조인 처리와 같이 다른 엔티티 객체의 내용을 사용하는 데 더 어렵다는 단점이 존재.
이렇게 보면 설계와 관리만 잘해준다면 양방향이 훨씬 좋아보이지만 그렇지만은 않다. 양방향 참조를 했을때 A객체의 정보는 필요하지만 굳이 B객체 정보까지 필요하진 않은 경우도 있을 것이다. 그렇지만 A객체의 정보를 출력하기 위해 연관이 있는 B객체의 관한 쿼리를 날리게 되고 불필요한 쿼리가 나가 N+1과 같은 문제를 일으킬수 있다.
그래서 나는 단방향으로 참조 관계를 맺고 필요할때 조인 처리를 하는 편이다. (사실 뭐가 정답인지는 모른다 ㅎㅎ!)
게시물의 댓글 엔티티가 다음과 같고 @ToString 어노테이션으로 board를 제외해주면 위에서 말한 상황은 일어나지 않는다. 하지만 분명 Board 객체의 정보가 필요한 상황이 있을 것이다.
여기서 FetchType을 LAZY로 설정했다. 이는 필요한 순간까지 데이터베이스에 연결하지 않는다는 것을 의미한다. 보통 fetch설정을 다 LAZY로 한다. (EAGER는 즉시로딩으로 reply를 로딩할때 board도 걍 로딩해버림)
정말 기본적으로 알아야 할 내용에 대해서 간략히 정리했다. 하지만 안정적인 시스템 구축을 위해 N+1와 같은 문제상황에 대해 자세히 찾아보고 깊은 이해가 필요하다.
'Spring' 카테고리의 다른 글
@RestControllerAdivce vs @Around("within(@org.springframework.web.bind.annotation.RestController *)") (0) | 2025.03.01 |
---|---|
싱글톤 (프로토타입과 스코프) (0) | 2024.04.18 |
IoC 컨테이너란 무엇인가 (0) | 2024.04.16 |
어노테이션이란? (0) | 2024.04.02 |
트랜잭션 어노테이션 (@Transactional, 속성, 정책, 방법) (0) | 2024.03.28 |