-
Notifications
You must be signed in to change notification settings - Fork 0
[테이블 설계] 게시글 내용의 데이터 타입 지정, varchar vs text
주말의집과 같이 에디터 형식을 지원하는 서비스를 개발하다 보면, 게시글의 내용에 정적 코드(HTML)과 이미지 주소 값 등 순수한 글자만을 갖는 내용이 아닌 다른 부가적인 것들이 포함되는 경우가 있다. 이 경우, 애플리케이션 코드 상에서는 String으로 커버되는 값들이 DBMS에서는 varchar(255)로 커버되지 않는다.
Java 혹은 Kotlin에서 String 타입으로 지정하는 컬럼은 별도의 길이를 제한하지 않는 한, 기본적으로 varchar(255)로 지정한다.
그렇기에 게시글 생성 API를 호출하면, SQL 오류가 발생한다. 오류는 게시글 내용 값이 255자를 넘어선다는 내용이다. 당연한 얘기이다. 게시글 내용에 부가적인 것들이 포함되면 255자는 훌쩍 넘기 마련이고, 주말의집 서비스의 특성 상 사용자가 게시글에 사진을 최대 10장까지 포함할 수 있으며 내용 역시 길게 작성하는 경우가 많다.
커뮤니티 게시판의 경우, 글자 수에 제한을 두지 않고 있다. 빈집 거래 게시판의 경우, 글자 수를 10,000자로 제한하고 있다.
앞선 오류를 해결하기 위해 시도한 방법은 데이터의 길이가 길 것으로 예상되는 컬럼에 varchar(Integer.MAX_LENGTH)로 길이를 제한하였다. 이를 DBMS에서는 TEXT 타입으로 간주한다.
그렇다면 TEXT 타입과 varchar 타입의 차이는 무엇일까?
우리가 흔히 문자열 데이터를 저장하고자 할 때, 지정하는 데이터 타입이다. varchar 타입은 최대 저장 가능 길이를 지정할 수 있으며, 길이에 따라 테이블을 생성하지 못할 수도 있다. 그 이유는 테이블의 하나의 레코드가 저장할 수 있는 최대 길이가 65,535 바이트이기 때문이다.
하나의 varchar 컬럼이 너무 큰 길이를 사용하면, 다른 컬럼이 사용할 수 있는 최대 공간의 크기에도 영향을 줄 수 있다. 따라서 varchar 타입의 최대 저장 길이 설정을 할 때에는 공간을 아껴서 설정해야 한다.
varchar 타입이 제한 사항이 있다는 점을 위에서 살펴 보았다. TEXT는 이러한 설정 제한으로부터 자유롭다. 8000자 이상의 문자열 데이터를 저장할 때 주로 사용하는 타입이다.
RDBMS에서 TEXT나 BLOB와 같은 대용량 데이터를 저장하는 컬럼 타입을 LOB( Large Object) 타입이라고 한다. 그리고 이 데이터는 off-page
라고 하는 외부 공간에 저장한다.
MySQL 서버는 레코드의 컬럼 데이터를 B-Tree에 저장하지만, 용량이 큰 LOB 데이터는 B-Tree 외부의 off-page 페이지로 저장한다. 항상 LOB 타입의 컬럼을 off-page로 저장하는 것은 아니고 길이가 길어서 저장 공간이 많이 필요한 경우에만 off-page로 저장한다.
MySQL 서버의 레코드 크기 제한은 앞서 말했듯이 65,535 바이트이지만, InnoDB 스토리지 엔진의 레코드 크기 제한은 페이지의 크기에 따라서 달라진다. 대부분 페이지 크기의 절반이 InnoDB 스토리지 엔진의 최대 레코드 크기 제한으로 작동한다.
즉, InnoDB 스토리지 엔진은 레코드의 전체 크기가 이 제한사항 ( 16KB 페이지에서는 8,117 바이트 )을 초과하면 길이가 긴 컬럼을 선택해서 off-page로 저장하게 된다.
varchar 타입은 최대 크기가 설정되기에 미리 메모리 공간을 버퍼에 할당 받아둘 수 있다는 점에서 LOB 타입과는 차이가 있다.
LOB 타입은 최대 크기만큼 메모리를 할당해 두면 낭비가 심해지는 문제가 있어 버퍼에 할당받아두지 않는다. 따라서 매번 레코드를 읽고 쓸 때마다 필요한 만큼 메모리가 할당되어야 한다.
varchar 타입에 저장된 값의 길이가 길어서 off-page로 저장된 경우, MySQL 서버는 버퍼를 사용하지 못하고 새롭게 메모리 공간을 할당해서 사용하기에 varchar 타입에 매우 큰 값이 빈번하게 저장되는 경우에는 주의가 필요하다.
주말의집 서비스에서는 게시글 내용 컬럼을 TEXT 타입으로 지정하고 있다. 그 이유는 게시글의 내용 길이가 8,000자를 넘어서는 경우가 훨씬 많기 때문이다. 해당 컬럼이 데이터 조회 시, 무조건 필요로 되는 요소이지만 varchar로 감싸기 힘들기에 TEXT로 지정하여 사용하고 있다.
DBMS 성능을 높이기 위해서는 대용량 데이터를 스토리지로 분리시켜 관리해야 하는 가에 대한 고민을 하고 있으나 이것 역시 네트워크 트래픽이 추가로 발생한다는 점에서 성능 상 이점이 될 지 명확히 판단이 서지 않아 진행하지 않았다.