PromleeBlog
sitemap
aboutMe

posting thumbnail
ORM의 개념과 장단점, 그리고 N+1 문제
ORM Concepts, Pros & Cons, and the N+1 Problem

📅

🚀

들어가기 전에 🔗

이번 시간에는 객체 지향 프로그래밍과 관계형 데이터베이스라는, 서로 다른 두 세계를 연결해주는 중요한 다리 역할의 기술, 바로
ORM(Object-Relational Mapping)
에 대해 알아보겠습니다.

우리가 자바나 코틀린 같은 객체 지향 언어로 코드를 작성할 때, 데이터는 '객체'의 형태로 존재합니다.
하지만 관계형 데이터베이스(RDBMS)는 데이터를 '테이블'의 형태로 저장합니다.
ORM은 이처럼 근본적으로 다른 두 패러다임의 불일치를 해결하고, 개발자가 SQL 쿼리 대신 익숙한 객체 중심으로 데이터를 다룰 수 있게 해주는 강력한 기술입니다.
오늘은 ORM의 기본 개념부터 장단점, 그리고 그 이면의 함정까지 깊이 있게 탐구해 보겠습니다.

🚀

객체와 테이블 🔗

객체 지향 세계와 관계형 데이터베이스의 세계는 데이터를 바라보는 방식이 근본적으로 다릅니다.
이것을
객체-관계 패러다임 불일치(Object-Relational Impedance Mismatch)
라고 부릅니다.

예를 들어, 객체는 상속이나 연관관계 같은 복잡한 구조를 가질 수 있지만, 테이블은 단순한 행과 열의 2차원 구조입니다.
이 때문에 개발자는 객체를 데이터베이스에 저장하기 위해, 객체의 필드를 테이블의 컬럼으로 변환하고, 다시 조회할 때는 테이블의 데이터를 객체로 변환하는 반복적이고 번거로운 작업(SQL 매핑)을 직접 해야만 했습니다.

🚀

ORM 🔗

ORM
은 이 불일치 문제를 해결해주는 '자동 통역사'와 같습니다.
개발자가 SQL을 직접 작성하는 대신, ORM 프레임워크가 객체와 테이블 사이의 모든 변환 작업을 대신 처리해 줍니다.
개발자는 오직 객체에만 집중하면 됩니다.

가장 대표적인 자바 진영의 ORM 기술 표준이 바로
JPA(Java Persistence API)
이며, Hibernate는 이 JPA 표준을 구현한 가장 유명한 프레임워크입니다.

이 중심에는
영속성 컨텍스트(Persistence Context)
가 있습니다.
이는 엔티티(객체)를 효율적으로 관리하는 일종의 '작업 공간'으로, 1차 캐시, 쓰기 지연, 변경 감지(Dirty Checking) 등의 기능을 통해 ORM의 성능과 편의성을 뒷받침합니다.

🚀

N+1 문제 🔗

ORM은 매우 편리하지만, 그 내부 동작 원리를 제대로 이해하지 않고 사용하면 심각한 성능 문제를 유발할 수 있습니다.
그중 가장 대표적인 것이 바로
N+1 문제
입니다.

N+1 문제는 연관 관계가 있는 엔티티를 조회할 때 발생합니다.
예를 들어, 1개의 게시글(
Post
)과 여러 개의 댓글(
Comment
)이 있는 상황을 생각해 봅시다.

  1. 먼저 게시글 목록을 조회합니다. (SQL 쿼리 1번 발생)
  2. 그리고 각 게시글에 달린 댓글 목록을 화면에 보여주기 위해, 각 게시글 객체의 댓글 리스트에 접근합니다.
  3. 이때 ORM은 각 게시글마다 별도의 쿼리를 날려 댓글들을 가져옵니다.
    만약 게시글이 N개라면, 댓글을 가져오기 위해 N개의 추가 쿼리가 발생합니다.

결과적으로, 총
1 + N
번의 쿼리가 실행되어 데이터베이스에 엄청난 부하를 주게 됩니다.


🚀

주요 면접 예상 질문 🔗

ORM은 현대적인 백엔드 개발의 핵심이므로, 그 원리와 트레이드오프를 묻는 질문이 자주 나옵니다.

1. ORM을 사용하는 이유와, 그에 따른 장단점을 설명해주세요. 🔗

ORM의 핵심 가치와 그 이면의 비용을 함께 설명해야 합니다.
ORM을 사용하는 주된 이유는
생산성 향상
객체 지향적인 코드 유지
입니다.
반복적인 SQL 매핑 작업을 ORM이 대신 처리해주므로, 개발자는 비즈니스 로직에 더 집중할 수 있습니다.
또한, 특정 데이터베이스 기술에 종속되지 않아
DB 교체가 용이하다는 장점
도 있습니다.
하지만
단점
으로는, 복잡하고 세밀한 튜닝이 필요한 쿼리를 작성하기 어렵고, 내부 동작 원리를 제대로 이해하지 못하면
N+1 문제와 같은 성능 이슈
를 유발할 수 있다는 점이 있습니다.
따라서 ORM은 SQL을 대체하는 기술이 아니라, 함께 이해하고 사용해야 하는 도구라고 생각합니다.

2. N+1 문제란 무엇이며, 어떻게 해결할 수 있나요? 🔗

ORM 사용 경험과 문제 해결 능력을 직접적으로 보여주는 클래식한 질문입니다.
N+1 문제는 연관 관계가 설정된 엔티티를 조회할 때,
첫 번째 쿼리의 결과로 N개의 추가 쿼리가 발생하는 성능 문제
를 의미합니다.
주로 지연 로딩(Lazy Loading)으로 설정된 연관 엔티티에 접근할 때 발생합니다.
가장 대표적인 해결 방법은
페치 조인(Fetch Join)
을 사용하는 것입니다.
JPQL에서 JOIN FETCH를 사용하여, 첫 번째 쿼리를 날릴 때 연관된 엔티티의 데이터까지 한 번의 쿼리로 모두 가져오도록 명시하여 불필요한 추가 쿼리를 방지할 수 있습니다.
그 외에도 @EntityGraph 어노테이션이나 배치 사이즈(Batch Size) 조절을 통해 문제를 완화할 수 있습니다.

🚀

결론 🔗

오늘은 객체와 테이블이라는 두 세계를 잇는 통역사, ORM에 대해 알아보았습니다.

참고 🔗