나는 오늘도 멋있다

함수형 프로그래밍 본문

Web/CS

함수형 프로그래밍

나는 오늘도 멋있다 2024. 3. 26. 17:35
1. 모든행동에는 목표를 정하고, 근거야 있어야 한다.
2. 문제가 발생하면 해결보다는 원인을 찾자
3. 다른사람의 관점을 고려하자

 

목적
JS를 하면서 많이 접하는 프로그래밍 패러다임은 객체지향 프로그래밍, 함수형 프로그래밍 처럼 두가지를 많이 접하게 된다. 객관적으로 스스로에게 이 프로그래밍 패러다임에서 이해하고 있냐고 물어본다면, 감각적으로는 알고있지만 다른사람을 이해할수 있게 쉽게 설명할수는 없을것 같다. 그말은 나도 두루뭉실하게 알고있는게 아닐까? 하는 생각으로 정확히 학습하고자 한다.

명령형(How) 프로그래밍 vs 선언형(what) 프로그래밍
함수형 프로그래밍, 객체지향 프로그래밍을 알기전에 먼저 선언형, 명령형에 대한 방식, 차이점을 알아야 한다.

 

[명령형 프로그래밍] - 어떻게?
명령형 프로그래밍은 상태와 상태를 변경시키는 구문의 관점으로 접근하는 프로그래밍 방식으로컴퓨터가 실행할 명령들을 실행 순서대로 구현해야 한다. 일반적으로 객체 지향 프로그래밍 언어가 명령형 프로그래밍 언어이며 알고리즘 처리 작업에 적합하다.(절차지향, 객체지향)
[선언형 프로그래밍] - 무엇을?
선언으로만 프로그램을 동작시키는 것을 의미한다. 프로그램을 실행하기 위해 구체적인 작동 순서를 나열하지 않아도 된다.함수형 프로그래밍을 활용해 일정 수준의 선언형 프로그래밍을 할 수 있다. 함수형 프로그래밍은 선언형 프로그래밍의 한종류

 


함수형 프로그래밍이 란?
자료 처리를 수학점 함수의 계산으로 취급하고, 상태와 가변데이터를 멀리하는 프로그래밍 패러다임이며, 함수를 응용을 강조하여, 문이 아닌 식이나 선언으로 수행되는 선언형 프로그래밍 패러다임을 따르고 있다. 

함수형 프로그래밍의 조건
  • 부수효과(Side-Effect)
    • 상태변경(State Mutation): 외부 변수나 객체의 상태를 변경하는 것을 의미한다
    • I/O 작업(Input/Output Operations): 파일시스템, 네트워크 통신 등 외부 자원에 접근하여 데이터를 읽거나 쓰는 작업
    • 예외발생(Exception Throwing): 예외를 발생시켜 프로그램의 실행 흐름을 변경하는것을 말함
  • 순수함수(Pure Function)
    • 부수효과(Side-Effect)가 발생하지않음
    • 입력 값에만 의존해야 한다
    • 동일한 인자에 대해 항상 동일한 결과를 반환한다
    • 여러 스레드(Thread safe)에서 동시에 함수를 호출해도 안전해야 한다.
  •  불변성(Immutability)
    • 객체가 생성된 후에 내부 상태가 변경되지 않는것을 의미 한다.
    • 시간적 결합(Temporal Coupling): 시간이 지남에 따라 어떤 데이터가 변할수 있음을 의미
    • 수정, 새로운값을 생성할때마다 새로운 객체를 반환해야 한다.
  • 1급 객체(First-class object)
    • 함수가 1급 객체여야 한다
    • 함수를 변수에 할당할수 있어야 한다
    • 함수를 다른함수의 인자로 받을수 있어야 한다
    • 함수를 다른함수의 반환값으로 활용 할수 있어야 한다
  •  참조 투명성(Referential Transparency)
    • 동일한 표현식이 어디에서든 항상 동일한 결과를 반환한다
    • 기존 값은 변경되지 않고 유지된다

함수형 프로그래밍의 기법
고차함수: 함수를 인자로 받거나, 함수를 반환하는 기법으로 함수를 값으로 다루는 기법
일반적으로 많이들 사용하는 Array.prototype.map()은 고차함수이다. map은 함수를 인자로 받고 새로운 배열을 순회하고 반환한다. 또한 함수를 반환하는 메서드로는  Function.prototype.bind()로 새로운 함수를 반환하는 메서드로 고차함수라고 할수있다. 물론 직접 정의하는 함수가 고차함수가 될수도 있다.
재귀함수(꼬리재귀): 반복문 대신 사용하기도 하며, 함수가 자기 자신을 호출하여 반복적으로 작업을 수행하는 기법
함수 내부에서 자기 자신을 호출을 할때는, 함수를 다시 호출하기때문에 호출스택(메모리)에 프레임을 계속해서 쌓아 나간다. 그렇기에 호출이 깊어질경우에는 스택 오버 플로우가 발생할 수가 있는데 이를 해결하기위해서는 꼬리재귀를 사용한다.
꼬리 재귀를 이용하면 재귀 호출이 깊어져도 호출 스택을 최적화된 형태로 사용한다. 즉 꼬리재귀는 연산을 하지않고 일반적인 자신을 호출하는것에 요점을 두면될 것 같다. 또한 꼬리재귀는 해당언어에서 TCO(Tail Call optimization)를 지원해야하는데 JS는 특정 조건에 대해서 꼬리 호출을 최적화 할수가 있다고한다. 이때문에 반복문을 많이 사용한다고 한다.
클로저: 함수와 함수가 선언될 당시의 렉시컬 환경의 조합을 나타내며, 외부 변수에 접근할 수 있는 함수를 생성하는 기법
외부함수안에 내부함수가 존재해야하고, 내부함수가 외부함수의 환경정보를 참조해야 한다.  클로저는 실행컨텍스트 와 렉시컬환경과 밀접하기 때문에 다른글에서 주제로 따로 다룬다. -> (링크 준비중)
커링: 여러 개의 인자를 받는 함수를 한개의 입력만 받는 여러 개의 함수로 변환하는 기법
주로 재사용성, 모듈성, 유연성을 위해 사용하는것으로 함수를 단계로 분해하는것

'Web > CS' 카테고리의 다른 글

브라우저의 동작 원리  (0) 2024.04.04
JavaScript의 동작 - 1 (stack,heap,Event Loop)  (0) 2024.03.27
컴퓨터 부품조사  (2) 2024.01.11
CORS(Cross-Origin Resource Sharing)에 대해서  (1) 2023.12.06