사전 필드
개념

필드

gabury1고친 사람 github-actions[bot]

필드는 데이터 한 덩이 안에서 값 하나를 담는 이름 붙은 칸입니다. 프로그램은 덩이 전체를 뒤지지 않고 필드 이름이나 번호로 원하는 값을 바로 꺼냅니다. 클래스와 데이터베이스와 네트워크 메시지가 모두 이 말을 씁니다. 화면의 입력 칸도 필드라 부르지만 이 항목은 데이터 안의 칸을 다룹니다.

쉽고 빠른 이해

필드는 데이터 안에서 값 하나에 이름을 붙여 둔 칸입니다. 회원 정보라면 이름 칸과 나이 칸이 각각 필드입니다.

칸을 미리 정해 두지 않으면 받는 쪽은 어느 값이 이름이고 어느 값이 나이인지 알 수 없습니다. 칸마다 이름을 붙여 두면 보내는 쪽과 받는 쪽이 같은 값을 같은 칸에서 찾습니다.

어떻게 도나:

  1. 어떤 칸이 있고 칸마다 어떤 값이 들어가는지 먼저 정합니다
  2. 데이터를 만들 때 칸마다 값을 채웁니다
  3. 읽는 쪽은 칸 이름이나 번호로 값을 꺼냅니다

대가는 바꾸기 어렵다는 것입니다. 칸 이름을 바꾸거나 칸을 지우면 옛 이름으로 찾던 쪽이 값을 못 찾습니다.

칸이 실행 중에 자꾸 바뀐다면 칸을 미리 정하지 않는 키-값 저장을 씁니다.

상세

이삿짐 상자를 떠올리면 됩니다. 상자 겉에 「주방」이라 적어 보내면 받는 쪽은 그 글씨를 보고 상자를 고릅니다. 번호와 내용을 적은 목록을 양쪽이 미리 한 장씩 나눠 가졌다면 겉에는 번호만 붙여 보내도 받는 쪽이 같은 상자를 찾아냅니다.

필드는 여러 값을 묶은 데이터 한 덩이에서 값 하나를 가리키는 단위입니다. 필드마다 이름이 붙습니다. 대개 들어갈 값의 종류도 정해집니다. 필드가 여럿 모인 덩이 하나가 레코드입니다. 데이터베이스 테이블의 한 행이나 프로그램 속 객체 하나가 레코드의 예입니다.

이 절은 먼저 필드를 이루는 요소를 봅니다. 이어서 필드를 찾는 방법이 맥락마다 어떻게 갈리는지 봅니다. 그다음 클래스와 프로토콜 버퍼와 HTTP(HyperText Transfer Protocol, 하이퍼텍스트 전송 프로토콜) 메시지의 필드를 차례로 살펴봅니다. 끝으로 필드와 열의 차이, 필드를 바꿀 때 조심할 점을 봅니다.

API(Application Programming Interface, 프로그램끼리 부르는 약속)를 설계할 때 가장 자주 만나는 필드가 프로토콜 버퍼와 HTTP 메시지의 필드입니다. 그래서 이 두 소절을 길게 다룹니다.

필드를 이루는 요소

필드 하나는 이름과 값으로 이루어집니다. 이름은 칸을 가리키는 표시입니다. 값은 칸에 들어간 내용입니다. age 가 이름이면 3 이 값입니다.

여기에 데이터 타입이 붙는 경우가 많습니다. 타입은 그 칸에 들어갈 수 있는 값의 종류입니다. age 칸을 정수로 정해 두면 글자가 들어오는 실수를 미리 막습니다.

어떤 필드가 있고 각각 어떤 타입인지를 적어 둔 설계도가 스키마입니다. 스키마가 있으면 데이터를 만드는 쪽과 읽는 쪽이 같은 설계도를 보고 일합니다.

맥락마다 필드를 찾는 방법

필드라는 뜻은 어느 맥락에서나 같습니다. 달라지는 것은 읽는 쪽이 필드를 무엇으로 찾느냐입니다. 크게 이름으로 찾기, 번호로 찾기, 위치로 찾기의 세 가지입니다.

맥락 필드가 가리키는 것 무엇으로 찾나
클래스 · 구조체 객체에 딸린 변수 소스에서는 이름, 실행할 때는 위치
관계형 데이터베이스 테이블 행 안의 값 하나 열 이름
JSON(JavaScript Object Notation) 같은 텍스트 포맷 키와 값 한 쌍 키 문자열
프로토콜 버퍼 메시지 스키마에 선언한 칸 필드 번호
HTTP 메시지 이름과 값 한 쌍 필드 이름
이진 프로토콜 헤더 정해진 비트 구간 헤더 시작점에서 떨어진 거리

