June.

2024년 1분기 안에는 꼭...

Portfolio

About

ESLint 설정을 나만의 라이브러리로 만들어보자. (eslint config npm 배포, 모노레포)

2023/01/07
개발

12 min read

ESLint 설정을 나만의 라이브러리로 만들어보자. (eslint config npm 배포, 모노레포)

완성된 라이브러리 미리 보기

  • junghyoensu/configs

eslint, prettier는 우리의 코드를 조금 더 깔끔하고 오류가 없게끔 해 줘요. 프로젝트를 시작할 때마다 eslintprettier 설정하기가 귀찮지 않나요?

BEFORE

이렇게 긴 .eslintrc.js 파일을...

1module.exports = { 2 root: true, 3 parser: "@typescript-eslint/parser", 4 parserOptions: { 5 project: "./tsconfig.json", 6 tsconfigRootDir: __dirname, 7 }, 8 extends: ["prettier"], 9 plugins: [ 10 "@typescript-eslint/eslint-plugin", 11 "react", 12 "prettier", 13 "json-format", 14 "simple-import-sort", 15 ], 16 ignorePatterns: [ 17 ".eslintrc.js", 18 "public", 19 "node_modules", 20 ".cache", 21 ".vscode", 22 ], 23 rules: { 24 "no-unused-vars": "error", 25 "@typescript-eslint/consistent-type-imports": [ 26 "error", 27 { 28 prefer: "type-imports", 29 disallowTypeAnnotations: false, 30 }, 31 ], 32 "prettier/prettier": [ 33 "error", 34 { 35 singleQuote: false, 36 semi: true, 37 tabWidth: 2, 38 useTabs: false, 39 trailingComma: "all", 40 printWidth: 100, 41 arrowParens: "always", 42 }, 43 { 44 usePrettierrc: false, 45 }, 46 ], 47 "simple-import-sort/imports": "error", 48 "simple-import-sort/exports": "error", 49 }, 50};

AFTER

이런 식으로 줄일 수 있어요.

1// 여러분들의 이름으로 된 라이브러리를 만들어봐요. 2module.exports = { 3 plugins: ["@junghyeonsu"], 4 extends: ["plugin:@junghyeonsu/auto"], 5};

프로젝트 환경

라이브러리로 만들 저장소를 만들어봐요.

개발환경에 대해서 알려드릴게요.

해당 기술들이 뭔지를 설명하는 글은 아니지만 간략하게나마 설명을 해볼게요.

monorepo

여러 패키지를 하나의 레파지토리에서 관리할 수 있어요.

저는 해당 레파지토리를 config 를 모아둔 레파지토리로 관리하기로 했어요. 아직은 eslint plugin밖에 없지만 추후에 더 많은 설정들이 생길 것 같아서 모노레포로 진행하기로 했어요.

대부분의 환경이 JavaScript 환경 아니면 TypeScript를 쓸 것 같고, 배포 환경이 비슷해서 여러 겹치는 부분들이 많다고 생각했어요.

yarn workspace

yarn workspace는 하나의 레파지토리에서 여러 패키지를 관리할 수 있게 해주는 패키지 매니저예요.

프로젝트 루트 package.json 파일에 다음과 같이 명시하게 되면 yarn workspace를 사용할 수 있어요.

1{ 2 "name": "@junghyeonsu/configs", 3 "workspaces": [ 4 "./packages/eslint" 5 ], 6 "..." 7}

공식 문서에서 조금 더 자세하게 살펴볼 수 있어요.

yarn berry

yarn berry는 yarn의 두 번째 버전이에요.

pnp는 지원하지 않는 패키지들이 아직 많아서 사용하지 않았어요. nodeLinkerpnpdefault 옵션이라서 node_modules를 다시 사용하고 싶으면 .yarnrc.yml 파일에서 nodeLinker: node_modules를 명시해 줘요.

1# .yarnrc.yml 2yarnPath: .yarn/releases/yarn-3.3.0.cjs 3 4nodeLinker: node-modules

빌드 도구: nanobundle

nanobundle은 라이브러리 빌드를 도와주는 오픈소스예요. esbuild로 동작하고 있어요.

package.json 혹은 tsconfig.json에 적힌 정보들을 바탕으로 빌드를 알아서 해 줘요. 에러 메세지도 잘 명시되어 있어서 뭐가 잘못됐는지 바로 알 수 있어요.

