명세서 바로가기

 

ES pipe operator (2021)

A PipeBody must not be an unparenthesized AssignmentExpression, such as YieldExpression, ArrowFunction, or ConditionalExpression—unless it is a ShortCircuitExpression. This is to prevent confusing expressions from being valid, such as: x |> yield % |> %

tc39.es

 

파이프 연산자의 필요성

현재 자바스크립트에서는 여러 함수들을 통한 연산을 연속적으로 수행할 때, 가독성을 포기하든 편리함을 포기하든 어느 한쪽은 포기해야 한다.

 

인자로 전달 받은 값에 2를 더해주는 작업을 하는 함수와, 인자로 전달 받은 값에 3을 곱해주는 작업을 하는 함수가 있다고 치자.

 

const xPlusTwo = (x = 0) => x + 2;
const xTimesThree = (x = 0) => x * 3;

 

임의의 정수 x에 2를 더한 뒤 3을 곱하려는 경우에, 1. 편리함을 취하고 가독성을 포기하는 방식과 2. 가독성을 취하고 편리함을 포기하는 방식을 차례로 적용해보자.

 

1. 편리함을 취하고 가독성을 포기하는 방식: 중첩해서 쓰기

const getResult1 = (x = 0) => xTimesThree(xPlusTwo(x));

 

- 한 줄에 다 때려박을 수 있어서 코드 쓰는 입장에서 편리하긴 하다.

- 대부분의 문화권에 있는 사람들에겐 왼쪽에서 오른쪽으로 읽는 방식이 익숙한데, 위와 같은 방식은 그런 순서가 아니라 안쪽부터 바깥쪽으로 읽어야 하니 직관적이라고 하기는 어렵다.

- 그래도 '늘 안쪽부터 바깥쪽으로 읽으면 된다'는 규칙이 있으면 그거에 적응하면 되는데, 우리 예제 같은 단순한 케이스가 아닌 아래와 같이 복잡한 케이스에선 그 규칙마저도 일관적이지 않다. 심한 경우엔 코드를 독해하는 게 아니라 해독해야 할 수도 있을 것이다.

출처: https://github.com/tc39/proposal-pipeline-operator#deep-nesting-is-hard-to-read

 

그러면.. 쓰는 사람 입장에서 불편함을 좀 감수하더라도 가독성 좋게 개선해볼까?

 

2. 가독성을 취하고 편리함을 포기하는 방식: 임시 변수 쓰기

const getResult2 = (x = 0) => {
  const temp = xPlusTwo(x);

  return xTimesThree(temp);
};

- 연산 과정이 위에서 아래로 쓰여져 있어서, 책 읽듯이 자연스럽게 읽어내려갈 수 있어 위쪽 방식보다는 좀 더 직관적인 것 같다.

- 근데 이 방법을 사용할 경우, 코드 작성자 입장에서는 손해보는 부분이 있는데.. 바로 변수명을 고민해야 된다는 점. 연산 과정에서 잠깐 쓰일 임시 변수를 위해서 작명을 위한 고뇌를 해야 한다니.. 물론 우리 예제처럼 임시 변수가 하나만 있어도 충분한 경우에는 대충 tmp, temp 이런 걸로 때우면 될 듯한데, 아래 그림과 같이 임시 변수가 두 개 이상 필요한 경우라면..?? 이렇게 공들여서 지은 것 치고 효과는 미미하다는 것을 우리는 경험상 알고 있다..

출처: https://github.com/tc39/proposal-pipeline-operator#temporary-variables-are-often-tedious

- temp1, temp2, temp3, ... 이런 식으로 짓자니 좀 없어보이고.. 그렇다고 임시 변수 이름을 힘들여서 짓는 건 투머치인 것 같고... 적당히 유의미하게 지으면 될까..? 응 뭐든 적당히 하는 게 제일 어려워~🤪

 

파이프 연산자가 도입이 되면 이런 고민들을 더 이상 하지 않아도 된다! 가독성과 편리함을 모두 취할 수 있게 되는 것이다..!

 

파이프 연산자 제안

파이프 연산자는 현재(2023.01.21) 기준, TC39 프로세스 단계 중 stage 2에 있는 상태여서, 언제가 될진 모르겠지만 언젠가는 자바스크립트에 도입될 것이라고 기대해봄직하다고 한다.

출처: https://www.slideshare.net/ItamarOKestenbaum/tc39-the-exciting-parts

만약에 파이프 연산자(|>)가 도입된다면 앞서 살펴본 예시를 어떻게 리팩토링할 수 있을까?

const getResult3 = (x = 0) => {
  return x
    |> xPlusTwo(%)
    |> xTimesThree(%);
};

% 자리에는 직전의 연산 과정에서 처리된 결과값이 전달된다. 처리 대상이 xPlusTwo를 먼저 거치고, 그 다음으로 xTimesThree를 거치는 과정이 위에서 아래로, 또는 왼쪽에서 오른쪽으로 사람에게 익숙한 방식으로 쓰여져 있어 책 읽듯이 자연스럽게 읽힌다. 게다가 임시 변수 이름 붙여주기 놀이를 안 해도 된다!

우리 예제는 원래도 딱히 복잡한 편이 아니었어서 차이가 명확하게 보이지 않을 수 있어서, 같이 살펴봤던 tc39/proposal-pipeline-operator 상의 예제의 리팩토링 결과를 함께 살펴보면, :

확실히 뭔가 복잡하게 엉켜있던 부분들이 풀려진 느낌이다!

 

함수형 프로그래밍 시 유용하게 사용될 것이라고 하는데.. 도입되면 많은 사람들이 애용하게 될 것 같다~

 


<참고>

 

- I've Waited YEARS For This JavaScript Feature... (유튜브 영상)

- https://github.com/tc39/proposal-pipeline-operator

'dev-log > JS' 카테고리의 다른 글

자바스크립트에서의 this  (0) 2021.10.17
타입 변환과 단축 평가  (0) 2021.05.18
객체 리터럴  (0) 2021.05.15
스코프(Scope)란?  (0) 2021.05.14
Set과 Map  (0) 2021.05.11
복사했습니다!