함수형VS명령형

백민지·2024년 6월 13일

프로그래밍 패러다임

  • 프로그래머에게 프로그래밍의 관점을 갖게하고 결정하는 역할을 한다

  • 명령형 프로그래밍: 프로그래밍의 상태와 상태를 변경시키는 구문의 관점에서 연산을 설명하는 방식

    • 절차지향 프로그래밍: 수행되어야 할 연속적인 계산 과정을 포함하는 방식 (C, C++)
    • 객체지향 프로그래밍: 객체들의 집합으로 프로그램의 상호작용을 표현 (C++, Java, C#)
  • 선언형 프로그래밍: 어떤 방법으로 해야 하는지(How)를 나타내기보다 무엇(What)과 같은지를 설명하는 방식

    • 함수형 프로그래밍: 순수 함수를 조합하고 소프트웨어를 만드는 방식

함수형 프로그래밍

  • 함수형 프로그래밍은 순수함수와 보조 함수의 조합을 통해 로직내에 존재하는 조건문과 반복문을 제거하여 복잡성을 해결하고 변수의 사용을 억제하여 상태 변경을 피하려는 프로그래밍 패러다임이다.

함수형 프로그래밍?

  • 함수형 프로그래밍은 순수한 함수를 작성하고, 공유된 상태와 변경 가능한 데이터 및 부작용을 피하여 소프트웨어를 작성하는 프로세스이다.
  • 함수형 프로그래밍은 선언형이며, 애플리케이션의 상태는 순수한 함수를 통해 전달된다.
  • 애플리케이션의 상태가 공유되고, 객체의 메소드와 사용되는 객체 지향 프로그래밍과는 대조된다.

함수형 프로그래밍의 원칙

  • 입출력이 순수해야합니다. (순수함수)
    • 입출력이 순수하다는 것은 반드시 하나 이상의 인자를 받고, 받은 인자를 처리하여 반드시 결과물을 돌려주어야한다는 것이다. 인자를 제외한 다른 변수는 사용하면 안 되며, 받은 인자만으로 결과물을 내야한다. 이러한 함수를 순수함수라고 부른다. 자바스크립트는 this라는 개념 때문에 (this를 어쩔 수 없이 사용해야하는 상황) 순수함수를 사용하기 힘들다.
  • 부작용(부산물)이 없어야합니다.
    • 부작용이 없어야한다는 것은, 프로그래머가 바꾸고자하는 변수 외에는 바뀌어서는 안 된다는 뜻이며, 원본 데이터는 불변해야한다
    • 함수형 프로그래밍에서는 프로그래머가 모든 것을 예측하고 통제할 수 있어야한다.
  • 함수와 데이터를 중점으로 생각합니다.

1. 1급 객체 (First Object, 또는 1급 시민)

  • 1급 객체(First class object)란 다음과 같은 조건을 만족하는 객체
    • 변수나 데이터 구조안에 담을 수 있다.
    • 파라미터로 전달 할 수 있다.
    • 반환값(return value)으로 사용할 수 있다.
    • 할당에 사용된 이름과 관계없이 고유한 구별이 가능하다.
    • 동적으로 프로퍼티 할당이 가능하다.

→ 자바스크립트에서 함수(Function)은 객체(Object)이므로 1급 함수로 불린다.

2. 고차 함수 (High-Order Function)

  • 람다 계산법에서 만들어진 용어로 아래 조건을 만족하는 함수
    • 함수에 함수를 파라미터로 전달할 수 있다.
    • 함수의 반환값으로 함수를 사용할 수 있다.

→ 고차 함수는 1급 함수의 부분 집합(Subset)이다.리액트의 고차 컴포넌트(HOC)는 컴포넌트를 사용하여 위의 조건을 만족하는 컴포넌트를 말한다.

3. 불변성 (Immutablility)

  • 함수형 프로그래밍에서는 데이터가 변할 수 없는데, 이를 불변성 데이터라고 한다. (자바스크립트는 가능하지만 불가능한 언어들이 있다)
  • 데이터 변경이 필요한 경우, 원본 데이터 구조를 변경하지 않고 그 데이터를 복사본을 만들어 그 일부를 변경하고, 변경한 복사본을 사용해 작업을 진행한다.
// 불변이 아닌 변하는(Mutatable) 데이터
function rateColor(color, rating) {
  color.rating = rating;
  return color;
}

console.log(rateColor(color_lawn, 5), rating) // 5
console.log(color_lawn.rating) // 5

// 불변성 데이터
function rateColor(color, ratring) {
  return Object.assign({}, color, {ratring:ratring});
}

console.log(rateColor(color_lawn, 5), rating) // 5
console.log(color_lawn.rating) // 0  *변하지 않음*

→ const 키워드와 불변은 구분해야 한다. const는 Object로 사용되는 경우 변경 가능하다.

4. 순수 함수 (Pure function)

  • 순수 함수란 함수형 프로그래밍에 필요한 개념으로 아래 조건을 만족하는 함수를 뜻한다.
    • 동일한 입력에는 항상 같은 값을 반환해야 한다.
    • 함수의 실행은 프로그램의 실행에 영향을 미치지 않아야 한다. (Side effect 가 없어야 한다)
      • 예를 들어, 함수 내부에서 인자의 값을 변경하거나 프로그램 상태를 변경하는 것

→ 순수 함수를 호출하면 프로그램의 어떠한 변화도 없고, 입력 값에 대한 결과를 예상할수 있어서 테스트하기가 쉽다.

// 순수하지 않은 함수, DOM을 변경하는 부수효과를 발생시킴
function Header(text) {
  let h1 = document.createElement('h1');
  h1.innerText = text;
  document.body.appendChild(h1);
}

// 순수한 함수, 부수효과를 발생시키지 않음
// DOM을 변경하는 책임은 애플리케이션의 다른 부분이 담당하도록 한다.
const Header = (props) => <h1>{props.title}</h1>
  • 순수함수를 사용한 코드는 전역 상태를 바꾸거나 깨뜨릴 일이 전혀 없으므로 테스트, 유지보수가 더 쉬운 코드를 개발하는 데 도움이 된다.
  • 함수형 프로그래밍은 코드를 선언적으로 작성하므로 헤아리기 쉽고 전체 애플리케이션의 가독성 역시 향상된다.
  • 여러 원소로 구성된 컬렉션 데이터는 map, reduce 같은 연산을 함수 체인으로 연결하여 물 흐르듯 매끄럽게 처리할 수 있다.
  • 함수형 프로그래밍은 함수를 기본적인 구성 요소로 취급합니다. 이는 일급/고계함수 개념에 기반을 두며 코드의 모듈성, 재사용성을 높인다.
  • 리액티브 / 함수형 프로그래밍을 융합하면 이벤트 기반 프로그램 특유의 복잡성을 줄일 수 있다.

함수형 프로그래밍을 구현하는 방법

함수형 프로그래밍은 순수 함수(pure function) 를 조합하고 공유 상태(shared state), 변경 가능한 데이터(mutable data) 및 부작용(side-effects) 을 피하여 소프트웨어를 만드는 프로세스다. 함수형 프로그래밍은 명령형(imperative) 이 아닌 선언형(declarative) 이며 애플리케이션의 상태는 순수 함수를 통해 전달된다.

규칙

  • 모든 데이터는 변경이 불가능 해야한다.
  • 함수는 순수 함수로 만든다. 인자를 적어도 하나 이상 받게 만들고, 데이터나 다른 함수를 반환해야 한다.
  • 루프보다는 재귀를 사용한다.

객체 지향 프로그래밍이란?

객체 지향 프로그래밍은 함수들의 집합 혹은 단순한 컴퓨터의 명령어들의 목록이라는 기존의 프로그래밍에 대한 전통적인 관점에 반하여, 컴퓨터 프로그램을 객체들의 모임으로 파악하고자 하는 프로그래밍 패러다임 중 하나입니다.

객체 지향 프로그래밍은 클래스를 이용해 연관 있는 처리 부분(함수)과 데이터 부분(변수)를 하나로 묶어 객체(인스턴스)를 생성해 사용합니다. 객체 지향 프로그래밍에서 각 개체는 메시지를 받을 수 있고, 데이터를 처리할 수 있으며, 또 다른 객체에 메시지를 전달할 수 있습니다. 즉, 각 객체를 별도의 역할이나 책임을 갖는 작은 독립적인 기계로 볼 수 있습니다.

객체 지향 VS 절차 지향

  1. 처리 방식
    • 객체지향: 문제를 여러개의 객체 단위로 나누어 처리
    • 절차지향: 문제를 여러개의 함수로 나누어 순차적으로 호출하여 처리
  2. 장점
    • 각 기능을 독립적인 모듈로 관리할 수 있기 때문에 하드웨어의 처리 양이 줄어들고, 유지보수가 쉬움
    • 컴퓨터의 작업 처리 방식과 유사하기 때문에 객체지향 언어를 사용하는 것에 비해 더 빠르게 처리됨
  3. 단점
    • 처리 속도가 절차 지향보다 느리고, 설계에 많은 시간이 소요됨
    • 실행 순서가 정해져 있기 때문에 코드의 순서가 바뀌면 동일한 결과를 보장하기 어려움
  4. 대표언어
    • Java
    • C언어

객체 지향 프로그래밍의 특징

1. 캡슐화(Encapsulation)

  • 객체의 속성(data field)과 행위(methods)를 하나로 묶고, 실제 구현 내용 일부를 외부에 감추어 은닉합니다.
  • 캡슐화의 이유는 외부의 잘못된 사용으로 인해 객체가 손상되지 않도록 하기 위하는데 있습니다.

2. 상속(Inheritance)

  • 하나 이상의 클래스를 특별한 버전의 클래스로 생성하는 하나의 방법입니다.
  • 자바스크립트에서는 부모 클래스의 인스턴스를 자식 클래스에 할당함으로써 상속이 이루어지며, 오직 하나의 클래스를 상속받는 것만 지원합니다.
  • 상속을 통해 반복된 코드의 중복을 줄일 수 있고, 유지 보수의 편리성을 얻을 수 있습니다.

3. 추상화(Abstraction)

  • 공통의 속성이나 기능을 묶어 이름을 붙이는 것을 말합니다.
  • 객체 지향 관점에서 클래스를 정의하는 것을 추상화라고 말할 수 있습니다.
  • 딸기, 오렌지, 복숭아를 각각 객체라고 한다. 이 객체들을 하나로 묶을 때, 과일이라는 추상적인 객체로 크게 정의 한다. 이 때, 딸기, 오렌지, 복숭아를 과일로 묶는 것을 추상화라고 한다.

4. 다형성(Polymorhphis)

  • 특정 기능을 선언 부분과 구현 부분으로 분리한 후, 구현 부분을 다양한 방법으로 만들어 사용할 수 있는 기능입니다.

4-1. 오버라이딩

자식 클래스에서 부모 클래스의 기능을 재정의할 때 사용하는 기능입니다.

오버라이딩은 두 가지 경우에 주로 사용합니다.

1) 부모 클래스의 기능을 사용하지 않고 자식 클래스에서 구현한 기능을 사용하고 싶은 경우

