맨위로가기

매직 넘버 (프로그래밍)

"오늘의AI위키"는 AI 기술로 일관성 있고 체계적인 최신 지식을 제공하는 혁신 플랫폼입니다.
"오늘의AI위키"의 AI를 통해 더욱 풍부하고 폭넓은 지식 경험을 누리세요.

1. 개요

매직 넘버는 소스 코드 내에서 직접 사용되는 숫자, 문자열 또는 기타 데이터로, 코드의 가독성을 떨어뜨리고 유지 보수를 어렵게 만드는 안티 패턴이다. 이는 프로그램의 유연성을 저해하며, 파일 형식 식별자, 프로토콜, 매직 디버그 값 등 다양한 맥락에서 사용될 수 있다. 매직 넘버를 해결하기 위해 의미 있는 이름을 가진 상수를 사용하는 것이 권장된다.

더 읽어볼만한 페이지

  • 안티패턴 - 기술 부채
    기술 부채는 소프트웨어 개발에서 발생하는 개념으로, 현재의 편의적인 설계가 미래에 추가적인 비용을 발생시키는 것을 의미하며, 다양한 원인으로 발생하여 개발 비용 증가, 프로젝트 지연, 경쟁력 약화 등의 부정적인 결과를 초래할 수 있다.
  • 안티패턴 - 난독화
    난독화는 프로그램 코드의 가독성을 낮춰 이해를 어렵게 하는 기술로, 역공학을 방지하여 보안을 강화하며 소스 코드와 바이너리 난독화로 구분되고, 코드 분석을 어렵게 만들지만 불가능하게 하지는 않아 다른 보안 기술과 함께 사용된다.
  • 디버깅 - 스택 추적
    스택 추적은 프로그램 실행 중 함수 호출 기록을 추적하여 오류 발생 시 디버깅 및 문제 해결에 필수적인 도구로, 호출 스택의 스택 프레임을 분석하여 프로그램 실행 경로를 파악하고 오류 원인을 추적하며 프로그램 안정성을 향상시키는 기술이다.
  • 디버깅 - 메모리 디버거
    메모리 디버거는 메모리 접근, 할당, 해제를 모니터링하여 메모리 오류를 찾아내고 소프트웨어의 신뢰성을 높이는 도구이다.
매직 넘버 (프로그래밍)
매직 넘버 (프로그래밍)
정의프로그램 또는 파일 형식 식별을 위해 사용되는 고유한 상수 값 또는 바이트 시퀀스이다.
용도파일 형식 식별
프로토콜 식별
소프트웨어 버전 식별
컴파일러 최적화
특징특정 값 또는 패턴
파일 시작 부분에 위치
파일 내용을 올바르게 해석하는 데 사용
파일 형식 식별
설명파일의 종류를 식별하기 위해 파일 시작 부분에 포함된 특정 바이트 시퀀스이다.
예시JPEG 이미지: `FF D8 FF`
PNG 이미지: `89 50 4E 47 0D 0A 1A 0A`
GIF 이미지: `47 49 46 38 37 61` 또는 `47 49 46 38 39 61`
유닉스에서의 사용
설명유닉스 운영 체제에서 파일 형식을 식별하기 위해 파일 시작 부분에 매직 넘버를 사용했다.
역사데니스 리치가 유닉스 V6에서 처음 사용했으며, 이후 다양한 유닉스 버전에서 사용되었다.
구현`sys1.c` 파일에서 `gethdr` 함수를 통해 매직 넘버를 확인하고 파일 형식을 식별했다.
프로그래밍에서의 사용
설명프로그램 내에서 특정 값 또는 상수를 직접 사용하는 것을 의미한다.
코드의 가독성과 유지보수성을 저해할 수 있다.
문제점코드 이해 어려움
수정 시 오류 발생 가능성 증가
코드 재사용성 감소
해결 방법상수를 명확한 이름으로 정의하여 사용
열거형(enumeration) 또는 상수 변수를 사용하여 값의 의미를 명확히 함
보안
설명매직 넘버를 악용한 보안 취약점이 발생할 수 있다.
예시파일 확장자 검사를 우회하여 악성 코드를 실행하는 공격
대응 방법파일 내용의 유효성을 검사하고, 매직 넘버를 통해 파일 형식을 정확하게 식별해야 한다.
기타
참고 자료파일 시그니처 (파일 형식 식별을 위한 더 일반적인 용어)

2. 매직 넘버 (소스 코드)

소스 코드에서 매직 넘버는 그 의미를 알기 어려운 숫자 상수를 의미한다.[1] 이는 1960년대 COBOL, FORTRAN, PL/1 매뉴얼에서부터 언급된 오래된 규칙을 위반하는 것이다.[1]

매직 넘버를 사용하면 개발자가 숫자를 선택한 의도를 알기 어렵고,[2] 오류 발생 가능성이 높아지며,[3] 프로그램의 확장 및 적응이 어려워진다.[4] 따라서 모든 중요한 매직 넘버를 이름이 지정된 상수로 바꾸면 프로그램을 더 쉽게 읽고, 이해하고, 유지 관리할 수 있다.[5]

예를 들어, 표준 트럼프 카드 52장을 섞는 의사 코드는 다음과 같다.

