๐Ÿš€ Growth/TIL

[TIL] 2026๋…„ 01์›” 07์ผ

devCloud 2026. 1. 7. 17:02
728x90

ORM ๋งคํ•‘์ด ํ•„์š”ํ•œ ์ด์œ 

๊ฐ์ฒด์™€ ๊ด€๊ณ„ํ˜• ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๊ฐ€ ๊ด€๊ณ„๋ฅผ ํ‘œํ˜„ํ•˜๋Š” ๋ฐฉ์‹์˜ ๊ทผ๋ณธ์ ์ธ ์ฐจ์ด๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ฐ์ฒด๋Š” ์„œ๋กœ ๋‹ค๋ฅธ ๊ฐ์ฒด๋ฅผ '์ฐธ์กฐ'ํ•˜๋ฉฐ ๊ด€๊ณ„๋ฅผ ๋งบ์Šต๋‹ˆ๋‹ค. ๋ฐ˜๋ฉด์— ํ…Œ์ด๋ธ”์€ '์™ธ๋ž˜ ํ‚ค' ๊ฐ’์„ ํ†ตํ•ด ๋‹ค๋ฅธ ํ…Œ์ด๋ธ”์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์—ฐ๊ฒฐํ•˜์ฃ . ์ด ์ฐจ์ด ๋•Œ๋ฌธ์— ORM ๋งคํ•‘์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

 

๐Ÿš€ ๋ฉ”๋ชจ๋ฆฌ(๊ฐ์ฒด) ↔ ์ €์žฅ์†Œ(ํ…Œ์ด๋ธ”) ๊ด€๊ณ„์—์„œ JPA๊ฐ€ ์ค‘๊ฐ„(์˜์†์„ฑ ์ปจํ…์ŠคํŠธ)์—์„œ ๋ฌด์—‡์„ ํ•˜๋Š”์ง€

ํ•ต์‹ฌ: ์ฝ”๋“œ์—์„œ๋Š” ๊ฐ์ฒด ์ฐธ์กฐ๋กœ ๊ด€๊ณ„๋ฅผ ๋งŒ๋“ค๊ณ , JPA๊ฐ€ ๊ทธ๊ฑธ DB์˜ FK๋กœ ๋ฐ”๊ฟ”์„œ ์ €์žฅํ•œ๋‹ค.

 

1) ์—”ํ‹ฐํ‹ฐ(๊ฐ์ฒด) ์ชฝ ์ฝ”๋“œ: "๊ฐ์ฒด ์ฐธ์กฐ"๋กœ ๊ด€๊ณ„ ํ‘œํ˜„

@Entity
@Table(name = "TEAM")
public class Team {
    @Id @GeneratedValue
    private Long id;

    private String name;
}

@Entity
@Table(name = "MEMBER")
public class Member {
    @Id @GeneratedValue
    private Long id;

    private String username;

    @ManyToOne
    @JoinColumn(name = "TEAM_ID") // MEMBER ํ…Œ์ด๋ธ”์— TEAM_ID(FK) ์ปฌ๋Ÿผ์ด ์ƒ๊น€
    private Team team;
    
    public void changeTeam(Team team) {
        this.team = team;
    }
}
  • ์—ฌ๊ธฐ์„œ Member.team์€ teamId ๊ฐ™์€ ์ˆซ์ž๊ฐ€ ์•„๋‹ˆ๋ผ, Team "๊ฐ์ฒด ์ž์ฒด"๋ฅผ ์ฐธ์กฐํ•ฉ๋‹ˆ๋‹ค.
  • ๊ทธ๋Ÿฐ๋ฐ @JoinColumn(name="TEAM_ID") ๋•Œ๋ฌธ์—, DB์—๋Š” MEMBER ํ…Œ์ด๋ธ”์— TEAM_ID(FK) ์ปฌ๋Ÿผ์œผ๋กœ ์ €์žฅ๋ฉ๋‹ˆ๋‹ค. (ManyToOne์ด๋ฉด FK๋Š” “์†Œ์Šค ์—”ํ‹ฐํ‹ฐ(์—ฌ๊ธฐ์„œ๋Š” MEMBER) ํ…Œ์ด๋ธ””์— ๋†“์ž…๋‹ˆ๋‹ค.)

 

