소개
마이그레이션하는 이유 이점 이해
시작하기 전: 전제조건
마이그레이션 시작: 프로젝트에 TypeScript 설정
React 구성요소 리팩토링
상태 관리 및 컨텍스트 API
라우팅 및 비동기 작업
TypeScript에서 테스트
TypeScript가 아닌 패키지 처리
모범 사례 및 일반적인 함정
결론
추가 리소스
안녕하세요, 동료 개발자 여러분! React 프로젝트에서 JavaScript 에서 TypeScript 로의 전환을 탐색할 준비가 된 여러분을 여기서 뵙게 되어 기쁩니다.
이제 JavaScript로 작업해 본 적이 있다면 이것이 낡고 편안한 신발과 같다는 것을 알 것입니다. 약간 낡고 때로는 예측할 수 없지만 친숙합니다. 그러나 TypeScript는 맞춤형 깔창으로 신발을 업그레이드하는 것과 같습니다. 걷는 경험은 동일하지만 추가 지원이 제공됩니다.
그렇다면 TypeScript에 대한 모든 소문은 무엇입니까?
글쎄, 그것은 본질적으로 JavaScript이지만 상당한 양의 추가 기능이 포함되어 있으며 가장 중요한 것은 유형 검사입니다.
성가시게 undefined is not a function
상상해 보세요. 이것이 바로 TypeScript가 여러분의 삶에 가져다주는 일종의 평화입니다.
이 가이드에서는 TypeScript를 React 프로젝트에 통합하는 이유와 방법을 안내합니다.
왜 반응해야 하는가? 왜냐하면 그것은 굉장하고 우리가 그것을 좋아하기 때문입니다. 또한 React의 구성 요소 기반 접근 방식과 TypeScript의 유형 검사 기능을 결합하면 매우 효율적이고 즐거운 코딩 경험이 가능해집니다.
다음은 프로젝트에 TypeScript를 추가하는 모습을 살짝 보여줍니다. 일반적인 JavaScript 구성요소에는 다음이 포함됩니다.
// JavaScript way function Greeting({ name }) { return <h1>Hello, {name}</h1>; }
TypeScript를 사용하면 name
항상 문자열로 처리되도록 하는 방법을 도입합니다.
// TypeScript style type Props = { name: string; }; function Greeting({ name }: Props) { return <h1>Hello, {name}</h1>; }
type Props
부분이 보이시나요 ?
이것이 TypeScript에서 "보고 있어요. name
이 문자열인지 확인하는 게 좋을 것 같아요!"라고 말하는 방식입니다. 이는 심오한 의미를 지닌 단순한 변화입니다. 이제 수호 천사가 유형 관련 버그를 적극적으로 방지하여 코드를 더욱 강력하고 예측 가능하게 만듭니다.
그러나 그것은 단지 작은 모습일 뿐입니다. 이 포괄적인 가이드에서 TypeScript의 다양한 이점과 사례를 살펴보겠습니다. 환경 설정부터 구성 요소 및 소품 리팩터링, 일반적인 함정을 피하기 위한 모범 사례까지 다루어야 할 내용이 많습니다. 그러니 버클을 채우고 이 쇼를 도로에서 감상하세요!
특히 React 프로젝트에서 JavaScript에서 TypeScript로의 전환을 고려하고 있다면 "정말로 번거로움을 겪을 가치가 있는가?"라는 의문이 드는 것은 혼자가 아닙니다. 전체 프로젝트의 언어를 전환하는 것은 결코 쉬운 일이 아닙니다. 노력과 학습이 필요하며 처음에는 생산성이 약간 느려집니다. 그렇다면 개발자는 왜 전환을 할까요? 설득력 있는 이유를 분석해 보겠습니다.
TypeScript의 핵심 기능은 정적 유형 시스템입니다. 동적으로 유형이 지정되는 JavaScript와 달리 TypeScript를 사용하면 변수, 함수 매개변수 및 반환 값에 대한 유형을 지정할 수 있습니다. 특혜는 무엇입니까? 코드가 프로덕션 단계에 가까워지기 훨씬 전에 개발 중에 오류가 포착됩니다.
간단한 예를 생각해보십시오.
// In JavaScript function createGreeting(name) { return `Hello, ${name}`; } // You might not catch this typo until runtime const greeting = createGreeting(123); console.log(greeting); // "Hello, 123" - Wait, that's not right!
이제 TypeScript가 어떻게 도움이 되는지 살펴보겠습니다.
// In TypeScript function createGreeting(name: string): string { return `Hello, ${name}`; } // TypeScript will flag this immediately - '123' is not a string! const greeting = createGreeting(123);
TypeScript를 사용하면 순진해 보이는 버그가 즉시 발견되어 사고가 발생하는 순간을 알 수 있습니다. 이렇게 하면 피드백 루프가 단축되고 프로덕션 환경에서 이상한 버그를 보면서 머리를 긁적일 필요가 없습니다.
TypeScript의 입력 강제는 다른 개발자(또는 미래의 개발자)가 함수가 기대하는 데이터 종류와 반환되는 데이터의 종류를 한눈에 이해할 수 있음을 의미합니다. 이러한 명확성은 코드베이스를 더 읽기 쉽고 자체적으로 문서화할 수 있게 만듭니다.
동료가 작성한 JavaScript 함수를 발견했다고 상상해 보십시오.
function calculateTotal(items) { // ... complicated logic ... }
어떤 items
있어야 하는지 이해하려면 함수를 자세히 살펴보거나 함수가 어디에 사용되는지 찾아야 할 것입니다. TypeScript를 사용하면 즉시 명확해집니다.
type Item = { price: number; quantity: number; }; // Now we know exactly what to expect! function calculateTotal(items: Item[]): number { // ... complicated logic ... }
TypeScript는 향상된 자동 완성, 리팩터링 및 디버깅을 통해 텍스트 편집기와 IDE를 향상하여 개발자 경험을 새로운 수준으로 끌어올립니다. TypeScript가 코드에 대한 이해를 편집기와 공유할 수 있기 때문에 이러한 통합이 가능합니다.
편집기에서 메서드 이름을 제안하거나 함수 매개변수 정보를 제공하거나 잘못된 함수 사용에 대해 경고하는 경우 이러한 현상을 경험하게 됩니다. 이는 추가 안전 계층으로 코드를 탐색하는 데 도움을 주는 부조종사가 있는 것과 같습니다.
팀 환경에서 TypeScript는 코드베이스 전체에 특정 표준과 구조를 적용하는 데 도움을 줌으로써 빛을 발합니다. 여러 개발자가 프로젝트에 기여하는 경우 TypeScript의 엄격한 규칙은 모든 사람이 동일한 코딩 지침을 준수하도록 보장하여 협업을 더욱 원활하게 만듭니다. 전반적으로 '품질과 일관성'을 말하는 공통 언어입니다.
JavaScript는 발전하고 있으며 TypeScript는 최신 기능을 따르는 것을 목표로 합니다. TypeScript를 사용하면 차세대 JavaScript 기능이 주류로 채택되기 전에 활용하여 프로젝트를 현대적이고 최첨단으로 유지할 수 있습니다.
결론적으로, TypeScript로 마이그레이션하는 것은 단지 오류를 더 일찍 잡는 것이 아닙니다. 이는 코딩 프로세스의 전체적인 개선에 관한 것입니다. 더 나은 팀 협업부터 미래 지향적인 프로젝트까지, TypeScript는 안정적이고 확장 가능하며 유지 관리 가능한 애플리케이션을 구축하기 위한 강력한 기반을 제공합니다.
처음에는 전환하는 것이 어려워 보일 수 있지만 위에 설명된 이점을 보면 TypeScript가 전 세계 많은 개발자에게 인기가 있는 이유가 분명해졌습니다. 다이빙할 준비가 되셨나요? 계속하자!
좋습니다. React 프로젝트에서 TypeScript로 전환할 준비가 모두 되었나요? 훌륭한 결정입니다!
하지만 실제 프로세스에 들어가기 전에 몇 가지 사항이 제대로 갖추어져 있는지 확인해야 합니다.
전환 프로세스가 버터처럼 원활하게 진행되도록 모든 도구를 준비하는 준비 단계를 생각해 보세요.
준비해야 할 사항은 다음과 같습니다.
먼저, 기존 React 프로젝트가 필요합니다. 이 프로젝트는 여러분이 편안하게 실험해볼 수 있는 프로젝트여야 합니다. 마이그레이션 프로세스는 매우 간단하지만 일시적으로 혼란스러워도 괜찮은 공간에서 이 작업을 수행하는 것이 좋습니다.
// Here's a simple React functional component in your project export default function Greeting({ name }) { return <h1>Hello, {name}!</h1>; }
이 구성 요소는 좋은 출발점입니다. 기능적이고 깔끔하며 무슨 일이 일어나고 있는지 한 눈에 볼 수 있습니다.
TypeScript 전문가가 될 필요는 없지만 기본 사항을 이해하면 이러한 전환이 훨씬 쉬워집니다.
유형과 인터페이스를 정의하는 방법을 알고 type
과 interface
의 차이점을 알아보세요.
약간의 숙제는 큰 도움이 됩니다. 저를 믿으세요.
// A sneak peek into TypeScript syntax type Props = { name: string; // defining the 'name' expected to be a string }; // Your component in TypeScript would look like this import React, { FC } from 'react'; interface GreetingProps { name: string; } const Greeting: FC<GreetingProps> = ({ name }) => { return <h1>Hello, {name}!</h1>; } export default Greeting;
차이점이 보이나요? 이제 Greeting
기대하는 바를 명시적으로 설명하여 구성 요소를 더욱 예측 가능하고 작업하기 쉽게 만들었습니다.
패키지를 처리하기 위해 npm
또는 yarn
사용할 것이기 때문에 개발 환경에는 Node.js가 설치되어 있어야 합니다. 이 요구 사항은 React를 사용하고 있기 때문에 주어지지만 확인하는 데에는 아무런 해가 되지 않습니다. 그렇죠?
# Check if Node is installed node --version # Check if npm is installed npm --version # Or for yarn yarn --version
터미널에는 이러한 도구의 현재 버전이 표시되어 도구가 모두 설정되어 사용할 준비가 되었음을 확인합니다.
TypeScript를 잘 처리할 수 있는 코드 편집기가 필요합니다. Visual Studio Code는 강력한 TypeScript 지원이 내장되어 있어 지능적인 코드 완성 및 오류 강조 기능을 통해 개발 프로세스를 더욱 원활하게 만들어 많은 사람들이 선호하는 제품입니다.
이 단계는 필수는 아니지만 현명한 단계입니다. 현재 프로젝트가 git으로 버전 관리되고 있는지 확인하세요. 문제가 발생하면(그렇지 않도록 노력하겠지만) 잠을 자지 않고도 언제든지 이전 버전으로 되돌릴 수 있습니다.
# Check if git is installed git --version # If not, you need to initialize version control before proceeding git init git add . git commit -m "Pre-TypeScript commit"
이 안전망이 있다는 것은 등이 보호된다는 것을 알고 자신감을 가지고 실험할 수 있다는 것을 의미합니다.
이것이 우리의 전제조건입니다! 프로젝트가 있고 TypeScript를 익혔으며 환경이 준비되었고 안전망이 마련되었습니다.
이제 마이그레이션 프로세스를 시작할 준비가 모두 완료되었습니다. 공을 굴려보자!
좋아, 다음 단계로 넘어간다!
TypeScript로 무대를 마련했지만 이제 손을 더럽혀야 합니다.
이제 React 구성요소를 리팩토링할 시간입니다. 이 단계에는 파일 확장자를 변경하는 것 이상의 작업이 포함됩니다. 보다 강력하고 오류 없는 코딩 경험을 위해 TypeScript의 기능을 활용하려면 구성 요소 코드를 업데이트해야 합니다.
뛰어들어보자!
먼저 구성 요소 파일의 이름을 바꾸겠습니다. 이 프로세스에는 JSX 코드가 포함된 파일의 확장자를 .js
에서 .tsx
로 변경하는 작업이 포함됩니다.
명령줄을 통해 프로젝트의 소스 디렉터리에서 이 작업을 한꺼번에 수행하는 방법은 다음과 같습니다.
# For Unix-like shells, navigate to your source folder and run: find . -name "*.js" -exec bash -c 'mv "$0" "${0%.js}.tsx"' {} \; # If you're using PowerShell (Windows), navigate to your source folder and run: Get-ChildItem -Filter *.js -Recurse | Rename-Item -NewName { $_.Name -replace '\.js$','.tsx' }
이 명령은 프로젝트의 소스 디렉터리에서 모든 .js
파일을 검색하고 이름을 .tsx
로 바꿉니다. 이는 파일에 "TypeScript 세계에 오신 것을 환영합니다!"라고 말하는 것과 같습니다.
파일 이름을 변경한 후 코드를 살펴보겠습니다. JavaScript의 간단한 기능적 구성 요소부터 시작하겠습니다.
// Before: MyComponent.js import React from 'react'; function MyComponent({ greeting }) { return <h1>{greeting}, world!</h1>; }
이제 TypeScript를 사용하도록 리팩토링해 보겠습니다.
// After: MyComponent.tsx import React, { FC } from 'react'; // Define a type for the component props interface MyComponentProps { greeting: string; } // Use the 'FC' (Functional Component) generic from React, with our props type const MyComponent: FC<MyComponentProps> = ({ greeting }) => { return <h1>{greeting}, world!</h1>; }
우리는 여기서 무엇을 했나요?
우리는 컴포넌트의 props를 설명하기 위해 MyComponentProps
인터페이스를 정의하여 유형 안전성을 보장했습니다. greeting
문자열이라고 말하면 TypeScript는 예를 들어 숫자를 대신 전달하려고 하면 소리를 지를 것입니다. 또한 React의 유형 정의에서 FC
유형( Functional Component
의 약어)을 사용하여 TypeScript가 이것이 React 구성 요소임을 인식하도록 했습니다.
기능적 컴포넌트의 공통 기능인 상태와 효과에 유형을 추가하여 컴포넌트를 더욱 업그레이드해 보겠습니다.
상태와 효과가 있는 구성요소는 다음과 같습니다.
// Before: Counter.js import React, { useState, useEffect } from 'react'; function Counter() { const [count, setCount] = useState(0); useEffect(() => { document.title = `You clicked ${count} times`; }); return ( <div> <p>You clicked {count} times</p> <button onClick={() => setCount(count + 1)}> Click me </button> </div> ); }
여기에 몇 가지 TypeScript 마법을 뿌려보겠습니다.
// After: Counter.tsx import React, { useState, useEffect, FC } from 'react'; const Counter: FC = () => { // Declare the 'count' state variable with TypeScript const [count, setCount] = useState<number>(0); useEffect(() => { document.title = `You clicked ${count} times`; }); return ( <div> <p>You clicked {count} times</p> <button onClick={() => setCount(prevCount => prevCount + 1)}> Click me </button> </div> ); }
리팩터링된 구성 요소에서 TypeScript에 count
상태에 대한 number
예상하도록 명시적으로 지시했습니다.
이 세부 사항은 실수로 예상 숫자 대신 문자열, 객체 또는 천국이 금지된 null
로 끝날 수 있는 성가신 버그를 방지합니다.
그리고 우리는 간다!
TypeScript를 사용하도록 React 구성 요소를 성공적으로 리팩터링했습니다. 구성 요소, 상태 및 소품을 명시적으로 입력함으로써 보다 예측 가능하고 유지 관리하기 쉬운 코드베이스를 만들고 있습니다. 우리는 단지 코딩만 하는 것이 아닙니다. 우리는 그에 합당한 정밀도로 걸작을 만들고 있습니다.
다음으로, 우리는 더 복잡한 시나리오와 TypeScript가 우리를 구출하는 방법에 대해 더 깊이 파고들 것입니다!
이제 TypeScript를 사용하여 React에서 상태 관리의 핵심을 살펴보겠습니다. JavaScript 프로젝트에서 Context API를 사용해 본 적이 있다면 이것이 모든 수준에서 props를 수동으로 전달할 필요 없이 구성 요소 트리를 통해 데이터를 전달하는 강력한 기능이라는 것을 알 것입니다. TypeScript에서는 엄격한 유형 지정의 추가 이점을 얻습니다. 이는 컨텍스트 데이터를 더욱 강력하고 예측 가능하게 만듭니다.
뛰어들 준비가 되셨나요? 갑시다!
먼저 TypeScript를 사용하여 새 컨텍스트를 생성하겠습니다. 이 컨텍스트는 기본값, 공급자 값 또는 소비자 구성 요소가 예상 유형과 일치하는지 확인합니다.
JavaScript에서 기본 컨텍스트를 정의하는 방법은 다음과 같습니다.
// Before: DataContext.js import React, { createContext, useState } from 'react'; export const DataContext = createContext(); export const DataProvider = ({ children }) => { const [data, setData] = useState(null); return ( <DataContext.Provider value={{ data, setData }}> {children} </DataContext.Provider> ); };
이제 TypeScript를 사용하여 이 컨텍스트를 입력해 보겠습니다.
// After: DataContext.tsx import React, { createContext, useState, FC, ReactNode } from 'react'; // First, we define a type for our context's state interface DataContextState { data: any; // Tip: Replace 'any' with the expected type of 'data' setData: (data: any) => void; // And here too, replace 'any' with the actual expected type } // We ensure our createContext() call is typed with the above interface export const DataContext = createContext<DataContextState | undefined>(undefined); // Now, let's create a provider component export const DataProvider: FC<{children: ReactNode}> = ({ children }) => { const [data, setData] = useState<any>(null); // Again, consider replacing 'any' with your actual data type // The context provider now expects a value that matches 'DataContextState' return ( <DataContext.Provider value={{ data, setData }}> {children} </DataContext.Provider> ); };
여기서 수행한 작업은 컨텍스트 데이터를 엄격하게 입력하는 TypeScript 인터페이스 DataContextState
만드는 것입니다. 또한 createContext
함수와 DataProvider
구성 요소를 입력하여 상태 변수부터 컨텍스트 값까지 모든 것이 정의된 유형과 일치하는지 확인했습니다.
이제 형식화된 DataContext
있으므로 구성 요소 내에서 이를 어떻게 활용할 수 있는지 살펴보겠습니다.
useContext
후크를 사용해야 하며 그 방법은 다음과 같습니다.
// ComponentUsingContext.tsx import React, { useContext, FC } from 'react'; import { DataContext } from './DataContext'; const ComponentUsingContext: FC = () => { // Here we're telling TypeScript to expect 'DataContextState' from our context const { data, setData } = useContext(DataContext) ?? {}; // This function would update the context state, triggering re-renders in consuming components const handleUpdateData = () => { const newData = { message: "Hello, TypeScript!" }; // This should match the structure of your data type setData(newData); }; return ( <div> <pre>{JSON.stringify(data, null, 2)}</pre> <button onClick={handleUpdateData}>Update Data</button> </div> ); };
ComponentUsingContext
에서는 컨텍스트에 액세스하고 TypeScript가 값이 DataContextState
와 일치하는지 확인하기를 기대합니다. 우리의 handleUpdateData
함수는 공유 상태를 업데이트하는 방법을 보여줍니다. DataContext
사용하는 모든 구성 요소는 setData
호출될 때 새 데이터로 다시 렌더링됩니다.
Context API와 함께 TypeScript를 사용함으로써 우리는 공유 상태 관리가 애플리케이션 전체에서 일관되게 유지된다는 확신을 얻습니다. 컴파일러는 컨텍스트가 제공하는 것과 구성 요소가 기대하는 것 사이의 불일치를 포착합니다. 이러한 시너지 효과는 우리의 코드를 더 안정적으로 만들고 개발 프로세스를 더 원활하게 만들어 우리가 직면할 수 있는 전체 버그 범주를 피할 수 있게 해줍니다.
계속해서 좋은 일을 하세요. 이제 약간의 타이핑으로 나중에 디버깅 시간을 많이 절약할 수 있다는 점을 기억하세요!
TypeScript가 React 애플리케이션의 다양한 측면을 어떻게 개선하는지 살펴보았으므로 이제 또 다른 중요한 영역인 테스트에 대해 이야기할 차례입니다.
테스트는 앱이 예상대로 작동하는지 확인하는 데 필수적이며 TypeScript를 사용하면 테스트를 더욱 안정적이고 효율적으로 만들 수 있습니다. 특히 React 프로젝트에서 TypeScript가 테스트에서 어떤 역할을 하는지 자세히 살펴보겠습니다.
코드를 시작하기 전에 React 프로젝트에서 테스트하는 데 필요한 라이브러리가 설치되어 있는지 확인하세요. 다음은 React 애플리케이션 테스트에 함께 널리 사용되는 Jest 및 React Testing Library를 사용한 빠른 설정입니다.
npm install --save-dev jest @types/jest @testing-library/react @testing-library/jest-dom
이러한 라이브러리는 단위 및 통합 테스트 작성을 위한 강력한 환경을 제공합니다. 이제 명확성을 위해 실제 시나리오를 고려해 보겠습니다.
앱에 하루 중 시간에 따라 사용자에게 인사하는 간단한 구성 요소가 있다고 상상해 보세요. 사용자의 이름을 prop으로, 현재 시간을 상태로 사용하는 기능적 구성 요소입니다.
UserGreeting
구성 요소는 다음과 같습니다.
// UserGreeting.tsx import React, { FC, useState, useEffect } from 'react'; interface UserGreetingProps { name: string; } const UserGreeting: FC<UserGreetingProps> = ({ name }) => { const [currentHour, setCurrentHour] = useState(new Date().getHours()); const [greeting, setGreeting] = useState(''); useEffect(() => { // Determine the time of day and set the appropriate greeting if (currentHour < 12) { setGreeting('Good morning'); } else if (currentHour < 18) { setGreeting('Good afternoon'); } else { setGreeting('Good evening'); } }, [currentHour]); return ( <div> <h1>{greeting}, {name}!</h1> </div> ); } export default UserGreeting;
이제 구성 요소가 다양한 조건에서 예상대로 작동하는지 확인하는 테스트를 작성해야 합니다. 테스트 사례에서는 시간에 따라 적절한 인사말이 표시되는지 확인합니다.
Jest 및 React 테스트 라이브러리를 사용하여 이러한 테스트를 작성하는 방법은 다음과 같습니다.
// UserGreeting.test.tsx import React from 'react'; import { render, screen } from '@testing-library/react'; import UserGreeting from './UserGreeting'; describe('UserGreeting Component', () => { // Mock date for consistent testing const originalDate = Date; beforeAll(() => { const mockDate = new Date(2023, 10, 17, 14); // 2:00 PM global.Date = jest.fn(() => mockDate) as any; }); afterAll(() => { global.Date = originalDate; // Restore original Date object }); it('displays the correct greeting for the afternoon', () => { render(<UserGreeting name="Jordan" />); // Assert the greeting based on the mocked time of day expect(screen.getByText('Good afternoon, Jordan!')).toBeInTheDocument(); }); // Additional tests would repeat this process for other times of day, // ensuring our component behaves consistently. });
이 스크립트에서는 설정된 시간(오후 2시로 가정)으로 구성 요소를 렌더링하고 예상대로 "좋은 오후"가 출력되는지 확인합니다. 구성 요소가 완전히 포함되는지 확인하기 위해 하루 중 다른 시간(아침, 저녁)에 대해 더 많은 테스트를 작성할 수 있습니다.
TypeScript를 통해 테스트에서 구성 요소에 전달하는 props가 예상되는 유형과 일치하는지 확인합니다. 이렇게 하면 테스트에서 거짓 부정으로 이어질 수 있는 잘못된 prop으로 인한 문제가 발생하는 것을 방지하여 테스트가 강력하고 신뢰할 수 있도록 보장합니다.
테스트에 TypeScript를 사용하면 개발 프로세스 초기에 문제를 파악하여 앱을 더욱 강력하고 유지 관리하기 쉽게 만들 수 있습니다. 윈윈(win-win) 상황입니다! 일관되고 포괄적인 테스트는 고품질 소프트웨어 개발의 특징이라는 것을 기억하십시오. 계속하세요!
좋습니다. React 프로젝트에서 TypeScript로 전환할 때 종종 사람들을 당황하게 만드는 영역, 즉 TypeScript로 작성되지 않은 JavaScript 라이브러리 및 패키지를 다루겠습니다. 일반적인 시나리오입니다. TypeScript 프로젝트를 시작하고 실행한 다음 타사 패키지를 설치했지만 TypeScript 컴파일러가 불평하는 것을 발견했습니다. 괜찮아요; 해결책이 있습니다.
일반적인 시나리오는 다음과 같습니다. 기본적으로 TypeScript를 지원하지 않는 패키지를 사용하려고 하면 TypeScript 컴파일러가 "'module-name' 모듈에 대한 선언 파일을 찾을 수 없습니다."와 같은 오류를 발생시키기 시작합니다. 익숙한 것 같나요?
이 문제는 TypeScript가 유형 정의에 의존하여 라이브러리 및 패키지의 구조를 이해하기 때문에 발생합니다. 이러한 유형 정의가 누락되면 TypeScript가 약간 손실됩니다. 하지만 걱정하지 마세요. 우리에게는 이 문제를 처리할 수 있는 전략이 있습니다.
가장 먼저 할 수 있는 일 중 하나는 커뮤니티가 DefinedTyped를 통해 패키지에 대한 유형 정의를 제공했는지 확인하는 것입니다. 확실히 Typed는 커뮤니티에서 유지 관리하는 유형 정의의 대규모 저장소입니다.
DefinedTyped의 유형을 확인하고 사용하는 방법은 다음과 같습니다.
@types/
접두사가 붙습니다. npm install @types/package-name
예를 들어 lodash
라이브러리를 사용하는 경우 다음을 실행합니다.
npm install @types/lodash
설치 후에는 프로젝트의 어느 곳에서나 유형을 명시적으로 가져올 필요가 없습니다. TypeScript는 이를 자동으로 감지하고 사용하므로 평소처럼 라이브러리를 가져오고 사용할 수 있으며 자동 완성 및 유형 검사를 받을 수 있습니다.
하지만 DefinedTyped에 사용할 수 있는 유형 정의가 없다면 어떻게 될까요?
DefinedTyped에 필요한 유형 정의가 없으면 사용자 정의 선언 파일을 생성할 차례입니다. 이 접근 방식에는 더 많은 노력이 필요하지만 TypeScript 프로젝트가 JavaScript 라이브러리와 원활하게 작동하도록 보장합니다.
수행할 수 있는 작업의 단순화된 버전은 다음과 같습니다.
프로젝트의 소스(또는 types
) 디렉토리 내에 확장자가 .d.ts
인 새 파일을 만듭니다. 이는 declarations.d.ts
와 같을 수 있습니다.
이 파일에서 모듈을 선언하고 잠재적으로 라이브러리에서 기대하는 기본 구조의 개요를 설명할 수 있습니다. 예를 들어:
// This is a simplistic type declaration file for a hypothetical package. // We declare the module so TypeScript recognizes it. declare module 'name-of-untyped-package' { // Below, we're declaring a very basic structure. It's saying // there's a function we're expecting to exist, which returns any. // Ideally, you'd want to flesh this out with more specific types // if you know them or as you learn more about the library. export function functionName(arg: any): any; // You can continue to define the shapes of other functions or variables // you expect to exist within the package. The more detailed you are here, // the more helpful your type checking will be. }
이 직접 만든 선언 파일은 전체 유형 정의 세트만큼 포괄적이지는 않지만 TypeScript에 "저를 믿으십시오. 이 모듈이 존재한다는 것을 알고 있으며 이러한 함수/변수를 제공합니다."라고 알려줍니다. 여기에서 필요에 따라 더 자세한 정의를 작성할 수 있습니다.
TypeScript가 아닌 패키지를 처리하는 것은 약간의 장애물이 될 수 있지만 이러한 전략을 사용하면 TypeScript 프로젝트가 견고하게 유지되고 우리가 추구하는 유형 안전성과 예측 가능성을 누릴 수 있습니다. 그것은 코드베이스에 대한 자신감에 관한 것입니다!
React 프로젝트에서 TypeScript로 전환하는 것은 단순히 파일 확장자를 변경하고 유형 주석을 추가하는 것이 아닙니다. 또한 일반적인 걸림돌을 피하면서 TypeScript가 제공하는 기능을 최대한 활용하기 위해 사고방식과 개발 방식을 조정하는 것도 중요합니다. 이제 이 여정 중에 발생할 수 있는 몇 가지 모범 사례와 일반적인 함정에 대해 논의해 보겠습니다.
모든 것에 주석을 달고 싶을 수도 있지만 TypeScript의 장점 중 하나는 유형 추론입니다. 코드의 모든 부분에 명시적 유형을 추가하는 것이 불필요한 경우가 많습니다.
// Instead of this: let x: number = 0; // You can rely on type inference: let x = 0; // TypeScript knows this is a number
과도한 주석을 달면 가치를 추가하지 않고도 코드를 장황하게 만들 수 있습니다. 가능한 경우 유형을 추론하려면 TypeScript를 신뢰하세요.
유틸리티 유형은 다양한 시나리오에서 유형을 처리하는 유연한 방법을 제공합니다. 이를 통해 많은 노력을 절약하고 유형 처리를 더욱 효율적으로 만들 수 있습니다.
// Example of using Partial to make all properties in an object optional function updateProfile(data: Partial<UserProfile>) { // function implementation } // Now you can pass only the parts of UserProfile you need to update updateProfile({ username: "newUserName" }); // This is valid
Partial
, Readonly
, Pick
및 기타 유틸리티 유형은 매우 편리할 수 있습니다.
특정 값만 사용할 수 있는 속성이 있는 경우 enum
사용하면 해당 값에 대한 유효성 검사를 제공하면서 의도를 명확하게 할 수 있습니다.
enum UserRole { Admin = 'ADMIN', User = 'USER', Guest = 'GUEST', } // Now UserRole can only be one of the values defined in the enum function assignRole(role: UserRole) { // function implementation }
type
과 interface
종종 서로 바꿔서 사용할 수 있지만 객체나 클래스의 구조를 정의하기 위해 interface
사용하면 코드를 더 쉽게 읽을 수 있고 더 나은 오류 메시지를 제공할 수 있습니다.
interface UserProfile { username: string; email: string; // More properties... }
any
any
사용하면 유형 검사를 우회하여 TypeScript의 이점이 무효화됩니다. 빠른 수정처럼 보일 수도 있지만 코드를 덜 안전하고 예측하기 어렵게 만듭니다.
// Try to avoid this: let userData: any = fetchData(); // Instead, define a type for the data you expect: let userData: UserProfile = fetchData();
TypeScript의 컴파일러 경고가 도움이 될 것입니다. 이를 무시하면 TypeScript를 사용하여 피하려고 하는 것과 동일한 종류의 버그 및 문제가 발생할 수 있습니다.
때로는 유형을 정확하게 만들기 위해 개발자가 이해하고 유지하기 어려운 매우 복잡한 유형 정의를 작성하는 경우도 있습니다. 유형이 복잡해지면 코드를 단순화하거나 리팩터링해야 할 때입니다.
타사 라이브러리를 사용하는 경우에는 확실히 TypeScript에 기존 TypeScript 유형이 있는지 항상 확인하세요. 그렇지 않으면 이러한 라이브러리의 유형 안전 기능이 누락될 수 있습니다.
결론적으로, TypeScript를 채택하는 것은 단순히 새로운 구문을 사용하는 것 이상입니다. 오류를 방지하고, 코드를 더 읽기 쉽게 만들고, 유지 관리를 개선하는 데 도움이 되는 새로운 방식을 채택하는 것입니다. 일반적인 함정을 피하고 목표는 더 깨끗하고 안정적이며 유지 관리하기 쉬운 코드를 작성하는 것임을 기억하세요!
여러분, 이제 TypeScript 마이그레이션 여정이 끝났습니다. 정말 힘든 시간이었죠, 그렇죠? 우리는 "왜"라는 큰 질문으로 시작하여 실제로 React 프로젝트를 JavaScript에서 TypeScript로 전환하는 핵심을 탐구했습니다. TypeScript 환경 설정부터 구성 요소 리팩토링, 상태 관리, 경로 처리, 성가신 비 TypeScript 패키지 처리까지 많은 내용을 다루었습니다.
이 여정을 되돌아보면 TypeScript로의 마이그레이션이 .js
파일을 .tsx
로 단순히 '검색 및 교체'하는 것이 아니라는 것이 분명해졌습니다. 이는 새로운 규칙을 배우고, 유형을 깊이 이해하며, 가장 중요한 것은 코드의 신뢰성과 일관성에 대해 생각하는 방식을 바꾸는 것을 포함하는 전략적 움직임입니다.
마무리하면서 몇 가지 요점을 말씀드리겠습니다.
Safety Net : TypeScript는 프로젝트에 안전 레이어를 도입하여 런타임 시 오류가 발생하기 전에 오류를 포착합니다. 이 안전망은 일단 익숙해지면 코드에 대한 신뢰도와 전반적인 개발 속도 측면에서 획기적인 변화를 가져올 것입니다.
더 명확한 의사소통 : 유형을 사용하면 이제 코드가 더 명시적으로 의사소통됩니다. 코드를 다시 방문하든, 구성 요소 구조를 이해하려고 하는 새로운 팀원이든 TypeScript는 추가 문서 계층 역할을 합니다.
리팩토링 자신감 : 리팩토링이 두려우신가요? 글쎄요, TypeScript가 여러분의 뒤를 지켜줄 것입니다. 코드 내에서 계약을 보장하는 유형을 사용하면 리팩토링 단계에서 많은 잠재적인 오류가 포착되어 프로세스가 덜 어려워집니다.
커뮤니티 및 생태계 : TypeScript를 수용하면 번성하는 생태계의 문이 열립니다. DefinedTyped의 형식화된 라이브러리부터 커뮤니티 포럼의 끝없는 지원과 더욱 간소화된 타사 패키지 통합에 이르기까지 귀하는 좋은 회사에 속해 있습니다.
학습 곡선 : 예, TypeScript에는 학습 곡선이 도입되었습니다. 아마도 좌절의 순간, 유형과 인터페이스에 대한 혼란, 컴파일러와의 씨름 등이 있었을 것입니다. 하지만 여러분의 여정을 되돌아보면 지금 코드와 그 동작을 얼마나 더 많이 이해하고 있는지 알게 될 것입니다.
TypeScript로의 전환은 단거리 경주가 아니라는 점을 기억하세요. 마라톤이야. 처음에는 몇 가지 장애물이 있을 수 있지만 코드 품질, 예측 가능성 및 유지 관리 가능성이 장기적으로 향상되면 그만한 가치가 있습니다.
개발 여정을 계속하면서 TypeScript에 대한 경험을 계속 탐색하고, 배우고, 공유하세요. 모든 도전은 배움의 기회입니다. 미래의 당신(그리고 당신의 팀)은 현재 당신이 개발하고 있는 강력하고 유형이 안전하며 훨씬 더 유지 관리하기 쉬운 코드베이스에 감사할 것입니다.
React를 사용한 TypeScript 탐색에 참여해 주셔서 감사합니다. 계속 코딩하고, 계속 개선하고, 가장 중요한 것은 프로세스를 즐겨보세요!
이 기사가 마음에 들었고 웹 개발에 대해 더 자세히 알아보고 싶다면 다양한 플랫폼에서 저에게 연락해 주세요.
귀하의 피드백과 질문은 언제나 환영입니다.
계속 학습하고, 코딩하고, 놀라운 웹 애플리케이션을 만들어 보세요.
즐거운 코딩하세요!
가이드가 끝났지만 TypeScript를 사용한 모험은 여기서 끝나지 않습니다. TypeScript의 세계는 탐색하고, 배우고, 기여할 수 있는 수많은 리소스가 있는 방대합니다. 다음은 TypeScript 커뮤니티에 대한 이해를 강화하고 최신 정보를 유지하는 데 도움이 되는 몇 가지 귀중한 리소스입니다.
TypeScript 공식 문서 : 공식 웹사이트 보다 TypeScript를 탐색하기에 더 좋은 곳은 없습니다. 다양한 기능에 대한 자세한 문서, 예제 및 설명이 포함되어 있습니다.
DefinitiveTyped : 타사 라이브러리로 작업할 때 확실히 Typed는 생명의 은인입니다. 고품질 TypeScript 유형 정의가 담긴 대규모 저장소입니다.
React TypeScript 치트시트 : 이 포괄적인 치트시트는 TypeScript로 전환하는 React 개발자를 위해 특별히 제공되며 일반적인 패턴과 사례를 다룹니다.
TypeScript Deep Dive : TypeScript에 대한 자세한 탐색을 제공하는 훌륭한 온라인 책입니다. Deep Dive는 실용적인 시나리오에 초점을 맞춰 TypeScript의 핵심을 설명합니다.
TypeScript GitHub 리포지토리 : 공식 TypeScript GitHub 리포지토리를 방문하여 커뮤니티에 참여하고 TypeScript의 최신 개발 소식을 받아보세요.
스택 오버플로 : 스택 오버플 로의 TypeScript 태그는 전 세계 개발자가 접하는 일반적인(그리고 흔하지 않은) 쿼리와 미묘한 사용 사례의 허브입니다. 실용적인 통찰력이 담긴 금광입니다.
TypeScript Weekly : 선별된 뉴스레터 인 TypeScript Weekly는 최신 기사, 팁 및 리소스를 받은 편지함으로 직접 전달합니다.
Reddit 및 Discord 채널 : Reddit의 r/typescript 및 다양한 Discord 채널과 같은 플랫폼의 커뮤니티에서는 TypeScript와 관련된 활발한 토론, 뉴스 및 문제 해결 스레드를 호스팅합니다.
공식 TypeScript 블로그 : TypeScript 팀의 공지 사항, 심층 분석 및 튜토리얼을 보려면 공식 블로그를 확인하세요.
온라인 코딩 플랫폼 : Codecademy , freeCodeCamp 및 Scrimba 와 같은 플랫폼을 통한 대화형 학습 경험은 실습 TypeScript 과정을 제공합니다.
커뮤니티는 참여를 통해 성장한다는 점을 기억하세요. 주저하지 말고 질문하고, 답변을 제공하고, 솔루션과 경험을 공유하세요. 커뮤니티 포럼, 공식 문서 및 지속적인 연습의 집단적 지혜는 TypeScript 숙달을 향한 길을 안내할 것입니다.
즐거운 코딩하세요!