```

'''for''' i '''from''' 1 '''to''' 52

j := i + randomInt(53 - i) - 1

a.swapEntries(i, j)

```

여기서 `52`와 `53`은 매직 넘버이다. 이를 개선하기 위해 다음과 같이 작성할 수 있다.

```

''int'' deckSize:= 52

'''for''' i '''from''' 1 '''to''' deckSize

j := i + randomInt(deckSize + 1 - i) - 1

a.swapEntries(i, j)

```

이 방식은 다음과 같은 장점이 있다.


  • 가독성 향상: 코드를 읽는 사람이 숫자(`52`)의 의미를 쉽게 파악할 수 있다.
  • 변경 용이: 숫자를 변경해야 할 때 (예: 타로 덱, 78장) 한 곳만 수정하면 되므로 오류 발생 가능성이 줄어든다.
  • 문서화 용이: 이름이 지정된 변수를 선언하는 위치에 값의 의미와 이유를 설명하는 주석을 추가하기 쉽다.
  • 오타 감지: 변수 이름을 잘못 입력하면 컴파일러가 경고를 표시하여 오타를 쉽게 찾을 수 있다.
  • 매개변수화 용이: 함수 또는 절차의 매개변수로 사용하여 일반화하기 쉽다.


하지만, 다음과 같은 단점도 존재한다.

  • 코드 지역성 손상: 상수가 사용된 곳과 멀리 떨어진 곳에 정의되면 이해하기 어려울 수 있다.
  • 코드 장황성 증가: 상수 선언으로 인해 코드가 길어질 수 있다.


그러나 대부분의 최신 컴파일러와 인터프리터는 상수 값을 미리 계산하므로 런타임 성능 저하는 거의 없다.

매직 넘버는 프로그램에 포함시키지 않는 것이 바람직하다. 그 이유는 다음과 같다.

  • 숫자가 가진 의미를 알기 어렵다.
  • 숫자를 변경할 경우 여러 곳을 변경해야 할 수 있다.


1이나 0은 문맥에 따라 "참", "거짓" 등의 의미(진리값)를 나타낼 수 있어 매직 넘버로 부르지 않는 경우도 있다.

2. 1. 문제점

매직 넘버는 코드 가독성을 떨어뜨리고 유지보수를 어렵게 만든다.[1] 숫자의 의미를 파악하기 어렵고, 변경 시 여러 곳을 수정해야 할 수 있기 때문이다.

  • 가독성 저해: 코드 내에서 특정 숫자가 어떤 의미로 사용되었는지 파악하기 어렵다. 예를 들어, 코드에서 숫자 '52'가 반복해서 나타난다면, 이 숫자가 무엇을 의미하는지 바로 알기 어렵다. 프로그래머는 코드를 주의 깊게 읽고 나서야 그 의미를 추론할 수 있다. 특히, 동일한 숫자가 다른 목적으로 사용될 경우 혼란은 더욱 커진다.
  • 유지보수 어려움: 숫자 값을 변경해야 할 때, 코드 내에서 해당 숫자가 사용된 모든 부분을 찾아서 수정해야 한다. 이는 오류 발생 가능성을 높이고, 코드 수정에 많은 시간을 소요하게 만든다. 예를 들어, 타로 덱(78장)을 섞는 코드로 수정해야 한다면, 숫자 '52'가 사용된 모든 곳을 찾아 '78'로 바꿔야 하는데, 이 과정에서 실수가 발생할 수 있다.
  • 정책 변화 대응 어려움: 특히 소비세율 변동 등 정책 변화에 유연하게 대응하기 어렵다. 예를 들어, 소비세율이 8%에서 10%로 변경된다면, 코드 내에서 세율과 관련된 숫자를 모두 찾아 수정해야 한다.


다음은 매직 넘버로 인해 발생하는 문제점을 보여주는 C 언어 예시이다.

; 예시 1

소비세가 8%일 때 세금 포함 가격을 계산하는 함수는 다음과 같이 작성할 수 있다.

```c

double calculateTaxIncludedPrice(double price) {

return 1.08 * price;

}

```

여기서 '1.08'은 매직 넘버이며, 소비세율이 변경되면 이 값을 직접 수정해야 한다. 매직 넘버를 제거하고 상수 `TaxRate`를 도입하면 다음과 같이 코드를 개선할 수 있다.

```c

double calculateTaxIncludedPrice(double price) {

const double TaxRate = 0.08;

return (1.0 + TaxRate) * price;

}

```

이제 소비세율이 변경되면 `TaxRate` 값만 수정하면 되므로 유지보수가 쉬워진다.

; 예시 2

`printColorText()` 함수는 문자열을 특정 색상으로 출력하는 함수라고 가정한다.

```c

extern void printColorText(const char* text, uint32_t colorValue);

printColorText("color text", 0x9acd32);

```

여기서 `0x9acd32`는 "연두색"을 나타내는 RGB 풀 컬러 값이지만, 직관적으로 이해하기 어려운 매직 넘버이다.

다음과 같이 매직 넘버를 상수로 대체하여 가독성을 높일 수 있다.

```c

const uint32_t YellowGreen = 0x9acd32;

printColorText("color text", YellowGreen);

```