2) "๋ฉ”๋ชจ๋ฆฌ์—์„œ ๋งŒ๋“ค๊ณ  → ์ €์žฅ ๋Œ€์ƒ์œผ๋กœ ๋“ฑ๋กํ•˜๊ณ  → ์ปค๋ฐ‹ ๋•Œ DB์— ๋ฐ˜์˜" ํ๋ฆ„

// ๋ณดํ†ต ์Šคํ”„๋ง์ด๋ฉด @Transactional ์•ˆ์—์„œ ์‹คํ–‰๋œ๋‹ค๊ณ  ๋ณด๋ฉด ๋ฉ๋‹ˆ๋‹ค.
Team team = new Team();
team.setName("TeamA");	//์ง€๊ธˆ์€ ๊ทธ๋ƒฅ ์ž๋ฐ” ๊ฐ์ฒด(๋ฉ”๋ชจ๋ฆฌ)

em.persist(team);	//์˜์†์„ฑ ์ปจํ…์ŠคํŠธ์— ๋“ฑ๋ก(๊ด€๋ฆฌ ์‹œ์ž‘)

Member member = new Member();
member.setUsername("member1");
member.changeTeam(team);	//๊ฐ์ฒด ์ฐธ์กฐ๋กœ ๊ด€๊ณ„ ์—ฐ๊ฒฐ

em.persist(member);		// member๋„ ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ์— ๋“ฑ๋ก

// ํŠธ๋žœ์žญ์…˜ commit ์‹œ์ ์— flush๊ฐ€ ์ผ์–ด๋‚˜๋ฉฐ DB์— ๋ฐ˜์˜๋จ
tx.commit();

 

์—ฌ๊ธฐ์„œ ํฌ์ธํŠธ๋Š” 3๋‹จ๊ณ„์ž…๋‹ˆ๋‹ค.

  1. new Team(), new Member()
    • ๊ทธ๋ƒฅ ๋ฉ”๋ชจ๋ฆฌ์˜ ์ž๋ฐ” ๊ฐ์ฒด์ž…๋‹ˆ๋‹ค. ์•„์ง DB๋ž‘ ๋ฌด๊ด€ํ•ฉ๋‹ˆ๋‹ค.
  2. em.persist(...)
    • ๊ฐ์ฒด๋ฅผ ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ(= EntityManager๊ฐ€ ๊ด€๋ฆฌํ•˜๋Š” ์˜์—ญ)์— ๋„ฃ์–ด์„œ "๊ด€๋ฆฌ ๋Œ€์ƒ(Managed)"์œผ๋กœ ๋งŒ๋“ญ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  "๋‚˜์ค‘์— DB์— ๋„ฃ์„ ๋Œ€์ƒ"์œผ๋กœ ์˜ˆ์•ฝ๋ฉ๋‹ˆ๋‹ค.
  3. commit(๋˜๋Š” flush)
    • ๋ณ€๊ฒฝ ์‚ฌํ•ญ์ด ์ฆ‰์‹œ DB๋กœ ๋‚˜๊ฐ€๋Š” ๊ฒŒ ์•„๋‹ˆ๋ผ, ๋ณดํ†ต ์ปค๋ฐ‹ ์ง์ „์— flush(๋™๊ธฐํ™”) ๋˜๋ฉด์„œ INSERT/UPDATE ๊ฐ™์€ SQL์ด DB์— ์ „๋‹ฌ๋ฉ๋‹ˆ๋‹ค.

 

3) find()๊ฐ€ "์—”ํ‹ฐํ‹ฐ๋ฅผ ์ฐพ๋Š”๋‹ค"๋Š” ๊ฒŒ ์ฝ”๋“œ์—์„œ ์–ด๋–ค ์˜๋ฏธ์ธ์ง€

Long teamId = 100L;
Team t1 = em.find(Team.class, teamId);
Team t2 = em.find(Team.class, teamId);

System.out.println(t1 == t2) 	// ๊ฐ™์€ ํŠธ๋žœ์žญ์…˜/๊ฐ™์€ ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ๋ฉด ๋ณดํ†ต true

 

