최근 수정 시각 : 2025-04-14 07:43:37

식별자


프로그래밍 언어 문법
{{{#!folding [ 펼치기 · 접기 ]
{{{#!wiki style="margin: 0 -10px -5px; word-break: keep-all"
프로그래밍 언어 문법
C(포인터 · 구조체 · size_t) · C++(클래스 · 이름공간 · 상수 표현식 · 특성) · C# · Java · Python(함수 · 모듈) · Kotlin · MATLAB · SQL · PHP · JavaScript(표준 내장 객체) · Haskell(모나드)
마크업 언어 문법
HTML · CSS
개념과 용어
함수(인라인 함수 · 고차 함수 · 콜백 함수 · 람다식) · 리터럴 · 문자열 · 식별자(예약어) · 상속 · 예외 · 조건문 · 반복문 · 비트 연산 · 참조에 의한 호출 · eval · 네임스페이스 · 호이스팅
기타
#! · == · === · deprecated · GOTO · NaN · null · undefined · 배커스-나우르 표기법
}}}}}}
프로그래밍 언어 목록 · 분류 · 문법 · 예제
파일:idents-in-java.png
Hello, world를 출력하는 Java 코드 예제에 포함된 식별자들
1. 개요2. 렉싱 규칙3. 예약어4. 컨벤션5. 언어별 상세
5.1. C5.2. Haskell5.3. Perl5.4. Ruby
6. 기타7. 관련 문서

1. 개요

identifier

프로그래밍 언어 등의 컴퓨터 언어에서 변수, 상수, 함수, 매크로, 클래스, 프로퍼티, 레이블[1], 타입, 모듈 등 특정 구성 요소를 참조(reference)하기 위해 개발자가 작명하는 고유한 이름. symbol, word[2] 등으로도 불린다.

2. 렉싱 규칙

언어별로 규칙이 상이하나 대부분의 주요 프로그래밍 언어에서 찾을 수 있는 특징들을 나열하면 다음과 같다.
  • 공문자열일 수 없음 - 너무 자명하게 여겨지곤 하나 언어 스펙을 설계하고 렉서를 구현하는 개발자들 입장에서는 실수하기 쉬운 부분이기도 하다. 렉서를 설계할 때 식별자를 /\w*/로 작성했다고 생각해 보자.
  • 숫자로 시작할 수 없음 - 이 경우 일반적인 숫자 리터럴과 구분하기 까다로워 질 수 있기 때문이다. 가령 12는 숫자일까 식별자일까? reserved word에 적용되는 렉싱 우선순위를 도입해 숫자로만 이루어진 렉심은 전부 숫자 리터럴로 분류함으로써 1차적으로 해결할 수는 있으나 그 외에도 여러 문제가 있다. 가량 C언어의 경우 정수 리터럴 끝에 표시자를 사용해 자료형을 명시할 수 있는데, 이 경우도 식별자 규칙과 충돌이 발생하게 된다. 때문에 대부분의 프로그래밍 언어에서는 종류를 막론하고 식별자를 숫자로 시작하지 않는 것이 암묵의 룰로 여겨진다.
  • 공백을 포함할 수 없음 - 여러 식별자가 나열되거나 다른 토큰과 함께 놓이는 경우 해석의 모호함을 피하기 위해서다. 때문에 대부분의 언어에서는 _ 등 문자로 표시하거나 대소문자를 다르게 하는 식으로 해결한다. 자세한 내용은 코딩 스타일 참고.
  • 로마자 알파벳만 허용 - 기본적으로 표준 아스키 코드에는 로마자 알파벳밖에 없기 때문이다. 유니코드 표준이 보편화된 이후 등장한 신생 언어들의 경우, 다국어 식별자를 제한적으로 허용하거나(Go 등) 완전히 허용하는 경우도 많다.
    • 대소문자 구분(case-sensitive) - 아스키 코드의 대문자와 소문자를 모두 허용하고, 일반적으로 대소문자 차이는 서로 다른 식별자로 렉싱한다. 다만 SQL, 포트란과 같이 구분하지 않는 언어들도 있다.

