---
title: "왜 아직도 Lisp를 배워볼 만한가"
published: 2026-07-09T13:06:04.000Z
canonical: https://jeff.news/article/4951
---
# 왜 아직도 Lisp를 배워볼 만한가

Lisp는 괄호가 많은 이상한 언어처럼 보이지만, 핵심은 문법이 아니라 언어 자체를 확장할 수 있다는 점에 있음. 매크로, 코드-데이터 동일성, REPL 중심 개발이 합쳐지면 프로그램을 '작성'한다기보다 살아 있는 시스템을 계속 진화시키는 방식으로 개발하게 됨.

## Lisp가 이상해 보이는 건 맞는데, 이상한 데 이유가 있음

- Lisp 코드를 처음 보면 대부분 반응은 비슷함. 괄호가 너무 많고, 들여쓰기도 낯설고, `format`에 왜 첫 인자로 출력 대상을 넘기는지부터 머리가 멈춤
  - 글쓴이도 처음엔 똑같이 당황했고, 그 다음엔 패키지, 심볼, 프로젝트 생성, 라이브러리 import, REPL, condition, restart 같은 Lisp식 생태계를 다시 배워야 했다고 함
  - 진짜 허들은 문법보다 사고방식임. 알고리즘을 짤 때 언어가 제공하는 문법 안에서만 생각하는 게 아니라, 문제에 맞게 언어를 키워나가는 쪽으로 머리가 바뀜

- 글의 핵심 주장은 단순함. Lisp를 배우면 다른 언어가 못 보여주는 종류의 힘을 보게 된다는 것
  - Paul Graham의 'Blub paradox'가 여기서 등장함. 덜 강력한 언어만 써본 사람은 더 강력한 언어가 제공하는 개념 자체를 못 알아볼 수 있다는 얘기
  - 그래서 Lisp의 장점은 설명만으로는 잘 안 꽂힘. 재즈를 물어보면 이미 늦었다는 Louis Armstrong식 농담처럼, 직접 써봐야 감각이 온다는 쪽

> [!IMPORTANT]
> 이 글에서 말하는 Lisp의 강점은 '괄호 문법이 취향에 맞냐'가 아니라, 언어 자체를 문제에 맞게 바꿀 수 있느냐에 있음.

## 매크로는 보일러플레이트 제거기가 아니라 언어 확장 장치임

- Lisp에서 가장 센 카드로 소개되는 건 매크로임. 그런데 여기서 말하는 매크로는 C, Rust, Swift의 매크로와 결이 다름
  - 다른 언어의 매크로가 주로 반복 코드 생성이나 보일러플레이트 제거에 가까운 반면, Lisp 매크로는 새 언어 구성요소를 만드는 도구에 가까움
  - 예를 들어 Common Lisp에 C 스타일 `while` 연산자가 없어도, 개발자가 직접 매크로로 `while`을 만들어 언어에 붙일 수 있음

- 왜 함수로는 안 되고 매크로여야 하냐가 이 글의 중요한 설명 포인트임
  - 함수는 인자를 호출 전에 평가함. 그래서 `fake-while` 같은 함수를 만들면 조건식과 본문이 먼저 실행되어 버리고, 본문 자리에 코드 블록이 아니라 값이 들어감
  - 글의 예시에서는 `(print counter)`와 `(decf counter)`가 먼저 평가되어 body가 `2`가 되고, 결국 `(funcall 2)`를 실행하려다 `2는 함수가 아니다`라는 에러가 남
  - 반면 매크로는 인자를 미리 평가하지 않고 코드 조각 그대로 받음. 그래서 조건과 본문을 원하는 형태로 감싸서 컴파일러가 실행할 코드로 확장할 수 있음

- Lisp에서는 매크로 확장 결과를 REPL에서 직접 확인할 수 있음
  - `macroexpand`로 매크로가 어떤 코드로 바뀌는지 볼 수 있고, 컴파일러가 실제로 받는 코드도 확인 가능함
  - 이게 중요한 이유는 매크로가 마법처럼 숨겨진 기능이 아니라, 코드 변환을 명시적으로 다룰 수 있는 도구라는 점 때문임

## 리스트가 끝까지 간다

- Lisp의 이름 자체가 `LISt Processing`에서 왔고, 이 글은 그 이름이 그냥 역사적 농담이 아니라고 설명함
  - Lisp 프로그램은 symbolic expression, 줄여서 s-expression의 연속으로 구성됨
  - s-expression은 원자(atom)이거나 리스트임. 숫자, 문자열, 심볼 같은 값도 있고, 그 값들을 담은 리스트도 있음

