데이터와 보안 ·

기본키와 외래키로 두 데이터 표를 정확히 연결하는 법

먼저 답부터

기본키는 표 안에서 각 행을 중복 없이 가리키는 번호이고, 외래키는 다른 표의 기본키를 참조해 기록 사이의 관계를 만듭니다. 이름처럼 바뀌거나 겹치는 값 대신 키로 연결하면 고객과 주문을 정확히 찾을 수 있으며, 삭제 규칙은 데이터 손실 범위를 확인한 뒤 정해야 합니다.

기본키와 외래키로 두 데이터 표를 정확히 연결하는 법 대표 이미지

회원 이름과 주문 내역을 한 표에 모두 적으면 처음에는 편해 보입니다. 하지만 같은 사람이 여러 번 주문할 때 주소와 전화번호가 반복되고, 이름이 같은 두 사람을 구별하기 어려워집니다. 그래서 데이터베이스는 종류가 다른 기록을 여러 표로 나누고 번호로 연결합니다.

학교에서 학생 명단과 도서 대출 장부를 따로 두는 모습을 떠올려 보세요. 대출 장부에 학생 이름을 매번 적기보다 학생 번호를 적으면 동명이인도 구분됩니다. 기본키와 외래키는 이 학생 번호와 장부의 연결 칸에 가깝습니다.

기본키는 한 행의 고유한 이름표다

primary key는 기본키라는 뜻으로, 한 표 안에서 특정 행 하나를 고유하게 식별하는 열 또는 열의 묶음입니다. 기본키 값은 중복될 수 없고 비어 있을 수도 없습니다. 고객 표에서 customer_id를 기본키로 정하면 7번 고객은 항상 한 행만 가리킵니다.

CREATE TABLE customers (
  customer_id integer PRIMARY KEY,
  name text NOT NULL
);

NOT NULL은 값이 비어 있으면 안 된다는 제약 조건입니다. constraint, 즉 제약 조건은 잘못된 데이터가 표에 들어오지 않도록 데이터베이스가 확인하는 규칙입니다. 기본키 역시 고유성과 빈 값 금지를 함께 보장하는 제약입니다.

이름보다 변하지 않는 식별자를 쓴다

사람 이름, 이메일, 상품명은 겹치거나 바뀔 수 있습니다. 이런 값을 모든 연결의 기준으로 쓰면 이메일을 바꿀 때 여러 표를 함께 수정해야 하고, 오타로 다른 사람 기록이 섞일 수 있습니다. 화면에는 이름을 보여 주더라도 내부 연결은 별도 식별자를 사용하는 이유입니다.

식당에서 “김민지 손님 주문”보다 “주문 41번, 고객 7번”이라고 기록하면 같은 이름의 손님이 와도 헷갈리지 않습니다. 식별자는 사용자에게 의미 있는 순번일 수도 있고 시스템이 만든 값일 수도 있습니다. 어떤 방식을 고르든 공개 URL에서 연속 번호만 바꿔 다른 사람 자료를 볼 수 없도록 서버 권한 검사가 필요합니다.

외래키는 다른 표의 행을 가리킨다

foreign key는 외래키라는 뜻으로, 한 표의 값이 다른 표의 기본키나 고유한 값에 실제로 존재하도록 확인하는 제약입니다. 주문 표의 customer_id가 고객 표를 참조하면 존재하지 않는 고객 번호로 주문을 만들지 못하게 할 수 있습니다.

CREATE TABLE orders (
  order_id integer PRIMARY KEY,
  customer_id integer REFERENCES customers(customer_id),
  item_name text NOT NULL
);

이 구조에서 orders는 참조하는 표이고 customers는 참조되는 표입니다. 외래키는 두 표의 글을 자동으로 합쳐 저장하는 기능이 아닙니다. 유효한 연결만 허용하는 안전 난간에 가깝습니다.

JOIN은 연결된 두 표를 함께 읽는다

JOIN은 공통된 키를 기준으로 두 표의 행을 함께 읽는 방법입니다. 고객 이름과 주문 상품을 한 화면에 보여 주려면 두 표의 customer_id가 같은 행을 연결할 수 있습니다.

SELECT customers.name, orders.item_name
FROM customers
JOIN orders
  ON customers.customer_id = orders.customer_id;

ON 뒤에는 어떤 열끼리 같은지 연결 조건을 적습니다. 조건을 빠뜨리면 서로 관련 없는 모든 조합이 만들어져 결과가 크게 늘 수 있습니다. 처음에는 표 이름과 열 이름을 모두 적어 어느 장부의 칸인지 드러내는 편이 좋습니다.

일대다와 다대다는 행의 개수로 본다

고객 한 명이 주문을 여러 개 가질 수 있는 관계를 one-to-many, 즉 일대다 관계라고 부릅니다. 한 고객 행에 연결된 주문 행이 여러 개일 수 있다는 뜻입니다. 반대로 주문 하나도 여러 상품을 담고 상품 하나도 여러 주문에 들어간다면 두 방향 모두 여러 개인 다대다 관계입니다.

