티스토리 뷰

728x90
SMALL

배경

바닐라 자바스크립트 또는 타입스크립트로 라이브리리, 프레임 워크없이 꽤나 많은 프로젝트를 했다. 그리고 리액트와 비교했을 때 여러가지 어려운 점이 있었지만 jsx를 사용하지 못하는 것도 조금 아쉬웠다. 그런데 리액트없이 바벨 플러그인 하나를 설치하면 jsx를 사용할 수 있다는 것을 알게 되었다. 그래서 한번 적용해보려고 한다.(사실 리액트 없이 jsx 세팅하는 것 보다 그냥 만드는 게 편하다)

웹팩 설정

나는 바벨을 웹팩에서 같이 설정하는 것을 선호한다. 물론 나눠도 상관없다. yarn add -D @babel/plugin-transform-react-jsx로 플러그인을 설치하고 바벨 플러그인에 @babel/plugin-transform-react-jsx 를 넣어주면 된다. 바벨을 따로 설정하는 분들이 헷갈릴지도 모른다고 생각해서 그냥 전체 코드를 올린다.

webpack.common.js

  module: {
    rules: [
      {
        test: /\.(ts|tsx|js|jsx)$/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: [
              '@babel/preset-typescript',
              [
                '@babel/preset-env',
                {
                  targets: '> 1%, not dead',
                  useBuiltIns: 'usage',
                  corejs: { version: '3' },
                },
              ],
            ],
            plugins: ['@babel/plugin-transform-react-jsx'],
          },
        },
        exclude: /(node_modules)/,
      },

jsx 함수 생성

jsx 함수를 만들어야 한다. 일단은 기본적으로 {type, props, children}을 리턴하면 된다. 리액트 코드를 바벨로 변환해본적이 있다면 쉽게 알 수 있다. 참고로 type은 htmlelement이고(button, div) props는 리액트에서 하위 컴포넌트에 넘겨주는 props 또는 attribute를 생각하면 된다. 그리고 children에는 jsx배열 혹은 any 배열(string, boolean, number 모두 가능)이 들어가게 된다.

조금더 생각해보자. 리액트에서는 문자열이 false나 undefined인 경우 문자열로 반환하지 않는다. 또한 props가 false거나 undefined이면 props를 제거한다. 지금 말한것을 바탕으로 코드를 짜면 다음과 같다.

/* eslint-disable no-param-reassign */
type TState = Record<string, any>;

export interface IJsx {
  type: string;
  props: TState;
  children: any[] | IJsx[];
}

function jsx(type: string, props: TState, ...children: any[] | IJsx[]): IJsx {
  const nextChildren: IJsx[] = [];
  children.forEach((child) => {
    if (child !== false && child !== undefined) nextChildren.push(child);
  });
  if (props) {
    Object.keys(props).forEach((key) => {
      if (props[key] === false || props[key] === undefined) delete props[key];
    });
  }
  return { type, props, children: nextChildren.flat() };
}

export default jsx;

jsx 글로벌 타입 설정

자바스크립트에서는 그냥 동작하지만 타입 스크립트에서 그냥 사용하려고 하면 타입 오류가 발생한다. 다음과 같이 타입 설정을 해줘야한다.

jsx.d.ts

declare module JSX {
  type Element = string;
  interface IntrinsicElements {
    [elemName: string]: any;
  }
}

tsconfing 설정

compilerOptions에 "jsx": "react"를 추가해줘야한다.

실제 사용하기

세팅이 끝났다. 이제 사용하면 된다. 다음 코드를 입력하면 jsx를 사용할 수 있다. 린트를 사용하지 않는다면 린트 코드는 지우면 된다.

/** @jsx jsx */
// eslint-disable-next-line @typescript-eslint/no-unused-vars
import jsx from '@/core/jsx';

추가로 하고 싶은말

vscode의 es6-string-html 플러그인을 설치하면 string 코드를 html 코드처럼 보이게 만들 수 있다. 이렇게 사용하는게 훨씬 편하다. 사서 고생하고 싶은 나같은 사람만 시도해보길... 이걸로 인해서 조금 다른 문제점들이 생긴다. 그건 다음글에서....

728x90
LIST
댓글
공지사항