왜 나는 lazymake를 만들었는가: Make의 UX 문제 해결

발행: (2026년 1월 5일 오전 03:43 GMT+9)
11 min read
원문: Dev.to

Source: Dev.to

새로운 프로젝트의 전형적인 워크플로

  1. Makefile 열기
  2. 500 + 줄이 넘는 난해한 규칙들을 스크롤하기
  3. build, build‑prod, build‑all가 무엇을 하는지 이해하려고 시도하기
  4. 결국 잘못된 타깃을 실행해 무언가를 깨뜨리게 됨
  5. Slack에 작성: “여러분, 스테이징에 배포하려면 어떤 명령을 실행해야 하나요?”

나는 각 프로젝트별로 가장 많이 사용하는 명령들을 별도로 메모해 두게 되었는데, 이는 이상하게 느껴졌다. 왜냐하면 Makefile의 전체 목적은 그 명령들을 중앙집중화하는 것이기 때문이다.

한계점

무언가 바뀌어야 한다고 결심한 순간은 새로운 프로젝트에 합류했을 때였다. 뛰어난 엔지니어인 선배 동료가 간단히 말했다:

“Makefile을 보세요, 거기엔 모든 것이 명확합니다.”

제가 파일을 열었을 때 충격을 받았다:

  • ~600줄의 코드
  • 변수들이 여기저기 존재한다
  • 조건 로직과 중첩된 의존성

수백 줄의 구문을 머릿속으로 파싱하지 않고는 프로젝트를 로컬에서 실행하는 방법을 알 수 없었다. 미친 짓처럼 보였다.

lazygit처럼 Git에 멋진 TUI를 제공하는 도구들을 떠올렸고, Makefile에 비슷한 것이 왜 없는지 궁금했다. 그것이 내 자체 TUI 애플리케이션 아이디어의 불꽃이 되었다.

개발

간단한 아이디어에서 시작했습니다: 대상 목록을 보여주고, 사용자가 하나를 선택하게 하고, 실행하고, 출력을 표시합니다. Bubble Tea 로 만든 매우 기본적인 TUI입니다. 첫 번째 버전은 Go 코드 200–300줄에 불과했지만 이미 작동했습니다.

그 후 저는 수년간 겪어온 불편함을 해결하기 위해 기능을 계속 추가했습니다.

Source:

의존성 그래프

첫 번째 주요 기능은 의존성 그래프였습니다. 이제 대상(target)을 실행해야 할 때 다음을 확인할 수 있습니다:

  • 전체 의존성 트리
  • 실행 순서
  • 임계 경로(전체 실행 시간을 결정하는 가장 느린 체인)
  • 병렬화 기회 – make -j 로 동시에 실행할 수 있는 부분

대상의 어느 곳이든 g 키를 눌러 그래프를 볼 수 있습니다:

Dependency Graph

이 기능만으로도 프로젝트의 가치는 크게 상승했습니다: 이제 Makefile을 추측하지 않고도 대상이 정확히 무엇을 하는지 확인할 수 있습니다. 또한 실수로 들어갈 수 있는 순환 의존성도 잡아냅니다.

변수 검사기

Make의 변수 시스템은 강력하지만 불투명합니다. 다음과 같은 질문들:

  • $(LDFLAGS)는 무엇으로 확장되나요?
  • 어떤 타깃이 $(VERSION)을 사용하나요?

전체 파일을 grep해야 했습니다.

lazymake를 사용하면 v 키를 눌러 모든 변수를 보여주고, 정의와 사용 위치를 표시하는 전체 기능 브라우저를 열 수 있습니다:

Variable Inspector

이전에는 20분이 걸리던 디버깅 세션이 이제는 20초 안에 조회됩니다.

Safety

동료들(저 자신 포함)이 대상이 무엇을 하는지 이해하지 못해 파괴적인 명령을 실수로 실행하는 경우를 자주 보았습니다.
이를 완화하기 위해, lazymake는 위험한 명령을 표시하는 패턴 매칭 안전 시스템을 포함하고 있습니다:

rm -rf /               # CRITICAL – requires confirmation
DROP DATABASE          # CRITICAL – requires confirmation
git push --force       # WARNING – shows alert
terraform destroy      # WARNING – context‑aware

이 시스템은 컨텍스트를 인식합니다. 예를 들어, clean-test-cache라는 대상 안에서 rm -rf를 사용하는 것은 허용되지만, nuke-everything이라는 대상에서 같은 명령을 실행하면 확인 프롬프트가 표시됩니다.

