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