Skip to main content

Rust ๋นŒ๋“œ ๋ฐ ํ…Œ์ŠคํŠธ

CI(์—ฐ์† ํ†ตํ•ฉ) ์›Œํฌํ”Œ๋กœ๋ฅผ ๋งŒ๋“ค์–ด Rust ํ”„๋กœ์ ํŠธ๋ฅผ ๋นŒ๋“œํ•˜๊ณ  ํ…Œ์ŠคํŠธํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ์•„๋ณด์„ธ์š”.

์†Œ๊ฐœ

์ด ๊ฐ€์ด๋“œ์—์„œ๋Š” Rust ํŒจํ‚ค์ง€๋ฅผ ๋นŒ๋“œํ•˜๊ณ  ํ…Œ์ŠคํŠธํ•˜๊ณ  ๊ฒŒ์‹œํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ณด์—ฌ ์ค๋‹ˆ๋‹ค.

GitHub ํ˜ธ์ŠคํŒ… ์‹คํ–‰๊ธฐ์—๋Š” Rust์˜ ์ข…์†์„ฑ์„ ํฌํ•จํ•˜๋Š” ์†Œํ”„ํŠธ์›จ์–ด๊ฐ€ ์‚ฌ์ „ ์„ค์น˜๋œ ๋„๊ตฌ ์บ์‹œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์ตœ์‹  ์†Œํ”„ํŠธ์›จ์–ด ๋ฐ ์‚ฌ์ „ ์„ค์น˜๋œ Rust ๋ฒ„์ „์˜ ์ „์ฒด ๋ชฉ๋ก์€ GitHub ํ˜ธ์ŠคํŒ… ์‹คํ–‰๊ธฐ์„(๋ฅผ) ์ฐธ์กฐํ•˜์„ธ์š”.

ํ•„์ˆ˜ ์กฐ๊ฑด

YAML ๊ตฌ๋ฌธ๊ณผ ์ด๋ฅผ GitHub Actions์™€ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ์ž˜ ์•Œ๊ณ  ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ž์„ธํ•œ ๋‚ด์šฉ์€ GitHub Actions์— ๋Œ€ํ•œ ์›Œํฌํ”Œ๋กœ ๊ตฌ๋ฌธ์„(๋ฅผ) ์ฐธ์กฐํ•˜์„ธ์š”.

Rust ์–ธ์–ด๋ฅผ ๊ธฐ๋ณธ์ ์œผ๋กœ ์ดํ•ดํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. ์ž์„ธํ•œ ๋‚ด์šฉ์€ Rust ์‹œ์ž‘ํ•˜๊ธฐ๋ฅผ ์ฐธ์กฐํ•˜์„ธ์š”.

Rust ์›Œํฌํ”Œ๋กœ ํ…œํ”Œ๋ฆฟ ์‚ฌ์šฉ

๋น ๋ฅด๊ฒŒ ์‹œ์ž‘ํ•˜๋ ค๋ฉด ์›Œํฌํ”Œ๋กœ ํ…œํ”Œ๋ฆฟ์„ ๋ฆฌํฌ์ง€ํ† ๋ฆฌ์˜ .github/workflows ๋””๋ ‰ํ„ฐ๋ฆฌ์— ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

