사전 식별자
개념

식별자

gabury1고친 사람 github-actions[bot]

식별자는 여럿 가운데 어느 하나를 집어내 가리키는 값입니다. 대상을 통째로 주고받는 대신 이 값만 건네면 받은 쪽이 그것으로 대상을 찾아냅니다. 데이터베이스의 한 행도, 기록에 남는 사용자도, 네트워크를 오가는 요청 하나도 저마다 식별자로 구별됩니다. 프로그래밍 언어가 변수와 함수에 붙이는 이름도 같은 말로 부릅니다.

쉽고 빠른 이해

식별자는 여럿 가운데 하나를 집어내려고 미리 붙여 둔 값입니다. 쇼핑몰에서 회원마다 붙는 회원 번호가 식별자입니다.

식별자가 없으면 「홍길동」처럼 사람이 읽는 이름으로 찾아야 합니다. 같은 이름이 둘이면 누가 누구인지 못 가릅니다. 이름이 바뀌면 옛 기록이 주인을 잃습니다.

어떻게 도나:

  1. 어느 범위 안에서 겹치지 않을 값을 정합니다
  2. 대상이 생길 때 값을 하나 붙이고 두 번 다시 바꾸지 않습니다
  3. 그 뒤로는 대상을 주고받을 때 이 값만 건넵니다

대가는 값만 봐서는 무엇인지 모른다는 것입니다. 회원 번호 4821 이 누구인지 알려면 회원 정보를 한 번 더 찾아야 합니다.

상세

아파트 1305호를 떠올리면 됩니다. 살던 사람이 이사를 나가고 새 사람이 들어와도 그 집은 건물이 서 있는 내내 1305호입니다. 문패의 이름이 바뀌어도 우편물과 택배는 그 번호를 보고 찾아옵니다.

식별자는 정해 둔 범위 안에서 대상 하나를 유일하게 가리키도록 붙인 값입니다. 값이 같으면 같은 대상입니다. 값이 다르면 다른 대상입니다. 이 약속 하나로 프로그램은 대상을 견주고 찾고 이어 붙입니다.

성질 셋을 먼저 봅니다. 이어서 이름과 무엇이 다른지, 값을 어떻게 만드는지를 봅니다.

식별자가 갖춰야 하는 성질 셋

식별자라고 부르려면 값이 세 가지를 지켜야 합니다. 셋 가운데 하나만 깨져도 그 값으로는 대상을 못 집어냅니다.

성질 무엇을 요구하나 깨지면
유일함 한 값이 대상 하나에만 붙는다 서로 다른 둘을 한 대상으로 봅니다
안 바뀜 한 번 붙인 값을 고치지 않는다 옛 기록이 주인을 잃습니다
범위 어디까지 겹치면 안 되는지 정한다 다른 시스템과 합칠 때 부딪힙니다

셋 가운데 설명이 필요한 것은 범위입니다. 식별자는 온 세상에서 유일할 필요가 없습니다. 쓰이는 범위 안에서만 겹치지 않으면 됩니다. 이 범위를 스코프라고 부릅니다.

아래 그림은 같은 「1번」이 서로 다른 범위에 따로 살아도 부딪히지 않는 것을 보입니다.

flowchart TD
    subgraph 회사["한 회사 안"]
        E["사번 1번"]
        subgraph 표["한 테이블 안"]
            R["행 번호 1번"]
        end
    end

사번 1번과 행 번호 1번은 값이 같지만 다른 범위에 있어 서로를 침범하지 않습니다. 반대로 두 회사를 합치면 두 사번 체계가 한 범위에 들어와 1번이 둘이 됩니다. 범위를 넓히는 일은 곧 충돌을 다시 따져야 한다는 뜻입니다.

이름 대신 식별자를 남기는 까닭

사람이 읽는 이름은 식별자로 쓰기에 약합니다. 동명이인이 있어 유일하지 않습니다. 개명이나 이메일 변경으로 값 자체가 바뀝니다.

감사 로그처럼 나중에 되짚어 볼 기록이 이 차이를 크게 받습니다. 「홍길동이 주문을 지웠다」고 적어 두면 홍길동이 둘일 때 누구인지 못 가립니다. 그 사람이 이름을 바꾸면 기록과 지금 회원 정보가 서로 다른 사람처럼 보입니다. 안 바뀌는 회원 번호를 적어 두면 이름이 바뀌어도 기록은 계속 같은 사람을 가리킵니다.

시스템은 대개 둘을 갈라 둡니다. 안에서 이어 붙이는 일은 식별자가 맡습니다. 사람에게 보여 줄 때만 그 식별자로 이름을 찾아 옵니다. 데이터 모델링에서 기본키를 따로 두는 것도 같은 까닭입니다.

다만 이미 안 바뀌고 유일한 값이 있다면 식별자를 새로 만들 까닭이 없습니다. 값을 하나 더 들고 다니는 비용만 늘어납니다.

식별자를 만드는 두 방법

겹치지 않는 값을 얻는 방법은 크게 둘입니다. 한 군데서 번호를 내주거나, 필요한 쪽이 각자 짓습니다.

가운데서 내주기 각자 짓기
누가 정하나 번호를 나눠 주는 곳 한 군데 값이 필요한 쪽이 스스로
값 모양 1, 2, 3 처럼 짧고 순서가 있다 길고 순서가 없다
안 겹치는 까닭 한 군데서만 내주니까 고를 수 있는 값이 워낙 많아서
아픈 곳 내주는 곳이 멈추면 전부 멈춘다 값이 길어 저장 공간과 인덱스를 더 먹는다