부모의 기능을 직접 수정하지 않고, 부모의 기능을 재정의할 때 오버라이딩을 사용합니다.

MyParent.prototype.부모메소드 = function() {}
MyChild.prototype.부모메소드 = function() {}

function MyParent() {
	this.property1 = 'data1';
	console.log('MyParent');
}

MyParent.prototype.method1 = function() {
	console.log('property1= ' + this.property1);
}

function MyChild() {
	console.log('MyChild');
}

//부모 클래스 상속
MyChild.prototype = new MyParent();
//생성자 설정
MyChild.prototype.constructor = MyChild;

//오버라이딩
MyChild.prototype.method1 = function() {
	console.log('프로퍼티 1은 '+ this.property1+' 입니다.');
}

//자식 인스턴스 생성
let child = new MyChild();
//메소드 호출
child.method1();

//console 출력 결과
//MyParent
//MyChild
//프로퍼티 1은 data1 입니다.

부모 클래스의 method1()는 더이상 동작하지 않고, 자식 클래스의 method1()이 동작하는 것을 확인할 수 있습니다.

2) 부모 클래스의 기능을 자식 클래스에서 확장하고 싶은 경우

부모의 기능을 완전히 새롭게 재정의하는 것이 아니라 부모의 기능을 그대로 사용하면서 기능을 약간 추가하고 싶은 경우가 있습니다. 이 경우에 오버라이딩을 사용합니다.

