ν˜„μž¬ νšŒμ‚¬μ—μ„œ μƒˆν•΄ λͺ©ν‘œλŠ” λΉ λ₯Έ 업무 처리λ₯Ό μœ„ν•΄μ„œ κ°„λ‹¨ν•œ 방식을 취함에 λ”°λΌμ„œ 지속적인 μ„±μž₯을 μ΄λ£¨μ–΄λƒˆμœΌλ‚˜ μ œν’ˆμ— λŒ€ν•œ μ‹ λ’°μ„±μ˜ 문제λ₯Ό κ²½ν—˜ν•˜κ³ λ‚˜μ„œλŠ” μ œν’ˆ ν’ˆμ§ˆμ„ κ°•ν™”ν•˜κΈ° μœ„ν•œ μ½”λ“œ ν’ˆμ§ˆ λ˜λŠ” ν…ŒμŠ€νŠΈ μžλ™ν™”μ— λŒ€ν•œ ν™˜κ²½ κ΅¬μΆ•μ˜ ν•„μš”μ„±μ„ 느끼고 λ§Žμ€ 것듀을 μ‹œλ„ν•˜κ³  μžˆλ‹€. κΉƒν—ˆλΈŒ ν’€ λ¦¬ν€˜μŠ€νŠΈλ₯Ό μˆ˜ν–‰ν•˜κ³  μžˆμ—ˆμœΌλ‚˜ μ½”λ“œ 리뷰가 μ£Όμš” ν…Œν¬ κΈ°μ—…μ΄λ‚˜ μŠ€νƒ€νŠΈμ—…μ²˜λŸΌ 개발 λ¬Έν™”λ‘œ μ •μ°©λ˜μ–΄μžˆμ§€ μ•ŠμŒμœΌλ‘œ μΈν•΄μ„œ λ‹¨μœ„ ν…ŒμŠ€νŠΈ μ½”λ“œλ₯Ό μž‘μ„±ν•˜λ„λ‘ μš”κ΅¬ν•œλ‹€κ±°λ‚˜ 정적 뢄석 도ꡬλ₯Ό 톡해 μ½”λ“œ ν’ˆμ§ˆμ— λŒ€ν•΄μ„œ λΆ„μ„ν•˜κ³  λ¦¬νŒ©ν† λ§μ„ μˆ˜ν–‰ν•˜λŠ” 과정이 μ—†λ‹€λ³΄λ‹ˆ κ°œλ°œμžλ“€μ΄ 슀슀둜 νŽΈν•œ 방식을 μ‚¬μš©ν•΄μ„œ μž‘μ—… μš”κ±΄μ— λŒ€ν•΄μ„œ μ²˜λ¦¬ν•΄μ™”λ‹€.

νŽ˜μ–΄ ν”„λ‘œκ·Έλž˜λ°μ„ μ„ ν˜Έν•˜λŠ” μ‹œλ‹ˆμ–΄ κ°œλ°œμžλ„ κΉƒν—ˆλΈŒ μ½”λ“œλ¦¬λ·°μ— λŒ€ν•΄μ„œλŠ” μŠ΅κ΄€ν™” λ˜μ–΄μžˆμ§€ μ•Šμ•˜κΈ°μ— 비둝 브랜치 보호 κΈ°λŠ₯을 톡해 리뷰어 μŠΉμΈμ„ 받도둝 κ°•μ œν•˜λ”λΌλ„ μƒμ„Έν•˜κ²Œ μ½”λ“œ 변경사항을 κ²€ν† ν•˜μ§€ μ•Šκ³  승인만 ν•΄λ²„λ¦¬λŠ” 상황이 λ°œμƒν–ˆμ—ˆλ‹€. κ·ΈλŸΌμ—λ„ 브랜치 보호 κΈ°λŠ₯으둜 λΆˆνŽΈν•¨μ„ κ°•μ œν•¨μœΌλ‘œμ¨ μž‘μ—…μ— λŒ€ν•΄ 브랜치λ₯Ό λ§Œλ“€μ–΄μ„œ μž‘μ—…ν•˜κ³  ν’€ λ¦¬ν€˜μŠ€νŠΈλ₯Ό μš”μ²­ν•˜λŠ” 방법에 λŒ€ν•΄μ„œλŠ” λͺ¨λ“  κ°œλ°œμžλ“€μ΄ μ΅μˆ™ν•΄μ‘Œλ‹€κ³  생각이 λ“ λ‹€. μ•„λ¬΄νŠΌ κΉƒν—ˆλΈŒ ν’€ λ¦¬ν€˜μŠ€νŠΈλ₯Ό ν™œμš©ν•¨μ—λ„ μ œλŒ€λ‘œ 된 μ½”λ“œ 리뷰 λ¬Έν™”κ°€ 이루어지지 μ•ŠκΈ° λ•Œλ¬Έμ— μ΅œμ†Œν•œ μ½”λ“œ ν’ˆμ§ˆμ— λŒ€ν•΄μ„œ κ°œλ°œμžλ“€μ΄ 인지할 수 μžˆλ„λ‘ κΉƒν—ˆλΈŒ ν’€ λ¦¬ν€˜μŠ€νŠΈ μ‹œ μƒνƒœ 검사λ₯Ό 톡해 리뷰 이외에도 μƒνƒœ 검사가 ν†΅κ³Όλ˜μ–΄μ•Όλ§Œ μ›ν•˜λŠ” λΈŒλžœμΉ˜μ— 머지할 수 μžˆλ„λ‘ κ°•μ œν•˜κ³ μž ν•œλ‹€.

