[코팩] NestJs Column Annotation 상세하게 사용해보기

Seong Hyeon Kim·2024년 3월 20일
0

NestJs

목록 보기
12/14

Column Annotation

우선 이 내용을 기존과 겹치면 오히려 헷갈릴 수 있기 때문에 깔금하게 새로운 프로젝트를 만들고 시작합니다.

  1. 새로운 네스트 프로젝트 만들기

    nest new 프로젝트 이름

터미널창에서 위 키워드를 입력해서 새로운 프로젝트를 만들어줍니다.

  1. 도커파일도 새롭게 만들기
services:
  postgres:
    image: postgres:15
    restart: always
    volumes:
      - ./postgres-data:/var/lib/postgresql/data
    ports:
      - "5432:5432"
    environment:
      POSTGRES_USER: postgres2
      POSTGRES_PASSWORD: 패스워어어어어어드
      POSTGRES_DB: typeormstudy

도커파일도 새롭게 만들어준 후
postgres-data 라는 폴더도 만들어줍니다.

이후엔 미리 설치된 도커파일 다시 실행시켜놓고

터미널창에서 docker-compose up 을 입력해서 다시 도커로 db 연결까지 잘 마무리 해 놓고 다시 시작을 해보겠습니다.




이제 app 모듈에서 db 설정도 작성해줍니다.

src/app.module.ts

