개요
프로그래밍에서 함수를 호출할 때 매개변수를 전달하는 방식에 따라 함수 호출은 크게 두 가지로 나뉩니다. 바로 값에 의한 호출(Call by Value)과 참조에 의한 호출(Call by Reference)입니다. 이름 그대로, 값에 의한 호출은 인자의 실제 값을 복사하여 전달하는 방식이고, 참조에 의한 호출은 인자가 저장된 메모리 주소(참조)를 전달하는 방식입니다.
아래 표에서 두 호출 방식의 주요 차이점을 한눈에 비교해 보겠습니다.
| 번호 | 구분 기준 | 값에 의한 호출 | 참조에 의한 호출 |
|---|---|---|---|
| 1 | 명명 규칙 | 매개변수의 '값' 자체를 전달하여 함수를 호출하기 때문에 '값에 의한 호출'이라고 부릅니다. | 매개변수의 '참조(주소)'를 전달하여 함수를 호출하기 때문에 '참조에 의한 호출'이라고 부릅니다. |
| 2 | 내부 동작 방식 | 함수 호출 시 전달된 값이 함수 내부의 지역 매개변수로 복사됩니다. | 전달된 매개변수의 메모리 주소가 복사되어 함수의 지역 매개변수에 할당되므로, 원본 변수와 함수 내부 매개변수가 같은 메모리 위치를 가리킵니다. |
| 3 | 변경 사항의 영향 | 값이 복사된 것이므로 함수 내부에서 매개변수를 아무리 변경해도 원본 변수에는 영향을 주지 않습니다. | 두 변수가 같은 메모리 위치를 공유하므로 함수 내부에서 변경한 내용이 그대로 원본 변수에 반영됩니다. |
| 4 | 메모리 위치 | 원본 변수와 함수의 매개변수는 서로 다른 메모리 위치를 사용합니다. | 원본 변수와 함수의 매개변수는 동일한 메모리 위치를 공유합니다. |
| 5 | 지원 언어 | C, Java, PHP, Python 등 대부분의 언어에서 기본적인 인자 전달 방식으로 사용됩니다. | C++(포인터·참조자), C#(ref/out 키워드) 등에서 명시적으로 지원합니다. |
예제 1: 값에 의한 호출 (Call by Value)
다음 C 코드는 값에 의한 호출로 두 수를 교환(swap)하려는 예제입니다.
by_value.c
#include <stdio.h>
void swapByValue(int, int); /* 함수 원형 */
int main() {
int n1 = 10, n2 = 20;
swapByValue(n1, n2);
printf("n1: %d, n2: %d\n", n1, n2);
return 0;
}
void swapByValue(int a, int b) {
int t;
t = a; a = b; b = t;
}
실행 결과
n1: 10, n2: 20
함수 내부에서 a와 b의 값은 서로 바뀌었지만, 이는 복사된 지역 변수일 뿐입니다. 따라서 main 함수의 원본 변수 n1과 n2는 변하지 않습니다.
예제 2: 참조에 의한 호출 (Call by Reference)
이번에는 포인터를 이용해 변수의 주소를 전달하는 예제입니다.
by_reference.c
#include <stdio.h>
void swapByReference(int*, int*); /* 함수 원형 */
int main() {
int n1 = 10, n2 = 20;
swapByReference(&n1, &n2);
printf("n1: %d, n2: %d\n", n1, n2);
return 0;
}
void swapByReference(int *a, int *b) {
int t;
t = *a; *a = *b; *b = t;
}
실행 결과
n1: 20, n2: 10
함수에 변수의 주소를 전달했기 때문에, 함수 내부의 포인터 a와 b는 원본 변수 n1, n2가 있는 메모리 위치를 직접 가리킵니다. 따라서 역참조(*)를 통해 값을 변경하면 main 함수의 원본 변수도 함께 변경됩니다.
마무리 정리
값에 의한 호출은 원본 데이터가 복사되어 전달되므로 함수가 원본을 실수로 변경할 위험이 없어 안전성이 높습니다. 반면 참조에 의한 호출은 함수가 원본 데이터를 직접 수정할 수 있어, 여러 값을 반환하거나 큰 데이터를 복사 비용 없이 효율적으로 전달할 때 유용합니다. 각 방식의 특성을 이해하고 상황에 맞게 선택하는 것이 좋은 코드를 작성하는 핵심입니다.