# 오픈클로 따라하기 — API 없는 레거시 ERP에 모던 앱 붙인 방법
API도 없고, DB는 읽기 전용이었다.
그런데 입력까지 되는 앱을 만들어야 했다.
처음엔 좀 막막했습니다. 요즘 시스템이면 보통 API부터 찾게 되는데, 이번엔 그 길이 아예 없었습니다. ERP는 Delphi 기반의 오래된 3rd-party 프로그램이었고, 내부 데이터베이스는 조회만 가능했습니다. 쓰기는 안 됐습니다.
그렇다고 포기할 수는 없었습니다. 조회는 빨라야 했고, 입력은 실제 업무에서 돌아가야 했습니다. 결국 답은 하나였습니다.
**읽기는 DB로, 쓰기는 RPA로 나누는 것.**

## 왜 이렇게 나눴나
이 구조의 핵심은 기술보다 판단이었습니다.
DB에서 읽을 수 있는데 굳이 화면을 뒤져가며 조회할 이유는 없습니다. 그건 느리고 불안정합니다. 반대로 DB에 직접 쓸 수 없는데 입력까지 한 번에 해결하려고 하면 처음부터 막힙니다.
그래서 경로를 아예 둘로 나눴습니다.
– **읽기 경로**: Flutter 앱 → 로컬 FastAPI 게이트웨이 → MS SQL
– **쓰기 경로**: Flutter 앱 → pywinauto → ERP 화면 자동화
이렇게 나누고 나니 구조가 오히려 단순해졌습니다. 읽기는 빠르게, 쓰기는 현실적으로 처리하면 됐습니다.
## 읽기 경로: 빠르게 가져오는 쪽
Flutter 앱에서 127.0.0.1 로컬 게이트웨이를 호출하고, 게이트웨이가 DB에서 필요한 데이터를 읽어옵니다.
이 방식의 장점은 분명했습니다.
– 자동완성이 빨라졌고
– 조회 응답이 안정적이었고
– ERP 화면을 직접 열어보지 않아도 필요한 정보를 먼저 확인할 수 있었습니다
실제로 써보면 이런 차이가 큽니다. 조회가 느리면 사람은 앱을 안 믿게 됩니다.
## 쓰기 경로: 사람이 하던 일을 코드로 옮기는 쪽
문제는 입력이었습니다.
DB에 직접 쓸 수 없으니, 결국 ERP 화면을 조작해야 했습니다. 여기서 `pywinauto`를 붙였습니다. Flutter 앱이 값을 넘기면, 로컬 자동화가 ERP 창을 찾아서 실제 입력 흐름을 수행하는 방식입니다.
말하자면 우회라기보다, **레거시를 건드리지 않고 감싸는 방식**에 가깝습니다.
이 방법이 좋았던 이유는 단순합니다.
– ERP 소스를 수정하지 않아도 되고
– 기존 운영 환경을 깨지 않고
– 사람이 반복하던 입력을 줄일 수 있었기 때문입니다
ERP를 안 건드린다는 건 생각보다 중요합니다. 업데이트나 장애가 생겼을 때 마음이 훨씬 편합니다.
## 검증 로직은 따로 놀면 안 됐다
읽기와 쓰기를 나누면, 그다음엔 **기준을 하나로 맞추는 일**이 중요해집니다.
게이트웨이는 A라고 판단하는데 RPA는 B라고 판단하면, 결국 더 큰 문제가 생깁니다. 그래서 검증 로직은 각자 따로 두지 않고 공유 모듈로 뒀습니다.
이건 겉으로 화려한 부분은 아닙니다. 하지만 실무에서는 이런 부분이 오래 버티는 구조를 만듭니다.
## 운영에서 의외로 중요했던 부분
하나 더 신경 쓴 건 게이트웨이 실행 방식이었습니다.
앱이 켜질 때 로컬 게이트웨이도 같이 뜨고, 앱이 종료되면 같이 정리되게 만들었습니다. 별거 아닌 것 같지만 이런 부분이 빠지면 나중에 꼭 사람을 괴롭힙니다.
– 포트 충돌
– 프로세스 중복 실행
– 꺼졌는지 안 꺼졌는지 모르는 상태
이런 걸 줄이는 것만으로도 운영 피로가 꽤 줄어듭니다.
## 이 방식이 잘 맞는 경우
이 구조는 특히 이런 상황에서 잘 맞습니다.
– ERP나 레거시 프로그램을 수정할 수 없을 때
– DB는 읽기만 허용될 때
– 모던한 UI는 필요하지만 시스템 교체는 어려울 때
– 실무에서 바로 써야 해서 “예쁘게”보다 “되게” 만드는 게 중요할 때
## 마무리
이번에 다시 느낀 건, 레거시 연동은 멋진 기술보다 **역할을 제대로 나누는 판단**이 더 중요하다는 점이었습니다.
읽기는 DB로.
쓰기는 RPA로.
이렇게 나누고 나니, 안 될 것 같던 구조가 실제로 굴러가기 시작했습니다.
비슷한 상황이라면, 먼저 **DB에 어디까지 권한이 있는지**부터 확인해보시면 됩니다. 거기서 설계 방향이 거의 결정됩니다.