처리중입니다. 잠시만 기다려주세요.
TTJ 코딩클래스
정규반 단과 자료실 테크 뉴스 코딩 퀴즈
테크 뉴스
Hacker News 2026.05.21 65

SBCL을 어셈블리 실험용 브레드보드처럼 쓰는 법: Lisp가 보여주는 저수준 코드의 우아함

Hacker News 원문 보기
SBCL을 어셈블리 실험용 브레드보드처럼 쓰는 법: Lisp가 보여주는 저수준 코드의 우아함

어셈블리를 빠르게 실험해보고 싶을 때, 우리는 보통 어떻게 하나요?

C로 짧은 함수를 짜고, gcc -S로 어셈블리를 뽑고, 마음에 안 들면 __asm__ 인라인으로 직접 명령어를 박아 넣어 보고, 다시 컴파일하고… 이 과정을 한 번이라도 해봤다면 얼마나 번거로운지 아실 거예요. 매번 컴파일러를 통과시키고, 링커를 거치고, 결과 바이너리를 실행해서 동작을 확인해야 하니까요. 특히 "이 명령어 두 개의 순서를 바꾸면 어떻게 될까?" 같은 아주 작은 실험을 하나하나 돌려보는 건 정말 시간 낭비처럼 느껴지죠.

이번에 다시 회자되고 있는 2014년 Paul Khuong의 글은 이런 답답함을 완전히 다른 각도에서 풀어낸 이야기예요. 글쓴이는 SBCL(Steel Bank Common Lisp)이라는 Common Lisp 처리기를 마치 전자공학의 "브레드보드"처럼 쓴다고 말하거든요. 브레드보드가 뭐냐면, 전자회로를 납땜 없이 핀만 꽂아서 즉석에서 실험해보는 보드예요. 무언가를 빠르게 시도하고, 안 되면 바로 바꿔보는 도구죠. SBCL을 어셈블리 실험에 그렇게 쓸 수 있다는 게 이 글의 핵심이에요.

SBCL이 어셈블리 실험에 왜 이렇게 잘 어울리는가

Common Lisp는 표준 자체가 "이미지 기반 개발"을 전제로 합니다. 이게 뭐냐면, 프로그램을 한 번 띄워놓고 그 안에서 함수를 새로 정의하고, 컴파일하고, 바로 호출하면서 계속 살아 있는 채로 코드를 키워나가는 방식이에요. 우리가 익숙한 "파일 저장 → 컴파일 → 실행" 사이클이 아니라, 마치 살아 있는 생물처럼 프로그램이 계속 진화하는 거죠.

SBCL은 여기에 더해서 네이티브 코드 컴파일러를 내장하고 있어요. 보통의 Lisp 인터프리터처럼 한 줄 한 줄 해석하는 게 아니라, 함수 하나를 정의하는 순간 그 자리에서 x86-64 기계어로 컴파일해버립니다. 그리고 결정적으로, SBCL은 컴파일러 내부의 VOP(Virtual Operation)이라는 인터페이스를 외부에 열어놨어요. VOP이 뭐냐면 컴파일러가 코드 생성을 할 때 쓰는 "중간 명령어 단위" 같은 건데, 이 안에서 사용자가 어셈블리 명령어를 직접 적어 넣을 수 있게 해줍니다.

예를 들어 define-vop이라는 매크로로 새 연산을 정의하면서 inst movq, inst addq 같은 식으로 x86-64 명령어를 한 줄씩 써내려갈 수 있어요. 이렇게 만든 VOP을 일반 Lisp 함수에서 호출하면, 그 함수는 컴파일될 때 우리가 적어둔 어셈블리를 그대로 끼워서 기계어를 뽑아냅니다. 그러면 REPL(대화형 프롬프트)에서 (my-asm-function 42)처럼 바로 호출해서 결과를 볼 수 있고, 마음에 안 들면 명령어 한 줄 고치고 다시 컴파일해서 또 호출해보면 되는 거예요. 컴파일 사이클이 거의 즉시 끝나니까, 어셈블리 명령어 하나하나의 동작을 "전등 스위치 켜고 끄듯" 실험할 수 있게 되는 거죠.

디스어셈블러까지 내장되어 있다

