관심쟁이 영호

[#6-2 Spring Boot 정주행] View Path를 없애보자! ㅣ MVC 프레임워크 만들기 본문

Bank-End/Spring Boot

[#6-2 Spring Boot 정주행] View Path를 없애보자! ㅣ MVC 프레임워크 만들기

관심쟁이 영호 2021. 9. 12. 17:18
반응형

이전 포스팅에서 FrontController를 통해서 공통 처리를 가능하게 하였다.

하지만 View의 Path를 설정하는 부분과, Servlet에서 View & 또 다른 Servlet으로 넘겨주는 함수가

모든 컨트롤러에 적용된다는 것을 알 수가 있었다.

 

이번 포스팅은 View Path 중복 코드 문제를 해결한다.

그리고 이전 포스팅의 코드를 계속해서 사용할 예정이다.

 

 

[#6 Spring Boot 정주행] MVC 프레임워크를 직접 만들어보자

이전에 포스팅한 글에서 서블릿 dispatcher를 통해서 JSP를 반환하는 것까지 성공했다! 하지만 문제가 있었다. 이번 포스팅에서는 해당 문제들을 짚어보고 하나씩 해결해보면서 MVC 프레임워크를 만

bestkingit.tistory.com

 


목차

  • 전략
  • 코드 적용
  • FrontController 수정
  • 문제점

 


전략

 

생각해보자.

view의 Path 설정 코드가 중복되는 것을 막기위해서는 어떻게 해야 할까?

 

내 생각에는 다음 방법을 사용하면 좋을 듯하다.

 

1. View 라는 새로운 객체를 만든다.
2. 컨트롤러에서 View 객체에 Path를 지정한다.
3. 컨트롤러는 FrontController에 View를 리턴한다.

 

말로 해서 잘 이해가 안 될 수도 있다.

그래서 코드로 직접 보도록 하자!

 


코드 적용

 

가장 먼저 View를 생성해보자.

 

View.java 생성

public class View {

    private String path;

    public View(String path){

        this.path = path;

    }

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

 

render를 보면 이전에 중복 문제가 있던 코드가 있는 것을 볼 수가 있다.

 

도메인도 하나 추가해보자.

 

User.java 생성

public class User {

    Long name;
    int age;

    public User(){
        ;
    }
    public User(Long userName, int userAge){
        this.name = userName;
        this.age = userAge;
    }
    public Long getName() {
        return name;
    }

    public void setName(Long name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

};

 

해당 User를 저장할 Repository도 만들어보자!

 

UserRepository.java 생성

public class UserRepository {

    private static Map<Long, User> store = new HashMap<>();
    private static long sequence = 0L;
    private static final UserRepository instance = new UserRepository();
    public static UserRepository getInstance() {
        return instance;
    }
    private UserRepository() {
    }
    public User save(User user) {
        user.setName(++sequence);
        store.put(user.getName(), user);
        return user;
    }
    public User findById(Long id) {
        return store.get(id);
    }
    public List<User> findAll() {
        return new ArrayList<>(store.values());
    }
    public void clearStore() {
        store.clear();
    }


};

 

Spring의 IOC, DI를 이용하면 Static 없이 편하게 사용할 수 있겠지만, 현재는 스프링을 사용하지 않으니까 Static으로 임시적으로 싱글톤 Repository를 사용하자!

 

그리고 Controller를 더 만들어보자. (각자 다른 Path와 logic 메서드를 가지기 위해서)

 

  • UserRegister.java 추가
public class UserRegisterController implements TestController{

    private UserRepository userRepository = UserRepository.getInstance();

    @Override
    public View logic(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        String username = req.getParameter("username");
        int age = Integer.parseInt(req.getParameter("age"));
        User user = new User(Long.parseLong(username), age);
        userRepository.save(user);
        req.setAttribute("user", user);
        return new View("/WEB-INF/views/userList.jsp");

    }
};
  • UserListController.java 추가
public class UserListController implements TestController{

    private UserRepository userRepository = UserRepository.getInstance();
    @Override
    public View logic(HttpServletRequest request, HttpServletResponse
            response) throws ServletException, IOException {
        List<User> users = userRepository.findAll();
        request.setAttribute("users", users);
        return new View("/WEB-INF/views/members.jsp");
    }
};
  • BoardListController.java 추가
public class BoardListController implements TestController{

    //board Repository 필요

    @Override
    public View logic(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        String path = "/WEB-INF/views/boardlist.jsp";

        //board List를 request에 포함 시켜 return 해야 함.

        return new View(path);
    }
};

 


FrontController.java 수정

 

FrontController에도 수정해야 할 부분이 있다!

View가 추가되었으니, Controller가 뱉은 View의 render를 실행해주는 메서드를 추가해야 한다!

 

다음 코드를 보자.

@WebServlet(name = "frontController", urlPatterns = "servlet/test/*")
public class FrontController extends HttpServlet {

    private Map<String, TestController> controllerList = new HashMap<>();

    public FrontController(){
        controllerList.put("servlet/test/boardList", new
                BoardListController());
        controllerList.put("servlet/test/register", new
                UserRegisterController());
        controllerList.put("servlet/test/Users", new
                UserListController());
    }

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse
            resp)
            throws ServletException, IOException {
        String requestURI = req.getRequestURI();
        TestController controller = controllerList.get(requestURI);
        if (controller == null) {
            resp.setStatus(HttpServletResponse.SC_NOT_FOUND);
            return;
        }
        View view= controller.logic(req, resp);

        view.render(req, resp);

    }
}

 

 

이제 완벽히 수행하는 것을 볼 수 있다!

 

최종적으로 완성한 내용을 그림으로 도식화해보자.

 

 

 


문제점

 

또또... 문제가 있다.

 

path에 "/WEB-INF/views/"와 ". jsp"가 중복된다.

그리고

HttpServletRequest, HttpServletResponse가 꼭 필요하진 않다!

 

그래서 다음 포스팅에는 해당 문제점을 해결하는 방향대로 가보자!!

 

 

 

 

해당 포스팅 글은 : 인프런의 "김영한 개발자님의 강의 - Spring MVC 1편"을 참고하여 작성했습니다.

300x250
Comments