티스토리 뷰
1. 개요
기존에는 movies 테이블에서 "Action,Comedy,Drama"처럼 장르가 문자열 하나에 묶여 있었는데, 이를 정규화된 구조로 분리하고 genres 테이브로가 movie_genres 중간 테이블을 만드는 실습을 해보았다.
2. 문제 상황
-- 예시 데이터 (movies 테이블 일부)
movie_id | title | genres
---------|------------------|-----------------------
1 | Inception | Action,Sci-Fi
2 | Parasite | Thriller,Drama
3 | The Lion King | Animation,Family,Drama
genres가 이런 식으로 구성되어 있는 경우, 대략 다음과 같은 문제점이 존재한다.
- 중복 데이터가 발생
- 검색//분석이 불편
- JOIN이 불가능
3. 정규화
3-1. genres 테이블 생성 및 고유 장르 추출
INSERT INTO genres (name)
SELECT DISTINCT UNNEST(STRING_TO_ARRAY(genres, ','))
FROM movies
GROUP BY genres;
- STRING_TO_ARRAY(text, delimiter): 문자열을 지정한 기준(delimiter) 기준으로 나누어서 배열로 변환
- UNNEST(array): 배열의 요소를 행(row)으로 펼침
- SELECT DISTINCT: 중복 제거
이를 통해 "Action,Drama,Sci-Fi"이 경우, Action, Drama, Sci-Fi 같은 고유 장르만 추출할 수 있다.
3-2. 다대다 관계 테이블 생성
CREATE TABLE movies_genres (
movie_id BIGINT NOT NULL,
genre_id BIGINT NOT NULL,
PRIMARY KEY (movie_id, genre_id),
created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP NOT NULL,
updated_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP NOT NULL,
FOREIGN KEY (movie_id) REFERENCES movies (movie_id),
FOREIGN KEY (genre_id) REFERENCES genres (genre_id)
);
영화 하나에 여러 장르가 있을 수 있고 장르 하나도 여러 영화에 적용될 수 있으니 M:N 구조로 연결하는 테이블이 필요하다.
3-3. movies_genres에 데이터 삽입
INSERT INTO movies_genres (movie_id, genre_id)
SELECT
movies.movie_id,
genres.genre_id
FROM movies
JOIN genres
ON movies.genres LIKE '%' || genres.name || '%';
movies.genres는 문자열 형태(예: "Action,Drama")이기에 genres.name이 해당 문자열에 포함되어 있는지를 LIKE로 비교해서 매핑한다.
3-4. 기존 컬럼 제거
ALTER TABLE movies DROP COLUMN genres;
기존 genres 컬럼은 필요 없어졌으니 삭제한다.
3-5. 최종 데이터 구조 (예시)
3-5-1. movies 테이블
movie_id | title |
1 | Inception |
2 | Parasite |
3-5-2. genres 테이블
genre_id | name |
1 | Action |
2 | Drama |
3 | Comedy |
3-5-3. movie_genres (다대다 연결 테이블)
movie_id | genre_id |
1 | 1 |
1 | 2 |
2 | 2 |
4. 요약 및 느낀 점
- 정규화 과정(순서)
- genres 문자열 → 배열 → 고유 장르 추출 및 genres 테이블 생성
- movies_genres 중간 테이블 생성
- LIKE를 활용한 장르 매핑
- 원본 genres 컬럼 제거로 정규화 완료
- 문자열 기반 컬럼은 확장성 및 유지보수 측면에서 좋지 않다고 느꼈다.
- PostgreSQL을 이용하면 정규화가 매우 수월해지는 것을 느꼈다.
'기록' 카테고리의 다른 글
트랜잭션(Transaction)에 대해 배운 것 정리 및 예제 (0) | 2025.04.19 |
---|---|
PostgreSQL Function & Procedure 배운 것 정리 (0) | 2025.04.13 |
MySQL Full-Text Search (0) | 2025.04.12 |
MySQL Unions, Events, Triggers (0) | 2025.04.06 |
cross join, inner join, after join (0) | 2025.04.05 |
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
링크
TAG
- Next.js
- 카카오맵
- 스택
- 알고리즘
- 비트마스킹
- 순열
- 자바스크립트
- aws
- SQL
- 프로그래머스
- 완전탐색
- C++
- 구현
- 타입스크립트
- react
- BFS
- 넥스트js
- themoviedb
- 리액트
- CSS
- 코드스테이츠
- 백준
- Redux
- 브루트포스
- 햄버거버튼
- 다이나믹프로그래밍
- NextJS
- async
- typescript
- 동적계획법
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
글 보관함