프로젝트/웹 ERD 프로젝트

[리팩토링] Controller/ Service/ DAO 책임 분배

킹갓홍 2023. 11. 9. 16:41

프로젝트를 진행하면서 Controller/ Service/ DAO(Data Access Object)로 나눠서 진행을 했었는데, 

정확히 "왜 나누지?" 에 대한 궁금증을 해결하지 않고 프로젝트를 진행하다 보니 Controller에서 너무 많은 일을 하는 것 같다는 피드백이 들어왔다.

 

Controller/ Service/ DAO 각각의 책임

  • Controller
    클라이언트의 요청을 처리하고 해당 요청에 대한 응답을 생성하는데 사용
    UI와 상호작용하고, 클라이언트에서 받은 데이터를 처리
    데이터 유효성 검사, 사용자 입력 처리, 응답생성 등의 제어흐름을 관리
  • Service
    비즈니스 로직을 구현하고 제공하는 역할
    Controller와 DAO간의 중간 레이어로 작용하여 비즈니스 로직을 추상화하고 모듈화
    데이터를 가공, 조작, 다른 서비스 레이어와 협력하여 비즈니스 요구사항을 충족
  • DAO(Data Access Object)
    데이터베이스와 상호작용하기 위한 데이터 엑세스 로직을 포함하는 역할
    데이터베이스와의 연결 및 쿼리실행을 처리, 특정 테이블 또는 엔티티와 상호작용
    데이터베이스 연동코드를 추상화하여 데이터베이스 종속성을 줄이고 코드 재사용성을 향상

위의 내용을 바탕으로 우선 Controller에 집중되어 있는 코드들과 비즈니스 로직을들을 Service에 위임하기로 했다.

 

MailController

@RequestMapping(value = "/sendMailProcess", method = RequestMethod.POST)
    public String sendMail(HttpSession session, HttpServletRequest request,
                @RequestParam("mail_file") MultipartFile multipartFile) {

        //사용자 정보
        MemberDTO loginDto = (MemberDTO)session.getAttribute("login");

        //메일 받는 사람들
        String addressListStr = request.getParameter("mail_receiver");

        //데이터 파싱
        String mail_title = request.getParameter("mail_title");
        String mail_content = request.getParameter("mail_content");
        String mail_sender = loginDto.getMail();
        int member_num = loginDto.getMember_num();	

        //Service에 넘겨줄 MailDTO
        MailDTO mailDto = new MailDTO();
        mailDto.setMail_title(mail_title);
        mailDto.setMail_content(mail_content);
        mailDto.setMail_sender(mail_sender);
        mailDto.setMember_num(member_num);

        String msg = service.insertMail(mailDto, addressListStr, multipartFile);
        session.setAttribute("msg", msg);	
        return "redirect:writeMail";
	}


MailService

//메일 보내기
public String insertMail(MailDTO mailDto, String addressListStr, MultipartFile multipartFile) {
    if(!multipartFile.isEmpty()) {
        saveFile(mailDto, multipartFile);
    }
    int res1 = dao.insertMail(mailDto);

    //최근 메일 고유번호
    int recentEmailNum = mailDto.getMail_num();
    
    //DB에 넘겨줄 MailRecDto
    MailRecDTO mailRecDto = new MailRecDTO();
    mailRecDto.setMail_num(recentEmailNum);

    //Mail_Rec테이블 insert (MappingTable -- 받은 사람들 저장하기)
    String msg = "메일전송이 완료되었습니다!";
    if(addressListStr != null) {
        String addressList[] = addressListStr.split(" ");
        List<Integer> rec_numList = dao.findMemberNumByEmail(addressList);

        int res = 0;
        for(int i=0; i<rec_numList.size(); i++) {
            mailRecDto.setRec_num(rec_numList.get(i));
            mailRecDto.setMail_receiver(addressList[i]);
            res += dao.insertReceiveTable(mailRecDto); //insert 작업
        }

        if(res != rec_numList.size()) {
            msg = "다시 시도해주세요";
            return "redirect:writeMail";
        }
    } 
    //내게쓰기인 경우
    else if(addressListStr == null) {
        mailRecDto.setRec_num(mailDto.getMember_num());
        mailRecDto.setMail_receiver(mailDto.getMail_sender());
        dao.insertReceiveTable(mailRecDto); //insert 작업
    }
    return msg;
}

 

이런식으로 Controller에는 Http요청과 HttpSession의 데이터 관리만 하고 
데이터들을 Service에 넘겨준 뒤 Service에서 비즈니스 로직들을 처리하도록 했다.

 

확실히 가독성이 많이 올라가고, 결합성이 줄어들어 유지보수가 쉬울 것 같다는 생각이 들었다.
그리고 이전의 코드는 메일쓰기와 내게 메일쓰기의 비즈니스 로직이 따로 처리가 되었지만,
가독성이 높아지면서 합쳐놔도 큰 문제가 생기지 않는다는 것을 알게되어 코드의 효율성도 올릴 수 있었다.