왜 동적 합성(dynamic composition)이 필요한가?
한 줄 요약: 소프트웨어에는 점점 더 "실행 중에 컴포넌트를 설치하고, 제거하고, 교체하는" 능력이 요구되지만, 지금의 소프트웨어 대부분은 그것을 하지 못합니다 — 설치하면 제거할 수 없거나, 제거하려면 프로그램 전체를 재시작하면서 모든 상태를 잃어야 하기 때문입니다. 동적 합성은 이 일을 안전하게 일어나게 하는 능력이며, 바로 DSH와 그 Cordis 논문이 해결하려는 핵심 문제입니다.
먼저 어떤 프로그래머의 하루 이야기를 합시다
리 씨는 챗봇 플랫폼을 유지보수하고 있고, 사용자들은 수십 개의 플러그인(날씨, 번역, 가계부……)을 설치해 두었습니다.
- 오후 2시: 사용자가 "번역 플러그인이 느려졌다"고 알려옵니다. 리 씨는 번역 서비스를 바꾸고 싶습니다.
- 현실은: 그는 봇 전체를 멈춰야 합니다(모든 플러그인이 함께 오프라인이 됨), 설정을 수정하고, 재시작합니다.
- 재시작 후: 사용자는 3분 동안 사용할 수 없고, 이전에 캐시된 핫 데이터는 전부 사라지고, 다른 29개의 플러그인도 억울하게 "동반" 재시작당합니다.
리 씨는 속으로 생각합니다: "나는 그저 하나의 플러그인을 바꾸고 싶었을 뿐인데, 왜 시스템 전체를 다 분해해야 하는 거지?"
이 문제가 바로 "동적 합성의 부재"라고 부르는 것입니다.
시나리오 1: 플러그인 시스템(당신이 매일 쓰고 있지만, 그것 때문에 골치 아팠던 적이 있다)
세계에서 가장 인기 있는 코드 에디터인 VSCode를 예로 들어 봅시다(논문에 있는 실제 데이터입니다):
VSCode는 모든 확장(플러그인)을 하나의 공유 프로세스에서 실행합니다. 코드를 포함한 확장 하나를 제거하고 싶다고요? 에디터 전체를 재시작하는 수밖에 없습니다. 설치 수 기준 상위 100개 확장 중 87개가 실행 가능한 코드를 포함하고 있습니다 — 다시 말해, 자주 쓰는 확장의 87%는 제거할 때 재시작이 필요합니다.
왜 제거할 수 없을까요? 플러그인이 "환경을 건드렸기" 때문입니다: 명령을 등록하고, 이벤트를 수신하고, 설정을 바꿉니다. VSCode는 이 변경 사항들을 어떻게 되돌리는지 모르기 때문에, "모르는 게 약" — 재시작해서 모든 것을 0으로 되돌릴 수밖에 없습니다.
🎁 1장의 주방 비유를 기억하나요? 요리사를 바꾸려고 가게 문을 닫고 인테리어를 새로 해야 하는 것, 이것이 현실입니다.
시나리오 2: 자기 진화 에이전트(미래의 일상)
이전 섹션에서 이야기했듯이, 미래의 에이전트는 스스로 도구를 작성하고, 스스로 설치하고, 스스로 제거할 것이며, 그것도 실행 중에, 사람의 감독이 거의 없는 상황에서 그렇게 합니다.
이것은 다음을 의미합니다:
- 변경할 때마다 재시작할 수는 없습니다 — 에이전트는 1분에 한 번씩 변경할 수도 있습니다. 재시작 = 상태 유실의 반복 + 다운타임의 반복
- 잘못 설치했다고 다 터져서는 안 됩니다 — 에이전트가 문제가 있는 모듈을 설치했는데 자기 자신의 "복구 메커니즘"까지 망가뜨렸다면, 정말로 하늘에 소리쳐도 대답이 없을 것입니다
- 남을 조용히 망가뜨려서는 안 됩니다 — 새 컴포넌트가 옛 컴포넌트를 대체할 때, 그것에 의존하는 다른 컴포넌트들은 조용히 오류를 내는 대신 자동으로 적응해야 합니다
자기 진화는 공상과학이 아니라 AI 발전의 명확한 방향입니다. 그리고 그것이 안전하게 실현될 수 있는지는 전적으로 동적 합성이 얼마나 잘 되어 있느냐에 달려 있습니다.
문제의 분해: 두 개의 차원
논문은 "동적 합성"을 서로 무관한(직교하는) 두 개의 차원으로 분해합니다:
차원 1: 시간적 합성성(설치할 수 있고, 분리할 수 있다)
컴포넌트를 제거할 때, 그것이 이전에 환경에 가한 모든 수정이 완전히 되돌려져야 합니다 — 플러그를 뽑으면 회로가 원래대로 돌아가야 하는 것처럼.
- 문제: 컴포넌트는 "설치"할 때 여러 가지를 바꿉니다(등록, 리스너, 캐시). "제거"할 때 누가 복원할 책임을 질까요?
- 현황: 아무도 책임지지 않음 → 재시작으로 땜질할 수밖에 없음
- 목표: 설치할 때 자동으로 기록하고, 제거할 때 자동으로 복원하기
차원 2: 공간적 합성성(내가 필요한 것을 시스템이 제공한다)
컴포넌트들은 의존성을 선언하고 자동으로 조율할 수 있어야 합니다 — 의존성이 갖춰져야 시작하고, 의존성이 사라지면 자동으로 멈춥니다.
- 문제: 번역 플러그인에는 "번역 서비스"와 "데이터베이스"가 필요합니다. 플러그인만 설치하고 서비스를 설치하지 않았다면 어떻게 될까요?
- 현실: 플러그인이 스스로 확인하고, 찾지 못하면 오류를 낸 후 충돌하거나, 서로를 기다리다 교착 상태에 빠집니다
- 목표: 시스템이 의존성 변화를 감시하고 컴포넌트를 자동으로 활성화/비활성화하기. 컴포넌트 자신은 아무것도 신경 쓸 필요가 없습니다
💡 한 줄로 기억하기: 시간 차원은 "분리한 후 환경이 깨끗한가"를 다루고, 공간 차원은 "컴포넌트끼리 어떻게 조율하는가"를 다룹니다. 두 차원은 서로 독립적이므로 따로 연구할 수 있습니다.
两个维度互相独立(正交):一个管「拆了干不干净」,一个管「组件怎么协调」
기존의 "억지 방법": 재시작과 컨테이너
어떤 사람은 이렇게 말할 것입니다: "재시작하면 재시작하는 거지, 지금의 클라우드 서비스들도 다 그렇잖아?" 맞습니다. 하지만 대가가 큽니다:
| 억지 방법 | 세분성 | 대가 |
|---|---|---|
| 프로세스 재시작 | 프로세스 전체 | 모든 메모리 상태(캐시, 연결, 절반쯤 계산한 작업)를 버림. 재구축에 몇 초에서 몇 분 소요. 그동안 중복 복제본으로 버텨야 함 |
| 컨테이너 오케스트레이션(Kubernetes 등) | 서비스 전체 | "같은 프로세스 안의 컴포넌트 간 의존성"을 표현할 수 없음. 원래 함수 호출 한 번이면 될 일이 네트워크 요청이 되어야 함 |
논문은 이것을 **세분성 불일치(granularity mismatch)**라고 부릅니다:
우리는 그저 "플러그인" 하나를 바꾸고 싶을 뿐인데, 프로세스 재시작은 "닭 잡는 데 소 잡는 칼을 쓰는 것"이고, 컨테이너 재시작은 "돼지를 잡는 것"입니다. 현대 시스템은 점점 더 컴포넌트라는 세밀한 세분성에서 합성됩니다 — 컴포넌트 자체와 같은 정도로 세밀한 수준에서 효과와 의존성을 관리해야 합니다.
동적 합성이 있다면, 리 씨의 하루는 어떻게 달라질까?
같은 시나리오에 동적 합성(예: DSH/Cordis)이 있다면:
- 리 씨는 콘솔에서 "번역 플러그인 → 서비스 제공자 전환"을 한 번 클릭합니다
- 시스템이 자동으로: 기존 번역 플러그인을 제거(등록한 명령과 캐시가 전부 복원됨) → 새 번역 플러그인을 설치
- 번역 서비스에 의존하는 다른 플러그인은 자동으로 재시작되어 적응하고, 의존하지 않는 플러그인은 꿈쩍도 하지 않습니다
- 전 과정에서 재시작이 전혀 없고, 다른 사용자들은 전혀 눈치채지 못합니다
이것이 논문(그리고 우리 사이트)이 여러분과 함께 이루고자 하는 목표입니다.
핵심 포인트 정리
- 동적 합성 = 실행 중에 안전하게 컴포넌트를 설치 / 제거 / 교체하는 것
- 두 차원: 시간(분리하면 복원됨)과 공간(의존성이 자동으로 조율됨)
- 현재의 억지 방법(재시작, 컨테이너)은 세분성이 너무 굵고 대가가 너무 큼
- 동적 합성은 플러그인 시스템과 자기 진화 에이전트의 공통적인 필수 요구 사항입니다
🚀 다음 장(제2장 · 논문 정독)에서는 드디어 본격적으로 그 논문에 들어가, "설치와 분리"를 "오류가 안 나길 기도하는 것"에서 "구조적 보증"으로 바꾸는 수학적 도구를 살펴봅니다. "이펙트/코이펙트"라는 단어를 아직 접해 보지 않았다면 — 걱정 마세요. 제5과에서 처음부터 차근차근 설명합니다.
자가 테스트 · 왜 동적 합성이 필요한가
답을 모두 선택한 후 「답안 제출」을 클릭하면 정답 여부와 해설을 확인할 수 있습니다.