ν’€ λ¦¬ν€˜μŠ€νŠΈμ— λŒ€ν•΄ μ œλŒ€λ‘œ λ¦¬λ·°ν•΄μ•Όν•œλ‹€κ³  λ§ν–ˆμœΌλ‚˜ λ‹Ήμž₯ 업무λ₯Ό μ²˜λ¦¬ν•˜λŠ”λ° λΆˆνŽΈν•¨μ΄ μžˆμœΌλ―€λ‘œ 받아듀여지지 μ•Šμ•˜λ‹€.

λ°λΈŒμ˜΅μŠ€μ— 이어 GitOpsκ°€ λ– μ˜€λ₯΄λ˜ μ‹œκΈ°μ— ν™•μΈν–ˆλ˜ 것은 ν’€ λ¦¬ν€˜μŠ€νŠΈμ— λŒ€ν•΄ μƒνƒœ 체크λ₯Ό μˆ˜ν–‰ν•  수 μžˆλ„λ‘ μ„€μ •ν•  수 μžˆλ‹€λŠ” κ²ƒμ΄μ—ˆλ‹€. μ‹€μ œλ‘œ λ‹€μŒκ³Ό 같이 λŒ€λΆ€λΆ„μ˜ μ˜€ν”ˆμ†ŒμŠ€μ—μ„œλŠ” ν’€ λ¦¬ν€˜μŠ€νŠΈλ‘œ λ³€κ²½λ˜λŠ” 뢀뢄에 λŒ€ν•΄μ„œ μƒνƒœ 체크λ₯Ό μˆ˜ν–‰ν•˜λ„λ‘ κΉƒν—ˆλΈŒ μ•‘μ…˜μ„ 톡해 μ›Œν¬ν”Œλ‘œμš°λ₯Ό ꡬ성해놓은 것을 확인할 수 μžˆλ‹€.

ν’€ λ¦¬ν€˜μŠ€νŠΈ μ‹œ μ½”λ“œ μƒνƒœ 검사λ₯Ό μˆ˜ν–‰ν•˜λŠ” 것에 λŒ€ν•œ 이점은 무엇이 μžˆμ„κΉŒ? ν˜„μž¬ 쑰직의 κΈ°μ€€μ—μ„œλŠ” μ œλŒ€λ‘œ 된 μ½”λ“œ 리뷰 λ¬Έν™”κ°€ κ°–μΆ”μ–΄μ Έ μžˆμ§€ μ•ŠκΈ° λ•Œλ¬Έμ— 기본적인 μ½”λ“œ ν’ˆμ§ˆμ— λŒ€ν•΄μ„œλŠ” Checkstyle λ˜λŠ” ESLintλ₯Ό μˆ˜ν–‰ν•˜μ—¬ 정적 뢄석을 μˆ˜ν–‰ν•˜κ³  μžλ™μœΌλ‘œ μ»¨λ²€μ…˜μ„ λ§žμΆ”λ„λ‘ κ°•μ œν•  수 μžˆλ‹€λŠ” 것에 μžˆλ‹€. μžμ‹ λ§Œμ˜ μ½”λ”© μ»¨λ²€μ…˜μ΄ 갖좔어지지 μ•Šμ€ μ‹ μž… κ°œλ°œμžλ“€μ—κ²ŒλŠ” μ‹œλ‹ˆμ–΄ κ°œλ°œμžλ“€μ΄ λ¦¬λ·°ν•˜μ§€ μ•Šλ”λΌλ„ μ»¨λ²€μ…˜μ— λŒ€ν•œ μ€‘μš”μ„±μ„ μΈμ§€μ‹œν‚€κ³  κ°€μ΄λ“œν•  수 있기 λ•Œλ¬Έμ΄λ‹€.

