'HTTP 완벽 가이드' 책을 읽고 정리한 내용입니다.
1장 HTTP 기초 링크 : https://codeboyed.tistory.com/17
2장에서는 인터넷의 리소스를 사용하기 위해 꼭 알아야 하는 URL 의 개념에 대해 다룹니다.
글을 읽기전 아래 URL에 대해서 자신이 아는 내용을 혼자 설명해보고 글을 읽는 것도 좋은 공부방법이 될 것 같습니다.
https://codeboyed.tistory.com/manage/newpost/?type=post&returnURL=%2Fmanage%2F#
URL(Uniform Resource Locator)은 인터넷의 리소스를 가리키는 표준이름이다. URL은 전자정보 일부를 가리키고 그것이 어디에 있고 어떻게 접근할 수 있는지 알려준다.
2.1 인터넷 리소스 탐색하기
URI 는 URL과 URN 을 포함하는 상위개념이다. URN은 리소스가 어디에 존재하든 상관없이 그 이름만으로 리소스를 식별하는데 비해 URL은 리소스가 어디 있는지 설명해서 리소스를 식별한다.
하지만 이 책에서는 URI 란 대부분 URL 을 가리키는 것으로 취급한다. (현재 사용하는 주소체계가 대부분 URL이다.)
예시 URL
http://www.woongs-blog.com/index.html
- URL의 첫 부분인 http는 URL의 스킴이다. 스킴은 웹 클라이언트가 리소스에 어떻게 접근하는지 알려준다. 이 경우에, URL이 HTTP 프로토콜을 사용한다.
- URL의 두 번째 부분인 www.woongs-blog.com 은 서버의 위치이다. 이는 웹 클라이언트가 리소스 어디에 호스팅 되어 있는지 알려준다.
- URL 세번째 부분인 /index.html은 리소스의 경로이다. 경로는 서버에 존재하는 로컬 리소스들 중에서 요청받은 리소스가 무엇인지 알려준다.
대부분의 URL은 동일하게 '스킴://서버위치/경로' 구조로 이루어져 있다.
2.2 URL 문법
URL 문법은 스킴에 따라 달라진다! 그러나 대부분의 URL은 일반 URL 문법을 따르며, 서로 다른 URL 스킴도 형태와 문법면에서 매우 유사하다. 대부분의 URL 스킴의 문법은 9개 부분으로 나뉜다.
<스킴>://<사용자이름>:<비밀번호>@<호스트>:<포트>/<경로>;<파라미터>?<질의>#<프래그먼트>
이 중에서도 중요한 것은 "스킴, 호스트, 경로" 세 컴포넌트이다.
컴포넌트 | 설명 | 기본값 |
스킴 | 어떤 프로토콜을 사용하여 서버에 접근해야 하는지 가리킨다. | 없음 |
사용자 이름 | 몇몇 스킴은 리소스에 접근하기 위해 필요하다. | anonymous |
비밀번호 | 사용자의 비밀번호를 가리키며, 사용자 이름에 콜론(:)으로 이어져서 기술 | <이메일 주소> |
호스트 | 리소스를 호스팅하는 서버의 호스트 명이나 IP 주소 | 없음 |
포트 | 리소스를 호스팅하는 서버가 열어놓은 포트번호. 많은 스킴이 기본 포트를 갖고 있다. | 스킴에 따라 다름 (http : 80) |
경로 | 이전 컴포넌트와 '/ ' 로 구분되어 있다. 서버 내 리소스가 어디에 있는지 가리킨다. 경로 컴포넌트의 문법은 서버와 스킴에 따라 다르다. | 없음 |
파라미터 | 특정 스킴에서 입력 파라미터를 기술하는 용도로 사용. 파라미터는 이름/값을 쌍으로 가진다. 다른 파라미터나 경로의 일부를 세미콜론(;)으로 구분하며 여러개를 가질 수 있다. | 없음 |
질의 | 스킴에서 애플리케이션에 파라미터를 전달하는데 쓰인다. URL 끝에 "?"로 구분한다. | 없음 |
프래그먼트 | 리소스의 조각이나 일부분을 가리키는 이름이다. 서버에 전달되지 않고 클라이언트에서만 사용한다. URL 끝에서 "#" 문자로 구분한다. | 없음 |
각 컴포넌트에 대해 더 자세히 알아보자.
2.2.1 스킴: 사용할 프로토콜
스킴은 주어진 리소스에 어떻게 접근하는지 알려주는 중요한 정보다. 지금까지 사용했던 예시의 스킴은 'http'이다. 스킴 컴포넌트는 알파벳으로 시작해야 하고 ':' 문자로 마지막을 구분한다. 대소문자를 가리지 않으므로 'http://www~ 과 'HTTP://www~' 는 같다.
2.2.2 호스트와 포트
인터넷에 있는 리소스를 찾으려면, 리소스를 호스팅하고 있는 장비와 그 장비 내에서 리소스에 접근할 수 있는 서버가 어디에 있는지 알아야 한다. URL의 호스트와 포트 컴포넌트는 그 두 가지 정보를 제공해준다.
2.2.3 사용자 이름과 비밀번호
많은 서버가 자신이 가지고 있는 데이터에 접근을 허용하기 전에 사용자 이름과 비밀번호를 요구한다. FTP 서버가 좋은 예다. 아래 예시를 보자
ftp://ftp.prop.ai.mit.edu/pub/gnu
ftp://anonymous@ftp.prop.ai.mit.edu/pub/gnu
ftp://anonymous:my_password@ftp.prop.ai.mit.edu/pub/gnu
1번 처럼 사용자 이름과 비밀번호를 기술하지 않고 FTP URL에 접근하면, 기본 사용자 이름 값으로 'anonymouse'가, 비밀번호는 브라우저마다 가지고 있는 기본값을 사용한다(인터넷 익스플로어는 'IEUser', 크롬은 'chrome@exmaple.com')
3번은 사용자 이름과 비밀번호를 ':' 문자로 분리하여 모두 기술한다.
2.2.4 경로
URL 경로 컴포넌트는 리소스가 서버의 어디에 있는지 알려준다.
http://www.woongs-blog.com/seasonal/index.html
이 URL 경로는 '/seasonal/index.html' 로 유닉스 파일 시스템의 파일 경로와 유사하다. 경로는 서버가 리소스의 위치를 찾는데 사용하는 정보다. HTTP URL에서 경로 컴포넌트는 '/ ' 문자를 기준으로 경로조각으로 나뉜다.
2.2.5 파라미터
많은 스킴이 호스트 및 경로 정보만으로는 리소스를 찾지 못한다. 사용자 이름, 비밀번호, 포트 등등 외에도 많은 프로토콜이 더 많은 정보를 요구한다.
URL을 사용하는 애플리케이션이 리소스에 접근하려면 프로토콜 파라미터가 필요하다. 프로토콜 파라미터가 없으면, 다른 한편에 있는 서버는 그 요청을 잘못 처리하거나 처리하지 않을 수 있다. 예를 들어 바이너리 이미지를 텍스트 형식으로 전송할 경우 바이너리 데이터가 엉망이 된다. 따라서 이 데이터는 바이너리로 전송하라는 정보가 필요하다. 이와 같이 서버에 정확한 요청을 하기 위해 필요한 것이 입력 파라미터이다.
이 컴포넌트는 이름/값 쌍의 리스트로 세미콜론(;) 문자로 구분하여 URL에 기술한다. 이를 통해 애플리케이션이 리소스에 접근하는데 필요한 어떤 추가 정보든 전달할 수 있다. 예를 들어 다음 경우를 보자
ftp://prep.ai.mit.edu/pub/gnu;type=d
이 경우 이름은 'type'이고 값은 'd'인 단 한 개의 파라미터를 전달한다. 또한 경로 컴포넌트는 '/' 문자로 나눠지는데 이때 나눠진 각 조각은 자체 파라미터를 가질 수 있다. 예를 들면 다음과 같다.
ftp://www.woongs.com/blogs;content=http/index.html;image=true
위 예시는 두개의 경로 조각에 두 개의 파라미터를 갖는 경우이다. 이러한 경우도 있다는 것만 알아두자
2.2.6 질의 문자열
데이터베이스 같은 서비스들은 요청받을 리소스 형식의 범위를 좁히기 위해서 질문이나 질의를 받을 수 있다.
( 제가 공부할 때는 쿼리 스트링이라고 배웠던 것 같다.. )
다음 URL 은 아이텀 번호 12731의 재고가 있는지 확인하기 위해 웹 데이터베이스 게이트웨이에 질의하는데 사용된다.
ftp://www.woongs.com/inventory-check?item=12731
즉, 이 질의 컴포넌트 (쿼리 스트링)은 게이트웨이 서버로 전달되고 해당 질의에 일치하는 정보가 있는 지 검사한다.
2.2.7 프래그먼트
HTML 같은 리소스 형식들은 본래의 수준보다 더 작게 나뉠 수 있다. 예를 들어 절(paragraph)이 포함된 문서의 경우, 그 리소스에 대한 URL은 텍스트 문서 전체를 가리키겠지만, 이상적으로는 리소스 안에 있는 특정을 가리킬 수 있어야 한다. 이를 가능하게 하는 것이 프래그먼트 컴포넌트이다. 프래그먼트는 URL 오른쪽에 # 문자에 이어서 온다. 예를 들면 다음과 같다.
ftp://www.woongs.com/tools.html#drills
위 예에서 drills 라는 프래그먼트는 /tools.html 웹페이지의 일부를 가리킨다.
일반적으로 HTTP 서버는 객체 일부가 아닌 전체만 다루기 때문에, 클라이언트는 서버에 프래그먼트를 전달하지 않는다. 브라우저가 서버로부터 전체 리소스를 내려받은 후, 프래그먼트를 사용하여 당신이 보고자 하는 리소스의 일부를 보여준다.
2.3 단축 URL
URL은 상대 URL과 절대 URL 두 가지로 나뉜다. 지금까지 우리가 본 것들은 절대 URL 뿐이었다.
2.3.1 상대 URL
상대 URL로 접근하는데 필요한 모든 정보를 얻기 위해서는, 기저(BASE) 라고 하는 다른 URL을 참고해야 한다. 다음 예시를 보자
<HTML>
<A HREF="./hammers.html">hammers
</HTML>
위 예시는 "http://www.woongs.com/tools.html"가 가 가리키는 리소스인 HTML 문서의 내용을 보여준다. 여기서 ./hammers.html URL을 가리키는 하이퍼링크가 있다. 이 URL은 미완성인 것처럼 보이지만, 올바른 문법의 "상대 URL" 이다. 상대 URL 문법에 따르면 다른 컴포넌트들을 모두 입력하지 않아도 된다. 그 정보는 컴포넌트가 포함된 리소스의 BASE URL에서 알아낼 수 있다. 위 예시의 경우 "http://www.woongs.com/tools.html"가 BASE URL이 된다.
상대 URL은 프래그먼트이거나 URL의 일부이다. URL을 처리하는 브라우저 같은 애플리케이션은 상대 URL과 절대 URL 간에 상호 변환을 할 수 있어야 한다. 상대 URL을 사용하면, 문서 집합의 위치를 변경하더라도, 새로운 BASE URL에 의해서 해석될 것이기 때문에 위치를 변경하더라도 잘 동작할 것이다.
- BASE URL (기저 URL)
변환 과정의 첫 단계는 BASE URL을 찾는 것인데, 가져오는 몇 가지 방법이 있다.
- <BASE> HTML 태그 등 HTML 문서 안에 명확하게 기술하는 방법(https://developer.mozilla.org/ko/docs/Web/HTML/Element/base)
- 만약 상대 URL에 BASE URL이 명시되지 않은 경우, 해당 리소스의 URL을 BASE URL로 사용할 수 있다. (앞에 예시의 경우)
- 기저 URL이 없는 경우에는 절대 URL 만으로 이루어졌다는 뜻이거나 불완전한 URL 이라는 뜻이다.
- HTML: Hypertext Markup Language | MDN
HTML 요소는 문서 안의 모든 상대 URL이 사용할 기준 URL을 지정합니다. 문서에는 하나의 요소만 존재할 수 있습니다.
developer.mozilla.org
상대 참조를 해석하는 알고리즘이 나오는데, 간략하게 소개하면
스킴이 비어 있지 않은 경우에는 절대 URL 이므로 상대 참조를 할 필요가 없다. 만약 스킴이 없는 경우에는 비어 있는 컴포넌트를 BASE URL로 부터 차례대로 상속 받아 (없지만 필요한 부분만!) 새로운 절대 URL을 만들게 된다.
2.3.2 URL 확장
- 호스트 명 확장예를들어 주소 입력란에 'yahoo'를 입력하면, 브라우저는 호스트 명에 자동으로 'www'와 '.com'을 붙여서 'www.yahoo.com'을 만든다. 어떤 브라우저는 'yahoo'란 단어를 포함한 사이트를 찾지 못하면 확장을 포기하기 전에 몇 가지의 URL을 추가로 제시한다. 하지만 호스트 명에 대한 확장 기능은 프락시와 같은 다른 HTTP 애플리케이션에 문제를 발생시킬 수도 있다.
- 히스토리 확장브라우저가 과거에 사용자가 방문했던 URL의 기록을 저장해 놓는 것이다. URL을 입력하면, 그 입력된 URL의 앞 글자들을 포함하는 완결된 형태의 URL들을 선택하게 해준다. www.yahoo 만 입력해도 www.yahoo.com 을 추천해 주는 것이다! (이전에 접속한 기록이 있다면)
2.4 안전하지 않은 문자
URL은 각 리소스에 유일한 이름을 지을 수 있게 설계되었다. 모든 프로토콜이 데이터를 전송하기 위해서 서로 다른 장치를 가지고 있기 때문에, 어떤 인터넷 프로토콜을 통해서든 안전하게 전송될 수 있도록 URL을 설계하는 것이 중요했다.
안전한 전송이란! 정보가 유실될 위험 없이 URL을 전송할 수 있다는 것을 의미한다.
URL 설계자들은, 모든 인터넷 프로토콜로 URL이 전송될 수 있기를 바랐고, 이와 함께 가독성도 있기를 바랐다. 따라서 출력이 되지 않거나 보이지 않는 문자를 사용하는 것을 배제했었다. 하지만 일반적으로 안전한 알파벳 외에도 다양한 문자를 포함하려고 할 때가 있다는 것을 알게 되었다. 그래서 이스케이프라는 기능을 추가하여, 안전하지 않은 문자를 안전한 문자로 인코딩할 수 있게 하였다.
2.4.1 URL 문자 집합
컴퓨터 시스템의 기본 문자 집합은 보통 영어 중심으로 설정되어 있다. 역사적으로 많은 컴퓨터 애플리케이션이 US-ASCII 문자 집합을 사용해왔다. US-ASCII는 만들어진 지 오래된 문자 집합이기 때문에, 적은 수의 문자만을 포함 하고 있다. 전 서계 사람들이 사용하는 유럽 언어나 수백 가지의 비 라틴계 언어들에 존재하는 변형된 문자들까지 US-ASCII가 지원하지는 않는다. 때문에 URL 설계자들은 URL에 이스케이프 문자열을 쓸 수 있도록 설계했다. 이스케이프 문자열이란 US-ASCII에서 사용이 금지된 문자들로, 특정 문자나 데이터를 인코딩할 수 있게 함으로써 이동성과 완성도를 높였다. 아래에 구체적인 예시를 보면서 이해해 보자!
=> 사용 금지된 문자들을 이스케이프 문자열로 변환하여 URL에 사용할 수 있게 만들겠다는 뜻!
2.4.2 인코딩 체계
인코딩이란 안전하지 않은 문자를 퍼센티지 기호(%)로 시작해, ASCII 코드로 표현되는 두 개의 16진수 숫자로 이루어진 '이스케이프' 문자로 바꾼다.
아래는 예시이다.
문자 | ASCII 코드 | URL의 예 |
~ | 126 (0x7E) | http://www.woongs.com/%7woo (원래는 ~7woo) |
빈 문자 | 32 (0x20) | http://www.woongs.com/more%20index.html |
% | 37 (0x25) | http://www.woongs.com/100%25index.html |
2.4.3 문자 제한
몇몇 문자는 URL 내에서 특별한 의미로 예약되어 있다. 즉, URL에서 예약된 문자들을 본래 목적이 아닌 다른 용도로 사용하려면 그 전에 반드시 인코딩 해야한다.
문자 | 선점 및 제한 |
% | 인코딩에 이스케이프 토큰으로 선점 |
/ | 경로 세그먼트를 나누는 용도로 선점 |
. | 경로 컴포넌트에서 선점 |
.. | 경로 컴포넌트에서 선점 |
# | 프래그먼트 구획 문자로 선점 |
? | 질의 문자열의 구획문자로 선점 |
; | 파라미터의 구획문자로 선점 |
: | 스킴, 사용자이름/비밀번호, 호스트/포트 의 구획문자로 선점 |
$, + | 선점 |
@ $ = | 특정 스킴에서 특별한 의미가 있기에 선점 |
{ } | \ ~ [ ] ` | 게이트웨이와 같은 여러 전송 에이전트에서 불안전하게 다루기 때문에 제한됨 |
< > " | 안전하지 않음. URL 범위 밖에서 역할이 있는 문자이기 때문에 반드시 인코딩 |
0x00-0x1F, 0x7F | 이 16진수 범위에 속하는 문자들은 인쇄되지 않는 US-ASCII 문자이다. |
> 0x7F (이진 연산인듯) | 이 16진수 범위에 속하는 문자들은 7비트 US-ASCII 문자가 아니다. |
2.4.4 좀 더 알아보기
애플리케이션은 정해진 방식대로 구현해야 한다. 어떤 애플리케이션에 어떤 URL을 보내든지, 그 전에 클라이언트 애플리케이션에서 안전하지 않거나 제한된 문자는 변환하는 것이 좋다. 안전하지 않은 모든 문자를 인코딩하기만 하면, 다른 애플리케이션으로부터 특별한 의미를 가지는 문자를 받았을 때 혼동할 걱정 없이, URL 원형을 유지할 수 있다.
입력받은 URL에서 어떤 문자를 인코딩해야 하는지 결정하는 데는 브라우저 같이 사용자로부터 최초로 URL을 입력받는 애플리케이션에서 하는 것이 가장 적절하다. URL을 구성하는 각 컴포넌트마다 사용할 수 있거나 없는 문자들이 있을 것이고, 또 어떤 문자는 스킴에 따라서 가용성이 달라지기 때문에, 해당 문자들을 직접 입력받는 애플리케이션이야 말로 어떤 문자를 인코딩해야 하는지 결정하기에 가장 좋은 위치이다.
2.5 스킴의 바다
아래 표는 가장 유명한 스킴들을 요약해 놓았다. 가볍게 읽어 보면 좋을 것 같다.
스킴 | 설명 |
http | 사용자 이름이나 비밀번호가 없다는 것을 제외하고는, 일반 URL 포맷을 지키는 하이퍼텍스트 전송 프로토콜(Hypertext Transfer Protocol) 스킴이다. 포트값이 생략되어 있으면 기본값은 80이다. - 기본형식 : http://<호스트>:<포트>/<경로>?<질의>#<프래그먼트> |
https | https 스킴은 http 스킴과 거의 같다. 다른 점이라고는 https는 HTTP 커넥션의 양 끝단에서 암호화 하기 위해 넷스케이프에서 개발한 보안 소켓 계층 (Secure Sockets Layer, SSL)을 사용한다는 것뿐이다. 문법은 HTTP와 같고 기본 포트값은 443이다. - 기본형식 : https://<호스트>:<포트>/<경로>?<질의>#<프래그먼트> |
malito | malito URL은 이메일 주소를 가리킨다. 이메일은 다른 스킴과는 다르게 동작해서 다른 포맷을 가진다. - 기본형식 : malito: <RFC-822-addr-spec> |
ftp | 파일 전송 프로토콜 (File Transfer Protocol, FTP) URL은 FTP 서버에 있는 파일을 내려 받거나 올리고, FTP 서버의 디렉토리에 있는 콘텐츠 목록을 가져오는 데 사용할 수 있다. - 기본형식 : ftp://<사용자 이름>:<비밀번호>@<호스트>:<포트>/<경로>;<파라미터> |
rtsp, rtspu | RTSP URL은 실시간 스트리밍 프로토콜( Real Time Streaming Protocol )을 통해서 읽을 수 있는 오디오 및 비디오와 같은 미디어 리소스 식별자다. rtspu 스킴에 있는 'u'는 리소스를 읽기 위해서 UDP 프로토콜이 사용됨을 뜻한다. - 기본형식 : rtsp(u)://<사용자 이름>:<비밀번호>@<호스트>:<포트>/<경로> |
file | 주어진 호스트 기기에서 바로 접근할 수 있는 파일들을 나타낸다. 만약 호스트가 생략되어 있으면, URL을 사용하고 있는 기기의 로컬 호스트가 기본값이 된다. - 기본형식 : rtsp://OFFICE-FS/policies/index.docs |
telnet | 대화형 서비스에 접근하는데 사용된다. telnet URL 자체가 객체를 가리키지는 않지만, 리소스라고 할 수 있는 대화형 어플리케이션은 이 telnet 프로토콜을 통해 접근할 수 있다. - 기본형식 : telnet://<사용자 이름>:<비밀번호>@<호스트>:<포트>/ |
2.6 URL의 미래
URL은 세상에 존재하는 모든 객체에 이름을 지을 수 있고 새로운 포맷을 쉽게 추가할 수 있도록 규칙이 짜여진 강력한 도구이다. 단점은 URL 리소스가 옮겨지면 찾을 수 없다는 것이다. 이런 문제를 예방할 수 있는 이상적인 방법은, 객체의 위치와 상관없이 그 객체를 가리키는 실제 객체의 이름을 사용하는 것이다. 사람처럼 리소스의 이름과 다른 몇 가지 정보만 있으면 그것의 위치가 바뀌더라도 리소스의 위치를 찾을 수 있다.
인터넷 기술 태스크 포스는 한동안 고심한 끝에 URN 이라는 새로운 표준 작업에 착수했다. 이 기술을 위해 PURL 이라는 것을 사용했는데, 추적하는 리소스 위치를 중개 서버에 두고 중개 서버 리소스를 우회 주소로서 제공하는 방식이다.
하지만 URL에서 URN으로 주소 체계를 바꾸는 것은 매우 큰 작업이고 URN을 지원하기 위해서는 많은 변화가 필요하다. 표준을 제정해야하고 여러 문제들과 합의도 필요하다. 때문에 URN로 전환하기 위해서는 많은 시간이 걸릴 것으로 본다.
'CS 스터디' 카테고리의 다른 글
[JS] let, const 와 var 의 차이 (0) | 2021.11.07 |
---|---|
[웅's HTTP 완벽가이드] 3장 (2편) - 상태 메시지와 헤더 총정리 (HTTP/1.1까지) (0) | 2021.10.24 |
[웅's HTTP 완벽 가이드] 3장(1편) - HTTP 메시지 ( 메서드 총정리 ) (0) | 2021.10.17 |
[웅's HTTP 완벽 가이드] 1장 - HTTP 기초 (0) | 2021.09.25 |
[JS] Object Prototype 이란? (0) | 2021.09.06 |