AI와 만드는 엔터프라이즈 번역 시스템 고도화 1편_버전 관리 & UX 혁신 편

“좋은 제품은 사용자가 실수할 수 있게 하고, 위대한 제품은 실수를 되돌릴 수 있게 한다.”
디자인 시스템과 품질 관리를 마친 우리 시스템은 겉보기에 완벽했다. 하지만 실제 운영 환경에서 번역가들이 마주한 공포는 예상치 못한 곳에 있었음. 바로 ‘수정 후 되돌릴 수 없다’는 심리적 압박감과 대량 작업 시의 동선 낭비였다.

6일 차, 사용자의 실수를 포용하는 버전 히스토리 시스템과 업무 효율을 극대화하는 하단 고정 바(Fixed Bottom Bar) 패턴을 도입했다.

1. 버전 히스토리 – 시간을 되돌리는 마법 구현

ㄱ. 번역 데이터의 휘발성 문제와 Audit Trail 설계

번역 관리 시스템에서 가장 위험한 순간은 사용자가 ‘저장’ 버튼을 누르는 찰나이다. 한 번 덮어씌워진 데이터는 이전 상태를 알 수 없게 되어,
“아까 그 문장이 더 나았던 것 같다”는 후회에 대응할 방법이 없었음. 이를 해결하기 위해 모든 변경 이력을 기록하는 Translation Audit Trail 시스템을 설계했다.

단순히 현재 텍스트를 업데이트하는 것에 그치지 않고, 별도의 translation_logs 테이블을 생성하여 이전 텍스트(previous_text), 새 텍스트(new_text), 변경자 정보를 차곡차곡 쌓기로 했다. 데이터베이스 인덱스를 translation_result_id와 생성 시각(created_at)에 걸어 조회 속도를 최적화했음

ㄴ. 사용자의 안심을 위한 버전 히스토리 UI 구현

단순히 기록만 하는 것이 아니라, 사용자가 직관적으로 시간을 되돌릴 수 있는 UI를 구축했다.
BulkVersionHistoryPanel 컴포넌트를 통해 현재 버전을 맨 상단에 파란색 배경으로 강조하여 현재 상태를 명확히 인지하게 했음.

가장 중요한 UX 디테일은 시간별 그룹화였다.
같은 시간에 수정된 여러 문장을 하나의 그룹으로 묶어 “2026년 2월 12일 오후 8시 버전”과 같이 표시했다. 사용자는 ‘복구 버튼’ 하나로 복잡한 쿼리 없이 이전 상태로 즉시 되돌릴 수 있게 되었음. 이는 사용자에게 “실수해도 괜찮다”는 심리적 안정감을 제공하는 결정적 계기가 되었다.

ㄷ. 자동 로깅 시스템과 API 통합

로그 생성을 수동으로 처리하면 개발자가 실수로 누락할 가능성이 크다.
따라서 API 엔드포인트(POST /api/translations/[id]/results) 수준에서 로깅 로직을 자동화했다. 특히 previousText !== newText 조건문을 넣어 의미 없는 저장 요청에 의한 데이터 낭비를 방지했음. 모든 변경 사항이 시스템 백엔드에서 조용히, 그러나 확실하게 기록되도록 조치했다.

2. 다중 제품 지원 – “RC+2” 배지의 탄생

ㄱ. Many-to-Many(다대다) 관계 리팩토링의 필요성

초기 설계에서는 하나의 용어가 하나의 제품에만 귀속되는 1:1 구조였다. 하지만 “이 용어는 RC, RV, RM 세 제품에 모두 공통으로 들어간다”는 실무자의 요구사항이 발생했음. 기획자로서 동일한 용어를 제품마다 세 번씩 등록하게 하는 것은 명백한 설계 결함이라고 판단했다.

기술적으로 이를 해결하기 위해 기존 glossary 테이블의 product_code 컬럼을 과감히 삭제하고, 중간 테이블인 glossary_products를 도입하는 M:N 관계 리팩토링을 단행했다. 이제 하나의 용어 아이디에 여러 개의 제품 코드를 연결할 수 있는 유연한 구조를 확보했음.

ㄴ. “RC+2” 형식의 스마트 배지 UI 적용

목록 화면에서 수많은 제품 이름을 나열하면 화면이 지저분해진다. 이를 해결하기 위해 첫 번째 제품명 뒤에 나머지 개수를 표시하는 “RC+2” 방식의 스마트 배지 로직을 구현했다. 제품이 하나일 때는 이름을 그대로 노출하고, 여러 개일 때는 ‘+n’ 형식을 취해 가독성을 높였음.

필터링 로직 역시 고도화했다. 특정 제품 탭을 클릭했을 때 해당 제품에 속한 용어뿐만 아니라 ‘전체 공통’ 용어까지 한 번에 조회되도록 Inner Join 쿼리를 최적화했음. 사용자는 이제 복잡한 관계를 신경 쓰지 않고도 자신이 담당하는 제품의 용어를 명확하게 확인할 수 있다.

