
C언어 extern은 파일이 하나일 때보다 여러 .c 파일로 나누는 순간부터 본격적으로 중요해집니다. 이 글은 extern을 단순 암기 대신 선언과 정의 차이, 헤더 파일 배치, static과의 대비로 설명합니다.

왜 C언어 extern이 필요한가
실제 C 프로젝트는 보통 main.c, counter.c, counter.h처럼 기능별로 나뉩니다. 이때 한 파일의 이름을 다른 파일에서 쓰려면 먼저 그 이름의 타입과 존재를 알려주는 선언이 필요합니다. extern은 바로 그 연결 지점에서 자주 등장합니다.
선언과 정의 차이부터 보기
extern을 이해하려면 declaration과 definition을 먼저 분리해야 합니다. comp.lang.c FAQ도 하나의 전역 이름에는 선언이 여러 번 있을 수 있지만 정의는 정확히 하나여야 한다고 설명합니다.
extern int g_count; /* 선언 */
int g_count = 0; /* 정의 */C언어 extern은 보통 저장 공간을 새로 만드는 줄이 아니라, 다른 곳의 정의를 참조하는 선언으로 읽는 편이 맞습니다.

여러 파일 예제로 extern 보기
/* counter.h */
#ifndef COUNTER_H
#define COUNTER_H
extern int g_count;
void increment(void);
int get_count(void);
#endif/* counter.c */
#include "counter.h"
int g_count = 0;
void increment(void)
{
g_count++;
}
int get_count(void)
{
return g_count;
}/* main.c */
#include <stdio.h>
#include "counter.h"
int main(void)
{
increment();
increment();
printf("count = %d\n", g_count);
printf("get_count() = %d\n", get_count());
return 0;
}핵심은 정의는 한 곳, 공유 선언은 헤더입니다. main.c는 g_count를 새로 만들지 않고, 헤더의 extern int g_count;를 통해 다른 곳의 정의를 참조합니다.
왜 헤더에는 extern 선언만 두는가
헤더 파일은 여러 translation unit에서 함께 include됩니다. 그래서 헤더 안에 int g_count = 0; 같은 정의를 넣으면 include한 파일마다 정의가 생겨 링크 단계에서 중복 정의 문제가 날 수 있습니다. 반대로 extern int g_count;는 선언만 제공하므로 안전합니다.
- 헤더 파일: extern 선언, 함수 프로토타입, 타입 선언
- 소스 파일: 실제 전역 변수 정의, 함수 본체
- 정의가 있는 .c 파일도 같은 헤더를 include해서 선언 불일치를 빨리 잡는 편이 좋다
C언어 extern과 static 차이
extern 감각은 ‘같은 이름을 여러 파일에서 함께 참조하고 싶다’에 가깝고, static 감각은 ‘이 이름을 현재 파일 안에만 숨기고 싶다’에 가깝습니다. C언어 static 변수 글과 이어서 보면 linkage 차이가 더 선명해집니다.
/* counter.c */
static int hidden_count = 0;
int visible_count = 0;hidden_count는 이 파일 안에서만 보이고, visible_count는 다른 파일에서 extern int visible_count;로 참조할 수 있습니다. 쉽게 말해 static은 이름을 파일 안으로 숨기고, extern은 바깥 정의를 참조하게 돕습니다.
자주 하는 오해 4가지
- extern을 붙이면 변수가 만들어진다
- 전역 변수는 모두 헤더에 써 두면 된다
- extern은 static의 단순 반대말이다
- extern을 쓰면 설계가 자동으로 좋아진다
네 가지 모두 조심해야 합니다. extern은 링크 단위에서 이름을 연결하는 장치일 뿐이고, 전역 상태 남용까지 정당화해 주지는 않습니다.
실무에서 바로 쓰는 배치 규칙
- 전역 변수의 실제 정의는 한 곳의 .c 파일에만 둔다
- 다른 파일에서 써야 하면 헤더 파일에 extern 선언을 둔다
- 함수 프로토타입도 보통 헤더 파일에 둔다
- 파일 내부 전용 이름이면 static을 먼저 검토한다
이 기준만 기억해도 undefined reference와 multiple definition 같은 초반 링크 오류를 훨씬 덜 막막하게 볼 수 있습니다. 선언 읽는 감각을 더 잡고 싶다면 C 언어 struct와 typedef 차이, 포인터 한정자까지 연결해서 보고 싶다면 C 언어 const 포인터 정리도 이어서 읽기 좋습니다.
마무리
C언어 extern의 핵심은 어렵지 않습니다. 다만 선언과 정의를 섞어 이해하면 바로 헷갈립니다. 다시 정리하면 extern 선언은 참조, 정의는 실제 저장 공간 제공, 헤더에는 선언, 파일 내부 전용 이름은 static 검토로 기억하면 됩니다.
더 자세한 기준은 cppreference의 extern 문서, storage duration and linkage 문서, 그리고 comp.lang.c FAQ의 declaration vs definition 정리를 참고했습니다.