...
MySQL에 배열 데이터를 저장
게시판을 제작하는데 있어, 게시글의 내용을 서버에 다음과 같이 보낸다고 가정해보자.
게시글 제목(title)과 게시글 제목(description) 그리고 게시글에 사용된 이미지(thumb_images) 정보가 들어있다.
이때 게시글 이미지들이 배열로 되어있는데 이를 어떻게 저장해야 할지 고민해보자.
{
"data": {
"thumb_images": ["https://example.com/product/H9881/thumb_image1.jpg",
"https://example.com/product/H9881/thumb_image2.jpg",
"https://example.com/product/H9881/thumb_image3.jpg"],
"description": "게시글 내용",
"title": "게시글",
}
}
1. 정규화 (테이블 분리 & 관계)
가장 정석적인 방법은 테이블 분리(정규화)이다.
데이터베이스에 배열을 그대로 하나의 레코드에 저장할 수는 없다. 왜냐하면 이는 제1정규형에 위반되므로 기본적으로 RDBMS에서 제한하기 때문이다.
따라서 따로 게시글 이미지를 저장하는 테이블을 만들어주고 관계를 맺어 게시글을 조회(select)할떄 조인(join) 해서 가져오면 그야말로 FM 이다.
하지만 잘 생각해보자.
댓글 같은 경우 이 역시 게시글 테이블과 댓글 테이블을 따로 만들고 관계(외래키)를 맺어 준다.
왜냐하면 댓글을 게시물 뿐만 아니라 유저 정보 테이블과도 관계를 맺어 불러와야 하기 때문에 테이블을 분리하여 설계하는 것이 효율적이다.
하지만 단순히 게시글의 이미지 url을 불러오는 건데 굳이 테이블을 분리하여 조인을 맺어야만 할까?
조인은 데이터베이스에게 꽤 부담되는 기능이다. 이는 곧 서비스 성능에 좌우된다.
데이터베이스의 정규화 이론에는 역정규화 라는 것도 있다.
역정규화란, 말 그대로 정규화를 따르지 않는것으로 RDBMS 만의 특징을 무시하고 그냥 nosql 처럼 데이터를 마구잡이 식으로 저장하는 것을 말한다.
DB 관리자들이 들으면 방방 뛸만한 내용이지만, 서버를 다루는 입장에서 역정규화는 굉장히 중요한 기술이다.
즉, 괜히 조인해서 DB 성능 떨어뜨리지말고 그냥 배열 그대로 테이블에 집어넣어 단순하게 꺼내와 서비스가 빠릿빠릿하게 돌아가도록 하면 된다.
2. 배열 문자열 저장
답은 단순하다.
배열 자료형을 문자열로 변환한 뒤 그대로 테이블 스트링 컬럼에 저장해버리면 된다.
그리고 꺼내쓸때도 문자열을 불러와서 다시 파싱하여 배열 자료형으로 만들어 사용하면 된다.
자바스크립트에서 기본으로 지원하는 JSON 클래스를 이용해 간단하게 배열을 문자열로 그리고 다시 복구도 할 수 있다.
const arr = ['Apple', 'Banana', 'Orange'];
let data = JSON.stringify(arr); // '["Apple","Banana","Orange"]' // 배열 문자열
let data2 = JSON.parse(data); // ['Apple', 'Banana', 'Orange'] 배열 자료형
JSON() 클래스는 자바스크립트 객체를 변환하는 api지만, 사실 자바스크립트 배열도 객체의 일종이기 때문에 이런식으로 응용이 가능하다
3. MySQL에서 지원하는 JSON 타입 사용
MySQL Ver. 5.7.8부터 아예 JSON 데이터를 저장할 수 있게 필드 타입 기능을 지원한다. 객체 뿐만 아니라 배열 역시 지원한다.
보다 데이터베이스 테이블을 하드하게 관리하고 싶다면 고려해볼만 하다.
다만 JSON 필드는 데이터를 능동적이게 저장하게 하기 위한 옵션이지, 쿼리 성능 자체는 그냥 스트링 타입 컬럼에 저장하고 꺼내쓰는것이 더 빠르다.
따라서 성능과 관리 두마리의 토끼를 잡기란 어려우므로 서비스 특성을 고려해서 잘 선택해야 한다.
CREATE TABLE example (
`id` int NOT NULL AUTO_INCREMENT,
`docs` JSON, -- json 타입 필드
PRIMARY KEY (`id`)
);
INSERT INTO example (docs) VALUES ('["hot", "cold"]'); -- 배열 문자열을 저장
-- 그러면 배열이 테이블에 들어가게 된다.
+----+-----------------+
| id | docs |
+----+-----------------+
| 1 | ["hot", "cold"] |
+----+-----------------+
이 글이 좋으셨다면 구독 & 좋아요
여러분의 구독과 좋아요는
저자에게 큰 힘이 됩니다.