Back to all articles
HTTPWeb
·

URI, URL, URN은 무엇이 다를까?

URI가 큰 우산이고 URL과 URN이 그 안에서 어떻게 다른지, 그리고 왜 셋의 경계가 생각만큼 딱 나뉘지 않는지 정리해요.

URI, URL, URN은 무엇이 다를까?

URI, URL, URN은 무엇이 다를까? thumbnail

URI, URL, URN은 비슷하게 들리지만 범위가 달라요. 이름이 길어서 헷갈릴 뿐이지, 관계를 한 번만 잡아 두면 생각보다 단순해요. 핵심은 URI가 가장 넓은 개념이라는 점이에요. 다만 셋의 경계가 칼처럼 딱 나뉘는 건 아니라서, 그 부분도 뒤에서 같이 짚어 볼게요.

URI는 우산 같은 말이에요

URI는 Uniform Resource Identifier의 약자예요. 말 그대로 어떤 자원을 식별하는 표준적인 방법이라는 뜻이에요. URL과 URN은 이 URI 안에 들어가는 하위 개념으로 보면 돼요.

용어의미
URI자원을 식별하는 전체 개념
URL자원이 어디에 있고 어떻게 찾는지 알려주는 주소
URN자원의 이름을 알려주는 식별자

즉, 모든 URL은 URI예요. 하지만 모든 URI가 URL인 것은 아니에요. URN은 이름 중심 식별자라서 위치 정보가 없을 수도 있어요.

여기서 말하는 "자원"은 웹 문서만 뜻하지 않아요. 이미지, 서비스, 심지어 책이나 사람처럼 인터넷으로 접근할 수 없는 대상도 자원이 될 수 있어요. URI는 그런 대상을 가리키는 이름표라고 생각하면 돼요.

URI는 이런 구조로 되어 있어요

URI는 아무렇게나 생긴 문자열이 아니라, 정해진 부품으로 나뉘어요. 이 공통 문법은 RFC 3986이 정의해요. 앞에서 본 웹 주소를 부품별로 뜯어보면 이렇게 나뉘어요.

https://example.com:443/posts/1?draft=false#title
구성요소예시 값하는 일
schemehttps어떤 규칙(프로토콜·식별 체계)으로 다룰지
authorityexample.com:443자원이 있는 곳 (host, 필요하면 port·사용자 정보)
path/posts/1계층적인 위치나 경로
querydraft=false부가 정보, 보통 key=value 형태
fragmenttitle문서 안에서의 특정 위치

몇 가지만 알아 두면 편해요. scheme은 반드시 있어야 하고, 표준상 소문자로 쓰는 게 정석이에요. authority는 [사용자정보@]host[:port] 꼴인데, :443처럼 그 scheme의 기본 포트(https는 443, http는 80)와 같으면 보통 생략해요. 그래서 앞서 본 https://example.com/posts/1 처럼 포트 없이 쓰는 게 흔해요.

