1. 관심사의 분리 (Separation of Concerns)
[YoilTeller.java]
// 날짜 연월일을 입력하면, 날짜를 말해주는 프로그램
@Controller // Controller 를 통해서, 로컬프로그램을 원격프로그램으로 변경
public class YoilTeller {
// public static void main(String[] args) {
@RequestMapping("/getYoil")
public void main(HttpServletRequest request, HttpServletResponse response) throws IOException{
// 1. 입력
String year = request.getParameter("year");
String month = request.getParameter("month");
String day = request.getParameter("day");
// 2. 작업
int yyyy = Integer.parseInt(year);
int mm = Integer.parseInt(month);
int dd = Integer.parseInt(day);
Calendar cal = Calendar.getInstance();
cal.set(yyyy, mm - 1, dd);
int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK); // 1 = 일, 2 = 월 ...
char yoil = "일월화수목금토".charAt(dayOfWeek);
// 3. 출력
response.setContentType("text/html"); // response 객체 형식을 적어야한다. 즉, 출력할 내용의 타입을 적어야한다.
response.setCharacterEncoding("UTF-8"); // 텍스트도 인코딩을 해야지 한글이 깨지지 않는다.
PrintWriter out = response.getWriter(); // response객체에서 브라우져로의 출력 스트림을 얻는다.
out.println(year + "년" + month + "월" + day + "일은 ");
// 원래 제대로 하려면 HTML 형식을 갖춰서 해야한다.
out.println(yoil + "요일입니다.");
}
}
관심사는 해야할 작업이라 생각하면 된다.
객체 지향적으로는 코드 분리를 잘해야한다.
현재 위의 [YoilTeller.java]파일에서 main이라는 메소드는 3개의 관심사가 있다.
즉 OOP 5대 설계원칙(SOLID)에 부합하는 코드로 보면, 좋은 코드는 아니다.
(SOLID는 추후에 계속 설명) SOLID의 S는 SRP는 단일 책임 원칙이다.
단일 책임(관심사)의 원칙은 "하나의 메소드는 하나의 책임만 진다"는 뜻이다.
즉 3개의 관심사를 분리해야한다.
분리
- 관심사의 분리
- 변하는 것과 변하지 않는 것의 분리 (common, uncommon = 자주 변하는 것과 아닌 것)
- 공통코드(중복코드)
작성한 코드를 보고, 3가지 분리사항에 부합하는지 보면 객체 지향적으로 잘 분리된 코드로 볼 수 있다.
2. 공통 코드의 분리 - 입력의 분리
각각의 입력부분을 떼어서, 공통코드로 한 곳으로 분류한다.
@RequestingMapping("/getYoil")
public void main(HttpServletRequest request, HttpServletRespons)
String을 int로 쓸 수도 있다.
(YoilTellerMVC.java 참고) 자동변환도 된다.
공통코드를 분리함으로써, 하나의 관심사가 사라지게 된다.
3. 출력(view)의 분리 - 변하는 것과 변하지 않는 것의 분리
[Spring MVC]
사용자의 요청이 들어오게 되면, 앞에서 입력처리를 한다. (DispatcherServlet),
DispatcherServlet 입력 처리 후에 해당 Controller에게 넘겨준다.
Controller는 처리한 결과를 Model 객체를 하나 만든 뒤에 값들을 다 저장하고 DispatcherServlet이 Model을 View에 전달한다.
View는 작업 결과를 읽어서, 응답을 만들어 낸 뒤에, 클라이언트에게 전송하게 된다.
이것이 Spring MVC 패턴이다.
4. MVC 패턴
View를 Controller와 분리하게 되면, 상황에 맞는 View를 보여주기 편리해진다.
그렇기에 아래의 경우에는 yoil.jsp와 yoilError.jsp 로 구분했다.
[YoilTellerMVC.java]
// 날짜 연월일을 입력하면, 날짜를 말해주는 프로그램
@Controller // Controller 를 통해서, 로컬프로그램을 원격프로그램으로 변경
public class YoilTellerMVC {
@RequestMapping("/getYoilMVC") // RequestMapping은 중복되는 게 있으면 안된다.
public String main(int year, int month, int day, Model model) throws IOException{
// String을 int로 변경, 반환타입은 String으로 변경
// 1. 유효성 검사 필요
if(isValid(year, month, day))
return "yoilError"; // WEB_INF/views/yoilError.jsp = 에러시에 나오는 view
// 2. 요일 계산
char yoil = getYoil(year, month, day);
// 3. 계산한 결과를 Model에 저장
model.addAttribute("year", year);
model.addAttribute("month", month);
model.addAttribute("day", day);
model.addAttribute("yoil", yoil);
return "yoil"; // WEB_INF/views/yoil.jsp
}
private boolean isValid(int year, int month, int day) {
// 클래스 내에서만 쓰기에 private
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); // 1 = 일, 2 = 월 ...
return "일월화수목금토".charAt(dayOfWeek);
}
}
[yoil.jsp]
<%@ page contentType="text/html; charset=UTF-8" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ page session="false" %>
<html>
<head>
<title>yoil</title>
</head>
<body>
<P> ${year }년 ${month }월 ${day }일은 ${yoil }입니다. </P>
</body>
</html>
[yoilError.jsp]
<%@ page contentType="text/html; charset=UTF-8" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ page session="false" %>
<html>
<head>
<title>yoilError</title>
</head>
<body>
<P> 잘못된 요청입니다.<br>
년, 월, 일을 모두 올바르게 입력해주세요. </P>
</body>
</html>
[servlet-context.xml]
src/main/webapp/WEB-INF/spring/appServlet 에 있는 servlet-context.xml에 적혀있는 것이다.
아래 코드 때문에, 접두사나 접미사에 경로나 확장자가 붙는 것이다.
<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>
5. ModelAndView
// 날짜 연월일을 입력하면, 날짜를 말해주는 프로그램
@Controller // Controller 를 통해서, 로컬프로그램을 원격프로그램으로 변경
public class YoilTellerMVC {
@RequestMapping("/getYoilMVC") // RequestMapping은 중복되는 게 있으면 안된다.
public ModelAndView main(int year, int month, int day) throws IOException{
// 반환타입을 ModelAndView로 변경
// 1. model and view의 경우
ModelAndView mv = new ModelAndView();
// 2. 유효성 검사
if(!isValid(year, month, day))
return mv;
// 3. 작업
char yoil = getYoil(year, month, day);
// 4. 작업 결과를 ModelAndView에 저장
mv.addObject("year", year);
mv.addObject("month", month);
mv.addObject("day", day);
mv.addObject("yoil", yoil);
// 5. 결과를 보여줄 view를 지정
mv.setViewName("yoil"); // view의 이름을 지정 // WEB_INF/views/yoil.jsp
return mv;
}
}
6. 컨트롤러 메서드의 반환타입
- [String]인 경우 = 뷰 이름을 반환
- [void]인 경우 = 맵핑된 url의 끝 단어가 뷰 이름
- [ModelAndView]인 경우 = Model과 뷰 이름을 반환
'Java, Spring > 개념정리' 카테고리의 다른 글
DI(Dependency Injection) (0) | 2023.01.12 |
---|---|
DI, IoC, Container (0) | 2023.01.10 |
액션태그 (0) | 2022.08.16 |
디렉티브 태그 (0) | 2022.08.15 |
스크립트태그 (0) | 2022.08.15 |