← 운영 블로그

27화: 검색이 4.5초 걸리던 날

회차: 27화

서비스를 공개하고 처음 받은 피드백이 이거였습니다.

“검색이 너무 느려요.”

직접 해봤습니다. “초코우유”를 입력하고 기다렸어요.

1초. 2초. 3초. 4초.

4.5초 만에 결과가 나왔습니다. 인터넷 세상에서 4.5초는 거의 영원이에요. 유튜브에서 광고 건너뛰기가 5초인데, 검색 결과를 4.5초 기다릴 사람은 없습니다.


원인을 찾아야 했습니다.

160만 개 제품이 들어있는 데이터베이스에서 검색하는 건, 어쩌다 보니 꽤 복잡한 일이었어요.

엑셀로 치면 시트가 3만 장입니다. 매번 “초코우유”라는 단어를 찾으려고 3만 장을 처음부터 넘기고 있었던 거예요.


첫 번째 문제를 찾았습니다.

검색할 때마다 “전체 제품이 몇 개인지” 세고 있었어요. “검색 결과 1,234건 중 1~20번째”를 보여주려면 전체 개수를 알아야 하니까요.

그런데 160만 건을 세는 것 자체가 1초 넘게 걸렸습니다.

해법은 간단했어요. 전체 개수를 안 세면 됩니다. “다음 페이지가 있다/없다”만 알려주는 방식으로 바꿨어요. 도서관에서 “전체 장서가 몇 권”인지 세지 않고, “다음 선반에 책이 더 있어요”라고만 안내하는 거죠.

4.5초 → 2초. 절반으로 줄었습니다. 하지만 아직 느렸어요.


두 번째 문제.

제조사 이름을 가져오는 방식이 비효율적이었습니다. 제품 하나를 표시할 때마다 별도로 “이 제품의 제조사가 누구지?”를 물어보고 있었어요.

20개 결과를 보여주려면 20번 추가 질문. 수학여행에서 학생 한 명한 명에게 “너 반이 어디야?”를 물어보는 대신, 명찰에 반을 미리 적어두면 되는 것과 같았습니다.

제조사 이름을 제품 정보에 미리 적어뒀습니다. 160만 건에 전부요.

2초 → 0.2초.


세 번째 문제.

그 160만 건에 제조사 이름을 적어넣는 작업 자체에서 서버가 죽었습니다.

메모리 부족. 914MB짜리 서버에서 160만 건을 한 번에 처리하려니까 숨이 막힌 거예요.

500개씩 나눠서 처리했더니 이번엔 무한루프. 제조사 정보가 없는 제품이 매번 “아직 안 했어요” 목록에 다시 들어갔거든요.

“다 됐다”고 생각할 때마다 새로운 함정이 나타났습니다. 양파 껍질을 벗기면 또 양파가 나오는 느낌이었어요.


네 번째 문제.

검색 자체의 방식을 바꿔야 했습니다.

일반적인 검색은 “초코우유”라는 글자가 포함된 모든 행을 처음부터 끝까지 훑습니다. 하지만 책 뒤에 색인(찾아보기)이 있으면? “초코우유 → 158페이지, 2,341페이지, 45,892페이지”처럼 바로 찾아갈 수 있어요.

데이터베이스에도 비슷한 색인을 만들 수 있었습니다. 이름이 조금 어렵게도 ‘GIN 인덱스’라고 하는데, 한국어 검색에 특화된 방식이에요.

0.2초 → 0.05초.


마지막 반전은 코드도, 데이터도 아닌 곳에 있었습니다.

아침에 첫 검색이 유독 느린 현상이 있었어요. 밤새 아무도 안 쓰면 데이터베이스 연결이 끊어지거든요.

무료 서버(AWS 프리티어)의 숨겨진 비용이었습니다. “3시간 이상 손님이 없으면 잠기는 무료 주차장” 같은 거예요. 다시 주차하려면 차를 꺼내고 다시 넣어야 하는데, 그게 2초.

연결을 끊지 않고 유지하도록 설정을 바꿨습니다.


4.5초 → 0.05초. 90배 빨라졌습니다.

한 번에 된 게 아니라, 네 번의 삽질과 서버 크래시와 무한루프를 거쳐서요.

160만 건의 세계에서 배운 건 이거예요.

“그냥 되겠지”는 없다. 측정하고, 고치고, 또 측정한다.


다음 화에서는, 이 데이터를 매일 불러오는 과정의 뒷이야기를 해볼게요. 104만 건을 매일 전부 다시 읽는 이유가 있습니다.