관심사의 분리와 MVC 패턴

뫄뫄(ahk)·2022년 9월 9일
0

Spring

목록 보기
4/18
post-thumbnail

OOP 5대 설계 원칙 - SOLID
첫번째 원칙 SRP(Single Responsibility Principle)
: 하나의 메서드는 하나의 책임만 져야한다
-> 관심사(concern) 즉 해야할 작업의 분리를 해야한다

객체지향적 설계를 위해서는 '분리'를 잘 해야하는데 첫째는 관심사, 둘째는 자주 변하는 것자주 변하지 않는 코드, 마지막으로 공통(중복)코드를 분리해야한다.

아래의 코드는 입력, 처리,출력 관심사가 분리되지 않는 메서드를 보여준다.

@PostMapping("/login")
public void login(HttpServletRequest req, HttpservletResponse res){
	//////입력//////
	String id = req.getParameter("id");
    String pwd = req.getParameter("pwd");
	//////입력//////
    
	//////처리//////    
    if(!checkLogin(id, pwd)){
    	...
    	return "/login";
    }
    
    String name = LoginService.getName(id);
	//////처리//////    
    
	//////출력//////    
    res.setContentType("text/html");
    res.setCharacterEncoding("utf-8");
    PrintWriter out = response.getWriter();
    out.println("<html>");
    ...
    out.println("</html>);
	//////출력//////    
}

입력의 분리

입력의 분리는 요청메시지의 parameter로 저장된 변수를 매핑된 메서드의 파라미터에 선언하면 Spring에서 자동으로 값을 넣어준다.

@PostMapping("/login")
public void login(String id, String pwd, HttpservletResponse res){
	
    //////처리//////    
    if(!checkLogin(id, pwd)){
    	...
    	return "/login";
    }

출력의 분리

입력은 분리했고, 처리와 출력은 어떻게 구분할까?
우선 구분을 하면 처리된 결과를 출력에 넘겨주는 수단이 필요하다. Spring은 이를 Model객체를 통해 결과값을 view(출력)단에 넘겨준다.

또한 출력을 PrintWriter 객체로 하지 않고, 출력 파일(ex. jsp)을 따로 분리하여 Model 객체로 건네받은 데이터를 출력 파일에 적용한 결과물을 응답으로 보낸다.

@PostMapping("/login")
public void login(String id, String pwd, Model m){  //입력의 분리 
    if(!checkLogin(id, pwd)){ //처리의 분리
    	...
    	return "/login";
    }
    
    String name = LoginService.getName(id);
    m.addAttribute(name);
    
    return "home"; //원래는 redirect여야한다.
}
//home.jsp파일 출력의 분리
<html>
<head></head>
<body>
	<p>${param.name}님 안녕하세요</p>
</body>
</html>

이렇게 입력, 처리, 출력이 분리된다.

처리와 출력 관심사의 분리의 방법들

(컨트롤러 메서드의 반환 타입에 따른)

  1. 뷰 이름을 반환
@RequestMapping("/getMypage")
public String main(String id, String pwd, Model m){
	...
	return "myPage";
}
  1. 매핑된 servletPath가 뷰 이름과 같음
@RequestMapping("/getMypage")
public void main(int age, String name, Model m){
	...
}
  1. ModelAndView객체를 반환
@RequestMapping("/getMypage")
public ModelAndView main(String id, String pwd){
	//Controller에서 Model객체 직접 생성
	ModelAndView mv = new ModelAndView();
	...
	//ModelAndView객체에 처리 결과값 저장
	mv.addObject(name, "youngja");
	mv.addObject(age, "33");
	
	//출력을 처리할 view페이지의 이름 지정
	mv.setViewName("myPage");
	return mv;
}
  • 메서드는 하나의 return값만 가질 수 있다. Controller는 출력할 view이름과view에 넘겨줄 model객체를 같이 넘겨줘야 하는데, ModelAndView객체가 그 일을 한다.

Reflection API를 사용해서 파라미터의 이름을 어떻게 가져올까?

  1. reflection API(jdk1.8, -parameters 옵션)

    java파일을 컴파일 할 때 컴파일러는 메서드의 파라미터 타입은 중요하게 여겨 저장하지만, 파라미터의 이름은 저장하지 않습니다. 그래서 reflectionAPI를 사용하여 코드를 작성해도, 컴파일 된 상태에서는 변수 이름이 저장되어있지 않기 때문에 읽을 수 없습니다.

따라서 컴파일 할 때 - -parameters 옵션을 줘야합니다.

  1. class file직접 읽어 가져오기

class file의 local variable table의 지역변수를 읽어서 가져와야한다.

이미 옵션을 주지 않고 컴파일 된 경우가 있기 때문에 두 가지 방법을 모두 고려해야한다.

profile
NONONONONONOYes!

0개의 댓글