Spring MVC-1 TIL (6)

YulHee Kimยท2021๋…„ 9์›” 10์ผ
1

Spring MVC

๋ชฉ๋ก ๋ณด๊ธฐ
6/11
post-thumbnail

[์ฐธ๊ณ  ๊ฐ•์˜] ๊น€์˜ํ•œ๋‹˜์˜ ์Šคํ”„๋ง MVC 1ํŽธ - ๋ฐฑ์—”๋“œ ์›น ๊ฐœ๋ฐœ ํ•ต์‹ฌ ๊ธฐ์ˆ 

๐Ÿ’ก MVC ํ”„๋ ˆ์ž„์›Œํฌ ๋งŒ๋“ค๊ธฐ

โœ๏ธ Model ์ถ”๊ฐ€

์„œ๋ธ”๋ฆฟ ์ข…์†์„ฑ ์ œ๊ฑฐ

์ปจํŠธ๋กค๋Ÿฌ ์ž…์žฅ์—์„œ HttpServletRequest, HttpServletResponse๊ฐ€ ๊ผญ ํ•„์š”ํ• ๊นŒ?
์š”์ฒญ ํŒŒ๋ผ๋ฏธํ„ฐ ์ •๋ณด๋Š” ์ž๋ฐ”์˜ Map์œผ๋กœ ๋Œ€์‹  ๋„˜๊ธฐ๋„๋ก ํ•˜๋ฉด ์ง€๊ธˆ ๊ตฌ์กฐ์—์„œ๋Š” ์ปจํŠธ๋กค๋Ÿฌ๊ฐ€ ์„œ๋ธ”๋ฆฟ ๊ธฐ์ˆ ์„ ๋ชฐ๋ผ๋„ ๋™์ž‘ํ•  ์ˆ˜ ์žˆ๋‹ค.
๊ทธ๋ฆฌ๊ณ  request ๊ฐ์ฒด๋ฅผ Model๋กœ ใ……์šฉํ•˜๋Š” ๋Œ€์‹ ์— ๋ณ„๋„์˜ Model ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค์–ด์„œ ๋ฐ˜ํ™˜ํ•˜๋ฉด ๋œ๋‹ค.

๋ทฐ ์ด๋ฆ„ ์ค‘๋ณต ์ œ๊ฑฐ

์ปจํŠธ๋กค๋Ÿฌ์—์„œ ์ง€์ •ํ•˜๋Š” ๋ทฐ ์ด๋ฆ„์— ์ค‘๋ณต์ด ์žˆ๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.
์ปจํŠธ๋กค๋Ÿฌ๋Š” ๋ทฐ์˜ ๋…ผ๋ฆฌ ์ด๋ฆ„์„ ๋ฐ˜ํ™˜ํ•˜๊ณ , ์‹ค์ œ ๋ฌผ๋ฆฌ ์œ„์น˜์˜ ์ด๋ฆ„์€ ํ”„๋ก ํŠธ ์ปจํŠธ๋กค๋Ÿฌ์—์„œ ์ฒ˜๋ฆฌํ•˜๋„๋ก ๋‹จ์ˆœํ™”ํ•˜์ž.
์ด๋Ÿฌ๋ฉด ๋‚˜์ค‘์— ๋ทฐ ํด๋” ์œ„์น˜๊ฐ€ ํ•จ๊ป˜ ์ด๋™ํ•ด๋„ ํ”„๋ก ํŠธ ์ปจํŠธ๋กค๋Ÿฌ๋งŒ ๊ณ ์น˜๋ฉด๋œ๋‹ค.

ex) /WEB-INF/views/new-form.jsp -> new-form

v3 ๊ตฌ์กฐ

ModelView

์„œ๋ธ”๋ฆฟ์˜ ์ข…์†์„ฑ์„ ์ œ๊ฑฐํ•˜๊ธฐ ์œ„ํ•ด Model์„ ์ง์ ‘ ๋งŒ๋“ค๊ณ , ์ถ”๊ฐ€๋กœ View ์ด๋ฆ„๊นŒ์ง€ ์ „๋‹ฌํ•˜๋Š” ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค์–ด๋ณด์ž.

public class ModelView {

    private String viewName;
    private Map<String, Object> model = new HashMap<>();

    public ModelView(String viewName) {
        this.viewName = viewName;
    }

    public String getViewName() {
        return viewName;
    }

    public void setViewName(String viewName) {
        this.viewName = viewName;
    }

