๊ด€๋ฆฌ ๋ฉ”๋‰ด

์‚ถ์˜ ๊ณต์œ 

[Spring] ๋ฐ์ดํ„ฐ ๋ชจ๋ธ๋ง ์™„๋ฒฝ ๊ฐ€์ด๋“œ ๋ณธ๋ฌธ

Web Dev/BackEnd

[Spring] ๋ฐ์ดํ„ฐ ๋ชจ๋ธ๋ง ์™„๋ฒฝ ๊ฐ€์ด๋“œ

dkrehd 2025. 5. 2. 00:04
728x90
๋ฐ˜์‘ํ˜•

๐Ÿ“Š Spring ๋ฐ์ดํ„ฐ ๋ชจ๋ธ๋ง ์™„๋ฒฝ ๊ฐ€์ด๋“œ: ์‹ค๋ฌด ์ค‘์‹ฌ ์ •๋ฆฌ

Spring ๊ฐœ๋ฐœ์ž๋กœ์„œ ๋ฐ์ดํ„ฐ ๋ชจ๋ธ๋ง(Data Modeling)์€ ๋‹จ์ˆœํ•œ DB ์„ค๊ณ„ ์ด์ƒ์ž…๋‹ˆ๋‹ค.
๋„๋ฉ”์ธ ๊ฐ์ฒด(Entity), ๋ ˆํฌ์ง€ํ† ๋ฆฌ ์„ค๊ณ„, ์„œ๋น„์Šค ๊ณ„์ธต๊นŒ์ง€ ์—ฐ๊ฒฐ๋˜๋Š” ํ•ต์‹ฌ ๊ธฐ๋ฐ˜์ด์ฃ .
์ด๋ฒˆ ๊ธ€์—์„œ๋Š” ๋ฐ์ดํ„ฐ ๋ชจ๋ธ๋ง์˜ ์ •์˜๋ถ€ํ„ฐ ERD ๊ตฌ์„ฑ ์š”์†Œ, PK/FK ๊ฐœ๋…, ๋ชจ๋ธ๋ง ์ ˆ์ฐจ๊นŒ์ง€ ์‹ค๋ฌด ๊ด€์ ์—์„œ ์ „๋ฌธ์ ์œผ๋กœ ์ •๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

 

1. ๋ฐ์ดํ„ฐ ๋ชจ๋ธ๋ง์˜ ์ •์˜: ํ˜„์‹ค์„ ๋ฐ์ดํ„ฐ๋กœ ๋ฒˆ์—ญํ•˜๋‹ค

  • ๋ชจ๋ธ๋ง(Modeling): ๋ณต์žกํ•œ ํ˜„์‹ค ์„ธ๊ณ„์˜ ๋Œ€์ƒ์„ ํ•ต์‹ฌ์ ์ธ ํŠน์ง•๋งŒ ์ถ”์ถœํ•˜์—ฌ ์ถ”์ƒํ™”ํ•˜๊ณ  ๋‹จ์ˆœํ™”ํ•˜์—ฌ ํ‘œํ˜„ํ•˜๋Š” ๊ณผ์ •์ž…๋‹ˆ๋‹ค. ์ง€๋„๋ฅผ ๋งŒ๋“ค๊ฑฐ๋‚˜ ๊ฑด์ถ• ์„ค๊ณ„๋„๋ฅผ ๊ทธ๋ฆฌ๋Š” ๊ฒƒ์„ ์ƒ๊ฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ๋ฐ์ดํ„ฐ ๋ชจ๋ธ๋ง(Data Modeling): ์ •๋ณด ์‹œ์Šคํ…œ์„ ๊ตฌ์ถ•ํ•˜๊ธฐ ์œ„ํ•ด, ์‹ค์ œ ์—…๋ฌด ํ”„๋กœ์„ธ์Šค์™€ ์š”๊ตฌ์‚ฌํ•ญ์— ๋งž์ถฐ ๋ฐ์ดํ„ฐ์˜ ๊ตฌ์กฐ, ํŠน์„ฑ, ๊ด€๊ณ„๋ฅผ ์ฒด๊ณ„์ ์œผ๋กœ ์ •์˜ํ•˜๊ณ  ํ‘œํ˜„ํ•˜๋Š” ์ž‘์—…์ž…๋‹ˆ๋‹ค. ์ด๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ๋ฐ์ดํ„ฐ๋ฅผ ์–ด๋–ป๊ฒŒ ์ €์žฅํ•˜๊ณ , ์ ‘๊ทผํ•˜๊ณ , ๊ด€๋ฆฌํ• ์ง€์— ๋Œ€ํ•œ ์ฒญ์‚ฌ์ง„ ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค.
  • ER ๋ชจ๋ธ (Entity-Relationship Model): ๋ฐ์ดํ„ฐ ๋ชจ๋ธ๋ง์˜ ๊ฐ€์žฅ ๋Œ€ํ‘œ์ ์ธ ๋ฐฉ๋ฒ•๋ก  ์ค‘ ํ•˜๋‚˜๋กœ, ํ˜„์‹ค ์„ธ๊ณ„์˜ ๊ฐœ๋…์ด๋‚˜ ๊ฐ์ฒด์ธ ๊ฐœ์ฒด(Entity) ์™€ ์ด๋“ค ๊ฐ„์˜ ๊ด€๊ณ„(Relationship) ๋ฅผ ์ค‘์‹ฌ์œผ๋กœ ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ๋ฅผ ํ‘œํ˜„ํ•ฉ๋‹ˆ๋‹ค.
  • ERD (Entity-Relationship Diagram): ER ๋ชจ๋ธ์„ ์‹œ๊ฐ์ ์œผ๋กœ ํ‘œํ˜„ํ•œ ๋‹ค์ด์–ด๊ทธ๋žจ์ž…๋‹ˆ๋‹ค. ์—”ํ‹ฐํ‹ฐ, ์†์„ฑ, ๊ด€๊ณ„ ๋“ฑ์ด ํ‘œ์ค€ํ™”๋œ ๊ธฐํ˜ธ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ทธ๋ ค์ง€๋ฏ€๋กœ, ๊ฐœ๋ฐœ์ž, ์„ค๊ณ„์ž, ํ˜„์—… ์‚ฌ์šฉ์ž ๊ฐ„์˜ ์˜์‚ฌ์†Œํ†ต ๋„๊ตฌ๋กœ ๋งค์šฐ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค.
  •  

