SSD Nodes Learn 🎉 VPS $5.50/월부터
가이드 Matt Connor작성자 Matt Connor

chmod 755와 u+x 차이점 및 권한 설정 가이드

chmod 명령어의 숫자 표기법과 기호 표기법을 비교합니다. 8진수 모드 사용 시 주의할 점과 재귀적 변경 시 발생하는 문제, 그리고 대문자 X 옵션이 파일과 디렉터리 권한을 어떻게 다르게 처리하는지 상세히 설명합니다.

chmod의 변경 방식

chmod는 파일이나 디렉터리의 권한 비트를 변경하며, 두 가지 표기법 중 하나를 사용하여 권한을 설정할 수 있습니다. 숫자 형식은 8진수 숫자를 사용하여 모든 권한 비트를 한 번에 교체합니다. 기호 형식은 사용자 클래스와 연산자를 지정하여 명시한 비트만 수정합니다. 두 방식 모두 최종적으로는 동일한 시스템 호출로 이어집니다. 차이점은 명시하지 않은 비트를 어떻게 처리하느냐에 있습니다.

모드를 읽는 것과 변경하는 것은 서로 다른 작업입니다. 긴 목록 형식의 문자가 아직 익숙하지 않다면, 먼저 drwxr-xr-x의 필드별 의미를 읽어보시기 바랍니다. 이 가이드는 권한 변경만을 다룹니다.

여기에 나오는 모든 명령은 일반 로그인 사용자로 실행하십시오. root 계정은 이러한 권한 검사를 우회하므로, root로 실행하는 권한 시연은 아무런 의미가 없습니다. 아직 새 서버에서 root로 작업 중이라면, 최소 권한을 가진 일반 사용자를 생성한 뒤 돌아오시기 바랍니다.

폐기 가능한 샌드박스 설정하기

cd "$(mktemp -d)"
touch notes.txt

mktemp -d은(는) /tmp 아래에 빈 디렉터리를 생성하고 해당 경로를 출력하며, 명령어 치환을 통해 그 경로를 즉시 cd로 전달합니다. 아래의 어떤 작업도 사용자가 중요하게 여기는 파일에는 영향을 주지 않습니다.

단일 명령어로 모든 변경 사항의 결과를 확인할 수 있습니다.

stat -c '%a %A %n' notes.txt

%a은(는) 모드를 8진수로 출력하고, %A은(는) 동일한 모드를 긴 목록 형식에서 사용하는 문자 형태로 출력하며, %n은(는) 이름을 출력합니다. 이어지는 블록에서 $로 시작하는 줄은 사용자가 입력하는 내용이며, 그 아래 줄은 명령어가 출력한 결과입니다. 직접 실행해 보십시오. 수치 모드는 환경에 영향을 받지 않으므로, 사용자의 기기에서도 출력 결과가 줄 단위로 일치해야 합니다.

숫자 표기법: 클래스당 8진수 한 자리

첫 번째 자리는 파일 소유자에게 해당합니다. 두 번째 자리는 파일 그룹에 해당합니다. 세 번째 자리는 그 외 모든 사용자에게 해당합니다. 각 숫자는 비트당 하나의 값을 합산한 결과입니다. 비트를 하나씩 설정하고 stat이 무엇을 보고하는지 확인하십시오.

$ chmod 400 notes.txt
$ stat -c '%a %A %n' notes.txt
400 -r-------- notes.txt
$ chmod 200 notes.txt
$ stat -c '%a %A %n' notes.txt
200 --w------- notes.txt
$ chmod 100 notes.txt
$ stat -c '%a %A %n' notes.txt
100 ---x------ notes.txt

문자는 숫자와 일대일로 대응합니다. 파일 유형을 나타내는 첫 문자를 제외하고, 첫 세 문자는 소유자, 다음 세 문자는 그룹, 마지막 세 문자는 그 외 모든 사용자의 권한입니다. 한 클래스 내에서 비트를 조합하려면 각 값을 더하십시오.

$ chmod 600 notes.txt
$ stat -c '%a %A %n' notes.txt
600 -rw------- notes.txt
$ chmod 700 notes.txt
$ stat -c '%a %A %n' notes.txt
700 -rwx------ notes.txt
$ chmod 750 notes.txt
$ stat -c '%a %A %n' notes.txt
750 -rwxr-x--- notes.txt

숫자 모드는 절대적입니다. 실행할 때마다 9비트 전체를 기록하므로, 고려하지 않았던 클래스까지 함께 변경됩니다.

$ chmod 755 notes.txt
$ stat -c '%a %A %n' notes.txt
755 -rwxr-xr-x notes.txt
$ chmod 600 notes.txt
$ stat -c '%a %A %n' notes.txt
600 -rw------- notes.txt