ㄷ. Multi-Select Dropdown을 통한 업무 효율화

여러 제품을 동시에 할당하는 과정은 물 흐르듯 자연스러워야 한다. 우리는 체크박스가 포함된 멀티 선택 드롭다운 컴포넌트를 개발했다. 키보드 네비게이션(방향키)을 지원하고 선택된 개수를 실시간으로 반영하여, 기존에 3분씩 걸리던 다중 제품 등록 작업을 단 15초 만에 끝낼 수 있도록 혁신했음.

3. 일괄 작업 UX 혁신 – 하단 고정 바(Fixed Bottom Bar)

ㄱ. 흩어진 액션 버튼의 통합과 시인성 확보

이전 UI에서는 항목을 선택한 뒤 버튼을 찾으러 화면 상단으로 스크롤을 올려야 하는 동선 낭비가 심각했다. “사용자가 있는 곳에 버튼을 두라”는 원칙에 따라, 모바일 앱에서 흔히 쓰이는 하단 고정 바(Fixed Bottom Bar) 패턴을 도입하기로 했음.

테이블에서 항목을 하나라도 체크하는 순간, 화면 하단에서 슬며시 올라오는 고정 바는 현재 선택된 개수를 명확히 보여준다. 여기에 ‘검수 완료’, ‘반영 완료’, ‘제품 변경’ 등 핵심 액션 버튼을 모아 배치하여 사용자가 스크롤 없이 즉시 작업을 완료할 수 있도록 설계했음.

ㄴ. Controlled Component 패턴을 이용한 상태 동기화

테이블의 체크박스와 하단 바의 선택 상태가 어긋나면 사용자 신뢰가 무너진다. 이를 방지하기 위해 단일 진실의 원천(Single Source of Truth) 원칙을 적용했다. 페이지 레벨에서 selectedIds 상태를 관리하고, 테이블과 하단 바가 동일한 상태를 바라보게 하는 제어된 컴포넌트 패턴을 구현했음.

하단 바에서 ‘선택 해제(✕)’를 누르면 테이블의 수백 개 체크박스가 즉시 해제된다. 복잡한 양방향 동기화 문제를 useEffect와 콜백 함수로 깔끔하게 해결하여 런타임 버그 발생 가능성을 0으로 줄였음.(그러나, 항상 무언갈 만들면 사이드의 사이드를 계속 내서 이 순간에만 0 으로 인식 해야한다)

ㄷ. 하단 바 전용 Upward Dropdown 구현

하단 바는 화면 제일 아래에 위치하므로 일반적인 드롭다운을 쓰면 목록이 화면 밖으로 가려지는 문제가 발생한다. 이를 위해 목록이 위로 솟아오르는 Upward Dropdown 기능을 추가했다. bottom: 100% 속성을 이용한 CSS 매직으로, 어떤 상황에서도 사용자가 선택 옵션을 놓치지 않도록 세심하게 배려했음.

4. 시스템 전체 표준화 및 최종 성과

ㄱ. API 응답 및 컴포넌트 재사용성 표준화

프로젝트가 커짐에 따라 각 API마다 제각각이었던 응답 형식을 successResponse, badRequest, serverError 미들웨어로 표준화했다. 또한, 번역 입력 폼을 TranslationFormFields라는 별도 컴포넌트로 추출하여 생성 모달과 수정 모달에서 코드를 70% 이상 재사용할 수 있게 했음. 이는 향후 유지보수 비용을 획기적으로 낮추는 결과로 이어졌다.

ㄴ. 숫자로 증명된 비즈니스 임팩트

1. 번역 복구 성공률: 100% (실수 대응 능력 확보)
2. 다중 제품 할당 시간: 건당 3분에서 15초로 91% 단축했음.
3. 일괄 작업 클릭 횟수: 기존 대비 60% 감소(30회 → 12회)하여 작업 피로도를 대폭 낮췄음
4. 버튼 탐색 시간: 스크롤 동선 제거로 80% 이상의 시간 절감 효과를 거두었음

5. 안심을 주는 제품이 좋은 제품이다

ㄱ. 기술은 도구일 뿐, 핵심은 사용자의 심리다

버전 히스토리는 단순한 기능 추가가 아니라 사용자에게 심리적 안정감을 주는 장치였다. “수정해도 언제든 되돌릴 수 있다”는 믿음이 생기자 번역가들의 작업 속도가 오히려 더 빨라졌음. 하단 고정 바와 다중 제품 지원 역시 ‘도구가 사용자의 손에 얼마나 편안하게 쥐어지는가’를 고민한 결과물이었다.

ㄴ. 5일간의 여정, 그리고 그 너머

Code는 복잡한 로직 구현의 시간을 단축해주었지만, 사용자의 불편함을 경청하고 해결책을 설계하는 것은 여전히 인간의 몫임을 다시 한번 깨달았음. 앞으로 실시간 협업과 AI 기반 자동 제안 기능을 더해 이 시스템을 더욱 진화시킬 예정이다.

댓글 남기기