Spring

[Spring] Controlle가 직접 DAO 객체의 메서드를 호출하면 안되는 몇가지 이유에 대해서

bkuk 2023. 4. 29. 02:38

Controller는 매개변수를 통해 전달된 DAO 객체를 이용해 사용자가 요청한 로직 처리

 

아래 코드를 살펴보자.

@Controller
@SessionAttributes("board")
public class BoardController {

	@RequestMapping("/insertBoard.do")
	public String insert(BoardVO vo, BoardDAO boradDAO) {
		boradDAO.insertBoard(vo);
		return "redirect:getBoardList.do";
	}
	
	@RequestMapping("/updateBoard.do")
	public String updaate(@ModelAttribute("board") BoardVO vo, BoardDAO boardDAO, ModelAndView mav){
		boardDAO.updateBoard(vo);
		return "redirect:getBoardList.do";
	}
	
	@RequestMapping("/deleteBoard.do")
	public String delete(BoardVO vo, BoardDAO boardDAO) {
		boardDAO.deleteBoard(vo);
		return "redirect:getBoardList.do";
	}
}

 

BoardController 모든 메서드가 사용자의 요청을 처리할 때 DAO 객체를 직접 이용하고 있다는 사실을 확인할 수 있다.

물론 위와 같이 개발을 한다고 해서 프로그램이 실행되지 않거나 심각한 문제가 발생하지 않는다.

하지만 Controller는 DAO 객체를 직접 이용해서는 안되며, 반드시 비즈니스 컴포넌트를 이용해야 한다.

 

BoardService 컴포넌트에 대한 클래스 다이어그램

비즈니스 컴포넌트VO 클래스, DAO 클래스, Service 인터페이스, Service 구현 클래스 등 네 개의 파일로 구성되어 있다.

아래 BoardService 컴포넌트에 대한 클래스 다이어그램을 확인해보자.

Controller는 비즈니스 컴포넌트를 이용하여 사용자의 요청을 처리해야 하며, 이때 컴포넌트가 제공하는 Service 인터페이스를 이용해야 한다.

그렇다면 Controller에서 DAO를 직접 사용하는 것이 어떤 문제를 일으키는지 확인해보자.

 

유지보수 과정에서 다른 DAO 클래스로 쉽게 교체가 가능하다

첫 번째 이유는 유지보수 과정에서 DAO 클래스를 다른 클래스로 쉽게 교체하기 위해서이다.

현재는 BoardController의 모든 메서드가 BoardDAO 객체를 매개변수로 받아서 DB 연동을 처리하고 있다.

그런데 사용하고 있던 DAO 클래스가 다른 DAO 클래스(MessageDAO, ForumDAO 등)으로 변경하거나 계속해서 변경되는 부분이 있다면?

BoardController의 모든 메서드를 수정해야 한다.

지금처럼 BoardDAO 클래스를 사용하는 Controller가 BoardController 하나면 상관이 없지만, 100_000개가 넘는다면?

해당 Controller를 모두 열어서 일일이 매개변수를 수정해야 한다. 이렇게 되면 비즈니스 컴포넌트가 변경되거나 새로운 요소가 추가될 때 마다 이를 사용하는 Controller를 수정한다면 유지보수는 어려울 수 밖에 없다.

정말 짜증나는 일이다...

 

비즈니스 컴포넌트가 수정되더라도 Controller는 수정하지 않아도 되게끔 하려면?

비즈니스 컴포넌트 입장에서 자신을 사용해주는 클라이언트는 Controller이다. 클라이언트가 인터페이스를 통해서 비즈니스 컴포넌트를 이용하면 컴포넌트의 구현 클래스를 수정하거나 다른 클래스로 대체해도 이를 사용하는 클라이언트는 수정하지 않아도 된다.

그렇다면 BoardController의 모든 메서드를 BoardService 컴포넌트의 인터페이스를 이용하도록 수정해보자.

boardService라는 멤버변수를 선언했고, 변수 위에 @Autowired 설정했으므로 BoardService 타입의 BoardServiceImpl 객체가 의존성 주입된다.

@Service("boardService")
public class BoardServiceImpl implements BoardService {
	@Autowired
	private BoardDAO boardDAO;
	
	@Override
	public void insertBoard(BoardVO vo) {
		boardDAO.insertBoard(vo);
	}

	@Override
	public void updateBoard(BoardVO vo) {
		boardDAO.updateBoard(vo);
	}
    // 생략..
}

 

그리고 모든 메서드에서 매개변수로 선언된 BoardDAO를 제거했고, 대신 boardService 변수를 이용해서 비즈니스 컴포넌트를 사용하도록 수정했다.