Skip to content

Repository files navigation

NestJS sample


프로젝트 개요

Daily Chore Tracker API

TypeScript + NestJS 기반의 backend quick-start template이다.

작은 프로젝트에서 자주 등장하는 CRUD / schema design / testing 구조를 보여주는 것을 목표로 한다.

이 서버는 다음 개념을 관리한다.

  • User : 서비스를 사용하는 사용자
  • Project : 사용자가 생성한 프로젝트
  • Chore : 특정 프로젝트에서 특정 날짜에 해야 하는 일 수행 여부

핵심 특징

  • TypeScript 기반 NestJS 서버
  • pnpm workspace
  • Vitest 기반 테스트
  • 간단하지만 현실적인 데이터 모델
  • 확장 가능한 구조

Domain Model

개념

User
  └ Project
        └ Chore (date unique per project)

Data Schema

Mermaid ER diagram

erDiagram

USER {
  uuid id PK
  string email
  string name
  timestamp created_at
}

PROJECT {
  uuid id PK
  uuid user_id FK
  string title
  timestamp created_at
}

CHORE {
  uuid id PK
  uuid project_id FK
  date chore_date
  boolean completed
  timestamp created_at
}

USER ||--o{ PROJECT : owns
PROJECT ||--o{ CHORE : has
Loading

Unique Constraint

Chore는 다음이 unique

(project_id, chore_date)

이유

  • 한 프로젝트에서
  • 같은 날짜의 chore는 하나만 존재

API Design

Create Project

POST /projects

request

{
  "userId": "uuid",
  "title": "Workout Plan"
}

response

{
  "id": "uuid",
  "userId": "uuid",
  "title": "Workout Plan"
}

Create Chore

POST /chores

request

{
  "projectId": "uuid",
  "date": "2026-03-14",
  "completed": true
}

validation

  • (projectId, date) must be unique

Get Projects by User

GET /users/:userId/projects

response

[
  {
    "id": "uuid",
    "title": "Workout Plan"
  }
]

Get Chores by Project

GET /projects/:projectId/chores

response

[
  {
    "date": "2026-03-14",
    "completed": true
  }
]

Suggested Project Structure

src

common
  exceptions
  logger

users
  user.entity.ts
  user.repository.ts

projects
  project.controller.ts
  project.service.ts
  project.entity.ts
  project.repository.ts

chores
  chore.controller.ts
  chore.service.ts
  chore.entity.ts
  chore.repository.ts

Testing Strategy

테스트는 Vitest 기반으로 작성한다.

목표

  • domain logic 검증
  • API behavior 검증

Example Tests

Project Service Test

import { describe, it, expect } from "vitest"
import { ProjectService } from "./project.service"

describe("ProjectService", () => {
  it("creates project", async () => {
    const repo = {
      save: async (p: any) => ({ id: "p1", ...p }),
    }

    const service = new ProjectService(repo as any)

    const project = await service.createProject({
      userId: "m1",
      title: "fitness",
    })

    expect(project.title).toBe("fitness")
  })
})

Chore Unique Constraint Test

import { describe, it, expect } from "vitest"
import { ChoreService } from "./chore.service"

describe("ChoreService", () => {
  it("prevents duplicate chore per day", async () => {
    const repo = {
      findByProjectAndDate: async () => ({ id: "existing" }),
    }

    const service = new ChoreService(repo as any)

    await expect(
      service.createChore({
        projectId: "p1",
        date: "2026-03-14",
        completed: true,
      })
    ).rejects.toThrow()
  })
})

Integration Test Example

API 테스트

describe("POST /projects", () => {
  it("creates project", async () => {
    const res = await request(app)
      .post("/projects")
      .send({
        userId: "m1",
        title: "study"
      })

    expect(res.status).toBe(201)
  })
})

공통 기능 (추천 구현 리스트)

README에서 **“future improvements”**나 **“engineering concerns”**으로 쓰면 좋다.


1️⃣ Validation Layer

NestJS DTO validation

class-validator
class-transformer

  • title length
  • valid date format

2️⃣ Global Error Handling

NestJS

ExceptionFilter

3️⃣ Request Logging

middleware

method
path
duration

4️⃣ Idempotency

POST /chores

같은 요청이 여러 번 오더라도

duplicate creation 방지

5️⃣ Pagination

GET /projects
GET /chores

6️⃣ Sorting

?sort=date

7️⃣ Domain Error Types

ProjectNotFoundError
DuplicateChoreError
UserNotFoundError

8️⃣ Repository Pattern

DB 구현을 쉽게 교체 가능

in-memory
postgres

9️⃣ Timezone Handling

chore date 문제

UTC normalization

🔟 Health Check Endpoint

GET /health

About

Typescript, NestJS, pnpm, Vitest

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages