TypeScript에서 for 루프를 사용하는 모범 사례

TypeScript에서 for 루프를 사용하는 모범 사례

이 기사는 TypeScript에서 for 루프를 사용하는 모범 사례를 설명합니다.

YouTube Video

TypeScript에서 for 루프를 사용하는 모범 사례

for 문은 반복 작업을 수행하기 위한 기본적이고 강력한 구문입니다. TypeScript에서는 타입 안전성을 활용하고 가독성과 유지 가능성을 고려하여 코드를 작성하면 오류가 적고 효율적인 코드를 작성할 수 있습니다.

적절한 루프 유형 선택하기

TypeScript는 각각의 다양한 사용 사례에 적합한 여러 가지 루프 구조를 제공합니다. 적절한 루프를 선택하는 것은 코드의 가독성과 성능에 중요합니다.

표준 for 루프

1for (let i = 0; i < 10; i++) {
2    console.log(i);
3}

표준 for 루프는 반복 인덱스를 정확히 제어해야 할 때 이상적입니다.

모범 사례
1const maxIterations = 10;
2for (let i = 0; i < maxIterations; i++) {
3    console.log(i);
4}

for 문을 작성할 때, 다음의 점들을 염두에 두면 더 안전하고 가독성이 높은 코드를 작성할 수 있습니다.

  • 인덱스 변수에는 let을 사용하세요
    • var 대신 let을 사용하면 스코프를 블록 내로 제한하여 의도치 않은 동작을 방지할 수 있습니다.
  • 상수를 사용하고 명확한 변수 이름을 지정하여 루프 경계를 명확히하세요
    • 매직 넘버를 피하고 의미 있는 변수 이름을 사용하면 가독성이 향상됩니다.

for...of 루프

1const array = [1, 2, 3];
2for (let value of array) {
3    console.log(value);
4}

for...of 루프는 배열과 문자열 같은 반복 가능한 객체를 순회하는 데 적합합니다.

모범 사례
1const array = [1, 2, 3];
2for (const value of array) {
3    console.log(value);
4}

for...of 루프를 작성할 때, 다음 사항에 유의하면 더 안전한 코드를 작성할 수 있습니다.

  • 루프 변수에는 const를 사용하세요
    • 루프 내에서 값이 수정되지 않는 경우, const를 사용하면 실수로 값을 재할당하는 것을 방지할 수 있습니다.

for...in 루프

1const obj = { a: 1, b: 2, c: 3 };
2for (const key in obj) {
3    console.log(`${key}: ${obj[key]}`);
4}

for...in 루프는 객체의 열거 가능한 속성을 순회합니다.

모범 사례
1const obj = { a: 1, b: 2, c: 3 };
2for (const key in obj) {
3    if (obj.hasOwnProperty(key)) {
4        console.log(`${key}: ${obj[key]}`);
5    }
6}

for...in 루프를 작성할 때 고려할 수 있는 점은 다음과 같습니다.

  • 속성을 필터링하세요
    • 상속된 속성을 피해야 할 경우, hasOwnProperty를 사용할 수 있습니다.
  • 배열에는 for...in을 사용하지 마세요 배열에 for...in 사용을 피하세요. 배열 인덱스가 아닌 열거 가능한 모든 속성을 반복할 수 있습니다.

forEach 메서드

1const array = [1, 2, 3];
2array.forEach((value, index) => {
3    console.log(`Index: ${index}, Value: ${value}`);
4});

배열을 순회할 때 forEach는 간결하며 인덱스를 관리할 필요가 없습니다.

모범 사례

forEach 메서드를 사용할 때 고려할 수 있는 점은 다음과 같습니다.

  • 화살표 함수(arrow functions)를 사용하세요
    • 간결한 화살표 함수를 사용하여 가독성을 높이세요.
  • 중단을 피하세요
    • forEachbreak 또는 continue를 지원하지 않습니다. 필요에 따라 for...of 또는 for 루프를 사용하세요:.

타입 안전성과 오류 방지

TypeScript의 타입 시스템을 활용하여 반복 중 런타임 오류를 방지할 수 있습니다:.

루프 변수에 엄격한 타입 정의

1const items = [1, 2, 3];
2items.forEach(item => {
3    console.log(item * 2);
4});
1const items: number[] = [1, 2, 3];
2items.forEach((item: number) => {
3    console.log(item * 2);
4});

루프 변수에 대해 명시적으로 타입을 지정하면 타입 불일치를 초기에 감지할 수 있습니다.

암시적 any 지양

1{
2  "compilerOptions": {
3    "noImplicitAny": true
4  }
5}

또한, tsconfig.json에서 noImplicitAny를 활성화하면 명시적인 타입이 없는 변수가 암시적으로 any 타입으로 할당되는 것을 방지할 수 있습니다.

필요할 때 ReadonlyArray 사용

1const numbers: ReadonlyArray<number> = [1, 2, 3];
2for (const value of numbers) {
3    console.log(value);
4}

