사전 표현 계층
개념

표현 계층

gabury1고친 사람 github-actions[bot]

표현 계층은 주고받는 데이터를 양쪽 컴퓨터가 똑같이 읽도록 적는 방식을 맞춰 줍니다. 컴퓨터마다 숫자와 글자를 바이트로 적는 방식이 달라서 이 일이 필요합니다. 네트워크 통신을 일곱 계층으로 나눈 모델에서 위에서 두 번째 계층입니다. 소프트웨어 설계에서 같은 이름으로 부르는 계층은 이것과 다른 계층입니다.

쉽고 빠른 이해

표현 계층은 데이터를 네트워크에 싣기 전에 양쪽이 합의한 공통 형식으로 바꿔 적습니다. 한글 「가」를 어떤 바이트로 적을지를 두 컴퓨터가 미리 맞추는 일이 그런 일입니다.

이게 없으면 바이트가 무사히 닿아도 뜻이 틀어집니다. 보낸 숫자가 다른 숫자로 읽히고 한글이 깨져 보입니다.

표현 계층은 이렇게 움직입니다:

  1. 양쪽이 주고받을 때 쓸 공통 형식을 정해 둡니다
  2. 보내는 쪽이 자기 방식으로 적힌 데이터를 공통 형식으로 바꿔 내보냅니다
  3. 받는 쪽이 공통 형식을 자기 방식으로 다시 바꿔 프로그램에 넘깁니다

대가는 바꾸는 일이 양쪽에서 한 번씩 더 든다는 것입니다. 인터넷에는 이 계층이 따로 없어서 그 일을 프로그램이 직접 떠맡습니다.

상세

한국 회사와 브라질 회사가 편지로 거래를 합니다. 두 회사는 편지를 영어로 쓰기로 약속합니다. 한국 쪽 통역사는 한국어 편지를 영어로 옮겨 보냅니다. 브라질 쪽 통역사는 받은 영어 편지를 포르투갈어로 옮겨 사장에게 올립니다.

표현 계층(presentation layer)은 데이터를 어떤 형식으로 적어 보낼지를 통신하는 양쪽이 맞추는 계층입니다. OSI(Open Systems Interconnection, 개방형 시스템 상호연결) 모델의 여섯 번째 계층입니다. 앞의 편지에서 양쪽이 약속한 영어가 공통 형식입니다. 두 통역사가 하는 일이 표현 계층의 일입니다.

OSI 모델은 네트워크 통신을 일곱 계층으로 나누고 계층마다 한 가지 일을 맡긴 모델입니다. 흔히 OSI 7계층이라고 부릅니다. 표현 계층은 여섯 번째라서 L6(Layer 6, 6계층)이라고도 합니다.

OSI 7계층에서 여섯 번째 계층

표현 계층이 어디에 끼어 있는지 먼저 봅니다. 아래 표는 OSI 모델의 일곱 계층을 위에서부터 적은 것입니다.

번호 계층 맡는 일
7 응용 계층 주고받는 메시지의 뜻을 정한다
6 표현 계층 데이터를 적는 형식을 양쪽이 맞춘다
5 세션 계층 대화를 언제 열고 닫을지 정한다
4 전송 계층 데이터를 상대 컴퓨터의 알맞은 프로그램에 건넨다
3 네트워크 계층 주소를 보고 목적지까지 길을 찾는다
2 데이터 링크 계층 바로 이웃한 장비까지 한 구간씩 나른다
1 물리 계층 비트를 전기나 빛 신호로 바꿔 보낸다

보내는 쪽에서 표현 계층은 위의 응용 계층에게 데이터를 받습니다. 그 데이터를 공통 형식으로 바꿔 아래 세션 계층에 넘깁니다. 받는 쪽에서는 이 순서가 거꾸로 돕니다.

표현 계층보다 아래 계층들은 데이터를 뜻 없는 바이트로만 다룹니다. 바이트가 무엇을 적은 것인지는 보지 않고 나르기만 합니다. 바이트를 어떻게 읽을지는 표현 계층에서 정해집니다.

컴퓨터마다 다른 데이터 표기

