사전 프레임
용어함정

프레임

gabury1고친 사람 github-actions[bot]

프레임은 무언가를 일정한 틀에 담아 한 칸으로 떼어 다루게 해 줍니다. 그런데 무엇을 담느냐에 따라 전혀 다른 물건을 가리킵니다. 네트워크에서는 선 하나를 건너가는 데이터 한 덩이입니다. 프로그램 실행에서는 함수 하나를 부를 때마다 만들어지는 작업 공간입니다.

쉽고 빠른 이해

무슨 일을 하는 물건인가 — 흘러가는 것을 한 칸씩 끊어 담는 틀입니다. 랜선 위를 지나가는 데이터 한 덩이도 프레임입니다. 자바 메서드 하나가 도는 동안 쓰는 메모리 한 칸도 프레임입니다. 가장 흔한 이 두 뜻은 이름만 같고 서로 이어지지 않습니다.

왜 이렇게 하나 — 네트워크에서는 받는 쪽이 어디서부터 어디까지가 한 덩이인지, 오는 길에 깨지지 않았는지 알아야 합니다. 함수 호출에서는 함수마다 제 변수를 따로 두어야 서로 값을 덮어쓰지 않습니다.

어떻게 도나

  1. 네트워크 프레임은 데이터 앞뒤에 주소와 검사값을 붙여 옆 장비로 보냅니다
  2. 라우터 같은 옆 장비는 그 프레임을 벗기고 다음 구간용 프레임을 새로 씌웁니다
  3. 함수 프레임은 함수를 부를 때 쌓입니다. 함수가 끝나면 맨 위에서 빠집니다

대가 — 네트워크 프레임은 앞뒤에 붙는 정보만큼 실어 나를 몫이 줄어듭니다. 함수 프레임은 호출이 너무 깊어지면 쌓을 공간이 바닥납니다. 대화에서 둘을 섞어 부르면 서로 다른 이야기를 하게 됩니다. 옆에 붙은 말이 장비 주소 이야기인지 함수 호출 이야기인지를 보면 어느 뜻인지 갈립니다.

상세

이 절은 「프레임」이 가리키는 물건들을 나란히 놓고 봅니다. 먼저 뜻들을 표 하나로 가릅니다. 그다음 네트워크의 프레임과 함수 호출의 프레임을 차례로 따라갑니다.

끝에서는 나머지 뜻들을 짧게 짚고, 대화에서 어느 뜻인지 알아채는 단서를 모읍니다.

프레임이 가리키는 물건들

뜻마다 담는 것과 쓰는 분야가 다릅니다. 공통점은 하나입니다. 이어져 있는 것을 정해진 틀로 끊어 한 칸씩 다룬다는 점입니다.

맥락 프레임 한 칸이 담는 것 예
네트워크 선 하나를 건너는 데이터 한 덩이 이더넷 프레임 · 와이파이 프레임
프로그램 실행 함수 호출 한 번이 쓰는 변수와 계산 공간 자바 메서드의 프레임 · C 함수의 스택 프레임
운영체제 메모리 물리 메모리를 같은 크기로 자른 한 조각 페이지 프레임
응용 프로토콜 한 연결 위를 오가는 가장 작은 단위 HTTP/2(HyperText Transfer Protocol 버전 2) 프레임 · 웹소켓 프레임
화면 · 영상 한 번에 보여 주는 정지 화면 한 장 애니메이션의 한 장면

백엔드 개발자가 제일 자주 만나는 것은 앞의 둘입니다.

네트워크의 프레임

네트워크는 여러 층으로 나뉘어 일합니다. 맨 아래에 가까운 링크 계층은 선 하나로 이어진 옆 장비까지 데이터를 건네는 일을 맡습니다. 이 층이 주고받는 데이터 한 덩이가 프레임입니다.

층마다 데이터 덩이를 부르는 이름이 다릅니다. 응용 프로그램이 보내는 한 덩이는 메시지입니다. 인터넷을 건너는 한 덩이는 패킷입니다. 프레임은 그 패킷을 옆 장비까지 실어 나르는 봉투입니다.

봉투가 필요한 까닭은 둘입니다. 첫째, 선 위로는 0과 1의 신호만 줄줄이 흐릅니다. 받는 쪽은 어디서 한 덩이가 시작하고 끝나는지 알아야 합니다. 둘째, 신호는 오는 길에 잡음을 맞아 깨질 수 있습니다. 받는 쪽은 깨진 덩이를 골라내야 합니다.

