함수형 프로그래밍 6편 - 함수형 사고 방식과 문제 해결 전략

2025. 7. 23. 17:16·CS 기초부터 한 걸음씩

함수형 프로그래밍은 문제를 데이터 흐름 중심으로 재구성하는 시각이다.


1. 왜 함수형 사고가 필요한가?

✅ 선언형 사고로의 전환

전통적인 명령형 사고는 “무엇을 어떻게 할 것인가”에 집중한다. 반면 함수형 사고는 “무엇을 할 것인가”에 집중한다.

📌 예시: 1부터 5까지의 짝수 제곱합 계산

// 1단계: 명령형 사고
var sum = 0
for (i in 1..5) {
    if (i % 2 == 0) sum += i * i
}

// 2단계: 선언형 전환
val evens = (1..5).filter { it % 2 == 0 }
val squares = evens.map { it * it }
val result = squares.sum()

// 3단계: 함수형으로 고도화 (파이프라인화)
val result2 = (1..5)
    .filter { it % 2 == 0 }
    .map { it * it }
    .sum()

➡️ 점진적으로 절차 → 선언 → 함수형 파이프라인으로 고도화하는 사고 전환 예시


2. 사고의 단위: 흐름을 중심으로 문제를 나눈다

✅ 작은 함수로 쪼개기 + 조합하기

함수형에서는 다음과 같이 사고한다:

  • 데이터를 어떻게 “변환”할까?
  • 필터링, 매핑, 축약이 어떻게 이어지는가?

✅ 사고 흐름 예시: 문자열 처리

val input = listOf(" apple ", "banana", "  cherry")
val cleaned = input
    .map { it.trim() }
    .filter { it.length > 5 }
    .sorted()

➡️ 하나의 흐름으로 구성된 파이프라인을 중심으로 문제를 분할한다.


3. 상태 대신 흐름을 설계한다

✅ 상태를 최소화하는 사고

함수형은 가능한 상태를 갖지 않는다. 그 대신 “값 → 값” 흐름으로 문제를 정의한다.

📌 부작용 없이 이메일 주소 검증하기

fun isValidEmail(s: String): Boolean =
    s.contains("@") && s.endsWith(".com")

➡️ 상태 없이, 조건만으로 결과를 도출하는 순수 함수 구성


4. 일급 함수로 전략을 사고한다

✅ 전략 패턴도 함수로 표현

전략 패턴이란?
동일한 문제 해결 방식(전략)을 객체 또는 함수로 분리해서 전달하는 디자인 패턴
예를 들어 정렬 기준, 계산 방식 등을 외부에서 주입 가능한 구조로 만들어 유연성을 높인다.

fun compute(x: Int, strategy: (Int) -> Int): Int = strategy(x)

val double = { it * 2 }
val square = { it * it }

println(compute(4, double))  // 8
println(compute(4, square))  // 16

➡️ 전략 패턴조차 “전달 가능한 함수”로 치환됨 → 유연한 사고 구조


5. 실제 문제에 함수형 사고 적용 예시

문제 정의

문자열 리스트에서 특정 키워드가 포함된 항목만 추출하고, 이를 알파벳 역순으로 정렬한다.


1단계: 명령형 사고

val items = listOf("alpha", "beta", "gamma", "alphabetical")
val result = mutableListOf<String>()
for (item in items) {
    if ("alp" in item) {
        result.add(item)
    }
}
result.sortDescending()
println(result)
  • 명령형에서는 상태(result)를 명시적으로 만들고, 조건과 정렬을 분리해서 처리
  • 절차는 명확하지만, 흐름이 나뉘고 재사용성도 낮음

2단계: 선언형으로 개선

val filtered = items.filter { it.contains("alp") }
val sorted = filtered.sortedByDescending { it }
println(sorted)
  • 중간 상태를 이름으로 표현해 가독성 확보
  • 연산 흐름은 명시적이나 여전히 나눠져 있음

3단계: 함수형 파이프라인으로 고도화

