본문으로 건너뛰기

안동민 개발노트

본문 시작

프로젝트 요구사항 분석과 설계

온라인 코드 편집기의 인증·파일 관리·실시간 협업 요구사항을 정리하고 서비스 경계와 데이터·API 구조를 설계합니다.

지난 12장에서는 NestJS를 활용한 서버리스 아키텍처, WebSocket 실시간 통신, CQRS 패턴, 그리고 도메인 주도 설계(DDD) 같은 고급 주제를 다뤘습니다.

13장에서는 지금까지 배운 내용을 묶어 실제 웹 애플리케이션 프로젝트를 기획하고, NestJS로 구현하는 과정을 단계별로 진행합니다.

이번 절은 그 출발점으로, 프로젝트 요구사항 분석과 전반 설계에 집중합니다.

좋은 설계는 프로젝트의 성공을 좌우하며, 이후 개발 과정의 시행착오를 줄이고 유지보수성을 높이는 기반이 됩니다.

협업 코드 에디터는 저장 경로와 실시간 경로가 만나는 시스템이다

Editor 입력은 REST로 파일 소유권과 버전을 저장하고 WebSocket으로 같은 room의 사용자에게 변경을 전파한다.

  1. Client Editor
    Client Editor 코드 입력 →

    컬 버전 → 충돌 표시

  2. REST 경로
    REST 경

    Auth → Project / File → DB 저장

  3. Realtime 경로
    Realtime 경

    join_file → code_change → Room broadcast

  4. 검증
    검증 권한 · 100ms 지연

    충돌·실패 응답


프로젝트 개요: 온라인 코드 에디터 및 실시간 협업 도구

이번 실전 프로젝트에서는 웹 기반의 온라인 코드 에디터 및 실시간 협업 도구를 NestJS를 사용하여 개발하겠습니다.

이 도구는 사용자들이 웹 브라우저에서 직접 코드를 작성하고, 여러 사용자가 동시에 동일한 파일을 편집하며, 변경 사항을 실시간으로 동기화하는 기능을 제공합니다.

핵심 기능
  • 코드 편집: 다양한 프로그래밍 언어(JavaScript, Python 등)에 대한 구문 강조(Syntax Highlighting)를 지원하는 웹 기반 코드 에디터.
  • 실시간 협업: 여러 사용자가 동시에 동일한 파일의 코드를 편집하고, 모든 참여자에게 변경 사항이 즉시 반영됩니다.
  • 프로젝트/파일 관리: 사용자가 개인 프로젝트를 생성하고, 프로젝트 내에 여러 파일/폴더를 생성, 삭제, 이름 변경할 수 있습니다.
  • 사용자 인증: 기본적인 사용자 가입 및 로그인 기능.
  • 버전 관리 (선택 사항/확장): 코드 변경 이력을 저장하고, 특정 시점으로 되돌리는 기능 (간단하게 구현하거나 향후 확장).

요구사항 분석

프로젝트 요구사항 분석과 설계는 사용자 시나리오, 비기능 요구사항, API 계약, 데이터 경계 기준으로 읽습니다.

요구사항은 모듈, API, 데이터, 테스트 계약으로 번역한다

온라인 코드 에디터 요구사항을 기능 목록에 멈추지 말고 구현할 백엔드 경계로 바꾼다.

  1. 사용자 행동

    회원가입, 프로젝트 생성, 파일 편집, 협업 참여를 유스케이스로 분리한다.

  2. 백엔드 경계

    REST API, WebSocket 이벤트, provider 책임을 나눈다.

  3. 데이터 구조

    User, Project, File, Folder 관계와 소유권을 정의한다.

  4. 검증 기준

    권한, 입력 검증, 실패 응답, 성능 목표를 테스트 신호로 둔다.

요구사항설계 산출물백엔드 계약테스트 신호
인증 로그인, 현재 사용자AuthModule, JWT strategy토큰 발급, guard 적용401/403 실패 케이스 포함
파일 관리 프로젝트/폴더/파일Project/File schema, REST routeownerId 기준 조회와 변경다른 사용자 접근 차단
실시간 협업 코드/커서 동기화Gateway room, socket eventjoin_file, code_change, ackroom 단위 이벤트 수신

프로젝트를 시작하기 전에, 어떤 기능을 만들 것인지, 누가 사용할 것인지, 어떤 제약사항이 있는지 등을 명확히 정의하는 것이 중요합니다.

