548.타입스크립트란 무엇인가요?
타입스크립트(TypeScript)는 자바스크립트의 "슈퍼셋(superset)" 언어입니다. 즉, 자바스크립트를 기반으로 한 확장된 프로그래밍 언어입니다.
타입스크립트의 뿌리는 자바스크립트에 있으며, 자바스크립트의 기본 문법(if 문, for 반복문, 객체 사용법 등)을 그대로 사용합니다.
하지만 타입스크립트는 자바스크립트 문법에 몇 가지 중요한 기능을 추가합니다.
타입스크립트의 주요 특징
정적 타입(statically typed):
- 타입스크립트는 정적 타입 기능을 제공합니다. 자바스크립트는 동적 타입(dynamically typed) 언어로, 변수의 타입이 실행 중에 결정됩니다. 반면, 타입스크립트는 변수의 타입을 미리 지정할 수 있습니다.
- 예를 들어, 함수의 매개변수 타입을 명시하여 의도치 않은 타입의 값이 들어오는 것을 방지할 수 있습니다.
자바스크립트와 호환성:
- 타입스크립트는 자바스크립트와 완벽히 호환됩니다. 기존 자바스크립트 코드에 타입스크립트 기능을 추가할 수 있으며, 타입스크립트 코드는 자바스크립트로 컴파일됩니다.
개발 도구와의 통합:
- 타입스크립트는 강력한 개발 도구 통합을 제공합니다. 코드 작성 중에 오류를 미리 발견할 수 있으며, 코드 자동 완성, 리팩토링 지원 등 다양한 개발 편의 기능을 사용할 수 있습니다.
왜 타입스크립트를 사용해야 하나요?
- 코드 품질 향상:
- 타입스크립트를 사용하면 타입 오류를 컴파일 단계에서 미리 잡아낼 수 있어, 런타임 오류를 줄이고 코드의 안정성을 높일 수 있습니다.
- 개발 생산성 향상:
- 강력한 타입 시스템 덕분에 코드 자동 완성, 인텔리센스 등의 기능을 통해 개발 생산성을 높일 수 있습니다.
- 대규모 프로젝트 관리:
- 타입스크립트는 대규모 코드베이스에서 특히 유용합니다. 여러 개발자가 동시에 작업할 때 타입 시스템이 코드의 의도를 명확히 하고,
- 잘못된 사용을 방지하여 협업 효율성을 높입니다.
타입스크립트의 예시 코드
자바스크립트에서는 변수나 함수의 매개변수에 타입을 지정하지 않습니다. 따라서 다음과 같은 코드가 실행됩니다:
function add(a, b) { return a + b; } console.log(add(5, 2)); // 출력: 7 console.log(add('5', '2')); // 출력: '52'
위 예시에서 첫 번째 호출은 숫자 더하기 연산이 수행되지만, 두 번째 호출은 문자열 연결이 수행됩니다.
타입스크립트를 사용하면, 함수의 매개변수 타입을 명시할 수 있습니다:
function add(a: number, b: number): number { return a + b; } console.log(add(5, 2)); // 출력: 7 console.log(add('5', '2')); // 컴파일 오류 발생
타입스크립트에서는 add 함수가 숫자형 매개변수를 요구하도록 명시하였습니다. 따라서 문자열을 전달하면 컴파일 단계에서 오류가 발생하여 잘못된 사용을 방지할 수 있습니다.
결론
타입스크립트는 자바스크립트의 기능을 확장하여 보다 안전하고 효율적인 코드 작성을 돕는 강력한 도구입니다.
정적 타입 시스템을 통해 코드의 오류를 미리 잡아내고, 개발 생산성을 높일 수 있으며, 특히 대규모 프로젝트에서의 협업을 더욱 원활하게 해줍니다.
타입스크립트의 이러한 장점 덕분에 많은 개발자들이 자바스크립트 프로젝트에 타입스크립트를 도입하고 있습니다.
549.TypeScript 설치 및 사용하기
타입스크립트를 사용하기 위해 먼저 설치해야 합니다. 이를 위해 공식 웹 페이지인 typescriptlang.org를 방문하여 설치 방법을 확인할 수 있습니다.
일반적으로 특정 프로젝트에만 설치하는 것이 좋습니다. 설치를 위해 터미널에서 npm 패키지 매니저를 사용합니다. 먼저 프로젝트 폴더에서 npm init -y 명령어를 실행하여 package.json 파일을 생성하고,
그 후 npm install typescript 명령어를 통해 타입스크립트를 설치합니다.
타입스크립트는 자바스크립트의 슈퍼셋이기 때문에, 컴파일 과정을 거쳐 자바스크립트 파일로 변환되어야 합니다. 이를 위해 타입스크립트 컴파일러를 사용해야 하며, 컴파일러는 프로젝트 내에 타입스크립트 구성 파일을 필요로 합니다. 컴파일러를 사용하여 타입스크립트 파일을 자바스크립트로 변환하고 오류를 확인할 수 있습니다. 컴파일 단계에서 오류가 발생해도 컴파일은 완료되며, 오류 정보는 표시됩니다.
타입스크립트의 핵심 기능을 이해하고 나면, 리액트와 함께 사용하는 방법에 대해 알아볼 수 있습니다. 리액트와 타입스크립트를 함께 사용하면 코드의 가독성과 유지 보수성이 향상되며, 타입 안정성을 보장할 수 있습니다. 따라서 리액트 프로젝트에서 타입스크립트를 적용하는 것이 권장됩니다.
with-typescript.ts
function add(a:number, b:number) { return a + b; } const result = add(2, 5); console.log(result);
550.기본 유형 탐색하기
타입스크립트에서 배열과 객체 타입을 어떻게 정의하고 사용하는지에 대해 자세히 알아보겠습니다. 먼저 배열 타입부터 살펴보겠습니다.
배열 타입 지정하기
만약 hobbies라는 변수가 문자열 배열 타입이라면, 타입스크립트에서 이를 명확하게 지정해야 합니다. 만약 hobbies에 단일 문자열을 저장하려는 것이 아니라 문자열의 배열을 저장하고 싶다면, 다음과 같이 타입을 지정해야 합니다:
let hobbies: string[];
위 코드에서 string[]는 hobbies가 문자열의 배열임을 타입스크립트에게 알리는 방식입니다. 이렇게 지정한 후에는 hobbies에 여러 개의 문자열을 할당할 수 있습니다:
hobbies = ['Reading', 'Traveling', 'Cooking'];
이렇게 할당하면 hobbies는 문자열 배열이 됩니다. 만약 여기에 문자열이 아닌 다른 타입의 값을 추가하려고 하면 타입스크립트가 오류를 발생시킵니다:
hobbies.push(42); // 오류 발생: 'number' 형식은 'string' 형식에 할당할 수 없습니다.
객체 타입 지정하기
이번에는 객체 타입을 지정해보겠습니다. 예를 들어, person이라는 변수에 객체를 저장하고 싶다면 다음과 같이 할 수 있습니다:
let person = { name: 'John', age: 30 };
기본적으로 타입스크립트는 이 변수의 타입을 any로 간주합니다. 하지만, 명확하게 특정 타입의 객체만 저장하고 싶다면, 타입을 지정해야 합니다. 다음과 같이 객체의 구조를 정의할 수 있습니다.
let person: { name: string; age: number };
위 코드에서 { name: string; age: number }는 person 객체가 name이라는 문자열 필드와 age라는 숫자 필드를 가져야 한다는 것을 나타냅니다.
이제 이 타입 정의에 맞는 객체만 person 변수에 할당할 수 있습니다
person = { name: 'John', age: 30 }; // 유효
만약 구조가 다른 객체를 할당하려고 하면 오류가 발생합니다.
person = { name: 'John', age: 30, isEmployee: true }; // 오류 발생: 'isEmployee' 필드는 할당할 수 없습니다.
배열과 객체 타입의 조합
배열과 객체 타입을 조합해서 사용할 수도 있습니다. 예를 들어, 여러 개의 person 객체를 포함하는 people 배열을 정의하고 싶다면 다음과 같이 할 수 있습니다
let people: { name: string; age: number }[];
위 코드에서 { name: string; age: number }[]는 people이 특정 구조를 가진 객체의 배열임을 나타냅니다. 이제 people 배열에 객체를 추가할 수 있습니다.
people = [ { name: 'John', age: 30 }, { name: 'Jane', age: 25 } ];
이 배열에는 name 필드가 문자열이고 age 필드가 숫자인 객체만 추가할 수 있습니다. 다른 구조를 가진 객체를 추가하면 오류가 발생합니다
people.push({ name: 'Doe', age: 40, isEmployee: true }); // 오류 발생
이렇게 타입스크립트에서 배열과 객체 타입을 정의하고 사용하는 방법을 통해 코드의 가독성과 안정성을 높일 수 있습니다. 다양한 타입스크립트 기능을 조합하면 더욱 복잡하고 견고한 타입 시스템을 구축할 수 있습니다
//Primitives:number, string, boolean //More complex types: arrays, objects, //Function types, parameters //Primitives let age: number; age =12; let userName: string; userName = "Max"; let isInstructor :boolean ; isInstructor=true;
551.배열 및 객체 유형 작업하기
타입스크립트에서 배열과 객체 타입을 지정하는 방법을 단계별로 살펴보겠습니다.
1. 배열 타입 지정
배열 타입을 지정하는 방법은 배열에 저장될 데이터 타입 뒤에 대괄호([])를 붙이는 것입니다. 예를 들어,
hobbies라는 변수가 문자열 배열을 저장하도록 지정하려면 다음과 같이 작성합니다.
let hobbies: string[];
이렇게 하면 hobbies는 문자열 배열이라는 것을 타입스크립트에게 알려주는 것입니다. 이제 hobbies 변수에는 여러 개의 문자열을 저장할 수 있습니다.
hobbies = ["reading", "traveling", "cooking"];
만약 문자열이 아닌 다른 타입의 값을 추가하려고 하면 오류가 발생합니다. 예를 들어, 숫자를 추가하려고 하면 타입 오류가 발생합니다.
hobbies.push(42); // 오류: 'number' 타입은 'string' 타입에 할당할 수 없습니다.
2. 객체 타입 지정
객체 타입을 지정하는 방법은 객체의 구조를 정의하는 것입니다. 예를 들어, person이라는 변수에 이름과 나이를 저장하는 객체를 할당하려면 다음과 같이 작성합니다.
let person: {
name: string;
age: number;
};
이제 person 변수에는 다음과 같은 구조를 가진 객체만 저장될 수 있습니다:
person = {
name: "John",
age: 30
};
만약 정의된 구조와 다른 형태의 객체를 할당하려고 하면 오류가 발생합니다. 예를 들어, 부울 값을 가진 객체를 할당하려고 하면 다음과 같은 오류가 발생합니다.
person = {
name: "John",
age: 30,
isEmployee: true // 오류: 'isEmployee' 속성은 '{ name: string; age: number; }' 타입에 존재하지 않습니다.
};
3. 배열과 객체 타입을 조합하기
배열과 객체 타입을 조합하여 더 복잡한 구조를 만들 수 있습니다. 예를 들어, people이라는 변수가 여러 개의 person 객체를 저장하도록 하려면 다음과 같이 작성합니다.
let people: {
name: string;
age: number;
}[];
이제 people 변수에는 여러 개의 person 객체를 배열 형태로 저장할 수 있습니다.
people = [
{ name: "Alice", age: 25 },
{ name: "Bob", age: 28 }
];
이렇게 하면 people 변수에는 정의된 객체 타입을 가진 객체 배열만 저장될 수 있습니다.
예제 코드
아래는 위에서 설명한 모든 내용을 포함하는 예제 코드입니다
// 문자열 배열 타입 지정
let hobbies: string[];
hobbies = ["reading", "traveling", "cooking"];
// hobbies.push(42); // 오류 발생: 'number' 타입은 'string' 타입에 할당할 수 없습니다.
// 객체 타입 지정
let person: {
name: string;
age: number;
};
person = {
name: "John",
age: 30
};
// person = {
// name: "John",
// age: 30,
// isEmployee: true // 오류 발생: 'isEmployee' 속성은 '{ name: string; age: number; }' 타입에 존재하지 않습니다.
// };
// 객체 배열 타입 지정
let people: {
name: string;
age: number;
}[];
people = [
{ name: "Alice", age: 25 },
{ name: "Bob", age: 28 }
];
타입스크립트에서는 선택적 속성을 지정할 수 있습니다. 이를 위해 속성 이름 뒤에 물음표(?)를 붙여서 해당 속성이 선택적임을 나타낼 수 있습니다.
이렇게 하면 해당 속성을 생략하거나 undefined로 설정할 수 있습니다. 아래에 예시를 들어 보겠습니다:
let person :{
name: string,
age: number,
isEmployee? : boolean
}
person = {
name: 'Max',
age: 32
}
person = {
isEmployee: true,
}
위의 코드에서 isEmployee는 선택적 속성이므로, person 객체를 생성할 때 이 속성을 생략해도 타입스크립트 오류가 발생하지 않습니다.
이렇게 하면 isEmployee 속성을 필수 입력 조건이 아니어도 오류가 발생하지 않게 할 수 있습니다.
이제 타입스크립트를 사용하여 배열과 객체의 타입을 명확하게 지정하고,
정의된 구조에 맞지 않는 데이터를 할당하려고 할 때 오류를 발생시켜 코드의 안정성과 가독성을 높일 수 있습니다.
552.타입스크립트의 타입 추론(Type Inference)
타입스크립트에서는 타입 추론을 통해 변수의 타입을 자동으로 유추합니다. 이를 통해 코드 작성이 간편해지고,
명시적으로 타입을 지정하지 않아도 안전하게 코드를 작성할 수 있습니다. 타입 추론의 기본 원리와 장점을 살펴보겠습니다.
타입 추론이란?
타입 추론은 타입스크립트가 변수나 상수의 초기 값을 바탕으로 해당 변수의 타입을 자동으로 결정하는 기능입니다.
이를 통해 타입을 명시적으로 지정하지 않아도 변수의 타입이 정해집니다.
예시를 통한 설명
변수를 선언하면서 타입을 지정하고 초기값을 할당하는 경우와, 초기값만 할당하고 타입을 지정하지 않는 경우를 비교해보겠습니다.
1. 명시적으로 타입 지정하기
다음은 변수를 선언할 때 타입을 명시적으로 지정하는 예시입니다.
let course: string;
course = "React 완벽 가이드";
2. 타입 추론을 이용하기
타입스크립트는 초기값을 보고 변수의 타입을 추론합니다.
let course = "React 완벽 가이드";
이 경우, 타입스크립트는 course 변수의 타입을 문자열(string)로 추론합니다. 따라서 course에 숫자 값을 할당하려고 하면 오류가 발생합니다.
course = 123; // 오류: 'number' 타입은 'string' 타입에 할당할 수 없습니다.
타입 추론의 작동 원리
타입스크립트는 변수에 초기값을 할당할 때 해당 값의 타입을 분석하여 변수의 타입을 결정합니다.
이 과정을 통해 코드 작성 시 타입을 명시적으로 지정하지 않아도 타입스크립트가 올바른 타입을 추론해줍니다.
let course = "React 완벽 가이드"; // 'course'는 자동으로 'string' 타입이 됩니다.
위 코드에서 course 변수는 초기값이 문자열이므로, 타입스크립트는 course의 타입을 자동으로 string으로 설정합니다.
타입 추론의 장점
- 코드의 간결성: 불필요하게 타입을 명시하지 않아도 되므로 코드가 간결해집니다.
- 유지보수 용이성: 코드 변경 시 타입을 자동으로 추론하므로, 타입을 일일이 수정할 필요가 없습니다.
- 자동 완성 기능 향상: 타입스크립트는 추론된 타입을 바탕으로 코드 자동 완성 기능을 제공합니다.
실습 예제
다음은 타입 추론을 이용한 간단한 예제입니다.
// 타입 추론을 통한 변수 선언
let course = "React 완벽 가이드"; // 'course'는 'string' 타입으로 추론됩니다.
// 숫자를 할당하려고 하면 오류가 발생합니다
// course = 123; // 오류: 'number' 타입은 'string' 타입에 할당할 수 없습니다.
이 예제에서 course 변수는 문자열로 초기화되었으므로, 타입스크립트는 자동으로 course의 타입을 string으로 추론합니다.
따라서 이후에 숫자를 할당하려고 하면 타입 오류가 발생합니다.
결론
타입 추론은 타입스크립트의 강력한 기능 중 하나로, 코드 작성 시 타입을 명시적으로 지정하지 않아도 타입스크립트가 자동으로 타입을 결정해줍니다.
이를 통해 코드의 간결성과 유지보수성이 향상됩니다. 가능하면 타입 추론을 활용하여 불필요한 타입 지정을 피하고, 더 간결하고 읽기 쉬운 코드를 작성하는 것이 좋습니다.
553.유니온 유형 사용하기
지금까지 타입스크립트에서 변수에 하나의 타입만 지정하는 방법을 배웠습니다. 하지만 경우에 따라 하나의 변수에 여러 타입의 값을 저장해야 할 때가 있습니다.
이런 상황에서는 유니온 타입을 사용하여 변수에 여러 타입을 허용할 수 있습니다.
유니온 타입이란?
유니온 타입은 하나의 변수에 여러 타입을 지정할 수 있도록 하는 타입스크립트의 기능입니다. 이를 통해 변수에 다양한 타입의 값을 저장할 수 있습니다.
유니온 타입 사용법
유니온 타입을 사용하려면 파이프(|) 문자를 사용하여 여러 타입을 나열합니다. 예를 들어, course 변수에 문자열 또는 숫자를 저장할 수 있도록 하려면 다음과 같이 작성합니다.
let course: string | number;
이렇게 하면 course 변수에는 문자열과 숫자 모두 저장할 수 있습니다.
course = "React 완벽 가이드"; // 문자열 저장
course = 101; // 숫자 저장
예제: 유니온 타입 사용하기
아래는 유니온 타입을 사용하여 여러 타입의 값을 저장할 수 있는 변수를 선언하는 예제입니다.
// course 변수는 문자열 또는 숫자를 저장할 수 있습니다.
let course: string | number;
course = "React 완벽 가이드"; // 문자열 할당
console.log(course); // 출력: React 완벽 가이드
course = 123; // 숫자 할당
console.log(course); // 출력: 123
// userName 변수는 문자열 또는 문자열 배열을 저장할 수 있습니다.
let userName: string | string[];
userName = "John Doe"; // 문자열 할당
console.log(userName); // 출력: John Doe
userName = ["John", "Doe"]; // 문자열 배열 할당
console.log(userName); // 출력: ["John", "Doe"]
이 예제에서 course 변수는 문자열과 숫자 모두를 저장할 수 있습니다. userName 변수는 문자열 또는 문자열 배열을 저장할 수 있습니다. 유니온 타입을 사용하면 변수에 저장될 수 있는 값의 타입이 다양해져 유연성이 높아집니다.
유니온 타입의 장점
- 유연성: 하나의 변수에 여러 타입의 값을 저장할 수 있어 코드의 유연성이 높아집니다.
- 안전성: 타입스크립트는 유니온 타입을 사용하더라도 타입 검사를 통해 잘못된 타입의 값이 할당되지 않도록 합니다.
- 코드 가독성: 변수에 저장될 수 있는 값의 타입을 명시적으로 정의하므로 코드의 가독성이 높아집니다.
유니온 타입을 활용한 실습 예제
아래는 유니온 타입을 활용한 간단한 실습 예제입니다.
// 변수에 문자열 또는 숫자를 저장할 수 있는 유니온 타입 지정
let identifier: string | number;
identifier = "ID_12345"; // 문자열 할당
console.log(`Identifier: ${identifier}`); // 출력: Identifier: ID_12345
identifier = 67890; // 숫자 할당
console.log(`Identifier: ${identifier}`); // 출력: Identifier: 67890
// 함수에 유니온 타입 매개변수 사용
function printId(id: string | number) {
console.log(`Your ID is: ${id}`);
}
printId("ID_12345"); // 출력: Your ID is: ID_12345
printId(67890); // 출력: Your ID is: 67890
// 객체에 유니온 타입 사용
let person: { name: string; age: number | string };
person = { name: "Alice", age: 25 }; // 나이는 숫자
console.log(`Person: ${person.name}, Age: ${person.age}`); // 출력: Person: Alice, Age: 25
person = { name: "Bob", age: "Twenty-five" }; // 나이는 문자열
console.log(`Person: ${person.name}, Age: ${person.age}`); // 출력: Person: Bob, Age: Twenty-five
이 예제에서는 유니온 타입을 사용하여 identifier 변수와 printId 함수의 매개변수, 그리고 person 객체의 age 속성에 여러 타입의 값을 할당할 수 있도록 했습니다.
결론
유니온 타입은 타입스크립트의 핵심 기능 중 하나로, 변수에 여러 타입의 값을 저장할 수 있게 해줍니다.
이를 통해 코드의 유연성과 가독성이 높아지며, 타입스크립트의 타입 검사를 통해 코드의 안정성을 유지할 수 있습니다.
유니온 타입을 적절히 활용하여 더 유연하고 안전한 코드를 작성해보세요.
554.Type Aliases의 이해
타입스크립트의 타입 별칭 (Type Aliases)
타입스크립트를 사용하다 보면 동일한 타입 정의를 반복해서 사용하는 경우가 많습니다. 이를 방지하고 코드의 재사용성을 높이기 위해 타입 별칭을 사용할 수 있습니다. 타입 별칭은 특정 타입 구조를 정의하고, 이를 여러 곳에서 사용할 수 있게 해줍니다.
타입 별칭이란?
타입 별칭(Type Alias)은 특정 타입 구조에 이름을 부여하여 재사용할 수 있도록 하는 기능입니다. 이를 통해 코드 중복을 줄이고, 코드의 가독성과 유지보수성을 높일 수 있습니다.
타입 별칭 정의하기
타입 별칭을 정의하려면 type 키워드를 사용합니다. 다음은 Person이라는 타입 별칭을 정의하는 예제입니다.
type Person = {
name: string;
age: number;
};
이제 Person 타입 별칭을 사용하여 변수를 선언할 수 있습니다.
let person: Person;
person = { name: "Alice", age: 25 }; // Person 타입의 객체 할당
예제: 타입 별칭 사용하기
다음은 타입 별칭을 사용하여 동일한 타입 구조를 여러 곳에서 사용하는 예제입니다.
// Person 타입 별칭 정의
type Person = {
name: string;
age: number;
};
// person 변수에 Person 타입 사용
let person: Person = { name: "Alice", age: 25 };
// people 배열에 Person 타입 사용
let people: Person[] = [
{ name: "Bob", age: 30 },
{ name: "Charlie", age: 35 }
];
console.log(person); // 출력: { name: 'Alice', age: 25 }
console.log(people); // 출력: [{ name: 'Bob', age: 30 }, { name: 'Charlie', age: 35 }]
이 예제에서는 Person 타입 별칭을 사용하여 person 변수와 people 배열을 선언했습니다. 이렇게 하면 코드의 중복을 피하고, 동일한 타입 구조를 여러 곳에서 일관되게 사용할 수 있습니다.
타입 별칭의 장점
- 코드 중복 감소: 동일한 타입 구조를 반복해서 정의할 필요가 없어 코드 중복이 줄어듭니다.
- 가독성 향상: 코드가 더 간결해지고, 타입 구조를 쉽게 이해할 수 있습니다.
- 유지보수 용이: 타입 정의를 한 곳에서 관리할 수 있어 유지보수가 쉬워집니다.
타입 별칭을 활용한 실습 예제
아래는 더 복잡한 타입 구조에 타입 별칭을 사용하는 예제입니다.
// Address 타입 별칭 정의
type Address = {
street: string;
city: string;
country: string;
};
// Person 타입 별칭 정의 (Address 타입 포함)
type Person = {
name: string;
age: number;
address: Address;
};
// person 변수에 Person 타입 사용
let person: Person = {
name: "Alice",
age: 25,
address: {
street: "123 Main St",
city: "Seoul",
country: "Korea"
}
};
console.log(person);
// 출력: { name: 'Alice', age: 25, address: { street: '123 Main St', city: 'Seoul', country: 'Korea' } }
// people 배열에 Person 타입 사용
let people: Person[] = [
{
name: "Bob",
age: 30,
address: {
street: "456 Park Ave",
city: "New York",
country: "USA"
}
},
{
name: "Charlie",
age: 35,
address: {
street: "789 Elm St",
city: "London",
country: "UK"
}
}
];
console.log(people);
// 출력:
// [
// { name: 'Bob', age: 30, address: { street: '456 Park Ave', city: 'New York', country: 'USA' } },
// { name: 'Charlie', age: 35, address: { street: '789 Elm St', city: 'London', country: 'UK' } }
// ]
이 예제에서는 Address 타입 별칭을 먼저 정의하고, 이를 Person 타입 별칭 내에서 사용했습니다. 이를 통해 Person 타입 객체를 선언하고, people 배열에 동일한 타입 구조를 사용하여 객체들을 저장할 수 있습니다.
결론
타입 별칭(Type Alias)은 타입스크립트의 강력한 기능 중 하나로, 코드의 재사용성을 높이고, 중복을 줄이며, 가독성과 유지보수성을 향상시킵니다. 이를 통해 더 효율적이고 관리하기 쉬운 코드를 작성할 수 있습니다. 필요에 따라 타입 별칭을 사용하여 코드를 더욱 간결하고 명확하게 작성해 보세요
555.함수 및 함수 유형
타입스크립트의 함수와 타입 지정
타입스크립트에서 함수에 타입을 지정하는 방법과 중요한 개념인 제네릭 타입에 대해 살펴보겠습니다. 먼저, 함수의 타입 지정부터 시작하겠습니다.
함수에 타입 지정하기
함수에 타입을 지정할 때, 매개변수와 반환 값의 타입을 명시할 수 있습니다. 이를 통해 함수의 입력과 출력 타입을 명확하게 정의할 수 있습니다.
예제: add 함수
function add(a: number, b: number): number {
return a + b;
}
이 함수는 두 개의 숫자를 입력받아 그 합을 반환합니다. 여기서 a와 b의 타입은 number로 지정되어 있고, 반환 타입도 number로 명시되어 있습니다.
타입스크립트는 반환 타입을 추론할 수 있기 때문에, 명시적으로 지정하지 않아도 괜찮습니다. 하지만 코드의 가독성을 위해 명시적으로 지정할 수도 있습니다.
예제: 반환 타입 추론
function add(a: number, b: number) {
return a + b;
}
let result = add(2, 3); // result의 타입은 number로 추론됨
타입스크립트는 add 함수의 반환 타입을 자동으로 추론하여 number로 간주합니다.
특별한 반환 타입: void
반환 값이 없는 함수의 경우, 반환 타입으로 void를 사용합니다.
function printOutput(value: any): void {
console.log(value);
}
이 함수는 반환 값이 없으므로 반환 타입을 void로 지정했습니다.
556.제네릭으로 뛰어들다.
타입스크립트 제네릭 (Generics)
제네릭은 타입스크립트에서 매우 강력한 기능으로, 함수, 클래스, 인터페이스, 그리고 기타 구조에서 타입을 유연하게 사용하도록 도와줍니다. 앞서 설명한 것처럼 제네릭을 사용하면 함수나 클래스가 다양한 타입을 처리할 수 있게 됩니다.
예제: 제네릭 함수
여기서 제네릭 함수를 만들면서 제네릭 타입의 사용법을 좀 더 자세히 살펴보겠습니다.
insertAtBeginning 함수
우선 insertAtBeginning 함수를 정의해 보겠습니다. 이 함수는 배열과 값을 매개변수로 받아서, 값을 배열의 시작 부분에 추가한 새로운 배열을 반환합니다.
function insertAtBeginning<T>(array: T[], value: T): T[] { return [value, ...array]; }
제네릭 타입 사용법
제네릭 타입 선언:
- 함수 이름과 매개변수 목록 사이에 <T>를 추가하여 제네릭 타입을 선언합니다. 여기서 T는 타입을 의미하는 임의의 식별자입니다.
제네릭 타입 사용:
- 함수 매개변수와 반환 타입에 T를 사용하여 함수가 다양한 타입을 처리할 수 있게 합니다.
함수 사용 예제
const demoArray = [1, 2, 3]; const updatedArray = insertAtBeginning(demoArray, -1); console.log(updatedArray); // 출력: [-1, 1, 2, 3] const stringArray = insertAtBeginning(['b', 'c', 'd'], 'a'); console.log(stringArray); // 출력: ['a', 'b', 'c', 'd']
여기서 updatedArray는 숫자 배열로, stringArray는 문자열 배열로 각각 올바르게 추론됩니다.
타입 안전성
타입스크립트는 insertAtBeginning 함수에 전달된 인수들의 타입을 확인합니다. 예를 들어, 다음과 같은 코드에서는 오류가 발생합니다.
const mixedArray = insertAtBeginning([1, 2, 3], 'string'); // 오류 발생
이 코드에서는 숫자 배열에 문자열을 추가하려고 하므로 타입스크립트는 오류를 표시합니다. 제네릭을 사용함으로써 함수가 타입 안전성을 유지하면서도 유연하게 사용할 수 있게 됩니다.
요약
제네릭은 타입스크립트에서 매우 중요한 기능입니다. 함수나 클래스, 인터페이스에 제네릭 타입을 사용하면 코드의 유연성과 타입 안전성을 동시에 확보할 수 있습니다. 제네릭을 사용하여 다양한 타입을 처리할 수 있는 강력한 함수를 작성할 수 있습니다.
557.제네릭 자세히 살펴보기
제네릭 유형("Generics")은 꽤 까다로울 수 있습니다.
그러나 실제로 우리는 항상 그들과 함께 일하고 있습니다. 가장 두드러진 예 중 하나는 배열입니다.
다음 예제 배열을 보시죠:
let numbers = [1, 2, 3];
여기서 유형이 유추되지만 명시적으로 할당하면 다음과 같이 할 수 있습니다:
let numbers: number[] = [1, 2, 3];
number[] 는 TypeScript 표기법으로써 "이것은 숫자의 배열입니다" 라고 정의하는 것입니다.
그러나 실제로, number[]는 문법적 설탕입니다.
실제 유형은 Array입니다. 모든 배열은 Array 유형입니다.
그러나 배열 유형은 배열의 항목 유형도 설명하는 경우에만 의미가 있으므로 Array 은 실제로는 제네릭 유형입니다.
위의 예를 다음과 같이 작성할 수도 있습니다:
let numbers: Array<number> = [1, 2, 3];
여기에 다시 꺾쇠 괄호(<>)가 있습니다! 그러나 이번에는 (이전 강의에서 했던 것처럼) 우리 자신의 유형을 만드는 것이 아니라 TypeScript에 실제 유형이 "generic type placeholder"에 사용되야 한다고 하는 것입니다 (T, 이전 강의에서).
지난 강의에서 본 것처럼 TypeScript는 이것을 추론할 수도 있습니다. 우리는 다음과 같이 작성할 때 그것에 의존합니다:
let numbers = [1, 2, 3];
그러나 명시적으로 유형을 설정하려면 다음과 같이 할 수 있습니다:
let numbers: Array<number> = [1, 2, 3];
물론 이 길고 투박한 유형을 작성하는 것은 약간 성가실 수 있습니다. 그래서 배열에 대해 다음과 같은 대안(문법적 설탕)이 있습니다:
let numbers: number[] = [1, 2, 3];
이전 강의의 예를 들면 자리 표시자에 대한 구체적인 유형을 설정할 수도 있습니다. T명시적으로:
const stringArray = insertAtBeginning<string>(['a', 'b', 'c'], 'd');
따라서 꺾쇠 괄호를 사용하여 제네릭 유형을 정의할 수 있을 뿐만 아니라 제네릭 유형을 사용하고 사용해야 하는 자리 표시자 유형을 명시적으로 설정할 수도 있습니다. 때로는 TypeScript가 (올바른) 유형을 유추할 수 없는 경우에 필요합니다. 이 과정 섹션의 뒷부분에서 살펴보겠습니다!
558.리액트 + TypeScript 프로젝트 만들기
리액트와 타입스크립트 프로젝트 생성 및 설정
리액트 프로젝트에서 타입스크립트를 사용하는 방법을 단계별로 살펴보겠습니다. 이 과정에서 새로운 리액트 프로젝트를 생성하고, 타입스크립트로 설정하는 방법을 다룹니다.
1. 새로운 리액트 프로젝트 생성
먼저, 터미널을 열고 다음 명령어를 사용하여 새로운 리액트 프로젝트를 생성합니다.
npx create-react-app my-app --template typescript
위 명령어에서 my-app은 프로젝트 이름이며, --template typescript 플래그를 사용하여 타입스크립트 템플릿을 적용합니다.
2. 프로젝트 디렉터리로 이동
프로젝트 생성이 완료되면 생성된 프로젝트 디렉터리로 이동합니다.
cd my-app
3. 개발 서버 실행
다음 명령어를 사용하여 개발 서버를 실행합니다.
npm start
브라우저에서 localhost:3000으로 접속하면 기본 리액트 시작 화면을 볼 수 있습니다.
4. 타입스크립트 설정 확인
프로젝트가 성공적으로 생성되었으면, 프로젝트 구조와 파일들을 확인해 봅니다. src 폴더에 있는 파일들은 .tsx 확장자를 가지며, 이는 타입스크립트와 JSX를 함께 사용하기 위해 필요합니다.
5. 타입스크립트 의존성 확인
package.json 파일을 열어보면, dependencies 섹션에 typescript, @types/react, @types/react-dom 등이 추가된 것을 볼 수 있습니다. 이들은 타입스크립트와 리액트 간의 타입 호환성을 위해 필요합니다.
"dependencies": { "react": "^17.0.2", "react-dom": "^17.0.2", "react-scripts": "4.0.3", "typescript": "^4.1.2", "@types/react": "^17.0.0", "@types/react-dom": "^17.0.0" }
559.컴포넌트 및 TypeScript 작업하기
App.tsx
import Todos from './components/Todos'; function App() { return ( <div> <Todos ></Todos> </div> ); } export default App;
Todos.tsx
function Todos() { return ( <ul> <li>Learn React</li> <li>Learn TypeScript</li> </ul> ); } export default Todos;
560.Props 및 TypeScript 작업하기
TypeScript와 React를 사용한 To-do 리스트 컴포넌트 작성
TypeScript와 React를 함께 사용하면 타입 안전성을 확보하면서 코드의 가독성과 유지보수성을 높일 수 있습니다. 특히, React 컴포넌트의 props를 정의할 때 TypeScript의 기능을 활용하면 컴포넌트 사용 시 올바른 props를 전달하지 않는 경우에 오류를 즉시 확인할 수 있습니다. 다음은 items라는 props를 받아서 목록을 렌더링하는 컴포넌트를 만드는 예제입니다.
1. 기본 설정
먼저, 프로젝트에 TypeScript와 React를 설정해야 합니다. 일반적으로 create-react-app을 사용하면 쉽게 설정할 수 있습니다:
npx create-react-app my-app --template typescript cd my-app
이 명령을 실행하면 TypeScript가 설정된 React 프로젝트가 생성됩니다.
2. Todos 컴포넌트 작성
다음으로, Todos 컴포넌트를 작성하겠습니다. 이 컴포넌트는 items라는 props를 받아서 이를 리스트 형태로 렌더링합니다.
import React from 'react'; // Todos 컴포넌트의 props 타입 정의 interface TodosProps { items: string[]; } // Todos 컴포넌트 정의 const Todos: React.FC<TodosProps> = ({ items }) => { return ( <ul> {items.map((item, index) => ( <li key={index}>{item}</li> ))} </ul> ); }; export default Todos;
이 코드는 items라는 문자열 배열을 받아서 각 항목을 <li> 요소로 렌더링하는 Todos 컴포넌트를 정의합니다. TodosProps 인터페이스를 사용하여 props의 타입을 정의했습니다
.
3. App 컴포넌트에서 Todos 사용
다음으로, App 컴포넌트에서 Todos 컴포넌트를 사용해 보겠습니다.
import React from 'react'; import Todos from './Todos'; const App: React.FC = () => { const todoItems = ['리액트 공부하기', '타입스크립트 공부하기']; return ( <div> <h1>To-do List</h1> <Todos items={todoItems} /> </div> ); }; export default App;
App 컴포넌트에서는 todoItems라는 문자열 배열을 정의하고 이를 Todos 컴포넌트에 props로 전달합니다.
4. 전체 코드 구조
위의 코드를 프로젝트에 적용하면 다음과 같은 구조가 됩니다.
my-app/ ├── node_modules/ ├── public/ ├── src/ │ ├── App.tsx │ ├── Todos.tsx │ ├── index.tsx │ ├── ... ├── package.json ├── tsconfig.json ├── ...
src/Todos.tsx 파일에 Todos 컴포넌트를 정의하고, src/App.tsx 파일에서 Todos 컴포넌트를 사용하여 To-do 리스트를 렌더링합니다.
5. TypeScript 설정
tsconfig.json 파일은 TypeScript 설정을 포함하며, 프로젝트의 타입 검사 규칙을 정의합니다. 기본 설정 외에도 필요에 따라 추가 설정을 적용할 수 있습니다.
{ "compilerOptions": { "target": "es5", "lib": ["dom", "dom.iterable", "esnext"], "allowJs": true, "skipLibCheck": true, "esModuleInterop": true, "allowSyntheticDefaultImports": true, "strict": true, "forceConsistentCasingInFileNames": true, "noFallthroughCasesInSwitch": true, "module": "esnext", "moduleResolution": "node", "resolveJsonModule": true, "isolatedModules": true, "noEmit": true, "jsx": "react-jsx" }, "include": ["src"] }
이 파일은 TypeScript가 프로젝트에서 어떻게 동작할지를 정의합니다.
strict 옵션을 통해 엄격한 타입 검사를 활성화하고, jsx 옵션을 통해 React JSX 구문을 사용할 수 있도록 설정했습니다.
이제 전체 설정과 코드를 통해 TypeScript와 React를 활용한 안전한 코드를 작성할 수 있습니다.
필요한 경우 추가적인 타입 정의와 타입 검사를 통해 더욱 견고한 코드를 작성할 수 있습니다.
561.데이터 모델 추가하기
1. Todo 클래스 정의하기
먼저 src/models/todo.ts 파일을 만들어 Todo 클래스를 정의합니다.
// src/models/todo.ts export class Todo { id: string; text: string; constructor(todoText: string) { this.text = todoText; this.id = new Date().toISOString(); } }
여기서 Todo 클래스는 id와 text 필드를 가지며, 생성자에서 text 필드를 초기화하고 id를 현재 시간으로 생성합니다.
2. App 컴포넌트 업데이트
App.tsx에서 todos 배열을 Todo 객체 배열로 만듭니다.
// src/App.tsx import React from 'react'; import Todos from './components/Todos'; import { Todo } from './models/todo'; const App: React.FC = () => { const todos = [new Todo('리액트 공부하기'), new Todo('타입스크립트 공부하기')]; return ( <div> <Todos items={todos} /> </div> ); }; export default App;
여기서는 new Todo()를 사용하여 두 개의 Todo 객체를 생성하고 todos 배열에 추가합니다.
3. Todos 컴포넌트 업데이트
Todos.tsx에서 items prop의 타입을 Todo 객체 배열로 변경합니다.
// src/components/Todos.tsx import React from 'react'; import { Todo } from '../models/todo'; interface TodosProps { items: Todo[]; } const Todos: React.FC<TodosProps> = (props) => { return ( <ul> {props.items.map((item) => ( <li key={item.id}>{item.text}</li> ))} </ul> ); }; export default Todos;
여기서는 TodosProps 인터페이스를 사용하여 items prop의 타입을 Todo 객체 배열로 정의합니다. 그런 다음, items 배열을 순회하면서 각 item의 id와 text를 사용하여 목록 항목을 생성합니다.
4. 타입스크립트와 리액트의 제네릭 타입 활용
리액트 컴포넌트를 제네릭 타입으로 정의하여 기본 props와 커스텀 props를 합치는 방법을 사용합니다.
// src/components/Todos.tsx import React from 'react'; import { Todo } from '../models/todo'; interface TodosProps { items: Todo[]; } const Todos: React.FC<TodosProps> = (props) => { return ( <ul> {props.items.map((item) => ( <li key={item.id}>{item.text}</li> ))} </ul> ); }; export default Todos;
여기서 React.FC<TodosProps> 타입을 사용하여 Todos 컴포넌트를 정의합니다. 이 타입 표기를 통해 Todos 컴포넌트는 TodosProps 타입의 props를 받아야 한다는 것을 명시적으로 나타냅니다.
요약
- Todo 클래스를 정의하여 할 일 항목의 데이터를 명확하게 모델링합니다.
- App.tsx에서 todos 배열을 Todo 객체 배열로 업데이트합니다.
- Todos.tsx에서 items prop의 타입을 Todo 객체 배열로 변경하고, 이를 통해 각 할 일 항목을 렌더링합니다.
- 리액트와 타입스크립트의 제네릭 타입을 활용하여 컴포넌트의 타입 안정성을 높입니다.
이 과정을 통해 코드의 구조가 명확해지고, 타입스크립트의 장점을 활용하여 타입 안전성을 확보할 수 있습니다.
562.연습하기 : 연습시간!
1. TodoItem 컴포넌트 생성
먼저, 새로운 TodoItem.tsx 파일을 src/components 폴더에 생성합니다.
TodoItem.tsx
import React from 'react' const TodoItem:React.FC<{text:String}>= (props)=>{ return <li>{props.text}</li> } export default TodoItem
Todos.tsx
import React from "react"; import Todo from "../models/todo"; import TodoItem from "./TodoItem"; const Todos :React.FC<{items:Todo[]}>=(props)=>{ return ( <ul> { props.items.map((item)=>( <TodoItem key={item.id} text={item.text} /> )) } </ul> ); } export default Todos;
여기서는 TodoItem 컴포넌트를 임포트하고, props.items를 매핑하여 각 Todo 객체를 TodoItem으로 변환합니다. key는 item.id를 사용하고, text는 item.text를 전달합니다.
요약
이제 TodoItem 컴포넌트를 분리하여, Todos 컴포넌트에서 개별 Todo 항목을 별도의 컴포넌트로 렌더링하도록 만들었습니다. 이 과정에서 타입스크립트를 사용하여 각 컴포넌트가 받을 props의 타입을 명확히 정의하였습니다.
- TodoItem 컴포넌트를 생성하고 text라는 문자열 타입의 프로퍼티를 받도록 설정하였습니다.
- Todos 컴포넌트에서 TodoItem을 사용하여 각 Todo 항목을 렌더링하였습니다.
- App 컴포넌트는 Todo 객체 배열을 Todos 컴포넌트에 전달하여 렌더링을 유지하였습니다.
이를 통해 코드의 재사용성을 높이고, 컴포넌트의 역할을 명확히 분리할 수 있습니다. 또한 타입스크립트를 사용함으로써 컴파일 타임에 오류를 사전에 방지할 수 있게 되었습니다.
댓글 ( 0)
댓글 남기기