두 번째 명령은 그룹이나 그 외 사용자에 대해 아무것도 언급하지 않았지만, 해당 비트는 어쨌든 변경되었습니다. 이것이 숫자 표기법의 특성이며, 작은 수정 작업에 숫자 표기법이 부적절한 이유입니다. (chmod은 이 세 자리 앞에 위치하는 네 번째 자리인 setuid, setgid, sticky 비트도 처리합니다. 이는 별도의 주제이므로, 이 가이드에서는 세 자리만 다룹니다.)

심볼릭 형식: 클래스, 연산자, 그리고 비트

먼저 클래스를 작성합니다. u는 소유자, g은 그룹, o는 그 외 모든 사용자, a는 이들 모두를 의미합니다. 다음으로 연산자를 작성합니다. +은 비트를 추가하고, -은 비트를 제거하며, =은 해당 클래스의 비트를 나열한 비트로 정확히 설정하고 나머지는 모두 지웁니다. 마지막으로 r, w 또는 x과 같이 비트 자체를 작성합니다.

$ chmod 640 notes.txt
$ stat -c '%a %A %n' notes.txt
640 -rw-r----- notes.txt
$ chmod u+x notes.txt
$ stat -c '%a %A %n' notes.txt
740 -rwxr----- notes.txt
$ chmod g-r notes.txt
$ stat -c '%a %A %n' notes.txt
700 -rwx------ notes.txt
$ chmod o=r notes.txt
$ stat -c '%a %A %n' notes.txt
704 -rwx---r-- notes.txt

각 명령은 하나의 클래스에만 영향을 주며 다른 클래스는 그대로 둡니다. 절을 쉼표로 구분하되 공백은 넣지 마십시오. chmod는 왼쪽에서 오른쪽 순서로 이를 적용합니다.

$ chmod u=rw,go=r notes.txt
$ stat -c '%a %A %n' notes.txt
644 -rw-r--r-- notes.txt
$ chmod go= notes.txt
$ stat -c '%a %A %n' notes.txt
600 -rw------- notes.txt

등호 뒤에 아무것도 없는 go=는 그룹과 그 외 모든 사용자로부터 모든 비트를 제거합니다. 이는 SSH 키 쌍의 개인 키와 같이 소유자만 읽을 수 있어야 하는 파일에 필요한 형태입니다.

chmod는 자신의 작업 내용을 보고할 수도 있는데, 이는 화면을 지켜보는 사람이 없는 스크립트 내부에서 중요합니다.

chmod -v u+x notes.txt
chmod -v u+x notes.txt

-v은 지정된 모든 파일에 대해 한 줄씩 출력합니다. 두 명령을 모두 실행하고 화면에 나타나는 두 줄을 비교해 보십시오. 첫 번째 줄은 파일 이름을 명시하고 변경 전후의 모드를 보고하며, 두 번째 줄은 추가하려는 비트가 이미 설정되어 있었기 때문에 모드가 유지되었다고 보고합니다. -c는 파일이 실제로 변경되었을 때만 한 줄을 출력하므로 로그에 기록하기에 더 적합합니다.

chmod 755와 u+x 비교: 어떤 표기법을 사용할 것인가

동일한 파일에서 시작하여 각 표기법이 어떤 결과를 남기는지 비교합니다.

$ chmod 640 notes.txt
$ chmod 755 notes.txt
$ stat -c '%a %A %n' notes.txt
755 -rwxr-xr-x notes.txt
$ chmod 640 notes.txt
$ chmod u+x notes.txt
$ stat -c '%a %A %n' notes.txt
740 -rwxr----- notes.txt

두 명령어 모두 파일 소유자에게 실행 권한을 부여했습니다. 하지만 그중 하나만이 나머지 두 클래스의 권한을 이전 상태 그대로 유지했습니다. 원하는 최종 상태를 정확히 알고 이를 강제해야 할 때는 숫자 모드를 사용하십시오. 이는 처음 접하는 시스템에서도 동일한 결과를 생성해야 하는 배포 스크립트에서 필수적인 방식입니다. 반면, 머릿속으로 추가하거나 제거한다는 개념을 생각할 때는 심볼릭 모드를 사용하십시오. 숫자 모드에는 특정 부분을 그대로 두라고 지시할 방법이 없기 때문입니다.

