쿼리빌더를 사용해서 코드 리팩토링 한 것을 알아보기 전에,
우선 어떤 작업인지 간단하게 설명하겠습니다.
현재 개발하고 있는 서비스는 학원을 관리하는 LMS 서비스로
수업을 조회하는 부분에서 필터링이 필요했습니다.
수업 상태를 기준으로 전체, 수업 예정/ 진행중, 수업 종료 3가지에 상태가 있고
수업 종류를 기준으로 전체, 정규 클래스, 원데이 클래스 3가지 종류가 있었습니다.
처음에는 switch case문을 중첩으로 사용하여 아래와 같이 짰는데요..
async findAll(pageRequest: ArtClassPageRequest, currentAcademy: Academy) {
let getRes: ArtClass[];
const [artClasses, count] = await this.artClassRepository.findAndCountByAcademy(currentAcademy, pageRequest);
switch (artClassStatus) {
// 모든 수업
case ArtClassStatus.ALL: {
switch (artClassType) {
case ArtClassType.ALL: {
getRes = await this.artClassRepository.find({
where: {
academy: currentAcademy,
},
});
break;
}
case ArtClassType.REGULAR: {
getRes = await this.artClassRepository.find({
where: {
academy: currentAcademy,
type: ArtClassType.REGULAR,
},
});
break;
}
case ArtClassType.ONE_DAY: {
getRes = await this.artClassRepository.find({
academy: currentAcademy,
type: ArtClassType.ONE_DAY,
});
break;
}
}
break;
}
// 예정이거나 진행중인 수업
case ArtClassStatus.IN_PROGRESS: {
switch (artClassType) {
case ArtClassType.ALL: {
getRes = await this.artClassRepository.find({
where: {
academy: currentAcademy,
endDate: MoreThan(moment().format()),
},
});
break;
}
case ArtClassType.REGULAR: {
getRes = await this.artClassRepository.find({
where: {
academy: currentAcademy,
type: ArtClassType.REGULAR,
endDate: MoreThan(moment().format()),
},
});
break;
}
case ArtClassType.ONE_DAY: {
getRes = await this.artClassRepository.find({
academy: currentAcademy,
type: ArtClassType.ONE_DAY,
endDate: MoreThan(moment().format()),
});
break;
}
}
break;
}
// 종료된 수업
case ArtClassStatus.FINISHED: {
switch (artClassType) {
case ArtClassType.ALL: {
getRes = await this.artClassRepository.find({
where: {
academy: currentAcademy,
endDate: LessThan(moment().format()),
},
});
break;
}
case ArtClassType.REGULAR: {
getRes = await this.artClassRepository.find({
where: {
academy: currentAcademy,
type: ArtClassType.REGULAR,
endDate: LessThan(moment().format()),
},
});
break;
}
case ArtClassType.ONE_DAY: {
getRes = await this.artClassRepository.find({
academy: currentAcademy,
type: ArtClassType.ONE_DAY,
endDate: LessThan(moment().format()),
});
break;
}
}
break;
}
}
return getRes;
}
위에 보이시는 것과 같이 수업 상태를 switch case문을 사용하여 바깥에서 감싸고,
수업 종류에 해당하는 분기 처리를 위해 switch case문을 한번 더 사용한 것을 볼 수 있습니다.
이것이 너무 비효율적이고, 코드도 길어서 쿼리빌더를 이용해서 리팩토링 해보았는데요.
1. 쿼리빌더 생성
2. 수업 상태(예정/진행, 종료)에 따라 쿼리 빌더 값의 where절에 들어갈 조건을 적용
3. 수업 종류(정규, 원데이)에 따라 쿼리 빌더에 andWhere절의 조건을 동적으로 할당해서 리팩토링 해보았습니다.
async findAndCountByAcademy(academy: Academy, pageRequest: ArtClassPageRequest) {
const queryBuilder = createQueryBuilder(ArtClass, 'artClass')
.leftJoinAndSelect('artClass.teachers', 'teacher')
.leftJoinAndSelect('artClass.artClassTimes', 'artClassTime');
switch(pageRequest.status) {
case ArtClassStatus.IN_PROGRESS:
queryBuilder.where('artClass.end_date >= :now_date', { now_date: moment().format()});
break;
case ArtClassStatus.FINISHED:
queryBuilder.where('artClass.end_date < :now_date', { now_date: moment().format()});
break;
}
if(pageRequest.type){
queryBuilder.andWhere(`artClass.type= '${pageRequest.type}'`);
}
if(pageRequest.pagingMode) {
queryBuilder.take(pageRequest.limit).skip(pageRequest.offset);
}
return queryBuilder.getManyAndCount();
}
완벽한 방법은 아니지만, 한결 간결해진 코드를 볼 수 있습니다.
좋은 방법이 있다면 댓글로 달아주시면 감사하겠습니다!
'JavaScript & TypeScript' 카테고리의 다른 글
[NestJS] iterable 객체 병렬처리 하기(feat.Bluebird JS) (1) | 2022.10.09 |
---|---|
[NestJS] class-validator를 사용한 필수값 체크(feat.다음 우편번호 API) (0) | 2022.10.08 |
[NestJS] DTO의 사용범위에 관한 고찰 및 리팩토링(feat.Layered Architecture) (4) | 2022.09.23 |
[NestJS] 이벤트 드리븐으로 기능 구현하기(feat.Event Emitter) (0) | 2022.09.18 |
[NestJS] Many-to-Many 생성시에 할당하는 코드 리팩토링 (feat.TypeORM) (0) | 2022.07.12 |