수정하면 안 되는 배열을 반복 처리해야 할 경우에는 ReadonlyArray를 사용할 수 있습니다.

성능 고려사항

대량의 데이터를 처리하거나 자주 실행되는 루프에서는 효율성이 중요합니다:.

최적의 루프 구현 방법을 선택하세요.

루프를 구현하는 방법에는 여러 가지가 있으며 각각 가독성과 실행 효율성에 차이가 있습니다.

 1// Prepare input data (an array from 1 to 1000000)
 2const input: number[] = Array.from({ length: 1000000 }, (_, i) => i + 1);
 3
 4// --- for ---
 5console.time('for loop');
 6const squaresFor: number[] = [];
 7for (let i = 0; i < input.length; i++) {
 8    squaresFor.push(input[i] * input[i]);
 9}
10console.timeEnd('for loop');
11
12// --- while ---
13console.time('while loop');
14const squaresWhile: number[] = [];
15let i: number = 0;
16while (i < input.length) {
17    squaresWhile.push(input[i] * input[i]);
18    i++;
19}
20console.timeEnd('while loop');
21
22// --- for-of ---
23console.time('for-of loop');
24const squaresForOf: number[] = [];
25for (const num of input) {
26    squaresForOf.push(num * num);
27}
28console.timeEnd('for-of loop');
29
30// --- forEach ---
31console.time('forEach loop');
32const squaresForEach: number[] = [];
33input.forEach((num: number): void => {
34    squaresForEach.push(num * num);
35});
36console.timeEnd('forEach loop');
37
38// --- map ---
39console.time('map');
40const squaresMap: number[] = input.map((value: number): number => value * value);
41console.timeEnd('map');

효율성은 실행 환경에 따라 다를 수 있지만, 예를 들어 루프를 백만 번 실행할 경우 그 차이가 상당히 눈에 띌 수 있습니다. 유지 보수성과 성능을 고려하여 최적의 루프 방법을 선택하십시오.

기본 반복 메서드 사용

 1const squares = [1, 2, 3].map(value => value * value);
 2console.log(squares);
 3
 4const numbers = [1, 2, 3, 4, 5, 6];
 5const evenNumbers = numbers.filter(value => value % 2 === 0);
 6console.log(evenNumbers); // [2, 4, 6]
 7
 8const squaredEvens = numbers
 9    .filter(value => value % 2 === 0) // Keep only even numbers
10    .map(value => value * value);     // Square the remaining values
11
12console.log(squaredEvens); // [4, 16, 36]

mapfilter 같은 메서드가 경우에 따라 더 가독성이 좋을 수 있습니다.

가독성을 위해 for...of 선호

성능은 제한된 경우에만 우선시해야 하며, 일반적으로 가독성이 높은 코드를 작성하는 것이 더 중요합니다. 예를 들어, for...of를 우선적으로 사용하면 가독성을 향상시킬 수 있습니다.

1const fruits = ["apple", "banana", "cherry"];
2
3for (let i = 0; i < fruits.length; i++) {
4    console.log(`${i}: ${fruits[i]}`);
5}
모범 사례
1const fruits = ["apple", "banana", "cherry"];
2
3for (const [index, fruit] of fruits.entries()) {
4    console.log(`${index}: ${fruit}`);
5}

for...of 루프를 우선적으로 사용하면 가독성이 높고 오류에 강한 코드를 작성할 수 있습니다. 이 예시와 같이 배열 인덱스가 필요하다면, entries()for...of를 결합하는 것이 효과적입니다.

일반적인 함정을 피하기

반복 중 컬렉션 수정

1const array = [1, 2, 3];
2for (const value of [...array]) {
3    if (value === 2) {
4        array.push(4); // Avoid this!
5    }
6}
7console.log(array);

반복 중 배열을 수정하면 예상치 못한 동작이 발생할 수 있습니다:. 필요한 경우 복사본을 사용하세요.

경계 사례를 고려하세요.

1const array: number[] = [];
2for (const value of array) {
3    console.log(value); // No output, but no errors
4}

이 코드는 잘 작동하지만, 빈 배열을 처리해야 한다면 다음과 같이 개선할 수 있습니다.

1const array: number[] = [];
2if (array.length === 0) {
3    console.log("The array is empty.");
4} else {
5    for (const value of array) {
6        console.log(value);
7    }
8}

경계 사례를 고려하면 후속 코드에서 오류를 방지할 수 있습니다.

결론

for 문을 TypeScript에서 잘 사용하려면 다양한 반복 구문을 이해하고, 타입 안전성을 준수하며, 성능을 최적화하는 것이 중요합니다. 이러한 모범 사례는 더 깔끔하고 신뢰할 수 있으며 유지보수가 쉬운 코드를 작성하는 데 도움을 줍니다.

위의 기사를 보면서 Visual Studio Code를 사용해 우리 유튜브 채널에서 함께 따라할 수 있습니다. 유튜브 채널도 확인해 주세요.

YouTube Video