셸 스크립트든, 파이썬이든, C++이든, 심지어 스크래치(Scratch)든 코드를 작성해 본 적이 있다면 변수가 얼마나 중요한지 잘 알 것입니다. 컴퓨터와 개발자는 변수를 일종의 중간 거점처럼 활용하며, 그 사이에서 정보를 몰래 주고받습니다. 예를 들어 셸 스크립트에서 사용자 이름을 처리해야 한다면, 변수를 하나 만들고 그 안에 사용자 이름을 넣은 뒤, 컴퓨터에게 해당 변수로 무언가를 하도록 지시하는 방식입니다(예를 들어 허가된 사용자 목록과 대조하기). 변수는 코드가 동적으로 작동할 수 있게 해주기 때문에 중요합니다. 즉, 코드를 실행할 때마다 달라질 것으로 예상되는 정보를 담는 자리 표시자 역할을 하는 것입니다.
그런데 변수는 워낙 흔하게 사용되다 보니 다루기 번거로워지기도 합니다. 하나의 코드 프로젝트에 변수가 너무 많이 모이면 전부 추적하는 것이 거의 불가능해집니다. 관련된 변수 앞에 공통 접두어를 붙이는(user_name, user_pass, user_time 등) 영리한 규칙을 사용하거나, 참조하기 쉽도록 어딘가에 마스터 목록을 만들어 둘 수도 있지만, 이 모든 것을 관리하는 부담은 점점 커지기 마련입니다.
이 문제에 대한 전통적인 해답이 바로 배열입니다. 배열은 Bash를 포함한 대부분의 프로그래밍 언어에서 훌륭하게 작동해 왔습니다.
인덱스 배열과 연관 배열
대부분의 셸은 인덱스 배열(indexed array)을 생성하고 조작하고 조회하는 기능을 제공합니다. 쉽게 말해 인덱스 배열이란 숫자가 붙은 항목들의 목록입니다. 이 항목 목록과 각각에 할당된 숫자는 하나의 변수에 깔끔하게 담기므로, 코드 안에서 손쉽게 '휴대'할 수 있습니다.
하지만 Bash에는 연관 배열(associative array)을 만드는 기능이 있으며, 이 배열을 다른 배열과 똑같이 취급합니다. 연관 배열을 사용하면 단순히 숫자로 매겨진 값이 아니라 키(key)와 값(value)의 쌍으로 이루어진 목록을 만들 수 있습니다.
임의의 키에 값을 할당할 수 있습니다:
$ declare -A userdata
$ userdata[name]=seth
$ userdata[pass]=8eab07eb620533b083f241ec4e6b9724
$ userdata[login]=`date --utc +%s`
키를 통해 값을 조회할 수 있습니다:
$ echo "${userdata[name]}"
seth
$ echo "${userdata[login]}"
1583362192
배열에서 기대할 수 있는 일반적인 연산 대부분이 지원됩니다. 예를 들어 모든 값을 나열할 수 있습니다:
$ echo "${userdata[*]}"
8eab07eb620533b083f241ec4e6b9724 seth 1583362192
배열 전체를 확인할 수도 있습니다:
$ typeset -A
declare -A BASH_ALIASES='()'
declare -A BASH_CMDS='()'
declare -A userdata='([pass]="8eab07eb620533b083f241ec4e6b9724"
[name]="seth"
[login]="1583362192" )'
unset 명령으로 배열에서 특정 항목을 제거할 수도 있습니다:
$ unset userdata[pass]
$ typeset -A
[...]
declare -A userdata='([name]="seth"
[login]="1583362192" )'
마지막으로, 배열 전체를 삭제할 수도 있습니다.
$ unset "userdata[*]"
데이터 저장을 위한 배열
배열은 서로 관련된 데이터를 한곳에 모아 두는 데 유용한 도구입니다. 대부분의 경우 일반 변수만으로도 충분하지만, 때로는 하나의 데이터 '객체'에 속한 여러 속성을 배열에 담아 데이터를 통합하고 색인해 두는 편이 더 논리적일 수 있습니다. 예를 들어 utmp에서 가져온 로그인 이름과 시간을 처리한다면, 두 데이터를 아무런 연관성 없는 별개의 변수로 저장하기보다는 로그인 시간을 해당 사용자와 연관시켜 두는 것이 훨씬 유용합니다.
더욱이 변수와 달리, 배열의 항목은 데이터를 저장하기 전에 미리 존재할 필요가 없습니다. 데이터를 저장하기 전에 정확히 얼마나 많은 데이터가 저장될지 알 필요도 없습니다. 통제하거나 예측할 수 없는 데이터를 처리할 때 이것이 큰 장점이 됩니다. utmp에 하루에 몇 명의 사용자가 기록될지 알 수 없다면, 모든 항목을 담는 스크립트를 작성하기 어렵습니다. 하지만 배열을 사용하면 배열 하나만 선언하고 데이터를 읽어 들이면 됩니다. 새로운 키-값 쌍을 계속 생성하면서 더 이상 읽어 들일 데이터가 없을 때까지 진행하면 되는 것입니다.
배열은 강력한 도구이며, Bash를 넘어 다양한 프로그래밍 언어에서 널리 사용됩니다. 지금 바로 배열을 활용해 보세요!