나를 나쁜 결과로부터 구해준 적이 있나요? 네 – 여러 번 있습니다.

Safety Features

TL;DR

  • lazymake는 Makefile 타깃, 의존성 및 변수를 탐색할 수 있는 TUI를 제공합니다.
  • 의존성 그래프를 시각화하고, 중요한 경로를 강조하며, 병렬화를 제안합니다.
  • 변수 인스펙터는 불투명한 변수 시스템을 투명하게 보여줍니다.
  • 내장된 안전 검사로 파괴적인 명령이 실수로 실행되는 것을 방지합니다.

이 모든 것이 방대한 Makefile을 수동으로 검색하던 번거로운 과정을 빠르고 인터랙티브한 경험으로 바꿔줍니다.

하이라이팅

이것은 처음에 제 기능 목록에 없었습니다. 하지만 Makefile은 사실상 어떤 언어든 포함할 수 있습니다 — bash, Python, Go, 무엇이든. 그래서 다중 라인 레시피를 읽기 위해 자동 코드 감지와 하이라이팅을 위해 Chroma를 통합했습니다:

Syntax Highlighting

Shebang, 명령 패턴, 혹은 수동 힌트를 통해 언어를 감지합니다. 복잡한 레시피를 읽는 것이 훨씬 쉬워집니다.

예상하지 못한 점

초기 테스트 중에 몇 가지 기능을 추가했습니다. 예를 들어 성능 추적입니다. 실행 시간을 자동으로 측정하고, 일반 실행 시간보다 > 25 % 느려지면 보고합니다. 이를 통해 여러 회귀를 발견했습니다.

또한 워크스페이스 관리를 추가했습니다. w 키를 눌러 프로젝트 내 모든 Makefile을 볼 수 있습니다. 이는 모노레포에서 유용할 수 있음을 알게 되었습니다.

게다가 실행 기록을 추가했습니다. 최근 5개의 타깃이 먼저 표시됩니다. 제 경험상 대부분의 경우 같은 명령을 반복해서 실행한다는 것을 알게 되었습니다.

어려웠던 점

Makefile 파싱

Makefile은 프로그래밍 언어도 아니고 단순한 설정 파일도 아닙니다. 변수 확장, 패턴 규칙, 조건부 포함 — 이 모든 것이 꽤 복잡합니다.

처음에는 Make 자체를 사용하려고 생각했습니다:

make -pn | grep "^[a-zA-Z].*:"

하지만 Makefile에서 주석, 의존성 등도 추출해야 했습니다. 그래서 직접 파서를 작성했습니다. 물론 완벽하진 않지만 제 역할은 하는 것 같습니다.

실시간 출력

Bubble Tea 덕분에 TUI에서 명령어의 스트리밍 출력을 얻을 수 있었습니다.

크로스‑플랫폼 지원

macOS, Linux, Bash, Zsh 등에서 애플리케이션이 잘 동작하도록 만들기가 꽤 어려웠습니다. 터미널 기능이 크게 다르거든요. 솔직히 아직 모든 환경에서 완벽히 동작한다는 확신은 없지만, 대체로 잘 작동하는 것 같습니다. :)

Try It Yourself

# macOS/Linux
brew install rshelekhov/tap/lazymake

# Or via Go
go install github.com/rshelekhov/lazymake/cmd/lazymake@latest

# Then simply:
lazymake

어떤 Makefile에서도 작동하며, 설정 없이도 실행됩니다(하지만 필요에 따라 프로그램을 구성할 수 있는 기능을 추가했습니다).

프로젝트를 더 발전시키고 싶지만, 이를 위해서는 사용자가 무엇을 필요로 하는지 이해해야 합니다. 프로젝트에 관심이 있고 사용을 시작하려는 생각이 있다면, Makefile을 사용할 때 가장 큰 불편함은 무엇인가요? 라는 질문에 답변을 주세요.

GitHub | Documentation

유용하다고 생각되면 저장소에 ⭐를 눌러주시고 의견을 알려 주세요. 피드백(또는 불만)도 언제든 환영합니다—그것도 큰 도움이 됩니다.

Back to Blog

관련 글

더 보기 »

Lyra: 명령줄 어시스턴트

나는 어시스턴트의 골격과 메인 루프를 코딩했다. 음성이나 AI 어시스턴트보다 CLI 어시스턴트를 선택한 이유는 하드웨어 제한 때문이다. 나는…