![[실전 DB 16] 데이터베이스의 한계와 다음 단계](https://img.thenullpage.com/posts/5708/5708_1_7012bf.webp)
이 시리즈의 마지막 편이다. 지금까지 측정에서 시작해 인덱스, 실행 계획, 페이지네이션, 반복 조회, 비정규화, 캐시, 그리고 데이터를 직접 다루는 원칙까지 왔다. 이번 편은 한 걸음 물러서서, 데이터베이스 자체의 한계와 그다음 단계를 이야기한다. 아무리 최적화해도 데이터베이스가 만능은 아니고, 어느 지점에서는 다른 도구가 필요해진다.
최적화의 마지막 지혜는 언제 최적화를 멈추고 도구를 바꿀지 아는 것이다. 이 편은 그 판단과 함께, 지금까지의 여정을 하나의 루틴으로 정리한다.
1. 데이터베이스에도 한계가 있다
지금까지의 최적화는 데이터베이스를 잘 쓰는 법이었다. 그런데 아무리 잘 써도 데이터베이스에는 넘을 수 없는 한계가 있다. 저장할 수 있는 용량에 한도가 있고, 한 번에 다룰 수 있는 규모에 한도가 있고, 특정 종류의 작업은 아무리 최적화해도 근본적으로 잘 못한다.
내가 쓰는 데이터베이스도 용량 한도가 정해져 있었다. 데이터가 계속 쌓이면 언젠가 그 한도에 닿는다. 최적화는 읽기 비용을 줄여주지만 저장 용량 자체를 늘려주지는 않는다. 그래서 데이터가 무한정 커진다면, 최적화만으로는 안 되고 다른 구조를 생각해야 하는 순간이 온다.
규모의 한계도 있다. 데이터가 어느 선을 넘으면, 잘 만든 인덱스로도 감당이 안 되는 작업이 생긴다. 전체를 훑어야만 하는 종류의 작업은 데이터가 커질수록 무거워지는데, 이건 인덱스로도 캐시로도 근본적으로는 못 피한다. 규모가 커지면 접근 자체를 바꾸거나 도구를 바꿔야 한다.
이 한계를 아는 게 중요한 이유는, 최적화로 풀 수 있는 문제와 없는 문제를 구분하기 위해서다. 최적화로 풀리는 문제는 끝까지 최적화하고, 최적화로 안 풀리는 한계는 도구를 바꿔 넘어야 한다. 이 둘을 구분 못 하면, 도구를 바꿔야 할 문제를 붙잡고 헛되이 최적화만 하게 된다.
다만 이 한계를 너무 일찍 걱정할 필요는 없다. 신생 사이트의 규모에서는 잘 최적화한 데이터베이스 하나로 오래 버틴다. 한도에 닿는 건 데이터가 아주 많이 쌓인 뒤의 이야기라, 대부분은 그 지점에 도달하기 한참 전이다. 그래서 지금의 최적화에 집중하되, 한계가 존재한다는 사실만 알아두고 그때가 오면 대응하면 된다.
2. 관계형 데이터베이스가 약한 일
관계형 데이터베이스는 정해진 조건으로 데이터를 거르고 잇는 데는 아주 강하다. 그런데 약한 분야도 분명히 있다. 대표적인 게 본문 전체를 뒤지는 검색이다. 글 내용 어딘가에 특정 단어가 들어간 걸 찾는 작업은, 인덱스가 잘 안 통해서 전체를 훑기 쉽다.
내가 만든 사이트에서도 본문 검색이 골칫거리였다. 단어가 본문 중간에 있으면 앞에서부터 매기는 인덱스가 안 통해, 결국 전체를 훑는 무거운 작업이 됐다. 앞서 다룬 스캔 비용이 검색에서 그대로 터진 것이다. 이건 인덱스를 아무리 손봐도 관계형 데이터베이스의 구조적 약점이라 근본 해결이 어려웠다.
이런 종류의 작업은 그걸 잘하는 전용 도구가 따로 있다. 본문 검색이라면 전문 검색엔진이 있다. 이런 도구는 단어를 미리 쪼개 색인해두어, 본문 어디에 있는 단어든 빠르게 찾는다. 관계형 데이터베이스가 못하는 걸 처음부터 잘하도록 만들어진 도구다. 약점이 분명한 작업은 그 작업에 맞는 도구에 맡기는 게 낫다.
비슷하게, 아주 자주 바뀌는 임시 값이나, 관계보다 순서가 중요한 데이터, 대량으로 흘러드는 기록 같은 것도 관계형 데이터베이스가 최선이 아닐 수 있다. 각각에 맞는 저장소가 따로 있다. 하나의 데이터베이스로 모든 걸 다 하려 하기보다, 일의 성격에 맞는 도구를 곁들이는 것이 규모가 커질 때의 방향이다.
검색의 경우 도구를 바꾸기 전에 절충으로 버틸 방법도 있다. 본문 전체를 뒤지는 대신 제목 같은 짧은 범위만 검색하게 좁히거나, 검색 결과를 캐시해 같은 검색이 반복될 때 원본을 다시 안 뒤지게 하는 것이다. 이런 절충으로 상당 기간을 버틸 수 있다. 전용 도구는 이런 절충으로도 안 될 만큼 검색이 중요하고 무거워졌을 때 들인다.
3. 언제 다른 저장소로 갈아타나
그렇다고 성급하게 도구를 늘리는 건 위험하다. 도구가 늘면 관리할 게 늘고, 데이터가 여러 곳에 흩어져 정합성 문제가 생긴다. 그래서 다른 저장소를 들이는 건, 지금 도구로 정말 안 될 때까지 미루는 게 좋다. 나눠야 할 이유가 분명해질 때까지 하나로 버티는 것이다.
갈아타거나 곁들일 때를 판단하는 기준은 두 가지다. 하나는 지금 도구의 한계에 실제로 부딪혔는가다. 검색이 너무 무거워 최적화로도 감당이 안 되거나, 용량 한도에 가까워졌거나 하는 실제 신호가 있어야 한다. 막연히 커질 것 같아서가 아니라, 지금 여기서 한계가 확인됐을 때 움직인다.
다른 하나는 그 작업이 전체에서 차지하는 비중이다. 무거운 검색이 어쩌다 한 번이면 참고 쓰지만, 핵심 기능이라 자주 쓰이면 전용 도구를 들일 값어치가 있다. 앞서 최적화에서 자주 쓰이면서 무거운 것부터 잡았듯, 도구 교체도 자주 쓰이면서 지금 도구가 약한 것부터 검토한다. 빈도와 무게를 곱한 부담이 여기서도 기준이다.
내 경우 대부분은 하나의 데이터베이스로 버텼다. 신생 사이트의 규모에서는 잘 최적화한 데이터베이스 하나로 충분했기 때문이다. 도구를 늘리는 건 그 한계가 실제로 발목을 잡을 때 하기로 미뤄뒀다. 지금 필요하지 않은 복잡함을 미리 짊어지지 않는 것도 중요한 판단이었다.
도구를 늘릴 때 가장 조심할 건 데이터가 여러 곳에 나뉘면서 생기는 정합성 문제다. 같은 정보가 데이터베이스와 검색엔진 양쪽에 있으면, 한쪽이 바뀔 때 다른 쪽도 맞춰야 한다. 앞서 비정규화에서 다룬 어긋남 문제가 저장소 사이에서 더 크게 벌어지는 것이다. 그래서 도구를 늘리는 건 그 관리 부담까지 감당할 각오가 설 때 한다.
4. 최적화의 우선순위 정리
이 시리즈 전체를 우선순위로 정리해보자. 첫째는 언제나 측정이다. 감으로 고치지 말고, 어느 쿼리가 자주 호출되면서 많이 훑는지 재서 가장 부담이 큰 것부터 잡는다. 측정 없이 손대면 엉뚱한 데 힘을 쓰고 정작 병목은 그대로 남는다. 모든 최적화는 측정에서 시작한다.
둘째는 인덱스다. 가장 무거운 쿼리에 알맞은 인덱스를 걸어 스캔을 검색으로 바꾼다. 실행 계획으로 인덱스가 실제로 쓰이는지 확인하고, 복합 인덱스의 컬럼 순서를 맞추고, 안 쓰이는 인덱스는 정리한다. 인덱스는 회당 읽기를 줄이는 가장 기본적인 무기다.
셋째는 구조적 문제다. 인덱스로 안 풀리는 것들, 즉 개수 세기와 건너뛰기 페이지네이션, 반복 조회 같은 것을 키셋 방식과 비정규화로 재설계한다. 넷째는 캐시다. 자주 조회되고 자주 안 바뀌는 걸 캐시해 읽는 횟수 자체를 줄인다. 단 캐시는 무효화와 보안을 함께 챙긴다. 이 순서가 대체로 투자 대비 효과가 큰 순서다.
이 우선순위가 중요한 건, 한정된 시간과 힘을 어디에 쓸지 정해주기 때문이다. 다 하려 들면 지치고, 순서 없이 하면 효과가 작은 데 힘을 쓴다. 측정으로 가장 큰 병목을 찾아 그것부터, 효과가 큰 순서로 하나씩 하는 것이다. 최적화는 전부 다가 아니라 큰 것부터라는 감각이 오래 가는 힘이다.
이 순서를 지키면 과잉 최적화도 피하게 된다. 측정으로 가장 큰 병목만 잡으니, 효과가 미미한 곳에 힘을 쏟지 않는다. 이미 충분히 빠른 걸 더 빠르게 만드느라 코드를 복잡하게 만드는 건, 얻는 것보다 잃는 게 크다. 최적화의 지혜는 어디까지 하느냐를 아는 것이기도 하다. 병목이 사라졌으면 손을 떼는 것이다.
5. 측정하고 최적화하는 루틴
이 시리즈를 관통하는 하나의 태도가 있다면, 감이 아니라 데이터로 판단한다는 것이다. 데이터베이스는 비용이 걸린 문제라 짐작으로 손대면 돈과 시간이 샌다. 재고, 가장 무거운 걸 고치고, 다시 재서 효과를 확인하는 이 순환이 최적화의 처음이자 끝이다. 한 번 하고 끝나는 게 아니라 습관으로 돌리는 것이다.
이 루틴을 정기적으로 돌리면 사이트가 커져도 데이터베이스가 건강하게 유지된다. 주기적으로 무거운 쿼리를 재고, 새로 생긴 병목을 잡고, 안 쓰이는 인덱스를 정리하고, 비정규화 값이 어긋나지 않았는지 점검한다. 데이터와 트래픽은 계속 변하니, 한 번의 최적화가 아니라 꾸준한 점검이 상태를 지킨다.
돌아보면 이 여정의 출발은 방문자가 적은데 읽기가 폭증하던 당혹감이었다. 읽기량이 반환한 행이 아니라 훑은 행이라는 관점 하나를 잡고, 측정으로 병목을 찾아 인덱스와 구조 개선과 캐시로 하나씩 풀어가니, 한도의 네 배를 넘던 읽기가 한도 안으로 들어왔다. 콘텐츠도 기능도 그대로인데 뒤에서 훨씬 적게 일하게 만든 것이다.
이 여정에서 가장 크게 남은 건 기술보다 태도였다. 문제가 생기면 짐작으로 손대지 않고 먼저 재는 것, 가장 큰 것부터 하나씩 푸는 것, 고친 뒤엔 다시 재서 확인하는 것이다. 인덱스나 캐시 같은 구체적인 기법은 도구가 바뀌면 세부가 달라지지만, 이 태도는 어떤 저장소를 다루든 그대로 통한다. 도구는 지나가고 태도는 남는다.
이 시리즈가 누군가 같은 당혹감을 겪을 때 길잡이가 되면 좋겠다. 도구는 바뀌어도 스캔이 비싸고 인덱스가 싸다는 원리, 자주 쓰이면서 무거운 것부터 잡는다는 순서, 감이 아니라 데이터로 판단한다는 태도는 오래 남는다. 데이터베이스 최적화는 겉으로 안 보이는 곳에서 사이트를 빠르고 싸게, 그래서 오래 살아남게 하는 일이다. 여기까지가 실전 데이터베이스 시리즈의 끝이다.