typescript와 tailwindcss로 티스토리 스킨 개발하기 (feat.webpack)

Pluto·2022년 11월 2일
0
post-thumbnail

시작하며

티스토리 스킨 적용에 필요한 파일에는 index.xml, skin.html, style.css, script.js가 있습니다. 이 파일들을 빌드하기 위해 개발 환경을 세팅해보았으며, 이에 대한 적용기를 적어보려 합니다.

스킨 개발에는 typescript와 tailwind css를 사용하였고, 이것들을 webpack을 이용해 한번에 빌드하는 과정에 대해서 작성하였습니다.

티스토리 스킨 개발을 위한 파일 디렉토리는 다음과 같습니다.

tistory_skin
 |- index.xml
 |- skin.html
 |- style.css
 |- /images
   |- script.js

xml과 html파일의 구조와 스킨을 만드는 방법에 대해서 궁금하신 분들은 제가 쓴 티스토리 스킨 구조 파악 글을 참고해주세요.

1. Typescript로 개발하기

우선 개발을 진행할 src 폴더를 만들어 script.ts 파일을 생성합니다. 이 파일에서 스킨에 적용할(사이드바 동작, TOC 등) 기능을 개발하면 됩니다.

ts파일을 생성했다면 이제 타입스크립트 개발환경을 세팅하고, js로 빌드해보겠습니다.

1-1. Typescript 설치

npm init

npm init 명령어를 실행하면 package.json파일이 생성되며 npm 환경이 세팅됩니다.

npm install typescript

그리고 npm을 통해 typescript를 설치합니다.

1-2. tsconfig.json 설정

typescript를 설치했다면 tsconfig.json파일을 생성하여 다음 내용을 입력해줍니다.

{
  "compilerOptions": {
    "target": "es2016",                            
    "module": "es6",
    "strict": true,
    "skipLibCheck": true,                               
    "outDir": "images",
    "watch": true
  },
  "include": [
    "src/script.ts"
  ]
}

outDirectory를 images로 설정한 다음, include속성에 js로 변환할 파일(src/script.ts)을 지정해줍니다.

1-3. Typescript 빌드하기

타입스크립트에서 자바스크립트로 빌드하는것은 쉽습니다. 아래 명령어를 터미널에서 실행하면 자동으로 빌드됩니다.

tsc

참고로 tsconfig파일에서 watch속성을 true로 주었기때문에 ts파일을 변경 및 저장할 때마다 자동으로 빌드합니다.

여기까지 따라왔다면 파일 구조는 다음과 같습니다.

tistory_skin
 |- index.xml
 |- skin.html
 |- style.css
 |- /images
   |- script.js
 |- /src
   |- script.ts
 |- /node_modules
 |- package.json
 |- package-lock.json
 |- tsconfig.json

2. TailwindCSS 적용하기

개발의 편의를 위해 style.css파일에 모든 스타일 속성을 적지않고, tailwind css를 설치하고 적용해보겠습니다.

그런데 설치 전에 스킨 배포의 용이성을 위해 dist폴더에 배포에 필요한 파일들만 담도록 파일 구조를 변경하겠습니다.

tistory_skin
 |- /dists
   |- index.xml
   |- skin.html
   |- style.css
   |- /images
     |- script.js
 |- /src
   |- script.ts
 |- /node_modules
 |- package.json
 |- package-lock.json
 |- tsconfig.json

2-1. tailwindcss 설치

npm install -D tailwindcss
npx tailwindcss init

npm을 이용해 tailwindcss를 설치해주고, npx tailwindcss init 명령어를 통해 tailwindcss.config.js파일을 생성하며 초기화합니다.

그리고 src경로에 input.css파일을 생성하고 다음과 같이 설정해줍니다. input.css파일에 필요한 스타일 속성을 작성할 수 있습니다.

/* src/input.css */

@tailwind base;
@tailwind components;
@tailwind utilities;

2-2. tailwind.config.js 파일 설정

생성된 tailwind config 파일에 아래와 같이 코드를 입력해줍니다. 파일의 content속성은 dist폴더의 skin.html을 템플릿파일로 설정한다는 의미입니다.

// tailwindcss.config.js

/** @type {import('tailwindcss').Config} */
module.exports = {
  content: ["./dist/skin.html"],
  theme: {
    extend: {},
  },
  plugins: [],
}

2-3. Tailwind CLI로 빌드하기

npx tailwindcss -i ./src/input.css -o ./dist/style.css --watch

또다른 터미널에서 위 명령어를 실행하면 dist경로에 style.css파일로 빌드됩니다. 명령어에서 --watch옵션을 주었기 때문에 input.css파일을 변경 후 저장할 때마다 자동으로 빌드합니다.

여기까지 설정을 마쳤다면 파일 구조는 다음과 같습니다.

tistory_skin
 |- /dists
   |- index.xml
   |- skin.html
   |- style.css
   |- /images
     |- script.js
 |- /src
   |- script.ts
   |- input.css
 |- /node_modules
 |- package.json
 |- package-lock.json
 |- tsconfig.json
 |- tailwind.config.js

