Javascript

TypeScript에서 Array<T>와 T[]의 차이점 이해하기

드리프트2 2024. 7. 17. 20:51

 

TypeScript 배열 탐험: Array<T> vs T[] - 당신에게 맞는 선택은?

 

TypeScript는 JavaScript에 강력한 타입 시스템을 더해 코드의 안정성과 예측 가능성을 높여줍니다.

 

특히, JavaScript의 유연한 배열 다루기를 타입 안정성을 보장하며 수행할 수 있도록 두 가지 방식, Array<T>T[]를 제공합니다.

 

겉보기에는 비슷해 보이는 이 두 방식은 미묘한 차이를 지니고 있으며, 상황에 따라 적절한 선택이 달라질 수 있습니다.

 

이 글에서는 Array<T>T[]의 차이점을 심층 분석하고, 실제로 어떻게 활용되는지 다양한 예제와 함께 살펴보며, 여러분의 프로젝트에 적합한 선택을 할 수 있도록 가이드를 제공합니다.

 

1. 기본 이해: Array<T>T[] - 같은 듯 다른 두 친구

Array<T>: TypeScript의 제네릭 타입 시스템을 활용한 방식입니다.

<T> 부분은 타입 변수를 나타내며, 배열에 담길 요소의 타입을 유연하게 지정할 수 있도록 해줍니다.

 

예를 들어, Array<number>는 숫자 타입 요소만을 담는 배열을 의미합니다.

 

T[]: JavaScript의 배열 표기법을 그대로 가져온 직관적인 방식입니다.

 

원하는 타입 뒤에 []를 붙여 해당 타입의 요소를 가지는 배열임을 나타냅니다. 예를 들어, number[]는 숫자 타입 요소로 이루어진 배열을 의미합니다.

 

두 방식 모두 동일한 JavaScript 코드로 컴파일되며, 기능적인 차이는 없습니다.

 

기본 예제:

// Array<T>를 사용한 숫자 배열 선언
let numbers1: Array<number> = [1, 2, 3, 4, 5];

// T[]를 사용한 숫자 배열 선언
let numbers2: number[] = [1, 2, 3, 4, 5];

// 두 방식 모두 동일한 JavaScript 코드로 컴파일됩니다.
// var numbers1 = [1, 2, 3, 4, 5];
// var numbers2 = [1, 2, 3, 4, 5];

 

2. 가독성: 복잡한 구조에서 빛을 발하는 Array<T>

 

단순한 배열에서는 Array<T>T[] 모두 직관적입니다.

 

하지만, 배열 안에 배열이 중첩된 복잡한 구조를 다룰 때, Array<T>는 가독성 측면에서 강력한 이점을 제공합니다.

 

복잡한 구조 예제:

// 2차원 숫자 배열
let matrix1: Array<Array<number>> = [[1, 2, 3], [4, 5, 6], [7, 8, 9]];

// T[]를 사용한 경우
let matrix2: number[][] = [[1, 2, 3], [4, 5, 6], [7, 8, 9]];

 

matrix1Array<Array<number>>number[][] 보다 시각적으로 복잡해 보일 수 있지만, 각 차원의 타입을 명확하게 보여줍니다.

 

특히, 다차원 배열이나 복잡한 자료구조를 다룰 때, 이러한 명확성은 코드의 가독성과 유지보수성을 크게 향상시킵니다.

 

3. 일관성: TypeScript 생태계와 조화로운 Array<T>

TypeScript는 Promise<T>, Map<K, V>, Set<T> 등 다양한 제네릭 타입을 제공합니다.

 

이러한 제네릭 타입을 사용하는 코드에서 배열을 표현할 때, Array<T>를 사용하는 것이 일관성을 유지하는 데 유리합니다.

 

 

제네릭 타입과의 일관성 예제:

// Promise 객체를 담는 배열
let promises: Array<Promise<string>> = [
  Promise.resolve("Hello"), 
  Promise.resolve("World!")
];

// Map 객체를 담는 배열
let numberMap: Array<Map<string, number>> = [
  new Map([["one", 1], ["two", 2]]),
  new Map([["three", 3], ["four", 4]])
]; 

 

Array<Promise<string>>, Array<Map<string, number>> 와 같이 Array<T>는 다른 제네릭 타입과 자연스럽게 어울려 코드 전체의 일관성을 높여줍니다.

 

4. 함수 시그니처: 명료함을 더하는 Array<T>

함수의 매개변수나 반환 값으로 배열을 사용할 때, Array<T>는 함수 시그니처를 더욱 명확하게 만들어줍니다.

 

함수 시그니처 비교:

// Array<T>를 사용한 함수 선언
function reverseArray<T>(arr: Array<T>): Array<T> {
  return arr.slice().reverse();
}

// T[]를 사용한 함수 선언
function reverseArrayAlt<T>(arr: T[]): T[] {
  return arr.slice().reverse();
}

 

두 함수 모두 동일한 기능을 수행하지만, Array<T>를 사용한 reverseArray 함수의 시그니처가 조금 더 명확하고 읽기 쉽습니다.

 

특히, 제네릭 타입을 사용하는 복잡한 함수의 경우, Array<T>를 사용하면 타입 정보를 명확하게 전달하여 코드의 가독성을 향상시키고 오류 가능성을 줄일 수 있습니다.

 

5. 프로젝트 스타일 가이드: 일관성 유지의 중요성

Array<T>T[] 중 어떤 방식을 선택할지는 궁극적으로 개발자의 취향이나 프로젝트 컨벤션에 따라 결정될 수 있습니다.

 

중요한 것은 프로젝트 전체에서 일관된 스타일을 유지하는 것입니다.

 

만약 이미 존재하는 프로젝트에 참여하는 경우, 기존 코드 스타일을 따르는 것이 좋습니다.

 

새로운 프로젝트를 시작하는 경우, 팀 내부적으로 합의된 컨벤션을 정하고 따르는 것이 좋습니다.

 

결론: 상황에 맞는 현명한 선택

Array<T>T[]는 TypeScript에서 배열을 다루는 두 가지 유효한 방식입니다.

 

어떤 방식을 선택하든 기능적인 차이는 없지만, 코드의 가독성, 일관성, 유지보수성을 고려하여 프로젝트에 가장 적합한 방식을 선택하는 것이 중요합니다.

 

일반적으로 복잡한 자료구조를 다루거나 TypeScript의 다양한 제네릭 타입과 함께 사용하는 경우, Array<T>를 사용하는 것이 코드의 명확성과 일관성을 높이는 데 도움이 됩니다.

 

반면, JavaScript 스타일과의 친숙함이나 간결함을 선택하고 싶다면 T[]를 사용하는 것도 좋은 선택입니다.

 

가장 중요한 것은 프로젝트 전체에서 일관된 스타일을 유지하여 코드의 가독성과 유지보수성을 향상시키는 것입니다.

 

이 글이 여러분의 TypeScript 코드 작성에 도움이 되기를 바랍니다!