티스토리 뷰

DEV/Java

Spring의 코드 분리

berom 2023. 5. 18. 14:51

Spring의 코드 분리

단일 책임 원칙(Single Responsibility Principle, SRP)에 따라서 주어진 예제를 리팩토링 하면서 관심사 분리 즉 코드 분리를 해보자

코드 분리의 기준은 아래와 같다.

  1. 관심사 분리: 각 부분이 서로 다른 목적을 가진 코드로 분리
  2. 변하는 것과 변하지 않는 것의 분리: 이는 코드 내에서 변동성이 큰 부분과 그렇지 않은 부분을 분리하는 것을 의미합니다
    1. 일반적으로 자주 변경되는 로직은 분리하여 관리함으로써 코드의 유연성을 높이고, 유지보수를 용이하게 합니다.
    2. 반대로 변동성이 적은 부분은 안정적인 기능을 제공하는 코드로서 그 자체로 응집력을 갖도록 관리합니다.
  3. 공통 코드와 중복 코드의 분리: 코드 베이스 내에서 반복적으로 사용되는 부분(공통 코드)이나 같은 기능을 수행하는 코드(중복 코드) 분리

예제 : 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)을 지켜 코드 가독성과 유지 보수의 용이함을 가져갔습니다

부족한 점이나 잘못 된 점을 알려주시면 시정하겠습니다 :>

728x90

'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