채팅 서버에 PostgreSQL과 MongoDB를 함께 사용하는 이유

shjk·2025년 3월 25일

실시간 채팅 서버를 구축할 때, 데이터 저장 방식과 처리 속도는 시스템의 전반적인 성능과 직결된다. 본 프로젝트에서는 데이터 저장소로 PostgreSQL과 MongoDB를 함께 사용하는 폴리글랏 퍼시스턴스(Polyglot Persistence) 아키텍처를 채택하였다. 본 글에서는 두 데이터베이스의 차이를 정리하고, 이 둘을 함께 사용하는 이유를 기술한다.


1. PostgreSQL과 MongoDB의 구조적 차이

항목PostgreSQLMongoDB
데이터 모델관계형(Relational)문서 기반(Document-Oriented)
스키마엄격한 스키마(Schema-on-Write)유연한 스키마(Schema-less)
쿼리 언어SQLBSON 기반의 쿼리 문법
트랜잭션ACID 완전 지원4.0 이후 다큐먼트 수준 트랜잭션 지원
인덱싱다양한 인덱싱 기능 제공복합 인덱스 및 텍스트 인덱싱에 강점
성능 특성복잡한 조인과 정규화에 적합읽기/쓰기 속도 및 확장성에 우수
저장 단위테이블, 로우컬렉션, 도큐먼트

2. 각각의 역할: 정형 vs 비정형 데이터 분리

채팅 시스템은 본질적으로 다음과 같은 이질적인 데이터 특성을 가진다.

2.1. 정형 데이터: 사용자 및 메타 정보 → PostgreSQL

  • 회원 정보 (id, 닉네임, 비밀번호 해시, 권한 등)
  • 채팅방 정보 (생성일자, 참여자, 고유 식별자 등)
  • 채팅방 참여 기록 및 메타데이터
  • 사용자 차단, 신고 내역 등 정규화 가능한 관계형 데이터

이러한 데이터는 명확한 스키마가 존재하고 정합성이 중요한 특성을 가지므로, PostgreSQL의 관계형 모델과 ACID 트랜잭션이 유리하다.

2.2. 비정형 데이터: 메시지 로그 → MongoDB

  • 메시지 본문 (텍스트, 이모지, 파일 링크 등)
  • 발신자, 수신 시간, 읽음 여부 등의 다양한 속성
  • 메시지 구조가 유동적일 수 있음 (예: 파일 메시지, 시스템 메시지 등)

메시지는 대량으로 쌓이는 로그성 데이터이며, 읽기/쓰기의 속도와 확장성이 핵심이므로, MongoDB의 도큐먼트 지향 모델과 수평 확장 기능이 적합하다.


3. 두 DB를 함께 사용하는 이유

✅ 성능과 확장성의 균형

  • PostgreSQL은 정합성을 확보해야 하는 사용자 기반 데이터 처리에 탁월하다.
  • MongoDB는 대규모 메시지 로그를 빠르게 쓰고 읽을 수 있다.

이를 통해, 각 DB의 강점을 살리면서도 병목을 최소화할 수 있다.

✅ 구조적 책임 분리 (Separation of Concerns)

  • DB 구조가 단순화되어 유지보수가 용이해진다.
  • 메시지 저장 로직과 사용자 인증/관리 로직이 독립적으로 관리된다.

✅ 향후 기능 확장 용이성

  • MongoDB의 유연한 스키마 덕분에 다양한 메시지 타입 (예: 투표 메시지, 위치 공유 등)을 빠르게 반영할 수 있다.
  • PostgreSQL의 강력한 SQL 기능을 활용하여 통계, 필터링, 권한 제어를 손쉽게 확장할 수 있다.

4. 구현 예시 구조

📦 backend/
 ┣ 📂 db/
 ┃ ┣ 📜 postgres.go       // 사용자, 채팅방 관련 CRUD
 ┃ ┗ 📜 mongo.go          // 메시지 저장 및 조회
 ┣ 📂 handlers/
 ┃ ┣ 📜 auth.go
 ┃ ┣ 📜 chatroom.go
 ┃ ┗ 📜 message.go
 ┣ 📜 main.go
// 메시지 저장 로직 예시 (MongoDB)
func SaveMessage(msg Message) error {
    collection := mongoClient.Database("chat").Collection("messages")
    _, err := collection.InsertOne(context.TODO(), msg)
    return err
}
// 사용자 조회 로직 예시 (PostgreSQL)
func GetUserByID(id int) (User, error) {
    row := pgDB.QueryRow("SELECT id, nickname FROM users WHERE id=$1", id)
    var user User
    err := row.Scan(&user.ID, &user.Nickname)
    return user, err
}

결론

PostgreSQL과 MongoDB는 상반된 철학을 가진 데이터베이스이지만, 서로 보완적으로 사용될 수 있다. 채팅 서버와 같이 정형/비정형 데이터가 공존하는 시스템에서는 단일 DB로 모든 요구사항을 해결하기보다, 역할에 따라 분리된 저장 전략을 설계하는 것이 더 안정적이고 확장 가능한 아키텍처를 만든다.


추후에는 Redis를 도입하여 메시지 전송의 실시간성과 캐시 처리 성능까지 향상시킬 예정이다.

profile
백엔드 개발자

0개의 댓글