리눅스나 macOS 터미널을 쓰다 보면 ~/.bash_profile, ~/.bashrc, ~/.profile 같은 파일들을 한 번쯤은 만지게 됩니다. 문제는 "PATH가 안 먹혀요", "새 터미널 열면 alias가 사라져요" 같은 이슈가 생길 때마다 이 파일들 중 뭘 고쳐야 하는지 헷갈린다는 점이에요.
이번 글에서는 bash가 시작될 때 어떤 파일을 어떤 순서로 읽는지, 그리고 .bash_profile과 .bashrc를 왜 나눠서 쓰는지 정리해보겠습니다.
셸의 두 가지 기준: 로그인 여부 · 대화형 여부
bash가 시작 파일을 고르는 기준은 딱 두 가지입니다.
- 로그인 셸(login shell)인가? — 사용자가 시스템에 로그인하면서 최초로 뜨는 셸인지
- 대화형 셸(interactive shell)인가? — 사람이 명령어를 직접 입력하는 셸인지, 스크립트 실행용인지
이 두 축의 조합에 따라 실행되는 파일이 완전히 달라집니다.
| 상황 | 예시 |
|---|---|
| 로그인 + 대화형 | SSH로 서버 접속, TTY 콘솔 로그인 |
| 비로그인 + 대화형 | 이미 켜진 터미널에서 새 탭/새 창 열기 |
| 비로그인 + 비대화형 | bash script.sh 실행, cron job |
전체 흐름도
말로 설명하는 것보다 그림으로 보는 게 빠릅니다.
정리하면 이렇습니다.
- 로그인 셸이면 먼저
/etc/profile(시스템 전체 설정)을 읽습니다. - 그다음
~/.bash_profile,~/.bash_login,~/.profile세 파일 중 가장 먼저 존재하는 파일 딱 하나만 읽습니다. 세 개를 다 읽는 게 아니라는 점이 핵심이에요. - 비로그인 + 대화형 셸이면
~/.bashrc만 읽습니다. - 비대화형 셸(스크립트 실행 등)은 기본적으로 아무 시작 파일도 읽지 않고,
$BASH_ENV환경변수에 지정된 파일이 있으면 그것만 읽습니다.
.bash_profile vs .bashrc, 왜 나눠져 있을까?
역사적으로 로그인 시 "환경(environment)을 한 번만 설정"하고, 이후 여는 모든 셸마다 "동작(behavior)을 매번 설정"하기 위해 분리되었습니다.
~/.bash_profile: 로그인할 때 딱 한 번 실행.PATH,LANG,EDITOR같은 환경변수는 여기서 한 번만 잡아주면 이후 자식 프로세스에도 상속됩니다.~/.bashrc: 새 터미널(비로그인 대화형 셸)을 열 때마다 실행.alias, 셸 함수, 프롬프트(PS1) 설정처럼 매 셸마다 필요한 것들은 여기에 둡니다.
문제는 alias나 함수는 자식 프로세스로 상속되지 않는다는 점이에요. 그래서 로그인 셸에서만 .bash_profile이 실행되면, 로그인 셸 안에서 다시 새 터미널을 열었을 때(즉 비로그인 셸) alias가 하나도 안 잡혀있는 상황이 생깁니다.
이걸 막기 위해 실무에서는 거의 항상 .bash_profile 안에서 .bashrc를 강제로 불러오도록 설정합니다.
# ~/.bash_profile
if [ -f ~/.bashrc ]; then
. ~/.bashrc
fi
export PATH="$HOME/bin:$PATH"
export EDITOR="vim"
이렇게 해두면 로그인 셸이든 아니든 .bashrc의 내용이 항상 적용되므로, 사실상 "관리는 .bashrc에서, .bash_profile은 진입점 역할만" 하는 구조가 됩니다.
macOS는 좀 다르다
macOS의 Terminal.app은 새 창을 열 때마다 셸을 로그인 셸로 띄웁니다(리눅스 데스크톱 터미널 대부분은 비로그인 셸로 띄우는 것과 대조적이에요). 그래서 macOS에서는 .bashrc를 아예 안 쓰고 .bash_profile 하나에 다 몰아넣는 경우도 흔합니다. 다만 위처럼 .bash_profile에서 .bashrc를 불러오는 구조로 통일해두면 리눅스/macOS 어디서든 동일하게 동작하니 이 방식을 추천합니다.
직접 확인해보기
지금 내 셸이 로그인 셸인지, 어떤 파일이 실행됐는지 궁금하다면 아래처럼 확인할 수 있습니다.
# 로그인 셸인지 확인 (앞에 -가 붙으면 로그인 셸)
echo $0
# 대화형 셸인지 확인
[[ $- == *i* ]] && echo "interactive" || echo "not interactive"
# 어떤 파일이 실행되는지 직접 추적 (bash -x 로 디버깅)
bash -xl -c 'exit' 2>&1 | head -20
bash_profile / bashrc / profile 요약 표
| 파일 | 실행 시점 | 주로 넣는 내용 |
|---|---|---|
/etc/profile |
모든 사용자, 로그인 셸 | 시스템 공통 환경변수 |
~/.bash_profile |
해당 사용자, 로그인 셸 | 개인 PATH, 환경변수, .bashrc 호출 |
~/.bash_login |
.bash_profile 없을 때만 |
(거의 안 씀) |
~/.profile |
위 둘 다 없을 때, 또는 sh 계열 | POSIX 호환 로그인 설정 |
~/.bashrc |
비로그인 대화형 셸마다 | alias, 함수, PS1 프롬프트 |
~/.bash_logout |
로그인 셸 종료 시 | 로그아웃 시 정리 작업(화면 클리어 등) |
마무리
정리하면, .bash_profile은 "로그인할 때 한 번", .bashrc는 "터미널을 열 때마다"라고 기억하면 됩니다. 그리고 실무에서는 .bash_profile에서 .bashrc를 불러오는 패턴이 사실상 표준이라, 이 구조 하나만 이해해두면 PATH나 alias가 안 먹히는 문제의 8할은 바로 원인을 찾을 수 있습니다.
'프로그래밍 > Linux' 카테고리의 다른 글
| 리눅스 기초 개념 정리 - 커널부터 파일 시스템, 권한, 프로세스까지 (0) | 2026.09.22 |
|---|