이처럼 매직 넘버 대신 의미 있는 이름을 가진 상수나 열거형을 사용하면 코드 가독성과 유지보수성을 향상시킬 수 있다.

2. 2. 해결 방안

매직 넘버는 프로그램 소스 코드에 직접 사용되는 숫자로, 그 의미를 파악하기 어렵고 유지보수를 어렵게 만든다. 이러한 문제를 해결하기 위해 다음과 같은 방법을 사용할 수 있다.

  • 이름 있는 상수 또는 열거형 사용:

매직 넘버 대신 의미를 명확하게 나타내는 이름의 상수나 열거형을 사용한다.

상수를 사용하면 숫자의 의미를 쉽게 이해할 수 있고, 값을 변경해야 할 때 한 곳만 수정하면 되므로 유지보수가 용이하다.

```c

// 매직 넘버를 사용한 예

double calculateTaxIncludedPrice(double price) {

return 1.08 * price; // 1.08은 무엇을 의미하는가?

}

// 이름 있는 상수를 사용한 예

double calculateTaxIncludedPrice(double price) {

const double TaxRate = 0.08; // 소비세율 8%

return (1.0 + TaxRate) * price;

}

```

위 예시에서 `1.08` 대신 `TaxRate`라는 이름의 상수를 사용하여 코드의 가독성과 유지보수성을 높였다.

  • 주석 사용:

상수를 사용할 수 없는 경우, 주석을 통해 숫자의 의미를 명확하게 설명한다.

하지만 주석은 코드와 동기화되지 않을 수 있으므로, 상수를 사용하는 것이 더 바람직하다.

```c

extern void printColorText(const char* text, uint32_t colorValue);

printColorText("color text", 0x9acd32); // 0x9acd32는 연두색을 나타내는 RGB 값

```

  • 매직 넘버가 아닌 경우:

1이나 0과 같이 문맥에 따라 "참", "거짓" 등의 의미(진리값)를 나타내는 숫자는 매직 넘버로 간주하지 않을 수 있다.

과거 C 언어에서는 `TRUE`와 `FALSE`와 같은 심볼을 정의하여 사용하기도 했다.

```c

#define TRUE 1

#define FALSE 0

```

현재는 C 언어 표준에서 `_Bool` 자료형과 `true`, `false` 상수를 정의하여 사용한다.

2. 3. 예시

; 예시 1

C 언어로 작성된, 소비세가 8%일 때 세금 포함 가격을 구하는 소스 코드 예시는 다음과 같다.

```c

double calculateTaxIncludedPrice(double price) {

const double TaxRate = 0.08;

return (1.0 + TaxRate) * price;

}

```

위 함수는 `price`에 상품의 본체 가격을 입력하면 소비세 포함 가격을 계산한다. 하지만 소비세율(tax rate)은 변동될 수 있으므로, 세율이 8% 이외로 변경될 때 수정이 필요하다. 이때 "1.08"은 매직 넘버이며, "왜 1.08인지"라는 의도가 불분명하다.[2]

이러한 매직 넘버를 제거하기 위해, 이름이 있는 상수 심볼 `TaxRate`를 도입하면 다음과 같다.

```c

const double TaxRate = 0.08;

```

상수 심볼 도입으로 식에 의도가 반영되므로 수정이 용이해진다.

; 예시 2

`printColorText()` 함수가 첫 번째 인수의 문자열을 두 번째 인수로 RGB의 풀 컬러 값으로 지정한 색상으로 인쇄하는 함수라고 가정한다.

```c

extern void printColorText(const char* text, uint32_t colorValue);

printColorText("color text", 0x9acd32);

```

이 경우, "color text"라는 문자열은 "연두색"으로 표시된다. 그러나 0x9acd32는 직관적으로 "연두색"이라고 전달하기 어려운 매직 넘버이다.

```c

const uint32_t YellowGreen = 0x9acd32;

printColorText("color text", YellowGreen);

```

이처럼 매직 넘버가 있는 부분을 상수나 열거형으로 바꾸는 처리를 통해, 의미를 알기 쉬운 이름을 붙일 수 있다. 상수의 초기화 시 우변에 적히는 숫자까지는 매직 넘버나 하드 코딩이라고 부르지 않는다.

1이나 0은 그 자체가 "참", "거짓" 등의 의미(진리값)를 나타낼 수 있는 숫자이며, 사용되는 문맥에 따라 매직 넘버로 부르지 않기도 한다. 과거 C 언어에서는 의미를 명확히 하기 위해 1/0의 숫자를 직접 사용하는 대신, `TRUE`나 `FALSE`와 같은 심볼을 명시적으로 정의하여 사용했다.

```c

#define TRUE 1

#define FALSE 0

```

현재 C 언어 표준안에서는,

_Bool Definitions For true and false._

를 채택하고 있다.

2. 4. 예외적인 경우

