2025-02-22T01:33:42
This commit is contained in:
193
docs/03_함수형 프로그래밍.md
Normal file
193
docs/03_함수형 프로그래밍.md
Normal file
@@ -0,0 +1,193 @@
|
||||
# **코틀린 vs 자바: 함수형 프로그래밍 차이점**
|
||||
|
||||
코틀린은 **객체지향 프로그래밍(OOP)과 함수형 프로그래밍(FP)을 모두 지원**하는 하이브리드 언어다. 반면, 자바는 원래 객체지향 언어였지만, 자바 8 이후로 람다 표현식과 스트림 API를 도입하면서 함수형 스타일을 부분적으로 지원하게 되었다.
|
||||
|
||||
이 글에서는 **함수형 프로그래밍의 핵심 개념**인 **고차 함수, 람다 표현식, 확장 함수, 불변성** 등을 자바와 코틀린을 비교하며 설명하겠다.
|
||||
|
||||
---
|
||||
|
||||
## **1. 함수형 프로그래밍이란?**
|
||||
함수형 프로그래밍(FP, Functional Programming)은 **순수 함수**와 **불변성(immutability)**을 중심으로 하는 프로그래밍 패러다임이다. 핵심 원칙은 다음과 같다.
|
||||
|
||||
- **순수 함수 (Pure Function):** 같은 입력에 대해 항상 같은 출력을 반환하며, 외부 상태를 변경하지 않는다.
|
||||
- **불변성 (Immutability):** 데이터를 변경하지 않고 새로운 값을 반환하는 방식으로 동작한다.
|
||||
- **고차 함수 (Higher-Order Function):** 함수를 인자로 받거나 반환하는 함수.
|
||||
- **람다 표현식 (Lambda Expression):** 간결한 익명 함수 표현.
|
||||
|
||||
---
|
||||
|
||||
## **2. 함수 선언 방식 차이**
|
||||
|
||||
### **자바의 함수 선언 (객체지향 스타일)**
|
||||
```java
|
||||
public class Calculator {
|
||||
public static int add(int a, int b) {
|
||||
return a + b;
|
||||
}
|
||||
}
|
||||
```
|
||||
```java
|
||||
int result = Calculator.add(3, 5);
|
||||
```
|
||||
|
||||
### **코틀린의 함수 선언 (함수형 스타일 지원)**
|
||||
```kotlin
|
||||
fun add(a: Int, b: Int): Int {
|
||||
return a + b
|
||||
}
|
||||
```
|
||||
```kotlin
|
||||
val result = add(3, 5)
|
||||
```
|
||||
|
||||
> **차이점 요약:**
|
||||
> - 코틀린에서는 클래스 없이 **함수를 직접 정의 가능**(파일 수준 함수).
|
||||
> - `fun` 키워드를 사용하며 **반환 타입을 `:`로 지정**.
|
||||
> - 한 줄짜리 함수는 `{}` 없이 `=`로 간결하게 표현 가능.
|
||||
|
||||
```kotlin
|
||||
fun add(a: Int, b: Int) = a + b
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## **3. 람다 표현식 (Lambda Expression)**
|
||||
|
||||
람다 표현식은 **익명 함수(Anonymous Function)**의 한 형태로, 간결한 함수형 코드를 작성하는 데 사용된다.
|
||||
|
||||
### **자바의 람다 표현식 (Java 8 이상)**
|
||||
```java
|
||||
// 두 수를 더하는 람다 함수
|
||||
BiFunction<Integer, Integer, Integer> sum = (a, b) -> a + b;
|
||||
System.out.println(sum.apply(5, 3)); // 출력: 8
|
||||
```
|
||||
> 자바에서는 `BiFunction<T, U, R>` 같은 **함수형 인터페이스**를 사용해야 람다를 활용할 수 있다.
|
||||
|
||||
### **코틀린의 람다 표현식**
|
||||
```kotlin
|
||||
// 두 수를 더하는 람다 함수
|
||||
val sum: (Int, Int) -> Int = { a, b -> a + b }
|
||||
println(sum(5, 3)) // 출력: 8
|
||||
```
|
||||
> 코틀린은 별도의 함수형 인터페이스 없이 **람다 표현식을 바로 변수에 할당 가능**.
|
||||
|
||||
#### **더 간결한 표현**
|
||||
코틀린에서는 **타입 추론**이 가능하므로, 타입을 생략할 수도 있다.
|
||||
```kotlin
|
||||
val sum = { a: Int, b: Int -> a + b }
|
||||
```
|
||||
|
||||
> **차이점 요약:**
|
||||
> - 자바는 람다를 사용하려면 `BiFunction<>` 같은 **함수형 인터페이스**가 필요.
|
||||
> - 코틀린은 **별도의 인터페이스 없이 람다를 변수에 직접 할당 가능**.
|
||||
> - `{ 파라미터 -> 함수 본문 }` 형태로 사용.
|
||||
|
||||
---
|
||||
|
||||
## **4. 고차 함수 (Higher-Order Function)**
|
||||
|
||||
고차 함수는 **다른 함수를 인자로 받거나 반환하는 함수**를 의미한다.
|
||||
|
||||
### **자바에서 고차 함수 구현 (익명 클래스 사용)**
|
||||
자바에서는 **람다 도입 전**에는 익명 클래스를 활용해야 했다.
|
||||
```java
|
||||
public interface MathOperation {
|
||||
int operate(int a, int b);
|
||||
}
|
||||
|
||||
// 고차 함수
|
||||
public static int executeOperation(int x, int y, MathOperation operation) {
|
||||
return operation.operate(x, y);
|
||||
}
|
||||
|
||||
// 사용 예시
|
||||
int result = executeOperation(5, 3, new MathOperation() {
|
||||
@Override
|
||||
public int operate(int a, int b) {
|
||||
return a + b;
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
자바 8 이후에는 람다 표현식 덕분에 훨씬 간결해졌다.
|
||||
```java
|
||||
int result = executeOperation(5, 3, (a, b) -> a + b);
|
||||
```
|
||||
|
||||
### **코틀린에서 고차 함수 구현**
|
||||
코틀린에서는 **함수를 직접 타입으로 선언 가능**.
|
||||
```kotlin
|
||||
fun executeOperation(a: Int, b: Int, operation: (Int, Int) -> Int): Int {
|
||||
return operation(a, b)
|
||||
}
|
||||
|
||||
// 사용 예시
|
||||
val result = executeOperation(5, 3) { x, y -> x + y }
|
||||
```
|
||||
|
||||
> **차이점 요약:**
|
||||
> - 자바에서는 **인터페이스를 먼저 정의해야 하지만**, 코틀린에서는 **함수를 직접 타입으로 선언 가능**.
|
||||
> - 코틀린의 람다는 **더 간결한 문법 제공**.
|
||||
|
||||
---
|
||||
|
||||
## **5. 확장 함수 (Extension Function)**
|
||||
|
||||
자바에서는 기존 클래스를 확장하려면 **상속(Inheritance)이나 유틸리티 클래스**를 사용해야 한다.
|
||||
|
||||
### **자바의 유틸리티 메서드 방식**
|
||||
```java
|
||||
public class StringUtils {
|
||||
public static String greet(String name) {
|
||||
return "Hello, " + name + "!";
|
||||
}
|
||||
}
|
||||
System.out.println(StringUtils.greet("Java"));
|
||||
```
|
||||
|
||||
### **코틀린의 확장 함수**
|
||||
코틀린에서는 **기존 클래스에 새로운 메서드를 추가하는 것처럼 확장 가능**.
|
||||
```kotlin
|
||||
fun String.greet(): String {
|
||||
return "Hello, $this!"
|
||||
}
|
||||
|
||||
println("Kotlin".greet()) // 출력: Hello, Kotlin!
|
||||
```
|
||||
|
||||
> **차이점 요약:**
|
||||
> - 자바에서는 **유틸리티 클래스의 정적 메서드**를 사용해야 함.
|
||||
> - 코틀린에서는 **클래스를 수정하지 않고도 확장 함수로 기능 추가 가능**.
|
||||
|
||||
---
|
||||
|
||||
## **6. 불변성과 컬렉션 처리**
|
||||
|
||||
### **자바의 불변 컬렉션**
|
||||
```java
|
||||
List<String> names = List.of("Alice", "Bob"); // 변경 불가능한 리스트 (Java 9+)
|
||||
```
|
||||
|
||||
### **코틀린의 불변 컬렉션**
|
||||
```kotlin
|
||||
val names = listOf("Alice", "Bob") // 변경 불가능한 리스트
|
||||
```
|
||||
|
||||
> **차이점 요약:**
|
||||
> - 코틀린은 `listOf()`, `setOf()` 등을 통해 불변 컬렉션을 쉽게 생성 가능.
|
||||
> - 자바 8까지는 `Collections.unmodifiableList()`를 사용해야 했음.
|
||||
|
||||
---
|
||||
|
||||
## **정리: 자바 vs 코틀린 함수형 프로그래밍**
|
||||
|
||||
| 기능 | 자바 | 코틀린 |
|
||||
|------|------|--------|
|
||||
| 람다 표현식 | `(a, b) -> a + b` (`BiFunction` 필요) | `{ a, b -> a + b }` (함수형 타입 지원) |
|
||||
| 고차 함수 | 함수형 인터페이스 필요 | 함수 타입 `(Int, Int) -> Int` 직접 사용 가능 |
|
||||
| 확장 함수 | 유틸리티 메서드 필요 | `fun String.greet() = "Hello, $this"` |
|
||||
| 불변 컬렉션 | `List.of()` (Java 9+) | `listOf()` |
|
||||
|
||||
코틀린은 자바보다 함수형 프로그래밍을 **더 자연스럽고 간결하게 지원**한다.
|
||||
|
||||
다음에는 어떤 개념을 비교해볼까?
|
||||
Reference in New Issue
Block a user