이 계층이 왜 필요한지는 같은 값을 다른 방식으로 적어 보면 드러납니다. 숫자 하나와 한글 한 글자를 예로 듭니다.

첫째는 숫자입니다. 2바이트 정수 258 은 1×256 + 2 라서 두 바이트 01 과 02 로 나뉩니다. 01 이 큰 자리 바이트입니다. 메모리에 적을 때 01 을 앞에 둘 수도, 02 를 앞에 둘 수도 있습니다. 이 순서가 바이트 순서입니다.

큰 자리를 앞에 두는 방식은 빅 엔디언입니다. 뒤에 두는 방식은 리틀 엔디언입니다. 어느 쪽을 쓰는지는 CPU(Central Processing Unit, 중앙 처리 장치) 종류마다 다릅니다.

아래는 같은 258 을 두 순서로 적어 보고, 빅 엔디언으로 적은 바이트를 리틀 엔디언으로 잘못 읽어 보는 파이썬 코드입니다.

Python
n = 258
n.to_bytes(2, "big")     # b'\x01\x02'
n.to_bytes(2, "little")  # b'\x02\x01'

b = b"\x01\x02"
int.from_bytes(b, "little")  # 513

리틀 엔디언은 뒤 바이트를 큰 자리로 봅니다. 그래서 01 02 를 2×256 + 1 = 513 으로 읽습니다. 보낸 쪽은 258 을 보냈는데 받은 쪽은 513 을 받은 셈입니다. 바이트는 한 개도 틀리지 않았습니다. 읽는 순서만 달랐습니다.

둘째는 글자입니다. 글자를 바이트로 바꾸는 규칙이 문자 인코딩입니다. 같은 글자라도 어느 규칙으로 적느냐에 따라 바이트가 달라집니다.

한글에 흔히 쓰는 문자 인코딩 두 가지로 「가」를 적어 봅니다. 먼저 UTF-8(Unicode Transformation Format 8-bit, 유니코드 변환 형식 8비트)로 적으면 3바이트입니다. EUC-KR(Extended Unix Code for Korean, 한국어 확장 유닉스 코드)로 적으면 2바이트입니다.

Python
"가".encode("utf-8")   # b'\xea\xb0\x80'
"가".encode("euc-kr")  # b'\xb0\xa1'

UTF-8 로 적은 바이트를 EUC-KR 규칙으로 읽으면 엉뚱한 글자가 나오거나 읽기에 실패합니다. 한글이 깨져 보이는 흔한 까닭이 이것입니다.

추상 구문과 전송 구문

표현 계층은 이 어긋남을 풀려고 앞에서 공통 형식이라 부른 것을 둘로 갈라 맞춥니다. 하나는 데이터의 생김새입니다. 다른 하나는 그 데이터를 바이트로 적는 규칙입니다. 양쪽은 둘 다 합의합니다.

추상 구문은 데이터가 어떤 칸으로 이루어졌는지를 기계와 상관없이 적은 것입니다. 「이름은 문자열, 나이는 정수」처럼 적습니다. 바이트 순서나 문자 인코딩은 여기에 들어가지 않습니다. 생김새를 기계와 떼어 적어 두면 양쪽이 같은 데이터를 두고 이야기하는지 먼저 맞춰 볼 수 있습니다.

전송 구문은 그 데이터를 네트워크에 실을 때 쓰는 바이트 규칙입니다. 공통 형식 가운데 선 위를 지나는 바이트를 정하는 쪽이 이것입니다. 양쪽은 전송 구문 하나를 골라 합의합니다. 각 컴퓨터가 속으로 무엇을 쓰든 선 위에는 합의한 규칙대로 적힌 바이트만 지나갑니다.

flowchart TD
    subgraph S["보내는 컴퓨터"]
        A["응용 계층 · 자기 방식으로 적힌 데이터"] --> B["표현 계층 · 전송 구문으로 바꾼다"]
    end
    subgraph R["받는 컴퓨터"]
        C["표현 계층 · 자기 방식으로 되바꾼다"] --> D["응용 계층 · 자기 방식으로 적힌 데이터"]
    end
    B -->|"합의한 전송 구문의 바이트"| C

