본문 바로가기

개발/개발 관련 Contents

성능최적화

반응형

[자바스크립트] 웹 사이트 최적화 라는 글을 읽고 정리하였습니다.

성능최적화 아는대로 애기하시오

 

이런 질문을 받는다면 나는 어떻게 답변할 수 있을까?
=> 웹페이지 구동속도를 빠르게 하는 방법으로 인터넷 속도를 늘리거나 서버 로직을 바꾸거나 불 필요한 자원을 낭비하지 않게 하면 됩니다. 정도?

 

웹 페이지의 반응시간, 속도는 웹서비스의 경쟁력 가운데 하나이다.

웹사이트의 반응 시간

0.1초 : 사용자의 동작에 해당 기능이 바로 반응한다고 느끼는 시간

1초: 불필요하게 오래 기다리지 않았다고 느끼는 시간, 0.2~1초의 시간은 컴퓨터가 동작하는 시간으로 이해될수 있는 시간. 시간이 1초 이상 걸리면 컴퓨터의 동작에 이상이 생겼다고 생각하게 된다.

10초: 사용자가 집중력을 잃지 않는 최대 시간

다양한 성능 최적화에 대해서 알아보자.


 

브라우저 동작 방식을 기반으로 한 최적화

웹페이지 최적화는 브라우저가 네트워크와 통신하는 과정은 물론 브라우저에서 페이지를 표시하는 과정에서의 응답 속도를 개선하는 것이다. 브라우저가 어떻게 동작하는지 이해해야 올바른 개선 방향을 잡을 수 있다.

  1. 서비스 이동단계 (Prompt for unload): 사용자가 웹 서비스를 이용하다 다른 주소로 이동할 때 브라우저가 제일 먼저 실행하는 단계이다.
  2. 리다이텍트 단계 : 사용자가 요청한 URL 에서 다른 URL 로 다시 보내는 단계이다. 프로세싱 모델의 redirect 에 해당한다.
  3. 애플리케이션 캐시 확인 단계 : 브라우저의 캐시에 데이터가 있는지 확인하는 단계이다. 프로세싱 모델의 App Cache 에 해당한다.
  4. 네트워크 통신 단계 ( DNS, TCP, Request, Response) : 브라우저가 네트워크와 통신해서 웹페이지와 구성 요소를 다운로드하는 단계로써 네트워크 통신 단계에 해당하는 프로세싱 모델의 단계는 DNS, TCP, Request, Response 등 이다.
  5. 브라우저 처리 단계(Processiong, onload) : 다운로드한 웹 페이지와 구성 요소로 웹 페이지를 화면에 그리는 단계이다.

서비스 이동 단계

프로세싱 모델의 Prompt for unload 에 해당하는 서비스 이동 단계는 사용자가 웹 서비스를 이용하다가 다른 주소로 이동할 때 브라우저가 제일 먼저 실행하는 단계이다. 이 단계의 작업은 다른 주소로 이동하기 전에 보고 있던 페이지에서 실행하는데, 모두 브라우저 내부에서 처리하기 떄문에 브라우저 성능과 직결된다.

 

웹서비스를 이용하면 페이지가 표시될때 우리도 모르게 이벤트가 할당되고 이때 메모리를 조금씩 사용하게 된다. 그런데 이 메모리를 더이상 사용하지 않을 떄, 즉 페이지를 떠날 떄는 메모리를 해제해야 한다. 이 메모리 해제 작업이 서비스 이동 단계에서 실행하는 작업 가운데 하나이다.

 

필요없는 메모리 해제를 담당하는 가비지 컬렉션 기능이 제대로 동작하지 않으면 브라우저가 응답 없음 상태가 되거나 실행 속도가 급격히 느려지게 된다. 웹 페이지에서 동시에 많은 변수가 생성되고 처리되는 동안 브라우저에서 허용한 임계치를 넘었을 때 가비지 컬렉션이 동작하게 되고, 가비지 컬렉션이 동작하면 스크립트 실행이 중단된다. 가비지 컬렉션이 완료되기 전까지는 스크립트가 동작하지 못해 페이지가 느려지는 것이다. 이를 해결하는 여러가지 방법이 있지만 성능이 개선된 최신 브라우저로 업데이트하는 방법이 가장 좋다.