//부모 클래스
function MyParent() {
	this.property1 = '문자열 데이터';
	console.log('MyParent()');
}

MyParent.prototype.info = function() {
	console.log('property1= '+ this.property1);
}

//자식 클래스
function MyChild() {
	console.log('MyChild()');
	this.property2 = '데이터';
}

//부모 클래스 상속
MyChild.prototype = new MyParent();
//생성자 설정
MyChild.prototype.constructor = MyChild;

//확장할 기능인 info를 자식 클래스에서 오버라이딩
MyChild.prototype.info = function() {
	MyParent.prototype.info.call(this); //call()을 이용해 부모 클래스의 info()메소드 호출
	console.log('프로퍼티 2는 '+this.propert2+' 입니다.')
};

//자식 인스턴스 생성
let child1 = new MyChild();
//자식 정보 출력
child1.info(); //프로퍼티 2는 데이터 입니다.

4-2. 오버로딩

동일한 이름을 가진 여러 개의 메소드를 만든 후 매개변수 타입과 개수에 맞는 메소드가 자동으로 호출되는 기능을 말합니다. 자바스크립트는 자료의 타입을 선언하지 않기 때문에 오버로딩을 제공하지 않습니다.

[명령형 vs 함수형]

프로그래밍이란?
- 명령형: 프로그램은 명령의 수행이다.
- 함수형: 프로그램은 함수의 계산이다.
중점적 시각
- 명령형: 어떻게 (how to) 에 초점
- 함수형: 무엇(what)에 초점
이론적 배경
- 명령형: 튜링 머신
- 함수형: 람다 계산식
주요 프로그래밍 언어
- 명령형: C, 자바 등 대부분의 언어
- 함수형: Scheme, Haskel

