확장 — 1만 명 · 10만 명
갱신일 2026-08-11 · 기준: CA 실측 형상 + SA §10 + ADR 0006 이 문서가 갖는 것: 부하 모델, 무엇이 어떤 순서로 부러지는가, 언제 무엇을 하는가. 네 축의 상세는 아래 문서들이 갖는다.
⚠︎ 이건 계획이지 현황이 아니다. 지금 서 있는 것은 현재 판 아키텍처 문서들이 갖는다. 여기 적힌 수는 전부 추정이고, 실측이 들어오면 갈아엎는다.
| 축 | 문서 | 갖는 것 |
|---|---|---|
| IA | 정보 구조 | 화자·그래프·외부 클라이언트가 화면에 만드는 변화 |
| AA | 애플리케이션 | 서비스 다섯 · 의존 방향 · 소유권 · 파이프라인 |
| SA | 시스템 | 경계 열하나 · 인증 · 런타임 흐름 · 새 천장 |
| CA | 클라우드 | ECS 형상 · GPU 운용 · 오디오 경로 · 관측 · AWS 운영 · 비용 |
| — | 데이터 | 저장소 다섯의 소유권 · 원본/파생 경계 · 무엇을 지워도 되나 · 재생성 경로 |
| — | ERD | 물리 스키마 — 테이블·칼럼·FK·제약 · 삭제 사슬 · 마이그레이션 순서 |
| — | 온톨로지 | 그래프 노드·관계 · 근거 규칙 · 가능해지는 기능 |
| — | 실시간 경로 | 오디오·채팅 스트림 개선 · 회의 중 에이전트 |
1. 확장과 함께 들어오는 것 다섯
규모만 커지는 게 아니다. 제품이 같이 바뀐다. 둘을 한 문서에서 보는 이유는 서로를 제약하기 때문이다.
| 무엇 | 아키텍처에 무엇을 요구하나 |
|---|---|
| Soniox 실시간 STT | 공급자 교체. 오디오는 서버를 지난다(§5) — egress와 릴레이 부하가 그대로 남는다 |
| pyannote 화자 분리 (배치) | GPU · 배치 · 오디오 보관 — 지금 아키텍처에 없는 세 가지가 한꺼번에. 실시간 대안이 없어 확정이다 |
| voice print | 생체정보 취급 · 별도 저장·삭제 경로 |
| Neo4j graph RAG | 네 번째 저장소 · 회의를 넘는 맥락 · 파생 규칙 |
| MCP · CLI | 두 번째 public edge · 토큰 인증 · 호출 상한 |
| 회의 중 에이전트 | 전사 스트림의 새 소비자 · LLM 부하가 버스트에서 지속으로 · 실시간 경로 |
2. 부하 모델 — 먼저 가정을 박는다
사용자 수는 부하가 아니다. 동시에 진행 중인 회의 수가 부하다. 아래를 바꾸면 이 문서의 모든 수가 따라 바뀐다.
| 가정 | 값 |
|---|---|
| DAU / 등록 사용자 | 20% |
| DAU 1인당 회의 참여 | 0.5건/일 |
| 회의당 참가자 | 4명 |
| 평균 회의 길이 | 45분 |
| 업무일 | 월 22일 |
| 피크 집중도 | 하루 회의의 25%가 피크 1시간에 시작 |
| 등록 1만 | 등록 10만 | |
|---|---|---|
| DAU | 2,000 | 20,000 |
| 회의 | 250건/일 · 5,500건/월 | 2,500건/일 · 55,000건/월 |
| 전사 시간 | 4,125시간/월 | 41,250시간/월 |
| 피크 동시 회의 | 50건 | 500건 |
| 피크 동시 WebSocket | 200 | 2,000 |
| 정각 종료 버스트 | 30건 동시 | 300건 동시 |
마지막 줄이 제일 중요하다. 회의는 정각에 끝난다. 부하가 고르게 퍼지지 않고 :00과 :30에 벽처럼 선다. 그리고 이제 그 벽 뒤에 GPU 배치가 있다.
3. 회의 종료가 한 방에서 다섯 단계가 된다
이게 이번 변화의 본체다. 지금은 종료 → 요약 한 방이고, 앞으로는 이렇다.
| 따라오는 요구 | 어디서 다루나 |
|---|---|
| 오디오를 저장해야 한다 (지금은 안 한다) | CA §8 |
| GPU를 파산하지 않고 운용해야 한다 | CA §6 |
| 단계별 실패·건너뛰기·재시도 | AA §3 |
| 대기 시간이 화면에 드러난다 | IA §5 |
| 5단계를 관통하는 트레이스 | CA §10 |
4. 천장이 걸리는 순서
순서가 중요하다. 뒤엣것을 먼저 고쳐도 앞엣것에서 막힌다.
| # | 천장 | 내용 |
|---|---|---|
| ① | ai 1GB + 동시 실행 상한 없음 | 정각 버스트에 OOM. 1만 명 문제가 아니라 지금 문제다 |
| ② | t4g 크레딧 소진 | 동시 50회의는 버스트가 아니라 지속 부하다. 크레딧이 마르면 small 0.4 vCPU · micro 0.2 vCPU로 산다. 에러 없이 느려지기만 한다 |
| ③ | STOMP 내부 브로커 | enableSimpleBroker 는 JVM 안이다. 2대로 늘리면 팬아웃이 조용히 반쪽 난다. 수평 확장·무중단 배포의 유일한 전제 |
| ④ | RDS db.t4g.micro Single-AZ | 1GB 안에서 OLTP와 pgvector가 싸운다. deletion_protection=false·skip_final_snapshot=true 는 사고 한 방에 끝나는 설정이다 |
| ⑤ | server 경유 오디오 | egress·CPU·대역폭이 한 대에 몰린다 (§5) |
| ⑥ | GPU 배치 처리량 | 새로 생기는 천장. 정각 300건 동시 |
| ⑦ | 전사 쓰기량 · 그래프 순회 · MCP 폭주 | SA §10 |
①④ 는 오늘 코드에 이미 있는 것이고, ⑤⑦ 은 새로 들어오는 것이다.
5. 결정 둘 — 오디오는 서버를 지나고, 화자 분리는 배치로 한다
앞선 판에서 미확인으로 두었던 두 가지가 결정됐다. 둘 다 비용이 늘어나는 쪽이다. 그래서 이 문서의 나머지가 그 위에 다시 선다.
| 결정 | 대안이었던 것 | 왜 이쪽 |
|---|---|---|
오디오는 브라우저 → 서버 → Soniox | 브라우저 → Soniox 직결 | 아래 |
| 화자 분리는 pyannote 배치 | Soniox 실시간 화자 분리 | 실시간 품질이 쓸 만하지 않다 |
오디오가 서버를 지나서 잃는 것
전사 1시간당 egress 230MB — 측정값이다. 이게 그대로 남는다.
| 전사 시간/월 | egress/월 | 비용/월 (추정) | |
|---|---|---|---|
| 지금 | 717시간 | 165GB | 약 $8 |
| 등록 1만 | 4,125시간 | 0.95TB | 약 $110 |
| 등록 10만 | 41,250시간 | 9.5TB | 약 $1,190 |
돈보다 큰 건 대역폭과 CPU가 백엔드에 몰린다는 것이다. 동시 500 스트림이면 상시 32MB/s를 릴레이하면서 STOMP 팬아웃과 REST를 같이 진다. 그래서 전사 릴레이 분리가 10만 구간에서 선택이 아니라 필수가 된다.
대신 얻는 것 — 이게 공짜가 아니다
| 얻는 것 | 왜 중요한가 |
|---|---|
| 전사 위조가 불가능해진다 | 서버가 Soniox 응답을 직접 받는다. 클라이언트가 보낸 텍스트를 믿을 필요가 없다 |
| 오디오 보관이 단순해진다 | 릴레이하면서 서버가 S3에 쓴다. 브라우저 이중 업로드·presigned 발급이 사라진다 |
| 브라우저가 단순해진다 | Soniox 단기 토큰 발급 경로가 통째로 없다 |
| 사용량 계측·차단이 경로 위에 있다 | 한도 초과를 실시간으로 끊을 수 있다 |
전사 위조 문제가 사라진 게 제일 크다. 직결 안에서는 이걸 막으려면 배치 재전사(전사 원가 2배)까지 갔어야 했다. 그 비용이 없어졌으므로 egress $1,190과 배치 재전사 비용을 맞바꾼 셈이고, 회의록 무결성이 중요한 제품이라면 나쁜 교환이 아니다.
화자 분리를 배치로 하면
pyannote가 확정이므로 GPU는 조건부가 아니라 상수다. CA §6의 운용 규칙(평소 0대 · Spot · 평탄화 우선)이 그만큼 더 중요해진다 — 이제 이게 인프라 최대 항목이다.
대신 배치 전사는 하지 않는다. 위조 문제가 없으므로 실시간 전사가 곧 정본이고, 오디오는 화자 분리에만 쓴다.
6. 등록 1만 명 — 무엇을 하는가
순서대로. 위에서부터 하지 않으면 아래가 의미 없다.
| # | 무엇 | 왜 지금 |
|---|---|---|
| 1 | RDS Multi-AZ + deletion_protection + 최종 스냅숏 | 사용자 데이터가 실재한다 |
| 2 | ai 분석에 동시 실행 상한 + 외부 큐 | 정각 버스트에 1GB가 OOM 난다 |
| 3 | STOMP 외부 브로커 릴레이 | 모든 수평 확장·무중단 배포의 전제 |
| 4 | APP-189 (재기동 시 전역 세션 중단) 해결 | 3번을 해도 이게 남으면 2대째가 1대째를 끊는다 |
| 5 | ECS Fargate로 이전 + ALB · IaC 같이 | 서비스가 다섯이면 손으로 굴리는 EC2가 다섯 배가 된다. 클러스터를 콘솔로 만들면 그때부터 늦다 |
| 6 | ai 분리·증설 | PgSingleFlight 덕에 지금도 수평 확장이 된다. 막는 건 크기뿐 |
| 7 | 오디오 S3 보관 + speech 서비스 + 파이프라인 5단계 | 화자 분리의 전제. 서버가 릴레이하면서 S3에 쓴다 |
| 8 | voice print — 생체정보 취급 설계 | 나중에 얹을 수 없다. 스키마·키·삭제 경로를 처음부터 |
| 9 | Neo4j + 그래프 투영 | 파생 규칙과 재생성 경로를 처음부터 박는다 — 온톨로지 |
| 10 | mcp 서비스 + 토큰·범위·상한 | 두 번째 public edge |
| 11 | server↔ai 인증 · access token 갱신 경로 | 인스턴스가 늘면 보안그룹만으로 안 된다 |
| 12 | 관측 유료 전환 + 파이프라인 트레이스 | Fargate는 host가 없어 push 모델이다. 5단계를 로그로 디버깅하는 건 불가능하다 |
| 12.5 | staging 환경 | 5단계 파이프라인을 prod에서 처음 돌리면 안 된다 |
| 13 | 워치독 스케줄러 리더 선출 | 2대가 되면 스케줄러가 둘 다 돈다 |
| 14 | 전사 릴레이 부하 실측 | 오디오가 서버를 지나므로 §7의 분리 시점을 수치로 잡아야 한다 |
| 15 | 오디오 Float32 → Int16 | 몇 줄로 대역폭 절반. 규모와 무관하게 이득 — 실시간 §7 |
| 16 | 전사 세션 재개 + 공유 챗봇 관전자 STOMP | 배포·장애가 한 코드로 처리되고 폴링이 사라진다 |
1~4는 성능이 아니라 정확성·생존 문제다. 5부터가 용량이고, 7부터가 새 기능이다.
7. 등록 10만 명 — 그다음
| # | 무엇 | 왜 |
|---|---|---|
| 15 | 정각 버스트 평탄화 (지연 + 지터) | 제일 싸고 효과가 크다. 정각 300건 → 5분에 300건이면 필요한 GPU가 한 자릿수로 떨어진다 |
| 16 | 전사 릴레이를 별도 서비스로 분리 | 동시 500 스트림 × 32MB/s 상시 릴레이가 REST·STOMP와 한 프로세스에 있으면 한쪽 스파이크가 다른 쪽을 죽인다. heymoa-transcription-worker 저장소가 이미 있다 |
| 17 | 읽기 복제본 + 세그먼트 쓰기 배치화 | |
| 18 | 벡터를 전용 스토어로 | pgvector를 OLTP와 같이 두는 건 1만까지 |
| 19 | organization 계층 (결제·SSO·감사) | IA §2 |
| 20 | project 경로 · 검색 1급 화면 | 워크스페이스당 노트 1,000건이 조건 |
| 21 | 알림 폴링 → push | 폴링이 그 자체로 부하가 된다 |
| 22 | 그래프 순회 깊이·팬아웃 상한 | 깊이·팬아웃 상한 → 온톨로지 §7 |
| 23 | LLM·STT 원가를 제품 정책으로 | 요금제·회의 길이 상한·재분석 정책 |
| 24 | 회의 중 에이전트 (C3 충돌만) | 그래프가 선 다음. LLM 호출이 요약의 6~20배가 되므로 게이트 정밀도가 곧 원가 — 실시간 §4 |
8. 비용
인프라는 문제가 아니다. 외부 API가 문제다. 상세는 CA §16.
| 등록 1만 (월) | 등록 10만 (월) | |
|---|---|---|
| 인프라 전체 (GPU 포함, 추정) | 약 $1,100 | 약 $5,000~7,000 |
| — 그중 GPU 배치 | $150~300 | $1,500~3,000 |
| — egress (오디오가 서버를 지난다) | $110 | $1,190 |
| Soniox 전사 | 4,125시간 | 41,250시간 |
| OpenAI 요약·채팅 | 5,500건 + 채팅 | 55,000건 + 채팅 |
아래 두 줄에 단가를 못 넣었다. 모른다. 시간당 $0.2만 돼도 10만에서 전사만 월 $8,000 이고, 위 인프라 전부보다 크다. 배치 재전사는 하지 않으므로 이 줄이 두 배가 되지는 않는다(§5).
결론은 인프라 결정이 아니라 제품 결정이다.
9. 설계 전제
- 동시 회의 수로 사이징한다. 등록 사용자 수로 하지 않는다. §2만 고치면 나머지가 따라온다.
- 정각을 부하의 기본 단위로 본다. 평균 처리량으로 사이징하면 매시 정각마다 무너진다.
- 버스트는 인스턴스보다 평탄화로 먼저 줄인다. 사용자는 "1분 뒤"와 "3분 뒤"를 구분하지 못하고, 스팟 시장은 구분한다.
- 정본은 Postgres 다. 그래프·벡터는 지우고 다시 만든다. 오디오만 예외이고 그래서 짧게 산다.
- 생체정보는 처음부터 따로 설계한다. 나중에 분리할 수 없다.
- 외부 API 원가를 아키텍처 제약으로 취급한다.
10. 미확인 — 확인 순서대로
§5의 결정 둘이 앞선 판의 1·2번을 지웠다. 남은 것.
| # | 무엇 | 무엇이 걸려 있나 |
|---|---|---|
| 1 | Soniox·OpenAI 실계약 단가 | §8의 빈 두 줄. 원가가 제품 정책을 정한다 |
| 2 | pyannote 처리 시간 · GPU 필요 여부 | speech 인스턴스 수·타입·타임아웃. CPU로 되면 훨씬 싸다 |
| 3 | 전사 릴레이 실측 부하 | 스트림당 서버 CPU·메모리. §7 16번(분리)의 시점을 정한다 |
| 4 | Spot 확보 가능성 (서울 g5·g6) | 안 되면 GPU 원가가 3배 |
| 5 | voice print 매칭 정확도·임계값 | 틀린 이름 vs 이름 없음의 교환비 |
| 6 | 현재 사용자 수 대비 전사 시간 | 월 165GB ⇒ 약 717시간/월. 활성 사용자 수로 나누면 §2가 실측이 된다 |
| 7 | Neo4j 재생성 소요 | "파생" 규칙이 실현 가능한지 |
| 8 | 결정·액션 아이템 추출 정확도 | 나쁘면 파이프라인에 사람 확인 단계가 하나 더 붙는다 |
| 9 | MCP로 내보낼 범위 | 보안·원가 양쪽 |
1과 2가 원가를 지배한다. 나머지는 만들면서 나온다.