본문 바로가기

개발 서적/웹을 지탱하는 기술

[웹을 지탱하는 기술] chapter 04. URI의 스펙

 


[목차]
chapter 01. 웹이란 무엇인가?

chapter 02. 웹의 역사
chapter 03. REST 웹의 아키텍처 스타일
chapter 04. URI의 스펙


 

일반적으로 URI의 설계와 구현을 웹 애플리케이션 프레임워크에 전적으로 맡겨버리는 사람도 많지만, URI 스펙을 바르게 이해하는 것은 쓰기 편한 웹 서비스와 웹 API로 가는 첫걸음이다.

URI의 중요성

URI(Uniform Resource identifier)는 ‘리소스를 통일적으로 식별하는 ID’를 말함.

  • 통일적 : 같은 규칙을 따름을 의미
  • 식별자 : 어떤 것을 그 밖에 다른 것과 구별하여 가리키키위한 이름/ID

URI를 사용하면 웹상에 존재하는 모든 리소스를 한결같은 방식으로 간단하게 접속할 수 있다.

 

URI의 구문

URI의 스펙은 RFC 3986

RFC 3986 - Uniform Resource Identifier (URI): Generic Syntax

  • RFC란?
  • Request for Comments. 미국의 국제 인터넷 표준화기구(IETF)에서 관리하는 문서로 인터넷 개발에 있어서 필요한 기술, 연구 결과, 절차 등을 기술해놓은 메모. 거의 모든 인터넷 표준은 RFC로 문서화가 되어 있음.

일반적인 URI의 예를 살펴보자.

<http://blog.example.com/entries/1>

URI 스키마 : http

  • URI는 URI 스키마로 시작됨.
  • 그 URI가 이용하는 프로토콜을 나타내는 것이 일반적이다.
  • URI 스키마와 이어지는 부분은 :// 로 구분됨

호스트명(host) : blog.example.com

  • 이어서 나타나는 호스트명은 DNS(Domain Name System)에서 이름을 해석할 수 있는 도메인명이나 IP어드레스
  • 인터넷에서 반드시 일의성(univocity - 존재가 언제 어디서나 동일한 목소리로 표현됨)을 가지게 됨.

경로(path) : /entries/1

  • 호스트명 뒤에는 계층화를 나타내는 경로가 이어짐.
  • 경로는 호스트 안에서 오로지 하나의 리소스를 가리킴.

→ 반드시 유일한 호스트명의 구조와 호스트 내에서 유일한 계층적인 경로를 결합하여 어떤 리소스의 URI가 전세계의 다른 리소스와 절대로 중복되지 않도록 되어 있음.

이번에는 조금 더 복잡한 인위적인 URI의 예를 들어보자

<http://yohei:pass@blog.example.com:8000/search?q=test&debug=true#n10>

URI 스키마: http

사용자 정보 : yohei:pass

  • 사용자 정보는 이 리소스에 접근할 때 이용할 사용자 이름과 패스워드로 구성됨. 사용자 이름과 패스워드는 : 로 구분 → (uri에 민감한 정보가 노출되는 거 같은데 괜찮나?)
  • 사용자 정보 다음에 구분 문자인 @ 가 있고, 그 뒤에 호스트 정보가 이어짐.

호스트명 정보 : blog.example.com:8080

  • 호스트 정보는 호스트명과 포트번호로 구성되며, 이 둘은 : 로 구분됨.
  • 포트번호는 이 호스트에 액세스 할 때, 프로토콜이 사용할 TCP의 포트번호를 나타냄.
  • 포트번호를 생략한 경우에는 각 프로토콜의 디폴트 값이 사용됨

경로 : /search

쿼리 파라미터 : q=test&debug=true

  • 경로 뒤에는 구분문자인 ? 가 오고, 이름=값 형식으로 된 쿼리가 이어짐.
  • 쿼리가 여러 개 존재할 때는 & 로 연결함. → 하나 이상의 쿼리의 집합을 ‘쿼리 파라미터(query parameter)’ 또는 ‘쿼리 문자열(query strinng)’이라고 부름.
  • 쿼리 파라미터는 검색 서비스에 검색 키워드를 전달할 때 등 클라이언트에서 동적으로 URI를 생성할 때 사용

URI 프래그먼트 : #n10

  • 마지막에 # 으로 시작되는 문자열은 ‘URI 프래그먼트'라고 함.
  • #앞에 문자열로 표현한 URI가 가리키는 리소스 내부에서 더 세세한 부분을 특정할 때 이용.
  • 예를 들어, 리소스가 HTML 문서인 경우는 id 속성 값이 ‘n10’인 요소를 나타내게 됨.

 

절대 URI와 상대 URI

URI의 경로는 UNIX의 파일 시스템과 같이 ‘/’를 루트로 하고, 디렉터리 명을 ‘/’로 구분하고 필요하면 마지막에 파일명을 연결하는 계층구조를 가짐

OS의 파일 시스템에서는 루트에서부터 전체 경로를 기술한 것을 절대 경로(Absolute Path)라고 부름

파일 시스템의 경우 매번 절대 경로를 기술하면 너무 길어지기 때문에, 커맨드 라인데서 디렉터리나 파일의 위치를 지정할 때는 현재 디렉터리부터의 상대 경로(Relative Path)로 나타낸다. 현재 디렉터리는 ., 그 상위 디렉터리는 .. 로 나타냄

URI에도 절대 URI와 상대 URI가 있다. 상대 URI는 URI스키마와 호스트명을 생략하고, 경로만으로 표현한다.

Base URI

