본문 바로가기
TypeScript

[타입스크립트 프로그래밍] 9장 프론트엔드 프레임워크와 백엔드 프레임워크

by 복숭아 우유씨 2023. 6. 9.

* 타입스크립트 프로그래밍(보리스 체르니, 프로그래밍 인사이트)를 읽고 요약 정리한 글입니다.

 

 

 

9.1 프론트엔드 프레임워크

타입스크립트와 프론트엔드 프레임워크

- 풍부한 JSX지원, 변경에 안전하게 대응 가능

- 안전성, 멋진 구조, 빠르게 변하는 프론트엔드 개발 환경에 적합한 정확하면서도 유지보수하기 쉬운 코드 구현 가능

 

타입스크립트에서 DOM API 사용하기

- tsconfig.json 설정하기

   : 타입 검사시 lib.dom.d.ts(브라우저와 DOM 타입 내장 선언)파일에 선언된 타입 포함하도록 설정하기

// tsconfig.json
{
	"compilerOptions": {
    	"lib": ["dom", "es2015"]
    }
}

9.1.1 리액트

리액트와 타입스크립트

- 리액트 컴포넌트는 타입스크립트로 정의되고 소비되므로 안전하다.

   (컴포넌트 정의와 소비자 모두 타입을 검사함)

- 타입으로 표현시 타입스크립트가 제한을 강제하고 사용자의 컴포넌트를 확인한다.

- 컴포넌트 정의와 소비자(뷰)에 제공하는 안전성이 높다.

 

JSX입문

- Javascript XML

- 리액트에서 사용하는 특별한 DSL로 뷰를 정의하고 자바스크립트 코드에 바로 삽입할 수 있다.

- JSX 컴파일러로 컴파일하면 자바스크립트 함수 호출로 변환해준다.

 

TSX = JSX + 타입스크립트

- TSX : 타입스크립트가 자바스크립트에 제공하는 것과 같은 기능 제공 (컴파일 타임 안전성, 실수 줄이기 등) 

- .tsx : JSX를 포함하는 타입스크립트 파일의 확장자

- TSX 사용하려면, 아래의 tsconfig 설정 추가 필요함

// tsconfig.json
{
	"compileerOptions": {
    	"jsx": "react"
    }
}

[ jsx 지시어가 제공하는 세가지 모드 ]

모드 JSX 컴파일 파일
react O .js 파일로 컴파일
react-native X
(JSX 보존)
.js 파일 생성
preserve X
(JSX 타입 검사만 진행)
.jsx 파일 생성

 

- TSX를 넣고 뺄수 있은 hook : global.JSX 네임스페이스에 존재하는 특별 타입, 이 네임스페이스를 참고하여 TSX 타입 검사함

 

리액트에서 TSX 사용하기

1) 함수 컴포넌트

import React from "react"; // React 임포트

type Props = { // 컴포넌트에 전달할 수 있는 프로퍼티 집합 선언, Props는 항상 객체 타입이며 Props로 이름 짓는 것이 규칙임
  isDisabled?: boolean; // 선택형
  size: "Big" | "Small";
  text: string;
  onClick(event: React.MouseEvent<HTMLButtonElement>): void; // 리액트에서 DOM 이벤트 사용시, 리액트 이벤트 타입 사용해야 함
};

// 함수 컴포넌트는 일반 함수이다. 최대 한개의 매개변수(props객체)를 받으며 리액트가 렌더링할 수 있는 타입을 반환한다
// 리액트가 렌더링 할 수 있는 타입: TSX, 문자열, 숫자, boolean, null, undefined 등 다양한 타입 가능
export function FancyButton(props: Props) { 
  const [toggled, setToggled] = React.useState(false); // 만약 타입스크립트가 추론할 수 없는 타입(배열 등)을 사용한다면 타입을 명시해야 함(ex. useState<number[]>([]))
  return (
    <button
      className={"Size-" + props.size}
      disabled={props.isDisabled || false}
      onClick={(event) => {
        setToggled(!toggled);
        props.onClick(event);
      }}
    >
      {props.text}
    </button>
  );
}

// TSX 문법으로 인스턴스 생성함, <FancyButton /> 문법은 호출과 기능이 거의 같지만 생명주기를 리액트가 관리하게 된다.
let button = (
  <FancyButton 
    size="Big"
    text="Sign up Now"
    onClick={() => console.log("Clicked!")}
  />
);

