일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- redis
- Spring cloud gateway
- Thread
- MDC
- Gateway
- 살아남았다.
- 톰캣
- spirng
- JWT
- tomcat
- 최종 합격
- resilience4j
- AOP
- 우아한테크코스
- 테스트코드
- 오어스
- Kotlin
- 우테코
- 커넥션 풀
- 동시성문제
- circuitbreaker
- Spring Batch
- Transactio
- Elk
- 우테코 5기
- DispatcherServlet
- 트랜잭션
- 우아한 테크 코스
- oauth
- HikariCP
- Today
- Total
코딩은 내일부터
HTTP와 톰캣은 뭘까? 본문
이번글은 톰캣을 구현하면서 공부한 HTTP, 톰캣 그리고 헷갈렸던 포인트인 서블릿부분을 포스팅했다.
웹 서버
웹 서버는 http요청을 처리하고 응답을 제공한다.
웹 서버는 HTTP프로토콜을 구현하고, 웹 리소스를 관리하고, 웹 서버 관리 기능을 제공하는데
기본 웹 서버의 요청은 다음 사진과같이 이루어진다.
우리가 http://localhost:8080/beaver.index페이지를 열어볼 때,
웹브라우저는 HTTP요청을 http://localhost:8080서버로 보낸다.
서버는 요청받은 객체를 찾고, 성공했다면 그것을 타입, 길이 등의 정보와 함께 http응답에 실어서 클라이언트에게 보낸다.
HTTP가 뭔데?
HTTP는 Hyper Text Transfer Protocol의 두문자어로,
인터넷에서 데이터를 주고받을 수 있는 프로토콜이다.
프로토콜은 데이터를 주고받을때 지켜야되는 규칙인데 이렇게 규칙을 정해두었기 때문에,
모든 프로그램이 이 규칙에 맞춰 개발해서 서로 정보를 교환할 수 있게 된 것이다.
그러면 HTTP는 어떤 정보를 넘겨?
그러면 사용자가 버튼 또는 URL을 입력하면 어떤 데이터가 넘어가는지 확인해보겠다.
먼저 첫줄을 start line이라고하는데
띄어쓰기(” ”)단위로 구분으로 HTTP 메서드,요청 Path HTTP 버전으로 구성되있다.
각각 살펴보면
HTTP메서드
이부분은 요청이 어떤동작을 취해야하는지 알려주는 부분이다.
- GET :서버에서 클라이언트로 지정한 리소스를 보내라.
- PUT :클라이언트에서 버러보 보낸 데이터를 지정한 이름의 리소스로 저장하라.
- DELETE :지정한 리소스를 서버에서 삭제하라.
- POST :클라이언트 데이터를 서버 게이트웨이 애플리케이션으로 보내라.
- HEAD :지정한 리소스에 대한 응답에서, HTTP 헤더 부분만 보내라.
요청 Path
요청 Path는 말 그대로 접근할 대상(서버)의 경로에 대한 상세 정보
즉, 어디경로로 이동할 것인지를 나타내는 부분이다.
HTTP 버전
이부분은 HTTP의 어떤 버전을 사용해서 요청했는지 알려주는 부분이다.
다음으로 headers에 대해 알아보겠다.
Headers에 무슨 정보를 담나요?
요청 및 응답 메시지 모두에서 사용 가능한 Entity(콘텐츠, 본문, 리소스 등)에 대한 설명 헤더 항목이다.
간단하게 말해 요청 및 응답의 대한 설명부분이다.
인터넷은 수천 가지 데이터 타입을 다루기 때문에, Content-Type만 알아보겠다.
HTTP는 웹에서 전송되는 객체 각각에 신중하게 MIME타입이라는 데이터 포맷라벨을 붙인다.
미니타입이란 사선(/)으로 구분된 주 타입(primary object type)과 부 타입(specific subtype)으로 이루어진 문자열 라벨이다.
그러면 어떤 정보를 받아?
요청(Request)명령을 알아봤으니 응답(Response)명령을 알아보겠다.
HTTP 상태코드
응답에서 첫번째 줄에있는HTTP버전과 숫자로 이루어진 상태코드로 이루어져있다.
이 상태코드는 요청이 성공했는지 아니면 추가 조치가 필요한지를 나타내는 부분이다.
- 1xx(Informational):요청이 수신되어 처리중
- 2xx(Successful):요청 정상 처리
- 3xx(Redirection):요청을 완료하려면 추가 행동이 필요
- 4xx(Client Error):클라이언트 오류,잘못된 문법등으로 서버가 요청을 수행할 수 없음
- 5xx(Server Error): 서버 오류, 서버가 정상 요청을 처리하지 못함
3.xx : 리다이렉션 상태코드 자세히보기
리다이렉션코드가 저는 생소한거같아서 한번 설명하겠다.
리다이렉션 상태 코드는 클라이언트가 관심있어 하는 리소스에 대해 다른 위치를 사용하라고 말해주거나,
그 리소스의 사용 대신 다은 대안 응답을 제공한다.
만약 리소스가 옮겨졌다면, 클라이언트에게 리소스가 옮겨졌으며 어디서 찾을 수 있는지 알려주기 위해 리다이렉션 상태 코드와 (선택적으로)Location 헤더를 보낼 수 있다.
301 308 302 303 307
리다이렉션 종류 | 영구(Permanent) | 영구(Permanent) | 일시(Temporary) | 일시(Temporary) |
리다이렉션시 메소드를.. | 변경 | 유지 | 변경 | 변경 (보장) |
Http/1.1 클라이언트는 Post요청을 보내고 307상태코드를 보내는 상황이라며,
서버는 클라이언트가 리다이렉션 URL에 대한 GET요청으로 리다이렉트를 따라가길 원한다. (HTTP/1.0은 302로보낸당.)
데이터의 흐름
위와같은 형태로 데이터가 이동하게 된다.
웹에도 캐시가 있어?
웹에는 캐시가 있는데 캐시가 있는 이유는 클라이언트가 서버에 똑같은 요청을 여러번 보내면 똑같은 바이트가 반복해서 이동한다. 이 불필요한 데이터 전송은 값비싼 네트워크 대역폭을 잡아먹고,
전송을 느리게 만들며, 웹서버에 부하를 준다. 이런 문제가 있을때 캐시를 사용해서 해결할 수 있다.
다음으로 캐시로 어떤문제를 해결할 수 있는지 살펴보겠다.
대역폭 병목 및 거리로 인한 지연
네트워크 속도와 문서 크기에따라 전송 시간이 많이 차이날 수 있다.
만약 대역폭이 낮은 네트워크라면 이 지도의 거리가 샌프란시스코에서 애틀랜타거리고 5MB크기의 파일이라면 도착하는데 30초가 걸릴수있다.
또한 애틀랜타가 아닌 반대편에있는 도시라고 한다면 빛의 속도로라 할지라도 지연이 일어날 수 있다.
갑작스런 요청 쇄도
캐싱은 갑작스런 요청 쇄도에 대처하기 위해 특히 중요하다. 갑작스런 사건(뉴스 속보같은)으로 인해 많은 사람이 거의 동시에 웹문서에 접근할 때 과부화가 걸리게되 심각한 장애를 야기시킬 수 있다.
캐시는 한 명의 사용자에게만 할당될 수도 있고 반대로 수천 명의 사용자들 같에 공유될 수도 있다.
한 명에게만 할당된 캐시를 개인 전용캐시(private cache)라 부른다.
반대로 공유되는 캐시를 공용 캐시(public cache)라고 불린다.
브라우저는 개인 전용 캐시를 내장하고 있다. 대부분의 브라우저는 자주 쓰이는 문서를 개인용 컴퓨터의 디스크와 메모리에 캐시해 놓고 사용자가 캐시 사이즈와 설정을 수정할 수 있다.
캐시 처리 단계
- 요청 받기 - 캐시는 네트워크로부터 도착한 요청 메시지를 읽는다.
- 파싱 - 캐시는 메시지를 파싱하여 URL과 헤더들을 추출한다.
- 검색 - 캐시는 로컬 복사본이 있는지 검사하고, 사본이 없다면 사본을 받아온다.(그리고 로컬에 저장한다.)
- 신선도 검사 - 캐시는 캐시된 사본이 충분히 신선한지 검사하고, 신선하지 않다면 변경사항이 있는지 서버에게 물어본다.
- 응답 생성 - 캐시는 새로운 헤더와 캐시된 본문으로 응답 메시지를 만든다.
- 발송 - 캐시는 네트워크를 통해 응답을 클라이언트에게 돌려준다.
- 로깅 - 선택적으로, 캐시는 로그파일에 트랜잭션에 대해 서술한 로그 하나를 남긴다.
어떻게 저장해?
캐시는 Get요청일때만 되고 Path을 key값으로 저장한다.
즉, Get요청일때만 Local 저장소를 뒤져보고 찾는 Key의 값으로 요청할때 사용한 Path를 사용해서 찾는다.
그래서 톰캣이 뭔데?
Tomcat이란 아파치 재단에서 만든 오픈 소스 WAS(Web Application Server)이다.
Tomcat은 Java Servlet과 JSP가 실행할 수 있는 환경을 제공하여 동적인 페이지를 생성한다.
그리고 DB 연결 및 데이터 조작, 다른 응용프로그램들과 상호 작용이 가능하다.
또한 웹서버를 포함하고있기 때문에 웹서버의 기능까지 수행하고 있다.
톰캣에는 catalina 와 coyote패키지가 있는데 각각의 패키지가 무엇을 하는지 알아보겠다.
Coyote
Coyote는 톰캣의 웹서버 역할을 하는데 핵심적인 기능을 가지고있는 Http11Processor 만 살펴보겠다.
Http11Processor는 클라이언트로부터 들어온 HTTP 요청을 해석하고,
이를 처리하기 위해 서블릿 컨테이너로 전달하며,
서블릿 컨테이너에서 생성된 응답을 클라이언트에게 반환하는 역할을 한다.
service()메소드에서 요청의대한 파싱이 이루어지고
389번줄에서 getAdapter().service를 통해 알맞은 서블릿을 찾고 로직을 수행한 후 Response에 값을 저장해서 처리한다.
Catalina
다음으로 catalina는 톰캣에 WAS역할을 하고있다.
먼저 위에서 말한 getAdapter().service가 실행되면 StandardWrapperValve객체안에있는 invoke()메서드가 실행되게된다.
invoke()가 실행되면 검증과정의 거친 후 allocate()메서드가 실행되는데,
이 메서드는 주석에서 설명되어있듯이 클라이언트의 요청을 처리하기 위해 서블릿 인스턴스를 할당한다는 의미이다.
이렇게 서블릿이 할당되고 filterChain.doFilter(request.getRequest(), response.getResponse()); 메서드를 통해
요청과 응답을 가로채고, 필터들이 추가적인 처리를 수행한 뒤, 최종적으로 서블릿의 service()메서드가 실행된다.
실행된 서블릿은 로직을 실행 후 값을 저장하고, Response값을 내보냅니다.
정리하면
1. Http11Processor 클래스의 service(SocketWrapperBase<?> socketWrapper) 메서드가 호출된다.
2. 이 메서드 내에서 getAdapter().service(request, response) 코드가 실행된다.
이를 통해 Connector에서 Request 객체와 Response 객체를 획득하고,
이를 사용하여 알맞은 StandardWrapper를 찾아 해당 서블릿의 service() 메서드를 호출한다.
3. StandardWrapper 클래스의 invoke(Request request, Response response) 메서드가 실행됩니다.
이 메서드 내에서 필요한 초기화 작업을 수행한다.
4. 그런 다음 StandardWrapper 클래스의 allocate() 메서드가 호출되어 알맞은 서블릿 인스턴스를 할당한다.
5. 할당된 서블릿의 service() 메서드가 호출된다.
이 때, 필터 체인을 통해 요청과 응답이 처리되며, 최종적으로 서블릿이 요청을 처리하고 응답을 생성한다.
6. filterChain.doFilter(request.getRequest(), response.getResponse()) 코드를 통해
필터들이 요청과 응답을 가로채고 추가적인 처리를 수행한다.
이 작업은 필터들이 처리를 마치면 서블릿의 service() 메서드를 호출한다.
7. 이렇게 서블릿의 service() 메서드가 호출된 후(응답처리 후),
다시 Http11Processor 클래스의service(SocketWrapperBase<?> socketWrapper) 메서드로 돌아온다.
그리고 해당 메서드에서는 다음 요청을 처리할 준비를 하고(소켓을 닫는다.), 반복적으로 요청을 처리하는 과정을 진행한다.
원래 내가 알던 서블릿은 DispatcherServlet밖에 없어서 톰캣의 서블릿이 와닿지 않았다..
그래서톰캣의 서블릿하고 스프링의 서블릿은 뭐가 다른건지 궁금해서 공식문서를 찾아본 결과!
공식문서에 따르면 톰캣의 onStartup를 오버라이딩한 후 DispatcherServlet의 구현체를 생성해서 톰캣에 주입을 하고 사용하고있던 것이었던 것이다….
그래서 구조는 다음과 같이 정리해보았다.
이런 사진은 많이봤을것이다. 하지만 나는 이사진 때문에? 톰캣이 스프링을 어떻게 요청하는지 너~~무 헷갈렸다.
위에 사진에 Servlet container를 자세히보면 밑의 사진으로 표현할 수 있다.
정적자원을 요청할때는 기본서블릿을 동적인 자원 혹은 서버안에있는 로직을 실행시켜야한다면
DispatcherServlet을 찾아서(이 키워드 찾기까지 이틀은 걸린거같다..) 실행시킨다.
이상으로 HTTP 와 톰캣이었다.
'우아한 테크 코스(우테코) > 우테코 공부' 카테고리의 다른 글
전략패턴을 이용한 외부API 추상화하기 (0) | 2023.09.10 |
---|---|
Thread 와 톰캣 튜닝하기 (2) | 2023.09.09 |
도커? 그게 뭔데. (0) | 2023.08.28 |
트랜잭션과 트랜잭션 격리수준 그게 뭔데. (0) | 2023.08.23 |
OAuth 그게 뭔데. (개념 및 구현) (0) | 2023.08.16 |