배열을 데이터베이스에 저장할 때 무엇을 먼저 판단해야 하는가
애플리케이션에서는 배열이나 리스트를 자주 다루지만, 관계형 데이터베이스는 기본적으로 행과 열 중심의 구조를 가진다. 그래서 애플리케이션의 배열을 DB에 그대로 저장하려고 하면 설계 선택지가 여러 갈래로 나뉜다.
핵심은 “배열을 저장할 수 있느냐”보다 그 배열을 나중에 어떻게 조회하고 수정할 것인가를 먼저 보는 것이다.
가장 먼저 볼 질문
배열을 DB에 저장할 때는 먼저 이 질문부터 해야 한다.
- 원소를 개별적으로 조회해야 하는가
- 원소의 순서가 중요한가
- 원소별 수정이 자주 일어나는가
- 조건 검색이 필요한가
이 질문에 따라 모델링 방식이 달라진다.
1. 정규화해서 별도 테이블로 분리하는 방식
가장 일반적인 방법은 배열 원소를 별도 테이블의 여러 행으로 저장하는 것이다.
예를 들어 주문의 여러 상품 ID를 저장한다면:
ordersorder_items
처럼 분리하는 방식이다.
이 방식의 장점:
- 조건 검색이 쉽다
- 인덱스를 걸기 쉽다
- 원소 단위 수정과 확장이 쉽다
단점:
- 조인이 필요하다
- 단순 저장 구조보다 테이블 수가 늘어난다
대부분의 관계형 DB 실무에서는 이 방식이 기본값에 가깝다.
2. 문자열이나 JSON으로 한 컬럼에 넣는 방식
배열을 콤마 구분 문자열이나 JSON 배열로 넣을 수도 있다.
예:
"1,2,3,4"["A","B","C"]
장점:
- 저장이 단순하다
- 초기 구현 속도가 빠르다
단점:
- 조건 검색이 어렵다
- 부분 수정이 불편하다
- 인덱스 활용이 제한적이다
- 데이터 정합성을 DB 레벨에서 보장하기 어렵다
즉, 보여주기용 속성이나 단순 캐시성 데이터가 아니라면 장기적으로는 불리한 경우가 많다.
3. DB가 배열 타입을 지원하는 경우
일부 데이터베이스는 배열 타입이나 JSON 타입을 더 적극적으로 지원한다. 예를 들어 PostgreSQL은 배열과 JSONB를 다룰 수 있다.
이 경우 선택지는 더 넓어지지만, 여전히 중요한 것은 질의 패턴이다.
지원된다고 해서 무조건 좋은 것이 아니라:
- 검색 조건이 복잡한가
- 인덱스 전략이 충분한가
- ORM이 이를 자연스럽게 다루는가
를 함께 봐야 한다.
언제 별도 테이블이 유리한가
다음 조건이면 보통 별도 테이블이 낫다.
- 원소별 조회가 필요하다
- 특정 원소 포함 여부를 자주 찾는다
- 원소 단위 업데이트가 일어난다
- 원소 자체가 독립 의미를 가진다
예:
- 주문 항목
- 사용자 권한 목록
- 상품 옵션
이런 경우는 배열처럼 보여도 사실상 독립 엔티티에 가깝다.
언제 한 컬럼 저장이 허용될 수 있는가
다음처럼 제한된 경우에는 한 컬럼 저장도 실용적일 수 있다.
- 조회 시 통째로만 사용한다
- 부분 검색이 없다
- 수정 빈도가 낮다
- 데이터 규모가 작다
예:
- 화면 설정값 목록
- 단순 태그 캐시
- 로그성 부가 정보
다만 이 경우에도 “나중에 검색이 필요해질 가능성”을 한 번은 점검해야 한다.
ORM 관점에서 생기는 문제
JPA 같은 ORM에서는 컬렉션 매핑을 쉽게 느낄 수 있지만, 실제 저장 구조와 쿼리 비용은 여전히 DB 모델링의 문제다.
즉:
- 매핑이 가능하다고 좋은 모델은 아니다
- 객체 구조와 테이블 구조를 구분해서 봐야 한다
배열이 객체에서는 자연스러워도, 테이블에서는 분리된 행이 더 자연스러운 경우가 많다.
정리
배열을 DB에 저장할 때 중요한 것은 저장 형식보다 조회와 수정 패턴이다.
- 검색과 수정이 중요하면 별도 테이블
- 통째로만 쓰는 작은 속성이면 컬럼 저장 가능
- DB 지원 타입을 쓰더라도 질의 패턴을 먼저 본다
결국 배열을 어떻게 저장할지는 문법 문제가 아니라, 데이터가 이후에 어떤 방식으로 사용될 것인지를 먼저 정의하는 모델링 문제다.
댓글
아직 댓글이 없습니다