들어가며
첫 컨퍼런스 후기글이다!
지난 11일 토요일, GDG Korea Android에서 주최한 ‘Build with AI 2026’ 컨퍼런스에 다녀왔다.
AI Agent를 직접 만들어볼 수 있다는 이야기가 꽤 흥미롭게 다가와 덜컥 신청했다. AI 관련 컨퍼런스에 참여하는건 이번이 처음이었다. AI에 대해 무지했기에 잘 따라갈 수 있을까하는 약간의 걱정도 있었다.
하지만 AI가 이미 개발의 판도를 크게 바꿔놓았고, 앞으로도 많은 변화를 가져다줄 것이기에 AI와 친해질 필요가 있다고 생각했다.
이번 컨퍼런스가 그런 좋은 기회라고 느꼈고, 다녀오고 난 지금은 참석하길 정말 잘했다는 생각이 든다.
이번 컨퍼런스에서 보고 느낀 것, 그리고 배운 것들을 여기에 정리해보려 한다.
Build with AI 2026 - GDG Korea Android

- 주최: GDG Korea Android
- 장소: 컬리 본사(서울 강남구 테헤란로 133 한국 타이어빌딩 18층)
- 일시: 2026.04.11.(토) 14:00~17:00
컬리 구경
사실 이 행사에 참석한 목적 중 하나는 컬리 본사를 구경하는 것이었다. 겸사겸사 컬리 본사를 볼 수 있는 좋은 기회였다.
행사 당일 지각을 하는 바람에, 입장 후 바로 세션에 참여하느라 행사 도중에는 내부를 구경할 정신이 없었다. 행사가 다 끝나고 나서야 한적해진 컬리를 살펴볼 수 있었다.
행사 중에는 신경쓰지 못했던 각종 인테리어가 눈에 띄었다.


입구에는 Kurly 로고가 반겨주고 있고, 전체적으로 마치 북카페처럼 편안한 인테리어로 꾸며져 있었다. 일반적인 회사 사무실 분위기가 아니었다. 또 화분이 곳곳에 놓여있어 분위기를 한층 더 편안하게 만들어주었다.

특히 각종 큼지막한 식재료들이 식물과 잘 어우러져있는 것이 재미있었다.

배인지 사과인지 모를 과일도 있었고, (검색해보니 시나노골드 사과인 것 같다)


