본문으로 건너뛰기

© 2026 Molayo

Dev.to헤드라인2026. 06. 27. 00:17

에이전트가 문서를 작성할 수 있도록 추상화(Abstraction)를 구축했지만, 결국 삭제했습니다.

요약

에이전트의 문서 생성 효율을 높이기 위해 구축한 추상화 레이어가 오히려 결과물의 동질성을 초래하여 결국 삭제하게 된 경험담을 다룹니다. 로우 레벨 라이브러리를 래퍼로 감싸 토큰을 절약하려 했으나, 에이전트의 창의성을 제한하는 부작용을 분석합니다.

핵심 포인트

  • 추상화 레이어는 토큰 비용과 오류를 줄이지만 결과물의 획일화를 초래할 수 있음
  • 에이전트에게 너무 좁은 인터페이스를 제공하면 창의적인 출력이 제한됨
  • 에러 메시지를 에이전트 친화적인 문서로 개선하는 것이 중요함
  • 효율성을 위한 설계가 실제로는 진전을 방해하는 가짜 진전일 수 있음

그래서 저는 제 에이전트에게 발표 자료를 만들어 달라고 요청했습니다. 에이전트는 자료를 만들어냈습니다. 깔끔한 표지, 몇 개의 통계 슬라이드, 마지막에 표가 포함된 구성으로 겉보기에는 괜찮았습니다. 두 번 확인할 필요도 없을 만큼 충분히 좋았습니다.

그러다 일주일 후, 저는 다른 주제, 다른 데이터, 다른 청중을 대상으로 한 다른 덱(Deck)을 요청했습니다. 그런데 에이전트가 가져온 것은 이전과 똑같은 덱이었습니다. 똑같은 표지, 똑같은 리듬, 그리고 마무리로 마지막에 표를 넣으려는 똑같은 방식이었습니다. 단어는 달랐지만, 겉모습은 동일했습니다.

첫 번째나 두 번째에는 눈치채지 못했습니다. 그것들을 옆으로 나란히 펼쳐놓고 어떤 것이 무엇인지 구분할 수 없게 되었을 때 비로소 깨달았습니다. 무엇도 고장 난 것은 없었습니다. 기술적으로는 모든 것이 문서였습니다. 다만 모두가 마치 똑같은 기계가 만든 것처럼 보였는데, 실제로 한 기계가 만들었으며 그 기계가 조용히 노력을 멈췄기 때문입니다.

그래서 제가 마주해야 했던 질문은 이것이었습니다. 왜 이 에이전트가 만드는 모든 것이 똑같은 옷을 입고 나오는지, 그리고 왜 그것을 알아차리기까지 그토록 많은 양의 결과물이 쌓여야 했는지 말입니다.

누군가 먼저 말하기 전에 미리 말씀드리자면, 네, 이 글의 한 줄 요약은 제가 실수로 밝혀진 추상화(Abstraction)를 구축했고, 그래서 그것을 삭제했다는 것입니다. 이 점은 미리 인정하겠습니다. 여러분의 시간을 들일 가치가 있는 부분은 실수가 아닙니다. 그 실수가 과정 내내 보이지 않았고, 마치 진전(Progress)처럼 보였으며, 추상화를 개선하는 것이 당연한 해결책처럼 보였지만 오히려 상황을 악화시켰을 것이라는 점입니다.

어떻게 여기까지 오게 되었나

잠시 뒤로 돌아가 보겠습니다. 이 '동질성'은 우연이 아니었습니다. 제가 직접 만든 것이었습니다.