설치하고, pakcage.json에 몇 가지 정보만 기입해 주고(main, exports map, ...etc), nanobundle build 명령어만 입력해주면 여러 환경(ejs, cjs)에서 작동할 수 있는 코드가 나와요.

스크립트 실행 도구: ultra-runner

ultra-runner는 모노레포에서 유용한 스크립트 실행기예요.

모노레포는 여러 개의 패키지로 이루어진 레파지토리라고 했죠? 현재 저는 eslint plugin 하나의 패키지밖에 없지만, 나중에 패키지가 4개, 5개 점점 늘어난다면 모든 패키지의 스크립트를 한꺼번에 실행시키고 싶은 욕구가 들 거예요. 그때 일일이 폴더를 찾아가서 yarn build 명령어를 일일이 칠 수는 없는 노릇이니까요.

ultra-runner는 해당 문제점을 해결해 줘요. 패키지가 여러 개 있어도 루트 폴더에서 단 한 번의 명령어만 입력하게 된다면 모든 패키지를 돌면서 해당 명령어가 있는지 확인하고, 전부 실행시켜 줘요. 또한 같은 명령어에 대해서 캐싱이 되어있다면, 패키지별로 판단해서 알아서 스킵해 줘요. 그리고 예쁜 콘솔창은 덤으로 가져갈 수 있어요.

첫 번째 빌드 실행했을 때
첫 번째 빌드 실행했을 때
두 번째 빌드 실행했을 때(캐싱적용)
두 번째 빌드 실행했을 때(캐싱적용)

버전 관리 도구: changesets

changesets은 버전 관리 도구예요.

1yarn add -D @changesets/cli 2npm install --dev @changesets/cli 3 4{/* 이후에 프로젝트 루트에서 아래 명령어로 환경 설정을 해 줘요. */} 5yarn changeset init 6npm changeset init

changesets 또한 모노레포에서 여러 패키지를 관리할 때 유용해요. 만약 우리의 패키지에 A, B, C 패키지가 있고 모두 변경 사항이 있어서 버전 업을 해야 하는 상황이에요. changesets를 사용하지 않으면 A, B, C 패키지를 일일이 버전을 올려주고 (package.json에 version 필드를 변경시켜주는 작업) 그리고 각 패키지 폴더에서 npm publish 명령어로 npm에 배포해주어야 해요.

changesets는 설치하고, 실행시키면 변경 사항이 있는 패키지를 판단해서 어떤 패키지들을 patch, minor, major로 버전 업 할 것인지 물어보고, 변경 사항 내용들을 입력받게 해요.

yarn changeset 명령어 입력 시
yarn changeset 명령어 입력 시

그리고 release 문서 쓰는 게 정말 귀찮은데 changeset을 사용한다면 자동으로 거저먹을 수 있어요.

release 문서를 챙겨줌
release 문서를 챙겨줌

프로젝트 세팅

그러면 정말 프로젝트를 한 번 만들어볼까요?

위에 소개된 오픈소스들을 활용해서 우리만의 eslint plugin을 만들 차례예요. 레파지토리 생성클론과 같은 작업은 생략할게요. 아, 저희는 yarn berry를 사용할 거기 때문에 yarn으로 프로젝트 세팅을 해주세요.

yarn berry로 설정

프로젝트에서 yarn set version berry을 입력하게 되면 yarn berry를 사용할 수 있어요.

1# .yarnrc.yml 2yarnPath: .yarn/releases/yarn-3.3.0.cjs 3 4nodeLinker: node-modules

제 프로젝트에선 pnp를 사용하지 않기로 했어요.

필요한 의존성 설치

1$ yarn add @changesets/cli ultra-runner

changeset 설치 후에는 yarn changeset init으로 필요한 설정 파일을 다운해요.

추가적으로 eslint, prettier를 설정하는 건 여러분의 몫이에요. 프로젝트를 조금 더 깔끔하게 유지하고 싶다면 설치해 주세요.

그리고 현재는 타입스크립트를 사용하지 않아요. 단순히 eslint의 config들을 내보내는 라이브러리라서 설치하지 않았어요. 다른 typescript가 필요한 라이브러리라면 설치와 설정해 주세요.

만약 pnp 환경에서 typescript, eslint 그리고 prettier를 사용하게 된다면 yarn dlx @yarnpkg/sdks vscode 명령어를 입력해 줘요.

패키지 개발