화분인 척하는 브로콜리도 발견했다.
예쁜 컬리 내부를 보니, 언젠가 이렇게 기업의 아이덴티티가 도드라지는 회사에서 근무하고 싶다는 생각이 들었다.
Hands-On Session: Agent, Koog Koog 하세요 - Kotlin으로 만드는 AI 코드리뷰 Agent(feat. Gemini)
첫 번째 세션은 현우님이 진행하시는 핸즈온 세션으로, 직접 AI Agent를 만들어보는 시간이었다. 코드 리뷰를 수행하는 Agent를 만들어보았는데, 미리 만들어주신 GitHub 레포지토리를 클론해서 진행했고, 코드랩도 직접 꼼꼼하게 만들어주셔서 설명을 잠시 놓쳤더라도 코드랩의 설명을 참고하면 금방 따라갈 수 있었다.
Koog라는 프레임워크를 사용하여 Kotlin 코드로 AI Agent를 설계할 수 있었다.
Koog: JVM-native framework by JetBrains for building AI agents
Koog is a framework for building scalable and enterprise-ready AI agents across all platforms – including JVM, Android, iOS, JavaScript, and WebAssembly.
www.jetbrains.com
Koog 프레임워크란?
JetBrains의 Koog 공식 문서에는 아래와 같이 설명되어 있다.
Koog is an open-source JetBrains framework for building AI agents designed specifically for the JVM ecosystem. It provides a first-class development experience for both Kotlin and Java developers, featuring an idiomatic, type-safe Kotlin DSL and fluent builder-style Java APIs.
While Java developers can leverage the full power of Koog on the JVM using idiomatic APIs, Kotlin developers can also deploy agents across JS, WasmJS, Android, and iOS targets using Kotlin Multiplatform.
Koog는 JVM 생태계에 특화되어 설계된 AI Agent 구축용 오픈소스 JetBrains 프레임워크입니다. Koog는 Kotlin 개발자와 Java 개발자 모두에게 최상의 개발 환경을 제공하며, 관용적이고 타입 안정성이 있는 Kotlin DSL과 유연한 빌더 스타일의 Java API를 특징으로 합니다.
Java 개발자는 관용적인 API를 사용하여 JVM에서 Koog의 모든 기능을 활용할 수 있으며, Kotlin 개발자는 Kotlin Multiplatform을 사용하여 JS, WasmJS, Android 및 iOS를 타겟으로 한 에이전트를 배포할 수도 있습니다.
Koog는 JVM 환경에서 돌아가는 AI Agent를 만들 수 있는 오픈소스 프레임워크이다.
Kotlin DSL을 지원하여 자연스럽고 타입 안정성이 있는 코드를 작성할 수 있고, 빌더 형식의 Java API도 함께 지원해 유연하게 개발할 수 있다.
무엇보다 KMP로 여러 플랫폼에서 사용할 Agent를 구축할 수 있다는 점이 매력적이었다.
AI Agent란?
챗봇과 AI Agent의 차이
챗봇과 AI Agent와의 차이가 무엇인지부터 짚고 넘어가면서 전체적인 개념을 이해시켜주셨다.
간단하게 비교하자면, 챗봇은 질문에 대해 1회성으로 답변만 하는 수동적인 역할인 반면, AI Agent는 사용자의 요청을 분석하고 필요한 작업을 스스로 판단해 수행하는 능동적인 주체라고 할 수 있다.
| 챗봇 | AI Agent | |
| 입력 | 질문 | 목표 / 작업 |
| 처리 | 1회성 응답 | 반복적 추론 + 행동 |
| 도구 | 없음 | 파일 읽기, 검색, API 호출 등 |
| 자율성 | 수동적 | 능동적 |
| 예시 | 은행 챗봇, ChatGPT, Gemini, Claude 등 | Claude Code, AutoGPT, Manus 등 |
Agent의 구성 요소
AI Agent는 크게 4가지 구성 요소로 이루어져 있다.
- System Prompt : 에이전트의 역할과 수행할 목표를 정의한다.
- Prompt Executor : 시스템 프롬프트를 실행하는 주체이다.
- Tool Registry : 에이전트가 사용할 수 있는 도구가 정의된 도구 목록이다. (LLM이 사용하는 공구 상자)
- Event Handler : 에이전트가 수행하는 작업을 관찰/로깅 한다.
AI Agent는 텍스트를 이해하고 생성하는 AI 모델인 LLM(Large Language Model)을 활용한다. 이 LLM에게 역할(시스템 프롬프트)과 도구를 부여해서, 단순 텍스트 생성을 넘어 실제 작업을 수행할 수 있게 만드는 구조이다.
Koog 프레임워크의 핵심 구성요소를 활용하여 이러한 구조를 만들어낸다.
| 클래스 | 역할 |
| GoogleLLMClient | Google Gemini API와 통신하는 LLM 클라이언트 |
| MultiLLMPromptExecutor | LLM에게 프롬프트를 실행하는 실행기 |
| AIAgent | 시스템 프롬프트, 모델, 도구를 조합한 에이전트 |
코드로 간단하게 살펴보면 아래와 같이 사용할 수 있다.
val llmClient = GoogleLLMClient(apiKey = apiKey) // GCP의 API 키
val executor = MultiLLMPromptExecutor(llmClient)
val agent = AIAgent(
promptExecutor = executor,
llmModel = GoogleModels.Gemini2_5Flash, // 여기서 원하는 모델을 설정할 수도 있다.
systemPrompt = "당신은 친구 같은 AI 에이전트입니다."
)
Google Cloud의 프로젝트로부터 발급받은 API 키를 활용해 Google Gemini API를 호출하는 방식으로 LLM에 접근할 수 있는데, GoogleLLMClient가 그 작업을 수행한다.
MultiLLMPromptExecutor는 이 클라이언트를 활용해 시스템 프롬프트를 실행하는 실행기 역할을 한다.
그리고 해당 Executor를 사용하여 AI Agent 인스턴스를 생성할 수 있다.
시스템 프롬프트로 역할 부여하기
평소 AI를 자주 활용하신 분들이라면, 대화창에 AI에게 구체적인 역할과 규칙을 마크다운 형식으로 작성해서 답변을 받아본 경험이 있을 것이다.
시스템 프롬프트도 이와 동일한 방식으로 작성할 수 있었다. 구체적인 역할과 출력 형식, 규칙 등을 자세하고 간략하게 명시한다.
아래는 핸즈온 세션에서 활용된 프롬프트 예시이다. 코드 리뷰 Agent의 역할과 코드 리뷰 규칙이 명시되어 있다.
# Kode Review - Kotlin 코드 리뷰 에이전트
## 역할
당신은 Kotlin/JVM 프로젝트를 전문으로 리뷰하는 시니어 코드 리뷰어입니다.
사용자가 제출한 코드를 분석하고, 구체적이고 실행 가능한 피드백을 제공합니다.
코드를 직접 수정하지 않으며, 리뷰 의견만 제공합니다.
## 심각도 수준
- **[CRITICAL]**: 즉시 수정 필요. 런타임 오류, 데이터 손실, 보안 취약점 유발 가능
- **[WARNING]**: 수정 권장. 잠재적 버그, 성능 저하, 유지보수 어려움 유발 가능
- **[SUGGESTION]**: 개선 제안. 코드 품질, 가독성, Kotlin 관용구 활용 향상
- **[NITPICK]**: 사소한 스타일/컨벤션 의견. 선택적 반영
## 행동 규칙
1. 항상 코드를 직접 읽고 확인한 후 리뷰합니다. 추측하지 않습니다.
2. 문제를 지적할 때 반드시 개선 방향 또는 코드 예시를 함께 제시합니다.
3. 한국어로 응답합니다.
Agent가 작업을 수행하는 도구 만들기
Agent에게 역할을 부여했으니, AI가 다른 작업을 수행할 수 있도록 손과 발, 그리고 공구를 쥐어줄 차례다.
AI Agent가 텍스트 생성 이외에 파일 읽기 및 쓰기, API 호출 등의 다른 작업을 할 수 있는 도구(Tool)를 만들 수 있다.
Function Calling
그런데 프롬프트 입력에 대해 응답을 자연어로 생성할 뿐인 LLM이 어떻게 텍스트 생성 이외의 다른 작업을 수행할 수 있는걸까?
이를 가능케하는 메커니즘이 바로 '함수 호출(Function Calling)' 이다.
LLM은 프롬프트를 전달 받을 때, 사용할 수 있는 도구 목록인 ToolRegistry도 함께 전달 받는다. 여기 안에는 각 도구의 이름, 사용 목적과 필요한 파라미터에 대한 설명이 포함되어 있다.
만약 "UserRepository.kt를 분석해줘."라는 프롬프트를 받았다면, LLM은 UserRepository.kt 파일을 읽어야하는 상황이라고 '추론'한다.
이후 파일을 읽는 도구를 호출하기 위해 JSON 형식의 요청을 생성해 전달하고, 해당 요청을 Koog 프레임워크가 전달 받아 파싱한다. 그리고 Tool 어노테이션이 붙은 함수를 호출하여 실제로 파일을 읽는다.
프레임워크가 읽은 파일 내용은 다시 LLM에게 전송되어 코드 분석을 수행할 수 있다.
즉, LLM이 직접 파일을 읽어들이는 것이 아니라, LLM이 도구를 사용할 상황을 추측하고, 프레임워크에게 함수 호출을 요청하고, 함수 호출 결과를 다시 LLM이 전달 받는 과정으로 도구가 사용되는 것이다.
도구 선언하기
Koog에서 두 가지의 어노테이션을 사용해 에이전트가 호출할 수 있는 함수(도구)를 선언하면 된다.
| 어노테이션 | 위치 | 역할 |
| @Tool("이름") | 함수 | LLM이 호출할 도구 이름 지정 |
| @LLMDescription("설명") | 함수/파라미터 | LLM에게 도구와 파라미터의 목적을 설명 |
@Tool과 @LLMDescription는 도구 이름과 도구 사용 목적을 명시해 LLM에게 도구 정보를 제공함과 동시에, 함수 호출 요청 JSON을 받은 에이전트가 해당 도구를 호출할 수 있게 해주는 이름표 역할을 한다.
@Tool("readFile")
@LLMDescription("주어진 경로의 파일 내용을 읽어서 반환합니다.")
fun readFile(
@LLMDescription("읽을 파일의 경로")
path: String
): String {
// 함수 본문 구현
}
도구 적용하기
선언한 도구를 AIAgent에 전달하여 Agent가 도구를 사용할 수 있도록 해보자.
우선 아래와 같이 ToolRegistry를 정의한다. 함수 참조를 Reflection으로 넘겨주며, 이 때 아래 tool 함수를 꼭 import 해야한다. 그렇지 않으면 린트 에러가 떠서 빌드가 불가능하다.
import ai.koog.agents.core.tools.reflect.tool
import my.agent.project.path.tools.readFile
// Tool Registry 정의
private val registry = ToolRegistry {
tool(::readFile)
}
그리고 AIAgent 인스턴스 생성 시 toolRegistry 인자에 정의한 Tool Registry를 넘겨주면 된다.
import ai.koog.agents.core.tools.ToolRegistry
import ai.koog.agents.core.tools.reflect.tool
import my.agent.project.path.tools.readFile
private val registry = ToolRegistry {
tool(::readFile)
}
// AI Agent 인스턴스 생성
val agent = AIAgent(
promptExecutor = executor,
llmModel = GoogleModels.Gemini2_5Flash,
systemPrompt = systemPrompt,
toolRegistry = registry, // Tool Registry 전달
)
이벤트 핸들러로 Agent가 하는 작업 훔쳐보기
LLM은 블랙 박스이기 때문에, Agent가 지금 무슨 작업을 하고 있는지, 즉, 언제 어떤 도구를 호출하는지 눈으로 보기 어렵다
그러나 Koog는 Agent가 현재 수행하는 작업을 보여주는 편리한 기능을 지원한다. Koog의 EventHandler 피처를 Agent에 설치하면 도구 호출 흐름을 실시간으로 관찰할 수 있다.
EventHandler는 AIAgent의 생명주기 이벤트를 구독할 수 있는 Koog 내장 피처라고 한다. installFeatures DSL을 통해 에이전트에 설치할 수 있다.
ReAct 패턴: 추론하고 행동하기
Koog는 어떻게 Agent의 도구 호출 흐름을 알 수 있는 것일까? 이는 Koog가 ReAct 패턴에서 발생한 이벤트를 관찰하기 때문이다.
Agent가 도구를 사용하는 방식은 ReAct(Reasoning + Acting) 패턴을 따른다.
LLM이 "생각 → 행동 → 관찰"을 반복하면서 복잡한 작업을 단계적으로 해결한다. Koog 프레임워크가 각 작업마다 이벤트를 발생시키고, 이 이벤트에 담긴 정보로 현재 LLM이 수행 중인 작업을 알 수 있는 방식이다. 따라서 Agent에 EventHandler를 설치하면 이러한 과정을 실시간으로 훔쳐볼 수 있다.
val agent = AIAgent(
// ...
installFeatures = {
install(EventHandler) {
onToolCallStarting { println(" [도구 호출] ${it.toolName}"); it.toolName }
onToolCallCompleted { println(" [도구 완료] ${it.toolName}"); it.toolName }
onToolCallFailed { println(" [도구 실패] ${it.toolName}"); it.toolName }
// 여기서의 it은 ToolCallStartingContext 타입의 데이터 클래스이며,
// 이것이 Koog로부터 전달받는 이벤트라고 이해하면 된다.
}
}
)
대화 기록 저장해서 기억시키기
Koog는 대화를 할 때마다 AI Agent를 매번 새로 생성한다. 그래서 이전 대화 내용을 기억하지 못한다.
그래서 대화 내용을 저장하는 기능을 직접 구현해야한다. 이 부분은 조금 번거로울 수 있다.
대화 기록을 저장하는 방식은 여러 가지가 있겠지만, 핸즈온 세션에서는 JSONL(JSON Lines) 형식을 활용했다.
{"timeStamp":"2026-04-15T07:01:24.422Z","message":{"type":"ai.koog.prompt.message.Message.User","parts":[{"type":"text","text":"..."}],"metaInfo":{"timestamp":"2026-04-15T07:01:24.422025Z"}}}
JSON 객체를 라인 단위로 나타낸 형식이다. 그래서 라인 별로 데이터를 저장하고 읽기가 편리하다.
사용자가 요청한 내용과 Agent가 응답한 내용을 저장하고, 이 대화 내용을 프롬프트에 함께 넣어주는 방식으로 Agent가 이전 대화 기록을 기억한다.
하지만 대화를 오래하면 기록이 점차 쌓여 에이전트에게 전달할 컨텍스트가 지나치게 많아진다. 한 번에 전달할 수 있는 컨텍스트 양은 제한되어있고, 이전 대화를 너무 많이 전달하면 사용자가 요청할 작업을 올바르게 수행하지 못할 수 있다.
이를 방지하기 위해서, 어느 정도 대화가 쌓이면 누적된 내용을 LLM에게 요약시키고, 압축된 내용을 Agent에게 전달하는 방식으로 컨텍스트를 제공할 수 있었다.
Hands-On Workshop: 나만의 업무용 툴 Agent 만들기
두 번째 세션에서는 나만의 Agent를 간단하게 만들어보고 이를 공유하는 시간을 가졌다.
해당 세션은 레아가 직접 만드신 Agent를 먼저 소개하며 진행을 맡으셨다. 프로젝트의 Contributor를 분석해서 해당 프로젝트의 Bus Factor가 얼마나 되는지 보여주는 Agent를 만드셨는데, 굉장히 참신하고 재미있었다. (역시 센스 만점 킹갓레아다!)
행사에 참석하신 다른 분들의 발표도 들었다. 안드로이드 SDK의 업데이트 내용을 요약해서 알려주는 Agent, 주식 투자를 분석하는 Agent, TDD 방식으로 개발을 수행하는 Agent 등 정말 다양한 아이디어가 나왔다. 모두 창의적이었고 한번 써보고 싶다는 생각도 들었다.
채용 공고 적합도 분석 Agent
나는 무엇을 만들까 고민하다가, 아직 취준생인 나는 취업 준비를 도와주는 Agent를 만들어보기로 했다.
최근 채용 공고를 분석해서 공고에 어울리는 이력서로 수정하는 과정이 번거롭고 시간이 많이 소요되어서 고민이었다. 그래서 채용 공고와 현재 나의 이력서를 비교해서 얼마나 잘 어울리는지 점수를 매겨주는 "채용 공고 적합도 분석 Agent"를 구상했다. 간단하게라도 만들어서 발표도 하고 싶었는데 구현이 늦어지는 바람에 발표 시간이 다 되었다. 아쉬운 대로 후기 글에서라도 공유해보려 한다.
채용 공고를 분석하는 JDAnalysisAgent와, 이력서를 읽고 공고 분석 내용을 토대로 적합도를 판단해주는 ResumeAnaylsisAgent를 각각 구현했다.
클로드의 도움을 받아 각 Agent의 프롬프트를 아래처럼 작성했다.
JDAnalysisAgent의 시스템 프롬프트
# JD 분석 에이전트
## 역할
당신은 채용 공고(Job Description)를 전문으로 분석하는 AI 어시스턴트입니다.
사용자가 제공한 채용 공고 URL에 접속하여 내용을 읽고, 구조화된 분석 결과를 제공합니다.
## 분석 항목
채용 공고를 분석할 때 다음 항목을 빠짐없이 추출합니다.
1. **기본 정보** - 회사명, 포지션명, 근무지, 고용 형태
2. **주요 업무** - 담당하게 될 구체적인 업무와 책임
3. **자격 요건 (Required)** - 반드시 갖춰야 하는 기술 스택, 경험, 학력 등
4. **우대 사항 (Preferred)** - 있으면 플러스가 되는 역량, 경험, 자격증 등
5. **기술 스택** - 언급된 모든 기술, 언어, 프레임워크, 도구를 중요도 순으로 정리
6. **회사 문화 / 인재상** - 회사가 강조하는 가치관, 일하는 방식, 원하는 인재 유형
7. **핵심 키워드** - 이력서에 반드시 포함해야 할 핵심 키워드 목록
## 행동 규칙
1. 반드시 fetchUrl 도구를 사용해 URL에 직접 접속하여 내용을 확인합니다. 추측하지 않습니다.
2. 페이지 내용을 가져온 후 분석 항목에 따라 구조화된 결과를 제공합니다.
3. 정보가 명시되지 않은 항목은 "명시되지 않음"으로 표기합니다.
4. 한국어로 응답합니다.
ResumeAnaylsisAgent의 시스템 프롬프트
# 이력서 분석 에이전트
## 역할
당신은 채용 공고와 이력서를 비교 분석하는 AI 어시스턴트입니다.
시스템 컨텍스트에 포함된 채용 공고 분석 결과와 사용자의 이력서 PDF를 비교하여, 얼마나 잘 맞는지 종합 점수와 상세 분석 결과를 제공합니다.
## 분석 방법
1. readPdf 도구를 사용해 이력서 PDF 파일을 읽습니다.
2. 시스템 컨텍스트의 채용 공고 분석 내용과 이력서 내용을 비교합니다.
3. 아래 형식에 따라 구조화된 분석 결과를 제공합니다.
## 출력 형식
### 종합 점수: XX / 100
### 카테고리별 점수
| 카테고리 | 점수 | 평가 |
|---|---|---|
| 기술 스택 일치도 | XX / 30 | 한 줄 평가 |
| 경력 / 경험 적합도 | XX / 25 | 한 줄 평가 |
| 직무 역할 적합도 | XX / 25 | 한 줄 평가 |
| 우대 사항 충족도 | XX / 20 | 한 줄 평가 |
### 강점 (채용 공고와 잘 맞는 부분)
- 구체적인 강점을 목록으로 제시
### 보완 필요 영역
- 부족하거나 보완이 필요한 부분을 목록으로 제시
### 이력서 개선 제안
- 점수를 높이기 위해 이력서에 추가하거나 강조해야 할 내용을 구체적으로 제시
## 행동 규칙
1. 반드시 readPdf 도구를 사용해 이력서 파일을 직접 읽습니다. 추측하지 않습니다.
2. 점수는 채용 공고의 요구 사항을 기준으로 객관적으로 산출합니다.
3. 개선 제안은 실행 가능하고 구체적으로 제시합니다.
4. 한국어로 응답합니다.
그리고 채용 공고 분석 내용을 토대로 이력서와 비교해 분석해야하기 때문에 채용 공고 분석 결과를 JSONL로 저장해 이를 불러오는 기능을 구현하고, 채용 공고 URL을 읽어들이는 도구와 PDF 파일을 읽어들이는 도구를 함께 추가했다.
실행 모습

