내 삶에 의미(부족)를 주기 위해 aarch64 어셈블리로 웹 서버 만들기

개발자 인생이 채워지지 않는 공허함. 프레임워크가 복잡성을 감싸주고, 고수준 언어들이 추상화의 안락한 집을 짓는다. 그 안에서 나는 무엇을 만들고 있을까? 이 질문이 나를 밀어붙였다. 어셈블리어로 웹 서버를 만들자. 그중에서도 현대 인프라의lingua franca가 된 ARM64(AArch64)로. 말 그대로 CPU의lingua franca와 직접 대화하는 것이다.
왜 하필 어셈블리인가
"그냥 다른 언어로 만들면 되잖아"라는 반응이 당연하다. Node.js나 Go는 훨씬 합리적인 선택이다. 그런데 바로 그불합리함 때문에 이 프로젝트에는 의미가 있다. 어셈블리를 직접 짜면 컴퓨터가 어떻게동쿠카 реаль으로 이해하게 된다. TCP 소캣이 커널과 어떻게 데이터를 주고받는지를 syscall만으로 체감하고, HTTP 프로토콜이 어떤 바이트 열로 해석되는지를 직접 코딩하며 배운다.
ymawky라는 프로젝트가 이 길 위의 등불이다. macOS에서 동작하는 순수 ARM64 어셈블리로 쓴 웹 서버로, libc도 없이 syscall만으로 동작한다. 개발자 imtomt는 "웹 서버를 왜 어셈블리로 만드냐"는 질문에 이렇게 대답했다. "내가 컴퓨터를 얼마나 이해하고 있는지 증명하고 싶었기 때문이다."
개발 환경 구축
필수 도구
AArch64 어셈블리로 웹 서버를 만들려면 아래 도구가 필요하다.
• ARM64 머신 또는 크로스컴파일러: Apple Silicon Mac이라면 native로 빌드할 수 있다
• assembler: GNU Assembler(as) 또는 LLVM의 arm64asm
• linker: ld 또는 ld.lld
• debugger(선택): lldb 또는 gdb
macOS에서 nasm 대신 .s 확장자의 GNU 어셈블리 문법을 주로 사용한다. Linux에서는 .s 파일을 as로 어셈블하고 ld로 링크하면 된다.
# macOS ARM Mac에서 어셈블리 컴파일 예시as -o server.o server.sld -o server server.o -lobjc -lsystem
프로젝트 구조
순수 어셈블리로 작성된 웹 서버의 전형적인 구조는 다음과 같다.
┌─────────────────────────────────┐│ main.s ││ (어셈블리어로 작성된 웹 서버) │├─────────────────────────────────┤│ - syscalls.s (시스템콜 래퍼) ││ - http.s (HTTP 파싱) ││ - socket.s (소켓 통신) │└─────────────────────────────────┘
핵심은 세 시스템콜이다. socket()으로 소캣을 생성하고, bind()로 포트를 할당하고, listen()으로 연결을 기다린다. 그리고 accept()로 클라이언트 연결을 수락한 후 read()/write()로 HTTP 요청/응답을 처리한다.
핵심 동작 원리
소켓 생성에서 요청 처리까지
AArch64 어셈블리에서 syscalls는 숫자로 호출된다. macOS ARM64에서상용적 syscall 번호는 다음과 같다.
• socket: 97 (AF_INET = 2, SOCK_STREAM = 1)
• bind: 104
• listen: 106
• accept: 30 (ARM64 macOS)
• read: 3
• write: 4
• exit: 1
ARM64에서는 함수 호출 규약으로 x0~x7 레지스터를 인자 전달에 사용한다. x0에는 syscall 번호, x1~x7에는 인자가 들어간다.
// socket() 시스템콜 예시mov x0, 2 // AF_INETmov x1, 1 // SOCK_STREAMmov x2, 0 // protocolmov x16, 97 // socket syscall numbersvc 0x80 // 시스템콜 실행// 반환값은 x0에 저장 (음수면 에러)
HTTP 요청을 파싱할 때는 읽어들인 바이트에서 \r\n\r\n 시퀀스를 찾으면 헤더의 끝을 알 수 있다. 응답은 간단한 문자열 포맷으로 구성한다.