다대다는 보통 order_items처럼 연결 전용 표를 둡니다. 이 표에는 주문 번호, 상품 번호, 수량을 적습니다. 한 칸에 상품 번호 여러 개를 쉼표로 넣으면 검색과 제약 확인이 어려워지므로 각각 한 행으로 나눕니다.

  • 고객과 주문은 일대다 관계입니다.
  • 주문과 상품은 연결 표를 사이에 둔 다대다 관계가 될 수 있습니다.
  • 연결 표에도 중복을 막는 기본키나 고유 제약이 필요합니다.
  • 화면에 보이는 이름은 키를 이용해 JOIN한 결과입니다.
  • 관계 종류는 실제 업무 규칙을 먼저 확인하고 정합니다.

삭제 규칙은 편의보다 영향 범위를 먼저 본다

참조되는 고객을 지우려 할 때 연결된 주문을 어떻게 할지 정해야 합니다. 삭제를 거절할 수도 있고, 주문의 고객 값을 비울 수도 있고, 연결된 주문까지 함께 지우도록 설정할 수도 있습니다. CASCADE는 기준 행 변경을 관련 행에 연쇄 적용하는 선택인데, 편리하지만 예상보다 많은 기록을 지울 수 있습니다.

회원을 탈퇴시킨다고 결제와 세금 기록까지 즉시 지워도 되는 것은 아닙니다. 개인정보 삭제 요청, 법적 보관, 익명화, 고객 지원 기준을 함께 봐야 합니다. 삭제 규칙을 코드 한 줄의 취향으로 정하지 말고 데이터 소유자와 보관 정책을 문서화합니다.

키가 있어도 권한 검사는 따로 필요하다

외래키는 존재하지 않는 고객 번호를 막지만, 로그인한 사용자가 다른 사람의 주문 번호를 요청하는 것까지 막지는 않습니다. 데이터 무결성은 기록 사이의 모순을 줄이는 성질이고, 인가는 사용자가 해당 기록을 볼 권한이 있는지 확인하는 절차입니다.

브라우저에서 customer_id 입력칸을 숨기는 것만으로 보호되지 않습니다. 요청 주소나 개발자 도구에서 값이 바뀔 수 있으므로 서버가 현재 로그인 사용자와 주문 소유자를 매번 비교해야 합니다. 데이터베이스 연결 계정도 필요한 표와 작업만 허용하는 최소 권한을 사용합니다.

오늘 바로 해볼 작은 실습

종이에 두 장의 작은 표를 그리고 선으로 연결합니다.

  1. 고객 표에 customer_id와 name 열을 적습니다.
  2. 서로 이름이 같은 고객 두 명에게 다른 번호를 줍니다.
  3. 주문 표에 order_id, customer_id, item_name을 적습니다.
  4. 각 주문의 고객 번호에서 고객 표의 기본키로 선을 긋습니다.
  5. 존재하지 않는 고객 번호 99를 넣으면 왜 거절해야 하는지 씁니다.
  6. 고객 한 명을 지울 때 주문을 유지할지 함께 지울지 결정하지 말고 필요한 정책 질문을 세 개 적습니다.

운영 데이터에서 키 타입이나 삭제 규칙을 즉흥적으로 바꾸지 마세요. 기본키 변경, 외래키 추가, CASCADE 삭제는 잠금과 대량 변경을 만들 수 있습니다. 백업 파일이 있다는 말만 믿지 말고 복구 시험과 영향 행 수를 확인하며, 결제나 개인정보가 연결됐다면 담당자 승인 전 실행하지 않는 것이 안전합니다.

확인한 자료

함께 읽기

  • 환경변수와 API 키를 서랍과 금고처럼 구분하는 법

    환경변수는 주소나 실행 모드처럼 프로그램 밖에서 바꿀 설정을 담는 서랍이고, API 키는 외부 서비스 사용 권한을 가진 비밀번호에 가깝습니다. 비밀키는 브라우저 코드나 Git 저장소에 넣지 말고 서버의 비밀 저장소에서만 읽도록 해야 합니다.

  • 쿠키와 세션과 브라우저 저장소를 보관함 위치로 구분하기

    쿠키는 브라우저가 보관하며 조건에 맞는 서버 요청에 함께 보낼 수 있는 작은 값이고, 세션은 보통 서버가 로그인 상태를 보관하고 쿠키에는 연결용 식별자만 두는 방식입니다. localStorage는 같은 출처의 브라우저에 남지만 요청에 자동 첨부되지 않으므로 화면 설정에는 쓸 수 있어도 비밀키 저장소로 보면 안 됩니다.

  • SQL로 데이터를 만들고 찾고 고치고 지우는 첫 연습

    SQL은 데이터베이스에 말을 거는 문법입니다. INSERT는 새 행을 넣고 SELECT는 조건에 맞는 행을 읽으며 UPDATE는 기존 값을 고치고 DELETE는 행을 지웁니다. 변경 명령은 WHERE 조건이 빠지면 범위가 커질 수 있으므로 같은 조건을 SELECT로 먼저 확인해야 합니다.