목록으로
제품

HWP 에이전트, 문서를 띄워놓고 말로 고치는 기능을 이렇게 만들었어요

팩트챗에 한글 문서를 올려 두고, 화면 왼쪽 대화로 오른쪽 문서를 직접 고치는 HWP 에이전트를 만들었어요. 목표는 처음부터 하나였어요. 말로 시켜서 한글 문서를 고치는, 완성도 높은 AI 한글 편집기를 만드는 것. 문서 엔진을 브라우저에서 돌리기로 한 이유, 편집기 화면이 무엇을 제공하는지, 표의 병합 셀과 누름틀에서 어려웠던 점을 적었어요.

2026-09-10

HWP 에이전트, 문서를 띄워놓고 말로 고치는 기능을 이렇게 만들었어요

TL;DR

  • 공공·대학 업무는 여전히 HWP로 돌아가는데, 팩트챗은 오래도록 읽기만 됐어요. 요약은 해주는데 그 결과를 다시 한글에 옮기는 건 사람 몫이었고요.
  • 처음엔 샌드박스에서 파이썬으로 HWPX를 고쳐 봤어요. 되긴 됐는데 사용자가 문서를 보면서 고칠 수가 없었어요.
  • 두 번째로 고른 길이 지금의 HWP 에이전트예요. 문서 엔진을 WebAssembly로 빌드해 브라우저에서 돌리고, 화면 왼쪽 대화로 오른쪽 문서를 직접 고쳐요.
  • 서버의 에이전트는 문서 바이트를 들고 있지 않아요. 오가는 건 파일이 아니라 "이 셀에 이 값을 넣어라" 같은 편집 명령이에요.
  • 신청서·공문처럼 서식이 정해진 문서에서 제일 잘 맞아요.

왜 만들었나 — 읽기는 되는데 쓰기가 안 됐다

팩트챗 고객의 상당수가 대학과 공공기관이에요. 이분들이 하루에 다루는 문서는 공문, 신청서, 제안요청서, 사업계획서고 그 확장자는 대부분 HWP예요.

팩트챗은 처음부터 HWP를 읽을 수는 있었어요. 문서를 올리면 파싱 서비스가 내용을 뽑아 주니까 요약하고 찾아주는 건 잘 됐죠. 문제는 그다음이었어요. AI가 써 준 문장을 복사해 한글을 열고, 표의 그 칸을 찾아 붙이고, 달라진 글꼴을 다시 맞추는 일. 시간을 잡아먹은 건 문장을 쓰는 일이 아니라 문장을 원래 서식 안으로 되돌려 놓는 일이었어요.

목표는 처음부터 분명했어요. 말로 시켜서 한글 문서를 고치는, 완성도 높은 AI 한글 편집기를 만드는 것. 문서를 읽어 주는 기능을 하나 더 붙이는 게 아니라, 담당자가 한글을 열지 않고도 작업을 끝낼 수 있는 편집기여야 한다고 봤어요.

HWPX 문서를 연 직후의 편집 화면 — 왼쪽은 대화, 오른쪽은 문서 본문

화면은 이렇게 나왔어요. 문서를 올리면 곧바로 이 화면이 열려요. 오른쪽은 미리보기 이미지가 아니라 지금 편집 중인 문서 자체라서, 글꼴이나 줄 간격을 손으로 만져도 돼요. 왼쪽에서 말로 시킨 결과가 오른쪽에 그대로 반영되고요.

처음 열면 왼쪽에 요청 예시 네 개가 떠요. 내용 요약, 맞춤법과 띄어쓰기 다듬기, 공문 형식에 맞게 문체 다듬기, 표로 정리할 만한 내용을 표로 바꾸기. 무엇부터 시켜야 할지 모르겠다는 말을 많이 들어서 자주 쓰는 네 가지를 그 자리에 뒀어요.

첫 번째 시도 — 샌드박스에서 파이썬으로 고쳐보기

2026년 5월 초에 먼저 해 본 건 이미 있는 것으로 붙이는 방법이었어요. 팩트챗 에이전트는 코드 실행 샌드박스를 쓰니까, 문서를 샌드박스에 내려받고 파이썬 라이브러리로 HWPX를 고치게 했죠. 레거시 .HWP는 그대로는 손댈 수 없어서 변환 도구를 하나 붙여 HWPX로 바꾼 다음 편집했어요.

동작은 했어요. 다만 제품으로 내기엔 두 가지가 걸렸어요.

첫째, 사용자가 결과를 볼 수가 없었어요. 편집은 샌드박스 안에서 일어나고, 사용자는 다 끝난 파일을 내려받아 한글로 열어봐야 무엇이 바뀌었는지 알았죠. 표 한 칸을 고쳤는데 행 높이가 늘어 다음 쪽으로 넘어갔다면, 그건 열어보기 전까지 아무도 몰라요.