2. ๋ฐ์ดํ„ฐ ๊ด€๊ณ„์˜ ํ•ต์‹ฌ: ๊ธฐ๋ณธ ํ‚ค(PK)์™€ ์™ธ๋ž˜ ํ‚ค(FK)

๊ด€๊ณ„ํ˜• ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋ชจ๋ธ๋ง์—์„œ ํ…Œ์ด๋ธ” ๊ฐ„์˜ ๊ด€๊ณ„๋ฅผ ์ •์˜ํ•˜๊ณ  ๋ฐ์ดํ„ฐ ๋ฌด๊ฒฐ์„ฑ์„ ๋ณด์žฅํ•˜๋Š” ๋ฐ ํ‚ค(Key)๋Š” ํ•„์ˆ˜์ ์ž…๋‹ˆ๋‹ค.

  • ๊ธฐ๋ณธ ํ‚ค (Primary Key, PK): ํ…Œ์ด๋ธ” ๋‚ด์˜ ๊ฐ ํ–‰(Row)์„ ๊ณ ์œ ํ•˜๊ฒŒ ์‹๋ณ„ํ•  ์ˆ˜ ์žˆ๋Š” ํ•˜๋‚˜ ์ด์ƒ์˜ ์ปฌ๋Ÿผ(Column)์ž…๋‹ˆ๋‹ค.
    • ํŠน์ง•:
      • ์œ ์ผ์„ฑ(Uniqueness): ํ…Œ์ด๋ธ” ๋‚ด์—์„œ ์ค‘๋ณต๋œ ๊ฐ’์„ ๊ฐ€์งˆ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. (Not Null + Unique)
      • ์ตœ์†Œ์„ฑ(Minimality): ์‹๋ณ„๋ ฅ์„ ๊ฐ–๋Š” ์ตœ์†Œํ•œ์˜ ์ปฌ๋Ÿผ์œผ๋กœ ๊ตฌ์„ฑ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
      • ์•ˆ์ •์„ฑ(Stability): ๊ฐ’์ด ์ž์ฃผ ๋ณ€๊ฒฝ๋˜์ง€ ์•Š์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค. (์ž์ฃผ ๋ณ€๊ฒฝ๋˜๋ฉด ์ด๋ฅผ ์ฐธ์กฐํ•˜๋Š” ๋‹ค๋ฅธ ๋ฐ์ดํ„ฐ์— ์˜ํ–ฅ์„ ๋ฏธ์นฉ๋‹ˆ๋‹ค.)
    • Spring/JPA: ์—”ํ‹ฐํ‹ฐ ํด๋ž˜์Šค ๋‚ด์—์„œ @Id ์–ด๋…ธํ…Œ์ด์…˜์œผ๋กœ ํ•„๋“œ๋ฅผ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค. ํ•„์š”์— ๋”ฐ๋ผ @GeneratedValue๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ž๋™ ์ƒ์„ฑ ์ „๋žต์„ ์ •์˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ์™ธ๋ž˜ ํ‚ค (Foreign Key, FK): ํ•œ ํ…Œ์ด๋ธ”์˜ ์ปฌ๋Ÿผ์ด ๋‹ค๋ฅธ ํ…Œ์ด๋ธ”์˜ ๊ธฐ๋ณธ ํ‚ค๋ฅผ ์ฐธ์กฐํ•˜์—ฌ ํ…Œ์ด๋ธ” ๊ฐ„์˜ ๊ด€๊ณ„(Relationship) ๋ฅผ ๋งบ๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ์ฐธ์กฐ ๋ฌด๊ฒฐ์„ฑ(Referential Integrity)์„ ๋ณด์žฅํ•˜๋Š” ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค. (์˜ˆ: ์ฃผ๋ฌธ ํ…Œ์ด๋ธ”์˜ ๊ณ ๊ฐ ID๋Š” ๊ณ ๊ฐ ํ…Œ์ด๋ธ”์˜ ๊ธฐ๋ณธ ํ‚ค๋ฅผ ์ฐธ์กฐ)
    • Spring/JPA: ์ฃผ๋กœ ๊ด€๊ณ„ ๋งคํ•‘ ์–ด๋…ธํ…Œ์ด์…˜(@ManyToOne, @OneToOne ๋“ฑ)๊ณผ ํ•จ๊ป˜ @JoinColumn ์–ด๋…ธํ…Œ์ด์…˜์„ ์‚ฌ์šฉํ•˜์—ฌ ์™ธ๋ž˜ ํ‚ค ์ปฌ๋Ÿผ์„ ๋ช…์‹œ์ ์œผ๋กœ ๋งคํ•‘ํ•ฉ๋‹ˆ๋‹ค.

