javascript(typescript) 비구조화 할당과 함수의 keyword argument 다루기

본론에 들어가기 전에 자바스크립트에 대해서 투덜거리고 싶다.
자바스크립트의 생태계는 너무 크다. 웹의 발전에 지대한 역할을 하며 지금까지 건재해왔지만 필자의 견해로는 언젠가는 이 틀을 깨트려야한다고 생각한다.
설명을 하면 너무 길어져서 결론만 말하면 자바스크립트는 너무 생태계가 복잡하다. 타입스크립트는 훌륭하지만 애초에 javascript의 한계를 보완하기 위해 만들었다. 그런데 typescript 또한 제대로 쓰려면 만만한 것이 아니다.
같은 동적 타이핑 언어인 python 진영에는 pydantic이라는 것이다. 지금까지 typescript와 pydantic을 비교해온 결과 pydantic이 더 깔끔하고 사용하기도 편리하다.
이번에 keyword argument를 자바스크립트에서 사용하는 방법을 정리 하면서 더욱 그렇게 느껴졌다.
자바스크립트는 애초에 언어차원에서 들어가면 좋을 문법들이 마련되지 않은 상황에서 생태계가 넓혀지다 보니 keyword argument와 같은 아주 기본적인 파라미터 지정전달에도 비구조화 할당이라는 es6(2015)의 기능을 사용해야 한다.

본론은 간단히

비구조화 할당.

const {a, b} = {a:3, b:9}

위 코드 의 결과는 다음과 같다.

const a = 3
const b = 9

객체의 key값과 같은 이름은 변수에 value를 할당하게 된다.
객체라면 {a,b}를 사용하지만,
배열이라면 [a,b] 를 사용하며 value만 존재하므로 a, b,에 배열의 값이 순서대로 할당된다.

const [c,d] = [1,2]

딱히 개수를 맞춰야 할 필요는 없다. 할당되지 않은 경우 undefined가 되며 넘치는 경우라면 넘치는 부분은 무시된다.

비구조화 할당의 기본값

비구조화 할당을 하기전 기본값을 정할 수 있다.

const {z=55, x } = {a:33, b:22, x:99}

결과과는 다음 코드와 같다.

const z = 55;  //기본값 할당
const x = 99;

할당되는 객체에 z key가 없으므로 기본값 55로 할당된다.

가장 간단한 키워드 argument 만들기

위 두가지 성질을 바탕으로 자바스크립트에서 keyword argument를 사용해보자.

function add({ a, b }) {
  console.log(a + b);
}

add({ a: 1, b: 33 });  //34

매개변수가 전달되는 과정에 다음과 같은 비구조화 할당이 이루어진다.

var {a, b} = {a:1, b: 33}

이렇게 ab는 함수의 지역변수로 사용되어진다.
다음과 같은 방식도 가능하다.

function add(params) {
  var { a, b } = params;
  console.log(a + b);
}

add({ a: 1, b: 33 });

주의할 점은 파라미터로 전달되는 값은 객체라는 점이다.

키워드 argument에 기본값 적용하기

매번 대부분 동일한 값을 갖거나 특수한 경우를 제외하고는 default롤 사용되어야할 argument가 있을 수 있다. 이럴 때 default 값이 필요한다.

function add({ a = 1, b }) {
  console.log(a + b);
}

add({ b: 33 }); //44

이렇게 a의 기본값을 사용한다면 a가 객체에 없어도 된다. 만약 기본값이 적용되지 않은 경우에 할당된 객체에도 해당 key가 없다면 undefined처리가 될 것이다.
다음과 방식도 가능하다.

function add(params) {
  var { a = 1, b } = params;
  console.log(a + b);
}

add({ b: 33 }); //34

다른 파라미터와 혼합

function add(greeging, params) {
  var { a = 1, b } = params;
  console.log(greeging, a + b);
}

add("hello", { b: 33 }); // hello 34

다음과 같은 방식도 가능하다.

function add(greeging, { a = 1, b }) {
  console.log(greeging, a + b);
}

add("hello", { b: 33 });

기본 할당 객체 적용

앞에선 할당 객체의 각 요소에 대해서 필요하다면 기본값을 적용하였다.
할당 객체 자체의 기본값을 적용해보자.

function add(greeging = "babo", { a = 1, b } = { a: 3, b: 33 }) {
  console.log(greeging, a + b);
}

add("hello");  // hello 36
add("hello", { b: 99 }); // hello 100

당연하지만 기본 할당 객체는 할당 객체가 전달되지 않을 경우만 적용된다
비구조화 된 파라미터의 기본값과 할당 객체의 기본값을 혼동하지 말자.

지금까지 내용들을 보면 비구조화 할당에 대한 내용을 이해하고 있다면 쉽게 이해할 수 있다. 하지만 흐름을 이해하는 것과 실제사용(결과만 적용하는것)은 차이가 있다.

타입스크립트를 적용해보기

interface MyObj {
  myNumbers: Array<number>;
  myStrings: Array<string>;
}

function add(greeging = "babo", { myobj, b }: { myobj: MyObj; b: number }) {
  console.log(greeging, myobj.myNumbers[0] + b);
}

add("hello", {
  myobj: { myNumbers: [1, 2, 3], myStrings: ["apple", "banana"] },
  b: 2,
}); // hello 3

타입스크립트와 할당 객체 요소의 기본 값

function add(
  greeging = "babo",
  { myobj, b = 33 }: { myobj: MyObj; b: number }
) {
  console.log(greeging, myobj.myNumbers[0] + b);
}

add("hello", {
  myobj: { myNumbers: [1, 2, 3], myStrings: ["apple", "banana"] }, // typescript Error
});

위와 같이 b=33의 기본값을 두면 타입스크립트가 에러를 낸다.
다음과 같이 해줘야 된다.

function add(
  greeging = "babo",
  { myobj, b = 33 }: { myobj: MyObj; b?: number } // Optional 표시
) {
...

할당 객체 요소에 기본값을 주면 생략이 가능하기 때문에 type정의에 옵셔널 표시가 필요하다.

이 외에도 다양한 상황이 연출될 수 있다.
비구조화 할당을 keyword argument에 적용하는 것은 매우 멋진 방법이고 인상적이라 생각한다. 그렇지만 사용법이 깔끔하지 않다. 파라미터로 전달되는 객체는 모양이 심히 보기 안좋아보인다.
마치 접착제가 없어서 밥풀로 땜빵하는 느낌같다.

이 댓글을 비밀 댓글로