[Chapter5] URI의 설계
웹을 지탱하는 기술을 공부하며 정리한 글입니다.
틀린 부분은 지적해주시면 감사드리겠습니다 😀
Cool URI
어느 날 북마크해둔 페이지에 접속했는데, 404 Not Found 페이지가 뜨면 기분이 어떨까? 아무래도 그 페이지를 다시 찾아야하는 귀찮음이 먼저 느껴질 것이다. 이처럼 좋은 URI는 변하지 않게 설계하는 것이 좋다. 이런 좋은 URI를 바로 Cool URI라고 부른다.
웹의 발명자 팀 버너스-리(Tim Berners-Lee)가 발표한 Cool URIs don’t change를 보면 자세하게 나와있다.
변하지 않는 URI 설계
URI는 여러 환경에 의해 변경될 수 있지만, 그럼에도 변하지 않는 URI로 웹 서비스를 구축할 수는 있다.
프로그래밍 언어에 의존적인 요소를 포함하지 않는다.
http://example.com/chi-bin/login.pl
이런 URI
는 요즘에도 찾아볼 수 있지만, 요즘에는 요청할 때마다 프로세스를 실행하게 하는 CGI(Common Gateway Interface) 방식이 성능적으로 문제가 있어 점차 줄어들고 있다. CGI란, 웹 서버와 외부 애플리케이션 간의 데이터를 주고 받기 위한 표준 인터페이스이다.
예를 들어, 사용자가
example.com/cgi-bin/login.pl
을 요청하면, 서버는login.pl
이라는Perl
스크립트를 실행하고, 실행 결과를 클라이언트에게 반환
이러한 방식이 문제가 되는 이유는 다음과 같다.
- 경로 이슈 :
chi-bin
이라는 경로에 있는login.pl
을 실행시키는 것이기 때문에, 패키지 내부 경로가 변경될 경우, 해당 URI 또한 변경되게 된다. - 언어 변경 이슈 : 만약
Perl
이 아닌 다른 방식으로 변경한다면,pl
이라는 확장자가 사라지거나, 다른 것으로 변경될 수 있어, URI 또한 변경되게 된다.
이처럼 특정 언어에 의존하는 문자열을 URI에 포함할 경우, 언어를 변경하자마자 URI를 사용할 수 없게 된다.
메소드명과 세션 ID를 포함하지 않는다.
http://example.com/Login.do?action=showPage
앞서 살펴본, 확장자도 물론 문제가 되지만, action=showPage
라는 메소드 이름이 포함된 것이다. 만약 리팩터링을 하는 과정에서 showPage
가 아닌 showLoginPage
라는 함수로 이름을 변경할 경우, URI 또한 변경되게 된다.
http://example.com/home.jsp?jsessionid=12345678
세션 ID는 로그인을 할 때마다 새로 부여받게 된다. 이런 세션 ID는 대부분 쿠키에 보관하는데, URI에 포함될 경우, 로그인을 할 때마다 URI가 변경되어 불편함을 겪게 된다.
URI는 리소스를 표현하는 명사로 한다.
챕터3에서 살펴본 것과 같이, 리소스의 이름은 URI로 표현된다. 만약 사람의 이름이 김밥먹다
라는 동사라면 정말 어색할 것이다. 이처럼, URI 또한 동사가 아닌 명사로 표현하는 것이 좋다.
http://example.com/sample/people/show/123
위 URI의 경우 show
라는 동사를 사용한 것으로 보아, 123이라는 고유 ID를 가진 사람의 정보를 조회하는 것으로 보인다. 그렇지만 우리는 show
라는 동사를 사용하지 않고도 다음과 같이 변경할 수 있다.
GET http://example.com/sample/people/123
이처럼 어떤 리소스를 취득할지, 갱신할지는 URI로 지정하는 것이 아닌, HTTP 메소드를 통해 표현하는 것이다.
URI 사용성
위에서 본 것 내용을 종합하여, 로그인 페이지의 URI를 설계한다면, 다음과 같을 것이다.
http://example.com/login
이처럼 구현 의존성을 배제하고 심플하게 만들면 Cool URI를 만들 수 있다. 이런 심플한 URI를 사용하면, 사용성(Usability)가 향상된다.
http://example.com/servlet/LoginServlet
복잡한 URI를 봤을 때, 우선 가장 눈에 띄는 것은 심플한 URI에 비해, 글자수가 길다는 것이다. 즉, 사용자가 URI를 기억하기 어렵고, 다른 곳에 기재할 때에도 길이가 길어 깨지는 경우가 생길 수 있다.
또 눈에 띄는 것은 바로 servlet
과 같은 구현 의존적인 문자열이다. 개발자가 아닌 일반인 사용자가 봤을 때, servlet
이라는게 무엇을 의미하는지 이해할 수 없다.
servlet = server + let
이처럼, 기억하기 쉽고, 개발자가 아닌 일반인도 사용하기 쉽다는 것이 바로 Cool URI의 장점이다.
URI를 변경하고 싶을 때
앞서 본 예시와 같이 CGI에서 다른 시스템으로 옮길 경우 결국엔 URI가 변경될 수 밖에 없다. 이럴 때는, Redirect를 통해 새로운 URI로 전송하도록 해야 한다.
http://example.com/old
위 URI에 접근할 경우, 서버에서는 새로 변경된 URI로 이동 시켜야한다.
http://example.com/new
HTTP/1.1 301 Moved Permanetly
Location: http://example.com/new
이렇게 301이라는 응답과 Location
헤더에 URI를 명시하면, 사용자도 이전 URI를 그대로 사용할 수 있다.
URI 설계의 테크닉
확장자로 표현을 지정
앞서 살펴본 내용에서 “프로그래밍 언어에 의존적인 요소를 포함하지 않는다.”라며, 확장자는 사용하지 않는 것을 이야기했다. 하지만, 좋은 측면을 가지는 경우도 있다.
http://example.com/2010/05/01/press
프레스 릴리스의 경우, 전 세계를 상대로 활동하며, 복수의 언어로 기술한다. 예를 들어, 기본 글은 영어로 작성되었지만, 한국어 OS 사용자로 해당 페이지에 접근하면, 다음과 같은 요청이 들어간다.
GET /2010/05/01/press HTTP/1.1
Host: example.com
Accept-Language: ko, en_us;q=0.7,en:q=0.3
이처럼 페이지에 접근하면, 서버에서는 한국어로 된 글을 응답으로 돌려주면 된다. 이를, 콘텐츠 네고시에이션(Content Negotiation)이라 한다.
하지만, 한국어 OS 이용자가 영어로도 보고 싶을 경우가 있을 것이다. 이럴 경우 브라우저 설정을 변경해주어야 하는데, 이럴 때는 차라리 확장자를 이용하는 것이 좋다.
http://example.com/2010/05/01/press.ko
이럴 경우 일반인도 URI를 보고 ko가 언어로 사용한다는 것을 알 수 있어 en으로 변경하면 되겠다라고 이해할 수 있다.
매트릭스 URI
URI는 슬래시(/)를 통해서 계층을 표현할 수 있다. 예를 들어, 아래 URI는 2010년 -> 5월 -> 1일이라는 계층 구조를 띄게 된다.
http://example.com/2010/05/01/press
하지만, Google Maps와 같은 지도 서비스는 위도와 경도를 계층으로 표현할 수 없고, 동일한 레벨로 봐야한다. 이를 표현하기 위해서는 다음과 같은 방법을 사용할 수 있다.
http://example.com/map/lat=35.705471;lng=139=751898
http://example.com/map/35.705471, 139=751898
첫 번째 방식인 세미콜론은 표준화되지는 못했지만, 순서에 제약이 없고, 편리하기 때문에 자주 이용된다. 하지만, 두번째 방식은 순서가 의미를 가지기 때문에 잘 알고 사용을 해야하는 단점이 있지만, lat=
, lng=
가 생략되어 간단하게 사용할 수 있다는 장점이 있다.
이처럼, 여러 파라미터의 조합으로 표현하는 리소스를 매트릭스 URI(Matrix URI)라고 부른다.
댓글남기기