자바스크립트의 변수와 객체, DOM 객체, AJAX 통신 등을 사용할 때 성능을 높이려면 코드스타일, 렌더링, UI 스레드와 타이머 사용, DOM 스크립팅, AJAX 와 다이나믹 로딩 방법등이 있다

 

서비스 이동 단계의 작업은 브라우저 내부에서 자동으로 실행된다. 만약 별도로 처리하려면 beforeunload 이벤트를 활용할 수 있다. 어떤 사이트를 방문한 다음 다른 사이트로 이동할 때 “이용해 주셔서 감사합니다.”라는 알림 문구가 나타나는 것은 beforeunload 이벤트를 활용한다. 메모리 해제를 담당하는 모듈을 만들 수 있다.


리다이렉트 단계

프로세싱 모델의 redirect 에 해당하는 리다이렉트 단계는 사용자가 요청한 URL 에 다른 URL 로 다시 보내는 단계이다. 쉽게 볼 수 있는 리다이렉트는 소셜 네트워크 서비스 에서 사용하는 단축 URL 이다. SNS 특성상 입력하는 글자수에 제한이 있다. 단축 URL 을 사용하면 SNS 의 글자수 제한을 피할 수 있다.

 

리다이렉트가 발생하면 상태 코드로 301 이나 302 를 반환하는데, 이는 HTTP 요청을 완수하기 위해서 추가로 무언가를 해야한다는 의미이다. 이런 이유로 리다이렉트가 발생하면 어떤 자원도 다운로드하지 않ㅇ으며 브라우저에 일시적으로 빈페이지가 보인다. 그렇기 떄문에 특정한 목적으로 리다이렉트를 사용하는 것은 어쩔 수 없지만 의도치 않게 또는 실수로 리다이렉트가 발생한다면 웹페이지의 성능 향상을 바로 잡아야 한다.

 

리다이렉트와 관련해서 개발자가 흔히 저지르는 실수 가운데 하나는 URL 뒤에 슬래쉬를 넣지 않는 것이다.

두번째로 실수하는 부분은 웹페이지를 이용한 리다이렉트이다. 흔한 사용방법은 메타태그를 이용하는 방버이다.

 

<meta http-equiv="refresh" content="1; url=http://www.naver.com/">

 

이 코드는 두가지 성능 문제가 있다. 첫번째는 이 코드를 실행시킬 별도의 페이지를 거쳐야 리다이렉트된다는 점이다. 두번째는 최종 페이지에 도착했을 때 캐시가 설정된 리소스임에도 불구하고 조건부 GET 요청이 이루어진다는 점이다.

 

조건부 GET 요청은 브라우저에 캐싱된 리소스를 사용하기 전에 해당 리소스를 사용해도 되는지 서버에 물어보는 것입니다. 이때 헤더의 If-Modified-Since 정보를 이용해 서버에 요청을 보냅니다. 리소스가 수정되지 않았다면 '304 Not Modified' 코드를 받아 캐시에 있는 리소스를 사용합니다. 자원이 수정됐다면 서버로부터 리소스를 다운로드 합니다. 웹페이지 주소뿐아니라 이미지와 스타일시트, 자바스크립트와 같이 페이지를 구성하는 요소도 리다이렉트 될 수 있습니다. Fiddler 를 이용하여 301 이나 302 상태 코드가 발생하는 요소들을 찾아 의도치 않게 리다이렉트가 발생하고 있는 부분은 성능향상을 위해 바로 잡아야 합니다.


어플리케이션 캐시 확인 단계

리다이렉트 작업을 마치고 HTTP 요청을 처리하기 위한 준비를 마쳤다면 브라우저는 맨 먼저 서버로 요청을 하게 된다. 서버에서 응답이 오면 개별요소 가 사용자 PC 에 있는 지 캐시 데이터를 찾게 된다. 별도로 설정하지 않았다면 윈도우 운영체제에서는 디렉터리에 캐시 데이터가 존재한다. 캐시 데이터의 종류에는 쿠키, 이미지, 스크립트, 스타일 시트 등이 있다. 성능 향상을 위해 가장 효과적인 방법은 브라우저와 서버 사이의 통신을 최대한으로 줄이는 것이다. 그러므로 다시 방문한 사용자에게 좀 더 빠른 응답을 속도를 제공하려면 애플리케이션 캐시를 잘 활용해야 한다.

