왜 셸의 역사를 알아야 할까?
오래된 설치 스크립트와 오늘 만든 셸 설정은 비슷해 보여도 서로 다른 언어 규칙을 따를 수 있어. #!/bin/sh로 시작한 파일에 bash 배열이나 zsh 전용 확장을 넣으면 개발 환경에서는 우연히 돌아가다가 다른 머신이나 CI에서 깨져. 셸의 계보를 알면 문법을 외우는 데서 끝나지 않고, 어떤 인터프리터가 그 문법을 해석해야 하는지 판단할 수 있어.
1979: Bourne 셸(sh)
Stephen Bourne이 Bell Labs에서 만든 sh는 파이프, 환경 변수, if/then/fi, 히어 도큐먼트와 종료 상태 같은 기본 문법을 널리 퍼뜨렸어. 오늘날 /bin/sh는 특정 제품 이름보다 POSIX 셸 계약을 뜻하는 경우가 많아. 배열이나 [[ ... ]] 같은 확장을 기대하지 않고, 여러 Unix 환경에서 통할 최소 문법을 선택할 때 사용해.
1989: Bourne Again 셸(bash)
GNU의 bash는 Bourne 셸 문법을 바탕으로 명령 기록, 줄 편집, 배열, [[ ... ]], 명령 치환 같은 기능을 더했어. macOS는 오랫동안 bash를 기본 셸로 제공했지만, 시스템에 포함된 버전은 GPLv3로 라이선스가 바뀐 이후 3.2 계열에 머물러 있어. 최신 bash 기능이 필요하다면 프로젝트가 요구하는 버전을 별도로 설치하고 shebang과 실행 경로를 함께 확인해야 해.
1990: Z 셸(zsh)
zsh는 강력한 자동 완성, 재귀 글로브, 프롬프트 확장과 플러그인 생태계를 제공해. macOS Catalina부터 새 계정의 기본 로그인 셸이지만, 기본값이라는 사실이 모든 스크립트를 zsh 문법으로 써도 된다는 뜻은 아니야. 대화형 작업에 zsh를 쓰면서도 배포 스크립트는 대상 환경이 보장하는 셸에 맞춰 작성할 수 있어.
2005: fish
fish는 자동 제안과 구문 강조처럼 대화형 사용 경험을 우선하고 POSIX 호환성을 의도적으로 따르지 않아. 프롬프트에서 쓰기 편하지만 bash나 sh 스크립트를 그대로 해석하지는 못해. fish를 로그인 셸로 선택하더라도 저장소의 스크립트는 선언한 인터프리터로 실행되므로 두 역할을 분리해서 생각해야 해.
현실에서 적용할 규칙
대화형 셸은 작업 습관에 맞춰 고르고, 공유 스크립트는 실행 대상이 보장하는 인터프리터에 맞춰 작성해. 파일 첫 줄의 shebang, 실제 실행 경로, 사용한 문법을 한 계약으로 다뤄야 해. command -v와 버전 출력을 확인하면 같은 이름의 셸이 어느 설치본을 가리키는지도 알 수 있어. “내 터미널에서 됐다”보다 “선언한 셸과 버전에서 됐다”가 재현 가능한 증거야.
윈도우 환경에서 공부중이라 bash를 다루기 어렵지만, 이번 챕터에서 key point는 내가 작업할 때는 사용이 편한 fish와 같은거를 쓰고, 공유할 때는 범용성이 뛰어난 bash와같은 문법을사용해라.
즉 사용버전과 배포버전 각각의 환경(나의 환경과 제3자들의환경)이 다름을 인식하라는 것인가요?