배경 이미지
728x90
반응형

1. 컴파일러란?

컴파일러는 우리가 쓰는 프로그래밍 언어 코드를 → 다른 언어로 변환하는 도구에요.

- C언어 컴파일러는 C언어 → 기계어 코드 변환을 해주고

- TypeScript 컴파일러는 TypeScript → JavaScript 코드 변환을 해줘요!

 

2. 컴파일러는 왜 등장했을까?

컴퓨터는 기본적으로 기계어로 작성된 프로그램만 이해할 수 있어요!

그런데, 위의 스크린샷을 보면 아시겠지만 기계어는 사람이 이해하거나 작성하기 어려워요

그래서 사람이 더 쉽게 사용할 수 있는 C언어 같은 고수준 프로그래밍 언어가 등장했어요.

하지만 컴퓨터가 C언어로 작성된 코드를 이해하려면 기계어로 변환이 필요했고, 이를 도와주는 컴파일러가 필요하게 되었죠!

 

3. TypeScript 컴파일러

TypeScript 컴파일러는 TypeScript → JavaScript 코드 변환을 해준다고 설명했었죠

☑️ 여기서 갑자기 궁금한 점 🤔 🤔

위에서 컴퓨터가 이해하기 위해서는 기계어로 변환되어야 한다고 했잖아요, 그럼 JavaScript도 결국에는 기계어로 변환 되어야할텐데, 왜 JavaScript는 컴파일러가 없나요?

JavaScript는 동적 언어(인터프리터 언어)라서, 기계어로 미리 변환할 필요가 없어요. 대신, 실행할 때 브라우저나 Node.js 같은 JavaScript 엔진이 그 코드를 한 줄씩 읽고 바로바로 기계어로 변환해서 실행해요.

  • Node.jsChrome 브라우저V8 엔진을 사용해서 JavaScript를 처리하고,
  • FirefoxSpiderMonkey 엔진을 사용해요.

 

4. 컴파일러와 인터프리터의 차이

정리하자면:

  • 정적 언어(컴파일 언어): C언어처럼 미리 기계어로 변환해야 실행할 수 있어요. 이때 변환을 도와주는 것이 컴파일러예요.
  • TypeScript: TypeScript는 컴파일러(tsc)를 통해 JavaScript로 변환되고, 변환된 JavaScript는 JavaScript 엔진이 실행하면서 기계어로 변환돼요.
  • 동적 언어(인터프리터 언어): JavaScript처럼 코드를 실행하면서 그때그때 해석하고 기계어로 변환해요. 컴파일러가 필요 없고, 인터프리터가 코드를 해석해서 바로 실행해줘요.

 

이제 정리가 되셨나요? 그렇다면, 왜 컴파일러를 알아야 할까요?

 

5. 컴파일러의 주요 역할 

☑️ 타입 검사

TypeScript 컴파일러(tsc)는 타입 오류를 미리 찾아줘요. 예를 들어, 숫자 변수에 문자를 넣으려고 하면 "잘못된 타입!"이라고 오류를 알려줘요. 이렇게 컴파일러는 오류를 미리 알려줘서, 개발자가 실행 전에 수정할 수 있게 도와주는 역할을 해요.

☑️ 코드 변환

컴파일러는 우리가 작성한 코드를 다른 언어로 변환해요. tscTypeScript 코드를 JavaScript로 변환하고, C언어 컴파일러C언어를 기계어로 변환해요. 이 과정이 있어야 코드가 컴퓨터에서 실행될 수 있죠.

 

☑️ 에러 처리와 디버깅 지원

컴파일러는 코드를 변환하면서 오류를 발견하면 에러 메시지를 출력해요. 개발자는 이 메시지를 보고 문제를 파악하고 빠르게 수정할 수 있어요. 컴파일러가 변환하는 과정을 잘 이해하면, 문제 발생 시 어떤 방식으로 해결할지 더 쉽게 예측할 수 있어요. 이를 통해 디버깅 과정에서 큰 도움이 돼요.

 

6. tsconfig.json 해부하기

tsconfig.json 이란?

  • TypeScript 프로젝트의 설정 파일이에요. 이 파일에서 여러 가지 옵션을 사용해서 TypeScript 코드가 어떻게 동작할지를 설정할 수 있어요.
  • tsc --init 명령어를 실행하면 이 파일이 생성돼요. 주로 컴파일할 파일컴파일 방법을 정의하는 데 쓰여요.

주요 옵션들

