How to add a directory to your PATH

Julia Evans

PATH에 디렉터리를 추가하는 방법

원문은 Julia Evans님이 에 게재했습니다. 이 블로그 구독하기

오늘 친구와 PATH에 디렉터리를 추가하는 방법에 대해 이야기하고 있었다. 터미널을 오래 써온 나에게는 너무나 “당연한” 일처럼 느껴지는데, 막상 방법을 검색해보니 모든 단계를 제대로 설명해주는 글을 찾기가 어려웠다. 대부분 “이걸 ~/.bashrc에 추가하세요”라고만 할 뿐이었다. 그런데 bash를 쓰지 않는다면 어떡하지? bash 설정 파일이 다른 곳에 있다면? 그리고 애초에 어떤 디렉터리를 추가해야 하는지는 어떻게 알아내라는 걸까?

그래서 좀 더 완전한 설명을 정리하고, 그동안 내가 겪었던 함정들도 함께 언급해보려 한다.

1단계: 어떤 셸을 사용하고 있나요?

자신이 어떤 셸을 쓰고 있는지 잘 모르겠다면, 이렇게 확인해보자. 다음 명령어를 실행하면 된다:

ps -p $$ -o pid,comm=
  • bash를 사용 중이라면 97295 bash처럼 출력된다
  • zsh를 사용 중이라면 97295 zsh처럼 출력된다
  • fish를 사용 중이라면 “In fish, please use $fish_pid” 같은 오류가 출력된다 ($$는 fish에서는 유효한 문법이 아니지만, 어쨌든 이 오류 메시지를 보면 fish를 쓰고 있다는 걸 알 수 있다 — 아마 이미 알고 있었겠지만)

참고로 bash는 Linux의 기본 셸이고, zsh는 Mac OS의 기본 셸이다(2024년 기준). 이 글에서는 bash, zsh, fish 세 가지만 다룬다.

2단계: 셸 설정 파일 찾기

  • zsh라면 아마 ~/.zshrc일 것이다
  • bash라면 ~/.bashrc일 수도 있지만, 좀 복잡하다. 다음 섹션의 참고 사항을 보자
  • fish라면 아마 ~/.config/fish/config.fish일 것이다 (100% 확실하게 하고 싶다면 echo $__fish_config_dir을 실행해보자)

bash 설정 파일에 대한 참고 사항

bash에는 세 가지 설정 파일이 있을 수 있다: ~/.bashrc, ~/.bash_profile, 그리고 ~/.profile이다.

시스템에서 어떤 파일을 사용하도록 설정되어 있는지 잘 모르겠다면, 이렇게 테스트해보는 걸 추천한다:

  1. ~/.bashrcecho hi there를 추가한다
  2. 터미널을 재시작한다
  3. “hi there”가 보인다면 ~/.bashrc가 사용되고 있다는 뜻이다! 성공!
  4. 그렇지 않다면 해당 줄을 지우고 ~/.bash_profile에 같은 방법으로 시도해본다
  5. 앞의 두 개가 모두 안 되면 ~/.profile도 시도해볼 수 있다.

(bash가 어떤 설정 파일을 사용할지 결정하는 과정을 설명하는 복잡한 순서도가 많이 있지만, 솔직히 그걸 외울 필요는 없고 그냥 직접 테스트해보는 게 가장 빠르다)

3단계: 추가할 디렉터리 찾기

http-server라는 프로그램을 설치해서 실행하려는데 이렇게 동작하지 않는다고 해보자:

$ npm install -g http-server
$ http-server
bash: http-server: command not found