em.find(Team.class, 100L)์€ PK๊ฐ€ 100์ธ Team ์—”ํ‹ฐํ‹ฐ(๊ฐ์ฒด)๋ฅผ ๊ฐ€์ ธ์˜จ๋‹ค๋Š” ๋œป์ด๊ณ , JPA๋Š” "ํ•œ ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ ์•ˆ์—์„œ ๊ฐ™์€ PK๋Š” ๊ฐ์ฒด 1๊ฐœ๋งŒ ์กด์žฌ"ํ•˜๋„๋ก ๊ด€๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

๊ทธ๋ž˜์„œ ๊ฐ™์€ ํŠธ๋žœ์žญ์…˜ ๋ฒ”์œ„์—์„œ ๊ฐ™์€ PK๋ฅผ ๋‘ ๋ฒˆ ์ฐพ์œผ๋ฉด DB๋ฅผ ๋˜ ์ฐ๊ธฐ๋ณด๋‹ค ๊ฐ™์€ ๊ฐ์ฒด๋ฅผ ์žฌ์‚ฌ์šฉํ•˜๋Š” ํ˜•ํƒœ๊ฐ€ ๋ฉ๋‹ˆ๋‹ค.(1์ฐจ ์บ์‹œ/๋™์ผ์„ฑ ๋ณด์žฅ)


1) Team ์—”ํ‹ฐํ‹ฐ ์ฝ”๋“œ ํ’€์ด

@Entity
@Table(name = "TEAM")
public class Team {
    @Id @GeneratedValue
    private Long id;

    private String name;
}
  • @Entity
    • ์ด ํด๋ž˜์Šค๊ฐ€ JPA๊ฐ€ ๊ด€๋ฆฌํ•˜๋Š” ์˜์† ๊ฐ์ฒด(์—”ํ‹ฐํ‹ฐ)๋ผ๋Š” ๋œป์ž…๋‹ˆ๋‹ค. ์ฆ‰, DB์— ์ €์žฅ/์กฐํšŒ ํ•  ๋Œ€์ƒ์œผ๋กœ ์ธ์‹๋ฉ๋‹ˆ๋‹ค. ์—”ํ‹ฐํ‹ฐ์˜ ์ƒํƒœ๋Š” ํ•„๋“œ(๋˜๋Š” ํ”„๋กœํผํ‹ฐ)๋กœ ํ‘œํ˜„๋˜๊ณ , ์—”ํ‹ฐํ‹ฐ๋Š” ์ตœ์†Œ 1๊ฐœ ์ด์ƒ์˜ @Id(PK)๋ฅผ ๊ฐ€์ ธ์•ผ ํ•œ๋‹ค.
  • @Table(name = "TEAM")
    • ์ด ์—”ํ‹ฐํ‹ฐ๊ฐ€ ๋งคํ•‘๋  ํ…Œ์ด๋ธ” ์ด๋ฆ„์„ TEAM์œผ๋กœ ์ง€์ •ํ•œ ๊ฒ๋‹ˆ๋‹ค. @Table์€ "์ด ์—”ํ‹ฐํ‹ฐ์˜ ๊ธฐ๋ณธ ํ…Œ์ด๋ธ”์ด ๋ฌด์—‡์ธ์ง€"๋ฅผ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค. (์ฐธ๊ณ ๋กœ @Table์„ ์•ˆ ์“ฐ๋ฉด ๊ธฐ๋ณธ ๊ทœ์น™์œผ๋กœ ํ…Œ์ด๋ธ”๋ช…์ด ๊ฒฐ์ •๋ฉ๋‹ˆ๋‹ค.)
  • @Id
    • id ํ•„๋“œ๊ฐ€ ๊ธฐ๋ณธ ํ‚ค(PK)๋ผ๋Š” ๋œป์ž…๋‹ˆ๋‹ค. ์—”ํ‹ฐํ‹ฐ๋ฅผ ๊ตฌ๋ถ„ํ•˜๋Š” ์‹๋ณ„์ž ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค.
  • @GeneratedValue
    • id ๊ฐ’์€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์ง์ ‘ ๋„ฃ๊ธฐ๋ณด๋‹ค, JPA/DB๊ฐ€ ์ž๋™ ์ƒ์„ฑํ•˜๋„๋ก ๋งก๊ธฐ๊ฒ ๋‹ค๋Š” ์˜๋ฏธ์ž…๋‹ˆ๋‹ค. @Id์™€ ๊ฐ™์ด ์“ฐ๋Š” PK ์ƒ์„ฑ ์ „๋žต ์ง€์ •์ž…๋‹ˆ๋‹ค.
  • private String name;
    • ๋ณ„๋„ ํ‘œ์‹œ๊ฐ€ ์—†์œผ๋ฉด ๊ธฐ๋ณธ์ ์œผ๋กœ DB ์ปฌ๋Ÿผ์œผ๋กœ ๋งคํ•‘๋˜๋Š” ์˜์† ํ•„๋“œ๋กœ ์ทจ๊ธ‰๋ฉ๋‹ˆ๋‹ค.(์˜์† ์ œ์™ธ๋Š” @Transient ๋“ฑ์œผ๋กœ ๋”ฐ๋กœ ํ‘œ์‹œ)

 