프레임 한 장의 생김새

프레임은 가운데 실어 나를 내용을 두고 앞뒤에 정보를 붙입니다. 가운데 실어 나르는 내용이 페이로드입니다. 네트워크 프레임에서는 위층이 건넨 패킷이 페이로드가 됩니다.

앞에 붙는 정보는 헤더입니다. 받는 쪽은 헤더를 보고 이 덩이가 누구에게 가는지, 안에 무엇이 들었는지 압니다.

뒤에 붙는 정보는 트레일러입니다. 오는 길에 덩이가 깨졌는지 확인할 값이 여기 들어갑니다.

유선 랜에서 가장 흔한 프레임은 이더넷 프레임입니다. 아래 그림과 설명은 모두 이더넷 프레임을 예로 듭니다.

이더넷 헤더에는 받는 장비와 보내는 장비의 주소가 들어갑니다. 이 주소가 MAC 주소(Media Access Control address, 매체 접근 제어 주소)입니다. 네트워크 카드마다 붙은 6바이트짜리 번호라서, 같은 선에 붙은 장비끼리 서로를 가려 부를 수 있습니다.

flowchart TD
    subgraph F["이더넷 프레임 한 장"]
        H["헤더 · 받는 MAC 주소 · 보내는 MAC 주소 · 안에 든 것의 종류"]
        P["페이로드 · 위층이 건넨 패킷"]
        T["트레일러 · 오류 검사값"]
        H --- P --- T
    end

그림의 위에서 아래가 선 위로 나가는 순서입니다. 헤더에 적힌 「안에 든 것의 종류」 값은 페이로드에 무엇이 들었는지 알려 줍니다. 받는 쪽은 이 값을 보고 IP(Internet Protocol, 인터넷 프로토콜) 패킷인지 다른 것인지 가려 위층에 넘깁니다.

트레일러에는 오류 검사값이 들어갑니다. 보내는 쪽이 프레임 내용으로 계산한 값입니다. 받는 쪽도 같은 계산을 해 봅니다. 두 값이 다르면 오는 길에 깨진 것이니 그 프레임을 버립니다.

버린 뒤에 다시 보내 달라고 하는 일은 이더넷이 하지 않습니다. 빠진 데이터를 다시 받는 일은 위층이 맡습니다. TCP(Transmission Control Protocol, 전송 제어 프로토콜)가 그런 위층입니다. 덕분에 이더넷은 한 구간을 빠르게 건네는 일에만 집중합니다.

위층의 덩이를 아래층 봉투에 넣는 이 방식이 캡슐화입니다. 메시지가 패킷에 담기고, 패킷이 다시 프레임에 담깁니다.

프레임은 한 구간만 간다

패킷은 출발지에서 목적지까지 가는 동안 모양을 거의 유지합니다. 프레임은 그렇지 않습니다. 프레임은 선 하나, 곧 한 구간만 건넙니다. 거기서 끝납니다.

집의 노트북이 멀리 있는 서버로 요청을 보낸다고 해 봅시다. 가운데에는 공유기 같은 라우터가 끼어 있습니다.

sequenceDiagram
    participant 노트북
    participant 라우터
    participant 서버
    노트북->>라우터: 프레임 1 · 받는 주소는 라우터
    Note over 라우터: 프레임 1 을 벗기고 패킷만 꺼낸다
    라우터->>서버: 프레임 2 · 받는 주소는 다음 장비
    Note over 노트북,서버: 안에 든 패킷은 처음과 같다

라우터는 받은 프레임의 헤더와 트레일러를 떼어 냅니다. 안의 패킷을 보고 다음으로 보낼 곳을 정합니다. 그리고 다음 구간용 헤더와 트레일러를 새로 붙입니다.

그래서 프레임의 MAC 주소는 구간마다 바뀝니다. 끝까지 유지되는 목적지 주소는 패킷의 IP 주소입니다. 와이어샤크(Wireshark) 같은 패킷 캡처 도구로 같은 요청을 두 구간에서 잡아 보면 MAC 주소만 다르게 찍힙니다.

같은 구간 안에서 여러 장비를 잇는 스위치는 조금 다르게 일합니다. 스위치는 프레임을 벗기지 않습니다. 헤더의 받는 MAC 주소만 보고 그 장비가 붙은 포트로 프레임을 넘깁니다.

함수 호출의 프레임

프로그램이 함수를 부르면 그 함수가 쓸 변수들을 둘 곳이 필요합니다. 함수 호출 한 번을 위해 잡는 이 작업 공간이 프레임입니다. 스택 프레임이나 호출 프레임이라고도 합니다.