☑️  compilerOptions - target 옵션:

  • 코드를 어떤 JavaScript 버전으로 변환할지 정하는 옵션이에요.
  • es5 로 설정하면 CommonJS 버전으로 컴파일되구요!
  • es2016(=es7) 로 설정하면 ES2016 버전으로 컴파일이 됩니다!
    • 최신 브라우저는 보통 ES2016을 지원하니 이렇게 설정하시는 것을 추천드려요!
  • 단, 이것을 정할 때는 TypeScript가 어느 환경에서 실행이 되어야하는지를 고려하셔야 해요!
    • 만약, 내가 만든 프로젝트가 생각보다 레거시한 환경에서 동작해야 된다면? → es5
    • 그렇지 않다면 → es2016

 

☑️  compilerOptions - module 옵션:

  • JavaScript 모듈 형식을 지정하는 옵션이에요. 모듈을 어떻게 가져오고 내보낼지를 정해줘요.
  • target 옵션과는 서로 독립적인 관계로 프로젝트의 요구사항에 따라 옵션을 설정하시면 됩니다!

☑️  compilerOptions - outDir 옵션:

  • 컴파일된 JavaScript 파일들이 저장될 폴더를 정하는 옵션이에요.(출력 디렉터리를 지정)
  • 예를 들어, "outDir": "dist"로 설정하면 컴파일된 파일들이 dist 폴더에 저장돼요.

☑️  compilerOptions - strict

  • 엄격한 타입 검사 옵션을 모두 활성화하는 옵션이에요!
    • strictNullChecks
      • 잠재적으로 null(undefined)이 될 수 있는 값들에 대해서 엄격하게 확인하는 옵션이에요!
    • strictFunctionTypes
    • strictBindCallApply
    • strictPropertyInitialization
    • noImplicitAny
      • 함수의 인자 또는 변수의 타입이 명시적으로 선언되지 않은 경우에 컴파일러가 자동으로 any타입을 부여하지 않도록 해요.
      • 이 옵션을 활성화하면 개발자가 누락된 타입 선언을 확인하고 명시적으로 타입을 선언할 수 있죠!
    • noImplicitThis
    • alwaysStrict해당 옵션을 true로 설정하면 아래의 옵션들이 자동으로 true로 설정이 되어요.
  • 이 옵션을 꼭 true로 설정하는 것을 추천해요.

☑️  compilerOptions - sourceMap 옵션:

  • 소스 맵을 생성하는 옵션이에요. 소스 맵이 있으면 디버깅할 때 원래 TypeScript 코드를 쉽게 찾을 수 있어요.
  • 개발 중에는 꼭 true로 설정하는 게 좋아요. 하지만 배포할 때는 용량이나 성능상의 이유로 sourceMap을 사용하지 않는 것이 나을 수 있어요!

☑️  include, exclude 옵션:

  • 컴파일할 파일컴파일에서 제외할 파일을 정하는 옵션이에요.
  • “include": ["src/**/*"]
    • src 디렉토리 밑의 친구들을 컴파일 하겠다는 의미에요!
  • "exclude": ["node_modules", "dist"]
    • node_modules, dist 디렉토리 밑의 친구들은 컴파일 대상에서 제외하겠다는 의미에요!

 

7. d.ts 파일 알아보기

💡 .d.ts 파일JavaScript 라이브러리를 TypeScript에서 사용할 수 있게 도와주는 파일이에요.

 

왜 d.ts 파일이 필요할까요?

    • TypeScript가 나오기 전에는 당연히도 JavaScript로만 코드를 작성했겠죠?
    • 아직까지 이 세계에는 JavaScript 코드의 양 >>> TypeScript 코드의 양일 것입니다.
    • 그렇다면, 이미 작성된 다양한 JavaScript 라이브러리와 호환성을 유지할 수 있어야겠죠?
    • 어떻게 TypeScript 코드는 JavaScript 라이브러리와 호환성을 유지할 수 있을까요?

@types 라이브러리의 등장

  • 이 라이브러리는 외부 JavaScript 라이브러리에 대한 타입 정보를 TypeScript에 제공해줘요.
  • 실제로 @types 디렉터리에 들어가 보면, .d.ts 파일들이 잔뜩 있어요.

그렇다면 이 .d.ts 파일은 무엇일까요?

  • .d.ts 파일은 TypeScript 타입 정의 파일이에요.
  • 이 파일은 TypeScript가 JavaScript 라이브러리의 타입 정보를 알 수 있게 도와줘요. 예를 들어:
    • 외부 라이브러리의 함수가 어떤 타입을 반환하는지,
    • 클래스가 어떤 타입인지,
    • 객체가 어떤 타입인지 등을 알려주는 역할을 해요.
  • 뿐만 아니라 타입 추론도 가능하게 해줘요. 타입 추론이란, 타입이 명시가 되지 않았을 때 컴파일러가 알아서 해당 타입에 대해 추론을 하는 것이에요.

따라서 해 라이브러리에 대한 .d.ts 파일만 있으면 기존의 JavaScript 라이브러리를 TypeScript에서도 그대로 사용할 수 있어요

 

728x90
반응형
728x90
반응형