    public Map<String, Object> getModel() {
        return model;
    }

    public void setModel(Map<String, Object> model) {
        this.model = model;
    }
}

๋ทฐ์˜ ์ด๋ฆ„๊ณผ ๋ทฐ๋ฅผ ๋ Œ๋”๋งํ•  ๋•Œ ํ•„์š”ํ•œ model ๊ฐ์ฒด๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค. model์€ ๋‹จ์ˆœํžˆ map์œผ๋กœ ๋˜์–ด ์žˆ์œผ๋ฏ€๋กœ ์ปจํŠธ๋กค๋Ÿฌ์—์„œ ๋ทฐ์— ํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ๋ฅผ key, value๋กœ ๋„ฃ์–ด์ฃผ๋ฉด ๋œ๋‹ค.

ControllerV3

public interface ControllerV3 {

    ModelView process(Map<String, String> paramMap);
}

์ด ์ปจํŠธ๋กค๋Ÿฌ๋Š” ์„œ๋ธ”๋ฆฟ ๊ธฐ์ˆ ์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค. ๋”ฐ๋ผ์„œ ๊ตฌํ˜„์ด ๋‹จ์ˆœํ•ด์ง„๋‹ค.
HttpServletRequest๊ฐ€ ์ œ๊ณตํ•˜๋Š” ํŒŒ๋ผ๋ฏธํ„ฐ๋Š” ํ”„๋ก ํŠธ ์ปจํŠธ๋กค๋Ÿฌ๊ฐ€ paramMap์— ๋‹ด์•„์„œ ํ˜ธ์ถœํ•ด์ฃผ๋ฉด ๋œ๋‹ค.
์‘๋‹ต ๊ฒฐ๊ณผ๋กœ ๋ทฐ ์ด๋ฆ„๊ณผ ๋ทฐ์— ์ „๋‹ฌํ•  Model ๋ฐ์ดํ„ฐ๋ฅผ ํฌํ•จํ•˜๋Š” ModelView ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋ฉด ๋œ๋‹ค.

ํšŒ์› ๋“ฑ๋ก ํผ

public class MemberFormControllerV3 implements ControllerV3 {

    @Override
    public ModelView process(Map<String, String> paramMap) {
        return new ModelView("new-form");
    }
}

ModelView๋ฅผ ์ƒ์„ฑํ•  ๋•Œ new-form์ด๋ผ๋Š” view์˜ ๋…ผ๋ฆฌ์ ์ธ ์ด๋ฆ„์„ ์ง€์ •ํ•œ๋‹ค. ์‹ค์ œ ๋ฌผ๋ฆฌ์ ์ธ ์ด๋ฆ„์€ ํ”„๋ก ํŠธ ์ปจํŠธ๋กค๋Ÿฌ์—์„œ ์ฒ˜๋ฆฌํ•œ๋‹ค.

ํšŒ์› ์ €์žฅ

public class MemberSaveControllerV3 implements ControllerV3 {

    private MemberRepository memberRepository = MemberRepository.getInstance();

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

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

        ModelView mv = new ModelView("save-result");
        mv.getModel().put("member", member);
        return mv;
    }
}

paramMap.get("username");
ํŒŒ๋ผ๋ฏธํ„ฐ ์ •๋ณด๋Š” map์— ๋‹ด๊ฒจ์žˆ๋‹ค. map์—์„œ ํ•„์š”ํ•œ ์š”์ฒญ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์กฐํšŒํ•˜๋ฉด ๋œ๋‹ค.

mv.getModel().put("member", member);
๋ชจ๋ธ์€ ๋‹จ์ˆœํ•œ map์ด๋ฏ€๋กœ ๋ชจ๋ธ์— ๋ทฐ์—์„œ ํ•„์š”ํ•œ member ๊ฐ์ฒด๋ฅผ ๋‹ด๊ณ  ๋ฐ˜ํ™˜ํ•œ๋‹ค.

ํšŒ์› ๋ชฉ๋ก

public class MemberListControllerV3 implements ControllerV3 {

    private MemberRepository memberRepository = MemberRepository.getInstance();

    @Override
    public ModelView process(Map<String, String> paramMap) {
        List<Member> members = memberRepository.findAll();
        ModelView mv = new ModelView("members");
        mv.getModel().put("members", members);

        return mv;
    }
}

FrontControllerServletV3