채용 공고 URL을 전달하면 fetchUrl 도구를 호출해 공고의 JD를 가져와 분석 및 요약한다.

그리고 PDF 파일을 읽는 readPdfFile 도구를 사용해 이력서를 읽고, 채용 공고 분석 내용와 이력서를 비교해 종합 점수와 분석 결과, 개선 사항을 알려준다.
예전에 작성해놓은 다른 버전의 이력서와 비교해보니 카테고리별 점수가 조금 다르게 나타났다. 현재 이력서와 비교하면 첫 페이지 소개 글과 상세 내용이 다른데, 이에 따라 분석 결과도 조금 다른 것을 확인할 수 있었다.

마치며
AI에 대해서 잘 몰랐음에도 쉽고 재미있게 배울 수 있어서 기억에 남는 컨퍼런스였다. 여러 개발자분들의 재미있는 아이디어도 엿볼 수 있었고, 이런 저런 이야기를 하며 앞으로의 개발에 대한 인사이트도 나눌 수 있어 좋았다. 좋은 컨퍼런스를 준비해주신 GDG Korea Android 분들께 다시 한 번 감사의 인사를 드리고싶다.
또 컨퍼런스에서 배운 것을 토대로 AI Agent를 정말 간단히, 가볍게 만들어 보았는데 생각보다 꽤 괜찮아보여서 개인 프로젝트로 더 디벨롭해보고 싶어졌다. 나중에 그럴듯하게 결과물이 나오면 블로그에 공유해보겠다.
추가로 Koog 프레임워크에 대해서도 더 공부해보고 싶다. 공식 문서를 살펴보니 컨퍼런스에서 다루지 못한 다양한 기능들이 꽤 많은 것 같았다. AI Agent가 많은 일을 담당하고 있는 시대에, 이를 잘 활용하면 신기하고 재미있는 기능을 여럿 만들어낼 수 있지 않을까 생각한다.
