느려진 목록 되살리기(인덱스)

주문이 만 건을 넘으면 목록 화면이 갑자기 안 열려요. 장부 뒤에 찾아보기를 붙이듯 기록에 색인을 붙여 찾아가는 길을 만들어 주는 처방이에요. 공짜는 아니고, 쓰는 쪽이 조금 느려지는 대가가 있어요.

쉽게 말하면

손님 3만 명이 적힌 두꺼운 장부에서 전화번호 하나를 찾아야 해요. 색인이 없으면 첫 장부터 한 줄씩 다 읽어야 해요. 그런데 장부 뒤에 전화번호 순으로 정리한 얇은 찾아보기를 붙여 두면, 몇 장만 넘겨서 "1,842쪽"을 확인하고 바로 그 쪽으로 가요. 데이터베이스의 인덱스가 정확히 그 찾아보기예요. 원래 기록은 그대로 두고, 찾아가는 길만 따로 만들어 두는 거예요.

그래서 인덱스는 기록을 고치는 일이 아니에요. 장부 내용은 한 글자도 안 바뀌고, 찾는 방법만 바뀌어요. 색인을 잘못 붙였다고 손님 명단이 사라지지는 않아요. 이 점이 데이터베이스 작업 중에서 인덱스가 비교적 안심하고 손볼 수 있는 부분인 이유예요.

색인 없는 장부
"010-1234-5678 손님 찾기" 1쪽부터 3만 줄 전부 읽기

100건일 때는 눈 깜짝할 사이예요. 3만 건이 되면 화면이 멈춘 것처럼 보여요.

색인 붙인 장부
찾아보기에서 번호 확인 해당 쪽으로 바로 이동

건수가 100배 늘어도 넘겨야 할 장수는 몇 장 더 늘어날 뿐이에요.

왜 어느 날 갑자기 느려지나

데이터베이스가 기록을 찾는 방법은 크게 두 가지뿐이에요. 처음부터 끝까지 한 줄씩 보기, 그리고 색인을 따라 바로 짚기. 색인이 없으면 선택지가 하나뿐이라 무조건 전부 훑어요.

전부 훑는 방식은 기록이 늘어나는 만큼 그대로 오래 걸려요. 1,000줄이면 1,000줄을 읽고, 10만 줄이면 10만 줄을 읽어요. 색인을 따라가는 방식은 다르게 늘어나요. 색인은 절반씩 좁혀 들어가는 구조라, 건수가 열 배 늘어도 짚는 횟수는 세 번쯤만 늘어요.

기록 수전부 훑으면 읽는 줄색인을 따라가면 짚는 횟수
1,000줄1,000줄약 10번
10,000줄10,000줄약 14번
100,000줄100,000줄약 17번
1,000,000줄1,000,000줄약 20번

오른쪽 칸이 거의 그대로인 게 인덱스의 정체예요. 짚는 횟수는 대략적인 값이고 데이터베이스 종류마다 다르지만, 왼쪽은 백 배가 되고 오른쪽은 두 배가 된다는 차이는 어디서나 같아요.

그런데 사장님이 체감하는 건 서서히 오르는 오르막이 아니라 절벽이에요. 어제까지 잘 열리던 목록이 오늘 안 열려요. 이유는 하나 더 있어요. 기록이 계산대 위에 있는지, 창고에 있는지의 차이예요.

장부가 계산대 위에 다 펼쳐져 있으면 3만 줄을 훑어도 손이 빠르게 지나가요. 그런데 장부가 두꺼워져서 계산대에 안 올라가면, 이제 한 묶음 읽고 창고에 갔다 오고, 또 한 묶음 읽고 창고에 갔다 와요. 서버도 똑같아요. 자주 쓰는 기록을 손 닿는 곳(메모리)에 올려 두는데, 기록이 그 크기를 넘어서는 순간부터 디스크를 왕복하기 시작해요. 그 지점이 절벽이에요.

만 건은 기준이 아니라 신호예요