3. Webpack으로 타입스크립트와 tailwindCSS 한번에 빌드하기

typescript와 tailwind를 빌드하기 위해서는 각각의 명령어를 입력해야합니다. 이렇게 하면 개발환경에서 터미널 두개를 띄워야하기 때문에 작업하는데 번거로움이 있습니다.

그래서 웹팩을 설치하여 한 명령어로 빌드과정을 통합하도록 해보겠습니다.

3-1. Webpack 설치

npm install webpack webpack-cli --save-dev

위 명령어로 webpack과 webpack-cli를 설치하면 웹팩을 프로젝트에서 사용할 수 있습니다.
그리고 webpack.config.js파일을 생성해서 아래와 같이 파일을 작성해 줍니다.

// webpack.config.js
const path = require('path');

module.exports = {
  entry: './src/script.ts',
  mode: 'production',
  output: {
    filename: 'script.js',
    path: path.resolve(__dirname, 'dist/images'),
  },
};

package.json파일을 다음과같이 설정하고, 터미널에서 npm run build 명령어를 실행하면 웹팩을 빌드할 수 있습니다.

// package.json
...
"scripts": {
  "build": "webpack",
},

npm run build

3-2. watch옵션으로 자동 빌드하기

파일을 저장할 때마다 자동으로 빌드하고싶다면 package.json에서 watch옵션을 설정해야합니다.

// package.json
...
"scripts": {
    "build": "webpack",
    "watch": "webpack --watch"
  },

npm run watch

터미널에서 명령어를 실행하면 파일이 저장될 때 마다 자동으로 웹팩이 빌드됩니다.

3-3. webpack.config.js 설정하기

여기까지 웹팩 설정을 마쳤다하더라도, 우리가 원하는 css파일과 js파일에 대한 config 파일 설정을 하지 않았기 때문에 빌드 과정에서 오류가 발생할 것입니다. 이제 관련 설정을 해보겠습니다.

ts-loader로 typescript 빌드하기

웹팩은 타입스크립트는 이해하지 못하기 때문에 관련 loader를 설치해줘야 합니다.

npm install -D ts-loader

ts-loader는 웹팩이 타입스크립트를 해석하도록 도와주는 역할을 합니다. 다음 코드처럼 webpack.config.js 파일을 구성하면 script.js 파일을 dist/images경로에 빌드합니다.

// webpack.config.js
const path = require('path');

module.exports = {
  entry: './src/script.ts',
  module: {
    rules: [
      {
        test: /\.ts?$/,
        use: 'ts-loader',
        exclude: /node_modules/,
      },
    ],
  },
  output: {
    filename: 'script.js',
    path: path.resolve(__dirname, 'dist/images'),
  },
};

여기까지 따라왔다면 script.ts 파일이 script.js로 잘 빌드된 것을 확인할 수 있습니다.
추가적으로, 파일 용량을 확인해보면 웹팩 적용 전보다 파일 크기가 2kb가량 파일 크기가 줄어든 것을 확인할 수 있습니다. 웹팩은 코드를 주석과 공백없이 한줄로 압축하며 빌드하기 때문입니다. 이는 빠른 웹페이지의 로딩에 도움을 줍니다.
webpack 적용 전 (4kb)
webpack 적용 후 (2kb)

MiniCssExtractPlugin으로 css 분리하기

티스토리 스킨은 style.css라는 파일을 따로 업로드 해줘야 하기 때문에 js파일에 같이 번들링을 하면 안되고, 따로 분리된 css파일이 필요합니다.

그렇기 때문에 css파일을 따로 분리해주는 MiniCssExtractPlugin을 적용해 봅시다. 보통 MiniCssExtractPlugin은 js 모듈의 개수가 많을 경우 css파일의 빠른 로드가 필요할 때 사용합니다.

// webpack.config.js
const path = require('path');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = {
  entry: './src/script.ts',
  mode: 'production',
  module: {
    rules: [
      {
        test: /\.ts?$/,
        use: 'ts-loader',
        exclude: /node_modules/,
      },
      {
        test: /\.css$/i,
        use: [MiniCssExtractPlugin.loader, "css-loader"],
      },
    ],
  },
  output: {
    filename: 'script.js',
    path: path.resolve(__dirname, 'dist/images'),
  },
  plugins: [new MiniCssExtractPlugin({filename : "../style2.css"})],
};
// srcipt.ts

import './input.css';

위와같이 script.ts 파일에 css를 import해주어야지 웹팩이 css 파일을 인식하고 플러그인에 따라 새 css 파일로 분리합니다. 위 코드로 설정을 해주고 빌드까지 끝났다면 아래와 같이 style2.css파일이 생성됩니다.

하지만 우리가 원하는 파일은 input.css파일 그 자체가 아니라, input.css에서 Tailwind CLI로 빌드된 파일입니다.

이를 위해 postCSS를 사용해보겠습니다. 참고로 style2로 파일명을 설정한 이유도 이때문입니다.ㅎㅎ

3-4. postCSS 설치 및 세팅

이 파트에서는 tailwindcss의 도큐멘트를 참고하여 구현했습니다. 도큐멘트에 따라 tailwindcss는 이미 설치하였으므로 postcss와 autoprefixer, postcss-loader를 설치하여줍니다.

