[Typescript] readonly와 순수 함수

Bam·2022년 3월 7일
0

Typescript

목록 보기
21/32
post-thumbnail

순수 함수

우선 순수 함수에 대해 설명을 해야합니다. 순수 함수(pure function)이란 함수형 프로그래밍에서 사용되는 언어로 함수가 수행하는 기능 외에 다른 효과가 나타나지 않는 것을 의미(부작용이 없다)합니다. 순수 함수가 아니고 기능 외에 다른 효과가 나타나는 함수를 불순 함수(impure function)이라고 부릅니다.

불순 함수는 순수 함수로 만드는 조건에 부합하게 재작성하면 순수 함수로 만들 수 있으며, 순수 함수의 조건에는 다음과 같은 조건들이 있습니다.

  • 함수 내부에 입출력 코드가 존재하면 안 된다.
  • 함수 내부에서 매개변수가 변경되면 안 된다.
  • 함수는 만들어진 결과를 즉시 반환한다.
  • 함수 내부에 전역/정적 변수를 사용하지 않는다.
  • 함수가 예외를 발생시키지 않는다.
  • 함수가 콜백이거나 함수 몸통에 콜백을 사용하면 안 된다.
  • 함수 내부에 비동기 처리 코드가 존재하면 안 된다.

다음과 같이 매개변수로 배열을 받아서 push를 통해 배열을 변경(= 매개변수를 변경)하는 것은 불순 함수의 대표적인 예시입니다.

let arr: number[] = [1, 2, 3];

const pushArr = (arr: number[]): number[] => {
    arr.push(4);

    return arr;
}

pushArr(arr);
console.log(arr);

readonly 타입 지정자

타입스크립트에서는 함수형 프로그래밍을 위해 순수 함수를 구현하기 쉽도록 readonly라는 키워드를 지원하고있습니다. 사용 방법은 변하면 안되는 매개변수 타입 앞에 readonly 키워드를 붙이기만 하면 됩니다. 이렇게 붙인 매개변수는 함수 내부에서 변경을 감지하면 오류를 띄워줍니다.

let arr: number[] = [1, 2, 3];

const pushArr = (arr: readonly number[]): number[] => {
    arr.push(4); //매개변수로 받은 배열을 변화시키므로 에러!

    return arr;
}

pushArr(arr);
console.log(arr);

그러면 함수 내부에서 배열은 어떻게 사용할까?

순수 함수를 유지하는 것이 좋고, 그에 필요한 키워드도 알았는데 그러면 순수 함수 내부에서 배열의 가공은 어떻게 할까요?

얕은 복사와 깊은 복사

우선 복사란 어떤 변수값을 다른 변수값으로 설정하는 것을 의미합니다.

let a = 4;
let b = a;

얕은 복사(shallow-copy)는 변수(객체 등)은 별도의 존재로 생성하지만, 그 안의 내용은 동일한 것을 의미합니다. 다음 코드는 얕은 복사의 예제입니다.

let arr: number[] = [1, 2, 3];
let copiedArr: number[] = arr;

copiedArr.push(4);

console.log(arr);
console.log(copiedArr);

복사한 변수에 push를 통해 값을 조작했지만, 원본인 arr도 값이 변했음을 알 수 있습니다.


반대로 깊은 복사(deep-copy)는 변수(객체 등)을 별도로 생성하고, 그안의 정보나 로직 등도 별도로 생성하는 것을 의미합니다. 다음 코드는 깊은 복사의 예제입니다.

let a: number = 4;
let b: number = a;

b += 1;

console.log(a);
console.log(b);

복사한 변수에 1을 더한 것이 기존 변수에 어떠한 영향도 미치지 않았습니다. 이는 깊은 복사로 인해 값과 로직이 동일한 별개의 변수로 복사되었기 때문입니다.

배열의 깊은 복사

그럼 순수 함수에서 배열을 가공하기 위에서는 원본(매개변수로 전달 된 배열)을 깊은 복사로 복사해서 이용하는 것이 좋다는 것을 우리는 알 수 있습니다.

배열의 깊은 복사를 위해서는 전개 연산자 ...를 이용합니다.

let arr: number[] = [1, 2, 3];
let copiedArr: number[] =[ ...arr];

copiedArr.push(4);

console.log(arr);
console.log(copiedArr);

전개 연산자의 깊은 복사 덕분에 기존 배열은 기존 배열대로, 복사본은 본사본 대로 동작합니다. 이런 점을 이용해서 우리는 순수 함수 내부에서 배열을 사용할 땐 전개 연산자를 이용한 깊은 복사를 하고, 깊은 복사된 배열을 기존 배열을 사용하듯이 이용 할 수 있다는 것을 알게 되었습니다.

또한 배열의 정제와 가공을 담당하는 filter와 map 메소드도 깊은 복사를 기반으로 진행되기 때문에 순수 함수 내부에서 사용 가능한 메소드입니다.

0개의 댓글