// HTTP 200 OK 응답 예시 (어셈블리 문자열).ascii "HTTP/1.1 200 OK\r\n".ascii "Content-Type: text/html\r\n".ascii "Content-Length: 13\r\n".ascii "Connection: close\r\n".ascii "\r\n".ascii "Hello, World!"
fork-per-connection 모델
ymawky는 연결마다 fork()를 호출하는 모델을 사용한다. 부모 프로세스는 listen() 상태로 새 연결을 기다리고, 자식 프로세스가 실제 요청을 처리한다.
// accept() 후 fork()mov x16, 2 // fork syscallsvc 0x80cmp x0, 0b.eq child_process // if x0 == 0: child// parent closes client fd, continues listeningmov x0, client_fdmov x16, 6 // closesvc 0x80b accept_loop
ARM64에서 fork()는 매개변수 없이 syscall 번자 2만 전달하면 된다. 반환값으로 0을 받으면 현재 프로세스가 자식이고,푸라스치오받으면 부모이다.
실전 예제: ymawky 구조 분석
GitHub에서 확인할 수 있는 ymawky 프로젝트의 핵심은 3개 파일로구성된다.
1. server.s: 메인 루프 — socket/bind/listen/accept
2. request.s: HTTP 요청 파싱 및 응답 생성
3. fork.s: 프로세스 포크 및 자식 프로세스 핸들링
실제로 돌려보면 아주 단순한 HTTP 응답만 가능하지만, 그 단순함 자체가 교육적이다. 우리가 너무 많은 것을 당연하게 여기는 것을 깨닫게 해준다.
# 빌드 및 실행git clone https://github.com/imtomt/ymawkycd ymawkymake./ymawky 8080# 브라우저에서 http://localhost:8080 접속# "Hello, World!" 확인
대안과의 비교
어셈블리 웹 서버를 실제 프로덕션에 쓰지는 않는다. 그러나 공부용으로는 최고의 선택이다. 다른 언어와 비교하면 다음과 같다.
| 언어 | 장점 | 한계 |
|---|---|---|
| 어셈블리 | 컴퓨터 동작 완전 이해, syscall 직접 호출 | 개발 속도 느림, 이식성 낮음 |
| C | 어셈블리에 가까운 성능, 이식성 양호 | 메모리 관리 직접 해야 함 |
| Go | goroutine으로 동시성 자연 처리, 빠른 개발 | 런타임 의존성 존재 |
| Rust | 메모리 안전성 보장,고성능 | 학습 곡선 가파름 |
어셈블리로 웹 서버를 만들면 다른 언어가 어떤 추상화를 제공하는지 정확히 이해할 수 있다. Go의 http.ListenAndServe가 내부적으로는 똑같은 socket/bind/listen/accept를 호출한다는 사실을 체감하게 된다.
결론: 의미는 만드는 것이다
완벽한 웹 서버가 아니어도 괜찮다. 실제로 동작하는 것만으로도 충분한 만족감이 있다. 어셈블리로 작성한 웹 서버가 채급타적 "의미"가 된다.
"왜 굳이?"라는 질문에는 단 하나로 대답한다. 컴퓨터가 어떻게동쿠카진실으로 알고 싶었기 때문이다. 프레임워크의 추상화에 묻히지 않고, CPU와 메모리와 syscall의 세계로 직접강리테이쿠 때 비로소 개발자는 컴퓨터의lingua franca를 읽는 것이 된다.
ARM64 어셈블리로 웹 서버를 만드는 이 여정은, 의미는 찾는 게 아니라 직접 만드는 것이라는 사실을 보여준다.
📚 출처
• GitHub - imtomt/ymawky: MacOS Web Server written entirely in ARM64 assembly
• Building a Web Server in Pure ARM64 Assembly
• Writing a Webserver in ARM64 Assembly - blog.nkoll.de
• HTTP Server in arm64 assembly Apple silicon M1 - Medium
tags: ARM64, AArch64, Assembly, WebServer, LowLevel, syscall, macOS, developer
📚 출처
'자동화&툴 리뷰' 카테고리의 다른 글
| Mini Shai-Hulud의 귀환: npm 생태계를 강타한 자가 전파형 공급망 공격 (5/11) (0) | 2026.05.14 |
|---|---|
| CodeBurn - AI 코딩 도구 토큰 사용량/비용 추적 TUI 대시보드 완벽 가이드 (0) | 2026.05.11 |
| React 및 Next.js에서 다수의 보안 취약점 공개, 즉시 패치 권고 완벽 가이드 (0) | 2026.05.09 |
| Show GN: Obsidian Vault Terminal — 사이드바에서 Claude Code를 실행하는 올바른 방법 (0) | 2026.05.09 |
| Toprank - SEO 및 광고 관리용 Claude Code 플러그인 완벽 가이드 (0) | 2026.05.08 |