[Project-Winter/#3] Contoller 기능 구현 중 문제

djawnstj·2023년 6월 21일
0

Project Winter

목록 보기
3/4

블로그 이전

Controller 기능 개발

서버 기능을 구현 후 예정대로 Controller 기능 개발을 하던 중 문제를 만났다.

Controller

interface Controller {
	public Object handle(HttpServletRequest req, HttpServletResponse res);
}

이렇게 컨트롤러 인터페이스를 만들고 이를 구현한 컨트롤러 클래스들을 실제 핸들러로 사용하고자 했다.

HandlerMapping

public interface HandlerMapping {
	void init();
    Object findHandler(HttpServletRequest req);
}

HandlerMapping 을 구현한 클래스로 http method, uri 를 Controller 클래스를 매핑해주고, 요청이 들어오면 해당 http method 와 uri 를 통해 Controller 를 반환해주는 역할을 하는것으로 설계했다.

하지만 여기서 바로 문제가 생겼다.

HandlerMapping 에서의 문제

HandlerMappinginit() 함수에서 http method, uri 와 Controller 클래스를 매핑해주려 했다. 하지만 어디에서도 Controller의 http method, uri 를 받아올 수 없어서 매핑을 해주는 방법에 대해 엄청 고민했다. 일단 SpringFramework 에서 어떤 흐름인지 찾아봤다.

DispatchServlet - initHandlerMappings()

private void initHandlerMappings(ApplicationContext context) {
    this.handlerMappings = null;

    if (this.detectAllHandlerMappings) {
        // Find all HandlerMappings in the ApplicationContext, including ancestor contexts.
        Map<String, HandlerMapping> matchingBeans =
                BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false);
        if (!matchingBeans.isEmpty()) {
            this.handlerMappings = new ArrayList<>(matchingBeans.values());
            // We keep HandlerMappings in sorted order.
            AnnotationAwareOrderComparator.sort(this.handlerMappings);
        }
    }
    else {
        try {
            HandlerMapping hm = context.getBean(HANDLER_MAPPING_BEAN_NAME, HandlerMapping.class);
            this.handlerMappings = Collections.singletonList(hm);
        }
        catch (NoSuchBeanDefinitionException ex) {
            // Ignore, we'll add a default HandlerMapping later.
        }
    }

    // Ensure we have at least one HandlerMapping, by registering
    // a default HandlerMapping if no other mappings are found.
    if (this.handlerMappings == null) {
        this.handlerMappings = getDefaultStrategies(context, HandlerMapping.class);
        if (logger.isTraceEnabled()) {
            logger.trace("No HandlerMappings declared for servlet '" + getServletName() +
                    "': using default strategies from DispatcherServlet.properties");
        }
    }

    for (HandlerMapping mapping : this.handlerMappings) {
        if (mapping.usesPathPatterns()) {
            this.parseRequestPath = true;
            break;
        }
    }
}

DispatchServlet 에서 HandlerMapping 들을 초기화 해주는 함수이다.
BeanFactoryUtils.beansOfTypeIncludingAncestors 를 통해 HandlerMapping 들을 받아오는거로 보이는데 구현 코드를 찾아가지 못했다..
추상화가 잘돼있고 호출되는 부분부터 역순으로 찾아가다 보니 구현 클래스를 찾아가기 어려운 부분이 있었다.

일단은 내 방식대로 구현을 해보기로 했다.

새로운 설계

내가 생각한 매핑 방법은 이용자가 설정 클래스를 구현하고, 해당 클래스에서 Controller 인터페이스를 구현한 클래스들을 등록해주고, 추가적으로 uri 와 http method 를 직접 매핑해주는 방법을 생각했다.

이런 방법을 구현하려면 애플리케이션 실행 시점에 설정 클래스를 로드 해야하고 생각한 방법은 xml 을 이용한 설정 방법, 그리고 @Configuration 애노테이션을 이용한 설정 방법을 생각했다.
그중 애노테이션 방법을 구현하기로 했고, 이걸 구현하기 위해 리플렉션을 먼저 구현하기로 했다.

profile
이용자가 아닌 개발자가 되자!

0개의 댓글