책상에 서류철을 쌓는 모습을 떠올리면 됩니다. 일을 하다 다른 일이 끼어들면 새 서류철을 위에 올립니다. 끼어든 일이 끝나면 그 서류철을 치우고 아래 것을 이어서 봅니다. 다만 서류철과 달리 프레임은 맨 위 것만 손댈 수 있습니다.

프레임에 담기는 것은 대개 셋입니다. 첫째는 함수가 받은 인자와 함수 안에서 만든 지역 변수입니다. 둘째는 계산하는 동안 잠깐 쥐는 중간값입니다. 셋째는 함수가 끝나면 돌아갈 곳입니다.

함수마다 제 프레임을 가지므로, 같은 함수를 두 번 불러도 두 호출의 변수가 섞이지 않습니다.

프레임은 스택에 쌓입니다. 스택은 나중에 넣은 것을 먼저 꺼내는 구조입니다. 가장 나중에 부른 함수가 가장 먼저 끝나니, 함수 호출과 모양이 맞습니다.

함수를 부르면 프레임이 하나 올라갑니다. 함수가 끝나면 맨 위 프레임이 빠집니다. 이렇게 프레임이 쌓인 스택이 호출 스택입니다.

프레임이 쌓이고 빠지는 모양

컨트롤러가 서비스를 부르고, 서비스가 계산 함수를 부르는 상황입니다. 그림에서는 handle(컨트롤러) → placeOrder(서비스) → add(계산 함수) 순서로 불렀습니다. 각 프레임 옆의 이름은 그 함수의 변수입니다.

flowchart TD
    subgraph S["호출 스택 · 위가 지금 도는 함수"]
        F3["add 의 프레임 · a · b · sum"]
        F2["placeOrder 의 프레임 · order · total"]
        F1["handle 의 프레임 · request"]
        F3 --- F2 --- F1
    end
    F3 -->|add 가 끝나면| X["add 의 프레임이 빠지고 placeOrder 가 이어서 돈다"]

맨 위 프레임의 함수만 지금 돌고 있습니다. 아래 프레임들은 위 함수가 끝나기를 기다립니다. 각 프레임에는 그 함수의 변수만 들어 있습니다.

예외가 나면 보이는 스택 트레이스가 이 모양을 글로 찍은 것입니다. 스택 트레이스의 한 줄이 프레임 하나입니다. 맨 윗줄이 예외가 난 함수입니다. 아래로 갈수록 그 함수를 부른 쪽입니다.

함수가 자기 자신을 다시 부르는 것을 재귀라고 합니다. 재귀는 부를 때마다 프레임이 하나씩 더 쌓입니다. 멈추는 조건이 없으면 프레임이 끝없이 쌓입니다.

호출 스택이 쓸 수 있는 메모리에는 끝이 있습니다. 쌓을 공간이 바닥나서 나는 오류가 스택 오버플로입니다. 자바에서는 StackOverflowError 로 드러납니다.

자바 가상 머신의 프레임

자바 코드는 바이트코드로 컴파일된 뒤 JVM(Java Virtual Machine, 자바 가상 머신)에서 돕니다. JVM 도 메서드를 부를 때마다 프레임을 하나 만듭니다. 메서드가 끝나면 그 프레임을 없앱니다.

스레드는 한 프로그램 안에서 동시에 도는 실행 흐름 하나입니다. JVM 은 스레드마다 스택을 따로 둡니다. 그래서 동시에 도는 두 요청의 메서드 호출이 서로의 프레임을 건드리지 않습니다.

JVM 의 프레임은 안이 두 칸으로 나뉩니다. 하나는 인자와 지역 변수를 번호 붙은 칸에 넣는 지역 변수 배열입니다. 다른 하나는 계산할 값을 잠깐 올려 두는 피연산자 스택입니다.

두 칸이 따로 있는 까닭은 값을 두는 시간이 달라서입니다. 변수는 메서드가 도는 내내 지역 변수 배열의 번호 붙은 칸에 둡니다. 계산 도중에 잠깐 쥐는 값은 피연산자 스택에 올렸다가 곧 꺼냅니다.

바이트코드 명령은 계산할 때 피연산자 스택만 씁니다. 더할 두 값을 먼저 스택에 올립니다. 더하기 명령이 둘을 꺼내 결과를 다시 올립니다.

두 수를 더하는 정적 메서드 하나를 따라갑니다.

