사용 라이브러리
"@nestjs/typeorm": "^10.0.0",
"typeorm": "^0.3.17",
"bcrypt": "^5.1.1",
"class-transformer": "^0.5.1",
"class-validator": "^0.13.2",
postgresql을 사용하는 이유
postgresql | mysql | |
아키텍처 | 객체 관계형 | 단일 관계 |
지원하는 데이터 타입 | 숫자 날짜(시간) 문자열 JSON boolean 열거형 XML 기하형 배열 범위 네트워크 주소 |
숫자 날짜(시간) 문자열 JSON 공간(Spatial) |
장점 | 복잡한 쿼리에 유용함 데이터베이스 크기에 제한이 없음 읽기-쓰기 속도가 빠름 |
확장에 유리함 광범위한 대중성 읽기 전용 명령을 사용할 수 있음 |
postgresql을 nestjs에 추가
app.module.ts파일에서 불러오는것으로 쉽게 사용할 수 있다.
@Module({
imports: [
TypeOrmModule.forRoot({
type: 'postgres',
host: 'localhost',
port: 5432,
username: 'postgres',
password: '1234qwer',
database: 'nestjsbackend',
entities: [User],
synchronize: true,
}),
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
entities의 경우는 저렇게 불러와서 직접 채워넣어도 되고, 와일드카드('*.entity.ts'와 같은)를 이용해 작성할 수 있다.
필자는 등록되어있는 entity를 해당 파일에서 한 눈에 볼 수 있도록 불러와 사용하는 방식을 채택했다.
Entity와 DTO 생성
import {
Entity,
Column,
CreateDateColumn,
BeforeInsert,
PrimaryColumn,
} from 'typeorm';
import * as bcrypt from 'bcrypt';
@Entity('user')
export class User {
@PrimaryColumn({ nullable: false, unique: true, type: 'varchar' })
id: string;
@Column({ nullable: false, type: 'varchar' })
password: string;
@CreateDateColumn()
createAt: Date;
@BeforeInsert()
async HashPassword(): Promise<void> {
this.password = await bcrypt.hash(this.password, 10);
}
}
User를 관리하는 Entity 파일이다.
id와 password가 있으며, mongodb처럼 timestamp를 따로 지원하지 않기 때문에 createAt이라는 칼럼을 만들어야한다.
이 Entity에선 단방향 암호화가 구현되어 있는데, 마지막 HashPassword가 그 역할을 한다.
typeorm에선 해당 데이터를 저장(insert)하기 전에 실행할 메서드를 BeforeInsert 데코레이터로 작성할 수 있다.
이 경우 해당 메서드에서 비밀번호를 bcrypt 라이브러리의 hash를 이용해 재 저장한다.
import { IsNotEmpty, IsString, MinLength } from 'class-validator';
export class CreateUserDto {
@IsNotEmpty()
@IsString()
@MinLength(8, { message: '아이디는 8글자 이상이여야 합니다!' })
readonly id: string;
@IsNotEmpty()
@IsString()
readonly password: string;
}
export type UpdateUserDto = Partial<CreateUserDto>;
DTO는 위와 같이 작성하였다.
UpdateUserDto는 CreateUserDto의 Partial 타입으로서, 상위 타입의 모든 속성을 Optional로 변경하여 필요한 값만 업데이트 할 수 있도록 했다.
CRUD 구현
@Post()
async create(@Body() data: CreateUserDto): Promise<ResponseType> {
const result = await this.userservice.createUser(data);
return {
message: '사용자가 성공적으로 생성되었습니다.',
content: result,
};
}
@Get('/:id')
async getOneUser(@Param('id') id: string): Promise<ResponseType> {
const result = await this.userservice.findUser(id);
return {
message: '사용자 조회 결과입니다',
content: result,
};
}
@Get()
async getUser(): Promise<ResponseType> {
const result = await this.userservice.findAllUser();
return {
message: '사용자 조회 결과입니다',
content: result,
};
}
@Patch('/:id')
async update(
@Param('id') id: string,
@Body() data: UpdateUserDto,
): Promise<ResponseType> {
const result = await this.userservice.updateUser(id, data);
return {
message: '사용자 정보 수정 결과입니다.',
content: result,
};
}
@Delete('/:id')
async deleteUser(@Param('id') id: string): Promise<ResponseType> {
const result = await this.userservice.deleteUser(id);
return {
message: '사용자 삭제 결과입니다.',
content: result,
};
}
컨트롤러 파일이다.
export class UserService {
constructor(
@InjectRepository(User)
private readonly userRepository: Repository<User>,
) {}
createUser(data: CreateUserDto): Promise<User> {
const user: User = new User();
user.id = data.id;
user.password = data.password;
return this.userRepository.save(user);
}
findUser(data: string): Promise<User> {
return this.userRepository.findOneBy({ id: data });
}
findAllUser(): Promise<User[]> {
return this.userRepository.find();
}
deleteUser(data: string): Promise<DeleteResult> {
return this.userRepository.delete({ id: data });
}
updateUser(id: string, data: UpdateUserDto): Promise<UpdateResult> {
return this.userRepository.update({ id: id }, data);
}
}
실제 api는 이렇게 되어있다.
눈여겨 보아야 할 곳은 생성자인데, User Entity를 토대로 repository라는 인터페이스를 생성한다.
repository에서 자체적으로 제공하는 메서드만으로 crud를 간단하게 구현할 수 있다.
'개발 > 백엔드' 카테고리의 다른 글
[nestjs] AWS S3를 이용한 이미지 업로드 (0) | 2024.05.21 |
---|---|
[nestjs] 프로젝트에 prisma 추가하기 (2) | 2023.10.20 |
[nestjs] 로그인과 권한 부여 (0) | 2021.12.20 |
[nestjs] socket.io 사용과 테스트 (0) | 2021.11.01 |
[koa] mongoose 연결 / CRUD (1) | 2021.10.07 |