부작용 (컴퓨터 과학)
"오늘의AI위키"의 AI를 통해 더욱 풍부하고 폭넓은 지식 경험을 누리세요.
1. 개요
부작용(컴퓨터 과학)은 함수의 실행이 예상된 반환 값 외에 다른 방식으로 프로그램의 상태를 변경하는 것을 의미한다. 부작용을 가진 함수는 참조 투명성을 해치며, 이는 같은 입력에 대해 항상 같은 결과를 반환해야 하는 순수 함수의 특징과 대조된다. 멱등성은 함수를 여러 번 적용해도 시스템 상태에 단일 적용과 동일한 영향을 미치는 특징을 의미하며, C 언어의 할당 연산자는 부작용의 대표적인 예시이다. 부작용은 프로그램의 디버깅을 어렵게 만들고, 최적화를 방해하며, 수학적 분석을 복잡하게 만들 수 있다.
더 읽어볼만한 페이지
- 프로그래밍 언어 이론 - 튜링 완전
튜링 완전은 계산 이론에서 시스템이 튜링 기계와 동등한 계산 능력을 갖춰 튜링 기계가 계산할 수 있는 모든 함수를 계산하고 범용 튜링 기계를 시뮬레이션할 수 있음을 의미하며, 튜링 동등이라고도 한다. - 프로그래밍 언어 이론 - 커리-하워드 대응
커리-하워드 대응은 증명 시스템과 계산 모델 간의 동형성을 나타내며, 증명은 프로그램이고 증명하는 공식은 프로그램의 타입이라는 일반화를 통해 논리 프로그래밍의 기초가 되어 현대 타입 이론 연구에 큰 영향을 미쳤다. - 함수형 프로그래밍 - 패턴 매칭
패턴 매칭은 데이터 구조나 문자열에서 특정 패턴을 찾아 식별하는 기법으로, 다양한 프로그래밍 언어와 시스템에서 사용되며 데이터 필터링, 추출 및 선언적 프로그래밍에 중요한 역할을 수행한다. - 함수형 프로그래밍 - 익명 함수
익명 함수는 이름이 없는 함수로, 람다 추상, 람다 함수, 람다 표현식, 화살표 함수 등으로 불리며, 함수형 프로그래밍 언어에서 람다식 형태로 많이 사용되고 고차 함수의 인수, 클로저, 커링 등에 활용되지만, 재귀 호출의 어려움이나 기능 제한과 같은 단점도 존재한다. - 컴퓨터 프로그래밍 - 순서도
순서도는 컴퓨터 알고리즘이나 프로세스를 시각적으로 표현하는 도구로, 흐름 공정 차트에서 기원하여 컴퓨터 프로그래밍 분야에서 알고리즘을 설명하는 데 사용되며, 다양한 종류와 소프트웨어 도구가 존재한다. - 컴퓨터 프로그래밍 - 의사코드
의사코드는 컴퓨터 과학 및 수치 계산 분야에서 알고리즘을 설명하기 위해 사용되는 비표준적인 언어로, 자연어와 프로그래밍 언어의 요소를 혼합하여 알고리즘의 논리적 흐름을 이해하기 쉽게 하고 프로그래머가 실제 코드로 구현하기 전에 알고리즘을 설계하고 검토하는 데 유용하다.
부작용 (컴퓨터 과학) |
---|
2. 참조 투명성 (Referential Transparency)
참조 투명성은 어떤 표현식(함수 호출 등)을 그 값으로 대체해도 프로그램의 동작에 영향을 미치지 않는다는 성질이다. 참조 투명성을 만족하기 위해서는 표현식이 순수 함수여야 한다. 즉, 표현식은 결정론적 알고리즘 (동일한 입력에 대해 항상 동일한 값을 반환)이어야 하고 부작용이 없어야 한다.
2. 1. 참조 투명성과 결정 함수
부작용을 이용하는 함수는 '''참조에 불투명'''하고 그렇지 않은 함수는 '''참조에 투명'''한 경우가 많다. 참조에 투명한 함수는 같은 인자를 주면 항상 같은 결과값을 돌려주는 함수이다. 또 다른 용어로 참조에 투명한 함수는 결정 함수 또는 결정론적 알고리즘이라고 한다.부작용은 없지만 참조에 불투명한 함수도 있다. 예를 들어 외부 세계를 측정하는 어떤 함수는 참조에 불투명하다. 예를 들어, 현재 시간을 컴퓨터의 시계에서 읽어오는 컴퓨터 함수는 같은 인자를 넘겨주더라도 다른 결과값을 돌려주어야 한다. 이것은 전역 상태를 전혀 바꾸지 않지만, 시간이라고 불리는 전역 상태가 변하여 영향을 받기 때문이다.
2. 2. 부작용이 없는 참조 불투명 함수
부작용을 이용하는 함수는 참조에 불투명(referentially opaque영어)하고 그렇지 않은 함수는 참조에 투명(referentially transparent영어)한 경우가 많다. 참조에 투명한 함수는 같은 인자를 주면 항상 같은 결과값을 돌려주는 함수이다. 또 다른 용어로 참조에 투명한 함수는 결정 함수(deterministic function영어) 또는 결정론적 알고리즘이다.부작용은 없지만 참조에 불투명한 함수도 있다. 예를 들어 외부 세계를 측정하는 어떤 함수는 참조에 불투명하다. 예를 들어, 현재 시간을 컴퓨터의 시계에서 읽어오는 컴퓨터 함수는 같은 인자를 넘겨주더라도 다른 결과값을 돌려주어야 한다. 이것이 전역 상태를 전혀 바꾸지 않지만, 시간이라고 불리는 전역 상태가 변하여 영향을 받기 때문이다.
2. 3. 예제
예제로 두 함수를 쓰기로 하자. 하나는 참조에 불투명하고 다른 하나는 참조에 투명하다.```c
globalValue = 0;
integer function rq(integer x)
{
globalValue = globalValue + 1;
return x + globalValue;
}
integer function rt(integer x)
{
return x + 1;
}
```
이제 `rt`는 참조에 투명하다. 왜냐하면 `x`의 값이 변하지 않는 이상 `rt(x) = rt(x)`이기 때문이다. 예를 들어, `rt(6) = rt(6) = 7, rt(4) = rt(3+1) = 5` 등이 성립한다. 그러나 `rq`에 대해서는 그런 말을 할 수 없는데 이것이 전역 변수를 변경하기 때문이다.
다음과 같은 코드를 보면 참조에 불투명함의 단점을 알 수 있다.
```c
integer p = rq(x) + rq(y) * (rq(x) - rq(x));
```
오른쪽 부분을 계산하여 정리하면 이렇게 될 것이다.
```c
integer p = rq(x) + rq(y) * (0) =
integer p = rq(x) + 0 =
integer p = rq(x);
```
그러나 이것은 `rq`에 대해서는 성립하지 않는데 `rq(x)`는 `rq(x)`와 같지 않기 때문이다. `rq`의 결과값은 전역값에 따라 차이가 있으며 그 전역값이 전달되는 것이 아니라 변경되고 있기 때문이다. 이것은 어떤 식에서 같은 식을 빼면 0이 된다는 상식을 깨뜨린다.
그러나 `rt`에 대해서는 이런 것들이 통할 것인데, 이것은 참조에 투명한 함수이기 때문이다.
3. 부작용 (Side Effect)
함수가 결과값을 반환하는 것 외에 다른 상태를 변경시키는 것을 부작용이라고 한다. 부작용은 프로그램의 동작을 예측하기 어렵게 만들고, 버그 발생 가능성을 높인다.[1]
부작용이 없어야 참조 투명성을 만족할 수 있지만, 이것만으로는 충분하지 않다. 참조 투명성은 표현식(함수 호출 등)을 해당 값으로 대체할 수 있음을 의미한다. 이를 위해서는 표현식이 순수 함수여야 하는데, 이는 표현식이 결정적 알고리즘(동일한 입력에 대해 항상 동일한 값을 반환)이어야 하고 부작용이 없어야 함을 뜻한다.
C 언어의 할당 연산자는 부작용의 대표적인 예시이다. `a = b`와 같은 할당문은 `b`와 동일한 값으로 평가되는 표현식이며, 동시에 `b`의 R-값을 `a`의 L-값에 저장하는 부작용을 일으킨다. 이러한 특성 덕분에 다중 할당이 가능하다.
a = (b = 3); // b = 3은 3으로 평가되며, 이 값이 a에 할당된다.
오른쪽 결합 연산자이므로, 위 코드는 아래와 같다.
a = b = 3;
이는 초보 프로그래머가 혼동하기 쉬운 함정을 만든다.
while (b == 3) {} // b가 3인지 확인
위 코드를 아래와 같이 혼동할 수 있다.
while (b = 3) {} // b = 3은 3으로 평가되고, true로 변환되어 무한 반복
3. 1. 부작용의 단점
부작용은 프로그램에 버그가 발생하기 쉽게 만든다. 프로그램을 테스트할 때는 나타나지 않았던 예외 상황들이 실제 사용 중에 발견될 수 있다. 이러한 예외 상황은 항상 발생하는 것이 아니기 때문에 디버깅을 더욱 어렵게 만든다.[1]프로그램의 결과값을 계산하는 것 외에 다른 상태를 변경시키기 때문에, 프로그램의 실행 순서에 따라 결과가 달라진다. 이는 프로그램의 최적화 및 느긋한 계산법 적용을 어렵게 만들고, 각 의존성을 심화시킨다. 심지어 최적화 후 실행 결과가 달라질 가능성도 있다. 실행 순서를 무시할 수 없으므로, 프로그래머는 실행 순서를 직접 지정해야 하는 부담을 갖게 된다.[1]
또한, 상식적인 방법으로 표현식을 값으로 대체하거나, 값 대신 변수로 대체하는 것이 불가능해져 수학적으로 분석하기 어려워진다.[1]
3. 2. 시간적 부작용 (Temporal Side Effects)
연산 실행에 소요되는 시간으로 인해 발생하는 부작용은 일반적으로 부작용 및 참조 투명성에 대한 논의에서 무시된다. 하드웨어 타이밍이나 테스트와 같은 일부 경우, 시간적 부작용을 위해sleep(5000)
또는 for (int i = 0; i < 10000; ++i) {}
와 같은 명령어를 특별히 삽입하기도 한다. 이러한 명령어는 완료하는 데 일정 시간이 걸린다는 점 외에는 상태를 변경하지 않는다.4. 멱등성 (Idempotence)
부작용이 있는 서브루틴은 여러 번 적용해도 시스템 상태에 한 번 적용한 것과 같은 영향을 주는 경우 멱등성을 가진다고 한다. 이는 서브루틴과 연관된 시스템 상태 공간에서 자기 자신으로의 함수가 수학적 의미에서 멱등성인 경우를 말한다.
순수 함수는 수학적 의미에서 멱등성이면 멱등성을 가진다.
4. 1. 멱등성 예제
서브루틴에 부작용이 있는 경우, 여러 번 적용해도 시스템 상태가 한 번 적용한 것과 동일하게 유지된다면, 즉 서브루틴과 관련된 시스템 상태 공간에서 자기 자신으로의 함수가 수학적 의미에서 멱등성을 가지면 멱등성을 가진다고 한다.예를 들어, 다음 파이썬 프로그램의 `setx` 함수를 보자.
```python
x = 0
def setx(n):
global x
x = n
setx(3)
assert x == 3
setx(3)
assert x == 3
```
`setx(3)`을 두 번 호출해도 `x`의 값은 3으로 유지된다. 두 번째 호출은 첫 번째 호출과 동일한 영향을 시스템 상태에 미치기 때문에 `setx`는 멱등성을 가진다.
순수 함수는 수학적 의미에서 멱등성을 가지면 멱등성을 가진다고 한다. 다음 파이썬 프로그램의 `abs` 함수를 보자.
```python
def abs(n):
return -n if n < 0 else n
assert abs(abs(-3)) == abs(-3)
```
`abs` 함수는 `abs(abs(-3))`과 `abs(-3)`의 결과가 같으므로 멱등성을 가진다.
5. C 언어에서의 부작용 예시 (할당 연산자)
C 언어의 할당 연산자는 부작용 동작의 흔한 예시이다. 할당 `a = b`는 `b`와 동일한 값으로 평가되는 표현식이며, `b`의 R-값을 `a`의 L-값에 저장하는 부작용이 있다. 이를 통해 다중 할당이 가능하다.
```c
a = (b = 3); // b = 3은 3으로 평가되며, 이 값이 a에 할당된다.
```
연산자가 오른쪽 결합하므로, 이것은 다음과 같다.
```c
a = b = 3;
```
이는 초보 프로그래머가 혼동할 수 있는 잠재적인 함정을 제시한다.
```c
while (b == 3) {} // b가 3으로 평가되는지 테스트
```
다음과 같이 혼동할 수 있다.
```c
while (b = 3) {} // b = 3은 3으로 평가되며, true로 변환되어 루프가 무한 반복된다.
참조
[1]
간행물
トランジスタ技術
https://toragi.cqpub[...]
CQ出版社
[2]
기타
プログラム言語論
http://www.cs.tsukub[...]
筑波大学
[3]
서적
Cクイックリファレンス第二版
オライリー・ジャパン
[4]
웹사이트
2020-10-09
[5]
간행물
Compiler Detection of Function Call Side Effects
James Cook University
1994-01
[6]
웹사이트
2020-10-09
[7]
문서
[8]
문서
본 사이트는 AI가 위키백과와 뉴스 기사,정부 간행물,학술 논문등을 바탕으로 정보를 가공하여 제공하는 백과사전형 서비스입니다.
모든 문서는 AI에 의해 자동 생성되며, CC BY-SA 4.0 라이선스에 따라 이용할 수 있습니다.
하지만, 위키백과나 뉴스 기사 자체에 오류, 부정확한 정보, 또는 가짜 뉴스가 포함될 수 있으며, AI는 이러한 내용을 완벽하게 걸러내지 못할 수 있습니다.
따라서 제공되는 정보에 일부 오류나 편향이 있을 수 있으므로, 중요한 정보는 반드시 다른 출처를 통해 교차 검증하시기 바랍니다.
문의하기 : help@durumis.com