[나의 앱개발기] 비개발자가 AI로 직장 업무 자동화 도구를 만들다 실패한 이야기

노조 집행부 일을 맡고 나서 가장 먼저 든 생각이 있었습니다. "이 공문 작업, 매번 이렇게 하는 건 너무 비효율적이다." 문서번호, 수신처, 제목, 본문을 매번 Word에서 양식 불러와서 고치고, PDF로 저장하고, 메일로 보내고. 반복되는 루틴이 몇 달째였습니다.

저는 개발자가 아닙니다. Google Apps Script를 조금 만져본 정도가 전부인 사람이에요. 그런데 어느 순간 Claude AI와 대화하다가 '이거, 나도 만들 수 있지 않을까?' 싶었거든요. 그래서 시작했습니다. 결론부터 말하면, 수십 번의 수정, 수십 번의 오류를 거쳤고, 지금도 완벽하게 작동하진 않습니다. 그런데 이 과정에서 건진 게 꽤 많았어요.

이 글은 그 실패의 기록입니다.

목차

1. 어떤 걸 만들려고 했나

2. 계속 발목을 잡은 오류들

3. 끝내 해결 못 한 것들

4. 그래도 이 경험에서 건진 것들

5. 다음 단계: 뭘 보완할 건지

* 어떤 걸 만들려고 했나.

목표는 단순했습니다. 공문 양식 위에 텍스트를 입력하면, 그게 그대로 PDF로 뽑히는 웹앱. Flask 같은 서버 없이, HTML 파일 하나로 돌아가는 형태로요. 누구한테 서버 빌려달라고 부탁하기도 귀찮고, 회사 PC에 뭔가 설치하는 것도 번거로우니까요.

구체적인 기능 목록은 이랬습니다.

  • 공문 양식 이미지를 배경으로, 그 위에 입력 박스 배치
  • 왼쪽에 입력하면 오른쪽 미리보기에 실시간 반영
  • 기존 PDF 공문을 불러오면 Claude AI가 내용 자동 추출
  • 본문 편집 가능 (글꼴, 크기, 정렬, 줄간격)
  • PDF로 저장
  • 작성한 문서 저장 및 불러오기

이걸 Claude와 대화하면서 하나씩 만들었습니다. 코드를 직접 짜는 게 아니라, Claude가 짜준 코드를 HTML 파일에 붙여넣고, 실행해보고, 안 되면 다시 물어보는 방식으로요. 처음엔 생각보다 잘 됐습니다. 그래서 방심했거든요.

* 계속 발목을 잡은 오류들.

오류는 한 가지씩 오지 않았습니다. 하나를 고치면 다른 게 터졌어요. 주요 문제들을 정리하면 이렇습니다.

문제 증상 원인 해결 여부
입력값 미리보기 미반영 왼쪽에 타이핑해도 오른쪽에 안 나옴 readonly 속성 + contenteditable div에 .value 접근 ✅ 해결
필드 위치 겹침 모든 입력 박스가 top:0에 쌓임 이미지 로드 전에 posFields() 실행 ✅ 해결
PDF 불러오기 CORS 오류 "네트워크 오류" 메시지만 반복 브라우저 직접 API 호출 차단 ✅ 해결
PDF 생성 한글 깨짐 특수문자(※, —)가 빈칸으로 출력 폰트 subset에 해당 문자 미포함 ✅ 해결
PDF 본문 위치 틀어짐 생성된 PDF에서 텍스트가 구분선에 붙거나 잘림 html2canvas 비율 오차 + Y좌표 오차 ⚠️ 부분 해결
띄어쓰기 사라짐 PDF 불러오면 "민주적노사관계를통한"처럼 붙음 pdf.js 텍스트 추출 시 공백 아이템 제거 ✅ 해결
f-string JS 충돌 SyntaxError: Invalid or unexpected token Python f-string의 {{ }}가 JS 템플릿 리터럴과 충돌 ✅ 해결

표로 정리하니 깔끔해 보이지만, 실제로는 하나를 고치는 데 하루가 걸리기도 했습니다. 특히 입력값이 오른쪽에 반영이 안 되는 문제는 원인을 찾는 데만 꽤 걸렸어요. div.value로 접근하면 당연히 안 되는 건데, 그걸 모르고 계속 다른 곳을 수정하고 있었거든요.

CORS 문제도 만만치 않았습니다. 브라우저에서 Claude API를 직접 호출하면 차단되는 게 기본값이에요. 처음엔 corsproxy.io 같은 프록시를 썼는데 불안정했고, 결국 Anthropic이 공식 지원하는 anthropic-dangerous-direct-browser-access 헤더를 쓰는 방식으로 해결됐습니다. 이런 헤더가 있다는 걸 모르면 며칠을 삽질할 수 있는 부분이죠.

한글 폰트 문제도 꽤 골치였습니다. NanumGothic을 woff2로 넣었더니 jsPDF가 woff2를 지원하지 않아서 'Cannot read properties of undefined (reading Unicode)' 오류가 났어요. TTF로 바꾸고, subset으로 만들어서 넣었더니 이번엔 ※ 같은 특수문자가 빠져 있었고요. 폰트 파일 하나 때문에 세 번을 다시 만들었습니다.

* 끝내 해결 못 한 것들.

솔직히 말하면, 아직 완성이라고 부르기 어렵습니다. 현재까지 해결 못 한 것들이 있거든요.

1. PDF 생성 결과물의 미묘한 위치 오차.

