1. ๊ฐ์
๊น์ํ ๊ฐ์ฌ๋์ ๊ฐ์๋ฅผ ๋ค์ผ๋ฉฐ ์น ๊ฐ๋ฐ์ ๊ณต๋ถํ๊ธฐ ์์ํ ์ดํ, ๊ธฐ๋ณธ ํค ์ ๋ต์ ์ค์ ํ ๋ ํญ์ ์ธ์กฐํค๋ฅผ ์ฌ์ฉํด์๋ค.
ํน๋ณํ ์ด์ ๋ฅผ ๊ณ ๋ฏผํด๋ณด์ง ์๊ณ ์ต๊ด์ ์ผ๋ก ์ธ์กฐํค๋ฅผ ์ ํํด์๋๋ฐ, ์ต๊ทผ ์ฝ๋ ๋ฆฌ๋ทฐ ์ค์ "์ด๋ฏธ ๊ณ ์ ํ ๊ฐ์ด ์กด์ฌํ๋๋ฐ, ์ ๊ตณ์ด ๋ณ๋์ ์ปฌ๋ผ์ ์ถ๊ฐํด ์ธ์กฐํค๋ฅผ ์ฌ์ฉํ๋๋"๋ ์ง๋ฌธ์ ๋ฐ๊ฒ ๋์๋ค.
ํ ๋ฒ๋ ๊น์ด ์๊ฐํด๋ณธ ์ ์๋ ๋ถ๋ถ์ด์๊ธฐ์, ์ด๋ฒ ๊ธฐํ์ ์์ฐํค์ ์ธ์กฐํค์ ์ฅ๋จ์ ์ ๋น๊ตํด๋ณด๊ณ , ์ด๋ค ํค๋ฅผ ์ ํํ๋ ๊ฒ์ด ๋ ์ข์์ง ์ ๋ฆฌํด๋ณด๋ ค ํ๋ค.
2. ์์ฐํค? ์ธ์กฐํค?
์์ฐํค๋ ๋น์ฆ๋์ค ๋ชจ๋ธ์์ ์์ฐ์ค๋ฝ๊ฒ ๋์ค๋ ์์ฑ์ด๋ค.
ํ์ ๋ฐ์ดํฐ๋ฅผ ์๋ก ๋ค๋ฉด, ํ์ ID๋ ๊ณ ์ ํ ๊ฐ์ด๋ฉฐ ๋ณ๊ฒฝ๋ ๊ฐ๋ฅ์ฑ์ ๊ฑฐ์ ์๋ค. ๋ํ ์ฃผ๋ฏผ๋ฑ๋ก๋ฒํธ๋ ๊ณ ์ ํ ๊ฐ์ผ๋ก ์์ฐํค์ ํ ์๊ฐ ๋ ์ ์๋ค.
์ธ์กฐํค๋ ๋น์ฆ๋์ค ๋ชจ๋ธ๊ณผ ๋ฌ๋ฆฌ ์ค๋ก์ง uniqueํจ์ ๋ณด์ฅํ๊ธฐ ์ํด์ ์ธ์กฐ์ ์ผ๋ก ๋ง๋ ์์ฑ์ด๋ค.
์๋ฅผ ๋ค๋ฉด UUID, Auto Increment๊ฐ ์ด์ ํด๋นํ๋ค.
3. ์์ฐํค๋ฅผ ์ฌ์ฉํ์ ๋ ๋ฌธ์ ์
์์ฐํค๋ฅผ ๊ธฐ๋ณธํค(PK)๋ก ๋์์ ๊ฒฝ์ฐ ๋ฐ์ํ๋ ๋ฌธ์ ์ ๋ค์ ๋ค์๊ณผ ๊ฐ๋ค.
1. ๋ณ๊ฒฝ ๊ฐ๋ฅ์ฑ์ ๋ฐฐ์ ํ ์ ์๋ค.
๊ณผ๊ฑฐ์๋ ์ฃผ๋ฏผ๋ฑ๋ก๋ฒํธ๋ฅผ ๊ธฐ๋ณธ ํค๋ก ๋๋ ๊ธฐ์ ์ด ๋ง์๋ค. ์ฃผ๋ฏผ๋ฑ๋ก๋ฒํธ๋ ๋ชจ๋ ์ฌ๋๋ค์๊ฒ ๋ฐ๋์ ๋ถ์ฌ๋๋ฉฐ(NOT NULL), ์ ์ผํ๊ณ (UNIQUE), ์ ๋ ๋ณํ์ง ์๊ธฐ ๋๋ฌธ์ ์ ํฉํด ๋ณด์๋ค.
ํ์ง๋ง, ์ ๋ถ ์ ์ฑ ์ด ๋ณ๊ฒฝ๋๋ฉด์ ์ฃผ๋ฏผ๋ฑ๋ก๋ฒํธ๋ฅผ ๋ฒ์ ์ผ๋ก ์ ์ฅํ ์ ์๊ฒ ๋์๋ค. ์ด๋ก ์ธํด ๋ง์ ์ฃผ๋ฏผ๋ฑ๋ก๋ฒํธ๋ฅผ PK๋ก ์ฌ์ฉํ๋ ๋ง์ ๊ธฐ์ ๋ค์ด ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ๊ตฌ์ฑ์ ๋ณ๊ฒฝํด์ผ๋ง ํ๋ค.
์ด๋ฌํ ๋ณ๊ฒฝ์ ๊ธฐ๋ณธ ํค๋ฅผ ๋ณ๊ฒฝํ๋ ๋จ์ํ ๋ฒ๊ฑฐ๋ก์ด ์์ ์ด ๋ ๋ฟ๋ง ์๋๋ผ, ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฑ๋ฅ์๋ ์ ์ํฅ์ ๋ฏธ์น๊ฒ ๋๋ค. MySQL๊ณผ ๊ฐ์ด ๊ธฐ๋ณธ ํค๊ฐ ๋ ์ฝ๋์ ๋ฌผ๋ฆฌ์ ์ ์ฅ ์์น๋ฅผ ๊ฒฐ์ ํ๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค์์ ๊ทธ ์ํฅ์ด ๋์ฑ ํฌ๋ค.
MySQL์์๋ PK๊ฐ ๋ ์ฝ๋์ ๋ฌผ๋ฆฌ์ ์ธ ์ ์ฅ ์์น๋ฅผ ๊ฒฐ์ ํ๊ธฐ ๋๋ฌธ์, ์ธ๋ฑ์ค๋ PK์ ์์กดํ๋ค. ๊ทธ๋์ผ ์ธ๋ฑ์ค๋ฅผ ํ๊ณ ๋ค์ด์์ PK๋ฅผ ํตํด ์ ์ฅ๋ ์์น์์ ๋ ์ฝ๋๋ฅผ ์ฝ์ด์ฌ ์ ์๊ธฐ ๋๋ฌธ์ด๋ค.
PK๊ฐ ๋ณ๊ฒฝ๋๋ค๋ ๊ฒ์ ๋ ์ฝ๋์ ๋ฌผ๋ฆฌ์ ์ธ ์ ์ฅ ์์น๊ฐ ๋ฐ๋์ด์ผ ํจ์ ์๋ฏธํ๋ฉฐ, ์ด๋ ์ธ๋ฑ์ค๊น์ง ์ฌ๊ตฌ์ฑํ๋๋ก ์ํฅ์ ์ค๋ค. ์ด๋ ์์ฒญ๋ ๋์คํฌ ์์ ์ ํ์๋ก ํ๋ค.
๋น์ฆ๋์ค ์์ญ์์ ์ ๋์ ์ผ๋ก ๋ณํ์ง ์๋ ๊ฒ์ ์๋ค
2. ์ฑ๋ฅ ๋ฌธ์ ๋ก ์ด์ด์ง๋ค.
PK๋ฅผ ๋์ฒดํค๋ก ์ฌ์ฉํ๊ฒ ๋๋ฉด ์ผ๋ฐ์ ์ผ๋ก ์๋ ์ฆ๊ฐ ์ซ์๋ฅผ ์ฌ์ฉํ๊ฒ ๋๋ฏ๋ก ์ฑ๋ฅ์ ํฅ์์ํฌ ์ ์๋ค. ๋ฐ๋๋ก ์์ฐํค๋ฅผ PK๋ก ์ฌ์ฉํ๋ ๊ฒฝ์ฐ ์ผ๋ฐ์ ์ผ๋ก ๋ฌธ์์ด๋ก ์ฌ์ฉ๋๋ฉฐ, ์ฌ์ง์ด ๋ณตํฉํค๋ก ๊ตฌ์ฑ๋๋ ๊ฒฝ์ฐ๊ฐ ๋ง์๋ฐ, ์ด๋ PK๋ฅผ ๋น๋ํ๊ฒ ๋ง๋ค์ด ์ฑ๋ฅ์ ์ข์ง ๋ชปํ๋ค.
๋น์ฆ๋์ค์ ๊ด๋ จํ๋ PK ๊ฐ์ ์๋ ์ฆ๊ฐํ๋ ์ ๋ต์ ๊ฐ๋ ์ธ์กฐํค๋ฅผ PK๋ก ๋์์ ๋ ๋ณด๋ค ํจ์ฌ ํฐ ๊ฐ์ ๊ฐ๋ ๊ฒฝ์ฐ๊ฐ ๋ง๋ค. ์ฃผ๋ฏผ๋ฑ๋ก๋ฒํธ์ ๊ฐ์ ๋ฌธ์์ด์ ๋จ์ ์ซ์๋ณด๋ค ํจ์ฌ ๋ฐ์ดํฐ๊ฐ ํฌ๋ฉฐ, ์ฌ์ง์ด ๋ณตํฉํค๋ก ๊ตฌ์ฑ๋ ๊ฒฝ์ฐ PK์ ํฌ๊ธฐ๋ ํจ์ฌ ๋น๋ํด์ง๋ค.
์ผ๋ฐ์ ์ผ๋ก PK์ ํฌ๊ธฐ๋ ์์์๋ก ์ข์ผ๋ฉฐ, ์์ํ์ ์ผ์๋ก ์ข๋ค.
์๋ ๋ด์ฉ์ RealMySQL์์ 5๊ฐ์ ์ธ๋ฑ์ค๋ฅผ ๊ฐ๋ ํ ์ด๋ธ์ ๊ธฐ๋ณธ ํค(Primary Key) ํฌ๊ธฐ์ ๋ฐ๋ฅธ ์ธ๋ฑ์ค ํฌ๊ธฐ ๋น๊ต๋ฅผ ๋ณด์ฌ์ค๋ค.
๋ ์ฝ๋ ํ ๊ฑด๋น ์ฝ 50๋ฐ์ดํธ์ ์ฐจ์ด๋ ๋ฏธ๋ฏธํด ๋ณด์ด์ง๋ง, ๋ ์ฝ๋ ๊ฑด์๊ฐ 100๋ง ๊ฑด์ด ๋๋ฉด ์ธ๋ฑ์ค ํฌ๊ธฐ๋ 190MB๋ ์ฆ๊ฐํ๊ฒ ๋๋ค.
๋ง์ฝ ๋ ์ฝ๋ ๊ฑด์๊ฐ 1000๋ง ๊ฑด์ด ๋๋ฉด ๊ทธ ์ฐจ์ด๋ ๋ฌด๋ ค 1.9GB๊น์ง ์ฆ๊ฐํ๋ค. ์ธ๋ฑ์ค์ ํฌ๊ธฐ๊ฐ ์ปค์ง์๋ก ๋์ผํ ์ฑ๋ฅ์ ์ ์งํ๊ธฐ ์ํด ๋ ๋ง์ ๋ฉ๋ชจ๋ฆฌ๊ฐ ํ์ํ๊ฒ ๋๋ค. ๋ฐ๋ผ์ ๊ธฐ๋ณธ ํค์ ํฌ๊ธฐ๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฑ๋ฅ์ ์ง์ ์ ์ธ ์ํฅ์ ๋ฏธ์น๊ธฐ ๋๋ฌธ์ ์ ์คํ๊ฒ ์ ํํด์ผ ํ๋ค.
3. ๋ณต์กํ ํ ์ด๋ธ ๊ตฌ์กฐ์ ๊ฐ๋ฐ ๋์ด๋ ์์น
์์ฐํค๋ฅผ PK๋ก ์ฌ์ฉํ๊ฒ ๋๋ฉด 1๊ฐ์ ์ปฌ๋ผ๋ง์ผ๋ก PK๋ฅผ ๊ตฌ์ฑํ์ง ๋ชปํ๊ณ ๋ณตํฉํค๋ฅผ ์ฌ์ฉํด์ผ ํ๋ ๊ฒฝ์ฐ๊ฐ ๋น๋ฒํ๊ฒ ๋ฐ์ํ๋ค.
๋ง์ฝ ๋ณตํฉํค๋ฅผ ๊ฐ๋ ํ ์ด๋ธ๊ณผ ์ฐ๊ด๊ด๊ณ๋ฅผ ๋งบ์ด์ผ ํ๋ค๋ฉด ๋ณตํฉํค๋ฅผ ์ ๋ถ ์ธ๋ํค๋ก ๊ฐ๊ณ ์์ด์ผ ํ๊ณ ์ด๋ ํ ์ด๋ธ ๊ตฌ์กฐ์ ๊ด๋ จ ์ฝ๋๋ฅผ ๋ณต์กํ๊ฒ ๋ง๋ ๋ค.
๋ณตํฉํค๋ฅผ PK๋ก ๊ฐ๋ ํ ์ด๋ธ๊ณผ ๊ด๊ณ๋ฅผ ๋งบ๋ ํ ์ด๋ธ์ด๋ผ๋ฉด ํด๋น ๋ณตํฉํค๋ฅผ ๋ค๋ฅธ ํ ์ด๋ธ๋ ๊ฐ์ ธ์ผ ํ๋ค. ์๋ฅผ ๋ค์ด (์๋ ์์ผ, ์ด๋ฆ, ์ฑ๋ณ)์ PK๋ก ๊ฐ๋ ์ฌ์ฉ์ ํ ์ด๋ธ์ด ์๋ค๊ณ ํ์. ๊ทธ๋ฌ๋ฉด ํด๋น ํค๊ฐ ์ฌ์ฉ์๋ฅผ ์๋ณํ ์ ์๋ ํค์ด๋ฏ๋ก ๋ฌด๊ฒฐ์ฑ์ ์ํด ์ฌ์ฉ์ ์ฃผ๋ฌธ ๋ด์ญ ํ ์ด๋ธ์๋ (์๋ ์์ผ, ์ด๋ฆ, ์ฑ๋ณ) ์ปฌ๋ผ์ ๋์ผํ๊ฒ ๊ฐ์ ธ์ผํ๋ ๊ฒ์ด๋ค.
JPA์์ ๋ณตํฉํค๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํด์ @Embeddable, @EmbeddedId๋ฅผ ์ฌ์ฉํ๊ฑฐ๋, @IdClass๋ฅผ ์ฌ์ฉํด์ผ ํ๋ค.
์๋ ์์ ์ฝ๋๋ @Embeddable, @EmbeddedId ๋ฅผ ์ฌ์ฉํ์ฌ ๋ณตํฉํค๋ฅผ ์ฌ์ฉํ๋ ๋ชจ์ต์ด๋ค.
@Embeddable
public class CompositeKey implements Serializable {
private String keyPart1;
private Long keyPart2;
// equals()์ hashCode() ๋ฐ๋์ ๊ตฌํ
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
CompositeKey that = (CompositeKey) o;
return Objects.equals(keyPart1, that.keyPart1) &&
Objects.equals(keyPart2, that.keyPart2);
}
@Override
public int hashCode() {
return Objects.hash(keyPart1, keyPart2);
}
@Entity
public class MyEntity {
@EmbeddedId
private CompositeKey id;
private String someValue;
}
}
๋ง์ฝ MyEntity์ ์ฐ๊ด๊ด๊ณ๋ฅผ ๋งบ๋ ์ํฐํฐ๊ฐ ์๋ค๋ฉด ์๋์ ๊ฐ์ ๋ฐฉ์์ผ๋ก ์ธ๋ํค๋ฅผ ์ค์ ํด์ค์ผ ํ๋ค.
import jakarta.persistence.*;
@Entity
public class ChildEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToOne
@JoinColumns({
@JoinColumn(name = "parent_key_part1", referencedColumnName = "keyPart1"),
@JoinColumn(name = "parent_key_part2", referencedColumnName = "keyPart2")
})
private MyEntity parent; // ๋ถ๋ชจ ํ
์ด๋ธ์ ๋ณตํฉํค ์ฐธ์กฐ
private String childValue;
public ChildEntity(MyEntity parent, String childValue) {
this.parent = parent;
this.childValue = childValue;
}
}
4. ๋ฌด๊ฒฐ์ฑ ๋ณด์ฅ์ ์ํ
๋์ฒดํค๋ฅผ ์ฌ์ฉํ๋ค๋ ๊ฒ์ ํค์ ์์ฑ ๋ฐ ๊ด๋ฆฌ๋ฅผ ์์ ํ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์์ํ๋ค๋ ๊ฒ์ด๋ค. ๋ฐ๋ฉด์ ์์ฐํค๋ฅผ ์ฌ์ฉํ๋ค๋ ๊ฒ์ ์ ํจ์ฑ ๊ฒ์ฌ์ ๋ฐ์ดํฐ์ ๋ฌด๊ฒฐ์ฑ ๋ฑ์ ๊ฐ๋ฐ์๊ฐ ์ง์ ๊ด๋ฆฌํ๋ค๋ ๊ฒ์ธ๋ฐ, ์๋ฌด๋๋ ์ฌ๋์ด ์ง์ ๊ด๋ฆฌํ๋ ๊ฒ ๋ณด๋ค๋ ์์คํ ์ ํตํด ์ด๋ฅผ ์์ํ๋ ๊ฒ์ด ์์ ์ ์ด๋ค.
์ธ์กฐํค๋ฅผ ์ฌ์ฉํ ๊ฒฝ์ฐ, ์ผ๊ด๋ ๋ฐฉ์์ผ๋ก ํค๋ฅผ ์์ฑ ๋ฐ ๊ด๋ฆฌํ์ฌ ๋ฐ์ดํฐ์ ๋ฌด๊ฒฐ์ฑ์ ๋ณด์ฅํ ์ ์๋ค.
4. ๊ฒฐ๋ก
JPA๋ ์ผ๊ด์ฑ์๊ฒ ํญ์ ์ธ์กฐ ํค๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ ๊ถ์ฅํ๋ค. ๊ทธ ์ธ์๋ PK๊ฐ ์ฃผ๋ฏผ๋ฒํธ์ ๊ฐ์ ๊ฐ์ธ ์ ๋ณด๋ผ๋ฉด ์ ์ถ ์ํ ๋ฑ์ ๋ถ์์ ์ธ ๋ฌธ์ ๊ฐ ์์ด์ ๊ฐ๊ธ์ ์ด๋ฉด ์ธ์กฐ ํค๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด ์์ฆ์ ์ถ์ธ์ด๋ค.
์ง๊ธ๊น์ง๋ ์ธ์กฐํค๋ฅผ ๋น์ฐํ๊ฒ ์ฌ์ฉํด์์ง๋ง, ์๊ณ ์ฐ๋ ๊ฒ๊ณผ ๋ชจ๋ฅด๊ณ ์ฐ๋ ๊ฒ์ ์ฒ์ง์ฐจ์ด์ด๋ค.
์? ์ ๋ํ ์ง๋ฌธ์ ๋์ง๋ฉฐ, ๋ ๊น์ด ๊ณ ๋ฏผํ๊ณ ์๊ฐํ๋ฉฐ ๊ฐ๋ฐํด ๋๊ฐ์ผ๊ฒ ๋ค.
'DB ๐' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[replication] mysql Replication ์ผ๋ก DB ๋ถํ ๋ถ์ฐ ์ํค๊ธฐ (0) | 2024.04.11 |
---|---|
[Neo4j] Graph Database๋? RDBMS์ ๋น๊ต, neo4j ๋์ ์ด์ (1) | 2024.03.27 |
[Redis] redis์์ ๋ฐ์ดํฐ ์๊ตฌ ์ ์ฅํ๋ ๋ฐฉ๋ฒ (RDB / AOF) (0) | 2024.03.09 |
[Lock] DB Lock & JPA Lock ์ฝ๋๋ก ์ดํด๋ณด์ (MySQL) (0) | 2024.02.20 |
[Index] MySQL ์ฑ๋ฅ ์ต์ ํ (+์คํ ๊ณํ) (0) | 2024.02.19 |