์˜ˆ์‹œ: ๊ณ ๊ฐ(Users)๊ณผ ์ฃผ๋ฌธ(Orders) ํ…Œ์ด๋ธ”

SQL DDL:

CREATE TABLE Users (
    user_id BIGINT PRIMARY KEY AUTO_INCREMENT, -- ๊ธฐ๋ณธ ํ‚ค (PK)
    username VARCHAR(255) NOT NULL UNIQUE,
    email VARCHAR(255) UNIQUE
);

CREATE TABLE Orders (
    order_id BIGINT PRIMARY KEY AUTO_INCREMENT, -- ๊ธฐ๋ณธ ํ‚ค (PK)
    order_date DATETIME,
    user_id BIGINT,                            -- ์™ธ๋ž˜ ํ‚ค (FK)
    FOREIGN KEY (user_id) REFERENCES Users(user_id) -- Users ํ…Œ์ด๋ธ”์˜ PK ์ฐธ์กฐ
);

 

Spring Data JPA Entities:

import jakarta.persistence.*; // ๋˜๋Š” javax.persistence.*;
import java.time.LocalDateTime;
import java.util.List;

@Entity
@Table(name = "Users")
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long userId; // PK ๋งคํ•‘

    @Column(nullable = false, unique = true)
    private String username;

    @Column(unique = true)
    private String email;

    @OneToMany(mappedBy = "user") // Order ์—”ํ‹ฐํ‹ฐ์˜ 'user' ํ•„๋“œ์— ์˜ํ•ด ๋งคํ•‘๋จ
    private List<Order> orders;

    // Getters and Setters
}

@Entity
@Table(name = "Orders")
public class Order {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long orderId; // PK ๋งคํ•‘

    private LocalDateTime orderDate;

    @ManyToOne(fetch = FetchType.LAZY) // ์ง€์—ฐ ๋กœ๋”ฉ ๊ถŒ์žฅ
    @JoinColumn(name = "user_id") // FK ์ปฌ๋Ÿผ๋ช… ์ง€์ • (nullable=true ๊ธฐ๋ณธ)
    private User user; // FK ๊ด€๊ณ„ ๋งคํ•‘

    // Getters and Setters
}