κΉƒν—ˆλΈŒ μ•‘μ…˜

ν’€ λ¦¬ν€˜μŠ€νŠΈ μ‹œ μƒνƒœ 검사λ₯Ό μˆ˜ν–‰ν•  수 μžˆλ„λ‘ κΉƒν—ˆλΈŒ μ•‘μ…˜μ„ 톡해 μ›Œν¬ν”Œλ‘œμš°λ₯Ό μž‘μ„±ν•  수 μžˆλ‹€. λ§Žμ€ κ°œλ°œμžλ“€μ΄ κ³΅μœ ν•˜μ—¬ μ‚¬μš©ν•˜λŠ” μ•‘μ…˜λ“€ μ€‘μ—μ„œ μƒνƒœ 검사λ₯Ό μœ„ν•΄ reviewdogλ₯Ό 기반으둜 μˆ˜ν–‰ν•˜λŠ” μ•„λž˜μ˜ 두가지 μ›Œν¬ν”Œλ‘œμš°λ₯Ό μ μš©ν•΄λ³΄κΈ°λ‘œ ν•˜μ˜€λ‹€. 쑰직 λ‚΄μ—μ„œ κ²°μ •ν•œ μžλ°” μ½”λ”© μ»¨λ²€μ…˜μ΄ 없어도 기본적인 ꡬ글 μžλ°” μŠ€νƒ€μΌμ„ ν†΅ν•΄μ„œ μƒνƒœ 검사λ₯Ό μˆ˜ν–‰ν•  수 있으며 ν”„λ‘ νŠΈμ—”λ“œ μ½”λ“œμ— λŒ€ν•΄μ„œλ„ ESLintλ₯Ό μˆ˜ν–‰ν•˜λ„λ‘ λ˜μ–΄μžˆμœΌλ―€λ‘œ μœ„ 두가지 μ›Œν¬ν”Œλ‘œμš°λ§Œ μˆ˜ν–‰ν•˜λ”λΌλ„ μΆ©λΆ„νžˆ μ½”λ“œ ν’ˆμ§ˆμ„ ν–₯μƒμ‹œν‚€κ³  μœ μ§€ν•  수 μžˆμ„ 것이라 μƒκ°λœλ‹€.

κΉƒν—ˆλΈŒ μ•‘μ…˜ μ›Œν¬ν”Œλ‘œμš° 파일 : .github/workflows/pr-checks.xml

name: PR Checks

on:
  workflow_dispatch:
  pull_request:
    branches:
      - main
    paths:
      - '**.java'
      - '**.js'
      - '**.vue'