Node.js의 등장가 등장하면서 JavaScript로 프론트엔드뿐만 아니라 백엔드까지 모두 개발할 수 있게 되었죠. 

하지만, 우리는 잊고 있었죠. JavaScript는 동적 타입 언어였다는 것을..

다들 한 번쯤 알 수 없는 “undefined” 에러를 보며 스트레스를 받은 기억이 있지 않나요?

[JavaScript의 단점]

☑️ 실행 중에만 에러를 알 수 있어요
JavaScript는 프로그램이 실행되는 동안에만 오류를 찾아요. 즉, 프로그램을 코딩할 때는 잘못된 부분이 있는지 모르고, 실행을 해봐야만 에러가 발생하는 것을 알 수 있어요. 이 때문에, 개발 중에 실수한 부분을 빨리 잡기 어렵죠. 예를 들어, 숫자 값을 다루는 함수에서 문자열이 들어가면 이상한 결과가 나와버리기도 해요.

 

☑️ 약한 타입 체크
JavaScript에서는 변수에 어떤 타입의 값이 들어가도 문제가 되지 않아요. 숫자를 넣었다가 나중에 문자열로 바꿔도 별다른 경고가 없어요. 이런 유연성 덕분에 쉽게 코드를 작성할 수 있지만, 실수로 잘못된 데이터를 넣으면 오류가 발생할 가능성이 높아요.

 

☑️ 객체의 유연함

const obj = { latitude: 11.5, longitude: 47.1 };
const result = obj.latitude * obj.longitute; // 보통은 이런 실수는 컴파일러가 잡아줘야 되는데
console.log(result) // NaN이라는 엉뚱한 값 출현!


JavaScript의 객체는 너무 유연해서 프로그래머가 실수로 잘못된 데이터를 넣거나 조작할 수 있어요. 예를 들어, GPS 좌표를 담은 객체에서 'latitude'와 'longitude'라는 값을 다루다가 오타로 'longitute'라고 쓰면, 프로그램은 이걸 미리 잡아내지 못하고 실행 후에야 문제가 발생해요.

이런 문제들이 쌓이면서, JavaScript로 대규모 프로젝트를 개발할 때 안정성을 보장하기가 어려웠어요. 이를 해결하기 위해 등장한 것이 바로 TypeScript에요.

 

[TypeScript의 등장]

TypeScriptMicrosoft에서 만든 프로그래밍 언어로, JavaScript의 단점을 보완하기 위해 만들어졌어요. TypeScript는 JavaScript에 정적 타입 기능을 추가했어요. 즉, 프로그램이 실행되기 전에 코드를 확인하고 잘못된 부분을 미리 알려주는 거죠.

 

☑️ 컴파일 시간에 오류 체크
TypeScript는 코드를 작성하는 순간부터 오류를 체크해줘요. 코딩을 하면서 잘못된 부분을 바로 잡을 수 있어서, 실행 중에 발생하는 에러를 크게 줄일 수 있어요.

 

☑️ 강한 타입 체크
TypeScript는 변수에 정확한 타입을 정해주기 때문에, 숫자는 숫자로, 문자열은 문자열로만 다루게 해줘요. 이 덕분에 실수로 타입을 잘못 입력하는 문제를 방지할 수 있어요.

 

☑️ 안전한 객체 사용
TypeScript는 객체의 속성도 잘못 사용하지 않도록 도와줘요. 객체의 속성 이름을 잘못 입력하면 코드를 작성하는 중에 바로 오류를 알려주기 때문에, 실행 전에 문제를 미리 해결할 수 있어요.

 

TypeScript의 매력은 이게 끝이 아닙니다!

 

☑️ 객체 지향 프로그래밍 지원

TypeScript는 객체 지향 프로그래밍(OOP) 개념을 강력하게 지원해요. 클래스 내부의 프로퍼티에 접근을 제한하는 기능이 있어, 외부에서 잘못된 값을 수정하는 것을 방지할 수 있어요.

  •  기존 JavaScript 객체 지향 프로그래밍 예시
class Person {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }

  growOlder() {
    this.age += 1;
  }
}

const spartan = new Person('dudu', 30);
spartan.age = 25; // 외부에서 age 속성을 마음대로 조작할 수 있어요! 뜻밖에 회춘?
spartan.growOlder();
console.log(spartan.age); // 결국 1살을 더 먹었지만 dudu는 26세

 

  • TypeScript 객체 지향 프로그래밍 예시
class Person {
  private name: string;
  private age: number; // age가 private인 것을 주목하세요!

  constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
  }

  public growOlder(): void {
    this.age += 1;
  }
}

const spartan = new Person('dudu', 30);
spartan.age = 25; // Error: Property 'age' is private and only accessible within class 'Person'.
spartan.growOlder();
console.log(spartan.age); // Error: Property 'age' is private and only accessible within class 'Person'.

 

 