새로운 파일이 처음 생성될 때의 모드는 chmod가 결정하는 것이 아닙니다. 해당 파일을 생성한 프로세스의 umask 값에서 결정됩니다. 현재 셸에서 umaskumask -S을 실행하여 적용 중인 값을 확인해 보십시오. 이 값은 배포판마다, 로그인 셸과 systemd 서비스 간에, 그리고 계정마다 다를 수 있습니다. umask는 모든 새 파일의 모드를 설정합니다. 따라서 chmod가 실행되기 전에 파일의 시작 상태를 결정하는 것은 바로 umask입니다.

디렉터리에서 실행 비트가 하는 역할

가장 많은 시간을 낭비하게 만드는 오해입니다. 일반 파일에서 실행 비트는 커널이 해당 파일을 실행할 수 있음을 의미합니다. 디렉터리에는 실행할 명령어가 없으므로 실행할 대상이 존재하지 않습니다. 디렉터리에서 실행 비트는 탐색(traversal)을 의미하며, 이는 디렉터리 내부의 이름을 해석할 수 있는 권한입니다. dir/file에 도달하려면 dir에 이 권한이 필요합니다. 읽기 비트는 별도의 권한이며, 디렉터리가 포함한 파일 목록을 나열할 수 있게 해줍니다. 두 권한은 독립적이므로 하나만 가질 수도 있으며, 직접 확인해보면 이해하기가 더 쉽습니다.

