본문 바로가기
AI 리더의 시대

DB관계 설정, PK와FK로 이해하기

by woojoon 2025. 12. 15.
반응형

FK와 PK로 배우는 테이블 관계 설정 관련 이미지

 

 

관계형 데이터베이스의 핵심은 '관계'입니다. 여러 테이블에 분산된 데이터를 연결하여 의미 있는 정보를 만들어내는 것이 관계형 데이터베이스의 강점입니다. 그리고 이 관계를 가능하게 하는 핵심 요소가 바로 기본키(Primary Key, PK)와 외래키(Foreign Key, FK)입니다. PK와 FK를 제대로 이해하지 못하면 데이터베이스 설계와 SQL 작성 모두 어려움을 겪게 됩니다.

PK는 테이블에서 각 행을 고유하게 식별하는 열입니다. 마치 주민등록번호처럼 중복되지 않는 유일한 값으로, 수많은 데이터 중에서 특정 데이터를 정확하게 찾아낼 수 있게 해 줍니다. FK는 다른 테이블의 PK를 참조하는 열입니다. FK를 통해 테이블 간의 관계가 형성되고, 분산된 데이터를 하나로 연결할 수 있습니다. 쇼핑몰에서 주문 테이블이 고객 테이블을 참조하는 것이 대표적인 예입니다.

이 글에서는 PK와 FK의 개념부터 시작하여, 1:1, 1:N, N:M 관계를 구현하는 방법, 참조 무결성을 보장하는 제약조건 설정, 그리고 실전에서 주의해야 할 사항까지 상세히 다룹니다. 데이터베이스 초보자도 이해할 수 있도록 쉬운 예시와 함께 설명하고, 실제 SQL 코드로 직접 따라 해볼 수 있도록 구성했습니다. 이 가이드를 마치면 테이블 간의 관계를 자유자재로 설계하고 구현할 수 있게 될 것입니다.

기본키 PK로 만드는 테이블 신분증

기본키(Primary Key, PK)는 테이블에서 각 행(Row)을 고유하게 식별하는 열(Column)입니다. 학교에서 학번이 학생을 식별하고, 회사에서 사번이 직원을 식별하듯이, 데이터베이스에서는 PK가 각 데이터를 식별합니다. PK가 없으면 수백만 건의 데이터 중에서 특정 데이터를 정확하게 찾아내기 어렵습니다.

PK는 두 가지 필수 조건을 만족해야 합니다. 첫째, 유일성(Uniqueness)입니다. PK 값은 테이블 내에서 중복될 수 없습니다. 두 명의 학생이 같은 학번을 가질 수 없듯이, 두 개의 행이 같은 PK 값을 가질 수 없습니다. 둘째, NOT NULL입니다. PK 값은 비어 있을 수 없습니다. 모든 행에 반드시 PK 값이 존재해야 합니다. 이 두 조건 덕분에 PK만 알면 정확히 하나의 행을 특정할 수 있습니다.

PK를 선택할 때는 두 가지 방식이 있습니다. 자연키(Natural Key)는 데이터 자체에서 유일한 값을 PK로 사용합니다. 주민등록번호, 이메일 주소 등이 예시입니다. 하지만 자연키는 변경될 수 있고, 개인정보 이슈가 있을 수 있습니다. 대리키(Surrogate Key)는 의미 없는 일련번호를 PK로 사용합니다. AUTO_INCREMENT를 사용하여 자동으로 증가하는 숫자를 부여하는 방식입니다. 실무에서는 대리키 방식이 더 널리 사용됩니다.

PK 생성은 SQL의 CREATE TABLE 문에서 PRIMARY KEY 제약조건으로 지정합니다. 단일 열을 PK로 지정할 때는 열 정의 뒤에 PRIMARY KEY를 붙이면 됩니다. 여러 열을 조합한 복합키를 만들 때는 테이블 정의 마지막에 PRIMARY KEY (열 1, 열 2) 형태로 지정합니다. MySQL에서는 INT AUTO_INCREMENT PRIMARY KEY 조합이 가장 흔히 사용됩니다.