3. ER ๋ชจ๋ธ์˜ ๊ตฌ์„ฑ ์š”์†Œ ์ƒ์„ธ

  • ์—”ํ‹ฐํ‹ฐ (Entity): ์ €์žฅ๋˜์–ด์•ผ ํ•  ๋ฐ์ดํ„ฐ์˜ ๋Œ€์ƒ์ด ๋˜๋Š” ์‹ค์กดํ•˜๋Š” ๊ฐœ์ฒด ๋˜๋Š” ๊ฐœ๋…์  ๋Œ€์ƒ์ž…๋‹ˆ๋‹ค. (์˜ˆ: ๊ณ ๊ฐ, ์ œํ’ˆ, ์ฃผ๋ฌธ, ๊ฒŒ์‹œ๊ธ€). ์ผ๋ฐ˜์ ์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ํ…Œ์ด๋ธ”๋กœ ๋งคํ•‘๋ฉ๋‹ˆ๋‹ค.
    • Spring/JPA: @Entity ์–ด๋…ธํ…Œ์ด์…˜์ด ๋ถ™์€ ํด๋ž˜์Šค์— ํ•ด๋‹นํ•ฉ๋‹ˆ๋‹ค.
  • ์†์„ฑ (Attribute): ์—”ํ‹ฐํ‹ฐ๊ฐ€ ๊ฐ€์ง€๋Š” ๊ตฌ์ฒด์ ์ธ ํŠน์„ฑ์ด๋‚˜ ์„ค๋ช…์œผ๋กœ, ๋ฐ์ดํ„ฐ๋ฅผ ํ‘œํ˜„ํ•˜๋Š” ๊ฐ€์žฅ ์ž‘์€ ๋…ผ๋ฆฌ์  ๋‹จ์œ„์ž…๋‹ˆ๋‹ค. (์˜ˆ: ๊ณ ๊ฐ ์—”ํ‹ฐํ‹ฐ์˜ ์ด๋ฆ„, ์ด๋ฉ”์ผ, ์ฃผ์†Œ). ํ…Œ์ด๋ธ”์˜ ์ปฌ๋Ÿผ์œผ๋กœ ๋งคํ•‘๋ฉ๋‹ˆ๋‹ค.
    • Spring/JPA: ์—”ํ‹ฐํ‹ฐ ํด๋ž˜์Šค ๋‚ด์˜ ํ•„๋“œ(๋ฉค๋ฒ„ ๋ณ€์ˆ˜) ์— ํ•ด๋‹นํ•˜๋ฉฐ, @Column, @Enumerated, @Temporal ๋“ฑ์˜ ์–ด๋…ธํ…Œ์ด์…˜์œผ๋กœ ์„ธ๋ถ€ ์†์„ฑ์„ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค.
  • ๊ด€๊ณ„ (Relationship): ์—”ํ‹ฐํ‹ฐ(๋˜๋Š” ์ธ์Šคํ„ด์Šค) ๊ฐ„์˜ ์˜๋ฏธ ์žˆ๋Š” ์—ฐ๊ด€์„ฑ์ด๋‚˜ ๊ทœ์น™์„ ํ‘œํ˜„ํ•ฉ๋‹ˆ๋‹ค. (์˜ˆ: ๊ณ ๊ฐ์€ ์—ฌ๋Ÿฌ ์ฃผ๋ฌธ์„ ํ•  ์ˆ˜ ์žˆ๋‹ค). ์ฃผ๋กœ ์™ธ๋ž˜ ํ‚ค(FK) ๋ฅผ ํ†ตํ•ด ๊ตฌํ˜„๋ฉ๋‹ˆ๋‹ค.
    • Spring/JPA: @OneToOne, @ManyToOne, @OneToMany, @ManyToMany ๋“ฑ์˜ ๊ด€๊ณ„ ๋งคํ•‘ ์–ด๋…ธํ…Œ์ด์…˜์œผ๋กœ ํ‘œํ˜„๋ฉ๋‹ˆ๋‹ค.
  • ์‹๋ณ„์ž (Identifier): ํ•˜๋‚˜์˜ ์—”ํ‹ฐํ‹ฐ ๋‚ด์—์„œ ๊ฐ ์ธ์Šคํ„ด์Šค(ํ–‰)๋ฅผ ๊ณ ์œ ํ•˜๊ฒŒ ๊ตฌ๋ณ„ํ•  ์ˆ˜ ์žˆ๋Š” ์†์„ฑ ๋˜๋Š” ์†์„ฑ๋“ค์˜ ์ง‘ํ•ฉ์ž…๋‹ˆ๋‹ค. ๊ธฐ๋ณธ ํ‚ค(PK) ๊ฐ€ ๋Œ€ํ‘œ์ ์ธ ์‹๋ณ„์ž์ž…๋‹ˆ๋‹ค.
    • Spring/JPA: @Id ์–ด๋…ธํ…Œ์ด์…˜์œผ๋กœ ์ง€์ •๋œ ํ•„๋“œ(๋“ค)์— ํ•ด๋‹นํ•ฉ๋‹ˆ๋‹ค.

4. ์—”ํ‹ฐํ‹ฐ ๊ด€๊ณ„(Entity Relationship)์˜ ์ข…๋ฅ˜์™€ ํ‘œํ˜„

