우당탕탕

TypeScript 처음 도입하면서 헷갈렸던 부분 직접 겪어보니 본문

언어/JavaScript

TypeScript 처음 도입하면서 헷갈렸던 부분 직접 겪어보니

모찌모찝 2026. 6. 14. 14:23

TypeScript를 처음 도입할 때, 저도 생각보다 엄청 헤맸어요. 문법부터 도구 설정, 타입 체커랑 친해지는 과정까지, 막상 해보면 이게 왜 이렇게 복잡하지 싶을 정도였거든요. 그런데 주변 동료나 다른 개발자들의 사례를 들어보니 저만 그런 게 아니더라고요. 그래서 제가 겪었던 헷갈렸던 부분들을 정리하면서, 다른 사람들의 경험과 비교도 같이 해봤어요. 덕분에 TypeScript를 좀 더 편하게 다룰 수 있었거든요.

이 글에서는 TypeScript 처음 도입하면서 실제로 부딪힌 문제들, 그리고 다른 개발자들이 겪었던 문제와 차이점, 그리고 그걸 어떻게 해결했는지 차근차근 이야기할게요. 프론트엔드나 앱 개발에 TypeScript를 처음 접하는 분들이 읽으면, 막연한 두려움이 조금 덜해질 거예요.

개발 환경 / 버전 정보

제가 사용한 환경은 TypeScript 5.0.4, Node.js 18 LTS, 그리고 프론트엔드 프레임워크는 React 18이었어요. 주로 VSCode 편집기를 사용했고, ESLint와 Prettier를 연동해서 코드 스타일도 자동으로 맞췄죠.

처음 헷갈렸던 타입 선언과 타입 추론, 다른 사람들은 어땠을까?

사실 TypeScript에서 가장 기본이지만 처음에 가장 많이 헷갈리는 게 '언제 명시적으로 타입을 써야 하나?'였어요. 저는 처음에 모든 변수에 전부 타입을 명시해야 하는 줄 알았거든요. 그래서 코드가 엄청 장황해지고 지저분해졌죠.

반면, 제 친구는 타입 추론에 꽤 의존했는데, 코드를 더 간결하게 유지하면서도 타입 오류는 꽤 잘 잡히더라고요. 물론 초반에는 '이 타입이 언제 어떻게 추론되는지'가 막연해서 헷갈려했지만, 강제로 타입을 명시하는 것보다 훨씬 자유로웠대요.

결론적으로, 타입 선언은 중요한 부분에만 명시하고 나머지는 타입 추론을 믿는 게 저는 훨씬 편했고, 권장되는 방법이라는 걸 깨달았어요.

간단한 예시 코드

// 명시적 타입 선언
const userName: string = 'Alice';

// 타입 추론 사용
const userAge = 30; // 자동으로 number로 추론

// 함수 파라미터는 명시적으로 쓰는 편
function greet(name: string) {
  return `Hello, ${name}`;
}

이렇게 타입 추론과 명시적 선언을 적절히 섞으면 코드가 훨씬 깔끔해지더라고요.

tsconfig.json 설정, 직접 바꾸면서 깨달은 점

처음에 저는 tsconfig.json 기본 설정을 그냥 쓰면서 막혔어요. 예를 들어 strict 모드를 켜니까 엄청 빡세게 에러가 났거든요. 급하게 끄고 싶었지만, 다른 팀에서는 오히려 strict 모드를 무조건 키고 개발한다더라고요.

저는 여러 옵션 하나씩 켜고 꺼보면서 어떤 게 안전한지, 어떤 게 너무 과한지 체감했는데요. 예를 들어 noImplicitAny 옵션은 켜는 게 좋았고, strictNullChecks도 처음엔 귀찮았지만 코드 안정성이 폭발적으로 좋아졌어요.

아래는 제가 추천하는 최소 tsconfig.json 설정이에요.

{
  "compilerOptions": {
    "target": "ES2020",
    "module": "ESNext",
    "strict": true,
    "noImplicitAny": true,
    "strictNullChecks": true,
    "jsx": "react-jsx",
    "moduleResolution": "node",
    "esModuleInterop": true
  },
  "include": ["src"]
}

이걸로 맞춘 뒤 오히려 에러가 많아져서 짜증났던 초기와 달리, 점점 안전한 코드가 작성된다는 생각이 들었어요.

타입 에러 처리 방법, 현장에서 많이들 헤매는 부분

TypeScript 도입 초기에 가장 스트레스 받았던 게 뜻하지 않은 타입 에러들이었어요. 특히 외부 API 데이터 응답 타입을 제대로 맞추지 못해서 고생했거든요. 저도 처음에는 any 타입을 남용했는데, 나중에 이게 독이 되더라고요.