정확한 임계점은 기록 한 줄의 크기, 서버 메모리, 동시 접속자 수에 따라 달라져요. 사진 정보가 붙은 무거운 기록이면 수천 건에서도 꺾이고, 가벼운 기록이면 수십만 건까지 버텨요. 그래서 "만 건"을 외우는 것보다 내 화면이 몇 초에 열리는지 재는 습관이 정확해요.

어디에 붙이나

인덱스는 기록 전체에 뿌리는 마법이 아니에요. 찾는 조건 하나마다 하나씩 만들어요. 그래서 붙일 자리를 찾는 일은 기술이 아니라 관찰이에요. 느린 화면이 무엇으로 걸러내고 무엇으로 줄 세우는지 보면 돼요.

  1. 1느린 화면 하나만 고르세요. 여러 개를 한꺼번에 고치려 들면 무엇이 효과였는지 알 수 없어요.
  2. 2그 화면이 하는 일을 한 문장으로 적어요. "내 가게 주문 중에서, 최근 것부터 20개"처럼요.
  3. 3그 문장에 나온 조건이 색인을 붙일 자리예요. 걸러내는 조건(내 가게)과 줄 세우는 조건(최근 것부터) 둘 다요.
  4. 4붙이기 전에 화면이 열리는 시간을 재 두세요. 몇 초였는지 적어 두지 않으면 나아졌는지 증명할 수 없어요.
  5. 5붙인 뒤 같은 방법으로 다시 재요. 안 빨라졌으면 색인을 잘못 짚은 거예요. 되돌리고 조건을 다시 보세요.
느린 화면실제로 하는 일색인을 붙일 자리
주문 목록내 가게 주문을 최근 순으로 20개가게 + 주문 시각을 한 묶음으로
손님 검색전화번호로 한 명 찾기전화번호
예약 조회이 달 1일부터 말일까지의 예약예약 날짜
미처리 문의답 안 한 문의만, 오래된 순으로처리 여부 + 접수 시각을 한 묶음으로
매출 합계지난달 결제 금액을 다 더하기색인만으로는 부족해요. 아래 선택지 표를 보세요

묶음 색인은 앞 칸부터예요

"가게 + 주문 시각" 색인은 가게만으로 찾을 때도 잘 쓰여요. 그런데 시각만으로 찾을 때는 쓰이지 않아요. 전화번호부가 성 다음 이름 순으로 정리돼 있어서, 성을 모르면 이름만으로는 못 찾는 것과 똑같아요. 그래서 묶음 색인은 칸의 순서가 성능을 가릅니다. 개발자가 순서를 바꿔 달라고 하면 트집이 아니라 정확한 요청이에요.

하면 안 되는 때

여기가 기초와 갈리는 지점이에요. 색인은 공짜가 아니에요. 찾아보기를 하나 붙였으면, 기록이 한 줄 들어올 때마다 찾아보기도 같이 고쳐 써야 해요. 주문 하나 받을 때 장부에 적고, 색인 세 권에도 각각 한 줄씩 끼워 넣는 셈이에요.

대가무슨 일이 생기나언제 문제가 되나
쓰기가 느려져요기록을 넣고 고칠 때마다 색인 전부를 함께 갱신해요색인이 대여섯 개를 넘고, 기록이 쉼 없이 들어올 때
저장 공간을 먹어요색인은 원본과 별도로 자리를 차지해요무료 구간이 있는 데이터베이스에서 용량 한도에 걸릴 때
안 쓰이는 색인도 비용은 내요쓰이지 않아도 갱신은 계속돼요"혹시 몰라서" 색인을 여러 개 만들어 뒀을 때
만드는 동안 멈출 수 있어요기록이 많은 표에 색인을 만들면 그 사이 쓰기가 막힐 수 있어요장사 시간에 작업할 때