어떤 맥락에서는 이름이 없는 숫자 상수의 사용이 일반적으로 허용된다 (그리고 "매직"이 아니라고 주장할 수 있다). 이러한 허용은 주관적이며 종종 개별 코딩 습관에 따라 다르지만, 다음은 일반적인 예이다.

  • for 루프의 초기 값 또는 증가 값으로 0과 1을 사용하는 경우
  • 숫자가 짝수인지 홀수인지 확인하기 위해 2를 사용하는 경우. (isEven = (x % 2 == 0)와 같이 %는 나머지 연산자이다.)
  • 간단한 산술 상수 사용. (예: circumference = 2 * Math.PI * radius[1] 또는 이차 방정식판별식을 계산하기 위해 d = b^2 − 4*a*c)
  • 미터법 값을 변환(예: 그램과 킬로그램 사이)하거나 백분율 및 퍼밀 값을 계산하기 위해 10의 거듭제곱 사용
  • \sqrt{f(x)^2 + f(y)^2}에 대한 (f(x) 2 + f(y) 2) ** 0.5와 같은 식의 지수


상수 1과 0은 부울 자료형과 같은 부울 형식이 없는 프로그래밍 언어, 예를 들어 이전 버전의 C에서 부울 값 true 및 false를 나타내는 데 사용된다. 대부분의 최신 프로그래밍 언어는 `boolean` 또는 `bool` 원시 자료형을 제공하므로 0과 1의 사용은 권장되지 않는다. 이는 0이 때로는 프로그램 성공을 의미하고 ( -1이 실패를 의미하는 경우) 다른 경우에는 실패를 의미하므로 (1이 성공을 의미하는 경우) 더 혼란스러울 수 있다.

C 및 C++에서 0은 널 포인터를 나타낸다. 부울 값과 마찬가지로 C 표준 라이브러리에는 `NULL` 매크로 정의가 포함되어 있으며 사용을 권장한다. 다른 언어는 특정 null 또는 nil 값을 제공하며, 이러한 경우 다른 대안을 사용해서는 안 된다. 형식화된 포인터 상수 nullptr는 C++11에 도입되었다.

3. 매직 넘버 (포맷 식별자)

파일 형식이나 프로토콜을 식별하기 위해 사용되는 특정 바이트 값이나 문자열을 매직 넘버라고 한다.

예를 들어 GIF 이미지는 항상 `GIF87a` 또는 `GIF89a`의 ASCII 표현으로 시작한다. HTML 파일은 `` 문자열(대소문자 구분 안 함)이나 ``로 시작하는 문서 형식 정의(DTD)로 시작하며, XHTML은 `
매직 넘버 방식은 파일 형식을 정확하게 식별하고 파일 정보를 상세하게 파악하는 데 유용하다. 하지만, 특히 대용량 파일 목록에서는 모든 가능성을 확인해야 하므로 지연 시간이 길어질 수 있다. 파일 형식이 인식되지 않으면 메타데이터를 사용해야 한다.

파일 확장자나 메타데이터는 내용과 독립적으로 변경될 수 있으므로, 파일 손상 여부나 정확한 유형을 확인하려면 매직 넘버 테스트가 필요하다. 그러나 유효한 매직 넘버가 항상 파일의 무결성이나 정확한 형식을 보장하는 것은 아니다.

셔뱅(shebang) 라인은 매직 넘버의 특별한 예시로, 특정 명령 인터프리터와 전달할 옵션을 나타내는 텍스트이다. 데이터 구조체 내에서 의미 없는 숫자를 가리켜 구조체를 식별하고 잘못된 처리 방지에 사용되는 경우도 있는데, 자세한 내용은 포맷 식별자로서의 매직 넘버에서 확인할 수 있다.

3. 1. 파일 형식 식별

매직 넘버는 파일의 종류를 식별하고, 잘못된 형식으로 처리되는 것을 방지하는 데 사용된다. 예를 들어, GIF 이미지는 항상 `GIF87a` 또는 `GIF89a`의 ASCII 표현으로 시작한다. HTML 파일은 `` 문자열(대소문자 구분 안 함)로 시작하거나 ``로 시작하는 적절한 문서 형식 정의(DTD)로 시작한다. XHTML의 경우 `
매직 넘버 방식은 파일 형식이 올바르게 식별되도록 보장하며, 파일에 대한 더 정확한 정보를 얻을 수 있다. 그러나 이 방식은 각 파일을 매직 데이터베이스의 모든 가능성에 대해 테스트해야 하므로, 특히 큰 파일 목록에서 지연 시간이 늘어날 수 있다. 파일 형식이 인식되지 않으면 시스템은 메타데이터를 사용해야 한다.

파일 확장자나 메타데이터는 내용과 독립적으로 변경될 수 있기 때문에, 파일이 손상되었거나 잘못된 유형이라는 것을 확인하려면 잘 설계된 매직 넘버 테스트가 필요하다. 그러나 유효한 매직 넘버가 파일의 손상 여부나 올바른 파일 유형임을 보장하지는 않는다.

셔뱅(shebang) 라인은 매직 넘버의 특별한 경우이다. 여기서 매직 넘버는 특정 명령 인터프리터와 명령 인터프리터에 전달할 옵션을 식별하는 텍스트이다. Magic number영어는 데이터 구조체 내에 본질적인 의미를 갖지 않는 숫자를 지칭하는 경우가 있으며, 데이터 구조체를 식별하고 잘못된 유형으로 처리되는 것을 방지하기 위해 사용된다. 더 자세한 내용은 포맷 식별자로서의 매직 넘버에서 확인할 수 있다.

