부작용 (컴퓨터 과학)

컴퓨터 과학에서 함수가 결과값 이외에 다른 상태를 변경시킬 때 부작용이 있다고 말한다. 예를 들어, 함수가 전역변수나 정적변수를 수정하거나, 인자로 넘어온 것들 중 하나를 변경하거나 화면이나 파일에 데이터를 쓰거나, 다른 부작용이 있는 함수에서 데이터를 읽어오는 경우가 있다. 부작용은 프로그램의 동작을 이해하기 어렵게 한다.

명령형 프로그래밍은 부작용을 사용하여 프로그램이 동작하게 하는 것으로 알려져 있다. 함수형 프로그래밍은 부작용을 최소화하는 것으로 알려져 있다.

참조 투명성 
부작용을 이용하는 함수는 참조에 불투명()하고 그렇지 않은 함수는 참조에 투명()한 경우가 많다. 참조에 투명한 함수는 같은 인자를 주면 항상 같은 결과값을 돌려 주는 함수이다. 또 다른 용어로 참조에 투명한 함수는 결정 함수() 또는 결정론적 알고리즘이다.

부작용은 없지만 참조에 불투명한 함수도 있다. 예를 들어서 외부 세계를 측정하는 어떤 함수는 참조에 불투명하다. 예를 들어, 현재 시간을 컴퓨터의 시계에서 읽어오는 컴퓨터 함수는 같은 인자를 넘겨주더라도 다른 결과값을 돌려주어야 한다. 이것이 전역 상태를 전혀 바꾸지 않지만, 시간이라고 불리는 전역 상태가 변하여 영향을 받기 때문이다.

예제 
예제로 두 함수를 쓰기로 하자. 하나는 참조에 불투명하고 다른 하나는 참조에 투명하다.

  globalValue = 0;
  integer function rq(integer x)
  begin
    globalValue = globalValue + 1;
    return x + globalValue;
  end

  integer function rt(integer x)
  begin
    return x + 1;
  end

이제 rt는 참조에 투명하다. 왜냐하면 x의 값이 변하지 않는 이상 rt(x) = rt(x)이기 때문이다. 예를 들어, rt(6) = rt(6) = 7, rt(4) = rt(3+1) = 5 등이 성립한다. 그러나 rq에 대해서는 그런 말을 할 수 없는데 이것이 전역 변수를 변경하기 때문이다.

다음과 같은 코드를 보면 참조에 불투명함의 단점을 알 수 있다.

  integer p = rq(x) + rq(y) * (rq(x) - rq(x));

오른쪽 부분을 계산하여 정리하면 이렇게 될 것이다.

  integer p = rq(x) + rq(y) * (0) = 
  integer p = rq(x) + 0           = 
  integer p = rq(x);

그러나 이것은 rq에 대해서는 성립하지 않는데 rq(x)는 rq(x)와 같지 않기 때문이다. rq의 결과값은 전역값에 따라 차이가 있으며 그 전역값이 전달되는 것이 아니라 변경되고 있기 때문이다. 이것은 어떤 식에서 같은 식을 빼면 0이 된다는 상식을 깨뜨린다.

그러나 rt에 대해서는 이런 것들이 통할 것인데, 이것은 참조에 투명한 함수이기 때문이다.

부작용의 단점 
부작용은 프로그램의 버그가 발생하기 쉽게 한다. 프로그램을 테스트할때에는 발생하지 않았던 예외 상황들이 프로그램을 사용하면서 발견되지만 항상 일어나지 않는 예외 상황이 일어나서 버그를 고치기 어렵게 하기도 한다.

프로그램의 결과값을 계산하는 것 이외에 다른 상태를 변경시키므로 프로그램의 순서에 따라서 다른 결과가 나온다. 이것은 프로그램의 최적화와 느긋한 계산법을 하기에 좋지 않은 특성이며, 각각의 의존성을 심화시킨다. 심지어 최적화를 한 경우 실행 결과가 달라질 가능성도 있다. 실행 순서를 무시할 수 없기 때문에 프로그래머는 실행 순서를 정해주어야 하는 부담이 있다.

마지막으로 상식에서 통하는 방법으로 표현식을 값으로 대체하거나 값 대신 변수로 대체하는 일을 할 수 없게 되며 수학적으로 다루기 어렵게 된다.

컴퓨터 프로그래밍
프로그래밍 언어 이론
함수형 프로그래밍