$ mkdir vault
$ printf 'hello\n' > vault/secret.txt
$ chmod 600 vault/secret.txt
$ chmod 100 vault
$ echo vault/*
vault/*
$ cat vault/secret.txt
hello

셸이 패턴을 변경하지 않고 그대로 출력한 이유는 vault/*를 확장하는 과정에서 디렉터리를 읽어야 하기 때문입니다. 일치하는 항목이 없는 glob은 오류를 발생시키는 대신 리터럴 텍스트로 그대로 전달됩니다. cat은 사용자가 직접 이름을 입력했고 탐색 권한이 허용되었기 때문에 여전히 정상적으로 작동합니다. 이제 두 비트를 서로 바꿔보겠습니다.

$ chmod 400 vault
$ echo vault/*
vault/secret.txt
$ cat vault/secret.txt
cat: vault/secret.txt: Permission denied

이제 이름은 보이지만 내용은 확인할 수 없습니다. 읽기 권한은 목록을 제공하고, 실행 권한은 진입 경로를 제공합니다. 사용하는 거의 모든 디렉터리는 두 권한을 모두 필요로 합니다.

$ chmod 500 vault
$ cat vault/secret.txt
hello

숫자 모드를 사용한 chmod -R이 디렉터리 구조를 손상시키는 이유

-R은 전체 디렉터리 구조를 순회하며 마주치는 모든 항목에 지정한 모드를 적용합니다. 디렉터리와 데이터 파일은 필요한 권한 비트가 서로 다르므로, 하나의 절대적인 숫자를 두 항목 모두에 적용하는 것은 옳지 않습니다. 작은 디렉터리 구조를 만들어 어떤 문제가 발생하는지 확인해 보십시오.

$ mkdir -p site/css
$ touch site/index.html site/css/main.css
$ printf '#!/bin/bash\necho hi\n' > site/deploy.sh
$ chmod 755 site site/css site/deploy.sh
$ chmod 644 site/index.html site/css/main.css
$ stat -c '%a %A %n' site site/css site/index.html site/css/main.css site/deploy.sh
755 drwxr-xr-x site
755 drwxr-xr-x site/css
644 -rw-r--r-- site/index.html
644 -rw-r--r-- site/css/main.css
755 -rwxr-xr-x site/deploy.sh

위 구조는 정적 파일이 담긴 디렉터리에 적합한 형태입니다. 다음은 첫 번째 재귀적 실수입니다.

$ chmod -R 755 site
$ stat -c '%a %A %n' site/index.html site/css/main.css
755 -rwxr-xr-x site/index.html
755 -rwxr-xr-x site/css/main.css

아무것도 깨지지 않았으며, 바로 그 점이 문제입니다. 이 실수는 아무런 경고 없이 지나가기 때문에 복사된 명령어 지침 속에 수년간 살아남습니다. 이제 두 개의 데이터 파일이 프로그램인 것처럼 설정되었습니다. Git은 실행 비트(execute bit)를 저장하므로, 다음 커밋에는 이 변경 사항이 포함되어 저장소를 복제하는 모든 사람에게 전달되며, rsynctar을 통해 이 구조를 복사하는 모든 장비로 전파됩니다.

두 번째 재귀적 실수는 즉각적인 문제를 일으킵니다. 실행 비트가 없는 모드를 디렉터리에 적용하면 해당 디렉터리는 접근이 차단됩니다.

$ chmod 644 site
$ stat -c '%a %A %n' site
644 drw-r--r-- site
$ echo site/*
site/css site/deploy.sh site/index.html
$ cd site
bash: cd: site: Permission denied
$ cat site/index.html
cat: site/index.html: Permission denied

읽기 비트(read bit)는 유지되었으므로 파일 이름은 나열되지만, 실행 비트가 제거되었기 때문에 디렉터리를 통과하는 모든 경로가 차단됩니다. chmod -R 644 site는 단 한 번의 명령으로 트리 내의 모든 디렉터리에 이 작업을 수행합니다. 이후 결과는 항상 일정하지 않을 수 있습니다. chmod는 자신이 접근 권한을 제거하고 있는 바로 그 디렉터리를 통과하며 작업을 수행해야 하기 때문입니다. 따라서 결과를 추측하지 말고 find site -type d -exec stat -c '%a %n' {} +를 사용하여 실제로 어떤 권한이 적용되었는지 확인하십시오. 계속하기 전에 다음 명령으로 복구하십시오.

$ chmod 755 site
$ chmod 644 site/index.html site/css/main.css
$ stat -c '%a %A %n' site site/index.html
755 drwxr-xr-x site
644 -rw-r--r-- site/index.html

재귀적 chmod 작업은 되돌릴 수 없습니다. chmod는 변경 전 상태를 기록하지 않으므로, 복구 작업은 사용자가 직접 이전 상태를 기억해 내어 권한을 재설정해야 합니다. 이는 실수로 rm -rf를 실행한 후 파일을 복구하는 작업만큼이나 느리고 불확실한 작업입니다. 교훈은 동일합니다. 재귀적 명령을 실행하기 전에 대상이 무엇인지 반드시 확인하십시오.

대문자 X: 모든 파일이 아닌 디렉터리에만 실행 권한 적용

심볼릭 모드는 X뿐만 아니라 x도 허용합니다. X은 실행 권한이 필요한 경우에만 실행 비트를 설정합니다. 즉, 디렉터리이거나 이미 특정 사용자 계층에 대해 실행 비트가 설정된 일반 파일인 경우에만 적용됩니다. 이 규칙은 정확히 -R가 따르기를 원했던 규칙과 일치합니다.

$ chmod -R u=rwX,go=rX site
$ stat -c '%a %A %n' site site/css site/index.html site/css/main.css site/deploy.sh
755 drwxr-xr-x site
755 drwxr-xr-x site/css
644 -rw-r--r-- site/index.html
644 -rw-r--r-- site/css/main.css
755 -rwxr-xr-x site/deploy.sh

명령어 하나로 데이터 파일은 그대로 둔 채 디렉터리만 탐색 가능한 상태로 유지했습니다. 스크립트 파일은 이미 실행 비트를 가지고 있었기 때문에 해당 비트가 유지되었으며, 이는 X 규칙의 후반부 내용입니다. X은 파일의 현재 모드를 읽어 들여 적용하므로, 이미 모든 실행 비트를 잃어버린 파일은 이 방식으로 다시 실행 권한을 부여할 수 없습니다.

$ chmod 644 site/deploy.sh
$ chmod -R u=rwX,go=rX site
$ stat -c '%a %A %n' site/deploy.sh
644 -rw-r--r-- site/deploy.sh
$ site/deploy.sh
bash: site/deploy.sh: Permission denied
$ chmod u+x site/deploy.sh
$ stat -c '%a %A %n' site/deploy.sh
744 -rwxr--r-- site/deploy.sh
$ site/deploy.sh
hi

동일한 규칙이 반대 방향으로도 작동합니다. X는 파일이 이미 가지고 있는 실행 비트를 다른 계층으로 확장합니다.

$ chmod go+X site/deploy.sh
$ stat -c '%a %A %n' site/deploy.sh
755 -rwxr-xr-x site/deploy.sh

따라서 소문자 x은 실행 가능하게 만들려는 특정 파일 하나를 대상으로 하며, X는 디렉터리 트리 전체를 일괄 처리할 때 사용합니다. 현재 모드에 기반한 규칙이 아니라 파일 종류별로 정확한 모드를 지정하고 싶다면, find를 사용하여 작업을 분리하십시오.

find site -type d -exec chmod 755 {} +
find site -type f -exec chmod 644 {} +
chmod u+x site/deploy.sh

-type d은 디렉터리를 선택하고 -type f은 일반 파일을 선택하므로, 각 종류에 적절한 모드가 적용됩니다. -exec ... +은 파일마다 프로세스를 새로 생성하는 대신 여러 경로를 하나의 chmod 호출로 묶어 처리하므로, 수천 개의 항목이 있는 트리 구조에서 효율적입니다. 스크립트의 실행 비트는 별도의 행에서 의도적으로 다시 부여합니다.

Check the result before you walk away

Two commands find the mistakes that matter after any recursive change. The first lists directories you can no longer walk into.

find . -type d ! -perm -u+x

The second lists files that any account on the machine may edit.

find . -type f -perm -o+w

In -perm -o+w, the leading - means at least these bits, so it matches a file whose o class holds the write bit whatever else is set. Neither command printing anything is the result you want. Run both from the top of any tree you have just changed with -R, and run stat -c '%a %A %n' on the handful of paths you meant to change, so the mode you believe you set is the mode the kernel actually holds.

FAQ

chmod 755과 chmod u+x는 어떤 차이가 있습니까?

숫자 모드는 절대적인 방식입니다. 파일의 모든 권한 비트를 덮어쓰므로, 의도하지 않은 클래스의 권한까지 변경될 수 있습니다. 심볼릭 모드는 편집 방식입니다. u+x는 소유자에게 비트 하나를 추가할 뿐, 나머지 비트는 그대로 유지합니다. 파일의 최종 상태를 정확히 알고 있다면 숫자 모드를 사용하십시오. 특정 권한 하나만 추가하거나 제거하려면 심볼릭 모드를 사용하십시오. 명령 실행 전후에 stat -c '%a %A %n' <file>를 실행하면 출력 결과에서 차이를 확인할 수 있습니다.

웹 파일이 담긴 디렉터리에 chmod -R 755를 사용하는 것이 왜 좋지 않습니까?

-R은 디렉터리와 일반 파일에 동일한 절대 모드를 적용하는데, 이 둘은 서로 다른 비트 설정이 필요하기 때문입니다. 디렉터리는 내부로 진입하기 위해 실행 비트가 필요합니다. 반면 HTML이나 CSS 같은 데이터 파일은 실행 비트가 필요 없으며, 이를 실행 가능하게 설정하면 git 커밋 시 변경 사항으로 기록되고 rsync 복사 시에도 그대로 반영됩니다. chmod -R u=rwX,go=rX <dir>을 사용하여 디렉터리에만 실행 비트를 적용하거나, -type d-type f을 조합한 find을 사용하여 파일과 디렉터리 각각에 적절한 모드를 적용하십시오.

디렉터리에서 실행 비트는 어떤 역할을 합니까?

실행이 아니라 진입 권한을 부여합니다. 디렉터리 내부에는 실행할 대상이 없습니다. 실행 비트는 디렉터리 내부의 이름을 해석할 수 있는 권한이므로, 경로 끝에 있는 파일을 열려면 해당 경로상의 모든 디렉터리에 이 비트가 있어야 합니다. 읽기 비트는 별개이며 파일 목록을 조회할 수 있는 권한을 부여합니다. 두 비트는 독립적입니다. 실행 비트만 있으면 이미 이름을 알고 있는 파일을 열 수는 있지만 셸에서 와일드카드(glob) 확장은 불가능합니다. 반대로 읽기 비트만 있으면 파일 이름은 볼 수 있지만 파일을 열려고 시도하면 모두 실패합니다.

소문자 x 대신 대문자 X는 언제 사용해야 합니까?

명령을 재귀적으로 실행할 때는 항상 X을 사용하십시오. X는 디렉터리에 실행 비트를 설정하며, 일반 파일의 경우 이미 실행 비트가 하나라도 설정되어 있을 때만 실행 비트를 추가합니다. 따라서 한 번의 작업으로 데이터 파일을 프로그램으로 바꾸지 않으면서도 디렉터리 트리를 탐색할 수 있게 만듭니다. 특정 파일 하나를 대상으로 작업할 때는 소문자 x을 사용하십시오. 한 가지 주의할 점은 X는 파일의 모든 실행 비트가 이미 제거된 상태라면 이를 복구할 수 없다는 것입니다. 이 경우에는 chmod u+x <file>를 사용하여 비트를 다시 설정하십시오.

chmod로 파일 소유자를 변경할 수 있습니까?

아니요. chmod은 권한 비트만 변경합니다. 소유권은 사용자에게는 chown, 그룹에게는 chgrp이 부여하며, 다른 사용자에게 파일을 넘기려면 root 권한이 필요합니다. 권한 비트는 파일을 마지막으로 작성한 사람이 아니라 파일에 기록된 소유자와 그룹을 기준으로 확인되기 때문에 이 점이 중요합니다. stat -c '%U %G %a %n' <file>를 실행하여 소유자, 그룹, 모드를 함께 확인한 뒤 필요한 명령을 결정하십시오.