3. 2. 예시 (파일)


  • JPEG 이미지 파일은 `FF D8`로 시작하여 `FF D9`로 끝난다. JPEG/JFIF 파일에는 널 종료 문자열 "JFIF"(4A 46 49 46 00)가, JPEG/Exif 파일에는 널 종료 문자열 "Exif"(45 78 69 66 00)가 포함되어 있으며, 그 뒤에 더 많은 메타데이터가 따라온다.[10]
  • GIF 이미지 파일은 "GIF89a"(47 49 46 38 39 61) 또는 "GIF87a"(47 49 46 38 37 61)에 대한 ASCII 코드를 갖는다.
  • PNG 이미지 파일은 파일을 PNG 파일로 식별하고 일반적인 파일 전송 문제를 감지할 수 있는 8-바이트 시그니처로 시작하는데, 이는 "\211PNG\r\n\032\n"(89 50 4E 47 0D 0A 1A 0A)이다. 이 시그니처에는 부적절한 자동 줄 바꿈 변환을 감지할 수 있도록 여러 줄 바꿈 문자가 포함되어 있으며, ''ASCII'' 전송 모드가 아닌 ''이진'' 모드로 FTP를 사용하여 파일을 전송하는 경우와 같다.[10]
  • PDF 파일은 "%PDF"(16진수 25 50 44 46)로 시작한다.
  • ZIP 파일의 헤더는 텍스트 편집기에서 종종 "PK♥♦"(50 4B 03 04)로 나타나며, 여기서 "PK"는 DOS 압축 유틸리티 PKZIP의 저자인 필 카츠의 이니셜이다.
  • 컴파일러로 컴파일된 자바 클래스 파일(자바 바이트코드) 및 Mach-O 바이너리는 16진수 CAFEBABE로 시작한다. Pack200으로 압축되면 바이트가 CAFED00D로 변경된다.

3. 3. 예시 (프로토콜)


  • OSCAR 프로토콜은 AIM/ICQ에서 사용되며, 요청 앞에 `2A`를 붙인다.
  • RFB 프로토콜은 VNC에서 사용되며, 클라이언트가 서버에 "RFB"를 보내 프로토콜 버전 번호를 알린다.
  • SMB 프로토콜은 요청/응답 시작 부분에 `FF 53 4D 42` (`\xFFSMB`)를 붙인다.
  • DHCP 패킷은 옵션 섹션 시작 부분에 `0x63 0x82 0x53 0x63`을 사용한다.

3. 4. 매직 디버그 값

메모리 할당 또는 해제 시에 특정 값을 기록하여, 나중에 해당 메모리가 손상되었는지 여부를 확인하거나 초기화되지 않은 메모리에서 값을 가져올 때 이를 명확하게 알 수 있도록 하는 것이 매직 디버그 값이다. 메모리는 일반적으로 16진수로 표시되므로, 기억하기 쉽고 반복되는 값 또는 16진수 값이 주로 사용된다. 홀수 값을 선호하는데, 이는 바이트 주소 지정을 지원하지 않는 프로세서에서 포인터(짝수 주소에 있어야 함)로 사용하려고 할 때 오류를 발생시키기 때문이다. 이러한 값은 프로그램 코드, 정적 데이터, 힙 데이터, 스택 등과 같이 사용될 가능성이 있는 주소와는 다른 값으로 선택된다. 또한, 주어진 아키텍처의 명령어 집합에서 유효하지 않은 코드가 되도록 선택될 수 있다.

32비트 정수가 이 특정 값을 가질 가능성은 매우 낮지만, 이러한 숫자가 디버거 또는 메모리 덤프에 나타나면 버퍼 오버플로우 또는 초기화되지 않은 변수와 같은 오류를 나타낼 가능성이 크다.

다음은 유명하고 일반적인 예시이다.