브라우저에서 URL 정보를 이용해 서버에 요청을 보내면 마크업 데이터가 브라우저에 도착합니다. 이때 a.gif 라는 이미지 파일을 다운로드하는 태그를 만났을 때 브라우저의 처리 절차는 다음과 같습니다.

  1. Expires 정보 확인 브라우저가 a.gif 파일을 서버에 요청하기 전에 사용자 PC 에 저장된 Expires 정보(만료 날짜)를 확인합니다. Expires 정보가 있고 설정한 기한이 남았다면 사용자 PC 의 a.gif 파일을 사용하게 됩니다. 이 단계가 네트워크 통신 단계의 Cache Read 단계입니다.
  2. If-Modified-Since 정보 확인 Expires 정보가 없거나 기한이 지났으면 If-Modified-Since 정보(마지막으로 수정한 날짜)가 있는지 확인합니다. If-Modified-Since 정보가 없으면 서버에 요청해 이미지를 받게됩니다. 이때 상태 코드는 ‘200 OK’입니다. If-Modified-Since 정보가 있으면 If-Modified-Since 정보를 서버에 보냅니다.
  3. If-Modified-Since 정보와 Last-Modified 정보 비교 서버는 브라우저가 보낸 If-Modified-Since 정보를 Last-Modified 정보(서버에 저장된 마지막 수정 날짜)와 비교합니다. 수정한 날짜가 같다면 상태 코드 ‘304 Not Modified’를 보내 사용자 PC 에 있는 파일을 사용하게 합니다. 날짜가 다르다면 서버에서 파일을 보냅니다. 이때 상태 코드는 200 OK 입니다.

네트워크 통신 단계

프로세싱 모델의 DNS, TCP, Request, Response 는 모두 네트워크 통신에 관련된 단계이다. 이 네 단계를 거치는 비용은 상당히 크다. 네트워크 통신에 들어가는 비용을 줄이면 성능 향상에 큰 효과를 볼 수 있다.

Blocked

브라우저에서 리소스를 호출하기 저넹 소요되는 개기시간이다. 이 대기 시간은 브라우저 캨시를 확인하는 시간과 네트워크에 연결하기 전에 소요되는 준비 시간으로 이뤄진다.

네트워크에 연결하기 전에 소요되는 대기 시간은 브라우저의 동시 연결 개수와 밀접한 관련이 있다. 동시 연결 개수가 많을 수록 대기 시간은 더 짧아진다.

DNS

호스트 이름으로 IP 주소를 조회한 시간이다. 보통 20~120ms 정도 소요된다. 이 작업이 완료되지 않으면 어떤 자원도 다운로드 되지 않는다. 브라우저에서 IP 주소를 조회할 때 동일한 호스트로 요청하는 요소는 다시 IP 주소를 확인하지 않아 시간이 추가로 걸리지 않는다. 그럼 하나의 호스트로 모든 리소스를 호출하면 시간을 줄일 수 있을 것 같지만, 대신 호스트별 동시 연결 기능은 포기해야 한다.
하나의 웹페이지를 기준으로 2~4 개 정도의 호스트를 사용하는 것 을 권장한다.

한번에 보이는 이미지 개수가 많을 떄 호스트를 여러개 만들어 동시에 다운로드하면 성능을 높일 수 있다고 생각하지만 실제로 고려할 사항이 많다. DNS Lookup 단계에서 걸리는 시간도 무시할 수 없다. 또한 동시 연결 개수가 2 개인 오래된 브라우저의 성능도 함께 고려해야 하기 때문에 여러가지 가정을 세워 테스트한 다음 최적의 호스트 개수를 찾아야 한다.

TCP(Connect)

웹 서버와의 TCP 연결을 생성하는데 필요한 시간이다. 프론트엔드에서는 이 시간을 줄일 수 없다. 백엔드 영역이다.