가운데서 내주는 방법은 데이터베이스의 시퀀스가 대표입니다. 번호를 세는 장부를 한 군데만 두고 요청이 올 때마다 다음 수를 건넵니다. 값이 짧고 순서가 있어 다루기 편한 대신, 값을 받으려면 그 한 군데에 물어봐야 합니다.

각자 짓는 방법은 UUID(Universally Unique Identifier, 전역 고유 식별자)가 대표입니다. 고를 수 있는 값의 폭을 아주 넓게 잡아 두고 그 안에서 무작위로 하나를 뽑습니다. 남에게 묻지 않고 바로 값을 만들 수 있습니다. 여러 서버가 동시에 데이터를 만드는 곳에서 이 방법을 씁니다.

순서가 있는 값에는 대가가 하나 더 붙습니다. 바깥에 보이는 웹 주소에 회원 번호를 그대로 쓰면 지금 회원이 몇 명인지가 드러납니다. 번호를 하나씩 바꿔 남의 것을 찍어 볼 수도 있습니다. 이 때문에 안에서 쓰는 번호와 바깥에 내보이는 식별자를 갈라 두기도 합니다.

주고받는 메시지를 짝짓는 식별자

식별자는 가만히 있는 대상만 가리키는 것이 아닙니다. 오가는 메시지에도 붙습니다.

요청을 여럿 한꺼번에 보내면 응답이 보낸 순서대로 돌아오지 않습니다. 그래서 요청마다 식별자를 실어 보냅니다. 응답에 그 값을 그대로 담아 돌려받아 짝을 맞춥니다.

sequenceDiagram
    participant 보내는쪽
    participant 받는쪽
    보내는쪽->>받는쪽: 요청 · 식별자 7
    보내는쪽->>받는쪽: 요청 · 식별자 8
    받는쪽-->>보내는쪽: 응답 · 식별자 8
    받는쪽-->>보내는쪽: 응답 · 식별자 7
    Note over 보내는쪽: 값이 같은 것끼리 짝지어 읽습니다

응답 8이 먼저 왔지만 보내는 쪽은 헷갈리지 않습니다. 값 8을 실어 보낸 요청과 짝지으면 되기 때문입니다.

상대가 살아 있는지 묻고 보낸 내용을 그대로 돌려받는 메시지를 에코라고 합니다. ICMP(Internet Control Message Protocol, 인터넷 제어 메시지 프로토콜)의 에코가 이 방식을 씁니다. 여기에 순서 번호를 더하면 몇 번째 요청인지까지 구별합니다.

서비스를 여럿 거치는 요청에서는 같은 역할을 상관 관계 ID가 맡습니다. 맨 앞에서 값을 하나 만들어 뒤로 계속 넘기면, 흩어진 기록을 그 값으로 모아 한 요청의 경과를 이어 볼 수 있습니다.

프로그래밍 언어의 식별자

프로그래밍 언어에서 식별자는 변수·함수·클래스에 붙이는 이름을 가리킵니다. 소스 코드를 잘게 쪼개 읽을 때 이 이름 하나가 토큰 하나가 됩니다.

문법이 이름의 모양을 정해 둡니다. 대개 글자나 밑줄로 시작해야 하고 숫자로 시작할 수 없습니다. if 나 class 처럼 언어가 이미 뜻을 정해 둔 예약어도 쓸 수 없습니다.

아래 코드에서 이름과 값이 어떻게 갈리는지 봅니다.

Java
int userAge = 3;             // 값 3
int nextAge = userAge + 1;   // 값 4

userAge 와 nextAge 가 식별자입니다. 3 과 4 는 그 이름이 가리키는 값입니다. 둘째 줄은 userAge 라는 이름을 불러 그 값을 꺼내 씁니다.

이름은 사람이 읽으라고 붙인 것입니다. 컴파일러는 이 이름을 메모리의 어느 칸으로 바꿔 둡니다. 그래서 프로그램이 도는 동안에는 이름이 필요 없습니다.

둘 다 대상 하나를 골라 가리킵니다. 갈리는 것은 유일해야 하는 범위입니다. 언어의 식별자는 그 프로그램 안에서만 구별되면 됩니다. 회원 번호는 그 서비스가 도는 내내 구별되어야 합니다.

관련 항목

식별자가 지켜야 하는 성질

유일성 · 불변성 · 스코프 · 네임스페이스 · 충돌 · 참조 무결성

데이터베이스에서 식별자로 쓰는 키

기본키 · 외래키 · 대리키 · 자연키 · 유니크 제약 · 시퀀스 · 자동 증가 · 복합키

겹치지 않는 값을 만드는 방식

UUID · ULID · 난수 생성기 · 해시 함수 · 일련번호 · 체크 디지트

주고받는 메시지를 짝짓는 식별자

상관 관계 ID · 트레이스 ID · 요청 ID · 순서 번호 · 세션 ID · 멱등성 키

자원이 놓인 위치를 가리키는 이름 체계

URI · URL · 도메인 이름 · IP 주소 · MAC 주소 · 포트 번호 · 경로

프로그램 안에서 대상을 가리키는 값

포인터 · 참조 · 핸들 · 디스크립터 · 레이블 · 태그

프로그래밍 언어가 이름을 다루는 단계와 규칙

토큰 · 예약어 · 변수 · 어휘 분석 · 심볼 테이블 · 이름 규칙

사람과 권한을 가리키는 식별자

사용자 ID · 계정 · 주체 · 감사 로그 · 개인 정보 · 가명 처리

다른 이름: identifier · identifiers · ID