๐Ÿ”Ž [JPA] @Table(uniqueConstraints) vs @Column(unique = true) โ€” ์–ด๋–ค๊ฒŒ ๋” ์ข‹์€๊ฐ€?

๋ฐ•์ค€ํ˜•ยท2025๋…„ 5์›” 31์ผ

์Šคํ”„๋ง ๊ฐœ๋ฐœ

๋ชฉ๋ก ๋ณด๊ธฐ
8/20
post-thumbnail

Unique ์ œ์•ฝ ์กฐ๊ฑด์€ ๋ฐ์ดํ„ฐ ๋ฌด๊ฒฐ์„ฑ์„ ์ง€ํ‚ฌ ์ˆ˜ ์žˆ๊ฒŒ ๋„์™€์ค€๋‹ค.
๋‚˜๋Š” ์ด์ „๊นŒ์ง€๋Š” @Column(unique = true)๋ฅผ ํ•„๋“œ๋“ค์— ์ง์ ‘ ์ฃผ์–ด ์„ค์ •ํ•ด ์™”์—ˆ๋Š”๋ฐ ์ตœ๊ทผ ์ƒˆ๋กœ์šด unique ์ ์šฉ ๋ฐฉ๋ฒ•์„ ์•Œ๊ฒŒ๋˜์—ˆ๋‹ค.

์ด๋ฒˆ ๊ธ€์—์„œ๋Š” ์ด ๋‘ ๊ฐ€์ง€ ๋ฐฉ๋ฒ•์„ ๋น„๊ตํ•˜๊ณ , ์‹ค๋ฌด์—์„œ๋Š” ์–ด๋–ค ๋ฐฉ์‹์ด ๋” ๋‚˜์€์ง€ ๊ทธ ์ด์œ ๊นŒ์ง€ ์ •๋ฆฌํ•ด๋ณผ๊ฒŒ์š”.

โœ… ๋‘ ๊ฐ€์ง€ ๋ฐฉ๋ฒ• ์˜ˆ์‹œ

โ‘  @Table(uniqueConstraints)

@Entity
@Table(
    name = "member",
    uniqueConstraints = {
        @UniqueConstraint(columnNames = {"email"}),
        @UniqueConstraint(columnNames = {"username"}),
        @UniqueConstraint(columnNames = {"provider", "provider_id"})  // ์†Œ์…œ ๋กœ๊ทธ์ธ์šฉ ๋ณตํ•ฉ UNIQUE ์˜ˆ์‹œ
    }
)
public class Member {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String email;

    private String username;
}

โ†’ ํ…Œ์ด๋ธ” ๋ ˆ๋ฒจ์—์„œ Unique ์ ์šฉ
โ†’ DDL ์ƒ์„ฑ ์‹œ ALTER TABLE ์ˆ˜์ค€์—์„œ UNIQUE KEY ์ƒ์„ฑ

โ‘ก @Column(unique = true)

@Entity
public class Member {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(unique = true)
    private String email;

    @Column(unique = true)
    private String username;
}

โ†’ ์ปฌ๋Ÿผ ๋‹จ์œ„์—์„œ Unique ์ ์šฉ
โ†’ DDL ์ƒ์„ฑ ์‹œ ํ•ด๋‹น ์ปฌ๋Ÿผ ๋’ค์— UNIQUE ์˜ต์…˜ ์ถ”๊ฐ€

โœ… ์ฐจ์ด์  ๋น„๊ต

๋น„๊ต ํ•ญ๋ชฉ (์ฐจ์ด์ ์„ ์ค‘์‹ฌ์œผ๋กœ )@Table(uniqueConstraints)@Column(unique = true)
์ ์šฉ ์œ„์น˜ํ…Œ์ด๋ธ” ๋ ˆ๋ฒจ์ปฌ๋Ÿผ ๋ ˆ๋ฒจ
๋ณตํ•ฉ UNIQUE ์ง€์› ์—ฌ๋ถ€๊ฐ€๋Šฅ (columnNames = {"col1", "col2"})๋ถˆ๊ฐ€๋Šฅ (๋‹จ์ผ ์ปฌ๋Ÿผ๋งŒ)
DDL ์ƒ์„ฑ ๊ฒฐ๊ณผ ํ˜•์‹๋ณ„๋„ ALTER TABLE or CONSTRAINT ์ƒ์„ฑ์ปฌ๋Ÿผ ์ •์˜ ๋’ค์— UNIQUE ์ถ”๊ฐ€
DDL ๊ด€๋ฆฌ ํˆด๊ณผ์˜ ํ˜ธํ™˜์„ฑ๋” ๋ช…ํ™•ํ•˜๊ฒŒ ๊ด€๋ฆฌ๋จ์ปฌ๋Ÿผ ์ œ์•ฝ์œผ๋กœ ๋‚˜์˜ค๋ฏ€๋กœ ๋œ ๋ช…ํ™•ํ•  ์ˆ˜ ์žˆ์Œ
JPA ํ‘œ์ค€ ์ค€์ˆ˜ ์—ฌ๋ถ€JPA ํ‘œ์ค€ ์–ด๋…ธํ…Œ์ด์…˜Hibernate ๊ตฌํ˜„์ฒด ํŠนํ™” ์„ฑ๊ฒฉ ๊ฐ•ํ•จ (@Column(unique=true)๋Š” JPA ํ‘œ์ค€์ด ์•„๋‹˜ โ†’ Hibernate ํ™•์žฅ ๊ธฐ๋Šฅ์ž„)
์‹ค๋ฌด ์‚ฌ์šฉ ๊ถŒ์žฅ ์—ฌ๋ถ€๐Ÿ‘ ๋งŽ์ด ์‚ฌ์šฉโš ๏ธ ์ž˜ ์“ฐ์ง€ ์•Š์Œ (ํ…Œ์ŠคํŠธ/๊ฐ„๋‹จํ•œ ๊ฒฝ์šฐ๋งŒ)