Java
static int add(int a, int b) {
    int sum = a + b;
    return sum;
}

이 메서드가 불리면 지역 변수 배열의 0번 칸에 a, 1번 칸에 b 가 들어갑니다. sum 은 2번 칸을 씁니다. 아래는 컴파일된 바이트코드입니다. 줄마다 오른쪽 주석에 그 명령 뒤 피연산자 스택을 적었습니다.

iload_0    // 스택 [a]
iload_1    // 스택 [a, b]
iadd       // 스택 [a+b]
istore_2   // 스택 []  2번 칸 = a+b
iload_2    // 스택 [sum]
ireturn    // 값을 넘기고 프레임이 빠진다

iload 는 지역 변수 칸의 값을 스택에 올립니다. istore 는 스택 맨 위 값을 칸에 내립니다. 마지막 ireturn 이 결과를 부른 쪽 프레임의 피연산자 스택에 건네면 이 프레임은 사라집니다.

그 밖의 프레임

페이지 프레임 — 운영체제는 물리 메모리를 같은 크기의 조각으로 잘라 관리합니다. 이 조각 하나가 프레임입니다.

프로그램은 실제 메모리 대신 운영체제가 보여 주는 가상 메모리를 봅니다. 가상 메모리도 같은 크기의 페이지로 잘립니다. 운영체제가 페이지 하나를 프레임 하나에 이어 붙입니다.

HTTP/2 프레임 — HTTP/2 는 요청과 응답을 더 작은 조각으로 나눠 한 연결 위에 섞어 보냅니다. 이 가장 작은 조각이 프레임입니다. 헤더를 싣는 프레임과 본문을 싣는 프레임이 따로 있습니다. 각 프레임에는 어느 요청의 조각인지 가리키는 번호가 붙습니다. 웹소켓도 메시지를 프레임 단위로 주고받습니다.

화면 프레임 — 애니메이션과 영상은 정지 화면을 빠르게 바꿔 보여 줍니다. 그 정지 화면 한 장이 프레임입니다. 1초에 몇 장을 보여 주는지가 프레임률입니다.

어느 뜻인지 가르는 단서

대화나 문서에서 「프레임」이 나오면 함께 붙은 낱말을 봅니다. 대개 그것만으로 어느 뜻인지 갈립니다.

함께 나오는 말 뜻
MAC 주소 · 이더넷 · 스위치 · 패킷 캡처 · 프레임이 깨졌다 네트워크
스택 · 호출 · 재귀 · 스택 트레이스 · 지역 변수 함수 호출
페이지 · 물리 메모리 · 가상 메모리 운영체제 메모리
HTTP/2 · 웹소켓 · 연결 하나에 섞어 보낸다 응용 프로토콜
초당 몇 프레임 · 화면이 끊긴다 · 렌더링 화면 · 영상

「프레임워크」는 이름에 같은 낱말이 들어 있을 뿐 여기 어느 뜻과도 이어지지 않습니다. 코드를 짜는 뼈대가 되는 라이브러리를 가리킵니다.

관련 항목

네트워크 프레임을 이루는 구성 요소

헤더 · 페이로드 · 트레일러 · MAC 주소 · EtherType · FCS · 프리앰블 · 순환 중복 검사

네트워크 프레임을 만들고 넘기는 장비

네트워크 인터페이스 카드 · 스위치 · 라우터 · 브리지 · 무선 액세스 포인트

계층마다 데이터 덩이를 가리키는 다른 이름

메시지 · 세그먼트 · 데이터그램 · 패킷 · PDU · 비트

네트워크 프레임이 속하는 계층과 규격

링크 계층 · 데이터 링크 계층 · OSI 7계층 · 이더넷 · 와이파이 · 캡슐화 · 프레이밍 · MTU

호출 프레임이 쌓이는 스택 구조

스택 · 호출 스택 · 스택 프레임 · 스택 포인터 · 프레임 포인터 · 반환 주소 · 스레드

자바 가상 머신 프레임을 이루는 구성 요소

지역 변수 배열 · 피연산자 스택 · 런타임 상수 풀 · 바이트코드 · JVM 스택

호출 프레임에서 자주 나는 오류

StackOverflowError · 스택 오버플로 · 재귀 · 꼬리 호출 최적화 · 스택 트레이스

프레임과 이름이 겹치는 다른 개념

페이지 프레임 · 페이지 · 가상 메모리 · HTTP/2 · 웹소켓 · 프레임률 · 프레임버퍼 · 프레임워크

다른 이름: frame