그래서 아래 경우에는 색인을 붙이지 않는 편이 나아요. 하나하나가 실제로 겪는 상황이에요.

  1. 1기록이 아직 적을 때. 수백 건짜리 표는 전부 훑어도 순식간이에요. 색인을 붙여도 체감 차이가 없고 갱신 비용만 생겨요.
  2. 2값의 종류가 두세 가지뿐인 칸. 결제 상태가 완료와 취소 둘뿐이면, 색인을 따라가도 절반을 짚게 돼요. 그럴 때 데이터베이스는 색인을 무시하고 그냥 전부 훑기를 고르는데, 그게 실제로 더 빨라요.
  3. 3한 달에 한 번 보는 화면. 관리자만 분기말에 여는 통계 화면 때문에 매일 들어오는 주문의 쓰기를 느리게 만들 이유는 없어요.
  4. 4기록이 쏟아져 들어오는 표. 방문 기록이나 로그처럼 초당 여러 줄이 쌓이는 표는 읽기보다 쓰기가 압도적이에요. 색인이 곧 병목이 돼요.
  5. 5이미 있는 색인의 앞부분과 겹칠 때. "가게 + 시각" 색인이 있으면 "가게" 단독 색인은 대개 군더더기예요. 앞 칸만 쓰는 건 기존 색인이 이미 해 줘요.

선택지는 색인만이 아니에요

"목록이 느리다"의 처방은 다섯 가지쯤 돼요. 각각 효과와 대가가 다르고, 진짜 해결은 보통 두 개를 겹쳐 쓰는 거예요. 개발자가 이 중 하나만 말한다면 나머지를 물어볼 만해요.

처방언제 맞나대가
색인 붙이기특정 조건으로 걸러내거나 줄 세우는 화면이 느릴 때쓰기가 느려지고 용량을 먹어요
한 번에 20개씩만 보여주기목록을 전부 불러와 그리고 있을 때. 가장 자주 놓치는 처방이에요"더 보기"를 눌러야 해요. 전체 개수 세는 것도 따로 손봐야 해요
합계를 미리 계산해 두기매출 합계처럼 매번 전부 더해야 하는 화면실시간이 아니게 돼요. 몇 분 전 숫자를 보여줘요
오래된 기록 옮겨 두기3년 치가 쌓였는데 실제로 보는 건 최근 3개월일 때옛 기록을 볼 때는 따로 꺼내야 해요
서버 키우기위 네 가지를 다 했는데도 부족할 때매달 비용이 늘어요. 근본 원인은 그대로예요

순서를 지키면 돈이 덜 들어요

한 번에 20개씩 보여주기와 색인 붙이기가 먼저예요. 이 둘은 대개 코드 몇 줄과 색인 한두 개로 끝나고 매달 나가는 돈이 안 늘어요. 서버 키우기를 먼저 하면 느린 원인은 그대로 둔 채로 비용만 늘고, 기록이 또 두 배가 되면 같은 자리에서 다시 막혀요.

사장님이 실제로 겪는 장면

장면 1 · 손님은 괜찮은데 관리자 화면만 느리다

손님용 주문 페이지는 잘 열리는데, 제가 보는 전체 주문 목록만 한참 돌아요.

정상적인 증상이에요. 손님 화면은 자기 주문 몇 건만 찾지만, 관리자 화면은 가게 전체 주문을 훑어요. 그래서 규모가 커질 때 관리자 화면이 늘 먼저 무너져요. 여기서 얻을 교훈은 하나예요. 느려지는 신호는 손님이 아니라 사장님이 먼저 봐요. 손님이 불편을 느끼기 전에 손볼 시간이 있다는 뜻이에요.

장면 2 · 맡긴 개발자가 인덱스로 해결된다고 한다

주문 테이블에 인덱스 걸면 해결됩니다. 작업 반나절이요.

맞는 처방일 가능성이 높아요. 다만 그대로 넘기지 말고 세 가지를 물어보세요. 어떤 조건의 색인인지(문장으로 설명 가능해야 해요), 작업 전후 시간을 재서 보여줄 수 있는지, 만드는 동안 서비스가 멈추는지요. 세 가지에 다 답하는 개발자면 믿을 만해요. "그냥 걸면 빨라져요"라고만 하면 짚을 자리를 아직 안 본 거예요.

장면 3 · 색인을 넣었는데 그대로 느리다

인덱스 추가했다는데 체감이 똑같아요.

