사전 요청 대상
개념

요청 대상

gabury1고친 사람 github-actions[bot]

요청 대상은 그 요청이 서버의 무엇을 겨냥하는지를 알립니다. 서버는 요청 첫 줄에서 요청 대상을 읽고 어느 게시글을 다룰지 정합니다. 게시글 42번을 지우라는 요청은 /posts/42 를 그 값으로 적습니다. 시키는 일이 같아도 이 값이 다르면 손이 닿는 대상이 달라집니다.

쉽고 빠른 이해

무슨 일을 하는 물건인가 — 요청이 서버의 어느 것을 다루려는지 가리키는 값입니다. 게시글 42번을 지우라는 요청이라면 /posts/42 가 그 값입니다.

왜 이렇게 하나 — 무엇을 해 달라는 말과 어디에 하라는 말이 갈라져 있어야 받는 쪽이 둘을 따로 읽습니다. 지우라는 말만 오고 어디를 지울지가 없으면 요청이 성립하지 않습니다.

어떻게 도나

  1. 보내는 쪽이 요청 첫 줄 가운데에 요청 대상을 적습니다
  2. 받는 쪽이 이 값과 호스트 이름을 합쳐 완전한 주소를 다시 맞춥니다
  3. 그 주소가 가리키는 게시글·사용자 같은 것에 요청받은 일을 합니다

대가 — 이 값 하나로는 주소가 완성되지 않습니다. 대개 경로만 적고 호스트 이름은 따로 싣습니다. 둘을 잘못 맞추면 엉뚱한 사이트의 게시글을 내주게 됩니다.

상세

멀티플렉스에서는 어느 상영관에나 G열 12번 자리가 하나씩 있습니다. 그래서 표에 좌석 번호만 적혀 있으면 어디에 앉을지가 정해지지 않습니다. 몇 관인지가 함께 적혀야 비로소 앉을 자리 하나가 가려집니다.

요청 대상은 이 좌석 번호에 해당합니다. 요청이 겨냥하는 자원을 가리키는 값입니다. 자원은 게시글 한 편이나 사용자 한 명처럼 서버가 이름을 붙여 가리키는 대상입니다. 주소의 경로 부분인 /posts/42 가 이 값으로 들어가는 것이 가장 흔한 꼴입니다.

요청줄의 가운데 토막

HTTP(HyperText Transfer Protocol, 하이퍼텍스트 전송 프로토콜) 요청은 첫 줄에 세 가지를 나란히 적습니다. 무엇을 해 달라는 요청 메서드, 어디에 하라는 요청 대상, 그리고 규약의 몇 판을 쓰는지입니다. 이 첫 줄을 요청줄이라 부릅니다.

DELETE /posts/42 HTTP/1.1   ← 가운데가 요청 대상
Host: example.com           ← 호스트 이름은 헤더로

가운데 /posts/42 가 요청 대상입니다. 앞의 DELETE 는 지우라는 뜻이고 뒤의 HTTP/1.1 은 규약의 판 번호입니다. 셋이 빈칸 하나씩으로 갈라져 있습니다. 받는 쪽은 빈칸을 세어 세 값을 떼어냅니다.

요청 대상에 적히는 네 가지 꼴

무엇을 적을지는 이 요청을 누구에게 보내느냐에 따라 갈립니다. 서버로 바로 보낼 때와 프록시를 거칠 때가 다릅니다. 프록시는 중간에 서서 요청을 대신 받아 다음 서버로 넘기는 서버입니다. 주소를 댈 것이 없는 요청도 있습니다.

꼴 적는 값 쓰는 때
origin-form /posts/42?page=2 (경로부터 뒤쪽만) 서버로 바로 보내는 보통 요청
absolute-form http://example.com/posts/42 (주소 전체) 프록시에게 대신 가져다 달라고 할 때
authority-form example.com:443 (호스트와 포트만) 프록시에게 그 호스트까지 길을 뚫어 달라고 할 때
asterisk-form * (별표 한 글자) 어느 자원이 아니라 서버 자체에 묻는 요청일 때

