Projects로 돌아가기

PROJECT CASE STUDY

04

서울 어디가? · 공공데이터 외출 계획 에이전트

2026 서울시 빅데이터 활용 경진대회 창업 부문 출품작으로, 공공데이터와 지도·음성을 하나의 외출 계획 흐름으로 연결했습니다.

챗봇은 왜 계획에서 멈출까?

서울에서 하루 외출을 계획하려면 장소, 예약 가능 여부, 동행인의 이동 부담, 주차장, 경로와 다음 일정을 계속 함께 조정해야 합니다. 공공데이터와 지도 API에는 필요한 정보가 흩어져 있지만, 데이터가 존재한다고 해서 사용자의 계획이 완성되지는 않습니다.

일반적인 챗봇은 장소 목록을 제안할 수 있습니다. 그러나 사용자가 두 번째 후보를 고르고 “차로 갈 건데 주차도 편한 곳으로 바꿔줘”라고 말하는 순간, 이전 선택과 이동수단, 지도 위치, 공공예약 상태가 다음 답변의 전제가 됩니다.

서울 어디가 서비스의 첫 화면. 서울 어디가 로고 아래 자연어와 음성으로 외출 계획을 요청할 수 있는 입력창이 있다.
사용자는 검색 필터를 하나씩 조작하는 대신, 원하는 외출 조건을 자연어 또는 음성으로 설명하며 계획을 시작합니다.원본 크기로 보기

답변이 아닌 계획 상태

서울 어디가?는 2026 서울시 빅데이터 활용 경진대회 창업 부문 제품 및 서비스 개발 출품작입니다. 서울 열린데이터광장의 공공서비스예약·공영주차장 정보와 장소 검색, 지도, 경로, 음성 입력을 사용자의 의사결정 순서에 맞춰 연결했습니다.

agent의 결과물은 긴 추천 문장이 아니라, 사용자가 확인하고 수정할 수 있는 계획 상태입니다. 장소 후보는 지도 marker와 선택 카드로, 경로는 비교 가능한 후보로, 확정한 선택은 다음 질문에서 다시 읽을 수 있는 상태로 남깁니다.

대화가 UI를 움직이는 법

단일 Main Agent는 요청을 해석하고 공공데이터·장소·경로 tool을 호출합니다. 다만 결과를 그대로 채팅에 출력하지 않고, 장소 선택, 경로 후보, 지도 viewport, 공유 요약을 위한 typed UI tool로 변환합니다.

REQUEST → STATE → UI

사용자 요청 또는 음성 입력
  → Main Agent: 의도·조건 해석
  → 공공데이터 · 장소 · 경로 tool
  → typed UI state tool
  → Zustand AgentUiStore
  → Scene / Frame / Surface 렌더링
  → 사용자 선택
  → compact UI snapshot
  → 다음 agent turn

Next.js App Router 위의 Zustand `AgentUiStore`는 chat, frame, route, selection, itinerary, share, planning, voice 상태를 함께 관리합니다. `frame_open`, `route_set_places`, `route_set_candidates`, `selection_set_options`, `share_set_state`처럼 허용된 tool만 store action을 실행합니다.

사용자가 marker나 후보 카드를 선택하면 결과가 store에 기록되고, 다음 요청에는 필요한 내용만 담은 UI snapshot이 전달됩니다. agent가 React component나 DOM을 직접 다루지 않도록 하면서도, 대화와 사용자의 선택이 다음 계획에 반영되게 한 feedback loop입니다.

사용자 조건이 장소 후보와 선택 가능한 카드로 정리되는 서울 어디가 화면 녹화
agent는 검색 결과를 긴 목록으로 쌓지 않고, 다음 선택에 필요한 후보와 조건을 같은 계획 상태로 정리합니다.원본 크기로 보기
대화, 서울 지도, 장소 후보와 이동 경로가 함께 갱신되는 서울 어디가 화면 녹화
장소·이동수단·경로 후보가 달라지면 지도와 비교 surface도 함께 바뀌며, 사용자는 그 상태에서 다음 선택을 이어갈 수 있습니다.원본 크기로 보기

LLM의 화면 권한은 제한한다

자유 생성보다 제한된 화면 언어

초기에는 LLM이 2D grid에 pane을 배치하는 tiling manager도 실험했습니다. 하지만 지도, chat, 카드 목록, 일정, 공유 화면은 필요한 크기와 반응형 조건이 달랐고, 좌표와 크기까지 모델에게 맡기면 prompt와 결과가 함께 불안정해졌습니다.

그래서 제품의 기본 구조는 scene/frame preset 방식으로 옮겼습니다. agent는 “지도를 특정 좌표에 그려라”라고 지시하지 않고, route map frame을 열어 장소·경로·viewport·선택 상태만 바꿉니다. React controller가 화면의 실제 layout과 modal, 반응형 동작을 결정합니다.

