API 1회에 많은 데이터 vs 이걸 나눠서 API 여러개
-> API 요청은 병렬처리가 가능하기 때문에 나누어서 여러 개. 즉, 후자의 속도가 빠름
데이터베이스에 모두 들고와서 Service에서 데이터 가꾸기 vs 데이터베이스에서 조건으로 데이터 빼오기
-> 둘다 출력되는 데이터는 같다고 가정
-> 전체 데이터를 가져와서 필요한 데이터만 추출하는 경우, 데이터베이스에서 불필요한 데이터까지 모두 가져오므로 네트워크 대역폭을 낭비하고, 불필요한 데이터를 서버 메모리에 적재하고 처리해야 하기 때문. 반면에 필요한 데이터만 가져오면 네트워크 대역폭과 서버 메모리를 절약할 수 있으므로 성능이 더 좋아질 수 있음 !
-> 하지만 상황에 따라 다르다는 것 (벤치마킹을 이용하여 속도 재보는게 제일 정확함)
코드 줄이기(가독성 챙기기)
이렇게 데이터를 불러오고 DB 상에선 status 코드로 구분을 해놓았다.
그래서 Controller 3개, Service 메서드 3개를 만들어 구현을 하고 있었다.
ConsultController.java @GetMapping ("consultation/last-upcoming")
public ValidCheck consultUpcoming(){
return new ValidCheck(consultService.upcoming(10L));
}
@GetMapping ("consultation/proceeding")
public ValidCheck consultProceeding(){
return new ValidCheck(consultService.proceeding(10L));
}
@GetMapping ("consultation/previous")
public ValidCheck consultPrevious(){
return new ValidCheck(consultService.previous(10L));
}
ConsultService.javapublic interface ConsultService {
public List<ConsultRespDto> upcoming(Long tutorId);
public List<ConsultRespDto> proceeding(Long tutorId);
public List<ConsultRespDto> previous(Long tutorId);
}
요롷게,,
코드를 짜놓고 보니 결국 코드 복붇 세개다.. 이럴 순 없지
-> 기존에 3개의 Controller 메서드를 1개로 줄이고
@GetMapping ("consultation/list")
public ValidCheck consultUpcoming(@RequestParam int status){
return new ValidCheck(consultService.getList(10L, status));
}
-> status를 쿼리스트링으로 받아서 Service에 매개변수로 전달하여 반복되는 코드를 줄였다
//Interface
public interface ConsultService {
public List<ConsultRespDto> getList(Long tutorId, int status);
}
//Service
@Service
@RequiredArgsConstructor
public class ConsultServiceImpl implements ConsultService{
// 0: 상담 수락 전, 1: 상담 전, 2: 상담 종료, 3:상담 거절
private final ConsultRepository consultRepository;
private final UserRepository userRepository;
private final QueryRepository queryRepository;
@Override
public List<ConsultRespDto> getList(Long tutorId, int status) {
List<Consult> consultList = consultRepository.findAllByTutorIdAndStatus(tutorId, status);
// 리스트 -> 개별 consult -> stu, query
Long stuId;
Long consultId;
List<ConsultRespDto> consultRespDtoList = new ArrayList<>();
for(int i=0; i<consultList.size(); i++) {
ConsultRespDto consultRespDto = new ConsultRespDto();
stuId = consultList.get(i).getStuId();
consultId = consultList.get(i).getId();
consultRespDto.setQuery(queryRepository.findByConsultId(consultId));
consultRespDto.setMenteeRespDto(userRepository.findById(stuId).get().toMenteeRespDto());
consultRespDto.setConsultId(consultId);
consultRespDto.setMajor(consultList.get(i).getMajor());
consultRespDto.setZoomLink(consultList.get(i).getZoomLink());
consultRespDtoList.add(consultRespDto);
}
return consultRespDtoList;
}
}
이 코드들을 곧 이쁘게 만들어서 바꿔서 다시 돌아오도록 하겠다.
@Service
@RequiredArgsConstructor
public class ConsultServiceImpl implements ConsultService{
// 0: 상담 수락 전, 1: 상담 전, 2: 상담 종료, 3:상담 거절
private final ConsultRepository consultRepository;
private final UserRepository userRepository;
private final QueryRepository queryRepository;
@Override
public List<ConsultRespDto> getList(Long tutorId, int status) {
List<Consult> consultList = consultRepository.findAllByTutorIdAndStatus(tutorId, status);
List<ConsultRespDto> consultRespDtoList = new ArrayList<>();
for (Consult consult : consultList) {
ConsultRespDto consultRespDto = mapToConsultRespDto(consult);
consultRespDtoList.add(consultRespDto);
}
return consultRespDtoList;
}
private ConsultRespDto mapToConsultRespDto(Consult consult) {
ConsultRespDto consultRespDto = new ConsultRespDto();
consultRespDto.setConsultId(consult.getId());
consultRespDto.setMajor(consult.getMajor());
consultRespDto.setZoomLink(consult.getZoomLink());
consultRespDto.setQuery(queryRepository.findByConsultId(consult.getId()));
consultRespDto.setMenteeRespDto(userRepository.findById(consult.getStuId()).get().toMenteeRespDto());
return consultRespDto;
}
}
mapToConsultRespDto() 메소드를 추가하여 코드의 가독성을 높였다.for-each 루프를 사용하여 코드를 간결하게 만들었다.
같은 고민을 해본적이 있어 의견을 남겨봅니다.
mapToConsultRespDto()는 비즈니스 로직이 아니므로 서비스가 아닌, Dto내에서 Consult를 매개변수로 받는 생성자를 작성하는건 어떨까요??