객체지향 프로그래밍의 코드 예시

class BankAccount {
  constructor(balance) {
    this.balance = balance;
  }

  deposit(amount) {
    this.balance += amount;
  }

  withdraw(amount) {
    if (amount > this.balance) {
      console.log("Insufficient funds");
    } else {
      this.balance -= amount;
    }
  }
}

let account = new BankAccount(100);
account.deposit(50);
console.log(account.balance);  // 150

account.withdraw(75);
console.log(account.balance);  // 75

함수형 프로그래밍의 코드 예시

const deposit = (balance, amount) => balance + amount;

const withdraw = (balance, amount) => {
  if (amount > balance) {
    console.log("Insufficient funds");
    return balance;
  }
  return balance - amount;
};

let balance = 100;

balance = deposit(balance, 50);
console.log(balance);  // 150

balance = withdraw(balance, 75);
console.log(balance);  // 75

예상 질문

  • 함수형 프로그래밍에 대해 설명하라 함수형 프로그래밍은 순수함수와 보조 함수의 조합을 통해 로직내에 존재하는 조건문과 반복문을 제거하여 복잡성을 해결하고 변수의 사용을 억제하여 상태 변경을 피하려는 프로그래밍 패러다임이다.
  • 함수형 프로그래밍에 개념에서 순수함수란 무엇인가 순수함수는 같은 입력이 주어지면, 같은 출력을 반환해야하고, side effect(부작용) 이 없어야한다.결국, 함수형 프로그래밍은 순수함수를 통해 sideeffect를 최대한 억제하여 오류를 피하고 프로그램의 안정성을 높이려는 노력의 한 방법
  • OOP와 함수형 프로그래밍의 가장 큰 차이점은 무엇인가 객체지향은 객체 안에 상태를 저장하고, 이 상태를 이용해서 메소드를 추가하고 상태변화를 설정하고 조정하기위해 다양한 기능을 사용한다. 이에 반해 함수형 프로그래밍은 상태를 제어하는것보다 상태를 저장하지 않고 없애는데 주력한다. 예를들면, 객체 지향은 상태를 저장하는 필드와 그 필드들을 이용해 기능을 제공하는 메소드를 만들고 클래스를 만듭니다. 반면 함수형은 몇몇 자료구조(list, map, set) 등을 이용해 최적화된 동작을 만들어낸다.

0개의 댓글