지난 시간 재귀 함수를 알아본 것에 이어, 이번엔 Helper 메소드 재귀와 순수 재귀에 대해 알아보자. 필수적인 개념은 아니지만, 알아두면 유용한 개념이라고 이해하면 되겠다!
이 글은 JavaScript 알고리즘 & 자료구조 마스터클래스를 참고하여 작성되었습니다.
만약 재귀함수를 통해 배열을 조작하고 싶다면 어떻게 해야할까? 예를 들어 여러 수가 들을 배열을 받아 그 중 홀수만 담은 새로운 배열을 리턴하고 싶다면 말이다.
function collectOddValues(arr) {
let result = [];
if (arr.length === 0) return;
if(arr[0] % 2 !== 0) {
result.push(arr[0]);
};
collectOddValues(arr.slice(1));
return result;
}
console.log(collectOddValues([1, 2, 3, 4, 5])); // [1]
[1, 3, 5]
가 나올 것이라는 기대와는 다르게 [1]
이 결과값으로 리턴된다. 이유는 collectOddValues함수가 실행될 때마다 result값이 초기화되기 때문이다. 그렇다면 result 변수를 상위 스코프로 옮겨보자.
let result = [];
function collectOddValues(arr) {
if (arr.length === 0) return;
if(arr[0] % 2 !== 0) {
result.push(arr[0]);
};
collectOddValues(arr.slice(1));
return result;
}
console.log(collectOddValues([1, 2, 3, 4, 5])); // [1, 3, 5]
결과 변수를 상위 스코프로 올렸더니 무사히 결과가 나온걸 확인할 수 있다. 근데 만약 해당 파일에 여러 함수가 존재하고, result 변수와 collectOddValues 사이에 무수히 많은 line이 존재한다면 변수와 함수 사이의 연관성을 확인하는 것이 쉽지 않을 것이다. 이때 활용할 수 있는 것이 바로 Helper 메소드 재귀이다.
function collectOddValues(arr) {
let result = [];
function helper(helperArr) {
if (helperArr.length === 0) return;
if(helperArr[0] % 2 !== 0) {
result.push(helperArr[0]);
};
helper(helperArr.slice(1));
}
helper(arr);
return result;
}
console.log(collectOddValues([1, 2, 3, 4, 5])); // [1, 3, 5]
Helper 메소드 재귀는 Helper라는 말 그대로 기존 재귀 함수를 도와주는 함수를 의미한다.
사용 방법은 아주 간단한데, 방법은 다음과 같다.
- 기존 collectOddValues 함수 내에 결과 값을 리턴할 변수를 선언한다.
- helper 함수를 선언하고 그 안에 기존 함수식을 작성한다.
- helper 함수에 매개변수를 전달해 호출하고, 결과값을 리턴한다.
이렇게 helper함수를 이용하면 결과 변수와 함수 간의 연관성을 유지할 수 있고, 전역 변수로 두지 않고도 변수를 조작할 수 있어 훨씬 안전하고 가독성이 뛰어나다.
그리고 Helper 메소드 재귀를 사용하지 않고, 순수 재귀를 이용한 방법도 있다.
function collectOddValues(arr) {
let newArr = [];
if (arr.length === 0) return newArr;
if(arr[0] % 2 !== 0) {
newArr.push(arr[0]);
};
newArr = newArr.concat(collectOddValues(arr.slice(1));
return result;
}
console.log(collectOddValues([1, 2, 3, 4, 5])); // [1, 3, 5]
- 마찬가지로 collectOddValues 내부에 결과 값을 리턴할 변수를 선언한다.
- 그리고 탈출 조건에 해당하면 해당 변수를 리턴한다.
- 해당 함수를 호출해 배열에 요소를 추가하는 대신, 계산이 완료되면 현재 배열과 모든 배열의 값을 하나의 배열롸 합쳐(concat) 반환한다.
만약 배열을 사용하고 + helper 메소드 없이 순수 재귀로만 로직을 구현하고 싶다면
→ 배열을 복사하는 slice
, spread
, concat
과 같은 연산자를 사용해 배열을 변경하지 않고도 배열을 조작할 수 있다. 객체의 경우는 Object.assign
이나 spread
연산자를 사용할 수 있다.