미리보기에서는 딱 맞게 보이는데, PDF로 저장하면 텍스트가 미묘하게 밀립니다. 구분선과 본문 사이 여백이 좁거나, 필드값이 레이블에 살짝 겹치거나. 매번 Y좌표를 수동으로 조정하는데도 완전히 잡히지 않아요. html2canvas 방식은 화면 캡처라 비율이 틀어지고, jsPDF 직접 삽입 방식은 좌표 계산이 까다롭습니다.

2. PDF 불러오기 서식 복원.

기존 공문 PDF를 불러오면 내용은 추출되는데, 줄간격이나 가운데 정렬 같은 서식은 완벽하게 재현이 안 됩니다. pdf.js로 텍스트를 뽑으면서 위치 정보는 어느 정도 건지지만, '— 아 래 —' 같은 가운데 정렬 텍스트가 오탐되는 경우가 있었거든요. Claude에게 추출을 시켜도 한계가 있습니다.

3. 공용 저장소.

여러 사람이 같은 문서 목록을 공유하는 기능은 결국 서버 없이는 안 된다는 걸 알게 됐습니다. localStorage는 해당 브라우저에만 저장되니까요. 임시방편으로 기본 문서 2개를 HTML에 하드코딩해뒀는데, 이건 진짜 해결이 아닙니다.

미리보기와 PDF가 다르게 보이는 문제
서식이 완벽히 복원 안 되는 문제
공용 저장소 부재

이 세 가지가 아직 숙제입니다.

* 그래도 이 경험에서 건진 것들.

실패라고 생각하지 않는 이유가 있습니다. 이 과정에서 배운 게 훨씬 많았거든요.

가장 큰 수확은 브라우저와 HTML이 어떻게 돌아가는지에 대한 감각을 얻은 겁니다. contenteditable이 뭔지, DOM 조작이 어떻게 되는지, 이미지 로드 타이밍이 왜 중요한지. 코딩 책에서 배우는 게 아니라, 실제로 오류를 겪으면서 몸으로 익힌 거죠. 그게 다릅니다.

그리고 AI와 협업하는 방법도 조금 알게 됐어요. Claude에게 뭔가를 물어볼 때, '증상을 정확히 설명할수록' 답이 빠르다는 걸요. 처음엔 "왜 안 돼요?"라고만 했는데, 나중엔 "콘솔에 이런 오류가 뜨고, 해당 함수는 이렇게 생겼는데, 이 부분이 문제인 것 같다"는 식으로 바뀌었거든요. 개발자들이 왜 스택 트레이스를 공유하는지 이해가 됐습니다.

마지막으로, 복잡한 걸 반복해서 고치다 보면 언제 전면 재작성이 필요한지도 감이 옵니다. 처음엔 부분 수정만 하다가, 어느 순간 코드가 너무 꼬여서 v5로 처음부터 다시 만들었거든요. 그게 훨씬 빠르고 깔끔했어요. 이 판단을 언제 해야 하는지가 실력이더라고요.

* 다음 단계: 뭘 보완할 건지.

이 프로젝트를 완성이라고 부르려면 세 가지가 더 필요합니다.

1. PDF 좌표 정밀화.
pdfplumber 같은 도구로 공문 양식의 각 영역을 mm 단위로 정확히 측정하고, 그 좌표를 기준으로 텍스트를 삽입하는 방식으로 바꿔야 합니다. 눈대중이 아니라 수치 기반으로요.

2. Google Sheets 연동.
공용 저장소는 Google Apps Script + Sheets 조합이 가장 현실적입니다. 이미 GAS 경험이 있으니, 저장/불러오기 API를 만들어서 연결하면 됩니다. 서버 없이도 되거든요.

3. 서식 복원 로직 개선.
pdf.js 텍스트 추출 시 x, y 좌표 정보를 더 적극적으로 활용하고, 가운데 정렬 판정 기준을 더 엄격하게 잡으면 됩니다. 이미 방향은 잡혀 있어요.

한 번에 완성된 건 아무것도 없었습니다. 그리고 생각해보면, 그게 맞는 순서인 것 같기도 해요. 작동하는 걸 하나 만들고, 거기서 문제를 찾고, 다시 고치고. 개발자들이 하는 일이 정확히 이거더라고요.

애드센스 6번째 도전을 앞두고 이 글을 쓰는 것도, 비슷한 마음입니다. 5번 떨어졌다고 포기할 이유가 없고, 매번 떨어진 이유가 달랐으니 그 이유를 정확히 이해하면 됩니다. 공문 자동화 도구를 만들다가 배운 것처럼요.

* 마무리 정리.

비개발자가 AI와 함께 업무 자동화 도구를 만들면서 마주친 현실은 이랬습니다. 하나를 고치면 하나가 터지고, 원인을 모르면 엉뚱한 곳만 수정하게 되고, 그래도 계속 하다 보면 어느 순간 작동하는 것들이 쌓입니다.

완성하지 못한 부분이 있다는 게 부끄럽지 않습니다. 3개월 전에는 contenteditable이 뭔지도 몰랐는데, 지금은 왜 그게 .value로 안 되는지 설명할 수 있으니까요. 그걸로 충분합니다. 일단은.

비슷한 시도를 하고 있는 분이 있다면, 이 글이 조금이라도 위안이 됐으면 합니다. 오류는 당신이 멍청해서가 아니라, 원래 그런 겁니다.

이 블로그의 인기 게시물

[나의 앱 개발기] 코딩 모르는 직장인이 AI 문제출제 앱 혼자 만든 이야기 (feat. Claude, Next.js, Vercel)

[나의 앱 개발기] 딸을 위해 '무한의 계단' 게임을 직접 만들어봤다 — AI + HTML + GitHub Pages 1인 개발기

[나의 앱 개발기] Claude로 클래식 테트리스 게임 직접 만들어본 후기