node cli 로 @font-face generator 만들기 - 1

엄현태·2021년 12월 11일
0
post-thumbnail
post-custom-banner

개요

오랜만에 글을 쓰게 되었는데 요즘 일이 너무 바빠서 개인 프로젝트 할 시간이 없었다 (핑계...)

무튼 사실 개인프로젝트 뭐할지 생각도 안나고, 마땅히 끌리는게 없어서 안하게 되고 그러다보니 자연스럽게 글도 안쓰게 되는것 같았다.

그러던 중 폰트 작업을 할 일이 생겼다. 그러다가 폰트들을 추가하고 각 폰트마다 @font-face 를 추가해서 사용하는 방식이 너무 귀찮다고 생각이 들어서 이걸 한번에 만들어주는 빌더가 있으면 좋겠다라는 생각을 하게 되었다.

물론 다양한 오픈소스가 있고 쉽게 만들어주는 것도 있겠지만 한번 만들어 보자는 생각에 시작하게 되었다.

설계

일단 간단하게 node 로 만들 생각이였다.
node 로 recursive 하게 폰트 파일들을 읽어와서 각 폰트 파일에 이름을 바탕으로 @font-face 를 만들고 거기에 font-family, src 를 추가해주는 방식으로 생각을 하였다.

@font-face {
 font-family: '${FontName}';
 src: url('${FontUrl-ttf}'), url('${FontUrl-otf}'), url('${FontUrl-woff}');
}

뭐 대략 위와같은 느낌? 추가적인 폰트 설정 및 local url 설정들은 일단 다음에 생각하기로 하고 기본적인 틀만 다음과 같이 만들기로 하였다.

구현

기본적인 컨셉

구현 방식은 의외로 간단하였다. 예전에 node 를 통하여 fileSystem 접근을 한적이 있기 때문에 쉽게 검색을 통하여 할 수 있었고, 이 파일이 dir 인지 file 인지 구분 또한 fs 에서 제공해주고 있기 때문에 쉽게 recursive 하게 구현 할 수 있었다.

node js file system

그리고 파일이면 다음과 같이 폰트 파일인지에 따라서 한번 더 구분해주고폰트 이름과 각 폰트에 대한 url 로 Map 을 만들어 주었다. 대략 다음과 같은 느낌으로(?)

const FileFormat = ['.otf', '.ttf', '.woff', '.woff2'];

const fontObject = {
  RIDIBatang: [ './fonts/RIDIBatang/RIDIBatang.otf' ],
  'SpoqaHanSansNeo-Bold': [
    './fonts/SpoqaHanSansNeo/SpoqaHanSansNeo-Bold.ttf',
    './fonts/SpoqaHanSansNeo/SpoqaHanSansNeo-Bold.woff',
    './fonts/SpoqaHanSansNeo/SpoqaHanSansNeo-Bold.woff2'
  ],
  'SpoqaHanSansNeo-Light': [
    './fonts/SpoqaHanSansNeo/SpoqaHanSansNeo-Light.ttf',
    './fonts/SpoqaHanSansNeo/SpoqaHanSansNeo-Light.woff',
    './fonts/SpoqaHanSansNeo/SpoqaHanSansNeo-Light.woff2'
  ],
}

그런 다음 fontObject key 를 바탕으로 폰트 이름을 정의한 다음에 폰트 이름을 font-family 에 각 url 를 url 에 값으로 지정해 주어 다음과 같이 만들도록 하였다.

@font-face {
 font-family: 'RIDIBatang';
 src: url('./fonts/RIDIBatang/RIDIBatang.otf');
}

@font-face {
 font-family: 'SpoqaHanSansNeo';
 src: url('./fonts/SpoqaHanSansNeo/SpoqaHanSansNeo-Bold.ttf'),
      url('./fonts/SpoqaHanSansNeo/SpoqaHanSansNeo-Bold.woff'),
      url('./fonts/SpoqaHanSansNeo/SpoqaHanSansNeo-Bold.woff2')
}

@font-face {
 font-family: 'SpoqaHanSansNeo';
 src: url('./fonts/SpoqaHanSansNeo/SpoqaHanSansNeo-Light.ttf'),
      url('./fonts/SpoqaHanSansNeo/SpoqaHanSansNeo-Light.woff'),
      url('./fonts/SpoqaHanSansNeo/SpoqaHanSansNeo-Light.woff2')
}

그리고 다음파일을 특정 output css 파일에다가 write 해주면 된다. 생각보다 어렵지 않았고 그렇기 때문에 많은 기술이 들어가진 않았다.

CLI 를 통한 핸들링