이외에도 직렬화 등 이유로 이미 등록된 예약어와 같은 이름의 식별자를 만들어야 하는 경우, 이를 우회할 수 있게끔 이스케이프하는 문법을 지원하는 언어들도 존재한다.

3. 예약어

reserved word, keyword

식별자 중 문법(syntactic) 요소로 쓰이기 위해 언어 스펙 상에서 사전에 예약해둔 식별자들을 말하며 키워드라고도 불린다. 대표적인 예시들로 if, else, for, while, break 등 개별 문법 형태를 이루는 키워드들이 있으며, 언어나 구현에 따라 자료형도 예약어로 고정하는 경우도 있다.

대부분의 언어에서는 예약어가 식별자의 렉싱 규칙과 겹치기 때문에, 둘 다로 판단할 수 있는 경우 예약어로 판단하는 것을 우선한다. 예를 들어 i는 식별자, if는 예약어, iff는 식별자로 판단하는 식.

다만 렉서 수준에서 구현하지 않고 문법상 사용된 위치에 따라 같은 토큰이라도 예약어로 쓰였는지 식별자로 쓰였는지 똑똑하게 구분해 낼 수 있는 언어도 존재한다. 이러한 언어들은 파서 제작이 다소 까다로운 편이지만, 하위 호환성에 매우 민감한 언의 경우 이러한 방법을 채택하기도 한다. 대표적인 예시로 JavaScript가 있다.
#!syntax javascript
of = async async => async

4. 컨벤션

문법상으로 차이가 나는 것은 아니나, 관습적으로 많은 언어에서 의미에 따라 식별자의 형태를 일정한 규칙에 맞출 것을 권고하고 있다.
  • _로 시작하는 식별자는 숨은 속성 - 주로 개발자가 내부적으로 사용하는 변수이거나, 라이브러리 사용자가 함부로 읽거나 쓰면 안 되는 변수임을 의미한다. Python과 같이 문법 수준에서의 객체 보호 기능이 없는 언어의 경우 사실상 표준에 가까운 규칙으로 통용되기도 한다.
  • 전부 대문자로 쓴 식별자는 상수 - 언어에 따라 차이가 많이 나는 편. 주로 로우 레벨 프로그래밍 언어에서 자주 통용된다.
  • 대문자 다음에 소문자가 올 경우 띄어쓰기 - camelCase 참고.
  • 타입의 경우 대문자로 시작 - 언어에 따라 차이가 많이 나는 편.

5. 언어별 상세

5.1. C

가장 보편적인 식별자 규칙을 가지고 있다. 숫자로 시작할 수 없고 글자는 [A-Za-z0-9] 그리고 _만 사용할 수 있으며, 공백은 허용되지 않는다.

길이의 경우 내부 단일 식별자 최대 길이는 63자, 외부(extern) 식별자 최대 길이는 31자이나, 실제 제한은 컴파일러 구현체마다 매우 상이한 편.

5.2. Haskell