기능 요구사항

사용자가 시스템을 통해 무엇을 할 수 있어야 하는지에 대한 정의입니다.

  • 사용자 관리
    • 사용자는 회원가입을 할 수 있다. (이메일/비밀번호 기반)
    • 사용자는 로그인/로그아웃을 할 수 있다. (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.ioSocket.IO
    • 아키텍처
      • API Gateway: 클라이언트의 HTTP 요청을 처리하고, 인증/권한 부여를 담당. (NestJS 컨트롤러)
      • Application Services: 비즈니스 로직 조정, 도메인 객체 사용. (NestJS 서비스)
      • Domain Models: 프로젝트, 파일, 사용자 등 핵심 도메인 객체 및 비즈니스 규칙. (DDD 원칙 적용)
      • Infrastructure: 데이터베이스 접근, 외부 서비스 연동 (Repository 패턴).
      • WebSocket Gateway: 실시간 통신 요청 처리, Socket.IO 서버 관리.
  • 데이터베이스
    • 주 데이터베이스: PostgreSQL (관계형 데이터 모델)
      • 사용자, 프로젝트, 파일/폴더 메타데이터 저장.
    • 캐시/보조 데이터베이스 (선택 사항/확장): Redis
      • WebSocket 세션 관리, 실시간 편집 내용의 임시 저장, 메시지 브로커(Socket.IO Redis Adapter).
기능 요구사항을 백엔드 책임과 검증 기준으로 나눈다

온라인 코드 에디터는 기능 목록보다 인증, 파일 관리, 실시간 협업, 운영 검증을 누가 책임지는지가 먼저 정리되어야 한다.

  1. 사용자 컨텍스트

    Auth JWT guard와 ownership 검증을 REST와 Gateway에서 공유한다.

  2. 저장 구조

    Project/File 프로젝트, 폴더, 파일, 최근 수정 시각을 repository 계약으로 관리한다.

  3. 실시간 이벤트

    Collaboration join_file, code_change, cursor_change를 room 단위로 처리한다.

  4. 품질 지표

    Ops Redis, 로그, health check, E2E 테스트가 운영 품질을 검증한다.

요구사항구현 책임백엔드 경계검증 신호
회원 인증 가입, 로그인, 프로필AuthService, JwtStrategy, AuthGuardGateway와 REST에 사용자 기준이 일치함토큰 발급, 만료, 보호 API 접근
파일 관리 프로젝트와 파일 트리ProjectService, FileService, repository다른 사용자 파일 접근, 권한 개별 검증ownerId 필터와 삭제 트랜잭션
협업 세션 코드와 커서 동기화Gateway room, Redis adapterroom 누락, 일부 사용자 메시지 유실두 클라이언트 이벤트 수신

데이터베이스 스키마 설계 (간략)

User 테이블
컬럼명타입제약조건설명
idUUIDPK, Auto-gen사용자 고유 ID
emailVARCHARUnique, Not Null이메일
passwordVARCHARNot Null해싱된 비밀번호
nicknameVARCHARNullable닉네임
createdAtTIMESTAMPNot Null생성일
updatedAtTIMESTAMPNot Null마지막 수정일
Project 테이블
컬럼명타입제약조건설명
idUUIDPK, Auto-gen프로젝트 고유 ID
nameVARCHARNot Null프로젝트 이름
ownerIdUUIDFK (User.id)프로젝트 소유자
createdAtTIMESTAMPNot Null생성일
updatedAtTIMESTAMPNot Null마지막 수정일
File 테이블
컬럼명타입제약조건설명
idUUIDPK, Auto-gen파일 고유 ID
nameVARCHARNot Null파일 이름
pathVARCHARNot Null프로젝트 내 파일 경로
contentTEXTNullable파일 내용 (최종 저장분)
typeVARCHARNullable파일 타입 (예: 'js')
projectIdUUIDFK (Project.id)소속 프로젝트 ID
createdAtTIMESTAMPNot Null생성일
updatedAtTIMESTAMPNot Null마지막 수정일
Folder 테이블
컬럼명타입제약조건설명
idUUIDPK, Auto-gen폴더 고유 ID
nameVARCHARNot Null폴더 이름
pathVARCHARNot Null프로젝트 내 폴더 경로
projectIdUUIDFK (Project.id)소속 프로젝트 ID
createdAtTIMESTAMPNot Null생성일
updatedAtTIMESTAMPNot 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: 폴더 삭제
WebSocket 이벤트
  • 클라이언트 -> 서버
    • 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/이벤트·데이터·배포 검증까지 같은 식별자로 연결한다.

  1. User Story

    회원·프로젝트·파일·협업 행동과 성공 조건을 쓴다.

  2. Module

    Auth·Projects·Files·협업 모듈의 책임을 정한다.

  3. Contract

    REST 경로 또는 WebSocket 이벤트와 실패 응답을 고정한다.

  4. Data

    소유자·경로·room·세션이 저장될 위치를 정한다.

  5. Verify

    테스트와 지연·오류율 같은 비기능 지표를 연결한다.

  6. 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 계약, 데이터 모델, 테스트, 배포 단계에서 끊기지 않아야 한다.

  1. 1
    Requirements

    사용자 행동과 성능·권한·실패 목표를 분리한다.

  2. 2
    Modules

    Auth·Users·Projects·Files·협업 모듈의 책임을 배치한다.

  3. 3
    Contracts

    REST 성공/실패와 room 이벤트·ack를 정의한다.

  4. 4
    Data

    PostgreSQL 관계와 Redis 세션·room 상태를 나눈다.

  5. 5
    Tests

    HTTP 계약·실시간 이벤트·비기능 지표를 검증한다.

  6. 6
    Delivery

    환경값·로그·Docker·CI/CD로 운영 가능성을 확인한다.

이번 절에서는 온라인 코드 에디터 및 실시간 협업 도구 프로젝트의 전반적인 요구사항을 분석하고 시스템 아키텍처를 설계했습니다.

다음 절부터는 이 설계를 바탕으로 NestJS 백엔드 개발을 시작하며, 각 핵심 기능을 단계별로 구현합니다.

이 단계에서는 요구사항, 데이터 모델, API 경계, 인증 흐름, 배포 제약을 먼저 검증해야 합니다.

요구사항은 구현 산출물과 검증 신호까지 이어져야 한다

기능 요구사항을 API, 이벤트, 데이터, 운영 기준으로 연결해야 빠진 책임을 찾을 수 있다.

요구사항구현 산출물검증 기준누락 징후
사용자 관리 회원가입, 로그인, 내 프로필AuthModule, JWT, POST /auth/login비밀번호 해시, 토큰 만료, 401 응답profile까지 같은 토큰으로 이어지는가
파일 관리 프로젝트와 파일 트리Project, File, Folder schema와 REST APIownerId 필터, 삭제 트랜잭션다른 사용자 접근이 차단되는가
협업 세션 join_file, code_changeGateway room, Socket.IO event100ms 동기화, reconnect 처리room 별 사용자가만 전파되는가
운영 기준 PostgreSQL, Redis, DockerDB migration, Redis adapter, health check500ms API, 로그, 배포 재현성장애 신호가 로그까지 이어지는가

아래 다이어그램은 온라인 코드 에디터 요구사항이 API 계약, 데이터 규칙, 품질 기준으로 번역되는 흐름을 정리합니다.

요구사항은 기능 목록이 아니라 검증 가능한 백엔드 계약으로 바뀐다

사용자 행동을 그대로 구현하지 말고 API 계약, 저장 규칙, 완료 기준으로 쪼개야 누락이 줄어든다.

  1. 사용자 행동

    요구 회원가입, 프로젝트 생성, 실시간 편집처럼 사용자가 원하는 일을 문장으로 적는다.

  2. 요청·응답 계약

    API method, path, DTO, status, error code, 권한 조건으로 고정한다.

  3. 저장 규칙

    Data 소유권, 관계, unique 제약, transaction, 삭제 정책을 명시한다.

  4. 완료 기준

    Done 성공, 실패, 권한, 성능, 검사 로그를 테스트 가능한 기준으로 둔다.

기능API 계약데이터 규칙완료 기준
회원가입 이메일 계정 생성POST /auth/signup, 201, conflictemail unique, password hashvalidation, rate limit, audit
프로젝트 소유자가 생성POST /projects, owner guardownerId, member relation권한 테스트, 삭제 정책
협업 편집 동시 수정WebSocket event, ack, errordocument version, transactionlatency, conflict handling