"당신의 한 문장이 베스트셀러의 시작이 됩니다." 누구나 작가가 되어 실시간으로 소설을 완성하는 집단 지성 창작 플랫폼
문서 구조:
- PART 1: 공통 (Common) - 프로젝트 개요, 팀 구성, 기술 스택, 기능 명세
- PART 2: AS-IS (Monolithic) - 초기 단일 애플리케이션 아키텍처 (2025.12.23 ~ 2026.01.10)
- PART 3: TO-BE (MSA) - Microservices Architecture (2026.01.11 ~ 현재) ✅ 현재 운영
- 프로젝트 소개
- 팀원 및 역할 분담
- 기술 스택
- 주요 기능 & 유스케이스
- 요구사항
- ERD 설계
- Database Schema
- 팀 그라운드 룰 (XP)
- 단위 테스트 결과서
- API 테스트 결과서
프로젝트 전반에 대한 개요, 팀 구성, 기술 스택, 기능 요구사항을 다룹니다.
Next Page는 한 사람이 모든 이야기를 쓰는 것이 아니라, 여러 사용자가 문장 단위로 이어 쓰며 하나의 소설을 완성하는 릴레이 창작 서비스입니다.
단순한 게시판이 아닙니다. WebSocket을 활용한 실시간 타이핑 표시, 순서(Sequence) 제어, 투표 기반 평가가 결합된 몰입형 창작 플랫폼입니다. 앞사람이 글을 완료해야만 뒷사람이 쓸 수 있는 동시성 제어와 도메인 규칙을 엄격하게 준수합니다.
- 2025.12.23 ~ 2026.01.16 (총 4주)
- Phase 1 - Monolithic (2025.12.23 ~ 2026.01.10): 단일 Spring Boot 애플리케이션
- Phase 2 - MSA (2026.01.11 ~ 현재): Microservices Architecture로 전환 완료 ✅
| 기능 영역 | 상태 | 완료 항목 |
|---|---|---|
| ⚡ 실시간/웹소켓 | ✅ 완료 | 실시간 타이핑/편집 잠금, 댓글/문장 실시간 푸시, STOMP 프로토콜 최적화 |
| 🔐 인증/인가 | ✅ 완료 | JWT, Refresh Token, 강제 로그인 모달, Soft Delete(User) |
| 👤 회원 관리 | ✅ 완료 | 회원가입/탈퇴, 실시간 입력값 검증, 마이페이지 대시보드 |
| 📖 소설 집필 | ✅ 완료 | 문장 이어쓰기(순서 제어), 마지막 문장만 수정/삭제(Restriction), 편집 중 잠금(Lock) |
| 📚 소설 조회 | ✅ 완료 | 무한 스크롤, 페이징/정렬, 책 넘김 효과 뷰어, 내가 쓴 글/댓글 모아보기 |
| ❤️ 반응/평가 | ✅ 완료 | 실시간 댓글(WebSocket), 계층형 대댓글, 개추/비추 투표, Soft Delete(Comment) |
| 🏗️ MSA 전환 | ✅ 완료 | Eureka, Gateway + JWT Filter, Feign Client, 3개 DB 분리, Application Level Join |
| 🛡️ 안정성 | ✅ 완료 | Resilience4j (Circuit Breaker) 적용, 장애 전파 방지 및 Fallback 처리 |
| API & Architecture | ✅ 완료 | HATEOAS, CQRS, Swagger, Dynamic Topic Routing (/topic/{bookId}) |
| 🎨 UI/UX | ✅ 완료 | Cute Pop 디자인, 로고 폰트(Gaegu), 모달 UX 개선, 토스트 알림 |
| 🧪 테스트 | ✅ 완료 | 전체 API 시나리오 테스트 (http/api-test.http), 단위/통합 테스트 환경 |
우리는 도메인 주도 설계(DDD) 원칙에 따라, 기능 단위가 아닌 도메인(Context) 단위로 역할을 분담하여 전문성을 높였습니다.
| 이름 | 포지션 | 담당 도메인 & 핵심 역할 |
|---|---|---|
| 정진호 | Team Leader | 🏛 Core & Architecture - 프로젝트 아키텍처 설계 (CQRS, WebSocket, MSA 전환) - 실시간 타이핑 및 알림 시스템 구현 - Story 애그리거트 상태/순서 제어 로직✍️ Writing & Query - 문장 작성(Append) 및 유효성 검사 - 동적 쿼리(MyBatis) 기반 조회/검색 최적화 |
| 김태형 | Sub Leader | 🔐 Member & Auth - Spring Security + JWT 인증/인가 시스템 - Soft Delete를 적용한 안전한 회원 탈퇴/관리 - 실시간 유효성 검증 로직 및 마이페이지 - MSA: member-service 구축 및 Internal API 제공 |
| 정병진 | Developer | ❤️ Reaction & Support - 개추/비추(Thumb Up/Down) 투표 시스템 - 계층형 댓글(대댓글) 구조 설계 및 구현 - 관리자 권한(댓글/유저 관리) 기능 구현 - MSA: reaction-service 구축 및 양방향 Feign 통합 |
| 최현지 | Document Manager | 📄 Documentation & QA - 프로젝트 문서화 및 리드미(README) 관리 - API 명세 및 개발자 가이드 최신화 - 전체 기능 QA 및 시나리오 점검 |
- IDE: IntelliJ IDEA
- JDK: Java 17 (Amazon Corretto or Azul Zulu)
- Database: MariaDB 10.6+
- Build Tool: Gradle
- Framework: Spring Boot 3.5.9
- RESTful API: 자원(Resource) 중심의 명확한 URI 설계 및 HTTP Method 활용
- CQRS Pattern:
- Command (쓰기): JPA (Domain Logic, Dirty Checking) - 데이터 무결성 보장
- Query (읽기): MyBatis (Dynamic Query) - 복잡한 통계/조회 성능 최적화
- Event-Driven: WebSocket을 통한 실시간 상태 동기화 (작성 중, 댓글 작성 등)
사용자와 관리자가 시스템에서 수행할 수 있는 주요 시나리오입니다.
flowchart TD
User((일반 회원))
Guest((게스트))
Admin((관리자))
subgraph "👤 Member Domain"
Auth[회원가입/로그인]
Withdraw[회원 탈퇴]
MyPage[마이페이지]
ViewActivity[활동 내역 조회]
end
subgraph "📖 Story Domain - 창작"
CreateBook[소설방 생성]
AppendSentence[문장 이어쓰기]
EditSentence[마지막 문장 수정]
CompleteBook[소설 수동 완결]
end
subgraph "📚 Story Domain - 감상"
BrowseBooks[소설 목록 조회]
ReadBook[소설 상세 보기]
ViewerMode[완결 소설 뷰어 모드]
end
subgraph "❤️ Reaction Domain"
WriteComment[댓글 작성]
WriteReply[대댓글 작성]
VoteBook[소설 투표]
VoteSentence[문장 투표]
end
subgraph "⚡ Realtime Features"
TypingIndicator[타이핑 인디케이터]
LiveUpdate[실시간 업데이트]
end
%% Guest Interactions
Guest --> BrowseBooks
Guest --> ReadBook
Guest --> ViewerMode
Guest -.->|require login| Auth
%% User Interactions - Member
User --> Auth
User --> Withdraw
User --> MyPage
User --> ViewActivity
%% User Interactions - Story
User --> CreateBook
User --> AppendSentence
User --> EditSentence
User --> CompleteBook
User --> BrowseBooks
User --> ReadBook
User --> ViewerMode
%% User Interactions - Reaction
User --> WriteComment
User --> WriteReply
User --> VoteBook
User --> VoteSentence
%% User Interactions - Realtime
User <-.-> TypingIndicator
User <-.-> LiveUpdate
%% Admin Interactions
Admin --> Auth
Admin -.->|manage| User
Admin -.->|moderate| WriteComment
Admin -.->|delete| CreateBook
%% Relationships
CreateBook --> AppendSentence
AppendSentence --> EditSentence
AppendSentence --> CompleteBook
ReadBook --> WriteComment
WriteComment --> WriteReply
ReadBook --> VoteSentence
BrowseBooks --> VoteBook
-
실시간 타이핑 인디케이터:
- 누군가 문장을 작성 중이면 다른 사용자들에게 "홍길동님이 문장을 쓰고 있어요..." 표시
- 댓글 작성 중에도 동일하게 작동
- 작성 중일 때 다른 사람의 입력 차단 (동시성 제어)
-
라이브 업데이트:
- 새 소설이 생성되면 메인 페이지에 즉시 표시
- 문장이 추가되면 읽고 있는 모든 사용자에게 실시간 반영
- 댓글이 달리면 즉시 업데이트
전체 Flow:
-
소설방 개설 (작가A)
- 제목, 장르, 최대 문장 수 설정
- 첫 문장 작성 (예: "어느 날, 하늘에서 이상한 물체가 떨어졌다.")
-
문장 이어쓰기 (작가B, C, D...)
- 이전 문장을 읽고 다음 스토리 전개
- 제약 조건:
- 직전 작성자는 연속으로 쓸 수 없음 (최소 1명 대기)
- 현재 순서(sequence)만 작성 가능
- 실시간 타이핑 중에는 다른 사람 입력 차단
-
수정 규칙
- 마지막 문장만 수정/삭제 가능 (스토리 일관성 유지)
- 중간 문장 수정 불가 → 완결 후 전체 다운로드하여 2차 창작 가능
-
완결
- 자동 완결: 최대 문장 수 도달 시
- 수동 완결: 방장이 임의로 완결 처리
- 완결 후 뷰어 모드로 전환
-
계층형 댓글:
- 부모 댓글과 대댓글 구조 (depth 제한 없음)
- Soft Delete로 삭제된 댓글도 "[삭제된 댓글입니다]"로 구조 유지
-
투표 시스템:
- 소설 전체 평가: 좋아요(개추) / 싫어요(비추)
- 문장별 평가: 베스트 문장 선정
- 1인 1투표, 토글 방식 (취소 가능)
신규 사용자 (게스트) → 활발한 작가
- 소설 목록 둘러보기 (비로그인 가능)
- 재미있는 소설 발견 → 회원가입 모달 표시
- 회원가입 (이메일 중복 체크, 비밀번호 강도 검증)
- 로그인 후 자동으로 소설 상세 페이지 이동
- 문장 이어쓰기 → 실시간 타이핑 경험
- 마이페이지에서 내 활동 확인
- 새 소설방 개설 → 커뮤니티 확장
프로젝트 분석 결과에 따른 완전한 기능(Functional) 및 비기능(Non-Functional) 요구사항 명세입니다.
| ID | 분류 | 요구사항 명 | 상세 내용 | 비고 |
|---|---|---|---|---|
| FR-M01 | Auth | 이메일 회원가입 | 이메일, 비밀번호, 닉네임 입력. 이메일 형식(Regex) 및 비밀번호 복잡도(8자 이상, 특수문자 포함) 검증 | 실시간 중복 체크 |
| FR-M02 | Auth | 로그인 | 이메일/비밀번호 인증. 성공 시 JWT Access Token(Body) 및 Refresh Token(Cookie) 발급 | Access: 1h, Refresh: 7d |
| FR-M03 | Auth | 토큰 재발급 (Silent Refresh) | Access Token 만료 시, HttpOnly Cookie의 Refresh Token으로 인증하여 Access Token 재발급 | 보안 강화 |
| FR-M04 | Auth | 로그아웃 | Refresh Token 쿠키 삭제 및 만료 처리. 클라이언트 측 Access Token 폐기 | - |
| FR-M05 | Member | 내 정보 조회 (마이페이지) | 본인의 닉네임, 이메일, 가입일, 활동 통계(작성한 소설/문장/댓글 수) 조회 | - |
| FR-M06 | Member | 내 활동 내역 조회 | 내가 작성한 소설, 문장, 댓글 리스트 페이징 조회 (최신순) | 탭(Tab) 구분 |
| FR-M07 | Member | 회원 정보 수정 | 닉네임 변경 가능 (중복 검사 포함). 비밀번호 변경 기능 | - |
| FR-M08 | Member | 회원 탈퇴 | DB에서 물리적 삭제가 아닌, 상태값(status)을 DELETED로 변경하는 Soft Delete 처리 |
30일 후 영구 삭제 가능 |
| FR-M09 | Member | 관리자 승인 (신규) | 관리자 가입 신청 시 PENDING 상태로 생성되며, 기존 관리자(Super Admin) 승인 후 ACTIVE 전환 |
보안 강화 |
| ID | 분류 | 요구사항 명 | 상세 내용 | 비고 |
|---|---|---|---|---|
| FR-S01 | Story | 소설방 생성 | 제목, 카테고리(스릴러/로맨스/판타지 등), 최대 문장 수 설정하여 생성 | 초기 커버 이미지 랜덤 배정 |
| FR-S02 | Story | 소설 목록 조회 | 무한 스크롤(Infinite Scroll) 기반 페이징. 최신순/인기순(참여자수/조회수) 정렬 | 검색/필터 지원 |
| FR-S03 | Story | 소설 상세/정보 조회 | 소설 메타데이터(작가, 진행률 등) 및 참여자 리스트 조회 | 실시간 업데이트 |
| FR-S04 | Writing | 문장 이어쓰기 (Append) | 현재 순서(current_seq)에 맞춰 새 문장 작성. 직전 작성자 연속 작성 불가 규칙 적용 |
동시성 제어 (Lock) |
| FR-S05 | Writing | 입력 유효성 검증 | 문장 길이 제한(10~200자), 비속어 필터링(선택적), 공백 제외 유효 글자 수 체크 | - |
| FR-S06 | Writing | 문장 수정 | 자신이 쓴 마지막 문장이면서, 뒤에 이어진 문장이 없을 때만 수정 가능 | 스토리 무결성 보장 |
| FR-S07 | Writing | 문장 삭제 | 자신이 쓴 마지막 문장에 한해 삭제 가능. 삭제 시 소설의 current_seq 롤백 |
- |
| FR-S08 | Story | 자동 완결 | 설정된 max_sequence에 도달하면 소설 상태가 COMPLETED로 자동 변경 |
- |
| FR-S09 | Story | 수동 완결 | 방장(최초 생성자) 권한으로 소설 조기 완결 처리 가능 | - |
| FR-S10 | Viewer | 완결 작품 뷰어 | 책 넘김 효과(Page Flip) 또는 스크롤 모드로 전체 스토리 정주행 | UX 최적화 |
| ID | 분류 | 요구사항 명 | 상세 내용 | 비고 |
|---|---|---|---|---|
| FR-R01 | Comment | 소설 댓글 작성 | 특정 소설에 대한 댓글 작성. 이모지 포함 가능 | - |
| FR-R02 | Comment | 대댓글 (Reply) | 댓글에 대한 답글 작성 (계층형 구조 지원) | Depth 제한 없음 |
| FR-R03 | Comment | 댓글 삭제 | 본인 작성 댓글 삭제. 대댓글이 있는 경우 "삭제된 메시지입니다" 로 내용만 마스킹 처리 | 대댓글 보존 |
| FR-R04 | Vote | 소설 개추/비추 | 소설 전체에 대한 좋아요/싫어요 투표. 1인 1투표, 토글(취소) 및 변경 가능 | - |
| FR-R05 | Vote | 문장 투표 | 특정 문장에 대한 좋아요 투표. "베스트 문장" 선정에 활용 | - |
| ID | 분류 | 요구사항 명 | 상세 내용 | 비고 |
|---|---|---|---|---|
| FR-RT01 | Socket | 문장 타이핑 알림 | 사용자가 문장 입력창에 타이핑 시, 타 사용자에게 "OOO님이 입력 중.." 표시 (Debounce 적용) | WebSocket (STOMP) |
| FR-RT02 | Socket | 댓글 타이핑 알림 | 댓글 작성 중인 상태 실시간 공유 | - |
| FR-RT03 | Socket | 실시간 문장 로딩 | 누군가 문장을 등록 완료하면(Commit), 새로고침 없이 화면에 즉시 문장 카드가 생성 | - |
| FR-RT04 | Socket | 실시간 댓글 로딩 | 누군가 댓글 등록 시 리스트에 즉시 반영 | - |
| FR-RT05 | Socket | 동시 편집 방지 (Lock) | 한 명이 작성 중(Typing 상태)일 때 타인의 입력창을 비활성화하여 충돌 방지 (선택적 UX) | - |
| ID | 분류 | 요구사항 명 | 상세 내용 | 비고 |
|---|---|---|---|---|
| FR-SYS01 | Infra | 서비스 검색(Discovery) | 모든 마이크로서비스는 Eureka Server에 자동 등록 및 헬스 체크 | 동적 스케일링 대비 |
| FR-SYS02 | Gateway | 요청 라우팅 | 단일 엔드포인트(Port 8000)로 모든 요청 수신 후 서비스별 라우팅 (/api/members, /api/books 등) |
- |
| FR-SYS03 | Infra | 중앙 설정 관리 | Config Server를 통해 application.yml 설정 중앙화 및 동적 갱신(Refresh) 지원 |
보안 민감정보 암호화 |
| FR-AD01 | Admin | 컨텐츠 관리 | (Admin 전용) 부적절한 소설/댓글 블라인드 또는 강제 삭제 처리 | - |
| FR-AD02 | Admin | 회원 관리 | (Admin 전용) 악성 유저 정지 및 강제 탈퇴 처리 | - |
| ID | 분류 | 요구사항 명 | 상세 구현 내용 | 중요도 |
|---|---|---|---|---|
| NFR-01 | Reliability | Circuit Breaker | 타 서비스 장애(Timeout/Fail) 시 즉시 에러를 전파하지 않고 Fallback(기본값) 반환 | 상 |
| NFR-02 | Security | Stateless Auth | 세션을 사용하지 않고 JWT + Gateway Filter 기반의 무상태 인증 아키텍처 구현 | 상 |
| NFR-03 | Performance | Traffic Splitting | 쓰기(Command)와 읽기(Query) 트래픽을 분리하여 조회 성능 최적화 (CQRS) | 중 |
| NFR-04 | Performance | Async Processing | 알림, 통계 집계 등 비동기 작업은 Event Driven 방식으로 처리 (추후 Kafka 도입 고려) | 중 |
| NFR-05 | Scalability | DB Isolation | 서비스별 전용 DB(Schema)를 사용하여 결합도 제거 및 독립적 확장 보장 | 상 |
| NFR-06 | Observability | API Tracing | Gateway에서 생성한 Request ID를 전파하여 분산 로그 추적 가능하게 설계 | 중 |
| NFR-07 | UX | Reactive UI | 모든 데이터 변경(생성/삭제)에 대해 페이지 새로고침 없는 Ajax/WebSocket 갱신 보장 | 상 |
| NFR-08 | Code | Standardization | 구글 자바 스타일 가이드 준수, Checkstyle 적용, 통합된 ErrorResponse 포맷 사용 | 하 |
MSA 아키텍처에 맞춰 3개의 데이터베이스로 분리된 구조를 반영했습니다. 서비스 간 관계는 물리적 FK가 아닌 **논리적 참조(Logical Reference)**로 연결됩니다.
erDiagram
%% Member Service
users {
BIGINT user_id PK
VARCHAR email
VARCHAR nickname
}
%% Story Service
books {
BIGINT book_id PK
BIGINT writer_id
VARCHAR title
}
sentences {
BIGINT sentence_id PK
BIGINT book_id FK
BIGINT writer_id
TEXT content
}
categories {
VARCHAR category_id PK
VARCHAR category_nm
}
%% Reaction Service
comments {
BIGINT comment_id PK
BIGINT book_id
BIGINT writer_id
TEXT content
}
book_votes {
BIGINT vote_id PK
BIGINT book_id
BIGINT voter_id
}
sentence_votes {
BIGINT vote_id PK
BIGINT sentence_id
BIGINT voter_id
}
%% Physical Relationships (Within Domain)
books ||--|{ sentences : "contains"
categories ||--o{ books : "categorizes"
comments ||--o{ comments : "replies"
%% Logical Links (Cross-Service)
users ||..o{ books : "logically creates"
users ||..o{ sentences : "logically writes"
users ||..o{ comments : "logically writes"
users ||..o{ book_votes : "logically votes"
users ||..o{ sentence_votes : "logically votes"
books ||..o{ comments : "logically has"
books ||..o{ book_votes : "logically has"
sentences ||..o{ sentence_votes : "logically has"
Database per Service 패턴을 적용하여, 각 마이크로서비스는 독립적인 데이터베이스를 소유합니다.
| 서비스 | 데이터베이스명 | 주요 테이블 |
|---|---|---|
| Member Service | next_page_member |
users, refresh_token |
| Story Service | next_page_story |
books, sentences, categories |
| Reaction Service | next_page_reaction |
comments, book_votes, sentence_votes |
우리 팀은 Extreme Programming (XP) 의 가치를 지향하며, 효율적이고 건강한 협업 문화를 만들기 위해 노력합니다.
👉 팀 그라운드 룰 상세 보기 (GROUND_RULES.md)
- 의사소통: 상시 공유와 구체적인 질문
- 단순성: 가독성 좋은 코드와 명확한 설계
- 피드백: 상호 존중 기반의 코드 리뷰
- 용기: 문제 공유 및 적극적인 개선 제안
- 존중: 사람 중심이 아닌 기술 중심의 논의
전체 마이크로서비스에 대해 수행된 단위/통합 테스트 명세와 결과입니다.
- 📝 전체 테스트 코드 보기 (소스 코드 포함) - 31개 테스트 파일의 전체 Java 소스 코드 (토글 형식)
- 📋 전체 테스트 명세서 - TC 코드 기반 252개 테스트 케이스 상세 문서
| 모듈 | 라인 커버리지 | 브랜치 커버리지 | 테스트 파일 수 | 테스트 메서드 수 |
|---|---|---|---|---|
| Common Module | 70% | 0% | 5 | 37 |
| Member Service | 82% | 72% | 10 | 90+ |
| Story Service | 90% | 63% | 5 | 75+ |
| Reaction Service | 97% | 80% | 5 | 50+ |
| 전체 평균 | 85% | 71% | 25 | 252+ |
✅ 모든 테스트 Pass 상태 | 목표: 라인 70% 이상, 브랜치 70% 이상
📄 상세 테스트 문서: 👉 전체 테스트 명세서 보기 (next-page-msa/TEST_DOCUMENTATION.md)
- TC 코드 체계 (TC-001.001.001) 기반 252개 이상 테스트 케이스 전체 문서화
- JaCoCo 테스트 커버리지 상세 분석
- 테스트 방식별 분류 (Unit/MockMvc/Integration)
- Common Module 포함 전체 모듈 테스트 커버리지
- 테스트 실행 방법 및 개선 필요 항목
# 전체 테스트 실행
./gradlew test
# 테스트 및 JaCoCo 리포트 생성
./gradlew test jacocoTestReport
# 커버리지 검증 (70% 기준)
./gradlew test jacocoTestCoverageVerificationJaCoCo 리포트 확인:
next-page-msa/[module]/build/reports/jacoco/test/html/index.html
전체 마이크로서비스의 REST API에 대해 수행된 통합 테스트 결과입니다.
- 🧪 API 통합 테스트 스크립트 - IntelliJ HTTP Client 기반 31개 API 테스트
- 📋 API 테스트 결과서 - 시나리오별 테스트 결과 상세 문서
| 서비스 | 총 API 수 | PASS | FAIL | 커버리지 |
|---|---|---|---|---|
| Member Service | 11 | 11 | 0 | 100% |
| Story Service | 12 | 12 | 0 | 100% |
| Reaction Service | 8 | 8 | 0 | 100% |
| 합계 | 31 | 31 | 0 | 100% |
✅ 전체 API 테스트 Pass 상태
1. 회원 가입 및 인증 (Member)
└─→ 2. 소설 생성 및 관리 (Story)
└─→ 3. 반응 및 투표 (Reaction)
└─→ 4. 관리자 승인 프로세스 (Admin)
└─→ 5. 콘텐츠 관리 및 삭제
└─→ 6. 데이터 정리 (Cleanup)
- IntelliJ IDEA에서
next-page-msa/http/api-test.http파일 열기 - 시나리오 순서대로 각 요청 실행 (▶ 버튼)
- 전역 변수 자동 설정 확인 (토큰, ID 등)
📄 상세 결과 문서: 👉 API 테스트 결과서 보기 (next-page-msa/docs/API-Test-Result.md)
- 31개 API 엔드포인트 전체 검증
- 시나리오별 상세 테스트 케이스 (TC 코드 체계)
- 투표 토글 로직, 연속 작성 제한, 권한 검증 등 특수 시나리오 포함
- 성공/실패 응답 형식 및 에러 코드 참조
초기 버전의 단일 애플리케이션 아키텍처 (2025.12.23 ~ 2026.01.10)
graph TD
Client[Client Browser]
App["Spring Boot Application<br/>(8080)"]
DB[(MariaDB: next_page)]
Client --> App
App --> DB
✅ 장점: 단순한 배포, 트랜잭션 관리 용이, 빠른 프로토타이핑 ❌ 한계: 낮은 확장성, 장애 전파, 기술 종속성
(생략 - 가이드 문서 참고)
Microservices Architecture 전환 (2026.01.11 ~)
- 확장성: 특정 기능만 스케일링 불가 (전체 재배포 필요)
- 장애 격리: 부분 장애 시 전체 시스템 다운
- 배포: 작은 변경도 전체 재배포 필요
- 팀 협업: 도메인별 독립 개발 어려움
| 날짜 | 작업 | 상태 |
|---|---|---|
| 2026-01-11 | Discovery Server, Gateway 구축 | ✅ |
| 2026-01-12 | DB 3개 분리 (member, story, reaction) | ✅ |
| 2026-01-13 | member-service 이관 | ✅ |
| 2026-01-14 | story-service, reaction-service 이관 | ✅ |
| 2026-01-15 | Config Server, Actuator, Feign 적용 | ✅ |
graph TD
Client["Client Browser"]
Gateway["API Gateway Server (8000)"]
Discovery["Discovery Server (8761)"]
Config["Config Server (8888)"]
subgraph "Domain Services"
Member["Member Service (8081)"]
Story["Story Service (8082)"]
Reaction["Reaction Service (8083)"]
end
subgraph "Databases"
DB_M[("DB: Member")]
DB_S[("DB: Story")]
DB_R[("DB: Reaction")]
end
Client --> Gateway
Gateway --> Member
Gateway --> Story
Gateway --> Reaction
Member --> DB_M
Story --> DB_S
Reaction --> DB_R
Member -.-> Discovery
Story -.-> Discovery
Reaction -.-> Discovery
Gateway -.-> Discovery
Member -.-> Config
Story -.-> Config
Reaction -.-> Config
Gateway -.-> Config
| 서비스 | 포트 | 주요 책임 |
|---|---|---|
| Config Server | 8888 | 중앙 설정 관리 (Git Repository 연동) |
| Discovery Server | 8761 | Eureka: 서비스 등록/탐색 |
| Gateway Server | 8000 | JWT 검증, 라우팅, 헤더 주입 (X-User-Id) |
| Member Service | 8081 | 회원가입/로그인, JWT 발급, 회원 정보 관리 |
| Story Service | 8082 | 소설 생성/조회, 문장 이어쓰기, WebSocket |
| Reaction Service | 8083 | 댓글/대댓글, 개추/비추 투표 |
- Config Server 도입: 모든 설정(
application.yml)을 Git에서 중앙 관리. - JPA 객체 참조 → ID 참조 전환: 서비스 간 결합도 제거.
- Application Level Join: 복잡한 연관관계를 Feign Client로 해결.
- Gateway JWT 필터: 인증/인가 로직을 Gateway로 이관하여 마이크로서비스는 비즈니스 로직에 집중.
- 통합 시나리오:
http/api-test.http를 통해 회원가입부터 소설 완결까지 전체 흐름 검증 완료. - 단위 테스트: 각 서비스(Member/Story/Reaction)의 핵심 비즈니스 로직에 대해 JUnit5 + Mockito 기반의 견고한 테스트 슈트 구축.
시스템의 핵심 흐름(Key Flows)을 보여주는 시퀀스 다이어그램입니다.
사용자가 로그인하여 토큰을 발급받는 과정입니다.
sequenceDiagram
autonumber
actor User
participant Gateway as API Gateway
participant Auth as Member Service
participant DB as Member DB
User->>Gateway: POST /api/auth/login <br/> {email, password}
Gateway->>Auth: Route Request
activate Auth
Auth->>DB: Find User by Email
DB-->>Auth: Return User Entity
Auth->>Auth: Verify Password (BCrypt)
Auth->>Auth: Generate Access Code & Refresh Token
Auth-->>Gateway: Return TokenResponse
deactivate Auth
Gateway-->>User: 200 OK <br/> (Body: AccessToken, Cookie: RefreshToken)
Gateway Filter가 헤더를 변환하고, Story Service가 동시성을 제어하며, WebSocket이 실시간 전파하는 전체 흐름입니다.
sequenceDiagram
autonumber
actor User
participant Gateway as API Gateway
participant Filter as JWT Filter
participant Story as Story Service
participant DB as Story DB
participant Socket as WebSocket Broker
Note over User, Gateway: Header: Authorization Bearer {Token}
User->>Gateway: POST /api/books/{id}/sentences
rect rgb(240, 240, 240)
Note right of Gateway: Gateway Processing
Gateway->>Filter: Intercept Request
Filter->>Filter: 1. Validate Token Signature
Filter->>Filter: 2. Parse Claims (UserId, Email)
Filter->>Gateway: 3. Add Headers (X-User-Id, X-User-Email)
end
Gateway->>Story: Route Request (with X-Headers)
activate Story
Story->>DB: SELECT * FROM books WHERE id=? <br/> (Pessimistic Lock / @Version)
DB-->>Story: Return Book + Lock
Story->>Story: Validate Sequence (Current vs Request)
Story->>Story: Check Previous Writer (Duplicate Prevention)
Story->>DB: INSERT into sentences
Story->>DB: UPDATE books SET current_seq++
par Async Notification
Story->>Socket: Send Message (/topic/books/{id})
Socket-->>User: Push Notification (New Sentence)
and Response
Story-->>Gateway: 201 Created
Gateway-->>User: 201 Created
end
deactivate Story
소설 조회 시 Feign Client를 통해 타 서비스(Member)의 데이터를 조회하고 병합하는 과정입니다.
sequenceDiagram
autonumber
actor User
participant Gateway
participant Story as Story Service
participant Member as Member Service (Feign)
User->>Gateway: GET /api/books/{id} (Viewer)
Gateway->>Story: Route Request
activate Story
Story->>Story: Fetch Book Data (WriterId=100)
rect rgb(240, 248, 255)
Note right of Story: Cross-Service Communication
Story->>Member: GET /internal/members/100
activate Member
Member-->>Story: Return {nickname: "Hong", ...}
deactivate Member
Note right of Story: Fallback if Member fails (Circuit Breaker)
end
Story->>Story: Aggregate Data (Book + Writer Nickname)
Story-->>Gateway: Return BookDetailDto
deactivate Story
Gateway-->>User: 200 OK (JSON)
"예상치 못한 변수와 기술적 난관을 팀워크로 극복하며, 단순 구현을 넘어 아키텍처 관점에서의 깊은 성장을 이뤘습니다."
"기획 단계의 변수와 MSA 전환 과정에서의 통신 이슈가 큰 도전이었습니다. 하지만 팀원들과 끝까지 방향을 맞춰가며 문제를 하나씩 해결했고, 마침내 시스템이 안정적으로 동작할 때 큰 보람을 느꼈습니다."
"우여곡절이 많았지만 적극적인 소통으로 기대 이상의 완성도를 달성했습니다. Gateway 인증 통합과 Circuit Breaker를 직접 구현하며 보안 기술과 MSA 요청 흐름을 깊이 체득할 수 있었던, 백엔드 개발자로서 크게 성장한 시간이었습니다."
"계층형 댓글 구조를 설계하며 클래스의 역할과 개발 흐름을 깊이 고민하게 되었습니다. 배운 내용을 실제 복잡한 아키텍처에 적용해보며 많은 것을 깨달았고, 함께 멋진 결과를 만들어낸 팀원들에게 감사함을 느낍니다."
"탄탄한 기획과 문서화가 개발 효율을 높인다는 것을 체감했습니다. 모듈 독립을 통해 장애 전파를 막는 내결함성의 중요성을 직접 확인했으며, 완성도 있는 구조 속에서 깊이 있게 공부할 수 있었던 뜻깊은 프로젝트였습니다."
상세한 REST API 명세(Request/Response 규격)는 별도 문서로 관리됩니다. 👉 API 상세 명세서 보러가기 (next-page-msa/API_SPECIFICATION.md)
Copyright © 2026 Team Next Page. All rights reserved.