최종적인 폴더 구조는 아래와 같이 될 거예요.

1📂.changeset 2📂.yarn 3📂node_modules 4📂packages (yarn workspace로 관리되는 패키지들이에요) 5┗ 📂eslint 6┃ ┣ 📂lib (빌드 결과물이에요) 7┃ ┃ ┣ 📜index.cjs 8┃ ┃ ┣ 📜index.js 9┃ ┃ ┗ 📜index.mjs 10┃ ┣ 📂src (eslint 설정들이 모여있어요.) 11┃ ┃ ┣ 📜auto.js 12┃ ┃ ┣ 📜base.js 13┃ ┃ ┣ 📜react.js 14┃ ┃ ┗ 📜typescript.js 15┃ ┣ 📜.ultra.cache.json 16┃ ┣ 📜CHANGELOG.md 17┃ ┣ 📜README.md 18┃ ┣ 📜index.js 19┃ ┗ 📜package.json 20📜.yarnrc.yml 21📜.gitignore 22📜package.json 23📜README.md 24📜yarn.lock

monorepopackages에 여러 패키지 폴더를 만들고 거기에서 개발하는 형태예요. 그래서 현재는 packages 폴더 안에 eslint 패키지밖에 없어요. (추후에는 더 생길 수 있겠죠?) 그래서 지금은 우리들의 커스텀 eslint plugin 하나를 만들어보는 데 집중해 보죠.

우선 위에 나와 있는 폴더 구조처럼 packages/eslint 폴더를 만들어줘요. 그리고 루트 폴더에 존재하는 package.json 파일에 yarn workspace에 관한 내용들을 적어줘야 해요.

1{ 2 "name": "@junghyeonsu/configs", 3 "version": "0.0.0-thisisnotpublished", 4 "description": "junghyeonsu's configs", 5 "...": "추가적인 정보들", 6 "workspaces": ["./packages/eslint"] 7}

"workspaces": ["./packages/eslint"]로 해당 폴더를 yarn workspace로 관리하게 해달라고 명시해줘요.

저희 라이브러리의 핵심인 설정을 작성해 볼까요?

junghyeonsu는 제 이름이니까 여러분들의 이름을 넣어서 라이브러리를 만들어봐요.

packages/eslint 폴더로 넘어와서 코드를 작성할 거예요. 단순하게 생각해서 packages/eslint 폴더도 하나의 레파지토리라고 생각해 주세요.

그래서 이 폴더 안에도 기본적인 정보들(package.json과 같은 파일들)이 다 적혀있어야 해요. eslint 설정을 npm에 내보내는 것은 eslint 공식 문서에 기본적인 설명들은 다 나와있어요.

간략하게 설명하자면

1module.exports = { 2 rules: { 3 semi: ["error", "always"], 4 quotes: ["error", "double"], 5 "no-console": "off", 6 }, 7};

위와 같은 우리만의 rule을 설정해서 npm에 배포해 놔요. 그럼 사용하는 측에서는 아래와 같이 사용할 수 있어요.

1module.exports = { 2 "plugins": [ 3 "my-custom-plugin" 4 ], 5};

또한 다른 플러그인들을 조합해서 하나의 플러그인으로 내보내고 싶다면 아래와 같이 하면 돼요.

1module.exports = { 2 "extends": ["extends1", "extends2", "extends3"] 3 "plugins": ["plugin1", "plugin2", "plugin3"], 4 "rules": { 5 "semi": ["error", "always"], 6 "quotes": ["error", "double"], 7 "no-console": "off" 8 } 9};

이렇게 하면 자신만의 플러그인을 만들 수 있어요.

저는 파일을 base(기본적인 js 플러그인들과 룰), react(리액트 관련 플러그인들과 룰), typescript(타입스크립트 관련 플러그인과 룰) 로 파일을 나눴고 최종적으로 auto.js 파일에서 따로 작성된 config 파일들을 어떤 확장자는 base를 적용하고, ts, tsx는 typescript config를 적용 그리고 마지막으로 jsx, tsx와 같은 확장자는 react config를 적용하도록 해놨어요.

그리고 저는 아래와 같은 패키지들을 설치했고 내보낼 거예요. dependencies에 설치해야 저희가 만든 라이브러리를 설치하면서 같이 의존성이 설치될 거예요.

전체적인 코드는 요기서 확인해주세요.