흔한 일이고, 원인은 보통 셋 중 하나예요. 화면이 실제로 쓰는 조건과 색인이 어긋났거나, 묶음 색인의 앞 칸이 아니라 뒤 칸으로만 찾고 있거나, 애초에 느린 원인이 색인이 아니라 목록을 전부 불러와 그리고 있는 것이거나요. 이때 필요한 건 색인을 더 붙이는 게 아니라 원인을 다시 재는 거예요.

남에게 맡길 때 요구할 것

인덱스 작업은 눈에 보이는 결과물이 없어요. 화면이 안 바뀌니 "했다"는 말만 남기 쉬워요. 그래서 외주로 맡길 때는 결과물을 숫자로 받는 게 중요해요.

  1. 1전후 측정값을 받으세요. "주문 목록 첫 화면: 작업 전 8.2초, 작업 후 0.4초"처럼 화면 이름과 초가 함께 적혀야 해요.
  2. 2무엇에 붙였는지 한 문장으로 받으세요. "가게 번호와 주문 시각 묶음으로 색인 하나"면 충분해요. 이 문장을 못 쓰면 근거 없이 붙인 거예요.
  3. 3되돌리는 방법을 확인하세요. 색인은 지워도 기록이 안 사라지니 되돌리기가 쉬운 작업이에요. 그 사실을 아는 사람이라면 편하게 답해요.
  4. 4작업 시간대를 합의하세요. 기록이 많은 표는 만드는 동안 쓰기가 막힐 수 있어요. 손님이 적은 시간으로 잡고, 멈춤 없이 만드는 방법이 있는지 물어보세요.
  5. 5다음에 어디가 느려질지를 물어보세요. 좋은 답은 "주문이 10만 건을 넘으면 통계 화면이 다음 차례"처럼 구체적이에요.

숫자 없는 보고는 받지 마세요

"많이 빨라졌습니다"는 보고가 아니에요. 측정은 어렵지 않아요. 브라우저에서 화면을 열고 다 뜰 때까지 초를 세는 것만으로도 충분히 비교돼요. 사장님이 직접 세어 본 숫자가 가장 강한 근거예요.

자주 묻는 것

Q. 색인을 붙이면 기록이 바뀌나요? 손님 명단이 위험해지진 않아요?
원본 기록은 그대로예요. 찾아가는 길만 따로 만드는 일이라, 지워도 기록이 남아요. 그래도 손대기 전 백업은 습관으로 두세요. 백업과 복구 편에 방법이 있어요.
Q. 색인은 몇 개까지 괜찮아요?
정해진 숫자는 없어요. 다만 표 하나에 대여섯 개를 넘어가면 한 번 정리할 시점이에요. 기준은 개수가 아니라 "이 색인을 실제로 쓰는 화면이 있는가"예요. 쓰는 화면을 못 대는 색인은 지우는 게 이득이에요.
Q. 바이브캠퍼스로 만든 서비스는 제가 색인을 직접 만들어야 하나요?
직접 만들 일은 거의 없어요. 목록 화면을 만들 때 필요한 설정은 대개 함께 잡혀요. 사장님이 할 일은 느려진 화면을 알아채고 말해 주는 것이에요. 어느 화면이 몇 초 걸리는지가 가장 쓸모 있는 정보예요.
Q. 이름으로 검색하는 화면도 색인으로 빨라져요?
전화번호처럼 앞에서부터 정확히 맞춰 찾는 검색은 잘 빨라져요. 반면 "이름 가운데에 김이 들어간 사람"처럼 중간을 찾는 검색은 일반 색인이 잘 못 도와줘요. 그건 검색 전용 방식이 따로 필요해요. 개발자가 "중간 검색은 인덱스가 안 먹어요"라고 하면 맞는 말이에요.
Q. 지금은 기록이 300건이에요. 미리 붙여 둘까요?
안 그래도 돼요. 300건에서는 차이가 안 느껴지고, 어떤 화면이 자주 쓰일지도 아직 몰라요. 실제로 쓰이는 화면이 정해진 뒤에 그 화면에 맞춰 붙이는 게 정확해요. 미리 짐작해서 붙인 색인은 대개 안 쓰이는 색인이 돼요.
Q. 느린 게 색인 문제인지 다른 문제인지 어떻게 구분해요?
간단한 갈림길이 있어요. 기록을 늘렸을 때만 느려지면 색인이나 목록 나누기 문제예요. 기록 수와 무관하게 늘 3초쯤 걸리면 화면 그리는 쪽이나 연결 문제예요. 후자는 성능 편이 다뤄요.