2) Member ์—”ํ‹ฐํ‹ฐ ์ฝ”๋“œ ํ’€์ด("๊ด€๊ณ„" ๋ถ€๋ถ„์ด ํ•ต์‹ฌ)

@Entity
@Table(name = "MEMBER")
public class Member {
    @Id @GeneratedValue
    private Long id;

    private String username;

    @ManyToOne
    @JoinColumn(name = "TEAM_ID") // MEMBER ํ…Œ์ด๋ธ”์— TEAM_ID(FK) ์ปฌ๋Ÿผ์ด ์ƒ๊น€
    private Team team;
    
    public void changeTeam(Team team) {
        this.team = team;
    }
}
  • private Team team;
    • ์—ฌ๊ธฐ์„œ ์ œ์ผ ์ค‘์š”ํ•œ ํฌ์ธํŠธ๋Š” teamId(Long)๊ฐ€ ์•„๋‹ˆ๋ผ Team “๊ฐ์ฒด ์ฐธ์กฐ”๋ฅผ ๋“ค๊ณ  ์žˆ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.
    • ์ฆ‰, ์ž๋ฐ” ์ฝ”๋“œ์—์„œ๋Š” “๋ฉค๋ฒ„๊ฐ€ ์–ด๋А ํŒ€์ธ์ง€”๋ฅผ ์ˆซ์ž FK๋กœ ๋“ค๊ณ  ์žˆ๋Š” ๊ฒŒ ์•„๋‹ˆ๋ผ Team ๊ฐ์ฒด๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋Š” ์ฐธ์กฐ๋กœ ํ‘œํ˜„ํ•ฉ๋‹ˆ๋‹ค.
  • @ManyToOne
    • “๋ฉค๋ฒ„ ์—ฌ๋Ÿฌ ๋ช…์ด ํ•˜๋‚˜์˜ ํŒ€์— ์†ํ•  ์ˆ˜ ์žˆ๋‹ค”๋Š” ์นด๋””๋„๋ฆฌํ‹ฐ(๋‹ค:1) ๋ฅผ ์„ ์–ธํ•œ ๊ฒ๋‹ˆ๋‹ค. ORM์ด ์ด ๊ด€๊ณ„๋ฅผ ์—”ํ‹ฐํ‹ฐ ์—ฐ๊ด€๊ด€๊ณ„๋กœ ์ธ์‹ํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.
  • @JoinColumn(name = "TEAM_ID")
    • ์ด ์—ฐ๊ด€๊ด€๊ณ„๋ฅผ DB์—์„œ ํ‘œํ˜„ํ•  ๋•Œ, MEMBER ํ…Œ์ด๋ธ”์— TEAM_ID๋ผ๋Š” ์กฐ์ธ ์ปฌ๋Ÿผ(=์™ธ๋ž˜ํ‚ค ์ปฌ๋Ÿผ)์„ ์“ฐ๊ฒ ๋‹ค๋Š” ๋œป์ž…๋‹ˆ๋‹ค. @JoinColumn ์ž์ฒด๊ฐ€ “์กฐ์ธ์„ ์œ„ํ•ด ์‚ฌ์šฉํ•  ์ปฌ๋Ÿผ”์„ ์ง€์ •ํ•˜๋Š” ์• ๋…ธํ…Œ์ด์…˜์ž…๋‹ˆ๋‹ค.
    • ๊ฒฐ๊ณผ์ ์œผ๋กœ DB์—์„œ๋Š” ๋Œ€๋žต ์ด๋Ÿฐ ๋ชจ์–‘์ด ๋ฉ๋‹ˆ๋‹ค.
      • TEAM(id PK, name, …)
      • MEMBER(id PK, username, TEAM_ID FK → TEAM.id)
  • “๊ทธ๋Ÿผ member.team = team ํ•˜๋ฉด DB์˜ TEAM_ID๋Š” ๋ˆ„๊ฐ€ ์ฑ„์›Œ์š”?”
    • Hibernate ๊ฐ™์€ JPA ๊ตฌํ˜„์ฒด๋Š” @ManyToOne ์—ฐ๊ด€๊ด€๊ณ„๊ฐ€ ์„ธํŒ…๋˜๋ฉด, ๊ทธ์— ๋งž๋Š” FK ์ปฌ๋Ÿผ ๊ฐ’์„ ์„ค์ •(๋™๊ธฐํ™”)ํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค.
    • ์ฆ‰, ์ฝ”๋“œ์—์„œ๋Š” member.team์„ ์„ธํŒ…ํ–ˆ๋Š”๋ฐ, ์ €์žฅ๋  ๋•Œ๋Š” DB์˜ MEMBER.TEAM_ID๊ฐ€ ์ฑ„์›Œ์ง€๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.
  • changeTeam(Team team) ๋ฉ”์„œ๋“œ
    • ์ด๊ฑด JPA ํ•„์ˆ˜ ๋ฌธ๋ฒ•์ด๋ผ๊ธฐ๋ณด๋‹ค๋Š”, ํŒ€ ๋ณ€๊ฒฝ์ด๋ผ๋Š” ํ–‰์œ„๋ฅผ ๋ฉ”์„œ๋“œ๋กœ ๋ฌถ์–ด์„œ ์บก์Аํ™”ํ•œ ๊ฒ๋‹ˆ๋‹ค. ๋‚˜์ค‘์— ์–‘๋ฐฉํ–ฅ ๊ด€๊ณ„๋กœ ํ™•์žฅ๋˜๋ฉด(Team์ด members ์ปฌ๋ ‰์…˜์„ ๊ฐ€์งˆ ๋•Œ) ์ด ๋ฉ”์„œ๋“œ ์•ˆ์—์„œ ์–‘์ชฝ์„ ํ•จ๊ป˜ ๋งž์ถ”๋Š” ์‹์œผ๋กœ “๊ด€๊ณ„ ์ผ๊ด€์„ฑ”์„ ์œ ์ง€ํ•˜๊ธฐ๋„ ์ข‹์•„์ง‘๋‹ˆ๋‹ค.

