OpenAI는 어떻게 PostgreSQL을 스케일했을까
- 개발
- 2026. 3. 10. 23:21
국내에서는 많은 기업들이 MySQL을 사용하는 경우가 많습니다. 그래서 다른 회사들이 어떤 데이터베이스를 사용하는지에 대해서는 크게 의식하지 않았습니다. 그러다가 우연히 OpenAI가 수억 명의 사용자 규모까지 서비스를 확장한 과정을 설명한 글을 읽게 되었습니다.
(https://blog.bytebytego.com/p/how-openai-scaled-to-800-million) 글을 읽다 보니 OpenAI가 PostgreSQL을 사용하고 있다는 점이 눈에 들어왔습니다. 다양한 데이터베이스가 존재하는데 왜 PostgreSQL을 선택했는지 궁금해졌습니다. 물론 이 글에서 PostgreSQL을 선택한 명확한 이유가 직접적으로 설명되지는 않습니다. 다만 일반적으로 PostgreSQL은 안정성과 성숙한 생태계를 갖춘 관계형 데이터베이스로 알려져 있습니다. 또한 복잡한 쿼리 처리 능력과 확장 기능이 강점으로 꼽히기 때문에 많은 서비스에서 기본적인 선택지로 사용되기도 합니다. 결국 OpenAI가 PostgreSQL을 선택한 이유가 반드시 특별한 기술적 이유 때문이라고 보기는 어렵지만, 안정적이고 검증된 관계형 데이터베이스라는 점에서 자연스러운 선택이었을 가능성이 높다고 생각했습니다.
Open Ai는 왜 스케일을 선택하였을까?
답은 간단합니다. 사용자가 급격히 증가했기 때문입니다.
OpenAI의 서비스는 매우 빠르게 성장했습니다. 예를 들어 GPT 출시 이후 API 서비스와 기업 고객이 늘어나면서 사용자 규모가 수억 명 수준까지 확대되었습니다.
사용자가 늘어나면 자연스럽게 서비스 요청도 증가합니다.
사용자가 증가하면 API 요청이 많아지고, 그 결과 데이터베이스에 대한 조회와 쓰기 요청 역시 함께 증가하게 됩니다.
만약 이런 상황에서 데이터베이스를 스케일하지 않는다면 어떤 문제가 발생할까요?
데이터베이스가 증가한 요청을 감당하지 못하게 되면 응답 속도가 느려지고, 동시에 데이터베이스 연결(connection)이 급격히 늘어나게 됩니다. 결국 이러한 상황이 지속되면 데이터베이스가 병목 지점이 되어 서비스 장애로 이어질 가능성이 높아집니다.
따라서 이러한 문제를 방지하기 위해 데이터베이스를 확장(Scaling) 하는 전략이 필요하게 됩니다.
DB확장 포인트
데이터베이스를 확장하기 위해서는 먼저 어디에서 병목이 발생하는지를 생각해 볼 필요가 있습니다.
즉, 쓰기 성능을 확장해야 하는지, 아니면 읽기 성능을 확장해야 하는지를 판단해야 합니다.
일반적으로는 읽기(Read) 성능부터 확장하는 경우가 많습니다.
먼저 성능 개선 단계로 쿼리 최적화 → 인덱스 사용 → 캐시 도입을 진행합니다. 그래도 문제가 해결되지 않는다면 레플리케이션(Replication)을 통해 읽기 트래픽을 분산합니다.
이후에도 트래픽이 계속 증가한다면 쓰기(Write) 성능 확장을 고려하게 됩니다.
앞서 살펴본 것처럼 OpenAI의 사용자 수는 급격하게 증가했습니다. 사용자 수가 증가했다는 것은 그만큼 쓰기 요청 또한 함께 증가했을 가능성이 높습니다.
그렇다면 자연스럽게 쓰기 성능 확장도 필요해 보입니다.
하지만 OpenAI는 쓰기 확장을 선택하지 않고, 레플리케이션을 통해 읽기 트래픽을 분산하는 구조를 사용했습니다.
그렇다면 어떻게 이런 구조로도 대규모 트래픽을 처리할 수 있었을까요?
그 이유는 생각보다 쓰기 요청이 많지 않기 때문입니다.
크게 3가지 이유가 있습니다.
대부분의 서비스는 읽기 >쓰기 구조입니다.
예를 들어, 사용자 프로필 조회, 설정 조회, 대화 기록 조회, API 상태 조회등 같은 요청들은 대부분 읽기 요청입니다.
그래서 보통 읽기 90% 쓰기 10%정도 구조가 됩니다. 그래서 Open AI도 읽기 트래픽을 분산 하는 것만으로도 큰 효과를 얻을 수 있었습니다.
하지만 OpenAI는 ChatGPT라는 LLM을 사용합니다. LLM은 채팅을 입력을 하게 되면 그것에대한 응답을 작성해줍니다.
여기서 OpenAI가 쓰기작업을 한다고 여겨집니다. 그렇다면, 읽기 90% 쓰기 10%는 OpenAI한테는 다른 의미인걸까요?
그 이유는 ChatGPT 응답은 DB가 아니라 GPU에서 처리가 되어지기 때문입니다.
사용자가 질문을 하면 실제로 일어나는 일은 이렇습니다.
User 질문 -> API Server -> LLM 모델 실행(GPU) -> 응답 생성
여기서 핵심 연산은 모델 추론입니다. 이 과정은 DB, SQL과 거의 관련이 없습니다.
즉, ChatGPT 응답 생성 은 GPU 계산입니다.
그래서 OpenAI도 읽기 트래픽을 분산하는 것만으로도 큰 효과를 얻을 수 있습니다.
여기까지 이해한 내용으로는 LLM 요청 자체는 데이터베이스의 쓰기 작업과 직접적인 관련이 없다는 점을 알 수 있었습니다. 하지만 여전히 의문이 완전히 해소된 것은 아닙니다.
LLM의 응답 생성이 GPU에서 이루어진다고 하더라도, 수억 명 규모의 사용자에게 발생하는 서비스 트래픽을 생각하면 여전히 상당한 쓰기 요청이 발생할 가능성이 있기 때문입니다.
예를 들어 사용자 수가 증가하면 자연스럽게 다음과 같은 데이터가 기록될 수 있습니다.
- API 사용량 기록
- billing 정보
- 사용자 활동 로그
- 시스템 메타데이터
이러한 정보들은 결국 데이터베이스에 저장되어야 합니다. 그렇다면 8억 명 규모의 사용자 환경에서 발생하는 쓰기 트래픽을 어떻게 감당할 수 있었을까요?
OpenAI는 Primary DB가 하는 일을 최소화했습니다.
일반적으로 Primary 역할은 쓰기만 담당하고 읽기는 Replica로 보냅니다.

이렇게 되면 Primary DB는 쓰기 작업만 처리하게 됩니다.
하지만 읽기와 쓰기 데이터베이스를 분리했다고 하더라도 데이터베이스에 부담이 완전히 사라지는 것은 아닙니다.
이를 해결하기 위해 OpenAI는 데이터베이스에 부담을 주는 요소를 최대한 줄이는 방향으로 시스템을 설계했습니다.
예를 들어 느린 쿼리를 제거하고, 인덱스를 최적화하며, connection pool을 사용하는 방식으로 데이터베이스 부하를 줄였습니다.
특히 PostgreSQL은 connection = process 구조를 가지고 있습니다.
즉, 데이터베이스 연결이 하나 생성될 때마다 하나의 프로세스가 생성됩니다.
따라서 connection 수가 과도하게 증가하면 메모리 사용량이 증가하고 context switching이 발생하면서 성능이 저하될 수 있습니다.
이를 해결하기 위해 connection pool을 사용하여 데이터베이스에 직접 연결되는 connection 수를 제한하고, 효율적으로 관리할 수 있도록 했습니다.
PostgreSQL은 connection 하나마다 하나의 process가 생성되는 구조를 가지고 있습니다.
이 방식은 thread 기반 구조에 비해 약간의 성능 비용이 발생할 수 있지만, 대신 높은 안정성을 제공하는 장점이 있습니다.
예를 들어 하나의 process에서 문제가 발생하더라도 해당 connection만 종료되며, 다른 connection에는 영향을 주지 않습니다.
즉, 하나의 요청에서 오류가 발생하더라도 데이터베이스 전체가 영향을 받지 않도록 격리된 구조로 동작합니다.
이러한 특성 때문에 PostgreSQL은 안정성과 신뢰성이 중요한 환경에서 널리 사용되는 데이터베이스 중 하나로 평가됩니다.
결론
물론 이것이 OpenAI의 PostgreSQL 확장 전략의 전부는 아닙니다.
글에서는 MVCC를 비롯해 더 깊이 있는 내용들도 함께 다루고 있으며, 실제로 어떤 방식으로 문제를 해결했는지에 대한 설명도 이어집니다.
이번 글에서는 그중에서도 OpenAI가 PostgreSQL을 어떤 방향으로 확장했는지, 그리고 왜 쓰기 확장보다 읽기 확장과 Primary DB 부하 최소화에 집중했는지를 중심으로 정리해보았습니다.
결국 중요한 점은 데이터베이스를 무작정 바꾸는 것이 아니라, 현재 사용 중인 데이터베이스를 어떻게 효율적으로 운영하고 확장할 것인지 고민하는 과정이라고 생각합니다.
출처
https://blog.bytebytego.com/p/how-openai-scaled-to-800-million
https://openai.com/ko-KR/index/scaling-postgresql/
'개발' 카테고리의 다른 글
| Actuator 메트릭 생성 하기 (0) | 2026.03.11 |
|---|---|
| Actuator (0) | 2026.03.11 |
| 프록시 JDBC(2) (0) | 2026.03.09 |
| 프록시 JDBC(1) (0) | 2026.03.08 |
| 분명... slow쿼리를 모니터링하려고 했는데... 어째서... (0) | 2026.03.06 |