사전 표현
개념

표현

gabury1

표현은 자원을 네트워크 선 위로 건널 수 있는 모양으로 바꿔 줍니다. 사용자 42번이라는 대상을 데이터 덩이로 적어 놓은 한 벌 같은 것입니다. 자원 자체는 서버 안의 대상이라 오가지 못합니다. 오가는 것은 언제나 그 자원을 바이트로 적은 표현입니다.

쉽고 빠른 이해

무슨 일을 하는 물건인가 — 서버가 들고 있는 자원 하나, 곧 사용자 한 명이나 게시글 한 편 같은 대상 하나를 상대가 읽을 수 있는 바이트 한 벌로 적어 놓은 것입니다. 사용자 한 명을 데이터 덩이로 적은 것도, 같은 사용자를 화면용 문서로 적은 것도 각각 표현 하나입니다.

왜 이렇게 하나 — 대상 자체는 선 위로 못 건넙니다. 건널 수 있는 것은 바이트뿐입니다. 대상과 그 대상을 적은 바이트에 따로 이름을 붙여야 「같은 것을 다른 모양으로 준다」는 말이 성립합니다.

어떻게 도나

  1. 클라이언트가 어떤 모양으로 받고 싶은지 밝힙니다
  2. 서버가 그 대상을 그 모양의 바이트로 적습니다
  3. 이 바이트를 어떻게 읽어야 하는지 알려 주는 설명을 붙여 내려보냅니다

대가 — 대상 하나에 여러 벌이 생기므로 지금 보고 있는 것이 어느 벌인지 늘 따져야 합니다. 저장해 둔 벌이 낡았는지 보는 일도 벌마다 따로 해야 합니다.

상세

웹과 API(Application Programming Interface, 응용 프로그램 프로그래밍 인터페이스) 설계에서 표현이라고 하면 이 뜻입니다. 계산식을 뜻하는 표현식이나 통신 계층 이름인 표현 계층은 다른 이야기입니다.

식당의 「오늘의 메뉴」를 떠올려 봅시다. 오늘의 메뉴 자체는 주방에서 정한 결정이라 손에 쥘 수 없습니다. 손님이 손에 쥐는 것은 한국어로 적은 종이이거나, 영어로 번역한 종이이거나, 사진을 붙인 안내판입니다.

셋은 서로 다른 종이입니다. 옮긴 결정은 같습니다.

표현은 자원이 어느 시점에 담고 있는 값을 바이트로 적은 한 벌입니다. 자원은 주소가 가리키는 대상 하나를 뜻합니다. 이 한 벌은 미리 만들어 두는 것이 아니라 요청을 받은 그때 적어 내는 경우가 더 흔합니다.

사용자 42번이라는 대상은 이름도 모양도 없는 개념이라 그대로는 못 건넵니다. 그 대상의 지금 값을 바이트로 적어야 건널 수 있습니다. 그렇게 적은 한 벌이 표현입니다.

바이트와 그 바이트를 푸는 설명

표현 한 벌에는 두 가지가 들어갑니다. 하나는 값을 적은 바이트입니다. 다른 하나는 그 바이트를 어떻게 읽어야 하는지 알려 주는 설명입니다. 뒤엣것을 표현 메타데이터라고 부릅니다.

설명이 없으면 같은 바이트가 다르게 읽힙니다. 중괄호로 시작하는 바이트 덩이를 받은 클라이언트는 그것을 데이터로 풀어야 할지 그냥 글자로 보여 줘야 할지 모릅니다. 그래서 바이트를 어떤 미디어 타입으로 읽어야 하는지를 Content-Type 같은 헤더에 적어 함께 보냅니다.

설명에 담기는 것은 형식만이 아닙니다. 형식 말고도 셋이 함께 갑니다.

  • 문자 인코딩 — 글자를 어떤 규칙으로 바이트에 옮겼는지
  • 언어 태그 — 어느 나라 말로 적혔는지
  • 콘텐츠 인코딩 — 바이트를 줄여 보냈다면 어떤 방식으로 줄였는지

같은 자원을 두 가지로 적으면 바이트와 설명의 짝도 두 벌이 됩니다. 그려 보면 이렇습니다.