๐Ÿ’ก ์—ฌ๊ธฐ์„œ ๋งํ•˜๋Š” teamId๋Š” ๋ฌด์—‡์ผ๊นŒ?

teamId๋Š” ์ง€๊ธˆ ์—”ํ‹ฐํ‹ฐ ์ฝ”๋“œ์— "ํ•„๋“œ๋กœ ์กด์žฌํ•˜๋Š” ๊ฐ’"์ด ์•„๋‹ˆ๋ผ, DB ๊ด€์ ์—์„œ ๋งํ•˜๋Š” ์™ธ๋ž˜ํ‚ค(FK) ๊ฐ’์„ ์‰ฝ๊ฒŒ ๋ถ€๋ฅธ ํ‘œํ˜„์ž…๋‹ˆ๋‹ค.

 

1) ์ฝ”๋“œ์—์„œ “teamId ํ•„๋“œ”๋Š” ์—†์Œ

  • ํ•„๋“œ ์ด๋ฆ„: team(ํƒ€์ž…์€ Team)
  • ์–ด๋…ธํ…Œ์ด์…˜: @JoinColumn(name = "TEAM_ID")

์—ฌ๊ธฐ์„œ @JoinColumn(name="TEAM_ID")๋Š” “์ด ์—ฐ๊ด€๊ด€๊ณ„๋ฅผ DB์— ์ €์žฅํ•  ๋•Œ, MEMBER ํ…Œ์ด๋ธ”์˜ TEAM_ID ์ปฌ๋Ÿผ์„ ์กฐ์ธ ์ปฌ๋Ÿผ(์™ธ๋ž˜ํ‚ค ์ปฌ๋Ÿผ)์œผ๋กœ ์“ฐ๊ฒ ๋‹ค”๋Š” ๋œป์ด์ง€, ์ž๋ฐ” ํ•„๋“œ ์ด๋ฆ„์„ teamId๋กœ ๋งŒ๋“ค๊ฒ ๋‹ค๋Š” ๋œป์ด ์•„๋‹™๋‹ˆ๋‹ค.

 