์—”ํ‹ฐํ‹ฐ ๊ฐ„์˜ ๊ด€๊ณ„๋Š” ํฌ๊ฒŒ ๊ด€๊ณ„์ˆ˜(Cardinality)์™€ ์„ ํƒ์„ฑ(Optionality)์œผ๋กœ ์ •์˜๋ฉ๋‹ˆ๋‹ค.

  • ๊ด€๊ณ„์ˆ˜ (Cardinality): ๋‘ ์—”ํ‹ฐํ‹ฐ ํƒ€์ž… ๊ฐ„์— ์ฐธ์—ฌํ•  ์ˆ˜ ์žˆ๋Š” ์ธ์Šคํ„ด์Šค(ํ–‰)์˜ ์ˆ˜๋ฅผ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.
    • ์ผ๋Œ€์ผ (1:1): ๊ฐ ์—”ํ‹ฐํ‹ฐ์˜ ์ธ์Šคํ„ด์Šค๊ฐ€ ์ƒ๋Œ€ ์—”ํ‹ฐํ‹ฐ์˜ ์ธ์Šคํ„ด์Šค ํ•˜๋‚˜์™€ ๊ด€๊ณ„๋ฅผ ๋งบ์Šต๋‹ˆ๋‹ค. (์˜ˆ: User์™€ UserProfile)
      • JPA: @OneToOne
    • ์ผ๋Œ€๋‹ค (1:N): ํ•œ ์—”ํ‹ฐํ‹ฐ์˜ ์ธ์Šคํ„ด์Šค๊ฐ€ ์ƒ๋Œ€ ์—”ํ‹ฐํ‹ฐ์˜ ์—ฌ๋Ÿฌ ์ธ์Šคํ„ด์Šค์™€ ๊ด€๊ณ„๋ฅผ ๋งบ์Šต๋‹ˆ๋‹ค. (์˜ˆ: User์™€ Orders)
      • JPA: @OneToMany (1 ์ชฝ์—์„œ) ์™€ @ManyToOne (N ์ชฝ์—์„œ)
    • ๋‹ค๋Œ€๋‹ค (M:N): ์–‘์ชฝ ์—”ํ‹ฐํ‹ฐ์˜ ์ธ์Šคํ„ด์Šค๊ฐ€ ์„œ๋กœ ์—ฌ๋Ÿฌ ์ธ์Šคํ„ด์Šค์™€ ๊ด€๊ณ„๋ฅผ ๋งบ์Šต๋‹ˆ๋‹ค. (์˜ˆ: Student์™€ Course)
      • ๊ด€๊ณ„ํ˜• DB: ์ง์ ‘ ํ‘œํ˜„์ด ์–ด๋ ค์›Œ ์ค‘๊ฐ„์— ๊ต์ฐจ ํ…Œ์ด๋ธ”(Intersection/Junction Table) ์„ ๋‘์–ด ๋‘ ๊ฐœ์˜ 1:N ๊ด€๊ณ„๋กœ ๋ถ„ํ•ดํ•ฉ๋‹ˆ๋‹ค. ๋ฐ์ดํ„ฐ ์ค‘๋ณต์„ ๋ฐฉ์ง€ํ•˜๊ณ  ๊ด€๊ณ„ ์†์„ฑ์„ ์ €์žฅํ•˜๊ธฐ ์œ„ํ•จ์ž…๋‹ˆ๋‹ค.
      • JPA: @ManyToMany ์–ด๋…ธํ…Œ์ด์…˜์œผ๋กœ ํ‘œํ˜„ ๊ฐ€๋Šฅ (JPA๊ฐ€ ์•”๋ฌต์ ์œผ๋กœ ์กฐ์ธ ํ…Œ์ด๋ธ” ์ƒ์„ฑ/๊ด€๋ฆฌ)ํ•˜๊ฑฐ๋‚˜, ์กฐ์ธ ํ…Œ์ด๋ธ” ์ž์ฒด๋ฅผ ๋ณ„๋„์˜ @Entity๋กœ ๋ช…์‹œ์ ์œผ๋กœ ๋งคํ•‘ํ•˜์—ฌ @OneToMany + @ManyToOne ๊ด€๊ณ„๋กœ ํ’€์–ด๋‚ผ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค (๊ถŒ์žฅ๋˜๋Š” ๋ฐฉ์‹).
  • ์„ ํƒ์„ฑ (Optionality): ๊ด€๊ณ„๋ฅผ ๋งบ๋Š” ์ƒ๋Œ€ ์—”ํ‹ฐํ‹ฐ์˜ ์ธ์Šคํ„ด์Šค๊ฐ€ ํ•„์ˆ˜์ (Mandatory)์ธ์ง€ ์„ ํƒ์ (Optional)์ธ์ง€ ์—ฌ๋ถ€๋ฅผ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.
    • ํ•„์ˆ˜ ์ฐธ์—ฌ (Mandatory, ์‹ค์„  ๋˜๋Š” ํŠน์ • ๊ธฐํ˜ธ): ๊ด€๊ณ„๋ฅผ ๋งบ๋Š” ์ƒ๋Œ€ ์ธ์Šคํ„ด์Šค๊ฐ€ ๋ฐ˜๋“œ์‹œ ์กด์žฌํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. (์˜ˆ: ์ฃผ๋ฌธ(Order)์€ ๋ฐ˜๋“œ์‹œ ํŠน์ • ๊ณ ๊ฐ(User)๊ณผ ์—ฐ๊ฒฐ๋˜์–ด์•ผ ํ•จ)
      • DB: FK ์ปฌ๋Ÿผ์— NOT NULL ์ œ์•ฝ์กฐ๊ฑด์„ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.
      • JPA: @ManyToOne(optional = false), @OneToOne(optional = false), @JoinColumn(nullable = false) ๋“ฑ์œผ๋กœ ํ‘œํ˜„ํ•ฉ๋‹ˆ๋‹ค.
    • ์„ ํƒ ์ฐธ์—ฌ (Optional, ์ ์„  ๋˜๋Š” ํŠน์ • ๊ธฐํ˜ธ): ๊ด€๊ณ„๋ฅผ ๋งบ๋Š” ์ƒ๋Œ€ ์ธ์Šคํ„ด์Šค๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š์„ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. (์˜ˆ: ์‚ฌ์šฉ์ž๋Š” ํ”„๋กœํ•„ ์‚ฌ์ง„์„ ๊ฐ€์งˆ ์ˆ˜๋„, ์•ˆ ๊ฐ€์งˆ ์ˆ˜๋„ ์žˆ์Œ)
      • DB: FK ์ปฌ๋Ÿผ์ด NULL ๊ฐ’์„ ํ—ˆ์šฉํ•ฉ๋‹ˆ๋‹ค.
      • JPA: optional = true(๊ธฐ๋ณธ๊ฐ’), nullable = true(๊ธฐ๋ณธ๊ฐ’)์œผ๋กœ ํ‘œํ˜„๋ฉ๋‹ˆ๋‹ค.
  • ์‹๋ณ„ ๊ด€๊ณ„ vs ๋น„์‹๋ณ„ ๊ด€๊ณ„:
    • ์‹๋ณ„ ๊ด€๊ณ„: ๋ถ€๋ชจ ์—”ํ‹ฐํ‹ฐ์˜ ๊ธฐ๋ณธ ํ‚ค(์‹๋ณ„์ž)๊ฐ€ ์ž์‹ ์—”ํ‹ฐํ‹ฐ์˜ ๊ธฐ๋ณธ ํ‚ค์˜ ์ผ๋ถ€๊ฐ€ ๋˜๋Š” ๊ด€๊ณ„์ž…๋‹ˆ๋‹ค. (์ž์‹ ์—”ํ‹ฐํ‹ฐ๋Š” ๋ถ€๋ชจ ์—†์ด๋Š” ์‹๋ณ„๋  ์ˆ˜ ์—†์Œ).
      • JPA: @MapsId ๋˜๋Š” @IdClass, @EmbeddedId ๋“ฑ์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ณตํ•ฉ ํ‚ค๋ฅผ ๋งคํ•‘ํ•  ๋•Œ ๋‚˜ํƒ€๋‚ฉ๋‹ˆ๋‹ค.
    • ๋น„์‹๋ณ„ ๊ด€๊ณ„ (์ผ๋ฐ˜์ ): ๋ถ€๋ชจ ์—”ํ‹ฐํ‹ฐ์˜ ๊ธฐ๋ณธ ํ‚ค๊ฐ€ ์ž์‹ ์—”ํ‹ฐํ‹ฐ์˜ ์ผ๋ฐ˜ ์†์„ฑ(FK)์œผ๋กœ ์ฐธ์กฐ๋˜๋Š” ๊ด€๊ณ„์ž…๋‹ˆ๋‹ค. (์œ„์˜ User-Order ์˜ˆ์‹œ)