1{ 2 "...": "", 3 "dependencies": { 4 "@typescript-eslint/eslint-plugin": "^5.45.0", 5 "@typescript-eslint/parser": "^5.45.0", 6 "eslint": "^8.29.0", 7 "eslint-config-prettier": "^8.5.0", 8 "eslint-plugin-import": "^2.26.0", 9 "eslint-plugin-json-format": "^2.0.1", 10 "eslint-plugin-jsx-a11y": "^6.6.1", 11 "eslint-plugin-prettier": "^4.2.1", 12 "eslint-plugin-react": "^7.31.11", 13 "eslint-plugin-react-hooks": "^4.6.0", 14 "eslint-plugin-simple-import-sort": "^8.0.0", 15 "prettier": "^2.8.0" 16 }, 17 "...": "", 18}

그리고 위에서 말했듯 저는 base, react, typescript로 config들을 분리시켰어요. 해당 코드들은 아래를 참조해 주세요. 단순히 eslintrc.js 파일과 비슷한 구성이고, 제가 원하는 설정을 해놨어요. 여러분은 여러분들이 원하는 rule, plugin들을 모아서 여러분만의 custom config를 만들어보세요.

그리고 최종적으로는 각각의 config들을 적용시켜 줄 auto 파일을 만들었어요. 그리고 각각의 파일들에 진입할 수 있는 최초 진입점 index 파일을 만들어주면 eslint custom config 코드 작성은 끝이에요.

아래는 그렇게 완성된 @junghyeonsu/eslint-plugin 패키지 구조

1📦eslint 2┣ 📂src 3┃ ┣ 📜auto.js 4┃ ┣ 📜base.js 5┃ ┣ 📜react.js 6┃ ┗ 📜typescript.js 7┣ 📜README.md 8┣ 📜index.js 9┗ 📜package.json

코드 작성이 끝났으니 빌드를 해봐요.

코드 작성은 다 되었지만 다양한 환경에서 저희 커스텀 config를 사용할 수 있도록 빌드해볼게요. 저희는 nanobundle을 사용할 건데 package.json에 꼭 적어줘야 해당 정보들을 가지고 nanobundle이 빌드를 해 줘요.

1{ 2 "name": "@junghyeonsu/eslint-plugin", 3 "version": "0.0.0", 4 "description": "junghyeonsu eslint custom plugin and config", 5 "exports": { 6 ".": { 7 "source": "./lib/index.js", 8 "require": "./lib/index.cjs", 9 "import": "./lib/index.mjs" 10 }, 11 "./package.json": "./package.json" 12 }, 13 "main": "./lib/index.js", 14 "files": ["index.js", "src", "lib"], 15 "scripts": { 16 "build": "nanobundle build --root-dir=./", 17 "prepublishOnly": "npm run build" 18 }, 19 "...": "..." 20}

위 코드에서 exports field를 설명하자면, "." 경로에는 "./lib/index.js" 파일을, 그때 require 문법을 사용하는 commonjs 환경에선 "./lib/index.cjs"을 import 문법을 사용하는 esm 환경에서는 "./lib/index.mjs"을 불러와서 사용할 수 있게끔 명시해주는 필드에요.

main 필드는 저희 라이브러리의 최초 진입점을 명시해주면 돼요.

files 필드는 저희 라이브러리에 포함될 파일이나 폴더를 명시해 줘요.

그리고 마지막으로 script를 작성해 줘요. --root-dir 옵션을 "./"으로 줘야 우리 프로젝트의 index.js 파일을 읽어서 빌드해줄거에요. 그리고 이제 packages/eslint 폴더에서 build 명령어를 수행해도 되지만, 모노레포를 사용하고 있으니 추후에 추가될 패키지들을 대비해서 ultra-runner를 통해서 빌드를 해볼게요.

그전에 저희 모노레포 루트의 package.json에 명시해줘야 할 게 있어요.

1{ 2 "name": "@junghyeonsu/configs", 3 "version": "0.0.0-thisisnotpublished", 4 "workspaces": [ 5 "./packages/eslint" 6 ], 7 "scripts": { 8 "build": "ultra -r build", 9 "release": "yarn changeset publish", 10 "version": "changeset version && yarn install --no-immutable" 11 }, 12 "devDependencies": { 13 "@changesets/cli": "^2.25.2", 14 "eslint": "^8.29.0", 15 "prettier": "^2.8.0", 16 "ultra-runner": "^3.10.5" 17 }, 18 "ultra": { 19 "concurrent": [ 20 "build" 21 ] 22 } 23}