2) ๊ทธ๋Ÿผ TEAM_ID(=teamId)๋Š” ์–ด๋””์— ์žˆ๋ƒ๋ฉด “DB ํ…Œ์ด๋ธ” ์ปฌ๋Ÿผ”์œผ๋กœ ์žˆ๋‹ค

์ž๋ฐ” ์ฝ”๋“œ์—์„œ๋Š” member.team์ด๋ผ๋Š” ๊ฐ์ฒด ์ฐธ์กฐ๋ฅผ ์„ธํŒ…ํ•˜์ง€๋งŒ, ์ €์žฅ๋  ๋•Œ๋Š” DB์— MEMBER.TEAM_ID = TEAM.ID ํ˜•ํƒœ๋กœ ๋“ค์–ด๊ฐ‘๋‹ˆ๋‹ค. ์ด๋•Œ ๊ทธ TEAM_ID ์ปฌ๋Ÿผ ๊ฐ’(=FK)์„ ํ”ํžˆ ๋ง๋กœ “teamId”๋ผ๊ณ  ๋ถ€๋ฅด๋Š” ๊ฒ๋‹ˆ๋‹ค.

 

3) teamId ๊ฐ’์„ ์ฝ”๋“œ์—์„œ ๋ณด๊ณ  ์‹ถ์œผ๋ฉด?

์—”ํ‹ฐํ‹ฐ์— teamId ํ•„๋“œ๊ฐ€ ์—†์œผ๋‹ˆ ๋ณดํ†ต์€ ์ด๋ ‡๊ฒŒ ๋ด…๋‹ˆ๋‹ค.

  • member.getTeam().getId() → “ํŒ€ ๊ฐ์ฒด์˜ id”, ์ฆ‰ DB์˜ TEAM_ID์— ๋“ค์–ด๊ฐ€๋Š” ๊ฐ’๊ณผ ๊ฐ™์€ ์˜๋ฏธ

์ •๋ฆฌํ•˜๋ฉด, teamId๋Š” ‘์ž๋ฐ” ํ•„๋“œ’๊ฐ€ ์•„๋‹ˆ๋ผ ‘DB์˜ ์™ธ๋ž˜ํ‚ค ์ปฌ๋Ÿผ ๊ฐ’’์„ ์˜๋ฏธํ•˜๋Š” ํ‘œํ˜„์ด๊ณ , JPA์—์„œ๋Š” ๊ทธ FK๋ฅผ ์ง์ ‘ ๋“ค๊ณ  ์žˆ๊ธฐ๋ณด๋‹ค Team team ์ฐธ์กฐ๋กœ ๊ด€๊ณ„๋ฅผ ๋ชจ๋ธ๋งํ•˜๋Š” ๊ฒŒ ๊ธฐ๋ณธ์ž…๋‹ˆ๋‹ค.

 

 

3) ์–‘๋ฐฉํ–ฅ ๋งคํ•‘์‹œ ์—ฐ๊ด€๊ด€๊ณ„์˜ ์ฃผ์ธ์— ๊ฐ’์„ ์ž…๋ ฅ

Team team = new Team();
team.setName("TeamA");

em.persist(team);

Member member = new Member();
member.setName("member1");
team.getMembers().add(member);

//์—ฐ๊ด€๊ด€๊ณ„์˜ ์ฃผ์ธ์— ๊ฐ’ ์„ค์ •
member.setTeam(team); //**

em.persist(member);

 

ํ•œ ์ค„ ์”ฉ ํ•ด์„ํ•ด๋ณด์ž

Team team = new Team();
team.setName("TeamA");

em.persist(team);
  • Team ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค๊ณ  ์ด๋ฆ„์„ ๋„ฃ์Šต๋‹ˆ๋‹ค. 
  • em.persist(team)๋กœ Team์„ ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ์— ๋“ฑ๋กํ•ด์„œ "์ €์žฅ ๋Œ€์ƒ"์œผ๋กœ ๋งŒ๋“ญ๋‹ˆ๋‹ค. (๋ณดํ†ต ์ปค๋ฐ‹/ํ”Œ๋Ÿฌ์‹œ ์‹œ์ ์— INSERT๊ฐ€ ๋‚˜๊ฐ‘๋‹ˆ๋‹ค.)
