์—…๋ฐ์ดํŠธ๋กœ ๋Œ์•„๊ฐ€๊ธฐ
New releaseSep 15, 2026

giskard-oss giskard-checks/v1.0.4

๐Ÿข LLM ์—์ด์ „ํŠธ์šฉ ์˜คํ”ˆ์†Œ์Šค ํ‰๊ฐ€ ๋ฐ ํ…Œ์ŠคํŠธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ

๊ณต์œ 

giskardlogo giskardlogo

์—์ด์ „ํŠธ ์‹œ์Šคํ…œ์„ ์œ„ํ•œ ํ‰๊ฐ€(Evals), ๋ ˆ๋“œ ํŒ€(Red Teaming) ๋ฐ ํ…Œ์ŠคํŠธ ์ƒ์„ฑ

๋ชจ๋“ˆํ˜•, ๊ฒฝ๋Ÿ‰, ๋™์  ๋ฐ Async ์šฐ์„ 

GitHub release License Downloads CI Giskard on Discord

๋ฌธ์„œ โ€ข ์›น์‚ฌ์ดํŠธ โ€ข ์ปค๋ฎค๋‹ˆํ‹ฐ


[!IMPORTANT] Giskard v3๋Š” AI ์—์ด์ „ํŠธ์˜ ๋™์  ๋‹ค์ค‘ ํ„ด ํ…Œ์ŠคํŠธ๋ฅผ ์œ„ํ•ด ์ƒˆ๋กญ๊ฒŒ ์žฌ์ž‘์„ฑ๋œ ๋ฒ„์ „์ž…๋‹ˆ๋‹ค. ์ด๋ฒˆ ๋ฆด๋ฆฌ์Šค๋Š” ํšจ์œจ์„ฑ์„ ๋†’์ด๊ธฐ ์œ„ํ•ด ๋ฌด๊ฑฐ์šด ์˜์กด์„ฑ์„ ์ œ๊ฑฐํ•˜๋ฉด์„œ, ๋” ๊ฐ•๋ ฅํ•œ AI ์ทจ์•ฝ์  ์Šค์บ๋„ˆ์™€ ํ–ฅ์ƒ๋œ RAG ํ‰๊ฐ€๋ฅผ ๋„์ž…ํ–ˆ์Šต๋‹ˆ๋‹ค. ๋‘ ๊ธฐ๋Šฅ ๋ชจ๋‘ ์ด์ œ giskard-scan์— ๊ธฐ๋ณธ ๋‚ด์žฅ๋˜์–ด v2์— ๋Œ€ํ•œ ์˜์กด์„ฑ์ด ์—†์Šต๋‹ˆ๋‹ค. ํ…Œ์ด๋ธ” ํ˜•์‹/ML ๋ชจ๋ธ์„ ์œ„ํ•œ ๋ ˆ๊ฑฐ์‹œ ์Šค์บ”๋งŒ v2 ์ „์šฉ์œผ๋กœ ์œ ์ง€๋ฉ๋‹ˆ๋‹ค. Giskard v2๋Š” ๊ณ„์† ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ๋” ์ด์ƒ ์ ๊ทน์ ์œผ๋กœ ์œ ์ง€๋ณด์ˆ˜๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ง„ํ–‰ ์ƒํ™ฉ์„ ํŒ”๋กœ์šฐํ•˜์„ธ์š” โ†’ v3 ๋ฐœํ‘œ ์ฝ๊ธฐ ยท ๋กœ๋“œ๋งต

์„ค์น˜

pip install giskard           # checks (+ agents, llm, core)
pip install "giskard[scan]"   # + ์ทจ์•ฝ์  / ํ’ˆ์งˆ ์Šค์บ”
pip install "giskard[openai]" # LLM ํŒ์ •/์ƒ์„ฑ๊ธฐ๋ฅผ ์œ„ํ•œ provider SDK

Python 3.12+ ํ•„์š”.

Extra์ถ”๊ฐ€ ํ•ญ๋ชฉ
(์—†์Œ)giskard-checks ๋ฐ ์˜์กด์„ฑ
scangiskard-scan
openai / anthropic / โ€ฆprovider SDK (pyproject.toml ์„ ํƒ ์˜์กด์„ฑ ์ฐธ์กฐ)