@WebServlet(name = "frontControllerServletV3", urlPatterns = "/front-controller/v3/*")
public class FrontControllerServletV3 extends HttpServlet {

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

    public FrontControllerServletV3() {
        controllerMap.put("/front-controller/v2/members/new-form", new MemberFormControllerV3());
        controllerMap.put("/front-controller/v2/members/save", new MemberSaveControllerV3());
        controllerMap.put("/front-controller/v2/members", new MemberListControllerV3());
    }

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

        String requestURI = request.getRequestURI();

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

        //paramMap
        Map<String, String> paramMap = createParamMap(request);

        ModelView mv= controller.process(paramMap);
        String viewName = mv.getViewName();//๋…ผ๋ฆฌ ์ด๋ฆ„ new-form
        MyView view = viewResolver(viewName);

        view.render(mv.getModel(), 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;
    }
}

view.render(mv.getModel(), request, response)์—์„œ ์ปดํŒŒ์ผ ์˜ค๋ฅ˜๊ฐ€ ๋‚˜๋ฏ€๋กœ ๋‹ค์Œ ์ฝ”๋“œ๋ฅผ ์ฐธ๊ณ ํ•ด์„œ MyView๊ฐ์ฒด์— ํ•„์š”ํ•œ ๋ฉ”์„œ๋“œ๋ฅผ ์ถ”๊ฐ€ํ•˜์ž

createParamMap()
HttpServletRequest์—์„œ ํŒŒ๋ผ๋ฏธํ„ฐ ์ •๋ณด๋ฅผ ๊บผ๋‚ด์„œ Map์œผ๋กœ ๋ณ€ํ™˜ํ•œ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ํ•ด๋‹น Map(paramMap)์„ ์ปจํŠธ๋กค๋Ÿฌ์— ์ „๋‹ฌํ•˜๋ฉด์„œ ํ˜ธ์ถœํ•œ๋‹ค.

๋ทฐ ๋ฆฌ์กธ๋ฒ„

MyView view = viewResolver(viewName)
์ปจํŠธ๋กค๋Ÿฌ๊ฐ€ ๋ฐ˜ํ™˜ํ•œ ๋…ผ๋ฆฌ ๋ทฐ ์ด๋ฆ„์„ ์‹ค์ œ ๋ฌผ๋ฆฌ ๋ทฐ ๊ฒฝ๋กœ๋กœ ๋ณ€๊ฒฝํ•œ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์‹ค์ œ ๋ฌผ๋ฆฌ ๊ฒฝ๋กœ๊ฐ€ ์žˆ๋Š” MyView ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค

  • ๋…ผ๋ฆฌ ๋ทฐ ์ด๋ฆ„: members
  • ๋ฌผ๋ฆฌ ๋ทฐ ๊ฒฝ๋กœ: /WEB-INF/views/members.jsp

view.render(mv.getModel(), request, response)

  • ๋ทฐ ๊ฐ์ฒด๋ฅผ ํ†ตํ•ด์„œ HTML ํ™”๋ฉด์„ ๋ Œ๋”๋ง ํ•œ๋‹ค.
  • ๋ทฐ ๊ฐ์ฒด์˜ render()๋Š” ๋ชจ๋ธ ์ •๋ณด๋„ ํ•จ๊ป˜ ๋ฐ›๋Š”๋‹ค.
  • JSP๋Š” request.getAttribute()๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์กฐํšŒํ•˜๊ธฐ ๋•Œ๋ฌธ์—, ๋ชจ๋ธ์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๊บผ๋‚ด์„œ request.setAttribute()๋กœ ๋‹ด์•„๋‘”๋‹ค.
  • JSP๋กœ ํฌ์›Œ๋“œ ํ•ด์„œ JSP๋ฅผ ๋ Œ๋”๋ง ํ•œ๋‹ค.

MyView

public class MyView {
    private String viewPath;

    public MyView(String viewPath) {
        this.viewPath = viewPath;
    }

    public void render(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        RequestDispatcher dispatcher = request.getRequestDispatcher(viewPath);
        dispatcher.forward(request, response);
    }

    public void render(Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        modelToRequestAttribute(model, request);
        RequestDispatcher dispatcher = request.getRequestDispatcher(viewPath);
        dispatcher.forward(request, response);
    }

    private void modelToRequestAttribute(Map<String, Object> model, HttpServletRequest request) {
        model.forEach((key, value) -> request.setAttribute(key,value));
    }
}