- Lisp의 독특한 힘은 코드와 데이터가 같은 재료로 만들어진다는 데서 나옴
  - `( + 1 2 )` 같은 리스트는 평가되면 `+` 심볼이 함수로 해석되어 3을 만듦
  - 그런데 앞에 quote를 붙이면 같은 리스트가 실행되지 않고 데이터로 남음
  - 이 성질을 동형성(homoiconicity)이라고 부름. 코드도 리스트고 데이터도 리스트라서, 코드를 데이터처럼 조작할 수 있음

- 이 구조 때문에 Lisp 매크로는 단순 치환보다 훨씬 강함
  - 코드가 리스트라면 리스트를 바꾸는 방식으로 소스코드를 바꿀 수 있음
  - 결과적으로 '프로그램을 쓰는 프로그램'을 자연스럽게 만들 수 있고, 다른 언어들이 수십 년 동안 흉내 내려 한 능력이 여기서 나옴

## REPL은 콘솔이 아니라 살아 있는 프로그램의 창임

- Lisp 개발자는 보통 에디터에서 파일만 열고 시작하지 않음. 먼저 Lisp 프로세스를 띄우고, REPL에 붙이고, 그 프로세스 안으로 프로젝트를 로드함
  - REPL은 Read-Eval-Print Loop의 약자고, 코드를 읽고 평가하고 결과를 출력하는 인터랙티브 환경임
  - 중요한 건 이 REPL이 현재 실행 중인 Lisp 프로세스와 연결되어 있다는 점임

- 일반적인 개발 흐름은 작성, 컴파일, 실행, 디버깅의 반복임. Lisp는 이 흐름이 꽤 다름
  - 실행 중인 프로세스에 함수를 평가해 넣고, 바로 결과를 보고, 필요하면 다시 정의함
  - 함수 하나만 따로 테스트할 수도 있고, 데이터베이스 쿼리, 변수 검사, 디버깅 같은 작업도 같은 환경에서 바로 할 수 있음
  - Lisp 프로세스는 며칠에서 몇 주 동안 계속 살아 있을 수 있고, 그 안에서 함수, 매크로, 변수가 계속 재정의됨

- 글쓴이는 이걸 현대 프론트엔드의 핫 리로딩과 비교함
  - 웹 프론트엔드는 파일 저장만 해도 번들러가 변경된 모듈을 다시 컴파일하고, 웹소켓으로 페이지에 변경분을 주입함
  - 하지만 Lisp에서는 핫 리로딩이 별도 도구가 아니라 코드 평가의 기본 결과에 가까움
  - 심볼을 다시 정의하면 함수든 데이터든 매크로든 실행 중인 시스템이 새 정의를 집어듦

> [!NOTE]
> 글쓴이는 Lisp 개발을 '프로그램을 건설하는 것'보다 '프로그램을 진화시키는 것'에 가깝다고 표현함. 새 프로세스에 코드가 평가되어 들어가는 순간, 그 살아 있는 시스템 자체가 프로그램이 된다는 얘기임.

## 확장 가능한 소프트웨어를 만들 때 Lisp가 빛남

- 글은 Lisp의 언어 확장성과 라이브 시스템이 합쳐지면, 확장 가능한 소프트웨어를 만들기 쉬워진다고 봄
  - 보통 데스크톱 앱은 플러그인 시스템이나 스크립팅 언어로 확장성을 제공함
  - 문제는 개발자가 별도 확장 시스템을 설계하고 유지해야 하고, 사용자는 또 그 API나 스크립트 문법을 배워야 한다는 점임

- Lisp에서는 내부 DSL을 만들고, 필요하면 그걸 사용자에게 노출하는 방식이 자연스러움
  - 글쓴이는 클라이언트 웹사이트용 CMS 서버에서 서버 사이드 웹페이지를 생성하는 매크로를 만들었다고 함
  - 이 DSL을 사용자에게 열어주면, 사용자는 별도 템플릿 언어의 `{{ user_name }}`나 `{% for %}` 같은 문법을 배우는 대신 Lisp 표현식 안에서 변수, 반복, 문자열 포맷을 그대로 쓸 수 있음
  - 템플릿도 Lisp 코드라서 조건문, 재귀, 고차 함수, REPL 디버깅까지 그대로 따라옴

- 수학 소프트웨어 예시도 나옴. 사용자가 수식을 쓰면 Cartesian graph에 렌더링하는 프로그램에서, 수학과 드로잉을 위한 작은 DSL을 만들었다는 얘기
  - 사용자는 복잡한 렌더링 코드를 몰라도 짧은 코드로 곡선을 그릴 수 있음
  - Lisp이기 때문에 변수, 헬퍼 함수, 루프를 써서 여러 곡선을 생성하는 것도 가능함

