흩어진 업무 규칙을 온톨로지로 연결하기

흩어진 업무 규칙을 코드·데이터·테스트와 연결하고 변경된 소스의 검증 상태를 추적한 과정.

4분 분량 #Ontology #SHACL #AI Engineering 이 글의 방문자 수

피트니스 센터 관리 서비스를 개발하면서 환불 규칙 하나를 고치려 해도 볼 데가 많았다. 결제 기록 테이블, 환불 서비스 코드, 회의에서 정한 정책, 그리고 아직 정하지 못한 정책까지. 규칙이 한곳에 모여 있지 않았다.

센터 관리자 웹과 운영 백오피스, 회원·코치 앱이 API 하나를 함께 쓰는 구조였다. 화면은 나뉘어 있어도 결제와 환불, 예약 규칙은 서로 연결돼 있었다.

업무 규칙 카드와 노트북, 검사 결과가 표시된 투명한 상자가 선으로 이어져 있는 개념 삽화

시작은 무결성 검사였다

10월 2일에는 금액이 바뀌는 코드를 검사하고 있었다. 동시에 들어온 요청이 잔액을 두 번 쓰지 않는지, 중간에 실패하면 재고와 포인트가 어긋나지 않는지를 실제 DB에서 재현해 보는 일이었다.

그런데 검사를 하다 보니 계속 같은 걸 적고 있었다. 이 규칙은 어떤 개념 사이의 관계인지, 이 테스트는 어떤 업무 질문에 답하는지. 그래서 코딩 에이전트에게 이게 온톨로지랑 비슷하지 않냐고 물었고 그날 표준 조사를 맡겼다.

조사한 건 Stanford의 Ontology Development 101, W3C의 OWL 2·Turtle·SHACL, OMG의 SBVR·UML·DMN이다. 계획은 질문 → 용어 → 온톨로지 → 규칙 → 상태 → 검증 → 시각화, 7단계로 잡았다.

OWL은 개방세계 가정을 쓴다. 필수 데이터가 빠졌다고 해서 OWL 선언만으로 그걸 잡아낼 수는 없다. 그래서 필수값 같은 제약은 SHACL로, 잠금이나 롤백은 실제 DB 테스트로 확인하기로 했다.

결제와 환불부터

먼저 회원 결제 기록과 환불 영역에 7단계를 적용했다.

  • 질문(CQ) 10개와 그 답, 아직 정하지 못한 사항
  • 개념 클래스 6개, 관계 5개
  • 규칙 8개, SHACL Core·SPARQL 제약
  • 상태 3개와 환불 사례 5개
  • 데이터 정상 5개, 반례 10개

반례는 일부러 규칙을 어기게 만든 데이터다. 검사가 반례를 잡아내야 규칙이 제대로 적혔다고 볼 수 있다. 결제 영역을 이렇게 끝까지 이은 다음 8개 업무 영역으로 넓혔다.

테이블과 업무 개념은 따로 뒀다

저장 모델은 114개였지만 업무 개념은 47개로 정리했다. 테이블 하나가 업무 개념 하나와 대응하는 구조는 아니었다.

DB 테이블 쪽은 Prisma 스키마에서 뽑았고 업무 개념은 사람이 정의했다. 저장 구조는 JSON을 문자열로 들고 있고 관계에는 양방향 탐색 필드까지 들어 있어서 외래키 개수와도 맞지 않는다. 둘을 같은 것으로 다룰 수가 없어서 네임스페이스를 나눴다. 저장 구조 쪽 SHACL은 타입, 필수값, 고유키 정도만 본다. 그걸 통과했다고 업무적으로 맞는 데이터가 되는 건 아니다.

범위를 넓힐 때는 빠뜨린 코드가 없어야 했다. 그래서 소스에서 찾은 1,366개 항목을 전부 어느 영역에 속하는지 배정했다. 새 항목이 생기거나, 사라지거나, 배정되지 않은 게 있으면 검사가 실패한다. 다만 기계적으로 뽑은 항목에는 ‘추출됨’ 표시를 따로 붙였다. 배정했다고 의미까지 검토한 건 아니니까.

규칙 ID를 넣으면 근거가 나온다

온톨로지를 실제 코드 수정에 쓰려고 조회 도구를 하나 만들었다. 규칙 ID를 넣으면 그 규칙에 연결된 개념, 한 단계 떨어진 관계, 업무 질문, 상태, 코드와 테스트의 경로·해시, 마지막 실행 결과를 모아서 보여 준다. 예를 들어 “확정된 충전 신청은 같은 센터·같은 금액·유상 적립이고 멱등키가 있어야 한다”는 규칙을 고친다면, 이 규칙의 ID로 같이 봐야 할 근거를 한 번에 꺼낼 수 있다.

이 도구의 기본 규칙은 오래된 검증 결과를 현재 결과처럼 보여 주지 않는 것이다. 마지막 검증 이후 관련 소스의 해시가 바뀌면 상태가 stale-or-absent로 바뀌고 예전에 통과한 기록은 지금 소스의 검증으로 쓰지 않는다. 나중에는 SQL 마이그레이션 파일도 해시에 넣었다. Prisma 모델은 그대로인데 DB 변경 SQL만 바뀌는 경우도 있어서다.

조회 도구는 관련 자료를 모아 보여 주는 역할만 맡겼다. 실제 수정에 들어가기 전에는 권한이나 상위 업무 흐름도 따로 확인한다. 한 단계 떨어진 관계만으로는 변경의 영향을 전부 알기 어렵기 때문이다.

작업 순서도 정해 뒀다. 규칙을 고르고, 사실과 아직 정하지 않은 정책을 확인하고, 코드를 고치고, 테스트와 온톨로지 검사를 돌리고, 소스가 일치하는 결과인지 본다. 검사를 통과시키려고 금액이나 권리, 수신자를 바꾸지는 않는다.

규칙과 코드를 관계도로 보기

2D·3D 관계도도 만들었다. 반례를 누르면 합성 레코드가 어디서 규칙을 어기는지 그래프로 보인다. 그래프에서 점을 옮겨도 원본 정의는 바뀌지 않고 선이 없는 곳에 관계를 지어 넣지도 않는다. 정책 상태와 테스트, 상태 전이를 한 화면에서 보려고 뷰어를 직접 만들었다. Protégé에서 열리는지는 확인했다.

코드가 바뀌면 검증도 다시

2026년 10월 6일 오전 실행에서는 정의 검사 59개와 PostgreSQL·서비스 검사 744개가 통과했다. 인수 검토를 기다리는 단계였고, 소스가 바뀌면 이 결과도 다시 확인하도록 했다.

규칙을 적어 두는 것만큼, 그 규칙이 어느 코드와 테스트에 연결돼 있는지 따라갈 수 있게 만드는 데 집중했다. 예전에 통과한 테스트가 지금 코드에도 유효한지 바로 구분할 수 있어야 실제 개발에 쓸 수 있기 때문이다.

구현과 실행은 주로 코딩 에이전트에 맡겼다. 나는 조사 방향과 적용 범위, 센터 정책을 정하고 후속 작업을 승인했다. 결제 재시도처럼 정책부터 정해야 하는 부분은 미정 상태로 남겼다. 코드를 고쳐서 해결할 일과 업무 결정을 먼저 해야 할 일을 구분하는 것도 이 구조에 포함했다.

키보드 단축키