그림에서 두 컴퓨터는 서로의 속사정을 모릅니다. 각자 자기 방식과 전송 구문 사이만 오가면 됩니다. 상대가 늘어나도 바꾸는 규칙은 하나로 충분합니다. 거래처가 늘어도 통역사는 영어 하나만 알면 되는 것과 같습니다. 대가는 보낼 때와 받을 때 한 번씩 바꾸는 계산을 더 해야 한다는 것입니다.

ASN.1 과 DER

추상 구문과 전송 구문은 지금도 인증서 안에 살아 있습니다. 웹사이트가 자기 신원을 증명할 때 내미는 X.509 인증서가 이 둘을 갈라 적습니다. 인증서에 쓰이는 이름 셋이 두 구문 가운데 어느 쪽인지 차례로 짚어 봅니다.

추상 구문을 적는 언어는 OSI 표준을 만들면서 함께 정했습니다. 그 언어가 ASN.1(Abstract Syntax Notation One, 추상 구문 표기법 1)입니다. 인증서의 칸 구성은 ASN.1 로 적혀 있습니다.

ASN.1 로 적은 데이터에 쓰는 전송 구문도 정해 두었습니다. 그 기본이 BER(Basic Encoding Rules, 기본 인코딩 규칙)입니다. BER 은 같은 값을 여러 가지 바이트로 적는 것을 허용합니다.

DER(Distinguished Encoding Rules, 고유 인코딩 규칙)은 BER 을 좁혀 한 값에 한 가지 바이트만 허용하는 전송 구문입니다. 인증서에는 발급 기관의 전자 서명이 붙습니다. 서명은 바이트를 두고 확인하므로 같은 값이 늘 같은 바이트여야 합니다. 그래서 인증서는 DER 로 바이트를 적습니다.

형식 변환 말고 맡는 두 가지 일

형식을 맞추는 일 곁에 두 가지가 더 이 계층의 몫으로 꼽힙니다. 둘 다 데이터의 겉모습을 바꾸는 일이라 같은 계층에 들어갑니다.

압축은 데이터를 더 적은 바이트로 줄여 보내는 일입니다. 받는 쪽은 풀어서 원래 데이터를 되찾습니다. 보낼 양이 줄어드는 대신 양쪽이 줄이고 푸는 계산을 해야 합니다.

암호화는 열쇠가 없으면 읽을 수 없는 바이트로 바꿔 보내는 일입니다. 받는 쪽은 열쇠로 풀어 원래 데이터를 되찾습니다. 중간에서 바이트를 엿본 사람은 내용을 알 수 없습니다.

인터넷에서는 따로 없는 계층

인터넷은 OSI 모델이 아닌 다른 계층 모델을 씁니다. 그 모델에는 표현 계층이 없습니다. OSI 의 위 세 계층이 하던 일은 그 모델의 맨 위 응용 계층이 함께 맡습니다.

프로토콜은 통신하는 양쪽이 데이터를 주고받는 순서와 형식을 정해 둔 규칙입니다. 인터넷의 계층 모델은 대표 프로토콜 둘의 이름을 따서 TCP/IP 모델이라 합니다.

하나는 TCP(Transmission Control Protocol, 전송 제어 프로토콜)입니다. 다른 하나는 IP(Internet Protocol, 인터넷 프로토콜)입니다. TCP/IP 모델은 응용 계층 · 전송 계층 · 인터넷 계층 · 링크 계층의 네 계층으로 되어 있습니다.

그렇다고 형식을 맞추는 일이 사라지지는 않았습니다. 응용 계층 프로토콜과 프로그램이 부르는 라이브러리가 그 일을 나눠 맡습니다.

웹에서 쓰는 HTTP(HyperText Transfer Protocol, 하이퍼텍스트 전송 프로토콜)의 응답을 예로 봅니다. HTTP 응답은 본문 앞에 「이름: 값」 꼴의 줄을 붙여 본문을 어떻게 읽을지 알립니다. 이 줄들이 헤더입니다. 아래는 서버가 사용자 정보를 돌려주는 응답의 앞부분입니다.

http
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Content-Encoding: gzip