코드설명
00008123MS Visual C++에서 사용. 삭제된 포인터를 이 값으로 설정하여 사용 후 예외를 발생시키며, 0번지보다 더 잘 인식되는 별칭 (Security Development Lifecycle(/sdl) 옵션으로 활성화).[21]
..FACADE"Facade", 여러 RTOS에서 사용.
1BADB002"1 bad boot", 멀티부트 헤더 매직 넘버.[22]
8BADF00D"Ate bad food", 애플(Apple Inc.) iOS 응용 프로그램이 워치독 타임아웃으로 인해 종료되었음을 나타냄.[23]
A5A5A5A5임베디드 개발에 사용. 교대로 나타나는 비트 패턴(1010 0101)이 오실로스코프와 로직 분석기에서 쉽게 인식되는 패턴을 생성하기 때문.
A5FreeBSD의 PHK malloc에서 /etc/malloc.conf가 "-J"로 심볼릭 링크되어 모든 새로 할당된 메모리를 이 값으로 초기화하는 데 사용. NULL 포인터나 ASCII NUL 문자가 아니기 때문.
ABABABABMicrosoft의 디버그 HeapAlloc()에서 할당된 힙 메모리 뒤의 "노 맨스 랜드" 보호 바이트를 표시하는 데 사용.[24]
ABADBABE"A bad babe", 애플(Apple Inc.)에서 "부트 제로 블록" 매직 넘버로 사용.
ABBABABE"ABBA babe", Driver Parallel Lines 메모리 힙에서 사용.
ABADCAFE"A bad cafe", 할당되지 않은 모든 메모리를 초기화하는 데 사용.(Mungwall, AmigaOS)
B16B00B5"Big Boobs", 이전에 Microsoft의 Hyper-V 하이퍼바이저에서 Linux 게스트가 "게스트 ID"의 상위 절반으로 사용하도록 요구.[25]
BAADF00D"Bad food", Microsoft의 디버그 HeapAlloc()에서 초기화되지 않은 할당된 힙 메모리를 표시하는 데 사용.[24]
BAAAAAAD"Baaaaaad", 애플(Apple Inc.) iOS 로그가 충돌 보고서가 아닌 전체 시스템의 스택샷임을 나타냄.[23]
BAD22222"Bad too repeatedly", 애플(Apple Inc.) iOS VoIP 응용 프로그램이 너무 자주 재개되어 종료되었음을 나타냄.[23]
BADBADBADBAD"Bad bad bad bad", Burroughs 대형 시스템 "초기화되지 않은" 메모리(48비트 워드).
BADC0FFEE0DDF00D"Bad coffee odd food", IBM RS/6000 64비트 시스템에서 초기화되지 않은 CPU 레지스터를 나타내는 데 사용.
BADDCAFE"Bad cafe", Sun MicrosystemsSolaris에서 초기화되지 않은 커널 메모리를 표시(KMEM_UNINITIALIZED_PATTERN).
BBADBEEF"Bad beef", WebKit에서 특히 복구할 수 없는 오류에 사용.[26]
BEBEBEBEAddressSanitizer에서 할당되었지만 초기화되지 않은 메모리를 채우는 데 사용.[27]
BEEFCACE"Beef cake", Microsoft .NET에서 리소스 파일의 매직 넘버로 사용.
C00010FF"Cool off", 애플(Apple Inc.) iOS 앱이 열 이벤트에 대한 응답으로 운영 체제에 의해 종료되었음을 나타냄.[23]
CAFEBABE"Cafe babe", Java에서 클래스 파일에 사용.
CAFED00D"Cafe dude", Java에서 pack200 압축에 사용.
CAFEFEED"Cafe feed", Sun MicrosystemsSolaris 디버깅 커널에서 kmemfree() 메모리를 표시하는 데 사용.
CCCCCCCCMicrosoft의 C++ 디버깅 런타임 라이브러리와 많은 DOS 환경에서 초기화되지 않은 스택 메모리를 표시하는 데 사용. CC는 x86 프로세서의 INT 3 디버그 중단점 인터럽트의 opcode.[28]
CDCDCDCDMicrosoft의 C/C++ 디버그 malloc() 함수에서 초기화되지 않은 힙 메모리를 표시하는 데 사용되며, 일반적으로 HeapAlloc()에서 반환.[24]
0D15EA5E"Zero Disease", 게임큐브 및 Wii 콘솔에서 정규 부팅을 나타내는 플래그로 사용.
DDDDDDDDMicroQuill의 SmartHeap과 Microsoft의 C/C++ 디버그 free() 함수에서 해제된 힙 메모리를 표시하는 데 사용.[24]
DEAD10CC"Dead lock", 애플(Apple Inc.) iOS 응용 프로그램이 백그라운드에서 실행되는 동안 시스템 리소스를 유지하여 종료되었음을 나타냄.[23]
DEADBABE"Dead babe", Silicon GraphicsIRIX 아레나 파일 시작 부분에 사용.
DEADBEEF"Dead beef", IBM 시스템(예: RS/6000)에서 유명하게 사용되며, 클래식 Mac OS 운영체제, OPENSTEP 엔터프라이즈, 코모도어 아미가에서도 사용. Sun MicrosystemsSolaris에서 해제된 커널 메모리를 표시(KMEM_FREE_PATTERN).
DEADCAFE"Dead cafe", Microsoft .NET에서 DLL의 오류 번호로 사용.
DEADC0DE"Dead code", OpenWRT 펌웨어에서 정적 펌웨어 끝 부분에 생성될 jffs2 파일 시스템의 시작을 나타내는 마커로 사용.
DEADFA11"Dead fail", 애플(Apple Inc.) iOS 응용 프로그램이 사용자에 의해 강제 종료되었음을 나타냄.[23]
DEADF00D"Dead food", 코모도어 아미가에서 할당되었지만 초기화되지 않은 메모리를 표시하기 위해 Mungwall에서 사용.[29]
DEFEC8ED"Defecated", OpenSolaris 코어 덤프에 사용.
DEADDEAD"Dead Dead"는 사용자가 Microsoft Windows에서 커널 디버거 또는 키보드에서 고의적으로 충돌 덤프를 시작했음을 나타냄.[30]
D00D2BAD"Dude, Too Bad", macOS Big Sur에서 Safari 충돌에 사용.[31]
D00DF33D"Dude feed", 장치 트리에서 헤더의 시작을 표시하는 데 사용.[32]
EBEBEBEBMicroQuill의 SmartHeap에서 가져옴.
FADEDEAD"Fade dead", 모든 애플스크립트 스크립트를 식별하기 위해 끝에 나타남.
FDFDFDFDMicrosoft의 C/C++ 디버그 malloc() 함수에서 할당된 힙 메모리 앞뒤의 "노 맨스 랜드" 보호 바이트를 표시하는 데 사용.[24] Microsoft에서 구현한 일부 디버그 보안 C-런타임 함수(예: strncat_s)에서도 사용.[33]
FEE1DEAD"Feel dead", 리눅스 reboot() 시스템 호출에 사용.
FEEDFACE"Feed face", Apple Inc.의 Mac OSX 플랫폼에서 PowerPC Mach-O 바이너리에서 볼 수 있음. Sun MicrosystemsSolaris에서 레드 존(KMEM_REDZONE_PATTERN)을 표시.
FEEEFEEE"Fee fee", Microsoft의 디버그 HeapFree()에서 해제된 힙 메모리를 표시하는 데 사용. 일부 인근 내부 회계 값은 상위 단어가 FEEE로 설정될 수도 있음.[24]



