안녕하세요. MyDATA에서 프론트엔드 개발하고있는 JT입니다.
이번 포스팅에서는 Next.js 프레임워크를 기반으로 한 JavaScript 프로젝트를 TypeScript로 전환하는 경험을 공유하려 합니다. TypeScript의 장점과 전환 가능성을 살펴보기 위해, 작은 사이드 프로젝를 전환해 보았고, 그 과정에서의 경험과 고민들을 중심으로 본문을 진행하겠습니다.
1. 왜 TypeScript를 사용해야 하는가?1-1. 사전 오류 발견1-2. 코드의 명확한 의도 전달2. TypeScript 전환2-1. TypeScript 관련된 패키지 및 외부 라이브러리 설치2-2. TypeScript 설정 파일 생성2-3. 파일 확장자 변경2-4. 타입 설정2-5. 커스텀 타입 및 인터페이스 작성3. 총평
1. 왜 TypeScript를 사용해야 하는가?
2012년 마이크로소프트가 발표한 TypeScript는 JavaScript를 기반으로 정적 타입 문법을 추가한 프로그래밍 언어입니다.
최근 몇 년간 사용률이 계속해서 증가하고 있고, 2023 stack overflow 설문조사에 따르면 admired부분에서 70% 이상을 기록하며, TypeScrtipt를 계속 사용하고 싶어 하는 개발자가 많은 것으로 알 수 있습니다.
그러면 왜 개발자들은 TypeScript를 선호하며, 우리는 언제 JavaScript대신 TypeScript써야 하는 걸까요?
1-1. 사전 오류 발견
typescript의 정적 타입 검사를 통해 코드를 실행하기 전에 타입 관련 오류를 사전에 발견하고 수정할 수 있습니다. 이는 디버깅 시간을 줄여주며, 런타임에서의 예기치 않은 오류 발생을 방지합니다.
예를 들어, 수를 더하기 위한 sum() 함수를 작성할때
// math.js function sum(a, b) { return a + b; } sum(10, 20); // 30 sum('10', '20'); // 1020
javascript일때는 매개변수로 숫자가 아닌 값이 들어왔을 때 의도와 다르게 나옵니다.
// math.ts function sum(a: number, b: number) { return a + b; } sum('10', '20'); // Error
typescript를 사용하면 IDE에서 타입 관련 오류를 실시간으로 확인할 수 있으며, 디버깅 과정에서도 잠재적인 문제점을 미리 인지하고 수정할 수 있습니다.
1-2. 코드의 명확한 의도 전달
typescript의 정적 타입 검사는 코드의 의도를 분명히 하여, 개발자 간의 오해를 줄일 수 있습니다. 특히 대규모 프로젝트에서 팀원들 사이의 명확한 커뮤니케이션은 코드의 품질과 개발 속도에 큰 영향을 미칩니다. 타입스크립트를 사용하면, 함수나 변수의 목적과 그 사용 방법이 타입을 통해 분명해질 뿐만 아니 코드를 더욱 쉽게 이해하고, 오류 없이 활용할 수 있게 됩니다.
위의 예시에서 사용했던 sum()함수의 반환 값을 number로 명시함으로써, 해당 함수가 숫자 값을 반환한다는 것을 명확히 알 수 있습니다. 이는 다른 개발자들이 해당 함수를 사용할 때 어떤 형태의 값을 기대해야 하는지 확실히 알려줍니다.
또한, 대부분의 IDE에서 정적 타입 검사를 지원하므로, 개발자가 코드를 작성하는 도중 잘못된 타입의 값이 사용될 경우 즉각적인 피드백을 받을 수 있습니다. 이는 실수를 줄이고, 코드의 품질을 높이는 데 큰 도움이 됩니다.
2. TypeScript 전환
전환하려는 프로젝트는 JavaScript를 사용한 Next.js 기반의 프로젝트입니다. 해당 프로젝트의 JavaScript를 TypeScript로 전환하는 과정에 대해 간략하게 나열하겠습니다.
2-1. TypeScript 관련된 패키지 및 외부 라이브러리 설치
npm install --save typescript @types/react @types/node
다음 명령어를 통해 typescript, React타입 정의 패키지와 Node.js 타입 지원 패키지를 설치해야 합니다.
그리고 사용중인 외부 라이브러리가 있다면 TypeScript를 지원하는지 확인하고, 해당 라이브러리의 타입 정의를 @types/{library-name} 형태로 설치해야 할 수도 있습니다.
2-2. TypeScript 설정 파일 생성
NextJS 공식문서에 타입스크립트 설정을 참고하여 실행하시면 됩니다.
touch tsconfig.json
tsconfig.json 파일을 만들고,
npm run dev
명령어를 실행하면 tsconfig.json 파일에 기본 내용이 작성됩니다.
2-3. 파일 확장자 변경
NextJS프로젝트에서 JavaScript로 작성할 때 주로 JSX 파일 내의 컴포넌트로 구성됩니다. JSX(JavaScript XML)는 React의 UI 컴포넌트를 표현하기 위한 문법 확장입니다. 이를 사용하면 JavaScript 내에서 UI 컴포넌트를 HTML과 유사한 문법으로 작성할 수 있습니다. NextJS에서 JavaScript를 TypeScript로 전환은 JS파일과 JSX파일을 각각 TS와 TSX로 변경하면서 내부의 타입을 정의하는 작업이 필요합니다.
다음과 같이 확장자를 변경했다면, 내부에 타입이 정의되지 않은 변수나 함수 반환값에 대한 설정해줘야 합니다.
// tsconfig.json { ... "allowJs": true, ...
tsconfig 설정의 이 옵션은 TypeScript 컴파일러가 JavaScript 파일을 처리할 수 있게 하므로, 기존 JS 코드와 함께 TS 코드를 점진적으로 도입할 수 있습니다.
2-4. 타입 설정
- 변수, 상수의 타입을 정의해줘야합니다.
// post.jsx const [perPage, setPerPage] = useState(5); const [page, setPage] = useState(1); const [search, setSearch] = useState(''); const [accessToken, setAccessToken] = useRecoilState(accessTokenState) const [refreshToken, setRefreshToken] = useRecoilState(refreshTokenState)
// post.tsx const [perPage, setPerPage] = useState<number>(5); const [page, setPage] = useState<number>(1); const [search, setSearch] = useState<string>(''); const [accessToken, setAccessToken] = useRecoilState<string>(accessTokenState) const [refreshToken, setRefreshToken] = useRecoilState<string>(refreshTokenState)
2-5. 커스텀 타입 및 인터페이스 작성
- 커스텀 타입
TypeScript에서는 type이라는 키워드로 사용자 정의 유형을 생성할 수 있습니다.
// write.jsx const [post, setPost] = useState({ title: '', content: '', boardId: 0 });
// write.tsx type WritePost = { title: string; content: string; boardId: number; } const [post, setPost] = useState<WritePost>({ title: '', content: '', boardId: 1 });
위와 같이 useState훅에 제네릭 타입을 전달하여 사용할 수 있습니다. 이렇게 타입을 명시적으로 정의함으로써 코드의 안정성을 높이고, 대규모 프로젝트나 여러 팀원과의 협업에 있어 중요한 역할을 합니다. 제네릭을 활용하여
post
변수에 WritePost
타입을 지정하면, 잘못된 타입의 할당 시 TypeScript 컴파일러가 오류를 표시합니다. 이를 통해 오류 가능성을 대폭 줄일 수 있습니다.- 인터페이스 작성
인터페이스는 객체의 구조를 정의하는 데 사용되는 강력한 도구입니다. 예를 들어, 사용자 정보를 나타내는 인터페이스를 다음과 같이 작성할 수 있습니다.
// interfaces.tsx export default interface ILoginReq { loginId: string; loginPw: string; } export default interface IResponseData { accessToken: string; refreshToken: string; userId: string; accessTokenExpiresAt: string; refreshTokenExpiresAt: string; }
인터페이스를 사용하면 타입의 객체를 생성할 때 각 필드의 타입을 준수해야 합니다.
커스텀 타입과 인터페이스를 활용하면 코드의 구조와 의도를 명확하게 나타낼 수 있습니다. 또한, 이를 통해 코드의 오류를 줄이고 팀원 간의 협업 효율을 높일 수 있습니다.
3. 총평
TypeScript는 코드의 안정성을 높여 줄 뿐만 아니라, 코드의 의도를 명확하게 전달하면서도 확장성과 유지 보수성을 크게 향상시키고, 특히 Next.js와 TypeScript의 조합은 매우 유용했습니다. Next.js는 타입스크립트의 통합을 원활하게 지원하므로, 프로젝트를 TypeScript로 전환하는 데 큰 어려움이 없었습니다.
물론 도입 초기에는 학습 곡선이나 라이브러리 호환성 문제 등 몇몇 단점도 고려해야 합니다. 하지만 장기적으로 볼 때 이러한 투자는 큰 가치를 가져올 것으로 생각했습니다.
또한, TypeScript를 점층적으로 적용하는 방법은 프로젝트 전체를 한 번에 변경하는 부담을 줄여줬습니다. allowJs 설정을 통해 기존 JavaScript 코드와 TypeScript 코드를 동시에 유지할 수 있는 것은 전환 과정을 훨씬 수월하게 만들어줬습니다.
TypeScript는 프로젝트의 품질 향상과 팀 생산성 증가에 기여하는 좋은 선택이 될 거라 생각합니다.
[레퍼런스]
타입스크립트 핸드북 - https://joshua1988.github.io/ts/
TypeScript vs JavaScript - https://www.guru99.com/typescript-vs-javascript.html
Share article