[Spring] 관심사의 분리, MVC패턴

Jeini·2023년 5월 20일
0

🍃  Spring

목록 보기
2/33
post-thumbnail

💡 관심사의 분리 Separation of Concerns


❗️ oop 5대 설계 원칙: SOLID

📎 SRP(단일책임의 원칙)

✔️ 하나의 메서드는 하나의 책임을 진다.

  • 책임 = 관심사
    : 하나의 메서드는 한개의 관심사가 있어야 한다. 따라서, 저 위 예제의 메서드 1, 2, 3을 따로 분리해야 한다.

  • 객체지향적인 코드를 만들기 위해서는 코드의 분리를 잘해야 한다.

✏️ 코드의 분리

  1. 관심사의 분리
  2. 변하는 것, 자주 변하지 않는것의 분리 (common / uncommon)
  3. 공통 코드의 분리

💡 공통 코드의 분리 - 입력의 분리


  • 입력: request.getParamater()

  • 스프링이 공통 처리를 해준다.
    ➡️ 분리할 수 있는 이유는 입력 부분이 다 비슷하기 때문이다.
    ➡️ 입력을 분리하여 관심사가 2개로 줄었다.

  • request.getParamater()String 으로 받아와야 하지만, 스프링은 자동 형변환을 해줘서 int 를 파라미터에 넣는 것이 가능하다.

💡 출력(view)의 분리


✔️ 변하는 것, 자주 변하지 않는것의 분리 (common / uncommon)

업로드중..

📌 MVC 패턴

  • 처리: Controller
  • 출력: View
  • 처리와 출력 사이 데이터가 오가는 객체: Model

같이 묶여져 있던 것을 분리를 하면, 이제 출력 부분의 yoil 변수를 쓰지 못하게 된다.
따라서, 우리는 처리와 출력 사이에 서로 주고받을 있는 객체를 만들어줘야 하는데 그것을Model 이라고 한다.

📎 MVC 패턴 단순화

  1. 요청이 들어오면 DispatcherServlet 이 받고 그 받은 요청을 Controller 에게 보낸다.

  2. Controller 가 처리한 결과(Model)를 저장하여 다시 DispatcherServlet 에게 보낸다.

  3. DispatcherServlet 이 전달 받은 ModelView 에게 전달한다.

  4. View 에서 작업결과를 읽어서 응답을 만들어내서 클라이언트에게 전송하게 된다.

📎 MVC 패턴 코드로 보기

2번 코드를 보면 파라미터에 model이 있다. 이것은 DispacherServlet에서 model을 받아야되기 때문에 넣은 것이다. (request랑 비슷)
➡️ DispacherServlet이 Controller의 매개변수를 보고 new Model() 을 만들어 넘겨준다.
➡️ model의 작업은 Controller가 처리한다.

3번 과정에서 작업 결과를 보여줄 View의 이름을 반환한다. 그래서 4번 에서 yoil.jsp 를 보여준 것이다.

✏️ MVC 패턴 예시


✏️ 입력 분리

package kr.ac.jipark09.ch2;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Calendar;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

// 년,월,일을 입력하면 요일을 알려주는 프로그램
@Controller
public class YoilTellerMVC {
	@RequestMapping("/getYoilMVC")
	// request를 받는대신 파라미터 값을 직접 받아온다.
	public void main(int year, int month, int day, HttpServletResponse response) throws IOException {
		
		// 2. 처리
		Calendar cal = Calendar.getInstance();
		cal.set(year, month - 1, day);
		
		int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK);
		char yoil = " 일월화수목금토".charAt(dayOfWeek);
		
		// response 객체에서 브라우저로의 출력 스트림을 얻는다.
		response.setContentType("text/html");
		response.setCharacterEncoding("utf-8");
		// response 객체에서 브라우저로의 출력 스트림을 얻는다.
		PrintWriter out = response.getWriter();
		out.println("<html>");
		out.println("<head>");
		out.println("</head>");
		out.println("<body>");
		out.println(year + "년" + month + "월" + day + "일");
		out.println(yoil + "요일 입니다.");
		out.println("</body>");
		out.println("</html>");
	}

}

✏️ 출력 분리: String 반환 ⭐️

✔️ String반환은 View 이름 (.jsp)

package kr.ac.jipark09.ch2;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Calendar;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