둘째, 매번 코드를 새로 짜는 구조였어요. 같은 요청이라도 그때그때 다른 코드가 나오니 결과가 흔들렸고요.

이 두 가지가 다음 결정을 정해 줬어요. 편집은 보이는 곳에서, 정해진 조작으로 일어나야 한다는 것.

세 갈래 중에 무엇을 고를까

핵심 결정은 문서 엔진을 어디서 돌릴지였어요.

첫 번째는 윈도우에서 한글 프로그램을 자동 조작하는 길이에요. 한글이 직접 여니까 제일 정확해요. 대신 한글이 깔린 윈도우 머신이 필요하고, 사용자가 동시에 열 명만 들어와도 그만큼의 세션을 관리해야 해요. 서비스로 굴리기엔 운영 부담이 컸어요.

두 번째는 서버에서 문서 엔진을 돌리는 길이에요. 운영은 단순해지는데, 고객 문서 파일이 우리 서버 메모리에 올라와요. 문서 반출에 민감한 기관일수록 이 지점을 물어보시거든요.

세 번째가 우리가 고른 길이에요. 문서 엔진을 WebAssembly로 만들어 브라우저에서 돌리는 방식이죠. 파일을 여는 일도, 화면에 그리는 일도, 저장하는 일도 전부 사용자 브라우저 안에서 해요. 서버의 에이전트는 문서 바이트를 들고 있지 않고, 편집 명령만 브라우저로 보낸 뒤 결과를 돌려받아요.

구성 — 무엇이 어디에 있나

팩트챗 HWP 에이전트 구성도 — 브라우저의 문서 엔진, 서버의 에이전트 루프, 모델

왼쪽이 사용자 브라우저예요. 채팅 패널과 문서 엔진이 든 iframe이 한 화면에 나란히 있어요. 문서 파일은 여기서 열리고 여기서만 살아 있고요.

가운데가 팩트챗 서버예요. 업로드로 세션을 만드는 REST 엔드포인트가 하나 있고, 편집 대화는 WebSocket으로 붙어요. 에이전트 루프는 요청 하나를 편집 명령 여러 개로 쪼개는 일을 해요. 도구는 표·셀·누름틀·서식·쪽 설정·이미지처럼 문서에 실제로 가할 수 있는 조작으로 나뉘어 있고, 각 도구는 iframe 안 엔진을 부르는 RPC 한 번으로 끝나요.

오른쪽이 모델이에요. 모델에는 조회 결과와 편집 계획만 오가요. 문서 파일 자체는 여기까지 오지 않고요.

짚어 둘 게 하나 있어요. 브라우저에서 파일을 처리한다고 해서 문서 내용이 아무 데도 안 나가는 건 아니에요. AI가 무엇을 고칠지 판단하려면 표 구조나 문단 텍스트 같은 조회 결과는 모델 입력으로 들어가요. 원본 파일이 어디서 처리되는지와 모델에 무엇이 전달되는지는 따로 봐야 해요. 망분리나 반출 제한이 있는 환경이라면 이 구분을 먼저 확인해 주세요.

요청 한 줄이 문서에 닿기까지

한 번의 요청이 처리되는 순서 — 채팅 패널, 에이전트 루프, 문서 엔진, LLM 사이의 시퀀스

"3번 표의 빈칸을 채워줘"라고 치면 이런 순서로 흘러가요.

  1. 요청이 서버의 에이전트 루프로 가요.
  2. 무엇을 물어보고 무엇을 고칠지를 모델과 정해요. 문서를 안 보고 값을 채우는 일은 없어요.
  3. 문서 구조를 조회하고 편집 명령을 브라우저 엔진에 보내요. 이때도 문서 파일은 서버로 오지 않아요.
  4. 화면의 문서가 그 자리에서 바뀌어요. 값을 넣은 뒤에는 행 높이와 쪽 넘김이 그대로인지 다시 확인해요. 글자가 들어간 것과 배치가 유지된 건 따로 확인해야 하니까요.

턴이 끝나면 엔진이 문서 전체를 내보내고, 서버는 그 시점의 상태를 기록해 둬요. 되돌리기가 이 기록 위에 있고요.

실제로 해 보면 이렇게 나와요. 위의 표지 문서를 열어 두고 "표지의 '지자체명'을 '마인드로직시'로 바꾸고, 그 아래 발행 연월을 2026. 9. 로 맞춰줘"라고 한 줄 보냈어요.

요청 한 줄로 표지의 지자체명과 발행 연월이 바뀐 화면, 왼쪽에는 문서 확인 1회·문서 편집 2건의 작업 내역이 펼쳐져 있다

