조금만 더 nerd하게 가보자. MANY-TO-MANY 구조 만드는 과정을 단계별로 찬찬히 살펴볼게. 준비됐지?
학생과 강의 사이의 MANY-TO-MANY 관계는 한 테이블로 바로 표현할 수 없어. 한 학생이 여러 강의를 들을 수 있고, 한 강의에 여러 학생이 동시에 등록될 수 있으니까.
이 문제를 해결하려고 우리는 중간 테이블 enrollments를 만들어. 이 테이블은 등록 정보를 저장해, 즉 어떤 학생-강의 쌍이 있는지 알려주는 거지. 이렇게 하면 데이터 무결성도 보장되고, 예를 들어 등록 날짜 같은 기능도 쉽게 추가할 수 있어.
enrollments 테이블은 어떻게 생겼을까?
이미 알겠지만, enrollments 테이블은 students랑 courses 테이블을 연결하는 중심 허브야. 구조는 이래:
CREATE TABLE enrollments (
enrollment_id SERIAL PRIMARY KEY, -- 유니크한 ID 레코드
student_id INT REFERENCES students(student_id), -- students 테이블의 외래 키
course_id INT REFERENCES courses(course_id), -- courses 테이블의 외래 키
enrollment_date DATE DEFAULT CURRENT_DATE -- 학생이 강의에 등록된 날짜
);
각 줄을 하나씩 볼게:
enrollment_id: 각 레코드의 유니크한 식별자야. 강의에 등록된 학생마다 고유하게 구분해야 하니까.student_id: 어떤 학생이 등록됐는지 알려줘.students테이블(student_id컬럼)에 연결된 외래 키야.course_id: 어떤 강의에 등록됐는지 알려줘. 이 컬럼은courses테이블(course_id컬럼)과 연결돼 있어.enrollment_date: 등록 날짜를 보여주는 유용한 추가 정보야.DEFAULT CURRENT_DATE를 써서 레코드 만들 때 자동으로 오늘 날짜가 들어가게 했어.
students랑 courses 테이블 만들기
다음 단계로 가기 전에, students랑 courses 테이블이 이미 있는지 확인하자:
CREATE TABLE students (
student_id SERIAL PRIMARY KEY, -- 학생의 유니크한 식별자
name TEXT NOT NULL, -- 학생 이름
email TEXT NOT NULL UNIQUE -- 학생 이메일, 중복 방지
);
CREATE TABLE courses (
course_id SERIAL PRIMARY KEY, -- 강의의 유니크한 식별자
title TEXT NOT NULL, -- 강의 제목
description TEXT, -- 강의 설명
start_date DATE -- 강의 시작 날짜
);
여기서 학생 이메일을 유니크하게 하고, courses 테이블에 강의 설명을 추가하는 등 유용한 디테일을 넣었어.
모두 연결하기
이제 테이블이 준비됐으니, enrollments 테이블을 만들어보자:
CREATE TABLE enrollments (
enrollment_id SERIAL PRIMARY KEY, -- 등록의 유니크한 ID
student_id INT NOT NULL REFERENCES students(student_id), -- 외래 키
course_id INT NOT NULL REFERENCES courses(course_id), -- 외래 키
enrollment_date DATE DEFAULT CURRENT_DATE -- 등록 날짜
);
테이블에 데이터 넣기
테이블만 있고 데이터가 없으면 심심하지. 학생, 강의, 그리고 등록 정보를 넣어보자:
학생 추가:
INSERT INTO students (name, email)
VALUES
('Alex Lin', 'alex.lin@example.com'),
('Maria Chi', 'maria.chi@example.com'),
('Otto Song', 'otto.song@example.com');
강의 추가:
INSERT INTO courses (title, description, start_date)
VALUES
('프로그래밍 기초', '초보 프로그래머를 위한 강의.', '2023-11-01'),
('데이터베이스', 'SQL과 관계형 데이터베이스 배우기.', '2023-11-15'),
('웹 개발', '웹사이트와 웹앱 만들기.', '2023-12-01');
등록 정보 추가:
INSERT INTO enrollments (student_id, course_id)
VALUES
(1, 1), -- Alex Lin이 "프로그래밍 기초" 수강
(1, 2), -- Alex Lin이 "데이터베이스" 수강
(2, 2), -- Maria Chi가 "데이터베이스" 수강
(3, 3); -- Otto Song이 "웹 개발" 수강
여기서 student_id와 course_id는 각 테이블의 식별자와 일치해.
쿼리로 관계 확인하기
모든 등록 정보 가져오기:
SELECT e.enrollment_id, s.name AS student_name, c.title AS course_title, e.enrollment_date
FROM enrollments e
JOIN students s ON e.student_id = s.student_id
JOIN courses c ON e.course_id = c.course_id;
결과:
| enrollment_id | student_name | course_title | enrollment_date |
|---|---|---|---|
| 1 | Alex Lin | 프로그래밍 기초 | 2023-11-01 |
| 2 | Alex Lin | 데이터베이스 | 2023-11-01 |
| 3 | Maria Chi | 데이터베이스 | 2023-11-01 |
| 4 | Otto Song | 웹 개발 | 2023-11-01 |
직접 해보는 연습 문제
학생과 강의를 더 추가하고, enrollments 테이블에 등록시켜봐. 예를 들어 "머신러닝" 강의를 추가하고 1~2명 학생을 등록해봐. 위에 있는 쿼리로 결과를 확인할 수 있어.
자주 하는 실수들
외래 키랑 중간 테이블 쓸 때 자주 빠지는 함정 몇 가지가 있어:
부모 테이블에 레코드가 없음:
enrollments에student_id나course_id가students나courses에 없으면 에러 나. 외래 키가 엄격하게 체크해.삭제할 때 데이터 무결성 깨짐: 이미
enrollments에 쓰이고 있는 학생이나 강의를ON DELETE CASCADE없이 지우면 에러 나.중복 등록: 한 학생이 같은 강의에 여러 번 등록되지 않게 조심해. 비즈니스 로직상 허용되는 경우가 아니라면 말이야.
이제 PostgreSQL에서 학생과 강의 사이의 MANY-TO-MANY 관계를 표현하는 실전 모델이 생겼어. 이 구조는 학습 관리 시스템, CRM 등 실제 앱에서 엄청 자주 써. 다음 강의로 고고!
GO TO FULL VERSION