codingstairs
노트에듀라이프연락
⌕검색⌘K
koen

Navigation

  • Intro
  • Blog
  • Life

연락하기

로그인 없이도 보낼 수 있어요. 답변이 필요하면 이메일을 함께 적어 주세요.

  • 익명 폼으로 의견 남기기 →
  • ✉ warragon112@gmail.com
  • 카카오톡 오픈채팅 ↗

© 2026 codingstairs

  • 노트
  • 에듀
  • 검색
  • 라이프
  • 연락
  • 약관
  • RSS
  • GitHub
노트›programming

OOP 와 함수형 — 두 시각의 공존

2026-04-28 게시· 2026-05-18 갱신·0회 조회

OOP 와 함수형 — 두 시각의 공존

"객체지향이냐 함수형이냐" 라는 질문은 한때 진영 다툼처럼 다뤄졌습니다. 오늘날의 모던 언어는 둘을 함께 지원하고, 실무 코드는 두 패러다임을 자연스레 섞어 씁니다. 이 글은 두 패러다임의 출자 · 핵심 원칙 · 모던 언어가 둘을 어떻게 흡수했는지 · 실무에서 어느 자리에 어느 시각이 잘 맞는지.

1. OOP 와 FP 에 대한 이야기

OOP — 가장 자주 인용되는 출자는 1972 년 Alan Kay 가 Xerox PARC 에서 만든 Smalltalk. 그 전에 1967 년 Simula 67 (Ole-Johan Dahl · Kristen Nygaard) 이 클래스 · 상속 같은 핵심 개념을 도입했고, Smalltalk 가 "메시지 전달" 이라는 모델을 명확히. Alan Kay 본인이 "객체지향이라 부를 때 핵심은 메시지 전달이지 클래스가 아니다" 라고 한 발언이 자주 인용. 대중화는 1980 년대 C++ (1985 년 Bjarne Stroustrup), 1995 년 Java 가 결정적.

FP — 뿌리는 1958 년의 Lisp (John McCarthy). 람다 계산 (1930 년대 Alonzo Church) 을 모델로 한 첫 실용 언어. 이후 ML (1973) · Miranda (1985) · Haskell (1990) 이 순수 함수형의 형태를 다듬었고, Erlang (1986) 이 동시성 · 내고장성 자리에서 자리 잡음. 대중화는 2010 년대 멀티코어 시대에 부수효과 없는 코드의 가치가 재조명되며 진행.

2. OOP 의 4 원칙

원칙 의미
캡슐화 데이터와 그 위에 작용하는 행동을 한 객체에 묶음
상속 부모의 정의를 자식이 물려받아 확장
다형성 같은 인터페이스에 다른 구현
추상화 복잡한 내부를 간단한 인터페이스로 가림
// Java 예
abstract class Animal {
  abstract String speak();
}

class Dog extends Animal {
  @Override String speak() { return "멍멍"; }
}

class Cat extends Animal {
  @Override String speak() { return "야옹"; }
}

Animal a = new Dog();
a.speak(); // "멍멍"  ← 다형성

상속은 처음 익히면 강력해 보이지만, 깊은 상속 트리는 결합을 늘려 유지가 힘들다는 비판이 누적되어 2000 년대부터는 "상속보다 합성 (composition over inheritance)" 이 자주 권장 (GoF 책에도 명시).

3. 함수형의 핵심 개념

개념 의미
순수 함수 같은 입력에 항상 같은 출력. 외부 상태 변경 없음
불변성 데이터는 만든 후 바뀌지 않음. 변경 = 새 값 생성
1 급 함수 함수도 값. 인자로 전달, 반환, 변수에 저장
고차 함수 함수를 받거나 반환하는 함수
참조 투명성 식을 그 결과로 치환해도 의미 불변
재귀 반복 대신 재귀로 표현 (꼬리 재귀 최적화 포함)
// 명령형
const xs = [1, 2, 3, 4];
let sum = 0;
for (let i = 0; i < xs.length; i++) sum += xs[i] * 2;

// 함수형
const sum2 = xs.map(x => x * 2).reduce((acc, x) => acc + x, 0);

map · filter · reduce 는 함수형 사고가 명령형 언어에 흡수된 가장 친숙한 자리.

4. 두 시각의 비교

항목 OOP FP
상태 객체에 캡슐화 가능한 한 불변
동작 객체의 메서드 자유로운 함수
결합 클래스 계층 함수 합성
부수효과 자연스러움 격리 권장
동시성 락 · 뮤텍스 필요 불변성 덕에 자연스러움
모델링 도메인을 객체로 도메인을 데이터 + 변환으로

어느 한쪽이 절대 우월하지 않습니다. 같은 문제에 다른 모양이 자연스러운 자리가 있음. UI · 도메인 모델 · 시뮬레이션은 OOP, 데이터 변환 · 동시성 · 검증은 FP 가 자연스럽다는 평이 자주.