복합키(Composite Key)는 두 개 이상의 열을 조합하여 PK를 구성하는 방식입니다. 단일 열로는 유일성을 보장할 수 없을 때 사용합니다. 예를 들어, 수강 테이블에서 학생번호와 과목번호를 조합한 (학생번호, 과목번호)가 복합키가 될 수 있습니다. 같은 학생이 같은 과목을 중복 수강할 수 없다면 이 조합은 유일합니다. 복합키는 N:M 관계의 연결 테이블에서 자주 사용됩니다.

외래키 FK로 연결되는 테이블 관계

외래키(Foreign Key, FK)는 다른 테이블의 PK를 참조하는 열입니다. FK를 통해 테이블 간의 관계가 형성됩니다. FK를 가진 테이블을 자식 테이블, FK가 참조하는 PK를 가진 테이블을 부모 테이블이라고 합니다. 부모-자식 관계가 형성되면 두 테이블의 데이터를 연결하여 조회할 수 있습니다.

FK의 핵심 역할은 참조 무결성(Referential Integrity) 보장입니다. 참조 무결성이란 FK 값이 반드시 부모 테이블의 PK에 존재하는 값이어야 한다는 규칙입니다. 예를 들어, 주문 테이블의 고객번호 FK는 반드시 고객 테이블에 존재하는 고객번호여야 합니다. 존재하지 않는 고객번호로 주문을 생성하면 데이터베이스가 오류를 발생시킵니다. 이 덕분에 "누가 주문했는지 모르는 주문"이 생기는 것을 방지할 수 있습니다.

FK 생성은 FOREIGN KEY 제약조건으로 지정합니다. 기본 형식은 FOREIGN KEY (열이름) REFERENCES 부모테이블(PK열이름)입니다. FK 열의 데이터 타입은 참조하는 PK와 동일해야 합니다. PK가 INT라면 FK도 INT여야 합니다. FK 열의 이름은 PK와 같을 필요는 없지만, 관례적으로 같은 이름을 사용하면 관계를 파악하기 쉽습니다.

FK를 설정할 때 중요한 옵션이 ON DELETE와 ON UPDATE입니다. 부모 테이블의 데이터가 삭제되거나 수정될 때 자식 테이블을 어떻게 처리할지 정의합니다. CASCADE는 부모가 삭제되면 자식도 함께 삭제합니다. SET NULL은 부모가 삭제되면 자식의 FK를 NULL로 설정합니다. RESTRICT는 자식이 있으면 부모 삭제를 거부합니다. 비즈니스 요구사항에 따라 적절한 옵션을 선택해야 합니다.

FK 없이도 열 값으로 관계를 표현할 수 있지만, FK 제약조건을 설정하면 몇 가지 이점이 있습니다. 첫째, 참조 무결성이 데이터베이스 수준에서 자동으로 보장됩니다. 둘째, ERD 도구에서 관계를 자동으로 인식합니다. 셋째, 쿼리 최적화기가 관계 정보를 활용하여 더 효율적인 실행 계획을 세울 수 있습니다. 따라서 관계가 있는 테이블에는 FK 제약조건을 명시적으로 설정하는 것이 좋습니다.

1:1, 1:N, N:M 관계 이해

테이블 간의 관계는 세 가지 유형으로 분류됩니다. 1:1, 1:N, N:M 관계이며, 각각 구현 방식이 다릅니다. 어떤 관계인지 정확히 파악하고 적절한 방식으로 구현해야 데이터 무결성을 보장할 수 있습니다.

1:1 관계는 한 테이블의 한 행이 다른 테이블의 한 행과만 연결되는 관계입니다. 사용자와 프로필, 직원과 신분증 정보 등이 예시입니다. 1:1 관계는 두 가지 방식으로 구현할 수 있습니다. 첫째, 한쪽 테이블에 FK를 두고 UNIQUE 제약조건을 추가합니다. FK가 UNIQUE이면 같은 값이 중복될 수 없으므로 1:1이 보장됩니다. 둘째, 양쪽 테이블이 같은 PK를 공유합니다. 자식 테이블의 PK가 동시에 FK 역할을 하는 방식입니다.

1:N 관계는 가장 흔한 관계 유형입니다. 한 테이블의 한 행이 다른 테이블의 여러 행과 연결됩니다. 고객과 주문, 부서와 직원, 게시글과 댓글 등이 대표적입니다. 1:N 관계에서 FK는 항상 N쪽 테이블에 위치합니다. 주문 테이블에 고객번호 FK가 있는 식입니다. 한 고객이 여러 주문을 할 수 있으므로, 여러 주문 행에 같은 고객번호가 들어갈 수 있습니다.

