자바 - HTTP 서버 개발(with 리플렉션 + 애노테이션)

애노테이션이 필요한 이유

  • 리플렉션 서블릿은 요청 URL과 메서드 이름이 같다면 해당 메서드를 동적으로 호출할 수 있다. 하지만 요청 이름과 메서드 이름을 다르게 하고 싶다면 어떻게 해야할까?

  • 그리고 /, /favicon.ico, /add-memeber와 같은 URL은 자바 메서드로 만들 수 없다.

결국 메서드 이름만으로는 해결이 어렵다. 추가 정보를 코드 어딘가에 적어두고 읽을 수 있어야 한다.

public class Controller {
    
    // "/site1"
    public void page1(HttpRequest request, HttpResponse response) {
        //...
    }

    // "/"
    public void home(HttpRequest request, HttpResponse response) {
        //...
    }

    // "/add-member"
    public void addMember(HttpRequest request, HttpResponse response) {
        //...
    }
}

리플렉션 같은 기술로 메서드 이름 뿐만 아니라 주석까지 읽어서 처리할 수 있으면 좋을 것 같다. 그러면 해당 메서드에 있는 주석을 읽어서 URL 경로와 비교할 수 있고, 같다면 해당 주석이 달린 메서드를 호출하면 된다.

그런데 주석은 코드가 아니기 때문에 컴파일 시점에 모두 제거된다. 애노테이션을 사용하면 프로그램 실행 중에 읽어서 사용할 수 있는 주석을 만들어 해결할 수 있다.


애노테이션 서블릿 - V7

  • 리플렉션을 사용하는 코드와 비슷하다. 차이는 호출할 메서드를 찾을 때 메서드의 이름을 비교하는 대신 메서드에서 @Mapping 애노테이션을 찾고, 그곳의 value 값으로 비교한다.

애노테이션을 사용해 편리하고 실용적인 웹 애플리케이션을 만들 수 있게 되었다. 현대의 웹 프레임워크들은 대부분 애노테이션을 사용해서 편리하게 호출 메서드를 찾을 수 있는 지금과 같은 방식을 제공한다.


애노테이션 서블릿 - V8

위 버전의 아쉬운 부분이 있는데 HttpRequest, HttpResponse가 필요하지 않아도 항상 인자로 받도록 되어 있다.

컨트롤러의 메서드를 만들 때 둘 중에 필요한 메서드만 유연하게 받을 수 있도록 개선해보자.

호출할 컨트롤러 메서드의 매개변수를 먼저 확인한 다음에 매개변수에 필요한 값을 동적으로 만들어서 전달했다. 덕분에 컨트롤러의 메서드는 자신에게 필요한 값만 선언하고 전달받을 수 있다. 이런 기능을 확장하면 다양한 객체들도 전달할 수 있다.

스프링 MVC도 이런 방식으로 다양한 매개변수의 값을 동적으로 전달한다.


애노테이션 서블릿 - V9

위 버전의 아쉬운 부분이 있다.

문제1. 성능

  • 모든 컨트롤러의 메서드를 하나씩 순서대로 찾는다. 결과적으로 O(n)의 성능을 보인다.

  • 문제는 고객의 요청 때마다 이 로직이 호출된다는 것이다.

문제2. 중복 매핑 문제

  • 개발자가 실수로 @Mapping에 같은 URL을 정의할 수도 있다.

  • 이 경우 현재 로직에서는 먼저 찾은 메서드가 호출된다.

  • 이런 모호한 문제는 반드시 제거해야 한다.

  • AnnotationServletV3을 생성하는 시점에 @Mapping을 사용하는 컨트롤러의 메서드를 모두 찾아서 pathMap에 보관한다.

  • ControllerMethod 객체에 @Mapping의 대상 메서드와 메서드가 있는 컨트롤러 객체를 캡슐화했다.

  • 중복 경로가 발생하면 컴파일 오류가 발생하면서 서버가 실행되지 않는다.


이전 ↩️ - 애노테이션arrow-up-right

메인 ⏫arrow-up-right

Last updated