Computer >> 컴퓨터 >  >> 프로그래밍 >> Bash 프로그래밍

Bash 변수 완벽 가이드: 선언부터 내보내기까지

컴퓨터 과학(그리고 일상적인 컴퓨팅)에서 변수(variable)란 나중에 사용할 임의의 정보를 담아두는 메모리상의 위치를 말합니다. 다시 말해, 데이터를 넣고 꺼낼 수 있는 임시 저장 용기입니다. Bash 셸에서 이 데이터는 단어(컴퓨터 용어로는 문자열)이거나 숫자(정수)일 수 있습니다.

컴퓨터에서 변수를 의식적으로 사용해 본 적이 없더라도, 일상생활에서는 이미 변수를 사용하고 있었을 가능성이 높습니다. "저거 좀 줘" 또는 "이거 좀 봐"라고 말할 때 우리는 문법적 변수, 즉 대명사를 사용하는 것입니다. "이것"과 "저것"의 의미는 머릿속에 그리는 대상이나 손으로 가리키는 대상에 따라 달라지기 때문입니다. 수학을 할 때도 미지의 값을 나타내기 위해 변수를 사용하지만, 그것을 굳이 '변수'라고 부르지 않을 뿐입니다.

여러분이 매일 사용하고 있다는 사실을 모르고 있을 수도 있는 Bash 변수의 간단한 예를 살펴보겠습니다. PS1 변수는 터미널 프롬프트가 어떻게 표시될지에 대한 정보를 담고 있습니다. 예를 들어, PS1 변수를 재정의하여 백분율 기호(%)처럼 아주 단순한 형태로 설정할 수 있습니다:

$ PS1="% "
%

이 글은 Linux, BSD, Mac 또는 Cygwin에서 실행되는 Bash 셸의 변수를 다룹니다. Microsoft의 오픈 소스 PowerShell 사용자라면 PowerShell 변수에 관한 별도의 글을 참고하시기 바랍니다.

변수는 무엇에 쓰이나요?

Bash에서 변수가 필요한지 여부는 터미널에서 하는 작업에 따라 달라집니다. 일부 사용자에게 변수는 데이터 관리의 필수 수단이며, 다른 사용자에게는 사소하고 일시적인 편의 기능이고, 또 다른 사용자에게는 없는 것이나 마찬가지일 수 있습니다.

궁극적으로 변수는 하나의 도구입니다. 필요할 때 사용하거나, 운영체제가 알아서 관리한다는 안도감 속에 그냥 두어도 됩니다. 하지만 지식은 곧 힘입니다. Bash에서 변수가 작동하는 방식을 이해하면 예상치 못한 창의적인 문제 해결로 이어질 수 있습니다.

변수 설정 방법

변수를 생성하는 데 특별한 권한은 필요하지 않습니다. 생성도 자유롭고, 사용도 자유롭고, 대체로 무해합니다. Bash 셸(Linux 및 Mac)에서는 변수 이름을 정의하고 값을 지정하는 방식으로 변수를 만들 수 있습니다. 다음 예제는 FOO라는 새 변수를 만들고 /home/seth/Documents라는 문자열로 값을 설정합니다:

$ declare FOO="/home/seth/Documents"

성공했을 때는 아무런 출력이 없기 때문에 변수가 제대로 설정되었는지 확신하기 어려울 수 있습니다. echo 명령으로 직접 결과를 확인할 수 있으며, 변수 앞에 달러 기호($)를 붙여 변수를 불러옵니다. 변수가 정의된 그대로 정확하게 읽히도록 하려면 중괄호와 따옴표로 감싸는 것도 좋습니다. 이렇게 하면 변수에 포함될 수 있는 특수 문자가 그대로 보존됩니다. 이 예제에서는 해당되지 않지만, 좋은 습관으로 길러두면 유용합니다:

$ echo "${FOO}"
/home/seth/Documents

셸을 자주 사용하는 사람들에게 변수 설정은 일상적인 작업이라 과정이 다소 간소화되었습니다. 문자열 뒤에 등호(=)와 값이 오면 Bash는 자동으로 변수 설정으로 간주하므로 declare 키워드가 생략 가능합니다:

$ FOO="/home/seth/Documents"

변수는 보통 한 시스템에서 다른 시스템으로 정보를 전달하기 위해 사용됩니다. 이 간단한 예제에서 변수는 크게 유용하지 않지만, 여전히 정보를 전달하는 역할을 합니다. 예를 들어, FOO 변수의 내용이 파일 경로이므로 ~/Documents 디렉터리로 이동하는 지름길로 활용할 수 있습니다:

$ pwd
/home/seth
$ cd "${FOO}"
$ pwd
/home/seth/Documents

변수 이름은 예약되지 않은 문자열(정수와 밑줄 포함)이면 무엇이든 될 수 있습니다. 대문자로 쓸 필요는 없지만, 변수임을 쉽게 식별할 수 있도록 대문자로 작성하는 경우가 많습니다.