fragment(#title)는 조금 특별해요. 이 부분은 서버로 전송되지 않고 브라우저(클라이언트)가 처리해요. 그래서 같은 페이지 안에서 #섹션으로 이동해도 서버로 가는 요청 자체는 바뀌지 않아요.

URL은 위치와 접근 방법을 알려줘요

웹에서 흔히 보는 https://example.com/posts/1 같은 값은 URL로 부르면 돼요. 이 값은 어디에 있는지, 어떤 경로로 접근하는지 알려줘요. 브라우저 주소창에 넣는 값도 보통 URL이라고 생각하면 크게 틀리지 않아요.

https://example.com/posts/1?draft=false#title

이 값은 URI이기도 하고 URL이기도 해요. 위치와 접근 방법을 함께 알려주기 때문이에요. 위 구조에서 특히 authority(위치)를 갖는 경우라고 보면 돼요. 경로, 쿼리, fragment가 함께 들어가면 웹에서 다루기 더 편해요.

URL이 꼭 http/https만 뜻하는 건 아니에요. ftp://ftp.example.com/file.zip이나 file:///Users/me/note.txt처럼 위치를 알려주는 다른 scheme도 URL(위치 기반 식별자)에 해당해요.

URN은 이름 중심 식별자예요

URN은 Uniform Resource Name의 약자예요. 위치가 아니라 이름 자체를 식별하는 쪽에 가까워요. 예를 들면 ISBN 같은 식별자를 떠올리면 쉬워요.

urn:isbn:9780131103627

URN도 정해진 구조가 있어요. urn:<NID>:<NSS> 형태예요.

구성요소예시 값하는 일
schemeurnURN임을 나타내요
NIDisbn이름 공간(namespace) 식별자
NSS9780131103627그 이름 공간 안에서의 실제 이름

NID는 Namespace Identifier(이름 공간 식별자), NSS는 Namespace Specific String(이름 공간별 문자열)이에요. urn:ietf:rfc:3986이나 urn:issn:1234-5678처럼, NID가 "어떤 체계의 이름인지"를, NSS가 "그 안에서의 값"을 담당해요.

URN의 핵심은 영속성(persistent)과 위치 독립성(location-independent)이에요. 자원이 옮겨지거나 사라져도 이름 자체는 계속 유효하도록 설계돼요. 다만 urn:으로 시작한다고 다 URN인 건 아니에요. NID가 IANA에 등록되어 있고 정해진 규칙대로 값이 부여돼야 진짜 URN이에요. 참고로 scheme(urn)과 NID는 대소문자를 구분하지 않지만(ISBN = isbn), NSS는 기본적으로 대소문자를 구분해요.

이 값은 자원이 어디에 있는지보다, 무엇인지를 이름으로 알려줘요. 실무 웹 개발에서는 URL보다 덜 자주 보이지만, 표준 문서나 식별 체계(ISBN, ISSN, XML 네임스페이스 등)에서는 의미가 있어요.

URL과 URN은 칼같이 나뉘지 않아요

여기서 한 번 짚고 갈 부분이 있어요. 흔히 URI라는 큰 원 안에 URL과 URN이 서로 겹치지 않는 두 칸으로 들어간다고 생각하기 쉬워요. 그런데 RFC 3986은 조금 다르게 설명해요.

하나의 URI는 위치를 알려주는 것(locator)일 수도, 이름 역할을 하는 것(name)일 수도, 둘 다일 수도 있어요. 즉 "위치를 알려주는가"와 "이름 역할을 하는가"는 서로 배타적인 게 아니라, 한 URI가 동시에 만족할 수 있는 성질이에요. 그리고 이건 scheme에 의해 자동으로 정해지기보다, 그 식별자를 얼마나 꾸준하고 신중하게 관리하느냐에 더 가까워요.

그래서 RFC 3986은 앞으로 문서에서는 URL/URN 같은 좁은 용어보다 URI라는 일반 용어를 쓰라고 권해요. 실제로 잘 관리된 http 주소는 오래 유지되는 이름처럼 쓰일 수 있고(안정적인 permalink를 떠올리면 돼요), 반대로 URN도 resolver를 통해 실제 위치로 연결될 수 있어요.

정리하면, URL과 URN은 서로 다른 "종류"라기보다 URI가 가진 "성격"에 가까워요. 그래서 무엇으로 부를지보다, 지금 위치를 말하는지 이름을 말하는지가 더 중요한 구분이에요.

URI가 있다고 접근이 되는 건 아니에요

또 하나 자주 오해하는 지점이 있어요. URI가 있다고 해서 그 자원에 꼭 접근할 수 있는 건 아니에요.

URI 자체는 식별만 해요. 접근이 되는지, 어떻게 접근하는지는 그 URI가 쓰이는 프로토콜이 정해요. 예를 들어 http://localhost/는 누구에게나 같은 의미로 해석되지만(식별), 실제로 열리는 결과는 각자 환경에 따라 달라요. 그래서 존재하지 않는 자원을 가리키는 URI도 문법적으로는 완전히 정상이에요. 식별과 접근은 별개라는 감각을 가지고 있으면, URN처럼 "위치 없이 이름만 있는" 식별자도 자연스럽게 받아들여져요.

한글이나 공백은 어떻게 표현하나요

URI에 그대로 쓸 수 있는 글자는 제한돼 있어요. 영문자와 숫자, 그리고 몇몇 기호(-, ., _, ~ 같은 unreserved 문자) 정도예요. 반면 / ? # [ ] @ : 같은 reserved 문자는 구분자 역할을 하기 때문에, 데이터로 쓰려면 percent-encoding(퍼센트 인코딩)을 거쳐요. 대표적으로 공백은 %20이 돼요.

그럼 한글은요? URI 문법 자체는 ASCII만 허용해요. 그래서 한글은 UTF-8로 바꾼 뒤 각 바이트를 percent-encoding 해요. 예를 들어 한글은 이렇게 돼요.

%ED%95%9C%EA%B8%80

브라우저 주소창에서 한글이 그대로 보이는 건 사용자에게 보기 좋게 보여줄 뿐이고, 실제 요청은 인코딩된 형태로 나가요. 이렇게 유니코드까지 허용해 사람이 읽기 좋게 만든 개념은 따로 IRI(Internationalized Resource Identifier)라고 부르고, RFC 3987에 정의돼 있어요.

실무에서는 어떻게 쓰면 되나요

일상적인 웹 개발에서는 URL이라고 말해도 대부분 충분해요. API 주소, 이미지 주소, 페이지 주소는 거의 URL이라고 부르면 돼요. 팀에서 소통할 때도 이 정도면 오해가 잘 안 생겨요. 다만 RFC나 표준 문서를 읽을 때는 URI라는 더 넓은 용어가 자주 등장하니, 그때는 "상위 개념이구나" 하고 받아들이면 돼요. 그래서 용어를 너무 엄격하게 외우기보다, 다음 기준으로 잡는 게 실용적이에요.

  • 위치를 주면 URL이라고 생각해요.
  • 이름만 주면 URN에 가깝다고 생각해요.
  • 둘 다 포괄하는 말이 필요하면 URI를 써요.

URL과 URI를 구분하는 일보다 중요한 건, 내가 지금 위치를 말하는지 이름을 말하는지 분명히 하는 일이에요. 그 기준이 서면 문서를 읽을 때도 덜 헷갈려요.

정리

  1. URI는 자원을 식별하는 가장 넓은 개념이에요.
  2. URL은 위치와 접근 방법을 알려주는 주소예요.
  3. URN은 이름 중심 식별자예요.
  4. URI는 scheme, authority, path, query, fragment로 나뉘고, URN은 urn:NID:NSS 구조예요.
  5. URL과 URN은 딱 나뉘는 종류라기보다 URI가 가진 성격에 가까워요. 그래서 표준 문서는 URI를 기본 용어로 권해요.
  6. 한글·공백 같은 글자는 percent-encoding으로 표현하고, 유니코드까지 허용하는 개념은 IRI라고 불러요.

참고