Skip to content

[이슈] 게시글 테이블 데이터 길이 초과로 인한 테이블 분리 작업

이은비 edited this page Apr 23, 2023 · 1 revision

문제 상황

노션과 네이버 블로그 등과 같이 사용자가 자유롭게 게시글을 작성할 수 있는 에디터 형식의 작성 페이지를 기획했다. 프론트엔드에서 이를 처리하기 위해 react-quill 라이브러리를 사용한다. 서버에서는 사용자가 작성한 게시글에 대해 아래와 같이 테이블 구조를 갖고 있다.

Board(Id, CreatedAt, UpdatedAt, Category, Code, Content, Fixed, FixedAt, ImageUrls, PrefixCategory, Title, UseYn, UserId )

Code 컬럼은 프론트엔드 측에서 넘어오는 HTML 태그가 포함된 데이터이다. Content 컬럼은 Code 태그에서 HTML 태그를 벗겨낸 순수한 글의 내용만을 갖는 데이터이다. Image_Urls 는 사용자가 최대 10개까지의 이미지를 첨부할 수 있는데, 그때의 S3 주소값이다.

컬럼의 Type을 보면, Code와 Content 는 Text이다. 자바에서 String으로 선언하면 JPA에서는 기본적으로 varchar 타입으로 지정하며 별도의 length를 두지 않으면 255로 할당한다.

원인 파악 및 해결 과정

첫번째 이슈

게시글 생성 API 요청을 보냈을 때, 서버에서 500에러가 발생했다. 그 이유는 SQL insert 쿼리 오류 때문이다. code와 content가 varchar (255)로 되어 있어서 length를 넘어선 것으로 인해 insert가 되지 않았다. 이를 해결하기 위해 varchar에 max_length(65535)를 넣었지만, 이것으로 해결되지 않았다. 그래서 그 다음으로 수행한 것이 text 타입으로의 변경이다.

두번째 이슈

이미 게시글 테이블 내에 많은 컬럼이 존재하고, 그 중 위에서 언급했던 Code와 Content는 Text 타입을 가져야 할 만큼 데이터의 사이즈가 크다. 이로 인해 하나의 Row 가 가질 수 있는 범위를 넘어서면서 insert 오류가 발생했다. 이를 해결하기 위해 서버 파트의 긴급 회의가 열렸다.

1. 테이블 분리

가장 쉽게 떠올릴 수 있는 방법이 테이블의 분리이다. 데이터 사이즈가 가장 긴 code 컬럼을 별도의 테이블로 만들어 관리하는 것이다. 아래와 같이 boardId를 pk로 갖고 code 값을 갖는 테이블을 만들어 조회 시, join으로 처리한다.

board ( boardId, … )

board_code ( boardId, code )

해당 방법의 장단점은 무엇일까?

우선 장점은 구현이 쉽다는 것이다. JPA에서 Board 테이블과 One-to-One 관계를 갖는 테이블을 만들면 된다.

단점으로는 JOIN이다. 데이터를 조회하거나 수정할 때 JOIN이 발생한다. 그리고 code 컬럼에 대해서만 분리하는 것으로 이러한 이슈가 발생하지 않을 것이라는 확신을 할 수 없기 때문에 content 컬럼도 테이블 분리가 일어날 수 있다. 이렇게 되면 하나의 게시글 조회를 위해서 2개의 테이블과 JOIN을 해야 하는 상황이 생길 수도 있다.

+추가 사항+

단순히 JOIN에서의 성능 이슈만을 고려한 것은 아니다. TEXT 라는 타입이 조회 시, tmp table을 메모리에 생성하지 못하고 디스크에 생성하기 때문이다.

메모리에서 조회하는 것과 디스크에서 조회하는 것의 차이가 무엇인지 궁금하지?

흔히 메모리라고 하면 RAM을 의미하는데, 얘는 기억할 내용을 전기 신호 형태로 저장하기 때문에 속도가 굉장히 빠르다. 여기에 주로 저장되는 게 컴퓨터의 CPU가 현재 처리 중인 데이터나 명령어들인데, 이건 일시적으로 저장하기 때문에 휘발성 메모리이다. 즉, 전원이 꺼지면 다 날아간다~!

전원을 꺼도 데이터를 보존하고 싶다? 그럴 때 저장하는 곳이 디스크! 우리가 게임 같은 거 맨 처음 실행할 때 보면, Loading… 이런 화면을 볼 때가 있다. 이게 의미하는 바가 디스크로부터 데이터 불러오는 중이라는 거다.

2. AWS S3에 올리기

대용량의 데이터를 AWS S3 버킷에 올려서 관리하는 것이다. S3는 스토리지 서비스로, 현재 주말의집에서는 이미지 파일 저장소로 사용하고 있다. ( 한 번 업로드된 이미지는 삭제되지 않습니다. )

S3에는 다양한 형식의 데이터를 저장할 수 있다. 그리고 저장소 내에서 데이터를 조회하는 서버리스 형식의 솔루션들이 여럿 있다. 그 중 대표적인 게 athena이다. 이 솔루션을 사용해서 게시글 내용을 검색할 수 있다.

하지만 이 방법에는 아이러니한 점이 생긴다.

현재 게시글 조회를 위해서는 커뮤니티 대분류 ( 자유 | 소개 | 홍보 )에 대한 필터링이 필요하고, 그 후에는 키워드를 통한 검색이 필요하다.

키워드를 이용해 검색을 하기 위해 게시글 테이블에는 code 컬럼에서 HTML 태그를 벗겨낸 값을 갖는 content 컬럼을 갖고 있다. 문제는 검색에 사용되는 조건인 content가 데이터 사이즈가 크다는 것이다. 래서 이 컬럼을 포함해 code를 스토리지에 저장해서 관리한다고 하자.

게시글 검색을 위한 필터링은 DB 서버 내에 테이블에 존재하고, 키워드를 이용한 검색조건은 DB 서버와 스토리지에 분산되어 존재하게 된다. 이 점 때문에 스토리지에서 관리하는 방식을 채택하지 않았다.

네트워크 측면에서도 효율적이지 못하다고 판단했다.

게시글 검색을 위해서 프론트엔드가 서버로 검색 API 요청을 보내면 서버는 DB 서버와 스토리지로 요청을 2번 보내야 하는 상황이기 때문에 네트워크 관점에서의 비용이 2배로 발생한다.

또한 실제 서버 운영 비용에서도 비효율적이다.

주말의집은 아직 출시 이전인 토이 프로젝트이고, 스토리지에 조회와 생성 요청이 잦은 데이터를 보관하는 저장소로 둔다는 것은 프리티어 범위를 넘어서기 때문에 추가 비용이 발생하게 된다.

결론

1번 방식인 테이블 분리로 현재의 이슈를 해결하기로 결론을 내렸다.

Clone this wiki locally