5. ๋ฐ์ดํ„ฐ ๋ชจ๋ธ๋ง ์ ˆ์ฐจ: ์ฒด๊ณ„์ ์ธ ์ ‘๊ทผ

๋ฐ์ดํ„ฐ ๋ชจ๋ธ๋ง์€ ์ผ๋ฐ˜์ ์œผ๋กœ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ ˆ์ฐจ๋ฅผ ๋”ฐ๋ฆ…๋‹ˆ๋‹ค.

  1. ๋ถ„์„ ๋‹จ๊ณ„:
    • ์—…๋ฌด ๋ถ„์„: ๋Œ€์ƒ ์—…๋ฌด์˜ ํ”„๋กœ์„ธ์Šค, ๊ทœ์น™, ์š”๊ตฌ์‚ฌํ•ญ์„ ๋ช…ํ™•ํžˆ ์ดํ•ดํ•ฉ๋‹ˆ๋‹ค.
    • ๋ฐ์ดํ„ฐ ๋ถ„์„: ์—…๋ฌด์— ์‚ฌ์šฉ๋˜๋Š” ๋ฐ์ดํ„ฐ์˜ ์ข…๋ฅ˜, ํ๋ฆ„, ์ œ์•ฝ ์กฐ๊ฑด์„ ํŒŒ์•…ํ•ฉ๋‹ˆ๋‹ค.
    • ์š”๊ตฌ์‚ฌํ•ญ ์ •์˜: ์‚ฌ์šฉ์ž ๋ฐ ์‹œ์Šคํ…œ ์š”๊ตฌ์‚ฌํ•ญ์„ ๊ตฌ์ฒดํ™”ํ•ฉ๋‹ˆ๋‹ค.
    • ๋ฐฉํ–ฅ ์ˆ˜๋ฆฝ: ๋ชจ๋ธ๋ง์˜ ๋ฒ”์œ„์™€ ๋ชฉํ‘œ, ๊ณ ๋ ค์‚ฌํ•ญ์„ ๊ฒฐ์ •ํ•ฉ๋‹ˆ๋‹ค. (๊ธฐ์กด ์‹œ์Šคํ…œ ๋ฒค์น˜๋งˆํ‚น, ํ™”๋ฉด ์ •์˜์„œ ์ž‘์„ฑ ๋“ฑ์ด ํฌํ•จ๋  ์ˆ˜ ์žˆ์Œ)
  2. ์„ค๊ณ„ ๋‹จ๊ณ„:
    • ๊ฐœ๋…์  ๋ชจ๋ธ๋ง (Conceptual Modeling): ์—…๋ฌด ์˜์—ญ์˜ ํ•ต์‹ฌ ์—”ํ‹ฐํ‹ฐ์™€ ๊ทธ๋“ค ๊ฐ„์˜ ์ฃผ์š” ๊ด€๊ณ„๋ฅผ ์ถ”์ƒ์ ์ธ ์ˆ˜์ค€์—์„œ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค. (ERD ์ดˆ์•ˆ ์ž‘์„ฑ)
      • ์ฃผ์ œ ์˜์—ญ ์ •์˜: ๋ชจ๋ธ๋ง ๋Œ€์ƒ๊ณผ ๋ฒ”์œ„ ํ™•์ •.
      • ํ•ต์‹ฌ ์—”ํ‹ฐํ‹ฐ ๋„์ถœ: ์ฃผ์š” ์—…๋ฌด ์ฃผ์ฒด, ๋Œ€์ƒ, ๊ฐœ๋… ์‹๋ณ„.
    • ๋…ผ๋ฆฌ์  ๋ชจ๋ธ๋ง (Logical Modeling): ๊ฐœ๋… ๋ชจ๋ธ์„ ๊ธฐ๋ฐ˜์œผ๋กœ ๊ตฌ์ฒด์ ์ธ ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ๋ฅผ ์„ค๊ณ„ํ•ฉ๋‹ˆ๋‹ค. ํŠน์ • ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๊ธฐ์ˆ ๊ณผ๋Š” ๋…๋ฆฝ์ ์œผ๋กœ, ์ •๊ทœํ™” ๋“ฑ์„ ํ†ตํ•ด ๋ฐ์ดํ„ฐ์˜ ์ผ๊ด€์„ฑ๊ณผ ํšจ์œจ์„ฑ์„ ํ™•๋ณดํ•ฉ๋‹ˆ๋‹ค.
      • ๋ชจ๋“  ์—”ํ‹ฐํ‹ฐ ์ƒ์„ธ ์ •์˜ (์†์„ฑ ํฌํ•จ).
      • ์—”ํ‹ฐํ‹ฐ ๊ฐ„ ๊ด€๊ณ„ ์ƒ์„ธ ์ •์˜ (๊ด€๊ณ„์ˆ˜, ์„ ํƒ์„ฑ, ์‹๋ณ„ ์—ฌ๋ถ€ ๋“ฑ).
      • ์†์„ฑ ์ •์˜ (๋ฐ์ดํ„ฐ ํƒ€์ž…, ์ œ์•ฝ ์กฐ๊ฑด ๋“ฑ).
      • ์ •๊ทœํ™” ์ˆ˜ํ–‰.
    • ๋ฌผ๋ฆฌ์  ๋ชจ๋ธ๋ง (Physical Modeling): ๋…ผ๋ฆฌ ๋ชจ๋ธ์„ ํŠน์ • ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์‹œ์Šคํ…œ(MySQL, Oracle ๋“ฑ)์— ๋งž๊ฒŒ ๋ณ€ํ™˜ํ•˜๋Š” ๊ณผ์ •์ž…๋‹ˆ๋‹ค. ์„ฑ๋Šฅ, ๋ณด์•ˆ, ์ €์žฅ ๊ณต๊ฐ„ ๋“ฑ์„ ๊ณ ๋ คํ•˜์—ฌ ํ…Œ์ด๋ธ”, ์ปฌ๋Ÿผ, ์ธ๋ฑ์Šค ๋“ฑ์„ ๊ตฌ์ฒด์ ์œผ๋กœ ์„ค๊ณ„ํ•ฉ๋‹ˆ๋‹ค.
      • ํ…Œ์ด๋ธ”/์ปฌ๋Ÿผ ๋ณ€ํ™˜: ์—”ํ‹ฐํ‹ฐ -> ํ…Œ์ด๋ธ”, ์†์„ฑ -> ์ปฌ๋Ÿผ (DB ํƒ€์ž… ๋งคํ•‘, ์ด๋ฆ„ ๊ทœ์น™ ์ ์šฉ).
      • ๋ฌด๊ฒฐ์„ฑ ์„ค๊ณ„: PK, FK, Not Null, Unique, Check ์ œ์•ฝ์กฐ๊ฑด, Default ๊ฐ’ ์„ค์ •. (JPA์—์„œ๋Š” @Id, @Column(nullable=false, unique=true), @Check ๋“ฑ์œผ๋กœ ๋ฐ˜์˜)
      • ์„ฑ๋Šฅ ํ–ฅ์ƒ: ์—ญ์ •๊ทœํ™”(ํ•„์š”์‹œ), ์ค‘๋ณต ์ปฌ๋Ÿผ ์ถ”๊ฐ€, ์ธ๋ฑ์Šค ์„ค๊ณ„(@Index), ํŒŒํ‹ฐ์…”๋‹(DB ๊ธฐ๋Šฅ) ๋“ฑ์„ ๊ณ ๋ คํ•ฉ๋‹ˆ๋‹ค.

