Spring의 코드 분리
단일 책임 원칙(Single Responsibility Principle, SRP)에 따라서 주어진 예제를 리팩토링 하면서 관심사 분리 즉 코드 분리를 해보자
코드 분리의 기준은 아래와 같다.
- 관심사 분리: 각 부분이 서로 다른 목적을 가진 코드로 분리
- 변하는 것과 변하지 않는 것의 분리: 이는 코드 내에서 변동성이 큰 부분과 그렇지 않은 부분을 분리하는 것을 의미합니다
- 일반적으로 자주 변경되는 로직은 분리하여 관리함으로써 코드의 유연성을 높이고, 유지보수를 용이하게 합니다.
- 반대로 변동성이 적은 부분은 안정적인 기능을 제공하는 코드로서 그 자체로 응집력을 갖도록 관리합니다.
- 공통 코드와 중복 코드의 분리: 코드 베이스 내에서 반복적으로 사용되는 부분(공통 코드)이나 같은 기능을 수행하는 코드(중복 코드) 분리
예제 : YoilTeller
1. 관심사 분리
원본 YoilTeller 클래스의 관심사를 분리합니다.
이미 정답을 말하자면 크게 입력, 요일 계산, 출력 단으로 기능이 분리 됩니다.
즉 현재 Yoil Teller는 너무 많은 책임을 지고 있습니다. (마치 가장의 무게처럼,)
입력
@Controller
public class YoilTeller {
@RequestMapping("/getYoil") // http://localhost:8080/ch2/getYoil?year=2021&month=10&day=1
// public static void main(String[] args) {
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");
int yyyy = Integer.parseInt(year);
int mm = Integer.parseInt(month);
int dd = Integer.parseInt(day);
처리(요일 계산)
// 2. 처리
Calendar cal = Calendar.getInstance();
cal.set(yyyy, mm - 1, dd);
int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK);
char yoil = " 일월화수목금토".charAt(dayOfWeek); // 일요일:1, 월요일:2, ...
출력
// 3. 출력
response.setContentType("text/html"); // 응답의 형식을 html로 지정
response.setCharacterEncoding("utf-8"); // 응답의 인코딩을 utf-8로 지정
PrintWriter out = response.getWriter(); // 브라우저로의 출력 스트림(out)을 얻는다.
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>");
out.close();
}
}
2. 공통 코드의 분리
입력
@Controller
public class YoilTeller {
@RequestMapping("/getYoil") // http://localhost:8080/ch2/getYoil?year=2021&month=10&day=1
// public static void main(String[] args) {
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");
int yyyy = Integer.parseInt(year);
int mm = Integer.parseInt(month);
int dd = Integer.parseInt(day);
입력 단의 코드를 최적화 해보자. 보면, request
에 저장된 데이터를 getParameter
로 데이터를 뽑아 오는 것을 볼 수 있습니다.
Spring에서는 인자로 HttpServelet을 사용하지 않고, 바로 파라미터를 받을 수 있습니다.
원본 코드에서 하는 일을 Spring에서 내부 적으로 처리하는 거죠
@Controller
public class YoilTeller {
@RequestMapping("/getYoil") // http://localhost:8080/ch2/getYoil?year=2021&month=10&day=1
public void main(int year, int month, int dev, HttpServletResponse response) throws IOException {
입력 단으로 코드를 옮겼을 뿐인데 훨씬 코드가 깔끔해졌습니다
처리(요일 계산)
// 2. 처리
char yoil = getYoil(year, month, day);
~~~~~~~~~~~~~~ 출력 단 코드 ~~~~~~~~~~~~~~~~~~~~~~~
}
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);
}
getYoil을 main 메소드에서 분리해서 따로 기능을 추출합니다.
출력
// 3. Model에 작업 결과 저장
model.addAttribute("year", year);
model.addAttribute("month", month);
model.addAttribute("day", day);
model.addAttribute("yoil", yoil);
// 4. 작업 결과를 보여줄 View의 이름을 반환
return "yoil"; // /WEB-INF/views/yoil.jsp
}
<html>
<head>
<title>YoilTellerMVC</title>
</head>
<body>
<h1>${year}년 ${month}월 ${day}일은 ${yoil}요일입니다.</h1>
</body>
</html>
이전에는 하나하나 println를 했다면 이제 모델을 사용하여 데이터를 저장합니다.
모델에 출력에 필요한 데이터를 저장해서 view로 넘깁니다. MVC 패턴을 위해서!
즉 처리하는 부분은 컨트롤러, view는 출력 , 컨틀롤러와 출력이 데이터를 주고 받을 때 사용하는 것은 Model로 나눕니다
결론
예제를 따라 리팩토링을 하였습니다.
MVC 모델을 사용해서 각자 책임을 분산하고, 클래스 내 Main 메소드에 쏠린 기능들도 분류하였습니다.
이를 통해 OOP의 단일 책임 원칙(Single Responsibility Principle, SRP)을 지켜 코드 가독성과 유지 보수의 용이함을 가져갔습니다
부족한 점이나 잘못 된 점을 알려주시면 시정하겠습니다 :>
'DEV > Java' 카테고리의 다른 글
Spring MVC (1) | 2023.05.19 |
---|---|
Java 런타임에 매개변수 이름 얻는 방법 (0) | 2023.05.19 |
Spring Response와 Request (0) | 2023.05.13 |
Spring의 HTTP 처리 (0) | 2023.05.13 |
Aspect-oriented programming (AOP) (0) | 2023.05.11 |