❗️ oop 5대 설계 원칙: SOLID
✔️ 하나의 메서드는 하나의 책임을 진다.
책임 = 관심사
: 하나의 메서드는 한개의 관심사가 있어야 한다. 따라서, 저 위 예제의 메서드 1, 2, 3을 따로 분리해야 한다.
객체지향적인 코드를 만들기 위해서는 코드의 분리를 잘해야 한다.
✏️ 코드의 분리
- 관심사의 분리
- 변하는 것, 자주 변하지 않는것의 분리 (common / uncommon)
- 공통 코드의 분리
입력: request.getParamater()
스프링이 공통 처리를 해준다.
➡️ 분리할 수 있는 이유는 입력 부분이 다 비슷하기 때문이다.
➡️ 입력을 분리하여 관심사가 2개로 줄었다.
request.getParamater()
은String
으로 받아와야 하지만, 스프링은 자동 형변환을 해줘서 int
를 파라미터에 넣는 것이 가능하다.✔️ 변하는 것, 자주 변하지 않는것의 분리 (common / uncommon)
📌 MVC 패턴
- 처리: Controller
- 출력: View
- 처리와 출력 사이 데이터가 오가는 객체: Model
같이 묶여져 있던 것을 분리를 하면, 이제 출력 부분의 yoil
변수를 쓰지 못하게 된다.
따라서, 우리는 처리와 출력 사이에 서로 주고받을 있는 객체를 만들어줘야 하는데 그것을Model
이라고 한다.
요청이 들어오면 DispatcherServlet
이 받고 그 받은 요청을 Controller
에게 보낸다.
Controller
가 처리한 결과(Model
)를 저장하여 다시 DispatcherServlet
에게 보낸다.
DispatcherServlet
이 전달 받은 Model
을 View
에게 전달한다.
View
에서 작업결과를 읽어서 응답을 만들어내서 클라이언트에게 전송하게 된다.
2번 코드를 보면 파라미터에 model이 있다. 이것은 DispacherServlet에서 model을 받아야되기 때문에 넣은 것이다. (request랑 비슷)
➡️ DispacherServlet이 Controller의 매개변수를 보고 new Model()
을 만들어 넘겨준다.
➡️ model의 작업은 Controller가 처리한다.
3번 과정에서 작업 결과를 보여줄 View의 이름을 반환한다. 그래서 4번 에서 yoil.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.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반환은 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로 만들 시, 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);
}
}
✔️ 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);
}
}
✔️ 웹 관련 설정파일
<?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