Pink Spider/Java는 multi paradigm 언어일까?

Created Mon, 20 Oct 2025 13:50:50 +0900 Modified Mon, 08 Dec 2025 08:41:47 +0900
1259 Words 6 min

Java는 멀티 패러다임 언어인가?

Java는 멀티 패러다임 언어라고 할 수 있습니다. 특히 Java 8 이후로는 더욱 명확해졌습니다. 초기에는 “순수한” 객체지향 언어를 목표로 했지만, 시간이 지나면서 다양한 프로그래밍 패러다임을 수용하게 되었습니다.

Java가 지원하는 프로그래밍 패러다임

1. 객체지향 프로그래밍 (OOP) - 핵심 패러다임

// 클래스, 상속, 캡슐화, 다형성
public class Animal {
    private String name;
    
    public void makeSound() {
        System.out.println("Some sound");
    }
}

public class Dog extends Animal {
    @Override
    public void makeSound() {
        System.out.println("Woof!");
    }
}

2. 명령형 프로그래밍 (Imperative)

// 상태 변경과 제어 흐름을 명시적으로 작성
public static int factorial(int n) {
    int result = 1;
    for (int i = 1; i <= n; i++) {
        result *= i;  // 상태 변경
    }
    return result;
}

3. 함수형 프로그래밍 (Functional) - Java 8+

import java.util.*;
import java.util.function.*;
import java.util.stream.*;

public class FunctionalExample {
    public static void main(String[] args) {
        // 1. 람다 표현식과 고차 함수
        Function<Integer, Integer> square = x -> x * x;
        Function<Integer, Integer> addOne = x -> x + 1;
        
        // 함수 합성
        Function<Integer, Integer> squareThenAdd = square.andThen(addOne);
        System.out.println(squareThenAdd.apply(3)); // 10
        
        // 2. 불변성과 순수 함수
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
        List<Integer> doubled = numbers.stream()
            .map(n -> n * 2)  // 원본을 변경하지 않음
            .collect(Collectors.toList());
        
        // 3. 함수를 파라미터로 전달
        calculate(10, 5, (a, b) -> a + b); // 15
        calculate(10, 5, (a, b) -> a * b); // 50
    }
    
    static void calculate(int x, int y, BinaryOperator<Integer> operation) {
        System.out.println(operation.apply(x, y));
    }
}

4. 제네릭 프로그래밍 (Generic)

// 타입 파라미터를 사용한 일반화
public class Box<T> {
    private T content;
    
    public void set(T content) {
        this.content = content;
    }
    
    public T get() {
        return content;
    }
}

// 제네릭 메서드
public static <T extends Comparable<T>> T findMax(List<T> list) {
    return list.stream()
        .max(Comparable::compareTo)
        .orElse(null);
}

5. 동시성/병렬 프로그래밍 (Concurrent/Parallel)

import java.util.concurrent.*;

public class ConcurrentExample {
    public static void main(String[] args) throws Exception {
        // CompletableFuture를 사용한 비동기 프로그래밍
        CompletableFuture<String> future1 = CompletableFuture
            .supplyAsync(() -> fetchDataFromAPI1());
            
        CompletableFuture<String> future2 = CompletableFuture
            .supplyAsync(() -> fetchDataFromAPI2());
            
        // 두 작업을 결합
        CompletableFuture<String> combined = future1
            .thenCombine(future2, (result1, result2) -> result1 + " " + result2);
            
        System.out.println(combined.get());
    }
}

6. 반응형 프로그래밍 (Reactive) - 라이브러리 사용

// RxJava 또는 Project Reactor 사용 예제
Flux.just(1, 2, 3, 4, 5)
    .filter(n -> n % 2 == 0)
    .map(n -> n * 2)
    .subscribe(System.out::println);

다양한 패러다임을 혼합한 실제 예제

import java.util.*;
import java.util.concurrent.*;
import java.util.stream.*;

// OOP: 클래스와 인터페이스 정의
interface DataProcessor<T> {
    CompletableFuture<List<T>> process(List<T> data);
}

public class HybridExample implements DataProcessor<Integer> {
    private final ExecutorService executor = Executors.newFixedThreadPool(4);
    
    @Override
    public CompletableFuture<List<Integer>> process(List<Integer> data) {
        // 함수형 + 동시성 프로그래밍
        return CompletableFuture.supplyAsync(() -> 
            data.parallelStream()           // 병렬 처리
                .filter(n -> n > 0)         // 함수형: 필터링
                .map(this::complexCalculation)  // 메서드 참조
                .sorted()                    // 정렬
                .collect(Collectors.toList()),
            executor
        );
    }
    
    // 명령형 스타일의 복잡한 계산
    private Integer complexCalculation(Integer n) {
        int result = n;
        for (int i = 0; i < 3; i++) {
            result = result * 2 + 1;
        }
        return result;
    }
    
    public static void main(String[] args) throws Exception {
        HybridExample processor = new HybridExample();
        List<Integer> data = Arrays.asList(1, -2, 3, 4, -5, 6);
        
        // 비동기 처리 시작
        CompletableFuture<List<Integer>> future = processor.process(data);
        
        // 콜백 체인 (함수형)
        future.thenApply(result -> {
            System.out.println("처리 결과: " + result);
            return result;
        })
        .thenAccept(result -> {
            // 결과 활용
            int sum = result.stream().mapToInt(Integer::intValue).sum();
            System.out.println("합계: " + sum);
        })
        .get(); // 완료 대기
        
        processor.executor.shutdown();
    }
}

Java의 멀티 패러다임 특징

장점

  • 점진적 도입: 기존 OOP 코드베이스에 함수형 요소를 점진적으로 도입 가능
  • 유연성: 문제에 가장 적합한 패러다임 선택 가능
  • 생태계: 다양한 스타일의 라이브러리와 호환

한계

  • 완전하지 않은 함수형: 불변성이 언어 차원에서 강제되지 않음
  • 혼재된 스타일: 여러 패러다임이 섞여 일관성 유지가 어려울 수 있음
  • 학습 곡선: 모든 패러다임을 효과적으로 사용하려면 학습이 필요

결론

Java는 “실용적인” 멀티 패러다임 언어입니다. 순수한 함수형 언어(Haskell)나 순수한 객체지향 언어(Smalltalk)와 달리, Java는 실용성을 중시하며 여러 패러다임의 장점을 선택적으로 활용할 수 있게 설계되었습니다. 특히 Java 8 이후로는 현대적인 프로그래밍 패러다임을 적극적으로 수용하고 있어, 진정한 멀티 패러다임 언어로 진화했다고 볼 수 있습니다.