웹에 날개를 달아주는 웹 성능 최적화 기법
- 본 책을 읽고 책의 내용을 간략하게 정리한 글입니다.
Chapter 6. 캐시 최적화
캐시
- 캐시: 컨텐츠 요청에 빠르게 응답하기 위해 서버와 클라이언트 사이에서 응답 컨텐츠 사본을 저장하는 공간
- 캐시는 보통 클라이언트와 서버 사이에 존재
- 캐시 서버의 종류 및 이점
캐시 종류 | 위치 | 이점 |
---|---|---|
브라우저 캐시 | 브라우저 | 한 번 다운로드한 리소스들을 재사용하여 사이트 로딩 속도 개선 |
프록시 캐시 | 브라우저와 ISP | 조직 내 사용자들이 접속하는 웹 사이트의 리소스들을 캐시하여 네트워크 연결과 대역폭 사용률을 감소시키고 사용자의 웹 사이트 로딩을 빠르게 함 |
트랜스패어런트 캐시 | ISP | ISP는 캐시를 사용하여 ISP 간 대역폭이 낭비되는 것을 방지함 |
리버스 프록시 캐시 | ISP와 웹 서버 | 원본 서버로 향하는 트래픽 대역폭을 감소시키고 사용자 응답 개선 |
- 쉽게 사용할 수 있는 오픈 소스 웹 캐시 서버
- Apache Traffic Server
- Nginx
- Varnish Cache
웹 캐시 동작원리
HTTP
- 캐시 서버는 HTTP/1.1 규격을 기반으로 동작하므로 HTTP를 먼저 이해해야 함
- TCP Connection 이 맺어지면 HTTP는 어떤 종류의 데이터든 전송할 수 있도록 설계
- HTTP의 특징
- 클라이언트 서버 모델로 동작
- 비연결성이며 상태를 유지하지 않는 프로토콜 (Connectionless, Stateless)
- 클라이언트와 서버 간 HTTP 메시지를 주고받으며 통신
- HTTP 메시지는 헤더와 바디 부분으로 구분되어 전송
- 하위 Transport Layer 프로토콜로 TCP를 사용하는데 일반적으로 80포트 (SSL은 443포트)를 사용
- HTTP 메시지는 크게 헤더와 페이로드로 구분
- 헤더에는 메시지를 전송할 호스트명, URL 패스 등 메시지 전송 및 처리에 필요한 데이터들이 포함
- 페이로드에는 HTML, 이미지 등 서버가 실제 전송하고자 하는 데이터들이 포함
HTTP의 캐시 제어 방식
- HTTP/1.1 부터 명시적으로 캐시를 제어할 수 있는 헤더를 추가함 = Cache-Control 헤더
- HTTP/1.1에서는 캐시를 제어하는 목적을 크게 두 가지로 정의
- 원본 서버로의 요청 수를 최소화함, 이는 네트워크 왕복 수를 줄여 결과적으로 사용자 요청에 대한 응답 속도를 단축
- 완전한 컨텐츠를 응답하지 않아도 됨, 이는 네트워크 대역폭과 리소스 낭비를 줄이고 비용을 효율화함
Expires
- HTTP/1.0은 Expires 헤더를 통해 원본 서버 컨텐츠의 유효 기간을 지정하도록 정의
Expires: Thu, 28 Sep 2017 05:16:39 GMT
- Expires 헤더는 캐시를 명시적으로 제어하지는 않지만 브라우저를 포함한 대부분 캐시 서버에서 컨텐츠를 언제까지 저장할 것인가 판단하기 위해 사용
- 캐시는 간단하게 Expires 날짜에서 Date 날짜를 빼는 것으로 해당 응답의 캐시 유지 시간 (Time To Live) 결정 가능
Time To Live (TTL) = Expires_value - Date_value
Cache-Control: max-age
- HTTP/1.1에서는 Cache-Control: max-age 헤더로 컨텐츠의 유지 시간을 정의
- 원본 서버는 해당 헤더를 사용해 캐시에서 특정 컨텐츠를 얼마나 오래 유지하고 있어야 하는지 명시적으로 설정
- Expires 헤더는 만료 일자를 지정하는 반면 Cache-Control: max-age는 유효 기간 지정
Cache-Control: max-age=2592000
- HTTP/1.0 기반의 캐시 서버나 브라우저가 Cache-Control: max-age를 지원하지 않기 때문에 원본 서버는 모든 응답에 두 헤더 값을 모두 표시해야 함
Cache-Control: s-maxage
- CDN과 같은 공용 캐시 주기 관리
- s-maxage를 이용하면 사용 중인 모든 CDN의 캐시 주기를 일괄적으로 설정하거나 변경 가능
- s-maxage는 표준으로 도입된 지 얼마 되지 않아 CDN 업체가 이 헤더를 지원하는지 먼저 확인 필요
ETag
- ETag (Entity Tag) 헤더는 원본 서버가 리소스를 식별하기 위해 부여하는 고유 번호
- 캐시 서버에서 ETag를 통해 원본 서버의 리소스가 시간이 지나 만료되었는지, 캐시된 리소스를 새로 갱신해야 하는지 여부 판단 가능
- ETag는 어떤 조합으로 작성할 지는 전적으로 ETag를 생성하는 원본 서버가 결정
- ETag는 컨텐츠의 해시값이나 TimeStamp 해시값 또는 일련 번호 등 구현하기 편한 문자를 사용할 수 있지만 고유한 값이어야 함
ETag: "27dad37 1425fcc55e4d42a1478"
- 크게 Strong ETag와 Weak ETag로 구분
- Strong ETag는 모든 리소스에 대해 유일한 값을 가져야 하므로 Weak ETag에 비해 값을 생성하는 과정이 까다로움
- Weak ETag를 사용하면 간단하게 값을 생성할 수 있지만 신뢰도가 약해짐
- Weak ETag 값을 할당할 때는 ETag 값에
w/
를 붙여 이 값이 유일하지 않을 수 있지만 괜찮다는 메시지를 캐시 서버에 전달해야 함ETag: w/ "0317"
- ETag는 캐시에 저장된 리소스의 캐시 주기가 끝났을 때 캐시 서버가 원본 서버와 캐시 유효성을 체크할 때도 중요하게 사용
Cache-Control: public
- Cache-Control: public으로 설정하면 그 응답은 모든 캐시 서버에 캐시될 수 있고 사용자 제한 없이 모든 사용자에게 응답이 전달됨
Cache-Control: private
- private로 설정하면 HTTP 요청에 대한 응답은 요청한 사용자만 캐시할 수 있고 CDN 같은 범용 캐시 서버에서는 캐시할 수 없음
- 엄밀히 말하면 범용 캐시 서버에도 캐시할 수 있지만 그 응답을 모든 사용자에게 공유할 수 없음
- Cache-Control: private를 설정한다고 해서 응답에 담긴 개인 정보까지 보호되지는 않으니 주의할 것
Cache-Control: no-cache
- no-cache 지시자가 요청 헤더에 있으면 브라우저는 원본 서버나 그 중간에 존재하는 캐시 서버들에게 캐시된 응답을 받지 않겠다는 메시지를 전달하는 것
max-age=0
을 사용하는 것과 비슷하게 동작하지만 미묘한 차이 존재- no-cache를 설정하면 캐시 서버는 항상 원본 서버로부터 최신 응답을 받아와야 함
max-age=0
은 캐시 서버가 원본 서버에서 전체 응답을 가져오기보다 조건부 요청을 이용해 캐시된 컨텐츠에 변경이 있는지를 검증
- no-cache 지시자가 HTTP 응답 헤더에 포함되면 원본 서버가 캐시 서버들에게 캐시된 응답을 보내기 전 원본 서버를 항상 확인하도록 강제
- 만약 원본 서버가 전체 응답이 아닌 특정 헤더 항목만 캐시하고 싶지 않다면 지시자 옆에 캐시하고 싶지 않은 헤더들을 나열하면 됨
- ex)
no-cache="Accept-Range"
: 캐시 서버는 응답을 캐시하되, Accept-Range 헤더는 캐시하지 않음
- ex)
Cache-Control: no-store
- 서버가 로컬 저장소에 메시지를 저장하지 않도록 지시
- no-cache는 응답을 항상 최신 상태로 유지하도록 지시하지만 로컬 저장소에 저장하는 것을 막지 않음
- 반면 no-store는 응답 메시지가 저장소에 저장되는 것 자체를 금지
- no-store의 목적은 캐시 데이터의 예기치 않은 유출 방지
캐시 유효성 체크
- 비효율적인 요청/응답을 방지하고자 HTTP 표준은 조건부 요청 (conditional request)라는 메커니즘 정의
- 저장된 응답 TTL이 만료되었을 경우 캐시가 항상 원본 서버에서 완전한 컨텐츠를 받아오는 대신 TTL 주기 동안 컨텐츠에 변화가 있을 때만 새 응답을 만들도록 요청
- 해당 컨텐츠에 변경이 있을 때 200 응답 코드와 함께 변경된 컨텐츠를 응답 본문에 포함해 보내짐
- 변경이 없다면 응답 본문 없이 304 (Not-modified) 코드만 헤더에 설정하여 보내는데, 응답에 본문이 없으므로 네트워크 자원 낭비 방지
- 조건부 요청을 보낼 때는 시간을 기반으로 보내는 방법과 컨텐츠 기반으로 보내는 두 가지 방법 사용
- 시간 기반의 조건부 요청
- 어떤 요청에 대한 원본 서버의 컨텐츠가 캐시에 저장된 후 변경되었는지 여부를 컨텐츠의 최종 변경 시간 중심으로 확인하는 방법
- 컨텐츠 기반의 조건부 요청
- 어떤 요청에 대한 요청에 대한 원본 서버의 컨텐츠가 캐시에 저장된 후 변경되었는지 여부를 컨텐츠 고유값 중심으로 확인하는 방법
- 원본 서버는 미리 정의된 대로 ETag 헤더에 해당 고유값을 넣어 보냄
-
Cache-Control: public, max-age=31536000 ETag: "15f0fff99ed5aae4edffdd6d7131f"
- 캐시는 최초 요청에 대한 응답을 캐시에 저장하고 TTL 시간이 지난 후 같은 요청이 오면 원본 서버에 ‘만약 이 컨텐츠와 일치하는 고유값이 없다면 전체 응답을 주세요.’ 같은 의미의 요청을 함
- If-none-match 헤더에 ETag 값을 복사해 원본 서버에 전송함으로써 이런 요청을 수행
-
If-none-match: "15f0fff99ed5aae4edffdd6d7131f"
캐시 컨텐츠 갱신
- 웹 사이트가 개편되거나 컨텐츠를 급하게 변경한 경우 캐시에 저장된 복사본들을 강제로 갱신해야 사용자에게 정상적인 웹 페이지 제공 가능
- 캐시 갱신 방법 1. 퍼지
- 저장소를 완전히 지우는 방식으로 대부분의 캐시 서버가 캐시를 모두 지우는 명령어나 API 제공
- 브라우저의 옵션 메뉴에서 로컬 캐시 삭제 가능
- 캐시 갱신 방법 2. 무효화
- 조건부 요청을 통해 캐시된 리소스들 중 변경이 있던 리소스만 새로 갱신하는 방법
- Cache-Control 헤더를 통해 캐시 서버의 내용을 강제로 무효화 가능
-
Cache-Control: max-age=0, must-revalidate
- 실제 변경된 리소스에 한해서만 전체 컨텐츠가 반환되므로 네트워크 대역폭 낭비를 크게 줄임
캐시 최적화 방안
캐시 가능한 컨텐츠 구분하기
- 운영 또는 개발하는 웹 페이지가 어떻게 구성되었고 얼마나 많은 파일들을 캐시할 수 있는지 WebPageTest를 통해 확인 가능
- 웹 사이트 구성 컨텐츠는 크게 정적 컨텐츠와 동적 컨텐츠로 분류할 수 있음
- 정적 컨텐츠
- URL을 호출할 때마다 변함없이 같은 응답을 주는 컨텐츠로 이미지, CSS, 자바스크립트 등이 대표적
- 동적 컨텐츠
- 사용자가 요청할 때마다 서버에 의해 다시 생성, 응답되는 컨텐츠로 서버에서 HTTP 요청과 함께 입력 시간을 포함한 다양한 변수값에 따라 컨텐츠를 동적으로 생성하여 응답함
- Ajax를 사용한 XHR 요청, 사용자가 로그인했을 때 만들어지는 개인화된 웹 페이지
- 캐시하기 어려운 컨텐츠는 다음과 같이 분류 가능
- 개인화된 컨텐츠
- 접속하는 사용자의 정보에 따라 달라지는 컨텐츠로 원본 서버에서 가공되는 컨텐츠를 의미
- API 호출이나 Ajax 요청에 대한 컨텐츠
- 인증이나 결제 등 서버의 작업이 필요하거나 시간에 따라 빠르게 변하는 정보를 받을 때 사용되므로 캐시에 적합하지 않음
- Beacon 전달 또는 쿠키 설정을 위한 호출
- 사용자 정보를 수집하거나 브라우저에 쿠키를 설정하기 위해 아주 작은 이미지를 호출하는 경우
- 이러한 요청에 대한 응답이 캐시에 저장되면 원본 서버에 정보를 보내거나 받을 수 없으므로 캐시하면 안 됨
- 개인화된 컨텐츠
올바른 캐시 정책 세우기
- 먼저 캐시할 수 있는 컨텐츠인지 판단
- 캐시할 수 있는 컨텐츠들은 매번 원본 서버에 변경 사항을 확인해야 하는지 판단
- 변경에 민감한 리소스는 응답 헤더에 Cache-Control: no-cache 나 Cache-Control: max-age=0 설정
- 응답할 리소스가 변경되지 않았다면 전체 리소스가 아닌 304 코드만 응답하면 되므로 네트워크 대역폭 낭비 방지
- 캐시할 컨텐츠들의 성격 판단
- 모든 사용자에게 공통으로 사용될 수 있다면 Cache-Control: public
- 개인화된 컨텐츠라면 Cache-Control: private
- Cache-Control: private 로 설정하면 일반적인 웹 캐시 서버에서 캐시할 수 없고 오직 개인 브라우저에서만 캐시함
- 캐시 주기를 설정하고 max-age 추가
캐시 주기 결정하기
- 캐시 주기는 컨텐츠 타입별로 다르게 설정 가능
- 특별한 이유가 없다면 캐시 주기를 1년 정도로 길게 설정하는 것 권장
- 만약 링크 변경 없이 이미지 내용만 바꿔야 한다면 캐시 무효화 방식으로 해당 이미지만 캐시에 업데이트
- 이미지나 미디어 파일을 제외한 CSS, 자바스크립트, 폰트 등의 웹 리소스 파일들은 변경이 얼마나 자주 일어나는지에 따라 다르게 설정하되, 그 범위에서 가능한 길게 설정
- 모든 정적 파일에 대해 캐시 주기를 길게 설정하고 수동으로 캐시 주기를 관리하는 방법
- 파일 요청 시 쿼리 스트링으로 버전을 지정하는 방법
-
core.min.js?201707311505 index.js?v=201709041404 lazy_loading.js?version=1.0
- 필요할 때마다 쿼리 스트링의 버전을 바꿔주면 됨
- 고객 반응에 민감할 경우 충분히 캐시할 수 있는 정적 컨텐츠도 캐시하지 않으려 하는 경우가 있음
- 이런 경우 Cache-Control: no-store 설정보다 Cache-Control: no-cache, max-age=0 을 사용하는 것 권장
- 전자는 모든 요청에 대해 원본 서버에 항상 전체 컨텐츠를 받는 방법
- 후자는 변경이 있을 경우만 바로 캐시에 업데이트하는 방법 = 네트워크 대역폭 낭비 방지
캐시에 적합한 디렉토리 구조 구성하기
- 캐시할 수 있는 컨텐츠들을 별도 폴더에 분류해 관리
- ex) 정적 컨텐츠들을 /static 폴더 아래에 배치
- 캐시 주기별로 나누어 구성
- 같은 자바스크립트라도 라이브러리와 특정 모듈에 사용되는 자바스크립트의 캐시 주기는 다름
- 모듈에 사용하는 자바스크립트는 자주 변경, 라이브러리에 사용되는 자바스크립튼느 쉽게 변경되지 않음
-
/static/js/lib /static/js/module/A /static/js/module/B
- 동일한 파일을 여러 곳에 분산시키지 않기
- 캐시 서버 역시 제한된 메모리와 디스크 영역으로 동작하므로 필요 없는 객체들로 리소스를 낭비하지 말아야 함
캐시 키 올바르게 사용하기
- 캐시 키: 캐시 서버가 원본의 복사본을 저장하고 빠르게 조회하기 위해 사용하는 키 값
- 일반적인 캐시 키 구성
-
호스트/패스?쿼리 스트링 www.foekorea.com/kr/feo/optimization/myPic.jpg?width=200&height:100
-
아래 캐시 키들은 서로 다른 객체를 참조함 www.foekorea.com/kr/feo/optimization/myPic.jpg www.foekorea.com/jp/feo/optimization/myPic.jpg www.foekorea.com/kr/feo/optimization/myPic.jpg?width=200 www.foekorea.com/kr/feo/optimization/myPic.jpg?width=200&height=100 www.foekorea.com/kr/feo/optimization/myPic.jpg?width=200&height=200
-
- 캐시 오염과 캐시 충돌
- 캐시 오염: 원본 서버에 하나의 원본 파일만 존재하는데 캐시에 복사본이 여러 개 존재하는 것
- 캐시 충돌: 요청 URL이 하나인데 브라우저 환경에 따라 서버에서 제공하는 응답이 달라지는 것
- 캐시 오염 제거
- URL에 붙은 특정 쿼리 스트링 값이 달라지더라도 응답이 항상 같다면 캐시 키에서 쿼리 스트링을 무시하도록 설정
- 쿼리 스트링의 순서를 동일하게 정렬
- 쿼리 스트링 순서가 달라져도 캐시는 다르게 인식함
- Vary 헤더를 바르게 사용하기
- Vary 헤더가 잘못 사용되었을 때 캐시는 같은 페이지의 복사본을 여러 가지 캐시 키로 다르게 저장하기도 함
- 꼭 필요한 경우가 아니라면 Vary 헤더를 사용하지 않거나 Cache-Control: private 설정할 것을 추천
- 캐시 충돌 방지
- 주로 동적 페이지를 캐시할 때 발생
- 일부 동적 페이지에 캐시를 사용하고자 한다면 Cache-Control: private로 사용자 브라우저에만 캐시하여 페이지 로딩 시간을 단축할 수 있음
CDN 사용하기
- CDN 서비스를 사용하면 세계 여러 지역 데이터 센터들에 리버스 프록시 캐시 서버를 두고 필요한 정적 컨텐츠들을 저장해놓을 수 있음
- 사용자와 가장 가까운 캐시 서버에서 해당 컨텐츠가 서비스되므로 시간 지연 없이 빠르게 웹 페이지를 로딩할 수 있음
동적 컨텐츠 개시
- 정적 컨텐츠와 동적 컨텐츠
- 정적 컨텐츠는 한번 생성되어 좀처럼 변하지 않는 컨텐츠
- 동적 컨텐츠는 사용자 요청에 따라 서버가 바로 생성하는 컨텐츠
- 익명 컨텐츠와 개인화 컨텐츠
- 동적 컨텐츠를 좀 더 분류하면 익명 컨텐츠와 개인화 컨텐츠로 나눌 수 있음
- 익명 컨텐츠는 누구에게나 드러나는 컨텐츠
- 개인화 컨텐츠는 요청한 사용자 정보에 따라 다르게 나타나는 컨텐츠
- 시간에 민감한 컨텐츠와 둔감한 컨텐츠
- 시간에 민감한지 여부는 컨텐츠를 필요로 하는 사람이나 제공자의 비즈니스 목적에 따라 다를 수 있음
- 통상 주식 시세, 환율 정보, 경기 중계 등은 시간에 민감한 컨텐츠
- 일기 예보, 비행기나 선박 스케줄 정보 등은 시간에 둔감한 컨텐츠
- 동적 컨텐츠를 사용자에게 전달하기 위해 원본 서버에서는 두 가지 방법 이용
- 동적 정보를 쿠키에 넣어 보냄
- Ajax 요청으로 관련 정보를 동적으로 받아옴
- 요청 쿠키, 헤더 또는 쿼리 스트링에 동적 컨텐츠에 대한 정보가 있으면 이 정보들을 캐시 키에 추가함으로써 동적 컨텐츠를 캐시할 수 있음
- 보안에 주의해야 함
- 캐시 서버 용량에 유의해야 함
- Ajax 요청에 대한 응답 형태인 JSON/XML 타입 컨텐츠는 다른 정적 응답 타입과 동일한 방식으로 캐시 가능, 단지 시간에 민감한지 여부가 관건
- 캐시하고자 하는 컨텐츠의 시간에 따른 민감도를 미리 결정하고, 이에 맞게 캐시 주기를 설정
-
TTL 1-3mins : sport results, currency feed, ... TTL 0s : real time data polling (e.g. trading feed ...)
-
- 캐시는 통상 HTTP GET 방식에서 동작하므로 Ajax 요청에 대한 응답을 캐시하고자 하면 HTTP POST 방식보다 GET 방식을 사용해야 함
- 캐시 주기로 0 TTL을 사용하려면 서버에서 해당 컨텐츠에 대한 If-Modified-Since (IMS) 요청을 지원해야 함
- IMS 요청을 지원하지 않으면 캐시 서버는 모든 요청을 서버로 보내고 서버는 매 요청마다 새로운 컨텐츠로 응답하므로 캐시하지 않은 것고 동일
POST 응답 캐시
- POST 메서드를 사용하면 HTTP 페이로드에 쿼리 스트링 내용을 포함해 보내므로 데이터 크기에 제한 없음
- 일반적으로 POST 메서드에 의한 응답은 POST 요청 본문에 포함된 매개 변수들에 의해 결정
- POST 응답 내용이 보안 측면에서 공개되어도 안전한 내용이라면 이 POST 요청/응답 역시 캐시 가능
- 캐시 키에 요청 매개 변수값들이 모두 포함되어야 캐시 오염, 캐시 충돌 같은 오류 현상 방지 가능
- 캐시 키에 매개 변수값들이 노출되지 않아야 하므로 MD5 같은 해시 알고리즘을 이용해 타인이 쉽게 알 수 없도록 값을 암호화해야 함
- POST 요청/응답을 캐시하기 위해선 다음 조건들을 만족해야 함
- 매개 변수값에 항상 같은 응답이 오는 경우
- 개인 정보가 포함되지 않은 경우
- 요청 사이즈가 크지 않은 경우
고급 캐시 전략
Edge Side Include
- 첫 번째 HTML이 서버에서 브라우저까지 도달하는 시간을 Time To First Byte 라고 하며 웹 사이트 성능을 측정하는 매우 중요한 지표
- 많은 관리자들이 첫 HTML을 캐시하지 않는데, 이 HTML을 구성하는 컨텐츠 중 서버에서 동적으로 만들어내는 부분들이 존재하기 때문
- 이런 동적으로 만들어내는 부분만 따로 떼어 별도로 수행시킨 후 캐시된 나머지 부분과 다시 조합할 수 있다면 로딩 성능 개선 가능
- ESI (Edge Side Include): 인터넷 Edge에서 웹 페이지 조각을 동적으로 조합, 조립, 전달할 수 있도록 이에 대한 문법과 용도 등을 정의한 XML 기반 표준 마크업 언어
- ESI를 사용하면 한 페이지 안에 다른 페이지를 포함시킬 수 있을 뿐만 아니라 각 페이지들이 독립 객체로 취급되어 각각 다른 캐시 정책을 사용할 수 있음
- 캐시 서버는 HTML을 캐시 또는 서버에서 먼저 가져온 뒤 ESI 작성 부분을 수정하여 완벽한 HTML을 만들어 클라이언트에게 전달
HTML5 로컬 스토리지
표준안 | 연도 | 설명 | 관련기관 |
---|---|---|---|
HTML 2.0 | 1995 | IETF의 HTML Working Group이 개발함 1994년 실제 사례를 기반으로 HTML 핵심 기능들을 표준으로 개발 |
IETF |
HTML 3.2 | 1997 | 1996 동안 사용된 HTML 주요 특징들에 대한 상호 합의를 기반으로 W3C에서 처음 권고 HTML 3.2는 현재도 널리 쓰이는 테이블, 애플릿 이미지 주변의 텍스트 플로우 등의 기능들을 추가 |
W3C |
HTML 4.01 | 1999 | 추가적인 멀티미디어 옵션들, 스크립팅 언어, 스타일 시트 등 사용자 접근성을 높이는 기능들을 추가 | W3C |
XHTML 1.0 | 2000 | HTML4.01과 XML의 강점을 통합하여 새로운 표준 제시 | W3C |
HTML5 | 2014 | HTML4.01과 XHTML1.0을 대체할 새로운 표준으로 등장 | W3C, WHATWG |
- HTML5의 주요 기능
- WeSemantic Tag
- 본래 많은 양의 DIV를 통해 부여했던 Semantic을 표준 Tag로 정의해 사용하게 됨
- 머신 간 가독성 및 사용자 접근성을 향상시킴
- Web Storage
- API를 통해 세션 스토리지, 로컬 스토리지 IndexedDB를 사용할 수 있고 오프라인인 상태에서 웹 페이지 로딩 가능
- Multimedia
- 플러그인 없이 오디오와 비디오 재생 가능
- Graphics
- 그래픽을 위한 툴박스가 SVG, Canvas, WebGL, CSS3 3D 등으로 확대되어 플러그인 없이 그래픽 표현
- Device Access
- 기기의 마이크로폰, 카메라, 연착처, 이벤트 등에 네이티브 앱처럼 접근 가능
- Performance
- Web Worker를 도입해 백그라운드 프로세싱 기능과 멀티스레드를 사용해 속도 향상
- Connectivity
- Web Socket을 사용해 클라이언트와 서버 간 TCP 통신 가능
- 실시간 메시징, 푸시 알림 등 양방향 통신 구현 가능
- CSS3
- CSS3를 지원하여 유연하고, 풍성한 화면을 더욱 쉽게 구현 가능
- WeSemantic Tag
- 웹 성능과 관련해선 웹 스토리지 API 기능을 살펴볼 필요 있음
- 사용자의 주요 정보들이나 웹 리소스를 브라우저 로컬 저장소에 저장하여 재사용할 수 있음
- 스토리지는 세션이 살아있는 동안만 저장되는 세션 스토리지와 영원히 저장되는 로컬 스토리지가 존재
- 렌더링에 있어 중요한 CSS, 자바스크립트를 로컬 스토리지에 저장해놓으면 나중에 재방문할 때 로딩 속도 대폭 개선 가능
- 폰트 파일 역시 로컬 스토리지에 저장하면 폰트로 인한 사이트 로딩 지연 방지 가능
웹에 날개를 달아주는 웹 성능 최적화 기법, 강상진, 윤호성 저, 루비페이퍼 출판