ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • NestJS에서 repository의 insert메서드로 유동적으로 데이터 생성하기
    Nest.js 2024. 6. 4. 18:30
    728x90
    // group repository create method
    export interface ICreateGroupArgs{
    	id: string;
        name: string;
        description: string;
        memberId: string;
    }
    
    async createGroup(createGroupArgs:ICreateGroupArgs){
    	await this.groupRepository.insert(createArgs)
    }
    예를들어 그룹을 생성하는 repository 메서드의 createGroup 메서드를 생성하여 사용하고 있다고 가정 했을때
    만약에 group-service에서 createGroup 메서드가 있고 createGroupAndCorverImage 메서드가 있다고 가정 해보자.

     

    // groups.service.ts
    async createGroup(createGroupArgs:ICreateGroupArgs){
    	return await this.createGroup(createGroupArgs);
    }
    
    async createGroupAndCorverImage(createGroupArgs:ICreateGroupArgs){
    	return await this.createGroup(createGroupArgs);
    }
    
    // groups.repository.ts
    export interface ICreateGroupArgs{
    	id: string;
        name: string;
        description: string;
        memberId: string;
        groupCoverImage?:string;
    }
    
    async createGroup(createGroupArgs:ICreateGroupArgs){
    	await this.groupRepository.insert(createArgs)
    }

     

    groupCoverImage 프로퍼티에 옵셔널을 주어서 각각 다른 service 메서드에서 호출 가능하다. 그런데 만약에 프로퍼티가 늘어난 케이스가 아니라 줄어든다면 어떻게 될까

     

    // groups.service.ts
    // id, name, description, memberId
    async createGroup(createGroupArgs:ICreateGroupArgs){
    	return await this.createGroup(createGroupArgs);
    }
    
    // Param: id, name, description, memberId, groupCoverImage
    async createGroupAndCorverImage(createGroupArgs:ICreateGroupArgs){ 
    	return await this.createGroup(createGroupArgs);
    }
    
    // Param: id, name
    async createGroupFromName(createGroupArgs:ICreateGroupArgs){ 
    	return await this.createGroup(createGroupArgs);
    }
    
    // groups.repository.ts
    export interface ICreateGroupArgs{
    	id: string;
        name: string;
        description?: string;
        memberId?: string;
        groupCoverImage?:string;
    }
    
    async createGroup(createGroupArgs:ICreateGroupArgs){
    	await this.groupRepository.insert(createArgs)
    }
    controller에서 넘겨주는 인자값이 createGroupFromName메서드에 id와 name만 주어진다면 결국 다른 프로퍼티들은 옵셔널을 주어야 되고 이런식으로 가다간 모든 프로퍼티에 다 옵셔널을 주어야 할것이다.

     

    // TypeOrm insert method spec
    insert(entity: QueryDeepPartialEntity<Entity> | QueryDeepPartialEntity<Entity>[]): Promise<InsertResult>;

     

    TypeOrm insert 메서드는 Entity의 프로퍼티들을 전부 Partial타입으로 받는다. 그럼으로 해당 타입을 그대로 사용 하고자 하는 service에서 사용할 수 있게 overrideInsertFeild 타입으로 인자값을 받아준다.

     

    // types/repository.ts
    import { DeepPartial } from 'typeorm';
    
    export type OverrideInsertFeild<T> = DeepPartial<T>;
    
    // feeds.repository.ts
    async createFeed(
        overrideInsertFeilds: OverrideInsertFeild<FeedEntity>,
        qr?: QueryRunner,
    ): Promise<FeedByIdResDto> {
        const feedsRepository = this.getFeedsRepository(qr);
    
        const insertResult = await feedsRepository.insert(overrideInsertFeilds);
    
        const id: string = insertResult.identifiers[0].id;
    
        return this.findOrFailFeedById(id, qr);
    }
    
    // feeds.service.ts
    async createFeed(
    { medias, mentions, ...rest }: ICreateFeedArgs,
    qr?: QueryRunner,
    ): Promise<FeedByIdResDto> {
        const newFeed = this.feedsRepository.create({
            id: uuidv4(),
            ...rest,
        });
    
        const feed = await this.feedsRepository.createFeed(newFeed, qr);
    
    
        ... 중략
            
    }
    create 메서드를 이용하여 controller에서 생성이 필요한 property값들을 받아서 create메서드로 생성 한 후 repository의 인자값으로 넘겨준다.

     

    해당 방법의 장점

    • create메서드로 필요한 필드만을 이용하여  entity class 인스턴스를 생성하여 repository의 Insert 메서드를 실행 할 수 있다.
    • @BeforeInsert나 @AfterInsert 데코레이터가 실행 되려면 인스턴스화를 꼭 해주어야 하는 이슈가 있다. create 메서드로 생성하면 해당 entity class로 인스턴스화 된다.
    728x90
Designed by Tistory.