확인해 보세요

주문 목록 화면이 "내 가게 주문을 최근 순으로 20개" 보여줘요. 색인을 어디에 붙이는 게 맞을까요?

하나 더

방문 기록 표에 초당 여러 줄이 쌓여요. 이 표를 볼 일은 한 달에 한 번이에요. 색인을 붙일까요?

직접 해보기

느린 화면 하나를 스튜디오에 설명해 보세요

고칠 필요는 없어요. "주문 목록이 느려요. 이 화면이 무엇으로 걸러내고 무엇으로 줄 세우는지, 색인이 필요한 자리가 어디인지 알려 주세요"라고 물어보는 연습이면 충분해요. 조건을 문장으로 만드는 것이 이 문서의 절반이에요.

스튜디오 열기

더 깊이 (안 읽어도 괜찮아요)

찾아보기 비유가 어디부터 다른가 · 종이 찾아보기는 사람이 손으로 고쳐 쓰지만, 데이터베이스 색인은 기록이 들어올 때마다 자동으로 제자리에 끼워져요. 그리고 종이 색인은 순서가 흐트러지면 다시 만들어야 하는데, 데이터베이스 색인은 스스로 균형을 맞춰서 어느 쪽으로도 치우치지 않게 유지해요. 그 덕에 백만 줄에서도 짚는 횟수가 스무 번 남짓에 머물러요.

실행 계획이라는 말을 듣게 되면 · 데이터베이스는 요청을 받으면 "전부 훑을까, 색인을 쓸까"를 스스로 고르고, 그 결정을 보여주는 기능이 있어요. 개발자가 "실행 계획을 보니 인덱스를 안 타네요"라고 말하면 만들어 둔 색인을 데이터베이스가 안 쓰기로 했다는 뜻이에요. 조건이 어긋났거나, 색인을 쓰는 게 더 느리다고 판단한 거예요. 색인이 없다는 말과는 다르니 구분해서 들으세요.

정렬만으로도 느려질 수 있어요 · 걸러내기는 빠른데 줄 세우기가 느린 경우가 있어요. 조건에 맞는 것을 다 골라 놓고 그다음에 전부 정렬해야 하면, 골라낸 개수가 많을 때 그 정렬이 병목이 돼요. 그래서 걸러내는 칸과 줄 세우는 칸을 한 묶음 색인에 함께 넣는 게 목록 화면의 정석이에요. 골라낸 결과가 이미 순서대로 나오니 정렬 단계가 사라져요.

유일함을 보장하는 색인 · 색인에는 "이 값은 겹치면 안 된다"는 규칙을 함께 걸 수 있어요. 같은 이메일로 두 번 가입되는 사고나, 같은 주문번호가 두 개 생기는 사고를 데이터베이스가 직접 막아 줘요. 속도 얘기로만 알기 쉬운데, 실무에서는 이 중복 방지 쪽이 더 값진 경우도 많아요.

이것만 기억하세요

  • ·색인은 장부 뒤 찾아보기예요. 기록은 그대로 두고 찾아가는 길만 만들어요
  • ·느려지는 자리는 걸러내는 조건과 줄 세우는 조건이에요. 그 둘을 한 묶음으로 붙여요
  • ·색인은 쓸 때 대가를 치러요. 기록이 적거나 값 종류가 두세 개면 붙이지 않아요
  • ·처방은 색인 말고도 네 가지 더 있어요. 서버 키우기는 맨 마지막이에요
  • ·맡길 때는 전후 초와 붙인 자리를 문장으로 받으세요. 숫자 없는 보고는 보고가 아니에요
VibeCampus새 빌드