[함수형 자바스크립트]2. 고계 자바스크립트


자연어는 지배적인 패러다임이 없다. 자바스크립트도 마찬가지이다. 개발자들은 절차적, 함수형, 객체지향형 접근 방법을 적절히 골라 섞어 쓰면 된다.

자바스크립트와 함수형 프로그래밍

자바스크립트는 어디에나 있다. 꾸준히 개선되고 있으며, 객체형인 동시에 함수형이다.

함수형 대 객체지향 프로그래밍

객체지향과 함수형의 가장 중요한 차이점은 데이터(객체 속성)와 기능(함수)을 조직하는 방법에 있다. 객체지향은 인스턴스 메서드를 통해 가변 상태를 노출하고 조작할 수 있고, 캡슐화되어 응집도가 높은 패키지가 형성된다.

반면, 함수형 프로그램은 데이터를 숨길 필요 없이 데이터와 기능을 느슨하게 결합한다. 그로인해 특정 코드에 종속되지 않아 재사용성과 유지보수성이 좋다.

즉, 객체지향은 데이터와 데이터 관계의 본질에 초점을 두는 반면, 함수형은 오직 기능만을 초점한다.

vs함수형객체지향형
합성단위함수객체(클래스)
프로그래밍 스타일선언적명령형
데이터와 기능순수함수의 느슨한 결합클래스 안에서 메서드와 강한 결합
상태관리불변값으로 취급객체를 변이시킴
제어흐름함수와 재귀루프와 조건 분기
스레드 안전동시성 프로그래밍 가능캡슐화하기 어려움
캡슐화불변이라 필요없음데이터 무결성을 지키기위해 필요

자바스크립트 객체의 상태 관리

상태란 어느 시점에 찍은 모든 객체에 저장된 데이터의 스냅샷이다. 상태를 보호하는 측면에서 자바스크립트는 사실 최악의 언어 중 하나이다.

자바스크립트는 너무나 동적이어서 언제건 속성을 추가, 삭제, 수정할 수 있다. 자유에는 언제나 책임이 수반되는 법. 관리가 어려워지지 않도록 스스로 데이터를 보호하는 훈련을 해야한다.

객체를 값으로 취급

불변성을 바탕으로 사고하려면 사실상 모든 객체를 값으로 취급해야 한다.자바의 final같은 장치가 그것이다. 하지만 자바스크립트에서는 그런 호사를 누릴 수가 없다. 이 때 객체 구조가 단순하다면 값 객체 패턴을 사용하는 것도 좋다.

또한 Object.freeze()를 사용하면 객체 상태를 못바꾸게 동결할 수 있다. 하지만 이 또한 얕은 연산이라 확실히 동결하고 싶다면 중첩구조를 일일이 동결해야한다.

지금까지 불변성에 대해 강조했지만 사실 상태를 전혀 바꾸지 않는 어플리케이션은 현실적으로 존재하기 어렵다. 따라서 원본 객체에서 새 객체를 만드는 엄격한 정책을 적용하면 도움이 될 수 있다. 한가지 기법이 더 있다면 객체의 불변 상태를 한 곳에서 관리하는 렌즈라는 기법이 있다.

객체 그래프를 렌즈로 탐색/수정

람다JS를 사용하면 렌즈를 손쉽게 사용할 수 있다. 람다는 Copy On Write기법을 사용해 게으른 복사를 실행하게 도와준다. 그로인해 아래와 같은 코드가 동작된다.

const newPerson = R.set(lastnameLens, 'Mourning', Person);
newPerson.lastname; // 'Mourning'
person.lastname; // 'Church'

함수

함수형 프로그래밍에서 함수는 작업의 기본 단위이며, 표현식(값을 내는 함수)과 구문(값을 내지 않는 함수)로 구분할 수 있다.

일급 함수

자바스크립트 함수는 실제로 객체이기 때문에 일급(first class)이다. 자바스크립트 함수는 모두 Function 형식의 인스턴스이며 length 속성은 정규 매개변수 개수를 의미한다.

고계 함수

함수의 작동 원리는 일반 객체와 같아서 함수를 인수로 전달하거나 반환할수 있다. 이런 함수를 고계 함수라고 한다. 자바스크립트 함수는 일급이면서 고계여서 여느 이나 다름없다. 즉, 자신이 받은 입력밧을 기반으로 정의된 언젠가 실행될 값에 지나지 않는다.

함수 호출 유형

  • 전역함수로 호출
function doWork() {
    this.myVar = 'something' // 전역의 this
}

doWork()
  • 메서드로 호출
const obj = {
    prop: 'some prop'
    getProp: function () {
        return this.prop // 소유 객체의 this
    }
}

obj.getProp();
  • new를 붙여 생성자로 호출
function MyType(arg) {
    this.props = arg; // 방금 생성된 객체의 this
}

const someVal = new MyType('something')

다른 프로그래밍 언어와는 달리 자바스크립트는 this 레퍼런스가 가리키는 대상이 함수를 사용하는 방법에 따라 달라진다. 이 때문에 이해하기 어려운 코드가 될 수도 있으니 문맥을 잘 살펴야 한다.

물론 함수형 프로그래밍 기법을 사용한다면 자바스크립트에서 this를 사용할 일은 거의 없다. 아니, 어떤 일이 있더라도 쓰지 않도록 해야한다.

함수 메서드

자바스크립트 함수는 프로토타입에 소속된 일종의 상위 함수인 applycall 메서드로도 호출할 수 있다.

클로저와 호이스팅

클로저는 함수를 선언할 당시의 환경에 함수를 묶어둔 자료구조이다. 클로저와 호이스팅에 대한 이해는 이 슬라이드 후반부를 참조하자.

전역 스코프

전역 스코프는 위험하다는 건 모두가 공감할 것이다. 특히 자바스크립트가 사용되는 환경 중에 하나인 브라우저에서는 직접 관리하지 않는 전역 변수가 많기 때문에 이름 공간이 충돌이 날 수가 있다.

이처럼 사이드 이펙트를 낼 수 있는 여지가 다분하니 전역변수는 가능한한 삼가해서 사용하도록 하자.

함수 스코프

함수 스코프는 자바스크립트가 선호하는 스코프 방식이다. 함수 내부에 선언된 변수는 해당 함수의 지역변수라서 다른 곳에서는 안 보이고, 함수가 반환되는 시점에 이들은 모두 사라진다.

함수 스코프를 체크하고, 부모 스코프를 체크하고, 전역 스코프를 체크한 뒤 에도 없다면 undefined를 반환한다.


2023년 새해에는 성장하고 함께하고 싶다면?

Pre A 단계 이상의 스타트업 C 레벨들이 모여서 커뮤니티를 만들었습니다. 같이 스터디하고 친해질 일잘러를 찾습니다.




© 2017. by isme2n

Powered by aiden