* 설계
- 이미지가 생성되고
- post 생성되고 를 묶어서
- all or nothing으로 만들고자 함.
* image table 생성
- post 는 여러개의 image를 가진다.
import { BaseModel } from "./base.entity";
import { IsEnum, IsInt, IsOptional, IsString } from "class-validator";
import { Column, Entity, ManyToOne } from "typeorm";
import { Transform } from "class-transformer";
import { join } from "path";
import { POST_PUBLIC_IMAGE_PATH } from "../const/path.const";
import { PostsModel } from "../../posts/entities/posts.entity";
export enum ImageModelType{
POST_IMAGE,
}
@Entity()
export class ImageModel extends BaseModel{
@Column({
default: 0,
})
@IsInt()
@IsOptional()
order: number; //이미지 보여줄 순서
// usersMode -> 사용자 프로필 이미지
// postModel -> 포스트 이미지
@Column({
enum: ImageModelType,
})
@IsEnum(ImageModelType)
@IsString()
type: ImageModelType;
@Column()
@IsString()
@Transform(({value, obj}) => { //value == img이름, 현재객체(image객체)
if(value && obj.type === ImageModelType.POST_IMAGE){
return join(
POST_PUBLIC_IMAGE_PATH,
value,
)
}
else{
return value;
}
})
path: String;
//연동될타입, 어떤 속성과 연동될건지
@ManyToOne((type) => PostsModel, (post) => post.images)
post?: PostsModel;
}
@Entity() //테이블생성해줘
export class PostsModel extends BaseModel{
...
@OneToMany((type)=> ImageModel, (image)=> image.post)
images?: ImageModel[];
- app.module에서 typeOrm entities에 추가도 빼먹지 말것.
TypeOrmModule.forRoot({
type: 'postgres',
host: process.env[ENV_DB_HOST_KEY],
port: +process.env[ENV_DB_PORT_KEY],
username: process.env[ENV_DB_USERNAME_KEY],
password: process.env[ENV_DB_PASSWORD_KEY],
database: process.env[ENV_DB_DATABASE_KEY],
entities: [
PostsModel,
UsersModel,
ImageModel,
], //생성할 모델들
* 서비스 구현
- dto 수정
export class CreatePostDto extends PickType(PostsModel, ['title', 'content']){
@IsString({
each:true, //배열의 모든 요소 검증
})
@IsOptional()
images?: string[] = [];
}
- 의존성 주입
@Injectable()
export class PostsService {
constructor(
@InjectRepository(PostsModel)
private readonly postsRepository: Repository<PostsModel>,
@InjectRepository(ImageModel)
private readonly imageRepository : Repository<ImageModel>,
- 모델만 주입받을때는 TypeOrm에 import 할것 주의!!
@Module({
imports:[
TypeOrmModule.forFeature([
PostsModel,
ImageModel, //Repository만 import할때는 여기!
]),
AuthModule,
UsersModule,
CommonModule,
],
controllers: [PostsController],
providers: [PostsService],
})
export class PostsModule {}
- 이미지 등록 dto 생성
import { PickType } from "@nestjs/mapped-types";
import { ImageModel } from "../../../common/entity/image.entity";
// 이미지 1개에 대한 정보
export class CreatePostImageDto extends PickType(ImageModel, ['path','post','order','type']){
}
- 컨트롤러
- body의 image들에 대해 하나씩 돌면서 imageTable에 넣어주기
@Post()
@UseGuards(AccessTokenGuard)
async postPost(
@User('id') userId : number,
@Body() body : CreatePostDto,
){
const post = await this.postsService.createPost(userId ,body);
/**
* body의 image 이름들에대해
* 각각 정보들을 넣어서 이미지를 만듬(db에 저장)
* 주인은 post
*/
for(let i=0;i<body.images.length;i++){
await this.postsService.createPostImage({
post,
order:i,
path:body.images[i],
type:ImageModelType.POST_IMAGE,
});
}
return this.postsService.getPostById(post.id);
}
* post조회시 외래키 표시 속성 일반화
import { FindManyOptions } from "typeorm";
import { PostsModel } from "../entities/posts.entity";
export const DEFAULT_POST_FIND_OPTIONS: FindManyOptions<PostsModel> ={
relations:{
author: true,
images: true,
}
}
- 사용
async getPostById(id:number) {
const post = await this.postsRepository.findOne({
where:{
id,
},
...DEFAULT_POST_FIND_OPTIONS,
});
'JS > Nest.js' 카테고리의 다른 글
[Nest] Interceptor => logger 구현, @Transactional 구현 (0) | 2024.09.22 |
---|---|
[Nest] Transaction 구현 (0) | 2024.09.22 |
[Nest] 이미지 업로드 구현V2 (0) | 2024.09.22 |
[Nest] 이미지 업로드 구현 V1 (0) | 2024.09.22 |
[Nest] 환경변수 .env 구현 (0) | 2024.09.22 |