인프런 커뮤니티 질문&답변

Heemok Son님의 프로필 이미지
Heemok Son

작성한 질문수

자바 ORM 표준 JPA 프로그래밍 - 기본편

테이블 설계 관련 문의 및 MongoDB JPA 관련

작성

·

622

0

안녕하세요 영한님,

며칠 전 복합키 관련 질문을 올렸고,  원하는 답변을 얻을 수 있었습니다.

그리고 추가 질문이 있어서 다시 문의드립니다.

1. 테이블 PK 관련..

설계를 진행하면서 사수 분 생각과 차이가 있어서 문의 드립니다.

고견 부탁 드립니다.

Member 라는 회원 정보 테이블의 경우 일반적으로 Member의 Id 값이 PK가 되지만

Group이라는 그룹 테이블의 경우 no나 id 등의 (1, 2, 3 등 순차적인 값)들이 PK가 될 것 같습니다.

허나 사수의 경우 no, id 같이 단순 의미(비즈니스적으로) 없는 컬럼을 두는 것보다

name(그룹명)과 reg_date(생성일자) 등의 컬럼을 PK(복합키)로 두자는 의견입니다.

질문의 요지는.. PK로 명확하지 않은 테이블의 경우 no 같은 순차값들을 PK로 두는 것이

JPA 개발 시(?) 복합키를 사용하지 않으니 조금 더 효율적이라 생각되는데,

굳이 no 같은 순차값을 가지는 PK를 두지 않고 필요한 컬럼에서 여러 컬럼을 복합키로 활용하는 것이 더 맞는건가요?

1) no와 같은 의미는 없는 컬럼이지만 PK 값을 가지는게 효율적이다.

2) 의미 없는 컬럼을 생성하지 않고 기존의 필수 컬럼을 복합키로 PK로 두는 것이 효율적이다.

JPA를 사용할 경우 복합키를 가지는 테이블의 경우 @IdClass 또는 @EmbeddedId를 써야 하더라구요.

즉, 해당 테이블에 PK클래스가 하나 더 있어야 하는 것 같은데..

고견 부탁 드립니다.

그리고...

Spring boot의 경우 Spring data?를 통해 MongoDB를 JPA로 사용할 수 있던데

스프링이 아닌 순수 자바 애플리케이션에서 MongoDB를 JPA로 활용할 수 있는 방법이 있을까요?

현재는 본 강의를 통해 PostgreSQL를 JPA로 활용하고 있는데, MongoDB 역시 사용하고 있어서 문의 드립니다.

Spring boot가 아닌 본 강의처럼 Java에서 MongoDB를 JPA를 써서 활용하고 싶습니다.

질문 내용이 두서없고 명확하게 이해가 안가실 수 있을텐데..

답변 부탁 드립니다.

감사합니다.

건상하세요!

답변 1

3

김영한님의 프로필 이미지
김영한
지식공유자

안녕하세요. Heemok Son님

사수분과의 충돌이라니!

(쉽지 않겠네요. 열려있는 사수분이길...)

자연 키 vs 대리 키(surrogate key)

이게 참 쉽지 않습니다^^!

우선 JPA를 사용하고 안하고를 떠나서, 이 부분은 근본적으로 관계형 데이터베이스 설계에 대한 내용입니다.

둘중에 어떤 방향으로 PK로 잡느냐는, 둘다 장점과 단점을 동시에 가지고 있기 때문에, 경험이 많이 필요합니다.

참고로 과거에는 자연 키를 잡는 방식으로 설계가 많이 진행되었지만, 이 방식은 한번 결정되면, 방향을 틀기가 참 어렵습니다. 요즘처럼 비즈니스가 급변하는 시기에는 대리 키 방식을 많이 선호합니다. 하나의 애플리케이션 안에서 한가지 방식을 꼭 고집할 필요는 없고, 같은 시스템이어도 그 안의 테이블 상황에 따라 방식을 혼합해도 됩니다.

