Skip to content
01 / 07 Featured · Agent UX · 2025–2026

ARIS를 어떻게
만들었는가.

모바일 SSH의 한계, 서버 런타임 분리, provider 통합, 실시간 동기화, iOS viewport와 scroll manager까지. 제품 뒤에 남은 개발 노트입니다.

From the project slide · chat-first agent runtime
You 1d ago
선택기에서 바꾼 모델이 새 채팅 만들 때도 그대로 유지되는지 확인해줘.
Codex · gpt-5.4 1d ago
추가로 한 가지 더 봐야 할 부분이 있습니다. 설령 첫 전송에 모델명이 들어가더라도, 그 선택이 채팅 레코드에 저장되지 않으면 화면을 다시 열었을 때 다시 원래 모델로 돌아갈 수 있어서 그 지속성까지 확인하겠습니다.
3 actions
Trigger 모바일 SSH/TUI의 한계
Approach 서버 런타임 + 웹 인터페이스
Providers Codex · Claude Code · Gemini
Status Active · 2025–2026 · Solo

연구 개발은 실험 서버, 코드 변경, 웹 구현, 문서 정리처럼 여러 환경을 오가며 진행됩니다. 이동 중에도 agent와 대화를 이어가려고 모바일에서 SSH 터미널을 열어 TUI 에이전트를 띄웠지만, 실제로는 작업 맥락이 자주 끊겼습니다.

  1. 01

    TUI cost

    채팅 전환, agent mode 전환, git diff, 파일 확인을 모두 명령어로 처리해야 했습니다. 작은 화면에서 매번 텍스트를 입력하는 비용이 누적되며 작업 맥락이 잘 유지되지 않았습니다.

  2. 02

    Runtime drop

    기기가 슬립모드로 들어가거나 SSH 앱이 백그라운드로 내려가면 SSH 연결과 함께 agent runtime까지 종료되었습니다. 단순 연결 끊김이 아니라 작업 그 자체가 사라지는 문제였습니다.

  3. 03

    Multi-agent gap

    여러 agent를 동시에 운용하고 provider별 강점을 나눠 쓰기 위한 통합 인터페이스가 부족했습니다. TUI 환경에서 Codex · Claude Code · Gemini를 함께 다루는 건 사실상 별도 세션의 잡일이 됐습니다.

  4. 04

    Korean input

    일부 모바일 SSH 터미널은 한글 입력에서 글자 깨짐과 IME 버그가 발생했습니다. 긴 개발 대화에서 입력 자체가 병목이 되는 경험이 잦았습니다.

가장 먼저 잡은 결정은 단순합니다. agent runtime의 수명은 디바이스가 아니라 서버에 묶는다. 모바일 기기가 슬립으로 들어가도, 브라우저 탭을 닫아도, 다른 장소에서 접속해도, 실행 중인 agent와 그 컨텍스트는 서버에서 그대로 유지됩니다. 사용자는 웹 인터페이스로 그 위에 올라타서 흐름을 이어갑니다.

Figure 1. 어디서든(Anywhere) → 웹 표면(Web surface) → 서버 런타임(Server runtime) → 다중 Provider
Anywhere Mobile · Tablet · Desktop device-agnostic Web Surface Chat · Files Permissions stateless on device Server Runtime Persistent Agent Process WebSocket sync Providers Codex Claude Code Gemini

웹 표면(Web surface) × 서버 런타임(Server runtime)

웹 표면은 디바이스 위에서 가벼운 상태만 유지합니다. 채팅 스크롤, 모달, 입력 같은 것들입니다. 반대로 agent의 실제 실행 컨텍스트(권한, 파일, 명령 실행, 모델 상태)는 서버 런타임에 머무릅니다. 이 분리 덕분에 같은 세션을 데스크톱 브라우저에서 열어도, 폰에서 열어도 동일한 작업 흐름이 계속됩니다.

Provider 추상화

Codex, Claude Code, Gemini는 각자의 SDK·CLI·실행 모델·권한 흐름이 다릅니다. 초기에는 provider별 개별 경로를 두었는데 상태 관리가 빠르게 무너졌습니다. 지금은 세 provider를 단일 상태 클래스로 묶어, 사용자에게는 “provider를 바꾼다”는 한 가지 표면만 노출합니다.

ARIS의 표면은 “예쁘게 만들었다”가 아니라, agent가 무엇을 하고 있고 무엇을 봐야 하는지를 운영자의 질문 순서대로 배치한 작업대입니다. 네 가지 큰 표면이 중심이고, 그 안에 보조 표면이 함께 들어갑니다.

S1

Session

디바이스가 바뀌어도 같은 세션이 이어집니다. 진입할 때마다 서버 상태를 받아오고, 진행 중인 작업이 있으면 같은 자리에 놓입니다.

S2

Chat UI

모바일 · 태블릿 · 데스크톱에서 동일한 채팅 흐름. 명령어 입력 대신 action card, file chip, URL preview로 조작을 시각화합니다.

S3

Review

Git diff와 파일 뷰어가 대화 옆에서 함께 열립니다. agent가 언급한 파일은 칩을 누르는 순간 뷰어로 펼쳐집니다.

S4

Control

실행 승인, provider 상태, 서버 연결을 하나의 흐름으로 묶었습니다. 권한 요청은 대화 안에 끼어들어 흐름을 끊지 않습니다.

보조 표면

  • Action Cardagent의 한 행동을 한 칸에 압축
  • Markdown채팅 답변을 읽기 위한 형식
  • File chip언급된 파일을 즉시 펼치는 진입점
  • URL preview대화 흐름을 깨지 않는 링크 확인

Plan ↔ Execute 모드