[ 타입스크립트가 강제하는 것 ]

- JSX 문법 잘 지킬 것 (태그 꼭 닫기, 올바른 중첩, 태그명 오타 없을 것)

- 컴포넌트 인스턴스화할 때 필요한 모든 프로퍼티를 전달해야 함

- 전달하는 프로퍼티는 모두 올바른 타입을 가져야 함

- 전달하는 프로퍼니는 필요한 프로퍼티만 전달하고, 그 외는 전달하지 않아야 함

 

2) 클래스 컴포넌트

import React from "react"; // React 임포트
import { FancyButton } from "./FancyButton";

type Props = { // Props 타입 선언해서 <SignUpForm /> 인스턴스에 전달할 데이터 정의65
  firstName: string;
  userId: string;
};

type State = { // 컴포넌트의 로컬 상태를 가리킬 State 타입 선언
  isDisabled?: boolean;
};

class SignUpForm extends React.Component<Props, State> { // 클래스 컴포넌트 선언
  state = { // 프로퍼티 초기화 과정, 로컬 상태에 기본값을 선언
    isLoading: false,
  };
  render() {
    return ( // 리액트가 렌더링할 수 있는 것을 반환한다.
      <> // TSX도 fragment를 지원한다. 
        <h2>Sign up for..., {this.props.firstName}</h2>
        <FancyButton
          isDisabled={this.state.isLoading}
          size="Big"
          text="Sign up Now"
          onClick={this.signUp}
        />
      </>
    );
  }
  private signUp = async () => {  // this 바인딩 때문에 화살표 함수로 정의
    this.setState({ isLoading: true });
    try {
      await fetch("/api/signup?userId=" + this.props.userId);
    } finally {
      this.setState({ isLoading: false });
    }
  };
}

let form = <SignUpForm firstName="Albert" userId="13ab9g3" />; // 인스턴스화 (new로 직접 인스턴수화 할 경우 리액트가 인스턴스의 생명주기 관리 하지 못함)

 [ 위에서 타입스크립트가 확인하는 것 ]

 - 필요한 모든 상태를 state initializer나 생성자에서 정의했는가?

 - props, state에 접근한 값이 실제 존재하며 의도한 타입을 갖고 있는가?

 - this.state에 값을 직접 쓰지는 않는가? (상태 갱신시 setState 사용해야 함)

 - render를 호출하면 JSX를 반환하는가?

 

9.1.2 앵귤러

 

앵귤러

 - 리액트보다 풍부한 기능

 - 뷰 렌더링, 네트워크 요청 전송/관리, 라우팅, 의존성 주입 등

 - 타입스크립트로 구현된 프레임워크

 - AoT(Ahead-of-Time, 선행 컴파일러): 앵귤러의 핵심, 타입정보를 이용해 코드를 자바스크립트로 컴파일함

 - 타입스크립트 직접 호출하지 않음, 전반적인 최적화 및 변형 진행 후 타입스크립트에 위임해서 자바스크립트로 컴파일 함

(* 앵귤러에 관한 더 자세한 내용은 추후 앵귤러를 사용하게 되면 다시 정리하도록 하겠다.)

 

9.2 타입 안전 API

통신에서 타입 안전성을 유지하는 방법?

1) 타입 안전성을 제공하는 프로토콜 직접 개발(타입 안전 프로토콜)

 - 단점 존재 

2) 타입 지원 코드 생성 API 

 - 예: Swagger, Apollo, Relay, Apache Thrift

 - 서버와 클라이언트가 동일한 프로토콜을 사용하도록 하며, 특정 언어에 맞는 구조로 컴파일한다.

 - 서버와 클라이언트간의 동기화가 깨지는 문제 피할 수 있음(코드 생성 기술 덕분)

 

9.3 백엔드 프레임워크

객체 관계 매퍼(ORM, object-relational mapper)

 - 고수준의 API 제공 (데이터베이스 스키마로부터 코드를 만들어 질의, 갱신, 삭제 등의 작업 가능)

 - 정적 타입 언어 사용시 타입 안전성 제공

 - 즉, 일반적인 안전성과 타입 안정성을 기본으로 제공한다.

 


Reference

1) 타입스크립트 프로그래밍, 보리스 체르니, 프로그래밍 인사이트

댓글