http-server가 어떤 디렉터리에 있는지 어떻게 찾을 수 있을까? 솔직히 말하면 일반적으로 이건 그리 쉽지 않다. 답이 “npm이 어떻게 설정되어 있느냐에 따라 다르다” 같은 경우가 많기 때문이다. 몇 가지 아이디어를 소개한다:

  • 새로운 설치 도구(예: cargo, npm, homebrew 등)를 처음 설정할 때 PATH를 어떻게 업데이트하라는 안내가 출력되는 경우가 많다. 그때 잘 보고 있으면 바로 방법을 알 수 있다.
  • 가끔 설치 프로그램이 셸 설정 파일을 자동으로 수정해 PATH를 업데이트해주기도 한다
  • 그냥 “where does npm install things?”라고 구글링하면 답이 나오기도 한다
  • 어떤 도구들은 어디에 설치하도록 설정되어 있는지 알려주는 하위 명령을 제공하기도 한다. 예를 들면:
    • Node/npm: npm config get prefix (뒤에 /bin/을 붙인다)
    • Go: go env GOPATH (뒤에 /bin/을 붙인다)
    • asdf: asdf info | grep ASDF_DIR (뒤에 /bin//shims/를 붙인다)

3.1단계: 올바른 디렉터리인지 다시 확인하기

올바른 것 같다고 생각되는 디렉터리를 찾았다면, 실제로 맞는지 확인해보자! 예를 들어 내 컴퓨터에서는 http-server~/.npm-global/bin에 있었다. 이렇게 해당 디렉터리에 있는 http-server 프로그램을 직접 실행해보면 올바른 디렉터리인지 확인할 수 있다:

$ ~/.npm-global/bin/http-server
Starting up http-server, serving ./public

실행됐다! 이제 PATH에 추가해야 할 디렉터리를 알았으니 다음 단계로 넘어가자!

4단계: 셸 설정 수정하기

이제 필요한 핵심 정보 두 가지를 모두 갖추었다:

  1. PATH에 추가하려는 디렉터리(예: ~/.npm-global/bin/)
  2. 셸 설정 파일의 위치(예: ~/.bashrc, ~/.zshrc 또는 ~/.config/fish/config.fish)

이제 셸에 따라 추가해야 할 내용이 달라진다:

bash 설정 방법:

셸 설정 파일을 열고, 다음과 같은 줄을 추가하자:

export PATH=$PATH:~/.npm-global/bin/

(당연히 ~/.npm-global/bin은 실제로 추가하려는 디렉터리로 바꿔야 한다)

zsh 설정 방법:

bash와 똑같이 해도 되지만, zsh에는 원한다면 사용할 수 있는 조금 더 멋진 문법도 있다:

path=(
  $path
  ~/.npm-global/bin
)

fish 설정 방법:

fish에서는 문법이 다르다:

set PATH $PATH ~/.npm-global/bin

(fish에서는 fish_add_path를 사용할 수도 있는데, 이에 대한 설명은 아래쪽에 있다)

5단계: 셸 재시작하기

이제 아주 중요한 단계다: 셸 설정을 업데이트해도 셸을 재시작하지 않으면 적용되지 않는다!

두 가지 방법이 있다:

  1. 새 터미널(또는 새 터미널 탭)을 열고, 헷갈리지 않도록 기존 터미널은 닫는다
  2. bash를 실행해 새 셸을 시작한다 (zsh를 쓴다면 zsh, fish를 쓴다면 fish)

내 경험상 두 방법 모두 보통 잘 동작한다.

이제 끝이다! 실행하려던 프로그램을 다시 실행해보자. 아마 이제 잘 동작할 것이다.

만약 여전히 안 된다면, 겪을 수 있는 몇 가지 문제를 소개한다:

문제 1: 잘못된 프로그램이 실행된 경우

잘못된 버전의 프로그램이 실행되고 있다면, 디렉터리를 PATH의 끝이 아니라 앞부분에 추가해야 할 수도 있다.

예를 들어 내 시스템에는 python3가 두 버전 설치되어 있는데, which -a를 실행하면 확인할 수 있다:

$ which -a python3
/usr/bin/python3
/opt/homebrew/bin/python3

셸이 사용하는 것은 목록에서 첫 번째로 나온 것이다.

Homebrew 버전을 사용하고 싶다면, 해당 디렉터리(/opt/homebrew/bin)를 PATH의 앞부분에 추가해야 한다. 셸 설정 파일에 이렇게 넣으면 된다(보통의 $PATH:/opt/homebrew/bin/ 대신 /opt/homebrew/bin/:$PATH로 쓴다)

export PATH=/opt/homebrew/bin/:$PATH

fish에서는 이렇게 한다:

set PATH ~/.cargo/bin $PATH

문제 2: 프로그램이 셸에서 실행되지 않는 경우

지금까지의 설명은 모두 프로그램을 셸에서 실행할 때만 동작한다. IDE나 GUI에서, cron 작업에서, 혹은 다른 방식으로 프로그램을 실행한다면 PATH에 디렉터리를 추가하는 방법이 달라지며, 구체적인 방법은 상황에 따라 다를 수 있다.

cron 작업에서

몇 가지 방법은 다음과 같다:

  • 실행하려는 프로그램의 전체 경로를 사용한다. 예: /home/bork/bin/my-program
  • crontab의 첫 줄에 원하는 전체 PATH를 넣는다(예: PATH=/bin:/usr/bin:/usr/local/bin:….). 셸에서 사용 중인 전체 PATH는 echo "PATH=$PATH"를 실행하면 확인할 수 있다.

IDE/GUI에서 어떻게 해야 하는지는 솔직히 잘 모르겠다. 오랫동안 겪어본 적이 없어서, 누군가 방법을 알려주면 여기에 추가하겠다.

문제 3: 중복된 PATH 항목 때문에 디버깅이 어려워지는 경우

PATH를 수정한 뒤 bash(또는 zsh, fish)를 실행해 새 셸을 시작하면, 셸이 시작될 때마다 계속 새로운 항목을 PATH에 추가하기 때문에 중복된 PATH 항목이 생기는 경우가 많다.

개인적으로 이런 중복 때문에 뭔가 고장 난 경우는 본 적이 없지만, PATH의 내용을 파악하려고 할 때는 중복 때문에 디버깅이 더 어려워질 수 있다.

이 문제를 다루는 몇 가지 방법은 다음과 같다:

  1. PATH를 디버깅할 때는 새 터미널을 열어서 “깨끗한” 상태에서 하자. 이렇게 하면 중복을 피할 수 있다.
  2. 셸 설정 파일의 마지막에서 PATH의 중복을 제거한다 (예를 들어 zsh에서는 typeset -U path로 할 수 있다고 한다)
  3. 디렉터리를 추가할 때 이미 PATH에 있는지 확인한다 (예를 들어 fish에서는 fish_add_path --path /some/directory로 할 수 있는 것으로 안다)

PATH 중복을 제거하는 방법은 셸마다 다르며, 항상 내장된 방법이 있는 것은 아니니 각 셸에서 어떻게 하는지 찾아봐야 한다.

문제 4: PATH를 업데이트한 뒤 히스토리를 잃어버리는 경우

bash나 zsh에서 쉽게 겪을 수 있는 상황은 다음과 같다:

  1. 명령어를 실행한다 (실패한다)
  2. PATH를 업데이트한다
  3. bash를 실행해 설정을 다시 불러온다
  4. 위쪽 화살표를 몇 번 눌러 실패했던 명령어를 다시 실행한다 (또는 새 터미널을 연다)
  5. 실패했던 명령어가 히스토리에 없다! 왜 그럴까?

이렇게 되는 이유는 bash에서는 기본적으로 셸을 종료하기 전까지 히스토리가 저장되지 않기 때문이다.

이를 해결하는 몇 가지 방법은 다음과 같다:

  • bash를 실행해 설정을 다시 불러오는 대신, source ~/.bashrc(zsh에서는 source ~/.zshrc)를 실행한다. 이렇게 하면 현재 세션 안에서 설정이 다시 불러와진다.
  • 셸이 종료될 때만 히스토리를 저장하는 대신 계속 저장하도록 설정한다. (방법은 bash를 쓰는지 zsh를 쓰는지에 따라 다르며, zsh의 히스토리 옵션은 좀 복잡해서 가장 좋은 방법이 무엇인지 정확히는 모르겠다)

source에 대한 참고 사항

cargo(Rust 설치 도구)를 처음 설치하면 PATH를 어떻게 설정하라는 안내가 나오는데, 특정 디렉터리를 전혀 언급하지 않는다.

This is usually done by running one of the following (note the leading DOT):

. "$HOME/.cargo/env"        	# For sh/bash/zsh/ash/dash/pdksh
source "$HOME/.cargo/env.fish"  # For fish

아이디어는 그 줄을 셸 설정에 추가하면, 해당 스크립트가 자동으로 PATH(그리고 어쩌면 다른 것들)를 설정해준다는 것이다.

이는 꽤 흔한 방식이다(예를 들어 Homebrewbrew shellenv를 eval하라고 제안한다). 이에 접근하는 두 가지 방법은 다음과 같다:

  1. 도구가 제안하는 대로 그냥 따른다(예: . "$HOME/.cargo/env"를 셸 설정에 추가한다)
  2. 실행하라는 스크립트가 PATH에 어떤 디렉터리를 추가하는지 알아낸 뒤, 직접 수동으로 추가한다. 내가 한다면 이렇게 할 것이다:
    • 셸에서 . "$HOME/.cargo/env"를 실행한다 (fish를 쓴다면 fish용 버전을 실행한다)
    • echo "$PATH" | tr ':' '\n' | grep cargo를 실행해 어떤 디렉터리가 추가되었는지 확인한다
    • /Users/bork/.cargo/bin이라고 나오는 것을 보고 이를 ~/.cargo/bin으로 줄인다
    • 이 글의 설명에 따라 ~/.cargo/bin 디렉터리를 PATH에 추가한다

도구가 제안하는 대로 하는 것에 뭐가 잘못됐다고 생각하지는 않는다(그게 “가장 좋은 방법”일 수도 있다!). 하지만 개인적으로는 정확히 어떤 설정을 바꾸는지 알고 싶어서 보통 두 번째 방법을 쓴다.

fish_add_path에 대한 참고 사항

fish에는 PATH에 디렉터리를 추가할 때 사용할 수 있는 fish_add_path라는 편리한 함수가 있다. 이렇게 실행한다:

fish_add_path /some/directory

이건 멋지다(정말 간단한 명령어다!) 하지만 나는 몇 가지 이유로 사용을 중단했다:

  1. 가끔 fish_add_path는 (“universal variable”을 이용해) 앞으로의 모든 세션에 대해 PATH를 업데이트하고, 가끔은 현재 세션에 대해서만 PATH를 업데이트하는데, 어느 쪽이 될지 구분하기가 어렵다. 이론상 문서에 설명이 되어 있지만 나는 이해할 수 없었다.
  2. 혹시 몇 주나 몇 달 뒤에 실수를 알아채고 PATH에서 해당 디렉터리를 제거해야 할 때, 하기가 꽤 어렵다(이 GitHub 이슈 댓글에 설명이 있긴 하다).

마무리

이 글이 누군가에게 도움이 되길 바란다. PATH에 디렉터리를 추가할 때 겪었던 다른 큰 함정이 있거나 이 글에 대해 질문이 있다면 (Mastodon이나 Bluesky에서) 알려달라!

이 글은 muse-spark-1.2-contributor 모델을 사용해 번역했습니다.

댓글