본문 바로가기

Development/Javascript

[Typescript] 변수 비구조화 (Destructuring)

비구조화란? (Destructuring이란?)

Typescript(or Javascript ES6)에서 변수값을 할당해주는데 있어 다른 언어에서는 볼 수 없는 어마무시한 기능이 있는데 바로 비구조화 할당이다. 이게 뭐냐면 변수에 값을 할당을 하면서 구조화되어 있는(Object, Array 등)을 즉각 분리 시켜 변수에 할당해주는 기능이다. 이게 처음 접하는 분들은 무슨 말인지 감이 안 올텐데 예제를 보면 쉽게 알 수 있다.

1. Array Destructuring

const [a, b] = [10, 20];

이게 뭘까? 보통 언어에서는 저런 문법 자체가 없기 때문에 처음 보면 그냥 작성자의 오타나 일부러 에러를 만들어낸 것 같아 보이는 코드인데 실제로 Javascript나 Typescript에서 동작하는 코드이다. 해석하자면 변수 a와 b를 선언하고 Array 0번 값을 변수a에 넣고, Array 1번 값을 변수b에 넣어주는 코드이다. Java언어에서 표현하자면 아래와 같다.

// 변수 할당해서 사용하거나
int[] arrayInt = { 10, 20 };
int a = arrayInt[ 0 ], b = arrayInt[ 1 ];

// 변수 할당하기 싫으면 이렇게
int a = new int[] { 10, 20 }[ 0 ], b = new int[] { 10, 20 }[ 1 ];

훨씬 길고 귀찮은 코드가 만들어졌다. Typescript는 저 귀찮은 코드를 짧게, 그리고 직관적이게 사용할 수 있는 기능을 제공한다.

1.1 배열 두 번째 자리만 할당하고 싶을 때 (혹은 특정자리만 할당하고 싶을 때)

혹시나 0번지의 값은 안 쓰고 1번지의 값만 사용하고 싶다면 다음의 코드처럼 작성하면 된다.

const [, b] = [10, 20];

1.2 앞자리 몇 개만 변수로 쓰고 나머지는 하나의 배열로 담고 싶을 때 (feat. Rest Op)

const [ a, ...b ] = [10, 20, 30, 40];

보면 알겠지만 나머지연산자를 사용하여 나머지 배열을 할당할 수 있다. 나머지 연산자에 대한 자세한 내용은 따로 참조.

1.3 배열이 없을 때는 기본값으로 넣어주고 싶을 때 (feat. Default Parameter Handling)

const [ a = 10 ] = [];

기본값 파라미터를 사용하면 된다.

1.4 응용으로 스왑

let a = 3, b = 6;
[ a, b ] = [ b, a ];
// a: 6
// b: 3

프로그래밍 처음 공부할 때 자주 쓰던 스왑이 이렇게 간편해진다.

2. Object Destructuring

Array와 마찬가지로 Object도 비구조화할 수 있다. 방법은 동일하다. 대신 대괄호(배열표현식)이 아닌 중괄호(객체표현식)를 사용하면 된다. 다만 배열에서는 순번을 기준으로 첫 번째 변수, 두 번째 변수로 구분하여 값을 넣어주지만 일반적으로 객체에는 순서가 없고 변수명으로 구분하기 때문에 객체 비구조화에는 변수명이 같아야 넣어줄 수 있다.

const obj = { a: 10, b: 20 };
const { a, b } = obj;

2.1 변수명을 바꾸고 싶을 때

변수명을 기존 선언되어 사용되는 변수명 말고 다른 변수명으로 바꿔 사용하고 싶다면 아래처럼 해야 한다. 코드가 쪼금 길어지고 귀찮아져 잘 안 쓰지만 가끔 이름에 의미를 더 부여하고 싶을 때 사용한다.

const obj = { a: 10, b: 20 };
const { a: a2, b: b2 } = obj;
// a2: 10
// b2: 20

2.2 객체 안에 안에 (중첩객체)

객체 안에 객체에 있는 변수를 사용하고 싶을 때 사용한다.

const user1 = { name: '홍길동', age: 24, address: { country: 'Korea', city: 'Seoul' } }
const { address: { city } } = user1;
console.log( city );
// Seoul

이렇게 해서 좋은 점이 길게 dot연산자를 사용하지 않고 짧게 쓸 수 있어서 좋지만 더 좋은 점은 undefined 체크를 firstName만 하면 된다는 것이다. 

// nullOrUndefined 체크 필요 없어서 편함.
const user = { name: { firstName: '길동', lastName: '홍' } };
const { name: { firstName } } = user;
console.log( 'firstName1: ',firstName );

// 에러 안 남.
const user2 = { name: undefined };
const { name: { firstName2 } } = user;
console.log( 'firstName2: ',firstName2 );

// 이 부분에서 에러.
try {
	const firstName3 = user2.name.firstName;
	console.log( 'firstName3: ',firstName3 );
} catch( e ) {
	console.log( 'error' );
}

// 위처럼 바로 접근해서 쓸 때 에러 안 나게 하려면 if나 아래처럼 해야 함.
const firstName4 = user2 && user2.name && user2.name.firstName;
console.log( 'firstName4: ', firstName4 );

2.3 응용으로 함수에서 편하게 사용하기

const users = [
  { name: '홍길동', age: 24 },
  { name: '고길동', age: 30 },
  { name: '이길동', age: 12 },
  { name: '박길동', age: 49 },
];
// 이름만 추출하기
const names = users.map( ( { name } ) => name );
console.log( names );
// ["홍길동", "고길동", "이길동", "박길동"]