“단순한 관리를 넘어, 자동화된 워크플로우를 만들 수 있을까?” 지난 1편에서는 Next.js와 Supabase를 활용해 시스템의 뼈대를 잡고 데이터베이스를 설계하는 과정을 다뤘다.
하지만 실제 운영 환경에서는 더 큰 도전이 기다리고 있었다. 왜냐하면, 처음에 간단하게 만들어볼까? 였는데 산출물을 보고나니깐 욕심이 성큼 생겨버렸다.
PDF 텍스트 자동 추출, AI 자동 번역 API 연동, 그리고 대량 데이터 처리라는 높은 벽을 Claude Code와 함께 어떻게 넘었는지 이야기를 해보고자 한다.
1. 도전 과제: 사용자의 귀찮음을 해결하라
시스템이 구축된 후, 실제 사용해보려고 하니 “번역할 문장이 200개가 넘는 초기 서비스라면, 이걸 다 손으로 입력해야하나?”라는 생각이 먼저 들었다. 그렇게 된다면, 기획자들의 사용성은 기존과 크게 달라질 것이라 생각하지 않았다.
그리고 다양한 부서에서 수 많은 문서들을 일일이 타이핑을 해야한다면 기존에 문서를 주면 끝나는 문제에 일을 복잡하게 만드는 시스템으로 자리 잡을 수 있을 것이라 생각이 되었다.
[추가 기능 리스트]
1. OCR & PDF 파싱: 파일 업로드만으로 번역 대상 추출
: 한 장 인 경우, 파일을 변환하여 업로드 하는 것도 귀찮을 수 있어, 화면 캡쳐해서 올릴 수 있는 방식을 선택 했다
: 많은 경우, PDF 변환하여 업로드 할 수 있는 방법을 선택 했다.
2. AI 번역 제안: OpenAI/Claude를 연동해 클릭 한 번으로 초안 완성
: 등록 시, 번역을 하지 않고 AI가 1차 작업을 하고 검수만 하면 되는 프로세스로 작업 했다
3. 벌크 시스템: 수백 개의 데이터를 끊김 없이 한꺼번에 처리
: 용어집 및 단 건도 바로 올려서 할 수 있게 했고, 기존의 번역 된 맥락을 가져다 쓰도록 향후에 학습 해야하는 목적도 있었다.
2. Claude Code와의 협업: 복잡한 로직을 해결하는 프롬프트 전략
기술적 난이도가 올라갈수록 AI에게 단순히 “코드를 짜줘”라고 하는 것은 위험하다고 한다.
특히 파일 처리나 API 연동은 ‘비용’과 ‘성능’이 직결되기 때문이였다. 하지만 나 또한 토큰을 엄청 많이 써가면서 해결할 수 밖에 없었다.
ㄱ. 비용 효율적인 AI 번역 로직 설계
나의 프롬프트: > “OpenAI API를 연결해서 자동 번역 기능을 만들 거야. 하지만 사용자가 버튼을 누를 때마다 매번 호출하면 비용이 너무 많이 나올 것 같아. 이미 번역된 적이 있는 문장은 캐싱(Caching)하고, 여러 문장을 한 번에 묶어서(Batch) 보내는 효율적인 로직을 제안해 줘.”
ㄴ. 대용량 PDF 처리의 기술적 한계 돌파
나의 프롬프트: > “용량이 큰 PDF를 업로드하면 브라우저가 멈춰버려.
unpdf라이브러리를 사용하되, 사용자 화면이 멈추지 않도록 비동기 처리를 하고 싶은데, 비개발자 사용자가 진행 상황을 알 수 있게 ‘로딩 프로그레스 바’ 수치까지 계산해 주는 코드를 작성해 줘.”
Claude Code는 단순히 코드를 짜는 것에 그치지 않고, “서버 부하를 줄이기 위해 클라이언트 사이드에서 텍스트를 먼저 정제한 뒤 전송하자”는 식의 아키텍처 가이드를 제공 할 수 있도록 했다.
아! 물론 클로드코드를 쓰면서 어떻게 해야할지 Gemini, GPT 등 다양한 AI도구도 활용했다.
3. 기술적 도전 (1): PDF 텍스트 추출 시스템
가장 먼저 해결한 것은 ‘입력의 자동화’이다. 사용자가 PDF 기획서나 스크린샷을 올리면 시스템이 글자를 읽어들여야 한다.
ㄱ. 구현의 핵심: unpdf 라이브러리 활용
우리는 서버를 거치지 않고 브라우저에서 즉시 PDF를 읽을 수 있는 unpdf를 선택했다. 보안상 안전하고 속도가 빠르기 때문이다.
[PDF 파일 핵심 코드]