jobs:
  checks:
    name: Checks
    runs-on: ubuntu-latest # ubuntu-22.04

    strategy:
      matrix:
        java: [11]
        node: [12]

    steps:
      - uses: dorny/paths-filter@v2
        id: changes
        with:
          filters: |
            java:
              - '**.java'
            vuejs:
              - '**.vue'
              - '**.js'
      - uses: actions/checkout@v2

      ###########################################
      ## Java Checkstyle
      ###########################################
      - if: steps.changes.outputs.java == 'true'
        name: Set up JDK ${{ matrix.Java }}
        uses: actions/setup-java@v3
        with:
          distribution: corretto
          java-version: ${{ matrix.java }}
          cache: 'gradle'
      - if: steps.changes.outputs.java == 'true'
        name: Run checkstyle
        uses: nikitasavinov/checkstyle-action@master
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}
          reporter: github-pr-check
          tool_name: 'checkstyle'
          checkstyle_version: 10.3
          checkstyle_config: checkstyle.xml

      ###########################################
      ## Node ESLint
      ###########################################
      - if: steps.changes.outputs.vuejs == 'true'
        name: Setup Node.js ${{ matrix.node }}
        uses: actions/setup-node@v2
        with:
          node-version: ${{ matrix.node }}
          cache: 'npm'
          cache-dependency-path: npm-shrinkwrap.json
      - if: steps.changes.outputs.vuejs == 'true'
        name: Cache Dependencies
        id: npm-cache
        uses: actions/cache@v3
        with:
          path: '**/node_modules'
          key: ${{ runner.os }}-node-${{ hashFiles('**/npm-shrinkwrap.json') }}
          restore-keys: |
            ${{ runner.os }}-node-
      - if: steps.changes.outputs.vuejs == 'true' && steps.npm-cache.outputs.cache-hit != 'true'
        name: Install Dependencies
        run: npm ci
      - if: steps.changes.outputs.vuejs == 'true'
        name: Run eslint
        uses: reviewdog/action-eslint@v1
        with:
          reporter: github-pr-check
          eslint_flags: '--ext .js,.vue ./src/main/resources/static/js'

μ²˜μŒμ—λŠ” κ°„λ‹¨ν•˜κ²Œ ν’€ λ¦¬ν€˜μŠ€νŠΈκ°€ μƒμ„±λ˜κ³  컀밋이 ν‘Έμ‹œλ˜μ—ˆμ„λ•Œ μ²΄ν¬μŠ€νƒ€μΌκ³Ό ESLintκ°€ λ™μž‘ν•˜λ„λ‘ μž‘μ„±ν•˜μ˜€μœΌλ‚˜ λ°±μ—”λ“œ μž‘μ—…μ‹œμ—λ„ λΆˆν•„μš”ν•˜κ²Œ ESLintλ₯Ό μˆ˜ν–‰ν•˜κ³  ν”„λ‘ νŠΈμ—”λ“œ μž‘μ—…μ‹œμ—λ„ λΆˆν•„μš”ν•˜κ²Œ μžλ°” νŒŒμΌμ— λŒ€ν•œ μ²΄ν¬μŠ€νƒ€μΌμ„ μˆ˜ν–‰ν•˜λŠ” λΉ„νš¨μœ¨μ μΈ λ™μž‘μ„ μˆ˜ν–‰ν•˜λŠ” κ΅¬μ‘°μ˜€λ‹€. 좔가적인 κ°œμ„ μ„ 톡해 ν’€ λ¦¬ν€˜μŠ€νŠΈ μ‹œ paths 문법을 ν™œμš©ν•΄μ„œ .java, .js, .vue νŒŒμΌμ— λŒ€ν•œ 변경사항이 μžˆμ„λ•Œλ§Œ μƒνƒœ 검사에 λŒ€ν•œ μ›Œν¬ν”Œλ‘œμš°κ°€ 싀행될 수 μžˆλ„λ‘ λ³€κ²½ν–ˆμœΌλ©° dorny/paths-filterλ₯Ό ν†΅ν•΄μ„œ μžλ°” νŒŒμΌμ— λŒ€ν•œ 변경사항이 μžˆλ‹€λ©΄ μ²΄ν¬μŠ€νƒ€μΌμ„ μˆ˜ν–‰ν•˜κ³  ν”„λ‘ νŠΈ νŒŒμΌμ— λŒ€ν•œ 변경사항이 μžˆλ‹€λ©΄ ESLintκ°€ κ°œλ³„μ μœΌλ‘œ μˆ˜ν–‰ν•  수 μžˆλ„λ‘ ν•˜μ˜€λ‹€.

ꡬ글 μ²΄ν¬μŠ€νƒ€μΌμ€ νšŒμ‚¬ μ½”λ“œμ— μ ν•©ν•˜μ§€ μ•Šλ‹€κ³  νŒλ‹¨λ˜μ–΄ κ°€μž₯ κ°„λ‹¨ν•œ κ·œμΉ™μœΌλ‘œ μˆ˜ν–‰ν•  수 μžˆλ„λ‘ μ»€μŠ€ν„°λ§ˆμ΄μ§• 된 μ²΄ν¬μŠ€νƒ€μΌ νŒŒμΌμ„ μΆ”κ°€ν–ˆμŠ΅λ‹ˆλ‹€.