참조 투명성

참조 투명성이란

표현식을 평가한 값으로 대체하거나 또는 그 반대로 값을 표현식으로 대체하더라도 프로그램의 동작이 변하지 않으면 해당 표현식을 참조 투명하다고 한다.

  • 참조한 값이나 표현식이 명확하게 드러나고, 예측 가능할 때, 그 코드를 투명하다고 한다.

  • 표현식이 예측 가능하기 위해선 순수해야 한다.

  • 동일한 입력에 대한 표현식의 값은 항상 동일해야 하며, 평가하는 과정에서 부수효과가 없어야 한다.

참조 투명성은 수식뿐만 아니라 함수 호출 등과 같이 모든 표현식에 적용할 수 있는 개념이다.

  • 구문(Statement) → 독립적으로 실행 가능한 코드의 조각, 자체적인 스코프를 가진다.

    • ex) if문, for문

  • 표현식(Expression) → 값으로 평가 가능한 코드 조각, 실행했을 때 어떤 값으로 변경되는 구문

    • ex) 사칙연산

  • 평가(Evaluation) → 코드를 계산해서 값을 구하는 과정 === 계산

  • 참조(Reference) → 어떤 값이나 표현식을 가리키는 간접적인 방법

참조 불투명한 경우

참조 불투명한 경우는 코드의 동작을 예측하기 어렵게 하고 디버깅을 어렵게한다.

  • 표현식에 가변적인 변수가 포함된 경우

  • 입력값 이외에 외부의 상태를 참조하거나 변경하는 경우

let totalPrice = 0;

const caclTotalPrice = (price: number): number => {
  totalPrice = totalPrice + price * 0.2;
  return totalPrice;
};

caclTotalPrice(1000); // 1200
caclTotalPrice(1000); // 1440

함수에 부수효과가 포함되어 있다면, 호출되는 횟수에 따라 애플리케이션 동작에 영향을 끼칠 수 있다.

즉, 부수효과가 포함된 함수는 참조 불투명하기 때문에 사용할 때 주의해야 한다.

참조 투명한 경우

부수효과가 없는 함수의 사용

const withVat = (price: number): number => price + price * 0.2;

// 표현식을 평가한 값으로 대체하거나 그 반대여도 동작은 변하지 않는다.
const totalPrice = 1200;
const totalPrice = withAat(1000);
// 참조를 평가식으로 변환해도 결과는 동일하다. 
totalPrice + totalPrice // 2400
withAat(1000) + withAat(1000); // 2400

장점

  • 코드의 동작이 예측 가능하므로 이해하기 쉽고, 테스트하기 용이하다

  • 입력값에만 의존하여 다른 코드와 독립적으로 사용할 수 있기 때문에 재사용성이 좋다.

  • 아무리 복잡한 코드라도 입력에 따른 출력이 명확하므로, 안심하고 리팩토링 가능

  • 함수를 직접 호출해야 할지 호출한 값을 사용해야 할지 고민할 필요가 없어지므로 함수 합성을 쉽게 할 수 있다.

  • 함수 호출 시점이나 실행 순서를 변경해도 결과가 동일하기 때문에 지연평가, 병렬실행 등을 통해 코드를 최적화할 수 있다.

Last updated