다른 사람들의 경우, 외부 데이터 타입 선언을 위한 별도의 타입 정의 파일을 만들어 관리하거나, 제네릭 타입과 유틸리티 타입을 적극 활용해서 에러를 사전에 방지했어요. 저는 보통 이렇게 했습니다.

interface ApiResponse {
  data: T;
  status: string;
}

// 예: 사용자 정보 타입
interface User {
  id: number;
  name: string;
}

async function fetchUser(): Promise<ApiResponse> {
  const response = await fetch('/api/user');
  const result = await response.json();
  return result;
}

이런 식으로 타입을 명확히 하니까 개발할 때 실수가 줄었어요.

JSX에서 TypeScript 쓸 때 유의점, 제가 겪은 트러블

React에 TypeScript를 적용할 때 많이들 헷갈리는 게 JSX 내 props 타입 선언인 것 같아요. 저는 처음에 props 타입을 인터페이스로 정의하긴 했는데, 기본 prop값을 설정하는 방법 때문에 한참 헤맸어요.

예를 들어 다른 동료는 React.FC 타입을 적절히 활용해서 간단하게 처리했더라고요. 그런데 저처럼 strict 옵션 켜 둔 환경에서는 기본 props와 관련된 타입 이슈가 복잡해지곤 해요.

제가 쓴 방법은 다음과 같아요.

interface ButtonProps {
  label: string;
  disabled?: boolean; // 선택적
}

const Button = ({ label, disabled = false }: ButtonProps) => {
  return <button disabled={disabled}>{label}</button>;
};

이렇게 기본값을 함수 파라미터에서 직접 지정하니까, 타입 오류 없이 깔끔하게 동작했어요.

여기서 삽질했던 부분들

이 에러가 왜 나는지 한참 찾았는데, TypeScript가 union 타입과 null 허용 여부를 엄격히 검사하면서 예상치 못한 오류가 났던 적이 있었어요. 예를 들어 아래 코드처럼 null 체크를 제대로 안 했을 때입니다.

function printName(name: string | null) {
  // 오류! 'name'이 null일 수도 있다고 경고
  console.log(name.length);
}

열심히 해결책을 찾아보니, 아래처럼 null 체크를 반드시 해야 한다고 하더라고요.

function printName(name: string | null) {
  if (name) {
    console.log(name.length);
  } else {
    console.log('No name provided');
  }
}

이 부분에서 막혀서 한참 헤맸는데, 다른 분들도 여기서 많이들 헷갈리는 것 같아요.

심화: 이렇게 하면 조금 더 편해집니다

좀 더 타입 시스템을 잘 활용하고 싶다면, TypeScript 유틸리티 타입을 적극 활용하는 걸 추천해요. 예를 들어 Partial<T>, Readonly<T>, Pick<T, K> 등이 있는데, 적절히 쓰면 코드가 훨씬 안전하면서도 유연해져요.

또, 다른 동료들은 자동 타입 생성 도구(swagger-typescript-api, openapi-generator 등)를 써서 API 타입 매핑을 자동화하더라고요. 저도 프로젝트가 커지면서 그런 자동화 도구가 필요하다고 느꼈어요.

자주 물어보시는 것들

Q. 타입스크립트에서 무조건 모든 변수에 타입 써야 하나요?

A. 꼭 그렇진 않아요. 타입 추론이 워낙 좋아서, 단순 변수는 대부분 생략해도 안전해요. 다만 함수 파라미터, 반환 타입, 복잡한 오브젝트 타입 등 중요한 부분은 명시하는 게 좋습니다.

Q. any를 쓰면 안 좋은가요?

A. any는 타입 체크를 무시하기 때문에 가능한 피하는 게 좋아요. 초기 도입 때는 어쩔 수 없이 쓸 수 있지만, 점점 타입을 명확히 해나가는 게 유지보수에 훨씬 도움이 됩니다.

Q. React 컴포넌트에 타입 어떻게 선언하나요?

A. props 타입을 interface나 type으로 정의하고, 함수 파라미터에 명시합니다. 함수 기본 파라미터로 기본값 설정도 가능합니다. React.FC 타입을 써도 되고, 최근에는 그냥 함수형 선언 후 명시하는 방식을 선호하는 경우가 많아요.

TypeScript 처음 도입할 때는 시행착오가 당연한 것 같아요. 저도 삽질하면서 많이 배웠고, 다른 분들의 경험도 듣고 비교하니 방향을 잡기 훨씬 수월해졌거든요. 이 글이 그런 고민에 조금이나마 도움이 됐으면 합니다. TypeScript는 한 번 익히면 결국 생산성이 확 올라가는 좋은 도구니까요!

Comments