유니코드 글자와 숫자, _, '를 사용할 수 있으며 반드시 글자나 _로만 시작한다. '는 주로 기존의 변수명 뒤에 붙혀 수학에서의 [math(A')]과 비슷한 의미로 사용한다.

5.3. Perl

각 자료형마다 식별자 규칙이 다르다. 예를 들어 일반 변수의 경우 $로, 배열의 경우 @로, 해시의 경우 %로 시작한다.

5.4. Ruby

식별자 규칙이 매우 복잡하고 상세한 편으로, 일반적인 언어에서는 허용되지 않는 여러 경우들을 사용할 수 있다.

예를 들어 10과 20을 더하는 간단한 표현식을 떠올려 보자.
#!syntax ruby
10 + 20
이는 충분히 직관적이나, 루비에서 +는 연산자가 아니라 Integer의 메서드로 정의되어 있다. 문법적 설탕(syntactic sugar)을 제거하면 이는 다음과 같다.
#!syntax ruby
10.+(20)
즉 이 메서드는 다음과 같이 정의되어 있고, 또 다음과 같이 오버라이딩 할 수 있다.
#!syntax ruby
class Integer
    def +(other)
        # ...
    end
end
이외에도 대부분의 유니코드 글자(letter)와 특수문자들을 유효한 식별자로 사용할 수 있다.

속성 또는 의미를 나타내기 위해 식별자 맨 앞 또는 뒤에 붙는 한두 글자의 기호를 sigil이라 부른다.
  • 스코프 관련
    • @: 인스턴스 변수. 클래스 내부에서 참조 가능한 변수를 말한다.
    • @@: 클래스 변수. 클래스 당 하나씩만 부여되는 싱글톤 값을 가리킨다.
      {{{#!syntax ruby
      class Example

      • @ins
        @@cls = 0
end}}}
  • $: 전역변수. 실행 환경 전역에서 접근 가능한 값을 읽거나 쓸 때 사용한다. 예를 들면 런타임 에러 정보를 저장하는 $! 변수 등이 있다.
  • 메서드 식별자. 타 sigil과 다르게 식별자의 맨 뒤에 붙으며, 문법적 의미는 없고 단순 규약이다.
  • ?: 해당 함수가 불리언(true 또는 false) 값만을 리턴한다는 의미. 주로 isXXX? 처럼 검사 로직 등에 사용한다.
  • !: 호출 시 주의를 요하는 경고성 식별자. 주로 새 상태를 반환하는 게 아닌 인스턴스 상태를 직접 변경하는 함수(sort! 등)를 뜻한다.

이외에도 _는 타 언어와 비슷하지만, 루프 등에서 변수를 넣어야 하나 해당 값을 사용하고 싶지 않을 때 자리 채움 용도로 사용하는 용례가 많다.

6. 기타

  • 파일:external/pbs.twimg.com/ByF5M0sIUAATowb.png

    우스갯소리로 좋은 식별자명 짓기가 개발자들이 가장 어려워하는 일 중 하나라는 말이 있다.

    언뜻 보기에는 복잡한 프로그래밍 지식이 필요한 것도 아니고 이름만 타이핑하는 게 어렵나? 싶을 수 있지만, 프로그램은 자신 혼자만 쓰고 끝나는 것이 아닌 라이브러리를 통해 팀원, 나아가 전세계의 불특적 다수가 이를 사용하게 된다. 너무 긴 이름도, 너무 짧은 이름도, 너무 추상적인 이름도, 너무 구체적인 이름도 좋지 않고 연관된 수많은 변수, 함수, 클래스 등의 연계와 조합을 생각하며 지어야 한다. 비슷한 단어 사이에서 고민되는 경우도 적지 않다. Array할지 List할지부터 시작해서 비슷한 기능을 뜻하는 수많은 동의어 중에서 하나만 정해야 하는데, 나중에 리팩토링하면서 까보니 비슷한 단어를 팀원들 각자 섞어서 썼다던가, 이미 누가 구현해둔 기능인데 없는 줄 알고 비슷한 이름으로 하나 더 만들었다던가... 그야말로 잘못된 이름 하나로 지옥이 펼쳐지게 된다.
  • 정적 분석이 가능한 언어라면 분석을 통해 해당 식별자가 어느 스코프(lexical scope)에서 쓰이는지, 어떤 식별자가 정확히 어디에서 정의된 것인지를 파악할 수 있다. 이를 보통 정의(definition) 위치와 참조(reference) 위치로 구분하고, 충분히 똑똑한 대부분의 개발환경은 식별자의 정의와 참조 위치를 검색할 수 있는 기능을 지원한다. 이를 이용하면 자동으로 해당 식별자가 쓰인 곳을 모두 찾아 식별자 이름을 한번에 교체할 수 있는데, 이를 주로 rename refactoring이라고 부른다. 리팩토링 외에도 활용할 수 있는 용도가 많은데, 예를 들어 소스 코드를 구조를 해치지 않고 난독화(obfuscation)할 때 대부분 심볼 리네임을 통해 모든 식별자를 서로 겹치지 않게 랜덤한 문자열로 바꾸게 된다.

7. 관련 문서


[1] GOTO, labeled break 등에서 쓰이는 요소.[2] 주로 어휘 분석기 구현에서 사용되는 용어.