서울 어디가에서 후보를 선택하고 계획 상태를 갱신하는 화면 녹화
모델은 카드의 위치나 스타일을 만들지 않습니다. 정해진 선택 surface에 후보와 선택 상태만 전달하고, 제품 코드가 일관된 상호작용을 렌더링합니다.원본 크기로 보기

A2UI와 AG-UI에서 가져온 문제의식

A2UI는 선언적 UI payload를, AG-UI는 agent와 frontend 사이의 state·tool event 전달을 다룹니다. 이 프로젝트는 두 protocol을 그대로 채택하지는 않았지만, 같은 문제의식에서 component 생성과 UI state 변경을 분리했습니다. 모델의 유연함은 자연어 이해와 tool 선택에 사용하고, 화면의 품질과 안전성은 제품 코드가 소유하도록 했습니다.

선택을 공유 가능한 계획으로 묶는다

계획 상태는 한 번의 답변으로 끝나지 않습니다. 사용자가 고른 장소와 이동 순서를 짧게 확인하고 다른 사람과 공유할 수 있어야, 다음 대화와 실제 외출 사이가 끊기지 않습니다.

그래서 공유 화면 역시 별도 문서를 생성하는 기능이 아니라, 현재 itinerary와 선택을 읽어 정리하는 동일한 state의 다른 surface로 다뤘습니다.

정리된 외출 계획과 장소 정보를 공유용 화면으로 보여 주는 서울 어디가 화면 녹화
같은 계획 상태를 공유에 맞는 화면으로 다시 보여 주되, 사용자가 확정한 선택과 다음 행동은 잃지 않도록 했습니다.원본 크기로 보기

음성과 화면의 역할 분리

장소·시간·동행인·이동수단처럼 조건이 많은 요청은 여러 필터를 누르는 것보다 문장 하나로 말하는 편이 빠르고 자연스럽습니다. 음성 transcription은 별도 command 체계가 아니라 같은 prompt input과 agent loop로 들어가 계획 상태를 수정합니다.

반면 최종 답변에는 표, 후보 카드, 링크, tool 결과가 들어갈 수 있어 그대로 읽기에는 적합하지 않습니다. `voice_prepare_speech` tool은 최종 답변을 복사하지 않은 짧은 발화문만 준비하고, ElevenLabs TTS는 이 payload만 재생합니다. 화면은 비교와 근거를 보여 주고, 음성은 다음 행동을 안내하도록 역할을 나눴습니다.

서울 어디가 첫 화면에서 마이크로 외출 조건을 말하는 화면 녹화
음성 입력은 따로 분리된 command가 아니라, 타이핑과 같은 계획 loop로 전달됩니다.원본 크기로 보기

모델 하나에 너무 많은 일이 몰렸다

이 프로젝트의 Main Agent에는 자연어 해석, data tool 선택, 결과 비교, UI state 변경, 화면 설명과 음성 요약까지 많은 책임이 모였습니다. tool이 늘어날수록 사용자가 체감하는 지연은 첫 token 속도만이 아니라, tool schema 이해와 호출 순서, 다음 UI payload 생성의 안정성에 좌우됐습니다.

프로젝트에서는 OpenRouter의 `deepseek/deepseek-v4-flash`를 tool 지원 provider와 함께 기본 모델로 사용했습니다. 더 작은 모델과 이전 모델도 비교했지만, 공공데이터 결과를 UI state로 이어 붙이는 다수 tool flow에서 이 모델이 실사용 가능한 안정성의 하한에 가까웠습니다.

후속 Cerebras integration smoke test에서는 `zai-glm-4.7`과 `gpt-oss-120b`도 같은 유형의 tool flow에 연결했습니다. 빠른 생성 속도와 별개로, 필요한 tool을 건너뛰거나 호출 순서와 화면 전환 payload가 흐트러지는 사례가 있어 이 contract를 대체하지는 못했습니다. 이는 모델 일반 성능 순위가 아니라, 이 agent 구조에서 얻은 관찰입니다.

복지 상담 안내 캐릭터 로디RELATED PROJECT · RODY RAG 01로디 복지 상담 에이전트 · RAG 1검색 기반과 agent 책임을 분리해, 상담 agent가 검증 가능한 근거를 읽도록 만든 다음 프로젝트

공공데이터의 운영 경계

예약·운영 정보의 최신성은 원본 provider에 달려 있고, 외부 API는 느리거나 일시적으로 응답하지 않을 수 있습니다. 추천 결과에는 원본 정보와 확인 시점을 보여 주고, 예약이나 이동 전에는 사용자가 다시 확인할 수 있어야 합니다.

또한 실제 운영 서비스에서는 provider별 quota와 cache, 장애 fallback, 위치정보와 개인정보 보관 정책을 더 구체화해야 합니다. 이 프로젝트는 공공데이터 API를 많이 연결하는 데서 끝나지 않고, data와 agent 결과를 사용자가 선택할 수 있는 상태로 바꾸는 방법을 실험했습니다.