
C 언어 struct와 typedef 차이는 문법 한 줄보다 선언을 어떻게 읽을지의 문제에 더 가깝습니다. 실전에서는 struct tag가 무엇이고 typedef alias가 무엇인지, 그리고 함수 인자와 포인터 선언에서 왜 더 빨리 읽히는지를 구분하면 헷갈림이 크게 줄어듭니다.
이번 글에서는 struct Person과 Person이 어떻게 다른지, typedef struct Node Node; 패턴이 왜 자주 보이는지, 그리고 언제는 오히려 typedef가 독이 되는지까지 쉬운 예시로 정리하겠습니다.
C 언어 struct와 typedef 차이: 먼저 한 줄로 정리
- struct는 구조체 타입을 정의한다
- typedef는 기존 타입에 다른 이름을 붙인다
- 둘은 경쟁 관계가 아니라 역할이 다른 도구다
struct Person {
char name[20];
int age;
};
struct Person a;
typedef struct Person Person;
Person b;핵심은 메모리 구조가 바뀌는 것이 아니라 선언을 읽는 표면 문법이 바뀐다는 점입니다. struct Person a;와 Person b;는 같은 구조체 타입을 가리키되, 두 번째가 더 짧고 빠르게 읽힙니다.
왜 typedef를 붙이면 선언이 더 읽기 쉬울까
초보자가 자주 멈추는 이유는 struct가 반복되기 때문입니다. 타입의 핵심은 Person인데, 눈은 매번 struct를 한 번 더 통과해야 합니다.
struct Person user;
struct Person *ptr;
void print_person(const struct Person *p);typedef struct Person Person;
Person user;
Person *ptr;
void print_person(const Person *p);특히 함수 인자에서 차이가 큽니다. const struct Person *p보다 const Person *p가 더 빨리 읽히는 이유는, 핵심 타입 이름이 먼저 보이고 나머지 장식이 뒤따르기 때문입니다.
typedef의 실전 가치는 구조를 바꾸는 데 있지 않고, 선언에서 핵심 타입을 더 빨리 보이게 만드는 데 있습니다.
struct tag와 typedef alias는 서로 다른 역할이다
struct Person {
char name[20];
int age;
};
typedef struct Person Person;
struct Person a;
Person b;- struct Person은 tag 이름을 struct와 함께 쓰는 방식
- Person은 typedef alias를 ordinary identifier처럼 쓰는 방식
- typedef는 새 타입을 만드는 것이 아니라 같은 타입의 별칭을 하나 더 만든다
겉보기에는 같은 철자라도, C에서는 tag 이름과 typedef 이름을 보는 위치가 다릅니다. 그래서 struct Person과 Person이 둘 다 성립할 수 있습니다.
연결 리스트 예제에서 typedef struct Node Node가 자주 보이는 이유
self-reference가 필요한 구조체에서는 이 패턴이 아주 실용적입니다. 연결 리스트나 트리 노드가 대표적입니다.
typedef struct Node Node;
struct Node {
int value;
Node *next;
};이렇게 쓰면 구조체 본문 안에서 Node *next;처럼 간단하게 적을 수 있습니다. typedef가 없으면 같은 자리에 struct Node *next;를 계속 써야 합니다.
struct Node {
int value;
struct Node *next;
};둘 다 맞는 코드입니다. 다만 멤버가 많아지고 함수 선언까지 늘어나면 alias가 있는 쪽이 더 빠르게 읽힙니다.
익명 struct typedef가 항상 더 좋은 선택은 아니다
typedef struct {
int x;
int y;
} Point;이 패턴은 좌표처럼 단순한 데이터 묶음에는 깔끔합니다. Point p;라고 바로 쓸 수 있어서 선언이 짧아집니다.
하지만 tag가 없다는 점은 기억해야 합니다. 자기 자신을 가리켜야 하는 구조체라면 이 방식이 바로 통하지 않습니다.
typedef struct {
int value;
Node *next;
} Node; // 오류구조체 본문을 읽는 시점에는 아직 Node typedef가 만들어지지 않았기 때문입니다. self-reference가 필요하면 보통 tag를 두고 typedef를 붙이는 방식이 더 자연스럽습니다.
함수 인자와 포인터 선언에서 헷갈림이 줄어드는 지점
int compare_person(const struct Person *a,
const struct Person *b);
void update_person(struct Person *p, int age);typedef struct Person Person;
int compare_person(const Person *a, const Person *b);
void update_person(Person *p, int age);- 먼저 타입이 보인다
- 그다음 포인터인지 읽힌다
- 마지막에 변수 이름을 확인하면 된다
이 순서가 만들어지면 선언이 문법 문제보다 의미 문제로 읽히기 시작합니다. 그래서 typedef는 함수 원형이 길어질수록 체감 효과가 큽니다.
typedef가 오히려 독이 되는 경우도 있다
typedef가 항상 가독성을 높이는 것은 아닙니다. 특히 포인터 타입 자체를 숨기면 초보자가 별표 위치를 놓치기 쉽습니다.
typedef Person *PersonPtr;
PersonPtr a, b; // 둘 다 포인터typedef char *String;
const String s; // char * const 에 가깝게 해석이런 예시는 typedef는 구조체 이름을 짧게 하는 데는 유용하지만, 포인터 자체를 감추는 데까지 가면 오히려 더 헷갈릴 수 있다는 점을 보여줍니다.
자주 하는 오해
- typedef를 쓰면 새로운 구조체 타입이 하나 더 생긴다
- struct와 typedef는 둘 중 하나만 써야 한다
- typedef struct { … } Name;이 언제나 더 modern하다
- struct Node와 Node는 완전히 다른 타입이다
- typedef는 언제나 가독성을 높인다
정확한 기준은 단순합니다. struct는 타입 정의, typedef는 별칭, 그리고 typedef의 실전 장점은 선언 가독성입니다.
실무에서는 이렇게 선택하면 무난하다
- 여러 곳에서 반복해서 쓰는 구조체라면 typedef struct Name Name; 패턴이 편하다
- self-reference가 필요 없는 단순 구조체는 익명 struct typedef도 괜찮다
- 연결 리스트나 트리처럼 자기 자신을 가리켜야 하면 tag를 두는 편이 안전하다
- 포인터 typedef는 남용하지 않는 편이 좋다
포인터 감각을 같이 정리하고 싶다면 C 언어 포인터와 배열 차이 글을, 동적 메모리까지 이어서 보고 싶다면 C 언어 malloc free 사용법 글을 함께 보면 흐름이 더 잘 이어집니다.
개념 기준은 cppreference struct 문서와 typedef 문서를 참고했습니다.
정리
C 언어 struct typedef 차이의 핵심은 둘이 같은 일을 하느냐가 아닙니다. struct는 구조체를 정의하고, typedef는 그 타입 이름을 사람이 읽기 쉬운 형태로 꺼내 쓰게 도와줍니다.
그래서 typedef를 붙인다고 구조가 달라지지는 않습니다. 대신 Person user, const Person *p, Node *next처럼 선언을 읽는 순서가 정리됩니다.
가장 좋은 기준은 구조를 바꾸려는가가 아니라, 선언을 덜 헷갈리게 만들려는가를 먼저 보는 것입니다. 이 기준만 잡히면 struct와 typedef를 훨씬 자연스럽게 선택할 수 있습니다.