🚀 자바스크립트 개발자라면 타입스크립트를 꼭 써야 하는 이유 (기초편)
안녕하세요! 오늘은 많은 개발자가 사랑하는, 그리고 어쩌면 몇몇 분들은 아직 망설이고 계실 타입스크립트(TypeScript)에 대해 이야기해보려고 합니다. “자바스크립트도 충분히 좋은데, 굳이 타입스크립트까지 배워야 할까?”라고 생각하셨다면, 이 글을 통해 그 생각이 바뀔지도 모릅니다. 😉
🤔 타입스크립트, 대체 정체가 뭐야?
가장 간단하게 말해볼까요? 타입스크립트는 자바스크립트에 타입(Type) 시스템을 추가한 언어입니다.
공식 문서에서도 타입스크립트를 ‘자바스크립트 위에 있는 레이어’라고 소개합니다. 완전히 새로운 언어라기보다는, 기존 자바스크립트의 모든 기능을 포함하면서 ‘타입’이라는 강력한 안전장치를 추가한 자바스크립트의 상위 집합(Superset)인 셈이죠.
이 말은 곧, 여러분이 작성하는 모든 .ts 파일 안에서 기존에 알던 자바스크립트 문법을 그대로 사용할 수 있다는 뜻입니다. 멋지지 않나요?
✨ 왜 다들 타입스크립트를 사용할까?
자바스크립트의 가장 큰 특징은 ‘유연함’입니다. 하지만 이 유연함은 때로 양날의 검이 되어, 예상치 못한 곳에서 에러를 발생시키곤 합니다. undefined is not a function 같은 에러 메시지, 다들 한 번쯤은 만나보셨죠?
타입스크립트는 바로 이 지점에서 진가를 발휘합니다. 코드를 실행하기 전, 컴파일 단계에서부터 타입을 체크해 에러를 미리 알려주거든요. 덕분에 우리는 소중한 시간을 아끼고, 실수를 획기적으로 줄일 수 있습니다.
타입스크립트의 핵심 장점 5가지
- 정적 타입 검사: 코드를 실행하기도 전에 타입 관련 오류를 잡아내 버그를 사전에 방지합니다.
- 똑똑한 자동완성: VSCode와 같은 에디터에서 변수, 함수, props의 타입을 추론해 놀랍도록 정확한 자동완성을 제공합니다.
- 코드 가독성 향상: 함수의 매개변수나 반환 값, 객체의 구조가 명확히 보여 코드를 이해하기 훨씬 쉬워집니다.
- 원활한 협업을 위한 최고의 도구: “이 API 응답에 어떤 데이터가 들어있지?” 와 같은 질문이 사라집니다. 타입을 보면 모든 구조를 알 수 있으니까요.
- 대규모 프로젝트에 최적화: 프로젝트가 커지고 복잡해져도, 타입 시스템 덕분에 유지보수와 확장이 매우 용이합니다.
✍️ 기본 타입 사용법 (Type Annotations)
자, 그럼 이제 실제로 타입을 어떻게 사용하는지 알아볼까요? 변수 이름 뒤에 콜론(:)을 붙이고 타입을 명시하면 됩니다.
// 숫자 타입
let age: number = 27;
// 문자열 타입
const name: string = "Jihyun Kim";
// 불리언 타입
let isActive: boolean = true;
// 유니언 타입 (둘 이상의 타입을 허용)
let id: string | number = "abc-123";
id = 456; // OK!
// 배열 타입
let list: number[] = [1, 2, 3];
// let list: Array<number> = [1, 2, 3]; // 이렇게도 사용 가능!
// 객체 타입
const user: { name: string; age: number } = {
  name: "Jihyun",
  age: 27,
};
// 함수 타입 (매개변수와 반환 값에 타입 지정)
function greet(name: string): string {
  return "Hi, " + name;
}있을 수도, 없을 수도 있다면? Optional Property
객체의 속성 중 필수가 아닌 값이 있다면 속성 이름 뒤에 물음표(?)를 붙여 선택적 속성(Optional Property)으로 만들 수 있습니다.
type Info = {
  title: string;
  description?: string; // description은 있어도 되고, 없어도 됩니다.
};
const data1: Info = {
  title: "첫 번째 정보",
  description: "이것은 설명입니다.",
};
const data2: Info = {
  title: "두 번째 정보", // description이 없어도 에러가 나지 않아요.
};함수에 타입 입히기
함수에 타입을 지정하는 몇 가지 방법을 알아봅시다.
1. 함수 선언식
function greet(name: string): string {
  return `Hello, ${name}`;
}2. 화살표 함수
// 함수 선언과 동시에 타입 지정
const greet = (name: string): string => {
  return `Hello, ${name}`;
};
// 함수 전체의 타입을 미리 선언 (컴포넌트 props로 함수를 받을 때 매우 유용!)
type GreetFunc = (name: string) => string;
const greet2: GreetFunc = (name) => {
  return `Hello, ${name}`;
};3. 반환 값이 없는 함수
함수가 아무것도 반환하지 않는다면 void 타입을 사용합니다.
function logMessage(message: string): void {
  console.log(message);
}타입을 정의하는 두 가지 방법: type vs interface
객체의 타입을 정의할 때 주로 type과 interface를 사용합니다.
1. type으로 직접 타입 선언하기
가볍고 빠르게 타입을 정의할 수 있지만, 확장은 조금 불편합니다.
type ProductType = {
  name: string;
  price: number;
};
const product: ProductType = {
  name: "노트북",
  price: 1500000,
};2. interface 사용하기
extends 키워드로 상속(확장)이 가능해 라이브러리나 컴포넌트의 props 타입을 정의할 때 매우 유용합니다.
interface Product {
  name: string;
  price: number;
}
interface DiscountedProduct extends Product {
  discountRate: number;
}
const discountedProduct: DiscountedProduct = {
  name: "키보드",
  price: 200000,
  discountRate: 0.1,
};⚛️ 리액트 컴포넌트와 훅에서 타입스크립트 활용하기
이론은 충분히 봤으니, 이제 리액트에서 실제로 어떻게 쓰이는지 살펴볼까요?
useState에 타입 지정하기
useState를 사용할 때 제네릭(<>) 문법으로 상태의 타입을 지정할 수 있습니다.
import { useState } from "react";
export default function Counter() {
  // count 상태는 number 타입만 가질 수 있습니다.
  const [count, setCount] = useState<number>(0);
  return <button onClick={() => setCount(count + 1)}>Click: {count}</button>;
}만약 상태의 초기값이 null일 수 있다면 유니언 타입을 활용하세요.
// user 상태는 string 또는 null 타입을 가질 수 있습니다.
const [user, setUser] = useState<string | null>(null);props에 타입 지정하기
컴포넌트가 받는 props의 타입을 type이나 interface로 정의하면 실수를 방지하고 재사용성을 높일 수 있습니다.
import React from "react";
// InfoCard 컴포넌트가 받을 props의 타입을 정의합니다.
type InfoCardProps = {
  title: string;
  description?: string; // 선택적 prop
};
export default function InfoCard({ title, description }: InfoCardProps) {
  return (
    <div>
      <h1>{title}</h1>
      {description && <p>{description}</p>}
    </div>
  );
}useEffect에서 타입 활용하기
useEffect 자체에는 특별한 타입이 필요 없지만, 비동기 API 호출 후 받아온 데이터의 타입을 지정할 때 매우 유용합니다.
import { useEffect, useState } from "react";
// API 응답 데이터의 타입을 미리 정의합니다.
interface UserData {
  name: string;
}
export default function UserInfo() {
  const [name, setName] = useState<string>("");
  useEffect(() => {
    fetch("/api/user")
      .then((res) => res.json())
      .then((data: UserData) => { // 받아온 데이터의 타입을 지정
        setName(data.name);
      });
  }, []);
  return <div>사용자 이름: {name}</div>;
}마무리하며
어떠셨나요? 타입스크립트가 처음에는 조금 번거롭게 느껴질 수 있지만, 익숙해지는 순간 이전의 자바스크립트 코드로 돌아가기 어려울 만큼 강력한 안정성과 개발 편의성을 제공해 준답니다.
오늘 소개한 내용은 타입스크립트의 정말 기본적인 부분입니다. 이 기초를 바탕으로 여러분의 프로젝트에 조금씩 타입스크립트를 적용해 보시면 어떨까요? 분명 더 즐겁고 생산적인 개발 경험을 하게 되실 겁니다
 

답글 남기기