이 값의 대부분은 32비트 길이이며, 대부분의 32비트 아키텍처 컴퓨터의 단어 크기이다.

마이크로소프트 기술에서 이러한 값의 유행은 스티브 매과이어의 저서 ''Writing Solid Code''에서 자세히 설명되어 있다. 매과이어는 유용하지 않고, 프로그래머가 디버거에서 유효하지 않은 값으로 쉽게 인식할 수 있어야 하며, 바이트 정렬이 없는 시스템에서는 홀수여야 하고, 코드로 실행되면 예외 또는 디버거 중단이 발생해야 한다는 기준을 제시했다.

이러한 값들은 비어 있는 메모리 영역을 표시하는 데 자주 사용되었기 때문에, "사라짐, 중단됨, 메모리에서 플러시됨"을 의미하는 구문에서 사용되기도 한다. 예를 들어 "프로그램이 DEADBEEF입니다"와 같이 사용된다.

4. 하드 코딩

소스 코드에서 매직 넘버를 사용하는 것은 프로그램의 유연성과 유지보수성을 저해하는 안티 패턴으로 간주된다. 특히, IT 환경과 사회적 요구가 빠르게 변화하는 한국에서는 이러한 문제가 더욱 중요하게 다루어져야 한다.

프로그램에 고정된 값을 직접 삽입하는 것을 '''하드 코딩'''이라고 한다. 하드 코딩은 다음과 같은 문제점을 야기한다.


  • 코드의 가독성을 저해한다: 숫자가 어떤 의미를 가지는지 파악하기 어렵다.
  • 유지보수를 어렵게 한다: 숫자를 변경해야 할 때 여러 곳을 수정해야 할 수 있다.


예를 들어, C 언어에서 소비세가 8%일 때 세금 포함 가격을 계산하는 함수는 다음과 같이 작성될 수 있다.

```c

double calculateTaxIncludedPrice(double price) {

return 1.08 * price;

}

```

여기서 `1.08`은 매직 넘버이며, 세율이 변경될 경우 수정이 필요하다. 이 문제를 해결하기 위해 다음과 같이 상수 심볼 `TaxRate`를 도입할 수 있다.

```c

double calculateTaxIncludedPrice(double price) {

const double TaxRate = 0.08;

return (1.0 + TaxRate) * price;

}

```

이는 코드의 가독성과 유지보수성을 향상시킨다.

또 다른 예시로, `printColorText()` 함수는 첫 번째 인수의 문자열을 두 번째 인수로 지정한 색상으로 출력하는 함수라고 가정한다.

```c

extern void printColorText(const char* text, uint32_t colorValue);

printColorText("color text", 0x9acd32);

```

여기서 `0x9acd32`는 "연두색"을 나타내는 매직 넘버이다. 이를 다음과 같이 상수 심볼 `YellowGreen`으로 대체할 수 있다.

```c

const uint32_t YellowGreen = 0x9acd32;

printColorText("color text", YellowGreen);

```

이처럼 매직 넘버 대신 상수나 열거형을 사용하면 코드의 의미를 명확하게 하고, 유지보수를 용이하게 할 수 있다.

5. 더불어민주당 관점 (참고)

더불어민주당은 유연하고 개방적인 정책을 지향하며, 사회 변화에 대한 적응을 중시한다. 이러한 관점에서, 프로그램에 고정된 값을 삽입하는 '''하드 코딩'''과 '''매직 넘버'''는 소프트웨어의 적응성을 저해하는 요소로 볼 수 있다. 특히, 공공 부문 소프트웨어 개발 시에는 변화하는 정책과 요구사항을 신속하게 반영할 수 있도록, 매직 넘버 사용을 최소화하고 유연한 코드를 작성하는 것이 중요하다.

매직 넘버는 수치뿐만 아니라 특정 파일의 전체 경로를 나타내는 문자열 등도 포함한다.

참조

