함수형 프로그래밍

sungs·2025년 7월 1일

자바

목록 보기
26/95

함수형 프로그래밍이란?

함수형 프로그래밍은 순수 함수(Pure Function)를 사용하여 부수 효과(Side Effect)를 최소화하고, 프로그램의 상태 변화를 피하는 프로그래밍 패러다임입니다. 쉽게 말해, 수학 함수처럼 입력이 같으면 항상 같은 출력을 보장하고, 외부의 상태를 변경하지 않는 함수들을 중심으로 코드를 작성하는 방식입니다.

주요 특징:

  • 불변성(Immutability): 데이터의 생성 후에는 그 상태를 변경하지 않습니다. 새로운 값이 필요하면 기존 데이터를 복사하여 새로운 데이터를 생성합니다.

  • 순수 함수(Pure Function):동일한 입력에 대해 항상 동일한 출력을 반환합니다. 함수 외부의 어떤 상태도 변경하지 않습니다 (부수 효과 없음).

  • 고차 함수(Higher-Order Function): 함수를 인자로 받거나 함수를 반환할 수 있는 함수입니다. 람다 표현식이 대표적인 예시입니다.

  • 선언형 프로그래밍(Declarative Programming): "무엇을" 할 것인지에 집중하며, "어떻게" 할 것인지는 라이브러리나 프레임워크에 위임합니다.

왜 자바에서 함수형 프로그래밍이 중요할까요?

자바 8부터 함수형 프로그래밍 요소가 도입된 것은 우연이 아닙니다. 현대 소프트웨어 개발에서 함수형 프로그래밍은 여러 이점을 제공합니다.

  1. 병렬 처리 용이성: 불변성과 순수 함수의 특징 덕분에 함수형 코드는 스레드에 안전하며, 병렬 처리에 매우 유리합니다. 복잡한 동기화 문제로부터 자유로워질 수 있습니다.

  2. 코드 간결성 및 가독성: 람다 표현식과 스트림 API를 활용하면 반복문(for-loop) 등을 대체하여 코드를 훨씬 간결하고 직관적으로 작성할 수 있습니다.

  3. 유지보수성 향상: 부수 효과가 없으므로 함수의 동작을 예측하기 쉽고, 이는 버그 발생률을 낮춰 유지보수를 용이하게 만듭니다.

  4. 테스트 용이성: 순수 함수는 독립적으로 테스트하기 매우 쉽습니다. 특정 입력에 대한 출력을 예상할 수 있으므로 단위 테스트 작성이 훨씬 간단해집니다.

자바 함수형 프로그래밍 핵심 요소

자바에서 함수형 프로그래밍을 가능하게 하는 주요 요소들은 다음과 같습니다.

1. 람다 표현식 (Lambda Expressions)

람다는 익명 함수를 생성하는 간결한 방법입니다. 함수형 인터페이스(추상 메서드가 하나뿐인 인터페이스)의 인스턴스를 표현하는 데 사용됩니다.

// 기존 익명 클래스
new Thread(new Runnable() {
    @Override
    public void run() {
        System.out.println("기존 익명 클래스");
    }
}).start();

// 람다 표현식
new Thread(() -> System.out.println("람다 표현식")).start();

2. 함수형 인터페이스 (Functional Interfaces)

오직 하나의 추상 메서드만 가지는 인터페이스를 의미합니다. @FunctionalInterface 어노테이션을 사용하여 명시적으로 선언할 수 있습니다. 자바에서 제공하는 대표적인 함수형 인터페이스는 Predicate, Function, Consumer, Supplier 등이 있습니다.

@FunctionalInterface
interface MyFunction {
    int calculate(int a, int b);
}

public class FunctionalInterfaceExample {
    public static void main(String[] args) {
        MyFunction add = (a, b) -> a + b;
        MyFunction multiply = (a, b) -> a * b;

        System.out.println("덧셈: " + add.calculate(10, 5));
        System.out.println("곱셈: " + multiply.calculate(10, 5));
    }
}

3. 스트림 API (Stream API)

컬렉션의 데이터를 함수형 방식으로 처리할 수 있도록 도와주는 API입니다. 데이터를 선언적으로 처리하며, 필터링, 매핑, 정렬, 집계 등 다양한 연산을 파이프라인 형태로 연결할 수 있습니다.

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class StreamApiExample {
    public static void main(String[] args) {
        List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David", "Eve");

        // 이름이 'A'로 시작하는 요소를 필터링하고 대문자로 변환하여 리스트로 수집
        List<String> filteredNames = names.stream()
                                          .filter(name -> name.startsWith("A"))
                                          .map(String::toUpperCase)
                                          .collect(Collectors.toList());

        System.out.println(filteredNames); // [ALICE]

        // 모든 이름의 길이를 합산
        int totalLength = names.stream()
                               .mapToInt(String::length)
                               .sum();

        System.out.println("총 길이: " + totalLength);
    }
}

함수형 프로그래밍 적용 시 고려사항

함수형 프로그래밍은 많은 장점을 가지고 있지만, 모든 상황에 만능은 아닙니다.

  • 학습 곡선: 초기에 익숙해지는 데 시간이 걸릴 수 있습니다. 특히 기존의 명령형 프로그래밍에 익숙한 개발자라면 더욱 그렇습니다.

  • 디버깅: 복잡한 스트림 파이프라인의 경우 디버깅이 어려울 수 있습니다.

  • 성능: 특정 상황에서는 명령형 코드보다 성능이 떨어질 수 있습니다. 하지만 대부분의 경우, 스트림 API는 최적화되어 있으므로 크게 문제가 되지 않습니다.

결론

자바 함수형 프로그래밍은 코드를 더 간결하고, 읽기 쉽게, 그리고 유지보수하기 쉽게 만들어주는 강력한 패러다임입니다. 람다, 함수형 인터페이스, 스트림 API를 적극적으로 활용하여 코드의 품질을 높이고, 현대적인 자바 개발 환경에 발맞춰 나가는 것이 중요합니다.

profile
앱 개발 공부 중

0개의 댓글