다음코드에서 InheritanceType.JOINED에 대해 알려줘.

자바 객체의 상속 구조를 JPA가 데이터베이스 테이블 구조로 어떻게 매핑할지 결정하는 어노테이션
입니다.
1. 실제로 테이블을 생성하는 역할은 누가 할까?
테이블 생성은 @Inheritance가 아니라 Hibernate의 DDL 자동 생성 기능이 담당합니다.
예를 들어 persistence.xml에서:
<property name="hibernate.hbm2ddl.auto" value="create"/>
또는 Spring Boot에서:
spring:
jpa:
hibernate:
ddl-auto: create
이 설정이 있으면 Hibernate가:
- 엔티티 클래스를 분석하고
- JPA 어노테이션을 읽고
- SQL CREATE TABLE 문을 만들고
- DB에 실행합니다.
2. 그러면 @Inheritance는 무엇을 제공할까?
예를 들어:
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
public abstract class Item {
@Id
@GeneratedValue
private Long id;
private String name;
private int price;
}
그리고:
@Entity
public class Book extends Item {
private String author;
private String isbn;
}
이 상태에서 Hibernate가 테이블을 만들 때:
@Inheritance(strategy = JOINED) 정보를 보고:
"아, Item과 Book은 상속 관계구나. JOINED 방식으로 테이블을 만들어야겠다."
라고 판단합니다.
그래서:
create table ITEM (
item_id bigint not null,
name varchar(255),
price integer,
primary key(item_id)
);
그리고:
create table BOOK (
item_id bigint not null,
author varchar(255),
isbn varchar(255),
primary key(item_id)
);
를 생성합니다.
3. 만약 @Inheritance가 없다면?
예를 들어:
@Entity
public class Item {
@Id
private Long id;
}
@Entity
public class Book extends Item {
private String author;
}
이렇게 하면 JPA는 기본 전략:
InheritanceType.SINGLE_TABLE
을 사용합니다.
즉:
ITEM
----------------
ID
NAME
PRICE
AUTHOR
처럼 하나의 테이블에 모든 것을 넣습니다.
4. 정리하면 역할 분담은 이렇게 됩니다.
| 자바 클래스를 엔티티로 등록 | @Entity |
| PK 지정 | @Id |
| 컬럼 이름 지정 | @Column |
| 상속 관계 매핑 방식 결정 | @Inheritance |
| 테이블 생성 SQL 실행 | Hibernate + ddl-auto/create |
| DB에 실제 테이블 생성 | DB(H2, MySQL, Oracle 등) |
따라서 질문하신 내용을 조금 수정하면:
❌ "@Inheritance는 DB 테이블이 없는 상태에서 자바 코드를 보고 테이블을 생성해주는 어노테이션이다."
보다는
✅ "@Inheritance는 Hibernate가 자바의 상속 구조를 DB 테이블 구조로 변환할 때 어떤 방식으로 설계할지 알려주는 어노테이션이고, 실제 테이블 생성은 Hibernate의 DDL 자동 생성 기능이 담당한다."
라고 이해하는 것이 정확합니다.