ํ…”๋ ˆ๋ฉ”ํŠธ๋ฆฌ: giskard-core๋ฅผ ํ†ตํ•œ ์„ ํƒ์  ์ง‘๊ณ„ ๋ถ„์„. ํ”„๋กฌํ”„ํŠธ๋‚˜ ์ถœ๋ ฅ์€ ์ „์†ก๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. Giskard๋ฅผ importํ•˜๊ธฐ ์ „์— ๋น„ํ™œ์„ฑํ™”: export DO_NOT_TRACK=1 ๋˜๋Š” export GISKARD_TELEMETRY_DISABLED=1. ์ž์„ธํ•œ ๋‚ด์šฉ: giskard-core README.


Giskard๋Š” ์—์ด์ „ํŠธ ์‹œ์Šคํ…œ์„ ํ…Œ์ŠคํŠธํ•˜๊ณ  ํ‰๊ฐ€ํ•˜๊ธฐ ์œ„ํ•œ ์˜คํ”ˆ์†Œ์Šค Python ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ž…๋‹ˆ๋‹ค. v3 ์•„ํ‚คํ…์ฒ˜๋Š” ๊ฐ๊ฐ ํ•„์š”ํ•œ ์˜์กด์„ฑ๋งŒ์„ ํฌํ•จํ•˜๋Š” ๋ชจ๋“ˆํ˜•์˜ ์ง‘์ค‘๋œ ํŒจํ‚ค์ง€ ์„ธํŠธ๋กœ, LLM, ๋ธ”๋ž™๋ฐ•์Šค ์—์ด์ „ํŠธ ๋˜๋Š” ๋‹ค๋‹จ๊ณ„ ํŒŒ์ดํ”„๋ผ์ธ ๋“ฑ ๋ฌด์—‡์ด๋“  ๋ž˜ํ•‘ํ•  ์ˆ˜ ์žˆ๋„๋ก ์ฒ˜์Œ๋ถ€ํ„ฐ ๊ตฌ์ถ•๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

์ƒํƒœํŒจํ‚ค์ง€์„ค๋ช…
โœ… ์•ˆ์ •giskard-checksํ…Œ์ŠคํŠธ ๋ฐ ํ‰๊ฐ€ โ€” ์‹œ๋‚˜๋ฆฌ์˜ค API, ๋‚ด์žฅ ๊ฒ€์‚ฌ, LLM-as-judge
โœ… ์•ˆ์ •giskard-scan์—์ด์ „ํŠธ ์ทจ์•ฝ์  ์Šค์บ๋„ˆ + RAG/ํ’ˆ์งˆ ํ‰๊ฐ€ โ€” ๋ ˆ๋“œ ํŒ€, ํ”„๋กฌํ”„ํŠธ ์ธ์ ์…˜, ํƒˆ์˜ฅ(jailbreaks) ๋ฐ ์œ ํ•ด ์ฝ˜ํ…์ธ  (vulnerability_scan, v2 Scan์˜ ํ›„์†), ์ง€์‹ ๋ฒ ์ด์Šค ํ’ˆ์งˆ ํ‰๊ฐ€ (quality_scan, v2 RAGET์˜ ํ›„์†)

์ด๋“ค์€ ์„ธ ๊ฐ€์ง€ ๊ธฐ๋ฐ˜ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ โ€” giskard-core(๊ณต์šฉ ์œ ํ‹ธ๋ฆฌํ‹ฐ ๋ฐ ํ…”๋ ˆ๋ฉ”ํŠธ๋ฆฌ), giskard-llm(provider์— ๊ตฌ์• ๋ฐ›์ง€ ์•Š๋Š” LLM ๋ผ์šฐํŒ…), giskard-agents(์—์ด์ „ํŠธ ๋ฐ ์›Œํฌํ”Œ๋กœ์šฐ ์˜ค์ผ€์ŠคํŠธ๋ ˆ์ด์…˜) โ€” ์œ„์— ๊ตฌ์ถ•๋˜๋ฉฐ, ์ž๋™์œผ๋กœ ์„ค์น˜๋˜๋ฉฐ ์ง์ ‘ ์‚ฌ์šฉ๋˜๋Š” ๊ฒฝ์šฐ๋Š” ๋“œ๋ญ…๋‹ˆ๋‹ค.

Giskard Checks โ€” ์—์ด์ „ํŠธ ํ…Œ์ŠคํŠธ๋ฅผ ์œ„ํ•œ ํ‰๊ฐ€ ์ƒ์„ฑ ๋ฐ ์ ์šฉ

pip install giskard-checks

Giskard Checks ๋Š” LLM ๊ธฐ๋ฐ˜ ์‹œ์Šคํ…œ์„ ํ…Œ์ŠคํŠธํ•˜๋Š” ํ‰๊ฐ€(evals)๋ฅผ ์ƒ์„ฑํ•˜๊ธฐ ์œ„ํ•œ ๊ฒฝ๋Ÿ‰ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ž…๋‹ˆ๋‹ค. ๋‹จ์ˆœํ•œ ๋‹จ์–ธ(assertion)๋ถ€ํ„ฐ LLM-as-judge ํ‰๊ฐ€๊นŒ์ง€ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ์กด์˜ ๋‹จ์œ„ ํ…Œ์ŠคํŠธ์™€ ๋‹ฌ๋ฆฌ, ํ‰๊ฐ€๋Š” ๋น„๊ฒฐ์ •์  ์ถœ๋ ฅ์„ ์œ„ํ•ด ์„ค๊ณ„๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๋™์ผํ•œ ์ž…๋ ฅ์ด ์„œ๋กœ ๋‹ค๋ฅธ ์œ ํšจํ•œ ์‘๋‹ต์„ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

Giskard Checks๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋‹ค์Œ์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:

  • ํšŒ๊ท€(regression) ๊ฐ์ง€ โ€” ๋ณ€๊ฒฝ ํ›„์—๋„ ์‹œ์Šคํ…œ์ด ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ๋™์ž‘ํ•˜๋Š”์ง€ ํ™•์ธ
  • RAG ํ’ˆ์งˆ ๊ฒ€์ฆ โ€” ๋‹ต๋ณ€์ด ๊ฒ€์ƒ‰๋œ ์ปจํ…์ŠคํŠธ์— ๊ทผ๊ฑฐํ•˜๋Š”์ง€ ํ™•์ธ
  • ์•ˆ์ „ ๊ทœ์น™ ์ ์šฉ โ€” ์ถœ๋ ฅ์ด ์ฝ˜ํ…์ธ  ์ •์ฑ…์„ ์ค€์ˆ˜ํ•˜๋Š”์ง€ ํ™•์ธ
  • ๋‹ค์ค‘ ํ„ด ์—์ด์ „ํŠธ ํ‰๊ฐ€ โ€” ๋‹จ์ผ ๊ตํ™˜์ด ์•„๋‹Œ ์ „์ฒด ๋Œ€ํ™” ํ…Œ์ŠคํŠธ

๋‚ด์žฅ ํ‰๊ฐ€์—๋Š” ๋ฌธ์ž์—ด ๋งค์นญ, ๋น„๊ต, ์ •๊ทœ์‹, ์˜๋ฏธ๋ก ์  ์œ ์‚ฌ์„ฑ ๋ฐ LLM-as-judge ๊ฒ€์‚ฌ(Groundedness, Conformity, LLMJudge)๊ฐ€ ํฌํ•จ๋ฉ๋‹ˆ๋‹ค.

๊ฐœ๋…

  • Target โ€” ํ…Œ์ŠคํŠธ ๋Œ€์ƒ ์‹œ์Šคํ…œ: ๋ชจ๋“  ๋™๊ธฐ/๋น„๋™๊ธฐ ํ˜ธ์ถœ ๊ฐ€๋Šฅ ๊ฐ์ฒด (inputs) -> outputs (์„ ํƒ์ ์œผ๋กœ trace ํฌํ•จ)
  • Scenario โ€” ํ•˜๋‚˜์˜ ํ‰๊ฐ€: ์ƒํ˜ธ์ž‘์šฉ + ๊ฒ€์‚ฌ
  • Check โ€” ํŠธ๋ ˆ์ด์Šค์— ๋Œ€ํ•œ ๋‹จ์–ธ ๋˜๋Š” LLM ํŒ์ •
  • Suite โ€” ํ•จ๊ป˜ ์‹คํ–‰๋˜๋Š” ์—ฌ๋Ÿฌ ์‹œ๋‚˜๋ฆฌ์˜ค

giskard.agents.Generator๋Š” ์›Œํฌํ”Œ๋กœ์šฐ/ํŒ์ •์„ ์œ„ํ•œ LLM ํด๋ผ์ด์–ธํŠธ์ž…๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž ๋ฉ”์‹œ์ง€๋ฅผ ํ•ฉ์„ฑํ•˜๋Š” giskard.checks ์ž…๋ ฅ ์ƒ์„ฑ๊ธฐ(LLMGenerator)์™€๋Š” ๋‹ค๋ฆ…๋‹ˆ๋‹ค.

๋น ๋ฅธ ์‹œ์ž‘

import asyncio
from giskard.checks import Scenario, Groundedness


def get_answer(inputs: str) -> str:
    return "Paris"  # ๋ชจ๋ธ / ์—์ด์ „ํŠธ๋กœ ๊ต์ฒด


async def main() -> None:
    scenario = (
        Scenario("test_france_capital")
        .interact(inputs="What is the capital of France?", outputs=get_answer)
        .check(
            Groundedness(
                name="answer is grounded",
                context="France is in Western Europe. Its capital is Paris.",
            )
        )
    )
    result = await scenario.run()
    result.print_report()


asyncio.run(main())

Groundedness๋Š” LLM ํŒ์ •์ž…๋‹ˆ๋‹ค. provider extra(์˜ˆ: pip install "giskard[openai]")๋ฅผ ์„ค์น˜ํ•˜๊ณ  ํ•ด๋‹น API ํ‚ค๋ฅผ ์„ค์ •ํ•˜์„ธ์š”. ๊ธฐ๋ณธ ๋ชจ๋ธ: openai/gpt-4o-mini.

Suites, LLMJudge, ๋‹ค์ค‘ ํ„ด ์‹œ๋‚˜๋ฆฌ์˜ค ๋“ฑ์— ๋Œ€ํ•œ ์ž์„ธํ•œ ๋‚ด์šฉ์€ ์ „์ฒด ๋ฌธ์„œ๋ฅผ ์ฐธ์กฐํ•˜์„ธ์š”.


Giskard Scan โ€” AI ์—์ด์ „ํŠธ์šฉ ์ทจ์•ฝ์  ์Šค์บ๋„ˆ

pip install "giskard[scan]"   # ๋˜๋Š”: pip install giskard-scan

Giskard Scan์€ ์—์ด์ „ํŠธ ์‹œ์Šคํ…œ์„ ์œ„ํ•œ ๋ ˆ๋“œ ํŒ€ ๋ฐ ์ทจ์•ฝ์  ์Šค์บ๋‹ ๊ณ„์ธต์ž…๋‹ˆ๋‹ค. ์—์ด์ „ํŠธ์— ๋Œ€ํ•œ ์ผ๋ฐ˜ ์–ธ์–ด ์„ค๋ช…์—์„œ ์ ๋Œ€์  ํ…Œ์ŠคํŠธ ์Šค์œ„ํŠธ๋ฅผ ์ž๋™์œผ๋กœ ์ƒ์„ฑํ•˜๋ฉฐ, ํ”„๋กฌํ”„ํŠธ ์ธ์ ์…˜, ์œ ํ•ด ์ฝ˜ํ…์ธ , ๊ณ ์ •๊ด€๋…, ์ž˜๋ชป๋œ ์ •๋ณด ๋“ฑ์„ ๋‹ค๋ฃน๋‹ˆ๋‹ค.

Giskard Scan์„ ์‚ฌ์šฉํ•˜์—ฌ ๋‹ค์Œ์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:

  • ์—์ด์ „ํŠธ ๋ ˆ๋“œ ํŒ€ โ€” OWASP LLM Top-10 ์œ„ํ˜‘ ๋ฒ”์ฃผ์— ๊ฑธ์ณ ์ ๋Œ€์  ์ž…๋ ฅ ์ž๋™ ์ƒ์„ฑ
  • ํ”„๋กฌํ”„ํŠธ ์ธ์ ์…˜ ํ”„๋กœ๋ธŒ ์‹คํ–‰ โ€” ์ฆ‰์‹œ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์ธ์ ์…˜ ํŽ˜์ด๋กœ๋“œ ๋‚ด์žฅ ๋ฐ์ดํ„ฐ์…‹
  • ์‚ฌ์šฉ์ž ์ •์˜ ์ƒ์„ฑ๊ธฐ๋กœ ํ™•์žฅ โ€” generate_suite์— ์ž์ฒด ScenarioGenerator ์ธ์Šคํ„ด์Šค๋ฅผ ์ „๋‹ฌํ•˜๊ฑฐ๋‚˜ vulnerability_suite_generator_registry์— ๋“ฑ๋ก

๋น ๋ฅธ ์‹œ์ž‘

import asyncio
from giskard.scan import vulnerability_scan


async def my_agent(inputs: str) -> str:
    # ์—์ด์ „ํŠธ / ๋ชจ๋ธ ํ˜ธ์ถœ๋กœ ๊ต์ฒด
    return f"Echo: {inputs}"


async def main() -> None:
    await vulnerability_scan(
        target=my_agent,
        description="A customer support chatbot for an e-commerce platform.",
        languages=["en"],
    )


asyncio.run(main())

์Šค์บ” ์ƒ์„ฑ๊ธฐ์—๋Š” ์œ„์˜ Checks ํŒ์ •๊ณผ ๋™์ผํ•˜๊ฒŒ LLM provider extra์™€ API ํ‚ค๋„ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

Giskard v2๋ฅผ ์ฐพ๊ณ  ๊ณ„์‹ ๊ฐ€์š”?

Giskard v2์—๋Š” Scan(์ž๋™ ์ทจ์•ฝ์  ํƒ์ง€)๊ณผ RAGET(RAG ํ‰๊ฐ€ ํ…Œ์ŠคํŠธ ์„ธํŠธ ์ƒ์„ฑ)์ด ํฌํ•จ๋˜์–ด ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

LLM ์—์ด์ „ํŠธ์˜ ๊ฒฝ์šฐ, ๋‘˜ ๋‹ค v3์—์„œ giskard-scan์œผ๋กœ ๋Œ€์ฒด๋˜์—ˆ์Šต๋‹ˆ๋‹ค: v2 LLM ์Šค์บ” ๋Œ€์‹  vulnerability_scan์„ ์‚ฌ์šฉํ•˜๊ณ , RAGET ๋Œ€์‹  quality_scan(KnowledgeBase ํฌํ•จ)์„ ์‚ฌ์šฉํ•˜์„ธ์š”.

v3๋Š” ML ๋ชจ๋ธ์—์„œ๋„ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค. ๋ชจ๋ธ์„ target์œผ๋กœ ๋ž˜ํ•‘ํ•˜๊ณ  giskard-checks ๋˜๋Š” giskard-scan์œผ๋กœ ํ‰๊ฐ€ํ•˜์„ธ์š”. ์•„๋ž˜ ์˜ˆ์ œ๊ฐ€ ๋‹ค๋ฃจ๋Š” ๊ฒƒ์€ v2 ์ „์šฉ ์ž๋™ ํ…Œ์ด๋ธ” ํ˜•์‹ ์Šค์บ”์ž…๋‹ˆ๋‹ค. ์ด๋Š” giskard.Model + giskard.Dataset์„ ๊ฒ€์‚ฌํ•˜์—ฌ ์„ฑ๋Šฅ, ํŽธํ–ฅ ๋ฐ ๊ฒฌ๊ณ ์„ฑ ๋ฌธ์ œ๋ฅผ ์ž๋™ ๊ฐ์ง€ํ•˜๋Š” ํƒ์ง€๊ธฐ ์Šค์œ„ํŠธ์ด๋ฉฐ, giskard.testing ML ํ…Œ์ŠคํŠธ ์Šค์œ„ํŠธ์™€ Giskard Hub๋„ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ๊ธฐ๋Šฅ์€ v3์— ๊ณ„ํš๋˜์–ด ์žˆ์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

pip install "giskard[llm]>2,<3"

Scan โ€” ์„ฑ๋Šฅ, ํŽธํ–ฅ ๋ฐ ๋ณด์•ˆ ๋ฌธ์ œ ์ž๋™ ๊ฐ์ง€

๋ชจ๋ธ์„ ๋ž˜ํ•‘ํ•˜๊ณ  ์Šค์บ”์„ ์‹คํ–‰ํ•˜์„ธ์š”:

import giskard
import pandas as pd


# my_llm_chain์„ ์‹ค์ œ LLM ์ฒด์ธ ๋˜๋Š” ๋ชจ๋ธ ์ถ”๋ก  ๋กœ์ง์œผ๋กœ ๊ต์ฒด
def model_predict(df: pd.DataFrame):
    """์ด ํ•จ์ˆ˜๋Š” DataFrame์„ ๋ฐ›์•„ ์ถœ๋ ฅ ๋ชฉ๋ก(ํ–‰๋‹น ํ•˜๋‚˜)์„ ๋ฐ˜ํ™˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค."""
    return [my_llm_chain.run({"query": question}) for question in df["question"]]


