TIL nest.js 고양이 프로젝트

0

TIL

목록 보기
25/29

nestjs 작동 순서

service -> module import-> app.ts

DB연결 & 환경변수 설정

mongoose

npm

환경변수 - 디비정보 , port 노출 안되도록 .env
process.env.MONGODB_uri
process.env.port

USEcreate index -> index 설정

개발단계 쿼리 로깅

.env -> MODE = 'dev'

export class AppModule implements NestModule {
  private readonly isDev : boolean = process.env.MODE ==='dev' ? true:false;

mongoose.set('debug',this.isDev) - //production 에서는 True -> log 남음
}

스키마 & controller & validation

스키마

  • 테이블 요소 설정
  • Prop으로 constraint 표현
  • options는 create 될 때 만들어진 날짜 + 업데이트 날짜 (django의 autonow add)

class validation

$ npm i --save class-validator class-transformer

  • 이메일 형태
  • 길이 몇 자 이상
  • 등등 .... 필요 조건 제약
  • main.ts에 bootstrap -> app.useGlobalPipes(new ValidationPipe)를 써줘야 등록됌!
import {Prop, Schema, SchmaFactory} from '@nestjs/mongoose';
import {IsEmail, IsNoEmpty, IsString} from 'class-validator'
import {Document, SchemaOptions} from 'mongoose';

const options : SchemaOptions = {
  timestamps: true;
}; // db에서 만들어질 때 업데이트, 만들어지는 날짜 찍어줌 

@Schema(options)
export class Cat extends Document{ // 원래는 클래스
	@Prop({
      required: true,
      unique : true,
    })  //각 필드에 대한 constraint
	@IsEmail() //validation
	@IsNotEmpty() //validation
	email: string;   //column email

	@Prop({
      required: true,
    })
	@IsString() 
	@IsNotEmpty() 
	name: string;   //column catname
	@Prop({
      required: true,
    })
	@IsString() 
	@IsNotEmpty() 
	password: string;   //column password
	@Prop({
      required: false,
    })
	@IsString() 
	imgurl: string;   //column imgurl
export const CatSchema = SchemaFactory.createForClass(Cat); // class -> schema

}

회원가입

  • @Body() 로 body 구현
  • body의 자료는 다 필수로 들어가도록 exception 처리 -> DTO 사용 (body에 타입지정)
  • catsService로 로직 ( 의존성 주입 이후)
    - 중복 이메일 확인 -> 에러 처리
    • 비밀번호 hash npm i bcrypt. // npm i -D @types/bcrypt
    • 스키마 이용 db 삽입
    • 패스워드 그대로 노출? -> 패스워드 숨겨야 함 -> mongoose - virtural field -> 노출할 정보만 readonlydata로 만듦

DTO패턴

  • Data Transfer Object - 데이터 교환을 위한 객체
  • express router에 대응
    -AOP 관점 지향 프로그래밍 반영
    ✓AOP : 부가기능을 aspect로 정의하여 핵심기능에서 부가기능을 분리함으로써 핵심기능을 설계할 때 객체지향을 지킬 수 있도록 도와주는 기법
// /cats/cats.controller.ts

@Post()
async signUp(@Body() body : CatRequestDto) {
  console.log(body);
  return await this.catsService.signUp(body)
}
// /cats/cats.request.dto
import {IsEmail, IsNoEmpty, IsString} from 'class-validator'

export class CatRequestDto {
  @IsEmail()
  @IsNotEmpty()
  email:String;

  @IsString()
  @IsNotEmpty()
  password:String;

  @IsString()
  @IsNotEmpty()
  name:String;

}
// cats/catsService

@injectable()
export class CatsService {
  constructor (@InjectModel (Cat.name) private readonly catModel: Model<cat>) {}
  
