MVC 프레임워크 만들기

JIWOO YUN·2023년 11월 22일
0

MVC기본 1

목록 보기
2/5
post-custom-banner

인프런의 김영한님의 mvc 기본 1편을 들으면서 정리한 내용


MVC 프레임워크 만들기

프론트 컨트롤러 ?

  • 프론트 컨트롤러 도입전

    • 공통 로직을 각각 깔고 특정 로직을 실행하는 로직을 사용 -> 중복이 발생
  • 도입 후

    • 공통 로직(서블릿)을 하나의 컨트롤러로 묶어서 각각 필요한 로직은 각각 처리하게
      • 공통의 관심사를 별도로 모음

특징

  • 프론트 컨트롤러 서블릿 하나로 클라이언트 요청을 받는다.
  • 프론트 컨트롤러가 요청에 맞는 컨트롤러를 찾아서 호출한다.
  • 프론트 컨트롤러를 제외한 나머지 컨트롤러는 서블릿을 사용하지 않아도 됨.
    • -> 요청 매핑을 할때 서블릿을 사용해서 요청 매핑을 했음.
    • 프론트 컨트롤러가 서블릿이기 때문에 프론트 컨트롤러가 직접 필요한 컨트롤러를 호출해줌.
    • WAS 서버가처음 요청을 처리하는 곳이 servlet 인데 이걸 프론트 컨트롤러가 대신 해줌

프론트 컨트롤러 도입 - v1버전

다형성 활용하기 위해서 인터페이스를 통해서 구현 로직을 추상화

  • 구현을 여러개 하는데 로직의 일관성을 유지하기 위해서 사용
public interface ControllerV1 {

    void process(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException;
}

회원 등록, 회원 저장, 회원 목록은 위의 인터페이스를 implement를 받아서 각자의 목적에 맞춰서 코드를 재정의 해줌.

FrontController에 생성자를 통해서 매핑 정보를 넣어두고 진행함.

클라이언트의 requestUrl을 가져와서 맵핑테이블안에있는 것에 맞춰서 가져옴 -> 없는경우 NOT_FOUND를 내보냄

있는 경우 -> 각자의 목적에 맞춰서 만들어둔 걸 실행함.

@WebServlet(name = "frontControllerServletV1" , urlPatterns = "/front-controller/v1/*")
public class FrontControllerServletV1 extends HttpServlet {


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

    //미리 생성자를 통해서 맵핑을 해둠.
    public FrontControllerServletV1() {
        controllerMap.put("/front-controller/v1/members/new-form",new MemberFormControllerV1());
        controllerMap.put("/front-controller/v1/members/save",new MemberSaveControllerV1());
        controllerMap.put("/front-controller/v1/members",new MemberListControllerV1());
    }

    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("FrontControllerServletV1.service");

        String requestURI = request.getRequestURI();

        //인터페이스로 일관성을 유지하기 때문에 가능함.
        ControllerV1 controller = controllerMap.get(requestURI);
        if(controller == null){
            response.setStatus(HttpServletResponse.SC_NOT_FOUND);
            return;
        }
        //각자 컨트롤러에 맞춰서 실행함.
        controller.process(request,response);
    }
}
  • 아까 짜둔 저장,등록,목록 jsp를 재사용하게됨.

문제점

  • 뷰로 이동하는 부분은 중복이 발생함 -> 별도로 뷰를 처리하는 객체가 필요하다.
  • v1버전은 구조적으로 개선 진행

tip

구조 개선시에는 구조만 개선하고 그다음 문제가 없을 시에 세세한 부분을 개선하는게 좋은 방법이라고 얘기하심.

두개를 한번에 같이 하게되면 짬뽕되서 문제가 발생되면 짬뽕된 코드를 보고 구조의 문제인지 코드의 문제인지 두개를 체크해야되는 문제가 생김

​ -> 한번에 하나씩 개선을 하면 구조개선할때 문제가 발생하면 구조가 문제인거를 빠르게 체크가가능해진다.

​ -> 세세한 부분개선을 할때 오류가 발생하면 부분 개선이 문제인 것을 알 수 있음.


Controller v2

view 분리하기
  • 전담하는 객체를 만든다.
  • controller가 직접 forward를 하지 않고 Myview()의 render를 호출시 forward를 진행하는 형식을 사용.
  • Controller가 view 에 대해서 생각하지 않아도 됨.
public class MemberFormControllerV2 implements ControllerV2 {
    @Override
    public MyView process(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        return new MyView("/WEB-INF/views/new-form.jsp");
    }
}
  • ControllerV2 에서 MyView 를 반환함으로써 컨트롤러가 직접 dispatcher.forward() 생성해서 호출하지 않아도 됨 -> MyView 객체를 생성하고 거기에 뷰 이름만 넣어줘서 반환

Myview는 생성하지 않고 반환만 하는 정도

  • 화면은 render를 통해서 forward 진행
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);
    }
}

view 도 인터페이스로 만들어서 다형성 설계가 가능함

profile
열심히하자
post-custom-banner

0개의 댓글