기본적인 컨셉을 통하여 로직을 만들었으니 이 로직을 CLI 를 통하여 핸들링 해야겠다고 생각하였다. (매번 node index.js 를 할 수는 없으니...)

필자가 사용한 라이브러리는 tj/commander 이다.
간편하게 node cli 를 만들어주는 라이브러리다.

일단 받을 수 있는 옵션으로는 font dir, output dir 정도라고 생각하였고 추후에는 Bold, Medium, Regular, Light, Thin offset, font style 에 대한 추가적인 정보를 받을 수 있다는 생각이 들긴 한다.

저런 옵션들을 받을 수 있도록 하는것도 tj/commander 를 사용하면 아주 간단하게 구현 할 수 있다.

program
  .option('-d, --dir <dir>', 'Parsing dir')
  .option('-o, --output <dir>', 'Output dir')
  .action(() => {
    const options = program.opts();
    main(options);
  });

// eslint-disable-next-line no-undef
program.parse(process.argv);

이런식으로 하면 options 안에 객체가 다음과 같이 생성된다.

options = { dir: ${dirName}, output: ${output dirName} }
// 만약 정의하지 않으면 비어있게 된다.
{}

이를 바탕으로 파싱을 해야하는 directory 와 output file 이 생성될 directory 위치를 지정해 줄 수 있도록 하였고 만약 아무것도 입력하지 않은 경우에는 자체적으로 ./fonts dir 을 찾도록 해주고 output 역시 파싱을 해야하는 directory 내부에 생성되도록 하였다.

이를 통하여 이제 다음과 같은 일을 할 수 있게 되었다.

node index.js
node index.js -d ./public/fonts
node index.js -d ./public/fonts -o ./dist
node index.js -o ./dist

마지막으로 매번 node index.js 를 사용할 수 없기 때문에 특정 이름을 만들어 주어야하는데 필자는 gen-font-face 으로 만들어 주었다. 그럼 package.json 파일을 수정해주어햐는데 다음과 같다.

{
  "name": "gen-font-face", // name 추가
  "version": "1.0.1",
  "description": "Generate font-face CSS file from font files",
  "bin": {
    "gen-font-face": "index.js" 
  }, // 이부분을 추가해야지 npm 설치 후 cli 에서 gen-font-face index.js 파일이 실행됨
}

그리고 cli 로 실행되는 파일에 상단에 다음과 같이 추가 해줘야한다.
#!/usr/bin/env node 는 이 파일이 node 인터프리터로 실행해야한다는 사실을 알려준다.

#!/usr/bin/env node

const fs = require('fs');
const path = require('path');
const program = require('commander');

const FileFormat = ['.otf', '.ttf', '.woff', '.woff2'];

이제 테스트를 해봐야한다. 매번 npm 에 올려서 테스트를 해 볼 수 없으니 내 로컬에서만 설치 한 후 테스트 해보면 된다.
npm install -g 를 입력하면 내 로컬 npm global list 에 설치 된것을 볼 수 있다.
image

그럼 이제 node index.js 를 사용하지 않고 gen-font-face 로 사용할 수 있게 된다.

gen-font-face
gen-font-face -d ./public/fonts
gen-font-face -d ./public/fonts -o ./dist
gen-font-face -o ./dist

결론

demo-gif

위의 데모 gif 를 보면 fonts 폴더내에 있는 폰트 파일을 바탕으로 css 파일을 만들어 주는것을 볼 수 있다.
간단하지만 tj/commander 를 통하여 cli 를 만들어 볼 수 있었다.

이와 비슷하게 지난 작업에서는

gen-simple-reactapp

라고 해서 create-react-app 대신에 Webpack 만 가지고 간단하게 React 프로젝트를 세팅할 수 있는 cli 를 만들었었는데 간단하게 데모 테스트를 할때 실제로 유용하게 사용하고 있다. (많관부...)

다음 포스팅에서는 gen-font-face 를 npm 에 올리고 github action 으로 자동 배포까지하는 법을 포스팅 해보겠다.

확실히 일을 하다가 귀찮은 부분이 있으면 간단하게 스크립트를 사용해서 만들면 시간이 단축되는것 같고 이것을 누군가는 필요로 하지 않을까 라는 생각에 귀찮지만 오픈소스도 해보고 있는 중이다. 다른 사람들이 더 많이 참여해서 더 좋은 프로젝트가 되면 좋을것 같고 간단하지만 나중에 Rust 로도? 이러다가 더 고도화된 자바스크립트 에코시스템도 만들 수 있으면 좋겠다.

gen-font-face

profile
개발을 취미로 하는 개발자가 되고픔
post-custom-banner

0개의 댓글