태그 검색 DB 설계 면접 질문: 콤마 문자열과 LIKE 검색이 깨지는 곳
시스템 디자인 Vol.1 · 04장 「태그로 글 찾기」에서
이런 화면입니다
블로그 글에 태그를 여러 개 답니다. redis 태그를 누르면 그 태그가 붙은 글만 모여 나옵니다.
한 글에 태그가 여럿, 한 태그에 글이 여럿입니다. 매일 보는 화면인데, 면접에서 테이블로 그려 보라고 하면 손이 멈추는 지원자가 많습니다.
면접관이 이렇게 묻습니다
글에 태그를 여러 개 달고, 태그로 글을 검색합니다. 테이블 구조와 검색 쿼리를 설계해 보세요.
범위부터 좁힙니다
규모와 규칙을 먼저 묻습니다. 태그를 자유롭게 적는지 목록에서 고르는지, 한 글에 몇 개까지인지, 태그 종류가 몇 개까지 늘어나는지.
여기서는 자유 입력, 한 글에 다섯 개까지, 태그 종류는 수만 개로 잡습니다. 태그 하나로 글 목록을 뽑는 것부터 되게 하고, 여러 태그를 한꺼번에 거는 검색은 그다음에 얹습니다.
한 글에 태그 여럿, 한 태그에 글 여럿. 이 관계를 테이블로 어떻게 담을지가 핵심 질문입니다.
가장 많이 나오는 답
글 테이블에 tags 칸 하나를 두고 콤마로 이어 붙입니다. 검색은 LIKE로 합니다.
-- posts.tags = 'redis,db,backend'
SELECT * FROM posts WHERE tags LIKE '%redis%';
글 몇 개로 시험하면 원하는 글이 잘 나옵니다.
그런데 여기서 깨집니다
redis를 찾았는데 redisson 태그가 붙은 글도 같이 걸려 옵니다. 문자열 안에서 글자를 찾는 검색이라 태그의 경계를 모릅니다.
앞에 %가 붙은 LIKE는 인덱스를 타지 못합니다. 글이 늘어날수록 검색 한 번이 테이블 전체를 훑습니다.
떨어지는 답은 이런 모양입니다
- 태그를 한 칸에 콤마로 이어 담습니다.
- LIKE 검색으로 끝내고, 그 검색이 인덱스를 못 탄다는 것을 짚지 못합니다.
면접관은 여기서 멈추지 않습니다
태그 두 개를 동시에 만족하는 글만 찾으려면요?
한 태그 검색을 넘어 조건이 겹칠 때 쿼리가 어떻게 바뀌는지 봅니다.
글에도 영상에도 상품에도 태그를 달아야 하면요?
태그를 붙일 대상이 늘어날 때 구조가 버티는지 봅니다.
글이 수백만 건인데 자동완성과 인기 태그를 빠르게 보여 주려면요?
검색과 집계의 부하를 따로 생각하는지 봅니다.
이 다음 판단은 책에서 이어집니다
책은 이 관계를 어떻게 담을지 정한 뒤, 태그로 글을 찾는 쿼리가 정확히 그 태그만 잡는 이유, 같은 태그가 두 번 붙는 것을 막는 방법, 태그 이름을 바꾸는 일까지 차례로 풉니다.
04장에서 이어지는 것
- 태그로 글을 찾는 쿼리
- 같은 태그를 두 번 다는 일을 막는 방법
- 태그 이름을 바꿀 때 생기는 일
- 이 글의 태그들과 이 태그의 글들을 함께 보는 방법