개발/🚀 데브코스

😺 서버 구동 방식 - Tomcat DispatcherServlet 😺

정소은 2024. 8. 15. 14:38

 

 

 

1.   웹이 동작하는 방식

 

https://sosoeunii.tistory.com/76

 

🖤 UMC 서버 3주차 스터디 - Web Server & Web Application Server(WAS), Reverse Proxy 🖤

웹이 동작하는 방식을 간단하게 요약하자면 클라이언트에서 요청이 들어오면 서버에서 요청을 처리한 후 반환하는 것이다. 예를 들어 로그인을 위해 사용자가 ID와 비밀번호를 입력하고 로그

sosoeunii.tistory.com

 

 

위 게시물에서 웹이 동작하는 큰 틀을 살펴볼 수 있다.

요약하자면, 클라이언트에서 요청이 들어왔을 때 apache나 nginx와 같은 WS에서 정적인 처리를 진행하고

만약 동적 처리가 필요하다면 리버스 프록시를 통해 tomcat과 같은 WAS에 처리를 부탁하고

WAS웹 컨테이너에 저장되어 있는 서블릿 클래스들 중 요청에 알맞은 클래스를 작동시켜 동적인 처리를 진행한다.

 

 

이번에는 WAS의 내부에서 일어나는 일들을 좀 더 구체적으로 알아보겠다.

즉, WAS에서 어떻게 클라이언트의 요청에 알맞은 서블릿 클래스를 찾는지, Spring에서는 이를 어떻게 자동화했는지 알아보겠다.

 

 

2.  외장 서버의 구동 방식을 통한 이해

 

사실 요즘은 Spring이 많이 발전하고 보편화되었기 때문에 외장 서버의 방식을 거의 사용하지 않는다.

Spring에 'spring-boot-starter-web' dependency 하나만 추가해주면

서버가 내장화되어 알아서 동적인 처리들(요청에 알맞은 서블릿 클래스 찾아서 작동시키기)을 해주기 때문이다.

 

하지만 자동화되었다고 해서 뚝딱 기능 혹은 문법을 외워서 끼워맞추기 식으로 공부하다 보면

나중에 문제가 터졌을 때 그 원인을 제대로 파악하지 못할 것이다.

 

따라서 오늘은 외장 서버의 구동 방식을 통해서 자동화된 기능들 내부에서 어떤 일이 벌어지고 있는지 알아보도록 하겠다.

우선 외장 서버 방식을 사용했던 개발자들은 웹 프로젝트를 개발할 때 어떤 절차를 거쳤었는지 알아보자.

예전 백엔드 개발자들의 방식
1 )  톰캣과 같은 WAS(Web Application Server) 설치
2 )  어플리케이션 코드 개발 후 WAR 빌드
3 )  WAR 파일을 WAS에 배포 ( 외장 서버 방식 ) 

 

그림으로 구조를 살펴보면 이런 느낌일 것이다.

 

톰캣은 포트 하나(보통 8080)를 완전히 점유한 뒤

외부(클라이언트)에서 요청이 들어오면

톰캣 내의 DispatcherServlet이 WAR 내에서 적절한 서블릿 혹은 jsp를 찾아서 '이 요청 처리해!' 하고 넘긴 뒤

처리된 결과를 다시 넘겨주는 역할을 한다

 

 

그렇다면 DispatcherServlet은 어떻게 적절한 서블릿 혹은 jsp를 찾는 것일까?

우선 클라이언트의 요청에 대해서 잠시 생각해보자.

클라이언트의 요청은 url로 분류되어서 들어온다

예를 들어, 클라이언트의 요청이 게시글 작성, 게시글 수정, 게시글 삭제 세가지가 있다면

게시글 작성 : /article/post

게시글 수정 : /article/update

게시글 삭제 : /article/delete

요청마다 서로 다른 세개의 url을 가짐으로써 분류된다

그렇기 때문에 클라이언트의 요청에 알맞은 처리를 해주기 위해서는 이 url을 통해서 매핑을 수행해주면 된다

가장 원시적인 방법은 web.xml에 url과 서블릿 혹은 jsp 클래스명을 매핑해주는 방법이다.

 

web.xml 예시

  <servlet>
    <servlet-name>articlePost</servlet-name>
    <servlet-class>com.example.articlePost</servlet-class>
  </servlet>
  
  <servlet>
    <servlet-name>articleUpdate</servlet-name>
    <servlet-class>com.example.articleUpdate</servlet-class>
  </servlet>
    
  <servlet>
    <servlet-name>articleDelete</servlet-name>
    <servlet-class>com.example.articleDelete</servlet-class>
  </servlet>
  
  <servlet-mapping>
  	<servlet-name>articlePost</servlet-name>
  	<url-pattern>/article/post</url-pattern>
  </servlet-mapping>
  
  <servlet-mapping>
  	<servlet-name>articleUpdate</servlet-name>
  	<url-pattern>/article/update</url-pattern>
  </servlet-mapping>
  
  <servlet-mapping>
  	<servlet-name>articleDelete</servlet-name>
  	<url-pattern>/article/delete</url-pattern>
  </servlet-mapping>

 

 

하지만 이 방식은 url과 클래스의 개수가 많아질수록 귀찮은 방식이다 

그래서 추후에 이 방식이 발전해서 @WebServlet을 사용하게 된 것이다

@WebServlet("/article/post")
public class articlePost extends HttpServlet {
// 서비스 로직
}

 

 

보통 WS에서 정적인 처리를, WAS에서 동적인 처리를 진행하기에

위 톰캣 내용을 WS랑 함께 통합해서 정리해보자면

😼 총정리

tomcat이 포트 점유
> 포트를 통해 클라이언트 요청(url) 도착
> WS에서 정적인 처리 진행
> 동적인 처리일 경우 WAS로 리버스 프록시 진행
> @WebServlet을 통해 매핑된 서블릿 클래스 찾아서 처리