SBCL이 특히 매력적인 건 (disassemble #'my-fn)이라는 함수 하나로 방금 정의한 Lisp 함수의 기계어를 깔끔하게 어셈블리로 풀어서 보여준다는 점이에요. 우리가 적은 VOP이 실제로 어떤 명령어 시퀀스로 변환됐는지, 어디에 패딩이 들어갔는지, 레지스터 할당은 어떻게 됐는지를 그 자리에서 확인할 수 있어요.

다른 언어에서 이걸 하려면 보통 objdumpgdb 같은 외부 도구를 켜야 하고, 심볼이 잘 안 풀려서 한참 헤매기도 합니다. 그런데 SBCL은 처리기 안에 디스어셈블러가 들어 있으니까, "함수 정의 → 컴파일 → 디스어셈블 → 수정"이 모두 같은 프롬프트 안에서 끝나요. 이 흐름의 차이가 생각보다 큽니다. 새로운 SIMD 명령어를 한 번 써보고 싶다든지, 캐시 라인 정렬에 따라 성능이 어떻게 바뀌는지 마이크로벤치마크를 돌려보고 싶을 때, 실험의 마찰이 거의 0에 가까워지거든요.

다른 도구들과 비교해보면

비슷한 목적의 도구로 요즘 가장 유명한 건 Compiler Explorer, 흔히 "godbolt"라고 부르는 웹사이트예요. C/C++/Rust 같은 코드를 적으면 옆 창에 컴파일된 어셈블리가 나오죠. 정말 훌륭한 도구지만 결국은 "코드 → 어셈블리 보기"라는 한 방향 흐름이에요. 어셈블리를 직접 짜서 바로 실행해보는 인터랙티브한 작업은 어렵습니다.

Rust나 C에서 인라인 어셈블리를 쓰는 방법도 있지만, 매번 cargo build 한 번씩 도는 시간이 누적되면 실험의 리듬이 깨져요. NASM이나 YASM으로 순수 어셈블리 파일을 짜는 것도 가능하지만, 그러면 OS 호출 규약이나 스택 정렬 같은 부수적인 것들을 전부 신경 써야 하고요. SBCL 방식의 강점은 호스트 언어가 알아서 호출 규약과 GC, 메모리 할당을 다 처리해주는 상태에서, 내가 보고 싶은 명령어 시퀀스만 콕 집어서 실험할 수 있다는 데 있어요. 마치 회로 전체를 직접 만들지 않고, 브레드보드에 이미 깔린 전원과 그라운드 위에 부품 몇 개만 꽂아서 동작을 확인하는 것과 같은 셈이죠.

한국 개발자에게는 어떤 의미가 있을까

Lisp가 한국 실무에서 자주 쓰이는 언어는 아니에요. 그래서 "SBCL을 당장 도입하세요"라고 말하기는 어렵습니다. 다만 이 글이 우리에게 던지는 진짜 메시지는 도구 이름이 아니라 "실험의 마찰을 어떻게 줄일 것인가"라는 질문이에요. 성능 튜닝을 하든, 새로운 명령어 집합을 익히든, 핫스팟의 어셈블리를 한 줄씩 다듬든, 결국 우리는 "바꾸고 → 확인하고 → 다시 바꾸는" 사이클을 얼마나 빠르게 돌릴 수 있느냐로 생산성이 결정되거든요.

저수준 코드를 다루는 분이라면 godbolt를 즐겨찾기에 두는 것 외에, 자신이 쓰는 언어에서 비슷한 "즉시 실행 가능한 어셈블리 환경"을 만들 수 있는지 한번 살펴볼 만해요. 예를 들어 Python에서는 ctypesmmap으로 직접 기계어 바이트를 메모리에 올려서 호출하는 트릭이 있고, Julia는 @code_native 매크로로 함수를 즉시 어셈블리로 풀어볼 수 있죠. 도구는 달라도 본질은 같아요. 컴파일러와 디스어셈블러가 한 프롬프트 안에 같이 있어야 어셈블리 학습 곡선이 부드러워진다는 거예요.

마무리

SBCL이 어셈블리 브레드보드로 쓰인다는 이야기는 단순한 트리비아가 아니라, 도구가 사고의 속도를 어떻게 바꾸는지 보여주는 좋은 사례예요. 컴파일 사이클이 1초가 안 되면, 우리는 "이거 한번 해볼까?"라는 질문을 100배 더 많이 던지게 되거든요.

여러분은 저수준 코드를 실험할 때 어떤 도구를 쓰시나요? godbolt 같은 웹 도구로 충분하다고 느끼시는지, 아니면 더 인터랙티브한 환경이 있었으면 좋겠다고 느끼신 적이 있는지 댓글에서 이야기 나눠봐요.


🔗 출처: Hacker News

이 뉴스가 유용했나요?

이 기술을 직접 배워보세요

파이썬으로 자동화를 시작해보세요

파이썬 기초부터 자동화까지 실전 강의.

파이썬 강의 보기

"비전공 직장인인데 반년 만에 수익 파이프라인을 여러 개 만들었습니다"

실제 수강생 후기
  • 비전공자도 6개월이면 첫 수익
  • 20년 경력 개발자 직강
  • 자동화 프로그램 + 소스코드 제공

매일 AI·개발 뉴스를 받아보세요

주요 테크 뉴스를 매일 아침 이메일로 전해드립니다.

스팸 없이, 언제든 구독 취소 가능합니다.