// 년,월,일을 입력하면 요일을 알려주는 프로그램
@Controller
public class YoilTellerMVC {
	@RequestMapping("/getYoilMVC")
	// request를 받는대신 파라미터 값을 직접 받아온다.
	// 뷰가 따로 떼어졌으니 더이상 response도 필요없다.
	// model 객체를 넣어주지 않으면 연산한 값들이 yoil.jsp에 전달되지 않는다.
	// String은 뷰 이름
	public String main(int year, int month, int day, Model model) throws IOException {
		
		//1. 유효성 검사
		if(!isVaild(year, month, day)) {
			return "yoilError";
		}
		
		// 2. 요일 계산
		char yoil = getYoil(year, month, day);
		getYoil(year, month, day);
		
		// 3. 계산한 결과를 model에 저장
		model.addAttribute("year", year);
		model.addAttribute("month", month);
		model.addAttribute("day", day);
		model.addAttribute("yoil", yoil);
		
		return "yoil"; // yoil.jsp를 보여줘라
	}

	private boolean isVaild(int year, int month, int day) {
		return true;
	}

	private char getYoil(int year, int month, int day) {
		Calendar cal = Calendar.getInstance();
		cal.set(year, month - 1, day);
		
		int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK);
		return " 일월화수목금토".charAt(dayOfWeek);
	}

}

✏️ 출력 분리: void

✔️ void로 만들 시, Mapping된 이름의 jsp파일이 열린다.
✔️ 보통 이렇게는 잘 쓰이지 않는다. 가능하다는 점만 알아두자.

package kr.ac.jipark09.ch2;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Calendar;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

// 년,월,일을 입력하면 요일을 알려주는 프로그램
@Controller
public class YoilTellerMVC {
	@RequestMapping("/getYoilMVC")
	
	// void로 만들 시, Mapping된 이름의 jsp파일이 열린다.
	public void main(int year, int month, int day, Model model) throws IOException {
		
		// 2. 요일 계산
		char yoil = getYoil(year, month, day);
		getYoil(year, month, day);
		
		// 3. 계산한 결과를 model에 저장
		model.addAttribute("year", year);
		model.addAttribute("month", month);
		model.addAttribute("day", day);
		model.addAttribute("yoil", yoil);
	}

	private boolean isVaild(int year, int month, int day) {
		return true;
	}

	private char getYoil(int year, int month, int day) {
		Calendar cal = Calendar.getInstance();
		cal.set(year, month - 1, day);
		
		int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK);
		return " 일월화수목금토".charAt(dayOfWeek);
	}

}

✏️ 출력 분리: ModelAndView

✔️ Model + View
✔️ 잘 쓰이지 않는다. 이렇게도 할 수 있다는 것만 알아두자.

package kr.ac.jipark09.ch2;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Calendar;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

// 년,월,일을 입력하면 요일을 알려주는 프로그램
@Controller
public class YoilTellerMVC {
	@RequestMapping("/getYoilMVC")
	
	// void로 만들 시, Mapping된 이름의 jsp파일이 열린다.
	public ModelAndView main(int year, int month, int day) throws IOException {
		// Model과 View를 담을 객체를 생성한다.
		ModelAndView mv = new ModelAndView();
		
//		//1. 유효성 검사
//		if(!isVaild(year, month, day)) {
//			return "yoilError";
//		}
		
		// 2. 요일 계산
		char yoil = getYoil(year, month, day);
		getYoil(year, month, day);
		
		// 3. 계산한 결과를 mvl에 저장: model 저장
		mv.addObject("year", year);
		mv.addObject("month", month);
		mv.addObject("day", day);
		mv.addObject("yoil", yoil);
		
		// 4. 결과를 보여줄 뷰를 지정: view 저장
		mv.setViewName("yoil");
		
		return mv;
	}

	private boolean isVaild(int year, int month, int day) {
		return true;
	}

	private char getYoil(int year, int month, int day) {
		Calendar cal = Calendar.getInstance();
		cal.set(year, month - 1, day);
		
		int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK);
		return " 일월화수목금토".charAt(dayOfWeek);
	}

}

⚙️ servlet-context-xml

✔️ 웹 관련 설정파일

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:beans="http://www.springframework.org/schema/beans"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd
		http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">

	<!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->
	
	<!-- Enables the Spring MVC @Controller programming model -->
	<annotation-driven />

	<!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
	<resources mapping="/resources/**" location="/resources/" />

	<!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory -->
	<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<beans:property name="prefix" value="/WEB-INF/views/" />
		<beans:property name="suffix" value=".jsp" />
	</beans:bean>
	
	<context:component-scan base-package="kr.ac.jipark09.ch2" />
</beans:beans>

❗️ ViewResolver: View의 경로를 지정하는 곳

<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
	<beans:property name="prefix" value="/WEB-INF/views/" />
	<beans:property name="suffix" value=".jsp" />
</beans:bean>
  • 접두사로 경로를 붙이고 접미사로 .jsp로 붙이라고 되어있다.
  • 만약 jsp말고 다른 파일을 사용하고 싶을 때 여기서 바꾸면 된다.

Reference
:https://fastcampus.co.kr/dev_academy_nks

profile
Fill in my own colorful colors🎨

0개의 댓글