- 실제 역사적 사례로는 AutoCAD와 Emacs가 나옴
  - AutoCAD는 AutoLISP로 반복 작업 자동화와 복잡한 기하 구조 생성을 지원해왔음
  - Emacs는 자체 Lisp 방언으로 대부분이 구현되어 있고, PDF 리더, 웹 브라우저, 이메일 클라이언트, RSS 리더, 터미널 멀티플렉서, Git 클라이언트, 음악 플레이어, 채팅 클라이언트, 스프레드시트, IRC 클라이언트, 윈도 매니저까지 확장된 사례로 소개됨

## 그래서 Lisp의 시대는 왔냐면, 안 왔고 아마 안 올 가능성이 큼

- 글은 Lisp 찬양으로만 끝나지 않음. 언젠가 Lisp의 시대가 와서 대학에서 널리 가르치고, 회사들이 Lisp 개발자를 쉽게 뽑고, 모두가 REPL 기반 개발을 하게 될 거라는 기대는 결국 실현되지 않았다고 선을 그음
  - Lisp는 1960년대부터 살아남았고, Fortran 다음으로 오래된 현역 언어 중 하나임
  - 수많은 언어가 Lisp에서 영감을 받았지만, Lisp의 핵심 조합을 그대로 대중화한 언어는 많지 않음

- 결론은 'Lisp를 실무 기본 언어로 쓰자'가 아니라 'Lisp를 배우면 프로그래밍 언어의 가능 범위를 다시 보게 된다'에 가까움
  - 매크로, REPL, 인터랙티브 환경, 확장 가능한 소프트웨어 모델 중 하나만 떼어서는 Lisp를 설명하기 어렵다는 게 글의 입장임
  - 이 기능들이 한데 묶였을 때 Lisp다운 개발 경험이 만들어짐
  - 그래서 Lisp를 안 쓰게 되더라도, 한 번 배워두면 다른 언어를 볼 때 '여기엔 뭐가 빠져 있지?'라는 질문을 하게 됨

---

## 기술 맥락

- Lisp가 매크로를 중요하게 보는 이유는 단순히 코드를 짧게 만들기 위해서가 아니에요. 함수 호출 전에 인자가 평가되는 일반 언어 모델로는 새 제어 구조를 만들기 어렵기 때문에, Lisp는 코드를 데이터로 받아 변환하는 쪽을 언어의 핵심 능력으로 둔 거예요.

- REPL 중심 개발이 강한 이유는 피드백 루프가 파일 단위가 아니라 실행 중인 프로세스 단위로 줄어들기 때문이에요. 서버를 다시 띄우고 전체 앱을 재시작하는 대신, 함수 하나를 바꿔서 살아 있는 환경에 바로 밀어 넣을 수 있으니 탐색과 디버깅 방식이 달라져요.

- DSL 이야기가 중요한 이유는 확장성을 플러그인 API로 따로 설계하지 않아도 된다는 점이에요. 내부에서 문제를 풀려고 만든 매크로와 표현식을 사용자에게 제한적으로 열어주면, 사용자는 별도 템플릿 언어나 스크립트 런타임을 배우지 않고도 같은 언어의 힘을 일부 가져갈 수 있어요.

- 다만 이 선택에는 비용도 있어요. 매크로와 동형성은 강력하지만, 팀 전체가 코드 확장 방식을 이해하지 못하면 추상화가 너무 멀리 가기 쉬워요. 글이 Lisp를 '쉽다'고 말하지 않고 '가파른 학습 곡선이 있다'고 인정하는 이유도 여기 있어요.

## 핵심 포인트

- Lisp 매크로는 반복 코드 생성 수준이 아니라 언어에 새 구문을 추가하는 도구에 가까움
- 코드와 데이터가 모두 리스트로 표현되는 동형성 덕분에 프로그램이 프로그램을 다룰 수 있음
- REPL 중심 개발은 핫 리로딩을 별도 도구가 아니라 언어의 기본 작업 방식으로 만든다는 게 포인트
- AutoCAD의 AutoLISP와 Emacs 사례처럼 Lisp는 확장 가능한 소프트웨어를 만들 때 특히 강함

## 인사이트

이 글의 재미는 'Lisp가 제일 세다'는 오래된 떡밥을 문법 취향 문제가 아니라 개발 워크플로와 확장성 문제로 다시 설명한다는 데 있음. 당장 실무 언어를 갈아타자는 얘기보다는, 언어가 문제에 맞춰 변할 수 있다는 감각을 배워두면 다른 스택을 볼 때도 눈이 달라진다는 쪽에 가깝다.
