자바에서의 일급 객체와 함수형 프로그래밍

김소희·2025년 10월 28일

1. 일급 객체(First-Class Object)란?

일급 객체(First-Class Object)
다른 객체들에 일반적으로 적용 가능한 연산을 모두 지원하는 객체를 말한다.
즉, 함수(또는 메서드)를 값처럼 변수에 담거나, 인자로 전달하거나, 결과로 반환할 수 있음을 뜻한다.

일급 객체의 조건

  1. 변수에 할당할 수 있다.
  2. 함수의 인자(Argument)로 전달할 수 있다.
  3. 함수의 반환값(Return Value)으로 사용할 수 있다.

자바스크립트, 파이썬, 루비처럼 함수 자체가 객체인 언어들은 기본적으로 이 조건을 만족한다.
자바는 원래 일급 객체 개념이 없었지만, Java 8부터 람다(Lambda)Function 인터페이스가 도입되면서
함수도 일급 객체처럼 다룰 수 있게 되었다.


2. 자바에서의 일급 객체

① 변수에 할당할 수 있다

import java.util.function.Function;

public class Example1 {
    public static void main(String[] args) {
        Function<Integer, Integer> square = x -> x * x; // 함수 할당
        System.out.println(square.apply(5)); // 25
    }
}

Function<Integer, Integer> 타입의 변수 square에 람다식을 직접 할당했다.
자바의 Function 인터페이스는 (입력) → (출력) 형태의 함수를 표현한다.


② 함수를 인자로 전달할 수 있다

import java.util.function.Function;

public class Example2 {
    public static int operate(Function<Integer, Integer> func, int num) {
        return func.apply(num);
    }

    public static void main(String[] args) {
        Function<Integer, Integer> square = x -> x * x;
        int result = operate(square, 3);
        System.out.println(result); // 9
    }
}

operate()는 함수를 매개변수로 받는 고차함수(Higher-Order Function)이고,
square는 전달인자로 넘겨진 콜백 함수(Callback Function)이다.


③ 함수를 반환할 수 있다

import java.util.function.Function;

public class Example3 {
    public static Function<Integer, Integer> add(int n) {
        return x -> x + n;
    }

    public static void main(String[] args) {
        Function<Integer, Integer> add3 = add(3); // 함수 반환
        System.out.println(add3.apply(4)); // 7
    }
}

→ 함수(add)가 또 다른 함수를 리턴한다.
이 역시 자바에서의 고차함수 구현이다.


3. 고차함수(Higher-Order Function)란?

“함수를 인자로 받거나, 함수를 반환하는 함수”

함수형 프로그래밍의 핵심 개념 중 하나로,
로직을 재활용하고 추상화 수준을 높일 수 있게 한다.

자바에서는 Function, Consumer, Supplier, Predicate 등의
함수형 인터페이스(Functional Interface)를 통해 고차함수를 만들 수 있다.


4. 명령형 vs 선언형 프로그래밍

함수형 프로그래밍을 이해하려면
먼저 명령형(imperative) 과 선언형(declarative) 프로그래밍의 차이를 알아야 한다.

구분명령형 프로그래밍선언형 프로그래밍
초점어떻게(How) 해결할지무엇을(What) 할지
대표 언어C, Java(전통), PythonSQL, HTML, 함수형 Java
설명상태 변경 중심, 명령 나열상태 불변, 추상화 중심

💡 비유 1 — 레스토랑 자리

당신은 애인과 함께 레스토랑에 도착했다.
직원에게 이렇게 말할 수 있다.

명령형 방식 : “저기 창가 쪽 자리가 비었네요. 저 자리로 걸어가서 앉을게요.”
선언형 방식 : “두 명 앉을 자리 부탁해요.”

명령형은 “어떻게” 앉을지를 직접 지시,
선언형은 “무엇을 원하는지”만 말한다.

💡 비유 2 — 길 묻기

누군가 “OO호텔이 어디죠?”라고 묻는다면?

명령형 방식 : “이 길로 직진하다가 롯데리아에서 우회전, 두 번째 신호에서 좌회전하세요.”
선언형 방식 : “OO호텔은 xx로 xx길 10에 있어요.”

선언형은 구체적인 “과정”이 아니라 “목표 상태”를 말한다.
(호텔까지 가는 방법은 내비게이션이라는 추상화가 대신 수행한다.)

💡 코드 예시

import java.util.Arrays;
import java.util.List;

public class Example4 {
    public static void main(String[] args) {
        List<Integer> numbers = Arrays.asList(1,2,3,4,5,6,7,8,9,10);

        // 명령형 방식
        int result1 = 0;
        for (int n : numbers) {
            if (n % 2 == 0) result1 += n;
        }

        // 선언형 (함수형)
        int result2 = numbers.stream()
                             .filter(n -> n % 2 == 0)
                             .mapToInt(Integer::intValue)
                             .sum();

        System.out.println(result1); // 30
        System.out.println(result2); // 30
    }
}

명령형은 “어떻게 더할지” 하나하나 지시하고,
선언형은 “무엇을 더하고 싶은지”만 기술한다.
Stream 내부가 바로 “내비게이션” 역할을 하는 셈이다.


5. 함수형 프로그래밍의 핵심 개념

함수형 프로그래밍(Functional Programming)은 선언형 프로그래밍의 한 형태로,
상태를 직접 변경하지 않고, 순수한 함수를 조합해 프로그램을 구성한다.

핵심 세 가지 개념

개념설명
순수 함수 (Pure Function)동일한 입력에 대해 항상 동일한 결과를 반환하며, 외부 상태를 변경하지 않는다.
일급 객체 (First-Class Citizen)함수를 변수에 담거나 전달하고, 반환할 수 있다.
불변성 (Immutability)데이터의 상태를 직접 수정하지 않고, 새로운 데이터를 생성한다.

6. 함수형 프로그래밍이 주는 장점

  • 코드의 가독성 향상 (무엇을 하는지 명확함)
  • 부수효과(Side Effect) 최소화
  • 동시성(Concurrency) 에 안전
  • 테스트 용이성 증가
  • 재사용성과 유지보수성 향상

7. 마무리

자바는 본래 명령형 언어였지만,
람다식(Lambda)Stream API의 등장으로
함수형 프로그래밍의 장점을 흡수했다.

이제 자바 개발자도 함수를 값처럼 다루는 사고방식을 익히면
더 깔끔하고, 오류에 강한 코드를 작성할 수 있다.

결국 “함수를 데이터처럼 다루는 능력”이
일급 객체의 핵심이며,
함수형 프로그래밍의 시작점이다.

profile
개발자 소희의 노트

0개의 댓글