Request (Send)

웹서버와 TCP 연결이 이뤄지면 원하는 정보를 서버에 보내는 시간이다. 주로 요청 헤더 정보를 보내는 시간이 여기에 해당된다. Send 시간은 파일 올리기와 같이 보내야 할 정보가 많을수록 오래 걸린다. 파일을 올리면 브라우저에서는 해당 파일을 바이너리 형태로 변환해 데이터를 헤더 정보에 실어서 웹 서버로 보내는데, 파일 크기가 클수록 Send 시간이 오래 걸린다.

Wait

웹서버에서 보내는 응답 메시지를 받기까지의 대기시간이다. 서버 연산 처리 시간에 해당된다. 모드 ㄴ요소에 대해서 Wait 시간이 전반적으로 느리다면 사용자가 ㅁ낳아 웹서버가 과부하 상태이거나 기타 다른 이유가 있을 수 있다. 그러나 특정 요소만 느리다면 서버 측 연산 처리 시간을 튜닝해야 한다. Ajax 로 개발 할 때 응답이 느리다면 먼저 Wait 시간을 확인해본다.

Response

서버에서 보내는 응답 메시지를 받는 시간이다. 이 시간은 해당 요소의 데이터 크기에 비례하기 떄문에 사용자의 네트워크 상태에 따라서 다를 수 있다. 이 단계에서 성능을 개선하는 방법으로는 데이터 크기를 줄이기 위해 Gzip 과 같은 파일 압축 기술을 사용하는 방법이 있다.

TTFB(Time To First Byte)

서버가 해당 요소의 첫번째 바이트 정보를 브라우저에 보내는 시간. 프론트엔드에서는 이 단계의 걸리는 시간을 줄일 수 없다.

Cache Read

사용자 PC 에 저장돼 있는 캐시를 읽어 오는 시간이다. Blocked 단계와 Cache Read 단계는 네트워크 단계에 속하지는 않는다.

브라우저 처리단계

프로세싱 모델의 Processing 과 onLoad 에 해당하는 브라우저 처리 단계는 서버에서 받은 HTML 과 이미지, 스타일 시트를 조합해 사용자가 실제로 보는 화면을 만드는 단계이다. 서버에 요청한 요소가 모두 도착하면 브라우저는 DOM 을 생성하기 시작. 이렇게 DOM 을 조작하는 시점에 따라 응답 속도가 달라질 수 있다.

예전에는 인라인으로 개발을 하였으나 UI 개발이 복잡해지면서 개발할 때는 인라인 형태의 이벤트 바인딩 방법보다는 이벤트 핸들러로 바인딩하는 방법을 사용한다. 이벤트 핸들러로 이벤트를 바인딩하려면 최우선 조건이 해당 DOM 이 존재해야 한다는 것이다. 모든 DOM 이 존재하는 바로 그 시점이 DOMContentLoaded 이벤트나 onload 이벤트가 발생하는 시점이다.

DOMContentLoaded 이벤트와 onload 이벤트는 모두 “이제 모든 준비가 완료됐으니 마음대로 DOM 을 조작해도 된다”라는 의미입니다

하나의 웹페이지가 나타날 때까지 브라우저 내부의 처리 과정은 상당히 복잡합니다. 그렇기 때문에 하나를 개선했다고 해서 속도가 갑자기 빨라지지는 않습니다. 다만 브라우저의 처리 과정을 이해함으로써 처음으로 성능 향상을 시도하는 개발자나 어디서부터 시작해야할지 몰랐던 개발자라면 성능을 향상시키려면 무엇을 고려해야 할지 대략적인 방향을 잡을 수 있을 것입니다.

 

출처

반응형

'개발 > 개발 관련 Contents' 카테고리의 다른 글

우아콘 2023 후기 by 3년차 프론트엔드 개발자  (3) 2023.11.22
강남사자봇 사용설명서  (2) 2022.07.18
Tortoise (svn gui tool)  (0) 2021.07.13
Process vs Thread  (0) 2021.07.09
Circle-CI 맛보기  (0) 2021.07.04