@Entity
같은 어노테이션을 통해 클래스는 테이블에, 필드는 컬럼에, 객체 인스턴스는 행에 자동으로 매핑합니다.repository.save(member)
나 repository.findById(1L)
과 같은 메서드 호출만으로 데이터의 생성, 조회, 수정, 삭제가 가능해집니다.JOIN FETCH
키워드를 사용하면, ORM에게 연관된 엔티티까지 한 번의 쿼리로 모두 가져오라고 명시적으로 알려줄 수 있습니다.
// Post를 조회할 때, 연관된 Comment까지 한 번의 JOIN으로 함께 가져옵니다.
@Query("SELECT p FROM Post p JOIN FETCH p.comments WHERE p.id = :id")
Post findPostWithComments(@Param("id") Long id);
ORM을 사용하는 주된 이유는생산성 향상과객체 지향적인 코드 유지입니다. 반복적인 SQL 매핑 작업을 ORM이 대신 처리해주므로, 개발자는 비즈니스 로직에 더 집중할 수 있습니다. 또한, 특정 데이터베이스 기술에 종속되지 않아DB 교체가 용이하다는 장점도 있습니다. 하지만단점으로는, 복잡하고 세밀한 튜닝이 필요한 쿼리를 작성하기 어렵고, 내부 동작 원리를 제대로 이해하지 못하면N+1 문제와 같은 성능 이슈를 유발할 수 있다는 점이 있습니다. 따라서 ORM은 SQL을 대체하는 기술이 아니라, 함께 이해하고 사용해야 하는 도구라고 생각합니다.
N+1 문제는 연관 관계가 설정된 엔티티를 조회할 때,첫 번째 쿼리의 결과로 N개의 추가 쿼리가 발생하는 성능 문제를 의미합니다. 주로 지연 로딩(Lazy Loading)으로 설정된 연관 엔티티에 접근할 때 발생합니다. 가장 대표적인 해결 방법은페치 조인(Fetch Join)을 사용하는 것입니다. JPQL에서JOIN FETCH
를 사용하여, 첫 번째 쿼리를 날릴 때 연관된 엔티티의 데이터까지 한 번의 쿼리로 모두 가져오도록 명시하여 불필요한 추가 쿼리를 방지할 수 있습니다. 그 외에도@EntityGraph
어노테이션이나 배치 사이즈(Batch Size) 조절을 통해 문제를 완화할 수 있습니다.