처리중입니다. 잠시만 기다려주세요.
TTJ 코딩클래스
정규반 단과 자료실 테크 뉴스 코딩 퀴즈
테크 뉴스
Hacker News 2026.09.05 38
#AI

에러가 난 그 글자를 가리킨다: uutils coreutils의 컴파일러식 진단

Hacker News 원문 보기

유닉스 도구는 오래도록 오류를 stderr에 한 줄로 뱉어 왔다. 그 한 줄은 무엇이 잘못됐는지는 말하지만 어디서 잘못됐는지는 말하지 않는다. 대부분의 명령에는 사실 가리킬 '어디'가 없기 때문에 이 방식으로 충분하다. 그러나 일부 명령은 인자 자체가 작은 언어(small language)에 가깝다. test의 조건식, chmod의 모드 문자열, sort의 키 지정, tr의 문자 집합이 그렇다. 이런 인자를 파싱하다 실패하면 사용자가 정작 알고 싶은 것은 '어느 인자, 혹은 그 인자의 몇 번째 글자에서' 파서가 걸려 넘어졌는가다. Rust로 유닉스 핵심 유틸리티를 재구현하는 프로젝트 uutils는 0.11.0부터 바로 이 지점을 겨냥한 새 오류 표시 방식을 도입했다.

캐럿이 범인을 가리킨다

아이디어 자체는 낯설지 않다. Rust 컴파일러 rustc는 수년 전부터 캐럿(^) 기호로 소스 코드의 문제 위치를 짚어 왔고, ariadne 같은 라이브러리를 쓰면 같은 렌더링을 손쉽게 가져올 수 있다. 이를 커맨드라인 도구에 적용하자는 발상은 이미 awk 프로그램의 오류를 그런 식으로 보여 주던 uutils awk에서 나왔다. coreutils의 인자는 awk 프로그램보다 훨씬 작은 언어지만 파싱된다는 점은 똑같다. 그래서 stderr가 터미널일 때 파싱 오류는 이제 하나의 '리포트'로 출력된다. 입력된 인자가 소스 라인처럼 되울려지고, 그 아래 캐럿이 문제가 된 부분을 표시하며, 문법에 대해 해 줄 말이 있으면 도움말 한 줄이 덧붙는다.

구체적인 개선 사례가 이 방식의 가치를 잘 보여 준다. tr의 기존 GNU 메시지는 사용자가 이미 '콜레이팅 시퀀스(collating sequence)'가 무엇인지 안다고 전제했지만, 새 리포트는 문제 지점을 직접 가리킨다. cut의 리스트는 항목이 길어질 수 있는데 그중 잘못된 하나만 콕 짚을 수 있고, sort 키처럼 짧은 인자에 끼어든 엉뚱한 글자는 눈에 잘 안 띄지만 캐럿이 대신 찾아 준다. 캐럿은 인자 전체가 아니라 단 한 글자만 가리킬 수도 있다. env -S처럼 셸 방식으로 명령줄 전체를 쪼개는 경우, 공백이 든 문자열은 따옴표로 감싸 되울려지고 캐럿은 그 따옴표 안에 정확히 내려앉는다. test는 여러 인자를 조합해 식을 만드는데, 리포트는 앞의 test를 떼고 식만 보여 주며 깨진 인자를 표시한다.

하나의 파서, 스물여덟 개의 유틸리티

특히 SIZE 처리가 인상적이다. SIZE는 숫자 뒤에 단위가 붙는 값인데, 리포트는 숫자와 단위 중 어느 쪽이 거부됐는지 알려 준다. 하나의 파서가 전체 스위트의 SIZE를 담당하기 때문에, tail -c, truncate -s, split -b, shred -s, od -N, sort -S는 물론 du -B와 df -B, ls --block-size의 블록 크기, du -t의 임계값까지 동일한 리포트를 공유한다. numfmt --format은 변환 지정자를 정확히 하나만 허용하는 printf식 형식인데, 규칙을 되풀이하던 옛 메시지 대신 이제 사용자가 실제로 쓴 변환을 지목한다. csplit의 정규식 오류는 정규식 엔진이 이미 알고 있던 실패 위치를 그대로 활용한다. 다만 그 라벨은 엔진에서 곧장 나오는 것이라 번역되지 않는데, 해당 문구가 존재하는 유일한 자리이기 때문이다. 0.11.0 기준 28개 유틸리티가 이 방식을 쓴다.