Member member = new Member();
member.setName("member1");
  • Member ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค๊ณ  ์ด๋ฆ„์„ ๋„ฃ์Šต๋‹ˆ๋‹ค. ์•„์ง ํŒ€๊ณผ์˜ ๊ด€๊ณ„๋Š” ์•ˆ ์žกํžŒ ์ƒํƒœ์ž…๋‹ˆ๋‹ค.
team.getMembers().add(member);
  • Team ์ชฝ ์ปฌ๋ ‰์…˜์—  member๋ฅผ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.
  • ๋‹ค๋งŒ Team.members๊ฐ€ mappedBy์ธ ๋ฐ˜๋Œ€ํŽธ(inverse side)์ด๋ผ๋ฉด, ์ด ์ค„์€ ๊ฐ์ฒด ๊ทธ๋ž˜ํ”„(๋ฉ”๋ชจ๋ฆฌ)์—์„œ๋งŒ ์—ฐ๊ฒฐ์„ ๋งŒ๋“  ๊ฒƒ์— ๊ฐ€๊น๊ณ , DB์˜ FK(TEAM_ID)๋ฅผ “๊ฒฐ์ •”ํ•˜๋Š” ์ฃผ์ฒด๋Š” ์•„๋‹™๋‹ˆ๋‹ค.
member.setTeam(team);  //**
  • ์ด ์ค„์ด ํ•ต์‹ฌ์ž…๋‹ˆ๋‹ค. Member.team์€ ๋ณดํ†ต @JoinColumn(TEAM_ID)๊ฐ€ ๋ถ™์€ ์—ฐ๊ด€๊ด€๊ณ„์˜ ์ฃผ์ธ(owning side) ์ด๊ณ , JPA๋Š” ์ด ์ชฝ ๊ฐ’์„ ๊ธฐ์ค€์œผ๋กœ MEMBER ํ…Œ์ด๋ธ”์˜ TEAM_ID(FK)๋ฅผ ์ฑ„์›๋‹ˆ๋‹ค.
  • ๊ทธ๋ž˜์„œ ํ™”๋ฉด์— "์–‘๋ฐฉํ–ฅ ๋งคํ•‘ ์‹œ ์—ฐ๊ด€๊ด€๊ณ„์˜ ์ฃผ์ธ์— ๊ฐ’์„ ์ž…๋ ฅํ•ด์•ผ ํ•œ๋‹ค"๋ผ๊ณ  ์ ํ˜€ ์žˆ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.
em.persist(member);
  • Member๋„ ์˜์† ์ƒํƒœ๋กœ ๋งŒ๋“ค๊ณ , ์ปค๋ฐ‹/ํ”Œ๋Ÿฌ์‹œ ๋•Œ ์ €์žฅ๋˜๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.
  • ๊ฒฐ๊ณผ์ ์œผ๋กœ DB์—๋Š” MEMBER.TEAM_ID = TEAM.ID ํ˜•ํƒœ๋กœ FK๊ฐ€ ๋“ค์–ด๊ฐ€๊ฒŒ ๋ฉ๋‹ˆ๋‹ค(์ฃผ์ธ ์ชฝ์„ ์„ธํŒ…ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์—).

JPA์—์„œ ์–‘๋ฐฉํ–ฅ ์—ฐ๊ด€๊ด€๊ณ„์˜ '์—ฐ๊ด€๊ด€๊ณ„ ์ฃผ์ธ'์€ ๋ฌด์—‡์„ ๊ธฐ์ค€์œผ๋กœ ๊ฒฐ์ •ํ•˜๋Š” ๊ฒƒ์ด ๊ฐ€์žฅ ์ค‘์š”ํ• ๊นŒ์š”?

