요즘 트렌드는 프론트/백엔드의 분리이다.
그러다보니 사용자에게 페이지를 제공할 때, 서버렌더링 방식이아닌 클라이언트 렌더링(브라우저에서 화면을 그림)방식을 많이 사용하게 된다.
나는 백엔드 개발자이긴 하지만, 프론트개발관련해서 웹애플리케이션이 브라우저에서 어떻게 동작하고 최적화 방법에 대해 공부가 필요해서 해당 내용을 정리하게 되었다.
참고한 책은 https://book.naver.com/bookdb/book_detail.nhn?bid=4587095 (웹 사이트 최적화 기법) 이며, 필요하다고 생각한 내용들만 적을 생각이다!
현실적으로 대부분의 웹 페이지는 최종 사용자의 반응 시간(브라우저 반응 시간) 중 HTML문서를 웹 서버로부터 다운로드 받는 데 소요되는 시간이 10~20%도 채 되지 않는다.
⇒ 우리는 나머지 80~90%에 초점을 맞추어 웹 사이트를 최적화해야 한다.
HTML 문서는 전체 응답 시간의 5% 밖에 되지 않는다.
그 외 HTML 페이지 안에 포함되어 있는 이미지, 스크립트, 스타일시트와 같은 HTML 구성요소가 응답 시간의 95%를 차지한다. (HTML, 스크립트 그리그 스타일시트를 파싱할 때 드는 시간은 극히 적다.)
조건부 GET 요청(conditional GET request)
⇒ 이미 캐시되어 있지만 HTTP 응답 헤더의 내용으로 인해 브라우저는 이 이미지를 사용자에게 보여주기 전에 갱신 여부를 확인하고 보여준다.
브라우저는 리소스를 어떻게 다룰까?
- 캐시된 이미지는 다운로드하지 않는다. (HTML HTTP 요청 뒤에 오는 빈 공간은 브라우저가 HTML, 자바스크립트, CSS를 파싱하고 캐시로부터 구성요소를 불러오는 시간)
- 동시에 다양한 HTTP 요청이 발생된다. (도메인 이름을 사용하거나, HTTP 프로토콜 버전에 따라 달라질 수 있음)
- 스크립트는 동시 다발적으로 요청하지 않는다. (스크립트가 다운로드중인 경우에 브라우저는 대부분 추가적인 HTTP 요청을 막기 때문)
성능 황금률(performance golden rule) : 10~20% HTML 문서 다운, 80~90% 페이지 안의 모든 구성요소 다운
HTTP의 이해
HTTP는 클라이언트와 서버 간의 요청과 응답으로 구성되는 프로토콜이다.
브라우저는 지정된 URL로 HTTP요청을 보내고 서버는 해당 URL에 해당되는 응답을 다시 돌려보내게 된다.
압축
브라우저와 서버 둘 다 압축을 지원한다면 압축을 이용해서 응답 크기를 줄일 수 있다.
- 브라우저가 서버에게 요청한다. index.html 을 받고 싶어. 근데 나 gzip 압축을 지원해 (Accept-Encoding : gzip)
- 서버가 브라우저에게 응답을 준다. 아! 너 gzip 지원하는 구나 압축해서 보내줄께 (Content-Encoding : gzip)
HTTP 헤더를 통해서 압축 지원 여부를 서로 교환하고, 압축된 파일을 제공해준다.
조건부 GET 요청(Conditional GET)
브라우저의 캐시에는 구성요소의 복사본이 있지만 그 구성요소가 유효한지 확실하지 않을 경우 조건부 GET 요청을 보낸다. 캐시안의 구성요소가 유효하다면 브라우저는 캐시로부터 그 구성요소를 복사해서 사용한다.
일반적으로 캐시된 구성요소의 유효성은 최종 수정 날짜로 판단한다.
브라우저는 구성요소가 마지막으로 언제 수정되었는지를 응답 헤더의 Last-Modified항목을 통해 알 수 있다.
브라우저는 If-Modified-Since라는 헤더 속성을 통해서 서버로 최종 수정 날짜를 보내게 된다.
브라우저 : 나에게는 최종 수정 날짜가 이러한 리소스가 있다. 이것을 사용해도 될까?
날짜가 수정되지 않았다면 "304 Not Modified"라는 상태 코드를 반환한다. 그러면 브라우저는 캐시된 복사본을 사용한다.
HTTP/1.1의 ETag와 If-None-Match 헤더는 조건부 GET 요청을 보내는 또 다른 방법이다.
만료기한
조건부 GET 요청과 304 응답은 페이지를 더 빠르게 로드할 수 있게 도와주지만 유효성을 확인하려면 여전히 클라이언트와 서버 간에 요청/응답의 왕복이 필요하다.
하지만 헤더 만료기한(Expires)은 서버로 접근하여 구성요소의 유효성을 확인하는 작업을 생략할 수 있게 해주고 브라우저는 캐시의 복사본이 아직 유효한지 바로 알 수 있게 해준다.
브라우저가 응답 안에 헤더 만료기한을 보게 될 경우 브라우저는 캐시 안에 구성요소의 만료기한을 저장한다. 구성요소의 기한이 만료되지 않는 동안 브라우저는 캐시되어 있던 구성요소를 이용하고 HTTP 요청을 피한다.
Keep-Alive
HTTP는 TCP(Transmission Control Protocol)로 구성된 프로토콜이다.
초기의 HTTP는 HTTP 요청을 보낼 때 마다 새로운 소켓 연결이 맺어졌었다.(효율적이지 못함)
=> 지속성 있는 연결(Persistent Connections)은 이렇게 같은 서버에 여러 개의 소켓 연결을 맺는 비효율 문제를 해결하기 위해 나왔다. (HTTP/1.0의 Keep-Alive) 즉, 하나의 연결 안에 여러 개의 요청을 보내느 것이다.
브라우저와 서버는 헤더의 Connection 속성에 Keep-Alive 값을 지정할 수 있다.
Connection의 Keep-alive 값은 HTTP/1.1에서는 필요하지 않지만 대부분의 브라우저와 서버는 이 값을 계속 포함하고 있다.
HTTP/1.1 에서 정의된 파이프라인 방식을 이용하면 응답의 기다림 없이 하나의 소켓연결을 이용해 여러 개의 요청을 보낼 수 있다. (HTTP/1.1의 파이프라인 방식은 지속성 있는 연결보다 더 좋은 성능을 보여줌)
파이프라인 방식이 더 넓게 사용될 때까지는 Keep-Alive를 이용하여 브라우저 및 서버와 통신하는 방법이 더 효율적일 수 있다. 이것은 HTTPS에서 더 중요한데, 보안 소켓 연결은 더 많은 시간을 필요로 하기 때문이다.
'프로그래밍 노트 > WEB' 카테고리의 다른 글
서버인증방식종류_세션/쿠키, 토큰방식 (0) | 2021.01.20 |
---|---|
Timeout에 관한 정리 (0) | 2020.03.03 |
REST API 보안_인가(Authorization) (0) | 2019.06.07 |
REST API 보안_인증(Authentication) (0) | 2019.06.07 |
REST API 보안_1 (0) | 2019.05.30 |