GitHub์€ ๋Œ€๋ถ€๋ถ„์˜ Rust ํ”„๋กœ์ ํŠธ์—์„œ ์ž‘๋™ํ•˜๋Š” Rust ์›Œํฌํ”Œ๋กœ ํ…œํ”Œ๋ฆฟ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ์ด ๊ฐ€์ด๋“œ์˜ ํ›„์† ์„น์…˜์—์„œ๋Š” ์ด ์›Œํฌํ”Œ๋กœ ํ…œํ”Œ๋ฆฟ์„ ์‚ฌ์šฉ์ž ์ง€์ •ํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•œ ์˜ˆ์‹œ๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

  1. GitHub์—์„œ ๋ฆฌํฌ์ง€ํ† ๋ฆฌ์˜ ๊ธฐ๋ณธ ํŽ˜์ด์ง€๋กœ ์ด๋™ํ•ฉ๋‹ˆ๋‹ค.

  2. ๋ฆฌํฌ์ง€ํ† ๋ฆฌ ์ด๋ฆ„ ์•„๋ž˜์—์„œ ์ž‘์—…์„ ํด๋ฆญํ•ฉ๋‹ˆ๋‹ค.

    "github/docs" ๋ฆฌํฌ์ง€ํ† ๋ฆฌ์˜ ํƒญ ์Šคํฌ๋ฆฐ์ƒท. "์ž‘์—…" ํƒญ์€ ์ฃผํ™ฉ์ƒ‰ ์œค๊ณฝ์„ ์œผ๋กœ ๊ฐ•์กฐ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.

  3. ๋ฆฌํฌ์ง€ํ† ๋ฆฌ์— ์›Œํฌํ”Œ๋กœ๊ฐ€ ์ด๋ฏธ ์žˆ๋Š” ๊ฒฝ์šฐ ์ƒˆ ์›Œํฌํ”Œ๋กœ๋ฅผ ํด๋ฆญํ•ฉ๋‹ˆ๋‹ค.

  4. "์›Œํฌํ”Œ๋กœ ์„ ํƒ" ํŽ˜์ด์ง€์—๋Š” ๊ถŒ์žฅ๋˜๋Š” ์›Œํฌํ”Œ๋กœ ํ…œํ”Œ๋ฆฟ์˜ ์„ ํƒ ํ•ญ๋ชฉ์ด ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค. โ€œRustโ€๋ฅผ ๊ฒ€์ƒ‰ํ•ฉ๋‹ˆ๋‹ค.

  5. ์ง€์†์  ํ†ตํ•ฉ์„ ํด๋ฆญํ•˜์—ฌ ์›Œํฌํ”Œ๋กœ ์„ ํƒ์„ ํ•„ํ„ฐ๋งํ•ฉ๋‹ˆ๋‹ค.

  6. โ€œRust - GitHub Actions ๊ธฐ์ค€โ€ ์›Œํฌํ”Œ๋กœ์—์„œ ๊ตฌ์„ฑ์„ ํด๋ฆญํ•ฉ๋‹ˆ๋‹ค.

    "์›Œํฌํ”Œ๋กœ ์„ ํƒ" ํŽ˜์ด์ง€์˜ ์Šคํฌ๋ฆฐ์ƒท. โ€œRustโ€ ์›Œํฌํ”Œ๋กœ์˜ โ€œ๊ตฌ์„ฑโ€ ๋ฒ„ํŠผ์€ ์ฃผํ™ฉ์ƒ‰ ์œค๊ณฝ์„ ์œผ๋กœ ๊ฐ•์กฐ ํ‘œ์‹œ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

  7. ํ•„์š”์— ๋”ฐ๋ผ ์›Œํฌํ”Œ๋กœ๋ฅผ ํŽธ์ง‘ํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด Rust ๋ฒ„์ „์„ ๋ณ€๊ฒฝํ•ฉ๋‹ˆ๋‹ค.

  8. ๋ณ€๊ฒฝ ๋‚ด์šฉ ์ปค๋ฐ‹์„ ํด๋ฆญํ•ฉ๋‹ˆ๋‹ค.

rust.yml ์›Œํฌํ”Œ๋กœ ํŒŒ์ผ์ด ๋ฆฌํฌ์ง€ํ† ๋ฆฌ์˜ .github/workflows ๋””๋ ‰ํ„ฐ๋ฆฌ์— ์ถ”๊ฐ€๋ฉ๋‹ˆ๋‹ค.

Rust ๋ฒ„์ „ ์ง€์ •

GitHub ํ˜ธ์ŠคํŒ… ์‹คํ–‰๊ธฐ๋Š” ์ตœ์‹  ๋ฒ„์ „์˜ Rust ๋„๊ตฌ ์ฒด์ธ์„ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค. rustup์„ ์‚ฌ์šฉํ•˜์—ฌ ์‹คํ–‰๊ธฐ์—์„œ ์„ค์น˜๋œ ๋ฒ„์ „์„ ๋ณด๊ณ ํ•˜๊ณ  ๋ฒ„์ „์„ ์žฌ์ •์˜ํ•˜๊ณ  ๋‹ค๋ฅธ ๋„๊ตฌ ์ฒด์ธ์„ ์„ค์น˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ž์„ธํ•œ ๋‚ด์šฉ์€ rustup ์ฑ…์„ ์ฐธ์กฐํ•˜์„ธ์š”.