flowchart TD
    R["자원 · 사용자 42번"]
    subgraph SA["표현 A"]
        A1["바이트 · 데이터 덩이"]
        A2["설명 · 데이터 덩이로 읽어라"]
    end
    subgraph SB["표현 B"]
        B1["바이트 · 화면용 문서"]
        B2["설명 · 화면용 문서로 읽어라"]
    end
    R --> A1
    R --> A2
    R --> B1
    R --> B2

위는 하나입니다. 아래는 둘입니다. 표현마다 바이트와 설명이 짝으로 붙습니다. 짝 가운데 한쪽만 오면 클라이언트는 그것을 못 씁니다.

자원 하나에 딸리는 여러 벌

같은 자원을 데이터 덩이로도 적고 화면용 문서로도 적을 수 있습니다. 웹에서 데이터 덩이는 대개 JSON(JavaScript Object Notation, 자바스크립트 객체 표기법)으로 적고, 화면용 문서는 HTML(HyperText Markup Language, 하이퍼텍스트 마크업 언어)로 적습니다. 한국어로 적은 것과 영어로 적은 것도 서로 다른 표현입니다.

주소는 하나입니다. 그 주소가 내려줄 수 있는 벌은 여럿입니다. 그러면 무엇을 내려줄지 정해야 합니다.

클라이언트가 받고 싶은 모양을 밝히고 서버가 그에 맞는 벌을 고르는 절차를 콘텐츠 협상이라고 부릅니다. 고른 한 벌을 선택된 표현이라고 부릅니다.

아래는 한 번의 주고받음입니다. 왼쪽은 오가는 줄입니다. 오른쪽 화살표 뒤는 그 줄이 뜻하는 바입니다.

요청
GET /users/42
Accept: application/json        → 데이터 덩이로 주세요

응답
Content-Type: application/json  → 데이터 덩이로 적었습니다
{"id": 42, "name": "eun"}

요청은 원하는 모양을 밝힙니다. 응답은 무엇으로 적었는지를 밝힙니다.

마지막 줄이 표현의 바이트입니다. 그 위의 설명이 그 바이트를 푸는 열쇠입니다. 같은 주소로 화면용 문서를 달라고 밝히면 같은 사용자가 다른 바이트로 내려옵니다.

요청과 응답 본문에 실리는 것

GET으로 받아 오는 것은 자원이 아니라 자원의 표현입니다. PUT으로 보내는 것도 표현 한 벌입니다. 서버는 받은 표현을 보고 자기가 들고 있는 자원의 값을 그 표현에 맞춥니다. 요청과 응답의 본문에 실리는 것이 곧 표현이라고 보면 됩니다.

한 번 받아 오고 한 번 고쳐 보내는 동안 선 위로 무엇이 지나는지 그려 보면 이렇습니다.

sequenceDiagram
    participant 클라이언트
    participant 서버
    클라이언트->>서버: 사용자 42번을 데이터 덩이로 주세요
    Note over 서버: 자원의 지금 값을 바이트로 적는다
    서버-->>클라이언트: 표현 + 이 바이트를 푸는 설명
    클라이언트->>서버: 고친 표현을 보냅니다
    Note over 서버: 받은 표현에 맞춰 자원의 값을 바꾼다

선 위를 지나는 것은 네 번 다 표현입니다. 자원은 서버 쪽에 그대로 머물러 있습니다.

이 구도에 이름을 붙인 것이 REST(Representational State Transfer, 표현 상태 전이)입니다. 이름 안의 표현이 이 표현입니다.

클라이언트는 받아 온 표현을 읽고 다음에 무엇을 할지 정합니다. 그렇게 클라이언트의 상태가 한 걸음씩 옮겨 간다는 뜻입니다.

벌마다 붙는 검증자

받아 온 표현을 캐시에 넣어 두면 다음에 다시 안 받아도 됩니다. 캐시는 한 번 받은 값을 가까운 곳에 두고 다시 쓰는 것을 말합니다. 그러려면 넣어 둔 벌이 아직 서버의 것과 같은지 물을 수 있어야 합니다.

