
700줄로 만든 C 컴파일러가 제게 가르쳐준 것들 (feat. ESP32)
단 700줄의 코드로 작성된 ESP32용 C 컴파일러 Xcc700을 통해 배운 기술의 본질과 복잡성을 걷어내는 미학, 그리고 실무적인 통찰을 공유합니다.
김테크
8년차 개발자

안녕하세요. 풀링포레스트 백엔드 개발자 김테크입니다.
개발자 생활을 8년 정도 하다 보니, 가끔은 거대한 시스템의 복잡도에 질릴 때가 있습니다. MSA 환경에서 수십 개의 마이크로서비스가 얽히고설키고, 배포 한 번 하려면 수 기가바이트짜리 Docker 이미지를 빌드해야 하는 상황 말이죠. "도대체 내가 짠 코드 한 줄이 CPU에 닿기까지 얼마나 많은 추상화 계층을 거치는 걸까?" 하는 회의감이 들 때쯤, 우연히 아주 흥미로운 프로젝트를 발견했습니다. 바로 Xcc700이라는 프로젝트입니다.
이 프로젝트는 이름 그대로 단 700줄의 C 코드로 작성된 ESP32(Xtensa 아키텍처)용 셀프 호스팅 C 컴파일러입니다. 우리가 흔히 쓰는 GCC나 LLVM이 수백만 줄의 코드로 이루어진 괴물이라는 점을 생각하면, 700줄은 정말 말도 안 되게 작은 크기입니다. 솔직히 처음에는 "장난감 수준이겠지"라고 생각했습니다. 하지만 코드를 뜯어보고, 그 동작 원리를 이해하면서 저는 적잖은 충격을 받았습니다. 오늘은 이 작은 컴파일러가 우리 같은 현업 개발자들에게 어떤 통찰을 주는지 이야기해 보려 합니다.
복잡함 걷어내기: 700줄의 미학
우리는 개발 도구를 블랙박스처럼 여길 때가 많습니다. IDE에서 실행 버튼을 누르면 마법처럼 바이너리가 뚝딱 나오니까요. 하지만 Xcc700은 그 마법의 베일을 아주 얇게 벗겨냅니다.
이 컴파일러는 while, if/else, 기본적인 포인터 연산, 함수 호출 등 C 언어의 핵심 기능만 구현했습니다. 구조체(struct)나 실수형(float), 복잡한 최적화 같은 건 과감히 버렸죠. 대신 단일 소스 파일을 읽어 즉시 실행 가능한 ELF 바이너리를 뱉어냅니다. 심지어 ESP32 위에서 자기 자신을 컴파일(Self-hosting)할 수도 있습니다.
저를 놀라게 한 건 이 프로젝트의 철학입니다. 제작자는 README에서 이렇게 묻습니다. "정말 300MB짜리 마우스 드라이버가 필요한가?" 이 질문이 뼈를 때리더군요. 우리는 클라우드 리소스가 풍족하다는 핑계로 비효율적인 코드를 방치하거나, 필요 이상으로 무거운 라이브러리를 가져다 쓰곤 합니다. 700줄만으로도 '동작하는' 컴파일러를 만들 수 있다는 사실은, 우리가 평소에 얼마나 군더더기 많은 개발을 하고 있는지 반성하게 만들었습니다.
제약 사항이 만들어낸 독특한 구조
물론 700줄이라는 제약 때문에 희생한 것도 많습니다. Xcc700은 레지스터 할당(Register Allocation) 같은 최적화를 전혀 수행하지 않습니다. 대신 Xtensa CPU를 마치 스택 머신(Stack Machine)처럼 다룹니다. 모든 연산을 스택에 푸시하고 팝하는 방식으로 처리하죠.
성능 면에서는 당연히 GCC로 컴파일한 바이너리보다 느립니다. 하지만 컴파일 속도 자체는 ESP32-S3 보드 기준으로 초당 17,500라인을 처리할 만큼 빠릅니다. 오류 처리도 매우 낙관적이라서, 문법이 조금만 틀려도 친절한 에러 메시지 대신 장렬하게 크래시가 날 수 있습니다.
하지만 이런 투박함이 오히려 매력적입니다. 코드가 짧으니 전체 구조가 한눈에 들어옵니다. 파서(Parser)가 어떻게 토큰을 읽고, 어떻게 심볼 테이블을 관리하며, 최종적으로 어떻게 기계어 코드를 생성해 ELF 포맷에 채워 넣는지, 그 흐름이 적나라하게 보입니다. 컴파일러 이론 책만 붙들고 있을 때는 막연했던 개념들이, 이 700줄짜리 코드를 보면서 "아, 이렇게 구현하면 되는구나" 하고 머릿속에서 연결되는 경험을 했습니다.
실무에서의 활용 가능성: 엣지 디바이스와 핫패치
풀링포레스트에서도 IoT 센서 데이터를 수집하는 일이 잦습니다. 보통 펌웨어 업데이트는 리스크가 크고 번거로운 작업입니다. 그런데 만약 이런 경량 컴파일러를 디바이스에 내장한다면 어떨까요?
서버에서 전체 펌웨어를 다시 굽는 대신, 아주 작은 C 소스 코드 조각만 네트워크로 전송하고, 디바이스가 그 자리에서 즉시 컴파일해서 메모리에 올리고 실행한다면요? 마치 웹 브라우저가 자바스크립트를 실행하듯, 임베디드 장치에서도 '스크립팅'이 가능해지는 셈입니다. 파이썬 같은 인터프리터를 올리기엔 리소스가 부족한 환경에서, Xcc700 같은 접근 방식은 훌륭한 대안이 될 수 있습니다. 실제로 이 컴파일러는 생성된 코드를 기존 펌웨어의 함수(libc, 커스텀 함수 등)와 동적으로 링크할 수 있는 기능을 제공합니다.
마치며: 두려워 말고 뜯어보세요
주니어 개발자분들과 이야기하다 보면, 컴파일러나 링커 같은 로우 레벨 기술을 막연히 두려워하는 경우를 종종 봅니다. 하지만 Xcc700이 보여주듯, 그 본질은 생각보다 단순합니다. 결국은 데이터를 읽고, 약속된 규칙대로 변환해서, 메모리에 쓰는 과정일 뿐입니다.
혹시 지금 복잡한 프레임워크와 라이브러리 숲에서 길을 잃은 기분이 든다면, 이번 주말에는 이 700줄짜리 코드를 한번 읽어보시는 건 어떨까요? 거창한 도구 없이도 무언가를 바닥부터 만들어내는 '야생의 개발'이 주는 짜릿함을 느끼실 수 있을 겁니다. 기술의 본질을 이해하는 것은, 결국 가장 튼튼한 응용 프로그램을 만드는 지름길이니까요.
오늘도 군더더기 없는 깔끔한 코드를 꿈꾸며, 이상 풀링포레스트 김테크였습니다.