  async signUp(body: CatRequestDto) {
    const {email, name, password} = body;
    const isCatExist = await this.catModel.exists({email});

    if (isCatExist){
      throw new UnauthorizedException ('해당하는 고양이는 이미 존재') //403안적어도 자동 반환
      //throw new HttpException ('해당하는 고양이는 이미 존재합니다' 403)
    }
    const hashedPassword = await bcrypt.hash (password, 10);
      
    const cat = await this.catModel.create({
      email,
      name,
      password: hashedpassword,
    })
    return cats.readOnlyData;
  }
}
    
    
    ```
 ```typescript 
// cats/cats.schema.ts

readonly readOnlyData: {id: string; email:string; name:string}; //typing

CatSchema.virtual('readOnlyData').get(function(this.Cat){
  return {
    id : this.id,
    email: this.email,  // 	보내줄 내용만 기록
    name: this.name,
  }
})

nestJs- fastify -협업을 위한 API 문서 만들기 CORS

swagger 적용

  • nestJs 기본적으로 express 기반 - fastify 호환가능 (구조, 속도가 더 유리) -> nest에서는 필요한 부분에 fastify 적용 가능
  • swagger - express 기반으로 설치 npm install --save @nestjs/swagger fastify-swagger
  • main.ts - bootstrap에 추가
  • swagger페이지 api 설명 : service에 해당 api에 ApiOperation(summary)추가 -> ex) post cats 회원가입
  • 미리 body 입력값 넣는 법 : Dto에 @ApiProperty로 표현
  • 미리 응답값 보여주는 법 : Controller- @ApiResponse - response에도 dto 사용 가능! - request와 동일하게 만들고 타입 지정
  • schema -> dto 상속 -> 재사용성 증가 -> password도 그대로? ->Picktype

CORS

  • 프론트엔드와 소통을 위해서 사용 - 신뢰하는 사이트로 만들어주기 위해
  • main.ts - bootstrap - app.enableCors 추가
  • origin - 개발을 할때는 true // 배포시에는 프론트 특정 url만 지정 ( 다른 접근을 막기 위해)
// main.ts
async fucntion bootstrap() {
.....

	const config = new DocumentBuilder()   //각 요소 수정 
      .setTitle('Cats Informaiton Service') 
      .setDescription('The cats API description') 
      .setVersion('1.0.0')
      .addTag('cats')
      .build();
  const document = SwaggerModule.createDocument(app, config);
  SwaggerModule.setup('docs', app, document);
  app.enableCors({
    origin : true,
    credentials: true
  })   //cors 추가!!
  .....

}
// /cats/cats.controller.ts

@ApiResponse({							//실패한 경우 출력
  status : 500,
  description : 'server error....'
  type : ReadOnlyDto // 응답값 dto
})
@ApiOperation({summary: '회원가입' }) // swagger페이지에 설명 추가가능 
@Post()
async signUp(@Body() body : CatRequestDto) {
  console.log(body);
  return await this.catsService.signUp(body)
}
// /cats/cats.request.dto
import {IsEmail, IsNoEmpty, IsString} from 'class-validator'

export class CatRequestDto {    
  @ApiProperty({  						// 데코레이터 추가-> swagger예시
    example : "andsa@kakao.com",
    description : 'email',
    required: true
  })
  @IsEmail()
  @IsNotEmpty()
  email:String;

  @ApiProperty({  					
    example : "password123",
    description : 'password',
    required: true
  })
  @IsString()
  @IsNotEmpty()
  password:String;

  @IsString()
  @IsNotEmpty()
  name:String;

}
// /cats/cats.request.dto  - 상속으로 refactoring
import {IsEmail, IsNoEmpty, IsString} from 'class-validator'
import {Cat} from '../cats.schema';


export class CarRequestDto extends PickType (Cat, ['email','name'] as const{   //pickType -원하는 것만 가져오기

export class CatRequestDto {    
  @ApiProperty({  						// 데코레이터 추가-> swagger예시
    example : "320002",
    description : 'id',
  })
	id: string;
	}
}
profile
기록을 통해 한 걸음씩 성장ing!

0개의 댓글