์ด ์˜ˆ์ œ์—์„œ๋Š” ์‹คํ–‰๊ธฐ ํ™˜๊ฒฝ์„ ์„ค์ •ํ•˜์—ฌ rust์˜ ์•ผ๊ฐ„ ๋นŒ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ๋ฒ„์ „์„ ๋ณด๊ณ ํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๋‹จ๊ณ„๋ฅผ ๋ณด์—ฌ ์ค๋‹ˆ๋‹ค.

YAML
      - name: Temporarily modify the rust toolchain version
        run: rustup override set nightly
      - name: Output rust version for educational purposes
        run: rustup --version

์ข…์†์„ฑ ์บ์‹ฑ

์บ์‹œ ์ž‘์—…์„ ์‚ฌ์šฉํ•˜์—ฌ ์ข…์†์„ฑ์„ ์บ์‹œํ•˜๊ณ  ๋ณต์›ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ์˜ˆ์ œ์—์„œ๋Š” ๋ฆฌํฌ์ง€ํ† ๋ฆฌ์— Cargo.lock ํŒŒ์ผ์ด ํฌํ•จ๋˜์–ด ์žˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•ฉ๋‹ˆ๋‹ค.

YAML
      - name: Cache
        uses: actions/cache@v4
        with:
          path: |
            ~/.cargo/registry
            ~/.cargo/git
            target
          key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}

์‚ฌ์šฉ์ž ์ง€์ • ์š”๊ตฌ ์‚ฌํ•ญ์ด ์žˆ๊ฑฐ๋‚˜ ์บ์‹ฑ์— ๋Œ€ํ•œ ๋” ์„ธ๋ถ€์ ์ธ ์ œ์–ด๊ฐ€ ํ•„์š”ํ•œ ๊ฒฝ์šฐ cache์ž‘์—…์— ๋Œ€ํ•œ ๋‹ค๋ฅธ ๊ตฌ์„ฑ ์˜ต์…˜์„ ํƒ์ƒ‰ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ž์„ธํ•œ ๋‚ด์šฉ์€ ์ข…์†์„ฑ ์บ์‹ฑ ์ฐธ์กฐ์„(๋ฅผ) ์ฐธ์กฐํ•˜์„ธ์š”.

์ฝ”๋“œ ๋นŒ๋“œ ๋ฐ ํ…Œ์ŠคํŠธ

์ฝ”๋“œ๋ฅผ ๋นŒ๋“œํ•˜๊ณ  ํ…Œ์ŠคํŠธํ•˜๊ธฐ ์œ„ํ•ด ๋กœ์ปฌ์—์„œ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ๊ณผ ๋™์ผํ•œ ๋ช…๋ น์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ์˜ˆ์‹œ ์›Œํฌํ”Œ๋กœ์—์„œ๋Š” ์ž‘์—…์—์„œ cargo build ๋ฐ cargo test๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ณด์—ฌ ์ค๋‹ˆ๋‹ค.

YAML
jobs:
  build:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        BUILD_TARGET: [release] # refers to a cargo profile
    outputs:
      release_built: ${{ steps.set-output.outputs.release_built }}
    steps:
      - uses: actions/checkout@v4
      - name: Build binaries in "${{ matrix.BUILD_TARGET }}" mode
        run: cargo build --profile ${{ matrix.BUILD_TARGET }}
      - name: Run tests in "${{ matrix.BUILD_TARGET }}" mode
        run: cargo test --profile ${{ matrix.BUILD_TARGET }}

์ด ์˜ˆ์ œ์—์„œ ์‚ฌ์šฉ๋˜๋Š” release ํ‚ค์›Œ๋“œ๋Š” cargo ํ”„๋กœํ•„์— ํ•ด๋‹นํ•ฉ๋‹ˆ๋‹ค. Cargo.toml ํŒŒ์ผ์—์„œ ์ •์˜ํ•œ ๋ชจ๋“  ํ”„๋กœํ•„์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํŒจํ‚ค์ง€ ๋˜๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ crates.io์— ๊ฒŒ์‹œ