이때 쓰는 것이 검증자입니다. 검증자는 표현 한 벌에 붙는 짧은 표식입니다. 그 벌이 바뀌면 표식도 바뀝니다.

클라이언트가 가진 표식을 함께 보내면 서버는 같은지 다른지만 알려 줍니다. 같으면 본문을 다시 안 보냅니다.

표식은 자원이 아니라 표현에 붙습니다. 같은 사용자라도 데이터 덩이로 적은 벌과 화면용 문서로 적은 벌은 서로 다른 표식을 갖습니다. 벌 하나가 바뀌었다고 다른 벌까지 낡은 것이 되지는 않습니다.

자원과 표현을 가른 값과 대가

자원과 표현을 한 덩이로 보면 주소 하나에 모양 하나가 붙박입니다. 데이터 덩이로도 주고 싶어지면 주소를 새로 하나 더 파야 합니다. 클라이언트는 같은 대상을 두 이름으로 알게 됩니다.

갈라 놓으면 주소는 그대로 두고 적는 방법만 늘릴 수 있습니다. 사람이 볼 화면과 프로그램이 읽을 데이터가 같은 주소를 씁니다. 서버가 안에서 값을 어떻게 저장하는지도 밖으로 안 새어 나갑니다. 저장한 모양과 내보내는 모양이 다른 것이 정상이 됩니다.

대가는 따질 것이 늘어난다는 것입니다. 어느 벌을 받았는지, 저장해 둔 벌이 어느 쪽인지, 고쳐 보내는 벌이 서버가 아는 모양인지를 그때그때 맞춰야 합니다.

그래서 두 말을 갈라 쓰는 것은 한 대상을 여러 모양으로 내보낼 때입니다. 사람이 볼 화면과 프로그램이 읽을 데이터를 같이 내보내는 서비스, 여러 나라 말을 함께 다루는 서비스가 그렇습니다. 반대로 파일 저장소처럼 바이트 그 자체가 곧 대상이면 갈라 부를 것이 없습니다. 그때는 그냥 파일이라고 부르면 됩니다.

현재 값이 아닌 표현

표현이 늘 자원의 현재 값 전부인 것은 아닙니다. 큰 파일을 앞에서부터 나눠 받으면 한 번에 오는 것은 그 일부입니다. 지난 판본을 따로 보관해 두었다가 내려주기도 합니다.

요청이 잘못됐을 때 돌아오는 본문도 표현입니다. 다만 그 표현이 설명하는 것은 자원이 아니라 무엇이 잘못됐는지입니다. 본문에 무엇이 실려 있든 그것이 그 주소의 현재 값이라고 단정하지 않는 편이 안전합니다. 무엇을 설명하는 표현인지는 함께 온 설명과 상태 코드가 말해 줍니다.

관련 항목

표현이 옮겨 적는 대상과 그 주소

자원 · URI · 요청 대상 · 엔드포인트 · 자원 지향 설계

표현에 붙어 그 바이트를 푸는 설명

표현 메타데이터 · Content-Type · 미디어 타입 · 문자 인코딩 · 언어 태그 · 콘텐츠 인코딩 · 메타데이터

여러 표현 가운데 한 벌을 고르는 절차

콘텐츠 협상 · 선택된 표현 · Accept · Vary · 품질값

표현을 주고받는 요청 메서드

GET · PUT · POST · PATCH · 요청 메서드

표현을 실어 나르는 메시지 부분

HTTP · 메시지 · 요청 본문 · 응답 본문 · 헤더 · 상태 코드

저장해 둔 표현이 낡았는지 보는 수단

캐시 · 검증자 · ETag · 조건부 요청 · Last-Modified

표현을 적는 데 쓰는 데이터 형식

JSON · HTML · XML · Protobuf · 직렬화

표현을 중심에 놓는 인터페이스 설계 방식

REST · API 설계 · 하이퍼미디어 · HATEOAS · 통일 인터페이스

이름이 겹쳐 헷갈리는 이웃

표현식 · 표현 계층 · 정규 표현식 · 직렬화 형식

다른 이름: representation · 리소스 표현