inflearn logo
강의

강의

N
챌린지

챌린지

멘토링

멘토링

N
클립

클립

로드맵

로드맵

지식공유

김영한의 실전 데이터베이스 - 설계 2편, 실무에서 반드시 마주치는 9가지 설계 패턴

다음으로

실제 FK제약조건을 설정하지 않는이유

30

오승환

작성한 질문수 1

0

안녕하세요 영한강사님! 좋은 강의 너무 잘들었습니다! 강의에는 없는 내용이긴한데요! 실무에서는 실제 FK제약조건을 설정하지 않더라구요. 선배님들은 확장성때문이라고 말씀해주시는데 이것말고도 다른 이유가 있는지 궁금합니다!

sql mysql dbms/rdbms 소프트웨어-설계 SQLD

답변 2

1

김영한

안녕하세요. 오승환님

모든 곳에서 다 FK를 빼고 사용하는 것은 아니고, 다음과 같은 이유로 FK를 빼는 경우들이 있습니다.

 

1. 운영이 불편함

배치, 데이터 이관, 테스트 셋업할 때 INSERT/DELETE 순서 맞춰야 하고, 조금만 꼬이면 제약 위반으로 실패합니다. FK 끄고 작업하는 일이 많아집니다.

2. 스키마 변경이 무거워짐

부모 테이블 구조 바꾸려면 자식 FK 드롭 → 작업 → 재생성하는 과정이 필요합니다.

3. 확장성 — DB 분리 대비

MSA로 쪼개면 DB 레벨 FK는 못 씁니다. 어차피 애플리케이션이 정합성을 책임져야 하니, 처음부터 그 구조로 갑니다.

 

하지만 트레이드오프를 고려해야 합니다.

FK를 빼면 운영 유연성과 확장성을 얻고, 대신 정합성 책임이 애플리케이션으로 넘어옵니다. 모든 검증 로직을 명확하게 애플리케이션 로직에서 책임져야 하는데, 시간이 지날수록 보통 잘 오염되고, 이상한 중복 데이터나, 자식이 반드시 필요한데 없는 경우가 발생합니다. 이 문제 때문에 또 방어 코드를 추가해야 하는 경우들도 생깁니다.

제가 추천하는 방법은 '기본적으로는 FK를 사용해 데이터 무결성을 보호하되, 시스템의 규모와 도메인 특성에 맞춰 유연하게 제거하는 것'입니다.

실무적인 관점에서 다음과 같이 접근해 보시길 권장합니다.

  • 정합성이 최우선인 코어 도메인 (결제, 정산 등): 데이터가 틀어질 때의 비즈니스 리스크가 매우 크므로 DB 레벨의 FK 제약조건을 굳건히 걸어두고 2중, 3중으로 보호하는 것이 좋습니다.

  • 대규모 트래픽 및 유연성이 필요한 도메인: 잦은 스키마 변경과 성능 최적화가 중요하거나, 향후 MSA 분리가 예상되는 서비스라면 FK를 물리적으로 제거하여 운영의 유연성을 확보합니다.

  • 논리적 관계 유지 및 보정 배치: DB에서 물리적인 제약조건CONSTRAINT)은 제거하더라도, ERD 상의 논리적 연관관계는 명확히 남겨두어야 합니다. JPA 같은 ORM을 사용한다면 애플리케이션 레벨에서 연관관계를 철저히 매핑하여 검증하고, 주기적으로 백그라운드 배치(Batch)를 돌려 고아 데이터나 정합성이 깨진 데이터를 모니터링하고 정리하는 안전장치를 함께 마련하는 것이 좋습니다.

결국 서비스 규모가 커지고 아키텍처가 복잡해질수록 무결성 유지의 책임은 DB에서 애플리케이션으로 넘어오게 됩니다. 현재 프로젝트의 단계, 트래픽 규모, 그리고 팀의 방어 코드 작성 역량을 종합적으로 고려하여 적절한 트레이드오프를 선택하시길 바랍니다.

감사합니다.

0

인프런 AI 인턴

안녕하세요, 인프런 AI 인턴입니다. 오승환님.

실제 실무에서 외래키(FK) 제약조건을 설정하지 않는 이유에 대해 궁금해 하시는군요. 외래키 제약조건 없이 설계를 하는 이유는 주로 성능과 설계의 유연성 때문입니다. 다음 링크들을 통해 관련 설명을 확인하실 수 있습니다:

  1. 외래키를 사용에 대해서

    • 이 게시물에서는 외래키가 없어도 JPA가 동작할 수 있으며, 외래키를 사용하지 않음으로써 데이터베이스 간의 관계를 더 유연하게 관리할 수 있음을 설명합니다.
  2. 서비스에서 외래 키 사용에 대해 질문 드립니다

    • 실무에서 왜 외래키를 사용하지 않는지에 대한 논의가 이루어지며, 외래키 없이도 필드 수준에서 관계를 유지하는 방법 및 이점에 대해 설명합니다.

데이터베이스에서 외래키 제약조건을 사용하지 않으면, 데이터 무결성을 보장하기 위해 프로그래밍 측면에서의 추가적인 관리가 필요한 반면, 성능상의 이점과 설계적 유연성을 확보할 수 있다는 장점도 있습니다. 외래키 없이도 연관 관계를 유지할 경우, 업데이트나 삭제 시 다른 테이블에 영향을 미치지 않기 때문에 설계가 유연해질 수 있습니다.

저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다.
현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏
추가적으로 궁금한 점이 있으시면 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.

히스토리 관련 질문

0

57

2

통계 데이터 수정 질문

1

63

2

공통 코드에서 Redis Pub/Sub은 최근 실무에서 쓰이진 않나요?

0

133

2

DELETE -> SELECT 질문 드립니다.

0

48

1

상속 관계 모델링의 적용 기준 질문

0

75

1

TTL 캐싱에 대한 질문

0

78

1

공통 코드 사용시 컬럼 타입 설정

0

83

1

history_creted_at과 valid_from

1

65

2

함수 기반 인덱스 (Function-Based Index)

0

68

1

추후 강의 질문있습니다

0

124

2

실무 통계 질문(고민) 드립니다..!

0

91

2

Json 컬럼의 객체 맵핑

0

64

1

[Deprecated] 오타 제보

0

86

1

오타 제보

0

73

2

category_path 테이블에서 idx_descendant 인덱스를 생성하는 이유가 궁금합니다

0

96

2

물리적으로 외래 키 제약 조건을 설정하지 않을 때

0

97

1

`전체 행 스냅샷 이력 테이블`의 대상 테이블 칼럼 변경

1

84

1

common_code_detail의 code 변경 가능성

1

112

1

[해결책 - 코드값 분리] 중 orders(order_status) - common_code(code) 타입 불일치 제보

0

87

1

이미 문자열 타입인 컬럼을 캐스팅하는 이유

0

106

2

계층 구조 모델링 기타 방법들

0

106

1

섹션 9의 퀴즈가 영어로 출력되요.

0

106

2

섹션 6 SOFT DELETE) UNIQUE 제약 조건 + 가상 컬럼

0

77

1

섹션2 공통 코드) 애플리케이션 ENUM을 API에 그대로 노출한다면?

0

126

1