본문 바로가기
개발일지

[개발일지] base64가 DB에 저장되면 일어나는 일

by 지지 2023. 2. 21.

문제

얼마 전 내가 맡고 있는 서비스의 board-api에서 부하가 많이 걸린다며(?) 한 번 확인해 달라는 요청이 들어왔다.
해당 서비스의 board-api는 지금은 퇴사한 직원이 만든 api이고, 내가 투입되던 시점(7월)부터는 큰 이슈가 없었기에 건드린 적이 없는 api였다.


원인 분석

어떤 작업에서 부하가 많이 걸리는지 확인하기 위해 먼저 로그를 살펴봤다.

로그창을 열자마자 알 수 없는 문자들이 촤라라라라라라라라락 지나갔고, 일단 해당 로그를 뱉어내는 api를 호출해 봤다.
해당 api는 게시글 리스트를 불러오는 api였으며, 이를 호출했을 때 응답 시간이 오래 걸리는 것(6초~15초)을 확인했다.
뭐지? 데이터가 이렇게 많지 않을 텐데?

[문제 해결 전 api 응답속도]

게시판 응답 데이터 개수 소요 시간
이벤트 33개 4~6초
활동소식 98개 13~17초
공지사항 132개 9~14초

예상대로 응답 데이터는 게시판 카테고리 별로 적게는 33개부터 많게는 132개로 많지 않은 데이터가 반환됐다.

이 수치는 운영되는 서버에 영향을 거의 미치지 않을 정도로 적은 수의 데이터라고 생각한다.

실제 운영되고 있는 많은 서비스들은 수천개부터 수십 수만개의 데이터를 반환하곤 하니까.

그렇다면 데이터  하나하나의 용량이 크던가 데이터를 불러오는 코드 또는 쿼리에 문제가 있다고 생각했다.

문제 해결을 위해 해당 api의 코드와 쿼리, DB테이블을 모두 살펴본 결과 아래 두 가지 원인이 발견되었다.

 

① 페이징 처리가 전혀 되어 있지 않음

코드의 문제로는 페이징 처리가 되어 있지 않은 것을 발견했다.

화면에만 보여주기식으로 페이징 처리를 해놓고 실제로는 처음 호출 시 모든 게시글을 다 불러오는 방식의 코드였다.

그래서 첫 호출엔 시간이 엄청 걸리고 그 후 다른 페이지로는 바로바로 넘어가지는 상황이었다.

따라서 해당 부분의 코드를 찾아 페이징 처리를 해주었고, 그 결과는 아래와 같다.

 

[페이징 처리 후 api 응답속도]

게시판 응답 데이터 개수 소요 시간
이벤트 33개 2~3초
활동소식 98개 3~4초
공지사항 132개 1~3초

 

이렇게 페이징 처리를 해주니 첫 호출 시 로딩시간이 확 줄어든 것을 확인할 수 있었다.

그러나 여전히 몇 개 없는 데이터를 불러오는데 로딩이 걸렸고, 페이징을 한 후로는 다른 페이지로 넘어갈 때도 로딩이 걸리는 문제가 있었다.

 

② 게시글 저장 시 이미지 주소가 base64 형태로 DB에 저장됨

보통 게시글을 저장할 때 html편집기를 이용해 이미지를 첨부할 수 있게 구현할 것이다.

나의 경우는 편집기가 이미지를 자동으로 base64형태로 인코딩 시켜 엄청난 길이의 텍스트를 img태그의 src 속성에 주입시켰고 해당 텍스트가 그대로 DB에 저장되고 있었다.

base64는 이미지에 따라 7000자 ~ 15만 자까지 나오며, DB에 저장했을 땐 레코드 한 줄에 몇 MB씩 차지하게 된다.

이 문제를 해결하기 위해선 게시글에 이미지를 첨부할 때, 이미지의 경로를 base64가 아닌 이미지가 저장된 서버의 주소를 img태그의 src속성에 넣어줘야 했다.

 

게시글 등록에 사용한 편집기는 toast-ui였고, 찾아보니 addImageBlobHook 함수를 사용하면 해결되는 문제였다.

addImageBlobHook첨부된 이미지를 file 객체로 만들어주고, callback을 통해 이미지 주소를 받아오는 기능을 하는 함수였다.

함수 사용법에 따라 코드를 작성하고! 다시 api를 호출해 주었다. 그 결과는!

 

[base64 -> url 처리 후 api 응답속도]

게시판 응답 데이터 개수 소요 시간
이벤트 33개 즉시
활동소식 98개 즉시
공지사항 132개 즉시

 

몇 초가 걸리던 api 응답 속도가 즉시 응답으로 개선된 것을 확인할 수 있었다!!


느낀 점

제일 위에 변명처럼 다른 사람이 만든 api라고 썼지만.. 누가 만들었든 현재 담당자는 나이기 때문에 제대로 확인 못한 내 책임이 크다고 생각한다.

사실 완전 몰랐던 것도 아니다. 내가 더 많은 지식이 있었다면 초기에 잡을 수 있는 이슈였다.

 

해당 api를 넘겨받자마자 들어온 수정사항이 있었는데, 당시 상황을 다시 돌이켜보면...

게시글을 저장할 때 에러가 난다는 이슈가 있었고, 확인결과 Data too long ~ 이라는 에러가 발생한걸 똑똑히 기억한다..ㅠ

그 당시 선배(?)이지만 같은 신입이었던.. 옆자리 동료분께 해결방법을 물어봤는데 타입을 더 큰 걸로 늘려주라길래 아! 하고 아무 생각 없이 더 큰 타입으로 늘렸었다.

그리고 분명 어마어마한 텍스트가 DB에 들어오는 것도 그때 이미 알고 있었다.

그러나 그게 문제가 될 줄은 정말 몰랐다. 그땐 그냥 '와! 엄청 길게 들어온당!' 이라고 생각하고 작업을 끝냈었다..

결국.. 무지했던 지난날의 나로 인해 전체 서버에 큰 부하를 주고 있었다.

 

이번 이슈를 해결하면서 정말 많은 것을 느꼈다.

컬럼 타입의 변경은 함부로 하면 안 된다는 것, base64는 DB에 저장 시 용량이 굉장히 클 수 있기 때문에 충분히 고민해 볼 것, DB구조의 변경은 반드시! 충분한 의논을 할 것, 기초를 더 열심히 다질 것.... 등등..

어떻게 보면 굉장히 기본적인 내용이라고 생각돼서 너무 부끄럽다.

그렇지만 어쩌겠는가..! 부끄러워도 이렇게 배워가고 알아가며 같은 실수를 반복하지 않으면 된다!

그래도 이번 이슈를 해결하고 나서는 굉장히 속이 시원했다. 고구마 100개 먹고 사이다 마신 느낌!!

 

정말 모르는 것 투성이지만 무지를 두려워하면 안 된다고 책에서 그랬다! 무지에 맞서 싸워 이기자!!!

모르면 공부하고, 동료에게 물어보고, 충분히 의논하고, 함께 결정하자!


[참고 블로그]

https://curryyou.tistory.com/474

https://gareen.tistory.com/49

 

댓글