셸 로직을 못 짜서 GUI에 갇혔던 개발자, Bash while 루프와 NodeJS child_process를 비교하다
- Will Keleher는 커리어 초반 몇 년간 셸에서 조건문, 반복문, 파이프 같은 로직을 못 짜서 명령을 하나씩만 실행했고, npm install 실패 시 status_code를 검사해 exit 1을 반환하는 스크립트를 겨우 쓰게 된 시점을 전환점으로 꼽음
- 같은 작업을 셸의
while pnpm exec mocha ...; do true; done과 NodeJS의 child_process execSync로 나란히 비교하며, require와 stdio: "inherit" 같은 준비가 필요 없는 셸이 더 간결하다고 봄 - JS 팀에는 zx를 권하지만, 로직과 자료형이 복잡해지면 셸 대신 표현력 있는 언어를 골라야 한다고 정리함. 빌드 스크립트를 다른 언어로 바꿔본 적 없는 사람이 셸을 비판한다는 지적도 덧붙임
- HN 댓글에서는 셸의 힘은 언어가 아니라 stdin/stdout/stderr로 임의 프로그램을 조합하는 인터페이스와 "모든 것은 파일" 추상화에서 나오며, 언어 선택은 세 번째 순위라는 의견이 나옴. 중요한 스크립트는 늘 /bin/sh라는 것
- 댓글에서 duckdb REPL의 JSON 파일 읽기, Perl과 Scsh 같은 셸용 언어, LLM에 자연어로 시키는 방식이 이 문제를 대체로 해결했다는 이야기가 나옴
Hacker News opinions
AI 없이 자기 머리로 배워서 실제로 써먹는 얘기라 좋다. 요즘엔 보기 드문 글임.
duckdb REPL이 JSON 파일을 읽는 건 오늘 처음 알았음. 큰 JSON 파일 뒤질 때 jq로 안 되면 써먹어야겠음. 근데 전용 도구인 jq가 SQL보다 언제 더 제한적인지는 좀 궁금하네.
셸 도구를 깊게 몰라도 원라이너 for 루프 문법만 외워두면 평생 써먹음. 이것만 가져가도 남는 장사임.
터미널만이 컴퓨터에 일 시키는 방법이라는 가정이 좀 이상함. OS 부팅시키는 것도 컴퓨터에 시키는 거잖아. GUI도 추상화 위에서 시키는 건 똑같은데 셸이 더 시키는 건 아니지 않나.
AI 프롬프트 얘기일 줄 알았는데 아니었음. LLM이 사실상 이 문제를 해결했고, 비개발자들이 말하는 바이브코딩이 딱 이거임. 악성 명령이 끼는 문제는 있지만 대충 충분함.
그 스크립트는 npm install || (echo "boom" && exit) 정도로 줄일 수 있음. echo가 실패하면 exit이 안 도는 차이는 있지만 나는 세미콜론보다 이게 편함.
앞 명령이 실패하면 종료 코드를 전파하면서 처리하는 문법이 따로 있는지 궁금함. 에러만 띄우면 die 같은 걸로 되지만 가끔은 정확한 코드를 알아야 할 때가 있음.
셸이 주력 언어로 안 쓰이는 이유는 배터리 포함임. 글로브와 find, xargs로 깊은 디렉터리를 훑는 걸 다른 언어로 하면 너무 불편해서 결국 셸로 돌아옴.
GUI는 남이 만든 추상화에 갇히지만 셸은 원하는 대로 조립할 수 있다는 차이가 큼. 물론 셸도 커널과 CPU 설계자의 제약 안이라는 반론도 맞는 말이고.
셸 같은 일을 가장 간결하게 하는 언어는 Perl임. Ruby가 훨씬 예쁘긴 하고, Scsh라는 선택지도 있음.
스크립팅을 빼면 CLI가 GUI보다 낫다는 주장이 확 약해짐. IDE에서 스크립팅하는 게 vim보다 훨씬 쉽고, 그래픽 디자인을 CLI로 하라고 하면 할 말이 없음.
셸의 힘은 언어가 아니라 순서가 이렇다고 봄. 1) stdin/stdout/stderr와 모든 것은 파일, 2) 같은 추상화로 맞물리는 표준 유틸리티, 3) 언어 선택임. 실제로 중요한 스크립트는 항상 /bin/sh임.
AI가 셸에서 하는 걸 보면서 오히려 많이 배움. 샌드박스에 에이전트 돌려서 디버깅 중인 머신에 어떤 명령을 쳐야 하는지 알려주게 하는 식임.
스크립팅은 터미널을 넘어 창 조작과 알림, 홈어시스턴트 API 호출까지 됨. OS만 있으면 터미널이 있고, Termux 덕에 Meta Quest에서도 됨.