N:M 관계는 양쪽 테이블 모두 여러 행과 연결될 수 있는 관계입니다. 학생과 수업, 상품과 태그, 사용자와 역할 등이 예시입니다. N:M 관계는 두 테이블만으로 직접 구현할 수 없습니다. 중간에 연결 테이블(Junction Table 또는 Bridge Table)을 만들어야 합니다. 연결 테이블에는 양쪽 테이블의 PK를 FK로 저장하며, 두 FK를 조합한 복합키가 연결 테이블의 PK가 됩니다.

N:M 관계의 구체적인 예를 봅시다. 학생 테이블(학생번호 PK)과 수업 테이블(수업번호 PK)이 있습니다. 수강 연결 테이블을 만들고, (학생번호 FK, 수업번호 FK)를 복합 PK로 설정합니다. 이렇게 하면 학생-수강은 1:N, 수업-수강도 1:N이 되어 결과적으로 학생-수업이 N:M 관계가 됩니다. 연결 테이블에는 추가 속성도 저장할 수 있습니다. 예를 들어 수강 성적, 수강 학기 등을 함께 저장할 수 있습니다.

실전에서 지키는 관계 설계 원칙

실전에서 PK와 FK를 설계할 때 몇 가지 주의사항이 있습니다. 먼저, 부모 테이블이 먼저 생성되어야 합니다. FK가 참조할 PK가 존재해야 FK를 만들 수 있기 때문입니다. 테이블 생성 순서가 중요합니다. 또한 데이터 삽입 시에도 부모 테이블에 먼저 데이터가 있어야 자식 테이블에 해당 FK 값을 넣을 수 있습니다.

식별 관계와 비식별 관계의 선택도 중요합니다. 식별 관계는 FK가 자식 테이블의 PK 일부가 되는 경우입니다. 주문상세 테이블에서 (주문번호, 상품번호)가 복합 PK이고 주문번호가 FK인 경우가 예시입니다. 비식별 관계는 FK가 PK가 아닌 일반 열인 경우입니다. 비식별 관계가 더 유연하고 관리가 쉬워 실무에서 많이 사용됩니다. 대부분의 테이블에 AUTO_INCREMENT PK를 두고 FK는 별도 열로 관리하는 방식이 일반적입니다.

FK 인덱스 설정도 놓치기 쉬운 부분입니다. FK 열에는 자동으로 인덱스가 생성되지 않는 DBMS도 있습니다(MySQL의 MyISAM 등). FK 열에 인덱스가 없으면 JOIN 성능이 크게 저하됩니다. FK를 생성할 때 해당 열에 인덱스도 함께 생성하는 것이 좋습니다. InnoDB 엔진은 FK 생성 시 자동으로 인덱스를 만들어줍니다.

삭제 정책 결정도 신중해야 합니다. ON DELETE CASCADE는 편리하지만 위험할 수 있습니다. 고객을 삭제하면 모든 주문이 함께 삭제되는 것이 바람직한지 고민해야 합니다. 대부분의 경우 ON DELETE RESTRICT나 SET NULL이 더 안전합니다. 또는 물리적 삭제 대신 '삭제 여부' 플래그를 사용하는 소프트 삭제(Soft Delete) 방식을 고려할 수도 있습니다.

마지막으로, 순환 참조를 피해야 합니다. A 테이블이 B를 참조하고, B가 C를 참조하고, C가 다시 A를 참조하는 구조는 데이터 삽입과 삭제가 복잡해집니다. 순환 참조가 불가피한 경우에는 FK를 NULL 허용으로 설정하거나, 트랜잭션을 활용하여 순서 문제를 해결해야 합니다.

PK와 FK는 관계형 데이터베이스의 기초이자 핵심입니다. 이 개념을 확실히 이해하면 테이블 설계, SQL 작성, 데이터 무결성 보장 모두 수월해집니다. 이 글에서 배운 내용을 바탕으로 실제 데이터베이스를 설계해 보세요. 간단한 쇼핑몰, 게시판, 회원 관리 시스템부터 시작하여 점점 복잡한 관계를 다루다 보면 어느새 데이터베이스 설계 전문가가 되어 있을 것입니다.

반응형