Folio 03 · Research Factory
CiteWell
의학 논문의 참고문헌을 검증하고 저널 형식으로 바꾸는 제품
- 기간
- 2023.12.11 — 현재
- 역할
- 풀스택 · 제품 개발
- 특허 출원
- 2건
서버 구조를 정리하는 일에서 시작해 논문 변환과 참고문헌 변환 두 프로그램을 개발. 이후 참고문헌 검증을 단독 제품으로 세우면서 구독·크레딧 체계와 검증 보고서 설계를 담당. 기반을 세우는 작업과 그 위에 올린 기능을 함께 맡아 온 2년 10개월.
Django · Django REST Framework · Vue · Redis · PostgreSQL · Paddle · ORCID
01 기반 재건 — REST API 기반 구조로 2024.01 — 2024.02
합류 시점 구성은 Vue 프론트엔드와 Django 백엔드. 인증, 오류 응답, 요청 검증을 담당하는 층이 서버에 자리잡기 전이라, 저널 옵션 같은 규칙을 얹으려면 통신 방식과 계층부터 정리가 필요한 상황.
요구사항
- 통신 방식
- 요청과 응답의 형태를 예측 가능하게 만들 것
- 확장 여지
- 저널 옵션 같은 복잡한 규칙을 얹을 수 있는 서버 구조 확보
- 인증 기반
- 미출판 원고를 다루므로 계정과 토큰 처리 정립
- 오류 일관성
- 실패 응답의 형식과 코드를 한 곳에서 정의
구현
-
REST API 구조 도입
- REST API 기반으로 프로젝트 구조 재편
- Django 5.0.1 이관 및 새 버전에 맞춘 CSRF 처리 방식 정리
- 프론트엔드의 요청 경로를 HTTP 호출 기준으로 정리
-
함수형 뷰 채택 설계 판단
- Django REST Framework의 관례는 클래스형 뷰지만 함수형 뷰로 결정
- 요청이 어떤 검증을 거쳐 무엇을 반환하는지가 위에서 아래로 읽히는 쪽이 인수인계와 디버깅에 유리하다는 판단
- 반복되는 소유권 검증은 데코레이터로 분리해 중복 차단
-
인증과 식별자 정리
- JWT 인증을 별도 앱으로 분리하고 리프레시 토큰 모델과 재발급 경로 구현
- 식별자를 순번에서 UUID로 전환
- 외부 노출값에서 내부 규모와 순서가 드러나지 않도록 차단
-
오류 체계와 검증 계층
- 실패 응답을 커스텀 에러 코드로 통일
- 요청 데이터 검증을 serializer 계층으로 이동
- 뷰에 섞여 있던 비즈니스 로직을 재사용 가능한 단위로 분리
까다로웠던 지점
구조 재편이 모든 요청 경로에 걸침
구조 재편은 특정 기능이 아니라 서버와 화면이 주고받는 모든 경로에 동시에 닿는 작업. 한 번에 바꾸면 무엇이 언제부터 깨졌는지 좁히기 어렵고, 그 사이에도 다른 기능 개발은 계속 진행되는 조건.
해결도메인 단위로 끊어서 이관. 인증을 먼저 옮겨 토큰과 권한의 기준을 세우고, 그 위에서 레퍼런스 도메인을 옮기는 순서로 진행해 한 번에 검증할 범위를 작게 유지
남긴 것
- 요청과 응답의 형태가 예측 가능해지고 오류 처리가 한 곳으로 수렴
- 여기서 만든 인증 계층이 2단계 인증, ORCID 연동, 기업 계정 권한 관리의 토대로 재사용
- 함수형 뷰와 데코레이터 조합이 이후 합류 인원의 코드 독해 기준으로 정착
02 참고문헌 검증과 형식 변환 2024.01 — 2025.09
저널마다 인용 형식이 상이해 투고자는 수십에서 수백 건의 문헌을 손으로 맞춰야 하는 상황. 재정렬 중 생긴 사소한 오류가 심사 단계의 수정 요청과 출판 지연으로 연결. 제품의 핵심 기능이자 가장 오래 붙잡은 영역.
요구사항
- 입력 다양성
- 일반 텍스트와 RIS·NBIB 파일을 모두 입력으로 수용
- 검증 신뢰도
- 입력된 서지정보를 외부 데이터베이스로 대조해 유효성 판정
- 형식 자유도
- 저널별 인용 형식을 템플릿으로 정의하고 재사용 가능할 것
- 판단 근거
- 검증 결과가 성공·부분·실패 중 어디에 해당하는지 사용자가 확인 가능할 것
구현
-
변환 엔진 내재화 설계 판단
- 기존에 외부 compile API에 의존하던 변환을 내부 로직으로 대체
- 변환 규칙이 제품 안에 있어야 저널 템플릿과 한 몸으로 움직인다는 판단
- 변환 함수의 인자를 템플릿 식별자에서 옵션 값으로 변경해 단위 테스트가 가능한 형태로 전환
-
요소 단위 템플릿
- 저자, 제목, 저널, 편집자, DOI 등 요소별 표현 방식을 개별 설정 항목으로 분해
- 요소의 배치 순서를 사용자가 바꿔 새 템플릿을 만들 수 있도록 편집기 구현
- 관리자가 등록한 공용 템플릿과 사용자 템플릿을 분리해 노출 범위 제어
-
외부 데이터베이스 검증
- PubMed를 기준 데이터베이스로 삼아 입력 서지정보를 대조
- 이후 Crossref를 추가해 두 곳을 병렬 조회하도록 확장
- 검증 결과를 성공·부분 일치·실패로 분류하고 각각의 후속 처리를 분리
-
포맷 상호 변환
- NBIB와 RIS reader·writer 구현으로 포맷 간 변환 지원
- Journal Article과 Book 등 문헌 유형별 필드 매핑 처리
- 변환 결과를 원하는 포맷으로 내려받을 수 있도록 출력 경로 추가
-
비교와 편집 보조
- 입력 원문과 검증된 데이터를 나란히 비교하는 화면 구성
- 드래그 앤 드롭 정렬과 중복 번호 처리로 목록 편집 지원
- 본문 요소에 마우스를 올리면 해당 파트를 표시해 편집 위치를 즉시 확인
까다로웠던 지점
검색 정확도와 속도의 상충
서지정보로 원문을 찾는 조회는 CrossRef·PubMed·OpenAlex의 휴리스틱 검색. 처음엔 "깨끗한 필드만 보내자"는 직관으로 제목과 첫 저자, 연도만 골라 보냈음. 결과는 반대였음. 단서가 적으니 후보가 수십 건씩 돌아와 느려졌고, 흔한 제목("Introduction", "Editorial")은 오탐이 절반을 넘음. 그렇다고 필드를 더 보내면 사용자가 붙여 넣은 참고문헌의 오타(저자 철자, 쪽수 한 자리)까지 같이 가서, 정확한 필드 다섯에 틀린 필드 하나가 섞이면 검색이 통째로 비는 일이 생김. 한 가지 더 있었음. CrossRef가 돌려주는 relevance score로 "몇 점 이하는 버리자"고 절대 기준을 두었더니, 같은 쿼리를 두 번 보내면 점수가 달라져 같은 논문이 후보에 들어왔다 나갔다 함. 테스트가 돌 때마다 다른 결과를 내는 플래키의 원인이 그것이었음.
해결발상을 뒤집어 참고문헌 한 줄을 통째로 query.bibliographic에 보냄. 상대 쪽 검색이 토큰 단위 가중치라, 단서 20개 중 하나가 틀려도 나머지 19개가 끌어올려서 오타 하나가 결과를 뒤집지 못하고, 단서가 많으니 후보도 좁혀져 응답이 1초 아래로 내려옴. 점수 절대 기준은 버리고, CrossRef가 relevance 순으로 준 상위 5건만 후보로 남긴 뒤 선택은 "필드가 얼마나 일치하는가"로 함. 점수는 쿼리에 상대적이라 흔들려도 순위는 안정적이기 때문. 코드 주석에 왜 절대 컷오프를 쓰지 않는지 적어 두어 다음 사람이 같은 함정에 빠지지 않게 함. 남는 오탐은 찾은 레코드와 입력 참고문헌을 필드마다 0~100으로 채점하는 판정 단계에서 걸러냄. 0~40은 severe, 41~69는 moderate, 70 이상은 good으로 밴드를 나누고, 어느 필드가 severe인지가 "왜 버렸는지"를 설명하는 근거가 됨. 밴드 경계 40은 운영 중 한 번 올린 값이라 코드에 날짜와 함께 남아 있음. "입력을 정제해서 보내야 한다"는 가정이 틀렸다는 걸 받아들이는 데 시간이 가장 오래 걸림.
남긴 것
- 참고문헌 변환이 제품의 주력 기능으로 자리잡아 이후 단독 제품화의 근거가 됨
- 요소 단위 템플릿 구조가 특허 「서지 정보 구조 자동 분석 및 형식 변경 방법」의 핵심 구성으로 반영
- 검증 결과 분류 체계가 이후 Verification Report의 판정 기준으로 재사용
03 계정과 접근 제어 2024.02 — 2024.08
외부 공개를 앞둔 시점. 변환 한 번에 외부 API 호출과 문서 파싱이 딸려 있어 호출을 무제한으로 열 수 없는 구조. 연구자 계정에는 미출판 원고가 담기므로 비밀번호 하나로 지킬 수 있는 자산이 아님.
요구사항
- 사용량 통제
- 원가가 발생하는 요청에 한도를 걸어 비용과 부하를 방어
- 계정 신뢰
- 실제 사용 가능한 이메일을 보유한 계정만 기능 이용
- 자산 보호
- 비밀번호 유출만으로 원고에 접근되지 않을 것
- 복구 경로
- 사용자가 스스로 비밀번호와 인증 상태를 회복할 수 있을 것
구현
-
요청 제한 이중 구성: 싸게 막을 수 있는 것과 알고 막아야 하는 것 설계 판단
- 계기는 어느 새벽의 로그. 같은 IP에서 로그인 엔드포인트로 분당 수천 건이 들어왔는데, DRF 스로틀은 멀쩡히 429를 돌려주고 있었음. 문제는 그 429 하나를 만들기까지 Django가 세션을 읽고 미들웨어 체인을 다 타고 뷰까지 들어간다는 것. 막긴 막았는데 CPU는 정상 트래픽의 세 배를 쓰고 있었음
- 그래서 두 층으로 나눔. 바깥 층은 Django 미들웨어 맨 앞에서 요청자 식별값만 보고 Redis 카운터 하나로 판정. 인증도 ORM도 건드리지 않아 요청당 1ms 안쪽. 한도는 60초에 1,000건으로 일부러 넉넉하게 두었음. 코드 주석에도 적어 두었듯 이 층은 안쪽의 DRF 스로틀을 방해하지 않는 선에서 "서버가 죽지 않기"만 맡고, "공정함"은 맡지 않음. 헬스체크와 Cloud Tasks 콜백 경로는 제외 목록에 둠. 그걸 세다가 오케스트레이터가 재시도를 재시도하는 일을 한 번 겪었기 때문
- 안쪽 층은 DRF 스로틀. 여기서는 누구인지 알 수 있으니 익명 50/분, 로그인 사용자 1,500/분을 바닥에 깔고, 그 위에 기능별 scope를 따로 매김. 참고문헌 검증 1,000/분, PDF 분류 200/분, 플레이그라운드 컴파일 10/분과 내보내기 6/분, 이메일 인증·비밀번호 재설정·OTP는 시간당 5건. 원가가 외부 API 호출이나 메일 발송인 기능일수록 숫자가 작아짐. 변환 시작만은 "분당 몇 건"이 아니라 "한 번 누르면 5초간 잠금"이라, DRF의 SimpleRateThrottle이 고정 시간 단위만 받는 한계를 피해 BaseThrottle을 상속한 duration 스로틀을 따로 씀
- 한도 숫자는 기능 코드에 두지 않고 settings의 DEFAULT_THROTTLE_RATES 한 곳에 모으고, 스로틀 클래스는 config/throttles.py에 scope 이름만 가진 껍데기로 둠. 숫자를 바꾸려고 변환 모듈을 배포하고 싶지 않았음. 두 층의 Redis 캐시 version을 middleware_throttle과 throttle로 다르게 둔 것도 의도적. 같은 Redis에서 서로의 카운터를 덮어쓰면 디버깅이 지옥이 됨. Redis가 잠깐 끊겼을 때는 두 층 모두 "통과"로 실패함. 레이트 리밋 때문에 서비스 전체가 멈추는 것보다 잠깐 제한이 풀리는 쪽이 낫다는 판단
-
이메일 인증 흐름
- 가입 시 인증 메일 발송과 인증 완료 처리 구현
- 인증 메일 재발송과 만료 처리 경로 추가
- 인증 완료 여부를 확인하는 permission을 두어 미인증 계정의 기능 사용 차단
-
2단계 인증
- pyotp와 Redis를 이용해 일회용 코드 발급·검증 구현
- 코드 전달은 별도 기기 없이 쓸 수 있도록 이메일 경로 선택
- 프론트엔드 2차 인증 화면과 코드 재발송·초기화 흐름 구현
-
비밀번호 재설정
- 메일 기반 재설정 요청과 토큰 검증 경로 구현
- 재설정 화면 진입 시 인증 가드에서 제외해 잠긴 계정도 복구 가능하도록 처리
까다로웠던 지점
보안 강화와 이탈의 교환
2단계 인증을 모든 로그인에 강제하면 안전하지만 매번 메일을 확인해야 하는 부담이 발생. 연구자는 장시간 한 작업에 머무는 사용 패턴이라 로그인 마찰이 곧 이탈로 연결될 위험.
해결인증을 계정 설정으로 두어 사용자가 위험도에 따라 선택하도록 구성. 기능 차단은 이메일 인증까지만 강제하고, 2단계 인증은 강제 대상에서 제외
남긴 것
- 외부 공개를 감당할 수 있는 계정 체계 확보
- 이메일 인증과 2단계 인증 흐름이 이후 ORCID 연동과 기업 계정 권한 관리에 그대로 확장
- 요청 제한 정책이 이후 Public API의 과금·쿼터 설계에 그대로 승계
04 저널 템플릿과 옵션 체계 2024.03 — 2024.12
논문 변환 프로그램의 기반. 저널이 요구하는 형식을 코드가 아니라 데이터로 표현하는 것이 목표. 저널이 늘어날 때마다 개발이 따라붙는 구조를 끊는 작업.
요구사항
- 데이터 기반
- 저널 규정을 코드가 아닌 옵션 데이터로 표현
- 화면 자동화
- 옵션이 추가되어도 편집 화면을 새로 만들지 않을 것
- 구조 변경 대응
- 옵션 구조가 바뀌어도 기존 템플릿이 유실되지 않을 것
- 정합성
- 옵션 간 논리적 충돌을 저장 시점에 차단
구현
-
옵션 구조가 화면을 결정 설계 판단
- 백엔드의 옵션 데이터 구조가 편집 화면 렌더링을 그대로 결정하도록 설계
- 저널 규정이 추가될 때 화면을 따로 만들지 않고 옵션 정의만 추가하면 되는 구조
- 문헌 유형별 기본 템플릿을 두어 새 유형 추가 시 기본값만 정의하면 대응 가능
-
템플릿 편집기
- 저널 템플릿의 생성·조회·이동·삭제 경로 구현
- 타깃 저널 검색과 선택 흐름을 별도 화면으로 분리
- 관리자 등록 템플릿만 목록에 노출하도록 범위 제어
-
옵션 마이그레이션
- 옵션 구조나 검증 규칙이 바뀔 때 기존 템플릿을 새 구조로 옮기는 변환 모듈 구현
- 변환 전 백업을 남기고, 변환 후 실제 변환이 성립하는지 검사하는 절차 추가
- 옵션 추가·제거 때마다 대응 스크립트를 함께 작성하는 방식으로 운영
-
옵션 간 정합성
- 옵션이 저장·수정될 때마다 규칙 집합에 따라 검증하도록 구성
- 변경이 발생하면 관련 필수 항목 상태를 초기화하고 사용자에게 안내
- 초록 소제목처럼 사용자 정의가 가능한 항목은 기본값 주입 경로를 별도 처리
까다로웠던 지점
옵션이 바뀌면 기존 데이터가 깨짐
저널 규정을 옵션으로 표현할수록 옵션 구조 자체가 자주 바뀌는 구조. 구조가 바뀌면 이미 저장된 템플릿은 옛 구조에 맞춰져 있어 변환이 실패하거나 잘못된 결과를 생성. 사용자가 만들어 둔 템플릿을 버릴 수도, 구조를 고정할 수도 없는 상황.
해결구조 변경과 데이터 이전을 한 묶음으로 처리하는 마이그레이션 모듈 도입. 백업 → 변환 → 변환 성립 검사 순서를 고정해 실패 시 되돌릴 수 있는 경로 확보
남긴 것
- 저널 추가가 개발 작업이 아니라 옵션 등록 작업으로 전환
- 마이그레이션 모듈이 논문 변환 특허의 구성요소로 명세에 포함
- 옵션 데이터를 화면 렌더링의 기준으로 삼는 방식이 이후 보고서 스타일 체계로 확장
05 참고문헌 검증을 단독 제품으로 2025.03 — 2025.12
참고문헌 검증·변환은 이미 제품의 주력 기능. 입력 범위가 좁고 검증 기준이 분명해 그것만으로 제품이 성립하는 상태. 논문 변환은 자동 분석·태깅, 변환, 옵션 관리 세 시스템이 모두 정확해야 결과가 나오는 구조라 완성까지의 거리가 달랐던 조건. 주력 축을 CiteWell이라는 단독 제품으로 세우는 단계.
요구사항
- 정체성
- 단독 제품에 맞는 명칭과 화면 구성 확립
- 자산 승계
- 논문 변환에서 만든 옵션 체계와 마이그레이션 모듈을 버리지 않고 옮길 것
- 신원 연동
- 연구자 식별 체계와 연결해 계정 신뢰도 확보
- 데이터 구조
- 주문과 개별 항목을 분리해 검증 결과를 안정적으로 관리
구현
-
단독 제품화 설계 판단
- 참고문헌 검증·변환을 CiteWell이라는 이름의 단독 제품으로 세우고, 화면 구성을 그 흐름 중심으로 재편
- 논문 변환은 개발을 멈추고, 완성 가능성과 시장 진입 속도가 앞선 축에 역량을 모으기로 결정
- 논문 변환에서 만든 옵션 체계와 마이그레이션 모듈은 이후 보고서 스타일 체계의 기반으로 승계
-
ORCID 연동
- 연구자 식별 체계인 ORCID를 OAuth로 연결
- 연동 계정의 권한 처리와 기존 계정과의 병합 경로 구현
-
주문과 항목 분리
- 참고문헌 주문과 개별 항목을 별도 구조로 분리
- 항목 단위로 검증 상태와 결과를 보관해 부분 재검증이 가능하도록 구성
- PubMed와 Crossref 병렬 검증 경로를 이 구조 위에 재배치
-
운영 가시성
- 사용량과 구독 상태를 사용자 화면에 노출
- 외부 데이터베이스 장애 시 원인을 구분해 안내하도록 오류 처리 분리
까다로웠던 지점
두 축을 함께 끌고 갈 수 없는 조건
논문 변환과 참고문헌 변환은 완성 조건이 다른 두 시스템. 같은 인원이 둘을 동시에 유지하면 어느 쪽도 유료 판매가 가능한 완성도에 이르지 못하는 구조.
해결완성 가능성과 시장 진입 속도를 기준으로 참고문헌 축을 선택. 논문 변환의 옵션 체계·마이그레이션 구조·검증 분류 체계는 그대로 승계해 설계 자산은 손실 없이 이어짐
남긴 것
- CiteWell이 하나의 문제를 끝까지 다루는 제품으로 정립
- 참고문헌 검증·변환이 유료 판매가 가능한 완성도에 도달
- 이 정립이 이후 기업 계약과 구독 체계 도입의 전제가 됨
06 구독과 크레딧 체계 2025.07 — 2026.06
기능이 아니라 사업을 지탱하는 층. 무료 공개 상태에서 유료 전환으로 넘어가면서 결제, 사용량 집계, 한도 판정을 한 흐름으로 묶는 작업.
요구사항
- 결제 수단
- 해외 결제와 세금 처리를 포함한 구독 결제 도입
- 요금 구조
- 개인 구독, 기업 구독, 일회성 크레딧 세 경로 지원
- 사용량 판정
- 요청마다 어떤 재원에서 차감할지 일관되게 결정
- 근거 기반
- 한도와 가격을 실제 사용 데이터에 근거해 산정
구현
-
결제 연동
- Paddle을 결제 수단으로 도입해 해외 결제와 세금 처리 위임
- 구독 생성·갱신·해지 이벤트를 제품 상태와 동기화
- 결제 실패와 중복 처리에 대비한 복원 경로 구현
-
세 갈래 재원
- 개인 구독, 기업 구독, 일회성 크레딧을 각각 별도 재원으로 정의
- 요청 시 어느 재원에서 차감할지 판정하는 우선순위 규칙 구현
- 크레딧 원장과 거래 내역을 분리해 잔액 변화를 추적 가능하도록 구성
-
사용량 집계
- 월간·연간·맞춤 계약의 사용량 집계 구간을 하나의 계산 규칙으로 통일
- 연간 계약은 전체 기간을 한 번에 소진하지 않고 월 단위로 분할
- 기업 구독은 조직이 공유하는 사용량으로 집계하고 멤버별 이력 보관
-
사용 데이터 기반 재책정 설계 판단
- 기업 고객사의 3개월 사용량을 추출해 월평균 약 1만 건 규모 확인
- 개인 최다 사용자도 월 1천 건대, 나머지는 그 이하로 분포
- 변환 유형별로 보면 텍스트 변환이 대부분이고 PDF·RIS·NBIB는 사용량 미미
- 원가가 실제 발생하는 텍스트 한도는 상향, 사용량이 적은 유형은 하향 조정
까다로웠던 지점
한도를 감으로 정할 수 없음
플랜별 한도를 임의로 정하면 고객에게는 부족하고 회사에는 손해인 구간이 생기는 구조. 특히 변환 유형마다 실제 발생 원가가 달라 동일한 한도를 적용하기 어려운 조건.
해결최근 3개월 실사용량을 유형별로 추출해 분포 확인. 노이즈를 제거한 평균을 기준으로 유형별 한도를 재산정하고, 사용량이 거의 없는 유형은 한도를 줄여 원가 부담 완화
기존 구독을 크레딧 체계로 이전
구독 한도와 크레딧이 별도로 존재하던 상태에서, 구독이 크레딧을 지급하는 하나의 체계로 통합하는 전환. 이미 결제한 사용자의 잔여 권리를 손실 없이 옮겨야 하고, 전환 중에도 서비스는 계속 동작해야 하는 조건.
해결기존 한도 필드를 즉시 제거하지 않고 사용 중지 상태로 유지하며 병행 기간 확보. 구독 크레딧 지급과 만료에 기존 사용량 집계 구간 계산을 재사용해 계약 유형별 차이를 흡수
남긴 것
- 무료 공개 제품에서 유료 결제가 가능한 제품으로 전환
- 기업 계약 체결로 연결되어 사용량 기반 계약 협의의 근거 자료 확보
- 이후 Public API의 과금과 크레딧 차감이 같은 재원 판정 규칙을 그대로 사용
07 Verification Report 설계 2026.01 — 2026.04
검증 결과를 화면에서 확인하는 것만으로는 부족한 단계. 기관과 학회는 제출하고 보관할 수 있는 형태의 문서를 요구.
요구사항
- 산출물화
- 검증 결과를 제품 밖으로 내보낼 수 있는 문서로 생성
- 작업 단위
- 보고서를 만들고 관리하는 작업 공간을 별도로 제공
- 조직 사용
- 기업 조직이 함께 쓰고 사용량을 공유할 수 있을 것
- 근거 표시
- 판정 결과에 대한 근거를 문서에서 확인 가능할 것
구현
-
보고서 작업 공간
- 보고서 생성·목록·상세로 이어지는 작업 화면 구성
- 파일 업로드와 진행 상태 표시를 작업 단위로 연결
- 보고서 데이터 구조를 정의하고 만료·삭제 처리 경로 구현
-
판정 결과 표현
- 검증 정확도와 항목별 판정을 문서 형식으로 배치
- 철회된 논문 정보를 별도로 표시해 사용자가 즉시 인지하도록 처리
- 인용 번호와 문맥을 연결해 어느 주장에 붙은 인용인지 확인 가능하도록 구성
-
조직 단위 사용
- 기업 조직 생성과 초대·승인 흐름 구현
- 조직별 사용량과 구독 기간을 집계해 화면에 노출
- 멤버별 사용 이력을 보관해 조직 관리자가 확인 가능하도록 처리
-
산출물 생성
- HTML과 PDF 두 형식으로 보고서 산출물 생성
- 산출물 버전을 관리해 재생성 시 이전 결과와 구분
- 생성 작업을 큐로 처리해 동시 요청 시 순차 처리
까다로웠던 지점
화면용 데이터와 문서용 데이터의 괴리
화면은 상호작용을 전제로 접었다 펴거나 필요할 때 더 불러오는 구성. 반면 문서는 한 번에 전체가 고정된 형태로 확정되어야 하는 구조. 같은 검증 결과를 두 매체에 맞추면서 표현이 어긋나기 시작.
해결보고서를 화면의 부산물이 아니라 독립된 산출물로 정의하고 데이터 구조를 분리. 화면과 문서가 같은 검증 결과를 각자의 방식으로 렌더링하도록 경계 설정
남긴 것
- 검증 결과가 제품 밖으로 나갈 수 있는 산출물로 전환
- 기업 고객이 제출·보관 용도로 사용할 수 있는 형태 확보
- 보고서 구조가 이후 Public API 응답과 스타일 체계의 기준으로 승계
08 Public API와 보고서 스타일 체계 2026.05 — 현재
보고서가 사용자 화면, 샘플, 관리자 미리보기, Public API 결과 네 경로에서 각각 렌더링되며 표현이 어긋나기 시작한 상태. 같은 데이터가 경로마다 다르게 보이면 보고서의 신뢰가 흔들리는 구조.
요구사항
- 표현 일치
- 네 경로가 동일한 표현 규칙을 공유할 것
- 변경 전파
- 스타일을 한 곳에서 바꾸면 모든 산출물에 반영될 것
- 외부 계약
- Public API 소비자가 결과 형식을 신뢰할 수 있을 것
- 운영 도구
- 개발 배포 없이 스타일을 조정할 수 있을 것
구현
-
스타일 모델 정의
- 보고서 스타일을 데이터 모델로 정의하고 적용 대상 계약 명시
- 샘플 보고서 미리보기를 제공해 적용 결과를 즉시 확인
- 관리자 스타일 편집 화면을 두어 배포 없이 조정 가능하도록 구성
-
Public API
- API 키 발급과 만료, 접근 권한 관리 구현
- 작업과 사용 그룹을 조회하는 대시보드 제공
- 보고서 PDF를 API로 내려받는 경로 추가
-
웹훅
- 작업 완료와 결과 수정 이벤트를 웹훅으로 전달
- 전달 이력을 보관해 재전송과 실패 확인이 가능하도록 처리
-
크레딧 운영 연결
- 견적 기반 크레딧 구매 경로 구현
- Public API 사용분을 기존 재원 판정 규칙으로 차감하도록 연결
까다로웠던 지점
네 경로의 표현을 하나로 묶기
네 경로가 각각 다른 시점에 다른 목적으로 만들어진 상태. 한 곳을 고치면 나머지 세 곳이 어긋나고, 그 어긋남을 사전에 잡아낼 수단이 없던 상태.
해결표현 규칙을 코드가 아니라 데이터로 정의하고 네 경로가 같은 정의를 참조하도록 변경. 04번에서 만든 옵션 기반 설계를 보고서 영역에 재적용
남긴 것
- 스타일 변경이 한 곳에서 모든 산출물로 전파되는 구조 확보
- 외부 소비자가 결과 형식을 신뢰할 수 있는 계약 수립
- 논문 변환에서 만든 옵션 기반 설계가 다른 영역에서 재사용됨을 확인
출원 특허
-
논문 변환
AI 및 프로그램을 통한 논문 구조 자동 분석 및 태깅과 변환 시스템 및 방법
자동 분석·태깅 시스템, 변환 시스템, 옵션 관리 시스템으로 구성
-
참고문헌 변환
서지 정보 구조 자동 분석 및 형식 변경 방법
다단계 검증과 AI 분석을 거쳐 저널별 템플릿으로 형식 변환