프로젝트 요구사항 분석과 설계
온라인 코드 편집기의 인증·파일 관리·실시간 협업 요구사항을 정리하고 서비스 경계와 데이터·API 구조를 설계합니다.
지난 12장에서는 NestJS를 활용한 서버리스 아키텍처, WebSocket 실시간 통신, CQRS 패턴, 그리고 도메인 주도 설계(DDD) 같은 고급 주제를 다뤘습니다.
13장에서는 지금까지 배운 내용을 묶어 실제 웹 애플리케이션 프로젝트를 기획하고, NestJS로 구현하는 과정을 단계별로 진행합니다.
이번 절은 그 출발점으로, 프로젝트 요구사항 분석과 전반 설계에 집중합니다.
좋은 설계는 프로젝트의 성공을 좌우하며, 이후 개발 과정의 시행착오를 줄이고 유지보수성을 높이는 기반이 됩니다.
Editor 입력은 REST로 파일 소유권과 버전을 저장하고 WebSocket으로 같은 room의 사용자에게 변경을 전파한다.
- Client EditorClient Editor 코드 입력 →
컬 버전 → 충돌 표시
- REST 경로REST 경
Auth → Project / File → DB 저장
- Realtime 경로Realtime 경
join_file → code_change → Room broadcast
- 검증검증 권한 · 100ms 지연
충돌·실패 응답
프로젝트 개요: 온라인 코드 에디터 및 실시간 협업 도구
이번 실전 프로젝트에서는 웹 기반의 온라인 코드 에디터 및 실시간 협업 도구를 NestJS를 사용하여 개발하겠습니다.
이 도구는 사용자들이 웹 브라우저에서 직접 코드를 작성하고, 여러 사용자가 동시에 동일한 파일을 편집하며, 변경 사항을 실시간으로 동기화하는 기능을 제공합니다.
핵심 기능- 코드 편집: 다양한 프로그래밍 언어(JavaScript, Python 등)에 대한 구문 강조(Syntax Highlighting)를 지원하는 웹 기반 코드 에디터.
- 실시간 협업: 여러 사용자가 동시에 동일한 파일의 코드를 편집하고, 모든 참여자에게 변경 사항이 즉시 반영됩니다.
- 프로젝트/파일 관리: 사용자가 개인 프로젝트를 생성하고, 프로젝트 내에 여러 파일/폴더를 생성, 삭제, 이름 변경할 수 있습니다.
- 사용자 인증: 기본적인 사용자 가입 및 로그인 기능.
- 버전 관리 (선택 사항/확장): 코드 변경 이력을 저장하고, 특정 시점으로 되돌리는 기능 (간단하게 구현하거나 향후 확장).
요구사항 분석
프로젝트 요구사항 분석과 설계는 사용자 시나리오, 비기능 요구사항, API 계약, 데이터 경계 기준으로 읽습니다.
온라인 코드 에디터 요구사항을 기능 목록에 멈추지 말고 구현할 백엔드 경계로 바꾼다.
- 사용자 행동
회원가입, 프로젝트 생성, 파일 편집, 협업 참여를 유스케이스로 분리한다.
- 백엔드 경계
REST API, WebSocket 이벤트, provider 책임을 나눈다.
- 데이터 구조
User, Project, File, Folder 관계와 소유권을 정의한다.
- 검증 기준
권한, 입력 검증, 실패 응답, 성능 목표를 테스트 신호로 둔다.
| 요구사항 | 설계 산출물 | 백엔드 계약 | 테스트 신호 |
|---|---|---|---|
| 인증 로그인, 현재 사용자 | AuthModule, JWT strategy | 토큰 발급, guard 적용 | 401/403 실패 케이스 포함 |
| 파일 관리 프로젝트/폴더/파일 | Project/File schema, REST route | ownerId 기준 조회와 변경 | 다른 사용자 접근 차단 |
| 실시간 협업 코드/커서 동기화 | Gateway room, socket event | join_file, code_change, ack | room 단위 이벤트 수신 |
프로젝트를 시작하기 전에, 어떤 기능을 만들 것인지, 누가 사용할 것인지, 어떤 제약사항이 있는지 등을 명확히 정의하는 것이 중요합니다.
기능 요구사항
사용자가 시스템을 통해 무엇을 할 수 있어야 하는지에 대한 정의입니다.
-
사용자 관리
- 사용자는 회원가입을 할 수 있다. (이메일/비밀번호 기반)
- 사용자는 로그인/로그아웃을 할 수 있다. (JWT 기반 인증)
- 사용자는 자신의 프로필 정보를 조회하고 수정할 수 있다. (예: 닉네임)
-
프로젝트 관리
- 로그인한 사용자는 새로운 프로젝트를 생성할 수 있다.
- 사용자는 자신의 프로젝트 목록을 조회할 수 있다.
- 사용자는 자신의 프로젝트를 열고 닫을 수 있다.
- 사용자는 자신의 프로젝트 이름을 변경하거나 삭제할 수 있다.
- 프로젝트는 이름, 생성자(User ID), 생성일, 마지막 수정일 등의 속성을 가진다.
-
파일/폴더 관리
- 프로젝트 내에서 파일을 생성, 삭제, 이름 변경할 수 있다.
- 프로젝트 내에서 폴더를 생성, 삭제, 이름 변경할 수 있다.
- 파일은 이름, 경로, 내용, 타입(언어), 마지막 수정일 등의 속성을 가진다.
- 폴더는 이름, 경로 등의 속성을 가진다.
-
코드 편집
- 사용자는 파일을 열어 코드를 편집할 수 있다.
- 코드 에디터는 구문 강조, 자동 완성(간단한 수준), 들여쓰기 등을 지원한다. (프론트엔드 에디터 라이브러리 활용)
- 코드 변경 내용은 자동으로 저장된다.
-
실시간 협업
- 여러 사용자가 동시에 동일한 파일을 편집할 수 있다.
- 한 사용자의 편집 내용은 다른 모든 참여 사용자에게 실시간으로 동기화된다. (WebSocket 활용)
- 누가 어느 위치에서 편집 중인지 커서 위치를 표시한다. (선택 사항/확장)
- 사용자는 다른 사용자에게 프로젝트 공유 초대 링크를 보낼 수 있다. (간단하게 구현하거나 향후 확장)
- 초대받은 사용자는 링크를 통해 프로젝트에 참여할 수 있다.
비기능 요구사항
시스템의 품질 속성에 대한 정의입니다.
-
성능
- 코드 편집 및 실시간 동기화는 100ms 이내의 지연 시간을 가져야 한다. (WebSocket 응답 시간)
- 동시 접속 사용자 100명까지 안정적인 실시간 협업을 지원해야 한다.
- 파일 및 프로젝트 생성/조회 응답 시간은 500ms 이내여야 한다.
-
확장성
- 향후 사용자 및 프로젝트 수 증가에 따라 시스템을 쉽게 확장할 수 있어야 한다. (클라우드 환경 고려)
-
보안
- 사용자 인증 및 권한 부여가 적절히 이루어져야 한다. (JWT)
- 민감한 사용자 정보(비밀번호)는 안전하게 저장되어야 한다.
- 모든 통신은 HTTPS/WSS를 통해 암호화되어야 한다.
-
유지보수성
- 클린 아키텍처 또는 DDD 원칙을 적용하여 모듈화되고 유지보수하기 쉬운 코드베이스를 유지한다.
- 적절한 로깅 및 모니터링 시스템을 구축한다.
-
사용 편의성
- 직관적인 사용자 인터페이스를 제공한다. (프론트엔드)
시스템 아키텍처 설계
요구사항 분석을 바탕으로 시스템의 큰 그림을 그립니다.
주요 컴포넌트, 기술 스택, 데이터 흐름 등을 정의합니다.
아키텍처 개요: 마이크로서비스 지향 모놀리식 + 실시간 서비스 분리
초기에는 개발 및 배포의 용이성을 위해 모놀리식(Monolithic) 구조로 시작하되, NestJS의 모듈 시스템을 활용하여 각 기능 도메인을 명확히 분리하는 모듈형 모놀리식(Modular Monolith) 형태로 설계합니다.
특히 실시간 협업 기능은 WebSocket을 사용하므로, 별도의 서비스(모듈)로 분리하여 유연성을 확보합니다.
계층별 구성-
클라이언트 (Frontend)
- 기술 스택: React, Vue.js, Angular 중 하나 (예: React)
- 코드 에디터 라이브러리: Monaco Editor, CodeMirror 등 (예: Monaco Editor)
- WebSocket 클라이언트: Socket.IO 클라이언트 라이브러리
- 역할: 사용자 인터페이스 제공, HTTP API 호출, WebSocket을 통한 실시간 통신 처리.
-
백엔드 (Backend - NestJS)
- 기술 스택: NestJS (TypeScript)
- 웹 서버: Express.js (NestJS 기본)
- 인증: Passport.js (JWT 전략)
- 데이터베이스 ORM: TypeORM (PostgreSQL, MySQL 등)
- 실시간 통신:
@nestjs/platform-socket.io및Socket.IO -
아키텍처
- API Gateway: 클라이언트의 HTTP 요청을 처리하고, 인증/권한 부여를 담당. (NestJS 컨트롤러)
- Application Services: 비즈니스 로직 조정, 도메인 객체 사용. (NestJS 서비스)
- Domain Models: 프로젝트, 파일, 사용자 등 핵심 도메인 객체 및 비즈니스 규칙. (DDD 원칙 적용)
- Infrastructure: 데이터베이스 접근, 외부 서비스 연동 (Repository 패턴).
- WebSocket Gateway: 실시간 통신 요청 처리, Socket.IO 서버 관리.
-
데이터베이스
- 주 데이터베이스: PostgreSQL (관계형 데이터 모델)
- 사용자, 프로젝트, 파일/폴더 메타데이터 저장.
- 캐시/보조 데이터베이스 (선택 사항/확장): Redis
- WebSocket 세션 관리, 실시간 편집 내용의 임시 저장, 메시지 브로커(Socket.IO Redis Adapter).
- 주 데이터베이스: PostgreSQL (관계형 데이터 모델)
온라인 코드 에디터는 기능 목록보다 인증, 파일 관리, 실시간 협업, 운영 검증을 누가 책임지는지가 먼저 정리되어야 한다.
- 사용자 컨텍스트
Auth JWT guard와 ownership 검증을 REST와 Gateway에서 공유한다.
- 저장 구조
Project/File 프로젝트, 폴더, 파일, 최근 수정 시각을 repository 계약으로 관리한다.
- 실시간 이벤트
Collaboration join_file, code_change, cursor_change를 room 단위로 처리한다.
- 품질 지표
Ops Redis, 로그, health check, E2E 테스트가 운영 품질을 검증한다.
| 요구사항 | 구현 책임 | 백엔드 경계 | 검증 신호 |
|---|---|---|---|
| 회원 인증 가입, 로그인, 프로필 | AuthService, JwtStrategy, AuthGuard | Gateway와 REST에 사용자 기준이 일치함 | 토큰 발급, 만료, 보호 API 접근 |
| 파일 관리 프로젝트와 파일 트리 | ProjectService, FileService, repository | 다른 사용자 파일 접근, 권한 개별 검증 | ownerId 필터와 삭제 트랜잭션 |
| 협업 세션 코드와 커서 동기화 | Gateway room, Redis adapter | room 누락, 일부 사용자 메시지 유실 | 두 클라이언트 이벤트 수신 |
데이터베이스 스키마 설계 (간략)
User 테이블| 컬럼명 | 타입 | 제약조건 | 설명 |
|---|---|---|---|
id | UUID | PK, Auto-gen | 사용자 고유 ID |
email | VARCHAR | Unique, Not Null | 이메일 |
password | VARCHAR | Not Null | 해싱된 비밀번호 |
nickname | VARCHAR | Nullable | 닉네임 |
createdAt | TIMESTAMP | Not Null | 생성일 |
updatedAt | TIMESTAMP | Not Null | 마지막 수정일 |
| 컬럼명 | 타입 | 제약조건 | 설명 |
|---|---|---|---|
id | UUID | PK, Auto-gen | 프로젝트 고유 ID |
name | VARCHAR | Not Null | 프로젝트 이름 |
ownerId | UUID | FK (User.id) | 프로젝트 소유자 |
createdAt | TIMESTAMP | Not Null | 생성일 |
updatedAt | TIMESTAMP | Not Null | 마지막 수정일 |
| 컬럼명 | 타입 | 제약조건 | 설명 |
|---|---|---|---|
id | UUID | PK, Auto-gen | 파일 고유 ID |
name | VARCHAR | Not Null | 파일 이름 |
path | VARCHAR | Not Null | 프로젝트 내 파일 경로 |
content | TEXT | Nullable | 파일 내용 (최종 저장분) |
type | VARCHAR | Nullable | 파일 타입 (예: 'js') |
projectId | UUID | FK (Project.id) | 소속 프로젝트 ID |
createdAt | TIMESTAMP | Not Null | 생성일 |
updatedAt | TIMESTAMP | Not Null | 마지막 수정일 |
| 컬럼명 | 타입 | 제약조건 | 설명 |
|---|---|---|---|
id | UUID | PK, Auto-gen | 폴더 고유 ID |
name | VARCHAR | Not Null | 폴더 이름 |
path | VARCHAR | Not Null | 프로젝트 내 폴더 경로 |
projectId | UUID | FK (Project.id) | 소속 프로젝트 ID |
createdAt | TIMESTAMP | Not Null | 생성일 |
updatedAt | TIMESTAMP | Not Null | 마지막 수정일 |
Collaboration (협업) 관련: 실시간 협업에서는 파일 내용이 자주 바뀌므로, 변경 내용을 매번 즉시 DB에 반영하기보다 WebSocket으로 변경 이벤트를 주고받고 주기적으로(또는 사용자가 편집을 멈췄을 때) DB에 최종 저장하는 방식을 고려합니다. (Operation Transformation(OT), Conflict-free Replicated Data Type(CRDT) 같은 복잡한 알고리즘은 이 프로젝트 범위를 넘어설 수 있으므로, 초기에는 단순한 덮어쓰기 방식으로 시작하고 이후 확장성을 고려합니다.)
주요 API 엔드포인트 및 WebSocket 이벤트 설계 (간략)
HTTP API (RESTful)POST /auth/register: 사용자 회원가입POST /auth/login: 사용자 로그인 (JWT 발급)GET /users/me: 내 프로필 조회POST /projects: 새 프로젝트 생성GET /projects: 내 프로젝트 목록 조회GET /projects/:projectId: 특정 프로젝트 조회 (파일/폴더 구조 포함)PATCH /projects/:projectId: 프로젝트 이름 변경DELETE /projects/:projectId: 프로젝트 삭제POST /projects/:projectId/files: 프로젝트 내 파일 생성PATCH /projects/:projectId/files/:fileId: 파일 이름 변경DELETE /projects/:projectId/files/:fileId: 파일 삭제POST /projects/:projectId/folders: 프로젝트 내 폴더 생성PATCH /projects/:projectId/folders/:folderId: 폴더 이름 변경DELETE /projects/:projectId/folders/:folderId: 폴더 삭제
-
클라이언트 -> 서버
join_file: 특정 파일 협업 세션 참가 ({ fileId: string, userId: string })leave_file: 특정 파일 협업 세션 이탈 ({ fileId: string, userId: string })code_change: 코드 변경 이벤트 ({ fileId: string, userId: string, changes: any })cursor_change: 커서 위치 변경 이벤트 ({ fileId: string, userId: string, position: { line: number, ch: number } })
-
서버 -> 클라이언트
file_joined: 파일 협업 세션에 사용자 참가 알림 ({ fileId: string, userId: string, userName: string })file_left: 파일 협업 세션에서 사용자 이탈 알림 ({ fileId: string, userId: string, userName: string })code_update: 다른 사용자의 코드 변경 내용 전파 ({ fileId: string, userId: string, changes: any })cursor_update: 다른 사용자의 커서 위치 변경 전파 ({ fileId: string, userId: string, position: { line: number, ch: number } })file_content: 파일 내용 요청 시 파일의 전체 내용 전송 ({ fileId: string, content: string })
기능 이름에서 멈추지 않고 모듈·API/이벤트·데이터·배포 검증까지 같은 식별자로 연결한다.
- User Story
회원·프로젝트·파일·협업 행동과 성공 조건을 쓴다.
- Module
Auth·Projects·Files·협업 모듈의 책임을 정한다.
- Contract
REST 경로 또는 WebSocket 이벤트와 실패 응답을 고정한다.
- Data
소유자·경로·room·세션이 저장될 위치를 정한다.
- Verify
테스트와 지연·오류율 같은 비기능 지표를 연결한다.
- Deploy
API·DB·Redis·프론트 배포 경계와 관측 위치를 남긴다.
개발 환경 및 배포 전략 (간략)
-
백엔드 (NestJS)
- 개발: Node.js, npm/yarn, Docker Compose (PostgreSQL, Redis).
- 배포: Docker 컨테이너화. AWS Fargate (ECS) 또는 Google Cloud Run과 같은 관리형 컨테이너 서비스에 배포를 고려.
- CI/CD: GitHub Actions를 통한 자동 빌드, 테스트, 이미지 푸시, 배포.
-
프론트엔드 (React)
- 개발: Node.js, npm/yarn.
- 배포: AWS S3 + CloudFront (정적 웹 호스팅).
- 데이터베이스: PostgreSQL. (AWS RDS, GCP Cloud SQL과 같은 관리형 서비스 이용).
- 로깅/모니터링: CloudWatch Logs/Metrics 또는 ELK Stack (Docker Compose 환경).
아래 점검표는 요구사항이 NestJS 모듈, API, WebSocket 이벤트, 데이터 및 배포 설계로 이어지는지 확인하는 기준입니다.
기능·비기능 목표가 Module, HTTP/WebSocket 계약, 데이터 모델, 테스트, 배포 단계에서 끊기지 않아야 한다.
- 1Requirements
사용자 행동과 성능·권한·실패 목표를 분리한다.
- 2Modules
Auth·Users·Projects·Files·협업 모듈의 책임을 배치한다.
- 3Contracts
REST 성공/실패와 room 이벤트·ack를 정의한다.
- 4Data
PostgreSQL 관계와 Redis 세션·room 상태를 나눈다.
- 5Tests
HTTP 계약·실시간 이벤트·비기능 지표를 검증한다.
- 6Delivery
환경값·로그·Docker·CI/CD로 운영 가능성을 확인한다.
이번 절에서는 온라인 코드 에디터 및 실시간 협업 도구 프로젝트의 전반적인 요구사항을 분석하고 시스템 아키텍처를 설계했습니다.
다음 절부터는 이 설계를 바탕으로 NestJS 백엔드 개발을 시작하며, 각 핵심 기능을 단계별로 구현합니다.
이 단계에서는 요구사항, 데이터 모델, API 경계, 인증 흐름, 배포 제약을 먼저 검증해야 합니다.
기능 요구사항을 API, 이벤트, 데이터, 운영 기준으로 연결해야 빠진 책임을 찾을 수 있다.
| 요구사항 | 구현 산출물 | 검증 기준 | 누락 징후 |
|---|---|---|---|
| 사용자 관리 회원가입, 로그인, 내 프로필 | AuthModule, JWT, POST /auth/login | 비밀번호 해시, 토큰 만료, 401 응답 | profile까지 같은 토큰으로 이어지는가 |
| 파일 관리 프로젝트와 파일 트리 | Project, File, Folder schema와 REST API | ownerId 필터, 삭제 트랜잭션 | 다른 사용자 접근이 차단되는가 |
| 협업 세션 join_file, code_change | Gateway room, Socket.IO event | 100ms 동기화, reconnect 처리 | room 별 사용자가만 전파되는가 |
| 운영 기준 PostgreSQL, Redis, Docker | DB migration, Redis adapter, health check | 500ms API, 로그, 배포 재현성 | 장애 신호가 로그까지 이어지는가 |
아래 다이어그램은 온라인 코드 에디터 요구사항이 API 계약, 데이터 규칙, 품질 기준으로 번역되는 흐름을 정리합니다.
사용자 행동을 그대로 구현하지 말고 API 계약, 저장 규칙, 완료 기준으로 쪼개야 누락이 줄어든다.
- 사용자 행동
요구 회원가입, 프로젝트 생성, 실시간 편집처럼 사용자가 원하는 일을 문장으로 적는다.
- 요청·응답 계약
API method, path, DTO, status, error code, 권한 조건으로 고정한다.
- 저장 규칙
Data 소유권, 관계, unique 제약, transaction, 삭제 정책을 명시한다.
- 완료 기준
Done 성공, 실패, 권한, 성능, 검사 로그를 테스트 가능한 기준으로 둔다.
| 기능 | API 계약 | 데이터 규칙 | 완료 기준 |
|---|---|---|---|
| 회원가입 이메일 계정 생성 | POST /auth/signup, 201, conflict | email unique, password hash | validation, rate limit, audit |
| 프로젝트 소유자가 생성 | POST /projects, owner guard | ownerId, member relation | 권한 테스트, 삭제 정책 |
| 협업 편집 동시 수정 | WebSocket event, ack, error | document version, transaction | latency, conflict handling |