6. ์ถ”๊ฐ€์ ์ธ ๋ชจ๋ธ๋ง ๊ณ ๋ ค์‚ฌํ•ญ: ๋ถ„๋ฅ˜ ํ…Œ์ด๋ธ”๊ณผ ์ฝ”๋“œ ํ…Œ์ด๋ธ”

  • ๋ถ„๋ฅ˜ ํ…Œ์ด๋ธ” (Classification Table): ๋ฐ์ดํ„ฐ์˜ ๋ถ„๋ฅ˜ ์ฒด๊ณ„๋ฅผ ๊ด€๋ฆฌํ•˜๊ธฐ ์œ„ํ•œ ํ…Œ์ด๋ธ”์ž…๋‹ˆ๋‹ค. ๊ณ„์ธต ๊ตฌ์กฐ๊ฐ€ ๊ณ ์ •์ ์ธ ๊ฒฝ์šฐ(๋Œ€/์ค‘/์†Œ ๋ถ„๋ฅ˜) ๋˜๋Š” ๋™์ ์ธ ๊ฒฝ์šฐ(์ƒ์œ„/ํ•˜์œ„ ๊ด€๊ณ„)์— ์‚ฌ์šฉ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
    • Spring/JPA: ๊ณ„์ธต ๊ตฌ์กฐ๋Š” @ManyToOne (self-referencing) ๋“ฑ์œผ๋กœ ํ‘œํ˜„ํ•˜๊ฑฐ๋‚˜, ๊ณ ์ • ๋ถ„๋ฅ˜๋Š” Enum ํƒ€์ž…์œผ๋กœ ๋งคํ•‘ํ•˜๋Š” ๊ฒƒ๋„ ์ข‹์€ ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค.
  • ์ฝ”๋“œ ํ…Œ์ด๋ธ” (Code Table): ์‹œ์Šคํ…œ ์ „๋ฐ˜์—์„œ ์‚ฌ์šฉ๋˜๋Š” ๋‹ค์–‘ํ•œ ์ฝ”๋“œ(์ƒํƒœ ์ฝ”๋“œ, ์œ ํ˜• ์ฝ”๋“œ ๋“ฑ)์™€ ๊ทธ ์˜๋ฏธ๋ฅผ ํ†ตํ•ฉ ๊ด€๋ฆฌํ•˜๋Š” ํ…Œ์ด๋ธ”์ž…๋‹ˆ๋‹ค. ์ฝ”๋“œ ๊ฐ’์˜ ์ผ๊ด€์„ฑ์„ ์œ ์ง€ํ•˜๊ณ  ๊ด€๋ฆฌ ์šฉ์ด์„ฑ์„ ๋†’์ž…๋‹ˆ๋‹ค.
    • Spring/JPA: ์ฝ”๋“œ ํ…Œ์ด๋ธ”์„ ์—”ํ‹ฐํ‹ฐ๋กœ ๋งคํ•‘ํ•˜๊ฑฐ๋‚˜, ์ž์ฃผ ๋ณ€๊ฒฝ๋˜์ง€ ์•Š๋Š” ์ฝ”๋“œ๋Š” Java Enum ํƒ€์ž…์œผ๋กœ ์ •์˜ํ•˜์—ฌ @Enumerated ์–ด๋…ธํ…Œ์ด์…˜์œผ๋กœ ๋งคํ•‘ํ•˜๋Š” ๊ฒƒ์ด ํšจ๊ณผ์ ์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๐Ÿง‘‍๐Ÿ’ป Spring์—์„œ ๋ฐ์ดํ„ฐ ๋ชจ๋ธ๋ง์€ ์ด๋ ‡๊ฒŒ ์—ฐ๊ฒฐ๋ฉ๋‹ˆ๋‹ค