거의 언제나 쓰는 것은 첫째 꼴입니다. 브라우저가 http://example.com/posts/42 를 열 때도 요청줄에는 경로만 적고 호스트 이름은 헤더로 보냅니다. 나머지 셋은 프록시를 부르거나 서버 자체를 물을 때만 나옵니다.

경로와 호스트가 갈라져 실리는 까닭

요청줄에 경로만 있으면 서버는 어느 사이트의 /posts/42 인지 알 수 없습니다. 한 대의 서버가 여러 사이트를 함께 받는 일이 흔하기 때문입니다.

그래서 받는 쪽은 세 가지를 합쳐 완전한 주소를 세웁니다. 요청 대상, 호스트 이름을 담은 Host 헤더, 그리고 주소 맨 앞에 오는 스킴입니다. 스킴은 http 나 https 처럼 어떤 방식으로 연결했는지를 가리키는 토막입니다.

이렇게 세운 완전한 주소를 대상 주소라 부릅니다. 아래 그림의 아래쪽 상자가 그 대상 주소입니다.

flowchart TD
    A["스킴 · https"] --> D["대상 주소 · example.com 의 /posts/42"]
    B["Host 헤더 · example.com"] --> D
    C["요청 대상 · /posts/42"] --> D

서버가 다루는 것은 요청 대상 하나가 아니라 이 대상 주소입니다. 그래서 Host 헤더가 빠진 요청은 주소를 세울 수 없어 거절됩니다.

쿼리 문자열과 프래그먼트의 경계

경로 뒤에 ?page=2 처럼 붙는 쿼리 문자열은 요청 대상 안에 함께 들어갑니다. 목록의 몇 쪽을 내줄지를 서버가 그 값을 보고 정하기 때문입니다.

반면 #comments 처럼 # 뒤에 붙는 프래그먼트는 요청 대상에 들어가지 않습니다. 그 값은 받은 문서의 어느 부분으로 화면을 옮길지 정합니다. 그래서 브라우저 쪽에서만 씁니다. 서버는 그런 값이 붙어 있었는지조차 모릅니다.

HTTP/2 이후의 요청 대상

HTTP/2 와 HTTP/3 에는 요청줄이 없습니다. 첫 줄에 세 값을 늘어놓는 대신, 헤더처럼 이름과 값을 짝지은 항목을 하나씩 보냅니다. 요청줄이 지던 값들도 그런 항목으로 나뉩니다.

앞에서 본 요청 대상 몫은 :path 항목이 받습니다.

:path: /posts/42          ← 요청 대상 몫
:authority: example.com   ← Host 헤더 몫

이름 앞의 : 는 보통 헤더와 구분하려고 붙입니다. 나뉘어 실릴 뿐 서버가 대상 주소를 세운다는 점은 같습니다. 규약의 판이 달라져도 요청이 무엇을 겨냥하는지 알리는 몫은 요청 대상이 집니다.

관련 항목

요청 대상과 함께 요청줄에 실리는 값

요청 메서드 · 요청줄 · 제어 데이터 · 메시지

요청 대상을 이루는 구성 요소

URI · 경로 · 쿼리 문자열 · 스킴 · 퍼센트 인코딩

요청 대상이 지목하는 자원과 그 값

자원 · 표현 · 엔드포인트 · 콘텐츠 협상

요청 대상을 읽어 다음 서버로 넘기는 중계 장비

프록시 · 리버스 프록시 · 로드 밸런서 · 게이트웨이 · 가상 호스팅

요청 대상을 지목해 부르는 요청 메서드

GET · POST · PUT · DELETE · OPTIONS · CONNECT

요청 대상을 실어 나르는 상위 프로토콜과 규격

HTTP · HTTPS · RFC 9112 · URL

요청 대상을 주소로 짜는 API 설계 관례

API 설계 · REST · 자원 지향 설계 · URI 템플릿 · 라우팅

다른 이름: request-target · request target