5. 모던 언어의 공존

언어 출자 양쪽 지원
Scala 2003 JVM 위 OOP + FP 융합
Kotlin 2011 OOP 기본, FP 친화
Rust 2010 OOP 없음. 트레잇 · 소유권. FP 영향 큼
Swift 2014 OOP + 프로토콜 · 값 타입 · 고차함수
TypeScript 2012 클래스 + 1 급 함수 + 불변 권장
Java (8+) 2014 람다 · Stream API 도입
Python 1991 클래스 · 1 급 함수 · 내포
C# 2002 람다 · LINQ · 레코드 타입

신규 언어 다수가 "OOP 만" 또는 "FP 만" 이 아니라 "양쪽" 의 좋은 부분을 담는 방향. 패러다임 자체가 더 이상 진영의 깃발이 아닙니다.

6. 다른 길

OOP / FP 외의 패러다임:

  • 명령형 (Imperative) — 가장 오래된 갈래. C 가 대표.
  • 선언형 (Declarative) — "무엇을" 만 표현. SQL · HTML · 정규식.
  • 로직 프로그래밍 — Prolog. 사실과 규칙으로 추론.
  • 데이터 흐름 / Reactive — RxJS · Akka Streams. 시간에 따른 데이터 변화를 그래프로.
  • 액터 모델 — Erlang · Akka. 작은 액터들이 메시지로 소통.
  • CSP — Go 의 채널 · 고루틴.

7. 같은 작업의 두 시각

// 사용자 목록에서 활성 사용자 이름만, 알파벳 순으로

// OOP 풍 (가상)
class UserService {
  constructor(users) { this.users = users; }
  getActiveSortedNames() {
    const active = [];
    for (const u of this.users) if (u.active) active.push(u);
    active.sort((a, b) => a.name.localeCompare(b.name));
    return active.map(u => u.name);
  }
}

// FP 풍
const getActiveSortedNames = users =>
  users
    .filter(u => u.active)
    .map(u => u.name)
    .sort((a, b) => a.localeCompare(b));

두 코드 모두 같은 결과지만 후자가 짧고 부수효과가 없음.

// React 컴포넌트 — 두 패러다임이 자연스레 만나는 자리
function UserList({ users }) {
  const visible = users.filter(u => u.active).map(u => u.name);  // FP
  return <ul>{visible.map(n => <li key={n}>{n}</li>)}</ul>;       // 컴포넌트는 OOP 적
}

8. 자주 걸리는 자리

상속의 함정 — 깊은 상속 트리는 변경 비용이 폭증. 합성 또는 인터페이스 / 트레잇이 자주 더 나음.

불변성의 비용 — 큰 자료를 매번 복사하면 성능이 나빠질 수 있음. Immer · Immutable.js · 영속 자료구조가 도움.

순수 강박 — 모든 코드를 순수 함수로만 짜려 하면 I / O · 외부 통신 자리에서 코드가 비비 꼬임. "경계에 부수효과를 모은다" 정도가 실용적.

OOP 강박 — 모든 것을 클래스로 모델링. 단순한 함수면 될 자리에 5 줄짜리 빈 클래스가.

모나드 공포증 — Haskell 식 용어가 처음에 무섭지만, JS 의 Promise.then 도 모나드 형태. 문법적 친숙함부터 익힘.

양쪽을 섞는 일관성 결여 — 한 코드베이스 안에서 어디는 OOP, 어디는 FP 의 기준이 흐려지면 읽기 어려움. 팀 약속 필요.

"이 언어는 OOP 가 아니다" 라는 단언 — 거의 모든 모던 언어가 양쪽을 지원. 특정 스타일이 더 자연스러운 차이일 뿐.

하고픈 말

OOP 와 FP 는 이제 진영이 아니라 같은 도구함의 두 자리. 모던 언어 거의 모두가 양쪽을 지원하고, 실무 코드는 자연스럽게 섞어 씁니다. UI · 도메인 모델 → OOP, 데이터 변환 · 검증 · 동시성 → FP. "경계에 부수효과를 모은다" 가 두 시각을 가장 잘 결합하는 한 줄.

Next

  • (programming 끝)

Alan Kay The Early History of Smalltalk (1993) · Design Patterns: Elements of Reusable Object-Oriented Software (1994) · Effective Java (Joshua Bloch) · Why Functional Programming Matters (John Hughes 1990) · Structure and Interpretation of Computer Programs (SICP) · Haskell.org Learn · Out of the Tar Pit (Moseley · Marks 2006) · Composing Software (Eric Elliott) · Scala 공식 · Rust Book · Kotlin Docs 를 참고합니다.

programming 카테고리의 다른 글

카테고리 전체 보기 →
  • 디자인 패턴 — 자주 만나는 풀이의 이름들
  • Big O — 알고리즘의 성능 표기
  • 자료구조 — 데이터를 담는 그릇들