폴드엘과 폴드알 함수의 차이점
1. 이게 뭔가요?
프로그래밍 언어에서 데이터 목록을 차례대로 합쳐 하나의 결과로 만드는 연산인 폴드엘과 폴드알의 정확한 차이와 작동 원리를 설명합니다. 두 함수는 흔히 왼쪽과 오른쪽에서 목록을 접는 방식으로 오해되지만, 실제로는 둘 다 목록을 왼쪽에서 오른쪽으로 똑같이 탐색합니다. 핵심적인 차이는 연산이 결합하는 방향에 있으며, 컴퓨터가 메모리를 처리하고 계산을 미루는 방식에 따라 프로그램의 효율이 완전히 달라집니다.
2. 왜 화제인가요?
초보 개발자는 하스켈처럼 결과를 당장 계산하지 않고 미뤄두는 지연 평가 언어에서 폴드엘과 폴드알의 차이를 모르면 컴퓨터 메모리가 낭비되거나 프로그램이 느려지는 문제를 겪기 쉽습니다. 저자는 엄격한 언어와 지연 평가 언어에서 각각 어떤 방식을 써야 메모리를 아끼고 효율적으로 동작하는지 그 원리를 명확하게 짚어 줍니다.
3. 핵심 내용
폴드엘과 폴드알은 각각 왼쪽과 오른쪽에서 목록을 접는 함수가 아닙니다. 두 함수 모두 목록을 왼쪽에서 오른쪽으로 똑같이 탐색하며, 차이점은 연산이 묶이는 방향인 결합성에 있습니다. 컴퓨터가 코드를 위에서 아래로 즉시 계산하는 엄격한 언어에서는 폴드엘이 목록을 탐색하면서 일정한 기억 공간만 사용하여 반복 계산을 효율적으로 처리할 수 있습니다. 반면에 폴드알은 계산을 시작하기 전에 목록의 길이만큼 컴퓨터 메모리에 임시 작업 공간을 미리 만들어야 합니다. 하스켈처럼 계산을 나중에 필요할 때까지 미루는 게으른 언어에서는 상황이 달라집니다. 게으른 언어에서 기본 왼쪽 접기 방식인 폴드엘을 쓰면 계산을 당장 하지 않고 미뤄둔 작업 덩어리가 입력 목록의 크기에 비례해서 점점 더 커집니다. 이 때문에 거대한 작업 덩어리를 쌓아두지 않고 목록을 훑어나가면서 중간 계산 결과를 효율적으로 갱신하는 엄격한 왼쪽 접기 버전인 폴드엘프라임을 사용해야 합니다. 폴드엘프라임은 목록의 다음 요소로 넘어가기 전에 미뤄둔 작업 덩어리를 먼저 강제로 계산해 버리므로 일정한 기억 공간만 쓰면서 목록을 계속 훑어나갈 수 있습니다. 반면에 오른쪽에서부터 접는 폴드알은 계산을 미루는 성질을 가지고 있습니다. 덧셈처럼 결과를 곧바로 계산하는 엄격한 연산과 쓰면 차이가 없지만, 계산을 미루는 지연 연산과 함께 쓰면 계산식이 늘어나 컴퓨터가 멈춰도 되는 상태에 도달합니다. 만약 전체 결과 리스트를 다 소비하지 않고 앞에서부터 두 개의 값만 골라내는 함수와 함께 쓰면, 합계를 구하는 함수가 값을 더하기 위해 리스트를 강제로 읽어 들일 때 미뤄둔 계산을 아예 평가하지 않으며 리스트를 전부 살펴보지 않고 일부만 거쳐 지나가게 됩니다. 따라서 요약 함수가 두 번째 전달인자에 대해 계산을 미루는 방식을 쓰고 결과 리스트를 전부 소모하지 않는다면, 폴드알이 불필요한 연산을 줄여 효율적으로 작동할 수 있습니다. 폴드알은 끝없이 이어지는 무한 리스트를 대상으로도 작동할 수 있습니다. 결론적으로 값을 누적하는 함수가 결과를 즉시 계산하는 엄격한 성질을 가졌다면 일정한 메모리 공간만 쓰며 리스트를 처리할 수 있는 엄격한 왼쪽 접기 함수인 폴드엘프라임을 사용해야 합니다. 값을 누적하는 함수가 두 번째 전달인자에 대해 계산을 미루는 성질을 가졌다면 작업을 조금씩 나누어 처리하여 데이터 흐름을 원활하게 만들고 일을 줄일 수 있도록 폴드알을 사용해야 합니다. 기본 폴드엘이나 엄격한 폴드알은 리스트를 다룰 때 성능이 더 떨어지므로 사용하지 말아야 합니다. 다만 이 내용은 오직 목록 자료 구조에만 적용되며, 데이터를 반대 방향으로 쌓아 올리는 스녹 목록이나 나뭇가지 형태의 나무 구조에서는 결합 방향이 달라지므로 상황에 맞는 다른 접는 함수를 고려해야 합니다.
4. 나에게 어떤 영향이 있나요?
일반 독자는 컴퓨터 내부의 메모리 관리나 프로그래밍 언어의 작동 방식을 깊게 몰라도 프로그램이 동작하는 기본 원리를 이해하는 데 도움이 됩니다. 직접 코드를 작성하는 개발자는 하스켈 같은 지연 평가 언어에서 목록을 처리할 때 누적 함수가 엄격한지 지연적인지 따져보고 적절한 폴드 방식을 골라야 합니다. 예를 들어 값이 확정된 계산에는 메모리 누수를 막는 엄격한 폴드엘프라임 방식을 쓰고, 무한히 긴 목록이나 일부만 필요한 작업에는 지연적인 폴드알 방식을 써서 불필요한 연산을 줄일 수 있습니다. 다만 이 글에서 다루는 최적화는 데이터의 크기가 클 때 의미가 있으며, 짧은 목록을 다룰 때는 프로그램 성능에 큰 차이가 없으므로 가벼운 마음으로 참고하는 것이 좋습니다.