변수 삭제 방법

unset 명령으로 변수를 삭제할 수 있습니다:

$ unset FOO
$ echo $FOO

실제로 이 작업은 자주 필요하지 않습니다. 변수는 상대적으로 "비용이 저렴"해서, 생성해두고 더 이상 필요하지 않으면 그냥 잊어버려도 됩니다. 다만, 다른 프로세스가 변수를 읽을 때 잘못된 정보가 전달되지 않도록 변수가 비어 있음을 확실히 해야 하는 경우가 있을 수 있습니다.

충돌 방지 기능이 있는 새 변수 생성

때때로 자신이나 다른 프로세스에 의해 이미 변수가 설정되어 있을 가능성이 있다고 판단될 수 있습니다. 기존 값을 덮어쓰고 싶지 않다면, 기존 값이 비어 있는 경우가 아니라면 기존 값을 유지하는 특수 구문을 사용할 수 있습니다.

이 예제에서는 FOO/home/seth/Documents로 설정되어 있다고 가정합니다:

$ FOO=${FOO:-"bar"}
$ echo $FOO
/home/seth/Documents

콜론-대시(:-) 표기법은 기존 값을 기본값으로 사용하도록 합니다. 반대 상황에서 이 구문이 어떻게 작동하는지 확인하려면 변수를 삭제한 후 다시 시도해 보세요:

$ unset FOO
$ echo $FOO

$ FOO=${FOO:-"bar"}
$ echo $FOO
bar

자식 프로세스에 변수 전달

변수를 생성하면 지역 변수(local variable)라고 불리는 것이 만들어집니다. 즉, 해당 변수는 현재 셸, 그리고 오직 현재 셸에서만 인식됩니다.

이러한 동작은 변수의 범위(scope)에 대한 의도적인 제한입니다. 변수는 설계상 기본적으로 로컬에서만 접근 가능하며, 정보 공유를 '알 필요가 있는 대상에만' 허용하려는 철학을 담고 있습니다. 예를 들어 중요한 비밀번호를 평문으로 담은 변수를 실수로 생성했다 하더라도, 시스템이 원격 셸이나 악성 데몬(또는 변수를 생성한 세션 외부의 그 어떤 것)이 해당 비밀번호에 접근하는 것을 허용하지 않는다는 점을 알면 안심할 수 있습니다.

이 글의 시작 부분 예제를 사용해 프롬프트를 변경한 후, 현재 셸 안에서 새 셸을 시작해 보세요:

$ PS1="% "
% bash
$

새 셸을 시작하면 변경된 PS1 값이 아니라 기본 프롬프트가 표시됩니다. 자식 프로세스는 부모에서 설정된 변수를 상속받지 않기 때문입니다. 자식 프로세스를 종료하면 부모 셸로 돌아가며, 커스텀 PS1 프롬프트가 다시 나타납니다:

$ exit
%

자식 프로세스에 변수를 전달하려면 명령 앞에 변수 정의를 붙이는 방법(prepend)과, 변수를 자식 프로세스로 내보내는 방법(export) 중 하나를 사용할 수 있습니다.

변수 앞에 붙이기(Prepending)

명령을 실행하기 전에 원하는 만큼 많은 변수를 앞에 붙일 수 있습니다. 자식 프로세스가 해당 변수들을 실제로 사용하는지는 프로세스에 달려 있지만, 어느 쪽이든 변수를 전달할 수는 있습니다:

$ FOO=123 bash
$ echo $FOO
123
$

이 방식은 특정 라이브러리 경로가 필요한 애플리케이션을 실행할 때(LD_LIBRARY_PATH 변수 사용), 비표준 컴파일러로 소프트웨어를 빌드할 때(CC 변수 사용) 등에 유용하게 활용됩니다.

변수 내보내기(Exporting)

자식 프로세스가 변수를 사용할 수 있게 하는 또 다른 방법은 Bash에 내장된 export 키워드입니다. export 명령은 지정한 변수의 범위를 넓혀줍니다:

$ PS1="% "
$ FOO=123
$ export PS1
$ export FOO
% bash
% echo $PS1
%
% echo $FOO
123

두 방식 모두 전달되거나 내보내진 지역 변수에 접근할 수 있는 것은 자식 셸뿐만이 아니라 그 셸의 모든 자식 프로세스입니다. 같은 셸에서 애플리케이션을 시작하면 해당 변수는 애플리케이션 내부에서 환경 변수로 사용할 수 있습니다.

시스템 전반에서 사용할 수 있도록 내보낸 변수를 환경 변수(environment variables)라고 하며, 이는 다음 글에서 자세히 다룰 주제입니다. 그동안에는 일상적인 작업에 변수를 직접 활용해 보면서 워크플로우에 어떤 변화를 가져오는지 확인해 보시기 바랍니다.