ultra -r build 명령어는 우리 패키지들을 recursive(순회적으로) 돌면서 package.json 파일들을 확인하고 scripts 필드에 build 명령어가 있다면 해당 명령어를 실행한다는 의미에요.

만약 루트 폴더에서 yarn build를 입력한다면 packages/eslint의 package.json 파일을 확인하고, build 명령어가 있는 것을 보고는 해당 명령어를 수행하겠죠?

그리고 아래 적힌 "ultra" 필드는 "build" 명령어에 한해서는 명령어를 동시에 수행하겠다는 의미예요. 여러 패키지를 동시에 build해도 병렬적으로 수행하기 때문에 속도가 굉장히 빨라요.

이렇게 해놓고 yarn build 명령어를 모노레포 루트 폴더에서 수행하면 빌드가 진행되고, packages/eslint 패키지에는 lib 폴더 안에 우리의 빌드 결과물들이 들어있을 거예요.

1📦eslint 2┣ 📂lib 3┃ ┣ 📜index.cjs 4┃ ┣ 📜index.js 5┃ ┗ 📜index.mjs 6┣ 📂src 7┃ ┣ 📜auto.js 8┃ ┣ 📜base.js 9┃ ┣ 📜react.js 10┃ ┗ 📜typescript.js 11┣ 📜.ultra.cache.json 12┣ 📜CHANGELOG.md 13┣ 📜README.md 14┣ 📜index.js 15┗ 📜package.json

다른 사람들이 쓸 수 있게 NPM에 배포해 봐요.

이제 빌드 결과물을 NPM에 배포해서 사람들이 설치할 수 있게 해야 해요. 그전에 준비물들이 있어요.

준비사항

  • NPM 회원 가입하기
  • 회원가입이 되어있다면 로컬에서 npm login 하기 (콘솔 창에 npm login 명령어 입력 후 아이디와 비번을 입력하고 로그인해놔요.)

그리고 changeset을 활용한 자동배포를 이루기 위해서는 아래와 같은 설정들이 필요해요.

  • NPM Token을 발급받아요. 자세한 방법은 요기를 참고해 주세요.

토큰을 발급받는 이유는 github action을 통해서 자동 배포를 할 텐데, 그때 github action ci 환경에서 npm에 배포할 때 배포자에 대한 정보가 없기 때문에 토큰을 통해서 정보를 확인하고 배포를 하는 거예요.

발급받은 토큰 등록하기
발급받은 토큰 등록하기

발급받은 토큰은 우리가 만든 레파지토리 깃허브에서 setting 탭에서 왼쪽 사이드바에서 Secrets의 탭에서 Actions에서 등록할 수 있어요. New repository secret 버튼을 클릭해서 NPM에서 발급받은 토큰을 NPM_PUBLISH_TOKEN이름으로 넣어주세요.

NPM 배포

위에 changeset 설명에도 적혀있듯, 모노레포 루트 폴더에서 yarn changeset을 입력하게 되면 아래와 같은 이미지 처럼될 거예요.

yarn changeset 명령어 입력 시
yarn changeset 명령어 입력 시

그럼 당황하지 않고 글을 차근차근 읽으면서 수행하면 돼요. 위아래 방향키로 움직일 수 있고, 스페이스바로 선택할 수 있으며 엔터로 다음으로 넘어갈 수 있어요.

바뀐 패키지들을 읽어서(지금은 하나일 거예요) patch(0.0.1 up), minor(0.1.0 up), major(1.0.0 up)를 선택하고 변경 사항들을 적어주고 엔터를 입력하면 마크다운 파일 하나가 생성될 거예요. 그 파일을 main에 푸시하게 되면 읽어서 changeset에서 알아서 처리해줄 거예요.

메인에 푸시하기 전에 github action을 이용한 자동 배포 코드를 작성해봐요. 프로젝트 루트 폴더에서 .github 폴더를 만들고 그 안에 workflows 폴더를 만들고 그 안에 yml 확장자로 된 자동 배포 코드를 작성할 수 있어요. 제가 작성한 코드를 기준으로 설명드릴게요.

github action에 대한 자세한 설명은 생략하고, 큼지막한 흐름을 기준으로 설명해 드릴게요.