ER ๋ชจ๋ธ ์š”์†Œ Spring ํ‘œํ˜„ ๋ฐฉ์‹
์—”ํ‹ฐํ‹ฐ(Entity) @Entity, Java ํด๋ž˜์Šค
์†์„ฑ(Attribute) @Column, ํ•„๋“œ
๊ธฐ๋ณธํ‚ค(PK) @Id
์ฐธ์กฐํ‚ค(FK) @ManyToOne, @JoinColumn
๊ด€๊ณ„ @OneToMany, @ManyToOne

 

๊ฒฐ๋ก : ๊ฒฌ๊ณ ํ•œ Spring ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์‹œ์ž‘

๋ฐ์ดํ„ฐ ๋ชจ๋ธ๋ง์€ ๋‹จ์ˆœํžˆ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์Šคํ‚ค๋งˆ๋ฅผ ๊ทธ๋ฆฌ๋Š” ์ž‘์—…์ด ์•„๋‹ˆ๋ผ, ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ํ•ต์‹ฌ ๊ตฌ์กฐ๋ฅผ ์„ค๊ณ„ํ•˜๋Š” ์ค‘์š”ํ•œ ๊ณผ์ •์ž…๋‹ˆ๋‹ค. ์—…๋ฌด ์š”๊ตฌ์‚ฌํ•ญ์„ ์ •ํ™•ํžˆ ๋ฐ˜์˜ํ•˜๊ณ , ๋ฐ์ดํ„ฐ์˜ ์ผ๊ด€์„ฑ๊ณผ ๋ฌด๊ฒฐ์„ฑ์„ ๋ณด์žฅํ•˜๋ฉฐ, ํ–ฅํ›„ ํ™•์žฅ์„ฑ๊ณผ ์„ฑ๋Šฅ๊นŒ์ง€ ๊ณ ๋ คํ•œ ๋ชจ๋ธ๋ง์€ Spring ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ํ’ˆ์งˆ์„ ๊ฒฐ์ •์ง“๋Š” ํ•ต์‹ฌ ์š”์†Œ์ž…๋‹ˆ๋‹ค.

๋ฐ˜์‘ํ˜•