moderate-nestjs
λ NestJS νλ μμν¬λ₯Ό κΈ°λ°μΌλ‘ νμ¬ μ¬λ¬ κΈ°λ₯λ€μ ꡬνν λ°±μλ ν
νλ¦Ώ(Template) μ
λλ€. μ΄λ―Έ μ°λ¦¬κ° μ¬μ©ν μ μλ μ λͺ
νκ³ λ€μν ν
νλ¦Ώλ€μ΄ μμ§λ§, μ΄ ν
νλ¦Ώμ μ’λ κ°λ³κ³ μ§κ΄μ μΈ κΈ°λ₯λ€μ μΆκ΅¬νμ¬ λꡬλ μμ μ μ
λ§λλ‘ μμ λ° λ³΄μν μ μλλ‘ νμμ΅λλ€. νΉν, NestJSλ₯Ό μΌλ°μ μΌλ‘ μ΄ν΄ν μμ€μ κ°λ°μλ₯Ό λμμΌλ‘, λ무 λΉμ½μ μΈ λ 벨μ
보λ€λ μ λΉν(Moderate) μμ€μΌλ‘ κ°μ λ κΈ°λ₯λ€μ ν΅νμ¬, λ°±μλ ꡬμΆμ λν μ½κ°μ λΆνΈν¨λ€μ ν΄μνλ λ°μ κ·Έ λͺ©μ μ΄ μμ΅λλ€. κ²°λ‘ μ μΌλ‘, μ΄ ν
νλ¦Ώμ ν΅ν΄ μ’λ μ½κ³ λΉ λ₯΄κ² NestJS λ°±μλ μμ€ν
μ ꡬμΆνλ κ²μ΄ μ£Όλ λͺ©νμ
λλ€.
μ΄ ν νλ¦Ώμμλ,
- NestJS(μ΄ν Nest) νλ μμν¬λ₯Ό μ΄μ©νμ¬ API μλ²λ₯Ό ꡬμ±ν©λλ€.
- PostgreSQL(μ΄ν Postgres) λ°μ΄ν°λ² μ΄μ€λ₯Ό ꡬμΆν©λλ€.
- λ°μ΄ν°λ² μ΄μ€μ μ°κ²°νλ ORMμΌλ‘μ¨, Prisma λ₯Ό μ΄μ©ν©λλ€.
- ꡬνλ Nest λ° Postgres λ Docker Container λ‘ μ€ν, λ°°ν¬λ©λλ€.
TBD: Postgres λ°μ΄ν°λ² μ΄μ€λ₯Ό κ΄μ°°νκΈ° μν μΌμ’ μ PG AdminμΌλ‘μ¨, Hasura (GraphQL Engine)λ₯Ό μ°λνλ κ²μ λν λ¬Έμκ° μ λ°μ΄νΈλ μμ μ λλ€.
μ¬λ¬λΆμ μ΄ ν νλ¦Ώμ ν΅ν΄, μ¬λ¬λΆλ§μ λ°±μλ μμ€ν μ λ³΄λ€ κ°κ²°νκ³ μ½κ² μμ, ꡬν, λ°°ν¬ν μ μμ΅λλ€.
λ³Έ λ¬Έλ¨μ ν νλ¦Ώμ ꡬμ±νλ Nest μ Postgres μ λν μ½κ°μ λ°°κ²½μ§μμ μ€λͺ ν©λλ€. μ΄λ―Έ μκ³ μλ μ§μμ΄λΌλ©΄ 건λ λ°μ΄λ 무방ν©λλ€.
μ¬λ¬λΆμ΄ κ°λ°μλΌλ©΄, λ°±μλλ₯Ό μ²μ μ νλλΌλ, λ°±μλ μμ€ν μ μ΅μ΄ ꡬμ±μΈ API μλ²μ λ°μ΄ν°λ² μ΄μ€μ ꡬμ±μ μκ³ μμ κ²μ λλ€. μ΄ ν νλ¦Ώμ λ± κ·Έ μμ€μ λ°±μλ μμ€ν μ ꡬμ±ν λ λμμ μ£ΌκΈ° μν΄ κ΅¬νλμμ΅λλ€.
μ΄ ν νλ¦Ώμ λ°±μλ μμ€ν μ ν¬κ² Nest μλ²μ Postgres λ°μ΄ν°λ² μ΄μ€λ‘ ꡬμ±λμ΄ μμ΅λλ€. Postgres λ°μ΄ν°λ² μ΄μ€λ μꡬμ μΈ(Persistent) λ°μ΄ν°λ₯Ό μ μ₯ν μ μλλ‘ νκ³ , Nest μλ²λ μΈλΆ μμ²μ λνμ¬ μ°λ¦¬κ° μνλ λ‘μ§λ€μ ν΅ν΄ λ°μ΄ν°λ₯Ό μ²λ¦¬νκ³ κ΄λ¦¬νλλ‘ ν©λλ€.
Nest λ κΈ°μ‘΄ JavaScriptλ‘ κ΅¬ννλ Node.jsλ₯Ό, TypeScript μλ²λ‘ ꡬνν μ μλλ‘ κ°λ°λ νλ μμν¬μ λλ€. Typeμ λͺ μν¨μΌλ‘μ¨ μ’λ μμ νκ³ κ²¬κ³ ν μ½λ©μ ν μ μλ€λ μ₯μ λΆν°, OOP (Object Oriented Programming), FP (Functional Programming) λ±, κΈ°μ‘΄ λ°±μλ νλ μμν¬λ‘ μ λͺ ν JAVA SpringBootμ κΈ°λ₯λ€μ μ μ¬νκ² κ΅¬νν μ₯μ λ€μ΄ μ‘΄μ¬νλ νλ μμν¬μ λλ€. Nest μ λνμ¬ μ’λ μμΈν μκ³ μΆλ€λ©΄ 곡μλ¬Έμλ₯Ό μ°Έκ³ νμΈμ.
μ΄ ν νλ¦Ώμμ Nest λ λ€μκ³Ό κ°μ μν μ μνν©λλ€.
- Nest μλ²λ REST API μλ²λ‘ ꡬνλμ΄, ν΄λΌμ΄μΈνΈμ μΈλΆ μμ²μ μμ νκ³ μ²λ¦¬ν©λλ€.
- Nest μλ²λ μ¬λ¬λΆμ λ°μ΄ν° λλ©μΈμ κ΄λ¦¬νκ³ μ£Όμ λΉμ¦λμ€ λ‘μ§λ€μ μ€νν©λλ€.
- Nest μλ²λ JWT λ°κΈ λ° κ²μ¦μ κΈ°λ°μΌλ‘, APIμ λν μ μ κΆν(Permission)μ μ μ΄ν©λλ€.
Postgres λ μ€νμμ€ κΈ°λ°μ κ΄κ³ν λ°μ΄ν°λ² μ΄μ€ μμ€ν (RDBMS: Relational Database Management System)μ λλ€. λ¬Όλ‘ , μ¬λ¬λΆμ΄ λ€λ£¨λ μμ€ν μ΄λ λͺ©μ , μν©μ λ°λΌ MySQLκ³Ό κ°μ λ°μ΄ν°λ² μ΄μ€λ₯Ό μ΄μ©ν μλ μμ§λ§, Postgres λν μΆ©λΆν λ§μ μμλ€μ΄ μ‘΄μ¬νκ³ λ€λ₯Έ μλΉμ€λ€κ³Όμ μ°λ λ° μ§μ μΈ‘λ©΄μμ λ€μν μ₯μ λ€μ κ°μ§κ³ μκΈ° λλ¬Έμ, μ΄ ν νλ¦Ώμμλ Postgres λ₯Ό μΆμ²ν©λλ€. νΉν, μ€νμμ€λ‘ μΈν΄ κΈ°μ μ λν μ§μμ μΈ μ λ°μ΄νΈ μ§μμ΄ μκ³ , λ°μ΄ν°λ² μ΄μ€ 무결μ±κ³Ό μ λ’°μ±μ 보μ₯νλ ACID Compatibility, JSON λ° JSONB νμ μ§μμ νΉμ±λ€μ΄ νμνλ€λ©΄ Postgres μ μ¬μ©μ μ κ·Ή κΆμ₯ν©λλ€. Postgres μ λνμ¬ λ νμ νκ³ μΆλ€λ©΄ 곡μλ¬Έμλ₯Ό μ°Έκ³ νμΈμ.
μ΄ ν νλ¦Ώμμ Postgres λ λ€μκ³Ό κ°μ μν μ μνν©λλ€.
- Postgres λ λ°μ΄ν°λ₯Ό μ μ₯νλ λ°μ΄ν°λ² μ΄μ€μ λλ€.
- Nest μλ²λ Postgres λ°μ΄ν°λ² μ΄μ€μ μ°κ²°νμ¬ λ°μ΄ν°λ₯Ό μ μ₯, μμ , μ‘°ν, μμ ν©λλ€.
Key Point | Use / Implementation / Connection |
---|---|
Framework | NestJS |
Language | TypeScript |
Package Manager | yarn |
Architecture | Monolith, CQRS |
Documentation | Swagger |
ORM | Prisma |
Database | Postgres |
Deployment | Dockerlized |
- Architecture from CQRS Pattern (but, not event-driven)
- Focusing on Code Sharing for Collaboration
- Swagger Documentation
- Health Checker & Throttler
- Cache on Database
- Custom Logging System
- JWT Authentication
- User/Auth Examples
- Linting and CI test by
Husky
- Git version management by
commitizen
- Docker Versioning and Deployment
Docker μμ§μ μ΄λ―Έ μ€μΉνμκ³
docker-compose
λͺ λ Ήμ΄λ₯Ό μ¬μ©ν μ μλ€λ©΄, μ΄ λ¨κ³λ₯Ό μ€ν΅νμΈμ.
μ°λ¦¬λ Nest μ Postgres μλ²λ₯Ό Docker Container λ‘ λ°°ν¬ λ° μ€ννκΈ° λλ¬Έμ docker
λͺ
λ Ήμ΄μ docker-compose
λͺ
λ Ήμ΄λ₯Ό μ΄μ©ν μ μμ΄μΌ ν©λλ€.
Docker λ λ°μ€ν¬ν± μ± ννλ μμ§ ννλ‘ μ€μΉν μ μμ΅λλ€. κ΄λ ¨νμ¬ Docker λ₯Ό μ€μΉν μ μλ λͺκ°μ§ λͺ
λ Ήμ΄λ₯Ό docker-installΒ λ¬Έμμ μμ±ν΄ λμμ΅λλ€. Docker μ€μΉκ° μλ£λλ©΄ λλΆλΆμ κ²½μ° docker-compose
λͺ
λ Ήμ΄κ° ν¨κ» μ€μΉλ©λλ€. λ§μ½ ν¨κ» μ€μΉλμ§ μμλ€λ©΄, λ³λλ‘ μ€μΉνμκΈ° λ°λλλ€.
μ΄ ν νλ¦Ώ λ ν¬μ§ν 리λ₯Ό Cloning ν©λλ€:
$ git clone https://github.com/hubts/moderate-nestjs.git
Nest μ Postgres μλ²λ₯Ό μ€ννκΈ° μν΄ λͺκ°μ§ μΈν
μ μνν΄μΌ ν©λλ€. μ΄ μΈν
μ λλΆλΆ .env
μ ν΄λΉνλ νκ²½λ³μ νμΌμ μμ±νλ κ²μ
λλ€. Postgres λλ ν 리μ νμ¬ Nest μμ€μ½λ λλ ν 리 κ²½λ‘μμ κ°κ° μμ νμΌ .env.example
νμΌλ€μ νμΈν μ μμ΅λλ€.
PostgresΒ λ°μ΄ν°λ² μ΄μ€λ₯Ό Docker Container λ‘ λ°°ν¬νκΈ° μν΄ ν΄λΉ λλ ν 리μ λ¬Έμλ₯Ό νμΈνμκΈ° λ°λλλ€. ν΄λΉ λ¬Έμμ λ¨κ³λ₯Ό λ°λ₯΄λ©΄, λ°μ΄ν°λ² μ΄μ€μ λν μΈν
ν λ€ μ€νν μ μκ² λ©λλ€. λ°μ΄ν°λ² μ΄μ€λ₯Ό μ€νν μ 보λ₯Ό κΈ°λ°μΌλ‘ Prisma λ₯Ό μν μλ DATABASE_URL
μ ꡬμ±νμκΈ° λ°λλλ€.
DATABASE_URL="postgresql://${username}:${password}@${localhost}:${5432}/${dbname}?schema=${schema}"
${λ³μλͺ
}
μ ν΄λΉνλ λͺ¨λ κ°λ€μ μ€μ κ°μΌλ‘ λμΉνμ¬ URLμ μμ±ν©λλ€.
Nest μλ²μ λν μΈν
μ μμ νκ²½λ³μ .env.example
νμΌμ 볡μ¬νμ¬ .env
νμΌμ μμ±ν λ€, νμν νκ²½λ³μλ€μ μμ±νλ κ²μ
λλ€.
μ€μ ν΄μΌ νλ νκ²½λ³μλ€μ μλμ κ°μ΅λλ€:
-
ENV
: μλ² νκ²½(λ‘컬, κ°λ°, μ΄μ λ±)μ κ²°μ ν©λλ€. μ΄λ Logging λ 벨 λ±μ μν₯μ μ€ μ μμ΅λλ€. -
PORT
: μλ² Listening ν¬νΈλ²νΈμ λλ€. -
EXTERNAL_ENDPOINT
: μλ²μ μ κ·Όνκ² λλ μΈλΆ μλν¬μΈνΈλ₯Ό μλ―Ένλ©°, Swagger OpenAPIμ μλ² URLλ‘ μ΄μ©λ©λλ€. NestJSμμ μ 곡νλ νκ²½λ³μ λμΉκ° μ¬λ°λ₯΄κ² μ μ©λλ©΄${λ³μ}
λ¬Έλ²μ μ¬μ©ν μ μμΌλ, λ§μ½ μ¬λ°λ₯΄κ² μ μ©λμ§ μλλ€λ©΄ μ§μ μμ±ν΄ μ£Όμ΄μΌ ν©λλ€. -
DATABASE_URL*
: Prisma κ° μ°λν , μ€νλ λ°μ΄ν°λ² μ΄μ€μ URL(μ°κ²°μ£Όμ)λ₯Ό μ λ ₯ν©λλ€. -
THROTTLER_*
: Throttler μ€μ μ λλ€. μΌμ μκ°(TTL) λ΄μ νμ©νλ μ΅λ μμ² κ°μ(Limit)λ₯Ό μ μν©λλ€. -
JWT_*
: JWT μ€μ μ λλ€ (μ΄μ΄μ μ€λͺ ν©λλ€).
Nest μλ²λ JWT Authentication(μΈμ¦)μ ν΅ν΄ μ μ κΆν μ μ΄λ₯Ό μνν©λλ€. Nest μλ²λ μ κ·Ό ν ν° (Access token)μ λ°ννκ³ , μΈλΆ ν΄λΌμ΄μΈνΈ μμ²μ λλ΄λ ν ν°μ κ²μ¦ν©λλ€. μ΄ κ³Όμ μ νμν ν€ μμ νκ²½λ³μλ‘ μ λ ₯ν΄ μ£Όμ΄μΌ ν©λλ€. λ³λμ μκ³ λ¦¬μ¦μ μ¬μ©ν΄λ λμ§λ§, μ΄ ν νλ¦Ώμμλ RSA256 μ κΆμ₯ν©λλ€. ν€ μμ μμ±νκΈ° μν΄ μλ μ€ν¬λ¦½νΈλ₯Ό μ€ννμΈμ:
$ ./script/util/jwt-key-generation.sh
μλ‘μ΄ RSA ν€ μμ΄ μμ±λκ³ ν°λ―Έλμ μΆλ ₯λ κ²μ
λλ€. μΆλ ₯λ ν€λ€μ 볡μ¬νμ¬ νκ²½λ³μ JWT_*
κ°λ€μ μ
λ ₯νλ©΄ λ©λλ€.
μκΈ° λ¬Έλ¨μ ν΅ν΄ λ°μ΄ν°λ² μ΄μ€λ₯Ό μ€νν©λλ€.
Nest μλ² μ€νμ νμν μ’ μμ±(ν¨ν€μ§)λ€μ μ€μΉν©λλ€:
$ yarn # or 'yarn install'
Nest μλ² νκ²½λ³μ .env
νμΌμ DATABASE_URL
νκ²½λ³μλ₯Ό μμ±νμκ³ μ’
μμ± μ€μΉλ₯Ό ν΅ν΄ prisma
Β ν¨ν€μ§κ° μ€μΉνμλ€λ©΄, PrismaΒ λͺ
λ Ήμ΄λ₯Ό μ΄μ©ν μ μμ΅λλ€:
$ yarn prisma [command]
μ²μ λ°°ν¬ν λ°μ΄ν°λ² μ΄μ€μλ λ³λμ Schema λ° Table μ΄ μ μλμ΄ μμ§ μμ΅λλ€. μ°λ¦¬κ° μλ²μμ λ€λ£¨κ² λ Schema λ prisma/schema.prisma
νμΌμ μμμΌλ‘ μ μλ©λλ€. μ΄κΈ° λΉμ΄μλ μνμμ ν΄λΉ Schema λ₯Ό λ°μ΄ν°λ² μ΄μ€μ λκΈ°νμν€κΈ° μν΄ μλ λͺ
λ Ήμ΄ μ΄μ©ν©λλ€:
$ yarn prisma:sync
ν΄λΉ λͺ
λ Ήμ΄μλ NestΒ μλ²κ° ν΄λΉ Schema λ₯Ό κΈ°λ°μΌλ‘ Table μ 보λ₯Ό TypeΒ μΌλ‘ λ°μλ€μΌ μ μκ² λλΒ generate
λͺ
λ Ήμ΄μ λ°μ΄ν°λ² μ΄μ€μ ν΄λΉ Schema λ₯Ό λ°μ΄λ£λ db push
λͺ
λ Ήμ΄κ° ν¬ν¨λμ΄ μμ΅λλ€.
μ΄μ μλ λͺ λ Ήμ΄λ₯Ό ν΅ν΄ Nest μλ²λ₯Ό μ€νν©λλ€:
# Start
$ yarn start
# Start with watch mode (to debug)
$ yarn start:dev
Nest μλ²κ° μ€νλκ³ κ°μ’ Log λ₯Ό ν΅ν΄ μ€ν κ²°κ³Όλ₯Ό νμΈν μ μμ΅λλ€.
λ§μ½ Docker Container λ‘ Nest μλ²λ₯Ό μ€ννλ €λ©΄ μλ λͺ λ Ήμ΄λ₯Ό μ΄μ©ν©λλ€:
$ yarn deploy
μ€ν¬λ¦½νΈλ₯Ό ν΅ν΄ μλ²μ Docker Image λ₯Ό μμ±νκ³ μ€νν©λλ€.
λ¨, μλ²κ° Docker Container λ‘ λ°°ν¬λλ κ²½μ° νκ²½λ³μμμ μ΄μ©νλ localhost
κ° λ±μ ContainerΒ κ°μ μ μ©λμ§ μκΈ° λλ¬Έμ μ€μ λ°μ΄ν°λ² μ΄μ€μμ μ°λμ μνμ¬ μΈλΆ Host μ£Όμλ₯Ό μ΄μ©νκ±°λ, Docker Container κ° Network λ₯Ό ν΅μΌνκ±°λ, host.docker.internal
λ± ContainerΒ μ£Όμ μ°κ²°μ μν μ€μ μ λ°λμ μνν΄μΌ ν©λλ€.
μ΄ ν
νλ¦Ώμλ commitizen
μ μ΄μ©νμ¬ νμκ΄λ¦¬λ₯Ό ν μ μλλ‘ μ€ν¬λ¦½νΈ λ° λͺ
λ Ήμ΄κ° μ€μ λμ΄ μμ΅λλ€:
$ yarn git [version|patch|minor|major|...]
ν΄λΉ μ€ν¬λ¦½νΈλ₯Ό νμΈνκ±°λ, μ λͺ λ Ήμ΄λ₯Ό ν΅ν΄ νμκ΄λ¦¬λ₯Ό μ§μ μνν΄ λ³΄λλ‘ ν©λλ€.