โœ… ์™œ ์‹ค๋ฌด์—์„œ๋Š” @Table(uniqueConstraints) ๊ฐ€ ๋” ์ข‹์€๊ฐ€?

1๏ธโƒฃ ๋ณตํ•ฉ UNIQUE ์ง€์› ๊ฐ€๋Šฅ

๋Œ€๋ถ€๋ถ„ ์„œ๋น„์Šค๋Š” ๋ณตํ•ฉ unique๊ฐ€ ํ•„์š”ํ•œ ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์Œ (ex: (user_id, email) ๊ฐ™์ด)

@Table(uniqueConstraints) ๋Š” ๋ณตํ•ฉํ‚ค๊นŒ์ง€ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ์ง€์›

@Column(unique=true) ๋Š” ๋‹จ์ผ ํ•„๋“œ๋งŒ ๊ฐ€๋Šฅ โ†’ ํ™•์žฅ์„ฑ ๋‚ฎ์Œ

2๏ธโƒฃ JPA ํ‘œ์ค€์„ฑ๊ณผ ์ด์‹์„ฑ

@Table(uniqueConstraints) ๋Š” JPA ํ‘œ์ค€ โ†’ ๋ชจ๋“  JPA ๊ตฌํ˜„์ฒด์—์„œ ์ง€์›

๋ฐ˜๋ฉด @Column(unique = true) ๋Š” Hibernate์—์„œ๋งŒ ํ™•์žฅ์ ์œผ๋กœ ์‚ฌ์šฉ ๊ฐ€๋Šฅ
โ†’ ๋‹ค๋ฅธ ๊ตฌํ˜„์ฒด๋กœ ๊ฐˆ ๊ฒฝ์šฐ ๊นจ์งˆ ์ˆ˜ ์žˆ์Œ

3๏ธโƒฃ DDL ๊ด€๋ฆฌ ์ธก๋ฉด

@Table(uniqueConstraints) ๋Š” DDL์ด ๋ช…ํ™•ํ•˜๊ฒŒ constraint ๋ ˆ๋ฒจ๋กœ ์ƒ์„ฑ๋จ

ALTER TABLE ADD CONSTRAINT UNIQUE (email)

@Column(unique=true) ๋Š” ์ปฌ๋Ÿผ ์ •์˜์— UNIQUE ๋ถ™์ด๋Š” ์ •๋„๋ผ
โ†’ DDL ํˆด/DBA๊ฐ€ ๊ด€๋ฆฌํ•  ๋•Œ ๊ฐ€๋…์„ฑ์ด ๋–จ์–ด์ง

4๏ธโƒฃ ์‹ค๋ฌด ๊ฒฝํ—˜์  ์ด์œ 

๋งŽ์€ ํŒ€์—์„œ @Column(unique = true) ๋ฅผ ์ผ๋‹ค๊ฐ€
โ†’ ๋ณตํ•ฉ unique ํ•„์š”ํ•˜๊ฑฐ๋‚˜ โ†’ DDL ํˆด๊ณผ ์ถฉ๋Œํ•˜๋ฉด์„œ โ†’ ์ „๋ถ€ @Table(uniqueConstraints)๋กœ ๋ณ€๊ฒฝํ•œ ์ผ€์ด์Šค ๋งŽ์Œ



โœ… ๊ฒฐ๋ก 

์ƒํ™ฉ์ถ”์ฒœ ๋ฐฉ์‹์ด์œ 
๋ณตํ•ฉ Unique ํ•„์š”ํ•œ ๊ฒฝ์šฐ@Table(uniqueConstraints)์œ ์ผํ•œ ์„ ํƒ์ง€
๋‹จ์ผ Unique๋ผ๋„ ์‹ค๋ฌด ์ ์šฉ@Table(uniqueConstraints)ํ‘œ์ค€์ , ๋ช…ํ™•, ์ด์‹์„ฑ ์šฐ์ˆ˜
๊ฐ„๋‹จํ•œ ํ…Œ์ŠคํŠธ/ํ”„๋กœํ† ํƒ€์ž…@Column(unique=true)๋น ๋ฅธ ํ…Œ์ŠคํŠธ์šฉ (์šด์˜ ๊ถŒ์žฅ X)

๋˜๋„๋ก ์šด์˜ ์ฝ”๋“œ์—์„œ๋Š” @Table(uniqueConstraints) ์‚ฌ์šฉ์ด ๋” ์•ˆ์ „ํ•˜๊ณ  ์‹ค๋ฌด์ ์œผ๋กœ ํ‘œ์ค€์ ์ด๋‹ค.
@Column(unique=true) ๋Š” ๋น ๋ฅธ ํ…Œ์ŠคํŠธ ์šฉ๋„๋กœ์„œ๋งŒ ์‚ฌ์šฉํ•˜์ž.

profile
๋งค์ผ ๋งค์ผ ์„ฑ์žฅํ•˜๊ธฐ

0๊ฐœ์˜ ๋Œ“๊ธ€