데이터베이스 선택 가이드

← 기술 결정 목록

결정: PostgreSQL 15+ 상태: 승인됨


목차


1. 후보 데이터베이스 비교

1.1 관계형 데이터베이스 (RDBMS)

PostgreSQL ✅ (선택)

장점:

단점:

MySQL/MariaDB

장점:

단점:

비교 요약

기능 PostgreSQL MySQL
ACID 트랜잭션 ✅ 완벽 ✅ 지원
JSON/JSONB ✅ JSONB (인덱싱 가능) ⚠️ JSON (제한적)
파티셔닝 ✅ 강력함 ⚠️ 제한적
Read Replica ✅ 용이 ✅ 지원
복잡한 쿼리 ✅ 우수 ⚠️ 제한적
확장성 ✅ 우수 ⚠️ 보통
성능 ✅ 우수 ✅ 우수 (읽기)

1.2 NoSQL 데이터베이스

MongoDB

장점:

단점:

Co-Talk에 부적합한 이유:

Redis

장점:

단점:

Co-Talk에서의 역할:


2. Co-Talk 프로젝트 요구사항 분석

2.1 데이터 모델 특성

관계형 데이터:

특징:

2.2 쿼리 패턴

복잡한 쿼리 예시:

  1. 친구 목록 조회 (최근 메시지 포함)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    
    SELECT 
     u.id, u.nickname, u.avatar_url,
     m.content as last_message,
     m.created_at as last_message_time
    FROM friends f
    JOIN users u ON f.friend_id = u.id
    LEFT JOIN (
     SELECT DISTINCT ON (chat_room_id) 
         chat_room_id, content, created_at
     FROM messages
     WHERE chat_room_id IN (
         SELECT id FROM chat_rooms 
         WHERE id IN (
             SELECT chat_room_id FROM chat_room_members 
             WHERE user_id = $1
         )
     )
     ORDER BY chat_room_id, created_at DESC
    ) m ON ...
    WHERE f.user_id = $1 AND f.status = 'accepted'
    ORDER BY m.created_at DESC;
    
  2. 채팅방 목록 조회 (읽지 않은 메시지 수 포함)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    
    SELECT 
     cr.id,
     u.nickname as other_user_name,
     COUNT(CASE WHEN m.id IS NOT NULL AND m.read_at IS NULL THEN 1 END) as unread_count,
     MAX(m.created_at) as last_message_time
    FROM chat_rooms cr
    JOIN chat_room_members crm ON cr.id = crm.chat_room_id
    JOIN users u ON crm.user_id = u.id AND u.id != $1
    LEFT JOIN messages m ON cr.id = m.chat_room_id
    WHERE crm.user_id = $1
    GROUP BY cr.id, u.nickname
    ORDER BY last_message_time DESC;
    

PostgreSQL의 장점:

2.3 트랜잭션 요구사항

친구 요청 수락 시:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
BEGIN;
  -- 1. 친구 요청 상태 업데이트
  UPDATE friend_requests SET status = 'accepted' WHERE id = $1;
  
  -- 2. Friends 테이블에 양방향 관계 추가
  INSERT INTO friends (user_id, friend_id, status) VALUES ($2, $3, 'accepted');
  INSERT INTO friends (user_id, friend_id, status) VALUES ($3, $2, 'accepted');
  
  -- 3. 채팅방 생성
  INSERT INTO chat_rooms (type) VALUES ('direct') RETURNING id;
  
  -- 4. 채팅방 멤버 추가
  INSERT INTO chat_room_members (chat_room_id, user_id) VALUES ($4, $2);
  INSERT INTO chat_room_members (chat_room_id, user_id) VALUES ($4, $3);
COMMIT;

PostgreSQL의 장점:


3. PostgreSQL의 Co-Talk에 특화된 장점

3.1 JSONB 지원

사용 사례:

예시:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
-- 사용자 프로필에 메타데이터 저장
CREATE TABLE users (
    id UUID PRIMARY KEY,
    email VARCHAR(255),
    nickname VARCHAR(50),
    profile_metadata JSONB  -- 유연한 확장
);

-- JSONB 인덱싱 및 쿼리
CREATE INDEX idx_users_metadata ON users USING GIN (profile_metadata);

-- 쿼리 예시
SELECT * FROM users 
WHERE profile_metadata @> '{"preferences": {"theme": "dark"}}';

MySQL과 비교:

3.2 파티셔닝

메시지 테이블 파티셔닝:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
-- 월별 파티셔닝
CREATE TABLE messages (
    id UUID,
    chat_room_id UUID,
    sender_id UUID,
    content TEXT,
    created_at TIMESTAMP
) PARTITION BY RANGE (created_at);