โœ๏ธ ๋‹จ์ˆœํ•˜๊ณ  ์‹ค์šฉ์ ์ธ ์ปจํŠธ๋กค๋Ÿฌ - v4

v3 ์ปจํŠธ๋กค๋Ÿฌ๋Š” ์„œ๋ธ”๋ฆฟ ์ข…์†์„ฑ์„ ์ œ๊ฑฐํ•˜๊ณ  ๋ทฐ ๊ฒฝ๋กœ์˜ ์ค‘๋ณต์„ ์ œ๊ฑฐํ•˜๋ฉฐ ์ž˜ ์„ค๊ณ„๋œ ์ปจํŠธ๋กค๋Ÿฌ์ด์ง€๋งŒ, ํ•ญ์ƒ ModelView ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ๋ฐ˜ํ™˜ํ•ด์•ผ ํ•˜๋Š” ๋ถ€๋ถ„์ด ์กฐ๊ธˆ ๋ฒˆ๊ฑฐ๋กญ๋‹ค.
v4๋Š” v3๋ฅผ ์กฐ๊ธˆ ๋ณ€๊ฒฝํ•ด์„œ ์‹ค์šฉ์„ฑ ์žˆ๋Š” ์ฝ”๋“œ๋กœ ๋ฐ”๊ฟ”๋ณด๊ฒ ๋‹ค!

v4 ๊ตฌ์กฐ


์ปจํŠธ๋กค๋Ÿฌ๊ฐ€ ModelView๋ฅผ ๋ฐ˜ํ™˜ํ•˜์ง€ ์•Š๊ณ , ViewName๋งŒ ๋ฐ˜ํ™˜ํ•œ๋‹ค

ControllerV4

public interface ControllerV4 {

    String process(Map<String, String> paramMap, Map<String, Object> model);
}

model ๊ฐ์ฒด๋ฅผ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋„˜๊ฒจ์ฃผ๊ณ  ๊ฒฐ๊ณผ๋กœ ๋ทฐ์˜ ์ด๋ฆ„๋งŒ ๋ฐ˜ํ™˜ํ•ด์ค€๋‹ค

MemberFormControllerV4

public class MemberFormControllerV4 implements ControllerV4 {

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

์ •๋ง ๋‹จ์ˆœํ•˜๊ฒŒ new-form์ด๋ผ๋Š” ๋ทฐ์˜ ๋…ผ๋ฆฌ ์ด๋ฆ„๋งŒ ๋ฐ˜ํ™˜ํ•˜๋ฉด ๋œ๋‹ค!

MemberSaveControllerV4

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

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("members", members);
        return "members";
    }
}

FrontControllerServletV4

์ด์ „ ๋ฒ„์ „๊ณผ ๊ฑฐ์˜ ๋™์ผํ•˜๋‹ค

๋ชจ๋ธ ๊ฐ์ฒด ์ „๋‹ฌ
Map<String, Object> model = new HashMap<>(); //์ถ”๊ฐ€
๋ชจ๋ธ ๊ฐ์ฒด๋ฅผ ํ”„๋ก ํŠธ ์ปจํŠธ๋กค๋Ÿฌ์—์„œ ์ƒ์„ฑํ•ด์„œ ๋„˜๊ฒจ์ค€๋‹ค. ์ปจํŠธ๋กค๋Ÿฌ์—์„œ ๋ชจ๋ธ ๊ฐ์ฒด์— ๊ฐ’์„ ๋‹ด์œผ๋ฉด ์—ฌ๊ธฐ์— ๊ทธ๋Œ€๋กœ ๋‹ด๊ฒจ์žˆ๊ฒŒ ๋œ๋‹ค.

๋ทฐ์˜ ๋…ผ๋ฆฌ ์ด๋ฆ„์„ ์ง์ ‘ ๋ฐ˜ํ™˜

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

ํ”„๋ ˆ์ž„์›Œํฌ๋‚˜ ๊ณตํ†ต ๊ธฐ๋Šฅ์ด ์ˆ˜๊ณ ๋กœ์›Œ์•ผ ์‚ฌ์šฉํ•˜๋Š” ๊ฐœ๋ฐœ์ž๊ฐ€ ํŽธ๋ฆฌํ•ด์ง„๋‹ค!

profile
๋ฐฑ์—”๋“œ ๊ฐœ๋ฐœ์ž

0๊ฐœ์˜ ๋Œ“๊ธ€