둘째 줄은 본문이 JSON(JavaScript Object Notation, 자바스크립트 객체 표기법) 형식이라고 알립니다. 글자를 UTF-8 로 적었다는 것도 같은 줄이 알립니다. 셋째 줄은 본문을 gzip 방식으로 압축했다고 알립니다. 받는 쪽은 이 두 헤더를 보고 본문을 풀고 읽을 방법을 고릅니다.

프로그램 안의 데이터를 JSON 처럼 정해진 형식의 바이트로 바꾸는 일이 직렬화입니다. 받는 쪽이 그 바이트를 다시 데이터로 되돌리는 일은 역직렬화입니다. OSI 식으로 말하면 자기 방식과 전송 구문 사이를 오가는 일입니다.

OSI 표현 계층이 맡던 일이 HTTP 세계에서 어디로 갔는지 표로 모읍니다.

표현 계층의 일 인터넷에서 맡는 것
데이터 형식 맞추기 JSON 같은 직렬화 형식과 Content-Type 헤더
문자 인코딩 맞추기 UTF-8 과 Content-Type 헤더의 charset
바이트 순서 맞추기 빅 엔디언으로 통일한 네트워크 바이트 순서
압축 gzip 같은 압축 방식과 Content-Encoding 헤더
암호화 TLS(Transport Layer Security, 전송 계층 보안)

표의 맨 아래 줄인 TLS 는 어느 계층에 둘지가 정해져 있지 않습니다. 암호화를 하므로 표현 계층의 일로 볼 수 있습니다. 전송 계층 바로 위에 끼운 계층으로 볼 수도 있습니다.

백엔드 코드에서 만나는 표현 계층의 일

백엔드 개발자는 표현 계층이라는 이름을 모른 채 이 일을 매일 합니다. 컨트롤러가 돌려준 객체를 웹 프레임워크가 JSON 문자열로 직렬화해 응답 본문에 싣습니다. 요청 본문의 JSON 은 거꾸로 객체로 역직렬화해 우리 함수에 넘깁니다.

한글이 깨지는 버그도 이 일에서 납니다. 보낸 쪽과 받은 쪽이 서로 다른 문자 인코딩을 쓰면 깨집니다. 응답에 charset 을 빠뜨려 받는 쪽이 짐작으로 고르게 되면 이런 일이 생깁니다.

같은 이름을 쓰는 설계의 계층

백엔드 코드를 설계할 때도 표현 계층이라는 말을 씁니다. 계층형 아키텍처에서 맨 앞에 서서 요청을 받고 응답을 돌려주는 계층을 가리킵니다. 웹 애플리케이션이면 컨트롤러가 이 계층에 속합니다.

이 계층은 네트워크의 표현 계층과 이름만 같습니다. 코드 구조를 이야기하다가 표현 계층이나 프레젠테이션 계층이라는 말이 나오면 이쪽 뜻입니다.

관련 항목

표현 계층이 속하는 계층 모델

OSI 7계층 · OSI 참조 모델 · TCP-IP 모델 · 계층 · 프로토콜 · 프로토콜 스택 · 인터넷 프로토콜 스위트

표현 계층의 위아래에 쌓이는 계층

응용 계층 · 세션 계층 · 전송 계층 · 네트워크 계층 · 데이터 링크 계층 · 물리 계층

표현 계층이 맞추는 데이터 표기

바이트 순서 · 엔디언 · 네트워크 바이트 순서 · 문자 인코딩 · UTF-8 · EUC-KR · 유니코드 · 바이트 순서 표시

표현 계층이 데이터를 적는 규칙

추상 구문 · 전송 구문 · ASN.1 · BER · DER · X.509 인증서 · 전자 서명

표현 계층의 일을 대신 맡는 인터넷의 형식

직렬화 · 역직렬화 · JSON · Protocol Buffers · XML · Base64 · HTTP · 헤더 · MIME 타입 · Content-Type · Content-Encoding

표현 계층의 몫으로 꼽히는 변환

압축 · gzip · 암호화 · TLS · HTTPS

표현 계층과 이름이 겹치는 설계 용어

레이어드 · 프레젠테이션 계층 · 컨트롤러 · 도메인 주도 설계 · 표현

다른 이름: presentation layer · L6 · 6계층