Daeseon Yoo
Back to project
·Decision·6 min

멀티리전 DB 결정: 미국/한국 사용자, DB를 둘로 나눌까?

미국/한국 사용자를 위해 DB를 둘로 나눌지 논의. 결론은 '지금은 1개'. 데이터를 리전으로 쪼개는 건 규정(데이터 거주) 해법이지 속도 해법이 아니고, 우리 앱의 cross-user 기여 링크를 깨뜨린다. 속도는 함수/DB 코로케이션 → 미디어 CDN → (나중) 읽기 복제본으로 푼다. 측정 전 분리는 자해. (논의 메모 — 구현 아님.)

질문

"미국 사용자랑 한국 사용자는 다른데, DB를 2개 만들어서 구분시킬 수 있나? 나중에 진지하게 고민하고 싶다."

처음엔 막연히 "사용자가 다르니 DB도 나눠야 하나" 싶었지만, 파고드니 두 개의 서로 다른 질문이 섞여 있었다.

먼저 갈라야 했던 것: "다르다"가 무슨 뜻인가

  1. UX·언어 차이 — 영어 화면 / 한국어 화면, 카피 분기. → 이건 이미 만들어 둔 i18n(ko/en, lib/copy.ts) 이 해결한다. 데이터가 어디 저장되든 사용자별로 다른 언어·경험을 보여주는 건 앱 레이어의 일이다.
  2. 데이터가 어디 저장되는가 — 지연(latency)과 법규(데이터 거주). → 이게 진짜 "DB를 나눈다"의 영역이다.

둘은 완전히 별개다. 내가 나누려던 진짜 이유속도/지연 이었다 (미국 사용자가 서울 DB까지 매번 왕복하면 느릴까봐). 그래서 그 관점에서만 보면 —

핵심 결론: 데이터를 리전으로 쪼개는 건 "속도" 해법이 아니다

데이터를 둘로 나누는 건 데이터 거주(규정) 를 위한 도구다. 속도 때문에 그걸 하면 도구를 잘못 고른 것이다. 이유:

우리 앱만의 함정: cross-user 기여 링크

곁에는 기여 링크가 있다 (코드로 확인: app/api/links/route.ts가 토큰을 발급하고, 다른 사람app/api/c/[token]/route.ts로 들어와 주인의 보관함에 한마디를 남긴다).

DB를 리전으로 가르면:

한국 사용자가 만든 링크를 미국에 있는 친구가 열 때, 그 토큰이 미국 DB엔 없어서 안 풀린다. 공유·기여 기능이 리전 경계에서 깨진다.

이걸 살리려면 링크에 region을 심거나 작은 공용 매핑 테이블을 둬야 한다 → 복잡도 급증. 거기에 DB 2개 = 관리·과금·마이그레이션·백업 전부 2배.

속도를 푸는 올바른 사다리 (싸고 효과 큰 순서)

  1. DB를 주 사용자 리전에 두고, Vercel 함수 리전을 거기 맞춘다. 곁은 한국 우선 → Supabase 서울 + 함수 리전 icn1. 미국 사용자는 바다를 한 번 건너지만, 이 앱은 가벼운 개인 메모형이라 체감이 작다.
  2. 미디어는 CDN(S3 + CloudFront). 사용자가 속도를 체감하는 건 사진·음성·영상이고, 그건 CDN 엣지가 지역 지연을 이미 풀어준다. 텍스트 쿼리 지연은 작다.
  3. 풀링된 커넥션(Supabase pooler) — 서버리스 콜드 커넥션 지연 제거. 리전과 무관하게 필수.
  4. 요청당 쿼리 수 줄이기 / 캐시 — 더 빠른 DB보다 왕복 횟수를 줄이는 게 더 크다.
  5. 미국 트래픽이 실제로 커지면 → 읽기 복제본(read replica). 이게 지역 지연의 정석 해법이다: 미국 함수는 가까운 복제본에서 읽고, 쓰기는 본 DB로. 2개 DB의 읽기-속도 장점은 다 주면서 데이터는 하나로 유지 → 기여 링크가 안 깨진다.

결정

한 줄

데이터를 리전으로 쪼개는 건 규정 때문에만 한다. 속도는 함수–DB 코로케이션 → 미디어 CDN → (나중) 읽기 복제본으로 풀고, 이 셋은 모두 하나의 논리적 데이터셋을 유지해 cross-user 기능을 살려둔다. 측정하지 않은 지연 때문에 데이터를 샤딩하지 말 것.

(이 글은 논의·결정 메모다. 코드 변경은 없었다 — 앱은 이미 단일 DATABASE_URL로 동작하며, 이 결정은 그 설계를 유지한다.)