[TypeScript를 배우면 할 수 있는 것]

☑️ TypeScript는 개발자 취업 시장에서 이제는 필수적인 기술 스택이 되었어요.

☑️ 더 높아지는 생산성 & 안정성

☑️ 정적 타입 시스템, 객체 지향 프로그래밍, 디자인 패턴 등 다양한 고급 프로그래밍 개념들을 학습할 수 있어요.

☑️ 줄어드는 테스트 코드: TypeScript는 JavaScript에 비해 테스트 코드보다 비지니스 로직 작성에 집중할 수 있게 해줘요!

 

 

끝!!

 

728x90
반응형
728x90
반응형

유니온 타입(Union Type)이란?

자바스크립트의 OR 연산자(||)와 같이 A이거나 B이다 라는 의미의 타입

하나의 변수나 함수가 여러 개의 타입을 가질 수 있게 하는 기능이다.

function getData(value: string | number) {
  // ...
}

 

유니온 타입 쓰는 이유

코드의 안정성과 가독성을 높이기 위해서이다.

아래와 같이 any 타입을 사용하는 경우 타입스크립트의 타입 추론 기능을 상실하게 되어 코드 작성 중 실수를 쉽게 잡아내지 못할 수 있다. 반면 유니온 타입을 사용하면 특정 타입에 대해 명확한 조건 검사를 통해 타입 안전성을 유지할 수 있다.

// any를 사용하는 경우
function getData(value: any) {
  value.toFixe(); // 에러 발생, age의 타입이 any로 추론되기 때문에 숫자 관련된 API를 작성할 때 코드가 자동 완성되지 않는다.
  return value;
}

// 유니온 타입을 사용하는 경우
function getData(value: number | string) {
  if (typeof value === 'number') {
    value.toFixed(); // 정상 동작, value의 타입이 `number`로 추론되기 때문에 숫자 관련된 API를 쉽게 자동완성 할 수 있다.
    return value;
  }
  if (typeof value === 'string') {
    return value;
  }
  return new TypeError('value must be number or string');
}

 

 

유니온 타입과 인터페이스 사용 시 주의할 점

interface Person {
  name: string;
  age: number;
}
interface Developer {
  name: string;
  skill: string;
}

function introduce(someone: Person | Developer) {
  console.log(someone.name); // O 정상 동작
  console.log(someone.age); // X 타입 오류
  console.log(someone.skill); // X 타입 오류
}

 

introduce 함수의 파라미터 타입을 Person과 Developer 인터페이스의 유니온 타입으로 정의했다.

유니온 타입은 "A도 될 수 있고 B도 될 수 있는" 타입이기 때문에, 함수 안에서 모든 속성을 사용할 수 있을 것 같지만, 타입스크립트는 Person 타입일지 Developer 타입일지 알 수 없으므로 공통 속성인 name만 접근할 수 있다.

 

해결방안

따라서 introduce 함수 안에서는 타입 가드(Type Guard)를 이용하여 타입의 범위를 좁혀야한다.

function introduce(someone: Person | Developer) {
  if ('age' in someone) {
    console.log(someone.age); // O 정상 동작
  }
  if ('skill' in someone) {
    console.log(someone.skill); // O 정상 동작
  }
}

유니온 타입을 사용할 때 타입 가드를 통해 타입의 범위를 좁히는 것은 매우 중요하다.

이를 통해 타입스크립트의 타입 시스템을 최대한 활용하고 코드의 안정성을 높일 수 있다.

 

 

 

728x90
반응형
728x90
반응형

옵셔널 체이닝이란?

객체의 속성에 접근할 때 해당 객체나 속성이 존재하지 않아도 에러를 발생시키지 않고 undefined를 반환하게 하는 기능이다.

사용하는 이유

특히 API 응답을 처리할 때 자주 유용한데, 중첩 객체를 접근할 때 보다 안전하게 접근을 할 수 있고, 가독성이 향상된다.

 

예시 

Person 을 사용하여 선언한 객체에 email 값이  존재하고, null, undefined, 빈 문자열("")이 아닌지 체크하기

interface Person {
  name: string;
  email?: string;
}
function check(obj: Person): boolean {
  return obj.email !== undefined && obj.email !== null && obj.email !== "";
}

이렇게 일일이 체크 할 팔요없이

function check(obj: Person): boolean {
  return obj.email?.length > 0 || false;
}

옵셔널 체이닝(?.)을 사용하면 null 또는 undefined인 경우에도 안전하게 체크할 수 있음

 

 

주의

옵셔널 체이닝 남용 금지!

무분별하게 남용하면 디버깅이 어려워질 수 있기떄문에 ?.는 존재하지 않아도 되는 대상에만 사용해야한다.

 

-끝-

 

728x90
반응형

+ Recent posts