1name: Release Packages 2 3on: 4 push: 5 branches: 6 - main 7 8jobs: 9 release: 10 name: Release Packages 11 runs-on: ubuntu-latest 12 permissions: 13 contents: write 14 pull-requests: write 15 16 steps: 17 - name: Checkout Repo 18 uses: actions/checkout@v3 19 with: 20 # This makes Actions fetch all Git history so that Changesets can generate changelogs with the correct commits 21 fetch-depth: 0 22 23 - name: Setup Node.js 18.x 24 uses: actions/setup-node@v3 25 with: 26 node-version: 18.x 27 28 - name: Use cached node_modules 29 uses: actions/cache@v3 30 with: 31 path: node_modules 32 key: nodeModules-${{ hashFiles('**/yarn.lock') }} 33 restore-keys: | 34 nodeModules- 35 - name: Install Dependencies 36 run: yarn install --immutable 37 38 - name: Build 39 run: yarn build 40 41 - name: 릴리즈 Pull Request를 만들거나 패키지를 배포해요 42 id: changesets 43 uses: changesets/action@v1 44 with: 45 publish: yarn release 46 version: yarn version 47 env: 48 GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 49 NPM_TOKEN: ${{ secrets.NPM_PUBLISH_TOKEN }}

해당 자동 배포의 이름은 Release Packages로 깃허브 레파지토리에 action 탭에서 확인할 수 있어요.

action 탭에서 Release Packages이름으로 job이 생성돼요.
action 탭에서 Release Packages이름으로 job이 생성돼요.

해당 워크플로우의 큰 틀은 다음과 같아요. (노란색 선 기준으로 살펴봐주세요.)

  1. main 브랜치에 push 이벤트가 발생했을 때 실행되는 job이에요.
  2. 우리의 레파지토리를 Checkout해요. 해당 동작은 우리 레포의 히스토리를 읽어서 changeset이 changelog와 알맞은 커밋을 할 수 있게 해줘요.
  3. github action 환경을 node 18 버전으로 맞춰요.
  4. node_modules가 github action 환경에서 캐싱 되어 있으면 그걸 사용해요.
  5. yarn install 명령어로 의존성을 설치해요.
  6. yarn build로 build를 실행해요. (ultra-runner가 실행되겠죠?)
  7. 마지막으로 yarn release 명령어와 yarn version으로 changeset을 이용해서 패키지를 배포하고, 풀리퀘스트를 생성해요.

yarn release, yarn version 명령어는 다음과 같아요. 모노레포 루트 package.json에 작성해 주세요.

1{ 2 "scripts": { 3 "build": "ultra -r build", 4 "release": "yarn changeset publish", 5 "version": "changeset version && yarn install --no-immutable" 6 } 7}

요렇게까지 하면 정말 배포 준비 완료에요. 해당 자동 배포 코드를 메인에 푸시해 놓고, yarn changeset으로 만들어진 마크다운 파일을 다시 메인에 푸시해 주면 우리가 만들어놓은 github action이 돌면서 자동으로 명령을 수행해줄 거예요.

그렇게 job이 성공적으로 수행됐다면 아마 레파지토리에 풀리퀘스트가 Version Packages 이름으로 자동 생성 됐을 거예요. 그럼, 그 풀리퀘스트를 메인에 머지시켜주면 해당 내용들로 npm에 자동 배포될 거예요.

이제 이렇게 되면 라이브러리 개발 플로우가 완성됐어요. 우린 앞으로 라이브러리 수정사항이 있다면 개발을 뚝딱뚝딱 열심히 하고, 개발이 끝났으면 프로젝트 루트에서 yarn changeset 명령어로 변경 사항에 대해서 버전들을 올려주고, 만들어진 마크다운 파일과 함께 코드를 메인에 푸시해 주면 풀리퀘스트를 만들어주고(협업할 때 변경 사항들을 같이 확인하기 위함이에요.), 해당 풀리퀘스트를 머지해주면 정식으로 버전업이 되면서 npm에 배포가 되는 플로우에요.

이렇게 라이브러리 개발 한 사이클을 한 번 쭉 돌아봤어요. 생각보다 별것 없죠? 그럼, 우리가 만든 eslint plugin을 설치해서 한 번 사용해 볼까요?

사용해 보기

아무 프로젝트를 생성하고, yarn add -D 자신의-라이브러리 eslint로 설치해서 사용해 봐요.