์™ธ๋ž˜ ํ‚ค๊ฐ€ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ํ…Œ์ด๋ธ” ์–ด๋””์— ์œ„์น˜ํ•˜๋Š”์ง€๊ฐ€ ์—ฐ๊ด€๊ด€๊ณ„ ์ฃผ์ธ์„ ๊ฒฐ์ •ํ•˜๋Š” ํ•ต์‹ฌ ๊ธฐ์ค€์ž…๋‹ˆ๋‹ค. ๋ณดํ†ต N:1 ๊ด€๊ณ„์—์„œ N์ชฝ์— ์™ธ๋ž˜ ํ‚ค๊ฐ€ ์žˆ์œผ๋ฏ€๋กœ N์ชฝ์ด ์ฃผ์ธ์ด ๋ฉ๋‹ˆ๋‹ค.

 

JPA ์–‘๋ฐฉํ–ฅ ์—ฐ๊ด€๊ด€๊ณ„์—์„œ '์—ฐ๊ด€๊ด€๊ณ„ ์ฃผ์ธ'์˜ ์—ญํ• ์€ ๋ฌด์—‡์ผ๊นŒ์š”?

์—ฐ๊ด€๊ด€๊ณ„ ์ฃผ์ธ๋งŒ์ด ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์žˆ๋Š” ์™ธ๋ž˜ ํ‚ค์˜ ๊ฐ’์„ ๋ณ€๊ฒฝํ•˜๊ฑฐ๋‚˜ ๋“ฑ๋กํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ฃผ์ธ ์•„๋‹Œ ์ชฝ(mappedBy ์„ค์ •๋œ ๊ณณ)์€ ์™ธ๋ž˜ ํ‚ค ๊ฐ’์„ ์ฝ๊ธฐ๋งŒ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

 

JPA ์—ฐ๊ด€๊ด€๊ณ„๋ฅผ ์„ค๊ณ„ํ•  ๋•Œ ๊ถŒ์žฅ๋˜๋Š” ์ดˆ๊ธฐ ์ ‘๊ทผ ๋ฐฉ์‹์€ ๋ฌด์—‡์ผ๊นŒ์š”?

์ฒ˜์Œ๋ถ€ํ„ฐ ์–‘๋ฐฉํ–ฅ์œผ๋กœ ์„ค๊ณ„ํ•˜๋ฉด ๋ถˆํ•„์š”ํ•˜๊ฒŒ ๋ณต์žกํ•ด์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋‹จ๋ฐฉํ–ฅ์œผ๋กœ ์ถฉ๋ถ„ํžˆ ์„ค๊ณ„ํ•œ ํ›„, ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๊ฐœ๋ฐœ ์ค‘ ์—ญ๋ฐฉํ–ฅ ์กฐํšŒ๊ฐ€ ์ •๋ง ํ•„์š”ํ•  ๋•Œ ์–‘๋ฐฉํ–ฅ์„ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.

 

JPA ์–‘๋ฐฉํ–ฅ ์—ฐ๊ด€๊ด€๊ณ„๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ, Lombok์˜ toString()์ด๋‚˜ JSON ์ง๋ ฌํ™” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์‚ฌ์šฉ ์‹œ ์ฃผ์˜ํ•ด์•ผ ํ•  ๊ฐ€์žฅ ํ”ํ•œ ๋ฌธ์ œ๋Š” ๋ฌด์—‡์ผ๊นŒ์š”?

์–‘์ชฝ ์—”ํ‹ฐํ‹ฐ๊ฐ€ ์„œ๋กœ๋ฅผ ์ฐธ์กฐํ•˜๋Š” ๊ตฌ์กฐ ๋•Œ๋ฌธ์— toString์ด๋‚˜ JSON ๋ณ€ํ™˜ ์‹œ ์„œ๋กœ๋ฅผ ๋ฐ˜๋ณต์ ์œผ๋กœ ํ˜ธ์ถœํ•˜๋ฉฐ ๋ฌดํ•œํžˆ ์ˆœํ™˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์˜ค๋ฅ˜๋กœ ์ด์–ด์ง‘๋‹ˆ๋‹ค.

728x90

'๐Ÿš€ Growth > TIL' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

[TIL] Git๊ณผ GitHub  (0) 2026.04.02
[TIL] ๊ฐœ๋ฐœ ๊ธฐ๋ณธ ์šฉ์–ด  (0) 2026.04.01
[TIL] 2026๋…„ 01์›” 05์ผ  (0) 2026.01.05
[์Šคํ”„๋ง] 2025-07-02  (1) 2025.07.02
[TIL] 2024๋…„ 11์›” 14์ผ  (1) 2024.11.15