엔티티(Entity) 개념 정리(도메인 엔티티, DB 엔티티, JPA 엔티티)

엔티티란 용어의 혼선

오늘날 많은 개발자들이 엔티티란 용어를 혼선한다. 특히 JPA란 ORM이 대두되면서 엔티티와 JPA 엔티티를 혼용하는 일이 많아졌다. ‘엔티티는 DB에 매칭되며 @Entity 어노테이션을 붙인 클래스’라고 설명하는 글들도 흔히 볼 수 있다. 하지만 엔티티는 JPA가 없던 시절부터 존재하던 개념이다. JPA의 엔티티는 이런 엔티티를 표현하기 위한 수단 중에 하나이다. 따라서 ‘엔티티는 @Entity 어노테이션을 붙인 클래스’라고 설명하는 것은 옳지 않다.

오늘 포스팅에서는 김우근님의 도서 <자바/스프링 개발자를 위한 실용주의 프로그래밍> 중 엔티티 부분을 정리 및 요약했습니다.

헷갈리기 쉬운 엔티티를 살펴보자.

  1. 도메인 엔티티
  2. DB 엔티티
  3. JPA 엔티티

보다싶이 엔티티는 보편적인 개념이다. 이 개념이 어느 곳에서 사용하느냐에 따라 도메인 엔티티, DB 엔티티, JPA 엔티티가 되는 것이다.

1. 도메인 엔티티

도메인 엔티티를 알려면 도메인이 무엇인지 알아야 한다. 도메인은 우리가 해결해야 하는 비즈니스 영역이다. 예를 들어 은행에서 사용할 소프트웨어를 만들고자 한다면 은행이 도메인이 된다.

이런 은행 도메인 아래에는 여러 개념이 존재한다. 계좌(Account), 거래(Transaction), 돈(Money)와 같은 개념들이다. 이러한 개념들을 도메인 모델이라고 한다.

이런 도메인 모델 중에서 계좌와 거래에 주목하자. 이 둘의 모델은 돈과는 사뭇 다르다. 이 모델들은 도메인 모델에 맞는 비즈니스 로직을 가질 수 있고, 고유 식별자가 존재하며, 생명주기(LifeCycle)이 있을 수 있다. 이렇게 도메인 모델 중에서 특별한 기능을 갖는 모델을 도메인 엔티티라고 한다. 소프트웨어 개발 분야에서 말하는 엔티티를 개발한다는 뜻은 도메인 엔티티를 만든다는 의미로 볼 수 있다.

도메인 엔티티를 정리하자면

  1. 식별자를 갖는다.
  2. 도메인 로직을 갖는다.

와 같다.

DB 엔티티

이 용어는 도메인 엔티티와 상관없이 원래 관계형 데이터베이스 분야에서 어떤 유무형의 객체를 표현하는 데 사용했던 용어이다.

여기서 객체는 객체지향의 객체가 아닌 정보를 담고 있는 데이터 모델로 이해하자

JPA 엔티티

관계형 데이터베이스에 있는 데이터를 객체로 매핑하는 데 사용되는 클래스를 JPA 엔티티라고 부른다. DB 엔티티나 도메인 엔티티와 비교하자면, JPA 엔티티는 DB 엔티티에 더 가까운 개념이다.

실제 JPA는 @Table, @Column과 같은 데이터베이스 용어를 사용한다. 소프트웨어 개발 분야에서 말하는 엔티티는 도메인 엔티티이다. 반면 JPA 엔티티는 DB 엔티티에 더 가깝다. 따라서 엔티티는 JPA의 @Entity로 선언된 클래스란 답변은 틀린 것이다.

이러한 개념적 불일치를 아는 것이 별것 아닌 것처럼 보일 수 있지만 이를 제대로 구분하느냐에 따라 개발 결과물이 달라질 수 있다. 단적인 예로 엔티티를 JPA 엔티티로 인식하는 개발자는 관계형 데이터베이스에 종속된 프로그램을 만들 확률이 높다.

엔티티 정의

엔티티의 시작은 현실 세계의 사물을 데이터로 정의할 때 어떻게 정의할 것인가 고민한 결과이다. 가령 사용자란 현실 세계의 존재를 데이터로 표현하기 위해서는 이름, 나이, 성별이란 데이터로 정의할 수 있을 것이다. 그럼 이런 ‘사용자’와 같은 자산은 무엇으로 부르면 좋을까? 프로그래밍과 데이터베이스 분야에서는 이런 자산 정보를 지칭하는 곳에 엔티티란 표현을 사용하였다.

엔티티는 개체란 뜻을 가지고 있다.

이런 자산 정보인 엔티티를 데이터베이스 세계에서는 테이블로 표현하였고, 객체지향 세계에서는 엔티티를 클래스로 표현하였다. 당연한 것이 객체지향 세계에서는 객체들간의 협력을 추구하였고 데이터베이스 세계에서는 데이터의 정합성, 중복 제거 등을 중요하게 여겼기 대문이다.

이렇게 표현된 엔티티는 각자의 세계에서 잘 발전했다. 그러다가 현실 세계에서 서비스를 만들 일이 생기자 양쪽은 협업해야 했다. 그러나 양쪽 세계에서 시작은 비슷했을지 몰라도 결과물은 너무나도 달랐기 때문에 서로를 일대일로 매핑하기에는 무리가 있었다. 따라서 개발자는 데이터베이스에서 데이터를 가져와 도메인 모델에다 데이터를 매핑해야하는 작업을 해야했다. 자바 진영에서는 대표적으로 MyBatis와 같은 라이브러리를 통해 필요한 데이터를 선택적으로 가져와 쿼리의 결과를 도메인 모델에 매핑했다. 하지만 이런 작업은 번거러웠고 곧 하이버네이트와 같은 ORM(object-relational mapping) 솔루션이 등장한 것이다.

따라서 JPA의 @Entity 어노테이션이 지정된 객체를 소프트웨어 개발 분야의 엔티티라 부를 수는 없다. 소프트웨어 개발에서의 엔티티는 도메인 엔티티이다.

예를 들어 MongoDB를 주 데이터베이스로 사용하는 프로그램이 있다고 해보자. MongoDB는 JSON과 유사한 BSON 형식으로 데이터를 다루며 데이터 하나하나를 도큐먼트라고 보는 도큐먼트 데이터베이스이다. 사용하는 용어도 관계형 데이터베이스와 차이를 보이는데 RDBMS에서 사용하는 엔티티란 용어는 도큐먼트라고 부르고, 테이블을 컬랙션으로 부른다. 자바로 매핑해보면,

1
2
3
@Document(collection = "user")
public class User {
}

와 같다.

만약 하나의 어플리케이션이 주 테이블로 MongoDB를 사용한다면 @Entity, @Column, @Table이란 명칭을 사용하지 않는다. 그렇다면 이 어플리케이션은 엔티티가 존재하지 않다고 봐야하는가? 아닌 것이다.

정리

  • 엔티티는 데이터로 표현하려는 유무형의 데이터이다.
  • DB 엔티티는 데이터베이스 분야에서 데이터로 표현하려는 대상이다.
  • 도메인 엔티티는 모데인 모델 중에서도 식별 가능하고 비즈니스 로직을 갖고 있으며 특별하게 관리되는 객체이다. 그리고 소프트웨어 개발 분야에서 말하는 엔티티는 이러한 도메인 엔티티이다.