npm install -D postcss autoprefixer
npm install -D postcss-loader

그리고 프로젝트에 postcss.config.js 파일을 추가하고, webpack.config.js 파일도 수정해줍니다.(postcss-loader를 추가해주고, 파일 이름을 style.css로 변경하였습니다.)

// postcss.config.js
module.exports = {
  plugins: {
    tailwindcss: {},
    autoprefixer: {},
  }
}
// webpack.config.js
const path = require('path');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = {
  entry: './src/script.ts',
  mode: 'production',
  module: {
    rules: [
      {
        test: /\.ts?$/,
        use: 'ts-loader',
        exclude: /node_modules/,
      },
      {
        test: /\.css$/i,
        use: [MiniCssExtractPlugin.loader, "css-loader", "postcss-loader"],
      },
    ],
  },
  output: {
    filename: 'script.js',
    path: path.resolve(__dirname, 'dist/images'),
  },
  plugins: [new MiniCssExtractPlugin({filename : "../style.css"})],
};

여기까지 마치고 npm run watch를 실행하면 잘 빌드되는것을 확인할 수 있으며, 파일 구조는 다음과 같습니다.

tistory_skin
 |- /dists
   |- index.xml
   |- skin.html
   |- style.css
   |- /images
     |- script.js
 |- /src
   |- script.ts
   |- input.css
 |- /node_modules
 |- package.json
 |- package-lock.json
 |- tsconfig.json
 |- tailwind.config.js
 |- webpack.config.js
 |- postcss.config.js

+) CssMinimizerPlugin으로 css파일 압축하기

앞서 js파일이 빌드될 때 파일이 한줄로 압축되는것을 알 수 있었습니다.
그렇다면 css파일도 압축하여 블로그의 로딩 속도를 단축시켜 볼 수 있습니다. 이를 위해 CssMinimizerPlugin을 적용해보겠습니다.

npm install css-minimizer-webpack-plugin --save-dev

// webpack.config.js
const path = require('path');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");

module.exports = {
  entry: './src/script.ts',
  mode: 'production',
  module: {
    rules: [
      {
        test: /\.ts?$/,
        use: 'ts-loader',
        exclude: /node_modules/,
      },
      {
        test: /\.css$/i,
        use: [MiniCssExtractPlugin.loader, "css-loader", "postcss-loader"],
      },
    ],
  },
  output: {
    filename: 'script.js',
    path: path.resolve(__dirname, 'dist/images'),
  },
  optimization: {
    minimizer: [
      new CssMinimizerPlugin(),
    ]
  },
  plugins: [new MiniCssExtractPlugin({filename : "../style.css"})],
};

여기까지 따라왔다면 style.css파일이 잘 압축된 것을 확인할 수 있습니다.

css 압축 전 (27kb)

css 압축 후 (18kb)

TroubleShooting 1 : script.js 압축 불가 현상

CssMinimizerPlugin로 css압축 시 script.js는 한줄로 압축이 되지 않는 현상이 발생합니다. 웹팩 config파일의 optimization.minimizer설정에 css만 포함되어있기 때문입니다.

이를 해결하기 위해 자바스크립트를 압축해주는 TerserPlugin을 적용해서 js파일도 설정에 추가해줘야 합니다.

npm install terser-webpack-plugin --save-dev

// webpack.config.js
const path = require('path');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
const TerserPlugin = require("terser-webpack-plugin");

module.exports = {
  entry: './src/script.ts',
  mode: 'production',
  module: {
    rules: [
      {
        test: /\.ts?$/,
        use: 'ts-loader',
        exclude: /node_modules/,
      },
      {
        test: /\.css$/i,
        use: [MiniCssExtractPlugin.loader, "css-loader", "postcss-loader"],
      },
    ],
  },
  output: {
    filename: 'script.js',
    path: path.resolve(__dirname, 'dist/images'),
  },
  optimization: {
    minimizer: [
      new CssMinimizerPlugin(),
      new TerserPlugin(),
    ]
  },
  plugins: [new MiniCssExtractPlugin({filename : "../style.css"})],
};

TroubleShooting 2 : 선언되었지만 읽히지 않은 함수

<!-- skin.html -->
<button onclick="{closeSidebar()}">

html에서 onclick으로 사용하도록 구현한 closeSidebar함수는 선언되었지만 읽히지 않은 함수는 웹팩 빌드 과정에서 삭제가 된다는 문제가 있습니다.

따라서 구현시에 html에서 onclick속성을 주지 말고, 자바스크립트에서 dom요소를 받아와 addEventListener로 선언해야합니다.

document.getElementById("writeBtn")!.addEventListener("click", onClickWriteBtn);

마치며

티스토리 스킨 개발을 위해 제가 했던 개발환경 세팅 과정을 글로 정리해보았습니다. 여기서는 티스토리 스킨 개발을 위한 설정을 했지만, 다른 프로젝트의 설정이나 개발에 도움이 되길 바랍니다.

profile
주니어 프론트엔드 개발자입니다.

0개의 댓글