실무자 입장에서 눈여겨볼 부분은 이것이 어디까지나 대화형 편의 기능이라는 점이다. uutils의 최우선 목표는 GNU coreutils의 드롭인 대체이므로, 리포트는 기본적으로 stderr가 터미널일 때만 그려지고 그 외에는 예전의 한 줄짜리 메시지가 유지된다. 이 판단은 UUTILS_DIAG 환경 변수로 덮어쓸 수 있다. always는 파일이나 파이프로 보낼 때도 리포트를 강제하고, never는 터미널에서도 평범한 한 줄을 유지하며, auto나 미설정은 종전대로 stderr를 보고 결정한다. 알 수 없는 값을 넣어도 일부러 오류로 처리하지 않는다. 셸 프로파일에 한 번 export해 두고 잊어버리는 종류의 변수인 만큼, 오타 하나가 유틸리티 실행 자체를 실패시켜서는 안 된다는 배려다.

플래그가 아니라 환경 변수인 이유

여기에 대응하는 커맨드라인 플래그는 없다. 정작 그것이 가장 필요할 test, printf, expr에서는 새 옵션이 불법이거나 피연산자와 구분되지 않아 모호해지기 때문이다. 스크립트나 CI 로그에서 리포트를 뽑아 버그 리포트에 붙이고 싶다면 UUTILS_DIAG로 강제하면 된다. 색상은 별개로, 여전히 터미널 여부로 결정된다. 파일로 강제된 리포트는 색 없이 쓰이므로 이스케이프 시퀀스를 나중에 걷어낼 필요가 없고, NO_COLOR는 그 중간에서 터미널이더라도 색만 뺀 평문 리포트를 그린다. 변수가 생기기 전부터 쓰이던 두 가지 요령도 그대로 통한다. stderr를 터미널이 아닌 곳으로 보내면 평문 한 줄이 나오고, script -qec나 expect의 unbuffer로 명령에 pty를 붙이면 다른 이유로 터미널 아래서 실행해야 할 때도 리포트를 되살릴 수 있다.

coreutils는 시작점일 뿐 종착점이 아니다. 렌더링은 다른 uutils 프로젝트들도 이미 의존하는 uucore::diagnostics에 들어 있어, 파서의 오류에 위치 정보(span)만 넘겨 주면 대체로 채택이 끝난다. find 표현식과 sed 스크립트 역시 캐럿이 도움이 되는 전형적인 작은 언어라 findutils와 sed가 지금 연결 작업 중이고, grep·awk 등도 같은 정규식과 형식 문자열을 가리킬 대상으로 두고 있다. 한국의 실무자에게 이 변화가 주는 함의는 분명하다. 스크립트 디버깅이나 로그 분석에서 유틸리티가 여전히 불친절한 한 줄만 던진다면, 이제는 그것을 당연하게 받아들이기보다 개선 여지가 있는 지점으로 볼 수 있다는 것이다. uutils는 그런 경우 패치를 환영한다고 밝히고 있다.

이 뉴스가 유용했나요?

이 기술을 직접 배워보세요

AI 도구, 직접 활용해보세요

AI 시대, 코딩으로 수익을 만드는 방법을 배울 수 있습니다.

AI 활용 강의 보기

"비전공 직장인인데 반년 만에 수익 파이프라인을 여러 개 만들었습니다"

실제 수강생 후기
  • 비전공자도 6개월이면 첫 수익
  • 20년 경력 개발자 직강
  • 자동화 프로그램 + 소스코드 제공

매일 AI·개발 뉴스를 받아보세요

주요 테크 뉴스를 매일 아침 이메일로 전해드립니다.

스팸 없이, 언제든 구독 취소 가능합니다.