// 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로 인스턴스화 된다.