DB 분리 전략 - KimGyuBek/Threadly GitHub Wiki
서비스 특성에 따라 DB를 분리하였다.
| 구분 | PostgreSQL | MongoDB |
|---|---|---|
| 데이터 구조 | 관계형 (RDB) | 문서형 (Document) |
| 스키마 | 고정 스키마, 명확한 제약 조건 | 스키마 유연, 구조 변경 용이 |
| 트랜잭션 | ACID 보장, 복잡한 트랜잭션 지원 | 단일 문서 수준 트랜잭션 강점, 복잡 트랜잭션은 제한적 |
| 관계 처리 | 조인(Join) 등 강력 | 조인 약함, 중첩 문서로 대체 |
| 성능 특성 | 쓰기·갱신 안정적 | 대규모 읽기·조회 성능 강점 |
| 확장성 | Scale-up 중심, 파티셔닝 가능 | Scale-out(샤딩) 용이 |
| 적합한 경우 | 엔티티 연관 관계 많고 무결성 요구 | 이벤트 로그, 조회 위주, 비정형 데이터 |
- 게시글, 댓글, 팔로우 등 엔티티 간 연관 관계가 복잡함
- 트랜잭션과 무결성이 중요하여 PostgreSQL이 적합.
- 데이터 무결성(참조 무결성, Unique 제약 등) 보장이 필요.
- 알림 이벤트, 읽음 여부 등 단순 구조 데이터 중심.
- 엔티티 연관 관계가 거의 없음.
- 알림은 사용자의 조회 비율이 매우 높기에 빠른 읽기 성능이 중요.
- 알림 타입 추가, 스키마 변경이 잦기 떄문에 MongoDB의 스키마 유연성이 강점.
- 특히
NotificationDoc.metadata는 다형적 구조(`PostLikeMeta, CommentMeta 등)로, 알림 타입마다 필드 구성이 달라지는데 이는 문서형 DB와 자연스럽게 맞아떨어진다.
//NotificationMetaData.java
public sealed interface NotificationMetaData //다형 메타데이터 인터페이스
permits PostLikeMeta, PostCommentMeta, CommentLikeMeta, FollowRequestMeta, FollowMeta,
FollowAcceptMeta {
}/*NotificationDoc.java*/
@Document(collection = "notifications")
public class NotificationDoc {
//...
@JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = As.PROPERTY,
property = "type"
)
@JsonSubTypes({
@JsonSubTypes.Type(value = PostLikeMeta.class, name = "POST_LIKE"),
@JsonSubTypes.Type(value = PostCommentMeta.class, name = "COMMENT_ADDED"),
@JsonSubTypes.Type(value = CommentLikeMeta.class, name = "COMMENT_LIKE"),
@JsonSubTypes.Type(value = FollowRequestMeta.class, name = "FOLLOW_REQUEST"),
@JsonSubTypes.Type(value = FollowMeta.class, name = "FOLLOW"),
@JsonSubTypes.Type(value = FollowAcceptMeta.class, name = "FOLLOW_ACCEPT")
})
private NotificationMetaData metadata;
// ...
}MongoDB 저장 예시
{
"receiver_id": "v050K70cHmI6uFNt",
"sort_id": {
"$oid": "68c9510335541b3b06df769c"
},
"notification_type": "POST_LIKE",
"is_read": false,
"metadata": {
"postId": "afjsZ7mxTq1wn1uN",
"_class": "com.threadly.notification.core.domain.notification.metadata.PostLikeMeta"
},
"occurred_at": {
"$date": "2025-09-16T11:58:59.294Z"
},
"actor_profile": {
"userId": "v050K70cHmI6uFNt",
"nickname": "test_user",
"profileImageUrl": "/"
},
"_class": "com.threadly.notification.adapter.persistence.notification.doc.NotificationDoc"
}PostgreSQL로도 구현할 수는 있지만, 알림 타입이 자주 늘어나고 구조 변경이 잦은데다가 조회가 많다 보니 MongoDB가 훨씬 다루기 편하고 운영하기 좋다고 판단했다.
그리고 단일 DB만 사용하기 보다 PostgreSQL과 MongoDB를 함께 적용해보고 싶었다. 이렇게 나누면서 두 DB의 장단점을 직접 경험할 수 있었고, 체감이 컸다.
- 서비스 독립성: 알림 폭주로 인한 부하가 본 서비스(threadly-service)에 영향을 주지 않는다.
- 데이터 특성 최적화: 관계형(연관 다수/무결성) <-> 문서형(조회 많고 변형 잦음) 매칭
- 엔티티 연관 관계가 많고 무결성이 중요한 영역 -> PostgreSQL
- 단순 구조, 조회 중심, 스키마 변경 유연성이 중요한 영역 -> MongoDB