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

자바스크립트의 값 전달과 참조 전달, 정확히 이해하기

자바스크립트는 기본적으로 값에 의한 전달(Pass by Value) 방식을 사용하는 언어입니다. 다만 객체(Object)의 경우, 그 '값' 자체가 곧 참조(Reference)라는 점이 중요합니다. 이 차이를 이해하면 함수 내부에서 변수를 조작할 때 원본 데이터가 어떻게 영향을 받는지 명확하게 예측할 수 있습니다.

원시 타입(Primitive Type)은 값 자체가 복사됩니다

예를 들어, 숫자(int)를 함수의 매개변수로 전달하고 함수 안에서 값을 증가시켜도, 호출자(caller) 쪽의 변수 값은 전혀 변경되지 않습니다. 함수에는 원본이 아닌 복사본이 전달되기 때문입니다.

예제 코드

let i = 0;
function increment(x) {
    x = x + 1
    console.log(x)
}
increment(i)
console.log(i)

실행 결과

1
0

함수 내부에서는 x가 1로 증가해 1이 출력되지만, 외부의 i는 여전히 0인 것을 확인할 수 있습니다. 즉, 원시 타입은 함수로 전달될 때 값이 복사되므로 원본에 영향을 주지 않습니다.

객체는 '참조값'이 전달됩니다

객체를 함수에 전달할 때는 두 가지 경우로 나누어 생각해야 합니다.

  • 참조 자체를 재할당하는 경우: 함수 내부에서 매개변수에 새로운 객체를 할당하면, 이는 지역 변수의 참조만 바뀌는 것이므로 원본 객체에는 영향을 주지 않습니다.
  • 객체의 내부 상태를 변경(mutate)하는 경우: 매개변수가 가리키는 객체의 속성을 추가하거나 수정하면, 같은 객체를 참조하고 있기 때문에 원본 객체에도 그대로 반영됩니다.

예제 코드

let obj = {'foo': 'bar'};
function updateRef(x) {
    // x의 지역 참조만 변경되며 obj에는 영향 없음
    x = {}
}
function addHelloWorld(y) {
    // y가 참조하는 객체에 새 속성 추가
    y['hello'] = 'world';
}
console.log(obj)
updateRef(obj)
console.log(obj)
addHelloWorld(obj)
console.log(obj)

실행 결과

{ foo: 'bar' }
{ foo: 'bar' }
{ foo: 'bar', hello: 'world' }

결과 분석

첫 번째 함수 updateRef에서는 객체 참조를 새 객체로 바꿨지만 원본 객체는 변하지 않았습니다. 이는 지역 변수 x만 재할당된 것이기 때문입니다. 반면 두 번째 함수 addHelloWorld에서는 y가 여전히 원본 obj 객체를 참조하고 있었고, 해당 객체의 내부 상태(속성)를 직접 변경했기 때문에 원본 객체에 hello: 'world' 속성이 추가된 것입니다.

정리

자바스크립트는 엄밀히 말해 항상 값에 의한 전달 방식입니다. 다만 객체의 값이 '참조'이기 때문에, 함수 내부에서 객체의 내용을 수정하면 원본에 영향을 미치고, 참조 변수 자체를 재할당하면 원본에 영향을 미치지 않습니다. 이 개념을 정확히 이해하면 의도치 않은 사이드 이펙트(side effect)를 예방하고 더 안전한 코드를 작성할 수 있습니다.