저는 yarn add @junghyeonsu/eslint-plugin eslint prettier으로 설치했어요. 제 플러그인에는 prettier 룰들도 들어가 있어서 같이 설치해 주었어요. 임시 vite 프로젝트를 만들어서 테스트해 봤어요.

1{ 2 "name": "my-vite-app", 3 "private": true, 4 "version": "0.0.0", 5 "type": "module", 6 "scripts": { 7 "dev": "vite", 8 "build": "tsc && vite build", 9 "preview": "vite preview" 10 }, 11 "dependencies": { 12 "react": "^18.2.0", 13 "react-dom": "^18.2.0" 14 }, 15 "devDependencies": { 16 "@junghyeonsu/eslint-plugin": "^1.0.1", 17 "@types/react": "^18.0.26", 18 "@types/react-dom": "^18.0.9", 19 "@vitejs/plugin-react": "^3.0.0", 20 "eslint": "^8.31.0", 21 "prettier": "^2.8.1", 22 "typescript": "^4.9.3", 23 "vite": "^4.0.0" 24 } 25}

그리고 vite는 package.json에 type 필드가 module로 되어있어서 .eslintrc.cjs로 eslintrc 파일을 생성해서 설정했어요.

1module.exports = { 2 root: true, 3 plugins: ["@junghyeonsu"], 4 extends: ["plugin:@junghyeonsu/auto"], 5 rules: { 6 // ... 7 }, 8};

"왜 위와 같이 이름들을 명시하나요?"에 답은 공식 문서를 참고해주세요.

이렇게까지 하고 나면 vite template에서 자동 생성된 App.tsx에서 오류들을 뱉어낼 거예요.

불-편
불-편
편-안
편-안

제가 설정한 config대로 잘 적용이 된 것 같네요!

완성도 높이기

사실 라이브러리를 만들어놔도 문서가 잘 작성되어 있지 않으면 오픈소스가 아니라 단순 자기만 쓰기 위한 코드가 되어버려요. 새로 찾아온 손님은 우리가 적어놓은 코드에 대한 맥락이 하나도 없으니까요.

많은 사람이 사용하기 위해서는 package.json에 더 명시해줄 필드들도 많고, 혹은 리드미를 기막히게 써서 공개해놔야 해요. 이 라이브러리가 나온 이유, 설치 방법, 그리고 CONTRIBUTING.md 파일 같은 것도 만들어서 기여할 수 있는 환경도 만들어요.

마무리

오늘 이런 식으로 간단하게 eslint config 라이브러리를 만들었어요. 설정 파일뿐만 아니라 다양한 코드들을 오픈소스로 열어놓을 수 있어요. 컴포넌트가 될 수도 있고, 어떤 유틸 함수가 될 수도 있겠죠.

다들 이번 기회에 오픈소스를 만들어서 오픈소스 생태계를 멋지게 만들어봐요.

관련 포스트가 4개 있어요.

ESM, CJS, TS를 모두 지원하는 라이브러리를 만들어보고, CLI를 간단하게 만들어보겠습니다.

개발
npm
deploy-simple-npm-library cover image
2024/03/19 (updated)
NEW POST

간단한 NPM 라이브러리 배포해보기 2탄 (CLI 간단한 라이브러리 만들기 & 모든 환경 지원, ESM, CJS, TS)

Figma Plugin을 이용하여 에셋을 전시하는 방법에 대해 알아봅니다.

개발
에셋타운
asset-town-figma-plugin cover image
2024/03/17
NEW POST

에셋 관리 시스템을 만들어보자 (에셋타운 4편 - Figma Plugin을 이용한 에셋 전시)

에셋타운에서 Cloudflare Workers와 R2를 이용하여 웹훅을 처리하고 CDN 캐싱을 제공하는 방법에 대해 설명합니다.

개발
에셋타운
asset-town-provide-cdn-using-webhook-and-cloudflare cover image
2024/03/01

에셋 관리 시스템을 만들어보자 (에셋타운 3편 - Cloudflare Workers, R2를 이용한 웹훅 처리와 CDN 캐싱)

에셋타운의 어드민 페이지 Sanity를 이용해서 만들어보기

개발
에셋타운
asset-town-admin-with-sanity cover image
2024/02/17

에셋 관리 시스템을 만들어보자 (에셋타운 2편 - 어드민 페이지 with Sanity)

profile

정현수.

Currently Managed

Currently not managed

© 2024. junghyeonsu all rights reserved.