에이전트로부터 실제 Office 문서를 만드는 것은 화려한 작업이 아닙니다. 내부적으로는 슬라이드를 위한 python-pptx, Word를 위한 python-docx, 스프레드시트를 위한 openpyxl, PDF를 위한 WeasyPrint를 사용합니다. 강력한 라이브러리들이지만, 로우 레벨(Low level)입니다. 만약 에이전트가 이 라이브러리들을 가공되지 않은 상태로 직접 다루게 내버려 두면, 모든 문서는 '이 상자를 만들어라', '저 폰트를 설정해라', '이 셀들을 병합해라'와 같은 명령으로 이루어진 5,000 토큰에 달하는 긴 스크립트가 됩니다. 생성 속도가 느리고 비용이 많이 들며, 에이전트는 절반 정도의 확률로 자신이 작성한 코드에 걸려 넘어지곤 합니다.

그래서 저는 당연한 일을 했습니다. 그것들을 래퍼(Wrapper)로 감싸는 것이었죠. 에이전트가 5,000토큰 분량의 스크립트 대신 단 다섯 줄만 작성할 수 있도록 얇은 헬퍼 레이어(Helper layer)를 만든 것입니다. 표지, 몇 개의 통계 블록, 표, 저장. 이렇게 하면 생성할 양이 줄어들고, 오류가 날 확률도 낮아지며, 매번 더 빨라질 것이기에 분명히 옳은 방향처럼 느껴졌습니다.

그 후 저는 몇 주 동안 이를 강화(Hardening)하는 데 시간을 보냈습니다. 에이전트는 날카로운 모서리(Sharp edges)를 향해 곧장 돌진하기 때문입니다. 그 과정에서 저를 괴롭혔던 몇 가지 사례들이 있습니다.

에이전트는 출력 경로(Output path)를 스타일링 정보가 들어가야 할 잘못된 인자(Argument)에 계속 전달했고, 아무런 정보도 주지 않는 NoneType 에러를 반환받았습니다. 그래서 에이전트는 허우적대며 다시 시도하고, 또 허우적댔습니다. 저는 에러 메시지가 모호하게 죽는 대신 실제 해결책을 명시하도록 수정하여 이 문제를 해결했습니다. 여기서 에이전트는 사용자이며, 에러 메시지는 문서(Documentation)입니다.

또 다른 사례가 있었습니다. 에이전트가 단일 슬라이드의 표에 40개의 행을 넣으면, 하단의 26개 행은 경계 밖으로 벗어나 사라져 버렸습니다. 소리 없는 데이터 손실이었죠. 그래서 저는 래퍼가 긴 표를 여러 슬라이드에 걸쳐 자동으로 분할하고, 내용이 넘칠 때마다 연속 슬라이드를 생성하도록 가르쳤습니다. 이 문제는 기억해 두세요, 다시 나타날 테니까요.

그리고 WeasyPrint는 이모지(Emoji)를 렌더링할 수 없습니다. 에이전트는 PDF에 로켓 이모지를 넣었다가 작은 '두부 상자(Tofu box, 깨진 글자 기호)'를 마주하게 되면, 이를 이미지로 래스터화(Rasterize)하여 패치하려고 네 개의 스크립트를 낭비하며 허둥댔습니다. 외부에서 보기에는 "PDF 생성에 시간이 너무 오래 걸린다"라고 보였을 것입니다. 문제는 렌더링이 아니라 허둥대는 과정(Flailing)이었습니다. 해결책은 간단했습니다. 이모지를 쓰지 말고 실제 아이콘을 사용하도록 하여, 한 번에 제대로 구축하는 것이었습니다.

요점은, 작동하고 있었다는 것입니다. 저는 제가 좋은 도구를 다듬고 있다고 생각했습니다.

진단

제가 실제로 구축한 것은 다음과 같습니다. 슬라이드 덱들을 나란히 놓아보기 전까지는 미처 깨닫지 못했습니다.

여기에는 두 가지 상황이 벌어지고 있으며, 솔직히 말하자면 덜 영광스러운 쪽을 먼저 말씀드리겠습니다. 에이전트 (Agent)는 결과 중심적입니다. 작업을 주면 결과를 반환하고 싶어 하는데, 래퍼 (Wrapper)가 문서를 생성해 버렸기 때문에 파일이 존재하는 순간 에이전트는 작업이 완료되었다고 판단했습니다. 좋은 문서가 아닐지라도 어쨌든 문서였고, 그것만으로도 에이전트가 멈추기에는 충분했습니다. 이 추상화 (Abstraction)는 에이전트에게 탈출로를 제공하여, 실질적인 사고를 수행하기도 전에 작업을 마쳤다고 선언할 수 있는 방법을 제공한 셈입니다.