문서 쪽은 앞 그림과 같은 자리에서 글자만 바뀌었고, 왼쪽에는 문서 확인 1회, 문서 편집 2건이라는 줄이 남았어요. 펼치면 전체 텍스트 확인 한 번과 블록 텍스트 바꾸기 두 번이 각각 완료로 찍혀 있어요. 위 시퀀스의 3~6번이 사용자 화면에서는 이 목록으로 보이는 거예요.

기술적으로 제일 오래 붙잡은 두 가지

1. 눈에 보이는 격자와 실제 셀은 같은 게 아니다

같은 표를 두고 화면의 격자 칸 수와 실제 셀 수가 다른 경우

한글 표는 병합된 셀이 여러 칸을 차지해요. 사람 눈에 보이는 3행 2열이 파일 안에서는 다른 셀일 수 있어요. 셀 속성에는 행·열 주소와 각각의 병합 개수가 들어 있고, 병합으로 덮인 좌표에는 셀이 아예 없거든요.

엔진은 화면의 격자 좌표와 값을 담는 실제 셀을 이어 주는 표현을 따로 만들어요. 에이전트는 값을 넣기 전에 표 구조를 먼저 조회하고, 값을 넣은 뒤에는 행 높이와 쪽 배치를 다시 확인해요. 한 줄이 두 줄이 되면 표가 다음 쪽으로 넘어가니까요.

2. 누름틀은 안내문을 바꾸는 게 아니다

빈 누름틀이 들어 있는 서식 — 안내문, 자리 이름, 채운 값은 각각 다르다

신청서의 회색 입력 자리는 글자처럼 보여도 필드예요. 화면에 보이는 안내문, 그 자리의 이름, 실제로 채운 값이 각각 달라요. 안내문을 찾아 치환하면 겉보기엔 채워졌는데 필드는 여전히 비어 있는 상태가 돼요.

그래서 누름틀은 이름을 먼저 조회하고, 그 이름으로 값을 넣는 경로를 따로 써요. 같은 서식을 여러 기관 이름으로 찍어낼 때 이 구분이 그대로 이득이 되고요.

HWP 문서 편집기를 더 자세히

오른쪽에 있는 건 뷰어가 아니라 편집기예요. 파일·편집·보기·입력·서식·쪽·표·도구 메뉴가 그대로 있고, 리본에는 되돌리기와 다시 실행, 문단 모양, 글자 모양, 표, 그림, 머리말·꼬리말, 각주가 붙어 있어요. 아래 상태바에는 지금 몇 쪽인지, 전체 몇 쪽인지, 배율이 얼마인지가 나와요. 한글을 쓰던 손이 그대로 얹히는 자리를 목표로 했어요.

사람과 에이전트가 같은 문서를 만져요

에이전트에게 시키다가 본인이 직접 고쳐도 돼요. 커서를 놓고 타이핑하거나, 글자 크기를 바꾸거나, 표에 행을 넣는 일을 손으로 해도 됩니다. 대신 에이전트가 편집하는 동안에는 문서가 잠깐 잠겨요. 그때는 「에이전트가 문서를 편집하는 중」, 조회만 하는 단계라면 「에이전트가 문서를 확인하는 중」이라는 표시가 문서 위에 떠요.

사람이 손으로 고친 내용은 그냥 묻히지 않아요. 다음에 에이전트에게 무언가를 시키면 「직전 턴 이후 사용자가 이렇게 바꿨다」는 정보가 함께 전달돼요. 에이전트가 자기가 마지막으로 본 상태를 기준으로 판단하다가 사람이 고친 부분을 덮어쓰는 일을 막으려고 넣은 장치예요.

중간에 멈춰도 괜찮아요

에이전트가 일하는 중에 중지 버튼을 눌러도 돼요. 이미 반영된 편집은 문서에 남고, 거기서부터 다시 시키면 돼요. 작업 중에 페이지를 벗어나려 하면 진행 중인 요청이 중단된다는 확인이 뜨고, 연결이 끊겨 턴이 중간에 멈춘 경우에는 다시 보내기 버튼이 나와요.

문서를 다시 찾는 자리

시작 화면에는 파일을 끌어다 놓는 자리와 지금까지 작업한 문서 목록이 같이 있어요. 문서 작업은 한 번에 끝나는 일이 드물어서, 어제 만지던 문서로 돌아오는 동선이 새 문서를 여는 동선만큼 중요해요.

파일을 끌어다 놓는 영역과 지금까지 작업한 문서 목록이 함께 있는 시작 화면

문서 카드에는 원본이 HWP였는지 HWPX였는지, 마지막으로 만진 게 언제인지, 몇 번 수정됐는지가 붙어요. 문서를 다시 열 때는 하던 대화를 이어갈지, 문서만 가져와 새 대화로 시작할지 고를 수 있어요. 같은 서식으로 다른 기관 문서를 만들 때 뒤쪽을 쓰게 돼요.