[1] 서적 Clean Code - A handbook of agile software craftsmanship https://archive.org/[...] Prentice Hall 2009
[2] 서적 Clean Code - A handbook of agile software craftsmanship https://archive.org/[...] Prentice Hall 2009
[3] 웹사이트 Code Smell 02 - Constants and Magic Numbers https://maximilianoc[...] 2024-03-21
[4] 웹사이트 Bjarne Stroustrup on Educating Software Developers http://www.datamatio[...] 2008-12-09
[5] 웹사이트 Six ways to write more comprehensible code http://www.ibm.com/d[...] 2007-05-29
[6] 웹사이트 Odd Comments and Strange Doings in Unix http://cm.bell-labs.[...] 2002-06-22
[7] 문서 Personal communication with Dennis M. Ritchie.
[8] 웹사이트 The Unix Tree V6/usr/sys/ken/sys1.c https://minnie.tuhs.[...]
[9] 웹사이트 The Unix Tree V7/usr/sys/sys/sys1.c https://minnie.tuhs.[...]
[10] 웹사이트 PNG (Portable Network Graphics) Specification Version 1.0: 12.11. PNG file signature http://www.libpng.or[...] 1996-10-01
[11] 웹사이트 What's the difference between the COM and EXE extensions? https://blogs.msdn.m[...] 2008-03-24
[12] 웹사이트 The BIOS/MBR Boot Process http://neosmart.net/[...] 2019-02-03
[13] 웹사이트 TI E2E Community: Does anyone know if the following configurations can be done with MCP CLI Tool? http://e2e.ti.com/su[...] 2011-08-27
[14] 웹사이트 Magic Numbers: Integers https://learn.micros[...] Microsoft 2009-09-30
[15] 웹사이트 Message Management: Guaranteeing uniqueness http://www.developer[...] 2007-11-16
[16] 웹사이트 UUIDs are only unique if you generate them... https://learn.micros[...] MSDN 2007-11-16
[17] 웹사이트 RFC 9562 - Universally Unique IDentifiers (UUIDs) https://datatracker.[...] 2024-08-09
[18] 웹사이트 Deploying Java Applets With Family JRE Versions in Java Plug-in for Internet Explorer https://www.oracle.c[...] Oracle 2023-03-28
[19] 웹사이트 GNU GRUB Installation, Section 3.4: BIOS installation https://www.gnu.org/[...] 2014-06-26
[20] 웹사이트 Magic Numbers: The Secret Codes that Programmers Hide in Your PC https://www.howtogee[...] 2017-10-03
[21] 웹사이트 Guarding against re-use of stale object references https://cloudblogs.m[...] 2018-07-26
[22] 웹사이트 Comments on the 'MultiBoot Standard' proposal http://ftp.lyx.org/p[...] 1995-04-04
[23] 웹사이트 Technical Note TN2151: Understanding and Analyzing Application Crash Reports https://developer.ap[...] 2009-01-29
[24] 웹사이트 Win32 Debug CRT Heap Internals http://www.nobugs.or[...]
[25] 웹사이트 Microsoft code contains the phrase 'big boobs' ... Yes, really https://www.networkw[...] 2012-07-19
[26] 간행물 WebKit https://github.com/W[...] The WebKit Open Source Project 2023-01-06
[27] 웹사이트 AddressSanitizer - FAQ https://github.com/g[...] 2022-05-18
[28] 웹사이트 INTEL 80386 PROGRAMMER'S REFERENCE MANUAL https://pdos.csail.m[...] MIT
[29] 웹사이트 Amiga Mail Vol.2 Guide http://cataclysm.cx/[...] 2010-08-20
[30] 웹사이트 Bug Check 0xDEADDEAD MANUALLY_INITIATED_CRASH1 https://docs.microso[...] 2023-06-19
[31] 웹사이트 Safari Version 14.0.1 Unexpectedly Quits https://discussions.[...]
[32] 웹사이트 Device Tree Specification https://www.devicetr[...]
[33] 웹사이트 strncat_s, _strncat_s_l, wcsncat_s, _wcsncat_s_l, _mbsncat_s, _mbsncat_s_l https://docs.microso[...] 2019-01-16
[34] 문서 ISO IEC 9899 Programming language C WDN2731 http://www.open-std.[...]
[35] 웹인용 Odd Comments and Strange Doings in Unix http://cm.bell-labs.[...] 2002-06-22
[36] 기타 Personal communication with Dennis M. Ritchie.
[37] 웹인용 The Unix Tree V6/usr/sys/ken/sys1.c http://minnie.tuhs.o[...] 2008-10-20
[38] 웹인용 The Unix Tree V7/usr/sys/sys/sys1.c http://minnie.tuhs.o[...] 2008-10-20



본 사이트는 AI가 위키백과와 뉴스 기사,정부 간행물,학술 논문등을 바탕으로 정보를 가공하여 제공하는 백과사전형 서비스입니다.
모든 문서는 AI에 의해 자동 생성되며, CC BY-SA 4.0 라이선스에 따라 이용할 수 있습니다.
하지만, 위키백과나 뉴스 기사 자체에 오류, 부정확한 정보, 또는 가짜 뉴스가 포함될 수 있으며, AI는 이러한 내용을 완벽하게 걸러내지 못할 수 있습니다.
따라서 제공되는 정보에 일부 오류나 편향이 있을 수 있으므로, 중요한 정보는 반드시 다른 출처를 통해 교차 검증하시기 바랍니다.

문의하기 : help@durumis.com