규턴의 개발블로그
article thumbnail

이번 2주차 웹서버를 구현하는 미션을 받았다.

 

해당 미션은 실제 웹서버를 Socket기반으로 통신하는것을 직접 하드하게 코딩하는것이었다. 

깃헙 주소:https://github.com/gyuturn/be-java-web-server

 

GitHub - gyuturn/be-java-web-server: 현대자동차 소프티어 부트캠프 2023 자바 웹 서버 프로젝트

현대자동차 소프티어 부트캠프 2023 자바 웹 서버 프로젝트. Contribute to gyuturn/be-java-web-server development by creating an account on GitHub.

github.com

 

다른팀원들의 코드를 본 경험중에 Reflection을 사용하여 Request를 매핑하여 해당 컨트롤러에 해당하는 Method를 찾는것을 보았다.

(참고로 나는 해당 Request를 매핑하기 위해 if-else if 문을 엄청 써서 코드가 더러웠다.)

 

이전까지 Spring이 Reflection을 사용한 FrameWork라는것은 알 고 있었지만, 실제로 어떻게 동작되고 있는지는 몰랐기에 이번 경험을 통해 Reflection을 공부하고 나도 3주차에는 나의 코드를 Reflection을 적용해볼까 한다.

 

 

Reflection이란?

 

한마디로 정의하면

구체적인 클래스 타입을 알지 못해도 그 클래스의 메서드, 타입, 변수들에 접근할 수 있도록 해주는 자바 API 이다.

라고 할 수 있다.

 

즉 해당기능을 통해 코드 작성시점에는 어떠한 클래스를 사용해하 하는지 모르고, 런타임 시점에 클래스를 가져와 해당 함수를 실행 할 수 있다.

 

나도 실제 웹서버를 구현하면서 위의 어려움을 겪었다. 

 

controller = Controller.FactoryController(httpRequest.getUrl());

if (controller instanceof FileController) {
  if (urlType.equals(UrlType.TEMPLATES_FILE)) {
     httpResponse = ((FileController) controller).TemplateController(clientOutPutStream, httpRequest);
   } else if (urlType.equals(UrlType.STATIC_FILE)) {
      httpResponse = ((FileController) controller).StaticController(clientOutPutStream, httpRequest);
   }} else if (controller instanceof UserController) {
     httpResponse = ((UserController) controller).UserQueryString(clientOutPutStream, httpRequest);
     }

 

이전까지 내가 Controller는 요청에 따라 어떠한 컨트롤러를 사용해야 하는지 정하기 위해 if-elseif문을 남발하고 있었고 잘못된 코드를 짜고 있는것을 느꼈지만, 방법이 없는줄 알았다....

 

Reflection의 원리

 

그럼 Reflection이 어떻게 동작되는지 Controller를 통해 알아보겠다.

 

클래스로더에의해 로딩된 자바코드는 컴파일시에 바이트코드로 변경되어 메모리에 저장된다. 클래스 정보는 컴파일되어 Heap영역, Metaspace에 저장된다.


리플렉션을 사용하면 런타임시에 위 영역에 접근하여 클래스의 정보, 접근제어자, 패키지, 어노테이션 등등을 알아낼수 있는 것이다.

예를 들어 좀 더 자세히 말해보자면, @Controller 어노테이션이 사용된 클래스를 알아내고 싶다면, 리플렉션을 사용해 Heap영역, Metaspace에서 모든 클래스 정보를 불러오고,
그 중 어노테이션에 @Controller가 포함되어 있는 클래스를 가져오면 된다.

리플렉션을 활용해 알아낼수 있는 정보는 다음과 같다.

  • ClassName
  • Class Modifiers
  • Package Info
  • Superclass
  • Implemented Interfaces
  • Constructors
  • MethodsFields
  • Annotations

 

Spring에서의 Reflection을 사용한 Controller 찾기

 

결국 내가 가장 알고싶어한 내용은 이것이다. 궁금해서 chatGPT한테 물어봤다.

 

 

 

간단하게 순서를 해석해보면 다음과 같다.

1. 개발자는 Controller에 @Controller와 @ReqeustMapping등을 명시한다.

2. Spring은 Request 요청이 오면  @Controller를 찾기위해, 리플렉션을 사용해 @Controller가 달린 Class를 찾는다.

3. Spring은 컨트롤러 내에서도 리플렉션을 활용해 @RequestMapping 달린 함수를 찾고 Request와 일치하는 URL,METHOD등을 구분한다 

4. 이후 Spring이 해당 컨트롤러와 그에 맞는 적절한 함수를 찾으면 DispatcherServlet으로 등록한다. 

 

- 예외로 만약 같은 컨트롤러의 같은 함수가 사용되는 요청이 들어온다면 DispatcherServlet에 이미 등록되어 있기 때문에 Reflection을 사용하지 않고 이미 등록된것을 사용한다. 

- 반대로 DispactherServlet에 요청에 맞는 Controller와 함수가 들어가있지 않다면 Spring은 Reflection을 사용하여 해당 요청에 맞는 Controller, method를 1~4번 과정에서 찾는다.

 

실제로 ChatGpt한테 물어봤음. ㅋㅋㅋ

 

 

 

다음 3주차에서 나도 컨트롤러와 그에 관련된 메서드를 리플랙션을 사용해 리팩토링 해볼까한다.

해당 과정을 통해 정말 Spring에 좀 더 가까운 웹서버를 만들어볼 수 있지 않을까??

profile

규턴의 개발블로그

@규턴이

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!