agent의 행동을 둘로 나눠 보여줍니다. Plan은 무엇을 할지 결정하는 단계, Execute는 그 결정을 실행하는 단계입니다. 사용자는 Plan 단계에서 권한과 범위를 좁히고, Execute에서는 같은 채팅 흐름 안에서 결과를 받습니다.

ARISPLAN
검색어 분포 5개를 비교 차트로 정리해줘.
3단계 계획을 제안할게요.
1. fetch_keywords
2. compute
3. render
권한Once
ARISEXECUTE
▶ charts.compare_keywords(...)
실행 완료 · 결과 첨부

세 provider는 잘하는 영역도, 사용 가능한 quota도, 막힌 문제를 푸는 관점도 다릅니다. 하나의 인터페이스에서 모델을 바꿔가며 작업을 이어가는 능력은 “여러 모델을 지원한다”는 기능이 아니라, 연구 개발을 멈추지 않기 위한 운영 전략이었습니다.

Provider Strength When to switch
Codex 백엔드 · Python · ML 연구 개발

실험 코드와 서버 런타임의 구조적 문제를 빠르게 추적합니다.

Claude Code 웹 디자인 · 프론트엔드 구현

화면 구조와 인터랙션을 더 섬세하게 다듬는 데 강점이 있습니다.

Gemini 대안 검토 · fallback · 비교 판단

한 agent가 막힌 문제를 다른 관점으로 다시 풀 때 사용합니다.

다음 방향: 협업형 런타임

지금은 채팅을 새로 열어 provider를 바꿉니다. 다음 단계는 하나의 채팅 안에서 provider를 전환하고, 작업 중간에 다른 agent를 불러 의견과 검토를 받는 협업형 런타임입니다. ARIS를 채팅 UI가 아니라 여러 agent를 조합해 연구 개발을 수행하는 인터페이스로 발전시키는 축입니다.

ARIS에서 가장 큰 난점은 새 기능을 만드는 일이 아니라, 이미 있는 책임을 어떤 객체·계층에 두고 어떻게 위임할지를 결정하는 일이었습니다. 구조가 흔들릴 때마다 기능 단위로 패치하지 않고, 책임 자체를 다시 그렸습니다.

Provider runtime

문제 · provider별 개별 경로가 상태 관리와 기능 변경을 어렵게 만들었습니다.

해결 · 공통 상태 클래스로 추상화해, 세 provider를 하나의 구조 안에서 다루도록 정리했습니다.

Realtime sync

문제 · polling으로 실시간성을 확보하려 하자 서버 부하가 커졌습니다.

해결 · WebSocket 기반 상태 동기화로 전환해 효율을 회복했습니다.

iOS viewport

문제 · iOS 26 Safari 하단 chrome과 sticky composer가 충돌해 입력 영역이 잘렸습니다.

해결 · 채팅 composer를 sticky 요소에서 제외해 clipping과 위치 문제를 줄였습니다.

Scroll manager

문제 · 파편화된 스크롤 로직이 페이지네이션과 충돌하며 떨림이 발생했습니다.

해결 · 스크롤 책임을 단일 클래스로 위임해 race condition을 제거했습니다.

Bundle · 15 MB → 236 KB

채팅 진입 번들을 15 MB에서 236 KB로 줄였습니다. 라우팅과 로딩 경계를 다시 잡아, 실제 사용자가 처음 대화 화면에 들어오는 시간을 좁혔습니다.

Before
15.0 MB
After
236 KB

64× 감소 · 진입 ~120ms

Challenges

개발 도중 부딪힌 결정적 지점들.

  • Runtime 수명을 어디에 둘 것인가 — 디바이스에 두면 모바일 환경에 그대로 묶이고, 서버에 두면 세션 관리·인증·복구 흐름을 직접 다뤄야 했습니다. 결국 후자를 택하고, 그 비용을 받아들이는 결정에서 시작했습니다.
  • Provider 통합의 추상 레벨 — 너무 얇게 추상화하면 provider별 특이성이 새고, 너무 두텁게 묶으면 새로운 provider 추가가 어려웠습니다. 공통 상태 클래스를 단일 진입점으로 잡되, provider 고유 동작은 어댑터로 분리했습니다.
  • 모바일 viewport 회귀 — iOS 26 환경에서 sticky composer가 어떻게 잘리는지 알기 전까지는 “브라우저 chrome이 가린다”는 막연한 인상밖에 없었습니다. 실제 디바이스에서 잘리는 순간을 찾고 나서야 sticky를 빼는 선택이 보였습니다.
  • 스크롤 책임의 분산 — 페이지네이션·자동 스크롤·새 메시지 도착이 같은 스크롤 위치를 두고 경쟁했습니다. 기능마다 작은 fix를 더하는 대신 책임을 한 클래스로 모아 race condition을 제거했습니다.

Lessons

이 프로젝트가 다음 작업에 남긴 것.

  • 도구를 만들면 다시 생산성이 돌아온다 — ARIS는 “필요한 도구를 직접 만들고, 그 도구가 다시 자신을 가속한다”는 positive feedback loop를 실제로 돌려본 첫 프로젝트였습니다.
  • LLM agent는 통합해야 운영 가능하다 — agent API 호출이나 채팅 UI 한 장이 아니라, 세션·권한·파일·Git·모바일 조작까지 묶어야 비로소 “연구 개발의 동료”로 다룰 수 있다는 점을 체감했습니다.
  • 구조는 책임 분배의 결과다 — 기능 추가만으로 안 풀리는 문제는 책임이 잘못 놓여 있다는 신호였습니다. 좋은 구조를 위한 직관은 이 과정에서 얻었습니다.
  • 다음 도구로 이어졌다 — ARIS의 경험은 연구 워크플로우에 더 특화된 ARES(Agentic Research Experimentation System)로 자연스럽게 이어졌습니다.
Next project ARES Agentic Research Experimentation System