추가로 저는 회원의 id도 PK로 잘 사용하지 않습니다. 왜냐하면 이 ID를 예를들어서 이메일로 했는데, 향후 이메일이 변경되면 정말 큰 고통을 당하겠지요. id도 정책이 변경되어서 통합 id 등의 개념이 생기면 연관된 테이블을 다 변경해야 합니다.

추가로 질문하신 MongoDB는 http://hibernate.org/ogm/ 이라는 것이 있는데, 저도 사용해보지 않아서, 권장해드리지는 않습니다^^

참고하시는데 도움이 되시라고, JPA 책 4.6.6 기본 키 매핑 정리에 나온 내용을 적어드리겠습니다.

권장하는 식별자 선택 전략

데이터베이스 기본 키는 다음 3가지 조건을 모두 만족해야 한다.

1. null값은 허용하지 않는다.

2. 유일해야 한다.

3. 변해선 안 된다.

테이블의 기본 키를 선택하는 전략은 크게 2가지가 있다.

•자연 키(natural key)

- 비즈니스에 의미가 있는 키

- 예: 주민등록번호, 이메일, 전화번호

•대리 키(surrogate key)

- 비즈니스와 관련 없는 임의로 만들어진 키, 대체 키로도 불린다. - 예: 오라클 시퀀스, auto_increment, 키생성 테이블 사용

자연 키보다는 대리 키를 권장한다

자연 키와 대리 키는 일장 일단이 있지만 될 수 있으면 대리 키의 사용을 권장한다. 예를 들어 자연 키인 전화번호를 기본 키로 선택한다면 그 번호가 유일할 수는 있지만, 전화번호가 없을 수도 있고 전화번호가 변경될 수도 있다. 따라서 기본 키로 적당하지 않다. 문제는 주민등록번 호처럼 그럴듯하게 보이는 값이다. 이 값은 null이 아니고 유일하며 변하지 않는다는 3가지 조건 을 모두 만족하는 것 같다. 하지만 현실과 비즈니스 규칙은 생각보다 쉽게 변한다. 주민등록번 호조차도 여러 가지 이유로 변경될 수 있다.

비즈니스 환경은 언젠가 변한다

나의 경험을 하나 이야기하겠다. 레거시 시스템을 유지보수할 일이 있었는데, 분석해보니 회원 테이블에 주민등록번호가 기본 키로 잡혀 있었다. 회원과 관련된 수많은 테이블에서 조인을 위 해 주민등록번호를 외래 키로 가지고 있었고 심지어 자식 테이블의 자식 테이블까지 주민등록 번호가 내려가 있었다. 문제는 정부 정책이 변경되면서 법적으로 주민등록번호를 저장할 수 없 게 되면서 발생했다. 결국 데이터베이스 테이블은 물론이고 수많은 애플리케이션 로직을 수정 했다. 만약 데이터베이스를 처음 설계할 때부터 자연 키인 주민등록번호 대신에 비즈니스와 관 련 없는 대리 키를 사용했다면 수정할 부분이 많지는 않았을 것이다.

기본 키의 조건을 현재는 물론이고 미래까지 충족하는 자연 키를 찾기는 쉽지 않다. 대리 키는 비즈니스와 무관한 임의의 값이므로 요구사항이 변경되어도 기본 키가 변경되는 일은 드물다. 대리 키를 기본 키로 사용하되 주민등록번호나 이메일처럼 자연 키의 후보가 되는 컬럼들은 필 요에 따라 유니크 인덱스를 설정해서 사용하는 것을 권장한다.

JPA는 모든 엔티티에 일관된 방식으로 대리 키 사용을 권장한다

비즈니스 요구사항은 계속해서 변하는데 테이블은 한 번 정의하면 변경하기 어렵다. 그런 면에 서 외부 풍파에 쉽게 흔들리지 않는 대리 키가 일반적으로 좋은 선택이라 생각한다.

Heemok Son님의 프로필 이미지
Heemok Son

작성한 질문수

질문하기