4. 기술적 도전 (2): AI 기반 자동 번역 엔진
번역 관리 시스템의 꽃은 ‘AI 번역 제안’이였다.
OpenAI의 GPT-4o 모델과 Anthropic의 Claude 3.5 Sonnet을 동시에 연동하여 사용자가 선택할 수 있도록 했다.
(향후에 회사의 지원이 kimi로 변경 되어서 AI는 kimi로 모든 것이 교체 되었다.)
ㄱ. 기획자의 인사이트: “AI는 초안일 뿐이다”
우리는 AI가 번역한 결과물을 바로 확정하지 않고, is_verified라는 필드를 두어, 반드시 ‘사람의 검토’를 거치게 설계했다. 이는 기술이 인간의 업무를 대체하는 것이 아니라 ‘돕는’ 도구라는 철학을 반영한 것이였다.
간혹, 맥락과 달리 단어만 맞추는 경우가 있기 때문에, 필수적으로 검수해야지 반영하도록 했다.
5. 기술적 도전 (3): 성능 최적화 (낙관적 업데이트)
데이터가 많아지면 시스템이 느려지기 마련이다.
특히 번역 상태를 바꿀 때마다 화면이 깜빡거리면 사용자 경험(UX)이 크게 저하되는 것을 고려하여 ‘낙관적 업데이트(Optimistic Updates)’ 기법을 적용했습니다.(이 것 또한 AI와 하면서 풀어나간 것이다)
ㄱ. 비개발자를 위한 설명: ‘일단 보여주고 나중에 저장하기’
사용자가 ‘번역 완료’ 버튼을 누르면, 실제로 서버에 저장이 완료되기 전이라도 화면에는 즉시 ‘완료’로 표시한다.
서버와의 통신 시간(약 0.5~1초)을 사용자가 느끼지 못하게 하여 ‘매우 빠른 시스템’이라는 인상을 줄 수 있다.
만약 저장이 실패하면? 시스템이 자동으로 이전 상태로 되돌리고 알림을 띄워주는 방식으로 만들어 나가는 방식을 선택 했다.
[낙관적 업데이트 로직_React Hook)]
![[낙관적 업데이트 로직_React Hook)]
const updateTranslation = async (id, newStatus) => {
// 1. 화면의 상태를 먼저 바꿉니다 (사용자는 즉각적인 반응을 느낌)
setOptimisticData(prev => prev.map(item => item.id === id ? {...item, status: newStatus} : item));
try {
// 2. 실제로 서버에 요청을 보냅니다
await supabase.from('translations').update({ status: newStatus }).eq('id', id);
} catch (error) {
// 3. 실패하면 원래대로 되돌립니다 (Rollback)
showError('저장에 실패했습니다. 다시 시도해 주세요.');
}
}](https://dophiplan.com/wp-content/uploads/2026/02/스크린샷-2026-02-24-오전-10.53.02.png)
6. 2~3일차의 성과: 무엇이 달라졌나?
고급 기능들이 추가되면서 시스템은 단순한 메모장에서 ‘전문적인 업무 도구’로 진화했다
1. 시간 절약: 기존에 수동으로 입력하던 100건의 번역 요청이 PDF 업로드 한 번으로 1분 만에 끝!
2. 품질 향상: AI가 제안한 초안 덕분에 번역가들의 작업 속도가 3배 이상 빨라졌음
3. 확장성: 이제는 수만 건의 데이터가 쌓여도 인덱싱과 비동기 처리 덕분에 시스템 안정 및 빠름
7. 기술보다 중요한 것은 ‘흐름’
Claude Code와 함께 복잡한 기능을 구현하며 깨달은 점은, 코드를 잘 짜는 것보다 ‘사용자의 업무 흐름’을 정확히 정의하는 것이 훨씬 중요하다는 것이다.