-- 파티션 생성
CREATE TABLE messages_2024_01 PARTITION OF messages
    FOR VALUES FROM ('2024-01-01') TO ('2024-02-01');
CREATE TABLE messages_2024_02 PARTITION OF messages
    FOR VALUES FROM ('2024-02-01') TO ('2024-03-01');

장점:

MySQL과 비교:

3.3 복잡한 인덱싱

복합 인덱스 예시:

1
2
3
4
5
6
7
8
9
-- 메시지 조회 최적화
CREATE INDEX idx_messages_room_time 
ON messages(chat_room_id, created_at DESC) 
INCLUDE (sender_id, content);

-- 친구 목록 조회 최적화
CREATE INDEX idx_friends_user_status 
ON friends(user_id, status) 
INCLUDE (friend_id);

PostgreSQL의 고급 인덱스:

3.4 Read Replica 설정

PostgreSQL의 장점:

설정 예시:

1
2
3
4
5
6
-- Primary 서버 설정
wal_level = replica
max_wal_senders = 3

-- Replica 서버 설정
primary_conninfo = 'host=primary_server port=5432 user=replicator'

3.5 확장성

수직 확장:

수평 확장:


4. 성능 비교

4.1 읽기 성능

작업 PostgreSQL MySQL MongoDB
단순 조회 ✅ 우수 ✅ 우수 ✅ 우수
복잡한 JOIN ✅ 우수 ⚠️ 보통 ❌ 불가
집계 쿼리 ✅ 우수 ✅ 우수 ⚠️ 제한적
전문 검색 ✅ 우수 ⚠️ 제한적 ✅ 우수

4.2 쓰기 성능

작업 PostgreSQL MySQL MongoDB
단일 삽입 ✅ 우수 ✅ 우수 ✅ 우수
배치 삽입 ✅ 우수 ✅ 우수 ✅ 우수
트랜잭션 ✅ 완벽 ✅ 지원 ⚠️ 제한적
동시성 ✅ 우수 ⚠️ 보통 ✅ 우수

4.3 대규모 트래픽 처리

10,000 TPS 처리:

차이점:


5. Co-Talk 프로젝트에서의 활용

5.1 데이터 모델링

PostgreSQL의 장점:

예시:

1
2
3
4
5
6
7
CREATE TABLE friends (
    id UUID PRIMARY KEY,
    user_id UUID REFERENCES users(id),
    friend_id UUID REFERENCES users(id),
    status VARCHAR(20) CHECK (status IN ('pending', 'accepted', 'blocked')),
    UNIQUE(user_id, friend_id)
);

5.2 확장성 고려

현재 (MVP):

확장 시:

5.3 향후 기능 확장

그룹 채팅:

메시지 검색:

알림:


6. 다른 데이터베이스와의 하이브리드 전략

6.1 PostgreSQL + Redis

PostgreSQL:

Redis:

6.2 PostgreSQL + Elasticsearch (향후)

PostgreSQL:

Elasticsearch:


7. 최종 선택 이유 요약

✅ PostgreSQL 선택 이유

  1. 관계형 데이터 모델링
    • 친구 관계, 채팅방 멤버 등 복잡한 관계
    • JOIN 쿼리 최적화
  2. 트랜잭션 보장
    • 친구 추가, 메시지 저장 시 여러 테이블 업데이트
    • ACID 트랜잭션 필수
  3. 복잡한 쿼리
    • 친구 목록 (최근 메시지 포함)
    • 채팅방 목록 (읽지 않은 메시지 수)
    • PostgreSQL의 고급 기능 활용
  4. 확장성
    • Read Replica로 읽기 확장
    • 파티셔닝으로 대용량 데이터 관리
    • 향후 샤딩 가능
  5. 유연성
    • JSONB로 NoSQL처럼 사용 가능
    • 향후 기능 확장 용이
  6. 성능
    • 복잡한 쿼리에서도 우수한 성능
    • 인덱싱 최적화

❌ 다른 데이터베이스가 부적합한 이유

MySQL:

MongoDB:

Redis:


8. 결론

PostgreSQL이 Co-Talk 프로젝트에 최적인 이유:

  1. 관계형 데이터: 친구 관계, 채팅방 멤버 등 복잡한 관계 모델링
  2. 트랜잭션: 데이터 일관성 보장 필수
  3. 복잡한 쿼리: 친구 목록, 채팅방 목록 등 복잡한 조회
  4. 확장성: Read Replica, 파티셔닝으로 대규모 트래픽 처리
  5. 유연성: JSONB로 향후 기능 확장 용이
  6. 성능: 복잡한 쿼리에서도 우수한 성능

하이브리드 전략: