본문 바로가기
C.W.K.
Stream
Lesson 02 of 08 · published

query()와 ClaudeSDKClient는 수명으로 골라

~16 min · query, ClaudeSDKClient, lifecycle

Level 0Observer
0 XP0/64 lessons0/13 achievements
0/150 XP to next level150 XP to go0% complete

한 번 실행과 지속 연결을 나눠

query(prompt, options)는 서브프로세스를 띄워 프롬프트 하나를 끝까지 처리하고 닫는 비동기 생성기야. ClaudeSDKClient(options)는 한 번 연결한 서브프로세스를 살려 두고 여러 메시지를 보내는 장기 클라이언트야. 기능 우열이 아니라 작업 수명의 차이야.

끝이 분명한 작업에는 query()

스크립트와 CI, 배치 변환처럼 일을 하나 끝낸 뒤 프로세스가 내려가도 되는 곳에 잘 맞아. 각 호출이 독립적이므로 상태 정리도 단순해. cwkFirebrand의 Claude 레그도 턴마다 query()를 한 번 부르고, 풀은 아예 없어.

대화와 운영자에는 지속 클라이언트

여러 메시지가 상태를 공유하는 채팅이나 오래 도는 운영 에이전트에는 ClaudeSDKClient가 맞아. 클라이언트는 턴마다 query()로 보내고 receive_response()로 받아. 이력은 그 뒤의 CLI 세션이 들고 있으니까 다시 보낼 필요가 없어. cwkPippa의 Claude 두뇌도 2026-05-14까지는 conversation_id마다 클라이언트 하나를 두고 이렇게 썼어. 지금은 턴마다 새 클라이언트를 띄우고 대화 전체를 다시 넣어. 자세한 건 아래 콜아웃에 있어.

원칙: 한 번이면 query(), 오래 이어지면 Client야. 같은 제품 안에서 섞어도 되지만 수명과 반대로 고르지는 마.

Code

query()로 one-shot·python
import asyncio
from claude_agent_sdk import AssistantMessage, ClaudeAgentOptions, TextBlock, query

async def explain_file(path: str):
    options = ClaudeAgentOptions(
        cwd="/Users/me/repo",
        tools=["Read"],          # 이 실행이 가진 기본 도구는 이것뿐: 편집도 셸도 없음
        allowed_tools=["Read"],  # 그리고 권한 프롬프트 없이 돌아
    )
    async for message in query(
        prompt=f"Read {path} and write a one-paragraph explanation of what it does.",
        options=options,
    ):
        if isinstance(message, AssistantMessage):
            for block in message.content:
                if isinstance(block, TextBlock):
                    print(block.text, end="")

asyncio.run(explain_file("src/main.py"))
Long-lived ClaudeSDKClient·python
import asyncio
from claude_agent_sdk import AssistantMessage, ClaudeAgentOptions, ClaudeSDKClient, TextBlock

def print_text(message):
    if isinstance(message, AssistantMessage):
        for block in message.content:
            if isinstance(block, TextBlock):
                print(block.text, end="")

async def chat_session():
    options = ClaudeAgentOptions(
        cwd="/Users/me/repo",
        system_prompt={"type": "preset", "preset": "claude_code"},
    )
    # 들어갈 때 connect(), 나올 때 disconnect(). 턴이 예외를 던져도.
    async with ClaudeSDKClient(options=options) as client:
        # 클라이언트 하나, 턴 둘: 그 사이 이력은 CLI 세션이 들고 있어.
        await client.query("What does this repo do?")
        async for message in client.receive_response():  # ResultMessage 뒤에 끝나
            print_text(message)
        await client.query("Add a CLI flag for verbose output.")
        async for message in client.receive_response():
            print_text(message)

asyncio.run(chat_session())

External links

Exercise

만들 기능 하나에 query()와 ClaudeSDKClient 중 하나를 고르고 수명으로 정당화해. 이미 구현했다면 선택이 맞는지 다시 봐.
Hint
일회성 스크립트가 지나치게 느리면 Client를, 채팅이 문맥을 잃으면 query를 잘못 썼을 수 있어.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인 — 댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.