스크립트의 규모가 커지면 중복되는 코드를 줄이기 위해 함수(Function)를 사용해야 합니다.
POSIX 표준을 따르면서 어디서나 잘 작동하는 함수 작성법을 알아봅니다.
기본 문법
가장 중요한 차이점은 function이라는 키워드를 쓰지 않는다는 것입니다.
# POSIX 표준 방식 (권장 ✅)
함수이름() {
# 실행할 내용
}
# Bash 전용 방식 (POSIX에서는 지양 ❌)
# function 함수이름 { ... }
- 함수 정의: 반드시 함수를 호출하기 전에 먼저 정의되어 있어야 합니다. (보통 스크립트 상단에 배치)
- 호출: 함수 이름만 적으면 실행됩니다. (괄호
()없이 이름만 사용)
인자 전달 (Arguments)
함수로 값을 보낼 때는 별도의 파라미터 이름을 정의하지 않고, 스크립트 실행 인자와 똑같이 위치 매개변수($1, $2, …)를 사용합니다.
greet() {
printf "안녕하세요, %s님!\n" "$1"
}
greet "홍길동" # $1에 "홍길동"이 전달됨
| 변수 | 의미 |
$1, $2 | 첫 번째, 두 번째 인자 |
$# | 함수에 전달된 인자의 총 개수 |
$@ | 전달된 모든 인자 목록 |
지역 변수 (Local Variables) 주의사항
이 부분이 POSIX 표준의 가장 큰 제약사항입니다.
- Bash:
local 키워드를 사용하여 함수 내부에서만 쓰는 변수를 만들 수 있습니다.
- POSIX (sh):
표준에는 local 키워드가 없습니다.
함수 안에서 선언한 변수도 기본적으로 전역 변수(Global)가 되어 스크립트 전체에 영향을 줍니다.
해결책: 함수 내에서만 쓰는 변수는 _var_name처럼 앞에 언더바를 붙이거나, 이름이 겹치지 않게 주의해서 지어야 합니다.
반환값 (Return Value)
함수의 실행 결과를 처리하는 방법은 두 가지입니다.
| 구분 | 종료 상태 코드 (Exit Status) | 표준 출력 (Standard Output) |
| 데이터 타입 | 0 ~ 255 사이의 정수 | 문자열 (텍스트 데이터) |
| 확인 방법 | $? 변수로 확인 | $(함수이름) (명령어 치환)으로 캡처 |
| 주 용도 | 성공(0) 또는 실패(그 외) 판별 | 처리된 결과값 전달 (이름, 날짜 등) |
| 비유 | “내 일 잘 끝냈어!” (결과 보고서의 합격/불합격 도장) | “내가 만든 결과물이야.” (결과 보고서의 내용물) |
① return: 종료 상태 코드 반환
숫자(0~255)만 반환할 수 있으며, 주로 성공(0)과 실패(그 외)를 알리는 용도입니다.
is_file_exist() {
if [ -f "$1" ]; then
return 0 # 성공
else
return 1 # 실패
fi
}
② printf/echo: 데이터 결과 반환
문자열이나 계산 결과 자체를 받아야 할 때는 출력문을 이용하고 명령어 치환($())으로 낚아챕니다.
get_date() {
printf "%s" "$(date +%Y-%m-%d)"
}
TODAY=$(get_date)
printf "오늘 날짜: %s\n" "$TODAY"
간단한 예시
#!/bin/sh
get_user_status() {
_USER_NAME="TestUser1" # 실제 사용자 이름을 여기에 설정
if [ "$_USER_NAME" = "TestUser" ]; then
# 1. 표준 출력으로 문자열을 내보냄 (반환 문자열)
printf "Active User"
# 2. 종료 코드로 성공을 알림 (명령어 마지막 실행 결과가 0)
return 0
else
printf "Unknown"
return 1
fi
}
# 실행 및 데이터 캡처
STATUS_TEXT=$(get_user_status) # "Active User"가 변수에 저장됨 , 출력 문자열($()): 함수가 무슨 데이터를 만들었는지 알려줌 (실제 값)
STATUS_CODE=$? # 0이 변수에 저장됨
printf "문자열 결과: %s\n" "$STATUS_TEXT"
printf "상태 코드: %d\n" "$STATUS_CODE"
로깅 함수 만들기
실제 프로젝트에서 유용하게 쓸 수 있는 메시지 출력 함수 예시입니다.
#!/bin/sh
# 로깅 함수 정의
log_message() {
_LEVEL="$1"
_MSG="$2"
_TIME=$(date '+%H:%M:%S')
# 형식: [시간] [로그레벨] 메시지
printf "[%s] [%s] %s\n" "$_TIME" "$_LEVEL" "$_MSG"
}
# 함수 호출
log_message "INFO" "애플리케이션을 시작합니다."
log_message "WARN" "설정 파일이 없습니다. 기본값을 사용합니다."
if [ "$?" -eq 0 ]; then # 상태 코드($?): 마지막 함수가 어떻게 끝났는지 알려줌 (성공/실패)
log_message "SUCCESS" "작업이 성공적으로 끝났습니다."
fi
핵심 요약 (Checklist)
function키워드는 빼자: 그냥name() { ... }형식을 사용하세요.local은 표준이 아니다: 변수 이름 충돌에 주의하세요.- 인자는
$1,$2로: 함수 호출 시 옆에 나열하면 됩니다. - 복잡한 결과는
printf로: 값을 돌려받고 싶을 땐 출력을 이용하세요.
주의사항
“출력되는 모든 것” : 함수 안에서 printf나 echo로 찍는 모든 내용은 밖에서 $( )로 감싸는 순간 하나의 반환 문자열로 합쳐집니다.
my_func() {
printf "Hello "
printf "World"
}
RESULT=$(my_func)
# RESULT에는 "Hello World"가 들어갑니다.
$? 사용 시 주의 : $?는 바로 직전 명령의 상태코드라서 즉시 변수에 저장하는 습관이 중요해요.
STATUS_CODE=$? # 이 줄은 OK # 하지만 이런 경우 주의! some_func echo "결과 출력" # 이 줄이 실행되면 $?가 덮어씌워짐 echo $? # some_func의 코드가 아님!
$()와 서브쉘 비용
RESULT=$(my_func) # 서브쉘이 생성됨 → 성능 비용 있음