빈 문서에서 시작하는 길도 옆에 뒀어요. 주제를 적으면 문서의 뼈대부터 만들어 주는 쪽이에요.

빈 문서로 시작했을 때의 화면

열어 두고 정한 제약 두 가지

데스크톱 전용으로 열었어요. 문서 엔진과 폰트를 브라우저로 받아야 해서 작은 화면에서는 무거워요. 지금은 모바일에서 안내 화면으로 대신하고 있어요.

한 문서는 한 탭에서만 열려요. 두 탭에서 같은 문서를 열면 편집이 엇갈리니까 뒤에 연 탭은 잠기고, 앞 탭을 닫으면 자동으로 이어져요.

권한은 기관이 정해요. 기관 단위로 켜고 끄는 것은 물론, 그 안에서 부서나 개인 단위로 좁힐 수도 있어요. 문서 편집은 모든 구성원에게 열 기능이 아닐 수 있으니까요.

이렇게 쓰면 잘 맞아요

값만 비어 있는 정형 서식 — 이런 문서에서 가장 잘 맞는다

제일 잘 맞는 건 서식이 정해진 문서예요. 위 그림처럼 틀은 고정이고 값만 바뀌는 문서죠. 표의 빈칸을 채우고, 누름틀에 기관명과 기간을 넣고, 머리말에 문서번호를 다는 일이 대화 몇 줄로 끝나요.

같은 서식을 여러 벌 만들 때도 좋아요. 누름틀 이름을 한 번 확인해 두면 대상만 바꿔가며 채우면 되거든요.

받은 문서를 우리 형식으로 맞출 때도 쓸 만해요. 글꼴이나 줄 간격, 여백을 정리하는 건 사람이 하면 지루하고 AI가 하면 빠른 일이니까요.

요청은 나눠서 주세요. "이 문서 전체를 다 고쳐줘"보다 "3번 표의 빈칸부터 채워줘"가 훨씬 잘 돼요. 고칠 자리가 분명할수록 결과가 정확하고요.

마지막엔 한글에서 한 번 열어보세요. 제출용 문서라면 담당자 눈으로 한 번 더 보는 게 맞아요.

기반이 된 오픈소스

이 기능의 문서 엔진은 Edward Kim 님이 만든 오픈소스 rhwp예요. Rust로 HWP와 HWPX를 읽고 화면에 그리고 고치는 프로젝트이고, MIT 라이선스로 공개돼 있어요. 네이티브 CLI와 WebAssembly를 같이 타깃으로 삼는 덕분에 브라우저에서 돌릴 수 있었고, 저희가 고른 세 번째 길도 그래서 가능했어요.

저희가 더한 것은 팩트챗의 에이전트가 이 엔진에게 무엇을 물어보고 무엇을 시킬지 정하는 부분, 그리고 실제 업무 서식으로 돌려보며 찾은 호환성 문제들이에요.

문서를 띄워놓고 말로 고친다는 것

이 기능의 값어치는 한 줄로 말할 수 있어요. 한글 문서를 자연어로 편집한다는 것. 표의 몇 번째 칸인지, 누름틀 이름이 무엇인지, 글꼴을 어디서 바꾸는지 몰라도 "이렇게 고쳐 줘"라고 말하면 문서가 그대로 바뀌어요. 그 한 문장을 제대로 만들려고 문서 엔진을 어디서 돌릴지부터 표의 병합 셀과 누름틀이 파일 안에서 어떻게 생겼는지까지 내려갔어요.

만들면서 제일 많이 확인한 건 기능이 되느냐가 아니라 사용자가 그걸 보고 있느냐였어요. 샌드박스에서 파일을 고치는 것도 편집은 편집이지만, 무엇이 어떻게 바뀌었는지 화면에서 확인하지 못하면 사람은 결국 한글을 다시 열어 처음부터 검토해요. 그러면 줄여 주려던 일이 그대로 남죠. 그래서 대화와 문서를 같은 화면에 두고, 에이전트가 건드린 자리를 작업 내역으로 남기고, 값을 넣은 뒤 배치가 그대로인지 한 번 더 보게 만들었어요.

공문과 신청서를 다루는 분들에게 이 기능이 대신해 줬으면 하는 일은 분명해요. 문서를 새로 쓰는 일이 아니라, 이미 정해진 틀 안에서 값을 옮기고 서식을 맞추는 반복이에요. 그 반복이 줄어든 자리에 담당자의 시간이 남는다면 저희는 만들려던 걸 만든 거예요.

한글 파일을 열어 두고 고쳐야 할 일이 쌓여 있다면, 그 문서를 그대로 올려서 한 줄 시켜 보세요. 어디까지 되고 어디서 막히는지는 저희도 계속 듣고 있어요.

참고 자료