DB SQL (JOIN - 정규화 활용법)

sungsimdangmascot·2026년 4월 21일

1. 정규화를 적용한 테이블 만들기 (CREATE)

모든 데이터를 한 곳에 몰아넣지 않고, 회원 정보와 게시글 정보를 담을 테이블을 각각 분리하여 생성한다. 이때 두 테이블을 연결해 줄 '연결 고리(외래키, Foreign Key)'를 설정하는 것이 핵심이다.

-- 데이터베이스 생성 및 선택
CREATE DATABASE IF NOT EXISTS site1;
USE site1;

-- 1) 회원 테이블 생성 (부모 테이블)
CREATE TABLE member (
    member_id INT AUTO_INCREMENT PRIMARY KEY, -- 고유 번호 (기본키)
    author_name VARCHAR(50) NOT NULL,         -- 작성자 이름
    author_email VARCHAR(100) NOT NULL        -- 작성자 이메일
);

-- 2) 게시글 테이블 생성 (자식 테이블)
CREATE TABLE article (
    article_id INT AUTO_INCREMENT PRIMARY KEY, -- 게시글 고유 번호
    title VARCHAR(200) NOT NULL,               -- 제목
    content TEXT NOT NULL,                     -- 내용
    member_id INT,                             -- 작성자가 누구인지 기록할 연결 고리
    -- 외래키 설정: 이 테이블의 member_id는 member 테이블의 member_id를 참조한다.
    FOREIGN KEY (member_id) REFERENCES member(member_id) 
);

이렇게 테이블을 분리해 두면, 회원의 이메일이 바뀌어도 member 테이블만 UPDATE 하면 되므로 데이터 관리가 훨씬 안전해진다.

2. 분리된 테이블에 데이터 넣기 (INSERT)

조인을 테스트하기 위해 가상의 데이터를 집어넣는다.

-- 회원 데이터 3명 추가 (이초보는 아직 글을 쓰지 않은 회원으로 가정)
INSERT INTO member (author_name, author_email) VALUES 
('김코딩', 'kim@test.com'),
('박해커', 'park@test.com'),
('이초보', 'lee@test.com'); 

-- 게시글 데이터 3개 추가 (1번 김코딩이 2개, 2번 박해커가 1개 작성)
INSERT INTO article (title, content, member_id) VALUES 
('첫 번째 글', '내용1', 1),
('두 번째 글', '내용2', 1),
('세 번째 글', '내용3', 2);

3. 조인(JOIN)으로 흩어진 데이터 모아서 보기 (SELECT)

이제 클라이언트(웹 브라우저) 화면에 "글 제목과 작성자 이름"을 함께 보여주어야 한다. 서로 다른 테이블에 있는 정보를 하나로 합쳐서 조회할 때 JOIN을 사용한다.

① INNER JOIN (가장 기본적인 조인)

글이 작성된 게시물과 그 글을 쓴 회원 정보가 모두 존재하는 데이터만 딱 맞춰서 가져온다.

-- article 테이블(a)과 member 테이블(m)을 합친다.
SELECT 
    a.article_id AS '글번호', 
    a.title AS '제목', 
    m.author_name AS '작성자'
FROM article AS a
INNER JOIN member AS m 
    ON a.member_id = m.member_id; -- 두 테이블의 member_id가 같은 것끼리 연결해라!

[실행 결과]
글을 한 번도 쓰지 않은 '이초보'의 정보는 출력되지 않는다. 양쪽 테이블에 모두 연결 고리가 있는 데이터만 교집합처럼 가져오기 때문이다.

② LEFT JOIN (한쪽 테이블을 기준으로 모두 가져오기)

게시글 작성 여부와 상관없이 "우리 사이트에 가입한 모든 회원 목록과, 그들이 쓴 글의 제목"을 보고 싶을 때 사용한다.

-- member 테이블(m)을 기준으로 왼쪽(LEFT)에 두고 모두 다 가져온다.
SELECT 
    m.author_name AS '회원이름', 
    a.title AS '작성한 글 제목'
FROM member AS m
LEFT JOIN article AS a 
    ON m.member_id = a.member_id;

[실행 결과]
왼쪽 테이블(member)에 있는 '이초보'의 이름도 무조건 출력된다. 단, '이초보'는 작성한 글이 없으므로 '작성한 글 제목' 칸에는 NULL(빈칸)이 표시된다. 이를 응용하면 글을 한 번도 쓰지 않은 유령 회원을 색출할 때 유용하다.


정리
1. 테이블을 설계할 때는 중복을 막기 위해 외래키(FOREIGN KEY)를 사용하여 정규화(분리) 한다.
2. 데이터를 조회할 때는 분리된 테이블을 ON 조건(주로 식별자 ID)을 기준으로 조인(결합) 하여 필요한 데이터만 뽑아낸다.

profile
성심당마스코트

0개의 댓글