표의 마지막 줄에 나오는 거리를 오프셋이라고 부릅니다. 헤더 안에서 몇 번째 비트부터 몇 비트가 어떤 필드인지 미리 정해 두는 방식입니다. TCP(Transmission Control Protocol, 전송 제어 프로토콜) 헤더의 출발 포트 필드가 이런 식으로 첫 16비트를 차지합니다.

찾는 방법에 따라 무엇을 바꿔도 되는지가 달라집니다. 이름으로 찾는 쪽은 이름을 바꾸면 깨집니다. 번호로 찾는 쪽은 이름을 바꿔도 되지만 번호를 바꾸면 깨집니다. 「프로토콜 버퍼 메시지의 필드」 소절과 마지막 소절의 표가 이 차이를 보여 줍니다.

클래스의 필드

자바 같은 객체 지향 언어에서 필드는 클래스 안에 선언한 변수입니다. 객체를 하나 만들면 필드마다 값을 담을 공간이 객체 안에 생깁니다. 메서드 안에서 잠깐 쓰고 사라지는 지역 변수와 달리, 필드는 객체가 살아 있는 동안 값을 들고 있습니다.

아래 코드는 필드 둘을 가진 클래스를 만들고 값을 채워 읽습니다.

Java
class User {
    String name;
    int age;
}

User u = new User();
u.name = "유미";
u.age = 3;
int next = u.age + 1;     // 4
int len = u.name.length(); // 2

u.age 처럼 객체 이름 뒤에 점을 찍고 필드 이름을 적어 값을 꺼냅니다. 소스 코드에서는 이름으로 부릅니다. 실행할 때는 객체 시작점에서 떨어진 위치로 값을 읽습니다. 필드마다 위치가 미리 정해져 있어 앞 필드를 차례로 훑지 않습니다. 그래서 필드를 꺼내는 비용은 필드가 몇 개든 거의 같습니다.

프로토콜 버퍼 메시지의 필드

프로토콜 버퍼는 구조가 있는 데이터를 바이트로 바꾸는 방식입니다. 데이터를 전송하거나 저장할 수 있게 바이트로 바꾸는 이 일을 직렬화라고 부릅니다.

서비스끼리 주고받을 데이터의 모양은 proto 파일에 적습니다. 이 파일 안에서 필드를 묶어 선언한 단위가 메시지입니다. 아래는 필드 둘을 묶은 메시지 하나입니다.

proto
message User {
  string name = 1;
  int32 age = 2;
}

= 1 은 기본값이 아닙니다. 필드마다 붙이는 필드 번호입니다. 직렬화된 바이트에는 필드 이름이 들어가지 않고 이 번호와 값만 들어갑니다. 받는 쪽은 번호를 보고 자기 스키마에서 어느 필드인지 찾습니다.

아래 그림은 이름이 어디에 남고 번호가 어디로 가는지를 보여 줍니다.

flowchart TD
    subgraph 스키마["proto 파일 · 양쪽이 나눠 가진 설계도"]
        S1["name · 번호 1"]
        S2["age · 번호 2"]
    end
    subgraph 바이트["직렬화된 바이트 · 네트워크로 가는 것"]
        W1["번호 1 · 유미"]
        W2["번호 2 · 3"]
    end
    S1 --> W1
    S2 --> W2

이름은 스키마에만 있고 바이트에는 번호만 실립니다. 그래서 필드 이름은 나중에 바꿔도 이미 오가는 데이터가 깨지지 않습니다. 반대로 번호를 바꾸거나, 지운 필드의 번호를 다른 필드에 다시 쓰면 옛 데이터를 엉뚱한 필드로 읽게 됩니다.

필드를 새로 더하는 일은 비교적 안전합니다. 옛 스키마를 가진 쪽은 모르는 번호를 만나면 건너뜁니다. 새 스키마를 가진 쪽은 옛 데이터에 없는 필드를 기본값으로 채웁니다. 스키마를 바꾸면서도 옛 프로그램과 계속 주고받을 수 있는 성질을 하위 호환성이라고 부릅니다.

HTTP 메시지의 필드

HTTP 메시지는 요청 하나나 응답 하나를 가리킵니다. 프로토콜 버퍼의 메시지와는 다른 말입니다.

