# BusyBox란 무엇인가?

> Clean Markdown view of GeekNews topic #29463. Use the original source for factual precision when an external source URL is present.

## Metadata

- GeekNews HTML: [https://news.hada.io/topic?id=29463](https://news.hada.io/topic?id=29463)
- GeekNews Markdown: [https://news.hada.io/topic/29463.md](https://news.hada.io/topic/29463.md)
- Type: GN+
- Author: [neo](https://news.hada.io/@neo)
- Published: 2026-05-13T16:02:51+09:00
- Updated: 2026-05-13T16:02:51+09:00
- Original source: [specular.fi](https://specular.fi/post/what-is-busybox)
- Points: 1
- Comments: 2

## Topic Body

- **BusyBox**는 여러 명령을 하나의 실행 파일에서 제공하는 **멀티콜 바이너리**로, Alpine의 기본 `wget`도 BusyBox를 통해 실행됨
- Alpine 컨테이너의 `/usr/bin/wget`은 실제 바이너리가 아니라 `/bin/busybox`를 가리키는 **심볼릭 링크**였음
- BusyBox는 실행 시 `argv[0]`에서 호출 이름을 읽고, 경로의 마지막 이름으로 실행할 **애플릿**을 결정함
- 각 애플릿은 이름으로 찾아 해당 `main` 함수로 진입하며, `wget`은 `wget.c`에 구현되고 최종적으로 `wget_main`이 실행됨
- `busybox --list`로 컴파일된 명령을 확인할 수 있고, Alpine 예시에서는 **304개**가 표시되며 각 유틸리티는 축소된 버전처럼 보임

---

### BusyBox의 동작 방식
- [BusyBox](https://busybox.net/)는 여러 명령을 하나의 실행 파일에서 제공하는 **멀티콜 바이너리(multicall binary)** 구조를 사용함
- Alpine 컨테이너에서 `/usr/bin/wget`은 실제 실행 파일이 아니라 `/bin/busybox`를 가리키는 **심볼릭 링크**였음
  ```bash
  docker run --rm -it alpine sh
  / # which wget
  /usr/bin/wget
  / # ls -lah /usr/bin/wget
  lrwxrwxrwx    1 root     root          12 Apr 15 04:51 /usr/bin/wget -> /bin/busybox
  ```
- `/usr/bin`에는 130개가 넘는 실행 파일이 하나의 바이너리에서 나온 형태로 보이며, BusyBox의 멀티콜 바이너리 구조와 연결됨
- BusyBox는 실행 시 `argv[0]`에서 호출된 이름을 가져오고, 경로의 마지막 이름만 뽑아 어떤 **애플릿(applet)** 을 실행할지 결정함
  ```c
  applet_name = argv[0];
  if (applet_name[0] == '-')
    applet_name++;
  applet_name = bb_basename(applet_name);
  ```
- `busybox ls -1`처럼 명시적으로 애플릿 이름을 넘겨도 동작하며, 존재하지 않는 이름을 주면 `applet not found`가 출력됨
  ```bash
  / # busybox ls -1
  bin
  dev
  etc
  home
  
  / # busybox meheh
  meheh: applet not found
  ```

### 애플릿 구성과 설치 방식
- BusyBox는 이름으로 애플릿을 찾은 뒤 해당 애플릿의 `main` 함수를 실행함
  ```c
  int applet = find_applet_by_name(name);
  // ...
  run_applet_no_and_exit(applet, name, argv);
  // ...
  xfunc_error_retval = applet_main[applet_no](argc, argv);
  ```
- 각 애플릿은 별도 C 파일을 가지며, `wget`은 **`wget.c`** 에 구현돼 있음
- 애플릿별 설정은 코드 주석 형태로 정의되어 있으며, `WGET` 설정에는 `wget (41 kb)`, 기본 활성화, HTTP와 FTP 서버에서 파일을 비대화식으로 내려받는 유틸리티라는 도움말, 빌드 대상 `wget.o`가 포함됨
  ```c
  //config:config WGET
  //config:	bool "wget (41 kb)"
  //config:	default y
  //config:	help
  //config:	wget is a utility for non-interactive download of files from HTTP
  //config:	and FTP servers.
  //applet:IF_WGET(APPLET(wget, BB_DIR_USR_BIN, BB_SUID_DROP))
  //kbuild:lib-$(CONFIG_WGET) += wget.o
  ```
- 최종적으로 `wget` 애플릿은 `wget_main`으로 진입함
  ```c
  int wget_main(int argc UNUSED_PARAM, char **argv)
  ```
- BusyBox는 하드 링크도 지원하며, `busybox --install -s`에서 `-s`는 **심볼릭 링크** 생성을 뜻함
  ```bash
  busybox --install -s
  ```
- 컴파일에 포함된 명령 목록은 `busybox --list`로 볼 수 있으며, Alpine 예시 환경에서는 **304개**가 표시됨
  ```bash
  / # busybox --list | wc -l
  304
  ```
- Alpine의 여러 명령은 BusyBox 기반 바이너리에 대한 인터페이스처럼 동작하며, 각 유틸리티는 완전한 원본 유틸리티보다 다소 **축소된 버전**처럼 보임

## Comments



### Comment 57410

- Author: joyfui
- Created: 2026-05-13T18:54:08+09:00
- Points: 1

안드로이드 커롬 가지고 놀때 많이 사용했는데 추억이네요

### Comment 57397

- Author: neo
- Created: 2026-05-13T16:02:51+09:00
- Points: 1

###### [Lobste.rs 의견들](https://lobste.rs/s/msrczi/what_is_busybox) 
* 인용된 질문의 답은 **재구현**에 가까움  
  BusyBox 소개는 https://busybox.net/about.html 에 있고, 소스는 https://github.com/vda-linux/busybox_mirror 에 있음

* 프로그램이 실제와 다른 이름인 척하는 게 꽤 거슬림  
  macOS에서 `gcc`를 실행했는데 실제로는 **clang**이 나오는 경우가 최악이고, PowerShell도 비슷하게 동작함. 그냥 다른 이름을 쓰면 좋겠음
  * 많은 개발자가 clang을 모르거나, 테스트할 Mac이 없거나, 현실적인 대안이 없던 시절에 시작했기 때문에 생긴 문제도 있음  
    Nixpkgs는 https://github.com/NixOS/nixpkgs/blob/441353f504b3a756b64437703cb06e8b8920ecd2/pkgs/development/libraries/sqlite/sqlar.nix#L21 같은 패치를 많이 해야 하고, sqlite 같은 유명 프로젝트도 예외가 아님. 반면 macOS는 그냥 **속이는 경로**를 택한 셈임
  * 많은 소프트웨어의 **makefile**을 쓰는 사람들이 `cc`를 모르는 경우가 있음
  * 답답함은 이해하지만, 대부분의 빌드 스크립트를 돌릴 만큼 **충분히 호환**되면 Linux와 여러 Unix 계열에서 같은 스크립트를 어느 정도 재사용할 수 있어서 퍼졌을 가능성이 큼
  * 때로는 현실적으로 불가능함  
    `gcc`가 하드코딩된 makefile이 많을 것이고, 다른 맥락에서도 비슷함. 예를 들어 기존 프로그램 다수가 올바른 해법인 `terminfo` 데이터베이스 대신 `TERM` 환경 변수의 `xterm-*`를 확인하므로, [다른 이름을 고르는 방식은 통하지 않음][kovidgoyal]

[kovidgoyal]: https://github.com/kovidgoyal/kitty/issues/879#issuecomment-419686348

* 컨테이너에서 이상한 문제를 진단할 때 `podman cp /usr/bin/busybox-static somecontainer:/bin`을 자주 씀

* **toybox**도 비슷한 구조임  
  일부 도구는 다른 곳에서 가져오거나 이식한 것으로 보이지만, 상당수는 BusyBox용으로 새로 구현됐고, 작게 만들며 정적 링크 시 작게 컴파일되도록 제한된 libc 기능만 쓰는 것이 목표임. 또 다른 장점은 셸 스크립트에서 이런 도구들을 내장 명령처럼 쓸 수 있다는 점임. 일부는 fork+exec가 아니라 **fork+jump**로 실행되고, 몇몇은 fork 없이 일반 함수 호출로도 실행됨
  * toybox는 원래 GPL 라이선스인 BusyBox의 **BSD 라이선스 대안**으로 만들어진 것으로 알고 있음  
    덧붙이면, [Toybox on Wikipedia](https://en.wikipedia.org/wiki/Toybox)에 따르면 “Toybox는 Rob Landley가 BusyBox의 원 제작자인 Bruce Perens와의 분쟁으로 BusyBox 유지보수자 역할을 그만둔 뒤 2006년 초에 시작했다”고 되어 있음

* 실제로는 **재구현**임. 다만 라이선스가 허용하는 경우라면 원래의 큰 구현에서 일부 코드를 빌려왔어도 놀랍지는 않음  
  [From the 'pedia:](https://en.wikipedia.org/wiki/BusyBox)에 따르면 BusyBox는 1995년 Bruce Perens가 처음 작성했고, 1996년 의도한 용도에는 완성됐다고 선언됐음. 처음 목표는 Debian 배포판의 복구 디스크이자 설치 프로그램 역할을 하는 완전한 부팅 가능 시스템을 플로피 디스크 하나에 넣는 것이었음. 이후 임베디드 Linux 장치와 Linux 배포판 설치 프로그램에서 사실상 표준 핵심 사용자 공간 도구 모음으로 확장됐고, Linux 실행 파일마다 몇 KB의 오버헤드가 필요하므로 200개가 넘는 프로그램을 하나로 합치면 디스크 공간과 메모리를 크게 절약할 수 있음  
  관련해서 [Toybox](https://codeberg.org/landley/toybox)도 구조와 철학이 비슷하지만 BSD 라이선스임. 주 개발자인 Rob Landley는 상업적으로 받아들이기 쉬운 라이선스라면 Android 기기에 포함될 수 있고, 그렇게 되면 모든 Android 휴대폰과 태블릿이 Unix 비슷한 개발 환경으로 바뀔 잠재력을 갖게 된다고 봤던 것으로 기억함. Toybox는 아직 Android의 일부인 것 같지만, Termux처럼 위 계층에서 도와주는 도구 없이는 Android에서 Unix처럼 쓰기 쉽지 않음
  * Google 같은 회사에 **무상 노동**을 해주는 일이 어떻게 자기 발목을 잡는지 보여주는 교과서적 사례로 이보다 완벽하기 어려움  
    특히 Google이 수년 동안 Termux를 막겠다고 위협해 온 점까지 생각하면 더 그렇다

* Windows 포트도 있음: https://github.com/rmyorston/busybox-w32  
  BusyBox의 작은 크기 덕분에 이런 포트가 더 현실적임. 다만 이제는 Windows 안에서 Linux를 그냥 실행할 수 있어서 관련성은 좀 줄어든 듯함
