{"id":247,"date":"2026-03-09T10:39:23","date_gmt":"2026-03-09T10:39:23","guid":{"rendered":"https:\/\/blog.rebalai.com\/ko\/2026\/03\/09\/setting-up-github-actions-for-python-applications\/"},"modified":"2026-03-09T22:30:52","modified_gmt":"2026-03-09T22:30:52","slug":"setting-up-github-actions-for-python-applications","status":"publish","type":"post","link":"https:\/\/blog.rebalai.com\/ko\/2026\/03\/09\/setting-up-github-actions-for-python-applications\/","title":{"rendered":"Python \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc744 \uc704\ud55c GitHub Actions \uc124\uc815: \uc9c1\uc811 \uc0bd\uc9c8\ud558\uba70 \ubc30\uc6b4 \uac83\ub4e4"},"content":{"rendered":"<p>\uc791\ub144 \uc774\ub9d8\ub54c\ucbe4\uc774\uc5c8\ub2e4. \ud300\uc774 5\uba85\uc73c\ub85c \ub298\uc5b4\ub0ac\uace0, \ub9e4 PR\ub9c8\ub2e4 &#8220;\ud14c\uc2a4\ud2b8 \ub3cc\ub838\uc5b4\uc694?&#8221;\ub77c\ub294 \uc9c8\ubb38\uc774 \ubc18\ubcf5\ub418\uace0 \uc788\uc5c8\ub2e4. Jenkins\ub97c \uc4f0\uace0 \uc788\uc5c8\ub294\ub370 \u2014 \uc124\uc815 \uc790\uccb4\uac00 \uace0\ud1b5\uc2a4\ub7fd\uace0, \uacb0\uad6d \ub098\ub9cc \uc190\ub308 \uc218 \uc788\ub294 \ube14\ub799\ubc15\uc2a4\uac00 \ub418\uc5b4\ubc84\ub838\ub2e4. \uadf8\ub798\uc11c GitHub Actions\ub85c \ub9c8\uc774\uadf8\ub808\uc774\uc158\uc744 \uacb0\uc815\ud588\ub2e4.<\/p>\n<p>2\uc8fc <a href=\"https:\/\/blog.rebalai.com\/ko\/2026\/03\/05\/autogen-vs-langgraph-vs-crewai-2026-ai\/\" title=\"\ub3d9\uc548 \uc9c1\uc811\">\ub3d9\uc548 \uc9c1\uc811<\/a> \uc124\uc815\ud558\uace0 \ub72f\uc5b4\uace0\uce58\uba74\uc11c \ubc30\uc6b4 \uac83\ub4e4\uc744 \uc815\ub9ac\ud588\ub2e4. \uacf5\uc2dd \ubb38\uc11c\ub9cc \ubcf4\uace0 \ub530\ub77c\ud588\uc744 \ub54c\uc640 \uc2e4\uc81c \ud504\ub85c\ub355\uc158\uc5d0 \ubd99\uc5ec\ubd24\uc744 \ub54c \uc0ac\uc774\uc5d0\ub294 \uaf64 \ud070 \uac04\uadf9\uc774 \uc788\uc5c8\ub2e4.<\/p>\n<h2>Jenkins\uc5d0\uc11c GitHub Actions\ub85c: \uae30\ub300\ud588\ub358 \uac83\uacfc \uc2e4\uc81c<\/h2>\n<p>GitHub Actions\uc758 \uccab\uc778\uc0c1\uc740 \uc88b\uc558\ub2e4. YAML \ud30c\uc77c \ud558\ub098\ub85c \uc124\uc815\uc774 \ub05d\ub098\uace0, UI\ub3c4 Jenkins\ubcf4\ub2e4 \ud6e8\uc52c \uc9c1\uad00\uc801\uc774\ub2e4. \ube4c\ub4dc \ub85c\uadf8\ub3c4 \ubcf4\uae30 \ud3b8\ud558\uace0, PR\uacfc \uc790\ub3d9 \uc5f0\ub3d9\ub418\ub294 \uac83\ub3c4 \ub9e4\ub825\uc801\uc774\uc5c8\ub2e4.<\/p>\n<p>\uadfc\ub370 Python \ud504\ub85c\uc81d\ud2b8\ub97c \ucc98\uc74c \uc5f0\uacb0\ud560 \ub54c \ud669\ub2f9\ud55c \uc77c\uc774 \uc788\uc5c8\ub2e4. \uacf5\uc2dd starter \uc608\uc81c\ub97c \uadf8\ub300\ub85c \ubcf5\uc0ac\ud574\uc11c \ubd99\uc5ec\ub123\uc5c8\ub354\ub2c8 \uccab \ube4c\ub4dc\uac00 \ubc14\ub85c <code>ModuleNotFoundError<\/code>\ub85c \ud130\uc84c\ub2e4. \uc6d0\uc778\uc740 \uac00\uc0c1\ud658\uacbd \uacbd\ub85c \ubb38\uc81c\uc600\ub2e4 \u2014 \ub85c\uceec\uc5d0\uc11c\ub294 <code>venv<\/code>\ub97c \uc9c1\uc811 activate\ud574\uc11c \uc4f0\ub294\ub370, Actions runner\ub294 \uadf8\uac78 \ubaa8\ub978\ub2e4. \uc0ac\uc18c\ud574 \ubcf4\uc774\uc9c0\ub9cc \ud300\uc6d0\ub4e4\uc774 \ucc98\uc74c \uc811\ud560 \ub54c \uc790\uc8fc \ub9c9\ud788\ub294 \uc9c0\uc810\uc774\ub2e4.<\/p>\n<p>Jenkins\uc5d0\uc11c Groovy \uc2a4\ud06c\ub9bd\ud2b8\ub85c \ubcf5\uc7a1\ud558\uac8c \uc124\uc815\ud588\ub358 \uac83\ub4e4\uc774 YAML\ub85c \ud6e8\uc52c \uac04\uacb0\ud574\uc9c4 \uac74 \ub9de\ub2e4. \ub2e4\ub9cc <code>actions\/cache<\/code> \uc124\uc815\uc774\ub098 \ub9e4\ud2b8\ub9ad\uc2a4 \uc804\ub7b5 \uac19\uc740 \uac83\ub4e4\uc740 \ucc98\uc74c\uc5d0 \uc0dd\uac01\ubcf4\ub2e4 \uc870\uac74\ub4e4\uc774 \ub9ce\uc544\uc11c \uc81c\ub300\ub85c \ub3d9\uc791\ud558\uae30\uae4c\uc9c0 \uba70\uce60\uc774 \uac78\ub838\ub2e4. &#8220;\uac04\ub2e8\ud558\ub2e4&#8221;\ub294 \ub9d0\uc744 \ub108\ubb34 \uace7\uc774\uace7\ub300\ub85c \ubbff\uc5c8\ub2e4.<\/p>\n<p>\ubb34\ub8cc \ud50c\ub79c \uae30\uc900\uc73c\ub85c public repo\ub294 \ubb34\uc81c\ud55c\uc774\uace0, private repo\ub294 \uc6d4 2,000\ubd84\uae4c\uc9c0 \ubb34\ub8cc\ub2e4. 5\uba85\uc9dc\ub9ac \ud300\uc5d0\uc11c \uc801\ub2f9\ud788 \uc4f0\uba74 \uc0ac\uc2e4 \ub3c8 \ub0bc \uc77c\uc774 \uac70\uc758 \uc5c6\ub2e4. Jenkins \uc11c\ubc84\ube44\uae4c\uc9c0 \ud569\uc0b0\ud588\uc744 \ub54c\uc640 \ube44\uad50\ud558\uba74 \ud655\uc2e4\ud55c \uc7a5\uc810\uc774\uc5c8\ub2e4.<\/p>\n<h2>\uccab \ubc88\uc9f8 \uc6cc\ud06c\ud50c\ub85c\uc6b0 \ud30c\uc77c: \ub3d9\uc791\ud558\ub294 \uac83\ubd80\ud130 \ub9cc\ub4e4\uae30<\/h2>\n<p><code>.github\/workflows\/<\/code> \ub514\ub809\ud1a0\ub9ac\ub97c \ub9cc\ub4e4\uace0 <code>ci.yml<\/code> \ud30c\uc77c\uc744 \ucd94\uac00\ud558\ub294 \uac83\ubd80\ud130 \uc2dc\uc791\ud55c\ub2e4. \uc544\ub798\uac00 \ub0b4\uac00 \uc2e4\uc81c\ub85c \uc4f0\ub294 \uae30\ubcf8 \uad6c\uc870\uc778\ub370, \uacf5\uc2dd \uc608\uc81c\ubcf4\ub2e4 \uc870\uae08 \ub354 \uc2e4\uc6a9\uc801\uc73c\ub85c \ub2e4\ub4ec\uc740 \ubc84\uc804\uc774\ub2e4.<\/p>\n<pre><code class=\"language-yaml\">name: Python CI\n\non:\n  push:\n    branches: [main, develop]\n  pull_request:\n    branches: [main]\n\njobs:\n  test:\n    runs-on: ubuntu-22.04  # latest \ub300\uc2e0 \ubc84\uc804 \uace0\uc815\n\n    steps:\n      - uses: actions\/checkout@v4\n\n      - name: Python \uc124\uc815\n        uses: actions\/setup-python@v5\n        with:\n          python-version: &quot;3.12&quot;\n\n      - name: \uc758\uc874\uc131 \uc124\uce58\n        run: |\n          python -m pip install --upgrade pip\n          pip install -r requirements.txt\n          pip install -r requirements-dev.txt\n\n      - name: \ub9b0\ud2b8 \uac80\uc0ac (ruff)\n        run: |\n          pip install ruff\n          ruff check .\n\n      - name: \ud14c\uc2a4\ud2b8 \uc2e4\ud589\n        run: pytest tests\/ -v --tb=short\n<\/code><\/pre>\n<p><code>actions\/checkout@v4<\/code>, <code>actions\/setup-python@v5<\/code>\ucc98\ub7fc \ubc84\uc804\uc744 \uba85\uc2dc\ud558\ub294 \uac8c \uc911\uc694\ud558\ub2e4. <code>@latest<\/code>\ub098 <code>@main<\/code>\uc744 \uc4f0\uba74 \uc5b4\ub290 \ub0a0 \uac11\uc790\uae30 breaking change\uac00 \ub4e4\uc5b4\uc640\uc11c \ube4c\ub4dc\uac00 \ud130\uc9c4\ub2e4. \uc2e4\uc81c\ub85c 2024\ub144 \ub9d0\uc5d0 <code>setup-python@v4<\/code>\uc5d0\uc11c <code>v5<\/code>\ub85c \uc62c\ub77c\uac00\uba74\uc11c \uce90\uc2dc \ub3d9\uc791 \ubc29\uc2dd\uc774 \ubc14\ub010 \uc801\uc774 \uc788\uc5c8\ub294\ub370, \ubc84\uc804 \uace0\uc815\uc744 \uc548 \ud558\ub358 \ud300\ub4e4\uc774 \uaf64 \uace0\uc0dd\ud588\ub2e4.<\/p>\n<p><code>runs-on: ubuntu-latest<\/code> \ub300\uc2e0 <code>ubuntu-22.04<\/code>\ub97c \uc4f0\ub294 \uac83\ub3c4 \uc774\uc720\uac00 \uc788\ub2e4. 2025\ub144\ubd80\ud130 <code>ubuntu-latest<\/code>\uac00 <code>ubuntu-24.04<\/code>\ub97c \uac00\ub9ac\ud0a4\uae30 \uc2dc\uc791\ud558\uba74\uc11c \uc77c\ubd80 C \ud655\uc7a5 \ubaa8\ub4c8 \ube4c\ub4dc\uac00 \uae68\uc9c0\ub294 \uacbd\uc6b0\uac00 \uc0dd\uacbc\ub2e4. \uc548\uc815\uc131\uc774 \uc911\uc694\ud558\ub2e4\uba74 \uad6c\uccb4\uc801\uc778 \ubc84\uc804\uc744 \uba85\uc2dc\ud558\ub294 \ud3b8\uc774 \ub0ab\ub2e4.<\/p>\n<h2>\uc758\uc874\uc131 \uce90\uc2f1\uc73c\ub85c \ube4c\ub4dc \uc2dc\uac04\uc744 8\ubd84\uc5d0\uc11c 2\ubd84\uc73c\ub85c<\/h2>\n<p>\ucd08\uae30 \uc124\uc815 \uc9c1\ud6c4 \ud3c9\uade0 \ube4c\ub4dc \uc2dc\uac04\uc774 8\ubd84 \uc815\ub3c4\uc600\ub2e4. \ub300\ubd80\ubd84\uc774 <code>pip install<\/code> \uc2dc\uac04\uc774\uc5c8\ub2e4. \uce90\uc2f1\uc744 \uc801\uc6a9\ud558\uace0 \ub098\uc11c 2\ubd84 \ucd08\ubc18\ub300\ub85c \uc904\uc5c8\ub2e4.<\/p>\n<p><code>actions\/setup-python@v5<\/code>\ub294 <code>cache<\/code> \uc635\uc158\uc744 \ub0b4\uc7a5 \uc9c0\uc6d0\ud55c\ub2e4:<\/p>\n<pre><code class=\"language-yaml\">- name: Python \uc124\uc815 (\uce90\uc2dc \ud3ec\ud568)\n  uses: actions\/setup-python@v5\n  with:\n    python-version: &quot;3.12&quot;\n    cache: &quot;pip&quot;\n    cache-dependency-path: |\n      requirements.txt\n      requirements-dev.txt\n<\/code><\/pre>\n<p><code>cache-dependency-path<\/code>\ub97c \uc9c0\uc815\ud558\uc9c0 \uc54a\uc73c\uba74 Actions\uac00 <code>requirements.txt<\/code> \ud558\ub098\ub9cc \ubcf4\uace0 \uce90\uc2dc \ud0a4\ub97c \ub9cc\ub4e0\ub2e4. <code>requirements-dev.txt<\/code>\uac00 \ubc14\ub00c\uc5b4\ub3c4 \uce90\uc2dc\uac00 \uadf8\ub300\ub85c\ub77c\uc11c, \uac1c\ubc1c \uc758\uc874\uc131\uc744 \ucd94\uac00\ud588\ub294\ub370 \ube4c\ub4dc\uc5d0\uc11c <code>ImportError<\/code>\uac00 \ub098\ub294 \ud669\ub2f9\ud55c \uc0c1\ud669\uc774 \uc0dd\uae34\ub2e4. \ub450 \ud30c\uc77c\uc744 \ubaa8\ub450 \uba85\uc2dc\ud574\uc57c \ud55c\ub2e4 \u2014 \uc774\uac70 \ucc98\uc74c\uc5d4 \uc65c \uc548 \ub418\ub294\uc9c0 \ud55c\ucc38 \ubd24\ub2e4.<\/p>\n<p><code>poetry<\/code>\ub098 <code>uv<\/code>\ub97c \uc4f4\ub2e4\uba74 \uc124\uc815\uc774 \uc870\uae08 \ub2e4\ub974\ub2e4. \uc694\uc998 <code>uv<\/code>\uac00 \ub300\uc138\uac00 \ub418\uace0 \uc788\ub294\ub370, \ubcc4\ub3c4 action\uc744 \uc4f0\ub294 \uac8c \ud3b8\ud558\ub2e4:<\/p>\n<pre><code class=\"language-yaml\">- name: uv \uc124\uce58 \ubc0f \uce90\uc2dc \uc124\uc815\n  uses: astral-sh\/setup-uv@v5\n  with:\n    enable-cache: true\n    cache-dependency-glob: &quot;uv.lock&quot;\n\n- name: \uc758\uc874\uc131 \uc124\uce58\n  run: uv sync --frozen\n<\/code><\/pre>\n<p>\uc194\uc9c1\ud788 \ub9d0\ud558\uba74, <code>uv<\/code>\uc758 \uc18d\ub3c4\uac00 \uc774 \uc815\ub3c4\uc77c \uc904\uc740 \ubab0\ub790\ub2e4. \uce90\uc2dc \ubbf8\uc2a4\uac00 \ubc1c\uc0dd\ud574\ub3c4 \uc124\uce58 \uc790\uccb4\uac00 <code>pip<\/code>\ubcf4\ub2e4 \ud6e8\uc52c \ube68\ub77c\uc11c \uce90\uc2dc \uc5c6\uc774\ub3c4 40\ucd08 \uc815\ub3c4\ubc16\uc5d0 \uc548 \uac78\ub838\ub2e4. \uc0c8 \ud504\ub85c\uc81d\ud2b8\ub77c\uba74 \ucc98\uc74c\ubd80\ud130 <code>uv<\/code>\ub97c \uc4f0\ub294 \uac78 \uc9c4\uc9c0\ud558\uac8c \uace0\ub824\ud574\ubcfc \ub9cc\ud558\ub2e4.<\/p>\n<h2>\ud14c\uc2a4\ud2b8 \ub9e4\ud2b8\ub9ad\uc2a4 \uc124\uc815\ud558\ub2e4 \ub4a4\ud1b5\uc218 \ub9de\uc740 \uc774\uc57c\uae30<\/h2>\n<p>\ub77c\uc774\ube0c\ub7ec\ub9ac\ub97c \ub9cc\ub4e4\uac70\ub098 \uc5ec\ub7ec Python \ubc84\uc804\uc744 \uc9c0\uc6d0\ud574\uc57c \ud55c\ub2e4\uba74 \ub9e4\ud2b8\ub9ad\uc2a4 \uc804\ub7b5\uc774 \ud544\uc694\ud558\ub2e4. \uc124\uc815 \uc790\uccb4\ub294 \uac04\ub2e8\ud574 \ubcf4\uc778\ub2e4:<\/p>\n<pre><code class=\"language-yaml\">jobs:\n  test:\n    runs-on: ${{ matrix.os }}\n    strategy:\n      fail-fast: false  # \uc774\uac70 \uaf2d \ub123\uc5b4\uc57c \ud55c\ub2e4\n      matrix:\n        python-version: [&quot;3.10&quot;, &quot;3.11&quot;, &quot;3.12&quot;]\n        os: [ubuntu-22.04, windows-latest, macos-latest]\n\n    steps:\n      - uses: actions\/checkout@v4\n\n      - name: Python ${{ matrix.python-version }} \uc124\uc815\n        uses: actions\/setup-python@v5\n        with:\n          python-version: ${{ matrix.python-version }}\n          cache: &quot;pip&quot;\n\n      - name: \ud14c\uc2a4\ud2b8 \uc2e4\ud589\n        run: pytest tests\/ -v\n<\/code><\/pre>\n<p><code>fail-fast: false<\/code>\ub97c \uaf2d \ub123\uc5b4\uc57c \ud55c\ub2e4. \uae30\ubcf8\uac12\uc774 <code>true<\/code>\uc778\ub370, \uadf8\ub7ec\uba74 \ud558\ub098\uc758 \ub9e4\ud2b8\ub9ad\uc2a4 \uc870\ud569\uc774 \uc2e4\ud328\ud588\uc744 \ub54c \ub098\uba38\uc9c0 \ube4c\ub4dc\uac00 \uc804\ubd80 \ucde8\uc18c\ub41c\ub2e4. Python 3.10\uc5d0\uc11c \uc2e4\ud328\ud588\ub2e4\uace0 3.12 \uacb0\uacfc\ub97c \ubabb \ubcf4\ub294 \uc0c1\ud669\uc774 \uc0dd\uae30\ub294 \uac70\ub2e4.<\/p>\n<p>\uc5ec\uae30\uc11c \uc608\uc0c1\uce58 \ubabb\ud55c \ubc1c\uacac\uc774 \uc788\uc5c8\ub2e4. Windows runner\uc5d0\uc11c \uacbd\ub85c \uad6c\ubd84\uc790(<code>\\<\/code>) \ubb38\uc81c\uac00 \uc0dd\uac01\ubcf4\ub2e4 \uc790\uc8fc \ud130\uc9c4\ub2e4. \ud300\uc774 macOS\uc640 Linux\ub9cc \uc4f0\uace0 \uc788\uc5b4\uc11c \ucf54\ub4dc \uacf3\uacf3\uc5d0 <code>os.path.join<\/code> \ub300\uc2e0 \uc2ac\ub798\uc2dc(<code>\/<\/code>)\ub85c \uacbd\ub85c\ub97c \ud558\ub4dc\ucf54\ub529\ud55c \ubd80\ubd84\uc774 \uc788\uc5c8\ub294\ub370, Windows \ub9e4\ud2b8\ub9ad\uc2a4\ub97c \ucd94\uac00\ud558\uc790\ub9c8\uc790 \ubc14\ub85c \ub4dc\ub7ec\ub0ac\ub2e4. \uae30\uc874 \ucf54\ub4dc\uc5d0\uc11c \uc774\ub7f0 \ubd80\ubd84\uc774 7\uad70\ub370\ub098 \uc788\uc5c8\ub2e4. \ub9e4\ud2b8\ub9ad\uc2a4 \ud14c\uc2a4\ud2b8\uac00 \uc5c6\uc5c8\uc73c\uba74 \uc601\uc6d0\ud788 \ubab0\ub790\uc744 \uac83\ub4e4\uc774\ub2e4.<\/p>\n<p>\uadf8\ub9ac\uace0 macOS runner\ub294 Linux \ub300\ube44 \ube4c\ub4dc \ubd84(minutes)\uc744 10\ubc30 \uc18c\ubaa8\ud55c\ub2e4. \ubb34\ub8cc \ud50c\ub79c\uc744 \uc4f4\ub2e4\uba74 macOS\ub294 \uaf2d \ud544\uc694\ud55c \uacbd\uc6b0\uc5d0\ub9cc \ud3ec\ud568\uc2dc\ucf1c\uc57c \ud55c\ub2e4. \ub098\ub294 <code>main<\/code> \ube0c\ub79c\uce58 push \ub54c\ub9cc macOS \uc870\ud569\uc744 \uc2e4\ud589\ud558\uace0, PR\uc5d0\uc11c\ub294 Linux\ub9cc \ub3cc\ub9ac\ub3c4\ub85d \ubd84\ub9ac\ud588\ub2e4. \uc6d4\uac04 \ubb34\ub8cc \ud55c\ub3c4\ub97c \ub109\ub109\ud558\uac8c \uc4f8 \uc218 \uc788\uc5c8\ub2e4.<\/p>\n<h2>\uc2e4\uc81c \ubc30\ud3ec\uae4c\uc9c0: Secrets \uad00\ub9ac\uc640 \ud658\uacbd \ubd84\ub9ac<\/h2>\n<p>CI\uac00 \uc548\uc815\ud654\ub418\uba74 \uc790\uc5f0\uc2a4\ub7fd\uac8c CD\uae4c\uc9c0 \uc5f0\uacb0\ud558\uace0 \uc2f6\uc5b4\uc9c4\ub2e4. \uc5ec\uae30\uc11c \uac00\uc7a5 \uc911\uc694\ud55c \uac8c secrets \uad00\ub9ac\uc640 \ud658\uacbd \ubd84\ub9ac\ub2e4.<\/p>\n<p>GitHub repository\uc758 <code>Settings \u2192 Secrets and variables \u2192 Actions<\/code>\uc5d0\uc11c secrets\ub97c \ucd94\uac00\ud55c\ub2e4. \uc6cc\ud06c\ud50c\ub85c\uc6b0\uc5d0\uc11c\ub294 \uc774\ub807\uac8c \ucc38\uc870\ud55c\ub2e4:<\/p>\n<pre><code class=\"language-yaml\">deploy:\n  needs: test        # test job\uc774 \uc131\uacf5\ud574\uc57c\ub9cc \uc2e4\ud589\ub428\n  runs-on: ubuntu-22.04\n  environment: production   # \ud658\uacbd \ubcf4\ud638 \uaddc\uce59 \uc801\uc6a9\n  if: github.ref == 'refs\/heads\/main' &amp;&amp; github.event_name == 'push'\n\n  steps:\n    - uses: actions\/checkout@v4\n\n    - name: Python \uc124\uc815\n      uses: actions\/setup-python@v5\n      with:\n        python-version: &quot;3.12&quot;\n        cache: &quot;pip&quot;\n\n    - name: \ubc30\ud3ec \uc2e4\ud589\n      env:\n        DATABASE_URL: ${{ secrets.PROD_DATABASE_URL }}\n        API_KEY: ${{ secrets.PROD_API_KEY }}\n      run: |\n        pip install -r requirements.txt\n        python deploy.py\n<\/code><\/pre>\n<p><code>needs: test<\/code>\ub97c \ube60\ub728\ub9ac\uba74 \ud14c\uc2a4\ud2b8 \uacb0\uacfc\uc640 \ubb34\uad00\ud558\uac8c \ubc30\ud3ec\uac00 \uc2e4\ud589\ub41c\ub2e4. \ub2f9\uc5f0\ud55c \uac83 \uac19\uc9c0\ub9cc \uc2e4\uc81c\ub85c \uc774 \ubd80\ubd84\uc774 \ube60\uc9c4 \uc6cc\ud06c\ud50c\ub85c\uc6b0\ub97c \uc5ec\ub7ec \ubc88 \ubd24\ub2e4.<\/p>\n<p><code>environment: production<\/code>\uc744 \uc124\uc815\ud558\uace0 \ub098\uc11c GitHub UI\uc5d0\uc11c \ud574\ub2f9 \ud658\uacbd\uc5d0 <code>Required reviewers<\/code>\ub97c 1\uba85 \uc774\uc0c1 \uc9c0\uc815\ud574\ub450\ub294 \uac78 \uac15\ub825\ud788 \uad8c\uc7a5\ud55c\ub2e4. \ub098\ub294 \uae08\uc694\uc77c \uc624\ud6c4\uc5d0 \uc774 \uc124\uc815 \uc5c6\uc774 \ubc30\ud3ec\ub97c \uc790\ub3d9\ud654\ud588\ub2e4\uac00 \u2014 \ud14c\uc2a4\ud2b8\ub294 \uc804\ubd80 \ud1b5\uacfc\ud588\uc9c0\ub9cc \uc2e4\uc81c \uc11c\ube44\uc2a4\uc5d0\uc11c \ud658\uacbd\ubcc0\uc218 \ucc28\uc774\ub85c \uc5d0\ub7ec\uac00 \ub0ac\ub2e4. \uadf8 \uc774\ud6c4\ub85c\ub294 \ud504\ub85c\ub355\uc158 \ubc30\ud3ec\uc5d0 \ubc18\ub4dc\uc2dc \uc218\ub3d9 \uc2b9\uc778 \ub2e8\uacc4\ub97c \ub123\uace0 \uc788\ub2e4. \uae08\uc694\uc77c \uc624\ud6c4 \ubc30\ud3ec\ub294 \uc9c4\uc9dc \ud558\uc9c0 \ub9c8\ub77c.<\/p>\n<p>\ud55c \uac00\uc9c0 \ub367\ubd99\uc774\uba74 \u2014 <code>ENVIRONMENT: staging<\/code> \uac19\uc740 \ube44\ubbfc\uac10 \uac12\ub3c4 secrets\uc5d0 \ub123\ub294 \uacbd\uc6b0\ub97c \uc885\uc885 \ubcf4\ub294\ub370, \uc624\ud788\ub824 \ubd88\ud3b8\ud558\ub2e4. GitHub\ub294 2023\ub144 \uc5c5\ub370\uc774\ud2b8\uc5d0\uc11c secrets\uc640 variables\ub97c \ubd84\ub9ac\ud588\ub2e4. \ubbfc\uac10\ud558\uc9c0 \uc54a\uc740 \ud658\uacbd\ubcc4 \uc124\uc815\uc740 <code>vars<\/code>\uc5d0 \ub123\uace0, \uc9c4\uc9dc \ube44\ubc00 \uac12(API \ud0a4, DB URL, \uc778\uc99d\uc11c \ub4f1)\ub9cc <code>secrets<\/code>\uc5d0 \ub123\ub294 \uac8c \ub9de\ub2e4. \uad00\ub9ac\ud558\uae30\ub3c4 \ud6e8\uc52c \uc26c\uc6cc\uc9c4\ub2e4.<\/p>\n<hr \/>\n<p>\uc774\uc81c 2\ub2ec \ub118\uac8c \uc774 \uc124\uc815\uc73c\ub85c \uc6b4\uc601\ud558\uace0 \uc788\ub294\ub370, Jenkins \uc2dc\uc808\ubcf4\ub2e4 \ud655\uc2e4\ud788 \ud3b8\ud558\ub2e4. \ud300\uc6d0 \ub204\uad6c\ub098 \uc6cc\ud06c\ud50c\ub85c\uc6b0 \ud30c\uc77c\uc744 \uc77d\uace0 \uc774\ud574\ud560 \uc218 \uc788\uace0, \uc0c8\ub85c\uc6b4 \uac80\uc0ac\ub97c \ucd94\uac00\ud558\ub294 \uac83\ub3c4 \ud30c\uc77c \ud558\ub098 \uc218\uc815\ud558\uba74 \ub05d\uc774\ub2e4.<\/p>\n<p>\ucc98\uc74c\ubd80\ud130 \uc644\ubcbd\ud558\uac8c \ub9cc\ub4e4\ub824\uace0 \ud558\uc9c0 \ub9c8\ub77c. \uae30\ubcf8 CI\ubd80\ud130 \ub3cc\uc544\uac00\uac8c \ub9cc\ub4e4\uace0, \uce90\uc2f1\uc744 \ucd94\uac00\ud558\uace0, \uadf8 \ub2e4\uc74c\uc5d0 \ub9e4\ud2b8\ub9ad\uc2a4\ub098 CD\ub97c \ubd99\uc774\ub294 \uc21c\uc11c\ub85c \uac00\uc57c \ud55c\ub2e4. \uc2e4\uc81c\ub85c \ub098\ub3c4 \ucc98\uc74c\uc5d4 \uc138 \uac00\uc9c0\ub97c \ub3d9\uc2dc\uc5d0 \uc124\uc815\ud558\ub824\ub2e4\uac00 \ud55c\ucc38 \ud5e4\ub9f8\ub2e4 \u2014 \ubb50\uac00 \uc65c \uc548 \ub418\ub294\uc9c0 \ud30c\uc545\ud558\uae30\uac00 \ub108\ubb34 \ud798\ub4e4\uc5b4\uc9c4\ub2e4.<\/p>\n<p><code>uv<\/code>\ub97c \uc544\uc9c1 \uc548 \uc368\ubd24\ub2e4\uba74 \ub2e4\uc74c \ud504\ub85c\uc81d\ud2b8\uc5d0\uc11c \ud55c\ubc88 \uc2dc\ub3c4\ud574\ubcfc \ub9cc\ud558\ub2e4. \ube4c\ub4dc \uc2dc\uac04 \ub2e8\ucd95 \ud6a8\uacfc\uac00 \uc0dd\uac01\ubcf4\ub2e4 \ud06c\ub2e4.<\/p>\n<p><!-- Reviewed: 2026-03-09 | Status: ready_to_publish | Changes: meta_description expanded for coverage, fail-fast explanation tightened, Friday deploy line punched up, conclusion de-formalized (removed \"\ub0b4 \ucd94\ucc9c\uc740 \uc774\ub807\ub2e4:\" list structure), minor paragraph length variation added, cache-dependency-path aside made more conversational --><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Jenkins\uc5d0\uc11c GitHub Actions\ub85c \ub9c8\uc774\uadf8\ub808\uc774\uc158\ud558\uba70 \uc9c1\uc811 \uacaa\uc740 \ud568\uc815\ub4e4. pip \uce90\uc2f1\uc73c\ub85c \ube4c\ub4dc 8\ubd84\u21922\ubd84 \ub2e8\ucd95, \ud14c\uc2a4\ud2b8 \ub9e4\ud2b8\ub9ad\uc2a4 \ud568\uc815, macOS runner 10\ubc30 \uacfc\uae08, \ud504\ub85c\ub355\uc158 \ubc30\ud3ec secrets \uad00\ub9ac\uae4c\uc9c0.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"site-sidebar-layout":"default","site-content-layout":"","ast-site-content-layout":"default","site-content-style":"default","site-sidebar-style":"default","ast-global-header-display":"","ast-banner-title-visibility":"","ast-main-header-display":"","ast-hfb-above-header-display":"","ast-hfb-below-header-display":"","ast-hfb-mobile-header-display":"","site-post-title":"","ast-breadcrumbs-content":"","ast-featured-img":"","footer-sml-layout":"","ast-disable-related-posts":"","theme-transparent-header-meta":"","adv-header-id-meta":"","stick-header-meta":"","header-above-stick-meta":"","header-main-stick-meta":"","header-below-stick-meta":"","astra-migrate-meta-layouts":"default","ast-page-background-enabled":"default","ast-page-background-meta":{"desktop":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"ast-content-background-meta":{"desktop":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"footnotes":""},"categories":[1],"tags":[],"class_list":["post-247","post","type-post","status-publish","format-standard","hentry","category-general"],"_links":{"self":[{"href":"https:\/\/blog.rebalai.com\/ko\/wp-json\/wp\/v2\/posts\/247","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.rebalai.com\/ko\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.rebalai.com\/ko\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.rebalai.com\/ko\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.rebalai.com\/ko\/wp-json\/wp\/v2\/comments?post=247"}],"version-history":[{"count":1,"href":"https:\/\/blog.rebalai.com\/ko\/wp-json\/wp\/v2\/posts\/247\/revisions"}],"predecessor-version":[{"id":275,"href":"https:\/\/blog.rebalai.com\/ko\/wp-json\/wp\/v2\/posts\/247\/revisions\/275"}],"wp:attachment":[{"href":"https:\/\/blog.rebalai.com\/ko\/wp-json\/wp\/v2\/media?parent=247"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.rebalai.com\/ko\/wp-json\/wp\/v2\/categories?post=247"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.rebalai.com\/ko\/wp-json\/wp\/v2\/tags?post=247"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}