HTTP 에서 필드는 이름과 값을 한 쌍으로 묶은 정보입니다. Content-Type: application/json 한 줄이 필드 하나입니다. 콜론 앞이 필드 이름이고 뒤가 값입니다.

HTTP 메시지에서 필드가 놓이는 곳은 두 군데입니다. 본문 앞의 헤더 구역과 본문 뒤의 트레일러 구역입니다. 트레일러는 본문을 다 보내고 나서야 알 수 있는 값을 뒤에 덧붙일 때 씁니다.

HTTP 에서는 두 구역에 놓인 것을 두루 「필드」라 부릅니다. 헤더 구역에 놓인 필드는 헤더 필드입니다. 트레일러 구역에 놓인 필드는 트레일러 필드입니다. 실무에서 흔히 「헤더」라고 부르는 한 줄이 대개 이 헤더 필드입니다.

HTTP 필드 이름은 대소문자를 가리지 않습니다. 아래 두 줄은 같은 필드입니다.

http
Content-Type: application/json
content-type: application/json

필드 이름을 코드에서 비교할 때 대소문자를 구분하면 같은 필드를 놓칩니다.

같은 이름의 필드가 여러 줄 올 수도 있습니다. 받는 쪽은 이 줄들을 순서대로 쉼표로 이어 한 줄로 합쳐 읽어도 됩니다. 그래서 값 안에 쉼표가 들어가는 필드는 이렇게 합칠 때 뜻이 흐려질 수 있습니다.

필드와 열

데이터베이스에서는 필드와 열을 섞어 부릅니다. 열은 테이블 설계에서 세로 한 줄 전체를 가리킵니다. 필드는 흔히 한 행 안에서 그 열에 들어간 값 하나를 가리킵니다.

예를 들어 users 테이블의 age 는 열입니다. 3번 회원 행의 age 칸에 든 3 을 가리킬 때 필드라는 말을 씁니다. 다만 둘을 가르지 않고 같은 뜻으로 쓰는 문서도 많습니다.

언제 필드를 더하고 언제 조심하나

필드를 더하는 일은 대개 싸게 끝납니다. 읽는 쪽이 모르는 필드를 건너뛰는 형식이면 옛 프로그램은 새 필드를 무시하고 계속 돕니다. JSON 을 주고받는 API 나 프로토콜 버퍼가 이렇게 동작합니다.

필드를 지우거나 이름을 바꾸는 일은 조심해야 합니다. 이름으로 찾는 형식에서는 옛 이름으로 읽던 쪽이 값을 잃습니다. 번호나 위치로 찾는 형식에서는 번호나 위치를 건드리는 순간 데이터 해석이 통째로 어긋납니다.

바꾸는 일 이름으로 찾는 형식 번호로 찾는 형식
필드 더하기 대개 안전 대개 안전
이름 바꾸기 옛 쪽이 값을 잃음 안전
번호 바꾸기 · 다시 쓰기 해당 없음 값을 엉뚱한 필드로 읽음
필드 지우기 옛 쪽이 값을 잃음 옛 쪽이 값을 잃음

필드 집합이 실행 중에 계속 바뀌어야 한다면 필드를 미리 정하는 방식이 맞지 않습니다. 그럴 때는 키와 값을 자유롭게 넣는 해시테이블이나 스키마를 강제하지 않는 문서 데이터베이스를 고릅니다.

관련 항목

필드를 모아 이루는 데이터 단위

레코드 · 구조체 · 객체 · 클래스 · 행 · 문서 · 메시지 · 튜플

필드를 이루는 구성 요소

데이터 타입 · 필드 번호 · 기본값 · 널 · 오프셋 · 패딩

필드 집합을 정의하는 설계도

스키마 · proto 파일 · JSON 스키마 · 인터페이스 정의 언어 · 매핑 · DDL

필드를 가리키는 다른 이름

열 · 속성 · 멤버 변수 · 인스턴스 변수 · 프로퍼티 · 키

필드를 실어 나르는 형식과 프로토콜

프로토콜 버퍼 · JSON · HTTP · RFC 9110 · TCP · Avro · Thrift

HTTP 메시지에서 필드가 놓이는 구역

헤더 · 헤더 필드 · 트레일러 · 트레일러 필드 · 시작줄 · 콘텐츠

필드를 바꿀 때 지키는 성질

하위 호환성 · 상위 호환성 · 스키마 진화 · 직렬화 · 역직렬화 · API 설계

필드를 미리 정하지 않는 저장 방식

해시테이블 · 맵 · 문서 데이터베이스 · EAV · 스키마리스

다른 이름: field · fields