1. 현재 코드의 의미
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
public abstract class Item {
@Id @GeneratedValue
private Long id;
private String name;
private int price;
}
이 코드에서 Item은 부모 클래스입니다.
예를 들어 아래와 같은 상속 구조를 생각해보겠습니다.
@Entity
public class Book extends Item {
private String author;
private String isbn;
}
@Entity
public class Album extends Item {
private String artist;
}
@Entity
public class Movie extends Item {
private String director;
private String actor;
}
객체 관점에서는:
Item
|
----------------
| | |
Book Album Movie
입니다.
JOINED 전략을 사용하면 테이블은 어떻게 만들어질까?
DB에는 다음처럼 만들어집니다.
ITEM 테이블
| 1 | JPA책 | 30000 |
| 2 | 아이유앨범 | 15000 |
BOOK 테이블
| 1 | 김영한 | 1234 |
ALBUM 테이블
| 2 | 아이유 |
즉 부모 데이터는 부모 테이블에 저장하고,
자식만 가지고 있는 데이터는 자식 테이블에 저장합니다.
2. 조회할 때는 JOIN 발생
예를 들어:
Book book = em.find(Book.class, 1L);
하면 Hibernate는 내부적으로:
select
i.item_id,
i.name,
i.price,
b.author,
b.isbn
from Item i
join Book b
on i.item_id = b.item_id
where i.item_id = 1;
처럼 JOIN SQL을 만듭니다.
그래서 이름이:
JOINED
입니다.
다른 전략과 비교
JPA에는 대표적으로 3가지 상속 전략이 있습니다.
1) JOINED (현재 방식)
Item
|
+-- Book
|
+-- Album
|
+-- Movie
DB:
ITEM
|
+---- BOOK
|
+---- ALBUM
|
+---- MOVIE
장점:
✅ 정규화된 구조
✅ 중복 데이터 없음
✅ 데이터 무결성이 좋음
단점:
❌ 조회할 때 JOIN이 많이 발생
❌ 테이블이 여러 개라 복잡
실무에서 가장 정석적인 방식입니다.
2) SINGLE_TABLE
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
하나의 테이블에 모두 저장합니다.
DB:
| 1 | JPA책 | 30000 | 김영한 | null | null | BOOK |
| 2 | 앨범 | 15000 | null | 아이유 | null | ALBUM |
테이블:
ITEM
하나뿐입니다.
장점:
✅ 조회 빠름 (JOIN 없음)
단점:
❌ 사용하지 않는 컬럼이 많음
예:
Album인데
AUTHOR
ISBN
DIRECTOR
컬럼이 필요 없습니다.
3) TABLE_PER_CLASS
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
각 자식 테이블에 부모 필드까지 모두 넣습니다.
BOOK:
| 1 | JPA책 | 30000 | 김영한 |
ALBUM:
| 2 | 앨범 | 15000 | 아이유 |
ITEM 테이블은 없습니다.
장점:
✅ 조회할 때 JOIN 없음
단점:
❌ 데이터 중복 발생
❌ 부모 타입 조회가 어려움
실무에서는 무엇을 많이 사용할까?
대부분:
@Inheritance(strategy = InheritanceType.JOINED)
또는
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
둘 중 하나를 선택합니다.
특히 JPA 강의(김영한님의 "실전! 스프링 부트와 JPA 활용")에서는 JOINED 전략을 기본 예제로 사용합니다.
추가로 현재 코드에는 작은 오류가 있습니다.
@Id
@GeneratedValue
@JoinColumn(name="item_id")
private Long id;
여기서:
@JoinColumn
은 사용할 수 없습니다.
@JoinColumn은 연관관계 매핑용입니다.
예:
@ManyToOne
@JoinColumn(name="member_id")
private Member member;
같은 곳에서 사용합니다.
ID 컬럼은:
@Id
@GeneratedValue
@Column(name="item_id")
private Long id;
가 맞습니다.
정리하면:
| JOINED | 부모/자식 테이블 분리 | 정규화, JOIN 발생 |
| SINGLE_TABLE | 하나의 테이블 | 빠름, 컬럼 낭비 |
| TABLE_PER_CLASS | 자식별 테이블 | 중복 발생 |
현재 코드의 InheritanceType.JOINED는 객체의 상속 구조를 DB의 여러 테이블로 나누어 저장하고, 부모 PK를 이용해 JOIN하는 가장 객체지향적인 매핑 방식이라고 이해하면 됩니다.
InheritanceType.TABLE_PER_CLASS 전략에서 데이터 중복이 발생하는 이유는 부모 클래스의 컬럼을 자식 테이블마다 복사해서 저장하기 때문입니다.
먼저 상속 구조를 보겠습니다.
@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class Item {
@Id
private Long id;
private String name;
private int price;
}
자식 클래스:
@Entity
public class Book extends Item {
private String author;
}
@Entity
public class Album extends Item {
private String artist;
}
@Entity
public class Movie extends Item {
private String director;
}
1. TABLE_PER_CLASS 방식의 테이블 구조
이 전략에서는 부모 테이블(Item)을 만들지 않습니다.
대신 자식 클래스마다 독립적인 테이블을 만듭니다.
결과:
BOOK 테이블
| 1 | JPA책 | 30000 | 김영한 |
ALBUM 테이블
| 2 | BTS앨범 | 15000 | BTS |
MOVIE 테이블
| 3 | 아바타 | 12000 | 제임스카메론 |
여기서 중요한 점:
name, price, id는 원래 부모 Item의 속성입니다.
그런데 부모 테이블이 없기 때문에:
Item
├── id
├── name
└── price
이 정보가 각각의 자식 테이블에 복사됩니다.
즉:
BOOK
----------------
id
name ← Item에서 복사
price ← Item에서 복사
author
ALBUM
----------------
id
name ← Item에서 복사
price ← Item에서 복사
artist
MOVIE
----------------
id
name ← Item에서 복사
price ← Item에서 복사
director
이것이 데이터 중복입니다.
2. 왜 이것이 문제가 될까?
예를 들어 Item에 새로운 공통 필드를 추가한다고 해봅시다.
private String manufacturer;
그러면:
BOOK 테이블:
ALTER TABLE BOOK ADD manufacturer varchar(255);
ALBUM 테이블:
ALTER TABLE ALBUM ADD manufacturer varchar(255);
MOVIE 테이블:
ALTER TABLE MOVIE ADD manufacturer varchar(255);
모든 테이블을 수정해야 합니다.
3. 조회도 문제가 됩니다.
예를 들어:
List<Item> items = itemRepository.findAll();
"모든 상품 조회"를 하고 싶다면 어떻게 해야 할까요?
Item 테이블이 없습니다.
그래서 Hibernate는 내부적으로:
SELECT * FROM BOOK
UNION ALL
SELECT * FROM ALBUM
UNION ALL
SELECT * FROM MOVIE
같은 SQL을 만들어야 합니다.
테이블이 많아질수록 성능 문제가 생깁니다.
4. 세 가지 전략 비교
| SINGLE_TABLE | 부모+자식 모두 하나의 테이블 | 조회 빠름 | 컬럼 낭비 가능 |
| JOINED | 부모 테이블 + 자식 테이블 | 정규화, 데이터 중복 없음 | JOIN 필요 |
| TABLE_PER_CLASS | 자식 테이블만 존재 | 구조 단순 | 중복 발생, 조회 어려움 |
5. 그래서 실무에서는?
대부분:
@Inheritance(strategy = InheritanceType.JOINED)
또는
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
을 사용합니다.
특히 JPA를 설명하는 예제(예: 상품(Item), Book, Album, Movie)에서는 보통:
- JOINED → 객체지향 모델과 DB 정규화 관점에서 좋은 선택
- SINGLE_TABLE → 성능과 단순성 때문에 많이 사용
이고,
TABLE_PER_CLASS는 거의 사용하지 않는 전략입니다.
'Spring&IntelliJ' 카테고리의 다른 글
| protected기본생성자를 사용하면 왜 개발자는 함부로 생성하지 못하고 JPA같은 프레임워크는 접근이 가능한거야? (0) | 2026.06.16 |
|---|---|
| @Embeddable에 대해서 (0) | 2026.06.16 |
| cascade = CascadeType.ALL은 어떨때 주로 쓰이고 왜 쓰여? (0) | 2026.06.16 |
| h2 파일 생성 실패시, Database not found 애러 해결방법 (0) | 2026.06.05 |
| JPA 지연로딩과 프록시객체 (0) | 2026.06.02 |