์›Œํฌํ”Œ๋กœ๋ฅผ ์„ค์ •ํ•˜์—ฌ ์ฝ”๋“œ๋ฅผ ๋นŒ๋“œํ•˜๊ณ  ํ…Œ์ŠคํŠธํ•œ ํ›„์—๋Š” ๋น„๋ฐ€์„ ์‚ฌ์šฉํ•˜์—ฌ ๋กœ๊ทธ์ธํ•˜์—ฌ ํŒจํ‚ค์ง€๋ฅผ crates.io์— ๊ฒŒ์‹œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

YAML
      - name: Login into crates.io
        run: cargo login ${{ secrets.CRATES_IO }}
      - name: Build binaries in "release" mode
        run: cargo build -r
      - name: "Package for crates.io"
        run: cargo package # publishes a package as a tarball
      - name: "Publish to crates.io"
        run: cargo publish # publishes your crate as a library that can be added as a dependency

ํฌ๋ ˆ์ดํŠธ๋ฅผ ๋นŒ๋“œํ•˜๊ณ  ํŒจํ‚ค์ง•ํ•˜๋Š” ๋ฐ ์˜ค๋ฅ˜๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ ๋งค๋‹ˆํŽ˜์ŠคํŠธ, Cargo.toml ํŒŒ์ผ์—์„œ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๋ฅผ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค. ๋งค๋‹ˆํŽ˜์ŠคํŠธ ํ˜•์‹์„ ์ฐธ์กฐํ•˜์„ธ์š”. ๋˜ํ•œ Cargo.lock ํŒŒ์ผ์„ ํ™•์ธํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. Cargo.toml ๋ฐ Cargo.lock ์„ ์ฐธ์กฐํ•˜์„ธ์š”.

์›Œํฌํ”Œ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์•„ํ‹ฐํŒฉํŠธ๋กœ ํŒจํ‚ค์ง€

์›Œํฌํ”Œ๋กœ๊ฐ€ ์™„๋ฃŒ๋˜๋ฉด ๋ถ„์„์„ ์œ„ํ•ด ๊ฒฐ๊ณผ ์•„ํ‹ฐํŒฉํŠธ๋ฅผ ์—…๋กœ๋“œํ•˜๊ฑฐ๋‚˜ ๋‹ค๋ฅธ ์›Œํฌํ”Œ๋กœ์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์›Œํฌํ”Œ๋กœ์— ์ด๋Ÿฌํ•œ ์˜ˆ์ œ ๋‹จ๊ณ„๋ฅผ ์ถ”๊ฐ€ํ•˜์—ฌ ๋‹ค๋ฅธ ์›Œํฌํ”Œ๋กœ์—์„œ ์‚ฌ์šฉํ•  ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์—…๋กœ๋“œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

YAML
      - name: Upload release artifact
        uses: actions/upload-artifact@v4
        with:
          name: <my-app>
          path: target/${{ matrix.BUILD_TARGET }}/<my-app>

์—…๋กœ๋“œ๋œ ์•„ํ‹ฐํŒฉํŠธ๋ฅผ ๋‹ค๋ฅธ ์ž‘์—…์—์„œ ์‚ฌ์šฉํ•˜๋ ค๋ฉด ์›Œํฌํ”Œ๋กœ์— ๋ฆฌํฌ์ง€ํ† ๋ฆฌ์— ๋Œ€ํ•œ ์˜ฌ๋ฐ”๋ฅธ ๊ถŒํ•œ์ด ์žˆ๋Š”์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค. ์›Œํฌํ”Œ๋กœ์—์„œ ์ธ์ฆ์— GITHUB_TOKEN ์‚ฌ์šฉ์„(๋ฅผ) ์ฐธ์กฐํ•˜์„ธ์š”. ๋‹ค์Œ ์˜ˆ์ œ ๋‹จ๊ณ„๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ด์ „ ์›Œํฌํ”Œ๋กœ์—์„œ ๋งŒ๋“  ์•ฑ์„ ๋‹ค์šด๋กœ๋“œํ•˜๊ณ  GitHub์— ๊ฒŒ์‹œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

YAML
      - uses: actions/checkout@v4
      - name: Download release artifact
        uses: actions/download-artifact@v4
        with:
          name: <my-app>
          path: ./<my-app>
      - name: Publish built binary to GitHub releases
      - run: |
          gh release create --generate-notes ./<my-app>/<my-project>#<my-app>