Spring/SpringMVC

단순하고 실용적인 컨트롤러 - v4

느리지만 꾸준하게 2022. 4. 25. 00:21

단순하고 실용적인 컨트롤러 - v4를 만들어 보자.

  • v3 컨트롤러는 서블릿 종속성을 제거하고 뷰 경로의 중복을 제거하는 등, 잘 설계된 컨트롤러이지만
  • 컨트롤러 인터페이스를 구현하는 입장에서 항상 ModelView 객체를 생성하고 반환해야 하는 부분이 번거롭다.

 

  • 프레임워크가 좋다는 거는 아키텍져도 좋지만 실제 개발자가 편리하게 사용하고 실용성이 있어야 한다.
  • v3를 조금 변경해서 개발자들이 편리하게 개발가능한 v4 버전을 개발해보자.

 

 

 

 

 

v4 package에서 ControllerV4를 만들어주자.

package hello.setvlet.web.frontcontroller.v4;

import java.util.Map;

public interface ControllerV4 {
    /**
     *
     * @param paramMap
     * @param model
     * @return
     */
    String process(Map<String, String> paramMap, Map<String, Object> model);
}

 

 

MemberFormControllerV4에서 는 modelvie가 필요가 없다

// MemberFormControllerV4

package hello.setvlet.web.frontcontroller.v4.controller;
import hello.setvlet.web.frontcontroller.v4.ControllerV4;

import java.util.Map;

public class MemberFormControllerV4 implements ControllerV4 {
    @Override
    public String process(Map<String, String> paramMap, Map<String, Object> model) {
        return "new-form";
    }
}

 

MemberFormControllerV3와 비교를 해보자.

// MemberFormControllerV3

package hello.setvlet.web.frontcontroller.v3.controller;

import hello.setvlet.web.frontcontroller.ModelView;
import hello.setvlet.web.frontcontroller.v3.ControllerV3;

import java.util.Map;

public class MemberFormControllerV3 implements ControllerV3 {

    @Override
    public ModelView process(Map<String, String> paramMap) {
        // 논리적인 이름을 넣어주자
        return new ModelView("new-form");
    }
}

 

 

 

 

MemberSaveControllerV4도 마찬가지로 굉장히 심플해졌다.

package hello.setvlet.web.frontcontroller.v4.controller;

import hello.setvlet.domain.member.Member;
import hello.setvlet.domain.member.MemberRepository;
import hello.setvlet.web.frontcontroller.v4.ControllerV4;

import java.util.Map;

public class MemberSaveControllerV4 implements ControllerV4 {

    private MemberRepository memberRepository = MemberRepository.getInstance();

    @Override
    public String process(Map<String, String> paramMap, Map<String, Object> model) {
        String username = paramMap.get("username");
        int age = Integer.parseInt(paramMap.get("age"));

        Member member = new Member(username, age);
        memberRepository.save(member);

        model.put("member", member);
        return "save-result";
    }
}

 

 

 

MemberListControllerV4도 보자 굉장히 심플하다.

package hello.setvlet.web.frontcontroller.v4.controller;

import hello.setvlet.domain.member.Member;
import hello.setvlet.domain.member.MemberRepository;
import hello.setvlet.web.frontcontroller.v4.ControllerV4;

import java.util.List;
import java.util.Map;

public class MemberListControllerV4 implements ControllerV4 {

    private MemberRepository memberRepository = MemberRepository.getInstance();

    @Override
    public String process(Map<String, String> paramMap, Map<String, Object> model) {
        List<Member> members = memberRepository.findAll();

        model.put("member", members);
        return "members";
    }
}

 

 

 

 

FrontControllerServletV4도 만들어주자. viewName을 만들어서 넘겨주자.

String viewName = controller.process(paramMap, model);

MyView view = viewResolver(viewName);
view.render(model, request, response);
package hello.setvlet.web.frontcontroller.v4;

import hello.setvlet.web.frontcontroller.ModelView;
import hello.setvlet.web.frontcontroller.MyView;
import hello.setvlet.web.frontcontroller.v4.controller.MemberFormControllerV4;
import hello.setvlet.web.frontcontroller.v4.controller.MemberListControllerV4;
import hello.setvlet.web.frontcontroller.v4.controller.MemberSaveControllerV4;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

@WebServlet(name = "frontControllerServletV4", urlPatterns = "/front-controller/v4/*")
public class FrontControllerServletV4 extends HttpServlet {

    private Map<String, ControllerV4> controllerMap = new HashMap<>();

    // 값을 넣어주게 될 것이다.
    public FrontControllerServletV4() {
        controllerMap.put("/front-controller/v4/members/new-form", new MemberFormControllerV4());
        controllerMap.put("/front-controller/v4/members/save", new MemberSaveControllerV4());
        controllerMap.put("/front-controller/v4/members", new MemberListControllerV4());
    }

    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {


        String requestURI = request.getRequestURI();

        ControllerV4 controller = controllerMap.get(requestURI);
        if (controller == null) {
            response.setStatus(HttpServletResponse.SC_NOT_FOUND);
            return;
        }

        Map<String, String> paramMap = createParamMap(request);
        Map<String, Object> model = new HashMap<>(); // 추가

        String viewName = controller.process(paramMap, model);

        MyView view = viewResolver(viewName);
        view.render(model, request, response);
    }

    private MyView viewResolver(String viewName) {
        return new MyView("/WEB-INF/views/" + viewName + ".jsp");
    }

    private Map<String, String> createParamMap(HttpServletRequest request) {
        Map<String, String> paramMap = new HashMap<>();
        request.getParameterNames().asIterator()
                .forEachRemaining(paramName -> paramMap.put(paramName, request.getParameter(paramName)));
        return paramMap;
    }
}

 

 

실행을 해주면 v4회원목록에 목록이 안나오고 v3 회원목록으로 다 넘어간다... 해결중이다...

 

정리하면

  • 이번의 컨트롤러는 단순하고 실용적인데 기존에 구조에서 모델을 파라미터로 넘기고, 뷰의 논리 이름을 반환한다는 작은 아이디어를 적용함으로써
  • 컨트롤러는 구현하는 개발자 입장에서 군더더기 없는 코드를 작성할 수 있다.

 

  • 또 여기까지 한번에 온것이 아닌 프레임워크가 점진적으로 발전하는 과정에서 이런 방법도 찾을 수 있었다.
  • => 프레임워크나 공통 기능이 수고로워야 개발자가 편리해진다.

 

 

 

 

 

 

 

 

 

 

 

<출처 김영한: 스프링 MVC 1편 - 벡앤드 웹 개발 핵심 기술>

https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-mvc-1/dashboard

 

스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술 - 인프런 | 강의

웹 애플리케이션을 개발할 때 필요한 모든 웹 기술을 기초부터 이해하고, 완성할 수 있습니다. 스프링 MVC의 핵심 원리와 구조를 이해하고, 더 깊이있는 백엔드 개발자로 성장할 수 있습니다., -

www.inflearn.com

 

'Spring > SpringMVC' 카테고리의 다른 글

유연한 컨트롤러2 - v5  (0) 2022.04.25
유연한 컨트롤러1 - v5  (0) 2022.04.25
Model 추가 - v3  (0) 2022.04.24
View 분리 - v2  (0) 2022.04.24
프론트 컨트롤러 도입 - v1  (0) 2022.04.24