val result = items
    .asSequence()
    .filter { "alp" in it }
    .sortedByDescending { it }
    .toList()
  • 중간 상태 없이 파이프라인 흐름으로 구성
  • asSequence()를 통해 지연 계산도 활용 가능

➡️ 여기까지 오면 흐름 자체가 “무엇을 하고 있는지”에 집중된 선언형 + 함수형 구조


6. 상태 없는 반복: 함수형 사고의 핵심 차이점

함수형 사고에서 가장 본질적인 전환 중 하나는
반복이나 흐름 처리 시, 상태(var)를 직접 갱신하지 않는다는 점입니다.

비교 예시: 합산

❌ 명령형 (상태 갱신 방식)

var sum = 0
for (i in 1..5) {
    sum += i
}
  • 루프를 통해 상태 sum을 계속 변경
  • 제어 흐름과 상태 관리가 함수 외부에서 이루어짐

✅ 함수형 (상태 없음, 흐름 조합)

val sum = (1..5).sum()
  • sum()은 내부적으로 fold/reduce 연산을 통해 값을 생성
  • 상태 없이 값 → 값으로의 흐름을 함수 조합으로 표현
 즉, 함수형은 “무엇을 조합할 것인가”에 집중하고, “어떻게 상태를 변경할 것인가”를 걷어낸 방식이다.

💡 정리

  • 명령형 사고는 상태(state)를 갱신하며 절차를 설계하고,
  • 함수형 사고는 흐름(flow)을 조합하며 목적에 집중한다.

🔚 마무리 요약

사고 방식 설명
명령형 사고 절차 중심. 상태를 갱신하며 흐름을 설계
함수형 사고 데이터 흐름 중심. 연산을 파이프처럼 조합해 설계
분해 단위 상태 단위가 아닌 변환/조합 단위로 사고
전략 구현 방식 객체 대신 함수를 전략처럼 전달해 유연성 확보

함수형 사고는 복잡한 문제를 흐름으로 재구성하는 기술이다.

'CS 기초부터 한 걸음씩' 카테고리의 다른 글

word2vec 이란? - 분포 가설부터 학습 알고리즘까지  (4) 2025.08.04
벡터 임베딩 - 비정형 데이터를 수치로 표현하는 방법  (3) 2025.08.04
함수형 프로그래밍 5편 - 지연 계산과 함수형 최적화 전략  (4) 2025.07.23
함수형 프로그래밍 4편 - 고차 함수와 클로저, 캡처와 순수성  (1) 2025.07.23
함수형 프로그래밍 3편 - 불변성과 구조 공유, 퍼시스턴트 자료구조  (1) 2025.07.23
'CS 기초부터 한 걸음씩' 카테고리의 다른 글
  • word2vec 이란? - 분포 가설부터 학습 알고리즘까지
  • 벡터 임베딩 - 비정형 데이터를 수치로 표현하는 방법
  • 함수형 프로그래밍 5편 - 지연 계산과 함수형 최적화 전략
  • 함수형 프로그래밍 4편 - 고차 함수와 클로저, 캡처와 순수성
Celion
Celion
오늘도 평소처럼 화이팅!
  • Celion
    Orion Log
    Celion
  • 전체
    오늘
    어제
    • 전체 글 (144)
      • Uncompiled Thoughts (8)
        • 네이버 부스트캠프 10기 (5)
      • CS 기초부터 한 걸음씩 (34)
      • Code Odyssey (22)
      • Algorithm (77)
        • Coding Test Records (63)
      • Git (3)
      • reference (0)
  • 블로그 메뉴

    • 태그
    • 방명록
  • 태그

    코테
    boostcamp
    프로그래머스
    Level2
    알고리즘고득점kit
    greedy
    시뮬레이션
    백준
    Kotlin
    문법정리
    java
    Level3
  • 최근 글

  • 인기 글

  • 최근 댓글

  • hELLO· Designed By정상우.v4.10.4
Celion
함수형 프로그래밍 6편 - 함수형 사고 방식과 문제 해결 전략
상단으로

티스토리툴바