하지만 저는 이것을 순전히 에이전트의 심리 문제로만 포장하고 싶지는 않습니다. 왜냐하면 그 중 일부는 그보다 훨씬 단순한 문제이기 때문입니다. 래퍼 (Wrapper)가 여지를 거의 남겨두지 않았습니다. 레이아웃 (Layout)과 팔레트 (Palette)가 호출 단계에 이미 포함되어 있었기 때문에, 에이전트가 더 나은 것을 시도하려 했을 때조차 쉬운 경로에는 고작 몇 가지 선택지만이 제공되었습니다. 표지 하나, 몇 개의 통계 블록 (Stat blocks), 그리고 확신이 서지 않을 때는 표 (Table) 하나. 커스터마이징 (Customization)할 수 있는 범위의 천장이 낮다는 것은, 만들 수 있는 결과물의 천장도 낮다는 것을 의미하며, 이것이 이야기의 더 지루하고도 실질적인 절반입니다. 에이전트가 일찍 포기한 것과 래퍼가 에이전트를 가둔 것은 두 얼굴을 가진 동일한 문제였습니다.

몇 달 간격으로 제작된 도구의 두 가지 버전을 통해 동일한 작업, 즉 세계 최고 부자 순위를 수행한 결과입니다. 기술과 지침 (Instructions)은 동일했습니다. 제가 의도적으로 변경한 유일한 점은 래퍼 (Wrapper)가 중간에 위치했는지 여부뿐입니다. 표지만 봐도 무언가 변했다는 것을 알 수 있습니다.

The wrapper's cover: dark, generic, left-aligned

이전, 래퍼 (Wrapper)가 있는 경우. 어둡고 일반적이며, 제목이 한쪽으로 밀려나 있음.

The same brief without the wrapper: lighter, designed, a clear motif

이후, 래퍼 (Wrapper)가 없는 경우. 더 밝고, 의도적인 모티프 (Motif)가 있으며, 실제로 아트 디렉션 (Art-directed)이 이루어짐.

하지만 표지는 쉬운 부분입니다. 진짜 이야기는 각 버전이 리스트를 요청했을 때 동일한 순위인 실제 데이터를 어떻게 처리하느냐에 있습니다.

(Wrapper)는 순위를 표 (Table)에 붙여넣습니다. 20개의 행입니다. 슬라이드 한 장에 다 들어가지 않기 때문에, 마지막 세 행은 "(cont.)"라고 표시된 두 번째 슬라이드로 넘겨집니다.

The wrapper dumps the twenty-row ranking into a table

(Wrapper)의 본능: 20개 행의 전체 순위를 표에 붙여넣기.

The last three rows spill onto a second slide stamped

다 들어가지 않으므로, 마지막 세 행은 "(cont.)"라고 표시된 별도의 슬라이드로 넘어갑니다.

그 이어지는 슬라이드가 바로 결정적인 단서이며, 실제로 저를 깨닫게 만든 부분이었습니다. 그것은 제가 (Wrapper)에게 긴 표를 자동으로 분할하도록 가르쳤기 때문에 존재할 수 있었는데, 당시에는 그것이 좋은 기능이라고 생각했습니다. 하지만 긴 표를 여러 슬라이드에 걸쳐 페이지를 나누는(Paginating), 제가 자랑스러워했던 그 기능은 하나의 증상이었습니다. (Wrapper)가 "행을 붙여넣는 것"을 쉬운 선택지로 만들었기에 에이전트가 행을 붙여넣었고, 저는 에이전트가 행을 붙여넣은 뒤에 이를 정리하는 도구를 만들었습니다. 저는 제가 만든 추상화 (Abstraction)가 계속해서 만들어내는 난장판을 자동화하여 치우고 있었던 것입니다.

이제 (Wrapper)가 없는 버전으로 동일한 순위, 동일한 숫자를 살펴보겠습니다.

No wrapper: the same ranking as a chart, one bar in the accent color, the rest grayed out

(Wrapper) 없음: 동일한 순위를 차트 (Chart)로 표현, 강조 색상(Accent color)을 사용한 하나의 막대, 핵심을 짚어주는 헤딩 (Heading).

표는 없습니다. 그것은 순위를 차트 (Chart)로 변환하고, 강조 색상 (Accent color)을 사용한 하나의 막대를 배치한 뒤 나머지는 회색으로 처리했으며, 레이블 (Label) 대신 논점을 제시하는 헤딩 (Heading)을 슬라이드에 부여했습니다. 래퍼 (Wrapper)는 해당 슬라이드를 "순자산 기준 상위 20위"라고 불렀습니다. 반면 이 버전은 "머스크 혼자서 다음 14명을 합친 것보다 더 많은 부를 보유하고 있다"라고 부릅니다. 데이터는 동일합니다. 하나는 주제를 명명하고, 다른 하나는 그것에 대해 어떻게 생각해야 할지를 알려줍니다. 그리고 그 격차가 기본적으로 이 포스트의 핵심입니다.

그리고 이는 단 하나의 슬라이드가 아니라 데크 (Deck) 전체에 걸쳐 나타납니다. 래퍼는 섹션을 "규모 (THE SCALE)", "국가별 분석 (Country Breakdown)", 그리고 하나는 문자 그대로 "01"이라고 번호만 매겨 구분합니다. 래퍼가 없는 버전은 매번 결론을 작성합니다. 래퍼를 제거하면 에이전트 (Agent)는 데이터를 쏟아내는 것 (Dumping)을 멈춥니다. 왜냐하면 쏟아내는 것이 더 이상 쉬운 해결책이 아니기 때문입니다.

역행하는 것처럼 느껴졌던 해결책

그래서 저는 라이브러리 (Library)를 삭제했습니다.

그것은 말하는 것보다 더 어려웠으며, 기술적인 이유 때문은 아니었습니다. 저는 그 래퍼에 몇 주를 보냈고, 버그를 수정할 때마다 그것은 점점 더 저의 것이 되어갔습니다. 제가 그것에 더 많은 것을 쏟아부을수록, 그것을 삭제하는 것은 마치 작업물을 불태워 버리는 것처럼 느껴졌습니다. 그것은 매몰 비용 (Sunk cost)이 말하는 것이며, 매몰 비용은 바로 당신이 무언가를 끝냈어야 할 훨씬 이후에도 계속해서 다듬게 만드는 주범입니다. 래퍼는 실행되고 파일을 생성한다는 좁은 의미에서는 작동했습니다. 하지만 그것이 작동하느냐는 질문이 아니었습니다. 질문은 그것이 저에게 조용히 어떤 비용을 치르게 하고 있는가였으며, 일단 그것을 깨닫고 나니 더 나은 래퍼가 답이 아니라는 것을 알게 되었습니다. 어떤 래퍼도 답이 아니었습니다. 그래서 저는 에이전트를 다시 원시 라이브러리 (Raw libraries), 긴 스크립트 (Scripts), 그 모든 것 위로 돌려놓았습니다.

하지만 단순히 원시 상태로 두고 희망에 맡긴 것은 아닙니다. 두 가지가 래퍼의 자리를 대신했으며, 그 중 어느 것도 코드는 아닙니다.

첫째, 에이전트가 무언가를 구축하기 전에 작성해야 하는 디자인 브리프 (design brief)입니다. 슬라이드가 아니라 브리프입니다. 방향을 정하십시오. 하나의 타이포그래피 스케일 (type scale)을 선택하고 이를 고수하십시오. 강조 색상 (accent color)을 하나 정하고, 왜 이 주제에 그 색상을 사용하는지 설명하십시오. 이 문서가 당신이 만든 지난 문서와 어떻게 다른지 증명하십시오. 모든 헤딩 (heading)은 레이블 (label)이 아닌 핵심 요약 문장 (takeaway sentence)이어야 합니다. 하나의 시각적 모티프 (visual motif)를 끝까지 유지하십시오. 에이전트는 python-pptx를 열기 전에 종이 위에서 이 모든 것에 전념해야 합니다.

둘째, 래퍼 (wrapper) 대신 레시피 북 (recipe book)입니다. 각 형식마다 스니펫 (snippets)으로 가득 찬 스타일링 가이드 (styling guide)가 있지만, 에이전트는 이를 그대로 붙여넣는 것이 아니라 적응시켜야 한다고 지시받습니다. 스니펫은 출발점일 뿐입니다. 그다음 에이전트는 이 특정 문서를 아트 디렉팅 (art-direct)하기 위해 색상, 크기, 구조를 변경해야 합니다.

제약 조건이 곧 창의성입니다. 쉬운 길을 제거하는 것이 에이전트로 하여금 결정을 내리게 강제하며, 이러한 결정이야말로 단순한 문서와 디자인된 문서 사이의 결정적인 차이를 만듭니다.

이것이 추상화 (abstraction)가 나쁘다는 뜻은 아닙니다. 로우 라이브러리 (raw libraries) 또한 완벽한 최종 해답은 아닙니다. 에이전트에게 몇 가지 프리셋 (presets) 대신 실제로 커스텀할 수 있는 여유를 주는 더 강력한 추상화가 있다면, 래퍼와 로우 스크립트 (raw scripts) 모두를 이길 수 있을 것입니다. 그것이 바로 제가 지금 구축하고자 하는 목표입니다. 하지만 그것은 아직 존재하지 않으며, 존재하기 전까지는 에이전트가 직접 수작업을 하게 만드는 것이 실제로 보낼 가치가 있는 결과물을 만들어내는 버전입니다.

대가

이 과정이 공짜였다고 거짓말하지는 않겠습니다. 공짜가 아니었기 때문입니다.

토큰 (Tokens) 사용량이 즉시 다시 치솟았습니다. 다섯 줄이었던 코드가 다시 거대한 스크립트가 되었고, 그 결과 모든 문서 제작 비용이 더 비싸지고 속도도 느려졌습니다. 변동성 (Variance) 또한 증가했습니다. 문서는 다시 망가진 상태로 돌아오기 시작했습니다. 예전에 래퍼가 삼켜버렸던 바로 그 버그들, 즉 투명한 채우기 (transparent fills), 슬라이드 범위를 벗어난 테이블 (off-slide tables) 등이 모두 다시 나타났습니다.

그렇다면 왜 그것을 유지해야 할까요? 창의성이 돌아왔기 때문입니다. 그리고 그것은 제가 다른 어떤 방법으로도 살 수 없는 유일한 것이었습니다. 버그는 수정할 수 있습니다. 에이전트에게 무엇을 피해야 하는지 말하면 에이전트는 그것을 피합니다. 하지만 '일반적이지만 작동은 하는 (Generic-but-working)' 상태는 버그가 아니라 한계치 (ceiling)이며, 한계치에는 패치 (patch)가 존재하지 않습니다. 저는 영구적으로 평범하면서도 그것을 즐거워하는 도구를 출시하느니, 차라리 수정 가능한 문제들을 쫓겠습니다.

보조 도구 없이 안전하게 유지하기

당연한 반론이 있을 것입니다. '좋습니다, 하지만 이제 당신의 결과물은 절반의 확률로 망가진다는 거군요.' 맞습니다. 그렇다면 방금 삭제한 것을 다시 추가하지 않고 어떻게 안전성을 다시 확보할 수 있을까요?

AI 자동 생성 콘텐츠

본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.

원문 바로가기
0

댓글

0