@Module({
  imports: [
    TypeOrmModule.forFeature([
      UserModel
  ]),
    TypeOrmModule.forRoot({
      type: 'postgres',
      host: '127.0.0.1',
      port: 5432,
      username: 'postgres2',
      password: '비밀번호오오오옹',
      database: 'typeormstudy',
      entities: [
        UserModel,
      ],
      synchronize: true,
    }),
  ],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

src/entity/user.entity.ts


import { Entity, Column, PrimaryGeneratedColumn, PrimaryColumn, CreateDateColumn, UpdateDateColumn, VersionColumn, Generated } from 'typeorm';

@Entity()
export class UserModel {

  /**
   * @PrimaryGeneratedColumn()
   * - PrimaryColumn 을 자동적으로 생성해주겠다는 의미가 있습니다.
   * 
   * 
   * @PrimaryColumn()
   *  - 자동생성이 빠진 모든 테이블에 기본으로 존재해야 하는 칼럼을 의미합니다.
   *  - 자동으로 생성되지 않기 때문에 반드시 직접 넣어줘야 합니다
   * 
   * 
   * @PrimaryGeneratedColumn(uuid)
   *  - PrimaryGeneratedColumn 의 값을 uuid값으로 생성해줍니다.
   *  ex) 0243c788-6f44-4cf4-8fdc-b387cf335342
   *
   * 
   *  @CreateDateColumn()
   *  - 생성된 날짜와 시간을 자동으로 생성해줍니다. 
   * 
   * 
   *  @UpdateDateColumn()
   *  - 업데이트 된 시간을 자동으로 생성해줍니다.
   * 
   *  @VersionColumn()
   *  - 데이터가 업데이트 될때마다 1씩 올라간다.
   *  - 처음 생성값은 1이고 정확히 말하면 save() 함수가 몇번 불렸는지를 기억하는 함수이다.
   * 
   * 
   *  @Generated(increment)
   *  - PrimaryColumn은 아니지만 그냥 1부터 1씩 증가한다
   *  - 사용할때에는 반드시 @Column() 과 같이 사용해줘야 한다.
   */

  @PrimaryGeneratedColumn()
  id: number;

  // 제목
  @Column()
  title: string;

  // 데이터 생성일자
  @CreateDateColumn()
  createdAt: Date;

  // 데이터 업데이트 일자
  @UpdateDateColumn()
  updateAt: Date;

  // 데이터가 변경될때마다 횟수를 카운팅
  @VersionColumn()
  version: number;

  @Column()
  @Generated('uuid')
  additionalId: string;
}

유저정보로 사용될 엔티티도 생성해줍니다.

src 폴더에서 entity 라는 폴더를 생성후 그 폴더에서 다시 user.entity.ts 라는 파일을 생성해주고 뒤 코드 내용을 입력해줍니다.

주석으로 적힌 내용을 다시 짚어보면서 설명을 하자면

자주 사용될 혹은 알고있으면 좋을 칼럼들은 다음과 같습니다.

@PrimaryGeneratedColumn()
PrimaryColumn 을 자동적으로 생성해주겠다는 의미가 있습니다

  • @PrimaryColumn()
    자동생성이 빠진 모든 테이블에 기본으로 존재해야 하는 칼럼을 의미합니다. 자동으로 생성되지 않기 때문에 반드시 직접 넣어줘야 합니다
  • @PrimaryGeneratedColumn(uuid)
    PrimaryGeneratedColumn 의 값을 uuid값으로 생성해줍니다.
    ex) 0243c788-6f44-4cf4-8fdc-b387cf335342

  • @CreateDateColumn()
    생성된 날짜와 시간을 자동으로 생성해줍니다.

  • @UpdateDateColumn()
    업데이트 된 시간을 자동으로 생성해줍니다.
  • @VersionColumn()
    처음 생성값은 1이고 데이터가 업데이트 될때마다 1씩 올라간다. 좀더 정확히 말하면 save() 함수가 몇번 불렸는지를 기억하는 함수이다.
  • @Generated(increment)
    PrimaryColumn은 아니지만 그냥 1부터 1씩 증가한다. 사용할때에는 반드시 @Column() 과 같이 사용해줘야 한다.

이제 위 엔티티를 실제로 사용해보기 위해 컨트롤러 에서 간단한 api 들을 만들어보겠습니다.

import { Controller, Get, Post,Patch, Param } from '@nestjs/common';
import { UserModel } from './entity/user.entity';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { retry } from 'rxjs';

@Controller()
export class AppController {
  constructor(
    @InjectRepository(UserModel)
    private readonly userRepository: Repository<UserModel>
  ) {}

  @Post('users')
  postUser() {
    return this.userRepository.save({
      title: 'test title'
    });
  }

  @Get('users')
  getUsers() {
    return this.userRepository.find();
  }

  @Patch('users/:id')
  async patchUser(
    @Param('id') id:string
  ){
    const user = await this.userRepository.findOne({
      where:{
        id:parseInt(id),
      }
    });
    return this.userRepository.save({
      ...user,
      title: user.title +'_+1',
    })
  }
}

거의 대분의 값을 이미 엔티티를 생성하면서 만들어지는게 많고 실제 값이 어떻게 나오는지를 테스트하기 위함이기 때문에 간단하게 작성을 해보았습니다.

title 값은 test title 로 고정하고

id 값

변경되는것은 version 이나




이제 이 내용을 토대로 포스트맨을 실행해보겠습니다

post 요청 사진입니다
사진상에서는 테스트로 여러번 만들어논후 캡쳐한거라 id 값이 3으로 나오고 있습니다.

그 외에 나머지 값들도 생각한대로 잘 나오는것을 볼 수 있습니다.


마찬가지로 get 요청 역시 잘되는것을 볼 수 있습니다.


patch 요청 사진 입니다.
2번 id 값의 내용을 수정하였고 수정할때마다 변경되기로한 version 값과 title의 +1 이 잘 나오는것도 확인할 수 있습니다.


Column Property 정리하기

column 은 보통 실제 테이블의 칼럼과 작성한 값을 매핑이 되는데 보통은 타입스크립트가 자동으로 유추를 하는데요,

일반적으로는 아래 예시와 같이 타입을 작성해서 지정해주는게 좋습니다.


  // 제목
  @Column({
    type: 'varchar'
  })
  title: string;

자동완성으로 타입을 찾기도 편하게 되어 있습니다.

이제 여기서 작성할 수 있는것들을 몇가지 예시로 작성해보자면 다음과 같습니다.

src/entity/user.entity.ts


  // 제목
  @Column({
    // 보통 자동으로 유추
    name: 'title',

    type: 'varchar',


    // 값의 길이를 지정한다. 최대 300
    length:100,

    // null 을 허용하는지
    nullable: true,
    
    // 타이틀값이 변경이 가능한지
    update:true,

    // 이 칼럼의 값을 보이게 할건지 안할건지
    select:false

    // 아무런 값도 입력하지 않았을대에 주어지는 기본값
    default: 'default value'
    
   // 칼럼중에서 유일무이한 값이 되어야 하는지
    unique: false,

  })
  title: string;

위 내용들의 설명은 주석과 같습니다.

이렇게 변경후 테스트로 다시 포스트맨을 실행해보겠습니다.


select를 예시로 먼저 더 보여드리도록 하겠습니다.
slect 값을 false 로 변경했을때에는 get 요청을 해도 값이 안나오는것을 볼 수 있습니다.

여기서 원래대로 false 를 true 로 변경하면 기존과 동일하게 나오게 하겠지만 엔티티파일에서가 아닌 컨트롤러에서도 변경이 가능한데요,

  @Get('users')
  getUsers() {
    return this.userRepository.find({
      select:{
        title:true,
      }
    });
  }

컨트롤러에 있는 get 요청 코드를 추가하면 select 만 보게 하는것도 가능합니다.


default 같은경우는 아무런 값도 입력하지 않았을때에 나오는 값을 의미합니다.

  @Post('users')
  postUser() {
    return this.userRepository.save({
      // title: 'test title'
    });
  }

포스트요청에서 기본으로 작성되었던 title 값을 주석처리하였고, 위에서 이미 null 값을 허용해놨기 때문에 post 요청이 실행을 잘될텐데요, 이때 입력될 값이 없었기 때문에 defalut 에 미리 입력해놓은 값으로 생성이 됩니다.



마지막으로 unique 입니다

유니크값은 primary 값이 아닌 값중에서 절대 겹치지 않아야될 유일무이한 값으로 지정해야할때 사용할 수 있습니다.

대표적인 예로 회원가입시 이메일 값을 unique 값으로 세팅할 수도 있겠습니다.

업로드중..

우선 기존에 있던 자료를 전부 지우고 새롭게 post요청을 해보면 다음과 같은 오류가 나오는데요,

이게 유니크 때문에 발생한 에러입니다.

profile
삽질도 100번 하면 요령이 생긴다. 부족한 건 경험으로 채우는 백엔드 개발자

0개의 댓글