카테고리 없음
Nest.js + Prisma(Postgres) + Docker
이런저런 IT 이야기
2023. 7. 16. 20:21
반응형
https://github.com/leeyonghe/NestPrismaProject
샘플코드입니다. 미리 살펴보세요.
1. Docker 구성
- Node Server 1대
- node:latest 서버 이미지를 사용
- 포트번호 3000번으로 적용
- 서버 실행시 반드시 prisma migrate 및 generate 명령어 사용
- npx prisma db push && yarn install && nest start --watch
- Postgres DB 1대
- DB 사용자 및 패스워드 적용
- POSTGRES_USER: postgres
- POSTGRES_PASSWORD: postgres123!
- DB 사용자 및 패스워드 적용
- docker-compose.yml 파일 내용
version: '3.7'
services:
dp_project:
tty: true
container_name: dp_project
build:
context: .
dockerfile: Dockerfile
ports:
- "3000:3000"
- "5555:5555"
volumes:
- ./project/:/main
command: sh -c "npx prisma db push && yarn install && nest start --watch"
depends_on:
- "postgres"
postgres:
container_name: postgres
tty: true
image: postgres
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres123!
PGDATA: /data/postgres
ports:
- "5432:5432"
restart: unless-stopped
- Dockerfile 내용 (Django 서버용)
FROM node:latest
RUN apt update
RUN npm i -g @nestjs/cli
WORKDIR /main
- npx 명령어를 사용하기 위해서 nodejs & npm & npx 단계적으로 설치
- npx 명령어는 docker-compose command에서 사용
2. Nest.js 프로젝트 생성
- 사전에 Prisma 설치 필요
- @nestjs/cli 설치
$ npm i -g @nestjs/cli
- Nest.js 프로젝트 생성
$ nest new project
- Prisma초기화
- 아래 명령어 실행후 prisma 폴더 및 안에 schema.prisma파일이 생성되었는지 확인
$ prisma init
- DB를 조회할 서비스 class 생성[user.service.ts]
import { Injectable } from '@nestjs/common';
import { PrismaService } from './prisma.service';
import { Prisma, user } from '@prisma/client';
@Injectable()
export class UserService {
constructor(private prisma: PrismaService) {}
async user(
userWhereUniqueInput: Prisma.userWhereUniqueInput,
): Promise<user | null> {
return this.prisma.user.findUnique({
where: userWhereUniqueInput,
});
}
async users(): Promise<user[] | null> {
return this.prisma.user.findMany();
}
async createUser(data: Prisma.userCreateInput): Promise<user> {
return this.prisma.user.create({
data,
});
}
}
- Prisma를 관리할 class 생성[prisma.service.ts]
import { INestApplication, Injectable, OnModuleInit } from '@nestjs/common';
import { PrismaClient } from '@prisma/client';
@Injectable()
export class PrismaService extends PrismaClient implements OnModuleInit {
async onModuleInit() {
await this.$connect();
}
async onModuleDestroy() {
await this.$disconnect();
}
}
- AppModule에 UserService, PrismaService 추가[app.module.ts]
import { Global, Module } from "@nestjs/common"
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { PrismaService } from './prisma.service';
import { UserService } from "./user.service";
@Module({
imports: [],
controllers: [AppController],
providers: [PrismaService, UserService, AppService], // 3개가 모두 등록되어야 함
})
export class AppModule {}
- ejs 파일 위치 설정 및 리소스 파일(css, js, 이미지) 위치 설정 [main.ts]
- ejs 템플릿 파일은 Embedded JavaScript의 약자로, 자바스크립트가 내장되어 있는 html 파일이다
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { NestExpressApplication } from '@nestjs/platform-express';
import { join } from 'path';
async function bootstrap() {
const app = await NestFactory.create<NestExpressApplication>(AppModule);
app.enableShutdownHooks()
app.useStaticAssets(join(__dirname, '..', 'src', 'public'));
app.setBaseViewsDir(join(__dirname, '..', 'src', 'views'));
app.setViewEngine("ejs");
await app.listen(3000);
}
bootstrap();
- ejs 파일을 저장할 폴더 생성
- src > views > view.ejs
- 리소스 파일들을 저장할 폴더 생성
- src > public > jquery-3.7.0.min.js
- Controller 설정
- 호출하는 함수위에 rendering할 파일을 표시 => @Render('view.ejs')
import { Controller, Get, Render } from '@nestjs/common';
import { AppService } from './app.service';
import { UserService } from './user.service';
@Controller()
export class AppController {
constructor(private readonly appService: AppService, private readonly userService: UserService) {}
@Get()
@Render('view.ejs')
async getHello(): Promise<object> {
try {
// [STEP1]
// this.userService.createUser({email : 'test@gmail.com', name: 'test' })
// [STEP2]
const user = await this.userService.user({email : 'test@gmail.com'})
console.log(JSON.stringify(user))
return this.appService.getHello(user);
} catch (error) {
console.log(error)
return { name: '', 'email': ''};
}
}
}
3. Prisma(Posgtgres)
- schema.prisma파일 수정
- postgres db 연결정보 및 user 추가
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = "postgresql://postgres:postgres123!@postgres:5432/postgres?sslmode=disable"
}
model user {
id Int @id @default(autoincrement())
email String @unique
name String?
}
4. 폴더구조
5. 프로젝트 실행
import { Controller, Get, Render } from '@nestjs/common';
import { AppService } from './app.service';
import { UserService } from './user.service';
@Controller()
export class AppController {
constructor(private readonly appService: AppService, private readonly userService: UserService) {}
@Get()
@Render('view.ejs')
async getHello(): Promise<object> {
try {
// [STEP1]
this.userService.createUser({email : 'test@gmail.com', name: 'test' })
// [STEP2]
// const user = await this.userService.user({email : 'test@gmail.com'})
// console.log(JSON.stringify(user))
return this.appService.getHello(user);
} catch (error) {
console.log(error)
return { name: '', 'email': ''};
}
}
}
- 최초 실행시 데이터가 없으므로 STEP1 부분을 주석을 풀고 STEP2를 주석처리후 실행
import { Controller, Get, Render } from '@nestjs/common';
import { AppService } from './app.service';
import { UserService } from './user.service';
@Controller()
export class AppController {
constructor(private readonly appService: AppService, private readonly userService: UserService) {}
@Get()
@Render('view.ejs')
async getHello(): Promise<object> {
try {
// [STEP1]
// this.userService.createUser({email : 'test@gmail.com', name: 'test' })
// [STEP2]
const user = await this.userService.user({email : 'test@gmail.com'})
console.log(JSON.stringify(user))
return this.appService.getHello(user);
} catch (error) {
console.log(error)
return { name: '', 'email': ''};
}
}
}
- 두번째 실행시 데이터가 있으므로 STEP2 부분을 주석을 풀고 STEP1를 주석처리후 실행
- 위와 같이 실행 결과를 볼수 있음
반응형