giskard_model = giskard.Model(
    model=model_predict,
    model_type="text_generation",
    name="My LLM Application",
    description="A question answering assistant",
    feature_names=["question"],
)

scan_results = giskard.scan(giskard_model)
display(scan_results)

Scan Example

RAGET โ€” RAG ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์šฉ ํ‰๊ฐ€ ๋ฐ์ดํ„ฐ์…‹ ์ƒ์„ฑ

์ง€์‹ ๋ฒ ์ด์Šค์—์„œ ์งˆ๋ฌธ, ์ฐธ์กฐ ๋‹ต๋ณ€ ๋ฐ ์ปจํ…์ŠคํŠธ๋ฅผ ์ž๋™ ์ƒ์„ฑ:

import pandas as pd
from giskard.rag import generate_testset, KnowledgeBase

# ์ง€์‹ ๋ฒ ์ด์Šค ๋ฌธ์„œ ๋กœ๋“œ
df = pd.read_csv("path/to/your/knowledge_base.csv")
knowledge_base = KnowledgeBase.from_pandas(df, columns=["column_1", "column_2"])

testset = generate_testset(
    knowledge_base,
    num_questions=60,
    language="en",
    agent_description="A customer support chatbot for company X",
)

RAGET Example

์ „์ฒด v2 ๋ฌธ์„œ

๐Ÿ‘‹ ์ปค๋ฎค๋‹ˆํ‹ฐ

AI ์ปค๋ฎค๋‹ˆํ‹ฐ์˜ ๊ธฐ์—ฌ๋ฅผ ํ™˜์˜ํ•ฉ๋‹ˆ๋‹ค! ์ด ๊ฐ€์ด๋“œ๋ฅผ ์ฝ๊ณ  ์‹œ์ž‘ํ•˜๊ณ , Discord์—์„œ ํ™œ๋ฐœํ•œ ์ปค๋ฎค๋‹ˆํ‹ฐ์— ์ฐธ์—ฌํ•˜์„ธ์š”.

์ง„ํ–‰ ์ƒํ™ฉ์„ ํŒ”๋กœ์šฐํ•˜๊ณ  ํ”ผ๋“œ๋ฐฑ์„ ๊ณต์œ ํ•˜์„ธ์š”: v3 ๋ฐœํ‘œ ยท ๋กœ๋“œ๋งต

๐ŸŒŸ ๋ณ„ํ‘œ๋ฅผ ๋‚จ๊ฒจ์ฃผ์„ธ์š”, ํ”„๋กœ์ ํŠธ๊ฐ€ ๋‹ค๋ฅธ ์‚ฌ๋žŒ๋“ค์—๊ฒŒ ๋ฐœ๊ฒฌ๋˜๊ณ  ๋ฉ‹์ง„ ์˜คํ”ˆ์†Œ์Šค ๋„๊ตฌ๋ฅผ ๊ตฌ์ถ•ํ•˜๋Š” ๋ฐ ๋™๊ธฐ๋ถ€์—ฌ๊ฐ€ ๋ฉ๋‹ˆ๋‹ค! ๐ŸŒŸ

โค๏ธ ์ €ํฌ ์ž‘์—…์ด ์œ ์šฉํ•˜๋‹ค๊ณ  ์ƒ๊ฐ๋˜์‹œ๋ฉด GitHub์—์„œ ํ›„์›์„ ๊ณ ๋ คํ•ด ์ฃผ์„ธ์š”. ์›”๊ฐ„ ํ›„์›์„ ํ†ตํ•ด ์Šคํฐ์„œ ๋ฐฐ์ง€๋ฅผ ๋ฐ›๊ณ , ์ด readme์— ํšŒ์‚ฌ๋ฅผ ํ‘œ์‹œํ•˜๋ฉฐ, ๋ฒ„๊ทธ ๋ณด๊ณ ๋ฅผ ์šฐ์„  ์ฒ˜๋ฆฌ๋ฐ›์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ ์ปจ์„คํŒ… ํ”„๋กœ์ ํŠธ ์ฐธ์—ฌ, ์›Œํฌ์ˆ ์ง„ํ–‰ ๋˜๋Š” ํšŒ์‚ฌ์—์„œ ๊ฐ•์—ฐ์„ ์›ํ•˜์‹œ๋ฉด ์ผํšŒ์„ฑ ํ›„์›๋„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

์นดํ…Œ๊ณ ๋ฆฌ