상대 URI의 기준이 되는 URI를 지정하는 것이 Base URI다. 상대 경로와 마찬가지로 . 와 .. 을 사용할 수 있고, 쿼리 파라미터와 URI 프래그먼트도 상대 URI로서 사용할 수 있다.

대표적인 2가지의 URI의 부여 방식은 다음과 같다.

리소스의 URI를 Base URI로 하는 방법

어떤 리소스를 가져왔을 때 상대 URI가 등장하면, 그 리소스의 URI를 Base URI로 하고 상대 URI를 해석한다.

직관적이고 이해하기 쉽지만, Base URI가 되는 리소스의 URI를 클라이언트 측에서 가지고 있어야만 한다는 문제점이 있다.

Base URI를 명시적으로 지정하는 방법

앞의 문제를 해결하는 방법 중 하나로 리소스 안에서 명시적으로 Base URI를 지정하는 방법이 있다.

  • HTML의 경우 <head>요소 안에 <base> 요소를 삽입한다.
  • XML 문서는 xml:base 속성을 이용하면, 어느 요소에서나 Base URI를 지정할 수 있다.

 

URI와 문자

URI에서 사용할 수 있는 문자

URI 스펙에 따르면 ASCII 문자들만 URI의 경로에 사용할 수 있다고 정해져 있다. 한글이나 일어 등 ASCII 이외의 문자를 URI에 넣을 때는 %-Encoding이라는 방식을 이용한다.

%인코딩

URI 스펙에서 허용하는 문자 이외의 것을 입력하기 위해서는 %인코딩으로 그 문자를 인코딩해야 한다.

예를 들어, 현대적인 브라우저로 ‘가'를 설명한 위키피디아 페이지를 열람하면 http://ko.wikipedia.org/wiki/가 와 같은 URI가 표시될 것이다.

외견상으로 이렇게 보이는 URI는 실제로는 다음의 문자열로 전개되어 브라우저와 서버 사이에서 전송된다. [<http://ko.wikipedia.org/wiki/%EA%B0%80>](<http://ko.wikipedia.org/wiki/%EA%B0%80>)

이는 ‘가'라는 문자가 UTF-8에서는 0xEA 0xB0 0x80의 3바이트로 이루어지는 것에 기인한다.

%인코딩에서는 UTF-8 문자를 구성하는 각 바이트를 %xx(xx는 16진수)로 기술하여 URI에 사용할 수 없는 문자를 표현한다.

일반적으로 URI는 알파벳 대소문자를 구별하여 사용하지만, %인코딩에서는 같은 의미를 가지도록 되어 있다. 단, URI 스펙에서는 대문자의 사용을 권장한다.

또한, %인코딩에서는 % 을 이스케이프 문자처럼 사용하고 있기 때문에 문자열로서 사용하기 위해서는 %25 라고 표기한다.

%인코딩의 문자 인코딩

실제 웹서비스에서는 UTF-8 이외의 문자 인코딩을 사용한 URI도 이용되고 있다.

서버가 제공하는 URI를 그대로 다루는 경우는 서버가 %인코딩하고 있으므로 문제가 없지만, 클라이언트 쪽에서 폼을 사용해 URI를 생성하는 경우에는 문제가 발생한다. 유저가 입력한 문자를 어느 문자 인코딩을 사용해 %인코딩할 것인지를 브라우저 같은 클라이언트가 판단할 수 없기 때문

이 문제는 일반적으로 그 폼을 제공하고 있는 웹 페이지의 문자 인코딩을 사용함으로써 해결한다. 즉, UTF-8로 기술한 폼이라면 UTF-8로, EUC-KR로 기술한 폼이라면 EUC-KR로 URI를 만든다. 단, 프록시에서 문자 인코딩을 변환하는 경우나 근본이 되는 웹페이지의 문자 인코딩 범위 외의 문자가 주어진 경우 등에선 오류 발생.

요즘은 많은 웹 사이트에서 문자 인코딩으로 UTF-8을 채용하고 있기 때문에, URI를 UTF-8로 %인코딩하는 경우 대부분이다. 특별한 이유가 없다면 UTF-8을 사용하는 것이 무난함.

 

URI의 길이 제한

스펙상으로는 URI의 길이에 제한은 없지만, 개별 브라우저 및 서버의 구현상으로는 제한이 존재한다. (Internet Explorer의 경우 버전 불문하고 2,083바이트까지로 제한되어 있음. 2000자 미만으로 유지할 것을 권장)

 

다양한 스키마

URI 스키마의 공식적인 목록은 IANA(Internet Assigned Numbers Authority)에 있다. 비공식을 포함한 URI 스키마는 100개 이상이 존재한다.

특정 네임스페이스 전용으로 URI 스키마를 새로 발명하는 것은 어리석은 일. 네임스페이스에는 http 스키마 같은 기존의 스키마를 지정하면 되기 때문이다. URI 스키마를 새로 등록해야만 하는 경우는 기존에 없는 프로토콜을 발명했을 때 정도라고 생각해도 좋다.

 

URI 구현에서 주의할 점들

웹 서비스와 웹 API를 구현함에 있어서 URI의 스펙상 주의해야 할 것은 상대 URI의 해석%인코딩을 다루는 2가지 사항

  • 클라이언트에서 상대 URI를 해석하는 것은 번거로운 처리가 필요 → 가능한 절대 URI를 사용하는 편이 좋음
  • URI에 ASCII 이외에 문자를 넣을 경우 문자 인코딩의 혼란이 올 수 있음 → %인코딩의 문자 인코딩으로 UTF-8을 이용하는 것이 바람직
반응형