World Wide Web
World Wide Web은 인터넷을 통해 식별된 자원을 연결하고 전송하며 이용할 수 있게 하는 전 세계적 분산 정보 시스템이다. 일반적으로 웹이라고 부르며, 문서와 이미지, 영상, 프로그램, 데이터와 각종 서비스를 하이퍼링크로 연결된 하나의 정보 공간으로 제공한다. 웹의 자원은 URI...
| 약칭 | WWW, W3, Web |
|---|---|
| 분류 | 분산 정보 시스템, 하이퍼텍스트, 인터넷 서비스 |
| 발명자 | 팀 버너스리 |
| 개발 기관 | CERN |
| 최초 제안 | 1989년 3월 |
| 최초 구현 | 1990년 |
| 공개 배포 | 1991년 |
| 자유 공개 | 1993년 4월 30일 |
| 핵심 식별 체계 | URI, URL |
| 핵심 통신 규약 | HTTP, HTTPS |
| 핵심 문서 형식 | HTML |
| 주요 클라이언트 | 웹 브라우저 |
| 주요 서버 | 웹 서버 |
| 표준화 단체 | W3C, WHATWG, IETF |
| 기반 네트워크 | 인터넷 |
World Wide Web은 인터넷을 통해 식별된 자원을 연결하고 전송하며 이용할 수 있게 하는 전 세계적 분산 정보 시스템이다. 일반적으로 웹이라고 부르며, 문서와 이미지, 영상, 프로그램, 데이터와 각종 서비스를 하이퍼링크로 연결된 하나의 정보 공간으로 제공한다. 웹의 자원은 URI나 URL로 식별되고, 주로 HTTP 또는 HTTPS를 통해 전송되며, 웹 브라우저가 HTML, CSS, JavaScript와 여러 미디어 형식을 해석하여 사용자에게 표시한다.
웹은 인터넷 자체와 같은 개념이 아니다. 인터넷은 여러 컴퓨터 네트워크를 연결하여 데이터를 전달하는 통신 기반 시설이고, 웹은 그 위에서 동작하는 정보 시스템이자 인터넷 서비스의 하나다. 전자우편, 파일 전송, 원격 접속과 인터넷 전화도 인터넷을 이용하지만 웹에 포함되는 것은 아니다. 다만 현대의 여러 인터넷 서비스가 웹 브라우저와 HTTP 기반 인터페이스를 제공하면서 일상에서는 웹과 인터넷이라는 표현이 서로 비슷한 의미로 사용되기도 한다.
웹은 1989년 CERN에서 근무하던 팀 버너스리가 서로 다른 컴퓨터에 흩어진 연구 정보를 연결하기 위한 인터넷 기반 하이퍼텍스트 시스템을 제안하면서 시작되었다. 그는 1990년까지 HTML, HTTP, URL의 초기 형태와 최초의 웹 브라우저 겸 편집기인 WorldWideWeb, 최초의 웹 서버인 CERN httpd를 구현하였다. CERN은 1993년 4월 30일 웹 기술을 누구나 자유롭게 사용할 수 있도록 공개하였고, 이후 웹은 학술 정보 교환 체계를 넘어 출판, 통신, 상거래, 교육, 행정, 금융, 오락과 소프트웨어 배포를 포괄하는 범용 정보 플랫폼으로 확장되었다.
초기의 웹은 서버에 저장된 문서를 내려받아 읽고 링크를 따라 이동하는 구조가 중심이었다. 이후 스타일 표현을 담당하는 CSS, 브라우저에서 프로그램을 실행하는 JavaScript, 서버 측 응용 프로그램, 데이터베이스, 멀티미디어, 실시간 통신과 다양한 웹 API가 결합되면서 웹 페이지는 상호작용하는 웹 애플리케이션으로 발전하였다. 오늘날의 웹은 정적인 문서 공간과 응용 프로그램 실행 환경, 공개 데이터 기반 시설, 대규모 서비스 배포 플랫폼이라는 성격을 함께 가진다.
역사
World Wide Web은 하나의 독립된 발명에서 갑자기 출현한 체계라기보다, 문서를 비선형적으로 연결하려는 하이퍼텍스트 연구, 서로 다른 컴퓨터를 연결한 인터넷, 네트워크 자원을 식별하고 전송하는 기술이 결합되면서 형성되었다. 초기에는 연구기관의 정보를 공유하기 위한 문서 시스템으로 출발했지만, 그래픽 웹 브라우저와 개방형 표준, 상업적 인터넷 서비스가 확산되면서 전 세계의 출판·통신·응용 프로그램 플랫폼으로 발전하였다.
웹 이전의 하이퍼텍스트
문서를 링크로 연결하고 연관된 정보를 따라 이동한다는 생각은 World Wide Web보다 오래되었다. 1945년 미국의 과학 행정가 버니바 부시는 〈As We May Think〉에서 개인이 방대한 문서와 기록을 저장하고 연관 경로를 만들어 탐색할 수 있는 가상 장치인 Memex를 제안하였다. Memex는 디지털 컴퓨터나 네트워크를 전제로 하지 않았지만, 자료를 고정된 분류 체계가 아니라 연상에 따라 연결한다는 개념을 제시하여 이후 하이퍼텍스트 연구의 선구적 구상으로 평가된다.[1]
1960년대에는 이러한 개념이 실제 컴퓨터 시스템으로 구체화되기 시작하였다. 테드 넬슨은 1965년 비순차적으로 읽고 연결할 수 있는 글쓰기 구조를 설명하면서 하이퍼텍스트라는 용어를 사용하였다. 넬슨이 추진한 Project Xanadu는 문서와 인용 관계를 전 세계적으로 연결하고 원본과 변경 이력을 추적할 수 있는 출판 시스템을 목표로 삼았다. Xanadu의 전체 구상은 웹보다 복잡했으며 널리 배포되는 완성된 시스템으로 자리 잡지는 못했지만, 전 지구적 문서 공간이라는 발상은 이후의 하이퍼미디어와 웹을 이해하는 중요한 배경이 되었다.[2]
더글러스 엥겔바트와 SRI International 연구진은 인간의 지적 작업과 협업을 컴퓨터로 확장하기 위한 NLS를 개발하였다. 1968년 공개 시연된 NLS는 하이퍼텍스트 링크, 계층적 문서, 공동 편집, 화면 창, 마우스와 원격 협업 기능을 통합하여 보여주었다. 이는 하이퍼텍스트가 단순한 문헌 관리 방식이 아니라 컴퓨터 사용자 인터페이스와 공동 작업 환경의 기반이 될 수 있음을 입증하였다.[3]
이후 브라운 대학교의 Hypertext Editing System과 FRESS, 카네기 멜런 대학교의 ZOG, Apple의 HyperCard를 비롯한 여러 하이퍼텍스트 시스템이 등장하였다. 이들 시스템은 링크를 따라 문서를 탐색하고 화면에서 정보를 조작하는 방식을 발전시켰지만, 대부분 특정 컴퓨터나 응용 프로그램, 폐쇄된 문서 집합 안에서 동작하였다. 서로 다른 운영체제와 네트워크에 존재하는 자원을 공통된 주소와 프로토콜로 연결하는 범용 체계는 아직 형성되지 않았다.[4]
CERN의 정보 관리 환경
1980년대의 CERN은 세계 여러 대학과 연구기관에서 온 과학자와 기술자가 대규모 실험을 공동으로 수행하는 국제 연구기관이었다. 연구자들은 서로 다른 시기에 프로젝트에 참여하고 떠났으며, 실험 장비와 소프트웨어, 보고서, 회의 기록과 연락처 정보는 다양한 컴퓨터와 데이터베이스에 분산되어 있었다. 컴퓨터의 제조사와 운영체제, 파일 형식, 정보 관리 프로그램도 서로 달랐기 때문에 필요한 정보가 존재하더라도 그 위치와 접근 방법을 알아내기 어려웠다.
팀 버너스리는 1980년 CERN에서 계약직 소프트웨어 기술자로 근무하면서 이러한 문제를 경험하였다. 그는 사람, 프로젝트, 소프트웨어와 문서 사이의 관계를 기록하기 위해 ENQUIRE라는 개인용 정보 관리 프로그램을 만들었다. ENQUIRE는 하나의 정보 항목을 다른 항목과 연결하고 관계의 종류를 기록할 수 있었지만, 버너스리 개인의 컴퓨터에서 사용된 실험적 시스템이었으며 CERN 전체에 배포되지는 않았다.
버너스리는 1984년 CERN에 다시 합류한 뒤 원격 프로시저 호출과 분산 시스템을 연구하였다. 당시 CERN의 정보 문제는 특정 데이터베이스를 새로 만드는 것만으로 해결하기 어려웠다. 중앙에서 모든 자료의 형식과 저장 위치를 통제하기보다, 이미 존재하는 서로 다른 시스템을 유지하면서 그 사이에 공통된 연결 구조를 제공해야 했기 때문이다.
CERN은 다양한 국가와 기관의 연구자가 공개적으로 정보를 교환하는 환경이었고, 이미 인터넷과 여러 컴퓨터 네트워크를 적극적으로 사용하고 있었다. 이러한 환경은 하이퍼텍스트, 개인용 컴퓨터와 데이터 네트워크를 결합하여 이질적인 정보 시스템을 연결한다는 구상이 발전할 수 있는 기반이 되었다. CERN은 웹이 처음부터 전 세계 일반 사용자를 위한 매체로 계획되었다기보다, 분산된 연구 공동체의 실제 정보 관리 문제를 해결하는 과정에서 형성되었다고 설명한다.[5]
1989년 최초 제안
1989년 3월 팀 버너스리는 CERN 내부의 정보 손실과 시스템 간 단절을 해결하기 위해 Information Management: A Proposal이라는 문서를 작성하였다. 이 제안은 문서, 사람, 장비, 소프트웨어와 조직을 노드로 취급하고, 노드 사이의 관계를 링크로 표현하는 분산 정보 관리 체계를 설명하였다. 특정한 계층 구조나 중앙 데이터베이스에 모든 정보를 맞추기보다, 정보가 실제로 형성되는 방식에 따라 자유롭게 연결될 수 있어야 한다는 구상이었다.
제안은 CERN의 복잡성을 조직도와 트리 구조만으로 표현하기 어렵다고 지적하였다. 실험 하나에도 여러 조직과 장비, 소프트웨어, 문서와 담당자가 얽혀 있었으며 이 관계는 시간이 지나면서 계속 변했다. 버너스리는 관계를 고정된 분류로 관리하는 대신, 임의의 정보 항목 사이에 링크를 만들 수 있는 하이퍼텍스트가 이러한 환경에 적합하다고 판단하였다.
버너스리의 상사였던 마이크 센달은 제안서에 “모호하지만 흥미롭다”는 취지의 메모를 남겼다. 이 문서는 즉시 공식 프로젝트로 승인된 것은 아니었지만, 버너스리가 구상을 발전시키고 시험할 수 있는 계기를 제공하였다.[6]
1989년 제안의 핵심은 새로운 문서 편집기 하나를 만드는 데 있지 않았다. 서로 다른 컴퓨터에 저장된 정보를 네트워크를 통해 연결하고, 사용자가 정보의 실제 저장 방식이나 서버 종류를 의식하지 않고 하나의 정보 공간처럼 탐색하게 만드는 것이었다. 이 구상을 실현하려면 모든 자원을 일관되게 식별하는 주소 체계, 서버에 자원을 요청하는 통신 규약, 링크를 포함하는 문서 형식과 이를 사용하는 클라이언트가 함께 필요했다.
1990년 5월 버너스리는 기존 제안을 수정하였고, 같은 해 11월 벨기에 출신 시스템 기술자 로베르 카이오와 함께 WorldWideWeb: Proposal for a HyperText Project를 작성하였다. 이 문서는 하이퍼텍스트를 사용자가 자유롭게 탐색할 수 있는 정보 노드의 웹으로 설명하고, CERN에 이미 존재하는 여러 서버와 데이터베이스를 하나의 사용자 인터페이스에서 접근하는 프로젝트를 제시하였다.[7]
최초의 웹 기술과 구현
버너스리는 1990년 하반기 NeXT Computer 워크스테이션을 사용하여 웹의 핵심 구성 요소를 직접 구현하였다. 이 과정에서 웹 자원의 위치를 나타내는 주소 체계, 하이퍼텍스트 문서를 표현하는 HTML, 문서를 요청하고 전송하는 HTTP가 함께 설계되었다. 이후 주소 체계의 명칭과 표준은 URI와 URL로 정리되었지만, 자원을 공통된 문자열로 식별한다는 기본 원칙은 초기 구현부터 존재하였다.
최초의 웹 브라우저는 프로젝트와 같은 이름인 WorldWideWeb이었다. 이 프로그램은 문서를 읽는 기능뿐 아니라 화면에서 문서를 직접 수정하고 링크를 만드는 편집 기능도 제공하였다. 이후 웹이라는 정보 공간과 프로그램 이름을 구분하기 위해 브라우저의 이름은 Nexus로 변경되었다.[8]
최초의 웹 서버는 버너스리의 NeXT 컴퓨터에서 실행된 CERN httpd였다. 이 컴퓨터는 실수로 전원을 끄지 않도록 서버라는 안내문이 부착된 상태로 그의 사무실에 놓였다. 서버의 주소인 info.cern.ch는 최초의 웹사이트 주소가 되었으며, 첫 웹사이트는 World Wide Web 프로젝트 자체를 설명하였다. 사이트에는 웹의 개념, 브라우저와 서버를 설치하는 방법, 서버를 만드는 방법과 당시 운영 중이던 다른 웹 서버로 연결되는 링크가 포함되었다.[9]
NeXT 전용 WorldWideWeb 브라우저만으로는 다양한 컴퓨터를 사용하는 연구자에게 웹을 보급하기 어려웠다. 버너스리와 CERN의 학생 연구원 니콜라 펠로는 문자 단말기에서도 실행할 수 있는 Line Mode Browser를 개발하였다. 이 브라우저는 그래픽 편집 기능은 제공하지 않았지만, 여러 운영체제와 단말기에서 웹 문서를 읽고 링크를 따라갈 수 있게 하였다. 웹의 초기 확산에는 고급 기능보다 서로 다른 환경에서 사용할 수 있는 이식성이 중요하게 작용하였다.
초기의 HTTP는 서버에 문서 경로를 요청하고 HTML 데이터를 반환하는 단순한 프로토콜이었다. 초기 HTML도 제목, 문단, 목록과 링크 등 연구 문서를 구조화하는 데 필요한 소수의 요소를 중심으로 구성되었다. 기능이 제한적이었던 대신 서버와 브라우저를 비교적 쉽게 구현할 수 있었으며, 기존의 FTP 자료나 뉴스, 데이터베이스를 웹을 통해 접근하도록 연결하는 게이트웨이를 만드는 것도 가능했다.
1990년 말까지 최초의 브라우저와 서버가 동작하였고, HTML·HTTP·주소 체계가 하나의 시스템으로 결합되었다. 이 시점에서 웹은 제안서의 개념을 넘어 실제로 문서를 게시하고 다른 컴퓨터에서 읽을 수 있는 작동 가능한 정보 시스템이 되었다.[10]
공개 인터넷으로의 확산
1991년 3월 웹 소프트웨어는 CERN 내부의 사용자에게 제공되기 시작하였다. 같은 해 8월 버너스리는 인터넷 뉴스그룹 alt.hypertext에 World Wide Web 프로젝트를 소개하고 브라우저, 서버와 개발용 라이브러리를 공개하였다. 이 발표를 통해 CERN 외부의 개발자와 연구기관도 웹 서버를 운영하거나 브라우저를 구현할 수 있게 되었다.[11]
1991년 12월에는 미국 스탠퍼드 선형 가속기 센터에 유럽 밖 최초의 웹 서버가 설치되었다. 이 서버는 고에너지 물리학 논문 데이터베이스인 SPIRES에 대한 접근을 제공하였다. 웹은 CERN의 내부 정보 체계를 넘어 국제적인 물리학 연구 공동체를 연결하는 도구로 확장되었으며, 이후 대학과 연구기관을 중심으로 서버 수가 증가하였다.
초기 웹은 Gopher, WAIS, FTP와 같은 기존 인터넷 정보 검색 서비스와 경쟁하거나 이들을 연결하는 위치에 있었다. Gopher는 계층적 메뉴를 통해 정보를 탐색하기 쉬웠지만, 웹은 문서 작성자가 서로 다른 서버의 자원을 자유롭게 링크할 수 있었다. HTML 문서 안에 다른 프로토콜의 자원을 가리키는 주소를 넣을 수도 있었기 때문에, 웹 브라우저는 여러 인터넷 서비스로 접근하는 통합 인터페이스 역할을 수행하였다.
웹의 확산 과정에서는 특정 기업이나 기관이 사용 허가를 통제하지 않는다는 점이 중요했다. 1993년 4월 30일 CERN은 World Wide Web 소프트웨어를 누구나 자유롭게 사용할 수 있도록 공개하였다. CERN은 이후 공개 라이선스를 통해 소프트웨어의 자유로운 사용과 수정, 재배포가 가능하다는 점을 명확히 하였다. 이 결정은 기업과 대학, 개인 개발자가 별도의 사용료나 허가 없이 브라우저와 서버를 만들고 웹사이트를 운영할 수 있는 기반을 마련하였다.[12]
같은 시기 버너스리는 CERN의 소규모 개발진만으로 웹 전체를 발전시키기 어렵다고 판단하여 인터넷을 통해 외부 개발자의 참여를 요청하였다. 여러 기관과 개인이 새로운 브라우저, 서버와 도구를 개발하면서 웹은 단일 구현이 아니라 공통된 규약을 따르는 분산 생태계로 성장하였다.
1994년에는 최초의 국제 World Wide Web 회의가 CERN에서 열렸다. 같은 해 버너스리는 미국 매사추세츠 공과대학교에 W3C를 설립하였다. W3C는 웹의 핵심 기술을 공개 표준으로 발전시키고 서로 다른 브라우저와 서버가 상호 운용되도록 조정하는 역할을 맡았다. 웹의 기술적 중심도 CERN의 단일 프로젝트에서 국제적인 표준화 공동체로 이동하기 시작하였다.
웹 브라우저의 대중화
초기의 웹 브라우저는 특정 워크스테이션에서만 실행되거나 문자 기반 인터페이스를 사용하는 경우가 많았다. ViolaWWW, Erwise, MidasWWW, Lynx 등 여러 브라우저가 개발되었지만, 웹은 주로 연구자와 대학 네트워크 사용자가 이용하는 기술로 남아 있었다.
대중화의 전환점은 미국 국립 슈퍼컴퓨팅 응용 센터에서 개발한 NCSA Mosaic이었다. 마크 앤드리슨과 에릭 비나가 중심이 되어 개발한 Mosaic은 1993년 Unix용으로 공개되었으며, 이후 Microsoft Windows와 Apple Macintosh용 버전이 제공되었다. Mosaic은 비교적 설치하기 쉬운 그래픽 인터페이스, 아이콘, 방문 기록, 북마크와 이미지 표시 기능을 제공하여 전문적인 명령줄 도구에 익숙하지 않은 사용자도 웹을 탐색할 수 있게 하였다.[13]
Mosaic이 최초의 그래픽 웹 브라우저는 아니었지만, 여러 대중적 운영체제에서 사용할 수 있었고 문서의 텍스트와 이미지를 하나의 화면에 자연스럽게 표시하였다. 1993년 말에는 매달 수천 건의 다운로드가 이루어질 정도로 빠르게 확산되었고, 웹은 학술 네트워크 밖의 언론과 기업에도 알려지기 시작하였다.
1994년 마크 앤드리슨은 실리콘 그래픽스의 창립자였던 짐 클라크와 Mosaic Communications를 설립하였다. 회사 이름은 이후 Netscape Communications로 변경되었고, 같은 해 Netscape Navigator가 공개되었다. Navigator는 빠른 렌더링과 상업적 지원, 개인 사용자에게 무료로 배포하는 전략을 통해 1990년대 중반의 대표적인 웹 브라우저가 되었다.
Microsoft는 1995년 Windows 95용 추가 패키지에 Internet Explorer를 포함하였고, 이후 브라우저를 Windows에 기본 구성 요소로 통합하였다. Netscape와 Microsoft는 새로운 HTML 요소, 스크립트 기능과 사용자 인터페이스를 경쟁적으로 추가하였다. 이른바 브라우저 전쟁은 웹 기술의 빠른 발전과 보급을 촉진했지만, 특정 브라우저에서만 작동하는 비표준 웹사이트와 구현 간 호환성 문제도 확대하였다.
1990년대 후반 Internet Explorer는 Windows와의 결합을 바탕으로 시장 점유율을 확대하였고 1998년경 Netscape를 추월하였다. Netscape는 브라우저 소스 코드를 공개하여 Mozilla 프로젝트의 기반을 마련했으며, 이 계통은 이후 Firefox로 이어졌다. 브라우저 경쟁은 웹이 하나의 프로그램이나 회사가 소유한 서비스가 아니라 여러 구현체가 동일한 공개 기술을 해석하는 플랫폼이라는 점을 지속적으로 드러냈다.[14]
상업화와 닷컴 시대
1990년대 초까지 인터넷의 상업적 이용에는 여러 제약이 있었지만, 상업 인터넷 서비스 제공자와 민간 네트워크가 성장하고 1995년 미국의 NSFNET 백본이 종료되면서 인터넷의 중심은 학술·정부 네트워크에서 민간 통신망으로 이동하였다. 웹 브라우저를 설치한 개인용 컴퓨터가 보급되면서 기업은 웹사이트를 새로운 홍보, 판매와 고객 지원 채널로 보기 시작하였다.
초기 기업 웹사이트는 회사 정보와 제품 목록을 제공하는 전자 브로슈어에 가까웠다. 그러나 웹 폼, 서버 측 프로그램과 데이터베이스가 결합되면서 사용자가 상품을 검색하고 주문하거나 계정 정보를 조회하는 서비스가 가능해졌다. SSL과 이후 TLS를 이용한 암호화 통신은 신용카드 정보와 인증 데이터를 전송하는 전자 상거래의 기술적 기반이 되었다.
1994년에는 Yahoo!의 전신인 웹 디렉터리와 Amazon, 여러 온라인 서비스가 등장하였고, 1995년에는 eBay가 서비스를 시작하였다. 검색 엔진, 웹 포털, 온라인 광고, 전자 상거래와 호스팅 서비스가 새로운 산업 분야로 성장하였다. 웹사이트의 수가 급증하면서 사람이 분류한 디렉터리만으로 정보를 찾기 어려워졌고, AltaVista, Google과 같은 자동화된 검색 엔진이 웹 크롤링과 색인, 링크 분석을 중심으로 발전하였다.
1995년 Netscape의 기업 공개는 웹 기반 기업에 대한 투자 열기를 크게 높인 사건으로 평가된다. Netscape는 개인에게 브라우저를 무료로 제공하면서 기업용 서버와 라이선스, 지원 서비스로 수익을 얻는 전략을 사용하였다. 공개 표준에 기반한 소프트웨어도 대규모 상업 시장을 형성할 수 있다는 가능성이 확인되면서 수많은 인터넷 기업이 설립되었다.[15]
1990년대 후반에는 기업 이름에 .com을 붙인 신생 회사가 빠르게 증가하였고, 실제 수익이나 지속 가능한 사업 구조보다 사용자 수와 성장 가능성을 중심으로 높은 평가를 받는 경우가 많았다. 통신 사업자도 웹 트래픽의 증가를 예상하여 광섬유와 데이터 센터, 서버 인프라에 대규모로 투자하였다.
2000년을 전후하여 투자 기대를 충족하지 못한 기업들이 폐업하거나 가치가 급락하면서 닷컴 버블이 붕괴하였다. 그러나 웹 자체의 이용과 전자 상거래가 사라진 것은 아니었다. 생존한 기업은 검색, 광고, 온라인 소매, 결제와 클라우드 기반 서비스의 기반을 확립하였고, 버블 기간에 구축된 네트워크와 서버 인프라는 이후 웹 서비스 성장에 활용되었다.
웹의 상업화는 일반 사용자가 더 많은 콘텐츠와 서비스를 이용하게 했지만, 광고와 사용자 추적, 대형 플랫폼의 시장 지배력, 도메인 이름 분쟁과 저작권 문제도 함께 확대하였다. 웹은 학술 정보 공유 도구에서 세계 경제의 주요 거래·유통 기반으로 변화하였다.
동적 웹과 웹 애플리케이션
초기 웹 페이지는 서버에 저장된 HTML 파일을 브라우저가 내려받아 표시하는 정적 문서가 중심이었다. 내용이 바뀌려면 작성자가 파일을 직접 수정해야 했으며, 사용자마다 다른 결과를 제공하거나 입력을 처리하는 기능은 제한적이었다.
서버 측에서는 CGI가 웹 서버와 외부 프로그램을 연결하는 공통 방식을 제공하였다. CGI 프로그램은 폼으로 전달된 사용자 입력을 처리하고 데이터베이스를 조회하여 그 결과로 HTML 문서를 생성할 수 있었다. 이후 Perl, PHP, ASP, Java Servlet, JavaServer Pages와 여러 웹 프레임워크가 등장하면서 게시판, 웹메일, 검색, 쇼핑몰과 콘텐츠 관리 시스템을 구현하기 쉬워졌다.
클라이언트 측에서는 1995년 Netscape의 브렌던 아이크가 개발한 JavaScript가 Navigator에 도입되었다. JavaScript는 서버에 새로운 문서를 요청하지 않고도 사용자 입력에 반응하고 문서 내용을 변경하는 기능을 제공하였다. Microsoft는 Internet Explorer에 JScript라는 호환 구현을 추가하였고, 1997년 Ecma International은 언어의 표준 기반인 ECMAScript를 발행하였다.[16]
문서의 구조와 표현도 분리되기 시작하였다. CSS는 1994년 호콘 비움 리가 처음 제안하였고 1996년 CSS Level 1이 W3C 권고안으로 발표되었다. CSS는 문서 구조를 나타내는 HTML과 글꼴, 색상, 배치 같은 시각적 표현을 분리하여 웹사이트 전체의 디자인을 일관되게 관리할 수 있게 하였다.[17]
JavaScript가 HTML 문서의 요소를 일관되게 읽고 변경하려면 공통 객체 모델이 필요했다. 브라우저마다 서로 다른 방식으로 제공되던 문서 조작 기능은 DOM 표준으로 정리되었다. HTML, CSS, JavaScript와 DOM의 결합은 문서를 표시하는 웹에서 프로그램이 실행되는 웹으로 이동하는 기반이 되었다.
1990년대 후반에는 이러한 기능을 묶어 Dynamic HTML 또는 DHTML이라고 불렀다. 그러나 Netscape와 Internet Explorer가 서로 다른 객체 모델과 비표준 기능을 제공하여 같은 코드를 여러 브라우저에서 실행하기 어려웠다. 개발자는 브라우저 종류를 감지하여 서로 다른 코드를 실행하거나 특정 브라우저만 지원해야 했다.
2000년대에는 표준 지원이 개선되고 JavaScript 라이브러리가 브라우저 차이를 추상화하면서 웹 인터페이스가 복잡해졌다. 웹메일과 지도 서비스는 브라우저가 서버와 백그라운드에서 데이터를 교환하고 화면의 일부만 갱신하는 방식을 널리 사용하였다. 2005년 이러한 개발 방식에 Ajax라는 이름이 붙으면서 전체 페이지를 다시 불러오지 않는 응답성 높은 웹 애플리케이션이 빠르게 확산되었다.
블로그, 위키, 소셜 네트워크, 동영상 공유와 사용자 참여형 서비스의 성장은 흔히 Web 2.0이라는 표현으로 묶였다. 이는 웹 프로토콜의 공식 버전을 뜻하는 것이 아니라, 운영자가 제공하는 정적인 페이지를 읽는 구조에서 사용자가 콘텐츠를 작성하고 관계를 형성하며 데이터를 지속적으로 교환하는 서비스 구조로의 변화를 가리켰다.
웹 애플리케이션이 복잡해지면서 서버는 HTML 전체를 생성하는 역할뿐 아니라 JSON이나 XML 형식의 데이터를 제공하는 API 서버 역할을 맡게 되었다. 브라우저에서는 프레임워크가 화면 상태, 라우팅과 서버 통신을 관리하였고, 단일 페이지 애플리케이션과 클라이언트 측 렌더링 방식이 확산되었다. 동시에 초기 화면 표시와 검색 접근성, 성능을 개선하기 위해 서버 측 렌더링과 정적 생성 방식도 함께 발전하였다.
오늘날 HTML 표준은 짧은 정적 문서부터 멀티미디어가 포함된 보고서와 완전한 대화형 응용 프로그램까지 같은 문서 모델 안에서 다룬다. 웹은 문서를 연결하는 체계를 유지하면서도 저장소, 백그라운드 작업, 실시간 통신, 그래픽, 오디오·비디오와 장치 접근을 제공하는 응용 프로그램 플랫폼으로 확장되었다.[18]
모바일 웹과 현대 웹 플랫폼
휴대전화에서 인터넷 정보를 제공하려는 시도는 스마트폰의 대중화 이전부터 존재하였다. 1990년대 후반에는 WAP과 WML을 사용하는 이동통신사 중심의 서비스가 등장하였다. 이러한 서비스는 작은 화면, 제한된 메모리와 낮은 전송 속도에 맞추어 단순화된 콘텐츠를 제공했지만, 데스크톱 웹과 별도의 문서 형식과 서비스 생태계를 사용하는 경우가 많았다.
1999년 일본 NTT 도코모가 시작한 i-mode는 뉴스, 전자우편, 게임, 지도, 결제와 쇼핑을 휴대전화에서 제공하며 모바일 인터넷 서비스를 대중화하였다. i-mode는 수천만 명의 이용자에게 모바일 정보 서비스와 결제를 보급했지만, 이동통신사가 관리하는 전용 플랫폼이라는 성격도 강하였다.[19]
2000년대에는 BlackBerry, Symbian, Palm 기반 스마트폰과 PDA에서 웹 브라우저가 제공되었지만, 작은 화면과 물리 키보드, 제한된 브라우저 기능 때문에 데스크톱 웹사이트를 그대로 이용하기 어려웠다. 많은 사이트는 별도의 모바일 주소와 축소된 페이지를 제공하였다.
2007년 출시된 iPhone은 데스크톱 웹 기술을 해석하는 브라우저와 멀티터치 인터페이스를 결합하여 일반 사용자가 휴대전화에서 완전한 웹 페이지를 탐색하는 경험을 대중화하였다. 이후 Android 기기와 고속 이동통신망이 확산되면서 모바일 기기는 웹 이용의 부차적인 단말기가 아니라 주요 접근 환경으로 변화하였다.[20]
초기에는 데스크톱용 사이트와 모바일용 사이트를 별도로 운영하는 방식이 일반적이었다. 그러나 화면 크기와 장치 종류가 다양해지면서 하나의 문서가 환경에 따라 배치와 크기를 조정하는 반응형 웹 디자인이 확산되었다. CSS 미디어 쿼리, 유동적인 격자와 크기가 조절되는 이미지가 결합되어 같은 URL과 콘텐츠를 여러 화면에서 사용할 수 있게 되었다.
동시에 플러그인 의존성은 감소하였다. 1990년대와 2000년대에는 Adobe Flash, Java 애플릿과 브라우저 플러그인이 애니메이션, 영상, 게임과 복잡한 응용 프로그램을 제공했지만, 모바일 환경에서는 성능, 전력 소비, 보안과 호환성 문제가 커졌다. HTML의 canvas, audio, video 요소와 CSS 애니메이션, JavaScript API가 발전하면서 브라우저 자체가 플러그인의 기능을 대체하기 시작하였다.
HTML5는 웹 문서와 응용 프로그램에 필요한 의미론적 요소, 멀티미디어, 그래픽과 여러 API를 하나의 개방형 플랫폼으로 정리하려는 흐름을 대표하였다. W3C는 2014년 10월 HTML5를 권고안으로 발표하였으며, 다양한 기기에서 풍부한 웹 애플리케이션을 구현하는 기반으로 설명하였다.[21]
웹 표준의 개발 방식도 변화하였다. 브라우저 개발사들이 2004년 설립한 WHATWG는 실제 구현과 지속적인 개선을 중심으로 HTML을 발전시켰고, HTML은 특정 시점마다 완결된 버전을 발표하는 방식에서 계속 갱신되는 Living Standard 방식으로 이동하였다. 현대의 웹 플랫폼은 HTML 하나가 아니라 CSS, ECMAScript, DOM, URL, Fetch, Streams, WebSocket, WebRTC, WebGL, WebAssembly와 수많은 API가 결합된 체계로 구성된다.
Service Worker, 웹 앱 매니페스트와 브라우저 저장소를 사용하는 프로그레시브 웹 애플리케이션은 웹사이트가 오프라인 캐시, 백그라운드 처리, 알림과 홈 화면 설치 같은 기능을 제공할 수 있게 하였다. 웹 애플리케이션과 운영체제에 설치되는 네이티브 애플리케이션의 경계는 점차 흐려졌으며, 일부 서비스는 같은 웹 기술을 데스크톱과 모바일 애플리케이션으로 패키징하여 배포한다.
WebAssembly는 C, C++, Rust와 같은 언어로 작성된 프로그램을 브라우저에서 비교적 효율적으로 실행할 수 있는 이식 가능한 명령 형식을 제공하였다. 이를 통해 게임 엔진, 영상·음성 처리, 설계 도구, 에뮬레이터와 기존 데스크톱 소프트웨어의 일부가 웹으로 확장되었다. WebGL과 WebGPU 같은 그래픽 API도 브라우저를 고성능 시각화와 3차원 응용 프로그램의 실행 환경으로 발전시켰다.
현대 웹은 모바일과 데스크톱뿐 아니라 텔레비전, 자동차, 전자책 단말기, 웨어러블 기기와 임베디드 시스템에서도 사용된다. 웹 브라우저에서 직접 표시되는 페이지 외에도, 모바일 앱과 서버 사이의 HTTP API, 하이브리드 앱, 설치형 데스크톱 앱과 클라우드 서비스의 사용자 인터페이스가 웹 기술을 기반으로 구축된다.
이러한 발전에도 웹의 기본 구조는 초기 설계와 이어져 있다. 자원은 URL로 식별되고, 클라이언트는 네트워크를 통해 자원을 요청하며, 문서와 응용 프로그램은 다른 자원으로 연결된다. 현대 웹 플랫폼은 이 단순한 구조 위에 실행 환경과 보안 경계, 저장소, 멀티미디어와 장치 API를 축적함으로써 범용 소프트웨어 배포 기반으로 발전하였다.
명칭과 범위
World Wide Web은 처음에는 인터넷에 연결된 문서와 정보 시스템을 하이퍼텍스트로 통합하기 위한 프로젝트의 이름이었지만, 이후 문서·미디어·데이터·응용 프로그램과 서비스를 포괄하는 전 세계적 정보 공간을 가리키게 되었다. 웹을 구성하는 대상을 어디까지 포함하는지는 문맥에 따라 달라진다. 좁은 의미에서는 HTTP를 통해 접근하는 상호 연결된 문서 집합을 뜻하고, 넓은 의미에서는 URI로 식별되고 웹 표준을 통해 상호작용하는 자원과 서비스 전체를 포함한다.
웹의 범위를 구분할 때는 여러 기준이 함께 사용된다. 사람이 읽는 단일 문서인지 여러 문서가 결합된 사이트인지, 정적인 표현물인지 프로그램 사이의 서비스인지, 누구나 접근할 수 있는지 인증된 사용자만 접근할 수 있는지, 일반 검색 엔진에 색인되는지 여부에 따라 서로 다른 용어가 적용된다. 이러한 구분은 서로 완전히 배타적이지 않으며 하나의 대상이 여러 범주에 동시에 속할 수 있다.
World Wide Web과 Web
World Wide Web은 일반적으로 WWW, W3 또는 Web으로 줄여 부른다. 한국어에서는 주로 월드 와이드 웹 또는 웹이라고 한다. 초기 문서에서는 World-Wide Web처럼 단어 사이에 하이픈을 넣은 표기도 사용되었지만, 이후에는 World Wide Web이 일반적인 정식 명칭으로 자리 잡았다.
명칭의 World Wide는 하나의 중앙 서버나 조직 안에 제한되지 않고 전 세계의 컴퓨터와 정보 시스템을 연결한다는 범위를 나타낸다. Web은 문서와 자원이 하이퍼링크를 통해 그물처럼 서로 연결되는 구조를 비유한 표현이다. 사용자는 하나의 고정된 계층이나 정해진 탐색 순서를 따르지 않고, 링크를 선택하여 여러 서버와 문서 사이를 이동할 수 있다.
초기 CERN 문서는 World Wide Web을 넓은 영역의 하이퍼미디어 정보 검색 계획으로 설명하였으며, 인터넷에서 이용할 수 있는 온라인 정보를 하나의 연속적이고 탐색 가능한 공간처럼 바라보는 방식으로 소개하였다.[22] 이후 W3C의 웹 아키텍처는 웹을 URI로 식별되는 자원과 이들 사이의 상호작용 및 표현으로 구성된 정보 시스템으로 설명한다.[23]
Web이라는 짧은 표현은 대체로 World Wide Web 전체를 뜻하지만, 문맥에 따라 웹 기술, 웹 기반 서비스, 웹 브라우저로 접근하는 환경 또는 특정 조직의 웹사이트 생태계를 가리킬 수도 있다. 예를 들어 웹 개발은 웹 전체를 개발한다는 의미가 아니라 HTML, CSS, JavaScript, HTTP와 서버 기술을 이용해 웹사이트나 웹 애플리케이션을 만드는 활동을 뜻한다.
웹은 인터넷과 같은 개념이 아니다. 인터넷은 서로 다른 네트워크 사이에서 패킷을 전달하는 전 세계적 네트워크 기반 시설이고, 웹은 그 위에서 작동하는 여러 응용 체계 가운데 하나다. 전자우편, SSH, 인터넷 전화와 일부 P2P 통신은 인터넷을 사용하지만 반드시 웹을 사용하지는 않는다. 반대로 웹 페이지나 웹 애플리케이션은 일반적으로 인터넷 또는 조직 내부의 IP 네트워크와 HTTP 계열 프로토콜에 의존한다.
일상에서는 브라우저를 열고 인터넷 서비스를 이용하는 행위를 모두 “웹을 한다” 또는 “인터넷을 한다”고 표현하기 때문에 두 용어가 혼용된다. 그러나 기술적으로는 웹 브라우저로 표시되는 서비스의 범위와 인터넷이 제공하는 전체 통신 기능의 범위를 구분할 필요가 있다.
웹 페이지와 웹사이트
웹 페이지는 웹 브라우저에서 하나의 문서 또는 하나의 화면 단위로 표현되는 웹 자원이다. 전통적인 웹 페이지는 하나의 HTML 문서를 중심으로 구성되며, CSS, JavaScript, 이미지, 글꼴, 영상과 다른 자원을 추가로 불러온다. 사용자가 보는 하나의 페이지가 여러 서버에서 전달된 수십 개 또는 수백 개의 자원을 조합하여 만들어질 수도 있다.
웹 페이지는 보통 고유한 URL을 가진다. 같은 URL에서 사용자 계정, 언어, 기기, 요청 헤더와 시간에 따라 다른 내용이 생성될 수도 있으므로 URL 하나가 항상 고정된 파일 하나에 대응하는 것은 아니다. 반대로 단일 페이지 애플리케이션에서는 여러 화면과 상태가 하나의 기본 HTML 문서와 URL 체계 안에서 동적으로 구성될 수 있다.
웹사이트는 공통된 목적, 소유 주체, 디자인, 탐색 구조 또는 도메인 아래에서 제공되는 여러 웹 페이지와 관련 자원의 집합이다. 개인 블로그, 기업 홈페이지, 뉴스 사이트, 온라인 상점, 위키와 검색 엔진이 모두 웹사이트에 포함될 수 있다. 웹사이트는 하나의 웹 서버에서 제공될 수도 있지만, 실제로는 여러 데이터 센터와 콘텐츠 전송 네트워크, API 서버, 저장소와 외부 서비스에 분산될 수 있다.
웹사이트와 도메인 이름은 일대일로 대응하지 않는다. 하나의 도메인에서 여러 사이트나 애플리케이션을 제공할 수 있고, 하나의 사이트가 여러 도메인과 하위 도메인을 사용할 수도 있다. 같은 사이트의 정적 파일, 사용자 업로드, API와 인증 시스템이 서로 다른 호스트 이름에 배치되는 경우도 일반적이다.
홈페이지는 원래 웹 브라우저가 시작할 때 표시하는 문서 또는 웹사이트의 대표 시작 페이지를 뜻한다. 한국어의 일상적 용법에서는 웹사이트 전체를 홈페이지라고 부르기도 하지만, 기술 문맥에서는 사이트 전체와 첫 페이지를 구분하는 편이 정확하다. 사이트의 첫 페이지는 보통 루트 URL이나 대표 경로에서 제공되며 다른 페이지로 이동할 수 있는 탐색 구조를 포함한다.
웹 페이지는 반드시 사람이 읽는 전통적인 문서 형태일 필요가 없다. 지도, 게임, 편집기, 대시보드와 메신저처럼 화면 대부분이 프로그램에 의해 실시간으로 생성되는 웹 애플리케이션도 브라우저 안에서는 웹 페이지의 문서 및 실행 환경을 사용한다. 이 때문에 현대의 웹 페이지는 문서와 응용 프로그램 화면의 성격을 동시에 가질 수 있다.
웹 서버는 웹사이트를 구성하는 HTML 문서와 이미지, 스타일시트, 스크립트 등의 파일을 저장하거나 요청에 따라 생성하여 클라이언트에 전달한다. 그러나 웹사이트 자체는 물리적인 서버 한 대를 의미하지 않으며, 사용자에게 제공되는 콘텐츠와 기능, 주소 및 탐색 구조의 논리적 집합을 뜻한다.[24]
웹 자원과 웹 서비스
웹 자원은 웹에서 식별할 수 있는 대상을 포괄적으로 가리킨다. HTML 문서와 이미지, CSS 파일, JavaScript 모듈, 영상, 글꼴, JSON 데이터와 다운로드 파일뿐 아니라 사람, 장소, 개념, 데이터 집합 또는 변화하는 서비스 상태처럼 하나의 고정된 파일로 환원되지 않는 대상도 자원으로 모델링할 수 있다.
웹 아키텍처에서 자원의 핵심 조건은 특정한 저장 형식이 아니라 URI로 식별된다는 점이다. 클라이언트는 URI를 사용하여 자원과 상호작용하고, 서버는 그 자원을 나타내는 표현을 반환한다. 같은 자원이 요청 조건에 따라 HTML, JSON, XML, 이미지 또는 서로 다른 언어의 표현으로 제공될 수 있다.
자원과 표현은 구분된다. 예를 들어 특정 인물이나 오늘의 날씨라는 자원은 그 자체가 전송되는 것이 아니라, 해당 자원을 설명하는 HTML 문서나 JSON 데이터가 네트워크를 통해 전달된다. 한 자원의 상태가 변경되면 같은 URI에서 반환되는 표현의 내용도 달라질 수 있다. 웹 아키텍처는 이러한 구조를 식별, 상호작용과 표현이라는 세 요소를 중심으로 설명한다.[25]
웹 서비스는 다른 소프트웨어가 네트워크를 통해 기능이나 데이터에 접근하도록 제공되는 소프트웨어 시스템을 뜻한다. 전통적인 W3C 정의에서 웹 서비스는 기계가 처리할 수 있는 형식으로 인터페이스가 기술되고, 다른 시스템과 상호 운용 가능한 기계 대 기계 통신을 수행하는 시스템이다.[26]
2000년대 초의 좁은 의미에서 웹 서비스는 주로 SOAP, WSDL과 XML 기반 메시지를 사용하는 체계를 가리켰다. 이후에는 HTTP와 URI를 사용하여 JSON이나 다른 표현을 교환하는 REST 방식의 API가 널리 보급되면서, 웹 API와 웹 서비스라는 표현이 더 넓은 의미로 사용되기 시작하였다.
웹사이트가 주로 사람에게 정보와 사용자 인터페이스를 제공한다면, 웹 서비스는 주로 프로그램이 사용할 수 있는 인터페이스를 제공한다. 그러나 두 범위는 분리되어 있지 않다. 하나의 웹 애플리케이션은 브라우저용 페이지와 모바일 앱용 API를 함께 제공할 수 있고, 공개 API의 설명서와 관리 화면 자체가 웹사이트로 제공될 수도 있다.
웹 서비스라고 해서 반드시 공개되어 있거나 누구나 사용할 수 있는 것은 아니다. 인증 키, 사용자 계정, 조직 내부 네트워크 또는 계약 관계를 통해 접근이 제한될 수 있다. 또한 HTTP를 사용하는 모든 서버 기능이 독립된 웹 서비스로 불리는 것도 아니다. 일반적으로 다른 소프트웨어가 재사용할 수 있는 명시적 인터페이스를 제공할 때 웹 서비스 또는 웹 API라고 부른다.
공개 웹과 비공개 웹
공개 웹은 특별한 조직 내부 권한이나 개인 계정 없이 일반 인터넷 사용자가 접근할 수 있도록 공개된 웹 자원과 서비스의 범위를 뜻한다. 공개 웹사이트는 보통 외부 인터넷에서 연결할 수 있는 서버에 배치되고, 사용자는 일반 웹 브라우저와 URL을 통해 접근한다.
공개 웹이라는 표현은 무료 이용을 뜻하지 않는다. 유료 구독이나 일회성 결제를 요구하는 사이트도 인터넷에 공개적으로 연결되어 있다면 공개 웹의 일부로 볼 수 있다. 다만 결제 이후에만 열리는 본문이나 계정별 데이터는 접근이 제한되므로 공개 영역과 비공개 영역이 한 사이트 안에 함께 존재할 수 있다.
비공개 웹은 접근 권한이 특정 사용자, 조직, 네트워크 또는 시스템으로 제한된 웹 자원을 뜻한다. 기업과 학교 내부의 인트라넷, 관리자 화면, 개인 웹메일, 클라우드 저장소, 인터넷 뱅킹 계정, 비공개 문서와 개발 중인 서비스가 여기에 포함될 수 있다.
비공개 웹도 일반적인 웹 기술을 사용한다. 브라우저, URL, HTTP, HTML과 JavaScript를 그대로 사용하면서 로그인, 접근 제어, VPN, 클라이언트 인증서, IP 주소 제한 또는 방화벽으로 접근 대상을 제한한다. 따라서 공개 웹과 비공개 웹의 차이는 사용하는 핵심 기술보다 누가 어떤 조건으로 접근할 수 있는지에 있다.
하나의 웹사이트가 완전히 공개되거나 완전히 비공개일 필요는 없다. 뉴스 사이트는 첫 화면과 일부 기사를 공개하면서 구독자 전용 기사를 제한할 수 있고, 소셜 네트워크는 공개 프로필과 비공개 메시지를 함께 제공할 수 있다. 기업 서비스도 공개된 제품 설명서, 고객 계정, 직원 전용 관리 도구를 같은 플랫폼에서 운영할 수 있다.
공개 여부는 검색 엔진 색인 여부와 동일하지 않다. 로그인 없이 접근 가능한 페이지라도 검색 엔진에 알려지지 않았거나 크롤링이 제한되면 색인되지 않을 수 있다. 반대로 검색 결과에는 로그인 페이지나 제한된 자료의 제목과 설명만 나타나고 실제 본문은 인증 이후에만 제공될 수 있다.
또한 공개 웹은 공공 웹이나 오픈 데이터와도 구분된다. 일반인이 읽을 수 있는 페이지라고 해서 내용을 자유롭게 복제하거나 수정·재배포할 수 있는 것은 아니다. 접근 가능성, 저작권과 라이선스, 데이터 재사용 권한은 서로 다른 조건이다.
표면 웹과 딥 웹
표면 웹은 일반적인 검색 엔진의 웹 크롤러가 발견하고 색인하여 검색 결과로 제공할 수 있는 웹 영역을 뜻한다. 가시 웹, 색인 웹 또는 Surface Web이라고도 한다. 다른 공개 페이지에서 연결된 링크를 따라 접근할 수 있고, 검색 엔진이 읽을 수 있는 문서가 대표적인 표면 웹에 해당한다.
표면 웹의 범위는 고정되어 있지 않다. 검색 엔진마다 크롤링 대상, 색인 정책, 지원 형식과 갱신 주기가 다르기 때문에 한 검색 엔진에서는 발견되는 페이지가 다른 검색 엔진에서는 나타나지 않을 수 있다. 페이지가 새로 생성되거나 삭제되고, 링크 구조와 접근 정책이 바뀌면서 표면 웹에 포함되는 범위도 계속 변한다.
딥 웹은 일반적인 검색 엔진의 표준적인 크롤링과 색인 과정으로는 내용이 검색되지 않는 웹 영역을 뜻한다. 보이지 않는 웹, 비가시 웹, 숨은 웹 또는 Deep Web이라고도 한다. 이 용어는 접근 권한이나 불법성보다 검색 엔진의 발견 및 색인 가능성을 기준으로 한 분류다.
딥 웹에는 로그인 이후의 개인 계정 페이지, 웹메일, 인터넷 뱅킹, 유료 구독 자료, 조직 내부 문서와 클라우드 저장소가 포함될 수 있다. 검색 폼에 값을 입력해야 생성되는 데이터베이스 결과, 링크가 연결되지 않은 페이지, 크롤러 접근이 제한된 자료와 일시적으로 생성되는 화면도 검색 엔진이 직접 색인하지 못하면 딥 웹에 속할 수 있다.
딥 웹의 상당 부분은 일상적인 합법적 서비스와 개인정보로 구성된다. 사용자의 메일함과 비공개 파일, 병원이나 학교의 업무 시스템, 기업 내부 데이터베이스가 검색 엔진에 노출되지 않는 것은 서비스가 정상적으로 접근 권한을 적용한 결과다. 따라서 딥 웹 자체를 범죄나 익명 네트워크와 동일하게 보는 것은 범위를 지나치게 좁히는 해석이다.
다크 웹은 딥 웹과 같은 개념이 아니다. 다크 웹은 일반 브라우저와 공개 DNS만으로 접근하기 어렵고, Tor, I2P와 같은 특정 네트워크나 별도 소프트웨어 및 설정을 사용하도록 의도적으로 은닉된 서비스의 범위를 가리킨다. 다크 웹은 딥 웹의 일부로 분류될 수 있지만, 딥 웹 전체가 다크 웹인 것은 아니다.
공개 웹·비공개 웹의 구분과 표면 웹·딥 웹의 구분도 서로 다른 축에 놓인다. 공개된 페이지라도 검색 엔진이 발견하지 못하면 딥 웹에 속할 수 있고, 접근이 제한된 서비스의 로그인 안내 페이지는 표면 웹에 색인될 수 있다. 공개 여부는 누가 접근할 수 있는가를 중심으로 하고, 표면·딥 웹의 구분은 검색 엔진이 내용을 발견하고 색인할 수 있는가를 중심으로 한다.
딥 웹의 규모를 정확한 비율로 나타내기는 어렵다. 데이터베이스에서 요청에 따라 생성할 수 있는 페이지의 수는 사실상 무한에 가까울 수 있고, 사용자별 비공개 자료와 실시간 데이터는 일반 웹 페이지처럼 단순히 개수를 셀 수 없다. 2001년 Michael K. Bergman의 연구는 당시 검색 엔진이 접근하지 못한 데이터베이스 중심의 웹을 설명하며 Deep Web이라는 용어를 널리 알렸지만, 그 연구에서 제시한 규모 추정치는 조사 방식과 웹의 변화 때문에 현대 웹에 그대로 적용하기 어렵다.[27]
따라서 표면 웹과 딥 웹은 인터넷 전체를 물리적으로 분할한 별개의 네트워크가 아니다. 둘 다 같은 웹 기술과 인터넷 기반 시설을 사용할 수 있으며, 검색 엔진의 발견 방식, 사이트의 링크 구조, 인증과 접근 정책에 따라 구분되는 논리적 범주다.
인터넷과의 관계
World Wide Web은 인터넷 위에서 동작하는 응용 계층의 정보 시스템이다. 인터넷이 서로 독립적으로 운영되는 네트워크와 컴퓨터 사이에서 데이터를 전달하는 공통 기반을 제공한다면, 웹은 그 기반을 이용하여 자원을 식별하고 요청하며 표현을 교환하고 하이퍼링크로 연결한다.
웹과 인터넷은 긴밀하게 결합되어 있지만 동일한 체계는 아니다. 인터넷은 웹이 등장하기 전부터 전자우편, 파일 전송, 원격 접속과 뉴스 그룹 같은 여러 서비스를 제공하고 있었으며, 웹이 아닌 응용 프로토콜도 계속 사용된다. 반대로 웹은 인터넷뿐 아니라 조직 내부의 사설 IP 네트워크에서도 운영될 수 있다. 따라서 웹은 인터넷의 대표적인 활용 분야이지만 인터넷 전체를 구성하거나 대체하지는 않는다.
인터넷 기반 시설
인터넷은 하나의 기업이나 서버가 운영하는 단일 네트워크가 아니라, 서로 독립적으로 관리되는 수많은 네트워크가 공통 프로토콜을 사용하여 연결된 네트워크의 네트워크다. 인터넷에 참여하는 통신사, 연구기관, 기업, 정부기관과 개인 네트워크는 각자의 장비와 운영 정책을 유지하면서 다른 네트워크와 패킷을 교환한다.
인터넷의 기본 전송 단위는 패킷이다. 송신 측에서 생성된 데이터는 여러 패킷으로 나뉘어 네트워크를 통과하며, 각 패킷은 목적지 주소에 따라 여러 라우터를 거쳐 전달된다. 특정 통신 경로를 통화가 끝날 때까지 전용으로 확보하는 전통적인 회선 교환과 달리, 패킷 교환 네트워크에서는 여러 통신이 같은 링크의 전송 용량을 공유할 수 있다.
IP는 서로 다른 종류의 물리 네트워크 위에서 패킷을 전달하기 위한 공통 계층을 제공한다. 유선 Ethernet, 광섬유 통신망, Wi-Fi, 이동통신망, 위성망과 데이터 센터 내부 네트워크는 물리적 구성과 링크 기술이 서로 다르지만, 상위 계층에서 IP 패킷을 전달함으로써 하나의 인터넷에 참여할 수 있다. Internet Society는 공통된 인터넷 프로토콜과 패킷 교환 인터페이스가 이질적인 네트워크를 상호 연결하는 인터넷의 핵심 속성이라고 설명한다.[28]
현재 인터넷에서는 IPv4와 IPv6가 함께 사용된다. IP는 패킷을 출발지에서 목적지까지 전달하려고 시도하지만, 패킷이 반드시 도착하거나 순서대로 전달된다고 보장하지는 않는다. 이러한 특성 위에서 TCP, UDP, QUIC과 같은 전송 프로토콜이 응용 프로그램의 요구에 맞는 통신 기능을 제공한다.
라우터는 서로 다른 네트워크 사이에서 패킷의 다음 전달 경로를 결정한다. 인터넷 서비스 제공자와 대규모 조직은 하나 이상의 자율 시스템을 운영하며, 자율 시스템 사이에서는 주로 BGP을 사용하여 어떤 IP 주소 범위에 도달할 수 있는지에 관한 경로 정보를 교환한다. 개별 사용자의 웹 요청은 접속망, 지역 통신사, 상위 통신망과 목적지 네트워크를 차례로 통과하거나, 이들 사이의 직접 연결을 통해 전달될 수 있다.
인터넷 교환 지점은 여러 네트워크가 트래픽을 직접 교환할 수 있는 물리적·논리적 기반을 제공한다. 네트워크 사업자 사이의 직접 연결인 피어링은 불필요하게 먼 상위 네트워크를 거치지 않고 패킷을 전달하여 지연 시간과 외부 전송 비용을 줄일 수 있다.
해저 광케이블, 지상 광섬유망, 이동통신 기지국, 위성 링크, 라우터, 스위치, 데이터 센터와 사용자 단말기는 인터넷의 물리적 기반을 구성한다. 그러나 인터넷의 논리적 구조는 특정한 전송 매체에 고정되지 않는다. IP 패킷을 전달할 수 있다면 새로운 유선·무선 기술도 인터넷 기반 시설에 통합될 수 있다.
웹사이트는 이 기반 위에서 웹 서버 또는 여러 서버 집합으로 운영된다. 사용자가 브라우저에 주소를 입력하면 요청은 일반적으로 사용자의 컴퓨터나 휴대전화에서 접속 라우터와 인터넷 서비스 제공자를 거쳐 웹 서버 또는 가까운 콘텐츠 전송 네트워크 노드로 전달된다. 응답 데이터도 여러 네트워크를 통과해 사용자에게 돌아오며, 각 방향의 패킷이 반드시 같은 경로를 사용할 필요는 없다.
현대의 대규모 웹 서비스는 하나의 원본 서버에만 의존하지 않는다. 여러 지역의 데이터 센터, 부하 분산 장치, 캐시, 리버스 프록시와 콘텐츠 전송 네트워크가 요청을 분산하여 처리한다. 그럼에도 사용자에게는 URI와 HTTP를 통해 하나의 논리적인 웹 자원이나 서비스로 표시될 수 있다.
인터넷은 자율적으로 운영되는 네트워크가 공개된 프로토콜에 자발적으로 합의하여 연결되는 구조를 가진다. IETF가 발행하는 RFC는 인터넷 프로토콜과 운영 절차의 핵심 기술 문서를 구성하지만, 모든 RFC가 인터넷 표준인 것은 아니다. RFC에는 표준 트랙 문서뿐 아니라 최선의 현재 관행, 실험, 정보 제공과 역사적 기록도 포함된다.[29]
웹이 사용하는 인터넷 프로토콜
웹은 하나의 프로토콜만으로 동작하지 않는다. 브라우저가 웹사이트의 이름을 해석하고 서버와 연결한 뒤 자원을 요청하고 안전하게 응답을 받기까지, 서로 다른 계층의 여러 인터넷 프로토콜이 함께 사용된다.
가장 아래의 네트워크 계층에서는 IP가 패킷의 출발지와 목적지를 식별하고 네트워크 사이에서 전달한다. IPv4와 IPv6는 주소 형식과 패킷 구조가 다르지만, 모두 웹 클라이언트와 서버 사이의 데이터를 인터넷을 통해 전달하는 기반으로 사용된다.
IP 주소는 통신에 적합하지만 사람이 기억하고 서비스 운영자가 관리하기에는 불편하다. DNS은 www.example.com과 같은 도메인 이름을 서버의 IP 주소와 관련 정보로 변환하는 분산 데이터베이스 체계다. 브라우저는 일반적으로 HTTP 연결을 시작하기 전에 운영체제나 DNS 해석기를 통해 대상 호스트의 주소를 조회한다.
DNS 조회 결과는 하나의 고정된 서버만 가리키지 않을 수 있다. 서비스는 사용자 위치, 네트워크 상태와 부하에 따라 서로 다른 주소를 반환할 수 있으며, IPv4용 A 레코드와 IPv6용 AAAA 레코드를 함께 제공할 수 있다. HTTPS와 서비스 연결에 필요한 추가 정보를 제공하는 SVCB 및 HTTPS 레코드도 사용할 수 있다.
전송 계층에서는 오랫동안 TCP가 웹 통신의 주요 기반으로 사용되었다. TCP는 응용 프로그램 사이에 신뢰성 있는 바이트 스트림을 제공하며, 손실된 데이터를 재전송하고 전달 순서를 복원하며 수신 측과 네트워크 상태에 따라 전송 속도를 조절한다. HTTP/1.0, HTTP/1.1과 HTTP/2는 일반적으로 TCP 위에서 동작한다.
TCP는 연결을 설정하고 신뢰성을 제공하는 과정에서 지연이 발생할 수 있다. HTTP/3은 TCP 대신 QUIC을 사용한다. QUIC은 UDP 데이터그램 위에서 신뢰성 있는 스트림, 흐름 제어, 혼잡 제어와 암호화된 연결 설정을 제공한다. 여러 스트림을 하나의 연결에서 독립적으로 처리하므로 한 스트림의 패킷 손실이 다른 스트림의 진행을 직접 막는 TCP 수준의 헤드 오브 라인 블로킹을 줄일 수 있다.
웹의 핵심 응용 계층 프로토콜은 HTTP다. HTTP는 분산된 협업형 하이퍼텍스트 정보 시스템을 위한 상태 비저장 응용 계층 프로토콜로 정의된다. 클라이언트는 대상 자원과 수행할 동작을 나타내는 요청을 보내고, 서버는 상태 코드, 헤더와 선택적인 콘텐츠를 포함한 응답을 반환한다.[30]
HTTP에서 GET은 일반적으로 자원의 현재 표현을 가져오는 데 사용되고, HEAD는 메시지 본문 없이 메타데이터를 확인하는 데 사용된다. POST, PUT, PATCH, DELETE 등은 데이터 제출, 자원 생성·수정과 삭제를 표현할 수 있다. 이러한 메서드의 의미는 HTTP가 정의하지만, 실제로 허용되는 동작과 결과는 각 웹 서비스의 구현과 권한 정책에 따라 정해진다.
HTTP 자체는 요청과 응답을 독립적인 메시지로 다루는 상태 비저장 프로토콜이다. 이는 서버가 사용자의 로그인 상태나 이전 행동을 기억할 수 없다는 뜻이 아니라, 각 요청의 의미가 이전 연결의 암묵적 상태에 의존하지 않도록 설계되었다는 뜻이다. 웹 애플리케이션은 쿠키, 인증 토큰, URL 매개변수와 서버 측 세션 저장소를 사용하여 여러 요청에 걸친 사용자 상태를 관리한다.
HTTPS는 HTTP 통신을 TLS로 보호하는 방식이다. TLS는 클라이언트와 서버 사이의 데이터를 암호화하고, 전송 중 변경 여부를 검증하며, 인증서를 통해 사용자가 연결한 서버의 신원을 확인할 수 있게 한다. HTTPS는 별개의 문서 형식이나 완전히 다른 웹 응용 프로토콜이 아니라, 보안이 적용된 HTTP URI 체계와 통신 방식이다.
TLS 보호는 브라우저와 연결된 서버 또는 중간 종단 사이에 적용된다. 사용자의 브라우저에 표시되기 전이나 서버에서 처리된 이후의 데이터 저장 방식까지 자동으로 보호하는 것은 아니다. 또한 HTTPS가 사용된다는 사실만으로 웹사이트의 콘텐츠와 사업자가 신뢰할 만하거나 안전하다는 의미가 되지는 않는다.
웹 페이지가 실시간 양방향 메시지 교환을 필요로 할 때는 WebSocket을 사용할 수 있다. WebSocket은 HTTP 기반의 초기 핸드셰이크로 시작한 뒤, 하나의 연결에서 클라이언트와 서버가 독립적으로 메시지를 전송할 수 있는 프레이밍 프로토콜로 전환된다. 이는 채팅, 공동 편집, 실시간 알림과 게임 상태 교환에 활용된다.[31]
WebRTC는 브라우저와 다른 단말기 사이의 실시간 음성·영상·데이터 통신을 지원한다. 연결 협상과 서비스 제어에는 웹 서버와 HTTP가 사용될 수 있지만, 실제 미디어 데이터는 지연 시간을 줄이기 위해 UDP 기반 프로토콜과 피어 간 경로를 사용하는 경우가 많다. 직접 연결이 어려우면 중계 서버를 통해 전송할 수 있다.
웹은 HTTP 이외의 URI 체계와 외부 프로토콜을 가리킬 수도 있다. 초기 브라우저는 FTP, Gopher와 뉴스 그룹 자원에 직접 접근하는 기능을 제공했고, 오늘날에도 mailto: 링크가 전자우편 프로그램을 실행하거나 사용자 정의 URI 체계가 다른 응용 프로그램으로 연결될 수 있다. 그러나 해당 서비스가 웹 브라우저에서 시작된다고 해서 그 서비스의 실제 통신이 모두 HTTP나 웹에 포함되는 것은 아니다.
웹 기술은 다른 응용 프로토콜을 HTTP 위에 다시 구성하기도 한다. 프로그램용 API, 원격 프로시저 호출, 스트리밍과 메시징 체계가 HTTP를 전송 기반으로 사용할 수 있으며, IETF는 HTTP를 이용해 새로운 응용 프로토콜을 설계할 때의 지침을 별도로 제공한다.[32]
따라서 현대 웹 통신은 대체로 다음과 같은 계층 관계를 가진다.
이 계층은 개념적 구분이며 실제 구현의 모든 관계를 완전히 나타내지는 않는다. 예를 들어 QUIC은 UDP 위에서 동작하면서 TLS 1.3의 암호화 기능을 통합하고, DNS도 전통적인 UDP와 TCP뿐 아니라 HTTPS 또는 TLS 위에서 전달될 수 있다.
웹에 포함되지 않는 인터넷 서비스
인터넷에서 동작하는 모든 서비스가 World Wide Web에 포함되는 것은 아니다. 인터넷은 웹보다 먼저 형성되었으며, 서로 다른 목적과 통신 모델을 가진 다수의 응용 프로토콜을 제공한다. 웹 브라우저나 웹 인터페이스가 특정 서비스를 관리하는 데 사용되더라도, 그 서비스의 핵심 통신 프로토콜은 웹과 별개일 수 있다.
전자우편은 대표적인 비웹 인터넷 서비스다. 메일 서버 사이의 전송에는 주로 SMTP가 사용되고, 사용자가 서버의 메일을 읽고 동기화할 때는 IMAP 또는 POP3가 사용될 수 있다. 웹메일은 브라우저에서 HTTP를 통해 사용자 인터페이스를 제공하지만, 서버 사이의 실제 메일 전달은 SMTP를 사용하므로 전자우편 전체가 웹 서비스로 바뀌는 것은 아니다.
FTP는 원격 서버와 파일을 전송하고 디렉터리를 조작하기 위해 만들어진 별도의 응용 프로토콜이다. 초기 웹 브라우저는 FTP 주소를 직접 열 수 있는 경우가 많았지만, 현대 브라우저에서는 보안과 유지보수 문제로 기본 FTP 지원이 제거되었다. 파일을 HTTP로 내려받는 행위와 FTP를 사용하는 파일 전송은 사용자에게 비슷하게 보일 수 있지만 서로 다른 프로토콜에 기반한다.
SSH는 원격 시스템에 안전하게 로그인하고 명령을 실행하거나 터널을 구성하는 프로토콜이다. SFTP는 SSH 연결 위에서 파일을 전송하며, 이름이 비슷한 FTPS나 FTP와는 별개의 프로토콜이다. 웹 기반 서버 관리 화면이나 브라우저 터미널이 내부적으로 SSH 연결을 중계할 수 있지만, SSH 자체는 웹 프로토콜이 아니다.
Telnet은 원격 단말 접속을 제공하는 초기 인터넷 프로토콜이다. 통신 내용이 기본적으로 암호화되지 않으므로 일반적인 원격 시스템 관리에서는 SSH로 대체되었지만, 일부 장비와 테스트 환경에서 계속 사용된다.
NNTP는 Usenet 뉴스 그룹의 게시물을 배포하고 읽는 데 사용된다. World Wide Web이 등장하기 전부터 인터넷의 공개 토론과 정보 배포에 널리 사용되었으며, 웹사이트가 뉴스 그룹의 내용을 표시할 수는 있어도 Usenet 자체는 웹과 다른 분산 서비스다.
IRC는 실시간 문자 대화를 위한 인터넷 프로토콜이다. IRC 클라이언트는 전용 프로그램일 수도 있고 웹 애플리케이션일 수도 있다. 웹 기반 IRC 클라이언트는 브라우저와 중계 서버 사이에서 HTTP나 WebSocket을 사용한 뒤, 중계 서버가 IRC 네트워크와 별도의 IRC 연결을 맺을 수 있다.
인터넷 전화와 영상 통화에는 SIP, RTP와 여러 미디어 전송 프로토콜이 사용될 수 있다. 서비스의 가입, 주소록과 설정 화면은 웹으로 제공되더라도 실제 음성·영상 데이터가 HTTP를 통해 전달될 필요는 없다. 반대로 WebRTC 기반 통화는 웹 플랫폼과 밀접하게 결합되지만, 미디어 전송에는 실시간 통신용 프로토콜이 함께 사용된다.
BitTorrent와 같은 P2P 프로토콜은 참여 단말기끼리 파일 조각이나 데이터를 직접 교환한다. 웹사이트는 토렌트 파일이나 마그넷 링크를 제공하고 검색 기능을 운영할 수 있지만, 실제 파일 전송은 일반적인 웹 서버의 HTTP 응답이 아니라 P2P 참여자 사이에서 이루어질 수 있다.
NTP는 인터넷에 연결된 시스템의 시계를 동기화한다. DHCP는 네트워크에 참가한 장치에 IP 주소와 설정을 제공하며, 일반적으로 인터넷 전체가 아니라 로컬 네트워크 범위에서 사용된다. SNMP는 네트워크 장비와 서버의 상태를 조회하고 관리하는 데 사용된다. 이들은 웹 페이지를 제공하지 않아도 인터넷과 IP 네트워크의 운영을 지원한다.
온라인 게임, 데이터베이스 연결, 분산 저장소와 기업용 메시징 시스템도 자체 프로토콜을 사용할 수 있다. 일부는 방화벽과 프록시를 통과하기 쉽고 기존 인프라를 재사용할 수 있다는 이유로 HTTPS 위에 통신을 구성하지만, HTTP 사용 여부만으로 사람이 탐색하는 전통적 웹사이트와 같은 성격을 가진다고 보기는 어렵다.
인터넷 서비스는 다음과 같이 웹과 결합될 수 있다.
따라서 어떤 서비스에 웹 페이지가 포함되어 있다는 사실과 서비스 전체가 웹 기술만으로 구성되어 있다는 사실은 구분해야 한다. 현대 인터넷 서비스는 사용자 인터페이스에는 웹을 사용하면서 내부 시스템과 서버 간 통신에는 여러 비웹 프로토콜을 함께 사용하는 경우가 많다.
일상적 용법에서의 혼용
일상에서는 인터넷, 웹, 온라인과 브라우저가 명확히 구분되지 않고 사용되는 경우가 많다. 사용자가 인터넷에 접속하는 주된 수단이 오랫동안 웹 브라우저였고, 검색·뉴스·쇼핑·영상·금융·행정과 소셜 미디어가 웹사이트를 통해 제공되었기 때문이다.
“인터넷 주소”라는 표현은 흔히 웹사이트의 URL을 뜻하고, “인터넷 창”은 웹 브라우저 창을 의미하며, “인터넷에서 검색한다”는 말은 검색 엔진의 웹 페이지에서 정보를 찾는 행위를 가리키는 경우가 많다. 이러한 표현은 일상적인 의사소통에서는 충분히 통하지만, 기술 문맥에서는 서로 다른 계층과 구성 요소를 가리킨다.
웹 브라우저가 실행되고 있어도 장치가 인터넷에 연결된 것은 아닐 수 있다. 사용자는 인터넷 연결 없이 로컬 HTML 파일을 열거나, 같은 조직의 내부 네트워크에서만 접근할 수 있는 인트라넷 웹사이트를 사용할 수 있다. 반대로 브라우저를 열지 않은 상태에서도 전자우편 클라이언트, 메신저, 온라인 게임, 운영체제 업데이트와 클라우드 동기화 프로그램이 인터넷을 사용할 수 있다.
스마트폰에서는 혼용이 더욱 두드러진다. 사용자는 네이티브 모바일 애플리케이션을 이용한다고 생각하지만, 앱 내부 화면의 일부가 내장 브라우저 구성 요소인 WebView로 표시되거나 서버와 HTTPS 기반 API로 통신할 수 있다. 반대로 외형이 웹사이트와 비슷한 앱도 자체 네트워크 프로토콜과 운영체제 기능을 사용할 수 있다.
온라인이라는 표현은 일반적으로 네트워크를 통해 다른 시스템이나 서비스에 연결된 상태를 뜻한다. 온라인 서비스가 반드시 공개 인터넷이나 웹을 사용해야 하는 것은 아니다. 조직 내부망, 게임 전용 네트워크와 폐쇄형 통신망에 연결된 상태도 문맥에 따라 온라인이라고 부를 수 있다.
클라우드 역시 웹이나 인터넷과 같은 말은 아니다. 클라우드 컴퓨팅은 원격 데이터 센터의 계산, 저장소와 플랫폼 자원을 필요에 따라 제공하는 운영 모델을 가리킨다. 사용자는 대개 인터넷과 웹 인터페이스를 통해 클라우드 서비스를 이용하지만, 전용 회선, 명령줄 도구, 가상 사설망과 비웹 API를 사용할 수도 있다.
Wi-Fi는 인터넷 자체가 아니라 장치와 무선 액세스 포인트 사이를 연결하는 근거리 네트워크 기술이다. Wi-Fi 연결이 활성화되어 있어도 해당 네트워크에 인터넷 경로가 없으면 외부 웹사이트에 접근할 수 없다. 반대로 이동통신망이나 유선 Ethernet을 사용하면 Wi-Fi 없이도 인터넷과 웹에 연결할 수 있다.
기술적으로 관계를 정리하면, 인터넷은 데이터 전달 기반이고 웹은 그 위에서 자원을 식별·요청·표현·연결하는 정보 시스템이다. 웹 브라우저는 웹에 접근하는 대표적인 클라이언트이고, 검색 엔진은 웹 자원을 발견하고 색인하는 서비스다. 웹사이트는 웹에서 제공되는 페이지와 기능의 논리적 집합이며, 인터넷 서비스 전체와 동일하지 않다.
World Wide Web의 초기 설명도 웹을 인터넷에서 이용할 수 있는 온라인 정보를 끊김 없이 탐색할 수 있는 연속적인 공간처럼 바라보는 방식으로 설명하였다. 이 표현은 웹이 인터넷의 정보를 이용하고 연결하는 인터페이스라는 점을 나타내지만, 인터넷 기반 시설과 웹 정보 공간 자체가 동일하다는 의미는 아니다.[33]
일상적 용법의 혼용은 웹이 인터넷의 가장 가시적인 부분이 되었다는 역사적 결과다. 다만 네트워크 구조, 장애 원인, 보안 정책과 소프트웨어 설계를 설명할 때는 인터넷 연결 문제, DNS 문제, 전송 프로토콜 문제, HTTP 서버 문제와 브라우저 렌더링 문제를 서로 구분해야 한다. 이 구분을 통해 사용자가 보는 하나의 “웹 접속 실패”가 실제로 어느 계층에서 발생했는지 판단할 수 있다.
기본 구조
World Wide Web은 네트워크에 연결된 여러 소프트웨어 구성 요소가 자원을 식별하고, 그 자원과 상호작용하며, 상태를 나타내는 표현을 교환하는 분산 정보 시스템이다. 전형적인 웹 이용에서는 웹 브라우저가 클라이언트 역할을 하고 웹 서버가 요청을 처리하지만, 실제 통신 경로에는 캐시, 프록시, 게이트웨이, 콘텐츠 전송 네트워크와 부하 분산 장치가 포함될 수 있다.
W3C의 웹 아키텍처는 웹의 핵심 구조를 식별, 상호작용, 표현이라는 세 요소로 설명한다. 자원은 URI로 식별되고, 에이전트는 HTTP와 같은 프로토콜을 사용하여 자원과 상호작용하며, 그 결과로 자원의 상태를 나타내는 HTML·JSON·이미지 등의 표현을 주고받는다.[34]
웹은 모든 정보를 하나의 중앙 서버에 저장하지 않는다. 서로 독립적으로 운영되는 서버가 각자의 자원을 제공하고, 사용자는 URI와 하이퍼링크를 통해 이들을 하나의 연결된 정보 공간처럼 탐색한다. 이러한 분산 구조는 웹이 특정 운영체제, 프로그램, 조직이나 저장 형식에 고정되지 않고 확장될 수 있는 기반이다.
클라이언트와 서버
클라이언트는 웹 자원에 접근하거나 서버에 작업을 요청하는 소프트웨어다. 대표적인 클라이언트는 웹 브라우저지만, 검색 엔진 크롤러, 모바일 애플리케이션, 명령줄 HTTP 도구, 자동화 프로그램과 다른 서버도 웹 클라이언트로 동작할 수 있다.
브라우저는 사용자가 입력한 URL이나 문서 안의 링크를 해석하고, 필요한 서버를 찾은 뒤 HTTP 요청을 전송한다. 응답으로 받은 HTML을 분석하고 CSS와 JavaScript, 이미지, 글꼴과 미디어 같은 추가 자원을 다시 요청하여 최종 화면을 구성한다. 하나의 웹 페이지를 표시하는 과정에서도 여러 호스트와 수많은 요청이 사용될 수 있다.
서버는 클라이언트의 요청을 수신하고 그에 대한 응답을 생성하는 소프트웨어다. 웹 서버는 디스크에 저장된 정적 파일을 그대로 반환할 수도 있고, 응용 프로그램을 실행하거나 데이터베이스를 조회하여 요청마다 다른 콘텐츠를 생성할 수도 있다.
서버라는 표현은 물리적 컴퓨터와 소프트웨어 역할을 모두 가리킬 수 있다. 하나의 물리적 컴퓨터에서 여러 웹 서버가 실행될 수 있고, 하나의 웹사이트가 여러 지역에 배치된 수많은 서버에서 제공될 수도 있다. 가상 머신, 컨테이너와 서버리스 실행 환경도 클라이언트 입장에서는 같은 HTTP 서버 역할을 수행할 수 있다.
클라이언트와 서버는 고정된 종류의 장치를 뜻하지 않는다. 하나의 프로그램은 어떤 상호작용에서는 서버로 요청을 처리하고, 다른 상호작용에서는 외부 서비스에 요청을 보내는 클라이언트가 될 수 있다. 예를 들어 웹 애플리케이션 서버는 브라우저에는 서버로 동작하지만 데이터베이스 프록시, 인증 서비스나 외부 API에는 클라이언트로 동작한다.
HTTP 명세에서는 연결을 시작하여 요청을 보내는 참여자를 클라이언트, 요청을 받아 응답을 보내는 참여자를 서버로 정의한다. 이 역할은 하나의 연결과 메시지 교환을 기준으로 정해지며, 특정 컴퓨터의 영구적인 속성이 아니다.[35]
웹 브라우저와 원본 서버 사이의 일반적인 관계는 다음과 같이 나타낼 수 있다.
기본적인 웹 자원 접근 흐름
- 사용자가 URL을 입력하거나 링크를 선택↓
- 클라이언트가 URI를 해석하고 서버 연결 준비↓
- 클라이언트가 HTTP 요청 전송↓
- 서버가 요청 대상과 메서드, 헤더와 권한 확인↓
- 서버가 자원을 조회하거나 응용 프로그램 실행↓
- 서버가 상태 코드, 헤더와 선택적인 콘텐츠를 포함한 응답 전송↓
- 클라이언트가 표현을 해석하거나 후속 요청 수행
이 흐름은 개념적인 기본 형태다. 실제 연결에서는 DNS 조회, TLS 연결, 캐시 검사, 리디렉션, 인증과 여러 중간 시스템이 추가될 수 있다.
요청과 응답
HTTP에서 클라이언트와 서버의 상호작용은 요청과 응답 메시지의 교환으로 이루어진다. 클라이언트는 서버에 요청을 보내고, 서버는 해당 요청의 처리 결과를 응답으로 반환한다. HTTP는 요청과 응답의 의미를 정의하지만, 메시지가 실제 네트워크에서 어떻게 프레이밍되고 전송되는지는 HTTP/1.1, HTTP/2와 HTTP/3에 따라 달라질 수 있다.
요청은 일반적으로 다음 정보를 포함한다.
- 요청 대상이 되는 URI 또는 경로
- 수행하려는 의미를 나타내는 HTTP 메서드
- 요청 조건과 클라이언트 정보를 담은 헤더 필드
- 필요한 경우 서버에 전달하는 콘텐츠
GET 요청은 대상 자원의 현재 표현을 가져오는 데 주로 사용된다. HEAD는 표현 본문 없이 응답 메타데이터를 확인하고, POST는 서버에 데이터를 제출하거나 자원별 처리를 요청한다. PUT, PATCH와 DELETE는 자원의 생성·변경·삭제와 관련된 의미를 나타낼 수 있다.
메서드는 요청이 의도하는 일반적인 의미를 정의하지만, 실제 동작은 자원을 운영하는 서버가 결정한다. 같은 POST 요청도 웹사이트에 글을 등록하거나, 검색을 수행하거나, 결제를 요청하거나, 원격 프로그램의 명령을 실행하는 데 사용될 수 있다.
요청 헤더에는 클라이언트가 처리할 수 있는 콘텐츠 형식과 언어, 인증 정보, 캐시 조건, 이전에 받은 표현의 식별자, 요청이 시작된 출처와 쿠키 등이 포함될 수 있다. 요청 콘텐츠는 폼 데이터, JSON 문서, 업로드 파일이나 다른 미디어 형식으로 구성될 수 있다.
응답은 일반적으로 다음 정보를 포함한다.
- 요청의 처리 결과를 나타내는 상태 코드
- 응답과 표현의 특성을 설명하는 헤더 필드
- 필요한 경우 자원의 표현이나 오류 설명을 담은 콘텐츠
HTTP 상태 코드는 세 자리 숫자로 구성되며 첫 번째 숫자에 따라 정보 응답, 성공, 리디렉션, 클라이언트 오류와 서버 오류로 나뉜다. 200 OK는 요청이 정상적으로 처리되었음을, 301 Moved Permanently와 302 Found는 다른 URI로의 이동을, 404 Not Found는 대상 자원을 찾지 못했음을 나타낸다. 500 Internal Server Error는 서버가 요청을 처리하는 과정에서 예상하지 못한 상태를 만났음을 나타낸다.[36]
상태 코드만으로 응답의 전체 의미가 결정되지는 않는다. 응답 헤더는 표현의 미디어 유형, 문자 인코딩, 길이, 수정 시각, 캐시 정책과 인증 요구 등을 전달한다. 응답 콘텐츠에는 성공적으로 요청한 HTML·JSON·이미지뿐 아니라 오류를 설명하는 문서도 포함될 수 있다.
HTTP 메시지는 의미상 독립적이지만, 실제 웹 애플리케이션은 여러 요청 사이에 상태를 유지한다. 서버는 쿠키와 세션 식별자, 인증 토큰, URL 매개변수와 데이터베이스를 이용하여 로그인 상태, 장바구니와 사용자 설정을 연결한다. HTTP가 상태 비저장이라는 것은 서버가 상태를 저장할 수 없다는 뜻이 아니라, 각 요청이 프로토콜 차원에서 독립된 의미를 갖는다는 뜻이다.
하나의 요청은 추가 요청을 유발할 수 있다. HTML 응답이 CSS, JavaScript와 이미지를 참조하면 브라우저는 각 자원에 대해 새로운 요청을 전송한다. JavaScript가 API를 호출하거나 사용자의 조작에 따라 데이터를 요청할 수도 있다. 따라서 하나의 페이지 방문은 단일 요청·응답이 아니라 상호 의존하는 여러 교환의 집합인 경우가 일반적이다.
조건부 요청은 이미 저장된 표현이 최신인지 확인하여 불필요한 데이터 전송을 줄인다. 클라이언트는 이전 응답의 ETag나 수정 시각을 조건으로 보내고, 자원이 바뀌지 않았다면 서버는 표현 본문을 다시 보내지 않고 304 Not Modified로 응답할 수 있다.
리디렉션 응답은 클라이언트에 다른 URI로 다시 요청하도록 지시한다. 브라우저가 리디렉션을 자동으로 처리하면 사용자는 하나의 페이지가 열린 것으로 인식하지만, 네트워크에서는 여러 요청과 응답이 순차적으로 발생한다.
자원의 식별, 상호작용과 표현
웹의 기본 구조에서 자원은 식별할 가치가 있는 모든 대상을 의미한다. HTML 문서와 이미지, 파일, 동영상과 API 데이터처럼 직접 전송 가능한 대상뿐 아니라 사람, 조직, 장소, 개념, 현재 날씨와 특정 시점의 상태도 자원으로 모델링할 수 있다.
자원은 URI로 식별된다. URI는 자원의 내용을 직접 포함하는 것이 아니라, 웹에서 그 자원을 가리키는 전역적인 식별자 역할을 한다. 서로 다른 문서와 응용 프로그램이 같은 URI를 참조하면 같은 자원에 관해 연결하고 정보를 교환할 수 있다.
웹에서 하나의 자원을 여러 URI로 식별하는 것은 가능하지만, 같은 자원에 일관된 URI를 사용하면 링크와 캐시, 검색, 인용과 데이터 통합이 쉬워진다. 반대로 하나의 URI가 서로 무관한 대상을 의미하도록 바뀌면 기존 링크와 기록의 의미가 손상될 수 있다.
식별은 자원이 무엇인지 가리키는 단계고, 상호작용은 해당 자원에 관하여 정보를 얻거나 상태 변경을 요청하는 과정이다. HTTP URI의 경우 클라이언트는 일반적으로 URI를 요청 대상으로 사용하여 GET, POST와 같은 HTTP 메서드를 전송한다.
URI를 사용한다고 해서 언제나 네트워크 요청이 발생하는 것은 아니다. URI는 문서 안에서 단순한 이름이나 관계 식별자로 사용될 수 있고, 일부 URI 체계는 HTTP와 다른 접근 방식을 가진다. HTTP URI에 접근하더라도 인증 실패, 네트워크 장애, 자원 삭제 또는 서버 정책으로 인해 표현을 얻지 못할 수 있다.
표현은 특정 시점에 자원의 상태를 나타내도록 전송되는 데이터와 그 데이터의 메타데이터다. HTML 문서, JSON 데이터, JPEG 이미지, PDF 파일과 음성 데이터가 표현의 예다. 클라이언트는 자원 자체를 물리적으로 전달받는 것이 아니라, 자원을 나타내는 표현을 전달받아 처리한다.
자원과 표현의 구분은 변화하는 대상에서 중요하다. 오늘의 날씨라는 자원의 URI는 유지되면서 시간에 따라 반환되는 표현이 달라질 수 있다. 온라인 문서도 같은 URI를 유지하면서 수정된 HTML 표현을 반환할 수 있다. 반대로 하나의 파일 내용이 여러 URI에서 동일한 표현으로 제공될 수도 있다.
같은 자원은 여러 형식의 표현을 가질 수 있다. 서버는 브라우저에는 HTML을, 프로그램에는 JSON을 제공하거나 요청한 언어에 따라 한국어와 영어 표현을 반환할 수 있다. 이러한 선택 과정을 콘텐츠 협상이라고 하며, 요청 헤더와 서버의 설정을 기준으로 수행된다.
표현의 형식은 Content-Type과 같은 메타데이터로 전달된다. 브라우저나 다른 클라이언트는 미디어 유형을 바탕으로 데이터를 HTML 문서로 분석할지, 이미지로 표시할지, JSON으로 처리할지 결정한다. 같은 바이트열이라도 미디어 유형과 문자 인코딩 정보가 잘못되면 올바르게 해석되지 않을 수 있다.
자원의 상태와 표현은 항상 일대일로 대응하지 않는다. 표현은 자원 상태의 일부만 포함하거나 계산·요약된 결과를 제공할 수 있다. 접근 권한과 사용자 설정에 따라 서로 다른 사용자가 같은 URI에서 다른 표현을 받을 수도 있다.
W3C는 웹을 식별자 자체가 아니라 표현을 통해 자원의 상태 정보를 교환하도록 설계된 체계로 설명한다. URI는 자원을 식별하고, 프로토콜 상호작용은 표현과 메타데이터를 전달한다.[37]
이 관계는 다음과 같이 정리할 수 있다.
자원 접근의 논리적 구조
- URI가 자원을 식별↓
- 클라이언트가 URI를 사용하여 자원과 상호작용↓
- 서버 또는 중간 시스템이 요청 해석↓
- 자원의 현재 상태와 요청 조건에 맞는 표현 선택↓
- 표현과 메타데이터를 응답으로 전송↓
- 클라이언트가 표현을 표시하거나 프로그램 데이터로 처리
이 구조 덕분에 자원을 식별하는 방식과 자원을 저장하는 내부 구현, 그리고 자원을 표현하는 형식을 어느 정도 분리할 수 있다. 서버는 데이터베이스 구조나 프로그램 언어를 변경하더라도 URI와 상호작용 의미를 유지할 수 있고, 클라이언트는 서버 내부의 저장 방식을 알지 않고도 자원을 사용할 수 있다.
프록시와 중간 시스템
클라이언트와 원본 서버 사이의 HTTP 통신은 항상 직접 이루어지는 것은 아니다. HTTP는 하나 이상의 중간 시스템이 요청과 응답의 전달 과정에 참여할 수 있도록 설계되었다. 중간 시스템은 트래픽을 전달하고, 캐시하고, 필터링하고, 변환하거나 여러 서버로 분산할 수 있다.
RFC 9110은 대표적인 HTTP 중간 시스템을 프록시, 게이트웨이와 터널로 구분한다.[38]
프록시는 클라이언트가 선택하거나 네트워크 정책에 따라 사용되는 요청 전달 중간자다. 클라이언트는 원본 서버에 직접 연결하는 대신 프록시에 요청을 보내며, 프록시는 요청을 처리하거나 다음 서버로 전달한 뒤 응답을 클라이언트에 반환한다.
순방향 프록시는 조직 내부 사용자의 외부 웹 접근을 중계하는 데 사용될 수 있다. 접근 제어, 악성 사이트 차단, 사용자 인증, 트래픽 기록과 캐싱 기능을 제공할 수 있으며, 외부 서버에는 최종 사용자가 아니라 프록시의 네트워크 주소가 보일 수 있다.
게이트웨이는 클라이언트에게 원본 서버처럼 보이면서 뒤쪽의 다른 서버나 프로토콜로 요청을 전달하는 중간 시스템이다. 웹 운영에서 흔히 사용하는 리버스 프록시는 게이트웨이 역할에 가깝다. 클라이언트는 리버스 프록시의 주소에 연결하지만, 실제 콘텐츠와 응용 처리는 내부 서버가 담당할 수 있다.
리버스 프록시는 TLS 연결 종료, 압축, 인증, 요청 경로 분배, 속도 제한과 보안 필터링을 담당할 수 있다. 여러 응용 서버 앞에 배치하여 요청을 분산하고 장애가 발생한 서버를 제외하는 부하 분산 장치로도 사용된다.
터널은 메시지의 내용을 HTTP 중간자로서 해석하거나 변경하기보다 두 연결 사이의 데이터를 그대로 전달한다. HTTPS 프록시에서 사용하는 HTTP CONNECT 메서드는 클라이언트와 대상 서버 사이에 바이트 전달 터널을 만드는 데 사용될 수 있다. 터널이 형성된 뒤 TLS 암호화가 클라이언트와 원격 서버 사이에 적용되면 중간 시스템은 일반적으로 암호화된 응용 데이터를 직접 해석할 수 없다.
캐시는 이전 응답을 저장했다가 이후 요청에 재사용하는 시스템이다. 브라우저 내부의 개인 캐시와 여러 사용자가 공유하는 프록시 캐시가 있으며, 콘텐츠 전송 네트워크도 대규모 분산 캐시로 동작할 수 있다.
캐시는 네트워크 전송량과 응답 시간을 줄이고 원본 서버의 부하를 낮춘다. 다만 모든 응답을 임의로 저장할 수 있는 것은 아니며, Cache-Control, Expires, ETag, Vary와 같은 HTTP 메타데이터와 요청 조건에 따라 저장 및 재사용 가능 여부를 판단한다. HTTP 캐싱의 동작은 RFC 9111에 정의되어 있다.[39]
콘텐츠 전송 네트워크는 여러 지역의 엣지 서버에 콘텐츠를 캐시하거나 원본 서버의 요청을 대신 처리한다. 사용자는 지리적·네트워크적으로 가까운 노드에서 응답을 받아 지연 시간을 줄일 수 있다. 동적 요청도 엣지 서버의 프로그램 실행, 연결 재사용과 최적화된 백본망을 통해 처리될 수 있다.
중간 시스템은 요청과 응답의 일부를 변경할 수도 있다. 연결별 헤더를 처리하고 압축을 적용하거나, 프로토콜 버전을 변환하고, 전달 정보를 추가할 수 있다. 그러나 HTTP 메시지의 의미를 손상하거나 종단 간 보안과 캐시 규칙을 위반하는 변경은 상호 운용성 문제를 일으킬 수 있다.
HTTPS는 클라이언트와 TLS 연결의 종단 사이를 암호화한다. 리버스 프록시나 CDN에서 TLS가 종료되면 해당 중간 시스템은 요청과 응답 내용을 처리할 수 있으며, 이후 원본 서버까지 별도의 TLS 연결을 사용할 수 있다. 따라서 화면에 HTTPS가 표시된다는 사실만으로 요청이 모든 중간 처리 시스템을 암호화된 상태로 통과했다는 의미는 아니다.
프록시와 중간 시스템을 포함한 일반적인 웹 배포 구조는 다음과 같다.
중간 시스템이 포함된 웹 요청 구조
- 브라우저 캐시
- 요청 전송
- 순방향 프록시 또는 조직 게이트웨이
- 인터넷
- 콘텐츠 전송 네트워크 또는 엣지 서버
- 캐시된 응답 반환
- 리버스 프록시 또는 부하 분산 장치
- 응용 서버
- 정적 파일 서버
- API 서버
모든 웹 요청이 이 구성 요소를 전부 통과하는 것은 아니다. 소규모 사이트에서는 클라이언트가 하나의 웹 서버에 직접 연결할 수 있고, 대규모 서비스에서는 여러 단계의 프록시와 캐시가 추가될 수 있다.
중간 시스템은 웹의 확장성과 성능을 높이지만 장애 원인의 위치를 복잡하게 만들기도 한다. 원본 서버가 정상이어도 DNS, 프록시, CDN, 캐시 또는 게이트웨이의 오류로 사용자가 자원에 접근하지 못할 수 있다. 오래된 캐시가 갱신되지 않거나 중간 시스템이 특정 요청 헤더를 제거하여 사용자마다 다른 결과가 나타날 수도 있다.
분산 정보 공간
웹은 모든 문서와 서비스를 하나의 중앙 데이터베이스에 등록하는 체계가 아니다. 서로 독립적인 개인과 조직이 각자의 서버와 도메인을 운영하고, URI를 부여하며, 다른 자원으로 하이퍼링크를 만들면서 전체 정보 공간이 형성된다.
웹의 분산성은 콘텐츠의 저장 위치뿐 아니라 관리 권한에도 적용된다. 각 사이트 운영자는 자신의 서버, 자원, 접근 정책과 콘텐츠를 관리하며, 새로운 웹사이트를 게시하기 위해 웹 전체를 통제하는 중앙 기관의 승인을 받을 필요가 없다. 도메인 이름과 네트워크 주소에는 계층적 관리 체계가 존재하지만, 개별 웹 문서와 링크의 게시 여부를 중앙에서 결정하지는 않는다.
하이퍼링크는 서로 다른 서버의 자원을 하나의 탐색 구조로 연결한다. 문서 작성자는 자신이 관리하지 않는 외부 자원의 URI를 링크할 수 있으며, 사용자는 링크를 선택할 때 서버 경계를 크게 의식하지 않고 이동한다. 이러한 연결의 집합은 고정된 목차가 아니라 계속 변화하는 웹 그래프를 형성한다.
웹의 분산 정보 공간에는 하나의 일관된 분류나 데이터 형식이 강제되지 않는다. 서버마다 HTML 구조, 언어, 디자인, 응용 프로그램과 데이터 모델이 다를 수 있다. URI, HTTP와 미디어 유형 같은 공통 규칙이 서로 다른 구현 사이의 최소한의 상호 운용 기반을 제공한다.
분산 구조에서는 하나의 자원에 여러 복사본과 표현이 존재할 수 있다. 원본 서버의 콘텐츠가 캐시와 CDN에 복제되고, 문서가 번역·인용·보관되거나 다른 형식으로 변환될 수 있다. 이러한 복제는 가용성과 성능을 높이지만 어떤 자료가 원본이며 최신인지 판단하는 문제도 만든다.
웹에는 전체 상태를 알고 있는 단일 구성 요소가 없다. 검색 엔진도 웹 전체를 완전하게 색인하지 못하며, 크롤러가 발견한 일부 공개 자원을 자체 데이터베이스에 저장할 뿐이다. 비공개 자원, 링크되지 않은 문서, 실시간으로 생성되는 데이터와 접근이 제한된 서비스는 검색 색인에 포함되지 않을 수 있다.
분산성은 부분적인 장애에 대한 독립성도 제공한다. 특정 웹사이트나 데이터 센터가 중단되어도 다른 서버의 웹 자원은 계속 이용할 수 있다. 반면 외부 자원에 대한 링크는 대상 서버의 이동이나 삭제로 인해 끊어질 수 있으며, 이를 링크 부패라고 한다.
웹의 보안 경계도 분산된 출처를 기준으로 형성된다. 브라우저는 URI의 스킴, 호스트와 포트를 조합한 출처를 중심으로 문서와 스크립트의 권한을 구분한다. 서로 다른 출처가 데이터를 공유하려면 CORS, 메시지 전달과 명시적인 권한 정책 같은 별도 메커니즘이 필요하다.
분산 정보 공간이 반드시 서비스와 영향력까지 고르게 분산되어 있다는 뜻은 아니다. 웹의 기술 구조는 누구나 서버를 운영하고 링크를 만들 수 있도록 설계되었지만, 실제 이용은 대형 검색 엔진, 소셜 플랫폼, 클라우드 사업자와 콘텐츠 전송 네트워크에 집중될 수 있다. 기술적 분산성과 경제적·사회적 중앙 집중화는 동시에 존재할 수 있다.
웹의 보편성은 서로 다른 기기, 운영체제, 언어와 미디어가 공통 URI 공간에 참여할 수 있다는 데 있다. 특정 프로그램에서만 사용할 수 있는 폐쇄된 문서 집합과 달리, 공개된 웹 표준을 구현하는 에이전트는 같은 자원을 식별하고 상호작용할 수 있다.
팀 버너스리는 웹을 대상에 주소를 부여할 수 있는 보편적 정보 공간으로 설명하였다. URI 체계는 하나의 중앙 저장소를 의미하지 않으며, 독립적으로 운영되는 자원을 공통된 식별 공간에서 참조할 수 있게 한다.[40]
분산된 자원은 다음과 같이 하나의 논리적 정보 공간을 형성한다.
분산된 웹 정보 공간
- 공통 URI 공간
- 개인이 운영하는 웹사이트
- 문서
- 미디어
- 기업과 기관의 서비스
- 웹 애플리케이션
- 웹 API
- 공공·학술 정보 시스템
- 데이터베이스
- 연구 자료
- 서로 다른 서버의 자원을 잇는 하이퍼링크
- 같은 사이트 내부 링크
- 외부 사이트 링크
- 문서, 데이터와 서비스 사이의 관계
사용자에게 웹은 하나의 거대한 정보 공간처럼 보이지만, 그 내부에서는 서로 다른 운영 주체와 기술 스택, 서버와 정책이 독립적으로 작동한다. 웹의 기본 구조는 이 독립성을 유지하면서도 URI, 표준화된 상호작용과 표현 형식을 통해 전체를 연결하는 데 있다.
자원 식별과 주소 체계
World Wide Web의 자원은 네트워크상의 실제 저장 위치나 구현 방식과 분리된 식별자를 통해 참조된다. 사용자는 주소를 입력하거나 하이퍼링크를 선택하고, 브라우저와 다른 소프트웨어는 그 식별자를 해석하여 적절한 프로토콜과 서버, 자원에 접근한다.
웹 주소는 단순한 파일 위치가 아니다. 같은 주소에서 프로그램이 동적으로 생성한 문서가 반환될 수 있고, 여러 서버가 하나의 주소를 공동으로 처리할 수도 있으며, 주소가 실제로 전송할 수 없는 사람이나 개념을 식별하는 데 사용될 수도 있다.
웹에서 사용하는 식별 체계의 가장 넓은 개념은 URI다. URL은 URI 가운데 자원에 접근하는 방법과 위치를 나타내는 형태다. HTTP와 HTTPS URL은 일반적으로 스킴, 권한 구성 요소, 경로, 질의와 프래그먼트로 구성되며, 호스트 이름은 DNS을 통해 네트워크 주소와 서비스 정보로 해석된다.
주소의 안정성은 웹의 연결 구조를 유지하는 데 중요하다. 공개된 주소가 서버 개편, 파일 이동이나 소프트웨어 교체 때마다 변경되면 외부 링크와 검색 색인, 인용과 북마크가 끊어진다. 따라서 웹 주소는 현재의 내부 파일 구조보다 장기간 유지할 논리적인 자원 구조를 기준으로 설계하는 것이 일반적이다.
URI
URI는 Uniform Resource Identifier의 약자로, 자원을 식별하기 위한 일정한 문법을 따르는 문자열이다. 한국어로는 통합 자원 식별자 또는 균일 자원 식별자라고 번역한다.
URI에서 말하는 자원은 반드시 내려받을 수 있는 파일이나 웹 페이지일 필요가 없다. 문서, 이미지와 프로그램뿐 아니라 사람, 조직, 장소, 책의 판본, 추상적인 개념과 특정한 데이터 집합도 URI로 식별할 수 있다. URI의 역할은 대상을 직접 저장하는 것이 아니라, 다른 문서와 프로그램이 같은 대상을 일관된 이름으로 참조할 수 있게 하는 데 있다.
RFC 3986은 URI를 자원을 식별하기 위한 단순하고 확장 가능한 체계로 정의한다. URI 문법은 여러 스킴이 공통 구조를 공유하면서도 각 스킴이 자체적인 구문과 의미를 추가로 정의할 수 있도록 설계되어 있다.[41]
일반적인 URI는 다음 구성 요소를 가질 수 있다.
scheme://authority/path?query#fragment
이 구조의 모든 구성 요소가 항상 존재하는 것은 아니다. URI는 스킴을 반드시 가지지만, 권한 구성 요소와 경로, 질의, 프래그먼트의 존재 여부는 스킴과 식별 대상에 따라 달라진다.
스킴은 URI의 첫 번째 : 앞에 위치하며 식별자의 해석 방식과 관련 체계를 나타낸다. http, https, mailto, ftp, urn, data 등이 URI 스킴의 예다.
https://example.com/document에서 스킴은 https다. 이는 해당 URI가 HTTPS 기반의 웹 자원 식별 및 접근 규칙을 사용한다는 뜻이다. mailto:[email protected]에서는 mailto가 전자우편 주소를 나타내는 URI 스킴이다.
권한 구성 요소는 // 뒤에 나타나며 일반적으로 호스트 이름과 선택적인 사용자 정보, 포트 번호를 포함한다. HTTP URL에서는 웹 서버나 서비스를 대표하는 도메인 이름이 주로 사용된다.
URI는 절대 URI와 상대 참조로 나눌 수 있다. 절대 URI는 스킴을 포함하여 독립적으로 해석할 수 있다.
https://example.com/docs/index.html
상대 참조는 기준 URI와 결합하여 해석된다.
../images/logo.svg
상대 참조는 문서가 같은 사이트 안의 다른 자원을 간결하게 가리킬 수 있게 하지만, 기준 URI가 바뀌면 해석 결과도 달라질 수 있다. HTML 문서에서는 현재 문서의 URL이나 base 요소가 상대 참조를 해석하는 기준이 된다.
URI 안에서는 일부 문자가 구조 구분자로 사용된다. /, ?, #, :, @와 같은 문자는 문맥에 따라 특별한 의미를 가지며, 데이터를 문자 그대로 표현해야 할 때는 퍼센트 인코딩을 사용할 수 있다.
퍼센트 인코딩은 문자의 바이트 값을 % 뒤의 두 자리 16진수로 표현한다. 예를 들어 공백은 문맥에 따라 %20으로 표현할 수 있고, UTF-8로 인코딩된 비ASCII 문자도 각 바이트를 퍼센트 인코딩하여 URI에 포함할 수 있다.
같은 자원을 가리키는 URI 문자열이 외형상 여러 형태로 존재할 수 있다. 호스트 이름의 대소문자, 기본 포트의 명시 여부, 퍼센트 인코딩 방식과 경로 정규화에 따라 문자열은 달라도 같은 결과로 해석될 수 있다. 그러나 모든 URI를 단순한 문자열 변환만으로 안전하게 동일하다고 판단할 수는 없다. 각 스킴과 서버가 경로 및 질의의 의미를 다르게 정의할 수 있기 때문이다.
URI의 구조는 스킴을 소유하거나 자원을 관리하는 주체의 권한과도 연결된다. RFC 8820은 URI의 하위 구조를 외부 표준이 임의로 강제하기보다 스킴 정의와 URI 소유자가 관리해야 한다는 원칙을 설명한다.[42]
URI는 자원의 이름과 위치를 엄격하게 분리한 두 종류의 체계로 단순 분류되지 않는다. 과거에는 URL을 위치를 나타내는 URI, URN을 이름을 나타내는 URI로 설명하는 경우가 많았지만, 현대 URI 표준에서는 이 구분이 실제 사용에서 명확하지 않을 수 있다고 본다. HTTP URI도 장기간 유지되는 이름 역할을 할 수 있고, 이름처럼 보이는 식별자도 해석 서비스를 통해 위치와 연결될 수 있다.
URI와 국제화된 식별자 사이에는 IRI라는 개념도 있다. IRI는 라틴 문자 이외의 유니코드 문자를 사람이 읽을 수 있는 형태로 포함할 수 있도록 URI 문법을 확장한다. 브라우저와 네트워크 소프트웨어는 IRI를 실제 요청에 사용할 수 있는 URI나 URL 표현으로 변환할 수 있다.
URL
URL은 Uniform Resource Locator의 약자로, 자원의 위치나 접근 방법을 나타내는 URI다. 한국어로는 주로 통합 자원 위치 지정자, 균일 자원 위치 지정자 또는 간단히 웹 주소라고 한다.
일반적인 웹 URL은 자원에 접근할 프로토콜과 서버의 호스트 이름, 서버 안의 자원 경로를 포함한다.
https://www.example.com/docs/page.html
이 URL은 HTTPS를 사용하여 www.example.com 호스트의 /docs/page.html 경로에 해당하는 자원에 접근하도록 지시한다.
URL을 단순히 인터넷상의 파일 경로로 보는 것은 현대 웹 구조를 충분히 설명하지 못한다. 해당 경로는 실제 파일 시스템에 존재하는 파일과 직접 대응할 수도 있지만, 응용 프로그램의 라우팅 규칙이나 데이터베이스 조회, 서버리스 함수 또는 여러 내부 서비스에 의해 동적으로 처리될 수도 있다.
브라우저에서 사용되는 URL의 구체적인 처리 방식은 WHATWG의 URL Living Standard가 정의한다. 이 표준은 실제 웹 플랫폼에서 URL 문자열을 분석하고 직렬화하며, 호스트와 경로, 질의, 프래그먼트를 다루는 알고리즘을 규정한다.[43]
RFC 3986의 URI 문법과 WHATWG URL 표준은 관련되어 있지만 목적과 세부 처리 방식이 완전히 같지는 않다. RFC 3986은 여러 URI 스킴이 공유하는 일반적인 문법을 정의하고, WHATWG 표준은 웹 브라우저와 웹 API가 현실의 URL 입력을 일관되게 처리하는 동작을 중심으로 정의한다.
HTTP와 HTTPS URL의 일반적인 구조는 다음과 같다.
https://[email protected]:8443/docs/page?lang=ko#history
이 주소는 다음 요소로 나뉜다.
HTTP URL의 구성 요소
- 전체 URL
- 스킴:
https - 권한
- 사용자 정보:
user - 호스트:
example.com - 포트:
8443
- 경로:
/docs/page - 질의:
lang=ko - 프래그먼트:
history
HTTP URL에서 사용자 정보 구성 요소를 사용할 수는 있지만, 사용자 이름과 특히 비밀번호를 URL에 포함하는 방식은 노출 위험과 혼동 가능성이 있어 현대 웹에서는 일반적으로 사용하지 않는다.
포트 번호는 서버에서 특정 네트워크 서비스를 구분한다. HTTP의 기본 포트는 80이고 HTTPS의 기본 포트는 443이다. URL에 포트가 생략되면 스킴의 기본 포트를 사용하는 것으로 해석된다. 기본 포트가 아닌 포트를 사용할 때는 :8443처럼 명시할 수 있다.
URL은 사람이 주소창에 직접 입력하는 문자열일 뿐 아니라 HTML 링크, 이미지와 스크립트의 출처, API 요청 대상, CSS 자원 참조와 리디렉션 위치에도 사용된다. 웹 응용 프로그램은 URL을 화면 상태와 탐색 기록을 표현하는 인터페이스로 사용할 수도 있다.
URL은 자원의 물리적 위치를 항상 그대로 노출하지 않는다. 리버스 프록시, CDN과 부하 분산 시스템은 하나의 공개 URL을 여러 서버와 지역으로 연결할 수 있다. 서버 내부의 실제 저장 위치가 변경되어도 공개 URL과 응답 의미를 유지할 수 있다.
URL의 스킴과 호스트, 포트는 브라우저의 출처를 결정하는 핵심 요소다. 동일 출처 정책에서는 일반적으로 두 URL의 스킴, 호스트와 포트가 모두 같아야 같은 출처로 취급한다. 경로가 다르더라도 이 세 요소가 같다면 같은 출처에 속할 수 있다.
URL은 주소 문자열 자체와 그 주소에서 현재 반환되는 콘텐츠를 구분해야 한다. 같은 URL에서 시간이 지나며 문서 내용이 수정될 수 있고, 사용자나 요청 조건에 따라 다른 표현이 반환될 수도 있다. URL은 자원을 식별하지만 그 표현이 영원히 동일한 바이트열임을 보장하지 않는다.
도메인 이름과 DNS
도메인 이름은 인터넷의 계층적인 이름 공간에서 호스트, 서비스 또는 관리 영역을 식별하는 이름이다. www.example.com과 example.org가 도메인 이름의 예다.
도메인 이름은 일반적으로 오른쪽에서 왼쪽으로 큰 계층에서 작은 계층으로 해석된다. www.example.com에서는 com이 최상위 도메인이고, example이 그 아래에 등록된 도메인이며, www는 해당 도메인 안에서 정의된 하위 이름이다.
DNS 이름 공간의 최상위에는 이름 없는 루트가 있다. 완전한 도메인 이름은 개념적으로 마지막에 루트 레이블을 나타내는 점을 포함할 수 있다.
www.example.com.
일상적인 입력에서는 마지막 점을 생략하는 경우가 대부분이다.
DNS은 도메인 이름에 연결된 정보를 저장하고 조회하는 계층적·분산 데이터베이스 시스템이다. DNS는 도메인 이름을 IP 주소로 변환하는 기능으로 가장 잘 알려져 있지만, 메일 서버, 별칭, 권한 있는 이름 서버, 서비스 정책과 다양한 메타데이터도 저장할 수 있다.
DNS의 기본 개념과 구조는 RFC 1034에, 메시지 형식과 구현 규칙은 RFC 1035에 정의되었다.[44][45]
브라우저가 https://www.example.com/에 접근할 때는 일반적으로 먼저 www.example.com에 대응하는 네트워크 주소를 확인한다. 운영체제나 브라우저는 로컬 캐시와 설정된 재귀 DNS 해석기를 사용하며, 필요한 경우 해석기는 루트, 최상위 도메인과 해당 도메인의 권한 있는 이름 서버를 단계적으로 조회한다.
일반적인 DNS 조회 관계는 다음과 같이 나타낼 수 있다.
도메인 이름 해석 흐름
- 브라우저가 URL의 호스트 이름 확인↓
- 운영체제 또는 브라우저 캐시 검사↓
- 재귀 DNS 해석기에 질의↓
- 해석기가 캐시를 확인↓
- 필요한 경우 루트 이름 서버에 질의↓
- 최상위 도메인 이름 서버에 질의↓
- 도메인의 권한 있는 이름 서버에 질의↓
- IP 주소 또는 다른 DNS 정보 반환↓
- 클라이언트가 반환된 주소로 연결 시도
이 과정의 실제 순서는 캐시, 별칭과 해석기 구현에 따라 달라질 수 있다. DNS 응답에는 일정한 유효 기간인 TTL이 포함되며, 해석기와 클라이언트는 그 기간 동안 결과를 캐시할 수 있다.
IPv4 주소는 A 레코드, IPv6 주소는 AAAA 레코드에 저장된다. CNAME 레코드는 한 도메인 이름을 다른 정식 이름의 별칭으로 연결한다. MX 레코드는 도메인의 전자우편을 처리할 서버를 나타내며, NS 레코드는 해당 DNS 영역의 권한 있는 이름 서버를 지정한다.
현대의 HTTPS 서비스는 SVCB와 HTTPS 레코드를 사용하여 대체 서비스 주소, 지원 프로토콜과 연결 힌트를 제공할 수도 있다. 그러나 모든 웹 연결이 이러한 레코드를 사용하는 것은 아니며, 기본적인 A와 AAAA 조회도 계속 널리 사용된다.
하나의 도메인 이름은 여러 IP 주소에 연결될 수 있다. 이는 부하 분산, 장애 대응과 지역별 서버 선택에 사용된다. 반대로 하나의 IP 주소에서 여러 도메인의 웹사이트를 운영할 수도 있다. HTTP의 호스트 정보와 TLS의 서버 이름 표시를 통해 서버는 같은 주소로 들어온 요청을 서로 다른 사이트로 구분할 수 있다.
도메인 이름과 웹사이트도 일대일 관계가 아니다. 하나의 등록 도메인 아래에 www, api, static과 같은 여러 하위 도메인이 있을 수 있고, 하나의 서비스가 여러 도메인을 동시에 사용할 수도 있다.
DNS는 도메인 이름을 웹 페이지의 전체 URL로 변환하지 않는다. DNS가 주로 처리하는 것은 URL 안의 호스트 이름과 관련된 네트워크 정보다. /docs/page, ?lang=ko와 #history 같은 경로와 질의, 프래그먼트는 DNS 조회에 사용되지 않는다.
국제화 도메인 이름은 한글과 여러 문자 체계를 사람이 읽을 수 있는 도메인에 사용할 수 있게 한다. 실제 DNS 프로토콜에서는 이러한 이름을 ASCII 호환 형태로 변환하여 전달하며, 이 표현은 xn-- 접두사를 사용하는 Punycode 기반 형태로 나타날 수 있다.
국제화 도메인은 사용자 접근성을 높이지만, 서로 비슷하게 보이는 다른 문자를 이용한 피싱과 혼동 문제도 만들 수 있다. 브라우저는 보안 정책과 문자 조합에 따라 국제화된 이름을 원문으로 표시하거나 ASCII 호환 형식으로 표시할 수 있다.
DNS는 웹 주소의 지속성에도 중요한 영향을 준다. 도메인 등록을 갱신하지 않거나 다른 주체에게 이전하면 해당 도메인 아래의 모든 URL이 더 이상 기존 자원을 가리키지 않을 수 있다. 장기적인 주소 유지를 위해서는 서버 운영뿐 아니라 도메인 이름과 DNS 영역을 지속적으로 관리해야 한다.
경로, 질의 문자열과 프래그먼트
HTTP와 HTTPS URL에서 호스트 뒤의 부분은 자원과 자원 안의 상태를 더 구체적으로 나타낸다. 대표적인 구성 요소는 경로, 질의와 프래그먼트다.
https://example.com/articles/web?lang=ko&page=2#history
이 주소에서 /articles/web은 경로, lang=ko&page=2는 질의, history는 프래그먼트다.
경로는 권한 구성 요소 뒤에서 시작하며 일반적으로 /로 구분된 여러 세그먼트로 구성된다. 경로는 서버가 관리하는 URI 공간 안에서 대상을 구분한다.
/articles/web/history
경로가 파일 시스템의 디렉터리와 파일 구조처럼 보일 수 있지만 실제로 파일 시스템과 일치할 필요는 없다. 서버는 이 경로를 응용 프로그램 라우트, 데이터베이스 키, 가상 자원이나 다른 내부 서비스에 연결할 수 있다.
경로가 /로 끝나는 주소와 끝나지 않는 주소는 서로 다른 URI다. 서버는 두 주소를 같은 자원으로 처리하거나 한쪽에서 다른 쪽으로 리디렉션할 수 있지만, 클라이언트가 임의로 동일하다고 가정해서는 안 된다.
경로 안의 점 세그먼트인 .과 ..는 상대 참조를 해석할 때 현재 단계와 상위 단계를 나타낸다. 브라우저와 URL 처리기는 기준 URL과 상대 경로를 결합하면서 이러한 세그먼트를 정규화한다.
경로의 대소문자 구분 여부는 URL 스킴과 서버 구현에 영향을 받는다. HTTP 호스트 이름은 대소문자를 구분하지 않지만, 경로는 서버에 따라 대소문자를 구분할 수 있다. 따라서 /Document와 /document가 같은 자원이라고 일반화할 수 없다.
질의 문자열은 URL의 ? 뒤에서 시작하고 #이나 URL의 끝까지 이어진다. 질의는 자원에 전달할 추가 입력이나 선택 조건을 나타낼 수 있다.
?lang=ko&page=2
웹 애플리케이션에서는 여러 값을 이름=값 형태로 작성하고 &로 구분하는 방식이 널리 사용된다. 그러나 URI 일반 문법은 질의 구성 요소 전체의 위치를 정의할 뿐, 모든 질의가 반드시 키와 값의 쌍이어야 한다고 규정하지는 않는다. 질의 내부의 구체적인 의미는 해당 웹 서비스가 정한다.
질의는 검색어, 페이지 번호, 정렬 방식, 필터와 API 매개변수를 전달하는 데 사용된다. 같은 경로에 서로 다른 질의를 붙인 URL은 일반적으로 서로 다른 URI로 취급되며, 서버는 질의에 따라 다른 표현을 반환할 수 있다.
질의 문자열은 브라우저 기록, 서버 로그, 프록시와 분석 시스템에 남을 수 있다. 링크로 공유되거나 다른 사이트에 전달될 가능성도 있으므로 비밀번호, 인증 토큰과 민감한 개인정보를 질의에 직접 포함하는 것은 피하는 편이 좋다.
HTTP 요청에서 질의는 서버에 전달된다. 서버와 중간 시스템은 질의를 사용하여 응답을 생성하고 캐시 키를 구분할 수 있다. 매개변수 순서와 중복 값의 의미는 응용 프로그램마다 다를 수 있으므로 임의의 정렬이나 제거가 안전하지 않을 수 있다.
프래그먼트는 URL의 # 뒤에 위치하며 자원의 표현 안에서 특정 부분이나 상태를 식별한다.
#history
HTML 문서에서는 프래그먼트가 특정 id를 가진 요소를 가리키는 경우가 일반적이다. 브라우저는 문서를 받은 뒤 해당 요소로 화면을 이동하거나 초점을 맞출 수 있다.
프래그먼트는 일반적인 HTTP 요청 대상에 포함되지 않으며 서버로 전송되지 않는다. 브라우저는 # 앞의 URL로 자원을 요청하고, 응답으로 받은 표현에 대해 프래그먼트를 로컬에서 해석한다. 따라서 같은 문서의 프래그먼트 사이를 이동할 때 새 네트워크 요청이 필요하지 않을 수 있다.
프래그먼트의 의미는 반환된 표현의 미디어 유형에 따라 달라질 수 있다. HTML에서는 요소 식별자를 가리킬 수 있고, SVG에서는 특정 그래픽 뷰나 요소를, 미디어 형식에서는 시간 구간이나 다른 내부 부분을 표현할 수 있다.
JavaScript 기반 웹 애플리케이션은 프래그먼트를 화면 상태나 클라이언트 측 경로를 나타내는 데 사용해 왔다. #/settings와 같은 형태는 서버 요청 없이 브라우저 안에서 화면을 전환하는 데 사용될 수 있다. 현대 응용 프로그램은 History API와 일반 경로를 사용하는 경우도 많다.
경로, 질의와 프래그먼트는 다음과 같은 처리 범위를 가진다.
URL 구성 요소의 처리 범위
- 경로
- HTTP 요청 대상에 포함
- 서버가 자원이나 라우트를 선택
- 응용 프로그램 내부 구조와 반드시 일치하지는 않음
- 질의
- HTTP 요청 대상에 포함
- 서버에 추가 조건이나 입력 전달
- 구체적인 형식과 의미는 서비스가 정의
- 프래그먼트
- 일반적으로 HTTP 요청에 포함되지 않음
- 클라이언트가 표현을 받은 뒤 해석
- 문서 내부 위치나 클라이언트 상태 식별
URL에서 ?와 #는 구성 요소의 경계를 나타낸다. 이 문자를 데이터 자체로 사용해야 할 때는 해당 문맥의 문법에 따라 퍼센트 인코딩이 필요할 수 있다.
영구 식별자와 링크 안정성
웹에서 주소는 다른 문서, 검색 엔진, 브라우저 북마크, 논문, 소프트웨어와 데이터베이스에 복제된다. 한번 공개된 URL은 운영자가 파악할 수 없는 수많은 외부 위치에서 참조될 수 있으므로, 주소 변경은 해당 사이트 내부의 문제에 그치지 않는다.
주소가 더 이상 기존 자원에 연결되지 않는 현상을 일반적으로 링크 부패라고 한다. 서버가 사라지거나 도메인이 만료되는 경우, 문서가 삭제되는 경우, 경로 구조가 바뀌는 경우와 리디렉션이 유지되지 않는 경우에 발생할 수 있다.
같은 URL이 시간이 지나며 전혀 다른 대상을 가리키게 되는 현상은 콘텐츠 변질 또는 문맥에 따라 content drift라고 할 수 있다. 주소가 응답을 계속 반환하더라도 원래 인용한 내용을 더 이상 나타내지 않으면 과거 기록과 검증 가능성이 손상된다.
영구 식별자는 자원의 저장 위치나 관리 시스템이 바뀌어도 장기간 같은 대상을 식별하도록 운영되는 식별자다. DOI, Handle, ARK, PURL과 일부 URN 체계가 대표적인 예다. 이러한 식별자는 현재의 접근 위치와 분리된 이름을 제공하고, 별도의 해석 시스템이 실제 URL로 연결할 수 있다.
영구 식별자는 특별한 문자열 형식만으로 영구성이 자동 보장되는 것은 아니다. 식별자 등록 정보를 유지하고, 자원 이동 시 새로운 위치를 갱신하며, 운영 조직과 도메인을 장기간 관리하는 정책과 제도가 필요하다.
HTTP URL 자체도 영구 식별자로 사용할 수 있다. W3C의 웹 아키텍처 자료는 URI의 지속성이 기술적 제약보다는 URI를 부여한 관리 주체의 정책과 약속에 달려 있다고 설명한다.[46]
팀 버너스리는 주소 설계 지침에서 좋은 URI는 변경되지 않는 URI라고 설명하였다. 문서의 상태, 현재 담당 조직, 서버 제품, 파일 확장자와 임시 디렉터리를 주소에 과도하게 노출하면 시스템 개편 때 주소를 바꿔야 할 가능성이 커진다.[47]
링크 안정성을 높이려면 주소를 물리적인 파일 구조보다 논리적인 자원 구조에 맞추는 것이 유리하다.
/products/widget
이 주소는 다음과 같은 내부 위치보다 구현 변경에 덜 의존할 수 있다.
/server2/php/products/widget.php
다만 짧고 보기 좋은 URL 자체가 지속성을 보장하지는 않는다. 실제 안정성은 도메인과 라우팅 규칙, 리디렉션 및 콘텐츠 관리 정책을 얼마나 오래 유지하는지에 달려 있다.
주소를 변경해야 할 때는 이전 URL에서 새 URL로 적절한 HTTP 리디렉션을 제공할 수 있다. 영구적인 이동에는 일반적으로 301 Moved Permanently 또는 요청 메서드 보존이 필요한 경우 308 Permanent Redirect를 사용할 수 있다.
리디렉션은 기존 링크와 북마크를 새 위치로 연결하고 검색 엔진이 주소 변경을 이해하도록 돕는다. 그러나 리디렉션도 장기적으로 유지해야 하며, 여러 차례의 사이트 개편으로 긴 리디렉션 체인이 만들어지면 성능과 관리 복잡성이 증가한다.
자원이 삭제되었고 대체 위치가 없다면 서버는 404 Not Found 또는 영구적으로 제거되었음을 나타내는 410 Gone을 반환할 수 있다. 관련 없는 홈페이지로 모두 리디렉션하면 사용자는 요청한 자료가 존재하는지 판단하기 어려워질 수 있다.
문서의 최신판과 특정 판본을 구분하는 주소 체계도 필요할 수 있다. 최신 내용을 계속 제공하는 URL과 변경되지 않는 버전별 URL을 함께 제공하면 일반 독자와 장기 인용의 요구를 모두 지원할 수 있다.
/specification/latest
/specification/2026-08-03
최신판 URL은 시간이 지나며 표현이 변경되고, 버전별 URL은 해당 시점의 내용을 유지하도록 운영할 수 있다. 실제 주소 형태는 사이트의 정책에 따라 다르다.
정규 URL인 canonical URL은 내용이 동일하거나 매우 비슷한 여러 URL 가운데 대표로 사용할 주소를 지정한다. HTML의 link rel="canonical"이나 HTTP Link 헤더는 검색 엔진과 다른 처리기에 선호하는 URL을 알리는 데 사용될 수 있다. 그러나 canonical 표시는 리디렉션이나 접근 제어를 대신하지 않으며, 다른 URL의 존재 자체를 제거하지도 않는다.
웹 보존 시스템은 사라지거나 변경되는 자원의 과거 표현을 저장하여 링크 부패의 영향을 줄일 수 있다. 다만 보관된 복사본이 원본과 같은 권위와 접근 권한을 가지는 것은 아니며, 동적 응용 프로그램과 인증된 콘텐츠는 완전하게 보존하기 어렵다.
지속 가능한 주소 체계는 다음 요소를 함께 필요로 한다.
링크 안정성을 위한 구성 요소
- 안정적인 식별자 설계
- 내부 서버와 파일 구조에 대한 의존 최소화
- 자원의 논리적 의미를 기준으로 주소 부여
- 같은 URI를 다른 대상에 재사용하지 않음
- 지속적인 운영
- 도메인 등록과 DNS 유지
- 서버와 콘텐츠 관리
- 조직 개편 이후에도 식별자 정책 계승
- 주소 변경 관리
- 이전 주소에서 영구 리디렉션 제공
- 리디렉션 체인 최소화
- 삭제된 자원에 적절한 상태 코드 반환
- 인용과 보존
- 최신판과 고정 버전 주소 구분
- DOI·Handle 등 영구 식별자 활용
- 웹 아카이브와 변경 이력 제공
웹 주소의 영구성은 완전히 기술적인 문제가 아니다. 조직이 사라지거나 도메인 소유권이 변경되고, 법적·재정적 이유로 자료 제공이 중단될 수 있다. 그럼에도 처음부터 장기간 유지할 주소를 설계하고 이전 식별자를 보존하면 웹의 연결성과 인용 가능성을 크게 높일 수 있다.
통신과 자원 전송
World Wide Web에서 클라이언트와 서버는 주로 HTTP를 사용하여 자원에 관한 요청과 응답을 교환한다. HTTP는 특정한 문서 형식이나 서버 구현에 종속되지 않으며, HTML 문서뿐 아니라 이미지, 영상, 프로그램 파일, JSON 데이터와 스트리밍 콘텐츠를 전송할 수 있다.
HTTP는 자원의 식별과 메시지의 의미를 정의하고, 각 프로토콜 버전은 그 의미를 네트워크 연결 위에서 표현하는 방식을 정의한다. HTTP/1.1은 텍스트 기반 메시지 구문과 지속 연결을 사용하고, HTTP/2는 하나의 연결에서 여러 스트림을 다중화하며, HTTP/3은 QUIC 위에서 HTTP 의미론을 전달한다.
HTTPS는 HTTP 통신에 TLS를 적용하여 연결을 암호화하고 무결성을 보호하며 서버 인증을 제공한다. 현대의 공개 웹에서는 HTTPS가 일반적인 전송 방식이지만, HTTPS가 웹사이트의 콘텐츠 자체를 보증하거나 서버 내부에 저장된 데이터까지 자동으로 보호하는 것은 아니다.
HTTP의 성능과 의미는 메서드, 상태 코드, 헤더, 메시지 콘텐츠, 연결 관리와 캐시 정책의 조합으로 결정된다. 클라이언트와 서버뿐 아니라 프록시, 콘텐츠 전송 네트워크와 브라우저 캐시도 이러한 공통 규칙을 해석하여 요청을 전달하거나 저장된 응답을 재사용한다.
HTTP
HTTP는 Hypertext Transfer Protocol의 약자로, 분산된 협업형 하이퍼텍스트 정보 시스템을 위한 상태 비저장 응용 계층 프로토콜이다. 웹 브라우저와 웹 서버 사이의 문서 전송을 위해 시작되었지만, 현재는 웹 API, 프로그램 간 통신, 소프트웨어 저장소와 미디어 전송 등에도 널리 사용된다.[48]
HTTP에서 통신은 일반적으로 클라이언트가 요청을 보내고 서버가 응답을 반환하는 형태로 이루어진다. 요청은 대상 자원, 수행하려는 메서드, 헤더 필드와 선택적인 콘텐츠를 포함한다. 응답은 처리 결과를 나타내는 상태 코드, 헤더 필드와 선택적인 콘텐츠를 포함한다.
HTTP는 전송되는 자원의 내용을 직접 규정하지 않는다. 응답 콘텐츠가 HTML인지, JSON인지, 이미지인지 또는 압축 파일인지는 Content-Type과 같은 표현 메타데이터와 응용 프로그램의 규칙으로 결정된다. 따라서 HTTP는 특정 파일 형식의 전송 규약이라기보다 자원에 대한 상호작용과 메시지 의미를 제공하는 범용 프로토콜에 가깝다.
HTTP의 상태 비저장성은 각 요청이 프로토콜 차원에서 독립적으로 해석될 수 있음을 뜻한다. 서버는 앞선 요청에서 사용한 연결이나 암묵적 순서를 기억해야만 현재 요청을 이해하도록 요구되지 않는다. 그러나 웹 애플리케이션은 쿠키, 세션 식별자, 인증 토큰과 서버 측 저장소를 사용하여 여러 요청에 걸친 사용자 상태를 유지할 수 있다.
HTTP는 확장 가능한 프로토콜이다. 새로운 헤더 필드, 메서드와 상태 코드가 등록될 수 있으며, 클라이언트와 서버는 자신이 이해하지 못하는 확장을 처리하는 일반적인 규칙을 따른다. 이러한 확장성은 HTTP가 초기의 단순한 하이퍼텍스트 전송을 넘어 다양한 응용 시스템에 사용될 수 있었던 기반이다.
HTTP의 의미론과 전송 형식은 분리되어 있다. GET, POST, 200 OK, 캐시 제어와 콘텐츠 유형의 의미는 HTTP 버전에 공통으로 적용된다. HTTP/1.1, HTTP/2와 HTTP/3는 이러한 의미를 서로 다른 메시지 프레이밍과 연결 방식으로 전달한다.
HTTP 자원은 일반적으로 http 또는 https URI로 식별된다. 클라이언트는 URI의 스킴, 호스트, 포트, 경로와 질의를 이용하여 요청 대상을 구성한다. 프래그먼트는 일반적인 HTTP 요청에 포함되지 않으며 표현을 받은 클라이언트가 해석한다.
HTTP 요청은 원본 서버에 직접 전달될 수도 있고 프록시, 게이트웨이, 캐시와 CDN을 거칠 수도 있다. 중간 시스템도 메서드와 상태 코드, 캐시 지시문을 이해할 수 있기 때문에 응용 프로그램의 내부 의미를 모두 알지 못해도 메시지를 전달하거나 재사용할 수 있다.
HTTPS와 TLS
HTTPS는 HTTP를 TLS로 보호하여 사용하는 방식이다. HTTPS URL은 https 스킴을 사용하며, 기본 포트는 443이다. HTTPS는 HTTP와 별개의 콘텐츠 형식이 아니라 HTTP 의미론을 인증되고 암호화된 연결 위에서 전달한다.
TLS는 클라이언트와 서버 사이의 통신에 다음과 같은 보안 속성을 제공하도록 설계되었다.
- 기밀성: 연결을 관찰하는 제3자가 응용 데이터를 읽기 어렵게 한다.
- 무결성: 전송 중 데이터가 탐지되지 않은 채 변경되는 것을 방지한다.
- 인증: 클라이언트가 연결한 서버가 대상 도메인에 대한 인증서를 보유하는지 확인한다.
TLS 1.3은 인터넷상의 클라이언트와 서버가 도청, 변조와 메시지 위조를 방지하도록 통신하는 프로토콜로 정의된다.[49]
HTTPS 연결을 시작할 때 클라이언트와 서버는 TLS 핸드셰이크를 수행한다. 이 과정에서 지원하는 TLS 버전과 암호 알고리즘을 협상하고, 서버가 인증서를 제시하며, 양측이 응용 데이터를 보호할 세션 키를 생성한다.
서버 인증서는 서버의 공개 키와 도메인 이름, 유효 기간, 발급자 등의 정보를 포함한다. 브라우저는 인증서의 서명 체인을 신뢰할 수 있는 인증 기관까지 검증하고, 인증서에 현재 접속한 호스트 이름이 포함되어 있는지 확인한다.
인증서 검증이 성공했다는 것은 연결한 서버가 해당 도메인을 통제한다는 근거를 제공한다. 이는 사이트 운영자가 제공하는 정보가 사실이거나, 서비스가 안전한 거래 상대이거나, 내려받는 파일에 악성 코드가 없다는 보증은 아니다.
일반적인 공개 HTTPS 연결은 서버만 인증하지만, 서버가 클라이언트 인증서를 요구하여 양방향 인증을 구성할 수도 있다. 클라이언트 인증서는 기업 내부 시스템, 장치 인증과 고보안 환경에서 사용될 수 있으나 일반 소비자 웹사이트에서는 계정 비밀번호나 토큰 기반 인증이 더 흔하다.
TLS는 HTTP 헤더와 콘텐츠를 암호화하지만 모든 네트워크 정보를 숨기지는 않는다. 통신 상대의 IP 주소, 전송 시각과 데이터 양 같은 메타데이터는 네트워크에서 관찰될 수 있다. DNS 조회가 별도로 암호화되지 않았다면 조회한 도메인 이름도 노출될 수 있다.
TLS 연결이 CDN이나 리버스 프록시에서 종료될 수도 있다. 이 경우 브라우저와 해당 중간 시스템 사이의 연결은 보호되지만, 중간 시스템은 복호화된 HTTP 요청을 처리할 수 있다. 중간 시스템과 원본 서버 사이에는 별도의 TLS 연결을 구성할 수 있다.
HTTPS는 전송 중인 데이터를 보호하지만 서버에 도착한 이후의 저장 데이터나 브라우저 화면에 표시된 정보까지 계속 암호화하는 것은 아니다. 서버 침해, 악성 스크립트, 취약한 계정 인증과 사용자의 단말기 문제는 별도의 보안 대책이 필요하다.
TLS 1.3은 이전 버전보다 핸드셰이크 절차를 단순화하고 오래된 암호 알고리즘을 제거하였다. 이전에 연결한 서버와의 세션 재개에서는 0-RTT 초기 데이터를 사용할 수 있지만, 0-RTT 데이터는 재전송 공격 가능성을 고려해야 하므로 모든 요청에 적합하지 않다.
HTTP/3은 QUIC 내부에 TLS 1.3의 보안 절차를 통합한다. 따라서 HTTP/3 연결은 프로토콜 설계상 암호화된 형태로 사용된다. HTTP/2도 공개 웹에서는 대부분 TLS와 함께 사용되지만, HTTP/2 명세 자체에는 TLS를 사용하지 않는 연결 방식도 정의되어 있다.
일반적인 HTTPS 연결 흐름
- 클라이언트가 HTTPS URL 해석↓
- DNS를 통해 서버 주소 조회↓
- 서버와 TCP 또는 QUIC 연결 시작↓
- TLS 버전과 암호 매개변수 협상↓
- 서버 인증서와 도메인 이름 검증↓
- 공유 세션 키 생성↓
- 암호화된 HTTP 요청과 응답 교환
HTTP 메서드와 상태 코드
HTTP 메서드는 클라이언트가 대상 자원에 대해 수행하려는 작업의 의미를 나타낸다. 상태 코드는 서버가 요청을 이해하고 처리한 결과를 세 자리 숫자로 표현한다. 메서드와 상태 코드는 응용 프로그램뿐 아니라 캐시, 프록시와 자동화된 클라이언트도 공통으로 이해할 수 있는 의미를 제공한다.
GET은 대상 자원의 현재 표현을 요청한다. 일반적인 웹 페이지, 이미지와 API 데이터 조회에 사용된다. GET 요청은 안전한 메서드로 정의되며, 요청 자체가 서버의 의도된 상태 변경을 요구하지 않는다.
안전하다는 것은 서버에서 로그 기록, 통계 증가나 캐시 갱신 같은 부수 효과가 전혀 없다는 의미가 아니다. 클라이언트가 요청한 의미가 읽기 중심이며, 사용자가 링크를 선택하거나 크롤러가 요청해도 자원의 상태 변경을 의도하지 않는다는 뜻이다.
HEAD는 서버가 GET 요청에 반환했을 헤더를 요청하지만 응답 콘텐츠를 포함하지 않는다. 자원의 존재 여부, 크기, 수정 시각과 캐시 검증 정보를 확인하는 데 사용할 수 있다.
POST는 대상 자원이 정의한 방식으로 콘텐츠를 처리하도록 요청한다. 폼 제출, 새 게시물 작성, 결제 요청, 명령 실행과 API 작업 등에 사용될 수 있다. POST의 결과는 새로운 자원 생성일 수도 있고 기존 자원의 처리 결과일 수도 있다.
PUT은 요청 콘텐츠로 대상 자원의 상태를 생성하거나 완전히 대체하도록 요청한다. 클라이언트가 대상 URI를 알고 있으며, 같은 요청을 반복해도 의도된 최종 상태가 같다는 멱등성을 가진다.
PATCH는 자원의 일부를 변경하기 위한 변경 명령이나 부분 표현을 전달한다. PUT과 달리 전체 표현을 교체하지 않을 수 있으며, 구체적인 패치 문서 형식은 미디어 유형과 API가 정의한다.
DELETE는 대상 자원과 현재 기능 사이의 연결을 제거하도록 요청한다. 서버가 내부 데이터를 즉시 물리적으로 삭제해야 한다는 뜻은 아니며, 삭제 권한과 보존 정책은 서버가 결정한다.
OPTIONS는 대상 자원이나 서버가 지원하는 통신 선택 사항을 확인한다. 브라우저는 교차 출처 요청에서 실제 요청 전에 허용되는 메서드와 헤더를 확인하는 CORS 사전 요청에 OPTIONS를 사용할 수 있다.
CONNECT는 요청 대상까지 터널을 구성한다. HTTP 프록시를 통해 HTTPS 서버로 연결할 때 사용될 수 있으며, 터널이 만들어진 뒤 프록시는 일반적으로 내부의 TLS 응용 데이터를 HTTP 메시지로 해석하지 않고 전달한다.
TRACE는 요청이 중간 시스템을 거치며 어떻게 전달되는지 진단하기 위한 루프백 기능을 제공한다. 보안상 이유로 공개 서버에서 비활성화되는 경우가 많다.
HTTP 메서드는 안전성, 멱등성과 캐시 가능성이라는 속성으로도 구분된다.
- 안전한 메서드는 읽기와 진단처럼 서버 상태 변경을 요청하지 않는다.
- 멱등 메서드는 같은 요청을 여러 번 보내도 의도된 최종 효과가 한 번 보낸 것과 같다.
- 캐시 가능성은 메서드뿐 아니라 응답 상태와 명시적인 캐시 정책에 따라 결정된다.
GET, HEAD, OPTIONS와 TRACE는 안전한 메서드다. PUT과 DELETE는 안전하지 않지만 멱등이다. POST와 PATCH는 일반적으로 멱등성이 보장되지 않는다. 다만 특정 API가 별도의 식별자와 규칙을 통해 멱등 동작을 제공할 수 있다.[50]
응답 상태 코드는 첫 번째 숫자에 따라 다섯 범주로 나뉜다.
1xx 정보 응답
1xx 상태 코드는 요청 처리가 계속 진행 중이거나 연결을 전환하기 위한 중간 정보를 전달한다.
100 Continue은 요청 헤더를 받은 서버가 클라이언트에 요청 콘텐츠를 계속 보내도 된다고 알린다. 큰 파일을 전송하기 전에 서버가 요청을 받아들일 가능성을 확인하는 데 사용될 수 있다.
101 Switching Protocols는 서버가 클라이언트의 요청에 따라 프로토콜을 전환함을 나타낸다. WebSocket의 HTTP/1.1 핸드셰이크에서 사용된다.
103 Early Hints는 최종 응답 전에 링크 정보를 보내 브라우저가 스타일시트와 다른 자원의 사전 로드를 시작하게 할 수 있다.
2xx 성공 응답
2xx 상태 코드는 요청이 성공적으로 수신되고 이해되어 처리되었음을 나타낸다.
200 OK는 일반적인 성공 응답이다. GET에서는 요청한 표현이 콘텐츠에 포함되고, 다른 메서드에서는 처리 결과가 포함될 수 있다.
201 Created는 요청이 처리되어 하나 이상의 자원이 생성되었음을 나타낸다. 새 자원의 URI는 Location 헤더로 제공할 수 있다.
202 Accepted는 요청이 처리를 위해 수락되었지만 아직 완료되지 않았음을 나타낸다. 비동기 작업이나 대기열 기반 처리에 사용할 수 있다.
204 No Content는 요청이 성공했지만 응답 콘텐츠가 없음을 나타낸다. 현재 문서를 다시 불러오지 않고 서버 상태만 갱신할 때 사용할 수 있다.
206 Partial Content는 범위 요청에 따라 자원의 일부만 반환했음을 나타낸다. 대용량 다운로드의 재개와 미디어 스트리밍에 활용된다.
3xx 리디렉션 응답
3xx 상태 코드는 요청을 완료하기 위해 다른 위치를 사용하거나 저장된 표현을 재사용해야 함을 나타낸다.
301 Moved Permanently는 자원이 새로운 URI로 영구 이동했음을 나타낸다. 클라이언트와 검색 엔진은 새 URI를 이후의 참조 대상으로 사용할 수 있다.
302 Found는 자원이 일시적으로 다른 URI에서 제공됨을 나타낸다. 역사적인 구현 차이 때문에 일부 클라이언트는 POST 요청 뒤의 메서드를 GET으로 바꾸어 처리한다.
303 See Other는 처리 결과를 다른 URI의 GET 요청으로 확인하도록 명시한다. 폼을 제출한 뒤 결과 페이지로 이동하는 패턴에 사용할 수 있다.
304 Not Modified는 조건부 GET 또는 HEAD 요청에서 저장된 표현이 여전히 유효함을 나타낸다. 응답 콘텐츠 없이 캐시된 표현을 재사용하게 한다.
307 Temporary Redirect와 308 Permanent Redirect는 각각 일시적·영구적 이동을 나타내며, 리디렉션 이후에도 원래 요청 메서드와 콘텐츠를 유지하도록 규정한다.
4xx 클라이언트 오류
4xx 상태 코드는 요청 구문, 인증, 권한, 대상 자원이나 요청 조건에 문제가 있음을 나타낸다.
400 Bad Request는 서버가 잘못된 구문이나 메시지 프레이밍 등의 이유로 요청을 처리할 수 없음을 나타낸다.
401 Unauthorized는 실제 의미상 인증이 필요하거나 제공된 인증 정보가 유효하지 않음을 나타낸다. 응답은 사용할 인증 방식을 WWW-Authenticate 헤더로 제시할 수 있다.
403 Forbidden은 서버가 요청을 이해했지만 처리를 거부했음을 나타낸다. 인증된 사용자에게도 권한이 없거나 정책상 접근을 허용하지 않을 때 사용할 수 있다.
404 Not Found는 대상 자원의 현재 표현을 찾지 못했거나 서버가 그 존재를 공개하지 않으려는 경우에 사용될 수 있다.
405 Method Not Allowed는 대상 자원은 존재하지만 요청 메서드를 지원하지 않음을 나타낸다. 서버는 허용되는 메서드를 Allow 헤더로 알릴 수 있다.
409 Conflict는 요청이 자원의 현재 상태와 충돌하여 완료되지 못했음을 나타낸다. 버전 충돌과 중복 식별자 등에 사용할 수 있다.
410 Gone은 대상 자원이 의도적으로 제거되었으며 전달할 새 주소가 없을 가능성이 높음을 나타낸다.
413 Content Too Large는 요청 콘텐츠가 서버의 처리 한도를 초과했음을 나타낸다.
415 Unsupported Media Type은 서버가 요청 콘텐츠의 미디어 유형이나 인코딩을 지원하지 않음을 나타낸다.
429 Too Many Requests는 클라이언트가 일정 기간에 너무 많은 요청을 보냈음을 나타낸다. 다시 시도할 시점을 Retry-After 헤더로 제공할 수 있다.
5xx 서버 오류
5xx 상태 코드는 서버가 유효해 보이는 요청을 처리하는 과정에서 실패했음을 나타낸다.
500 Internal Server Error는 구체적으로 분류되지 않은 서버 내부 오류를 나타낸다.
501 Not Implemented는 서버가 요청을 처리하는 데 필요한 기능이나 메서드를 지원하지 않음을 나타낸다.
502 Bad Gateway는 게이트웨이나 프록시가 상위 서버에서 유효하지 않은 응답을 받았음을 나타낸다.
503 Service Unavailable은 과부하나 유지보수로 서버가 일시적으로 요청을 처리할 수 없음을 나타낸다. 복구 예상 시점을 Retry-After 헤더로 전달할 수 있다.
504 Gateway Timeout은 게이트웨이나 프록시가 상위 서버에서 정해진 시간 안에 응답을 받지 못했음을 나타낸다.
상태 코드는 응용 프로그램의 세부 오류를 모두 표현하지 않는다. 서버는 상태 코드와 함께 사람이 읽을 수 있는 HTML 오류 문서나 프로그램이 해석할 수 있는 JSON 오류 정보를 반환할 수 있다. 다만 일반 HTTP 구성 요소가 이해할 수 있도록 상태 코드의 표준 의미를 유지하는 것이 중요하다.[51]
헤더와 메시지 본문
HTTP 메시지는 제어 정보인 헤더 필드와 선택적인 콘텐츠로 구성된다. HTTP/1.1에서는 시작 줄과 텍스트 형태의 헤더가 사용되고, HTTP/2와 HTTP/3에서는 같은 의미가 이진 프레임과 압축된 필드 블록으로 전달된다.
헤더 필드는 메시지, 요청 대상, 응답, 표현과 연결에 관한 메타데이터를 전달한다. 하나의 헤더 필드는 이름과 값으로 구성되며, 필드 이름은 대소문자를 구분하지 않는다.
요청 헤더는 클라이언트의 요구와 요청 조건을 전달한다. 대표적인 요청 헤더에는 다음과 같은 것이 있다.
Accept: 클라이언트가 선호하거나 처리할 수 있는 응답 미디어 유형Accept-Language: 선호하는 자연어Accept-Encoding: 처리할 수 있는 콘텐츠 인코딩Authorization: 서버 인증에 사용할 자격 정보Cookie: 이전에 서버가 설정한 쿠키If-None-Match: 캐시 검증에 사용할 엔터티 태그If-Modified-Since: 지정 시각 이후 변경 여부를 확인하는 조건Range: 자원의 특정 바이트 범위 요청Referer: 현재 요청이 시작된 이전 자원의 URI 정보User-Agent: 요청한 소프트웨어에 관한 정보
응답 헤더는 처리 결과와 반환되는 표현, 캐시와 인증 정책을 전달한다.
Content-Type: 콘텐츠의 미디어 유형과 선택적인 문자 인코딩Content-Length: 전송되는 콘텐츠의 길이Content-Encoding: gzip, br과 같이 표현에 적용된 인코딩Cache-Control: 캐시 저장과 재사용 정책ETag: 표현의 특정 버전을 나타내는 검증자Last-Modified: 자원이 마지막으로 수정된 시각Location: 생성된 자원 또는 리디렉션 대상 URISet-Cookie: 클라이언트가 저장할 쿠키WWW-Authenticate: 사용할 수 있는 서버 인증 방식Vary: 응답 선택에 영향을 준 요청 헤더Content-Security-Policy: 브라우저가 콘텐츠를 불러오고 실행할 출처 정책
일부 헤더는 요청과 응답 양쪽에서 사용될 수 있다. Date, Cache-Control과 콘텐츠 협상 관련 필드는 메시지 문맥에 따라 서로 다른 역할을 가질 수 있다.
HTTP에서 과거에 메시지 본문, 페이로드 본문과 엔터티 본문이라는 용어가 혼용되었지만, 현재 명세는 메시지 프레이밍과 의미상의 콘텐츠를 구분한다. 콘텐츠는 HTTP 메시지가 전달하는 표현 데이터나 처리 입력을 뜻한다.
요청 콘텐츠는 폼 데이터, JSON 문서, 업로드 파일, XML 메시지와 바이너리 데이터일 수 있다. POST, PUT과 PATCH에서 흔히 사용되지만, 메서드별 콘텐츠의 의미는 해당 메서드와 자원이 정의한다.
응답 콘텐츠는 요청한 자원의 표현이나 작업 결과, 오류 설명을 포함할 수 있다. HEAD, 204 No Content, 304 Not Modified와 일부 상태 코드에서는 응답 콘텐츠를 포함하지 않는다.
Content-Type은 콘텐츠를 어떻게 해석해야 하는지 나타낸다. HTML 문서는 text/html, JSON은 application/json, PNG 이미지는 image/png와 같은 미디어 유형을 사용한다. 콘텐츠의 실제 형식과 Content-Type이 일치하지 않으면 잘못된 표시나 보안 문제가 발생할 수 있다.
Content-Encoding은 원래 표현에 추가로 적용한 인코딩을 나타낸다. 서버가 HTML을 Brotli로 압축했다면 미디어 유형은 여전히 text/html이고 Content-Encoding: br이 추가된다. 클라이언트는 먼저 콘텐츠 인코딩을 해제한 뒤 미디어 유형에 따라 표현을 해석한다.
HTTP/1.1에서는 메시지 길이를 Content-Length, 청크 전송 코딩 또는 연결 종료 등으로 결정한다. 메시지 길이 해석이 송신자와 중간 시스템 사이에서 다르면 요청 밀수와 응답 분할 같은 보안 문제가 발생할 수 있으므로 명세는 엄격한 파싱 규칙을 요구한다.[52]
HTTP/2와 HTTP/3에서는 헤더와 콘텐츠가 별도의 프레임으로 전달된다. 하나의 메시지 콘텐츠가 여러 DATA 프레임으로 나뉠 수 있지만, 응용 프로그램에는 같은 HTTP 요청이나 응답으로 제공된다.
연결 관리와 HTTP의 발전
초기 HTTP는 하나의 요청을 보내고 응답을 받은 뒤 연결을 종료하는 단순한 형태였다. 웹 페이지가 텍스트 문서 몇 개로 구성되던 환경에서는 구현하기 쉬웠지만, 이미지와 스타일시트가 늘면서 자원마다 새 연결을 만드는 비용이 커졌다.
HTTP/0.9
초기의 HTTP는 이후 HTTP/0.9라고 불리게 되었다. 클라이언트는 한 줄의 GET 요청을 보내고 서버는 HTML 문서를 반환하였다. 상태 코드와 헤더가 없었으며, 요청 하나가 끝나면 연결도 종료되었다.
HTTP/0.9는 단순한 하이퍼텍스트 문서를 가져오는 데 적합했지만 콘텐츠 형식, 오류 상태, 캐시 정책과 메타데이터를 표현하기 어려웠다.
HTTP/1.0
HTTP/1.0은 요청과 응답 헤더, 상태 코드, 여러 메서드와 미디어 유형을 도입하여 웹이 HTML 이외의 자원을 전달할 수 있게 하였다. RFC 1945는 당시 여러 구현에서 사용하던 HTTP/1.0의 공통 동작을 기록하였다.
HTTP/1.0에서도 일반적으로 요청마다 TCP 연결을 새로 만들었다. 하나의 페이지가 여러 이미지를 포함하면 연결 설정과 종료가 반복되어 지연과 서버 부하가 증가하였다. 일부 구현은 Connection: keep-alive 확장을 사용해 연결을 재사용했지만 표준화된 기본 동작은 아니었다.
HTTP/1.1
HTTP/1.1은 지속 연결을 기본값으로 하여 하나의 TCP 연결에서 여러 요청과 응답을 순차적으로 처리할 수 있게 하였다. Host 헤더를 필수화하여 하나의 IP 주소에서 여러 도메인의 웹사이트를 운영하는 가상 호스팅도 보편화하였다.
청크 전송 코딩은 서버가 전체 콘텐츠 길이를 미리 알지 못해도 데이터를 나누어 전송할 수 있게 하였다. 캐시 제어, 조건부 요청, 범위 요청과 콘텐츠 협상 규칙도 확장되었다.
HTTP/1.1은 하나의 연결에서 앞선 응답이 완료되기 전에 여러 요청을 보내는 파이프라이닝을 정의했지만, 오류 처리와 중간 시스템 호환성 문제로 브라우저에서는 널리 활성화되지 않았다.
브라우저는 여러 자원을 병렬로 받기 위해 같은 서버에 여러 TCP 연결을 만드는 방식으로 성능을 보완하였다. 이 방식은 연결 수와 서버 자원을 증가시키고, 각 연결에서 혼잡 제어가 별도로 작동하는 문제를 만들었다.
현재 HTTP/1.1의 메시지 구문, 파싱과 연결 관리는 RFC 9112에 정의되어 있다.[53]
HTTP/2
HTTP/2는 HTTP 메서드와 상태 코드, URI와 헤더의 의미를 변경하지 않고 전송 방식을 이진 프레이밍 계층으로 교체하였다. 하나의 연결 안에 여러 독립적인 스트림을 만들고 요청과 응답 프레임을 서로 교차하여 전송할 수 있다.
스트림 다중화는 하나의 느린 응답이 응용 계층에서 다른 모든 요청의 전송 순서를 막는 HTTP/1.1의 문제를 줄인다. 브라우저는 같은 출처의 여러 자원을 적은 수의 연결로 병렬 전송할 수 있다.
HTTP/2는 반복되는 헤더 필드를 압축하는 HPACK을 사용한다. 쿠키와 사용자 에이전트처럼 요청마다 반복되는 필드의 전송량을 줄이고, 동적 테이블을 이용해 앞선 헤더 블록을 재사용할 수 있다.
스트림에는 우선순위 정보를 부여할 수 있지만, 실제 우선순위 처리 방식은 구현과 최신 확장에 따라 달라진다. 초기 HTTP/2의 복잡한 의존성 기반 우선순위 체계는 이후 별도의 확장 가능한 우선순위 방식으로 보완되었다.
HTTP/2의 다중화는 TCP 연결 하나 위에서 이루어진다. TCP는 모든 바이트를 순서대로 전달하므로 패킷 하나가 손실되면 해당 연결의 다른 HTTP/2 스트림도 손실된 바이트가 복구될 때까지 전달이 지연될 수 있다. 이를 전송 계층의 헤드 오브 라인 블로킹이라고 한다.
HTTP/2는 필드 압축과 하나의 연결에서의 동시 교환을 통해 네트워크 자원 사용과 지연을 개선하도록 설계되었다.[54]
HTTP/3
HTTP/3은 HTTP 의미론을 QUIC 위에서 전달한다. QUIC은 UDP를 기반으로 연결 설정, 신뢰성 있는 스트림, 혼잡 제어와 TLS 1.3 암호화를 통합한다.
QUIC의 각 스트림은 독립적인 순서 보장을 가진다. 한 스트림의 패킷이 손실되어도 손실과 관련 없는 다른 스트림의 데이터는 계속 응용 프로그램에 전달될 수 있다. 이는 TCP 연결 수준의 헤드 오브 라인 블로킹을 줄인다.
HTTP/3은 헤더 압축에 QPACK을 사용한다. QPACK은 QUIC의 다중 스트림 환경에서 헤더 압축 상태를 전달하면서도 하나의 압축 스트림 손실이 모든 요청을 과도하게 차단하지 않도록 설계되었다.
QUIC 연결은 네트워크 경로가 바뀌어도 연결 식별자를 이용하여 연결을 유지할 수 있다. 사용자가 Wi-Fi에서 이동통신망으로 전환하는 모바일 환경에서 연결 재설정 비용을 줄일 수 있다. 다만 실제 연결 이동의 지원은 클라이언트, 서버와 네트워크 환경에 따라 달라진다.
HTTP/3은 HTTP/2를 완전히 대체하는 별개의 웹 의미론이 아니다. 같은 메서드, 상태 코드, 필드와 캐시 규칙을 다른 전송 계층으로 표현한다. 서버는 HTTP/1.1, HTTP/2와 HTTP/3을 동시에 제공할 수 있으며 클라이언트와 연결 환경에 따라 버전을 선택한다.[55]
HTTP 버전의 발전
- HTTP/0.9
- 단일
GET, 헤더와 상태 코드 없음
- HTTP/1.0
- 요청·응답 헤더
- 상태 코드와 미디어 유형
- 일반적으로 요청마다 새 연결
- HTTP/1.1
- 지속 연결
- 가상 호스팅
- 조건부 요청과 범위 요청
- 텍스트 기반 메시지 구문
- HTTP/2
- 이진 프레임
- 하나의 TCP 연결에서 스트림 다중화
- HPACK 헤더 압축
- HTTP/3
- QUIC 기반 전송
- 스트림별 독립적인 손실 처리
- TLS 1.3 통합
- QPACK 필드 압축
HTTP 연결은 영구적인 사용자 세션과 같은 개념이 아니다. 하나의 연결에서 여러 요청을 처리할 수 있지만 연결은 네트워크 변화, 유휴 시간 초과, 서버 정책과 오류로 언제든 종료될 수 있다. 사용자 로그인과 응용 프로그램 상태는 연결 자체보다 쿠키, 토큰과 서버 저장소를 통해 유지해야 한다.
캐시와 콘텐츠 협상
HTTP 캐시는 이전 요청에서 받은 응답을 저장하고 이후 요청에 재사용하는 구성 요소다. 브라우저의 개인 캐시, 조직의 공유 프록시 캐시와 CDN의 엣지 캐시가 대표적이다.
캐시는 자원을 매번 원본 서버에서 다시 전송하지 않아도 되게 하여 응답 시간을 줄이고 네트워크 대역폭과 서버 부하를 절약한다. 사용자의 네트워크가 느리거나 원본 서버가 멀리 있을수록 캐시의 효과가 커질 수 있다.
저장된 응답은 신선한 응답과 오래된 응답으로 구분된다. 신선도 수명 안에 있는 응답은 일반적으로 원본 서버에 확인하지 않고 재사용할 수 있다. 오래된 응답은 원본 서버에 재검증하거나, 명시적으로 허용된 조건에서만 사용할 수 있다.
서버는 Cache-Control 헤더로 캐시 정책을 지정한다.
max-age는 응답이 생성된 뒤 신선한 것으로 간주할 시간을 초 단위로 지정한다. 공유 캐시에 별도의 시간을 적용하려면 s-maxage를 사용할 수 있다.
no-cache는 응답을 저장하지 말라는 뜻이 아니라, 재사용하기 전에 원본 서버에서 검증해야 한다는 뜻이다.
no-store는 캐시가 요청이나 응답을 저장하지 않도록 지시한다. 민감한 데이터에 사용될 수 있지만 이미 다른 위치에 저장된 복사본이나 응용 프로그램 내부 기록까지 제거하는 기능은 아니다.
private은 응답을 브라우저와 같은 개인 캐시에는 저장할 수 있지만 여러 사용자가 공유하는 캐시에는 저장하지 않도록 한다.
public은 일반적으로 인증된 요청이나 기본적으로 캐시하기 어려운 응답도 공유 캐시에 저장할 수 있음을 명시할 때 사용된다.
must-revalidate는 응답이 오래된 뒤 원본 서버의 확인 없이 재사용하지 않도록 요구한다.
immutable은 신선한 기간 동안 응답이 변경되지 않을 것임을 나타내어 사용자의 새로고침에서도 불필요한 재검증을 줄일 수 있다.
stale-while-revalidate는 오래된 응답을 잠시 제공하면서 백그라운드에서 새 응답을 가져오도록 허용한다. stale-if-error는 원본 서버에서 오류가 발생할 때 일정 기간 오래된 응답을 제공하도록 허용한다.
과거에는 Expires 헤더가 절대 시각으로 신선도 만료 시점을 지정하는 데 주로 사용되었다. 현대 HTTP에서는 Cache-Control이 더 세밀한 제어를 제공하며, 두 헤더가 함께 있으면 관련 규칙에 따라 Cache-Control이 우선할 수 있다.
응답이 오래되었을 때 클라이언트는 전체 표현을 다시 받는 대신 조건부 요청으로 변경 여부를 확인할 수 있다.
ETag는 서버가 선택한 표현 버전의 식별자다. 클라이언트는 저장된 응답의 ETag를 If-None-Match에 담아 전송한다. 현재 표현이 같다면 서버는 304 Not Modified를 반환하고 클라이언트는 저장된 콘텐츠를 재사용한다.
Last-Modified는 자원이 마지막으로 변경된 시각을 나타낸다. 클라이언트는 이를 If-Modified-Since에 포함할 수 있다. 정밀도와 의미가 제한적일 수 있으므로 ETag가 더 정확한 검증자로 사용되는 경우가 많다.
ETag에는 강한 검증자와 약한 검증자가 있다. 강한 ETag는 두 표현이 바이트 단위로 동일한지 확인하는 데 사용할 수 있고, W/로 표시되는 약한 ETag는 의미상 동등하지만 바이트가 완전히 같지 않을 수 있는 표현을 나타낼 수 있다.
캐시 재검증 흐름
- 클라이언트가 저장된 응답 확인↓
- 응답이 신선하면 즉시 재사용↓
- 오래되었으면 ETag 또는 수정 시각을 조건부 요청에 포함↓
- 서버가 현재 표현과 검증자 비교↓
- 변경되지 않았으면↓
304 Not Modified - 변경되었으면 새 표현과↓
200 OK - 캐시가 메타데이터와 콘텐츠 갱신
HTTP 캐시 동작과 관련 헤더는 RFC 9111에 정의되어 있다.[56]
캐시 키는 일반적으로 요청 메서드와 대상 URI를 중심으로 구성되지만, 같은 URI에서도 요청 헤더에 따라 다른 표현이 선택될 수 있다. 서버는 Vary 응답 헤더로 어떤 요청 헤더가 표현 선택에 영향을 주었는지 캐시에 알린다.
예를 들어 서버가 Accept-Encoding에 따라 gzip과 Brotli 표현을 제공한다면 다음과 같이 지정할 수 있다.
Vary: Accept-Encoding
캐시는 URI가 같더라도 요청의 Accept-Encoding 값이 다른 경우 별도의 응답 변형으로 관리한다. Vary가 잘못되거나 빠지면 한 사용자에게 선택된 표현이 호환되지 않는 다른 사용자에게 제공될 수 있다.
콘텐츠 협상은 같은 자원에 사용할 수 있는 여러 표현 가운데 클라이언트와 서버가 적절한 표현을 선택하는 과정이다. 미디어 유형, 언어, 문자 집합과 콘텐츠 인코딩을 기준으로 협상할 수 있다.
서버 주도 콘텐츠 협상에서는 클라이언트가 선호 정보를 요청 헤더로 보낸다.
Accept: 선호하는 미디어 유형Accept-Language: 선호하는 자연어Accept-Encoding: 지원하는 압축과 콘텐츠 인코딩Accept-Charset: 처리할 수 있는 문자 집합을 나타내지만 현대 웹에서는 사용이 제한적임
각 선택 항목에는 q 값을 사용하여 상대적인 선호도를 표현할 수 있다. 서버는 사용 가능한 표현과 클라이언트 선호를 비교해 하나를 선택한다.
선호 조건에 맞는 표현을 제공할 수 없을 때 서버는 406 Not Acceptable을 반환할 수 있다. 요청 콘텐츠의 형식을 서버가 지원하지 않는 경우에는 415 Unsupported Media Type을 사용할 수 있다.
에이전트 주도 협상에서는 서버가 선택 가능한 표현의 목록을 제공하고 클라이언트나 사용자가 직접 하나를 고른다. 언어 선택 페이지, 다운로드 형식 목록과 문서 버전 선택이 이에 해당할 수 있다.
콘텐츠 협상은 하나의 안정적인 URI에서 여러 표현을 제공할 수 있게 하지만 캐시 키가 복잡해지고 사용자별 결과가 달라질 수 있다. 언어와 파일 형식을 명시적인 별도 URI로 제공하는 방식과 협상을 함께 사용하는 사이트도 많다.
브라우저의 선호 언어와 사용자 계정 설정, URL의 언어 경로가 서로 충돌할 수도 있다. 공개 문서와 공유 가능한 링크에서는 사용자가 선택한 언어와 표현을 URI에 명시하고, 초기 방문에서만 협상을 사용하는 방식이 예측 가능성을 높일 수 있다.
압축 협상은 현대 웹에서 널리 사용된다. 클라이언트가 Accept-Encoding으로 gzip, Brotli 또는 다른 인코딩을 지원한다고 알리면 서버는 선택한 인코딩을 적용하고 Content-Encoding에 기록한다. 이미 압축된 이미지나 영상은 추가 압축의 효과가 작을 수 있다.
범위 요청도 자원 전송량을 조절한다. 클라이언트는 Range 헤더로 특정 바이트 구간을 요청하고, 서버는 지원할 경우 206 Partial Content와 Content-Range를 반환한다. 이는 중단된 파일 다운로드를 이어 받거나 영상에서 필요한 부분부터 재생하는 데 사용할 수 있다.
캐시와 콘텐츠 협상은 독립된 기능이 아니다. 협상 결과로 여러 표현이 존재하면 캐시는 Vary와 표현별 검증자를 올바르게 처리해야 한다. 반대로 일관된 캐시 정책이 없으면 콘텐츠 협상으로 선택된 응답이 불필요하게 반복 전송될 수 있다.
현대의 HTTP 자원 전송은 다음 요소가 결합된 결과다.
HTTP 자원 전송의 결정 요소
- 요청 의미
- 메서드
- 대상 URI
- 조건부 요청
- 클라이언트 요구
- 허용 미디어 유형
- 선호 언어
- 지원 콘텐츠 인코딩
- 범위 요청
- 서버 처리
- 인증과 권한 검사
- 표현 선택
- 상태 코드 결정
- 캐시 정책 설정
- 전송 방식
- HTTP/1.1
- HTTP/2
- HTTP/3
- 재사용과 검증
- 브라우저 캐시
- 공유 프록시 캐시
- 콘텐츠 전송 네트워크
- ETag와 수정 시각
이 구조를 통해 HTTP는 같은 자원을 여러 환경과 형식으로 제공하면서도, 클라이언트와 중간 시스템이 메시지의 의미를 공통으로 해석하고 불필요한 전송을 줄일 수 있게 한다.
웹 문서와 콘텐츠 기술
웹에서 전달되는 콘텐츠는 하나의 형식으로 구성되지 않는다. HTML은 문서의 의미와 구조, 링크와 사용자 인터페이스를 정의하고, CSS는 화면·인쇄물과 다른 출력 환경에서의 표현을 지정하며, JavaScript는 계산과 상태 변경, 사용자 입력과 네트워크 통신을 처리한다. 브라우저는 HTML을 문서 객체 모델로 변환하고 CSS 규칙과 스크립트 실행 결과를 결합하여 화면을 구성한다.
이미지, 오디오와 영상은 별도의 웹 자원으로 전송되어 HTML 문서에 포함될 수 있다. 브라우저는 여러 형식과 해상도, 네트워크 환경에 맞는 자원을 선택하고, 미디어 재생과 자막, 그래픽 처리에 필요한 API를 제공한다.
웹은 사람이 읽는 문서뿐 아니라 프로그램이 처리하는 데이터도 전달한다. JSON과 XML은 구조화된 데이터를 교환하는 데 사용되고, RDF와 JSON-LD는 웹 자원 사이의 의미 관계를 표현한다. 이러한 형식은 웹 페이지의 표시 내용, 웹 API, 검색 엔진용 메타데이터와 연결 데이터에 사용된다.
HTML, CSS와 JavaScript를 각각 구조·표현·동작으로 구분하는 설명은 웹의 역할을 이해하는 데 유용하지만, 실제 경계는 완전히 분리되지 않는다. HTML에도 기본적인 사용자 인터페이스 동작과 미디어 기능이 포함되고, CSS는 애니메이션과 상태에 따른 표현을 제공하며, JavaScript는 DOM과 CSSOM을 통해 문서 구조와 스타일을 모두 변경할 수 있다.
HTML
HTML은 HyperText Markup Language의 약자로, World Wide Web의 핵심 마크업 언어다. HTML은 텍스트와 미디어를 단순히 화면에 배치하는 형식이 아니라, 문서의 의미적 구조와 다른 자원과의 관계, 사용자 입력 요소와 웹 애플리케이션의 기본 실행 환경을 정의한다.
HTML은 처음에는 과학 문서를 의미적으로 기술하기 위한 언어로 설계되었다. 이후 일반 문서, 출판물, 멀티미디어 콘텐츠와 완전한 대화형 응용 프로그램까지 표현할 수 있도록 확장되었다. WHATWG HTML 표준은 짧은 정적 문서부터 긴 보고서, 멀티미디어 문서와 상호작용하는 응용 프로그램까지 모두 HTML 문서라는 범위에 포함한다.[57]
HTML 문서는 요소와 텍스트, 주석과 문서 형식 선언으로 구성된다. 요소는 시작 태그와 종료 태그, 속성, 자식 콘텐츠를 가질 수 있다.
<p>웹 문서의 문단이다.</p>
이 구조에서 p는 문단을 나타내는 요소 이름이고, 태그 사이의 문자열은 요소의 텍스트 콘텐츠다. 요소의 역할과 포함 가능한 자식 구조는 HTML 표준이 정의한다.
HTML 요소는 문서에서 맡는 의미에 따라 사용된다. h1부터 h6은 제목 단계, p는 문단, nav는 주요 탐색 영역, article은 독립적으로 배포하거나 재사용할 수 있는 콘텐츠, button은 사용자가 활성화할 수 있는 단추를 나타낸다. 올바른 의미의 요소를 사용하면 브라우저, 검색 엔진과 보조 기술이 문서 구조를 더 정확히 이해할 수 있다.
HTML은 문서의 시각적 모양을 직접 지정하는 것보다 콘텐츠의 의미와 역할을 나타내는 방향으로 사용된다. 같은 article 요소도 CSS에 따라 카드, 전체 화면 문서, 인쇄 기사 또는 음성 출력의 한 구역으로 표현될 수 있다.
문서의 기본 구조는 일반적으로 html, head와 body 요소로 구성된다. head에는 문서 제목, 문자 인코딩, 메타데이터, 스타일시트와 관련 자원 정보가 포함되고, body에는 사용자에게 제공되는 주요 문서와 인터페이스가 포함된다.
HTML 문서에는 다른 웹 자원을 참조하는 주소가 포함된다. a 요소의 href 속성은 하이퍼링크의 목적지를 지정하고, img의 src는 이미지 자원을, link는 스타일시트와 관련 문서를, script는 JavaScript 자원을 연결할 수 있다. 이 참조 관계를 통해 하나의 HTML 문서는 여러 서버에 분산된 자원을 조합한다.
HTML 폼은 텍스트 필드, 체크 상자, 단추, 파일 선택과 같은 입력 컨트롤을 제공한다. 사용자가 입력한 데이터는 서버에 제출하거나 JavaScript가 처리할 수 있다. 기본적인 폼 제출과 유효성 검사는 JavaScript 없이도 HTML 자체의 기능으로 사용할 수 있다.[58]
HTML은 이미지, 오디오, 영상, SVG와 MathML을 문서에 포함할 수 있다. canvas 요소는 JavaScript가 픽셀 기반 2차원 그래픽이나 다른 렌더링 결과를 그릴 수 있는 표면을 제공한다. iframe은 현재 문서 안에 별도의 탐색 문맥과 문서를 포함한다.
HTML 표준에는 문서 마크업만 포함되는 것이 아니다. 브라우저 탐색, 세션 기록, 폼, 미디어 재생, 드래그 앤 드롭, 저장소, 작업자와 여러 웹 API의 동작도 함께 정의되거나 다른 표준과 연결된다. 따라서 현대 HTML은 마크업 언어와 웹 응용 프로그램 플랫폼의 기반 명세라는 성격을 함께 가진다.
HTML 원문은 네트워크에서 바이트열로 전달된다. 브라우저는 HTTP의 Content-Type과 문자 인코딩 정보를 바탕으로 이를 문자열로 해석한 뒤 HTML 파싱 알고리즘을 사용하여 DOM 트리를 생성한다.
HTML 파서는 문법 오류를 만났다고 해서 항상 문서 처리를 중단하지 않는다. 실제 웹에 존재하는 불완전한 문서를 여러 브라우저가 일관되게 처리할 수 있도록 오류 복구 규칙도 표준에 정의되어 있다.[59]
HTML은 대소문자와 일부 태그 생략에 관대한 HTML 문법으로 작성할 수 있으며, XML 규칙을 따르는 XHTML 문법으로도 표현할 수 있다. 두 문법은 비슷한 요소를 사용하지만 파싱과 오류 처리 규칙이 다르며, 서버가 전달하는 미디어 유형도 처리 방식에 영향을 준다.
HTML은 특정 화면 크기나 입력 장치에 한정되지 않는다. HTML 표준은 문서를 미디어에 독립적인 상호작용 콘텐츠의 기술로 다루며, 브라우저는 이를 화면, 인쇄물, 음성 합성기와 보조 기술을 통해 제공할 수 있다.[60]
CSS
CSS는 Cascading Style Sheets의 약자로, HTML과 XML 같은 구조화된 문서가 화면, 인쇄물과 다른 출력 매체에서 어떻게 표현되는지를 기술하는 스타일시트 언어다.[61]
HTML이 문서의 구조와 의미를 나타낸다면 CSS는 글꼴, 색상, 여백, 테두리, 크기, 배치, 화면 변화와 애니메이션 등을 지정한다. 문서의 내용과 표현 규칙을 분리하면 하나의 스타일시트를 여러 문서에 적용하고, 같은 문서를 화면 크기와 출력 환경에 맞게 다르게 표현할 수 있다.
CSS의 기본 규칙은 선택자와 선언 블록으로 구성된다.
article { max-width: 70rem; }
선택자는 스타일을 적용할 요소를 찾고, 선언은 속성과 값을 지정한다. 위 규칙은 article 요소의 최대 너비를 설정한다.
선택자는 요소 이름, 클래스, 식별자, 속성, 문서 트리에서의 관계와 사용자 상호작용 상태를 기준으로 대상을 선택할 수 있다. :hover, :focus, :checked와 같은 의사 클래스는 요소의 현재 상태에 따라 스타일을 적용하고, ::before와 ::after 같은 의사 요소는 문서 트리에 직접 존재하지 않는 표현 대상에 스타일을 적용한다.
CSS의 캐스케이드는 여러 출처와 규칙이 같은 요소의 같은 속성에 값을 지정할 때 최종 값을 결정하는 체계다. 브라우저 기본 스타일, 사용자 스타일, 작성자 스타일, 중요도, 캐스케이드 계층, 선택자 명시도와 선언 순서가 함께 고려된다.[62]
상속은 특정 속성의 계산된 값이 부모 요소에서 자식 요소로 전달되는 방식이다. 글자색과 글꼴처럼 문서 전체에서 이어지는 것이 자연스러운 속성은 상속되는 경우가 많고, 테두리와 여백처럼 요소마다 독립적인 속성은 일반적으로 상속되지 않는다.
CSS는 각 요소를 하나 이상의 상자로 표현한다. 기본 상자 모델은 콘텐츠 영역, 안쪽 여백, 테두리와 바깥 여백으로 구성된다. 요소의 실제 화면 크기는 지정한 너비·높이뿐 아니라 box-sizing, 여백, 테두리와 레이아웃 규칙에 따라 결정된다.
문서 배치에는 일반 흐름, 블록과 인라인 배치, 표 배치, 위치 지정, 다단 구성, Flexbox와 CSS Grid 등이 사용된다. Flexbox는 주로 한 축을 중심으로 항목을 배치하고, Grid는 행과 열을 가진 이차원 레이아웃을 구성한다.
반응형 웹 디자인에서는 미디어 쿼리와 유동적인 크기, 현대적인 레이아웃 시스템을 사용하여 화면 폭, 해상도, 입력 방식과 사용자 환경에 따라 표현을 조정한다. 최근 CSS는 컨테이너 쿼리를 통해 전체 화면이 아니라 요소가 배치된 컨테이너의 크기를 기준으로 스타일을 변경할 수도 있다.
CSS 값에는 고정 길이뿐 아니라 비율, 뷰포트 크기, 글꼴 크기와 컨테이너에 상대적인 단위를 사용할 수 있다. px, %, em, rem, vw, vh 등은 서로 다른 기준을 가지며, calc()와 같은 함수로 여러 값을 계산할 수 있다.
CSS 사용자 정의 속성은 작성자가 이름을 정의하고 값을 재사용할 수 있게 한다. 사용자 정의 속성도 캐스케이드와 상속에 참여하므로 색상 체계, 간격과 구성 요소 변형을 문서 트리의 범위에 따라 관리할 수 있다.[63]
CSS 전환과 애니메이션은 속성 값의 변화를 시간에 따라 표현한다. JavaScript 없이도 요소의 상태 변화에 맞춰 이동, 크기, 색상과 투명도를 변경할 수 있다. 사용자가 동작 감소를 요청한 환경에서는 관련 미디어 기능을 사용해 과도한 애니메이션을 줄일 수 있다.
브라우저는 HTML과 DOM에서 요소 구조를 얻고, 적용 가능한 CSS 규칙을 계산하여 렌더링에 사용할 스타일 정보를 만든다. DOM이나 스타일 규칙이 변경되면 필요한 범위에서 스타일 계산, 레이아웃과 그리기 작업이 다시 수행될 수 있다.
CSS는 하나의 단일 버전 명세로만 발전하지 않는다. 선택자, 색상, 배치, 글꼴, 애니메이션과 캐스케이드 등의 기능이 여러 모듈로 나뉘어 독립적으로 표준화된다. W3C CSS Snapshot은 일정 시점의 안정적인 CSS 모듈 집합을 정리한다.
JavaScript
JavaScript는 웹 페이지와 웹 애플리케이션에서 계산, 상태 관리와 동적 상호작용을 구현하는 프로그래밍 언어다. 브라우저에서 HTML 문서와 사용자 입력, 네트워크와 여러 장치 API를 다루는 대표적인 스크립트 언어이며, 서버와 데스크톱·모바일 응용 프로그램에서도 사용된다.
JavaScript의 핵심 언어 표준 이름은 ECMAScript다. ECMAScript는 값과 타입, 객체, 함수, 문법, 실행 문맥과 기본 내장 객체를 정의한다. 브라우저의 DOM, 네트워크, 저장소와 화면 관련 API는 ECMAScript 자체가 아니라 웹 플랫폼의 호스트 환경이 제공한다.
ECMAScript 명세는 언어가 독립적으로 입출력 기능을 모두 제공하는 완결된 실행 환경이 아니며, 외부 데이터를 읽고 결과를 출력하는 기능은 호스트 환경이 제공한다고 설명한다.[64]
JavaScript는 동적 타입 언어다. 값에는 undefined, null, 불리언, 문자열, 심벌, 숫자, BigInt와 객체 등의 언어 타입이 있으며, 변수 자체에 고정된 타입이 선언되지 않아 실행 중 서로 다른 타입의 값을 참조할 수 있다.[65]
함수는 JavaScript의 주요 추상화 단위이며 값처럼 변수에 저장하거나 인자로 전달하고 다른 함수에서 반환할 수 있다. 객체는 이름이 붙은 속성의 집합으로 데이터를 표현하고, 프로토타입 연결을 통해 다른 객체의 속성과 동작을 상속할 수 있다.
브라우저의 JavaScript는 DOM API를 사용하여 요소를 찾고, 텍스트와 속성을 변경하며, 새로운 노드를 추가하거나 제거할 수 있다. CSS 클래스와 인라인 스타일을 변경하여 표현을 갱신하고, 클릭·키보드 입력·포인터 이동·폼 제출과 같은 이벤트에 반응한다.
JavaScript는 fetch()와 다른 네트워크 API를 사용하여 페이지 전체를 다시 불러오지 않고 서버와 데이터를 교환할 수 있다. 서버에서 JSON을 받아 화면 일부를 갱신하거나, 사용자 입력을 비동기적으로 제출하고, 실시간 통신 연결을 유지할 수 있다.
브라우저의 주 실행 환경에서는 일반적으로 하나의 이벤트 루프가 작업과 콜백 실행을 조정한다. 타이머, 사용자 입력, 네트워크 응답과 Promise의 후속 처리는 각각의 대기열과 실행 규칙에 따라 처리된다. JavaScript 코드가 오랫동안 실행되면 같은 실행 환경의 사용자 입력 처리와 화면 갱신이 지연될 수 있다.
Web Worker는 문서의 주 실행 환경과 분리된 작업자에서 JavaScript를 실행한다. 작업자는 일반적인 DOM을 직접 조작하지 못하지만 메시지를 통해 주 문서와 데이터를 교환하며, 계산량이 큰 작업이 사용자 인터페이스를 직접 차단하는 것을 줄일 수 있다.
JavaScript 모듈은 파일별로 선언과 의존성을 분리하고 import와 export로 기능을 공유한다. 브라우저는 모듈 의존 관계를 불러오고 각 모듈을 고유한 범위에서 평가한다.
브라우저는 보안상 출처와 실행 문맥에 따라 JavaScript의 권한을 제한한다. 동일 출처 정책은 한 출처의 스크립트가 다른 출처의 문서와 데이터를 임의로 읽지 못하도록 하고, CORS와 명시적인 메시지 전달 방식으로 제한된 교환을 허용한다.
JavaScript 실행 여부와 관계없이 가능한 기본 문서 탐색과 폼 제출을 HTML로 제공하고, JavaScript로 기능과 편의성을 확장하는 방식을 점진적 향상이라고 한다. 반대로 JavaScript 실행을 전제로 화면과 탐색을 모두 구성하는 웹 애플리케이션도 널리 사용된다.
ECMAScript는 TC39에서 지속적으로 발전하며, 완료된 언어 기능은 매년 발행되는 명세 판본에 포함된다. 웹 브라우저의 JavaScript 지원 범위는 언어 표준뿐 아니라 각 웹 API의 구현 상태에도 영향을 받는다.[66]
문서 객체 모델
문서 객체 모델 또는 DOM은 HTML과 XML 문서를 프로그램이 읽고 변경할 수 있는 객체와 노드 트리로 표현하는 표준 인터페이스다. DOM은 특정 프로그래밍 언어에 종속되지 않지만, 웹 브라우저에서는 주로 JavaScript를 통해 사용된다.
WHATWG DOM 표준은 DOM을 노드 트리, 이벤트와 비동기 작업 중단 등을 다루는 플랫폼 중립적 모델로 정의한다.[67]
브라우저는 HTML 원문을 파싱하면서 Document 객체를 루트로 하는 DOM 트리를 생성한다. 문서의 요소는 Element 노드, 문자 내용은 Text 노드, 주석은 Comment 노드로 표현된다. 각 노드는 부모·자식과 형제 관계를 통해 연결된다.
HTML 문서의 단순화된 DOM 구조
Documenthtmlheadtitle- 텍스트 노드
link
bodyheadermainarticleh1p
footer
DOM은 HTML 소스 문자열을 그대로 복사한 구조가 아니다. HTML 파서의 오류 복구와 암시적 요소 생성 규칙에 따라 원문에 명시되지 않은 노드가 생성될 수 있고, 잘못 중첩된 요소가 다른 위치로 재구성될 수도 있다.
JavaScript는 querySelector(), getElementById()와 같은 메서드로 노드를 찾을 수 있다. 요소의 속성과 텍스트를 수정하고, createElement()로 새로운 요소를 생성하며, append()와 remove() 등으로 문서 트리를 변경할 수 있다.
DOM의 변경은 메모리에 존재하는 현재 문서 객체에 적용된다. 서버에서 처음 받은 HTML 파일 자체가 자동으로 수정되는 것은 아니다. 변경 내용을 서버에 보존하려면 JavaScript가 별도의 요청을 전송하거나 폼 제출과 다른 저장 절차를 사용해야 한다.
DOM 이벤트 모델은 사용자의 입력과 문서 상태 변화를 객체에 전달한다. 이벤트는 대상 노드에 도달하기 전 조상 노드를 거치는 캡처 단계, 대상 단계와 다시 조상 방향으로 전달되는 버블링 단계를 가질 수 있다.
이벤트 위임은 자식 요소마다 개별 처리기를 등록하는 대신 공통 조상에서 버블링되는 이벤트를 처리하는 방식이다. 동적으로 생성되는 많은 요소를 다루거나 이벤트 처리기의 수를 줄이는 데 사용된다.
DOM 트리는 렌더링 결과와 같은 개념이 아니다. display: none으로 숨겨진 요소도 DOM에 존재할 수 있고, CSS 의사 요소처럼 화면에는 나타나지만 일반 DOM 노드로 존재하지 않는 대상도 있다. 브라우저는 DOM과 CSS 규칙을 바탕으로 렌더링에 필요한 별도의 내부 구조를 만든다.
DOM과 접근성 트리도 구분된다. 브라우저는 HTML 요소의 의미, ARIA 정보와 현재 상태를 바탕으로 보조 기술에 제공할 접근성 구조를 생성한다. 올바른 HTML 의미 구조는 DOM을 시각적으로 조작하는 것만큼 접근성에 중요하다.
XML 문서도 DOM으로 표현할 수 있지만 HTML과 XML은 파싱과 이름 처리, 오류 복구 방식이 다르다. HTML 문서는 HTML 표준의 규칙으로 생성된 Document 객체와 요소 인터페이스를 사용한다.[68]
DOM은 브라우저 내부 구현 전체를 뜻하지 않는다. 브라우저의 네트워크 계층, JavaScript 엔진, CSS 파서, 레이아웃 엔진과 그래픽 합성기는 DOM과 상호작용하지만 각각 별도의 기능을 담당한다.
이미지, 오디오와 영상
웹 문서는 텍스트뿐 아니라 래스터 이미지, 벡터 그래픽, 오디오, 영상과 시간 기반 자막을 포함할 수 있다. 이러한 콘텐츠는 HTML 문서 안에 직접 직렬화될 수도 있지만, 일반적으로 별도의 URL을 가진 자원으로 제공되어 필요할 때 브라우저가 요청한다.
이미지는 주로 img 요소로 문서에 포함한다. src 속성은 기본 이미지 URL을 지정하고, alt 속성은 이미지를 볼 수 없거나 시각적으로 인식하기 어려운 사용자에게 이미지의 의미를 전달하는 대체 텍스트를 제공한다.
대체 텍스트는 파일 이름이나 모든 시각 정보를 기계적으로 나열하는 설명이 아니다. 이미지가 문서에서 맡는 목적과 주변 문맥에 따라 동일한 정보나 기능을 텍스트로 전달해야 한다. 장식용 이미지는 보조 기술이 불필요하게 읽지 않도록 빈 대체 텍스트를 사용할 수 있다.
웹에서 사용하는 래스터 이미지 형식에는 JPEG, PNG, GIF, WebP와 AVIF 등이 있다. JPEG는 사진과 연속적인 색조 이미지에 널리 사용되고, PNG는 무손실 압축과 투명도를 지원한다. WebP와 AVIF는 손실·무손실 압축과 투명도, 애니메이션 등의 기능을 제공할 수 있다.
SVG는 XML 기반의 벡터 그래픽 형식이다. 도형, 경로, 텍스트와 필터를 구조화된 요소로 표현하며 크기를 확대해도 일반적으로 래스터 이미지처럼 해상도에 따른 픽셀화가 발생하지 않는다. SVG는 별도 이미지 파일로 불러오거나 HTML 문서 안에 직접 포함할 수 있다.
picture와 source 요소, srcset과 sizes 속성은 화면 크기, 픽셀 밀도와 지원 형식에 따라 여러 후보 이미지 중 하나를 선택하도록 한다. 브라우저는 이러한 정보와 현재 환경을 바탕으로 적절한 자원을 선택할 수 있다.[69]
이미지의 표시 크기와 실제 파일 해상도는 구분된다. 화면에 작게 표시하는 이미지라도 원본 파일이 지나치게 크면 불필요한 전송과 디코딩 비용이 발생한다. 반대로 고밀도 화면에서는 표시 크기보다 더 많은 픽셀을 가진 자원이 선명한 결과를 제공할 수 있다.
HTML의 audio와 video 요소는 플러그인 없이 오디오와 영상을 재생한다. controls, autoplay, loop, muted, preload 등의 속성과 JavaScript 미디어 API로 재생 상태를 제어할 수 있다.
source 요소는 같은 콘텐츠의 여러 파일 형식이나 인코딩을 제시한다. 브라우저는 자신이 지원하는 미디어 유형과 코덱을 고려하여 사용할 자원을 선택한다. 컨테이너 형식과 내부 코덱은 서로 구분되며, 같은 확장자라도 인코딩된 영상·음성 코덱에 따라 재생 가능 여부가 달라질 수 있다.
웹에서 사용되는 미디어 컨테이너에는 MP4와 WebM 등이 있고, 영상 코덱에는 H.264, VP9와 AV1, 음성 코덱에는 AAC, Opus와 MP3 등이 있다. 실제 지원 범위는 브라우저, 운영체제, 하드웨어와 라이선스 정책에 따라 달라질 수 있다.
track 요소와 WebVTT 형식은 자막, 캡션, 설명, 장과 메타데이터 같은 시간 기반 텍스트 트랙을 제공한다. 청각 장애인을 위한 캡션에는 대화뿐 아니라 화자와 중요한 음향 정보도 포함될 수 있다.
HTML 표준에서 미디어 요소는 오디오 데이터 또는 영상과 오디오 데이터를 사용자에게 제공하는 데 사용된다.[70]
미디어 파일 전체를 한 번에 내려받지 않고 일부 범위를 요청하거나 작은 세그먼트로 분할하여 전송할 수 있다. HTTP 범위 요청은 파일의 특정 바이트 구간을 가져오는 데 사용되고, Media Source Extensions 기반 스트리밍은 JavaScript가 여러 미디어 세그먼트를 재생 버퍼에 추가할 수 있게 한다.
적응형 스트리밍은 네트워크 속도와 기기 성능에 따라 서로 다른 비트레이트와 해상도의 미디어 세그먼트를 선택한다. HLS와 MPEG-DASH가 대표적인 방식이며, 브라우저의 기본 기능이나 JavaScript 플레이어와 결합하여 사용된다.
실시간 오디오와 영상 통신에는 WebRTC가 사용될 수 있다. 이는 저장된 영상 파일을 재생하는 video 요소와 달리 카메라·마이크와 원격 참여자의 실시간 미디어 스트림을 처리한다. WebRTC 스트림도 HTML 미디어 요소에 연결하여 화면과 스피커로 출력할 수 있다.
canvas는 스크립트가 그리는 비트맵 기반 표면을 제공하고, WebGL과 WebGPU는 그래픽 처리 장치를 이용한 2차원·3차원 렌더링과 범용 계산을 지원한다. SVG는 문서 트리 기반 벡터 그래픽이고, canvas는 그리기 명령의 결과를 픽셀 표면에 기록한다는 차이가 있다.
이미지와 미디어는 다른 출처에서 불러올 수 있지만, 픽셀 데이터 접근과 프로그램 처리에는 동일 출처 정책과 CORS가 적용될 수 있다. 허용되지 않은 외부 이미지를 canvas에 그린 경우 스크립트가 그 픽셀을 읽지 못하도록 제한될 수 있다.
자동 재생은 사용자 경험과 데이터 사용, 예기치 않은 소리 문제 때문에 브라우저 정책의 제한을 받는다. 음소거된 영상은 자동 재생이 허용될 수 있지만 소리가 포함된 미디어는 사용자 상호작용이 필요할 수 있다.
구조화 데이터와 웹 데이터 형식
웹 콘텐츠는 사람이 화면에서 읽는 문서뿐 아니라 소프트웨어가 일관된 구조로 해석하는 데이터도 포함한다. 구조화 데이터는 값의 종류와 계층, 필드 이름과 자원 사이의 관계를 명시하여 검색, 교환, 검증과 자동 처리를 가능하게 한다.
웹에서 사용되는 데이터 형식은 서로 다른 목적을 가진다. HTML은 문서와 사용자 인터페이스를 표현하고, JSON과 XML은 일반적인 구조화 데이터를 직렬화한다. CSV는 표 형태 데이터를 간단히 표현하고, RDF는 자원 사이의 의미 관계를 그래프로 모델링한다.
JSON
JSON은 JavaScript Object Notation의 약자로, 구조화된 데이터를 직렬화하기 위한 경량 텍스트 형식이다. JavaScript 객체 표기법에서 유래했지만 특정 프로그래밍 언어에 종속되지 않는 데이터 교환 형식이다.[71]
JSON은 객체, 배열, 문자열, 숫자, true, false와 null을 표현한다. 객체는 문자열 이름과 값의 구성원 집합이고, 배열은 순서가 있는 값의 목록이다.
JSON은 웹 API의 요청과 응답에 널리 사용된다. HTML보다 화면 표현과 문서 의미를 적게 포함하고 XML보다 문법이 간결하여 JavaScript와 여러 서버 언어에서 쉽게 처리할 수 있다.
JSON과 JavaScript 객체 리터럴은 비슷하지만 동일한 문법은 아니다. JSON은 함수, 주석, undefined, BigInt와 임의의 JavaScript 표현식을 포함하지 않는다. JSON 데이터는 실행 코드로 평가하지 않고 전용 파서로 처리해야 한다.
JSON 객체의 구성원 순서에 의미를 의존하면 상호 운용성이 낮아질 수 있다. 배열은 순서를 보존하지만 객체는 이름으로 값을 식별하는 구조이며, 중복된 이름의 처리도 구현에 따라 문제가 될 수 있다.
XML
XML은 Extensible Markup Language의 약자로, 요소와 속성, 텍스트와 이름 공간을 사용하여 구조화된 문서와 데이터를 표현한다. HTML과 달리 응용 분야에 맞는 요소 이름과 문서 구조를 정의할 수 있다.
XML은 웹 서비스, 구성 파일, 문서 형식, 출판과 산업 데이터 교환에 널리 사용되어 왔다. SVG와 MathML도 XML 문법을 사용하는 웹 형식이다.
XML 이름 공간은 서로 다른 어휘의 요소와 속성을 하나의 문서에서 이름 충돌 없이 결합할 수 있게 한다. XML Schema와 다른 스키마 언어는 문서에 허용되는 구조, 데이터 타입과 제약 조건을 정의할 수 있다.
XML은 JSON보다 문법과 처리 기능이 복잡하지만, 혼합 콘텐츠, 이름 공간, 문서 중심 데이터와 정교한 스키마가 필요한 분야에서 사용된다. 외부 엔터티와 같은 기능을 잘못 구성한 파서는 보안 문제를 일으킬 수 있으므로 신뢰할 수 없는 XML 입력에는 안전한 파서 설정이 필요하다.
CSV와 표 형식 데이터
CSV는 일반적으로 각 줄을 행으로, 구분된 값을 열로 표현하는 텍스트 형식이다. 단순한 표 데이터를 스프레드시트와 통계 도구, 데이터베이스 사이에서 교환하는 데 널리 사용된다.
CSV는 구현마다 구분 문자, 인용, 줄바꿈, 문자 인코딩과 헤더 처리 방식이 달라질 수 있다. RFC 4180은 일반적으로 사용되는 형식과 text/csv 미디어 유형을 문서화하지만 모든 CSV 파일이 같은 방언을 따르는 것은 아니다.
표 데이터가 셀의 표시값만 포함하면 열의 의미, 단위, 데이터 타입과 결측값 규칙을 별도로 알아야 한다. 메타데이터나 스키마를 함께 제공하면 자동 처리와 검증 가능성을 높일 수 있다.
RDF와 연결 데이터
RDF는 Resource Description Framework의 약자로, 웹의 자원에 관한 정보를 표현하기 위한 데이터 모델이다. RDF는 데이터를 주어, 술어, 목적어로 이루어진 트리플의 집합으로 나타내며, 이 트리플들은 방향이 있는 그래프를 형성한다.[72]
주어는 설명할 자원, 술어는 관계나 속성, 목적어는 다른 자원이나 리터럴 값을 나타낸다. 예를 들어 특정 문서와 작성자, 작성자의 이름을 서로 다른 트리플로 연결할 수 있다.
RDF 데이터 모델은 특정 파일 문법과 분리되어 있다. RDF/XML, Turtle, N-Triples와 JSON-LD 등 여러 형식으로 같은 RDF 그래프를 직렬화할 수 있다.
연결 데이터는 자원을 URI로 식별하고, HTTP를 통해 관련 정보를 제공하며, 다른 자원으로 이어지는 관계를 포함하여 서로 다른 데이터 집합을 웹 규모에서 연결하려는 방식이다.
JSON-LD
JSON-LD는 JavaScript Object Notation for Linked Data의 약자로, JSON 문법으로 연결 데이터를 표현하는 형식이다. 기존 JSON 구조에 문맥과 식별자, 타입과 관계 정보를 추가하여 RDF 데이터 모델과 연결할 수 있다.[73]
JSON-LD의 @context는 짧은 속성 이름이 어떤 URI와 의미를 가지는지 정의하고, @id는 자원의 식별자, @type은 자원의 유형을 나타낼 수 있다. 이를 통해 일반적인 JSON 처리 방식과 의미 웹의 전역 식별 체계를 함께 사용할 수 있다.
웹 페이지에서는 script 요소의 application/ld+json 형식으로 JSON-LD를 포함할 수 있다. 검색 엔진과 다른 처리기는 화면에 표시된 콘텐츠와 함께 이 데이터를 읽어 문서가 설명하는 사람, 제품, 기사, 행사와 조직 등의 구조를 파악할 수 있다.
구조화 데이터를 삽입한다고 해서 표시된 내용과 무관한 정보를 제공하거나 검색 결과의 특정 표현이 보장되는 것은 아니다. 문서에 보이는 실제 내용과 일치하는 데이터를 제공하고 사용하는 어휘와 처리기의 정책을 따라야 한다.
HTML 내부의 구조화 데이터
HTML 자체에도 문서의 의미를 나타내는 요소와 메타데이터 기능이 있다. article, time, address, 제목과 표 요소는 콘텐츠의 역할과 구조를 표현한다.
Microdata는 itemscope, itemtype, itemprop 등의 HTML 속성으로 문서 요소에 구조화된 의미를 추가한다. 데이터가 화면의 기존 HTML 요소와 직접 연결된다는 특징이 있다.
RDFa는 HTML과 XML 속성을 사용하여 RDF 트리플을 문서에 포함한다. Microdata, RDFa와 JSON-LD는 구조화 데이터를 표현하는 위치와 모델이 다르며, 사이트와 사용하는 도구에 따라 선택된다.
meta 요소는 문서 설명, 문자 인코딩과 애플리케이션 메타데이터를 제공하고, link 요소는 현재 문서와 다른 자원의 관계를 나타낸다. Open Graph와 같은 비표준 또는 공동체 기반 메타데이터 어휘도 소셜 서비스의 링크 미리보기에 사용된다.
바이너리 데이터 형식
모든 웹 데이터가 텍스트 형식일 필요는 없다. Protocol Buffers, CBOR와 MessagePack 같은 바이너리 형식은 데이터 크기, 파싱 비용과 타입 표현을 최적화하기 위해 사용될 수 있다.
CBOR은 JSON 데이터 모델을 포함할 수 있는 바이너리 데이터 형식으로, 작은 코드 크기와 작은 메시지 크기, 확장성을 목표로 한다. 제한된 장치와 고빈도 데이터 교환에서도 활용된다.
바이너리 형식은 사람이 직접 읽고 수정하기 어렵고, 브라우저 개발 도구와 일반 웹 인프라에서 JSON만큼 즉시 확인하기 어려울 수 있다. 반면 대규모 데이터, 실시간 통신과 엄격한 스키마 기반 시스템에서는 효율성과 타입 안정성의 이점을 제공한다.
데이터 형식과 미디어 유형
웹에서 데이터 형식을 정확히 처리하려면 HTTP의 Content-Type이 실제 콘텐츠와 일치해야 한다. JSON은 일반적으로 application/json, HTML은 text/html, XML 계열 형식은 각각 등록된 XML 미디어 유형을 사용한다.
파일 확장자만으로 데이터 형식을 안전하게 판단할 수 없다. URL에 확장자가 없을 수도 있고, 서버가 요청에 따라 같은 URL에서 서로 다른 형식을 반환할 수도 있다. 클라이언트는 미디어 유형과 해당 형식의 표준에 따라 콘텐츠를 해석한다.
웹 데이터의 구조와 의미는 직렬화 형식만으로 완전히 정해지지 않는다. 같은 JSON 문서라도 필드의 의미와 필수 여부, 허용 타입은 API 명세나 스키마가 별도로 정의한다. JSON Schema, XML Schema와 RDF 어휘는 데이터 구조와 제약 또는 의미 관계를 더 명시적으로 표현하는 데 사용된다.
현대의 웹 문서는 이러한 기술을 독립적으로 사용하는 것이 아니라 함께 조합한다. HTML이 기본 문서와 접근 가능한 인터페이스를 제공하고, CSS가 여러 환경에 맞는 표현을 구성하며, JavaScript가 DOM과 서버 데이터를 연결한다. 이미지와 미디어는 별도의 표현 자원으로 포함되고, 구조화 데이터는 사람에게 보이는 콘텐츠를 프로그램이 처리할 수 있는 형태로 보완한다.
웹 브라우저
웹 브라우저는 World Wide Web의 자원을 요청하고 해석하여 사용자에게 제공하는 사용자 에이전트다. 브라우저는 URL을 입력받아 네트워크 요청을 수행하고, HTML·CSS·JavaScript와 이미지·글꼴·오디오·영상 등의 자원을 처리하여 문서와 웹 애플리케이션을 표시한다.
웹 브라우저는 단순한 HTML 표시 프로그램이 아니다. 탭과 주소창을 제공하는 사용자 인터페이스, HTTP와 TLS를 처리하는 네트워크 계층, HTML과 CSS를 해석하는 렌더링 엔진, JavaScript와 WebAssembly를 실행하는 엔진, 그래픽 합성기, 저장소, 캐시, 보안 정책과 확장 기능 체계가 결합된 소프트웨어 플랫폼이다.
현대 브라우저는 신뢰할 수 없는 웹 콘텐츠를 사용자 컴퓨터에서 실행한다. 따라서 서로 다른 사이트와 브라우저 자체를 여러 프로세스로 분리하고, 콘텐츠 프로세스의 운영체제 권한을 제한하며, 동일 출처 정책과 샌드박스를 적용하는 구조가 일반적이다. Chromium은 브라우저와 렌더러를 비롯한 여러 프로세스로 기능을 분리하고, Gecko 역시 메인·콘텐츠·소켓·GPU·확장 프로세스 등을 사용하는 다중 프로세스 구조를 갖는다.[74][75]
브라우저와 브라우저 엔진은 같은 개념이 아니다. Google Chrome, Microsoft Edge, Firefox와 Safari는 사용자 인터페이스와 동기화, 설정, 업데이트, 계정 기능을 포함한 완성된 브라우저 제품이다. Blink, Gecko와 WebKit은 웹 문서와 플랫폼 기능을 처리하는 엔진이며, V8, SpiderMonkey와 JavaScriptCore는 JavaScript와 WebAssembly를 실행하는 엔진이다.
사용자 인터페이스
웹 브라우저의 사용자 인터페이스는 사용자가 웹 자원을 탐색하고, 현재 페이지의 상태와 보안을 확인하며, 여러 문서와 작업을 관리하도록 한다. 일반적인 브라우저는 주소창, 뒤로·앞으로 가기, 새로고침, 탭, 북마크, 방문 기록, 다운로드 관리, 설정과 개발자 도구를 제공한다.
주소창은 URL 입력란과 검색 입력란의 역할을 함께 수행하는 경우가 많다. 사용자가 완전한 URL을 입력하면 해당 자원으로 이동하고, 일반 문구를 입력하면 설정된 검색 엔진에 질의한다. 브라우저는 방문 기록과 북마크, 열린 탭과 검색 제안을 바탕으로 자동 완성 결과를 표시할 수 있다.
주소창은 현재 문서의 출처와 연결 보안 상태를 전달하는 보안 인터페이스이기도 하다. HTTPS 연결 여부, 인증서 오류, 사이트 권한과 안전하지 않은 혼합 콘텐츠 상태 등이 주소창 주변에 표시될 수 있다. 웹 페이지 자체도 브라우저와 비슷한 주소창이나 경고 화면을 그릴 수 있으므로, 사용자는 페이지 콘텐츠와 브라우저가 직접 제공하는 신뢰된 인터페이스를 구분할 필요가 있다.
뒤로 가기와 앞으로 가기는 브라우저의 세션 기록을 탐색한다. 기록 항목은 단순히 방문한 URL 문자열만 저장하는 것이 아니라 문서와 스크롤 위치, 폼 상태, 문서에 연결된 세션 기록 상태를 포함할 수 있다. 웹 애플리케이션은 History API를 사용하여 전체 문서를 다시 불러오지 않고도 기록 항목과 URL을 변경할 수 있다.
새로고침은 현재 자원을 다시 탐색하거나 서버와 캐시 상태를 검증한다. 일반 새로고침은 조건부 요청과 캐시를 사용할 수 있고, 강제 새로고침은 일부 저장된 응답을 무시하고 네트워크에서 자원을 다시 요청할 수 있다. 구체적인 동작과 단축키는 브라우저마다 다르다.
탭은 여러 탐색 문맥을 하나의 브라우저 창에서 관리한다. 각 탭에는 독립적인 문서와 탐색 기록이 있지만, 같은 출처의 문서가 저장소와 작업자, 인증 상태를 공유할 수 있다. 탭 하나가 운영체제 프로세스 하나에 항상 대응하는 것은 아니다. 브라우저는 사이트 격리와 자원 사용 정책에 따라 하나의 탭을 여러 렌더러 프로세스로 나누거나 여러 탭에 프로세스를 재사용할 수 있다.
탭 그룹, 세로 탭, 고정 탭과 작업 공간은 많은 페이지를 분류하고 다시 열 수 있게 한다. 종료할 때 열려 있던 탭을 복원하거나 계정 동기화를 통해 다른 기기로 탭을 전송하는 기능도 제공될 수 있다.
북마크는 사용자가 다시 방문할 URL과 제목을 저장한다. 방문 기록은 과거 탐색 정보를 시간 순서나 검색 가능한 데이터로 관리한다. 이러한 정보는 편의 기능에 사용되지만 사용자의 관심사와 활동을 나타낼 수 있으므로 삭제, 보존 기간과 동기화 설정이 개인정보 보호와 연결된다.
다운로드 관리자는 웹에서 받은 파일의 진행 상태, 저장 위치와 완료 결과를 표시한다. 브라우저는 알려진 악성 파일이나 위험한 실행 파일을 경고하고, 운영체제 또는 외부 보안 서비스와 연동할 수 있다. 파일을 내려받았다는 사실만으로 그 파일이 브라우저의 웹 콘텐츠 샌드박스 안에서 계속 실행되는 것은 아니다.
사이트 권한 인터페이스는 위치, 카메라, 마이크, 알림, 클립보드와 파일 접근 등 웹사이트가 요청한 기능을 허용하거나 차단한다. 권한은 일회성, 현재 세션 또는 지속 설정으로 저장될 수 있으며, 브라우저 설정이나 주소창의 사이트 정보 화면에서 변경할 수 있다.
비공개 탐색 또는 시크릿 모드는 일반 창과 별도의 임시 세션을 제공한다. 브라우저는 비공개 창을 닫은 뒤 해당 세션의 방문 기록, 쿠키와 사이트 데이터를 보존하지 않도록 설계할 수 있다. 그러나 인터넷 서비스 제공자, 회사나 학교의 네트워크 관리자, 방문한 사이트와 로그인한 서비스로부터 사용자의 활동을 익명화하는 기능은 아니다.
읽기 모드, 번역, 화면 확대, 고대비, 글꼴 조정과 음성 읽기 기능은 문서의 가독성과 접근성을 높인다. 브라우저는 운영체제의 스크린 리더와 입력 보조 기능에 접근성 트리를 제공하고, 자체 사용자 인터페이스도 키보드와 보조 기술로 조작할 수 있어야 한다.
개발자 도구는 DOM과 CSS 검사, JavaScript 디버깅, 네트워크 요청 분석, 저장소 확인, 성능 프로파일링과 접근성 검사를 제공한다. 개발자 도구는 페이지와 같은 브라우저 안에 표시되지만, 일반 웹 콘텐츠보다 높은 디버깅 권한을 가진 브라우저 기능이다.
사용자 인터페이스의 일부는 웹 콘텐츠와 분리된 브라우저 크롬이라고 부른다. 여기서 크롬은 Google Chrome 제품을 뜻하는 것이 아니라 주소창, 탭과 메뉴처럼 웹 페이지 바깥에 있는 브라우저 자체의 사용자 인터페이스를 가리키는 전통적인 용어다.
렌더링 엔진
렌더링 엔진은 HTML·CSS와 관련 웹 표준을 해석하고 문서의 시각적 결과와 상호작용 구조를 생성하는 브라우저의 핵심 구성 요소다. 현대 엔진은 HTML 파싱, DOM, CSS 스타일 계산, 레이아웃, 그리기, 합성과 접근성 정보 생성을 처리한다.
렌더링은 하나의 단계로 끝나지 않는다. 브라우저가 HTML 응답을 받으면 바이트를 문자로 디코딩하고, HTML 파서를 사용하여 DOM 트리를 구성한다. HTML 파싱 중 스타일시트와 이미지, 스크립트 등 외부 자원의 참조를 발견하면 네트워크 계층에 추가 요청을 전달한다.
HTML 표준은 text/html 자원에서 DOM 트리를 생성하는 파싱 규칙을 정의한다. 오류가 있는 문서도 브라우저마다 최대한 같은 구조로 복구하도록 세부적인 오류 처리 알고리즘을 포함한다.[76]
CSS 파서는 외부 스타일시트와 문서 안의 스타일 규칙, 요소의 인라인 스타일을 읽는다. 브라우저 기본 스타일, 사용자 스타일과 작성자 스타일을 캐스케이드 규칙에 따라 결합하고 각 요소에 적용할 계산된 스타일을 구한다.
레이아웃은 DOM의 요소와 계산된 스타일을 바탕으로 상자의 크기와 위치를 정한다. 블록·인라인 흐름, Flexbox, Grid, 표, 절대 위치와 다단 배치가 서로 다른 레이아웃 알고리즘을 사용한다. 글꼴의 실제 글리프 크기, 줄바꿈, 화면 크기와 스크롤 영역도 이 과정에 영향을 준다.
그리기 단계에서는 배경, 테두리, 텍스트, 그림자와 이미지를 어떤 순서로 표시할지 정하고 그래픽 명령을 만든다. 페이지 전체를 매번 하나의 비트맵으로 다시 그리는 대신, 브라우저는 여러 시각적 영역을 레이어로 분리할 수 있다.
합성은 여러 레이어를 GPU 또는 그래픽 시스템을 사용해 최종 화면으로 조합한다. 스크롤, 변형과 투명도 애니메이션처럼 레이아웃이나 전체 다시 그리기 없이 합성 단계에서 처리할 수 있는 변화도 있다.
단순화한 웹 문서 렌더링 흐름
- HTML·CSS와 관련 자원 수신↓
- 문자 디코딩과 HTML 파싱↓
- DOM 트리 생성↓
- CSS 파싱과 캐스케이드 적용↓
- 요소별 계산된 스타일 결정↓
- 레이아웃으로 크기와 위치 계산↓
- 그리기 명령과 시각적 레이어 생성↓
- GPU 또는 그래픽 시스템에서 합성↓
- 브라우저 창에 최종 프레임 표시
이 흐름은 이해를 위한 단순화다. 실제 브라우저는 HTML을 전부 받은 뒤 순서대로만 처리하지 않는다. 데이터를 스트리밍으로 파싱하면서 일부 콘텐츠를 먼저 표시하고, 필요한 자원을 병렬로 요청하며, JavaScript 실행과 스타일시트 수신에 따라 파싱과 렌더링을 중단하거나 다시 계산할 수 있다.
JavaScript가 DOM이나 스타일을 변경하면 브라우저는 영향을 받는 범위의 스타일과 레이아웃, 그리기를 다시 수행한다. 모든 변경이 전체 문서를 다시 처리하는 것은 아니며, 엔진은 무효화 범위를 추적하여 필요한 작업만 수행하려고 한다.
레이아웃 결과를 즉시 읽는 JavaScript와 연속적인 DOM 변경이 반복되면 브라우저가 레이아웃 계산을 자주 강제로 수행할 수 있다. 이는 흔히 레이아웃 스래싱이라고 하며 페이지 성능 저하의 원인이 된다.
렌더링 엔진은 화면 표시뿐 아니라 인쇄, PDF 생성과 접근성 트리에도 관여한다. HTML 표준은 브라우저 같은 사용자 에이전트가 HTML 문서를 처리하는 방식을 정의하지만, 모든 사용자 에이전트가 문서를 시각적으로 완전히 같은 형태로 표시하도록 강제하지는 않는다.[77]
현대의 대표적인 렌더링 엔진에는 Chromium 계열의 Blink, Mozilla의 Gecko, Apple 중심의 WebKit이 있다. 브라우저 제품은 엔진 위에 자체 사용자 인터페이스와 서비스, 정책을 추가한다.
Chromium에서는 브라우저 프로세스가 창과 탭, 권한과 네트워크 같은 높은 권한의 기능을 관리하고, 렌더러 프로세스에서 Blink가 웹 콘텐츠를 처리한다. 사이트 격리는 서로 다른 사이트의 콘텐츠를 가능한 한 별도의 샌드박스 렌더러 프로세스에 배치하여 한 사이트의 렌더러 취약점이 다른 사이트의 데이터로 이어지는 위험을 줄인다.[78]
Gecko는 HTML 파싱과 렌더링뿐 아니라 네트워킹, DOM, JavaScript 통합, 프로세스 간 통신과 운영체제 위젯 추상화를 포함하는 Mozilla의 웹 플랫폼 엔진이다.[79]
WebKit은 HTML·CSS·JavaScript와 DOM 등 표준 기반 웹 콘텐츠를 브라우저와 다른 응용 프로그램에서 표시하고 상호작용하기 위한 오픈 소스 엔진이다. Safari뿐 아니라 macOS와 iOS의 여러 응용 프로그램에 내장된다.[80]
JavaScript 엔진
JavaScript 엔진은 ECMAScript 프로그램을 파싱하고 실행하는 구성 요소다. 현대 브라우저의 JavaScript 엔진은 소스 코드를 단순히 한 줄씩 해석하는 데 그치지 않고, 바이트코드 생성, 기계어 컴파일, 실행 중 최적화, 메모리 관리와 WebAssembly 실행을 담당한다.
브라우저가 script 요소나 JavaScript 모듈을 불러오면 JavaScript 엔진은 소스 코드를 어휘 분석하고 구문 트리 또는 내부 표현으로 변환한다. 문법 오류가 없으면 바이트코드나 실행 가능한 중간 형태를 생성하고 프로그램을 평가한다.
초기 실행은 컴파일 비용을 줄이기 위해 인터프리터나 빠른 기본 컴파일러가 담당할 수 있다. 자주 실행되는 함수와 반복문은 실행 중 수집한 타입과 호출 정보를 바탕으로 최적화 컴파일러가 더 빠른 기계어로 다시 컴파일할 수 있다.
JavaScript는 변수에 고정된 정적 타입이 없는 동적 언어이므로, 최적화된 코드는 실행 중 값의 형태가 예상과 달라지면 기존 가정을 취소해야 할 수 있다. 엔진은 이 경우 최적화된 코드에서 일반적인 실행 경로로 되돌아가는 역최적화를 수행할 수 있다.
JavaScript 객체, 배열, 문자열과 함수는 실행 중 메모리를 사용한다. 엔진의 가비지 컬렉터는 더 이상 접근할 수 없는 객체를 찾아 메모리를 회수한다. 주 실행 스레드의 긴 가비지 컬렉션 중단을 줄이기 위해 세대별, 증분식, 동시와 병렬 수집 기법이 사용될 수 있다.
JavaScript 엔진은 DOM 자체를 구현하는 구성 요소와 구분된다. ECMAScript의 배열, 함수와 Promise 등은 엔진의 언어 기능이고, document, fetch, localStorage와 setTimeout은 브라우저의 웹 플랫폼이 제공하는 호스트 API다. Web IDL로 정의된 브라우저 객체와 JavaScript 값 사이에는 엔진과 렌더링 엔진을 연결하는 바인딩 계층이 존재한다.
웹 페이지의 주 JavaScript 실행 환경은 이벤트 루프와 연결된다. 이벤트, 타이머와 네트워크 작업이 태스크를 생성하고, Promise 반응은 마이크로태스크 대기열을 사용한다. 실행 중인 JavaScript 작업이 반환해야 브라우저가 다음 작업과 렌더링 갱신을 진행할 수 있으므로, 긴 동기 실행은 사용자 인터페이스를 응답하지 않는 상태로 만들 수 있다.
Web Worker는 문서의 주 실행 환경과 별도의 전역 환경에서 JavaScript를 실행한다. 작업자는 일반 DOM에 직접 접근하지 않지만 메시지 전달과 공유 메모리 등 허용된 방법으로 다른 실행 환경과 통신한다.
JavaScript 엔진은 신뢰할 수 없는 코드를 실행하므로 브라우저 보안의 핵심 공격 표면이다. 엔진 취약점이 발견되더라도 운영체제 전체 권한으로 곧바로 이어지지 않도록, 웹 콘텐츠는 일반적으로 권한이 제한된 렌더러 프로세스 안에서 실행된다. 브라우저는 엔진 보안과 프로세스 샌드박스, 사이트 격리를 함께 사용한다.
대표적인 JavaScript 엔진에는 다음이 있다.
- V8: Chromium과 Google Chrome에서 사용하는 JavaScript·WebAssembly 엔진이다. Node.js에서도 사용된다.[81]
- SpiderMonkey: Mozilla Firefox에서 사용하는 JavaScript·WebAssembly 엔진이다.[82]
- JavaScriptCore: WebKit에 내장된 JavaScript 엔진이며 Safari에서는 Nitro라는 명칭으로도 소개되어 왔다.[83]
렌더링 엔진과 JavaScript 엔진은 밀접하게 협력하지만 별개의 구성 요소다. Chromium 기반 브라우저는 일반적으로 Blink와 V8을 함께 사용하고, Firefox는 Gecko와 SpiderMonkey, Safari는 WebKit과 JavaScriptCore를 사용한다.
네트워크 처리
브라우저의 네트워크 계층은 URL을 실제 요청으로 변환하고, DNS 조회와 연결 설정, HTTP·TLS 처리, 프록시와 캐시, 쿠키 및 보안 정책을 관리한다. 사용자가 하나의 페이지를 열어도 HTML, CSS, JavaScript, 이미지, 글꼴과 API 요청이 서로 다른 출처로 전송될 수 있다.
브라우저는 URL의 스킴과 호스트, 포트, 경로와 질의를 분석한다. HTTP 또는 HTTPS URL이면 호스트 이름을 DNS로 해석하고 서버와 연결을 시도한다. 이미 사용할 수 있는 연결이 있다면 새 연결을 만드는 대신 재사용할 수 있다.
HTTPS에서는 HTTP 요청을 보내기 전에 TLS 핸드셰이크와 인증서 검증이 이루어진다. 브라우저는 인증서의 서명 체인, 유효 기간과 접속한 호스트 이름을 검사한다. 검증할 수 없는 인증서는 사용자에게 경고하거나 연결을 차단할 수 있다.
브라우저는 서버와 환경이 지원하는 HTTP 버전을 선택한다. HTTP/1.1에서는 하나 이상의 TCP 연결을 재사용하고, HTTP/2에서는 한 연결의 여러 스트림으로 요청을 다중화하며, HTTP/3에서는 QUIC을 사용한다.
HTML 파서가 외부 자원의 URL을 발견하면 렌더러가 네트워크 요청을 시작하도록 전달한다. 브라우저는 문서에 명시된 자원뿐 아니라 미리 불러오기가 유리하다고 판단한 스타일시트, 스크립트와 이미지 후보를 추측하여 사전 로드할 수 있다.
Chromium의 다중 프로세스 구조에서는 브라우저 프로세스가 네트워크 접근을 통제하고, 렌더러 프로세스의 자원 요청을 받아 네트워크 계층과 연결한다. 이는 렌더러가 임의의 로컬 파일이나 네트워크 자원에 직접 접근하지 못하게 하는 보안 경계의 일부다.[84]
브라우저는 HTTP 리디렉션을 처리하고, 새로운 URL에 대해 권한과 보안 정책을 다시 평가한다. 리디렉션이 다른 출처로 이동하면 쿠키와 인증 정보의 전송 범위, CORS와 리퍼러 정책이 달라질 수 있다.
동일 출처 정책은 한 출처에서 실행되는 스크립트가 다른 출처의 응답 내용을 임의로 읽지 못하도록 제한한다. 다른 출처의 이미지와 스타일시트 등을 문서에 포함하는 것은 허용될 수 있지만, 스크립트가 응답 데이터에 접근하려면 CORS와 같은 명시적인 허용이 필요할 수 있다.
브라우저는 쿠키의 Domain, Path, Secure, HttpOnly, SameSite 속성과 파티션 정책을 적용한다. 요청을 보낼 때 현재 URL과 최상위 사이트, 보안 연결 및 요청 문맥을 기준으로 포함할 쿠키를 선택한다.
혼합 콘텐츠 정책은 HTTPS 문서가 보안되지 않은 HTTP 스크립트나 프레임과 같은 자원을 불러오는 것을 차단하거나 업그레이드할 수 있다. 암호화된 최상위 문서 안에서 변조 가능한 능동 콘텐츠가 실행되면 HTTPS가 제공하는 보호가 무력화될 수 있기 때문이다.
콘텐츠 보안 정책, 리퍼러 정책, 교차 출처 격리 정책과 권한 정책도 네트워크 요청과 문서 실행에 영향을 준다. 서버는 HTTP 헤더로 이러한 정책을 전달하고 브라우저는 자원 요청과 스크립트 실행 전에 이를 적용한다.
브라우저는 프록시 설정과 VPN, 운영체제 네트워크 설정을 사용할 수 있다. 기업 관리 환경에서는 프록시 자동 구성, 인증 프록시, 사설 인증 기관과 트래픽 검사 시스템이 브라우저 연결에 참여할 수 있다.
다운로드 요청은 일반 문서 탐색과 다르게 처리될 수 있다. 응답의 콘텐츠 처리 지시와 미디어 유형, 사용자 선택에 따라 브라우저 안에서 표시하거나 파일로 저장한다. PDF와 일부 미디어는 내장 뷰어에서 표시될 수 있다.
서비스 워커는 특정 출처의 요청을 브라우저 안에서 가로채어 캐시된 응답을 반환하거나 네트워크 요청을 수정·대체할 수 있다. 다만 서비스 워커도 브라우저 보안 모델과 출처 범위 안에서 실행되며 임의의 다른 사이트 트래픽을 가로채지는 못한다.
브라우저의 일반적인 네트워크 처리
- 사용자가 URL 입력 또는 링크 선택↓
- URL 분석과 탐색 정책 확인↓
- 브라우저 캐시와 서비스 워커 확인↓
- DNS를 통한 호스트 주소 해석↓
- TCP 또는 QUIC 연결 설정↓
- HTTPS인 경우 TLS와 인증서 검증↓
- HTTP 요청 전송↓
- 리디렉션·인증·쿠키와 보안 정책 처리↓
- 응답 헤더와 콘텐츠 수신↓
- 캐시 저장 여부 결정↓
- 렌더러 또는 다운로드 처리기에 콘텐츠 전달
저장소와 캐시
브라우저는 웹 콘텐츠와 사용자 상태를 여러 종류의 저장소에 보관한다. HTTP 응답을 재사용하는 네트워크 캐시, 쿠키, Web Storage, IndexedDB, 서비스 워커 캐시, 방문 기록, 북마크, 비밀번호와 다운로드 기록은 목적과 접근 권한이 서로 다르다.
HTTP 캐시는 서버에서 받은 응답과 메타데이터를 저장한다. 저장된 응답이 신선하면 네트워크 요청 없이 재사용하고, 오래되었으면 ETag나 수정 시각을 사용한 조건부 요청으로 원본 서버에 검증할 수 있다.
브라우저 캐시는 일반적으로 특정 사용자 프로필이 사용하는 개인 캐시다. Cache-Control: private 응답도 저장할 수 있지만, no-store 지시가 있는 응답은 저장하지 않아야 한다. 캐시는 저장 공간 압박이나 사용자 설정에 따라 유효 기간 전에 제거될 수도 있으므로 영구 저장소로 사용할 수 없다.
메모리 캐시는 현재 브라우저 세션이나 문서에서 자주 사용하는 자원을 빠르게 재사용하고, 디스크 캐시는 더 큰 응답을 브라우저 재시작 이후에도 보존할 수 있다. 실제 캐시 계층과 우선순위는 브라우저 구현에 따라 다르다.
쿠키는 서버가 설정하고 이후 조건에 맞는 HTTP 요청에 포함되는 작은 이름·값 데이터다. 로그인 세션, 사용자 선택과 추적 식별자에 사용될 수 있다. HttpOnly 쿠키는 JavaScript 접근을 제한하고, Secure 쿠키는 보안 연결에서만 전송하며, SameSite는 교차 사이트 요청에 포함되는 범위를 제어한다.
Web Storage는 localStorage와 sessionStorage를 제공한다. localStorage는 출처별 문자열 키와 값을 브라우저 세션 이후에도 유지할 수 있고, sessionStorage는 대체로 탭의 페이지 세션 범위에서 사용된다. 두 저장소는 동기식 인터페이스이므로 많은 데이터를 빈번하게 처리하는 용도에는 적합하지 않을 수 있다.
IndexedDB는 출처별로 구조화된 객체와 인덱스를 비동기적으로 저장하는 데이터베이스 API다. 오프라인 응용 프로그램, 대규모 클라이언트 데이터와 캐시 이외의 지속 상태에 사용할 수 있다.
Cache API는 요청과 응답 객체의 쌍을 저장한다. 서비스 워커와 함께 사용하여 정적 자원과 API 응답을 오프라인에서 제공할 수 있다. HTTP 캐시와 이름이 비슷하지만 웹 애플리케이션이 명시적으로 항목을 관리하는 별도의 저장소다.
Origin Private File System과 파일 시스템 관련 API는 출처가 관리하는 파일 형태의 데이터나 사용자가 명시적으로 허용한 로컬 파일을 처리할 수 있다. 브라우저는 웹사이트가 사용자 파일 시스템 전체를 임의로 읽지 못하도록 권한과 범위를 제한한다.
저장소는 일반적으로 출처나 사이트 단위로 격리된다. 한 출처의 스크립트는 다른 출처의 IndexedDB와 localStorage를 직접 읽을 수 없다. 다만 쿠키의 도메인 범위와 임베디드 콘텐츠, 저장소 파티셔닝 규칙은 저장소 종류와 브라우저의 개인정보 보호 정책에 따라 달라진다.
타사 콘텐츠를 통한 교차 사이트 추적을 줄이기 위해 브라우저는 서드파티 쿠키를 차단하거나 사이트별로 저장소를 분할할 수 있다. 같은 광고 또는 임베디드 출처라도 어떤 최상위 사이트 안에서 실행되는지에 따라 별도의 저장 공간을 사용하게 할 수 있다.
브라우저 프로필은 쿠키, 기록, 확장 기능, 설정과 저장소의 상위 관리 단위다. 여러 프로필은 같은 브라우저 설치를 사용하면서도 로그인 계정과 사이트 데이터를 분리할 수 있다. 동기화 기능은 선택된 북마크, 비밀번호, 기록과 설정을 브라우저 제공자의 서버를 통해 다른 기기로 복제할 수 있다.
비밀번호 관리자는 사이트의 인증 정보를 암호화된 저장소에 보관하고 해당 출처에서 자동 완성을 제공한다. 패스키와 WebAuthn 자격 증명은 운영체제나 보안 장치, 동기화 서비스와 결합할 수 있으며 일반적인 웹 저장소에서 JavaScript가 직접 읽는 문자열 비밀번호와 다르게 처리된다.
브라우저는 저장소 사용량에 할당량을 적용한다. 사용 가능한 디스크 공간과 사이트 이용 상태, 저장소 지속성 요청에 따라 한도가 달라질 수 있다. 공간이 부족하면 덜 사용된 출처의 임시 데이터를 제거할 수 있다.
사용자가 사이트 데이터 삭제를 요청하면 브라우저는 쿠키, 저장소, 캐시와 서비스 워커 등록을 함께 제거할 수 있다. 다만 방문 기록, 다운로드 파일, 동기화된 데이터와 운영체제 자격 증명 저장소는 별도의 삭제 항목일 수 있다.
브라우저가 관리하는 주요 데이터
- 네트워크 재사용
- HTTP 메모리 캐시
- HTTP 디스크 캐시
- 조건부 요청 검증 정보
- 사이트 상태
- 쿠키
localStoragesessionStorage- IndexedDB
- Cache API
- 서비스 워커 등록
- 사용자 브라우저 데이터
- 방문 기록
- 북마크
- 다운로드 기록
- 저장된 비밀번호와 패스키
- 자동 완성 정보
- 브라우저 설정과 확장 기능
- 임시 실행 데이터
- DOM과 JavaScript 객체
- 디코딩된 이미지와 미디어
- 컴파일된 스크립트 정보
- 렌더링·GPU 자원
확장 기능
브라우저 확장 기능은 브라우저의 사용자 인터페이스와 웹 페이지 동작을 추가하거나 변경하는 설치형 소프트웨어 구성 요소다. 광고 및 추적 차단, 비밀번호 관리, 번역, 개발 도구, 접근성 보조와 업무 자동화 등에 사용된다.
확장 기능은 일반 웹 페이지보다 넓은 권한을 가질 수 있다. 사용자의 탭과 방문 중인 URL을 읽거나, 특정 사이트의 문서를 변경하고, 네트워크 요청에 관한 정보를 확인하며, 북마크와 다운로드를 관리할 수 있다. 실제 권한은 확장 기능이 선언하고 사용자가 허용한 범위에 따라 제한된다.
현대 Chromium 계열과 Firefox의 확장 체계는 대체로 WebExtensions 계열 API와 선언 형식을 사용한다. 확장 기능은 매니페스트 파일에 이름, 버전, 실행 코드와 필요한 권한을 선언하고, 브라우저가 제공하는 확장 API를 호출한다.
확장 기능의 주요 구성은 다음과 같이 나뉠 수 있다.
- 콘텐츠 스크립트는 허용된 웹 페이지 안에서 실행되어 DOM을 읽거나 변경한다.
- 백그라운드 컨텍스트는 탭과 브라우저 이벤트를 처리하고 장기간 상태를 관리한다.
- 브라우저 액션은 도구 모음 아이콘과 팝업 인터페이스를 제공한다.
- 옵션 페이지는 확장 기능의 설정 화면을 제공한다.
- 개발자 도구 확장은 브라우저 개발자 도구에 패널과 분석 기능을 추가한다.
콘텐츠 스크립트는 페이지 문맥과 관련되지만 일반적으로 별도의 JavaScript 실행 환경에 격리된다. 페이지와 DOM을 공유하면서도 JavaScript 전역 객체와 내부 변수가 직접 충돌하지 않도록 구성할 수 있다. 페이지 스크립트와 통신하려면 DOM 이벤트나 메시지 전달 등 명시적인 방법을 사용한다.
확장 기능은 브라우저 자체와 같은 권한으로 무제한 실행되는 전통적인 플러그인과 다르다. WebExtensions API는 허용된 기능만 노출하며, 브라우저는 확장 프로세스와 콘텐츠 스크립트에 별도의 보안 경계를 적용할 수 있다.
과거에는 NPAPI, ActiveX와 같은 브라우저 플러그인이 운영체제 네이티브 코드를 웹 페이지 안에서 실행하였다. 이러한 플러그인은 멀티미디어, 문서 뷰어와 응용 프로그램 기능을 제공했지만 안정성, 이식성, 업데이트와 샌드박스 문제를 일으켰다. HTML5 미디어, Canvas, WebGL, WebAssembly와 웹 API가 발전하면서 주요 브라우저는 범용 네이티브 플러그인 지원을 제거하였다.
확장 기능은 보안과 개인정보 보호의 위험도 가진다. 광범위한 사이트 접근 권한을 가진 확장은 사용자가 보는 문서와 입력 내용을 읽거나 변경할 수 있다. 정상적인 확장이 인수된 뒤 악성 업데이트가 배포되거나, 사용자 데이터를 외부 서버로 전송하는 사례도 발생할 수 있다.
브라우저는 확장 기능 스토어의 심사, 코드 서명, 권한 경고, 자동 업데이트와 악성 확장 차단을 사용한다. 사용자는 설치 전에 개발자와 요청 권한을 확인하고 사용하지 않는 확장을 제거할 수 있다.
확장 API는 브라우저마다 완전히 동일하지 않다. Chromium 기반 브라우저 사이에는 높은 호환성이 있지만 각 제품의 계정, 사이드바와 기업 정책 기능에는 차이가 있다. Firefox와 Safari도 WebExtensions 계열을 지원하지만 지원 API, 매니페스트 버전과 배포 절차가 다를 수 있다.
Microsoft는 Edge가 Chromium 오픈 소스 브라우저 프로젝트를 기반으로 하며 다른 Chromium 기반 브라우저와 확장 생태계의 상당 부분을 공유한다고 설명한다.[85]
확장 기능은 웹 표준 자체가 아니다. 특정 확장 API에 의존하는 기능은 해당 브라우저와 확장을 설치한 사용자에게만 제공된다. 일반 웹사이트의 핵심 기능을 특정 확장 설치에만 의존시키면 다른 브라우저와 환경에서 이용할 수 없을 수 있다.
주요 브라우저와 엔진
현대 웹 브라우저 시장에는 여러 제품이 존재하지만, 웹 콘텐츠를 처리하는 핵심 엔진은 크게 Chromium의 Blink, Mozilla의 Gecko와 Apple 중심의 WebKit 계열로 집중되어 있다. 같은 엔진을 사용하는 브라우저도 사용자 인터페이스, 개인정보 보호 정책, 계정 서비스, 업데이트 주기와 기본 기능은 서로 다르다.
Google Chrome과 Chromium
Chromium은 오픈 소스 브라우저 프로젝트이며 Blink 렌더링 엔진과 V8 JavaScript 엔진을 사용한다. Chromium 프로젝트는 브라우저 프로세스, 렌더러, 네트워크, UI와 확장 체계를 포함하는 기반을 제공한다.
Google Chrome은 Chromium을 기반으로 Google이 배포하는 브라우저다. Chromium의 웹 플랫폼 기능에 Google 계정 동기화, 업데이트 체계, 브랜드와 배포용 구성 요소를 결합한다.
Blink는 Chromium 소스 트리 안의 웹 렌더링 엔진이다. HTML·CSS·DOM과 여러 웹 API를 구현하며 Chrome뿐 아니라 Chromium 기반 브라우저와 Android WebView에서 사용된다.[86]
V8은 Chrome과 Chromium에서 JavaScript와 WebAssembly를 실행한다. V8은 브라우저 바깥의 Node.js와 다른 임베디드 환경에서도 사용되므로 Blink와 동일한 구성 요소는 아니다.[87]
Microsoft Edge
Microsoft Edge는 Microsoft가 개발하는 브라우저다. 초기 Edge는 자체 EdgeHTML 렌더링 엔진과 Chakra JavaScript 엔진을 사용했지만, 2020년부터 일반 배포된 현재 계열은 Chromium 프로젝트를 기반으로 한다.
현재 Edge는 Blink와 V8을 사용하면서 Microsoft 계정, Windows 통합, 기업 관리 정책, 추적 방지와 자체 사용자 인터페이스를 추가한다. Chromium 기반이므로 Chrome 확장 형식과 웹 플랫폼 구현의 상당 부분을 공유한다.[88]
Mozilla Firefox
Mozilla Firefox는 Mozilla가 개발하는 오픈 소스 브라우저다. 렌더링과 웹 플랫폼에는 Gecko, JavaScript와 WebAssembly 실행에는 SpiderMonkey를 사용한다.
Gecko는 HTML 파싱, DOM, CSS와 렌더링뿐 아니라 네트워킹, 프로세스 간 통신과 브라우저 플랫폼의 여러 부분을 포함한다. Firefox 데스크톱과 Android용 Firefox는 Gecko 계열을 사용하며, Android에서는 GeckoView를 통해 브라우저 응용 프로그램에 엔진 기능을 제공한다.[89]
SpiderMonkey는 Firefox에서 사용하는 JavaScript·WebAssembly 구현체이며 별도의 라이브러리와 명령줄 셸로도 구성할 수 있다.[90]
Firefox는 주요 데스크톱 브라우저 가운데 Chromium이나 WebKit이 아닌 독립적인 엔진 계보를 유지한다. 이는 웹 표준을 여러 독립 구현에서 검증하고 특정 엔진에만 맞춘 사이트를 발견하는 데 의미가 있다.
Apple Safari
Safari는 Apple이 macOS, iPhone과 iPad 등에 제공하는 웹 브라우저다. 웹 콘텐츠 엔진으로 WebKit, JavaScript 엔진으로 JavaScriptCore를 사용한다.
WebKit은 Safari뿐 아니라 Apple 플랫폼의 Mail, App Store와 여러 시스템 응용 프로그램에서 웹 콘텐츠를 표시하는 데 사용된다. Linux에서는 WebKitGTK와 WPE WebKit 같은 포트를 통해 다른 브라우저와 임베디드 응용 프로그램에서도 사용된다.[91]
WebKit은 하나의 브라우저 제품이 아니라 여러 플랫폼에 이식할 수 있는 엔진 프로젝트다. Safari는 WebKit 위에 Apple의 브라우저 인터페이스, 동기화, 개인정보 보호 기능과 운영체제 통합을 제공한다.
Opera, Brave와 Vivaldi
Opera, Brave와 Vivaldi는 Chromium을 기반으로 하는 데스크톱·모바일 브라우저다. 이들은 Blink와 V8, Chromium의 다중 프로세스 구조와 확장 기능 기반을 공유하면서 서로 다른 사용자 인터페이스와 서비스 정책을 제공한다.
Opera는 사이드바, 작업 공간, 데이터 절약과 자체 서비스 통합 기능을 제공한다. Brave는 광고·추적 차단과 개인정보 보호 기능을 중심으로 Chromium의 네트워크 및 콘텐츠 처리 정책을 변경한다. Vivaldi는 탭 배치, 패널, 명령과 사용자 인터페이스의 높은 사용자화를 강조한다.
Chromium 공식 개발자 문서는 Blink가 Chrome, Android WebView, Microsoft Edge, Opera와 Brave를 포함한 Chromium 기반 브라우저에서 사용된다고 설명한다.[92]
Chromium 기반이라는 사실은 모든 브라우저가 Google Chrome과 동일하다는 뜻이 아니다. 각 개발사는 동기화 서버, 기본 검색, 추적 방지, 광고 기능, 코덱, 업데이트와 UI 구성 요소를 변경하거나 제거할 수 있다.
NAVER Whale과 Samsung Internet
NAVER Whale은 네이버가 개발하는 Chromium 기반 브라우저다. Blink와 V8을 기반으로 사이드바, 듀얼 탭, 번역, 스크랩북과 네이버 서비스 통합 기능을 제공한다.
Samsung Internet은 삼성전자가 Android와 관련 환경에 제공하는 Chromium 기반 모바일 브라우저다. 모바일 장치와 삼성 생태계에 맞춘 사용자 인터페이스, 개인정보 보호와 확장형 콘텐츠 차단 기능을 제공한다.
이들 브라우저도 Chromium의 웹 호환성을 공유하지만 Chromium 버전 반영 시기, 기능 플래그와 플랫폼 API 지원에는 차이가 있을 수 있다.
WebKit 기반 브라우저와 임베디드 엔진
macOS의 Safari 외에도 GNOME Web 또는 Epiphany는 WebKitGTK를 사용한다. WPE WebKit은 임베디드·자동차·텔레비전과 같은 환경에서 웹 콘텐츠를 표시하는 데 사용된다.
운영체제의 WebView 구성 요소도 완성된 브라우저와 구분된다. Android WebView는 응용 프로그램 안에 Chromium 기반 웹 콘텐츠를 포함하고, Apple 플랫폼의 WKWebView는 WebKit 기반 콘텐츠를 응용 프로그램에 삽입한다. WebView를 사용하는 앱은 주소창과 탭 같은 일반 브라우저 UI를 제공하지 않을 수 있지만 웹 엔진의 문서 처리 기능을 사용한다.
엔진 계보와 구분
브라우저·렌더링 엔진·JavaScript 엔진의 관계는 다음과 같이 정리할 수 있다.
주요 웹 브라우저와 엔진
- Chromium 계열
- Mozilla 계열
- 웹 플랫폼·렌더링 엔진: Gecko
- JavaScript 엔진: SpiderMonkey
- GeckoView 기반 브라우저
- WebKit 계열
- 웹 콘텐츠 엔진: WebKit
- JavaScript 엔진: JavaScriptCore
- GNOME Web
- WebKitGTK 기반 응용 프로그램
- WPE WebKit 기반 임베디드 환경
- WKWebView 기반 응용 프로그램
KHTML은 KDE의 Konqueror에서 개발된 엔진으로 WebKit 형성에 영향을 주었다. Apple은 KHTML과 KJS를 바탕으로 WebKit과 JavaScriptCore를 발전시켰고, 초기 Google Chrome은 WebKit을 사용하였다. Google은 2013년 Chromium의 WebKit 계통을 분리하여 Blink를 만들었다.
엔진 이름의 경계는 프로젝트에 따라 다르다. Blink는 Chromium 안에서 웹 렌더링과 플랫폼 구현을 담당하지만 네트워크, 브라우저 UI와 V8 전체를 뜻하지 않는다. Gecko는 Mozilla 문서에서 렌더링뿐 아니라 네트워크, JavaScript 통합과 IPC 등 더 넓은 플랫폼 영역을 포함하는 엔진으로 설명된다. WebKit 역시 WebCore와 JavaScriptCore, 다중 프로세스 API 계층 등이 결합된 프로젝트다.
같은 웹 표준을 구현해도 엔진별로 기능 도입 시기, 성능 특성, 접근성, 그래픽과 플랫폼 통합에 차이가 있다. 웹 개발자는 하나의 Chromium 기반 브라우저에서 작동한다는 사실만으로 모든 브라우저에서 동일하게 작동한다고 가정하지 않고, 주요 독립 엔진에서 기능과 사용자 경험을 시험할 수 있다.
브라우저의 역할은 웹 표준을 그대로 실행하는 데만 있지 않다. 사용자의 인증 정보와 저장소, 장치 권한을 보호하고, 악성 콘텐츠를 격리하며, 접근성과 국제화를 지원하고, 빠르게 변화하는 웹 플랫폼을 이전 콘텐츠와 호환되도록 구현해야 한다. 따라서 현대 웹 브라우저는 운영체제 위에서 또 하나의 응용 프로그램 실행 플랫폼에 가까운 구조를 가진다.
웹 서버와 서버 측 처리
웹 서버는 HTTP 요청을 수신하고 상태 코드, 헤더와 선택적인 콘텐츠로 구성된 HTTP 응답을 반환하는 소프트웨어 또는 이를 실행하는 컴퓨터를 뜻한다. 웹 서버는 저장된 HTML·CSS·JavaScript·이미지 파일을 그대로 전송할 수도 있고, 요청을 응용 프로그램에 전달하여 사용자와 현재 데이터에 맞는 응답을 동적으로 생성할 수도 있다.
웹 서버와 서버 측 응용 프로그램은 같은 구성 요소일 수도 있고 분리될 수도 있다. 소규모 응용 프로그램은 하나의 프로세스가 HTTP 연결, 라우팅, 정적 파일과 동적 요청을 모두 처리할 수 있다. 대규모 서비스에서는 외부 요청을 받는 리버스 프록시, 여러 응용 서버, 데이터베이스, 캐시, 메시지 대기열과 파일 저장소가 각각 별도의 시스템으로 운영되는 경우가 많다.
서버 측 처리는 브라우저에 표시할 HTML만 생성하는 작업에 한정되지 않는다. JSON 기반 웹 API, 파일과 영상, 리디렉션, 인증 결과, 실시간 이벤트와 오류 응답도 생성할 수 있다. 브라우저에서 화면을 렌더링하는 클라이언트 측 처리와 서버에서 데이터와 권한을 처리하는 서버 측 처리는 하나의 웹 애플리케이션 안에서 함께 사용된다.
현대의 웹 서버 환경은 자체 컴퓨터 한 대에서 실행되는 전통적인 호스팅부터 가상 머신, 컨테이너, 관리형 응용 플랫폼, 함수형 서버리스 서비스와 전 세계에 분산된 클라우드 인프라까지 폭넓다. 배포 방식이 달라져도 클라이언트에는 일반적으로 URL과 HTTP 응답을 제공하는 같은 웹 자원으로 나타난다.
정적 파일 제공
정적 파일 제공은 서버에 미리 저장된 파일을 요청에 따라 읽어 거의 그대로 응답 콘텐츠로 전송하는 방식이다. HTML 문서, CSS 스타일시트, JavaScript 파일, 이미지, 글꼴, PDF와 미리 생성된 오디오·영상 파일이 대표적인 정적 자원이다.
클라이언트가 특정 URL을 요청하면 웹 서버는 설정된 문서 루트와 URL 경로 매핑 규칙에 따라 대응하는 파일을 찾는다. 파일이 존재하고 접근이 허용되면 적절한 상태 코드와 Content-Type, 파일 크기, 수정 시각과 캐시 관련 헤더를 포함하여 응답한다.
Apache HTTP Server는 정적 콘텐츠를 파일 시스템에 존재하는 HTML, 이미지와 CSS 등의 파일로 설명하며, 요청 경로를 서버의 문서 디렉터리에 연결하여 제공한다.[93]
URL 경로가 실제 파일 경로와 반드시 동일할 필요는 없다. 웹 서버는 별칭, 가상 호스트와 경로 규칙을 사용해 외부 URL을 다른 디렉터리나 저장소의 파일에 연결할 수 있다. /assets/logo.svg가 서버의 /srv/site/public/images/logo.svg에 대응하도록 구성하는 식이다.
디렉터리 URL이 요청되면 서버는 index.html과 같이 설정된 기본 문서를 찾을 수 있다. 기본 문서가 없을 때 디렉터리 목록을 생성하도록 설정할 수도 있지만, 파일 구조와 비공개 파일이 노출될 수 있어 공개 서비스에서는 비활성화되는 경우가 많다.
정적 파일의 응답 내용은 일반적으로 사용자 계정이나 요청 시각에 따라 바뀌지 않는다. 같은 파일 버전을 요청한 클라이언트는 같은 바이트열을 받을 수 있으므로 캐시와 콘텐츠 전송 네트워크를 효율적으로 사용할 수 있다.
브라우저와 중간 캐시는 Cache-Control, ETag와 Last-Modified를 이용해 정적 자원을 저장하고 재사용할 수 있다. 파일 이름에 콘텐츠 해시나 버전을 포함하면 내용이 바뀔 때 URL도 바뀌게 하여 긴 캐시 수명을 안전하게 설정할 수 있다.
app.7b92d4.js
이 방식에서는 해당 URL의 파일 내용이 바뀌지 않는다는 전제로 immutable과 긴 max-age를 적용하고, 새로운 배포에서는 새 해시를 가진 파일을 참조한다.
정적 파일은 gzip이나 Brotli로 미리 압축하거나 요청 시 압축해 전송할 수 있다. 서버는 클라이언트의 Accept-Encoding을 확인하고 선택한 인코딩을 Content-Encoding으로 알린다. JPEG와 영상처럼 이미 압축된 형식은 추가 압축의 효과가 작을 수 있다.
대용량 파일과 미디어에는 HTTP 범위 요청을 사용할 수 있다. 클라이언트가 파일의 일부 바이트 구간을 요청하면 서버는 지원 가능한 경우 206 Partial Content와 Content-Range를 반환한다. 중단된 다운로드의 재개와 영상 탐색에 사용된다.
웹 서버는 파일 확장자나 설정을 기반으로 미디어 유형을 결정한다. 실제 콘텐츠와 Content-Type이 일치하지 않으면 브라우저가 파일을 잘못 해석하거나 스크립트로 실행하는 보안 문제가 발생할 수 있으므로 올바른 유형을 지정해야 한다.
정적 사이트는 HTML을 요청 시점에 생성하지 않고 빌드 또는 작성 단계에서 미리 생성한다. 블로그, 문서 사이트와 제품 소개 페이지는 정적 사이트 생성기를 사용하여 템플릿과 원본 데이터를 배포 가능한 HTML 파일로 변환할 수 있다. MDN은 정적 사이트를 HTML·CSS·JavaScript 파일로 구성하며, 서버 측에서 매번 생성할 필요가 없는 콘텐츠 중심 사이트에 흔히 사용한다고 설명한다.[94]
정적이라는 표현은 브라우저에서 아무 동작도 하지 않는다는 뜻이 아니다. 정적으로 제공된 HTML과 JavaScript가 브라우저에서 API를 호출하고 화면을 동적으로 변경할 수 있다. 이 경우 서버가 제공한 파일은 정적이지만 사용자 경험은 동적 웹 애플리케이션일 수 있다.
정적 자원은 일반 웹 서버뿐 아니라 객체 저장소와 CDN에서 직접 제공할 수 있다. 객체 저장소 기반 정적 호스팅은 서버 프로세스를 직접 운영하지 않고 파일과 접근 정책, 기본 문서와 오류 문서를 설정하는 형태로 구성된다.
정적 파일 제공 흐름
- 클라이언트가 자원 URL 요청↓
- 웹 서버가 경로와 가상 호스트 규칙 확인↓
- 파일 시스템 또는 객체 저장소에서 대상 탐색↓
- 권한, 미디어 유형과 캐시 메타데이터 결정↓
- 조건부 요청과 범위 요청 확인↓
- 파일 콘텐츠 또는
304 Not Modified응답 반환
정적 파일 제공은 구조가 단순하고 빠르며 공격 표면이 비교적 작다. 그러나 로그인 사용자별 화면, 실시간 데이터와 입력 저장처럼 요청마다 달라지는 기능은 별도의 서버 측 처리나 브라우저의 API 통신이 필요하다.
동적 콘텐츠 생성
동적 콘텐츠는 서버가 요청을 처리하는 시점에 프로그램을 실행하거나 데이터를 조회하여 생성하는 응답이다. 같은 URL이라도 사용자, 요청 매개변수, 시간, 데이터베이스 상태와 권한에 따라 다른 콘텐츠를 반환할 수 있다.
동적 요청은 URL 경로와 HTTP 메서드, 헤더, 쿠키와 메시지 콘텐츠를 분석한 뒤 응용 프로그램의 특정 처리기로 전달된다. 응용 프로그램은 입력을 검증하고 필요한 데이터를 가져오며, 비즈니스 규칙을 적용하여 HTML, JSON 또는 다른 형식의 응답을 생성한다.
MDN은 동적 사이트의 일반적인 구조를 브라우저 요청이 서버 측 응용 프로그램으로 전달되고, 응용 프로그램이 데이터베이스에서 정보를 읽어 HTML 템플릿과 결합한 뒤 응답을 반환하는 형태로 설명한다.[95]
동적 HTML 생성에서는 문서의 공통 구조를 템플릿으로 정의하고, 요청마다 달라지는 값을 지정된 위치에 삽입한다. 기사 제목, 사용자 이름, 상품 목록과 검색 결과를 데이터베이스에서 가져와 하나의 HTML 문서로 조합할 수 있다.
서버가 완성도 높은 HTML을 생성하여 브라우저에 보내는 방식을 서버 측 렌더링이라고 한다. 브라우저는 초기 응답만으로 주요 내용을 표시할 수 있고, 이후 JavaScript가 이벤트 처리와 부분 갱신을 활성화할 수 있다. MDN은 서버 측 렌더링을 서버에서 HTML 콘텐츠를 생성하여 클라이언트에 전송하는 방식으로 정의한다.[96]
서버가 HTML 대신 JSON과 같은 데이터만 반환하고 브라우저의 JavaScript가 DOM을 구성할 수도 있다. 이 방식에서는 서버가 웹 API 역할을 하고 화면 렌더링은 클라이언트에서 이루어진다. 하나의 서비스가 최초 페이지에는 서버 측 렌더링을 사용하고 이후 탐색에는 API와 클라이언트 렌더링을 사용하는 혼합 구조도 가능하다.
동적 콘텐츠는 다음과 같은 정보를 기준으로 달라질 수 있다.
- URL 경로와 질의 매개변수
- HTTP 메서드와 요청 콘텐츠
- 로그인한 사용자와 권한
- 쿠키와 세션 상태
- 브라우저가 요청한 언어와 데이터 형식
- 데이터베이스의 현재 내용
- 시간, 위치와 서비스 상태
- 기능 실험과 사용자별 설정
요청 시점에 생성된다는 이유로 모든 동적 응답을 캐시할 수 없는 것은 아니다. 공개 뉴스 기사나 상품 목록처럼 일정 기간 여러 사용자에게 동일한 결과를 제공하는 응답은 서버 캐시, 리버스 프록시 또는 CDN에 저장할 수 있다.
사용자마다 달라지는 응답은 private, no-cache, no-store와 Vary 등의 캐시 정책을 신중하게 설정해야 한다. 인증된 사용자의 개인 정보가 공유 캐시에 저장되면 다른 사용자에게 노출될 수 있다.
동적 응답은 계산 비용과 외부 시스템 의존성을 가진다. 요청마다 복잡한 데이터베이스 질의와 템플릿 생성을 반복하면 응답 시간이 증가할 수 있으므로, 결과 캐시, 데이터 인덱스, 비동기 작업과 사전 계산을 사용한다.
시간이 오래 걸리는 작업은 요청 연결 안에서 모두 수행하지 않을 수 있다. 서버는 작업을 메시지 대기열에 넣고 202 Accepted로 수락 사실을 반환한 뒤, 별도의 작업 프로세스가 영상 변환, 보고서 생성이나 대규모 데이터 처리를 수행할 수 있다.
오류가 발생하면 서버는 처리 단계에 맞는 상태 코드와 오류 표현을 반환한다. 잘못된 입력에는 4xx, 서버 내부나 상위 시스템의 실패에는 5xx 상태 코드를 사용할 수 있다. 실제 프로그램 오류와 내부 경로, 자격 증명을 사용자용 오류 페이지에 그대로 노출하지 않아야 한다.
동적 응답 생성 흐름
- 클라이언트가 동적 자원 요청↓
- 웹 서버 또는 라우터가 요청 분류↓
- 인증, 권한과 입력 검증↓
- 응용 프로그램의 처리기 실행↓
- 데이터베이스, 캐시 또는 외부 서비스 조회↓
- 비즈니스 규칙 적용↓
- HTML 템플릿 또는 데이터 표현 생성↓
- 상태 코드와 헤더를 포함한 HTTP 응답 반환
정적 콘텐츠와 동적 콘텐츠는 하나의 사이트에서 함께 제공되는 경우가 일반적이다. CSS와 이미지 등의 파일은 정적으로 제공하고, 사용자 계정·검색·게시물과 결제 기능은 동적으로 처리할 수 있다.
서버 측 프로그래밍
서버 측 프로그래밍은 웹 서버가 받은 요청을 처리하고 데이터와 권한을 관리하며 HTTP 응답을 생성하는 프로그램을 작성하는 활동이다. 백엔드 개발 또는 서버 사이드 개발이라고도 한다.
서버 측 코드는 일반적으로 다음 작업을 수행한다.
- URL과 HTTP 메서드에 따른 라우팅
- 폼, JSON과 업로드 파일의 입력 처리
- 인증과 세션 관리
- 사용자와 역할에 따른 권한 검사
- 데이터베이스 읽기와 쓰기
- 템플릿 기반 HTML 생성
- 웹 API와 외부 서비스 호출
- 전자우편과 알림 발송
- 오류 처리, 로그와 성능 측정
- 비동기 작업과 메시지 처리
서버 측 프로그램은 다양한 프로그래밍 언어로 작성할 수 있다. JavaScript 또는 TypeScript, Python, PHP, Ruby, Java, C#, Go, Rust, C와 C++ 등이 사용되며, 같은 언어도 여러 런타임과 프레임워크를 선택할 수 있다.
대표적인 서버 측 환경에는 Node.js와 Deno, Django·Flask·FastAPI, PHP와 Laravel, Ruby on Rails, Java Servlet·Spring, ASP.NET Core, Go의 표준 HTTP 패키지와 여러 프레임워크 등이 있다. 이들은 라우팅, 요청 분석, 템플릿, 인증과 데이터베이스 연동에 필요한 공통 기능을 제공한다.
언어와 프레임워크는 HTTP 요청을 내부의 요청 객체로 변환하고, 프로그램이 반환한 결과를 HTTP 응답으로 직렬화한다. 일부 응용 서버는 직접 인터넷 연결을 받을 수 있지만, 운영 환경에서는 리버스 프록시 뒤에서 내부 포트나 Unix 도메인 소켓으로 요청을 받기도 한다.
초기의 대표적인 서버 프로그램 연결 방식에는 Common Gateway Interface가 있다. CGI는 웹 서버가 외부 프로그램을 실행하고 환경 변수와 표준 입출력을 통해 요청과 응답을 교환하는 규칙을 정의한다. Apache는 CGI를 웹 서버와 외부 콘텐츠 생성 프로그램이 상호작용하는 방식으로 설명한다.[97]
전통적인 CGI는 일반적으로 요청마다 새 프로세스를 실행하므로 높은 트래픽에서 시작 비용이 커질 수 있다. 이후 FastCGI, SCGI, WSGI, Rack, PSGI와 언어별 응용 서버 인터페이스가 지속 프로세스에서 여러 요청을 처리하도록 발전하였다.
현대의 응용 프로그램은 자체 HTTP 서버를 포함하는 경우가 많다. Node.js, Go와 ASP.NET Core 응용 프로그램은 독립적으로 포트를 열고 요청을 처리할 수 있다. 그래도 TLS 종료, 정적 파일, 압축, 접근 로그와 부하 분산을 위해 앞단에 범용 웹 서버나 관리형 게이트웨이를 둘 수 있다.
서버 측 프로그램은 여러 요청을 동시에 처리해야 한다. 프로세스와 스레드, 이벤트 루프, 비동기 입출력, 코루틴과 작업자 풀 등 다양한 동시성 모델이 사용된다. 적절한 모델은 언어 런타임, 작업의 CPU 사용량과 외부 입출력 비중에 따라 달라진다.
공유 상태를 응용 서버 한 대의 메모리에만 저장하면 요청이 다른 서버로 분산되거나 프로세스가 재시작될 때 상태가 사라질 수 있다. 세션과 중요한 데이터는 외부 데이터베이스, 분산 캐시 또는 서명된 클라이언트 토큰에 저장할 수 있다.
서버 프로그램은 클라이언트 입력을 신뢰해서는 안 된다. HTML 폼에서 제한한 값도 직접 조작된 HTTP 요청으로 바꿀 수 있으므로, 서버에서 형식과 길이, 범위, 권한을 다시 검증해야 한다.
템플릿에 사용자 입력을 삽입할 때는 출력 위치에 맞는 이스케이프가 필요하다. SQL 질의에는 매개변수 바인딩을 사용하고, 운영체제 명령과 파일 경로를 구성할 때도 명령 주입과 경로 순회 공격을 방지해야 한다.
비밀번호는 평문으로 저장하지 않고 비밀번호 저장에 적합한 단방향 키 파생 함수를 사용한다. 인증 쿠키와 토큰에는 유효 기간, 보안 전송, 사이트 범위와 위조 방지 정책을 적용해야 한다.
서버 측 프로그램은 처리 결과만 아니라 운영 정보를 남긴다. 접근 로그, 응용 로그, 분산 추적, 메트릭과 오류 보고를 사용해 요청 지연, 실패율과 외부 시스템 상태를 관찰한다. 개인정보와 인증 정보가 로그에 불필요하게 기록되지 않도록 해야 한다.
데이터베이스 연동
동적 웹 애플리케이션은 사용자, 문서, 상품, 주문, 권한과 서비스 상태를 지속적으로 저장하기 위해 데이터베이스를 사용한다. 서버 측 프로그램은 요청을 처리하면서 데이터를 조회하거나 수정하고 그 결과를 HTML 또는 API 응답으로 변환한다.
데이터베이스는 웹 서버의 로컬 파일일 수도 있지만 운영 환경에서는 별도의 프로세스나 서버, 관리형 클라우드 서비스로 분리되는 경우가 많다. 응용 서버와 데이터베이스는 전용 프로토콜과 인증된 네트워크 연결을 사용한다.
관계형 데이터베이스는 데이터를 표와 행, 열로 구성하고 키와 제약 조건으로 관계를 표현한다. PostgreSQL, MySQL, MariaDB, Microsoft SQL Server와 Oracle Database 등이 웹 서비스에 사용된다.
관계형 데이터베이스는 SQL을 사용하여 데이터를 조회하고 변경하며, 트랜잭션과 무결성 제약을 제공한다. 사용자와 주문, 결제처럼 서로 관련된 여러 데이터의 일관성이 중요한 시스템에서 널리 사용된다.
비관계형 데이터베이스는 문서, 키·값, 넓은 열과 그래프 등 다양한 모델을 제공한다. MongoDB, Redis, Cassandra, DynamoDB와 Neo4j 등이 해당 범주의 예다. 데이터 구조, 질의 형태, 확장 방식과 일관성 요구에 따라 선택된다.
하나의 웹 서비스가 여러 종류의 저장소를 함께 사용할 수 있다. 관계형 데이터베이스에 핵심 거래 데이터를 저장하고, Redis에 세션과 자주 조회하는 결과를 캐시하며, 객체 저장소에 이미지와 대용량 파일을 저장하고, 검색 엔진에 전문 검색용 색인을 유지할 수 있다.
일반적인 데이터베이스 요청 흐름은 다음과 같다.
웹 요청과 데이터베이스 연동
- 응용 서버가 요청과 사용자 권한 확인↓
- 데이터베이스 연결 풀에서 연결 획득↓
- 매개변수가 바인딩된 질의 또는 트랜잭션 실행↓
- 데이터베이스가 결과나 오류 반환↓
- 응용 프로그램이 결과를 객체와 도메인 모델로 변환↓
- HTML 템플릿 또는 JSON 응답 생성↓
- 트랜잭션 종료와 연결 반환
데이터베이스 연결을 요청마다 새로 만들면 인증과 네트워크 연결 비용이 커질 수 있다. 연결 풀은 미리 생성된 연결을 여러 요청이 재사용하도록 한다. 풀 크기를 지나치게 크게 설정하면 데이터베이스가 처리할 수 있는 연결 수를 초과할 수 있다.
SQL 문자열에 사용자 입력을 직접 이어 붙이면 SQL 삽입 공격이 발생할 수 있다. 준비된 문장과 매개변수 질의를 사용하여 코드와 데이터의 경계를 유지해야 한다.
객체 관계 매핑은 프로그램의 객체와 관계형 데이터베이스의 표를 연결한다. 반복적인 SQL과 변환 코드를 줄일 수 있지만, 생성되는 질의와 트랜잭션 동작을 이해하지 못하면 불필요한 다중 질의와 성능 문제가 생길 수 있다.
데이터를 여러 단계로 변경하는 작업에는 트랜잭션을 사용할 수 있다. 결제 기록을 추가하면서 주문 상태와 재고를 함께 변경해야 한다면 일부 변경만 반영되지 않도록 하나의 논리적 작업으로 처리한다.
동시 요청이 같은 데이터를 수정할 때 갱신 손실과 충돌이 발생할 수 있다. 잠금, 격리 수준, 버전 번호를 이용한 낙관적 동시성 제어와 원자적 데이터베이스 연산으로 처리할 수 있다.
자주 실행되는 질의의 검색 조건에는 적절한 인덱스를 둘 수 있다. 인덱스는 조회 성능을 높이지만 저장 공간을 사용하고 데이터 변경 비용을 증가시킨다. 실제 요청 패턴과 실행 계획을 분석하여 구성해야 한다.
캐시는 데이터베이스 질의 결과나 계산된 응답을 빠른 저장소에 보관한다. 캐시 적중 시 데이터베이스 접근을 줄일 수 있지만 원본 데이터가 변경되었을 때 캐시를 언제 갱신하거나 만료할지 결정해야 한다.
읽기 트래픽이 많은 시스템은 복제본에 조회를 분산할 수 있다. 복제가 비동기적으로 이루어지면 쓰기 직후 복제본에서 이전 값이 보일 수 있으므로 필요한 일관성 수준을 고려해야 한다.
샤딩은 데이터를 키나 범위에 따라 여러 데이터베이스에 나눈다. 저장 용량과 처리량을 확장할 수 있지만 여러 샤드에 걸친 질의, 트랜잭션, 재분배와 장애 복구가 복잡해진다.
데이터베이스 스키마는 응용 프로그램과 함께 변화한다. 테이블과 열, 인덱스를 변경하는 마이그레이션은 이전 코드와의 호환성, 대용량 데이터 처리와 무중단 배포를 고려해야 한다.
데이터는 정기적으로 백업하고 실제 복구 절차를 검증해야 한다. 고가용성 복제는 운영 장애를 줄이지만 잘못된 삭제와 프로그램 오류도 복제할 수 있으므로 백업을 대체하지 않는다.
데이터베이스 자격 증명은 소스 코드와 공개 저장소에 직접 포함하지 않고 환경 설정, 비밀 관리 시스템이나 실행 환경의 역할 기반 자격 증명을 통해 제공한다. 응용 프로그램에는 필요한 데이터와 연산에 한정된 최소 권한을 부여한다.
리버스 프록시와 게이트웨이
리버스 프록시는 외부 클라이언트의 요청을 먼저 받은 뒤 하나 이상의 내부 서버에 전달하고, 내부 서버의 응답을 클라이언트에 반환하는 중간 시스템이다. 클라이언트에는 리버스 프록시가 대상 웹 서버처럼 보인다.
순방향 프록시가 주로 클라이언트 측을 대신해 외부 서버에 접근한다면, 리버스 프록시는 서버 운영 측에 배치되어 원본 서버를 대표한다. MDN은 리버스 프록시가 부하 분산, 인증, 복호화와 캐싱을 통해 서버 접근을 통제하고 보호하는 데 사용된다고 설명한다.[98]
NGINX는 HTTP 웹 서버이면서 리버스 프록시, 콘텐츠 캐시와 부하 분산 장치로 사용할 수 있다.[99] Apache HTTP Server, HAProxy, Caddy, Envoy와 클라우드 사업자의 관리형 로드 밸런서도 비슷한 역할을 수행할 수 있다.
리버스 프록시는 URL의 호스트, 경로, 메서드와 헤더를 기준으로 요청을 서로 다른 서버에 전달할 수 있다.
/static/ 요청은 파일 서버로 보내고, /api/는 API 서버로, /account/는 인증 응용 프로그램으로 전달하는 식이다.
하나의 공개 도메인 아래에 여러 내부 서비스를 배치하면 클라이언트는 내부 주소와 포트를 알 필요가 없다. 내부 서버 구성과 배포 위치가 바뀌어도 외부 URL을 유지할 수 있다.
리버스 프록시의 주요 역할에는 다음이 포함된다.
- TLS 인증서와 HTTPS 연결 종료
- HTTP/2·HTTP/3와 내부 HTTP 버전 사이의 변환
- 정적 파일과 압축 응답 제공
- 여러 응용 서버로 부하 분산
- 장애 서버 제외와 상태 검사
- 응답 캐시와 콘텐츠 압축
- 인증과 접근 제어
- 요청 속도 제한과 연결 수 제어
- 웹 응용 프로그램 방화벽과 보안 필터
- 접근 로그와 요청 추적 정보 추가
부하 분산은 여러 상위 서버 가운데 요청을 처리할 대상을 선택한다. 순환 방식, 가중치, 최소 연결 수, 해시와 지연 시간 등 다양한 알고리즘을 사용할 수 있다. NGINX의 HTTP 부하 분산 기능은 HTTP·HTTPS뿐 아니라 FastCGI, uWSGI, SCGI와 gRPC 상위 서버에도 요청을 분산할 수 있다.[100]
상위 서버의 상태 검사를 수행하여 응답하지 않는 인스턴스를 대상에서 제외할 수 있다. 새 인스턴스를 추가하면 전체 서비스를 중단하지 않고 처리 용량을 늘릴 수 있다.
사용자 세션을 특정 서버의 로컬 메모리에만 저장하면 요청이 다른 서버로 이동할 때 로그인이 끊길 수 있다. 세션 고정으로 같은 사용자를 특정 서버에 보내거나, 세션 상태를 외부 저장소에 두어 모든 응용 서버가 공유할 수 있다.
리버스 프록시는 외부 HTTPS 연결을 종료하고 내부 서버에 HTTP 또는 새로운 HTTPS 연결을 만들 수 있다. 외부 연결이 암호화되어 있어도 프록시는 요청 내용을 읽고 라우팅과 필터링을 수행한다. 내부 네트워크도 신뢰할 수 없거나 규정상 암호화가 필요하면 상위 서버까지 TLS를 사용한다.
프록시는 원래 클라이언트의 IP 주소와 사용한 스킴, 호스트 정보를 내부 서버에 전달하기 위해 Forwarded 또는 X-Forwarded-* 계열 헤더를 추가할 수 있다. 응용 서버는 신뢰하도록 설정된 프록시가 추가한 값만 사용해야 하며, 외부 클라이언트가 임의로 보낸 같은 이름의 헤더를 그대로 신뢰하면 안 된다.
HTTP에서 게이트웨이는 클라이언트에 원본 서버처럼 보이면서 요청을 다른 서버나 프로토콜로 전달하는 중간 시스템이다. 리버스 프록시는 일반적으로 게이트웨이의 한 형태로 설명할 수 있다.
API 게이트웨이는 여러 API 서비스의 공통 진입점 역할을 한다. 경로 라우팅, 인증 토큰 검증, 요청 제한, API 키, 스키마 검사, 응답 변환, 사용량 측정과 개발자 정책을 중앙에서 처리할 수 있다.
웹 서버와 응용 프로그램 사이에는 HTTP 외의 게이트웨이 인터페이스도 사용된다. FastCGI는 지속적으로 실행되는 프로그램에 요청을 전달하고, WSGI와 ASGI는 Python 웹 서버와 응용 프로그램 사이의 호출 규약을 정의한다. Java의 Servlet과 Ruby의 Rack도 각 생태계에서 비슷한 추상화를 제공한다.
리버스 프록시가 포함된 서버 구조
- 인터넷 클라이언트
- CDN 또는 엣지 네트워크
- 리버스 프록시·부하 분산 장치
- 정적 파일 서버
- 웹 응용 서버
- 인스턴스 1
- 인스턴스 2
- 인스턴스 3
- API 게이트웨이
- 사용자 서비스
- 결제 서비스
- 검색 서비스
- 공통 저장소
- 데이터베이스
- 분산 캐시
- 객체 저장소
리버스 프록시는 서비스의 확장과 중앙 정책 적용을 돕지만 추가적인 장애 지점이 될 수 있다. 여러 인스턴스와 지역에 중복 배치하고, 설정 오류와 인증서 갱신, 상위 서버 시간 초과와 버퍼 제한을 관찰해야 한다.
호스팅과 클라우드 환경
웹 호스팅은 웹사이트와 웹 응용 프로그램을 인터넷 또는 네트워크에서 접근할 수 있도록 서버, 저장 공간, 연결과 운영 환경을 제공하는 서비스다. 호스팅 사업자는 물리 장비와 네트워크부터 운영체제, 런타임과 배포 플랫폼까지 서로 다른 수준으로 관리할 수 있다.
초기의 웹사이트는 기관이나 개인이 직접 관리하는 물리 서버에서 운영되는 경우가 많았다. 서버 관리자는 운영체제, 웹 서버, 네트워크 주소, 보안 업데이트와 백업을 직접 구성하였다. 이 형태는 높은 통제력을 제공하지만 장비와 회선, 전력과 장애 대응을 모두 관리해야 한다.
공유 호스팅은 하나의 서버 자원을 여러 고객의 웹사이트가 공유한다. 관리 비용이 낮고 간단한 사이트에 적합하지만 운영체제와 서버 설정에 대한 권한, 자원 사용량과 지원 기술이 제한될 수 있다.
가상 사설 서버는 하나의 물리 서버를 여러 가상 머신으로 나누어 각 고객에게 독립된 운영체제 환경을 제공한다. 사용자는 웹 서버와 데이터베이스를 직접 설치할 수 있지만 업데이트, 방화벽, 백업과 장애 대응도 관리해야 한다.
전용 서버는 물리 서버 전체를 하나의 고객이나 서비스가 사용한다. 자원 간섭을 줄이고 특수한 장비와 구성을 사용할 수 있지만 확장과 교체에 시간이 걸리고 비용이 높을 수 있다.
코로케이션은 고객이 소유한 장비를 데이터 센터에 설치하고 전력, 냉각, 물리 보안과 네트워크 연결을 제공받는 방식이다. 하드웨어 통제력은 높지만 장비 조달과 유지보수 책임이 사용자에게 남는다.
클라우드 컴퓨팅에서는 계산, 저장소, 데이터베이스와 네트워크 자원을 API와 관리 화면을 통해 필요에 따라 생성하고 제거할 수 있다. 물리 장비를 직접 구매하지 않고 사용량 또는 예약된 용량을 기준으로 비용을 지불한다.
클라우드 환경의 주요 호스팅 형태는 다음과 같이 구분할 수 있다.
가상 머신
클라우드 가상 머신은 사용자가 운영체제와 웹 서버, 런타임과 응용 프로그램을 직접 관리하는 형태다. 전통적인 서버와 비슷한 자유도를 제공하면서 인스턴스를 빠르게 생성하고 이미지로 복제할 수 있다.
운영체제 보안 업데이트, 방화벽, SSH 접근, 디스크 용량과 응용 프로그램 배포는 일반적으로 사용자의 책임이다. 여러 가상 머신을 부하 분산 장치 뒤에 배치하여 가용성과 처리량을 높일 수 있다.
컨테이너
컨테이너는 응용 프로그램과 필요한 라이브러리를 이미지로 패키징하고 호스트의 운영체제 커널을 공유하여 격리된 프로세스로 실행한다. 개발·시험·운영 환경의 차이를 줄이고 배포 단위를 표준화할 수 있다.
단일 서버에서 Docker나 Podman으로 실행할 수도 있고, Kubernetes와 관리형 컨테이너 플랫폼이 여러 서버의 배치, 재시작, 서비스 검색과 확장을 관리할 수 있다.
컨테이너 이미지는 일반적으로 실행 중 직접 수정하기보다 새 버전의 이미지를 배포하여 교체한다. 사용자 업로드와 데이터베이스처럼 유지해야 하는 데이터는 외부 볼륨, 데이터베이스와 객체 저장소에 둔다.
서비스형 플랫폼
Platform as a Service는 사용자가 소스 코드나 패키지를 배포하면 플랫폼이 런타임, 프로세스 실행, TLS, 로그와 일정 수준의 확장을 관리하는 방식이다. 운영체제와 서버 설정을 직접 관리할 필요가 줄어들지만 지원 언어, 배포 구조와 네트워크 설정에 제약이 있을 수 있다.
플랫폼은 Git 저장소나 컨테이너 이미지를 입력으로 받아 빌드와 배포를 자동화할 수 있다. 트래픽과 설정에 따라 인스턴스 수를 자동으로 조절하고 장애 난 인스턴스를 다시 시작할 수 있다.
서버리스 함수
함수형 서버리스 환경에서는 개발자가 요청이나 이벤트를 처리하는 함수를 배포하고, 플랫폼이 실행 인스턴스와 확장, 가용성을 관리한다. HTTP 요청, 파일 업로드, 메시지와 일정 이벤트를 함수 실행의 원인으로 사용할 수 있다.
함수는 요청이 있을 때만 실행되고 실행 시간과 호출 수에 따라 비용이 부과될 수 있다. 사용하지 않을 때 서버 프로세스를 계속 유지할 필요가 없지만, 첫 실행 지연, 실행 시간과 메모리 제한, 상태 유지 방식과 특정 서비스 의존성을 고려해야 한다.
AWS의 서버리스 개발 문서는 JavaScript·TypeScript·Python·Java·Go·C# 등의 관리형 런타임 또는 컨테이너 기반 사용자 정의 런타임을 사용하여 웹 요청과 API 처리, 동적 파일 생성 등을 수행할 수 있다고 설명한다.[101]
서버리스라는 명칭은 서버가 존재하지 않는다는 뜻이 아니다. 클라우드 사업자가 실제 서버와 실행 환경을 관리하고 사용자는 개별 서버의 설치와 용량 계획에서 추상화된다.
정적 호스팅과 엣지 실행
정적 웹사이트는 객체 저장소나 전문 정적 호스팅 서비스에 파일을 업로드하고 CDN을 통해 배포할 수 있다. 서버 측 렌더링이 필요 없는 사이트에서는 전통적인 응용 서버를 유지하지 않아도 된다.
Amazon S3의 정적 웹사이트 호스팅은 버킷에 색인 문서와 권한을 설정하고 HTML·CSS·JavaScript와 이미지 파일을 업로드하는 방식으로 구성된다.[102]
정적 프런트엔드는 브라우저에서 별도의 API 게이트웨이와 서버리스 함수, 관리형 데이터베이스에 요청을 보낼 수 있다. 정적 파일 제공과 동적 백엔드를 분리한 구조다.
엣지 컴퓨팅은 사용자와 가까운 CDN 또는 지역 노드에서 JavaScript나 WebAssembly 기반 코드를 실행한다. 리디렉션, 인증 확인, 헤더 변경, 개인화와 짧은 API 처리를 원본 데이터 센터까지 가지 않고 수행할 수 있다.
엣지 실행은 낮은 지연 시간을 제공할 수 있지만 런타임 API, 실행 시간, 데이터 접근과 일관성에 제약이 있을 수 있다. 전 세계의 여러 위치에서 동시에 실행되는 코드는 중앙 데이터베이스와의 거리와 복제 지연도 고려해야 한다.
관리형 데이터와 공통 서비스
클라우드 환경에서는 데이터베이스, 객체 저장소, 메시지 대기열, 캐시, 검색과 인증을 관리형 서비스로 사용할 수 있다. 사업자가 백업, 복제, 소프트웨어 업데이트와 장애 조치의 일부를 관리한다.
관리형 서비스는 운영 부담을 줄이지만 비용 구조, 데이터 이전, 지원 기능과 특정 사업자 API에 대한 의존성을 만든다. 장애와 잘못된 설정의 책임이 완전히 사라지는 것은 아니다.
확장성과 가용성
수직 확장은 서버의 CPU와 메모리, 저장 장치 성능을 높이는 방식이고, 수평 확장은 같은 역할의 서버 인스턴스를 여러 개 추가하는 방식이다. 웹 계층을 무상태에 가깝게 구성하면 요청을 여러 인스턴스로 분산하기 쉽다.
자동 확장은 트래픽, CPU 사용량, 대기열 길이와 사용자 정의 지표에 따라 인스턴스 수를 늘리거나 줄인다. 새 인스턴스가 실제 요청을 받을 준비가 될 때까지의 시작 시간과 갑작스러운 트래픽 증가를 고려해야 한다.
고가용성 서비스는 여러 장애 영역이나 데이터 센터에 인스턴스를 배치할 수 있다. 한 서버나 지역이 중단되면 부하 분산 장치와 DNS가 정상 위치로 트래픽을 이동한다.
여러 지역에 서비스를 복제하면 지리적 장애에 대응하고 지연 시간을 낮출 수 있지만 데이터 복제, 쓰기 충돌, 비용과 운영 복잡성이 증가한다.
배포와 운영
웹 응용 프로그램은 수동 파일 복사뿐 아니라 지속적 통합·배포 파이프라인으로 배포할 수 있다. 소스 코드 변경 뒤 자동으로 시험, 빌드, 보안 검사와 배포를 수행한다.
롤링 배포는 실행 중인 인스턴스를 일부씩 새 버전으로 교체한다. 블루·그린 배포는 기존 환경과 새 환경을 함께 유지한 뒤 트래픽을 전환한다. 카나리 배포는 일부 사용자나 트래픽에 먼저 새 버전을 적용하여 오류를 관찰한다.
응용 프로그램 설정과 자격 증명을 이미지나 소스 코드에 직접 넣기보다 환경 설정과 비밀 관리 시스템으로 분리한다. 배포 환경마다 데이터베이스 주소와 기능 플래그를 다르게 제공할 수 있다.
클라우드 호스팅은 서버 관리의 모든 책임을 사업자에게 이전하지 않는다. 사업자는 물리 시설과 서비스 계층을 관리하고 사용자는 계정 권한, 네트워크 공개 범위, 데이터 암호화, 응용 프로그램 취약점과 백업 정책을 관리하는 공유 책임 모델을 따른다.
비용은 계산 시간뿐 아니라 저장 공간, 데이터베이스 처리량, 네트워크 전송, 로그와 관리형 서비스 사용량에서 발생할 수 있다. 자동 확장이 기술적으로 성공하더라도 비정상 요청이나 공격으로 비용이 급증할 수 있으므로 요청 제한과 예산 경고가 필요하다.
웹 호스팅 환경의 범위
- 자체 관리 환경
- 자체 데이터 센터
- 코로케이션
- 전용 서버
- 가상 사설 서버
- 클라우드 기반 실행
- 가상 머신
- 관리형 컨테이너
- 응용 프로그램 플랫폼
- 서버리스 함수
- 엣지 실행 환경
- 정적 콘텐츠
- 웹 서버의 파일 시스템
- 객체 저장소
- 콘텐츠 전송 네트워크
- 관리형 백엔드
- 관계형·비관계형 데이터베이스
- 분산 캐시
- 객체 저장소
- 메시지 대기열
- 인증·검색·관찰 서비스
웹 호스팅 환경의 선택은 사이트 규모만으로 결정되지 않는다. 필요한 제어 수준, 개발 인력, 트래픽 변화, 데이터 위치, 규제, 장애 허용 범위, 특정 기술 요구와 장기 비용을 함께 고려해야 한다. 작은 정적 사이트는 객체 저장소와 CDN만으로 충분할 수 있고, 복잡한 서비스는 여러 지역의 응용 서버와 데이터 시스템을 결합할 수 있다.
하이퍼텍스트와 탐색
World Wide Web의 핵심은 서로 독립적으로 작성되고 운영되는 문서와 자원을 하이퍼링크로 연결하는 데 있다. 사용자는 문서를 처음부터 끝까지 정해진 순서로만 읽지 않고, 현재 문서에 포함된 링크를 선택하여 같은 사이트의 다른 페이지나 전혀 다른 서버의 자원으로 이동할 수 있다.
이러한 구조는 책의 목차나 색인처럼 정보를 연결하는 전통적인 장치를 확장하면서도, 연결 대상을 하나의 출판물이나 데이터베이스 안으로 제한하지 않는다. 링크를 만들기 위해 대상 서버의 승인을 받거나 대상 문서를 수정할 필요가 없으며, URI를 알고 있다면 누구나 자신의 문서에서 그 자원을 가리킬 수 있다.
브라우저는 링크를 따라 이루어진 이동을 탐색 기록으로 관리하고 뒤로 가기와 앞으로 가기를 제공한다. 한편 링크의 대상은 이동하거나 삭제될 수 있으므로 연결이 영구적으로 유지된다는 보장은 없다. 수많은 페이지와 링크를 방향성 그래프로 바라보면 웹의 탐색, 검색, 권위 분석과 정보 확산 구조를 연구할 수 있다.
하이퍼링크
하이퍼링크는 현재 자원과 다른 자원 또는 같은 자원 안의 특정 부분 사이의 연결을 나타낸다. 사용자가 링크를 활성화하면 브라우저는 링크의 대상 URI를 해석하고 새로운 문서를 탐색하거나 파일을 내려받고, 전자우편 프로그램과 다른 응용 프로그램을 실행할 수 있다.
HTML에서는 일반적으로 a 요소의 href 속성으로 하이퍼링크를 만든다.
<a href="https://example.com/document">문서 보기</a>
a 요소의 콘텐츠는 사용자에게 표시되는 링크 텍스트 또는 이미지이고, href는 링크의 목적지를 나타낸다. 링크는 절대 URL을 사용할 수도 있고 현재 문서의 기준 URL에 따라 해석되는 상대 참조를 사용할 수도 있다.
링크 대상은 반드시 다른 웹 페이지일 필요가 없다. HTML 문서, 이미지, PDF, 영상, 다운로드 파일, API 자원과 같은 HTTP·HTTPS URL뿐 아니라 mailto:, tel:과 다른 URI 스킴을 사용할 수 있다. 실제 동작은 URI 스킴과 브라우저, 운영체제에 등록된 처리기에 따라 달라진다.
같은 문서 안의 특정 요소로 이동하려면 프래그먼트를 사용할 수 있다.
<a href="#history">역사로 이동</a>
브라우저는 일반적으로 # 앞의 URL에 해당하는 문서를 가져온 뒤, 프래그먼트와 일치하는 id를 가진 요소로 화면을 이동한다. 대상이 현재 문서라면 별도의 네트워크 요청 없이 위치만 변경될 수 있다.
하이퍼링크에는 연결의 성격을 나타내는 링크 관계를 지정할 수 있다. HTML의 rel 속성이나 HTTP의 Link 헤더는 현재 자원과 대상 자원 사이의 의미를 표현한다. alternate, author, canonical, help, license, next, prev 등이 대표적인 링크 관계다.
웹 링크는 단순히 대상 URI만으로 구성되지 않는다. RFC 8288은 링크를 문맥 자원, 링크 관계 유형, 대상 자원과 선택적인 대상 속성의 관계로 설명한다.[103]
예를 들어 canonical 관계는 현재 콘텐츠를 참조할 때 선호하는 대표 URI를 알리고, alternate는 다른 언어나 형식의 표현을 가리킬 수 있다. 링크 관계를 사용하면 브라우저, 검색 엔진과 자동화된 클라이언트가 링크의 목적을 링크 텍스트에 의존하지 않고 해석할 수 있다.
링크 텍스트는 대상의 목적이나 내용을 문맥 안에서 이해할 수 있도록 작성하는 것이 좋다. “여기를 클릭”처럼 목적을 알 수 없는 표현이 반복되면 화면 낭독기 사용자와 문서를 빠르게 훑는 사용자가 각 링크의 차이를 파악하기 어렵다.
링크는 키보드와 보조 기술로도 활성화할 수 있어야 한다. 링크와 비슷하게 보이도록 만든 일반 요소에 JavaScript 클릭 처리만 추가하면 키보드 초점, 새 탭에서 열기, 주소 복사와 문맥 메뉴 같은 브라우저의 기본 링크 기능이 제공되지 않을 수 있다.
하이퍼링크와 단추는 역할이 다르다. 링크는 일반적으로 다른 자원이나 탐색 상태로 이동하고, 단추는 현재 문서나 응용 프로그램에서 명령을 실행한다. JavaScript를 사용하더라도 탐색에는 링크를, 작업에는 button 요소를 사용하는 편이 의미와 접근성에 맞는다.
링크의 target 속성은 현재 탐색 문맥, 새 탭이나 특정 이름의 탐색 문맥에서 대상을 열도록 지정할 수 있다. 새 창이나 탭을 강제로 여는 동작은 사용자의 탐색 흐름과 접근성에 영향을 줄 수 있으며, 외부 페이지가 원래 창을 조작하지 못하도록 관련 보안 설정이 적용될 수 있다.
사용자가 링크를 선택했을 때 반드시 전체 페이지가 새로 로드되는 것은 아니다. 웹 애플리케이션은 링크 이벤트를 처리하고 History API를 사용하여 브라우저의 탐색 기록과 URL을 변경하면서 화면 일부만 갱신할 수 있다. 그러나 사용자가 주소를 직접 열거나 새로고침했을 때도 해당 URL의 자원을 제공하도록 서버와 응용 프로그램을 구성해야 링크의 공유 가능성이 유지된다.
문서 간 연결 구조
하이퍼텍스트 문서는 고정된 한 방향의 읽기 순서 대신 여러 가능한 이동 경로를 제공한다. 한 문서는 관련 개념, 출처, 다음 단계, 상위 분류와 외부 자료를 가리킬 수 있으며, 사용자는 자신의 목적에 따라 링크를 선택한다.
사이트 내부 링크는 웹사이트 안의 문서 구조를 형성한다. 대표 페이지에서 분류와 하위 문서로 이어지는 계층 구조, 이전·다음 문서로 이어지는 순차 구조, 태그와 관련 문서를 중심으로 연결되는 망상 구조를 함께 사용할 수 있다.
탐색 메뉴, 목차, 이동 경로와 사이트맵은 링크를 체계적으로 조직한다. 이동 경로 또는 breadcrumb는 현재 문서가 사이트 분류에서 어느 위치에 있는지 보여주고 상위 단계로 이동하게 한다. 이전·다음 링크는 연속된 장이나 검색 결과를 정해진 순서로 탐색하게 한다.
HTML의 nav 요소는 주요 탐색 링크가 모인 영역을 의미적으로 나타낸다. 모든 링크 묶음을 nav로 표시할 필요는 없으며, 사이트의 주 메뉴, 문서 목차와 페이지 이동처럼 주요 탐색 구역에 사용한다.
문서 간 연결은 한 방향일 수 있다. 문서 A가 문서 B를 링크해도 B가 A로 돌아가는 링크를 제공할 의무는 없다. 대상 서버에 링크 생성 사실을 등록할 필요도 없으므로 웹의 연결은 중앙 조정 없이 빠르게 확장될 수 있다.
단방향 링크는 확장성이 높지만 연결의 존재와 유효성을 대상이 직접 관리하지 않는다는 특성도 가진다. 대상 자원이 이동하거나 삭제되어도 링크를 만든 모든 문서에 자동으로 변경 사실이 전달되지 않는다.
사이트 안의 링크 구조는 사용자뿐 아니라 검색 엔진 크롤러의 자원 발견에도 영향을 준다. 공개된 문서라도 다른 페이지에서 연결되지 않고 사이트맵이나 외부 목록에도 나타나지 않으면 일반적인 링크 탐색으로 발견하기 어려울 수 있다.
내부 링크의 앵커 텍스트와 주변 문맥은 대상 문서의 의미를 설명하는 신호가 될 수 있다. 여러 독립된 문서가 특정 페이지를 비슷한 표현으로 연결하면 검색 시스템은 링크 대상의 주제와 중요도를 분석하는 데 이를 활용할 수 있다.
외부 링크는 서로 다른 사이트와 조직의 문서를 하나의 정보 흐름으로 연결한다. 작성자는 자신의 문서에 모든 배경 설명과 근거를 복제하는 대신 원자료, 관련 연구와 보충 설명으로 연결할 수 있다.
링크가 많다고 항상 탐색성이 높아지는 것은 아니다. 문맥 없이 과도한 링크를 배치하면 읽기 흐름이 분산되고 중요한 경로를 구분하기 어려워질 수 있다. 링크의 위치, 설명과 계층을 콘텐츠 목적에 맞게 설계해야 한다.
문서 구조는 다음과 같은 여러 연결 방식을 함께 가질 수 있다.
웹 문서의 주요 연결 구조
- 계층적 연결
- 대문
- 분류
- 하위 분류
- 개별 문서
- 순차적 연결
- 이전 문서
- 현재 문서
- 다음 문서
- 연관 연결
- 관련 개념
- 같은 주제
- 출처와 참고 자료
- 외부 사이트
- 문서 내부 연결
- 목차
- 제목 앵커
- 각주
- 본문 참조
실제 웹사이트는 계층형 디렉터리처럼 보일 수 있지만, 전체 웹은 하나의 완성된 트리로 구성되지 않는다. 문서는 여러 상위 문맥과 주제에 동시에 속할 수 있고, 서로 다른 사이트의 링크가 교차하면서 복잡한 네트워크를 형성한다.
뒤로 가기와 탐색 기록
브라우저는 사용자가 문서를 탐색할 때 현재 탭 또는 탐색 문맥의 세션 기록을 관리한다. 사용자가 링크를 선택하고 다른 URL로 이동하면 일반적으로 새로운 기록 항목이 추가되며, 뒤로 가기와 앞으로 가기를 통해 이전 항목을 다시 활성화할 수 있다.
세션 기록 항목은 URL만 저장하는 단순한 목록이 아니다. 문서 객체, 상태 객체, 제목, 폼 데이터, 스크롤 위치와 정책 정보 등이 연결될 수 있다. HTML 표준은 탐색과 세션 기록의 생성·이동·교체 절차를 정의한다.[104]
뒤로 가기는 현재 기록 항목보다 앞서 생성된 항목으로 이동하고, 앞으로 가기는 뒤로 이동하기 전에 활성화했던 이후 항목으로 돌아간다. 기록 범위를 벗어나면 더 이상 이동하지 않는다.
세션 기록은 개념적으로 순서가 있는 항목을 가지지만 사용자가 실제로 거친 탐색은 항상 단순한 직선 구조는 아니다. 사용자가 뒤로 이동한 뒤 새로운 링크를 열면 기존의 앞으로 가기 경로가 제거되거나 새로운 기록 분기가 현재 순서에 반영될 수 있다.
브라우저가 이전 페이지로 돌아갈 때 반드시 네트워크에서 모든 자원을 다시 요청하는 것은 아니다. 문서가 뒤로-앞으로 캐시에 보존되어 있다면 JavaScript 실행 상태, DOM과 스크롤 위치를 포함한 문서를 빠르게 다시 활성화할 수 있다.
WHATWG HTML 표준은 탐색 기록 이동 때 재활성화할 수 있도록 문서를 보관하는 캐시를 back-forward cache 또는 bfcache라고 설명한다.[105]
문서가 캐시에 유지되지 않았거나 사용 조건을 충족하지 않으면 브라우저는 자원을 다시 불러오고 저장된 스크롤 및 폼 상태를 복원할 수 있다. 서버 응답과 페이지 스크립트에 따라 이전에 보던 화면과 완전히 같은 상태가 복원되지 않을 수도 있다.
웹 애플리케이션은 history.pushState()를 사용하여 새 문서를 서버에서 불러오지 않고 현재 세션 기록에 상태와 URL을 추가할 수 있다. history.replaceState()는 현재 기록 항목의 상태와 URL을 교체한다.
사용자가 이러한 기록 항목 사이를 이동하면 popstate 이벤트를 통해 응용 프로그램이 화면을 복원할 수 있다. 이를 이용하면 지도 위치, 선택한 탭, 검색 조건과 단일 페이지 애플리케이션의 내부 화면도 브라우저 뒤로 가기와 연동할 수 있다.
History API는 임의의 다른 출처 URL을 기록에 넣을 수 없으며 현재 문서의 보안 경계 안에서 사용된다. 브라우저 주소창의 출처를 속이거나 실제로 접근 권한이 없는 사이트처럼 표시하는 데 사용할 수 없다.
응용 프로그램이 모든 화면 변화를 하나의 URL에만 유지하면 사용자는 특정 상태를 북마크하거나 공유하기 어렵고 뒤로 가기도 예상대로 작동하지 않는다. 의미 있는 탐색 상태에는 안정된 URL과 기록 항목을 제공하는 것이 웹의 기본 탐색 방식과 잘 맞는다.
폼을 POST로 제출하여 생성된 문서를 새로고침하거나 기록에서 다시 불러오면 같은 작업이 반복될 가능성이 있다. 브라우저는 이러한 경우 재전송 확인을 요청할 수 있다. 서버는 성공적인 제출 뒤 다른 URL로 리디렉션하는 방식을 사용하여 재전송 위험을 줄일 수 있다.
탐색 기록은 현재 탭의 세션 기록과 브라우저가 장기간 저장하는 전체 방문 기록으로 구분할 수 있다. 세션 기록은 뒤로·앞으로 이동에 사용되고, 전체 방문 기록은 과거 방문 검색과 주소 자동 완성 등에 사용된다.
비공개 탐색 창도 열린 동안에는 뒤로 가기를 위한 세션 기록을 유지한다. 비공개 탐색은 기록 기능 자체를 제거하는 것이 아니라 창을 닫은 뒤 해당 세션의 기록과 사이트 데이터를 일반 프로필에 남기지 않도록 하는 방식이다.
링크 부패
링크 부패 또는 link rot는 하이퍼링크의 대상 자원이 이동·삭제되거나 서버와 도메인이 사라져 링크가 더 이상 원래 자료에 도달하지 못하는 현상이다. 사용자는 흔히 404 Not Found, 이름 해석 실패, 연결 오류와 만료된 도메인을 통해 이를 경험한다.
웹 링크는 대상 자원의 현재 상태를 확인하거나 보존을 약속받지 않아도 만들 수 있다. 이러한 느슨한 연결은 웹이 중앙 승인 없이 확장될 수 있게 하지만, 대상이 변할 때 기존 링크를 자동으로 갱신하지 못하는 원인이기도 하다.
링크가 끊어지는 주요 원인은 다음과 같다.
- 사이트 개편으로 URL 경로가 변경됨
- 문서나 파일이 삭제됨
- 도메인 등록이 만료되거나 소유자가 바뀜
- 호스팅 서비스와 조직이 운영을 종료함
- 로그인이나 권한 정책으로 공개 접근이 차단됨
- HTTP에서 HTTPS로 이동하면서 이전 주소가 유지되지 않음
- 질의 매개변수와 세션 기반 임시 주소가 만료됨
- 외부 저장소나 CDN의 파일 위치가 변경됨
링크가 HTTP 응답을 반환한다고 해서 원래 자료가 유지된 것은 아니다. 같은 URL에서 내용이 크게 바뀌거나 전혀 다른 자원이 제공되는 콘텐츠 변질 또는 content drift가 발생할 수 있다. 링크 부패와 콘텐츠 변질을 함께 참조 부패라고 부르기도 한다.
미국 의회도서관은 링크 부패와 참조 부패를 웹 자원이 점차 사라지는 현상을 설명하는 용어로 사용하며, 웹 아카이브가 빠르게 변화하는 온라인 자료의 스냅샷을 보존하는 역할을 한다고 설명한다.[106]
링크 부패는 일반적인 탐색 불편을 넘어 학술 논문, 법률 문서, 뉴스와 공공 기록의 검증 가능성을 손상한다. 인용한 근거가 사라지거나 다른 내용으로 바뀌면 독자는 작성 당시의 주장을 확인하기 어렵다.
사이트 운영자는 자원 주소를 변경할 때 이전 URL에서 새 URL로 영구 리디렉션을 제공하여 기존 링크를 유지할 수 있다. 내부 파일 구조와 서버 기술을 URL에 과도하게 반영하지 않고 자원의 논리적 의미를 기준으로 주소를 설계하는 것도 변경 가능성을 줄인다.
삭제한 자원과 무관한 홈페이지로 모든 요청을 리디렉션하면 링크가 기술적으로 응답하더라도 사용자는 원래 자료가 사라졌다는 사실을 알기 어렵다. 대체 자원이 없다면 404 Not Found나 410 Gone을 반환하고, 가능한 경우 삭제 사유와 관련 자료를 안내하는 편이 명확하다.
웹사이트는 자동 링크 검사 도구를 사용하여 내부와 외부 링크의 상태를 주기적으로 확인할 수 있다. 그러나 정상 상태 코드가 콘텐츠의 동일성을 보장하지 않고, 인증·속도 제한·일시적 장애가 결과에 영향을 주므로 자동 검사만으로 모든 참조 부패를 발견할 수는 없다.
학술·법률 자료에서는 DOI, Handle과 ARK 같은 영구 식별자를 사용할 수 있다. 이러한 식별자는 현재 자원의 실제 위치를 등록 정보로 관리하여 저장 위치가 바뀌어도 같은 식별자를 유지하는 것을 목표로 한다.
웹 보존 서비스는 특정 시점의 문서와 관련 자원을 수집하여 과거 표현을 다시 열 수 있게 한다. Perma.cc는 인용한 온라인 자원이 사라지거나 변경되는 링크·참조 부패에 대응하기 위해 인용 당시 자료의 기록을 보존한다.[107]
웹 아카이브도 모든 자원을 완전하게 보존하지는 못한다. 로그인 뒤의 콘텐츠, 로봇 접근이 차단된 자료, 복잡한 JavaScript 응용 프로그램, 실시간 데이터와 외부 서비스 의존 기능은 일부만 저장되거나 다시 실행되지 않을 수 있다.
링크 부패를 줄이기 위한 구조는 다음과 같이 정리할 수 있다.
링크 부패에 대한 대응
- 주소 설계
- 장기간 유지할 논리적 URL 사용
- 임시 세션과 내부 파일 경로 노출 최소화
- 동일 자원에 안정된 대표 주소 제공
- 사이트 변경
- 이전 URL에서 영구 리디렉션
- 리디렉션 체인 최소화
- 삭제 자원에 명확한 상태 코드 제공
- 인용
- 영구 식별자 사용
- 접근 날짜와 버전 기록
- 원자료와 보관본 함께 제시
- 보존
- 기관 웹 아카이브
- 자동 수집과 스냅샷
- 정기적인 링크 상태 검사
링크 부패를 완전히 제거하기는 어렵다. 웹의 자율적이고 분산된 구조에서는 누구나 자원을 게시하거나 제거할 수 있기 때문이다. 다만 안정적인 URI 정책, 리디렉션, 버전 관리와 웹 보존을 결합하면 연결의 수명을 연장할 수 있다.
웹 그래프
웹 페이지와 하이퍼링크의 연결 관계는 수학적인 방향 그래프로 모델링할 수 있다. 각 웹 페이지나 자원을 노드로, 한 페이지에서 다른 페이지로 향하는 하이퍼링크를 방향이 있는 간선으로 본 구조를 웹 그래프라고 한다.
문서 A가 문서 B를 링크하면 A에서 B로 향하는 간선이 생긴다. B가 A를 링크하지 않는다면 반대 방향의 간선은 존재하지 않는다. 따라서 웹 그래프는 일반적으로 방향성과 비대칭성을 가진다.
한 노드에서 외부로 향하는 링크의 수를 진출 차수, 다른 노드에서 들어오는 링크의 수를 진입 차수라고 한다. 많은 문서를 인용하는 색인·포털 페이지는 진출 링크가 많을 수 있고, 여러 독립 사이트에서 참조되는 자료는 진입 링크가 많을 수 있다.
링크 수만으로 문서의 품질이나 신뢰성을 확정할 수는 없다. 자동 생성된 링크, 광고, 사이트 공통 메뉴, 복제 문서와 의도적으로 만든 링크 집합도 그래프에 포함될 수 있다. 검색 시스템은 링크의 위치, 출처, 관계와 주변 텍스트를 함께 분석하고 조작을 줄이기 위한 별도 정책을 적용한다.
웹 그래프는 검색 엔진의 크롤링 범위를 결정하는 기반이다. 크롤러는 알려진 URL에서 문서를 가져오고, 그 안에서 새로운 링크를 발견하여 탐색 대기열에 추가한다. 연결되지 않은 페이지와 접근이 제한된 자원은 이 방식만으로 발견되지 않을 수 있다.
링크 구조는 검색 결과 순위에도 활용되어 왔다. 한 페이지로 들어오는 링크를 다른 작성자나 사이트의 참조로 해석하고, 링크를 보내는 페이지의 중요도와 관계를 반복적으로 계산할 수 있다. PageRank와 HITS는 이러한 링크 분석을 대표하는 알고리즘이다.
링크 분석은 검색뿐 아니라 관련 문서 발견, 웹 공동체 분석, 스팸 탐지와 정보 확산 연구에도 사용된다. 특정 주제의 사이트가 서로 조밀하게 연결되거나, 허브 역할의 페이지가 여러 권위 있는 문서로 사용자를 안내하는 구조를 찾을 수 있다.
웹 그래프는 정적이지 않다. 새로운 페이지가 생성되고 기존 문서가 삭제되며, 링크가 추가·수정되면서 그래프가 계속 변한다. 검색 엔진이 보유한 웹 그래프는 웹 전체의 현재 상태가 아니라 특정 시점과 크롤링 범위에서 관찰한 부분 그래프다.
2000년 Broder 등의 연구는 2억 개가 넘는 페이지와 약 15억 개의 링크를 포함한 AltaVista 크롤을 분석하여 당시 관찰한 웹이 거대한 강연결 구성 요소와 그 안팎의 여러 영역을 가진 이른바 나비넥타이 구조로 설명될 수 있다고 제시하였다.[108]
강연결 구성 요소에서는 방향 링크를 따라 대부분의 노드가 서로 도달할 수 있다. 그 구성 요소로 들어갈 수 있지만 다시 도달할 수 없는 영역, 구성 요소에서 나갈 수 있지만 반대로 들어올 수 없는 영역, 어느 쪽과도 제한적으로 연결된 덩굴과 분리 구성 요소가 존재할 수 있다.
웹 그래프의 단순화된 나비넥타이 구조
- IN 영역
- 링크를 따라 중심부로 진입 가능
- 거대한 강연결 구성 요소
- 내부 노드 사이에서 상호 도달 가능
- 링크를 따라 OUT 영역으로 이동 가능
- 중심부로 돌아가는 경로는 없음
- 주변 구조
- IN에서 OUT으로 우회하는 통로
- 중심 구조에 매달린 덩굴
- 연결되지 않거나 별도로 형성된 구성 요소
이 구조의 구체적인 비율은 웹 자체의 변화뿐 아니라 크롤러가 어떤 시작점과 정책으로 페이지를 수집했는지에 따라 달라진다. 이후 대규모 Common Crawl 데이터를 분석한 연구도 거대한 강연결 구성 요소의 존재를 확인했지만, 나비넥타이 각 영역의 비율은 크롤링 과정에 크게 영향을 받을 수 있다고 지적하였다.[109]
웹 그래프의 노드를 항상 개별 HTML 페이지로만 정의할 필요는 없다. 연구 목적에 따라 URL, 호스트, 등록 도메인, 웹사이트나 출처 단위로 여러 페이지를 묶을 수 있다. 같은 사이트의 공통 메뉴 링크를 모두 포함할지, 리디렉션과 중복 페이지를 어떻게 처리할지에 따라서도 그래프가 달라진다.
웹 그래프와 인터넷의 네트워크 토폴로지는 서로 다른 대상이다. 웹 그래프의 노드는 논리적인 페이지나 사이트이고 간선은 하이퍼링크다. 인터넷 토폴로지의 노드는 라우터, 자율 시스템과 물리·논리 네트워크이며 간선은 통신 연결과 경로 관계다.
두 웹 페이지가 서로 링크되어 있어도 서버가 물리적으로 가까이 있다는 의미는 아니다. 반대로 같은 데이터 센터와 서버에 저장된 두 페이지가 문서상으로 아무 링크도 가지지 않을 수 있다.
하이퍼링크는 웹 콘텐츠 위에 추가적인 구조와 문맥을 형성한다. 개별 문서의 텍스트만 분석할 때 보이지 않는 권위, 주제 공동체와 탐색 경로가 링크 관계에서 나타날 수 있다. 웹 그래프는 이러한 집단적인 연결 구조를 수집하고 분석하는 모델이다.
웹사이트와 웹 애플리케이션
정적 웹사이트
동적 웹사이트
단일 페이지 애플리케이션
다중 페이지 애플리케이션
프로그레시브 웹 애플리케이션
서버 측 렌더링과 클라이언트 측 렌더링
웹 표준과 상호 운용성
W3C
WHATWG
IETF
표준 명세와 브라우저 구현
개방형 표준
호환성과 점진적 향상
검색과 정보 발견
웹 디렉터리
검색 엔진
웹 크롤러
색인과 순위 결정
메타데이터와 검색 최적화
소셜 검색과 추천 시스템
동적 웹과 사용자 참여
폼과 사용자 입력
쿠키와 세션
비동기 통신
사용자 생성 콘텐츠
소셜 웹
웹 API와 서비스 연동
멀티미디어와 실시간 통신
이미지와 그래픽
오디오와 영상 스트리밍
실시간 메시징
WebSocket
WebRTC
게임과 대화형 콘텐츠
보안과 신뢰 모델
동일 출처 정책
콘텐츠 보안 정책
인증과 권한 부여
인증서와 공개 키 기반 구조
주요 웹 공격
브라우저 샌드박스
소프트웨어 공급망 보안
개인정보 보호와 추적
쿠키와 식별자
웹 분석과 광고 추적
브라우저 지문
권한과 사용자 동의
개인정보 보호 기술
관련 법률과 정책
접근성과 국제화
웹 접근성
보조 기술
의미론적 문서 구조
문자 인코딩
국제화 도메인 이름
다국어와 양방향 문자
성능과 콘텐츠 전송
브라우저 캐시
압축
콘텐츠 전송 네트워크
지연 시간과 대역폭
이미지와 스크립트 최적화
대규모 서비스의 분산 배포
분산화와 중앙 집중화
웹의 분산 설계
플랫폼과 서비스 집중
연합형 웹
개인 데이터와 데이터 이동성
분산 웹 기술
사회와 경제에 미친 영향
정보 출판과 언론
통신과 공동체
전자 상거래와 금융
교육과 연구
행정과 공공 서비스
문화와 오락
노동과 소프트웨어 산업
정보 격차와 사회적 문제
다른 인터넷 서비스와의 관계
전자우편
파일 전송
원격 접속
인터넷 전화와 메시징
P2P 네트워크
모바일 애플리케이션과 플랫폼
장점과 한계
관련 문서
- W3C: A Little History of the World Wide Web ↩
- W3C: Ted Nelson and Xanadu ↩
- Computer History Museum: Douglas C. Engelbart ↩
- W3C: Short History of Hypertext ↩
- CERN: Where the web was born ↩
- CERN: Tim Berners-Lee's proposal ↩
- CERN: WorldWideWeb—Proposal for a HyperText Project ↩
- W3C: 25 years ago the world changed forever ↩
- CERN: A short history of the Web ↩
- CERN: The birth of the Web ↩
- CERN: A short history of the Web ↩
- CERN: Restoring the first website ↩
- NCSA: NCSA Mosaic ↩
- Computer History Museum: Browser Wars ↩
- Computer History Museum: Browser Wars ↩
- MDN Web Docs: JavaScript ↩
- W3C: A brief history of CSS until 2016 ↩
- WHATWG: HTML Living Standard—Background ↩
- Computer History Museum: New iPhone Exhibit ↩
- Computer History Museum: Internet in Your Pocket ↩
- W3C: Open Web Platform Milestone Achieved with HTML5 Recommendation ↩
- W3C: The World-Wide Web ↩
- W3C: Architecture of the World Wide Web, Volume One ↩
- MDN Web Docs: What is a web server? ↩
- W3C: Architecture of the World Wide Web, Volume One ↩
- W3C: Web Services Architecture ↩
- Michael K. Bergman: The Deep Web—Surfacing Hidden Value ↩
- Internet Society: The Internet's Five Critical Properties ↩
- IETF: About RFCs ↩
- RFC 9110: HTTP Semantics ↩
- RFC 6455: The WebSocket Protocol ↩
- RFC 9205: Building Protocols with HTTP ↩
- W3C: The World-Wide Web ↩
- W3C: Architecture of the World Wide Web, Volume One ↩
- RFC 9110: HTTP Semantics — Client/Server Messaging ↩
- RFC 9110: HTTP Semantics — Status Codes ↩
- W3C: Architecture of the World Wide Web — Identification, Interaction and Representation ↩
- RFC 9110: HTTP Semantics — Intermediaries ↩
- RFC 9111: HTTP Caching ↩
- W3C Design Issues: Universal Resource Identifiers — Axioms of Web Architecture ↩
- RFC 3986: Uniform Resource Identifier — Generic Syntax ↩
- RFC 8820: URI Design and Ownership ↩
- WHATWG: URL Living Standard ↩
- RFC 1034: Domain Names — Concepts and Facilities ↩
- RFC 1035: Domain Names — Implementation and Specification ↩
- W3C: Introduction to Web Architecture — Cool URIs Don't Change ↩
- W3C: Cool URIs Don't Change ↩
- RFC 9110: HTTP Semantics ↩
- RFC 8446: The Transport Layer Security Protocol Version 1.3 ↩
- RFC 9110: HTTP Semantics — Methods ↩
- RFC 9110: HTTP Semantics — Status Codes ↩
- RFC 9112: HTTP/1.1 ↩
- RFC 9112: HTTP/1.1 ↩
- RFC 9113: HTTP/2 ↩
- RFC 9114: HTTP/3 ↩
- RFC 9111: HTTP Caching ↩
- WHATWG: HTML Living Standard — Introduction ↩
- WHATWG: HTML Living Standard — Forms ↩
- WHATWG: HTML Living Standard — Parsing HTML documents ↩
- WHATWG: HTML Living Standard ↩
- W3C: CSS Snapshot 2026 ↩
- W3C: CSS Cascading and Inheritance Level 6 ↩
- W3C: CSS Custom Properties for Cascading Variables Module Level 1 ↩
- ECMA-262: ECMAScript Language Specification — Overview ↩
- ECMA-262: ECMAScript Data Types and Values ↩
- TC39: Specifying JavaScript ↩
- WHATWG: DOM Standard ↩
- WHATWG: HTML Living Standard — Elements in the DOM ↩
- WHATWG: HTML Living Standard — The picture element ↩
- WHATWG: HTML Living Standard — Media elements ↩
- RFC 8259: The JavaScript Object Notation Data Interchange Format ↩
- W3C: RDF 1.1 Concepts and Abstract Syntax ↩
- W3C: JSON-LD 1.1 ↩
- Chromium: Multi-process Architecture ↩
- Mozilla Firefox Source Docs: GeckoView Architecture ↩
- WHATWG: Parsing HTML Documents ↩
- WHATWG: The CSS User Agent Style Sheet and Presentational Hints ↩
- Chromium: Site Isolation Design Document ↩
- Mozilla Firefox Source Docs: Gecko ↩
- WebKit: The WebKit Open Source Project ↩
- V8: Documentation ↩
- Mozilla Firefox Source Docs: SpiderMonkey ↩
- WebKit Documentation: JavaScriptCore ↩
- Chromium: Multi-process Resource Loading ↩
- Microsoft Learn: Overview of Microsoft Edge Extensions ↩
- Chromium: Blink ↩
- V8: Documentation ↩
- Microsoft Learn: Overview of Microsoft Edge Extensions ↩
- Mozilla Firefox Source Docs: Gecko ↩
- SpiderMonkey: Home ↩
- WebKit: WebKit ↩
- Chrome for Developers: What is Blink? ↩
- Apache HTTP Server: Getting Started ↩
- MDN Web Docs: Static Site Generator ↩
- MDN Web Docs: Introduction to the Server Side ↩
- MDN Web Docs: Server-side Rendering ↩
- Apache HTTP Server: Dynamic Content with CGI ↩
- MDN Web Docs: Proxy Servers and Tunneling ↩
- NGINX ↩
- NGINX: Using nginx as HTTP Load Balancer ↩
- AWS: Get Started with Lambda ↩
- AWS: Enabling Website Hosting ↩
- RFC 8288: Web Linking ↩
- WHATWG: HTML Living Standard — Navigation and Session History ↩
- WHATWG: HTML Living Standard — Session History Traversal ↩
- Library of Congress: Diving into Digital Ephemera — Identifying Defunct URLs in the Web Archives ↩
- Perma.cc: Documentation ↩
- Broder et al.: Graph Structure in the Web ↩
- Meusel et al.: The Graph Structure in the Web — Analyzed on Different Aggregation Levels ↩