본문으로 건너뛰기

안녕하세요.

백엔드 개발자정용상입니다.

통찰력을 바탕으로 모든 문제의 근본적 원인을 정의하며, 창의적이고 뛰어난 문제 해결 능력으로 사용자의 경험을 구조적으로 개선합니다.

SCROLL

About

당신은 누구인가요?

첫 직장에서의 품질 관리 업무 중 반복되는 데이터 처리를 자동화하며 개발자의 길을 발견했고, 현실의 문제를 해결하는 것이 소프트웨어의 본질임을 깨달았습니다. 이 경험을 계기로 개발자로 직무를 전환했습니다.

현재는 자신이 곧 프로그램의 사용자라는 의식으로 프론트엔드와 백엔드를 모두 아우르는 개발 역량을 강화하고 있으며, 전체 문제를 구조적으로 바라보는 사고와 기술적 전문성을 결합하여 완성도 높은 소프트웨어를 만들고 있습니다.

최근에는 AI 에이전트 활용에 대한 깨달음을 바탕으로 높은 안정성과 빠른 개발 속도를 함께 확보하는 AI 오케스트레이터로서의 역량도 강화하고 있습니다.

학력
컴퓨터공학 학사과정2027.02 학위 취득 예정학점은행제 · 현재 평점 4.5/4.5
개발 경력
2년 5개월MES 솔루션 개발비즈플러스 글로벌
희망 직무
백엔드 개발자MSA 기반 서비스 개발LLM 기능 연동
SCROLL

AI Capability

주력 사용 에이전트: Claude Code · Codex

Planning & Specification

기획·목표·지침 설계

목표
아이디어의 가치를 높이고, 이를 실현할 명확한 목표와 작업 지침 설계
  1. 목적에 부합하는 아이디어 직접 구상
  2. 단계별로 AI와 질의하며 대안·트레이드오프를 직접 비교·판단해 아이디어 구체화
  3. 단계별 결정안·선택 근거를 AI로 문서화해 목표·작업 지침으로 통합
  4. 최종적으로 확정된 목표·작업 지침을 우선순위 트리로 구성
    최상위 지침
    필수, 참조 우선순위에 따른 영역별 지침 문서 링크만 관리하여 가볍게 유지
    영역별 상세 지침
    컨벤션·구현·테스트 기준 등 영역별 상세 지침 지정
Implementation & Verification

구현·검증

목표
어떠한 에이전트 모델을 사용하더라도 높은 일관성과 안정성을 가진 코드의 빠른 구현
  1. 구현 범위·제약 사항을 담은 목표 프롬프트 작성
  2. 우선순위 트리 지침에 따른 에이전트의 자동 구현·검증 시작
  3. 작업 단위별 지침 준수 확인·코드 수정을 반복하는 자동 피드백 루프 실행
  4. 지침에 따라 최종 테스트를 실행하고 코드와 검증 결과 직접 확인
  5. 피드백 루프에 축적된 지침 미준수 항목을 직접 검토하고 필요한 지침 업데이트
Design & Visualization

UI 디자인 · PPT · 다이어그램

목표
사용 목적에 맞는 정보 구성과 높은 완성도를 갖춘 결과물 제작
  1. 아이디어를 바탕으로 직접 스케치
  2. 아이디어 스케치본과 상세한 목표 프롬프트를 바탕으로 병렬 요청하여 여러 시안 확보
  3. 사용 목적과 가독성, 디자인 등을 고려하여 가장 부합하는 시안 선택
  4. 선택된 시안을 세부적으로 수정하여 높은 품질의 결과물 완성
SCROLL

Skills

Backend & Data

Java
동시성과 스레드 안전성을 고려한 객체 설계·비동기 처리
Spring Boot
IoC·DI·AOP 원리에 기반한 책임 분리와 트랜잭션 경계 제어
JPA · QueryDSL
관계 매핑·영속성 관리와 N+1 방지를 고려한 동적 쿼리·조회 최적화
MySQL
복잡한 업무 관계 모델링과 효율적인 조회·집계 쿼리 작성
PostgreSQL
인덱스·제약·잠금을 활용한 데이터 정합성 확보
Redis
캐시 적중률·하드웨어 제약·TPS를 고려한 효율적 캐시 활용
Kafka
도메인 이벤트 발행·소비와 실패 재시도를 고려한 연동

Frontend

React
상태 의존성과 렌더링 비용을 고려한 컴포넌트·훅 구현
TypeScript
제네릭·타입 제약으로 백엔드·프론트엔드 간 데이터 타입의 일관성 확보
Redux Toolkit
상태 의존성과 갱신 흐름을 고려한 전역 상태 관리
RTK Query
서버 데이터 의존성에 따른 캐시 무효화·동기화 처리
Material UI
테마 토큰·컴포넌트 확장으로 일관된 반응형 UI 구성

AI & Infrastructure

Python · FastAPI
비동기 추론 API와 스트리밍·장애 격리·폴백 구현
Spring AI
모델 연동과 도구 실행 책임을 분리한 다단계 챗봇 구현
Docker
컨테이너별 자원·볼륨·기동 조건을 분리한 배포 환경 구성
AWS EC2
서비스 배포·HTTPS 연결·재시작 및 복구 검증

Collaboration Tools

Git / GitHub
Git Branch 전략 이해에 따른 협업 코드 관리
Jira
애자일 스프린트 및 미팅 관리 도구로 활용
Slack
개발 이슈와 업무 소통을 위한 메신저로 활용
Swagger
API 명세 문서화를 통한 프론트 & 백엔드 협업 도구
SCROLL
SCROLL

PROJECT 01WORK · MES

MES

생산·공정·품질·재고 흐름을 현장 기준으로 관리하는 제조 실행 솔루션

  1. 01문제 정의

    고객별 생산 방식 차이로 동일 기능 반복 개발

    • 신규 고객사마다 개발자를 투입해 MES 개별 구축
    • 반복 구축으로 공급 확대·기능 고도화에 자원 제약 발생
  2. 02실행

    생산 흐름을 추상화한 표준 MES 제안 및 구축

    • 고객별 생산 차이에 대응하는 동적 설정 및 기능 확장 포트 설계
    • Jira·Slack 도입으로 일정 관리·협업 환경 구축
  3. 03결과

    하나의 표준 MES로 다수 고객사에 대응

    • 고객사별 재개발 대신 설정·기능 확장으로 구축 방식 전환
    • 개발자는 공통 기능 고도화·유지보수에 집중
PROPOSAL STUDY

제안 전 설계 타당성 검토

MES · PROPOSAL STUDY

표준 MES 제안 전 ERD 초안

여러 생산 흐름의 적용 가능성을 검토하기 위해 퇴근 후 직접 작성한 개인 제안용 초안. 회사 내부 자료와 별개이며, 실제 개발 설계는 독립적으로 재작성.

화면 맞춤확대 후 드래그·스크롤·방향키로 이동

여러 생산 흐름의 적용 가능성을 검토하기 위해 퇴근 후 직접 작성한 ERD 초안

  • 회사 내부 자료가 아닌 개인 제안용 초안
  • 실제 개발 설계는 독립적으로 재작성
PROJECT IMPACT

표준 MES 전환 이후의 성과

하나의 표준 제품으로 다수 고객에 대응

고객사 구축 사업2025년 수주 기준
기능 수기존 평균 → 표준 MES
사업 선정 비율사업 신청 대비 평균
SCROLL

PROJECT 01WORK · MES

MES · 기술 트러블슈팅

대량 센서 이력의 조회·집계 성능 개선

01 문제 발생

센서 데이터 누적으로 이력·통계 조회 지연

표준 MES 도입과 함께 센서 종류별 포맷을 통합하고, 측정값을 공통 이력으로 수집·관리.

설비 30대 × 20채널 · 2초 주기 수집 → 시간당 약 108만 건 · 30일 기준 약 8억 건 누적

02 원인 분석

통계 조회 시 원본 데이터 반복 집계

조회 기간의 원본을 매 요청 GROUP BY로 집계. 기간이 늘어날수록 집계 대상·연산량 증가.

03 해결 아이디어 구상

아이디어 A

검토 결과 보완 적용

쿼리·인덱스 최적화

복합 인덱스로 센서·기간 탐색 범위 축소. 기간 내 원본 집계는 유지.

아이디어 B

검토 결과 보완 적용

시간 파티셔닝·이력 관리

시간 파티셔닝으로 원본 이력 분할·보존 관리. 기간 내 원본 집계는 유지.

아이디어 C

검토 결과 해결안 채택

서머리 테이블 기반 통계 조회

원본 이력은 보존하고, 통계는 서머리 테이블로 관리. 반복 집계를 조회 경로에서 분리.

04 개선 결과

MES · 기술 트러블슈팅

성능 검증·구현 상세

동일 조건의 쿼리 성능 검증

검증 데이터
10개 수치형 채널 · 30일 · 2초 간격의 테스트 데이터 12,960,000행. 시간별 통계 조회를 대상으로 비교.
비교 조건
같은 채널·기간의 시간별 통계 7,200행 반환. 원본에도 센서·항목·시간·측정값의 커버링 인덱스를 적용해 서머리 테이블 조회와 비교.
측정 기준
각 쿼리 1회 준비 실행 후 5회씩 교차 실행한 중앙값 사용. Performance Schema로 서버 실행·결과 전송 시간을 측정하며 접속·데이터 생성·사전 집계 준비 시간은 제외.
테스트 환경
MySQL 8.0.34 · InnoDB · 버퍼 풀 512MiB · Intel(R) Core(TM) i7-8700K CPU @ 3.70GHz. 동일 환경·단일 클라이언트에서 실행.
실행계획 확인
원본의 범위 조회 이후 임시 테이블·정렬 발생 확인. 디스크 임시 테이블 수는 원본 최대 1개, 집계 조회 최대 0개.
결과 검증
전체 시간 구간의 건수·합계·최솟값·최댓값·평균 비교. 정수와 구간 키의 일치, 부동소수점 연산의 상대오차 1e-7 이내 확인.

원본 집계에서 서머리 테이블 조회로 전환

변경 전

원본 이력의 채널·기간 필터 → 시간별 그룹화 → 통계 계산

12,960,000행10채널 × 30일 × 24시간 × 1,800건

변경 후

서머리 테이블의 채널·기간 필터 → 사전 집계된 통계 반환

7,200행10채널 × 30일 × 24시간 × 1건

같은 기간의 동일한 통계를 반환하면서 조회 대상 레코드를 1/1,800로 축소. 아직 집계가 끝나지 않은 구간은 원본 조회로 분리.

공통 이력 관리
센서 종류별 데이터 포맷을 센서·측정항목·기록 시각과 타입별 측정값으로 통합. 공통 구조로 쌓인 이력을 설비 조회와 기간별 통계에 함께 활용.
조회 범위
센서·측정항목의 동등 조건 뒤에 시간 범위를 배치한 복합 인덱스 적용. 반환할 열과 기간을 제한해 필요한 데이터만 탐색.
집계 입력량
기간 내 원본 전체를 매번 GROUP BY에 넣는 대신 시간별 건수·합계·극값을 서머리 테이블에 사전 집계. 반복 연산을 조회 시점에서 집계 갱신 시점으로 이동.
운영 비용
보조 인덱스의 적재·저장 비용을 고려해 필요한 인덱스로 한정. 오래된 원본은 보존 기준에 따라 파티션 단위로 이관.
검토 결과
인덱스·파티셔닝은 탐색과 이력 관리를 개선하는 보완책으로 적용. 통계 조회의 반복 집계를 제거하는 해결안으로 서머리 테이블 채택.

원본 보존과 서머리 테이블의 갱신 기준

갱신 주체·시점
조회 API와 분리된 집계 배치가 종료된 시간 구간을 처리. 지연 데이터로 변경된 구간도 재집계하고, 갱신 완료가 확인된 구간만 서머리로 조회.
최신값 역전 방지
측정 시각과 원천 순번을 비교해 최신 이벤트만 조건부 갱신. 늦게 도착한 과거 이벤트가 현재 상태를 덮어쓰지 않도록 처리.
측정 시각·지연 도착
측정 시각과 수신 시각을 구분해 집계 구간 결정. 늦게 수신한 데이터는 해당 분·시간 구간에 반영하고 상위 집계까지 재계산.
중복·재실행
원천 이벤트 식별자로 중복 적재 차단. 같은 집계 구간은 순차 갱신하고, 재계산·덮어쓰기 방식으로 재실행 시 중복 합산 방지.
미완료 구간 처리
집계가 완료된 구간은 서머리, 진행 중이거나 재집계 대기인 구간은 원본에서 조회. 구간 경계를 겹치지 않게 나눠 최신 데이터 누락·중복 합산 방지.
평균·극값 보존
count/sum/min/max를 저장하고 평균은 SUM(sum)/SUM(count)로 계산. 구간별 표본 수와 최솟값·최댓값을 유지하고, Boolean·enum·알람은 별도 이벤트 이력으로 관리.
파티션·유일성
시간 파티션 컬럼을 모든 UNIQUE/PK에 포함해 이벤트 식별 키 구성. 재전송에도 측정 시각을 유지해 중복 판정·집계 구간 기준 고정.
원본 이력 보존
이상 구간의 파형과 발생 순서는 원본으로 보존. 장기 통계는 서머리 테이블로 처리하되, 세부 분석은 보존된 원본 이력으로 연결.

원본 1,296만 건의 시간별 집계 조회 개선

변경 전
70.30초
변경 후
0.016초
실행시간 감소
99.98%

동일한 시간별 통계 결과 확인센서 수집·조회 조건을 모방한 테스트 환경에서 개선 전후 성능 실측

SCROLL

PROJECT 02CHAPTER 01 / 02

openAt

SEMI PROJECT

다양한 한정판 상품을 정해진 시각에 한정 수량으로 드롭하는 MSA 커머스 서비스

  1. 01문제 정의

    드롭 오픈 시 주문 집중과 재고 처리 병목

    • 같은 한정 재고에 주문이 몰려 초과 판매 방지 필요
    • 비관적 락으로 재고 행을 잠그면 경쟁 요청이 순차 처리되어 병목 발생
  2. 02실행

    재고 경쟁은 Redis로, 변경 이력은 RDB로 분리

    • 실시간 잔여 조회·Lua 원자 차감은 Redis가 담당
    • RDB에는 재고 행 갱신 대신 변동 이력을 기록하고, 신규 변경은 원장 기록 후 성공 응답
  3. 03결과

    초과 차감 방지와 실패 시 재고 복원까지 구현

    • 재시도는 멱등 처리하고, 원장 저장 실패 시 Redis 재고 복원
    • Redis 동시 차감 테스트에서 초기 재고를 초과하지 않는 처리 결과 확인
SCROLL

PROJECT 02PRODUCT · CONSISTENCY

openAt · 기술 트러블슈팅

상품 도메인 후속 보강 · 2026.08

취소 재시도와 동시 구매의 재고 정합성 보강

01 문제 발생

완료된 취소 재시도로 재고 중복 복원

Redis 멱등키가 만료된 뒤 같은 취소를 재요청하면 재고가 한 번 더 증가. 보상하기 전 다른 주문의 차감이 초과 수량으로 성공할 수 있는 구조.

02 원인 분석

중복 판정 전에 재고부터 변경

Lua 원자성은 Redis 내부에만 적용. RDB UNIQUE가 중복 원장을 막아도, 그 전에 다른 구매에 노출된 재고는 보호하지 못함.

03 해결 아이디어 구상

아이디어 A검토 결과한계 확인

UNIQUE 충돌 후 재고 보상

중복 취소 이력을 막고 증가분을 회수. 그사이 다른 주문의 차감이 성공하면, 잔여 재고를 보상해도 해당 승인은 취소되지 않음.

아이디어 B검토 결과단독 사용 제외

완료 원장 사전 조회

완료된 취소는 사전 조회로 차단. 두 요청이 조회를 통과한 뒤 처리 사이 멱등키까지 사라지면, 같은 재고를 다시 복원할 수 있음.

아이디어 C검토 결과해결안 채택

원장 선조회·동일 주문 잠금

같은 주문의 차감 원장을 잠근 뒤 취소 완료 여부 확인. 최초 취소만 복원하고, 재시도는 추가 변경 없이 반환.

04 검증 결과

openAt · 기술 트러블슈팅

정합성 검증·구현 상세

원장은 한 건인데, 왜 초과 차감이 가능한가?

주문 A의 차감과 취소가 모두 기록된 상태에서, 취소 멱등키만 만료되면 기존 코드는 같은 취소를 새 요청처럼 처리합니다. Redis에서 재고를 먼저 늘리고 RDB에 취소 이력을 넣으려다 UNIQUE 충돌을 확인하는 순서입니다. 문제는 이 두 작업 사이에 다른 주문이 들어올 수 있다는 점입니다.

변경 전의 실패 순서 · 총 재고 1개
시점실행Redis 잔여
취소 완료주문 A의 차감·취소 원장 모두 존재1개
멱등키 만료 후 재시도이미 끝난 취소인데 Redis 재고를 다시 복원2개
다른 주문의 차감서로 다른 주문 두 건이 차감·원장 기록을 완료0개
뒤늦은 중복 판정주문 A의 UNIQUE 충돌로 증가분을 보상−1개

UNIQUE는 취소 이력의 중복 INSERT를 막았습니다. 그러나 이미 성공한 다른 주문의 차감까지 취소하지는 않습니다. 최종 캐시와 원장 합이 일치하더라도, 둘 다 음수 재고로 수렴할 수 있으므로 성공 응답 수와 재고의 하한을 함께 검증해야 합니다.

같은 주문의 취소만 직렬화

  1. 존재하는 원 차감 이력에 잠금

    해당 주문의 DEDUCT 원장 행을 SELECT FOR UPDATE로 조회합니다. 아직 없는 ROLLBACK 행을 잠그려 하지 않고, 같은 주문의 취소들이 공유하는 기존 행을 직렬화 지점으로 사용합니다.

  2. 완료 여부와 요청 내용 확인

    잠금을 획득한 뒤 ROLLBACK 원장을 확인합니다. 이미 완료됐다면 주문·드롭·구매자·수량을 대조하고 Redis 재고를 다시 늘리지 않습니다.

  3. 최초 취소만 복원·기록

    완료 이력이 없을 때만 Redis 복원과 원장 기록을 수행합니다. 같은 주문의 후속 취소는 잠금 해제 후 완료 원장을 다시 확인합니다. 다른 주문의 정상 차감은 이 원장 행을 잠그지 않고 기존 Lua 경로로 진행합니다.

TTL 연장의 한계
유한한 멱등키 보존 시간을 늘려도, 만료 뒤 재시도의 완료 여부는 영구 원장으로 확인해야 합니다.
사전 조회만으로 부족한 이유
최초 취소 둘이 모두 미완료 원장을 읽고, 처리 도중 Redis 멱등키까지 유실되면 두 요청이 복원할 수 있습니다. 사전 조회와 실행 사이를 같은 주문의 DB 잠금으로 연결합니다.
트랜잭션 경계
rollback의 외부 트랜잭션이 DEDUCT 행 잠금을 유지하고, StockHistoryRecorder는 REQUIRES_NEW로 취소 이력을 독립 커밋합니다. 기록 충돌이 외부 트랜잭션에 rollback-only를 전파하지 않도록 분리한 구조입니다.
감수한 비용
같은 주문의 취소는 대기하고, 독립 원장 기록에는 추가 DB 연결이 필요합니다. 커넥션 풀과 대기 시간을 고려해야 하지만, 같은 드롭의 모든 구매를 하나의 재고 행에 줄 세우지는 않습니다.

PostgreSQL·Redis 전후 경합 검증

2026.09 추가 검증에서 기존 롤백 순서와 후속 보강 코드를 같은 기반에 놓고 비교했습니다. 기존 방식은 Redis 재복원 직후, 개선 방식은 완료 원장 확인 뒤에 취소 재시도를 잠시 멈췄습니다. 그 사이 다른 주문 두 건의 차감과 실제 원장 커밋을 먼저 끝낸 뒤 재시도를 재개했습니다.

각 5회 실행에서 동일하게 확인한 결과
검증 항목변경 전변경 후
신규 차감 승인 / 가용 재고2건 / 1개1건 / 1개
최종 Redis 잔여-1개0개
원장 기준 잔여-1개0개
완료 취소의 추가 복원1회0회
취소한 구매자의 Redis 구매량1개 · 원장은 0개필드 없음 · 원장도 0개
기존 주문의 취소 원장1건1건
환경·방법
PostgreSQL 16.14 · Redis 7.4.9 · Java 21.0.11. 실제 Spring 서비스·트랜잭션 프록시와 테스트 컨테이너를 사용하며, spy는 실행 순서와 호출 횟수만 제어합니다.
만료 조건
합성 주문의 취소 키를 30ms TTL로 만들고 50ms 후 부재를 확인합니다. 서비스의 1시간 설정은 바꾸지 않고, 만료 뒤 상태를 빠르게 재현했습니다.
추가 경합
완료 취소와 신규 차감 8건의 경합, 최초 취소 두 건 사이의 멱등키 유실·교차 차감을 검증했습니다. 같은 주문의 후속 취소는 잠금을 기다리고, 다른 주문의 차감은 진행되는지 함께 확인했습니다.
검증 범위
상품 서비스의 재고 차감 승인과 원장 커밋까지의 결과입니다. 주문·결제 전체 완료 수나 운영 TPS를 측정한 결과는 아닙니다.
남은 실패 경계
이번 보강은 완료 취소의 재실행과 동일 주문의 중복 취소 경쟁을 다룹니다. 최초 복원 뒤 DB·프로세스 장애나 진행 중 재워밍까지 원자적으로 처리하는 분산 트랜잭션은 아닙니다.

구현·검증 근거

세미에서 만든 상품 도메인의 후속 보강(2026.08)입니다. 기존 세미 기간과 구분하고, 아래 커밋의 서비스·잠금·실제 DB/Redis 테스트를 기준으로 검증했습니다. 비교용 기존 방식은 같은 코드 기반에서 롤백 경로만 c979876의 순서로 복원했습니다.

가용 재고 1개에서 초과 차감 차단

변경 전 · 신규 차감
2건 승인
가용 재고보다 1건 초과
변경 후 · 신규 차감
1건 승인
초과 차감 없이 잔여 0개

동일 경합을 각 5회 재현해 같은 결과 확인원장·Redis 잔여·구매자 카운터를 함께 대조한 재고 차감 검증

SCROLL

PROJECT 02CHAPTER 02 / 02

openAt

FINAL PROJECT

다양한 한정판 상품을 정해진 시각에 한정 수량으로 드롭하는 MSA 커머스 서비스

  1. 01문제 정의

    운영 현황을 확인할 관리자 기능 부재

    • 오늘 주문 수조차 DB를 직접 조회해야 하는 상태
    • 남은 일정에 운영 화면을 개별 구현하기 어렵고, 요구마다 기능을 추가해야 하는 부담
  2. 02실행

    자체 추론 서버를 활용한 관리자 챗봇 구축

    • 개별 운영 화면 대신, 하나의 질문창에서 요청을 받고 필요한 도메인 조회 도구 연결
    • 로컬 추론의 8K 컨텍스트·응답 지연을 고려해 필요한 도구·스키마만 단계별로 공개
    • 모델은 질문 해석·답변 생성을 맡고, 권한·도구 공개·실행 검증은 애플리케이션에서 통제
  3. 03결과
    openAt · FINAL PROJECT

    응답 성능 검증

    Spring AI 도입을 위한 응답 성능 비교

    로컬 추론의 응답 지연을 줄이기 위해, 영역 선택·입력 구조화를 각각 요청하던 기존 방식과 도구 선택·입력 구조화를 통합한 Spring AI 후보를 비교했습니다.

    동일 로컬 서버·모델 · 8개 질문 × 3회

    비교 지표기존 개별 호출Spring AI 후보
    응답 중앙값30.409s11.869s
    기능 성공20/2419/24

    응답 중앙값은 단축됐지만 기능 성공은 20/24에서 19/24로 감소했습니다. 상대 날짜는 서버에서 계산하도록 바꾸고 도구 선택·실행 규칙을 보완한 뒤, 필요한 도구·스키마만 단계별로 공개하는 구조로 발전시켰습니다.

    이후 확정한 1차 요청 구조에 19개 질문을 2회씩 요청해, 기대한 답변 또는 도구·영역 선택이 38/38회 일치하는지 확인했습니다. 이 검증은 1차 요청의 선택 범위이며, 전체 최종 답변의 성공률과는 구분됩니다.

    운영 정보를 자연어로 확인하는 관리자 기능 완성

    • 주문·상품 현황과 회원 집계를 DB 직접 조회 없이 자연어로 확인
    • 여러 정보가 필요한 질문은 먼저 완료된 결과부터 전달하고, 확인한 정보를 종합해 답변
TROUBLESHOOTING

챗봇 구축 중 발생한 문제

  1. Q1
    조회 API 증가로 다른 도메인의 구현 부담 확대

    통합 읽기 전용 뷰 제공에 합의하고, 원천 도메인과 AI 조회 계층의 책임 분리

  2. Q2
    8K 컨텍스트의 도구·스키마 수용 한계

    요청 단계마다 필요한 도구·스키마만 공개하는 다단계 호출 적용

  3. Q3
    다단계 호출로 길어지는 최종 응답 대기

    도구 스키마 크기에 따라 호출 단계를 나누고, 가벼운 결과부터 먼저 표시

LIVE DEMO

관리자 챗봇 시연

기본 조회·다중 데이터 처리·병렬 및 다단계 도구 추론 시연

SCROLL

PROJECT 02CHAPTER 02 / 02

openAt · 기술 트러블슈팅

관리자 챗봇

복합 운영 질문의 독립 조회·실패 격리

01 문제 발생

느린 조회 하나로 정상 결과까지 소실

주문 통계·회원 현황처럼 독립적인 정보를 함께 조회. 한 조회가 시간 제한을 넘으면, 이미 완료된 다른 조회 결과도 버리고 전체 요청을 실패 처리.

02 원인 분석

조회별 시간 초과를 전체 실패로 전파

Future를 기다리다 발생한 시간 초과를 공통 예외로 처리. 이미 완료된 결과까지 반환하지 못하는, 요청 단위의 실패 판정이 원인.

03 해결 아이디어 구상

아이디어 A검토 결과한계 확인

병렬 조회·일괄 실패

한 조회의 시간 초과에 전체 수집을 종료. 이미 완료된 다른 조회의 결과도 함께 폐기.

아이디어 B검토 결과단독 사용 제외

병렬 조회·개별 대기 제한

실패를 항목별로 수집해 정상 결과 보존. 각 결과에 대기 시간을 새로 주면 단계의 총 대기는 길어질 수 있음.

아이디어 C검토 결과해결안 채택

병렬 조회·공통 시간 제한

조회 단계 전체에 한 번 정한 제한 적용. 정상 사실과 미완료 항목의 실패 이유를 함께 답변 생성에 전달.

04 검증 결과

openAt · 기술 트러블슈팅

실패 격리·검증 상세

완료된 조회 결과가 사라진 위치

주문 통계와 회원 현황은 서로 독립적인 조회입니다. 기존 구현도 두 조회를 병렬로 실행했지만, Future를 기다리는 루프 바깥에서 시간 초과를 처리했습니다. 첫 조회가 지연되면 공통 catch가 전체 수집을 끝내므로, 뒤쪽 Future가 이미 정상 완료됐어도 그 값은 반환되지 않았습니다.

같은 조회 조합·지연 조건의 전후 비교
시점변경 전변경 후
조회 실행주문 통계는 지연, 회원 현황은 42명으로 먼저 완료
단계 제한 도달첫 대기의 시간 초과를 전체 예외로 전파미완료 주문 조회만 FAILED로 수집
정상 결과 반환완료된 회원 현황도 반환하지 못함회원 수·조회 범위·관측 시각 보존
답변 근거전체 수집 실패확인한 회원 현황과 주문 조회 실패를 함께 전달

입력 순서대로 결과를 수집하는 것 자체가 문제는 아닙니다. 개선본도 원래 식별자와 순서를 유지합니다. 바꾼 것은 조회 하나의 시간 초과를 요청 전체 실패로 해석하던 경계와, 결과마다 새로 부여하던 대기 시간입니다.

공통 시간 제한 안에서 항목별 상태 수집

  1. 조회 묶음의 시간 예산을 한 번 계산

    단계 제한과 전체 요청의 남은 시간 중 작은 값을 사용합니다. invokeAll에 이 시간을 적용하므로 여러 미완료 Future에 각각 새 대기 시간을 부여하지 않습니다.

  2. 완료와 실패를 같은 목록에 보존

    완료된 작업은 원래 결과를 사용하고, 취소·실패한 작업은 같은 binding ID의 FAILED 항목으로 바꿉니다. 실패 facts는 null과 사유를 남겨, 확인하지 못한 주문 수가 정상적인 0건으로 바뀌지 않게 합니다.

  3. 최종 추론까지 정보의 의미 유지

    정상 facts의 값·범위·관측 시각과 실패 항목을 EvidenceSegment로 함께 전달합니다. 모델이 어떤 정보를 확인했고 무엇을 확인하지 못했는지 구분할 수 있도록 실행 계층이 근거를 소유합니다.

단계 시간 초과
전체 요청에 시간이 남아 있다면 미완료 조회를 FAILED로 기록하고 정상 형제 결과는 보존합니다. 빠른 결과를 즉시 스트리밍하는 방식은 아니며, 같은 조회 묶음의 수집이 끝난 뒤 전달합니다.
전체 요청 기한
요청의 잔여 시간이 먼저 끝났다면 TIMEOUT으로 종료합니다. 정상 근거가 일부 있다는 이유로 기한을 연장하거나 정상 완료로 바꾸지 않습니다.
사용자 취소·포화
중단은 CANCELLED, 실행기 포화는 BUSY로 구분합니다. 실행되지 않은 요청에 정상 결과나 부분 성공을 만들어 붙이지 않습니다.
취소의 실제 범위
미완료 Future에 취소 신호를 전달하고 협조적인 작업의 interrupt 수신을 확인했습니다. 이것만으로 모든 HTTP·JDBC 작업이 즉시 물리적으로 중단된다고 보장할 수는 없으며, 외부 I/O의 timeout도 별도로 필요합니다.

완료 여부·값·상태를 함께 검증

2026.09 추가 재현에서는 실제 Java executor와 PlanFactory·ResultMapper·실행 어댑터를 사용했습니다. 데이터 포트에 합성 회원 현황과 주문 조회 지연을 주입하고, 정상 회원 현황이 먼저 완료됐다는 기록을 확인한 뒤 수집 결과를 비교했습니다.

전후 각 5회에서 확인한 결과 · 단계 500ms / 요청 10초
검증 항목변경 전변경 후
정상 회원 현황의 완료42명 확인42명 확인
수집 결과TimeoutException을 원인으로 전체 예외FAILED · SUCCESS 두 항목 반환
반환한 정상 결과없음회원 42명·원래 범위·시각 유지
실패를 정상 0건으로 변환해당 없음 · 전체 예외변환하지 않음 · facts=null과 사유
지연 작업의 interrupt수신 확인수신 확인

요청 마감·호출자 중단·실행기 포화도 별도 조건으로 실행해 TIMEOUT·CANCELLED·BUSY를 확인했습니다. 단순히 예외가 없어졌는지가 아니라, 정상 빈 결과와 부분 결과·실패의 의미가 섞이지 않는지도 검사했습니다.

실제 Spring AI 클라이언트에서 최종 요청까지 확인

로컬 OpenAI 호환 HTTP 응답 서버를 연결해 routing → binding → 실제 실행 어댑터 → orchestrator → 최종 답변 요청을 통과시켰습니다. 느린 주문 조회와 잘못된 dataset 항목은 실패로 남기고, 정상 회원 현황은 최종 요청의 verified-evidence JSON까지 전달되는지 대조했습니다.

실행 결과
FAILED · FAILED · SUCCESS. 정상 회원 42명, MEMBERSHIP/MEMBER_CURRENT, 관측 시각 2026-07-31T12:15:00+09:00를 포함한 모든 근거 필드의 일치 확인.
HTTP·종료
routing 1회 · binding 1회 · answer 1회. 단일 done 이벤트 확인. 이 통합 검증의 단계 제한은 3초로, 위 500ms 전후 비교와 구분합니다.
검증 범위
모델 응답과 조회 데이터는 통제된 fixture입니다. 실제 HTTP 클라이언트·파서·실행 계층·근거 전달 계약을 확인한 것이며, 실제 모델의 최종 답변 정확도나 DB 성능을 측정한 결과는 아닙니다.

조회 하나가 지연돼도 완료된 결과는 보존

변경 전 · 정상 결과 반환
0개
회원 현황도 전체 예외로 소실
변경 후 · 정상 결과 반환
1개
회원 현황 보존·주문 조회 실패 구분

값·조회 범위·관측 시각을 최종 답변 요청까지 유지응답 지연을 주입한 전후 각 5회 비교와 실제 HTTP 근거 전달 검증

SCROLL

PROJECT 03AI INFRA · PYTHON

Inference Gateway

보유 하드웨어에서 반복 사용할 수 있는 OpenAI 호환 로컬 추론 서버

  1. 01문제 정의

    토큰 사용 제약에 따른 추론 품질 문제

    • 한정된 토큰 예산으로 사용할 모델과 추론량에 제약
    • 모델과 추론량을 낮추면 AI 답변의 품질과 사용자 경험도 저하될 우려
  2. 02실행

    로컬 추론 서버 구축 후 OpenAI 모델과 비교 검증

    • GTX 1080 Ti에서 구동할 Gemma 4 12B 양자화 모델을 선정하고 Python·FastAPI로 서버 구축
    • 같은 평가 문항으로 사용 예정 OpenAI 모델과 블라인드 품질·응답 시간 비교
  3. 03결과

    품질·속도에 따른 모델 적용 기준 제안

    Gemma 4 12B
    품질8.89/10
    응답10.3초
    GPT-5 Mini
    품질7.67/10
    응답2.7초
    GPT-5.4 Nano
    품질7.11/10
    응답1.9초
    품질: 근거 함정·형식 준수 과제의 블라인드 점수 / 응답: 동일 66문항의 평균 시간
BENCHMARK DECISION

품질과 속도에 따라 나눈 적용 기준

품질 우선
로컬 추론 서버임베딩 · 이미지 분석 · 챗봇
속도 우선
OpenAI 모델추천 서비스

벤치마크와 서비스 요구를 바탕으로 팀에 제안한 적용 기준

SCROLL

PROJECT 03AI INFRA · STREAMING

Inference Gateway · 기술 트러블슈팅

스트리밍 응답의 완료 판정·장애 복구

01 문제 발생

중간에 끝난 답변을 정상 완료로 처리

답변 일부만 도착하고 HTTP 본문이 끝나도 전송을 정상 종료. 복구 확인 요청까지 성공으로 기록해 로컬 차단 해제.

02 원인 분석

전송 종료와 답변 완료를 같은 상태로 판단

HTTP 스트림이 예외 없이 끝났는지만 확인. 완료 이벤트 [DONE]의 수신 여부와 무관하게 정상 종료와 복구 성공을 기록.

03 해결 아이디어 구상

아이디어 A검토 결과한계 확인

전송 종료 기준

예외 없는 HTTP 본문 종료를 성공으로 처리. 완료 이벤트가 빠진 응답을 구분하지 못함.

아이디어 B검토 결과채택 제외

응답 전체 버퍼링

응답을 모두 모아 완료 여부를 확인한 뒤 전달. 답변이 끝날 때까지 첫 표시도 지연.

아이디어 C검토 결과해결안 채택

중계와 완료 판정 분리

답변 조각은 바로 중계하고 완료 이벤트는 별도로 추적. [DONE] 없이 끝나면 전송과 복구 확인을 실패로 판정.

04 검증 결과

Inference Gateway · 기술 트러블슈팅

스트림·검증 상세

HTTP 본문 종료가 답변 완료를 뜻하지 않는 이유

Chat Completions 스트림에서 HTTP 200을 받았더라도 답변 전체의 완료를 보장하지는 않습니다. 유효한 답변 조각이 일부 도착한 뒤 HTTP 본문이 예외 없이 끝나더라도, 완료 이벤트가 없으면 모델 응답의 정상 완료를 확인할 수 없습니다. TCP 연결이 끊기거나 HTTPX가 읽기 예외를 내는 경우와는 다른 실패 조건입니다.

기존 _stream_committed는 비동기 iterator가 정상 종료되면 바로 회로에 성공을 기록했습니다. 따라서 장애 후 복구를 확인하는 half-open 요청에서 같은 일이 발생하면, 잘린 응답뿐 아니라 로컬 서버의 호출 재개까지 잘못 판단할 수 있었습니다.

완료 이벤트 없는 복구 확인 요청의 판정 경계
관찰 지점기존 기준변경한 기준
응답 시작첫 유효 SSE 이벤트를 확보한 뒤 로컬 응답으로 확정
HTTP 본문 종료iterator가 정상 종료되면 성공완결된 [DONE] 수신까지 확인
종료 이벤트 누락정상 마지막 body 전송·복구 성공StreamTruncatedError·복구 실패 기록

스트리밍은 유지하고 완료 증거만 별도 추적

  1. 답변 조각은 받은 순서대로 중계

    전체 응답을 모으지 않고 확보한 초기 조각과 이후 조각을 그대로 전달합니다. 종료 추적기는 중계 바이트를 관찰하며, 응답 내용을 고치거나 다른 모델의 출력을 이어 붙이지 않습니다.

  2. 전송 청크와 SSE 이벤트 경계를 분리

    [DONE] 문자열이나 CRLF가 여러 청크에 나뉘어 도착해도 같은 이벤트로 인식합니다. 빈 줄로 이벤트가 완결되기 전에는 종료로 인정하지 않으며, 미완결 라인·이벤트의 누적 크기는 64KiB 상한으로 제한합니다.

  3. 완료를 확인한 뒤에만 성공 기록

    iterator의 정상 종료와 완료 이벤트 수신을 모두 확인한 뒤 record_success를 호출합니다. 종료 이벤트 누락은 실패로 기록하고 정상 마지막 body를 보내지 않아, 호출자가 불완전 전송을 감지할 수 있도록 합니다.

[DONE]은 이 게이트웨이가 중계하는 Chat Completions 응답의 계약이며, 모든 SSE 스트림에 공통으로 적용되는 종료 표준은 아닙니다. 종료 추적기는 후속 JSON의 모든 필드나 답변 품질을 검증하지 않고, 종료 이벤트 이후 추가 바이트를 차단하는 역할도 맡지 않습니다.

되돌릴 수 있는 시점까지만 모델 전환

첫 유효 이벤트 전
생성 요청의 로컬 장애가 폴백 대상이면 외부 모델을 시도합니다. 임베딩과 비폴백 4xx까지 외부로 재전송하는 정책은 아닙니다.
응답 시작 후
이미 전달한 로컬 답변을 다른 모델의 내용과 섞지 않습니다. 완료 이벤트 없이 끝나거나 전송 장애가 발생하면 HTTP 200을 뒤늦게 502로 바꾸거나 [DONE]을 합성하지 않고, 시작된 응답을 불완전 전송으로 끝냅니다.
회로 복구 판정
half-open 복구 요청이 완료되지 않았다면 다시 OPEN으로 전환합니다. 일반 CLOSED 상태의 요청은 연속 실패 임계값을 따르므로, 모든 실패 한 번이 즉시 차단을 뜻하지는 않습니다.
취소·자원 정리
호출자 취소와 downstream 전송 실패는 로컬 추론 실패와 구분합니다. 완료하지 못한 probe 슬롯을 반환하고, 취소된 scope에서도 upstream 응답을 닫도록 정리 작업을 보호합니다.

완료 여부와 회로 상태를 함께 확인

2026.09 추가 재현에서는 실제 Uvicorn·HTTPX·ASGI 중계와 원본 회로 차단기를 사용했습니다. 로컬 HTTP 서버가 같은 답변 조각을 보내고 Content-Length에 맞춰 정상 종료하되 [DONE]만 생략하도록 했습니다. 현재 소스에서 중계 메서드 하나만 이전 구현으로 복원해, 같은 입력을 전후 각 5회 비교했습니다.

완료 이벤트 누락 · 전후 각 5회 동일 결과
검증 항목변경 전변경 후
HTTP 시작 상태200200
전달한 응답122 bytes · 같은 답변 조각과 SHA-256
정상 마지막 body전송미전송
completed 기록truefalse
HTTPX 수신 결과정상 종료RemoteProtocolError
half-open 이후CLOSEDOPEN
응답 시작 후 폴백0회0회

정상 [DONE] 대조도 전후 각 5회 실행해 양쪽 모두 정상 완료·회로 복구를 확인했습니다. LF·CR·CRLF에 걸친 종료 이벤트 분할, 마지막 빈 줄 누락, 첫 유효 이벤트 전후의 장애를 포함한 32개 HTTP 실험으로 종료 판정과 폴백 경계를 대조했습니다.

별도로 원본의 스트림 분류·폴백·응답 시작 기한·회로·중계·관측 회귀 218개를 실행해 통과했습니다. 호출자 취소와 downstream 전송 실패에서 upstream 정리·probe 반환을 확인하는 테스트도 포함됩니다. 이 회귀는 운영 저장 경로만 임시 경로로 대체했고, 실제 Windows 운영 작업은 실행하지 않았습니다.

업스트림 응답은 통제된 fixture이며 실제 모델 품질이나 GPU 처리량을 측정한 실험은 아닙니다. 검증 대상은 원본의 중계·완료 판정·회로·관측 계약입니다. 게이트웨이가 불완전 전송을 드러내는 것과 모든 호출자가 오류를 올바르게 표시·재시도하는 것은 별도 책임입니다.

잘린 응답을 실패로 판정하고 복구 오판 차단

완료 이벤트 없는 복구 확인 요청 비교
판정 항목변경 전변경 후
응답 종료정상 전송 완료불완전 전송으로 종료
복구 확인성공·차단 해제실패·다시 차단

전달한 답변 조각 보존 · 응답 시작 후 폴백 없음완료 이벤트 누락 전후 각 5회 · 정상 응답과 전송 경계 함께 검증

SCROLL

PROJECT 04PRODUCT · ERP

Simple ERP

고객사·영업·계약·설비·AS와 사내 업무를 하나의 기준으로 연결한 현업 ERP

  1. 01문제 정의

    분산된 Excel 관리로 업무 정보의 정합성 훼손

    • 고객사 정보를 여러 파일에 중복 입력해, 변경 사항이 계약·AS 등 관련 업무에 미반영
    • 파일 복사본을 주고받으며 누락·중복이 발생하고, 최신 정보를 다시 확인하는 작업 반복
  2. 02실행

    업무 정보를 통합하고 도입 효과를 확인할 ERP 제안

    • 상용 ERP의 도입 효과를 확신하지 못한 상황에서, 직접 사용해 판단할 수 있는 제품 제안
    • 2주 내 구축과 이후 업무 확장을 고려해 Spring Modulith 선택
    • 기준 화면·API를 먼저 완성한 뒤 반복 구현은 Claude Code에 위임
  3. 03결과

    실사용을 통한 정식 ERP 도입과 후속 기능 확장

    • Simple ERP의 효용을 확인한 회사에서 하이웍스 ERP 정식 도입
    • 파일 보관 등 업무 불편을 비교한 직원들의 의견을 취합해 Simple ERP 확장 요청
    • 기존 모듈 구조와 에이전트 활용 경험을 바탕으로 주말 이틀간 확장·전체 검증
ADOPTION FLOW

실사용으로 이어진 판단과 확장

  1. 01Simple ERP 사용ERP 효용 확인
  2. 02하이웍스 도입실제 업무에서 비교
  3. 03확장 요청직원 의견·부장님 전달
  4. 04확장 기능 2일 구현주말 구현·전체 검증

실사용 환경·데이터와 분리한 합성 데이터 기반 공개 데모

SCROLL

PROJECT 04BUSINESS · AUTHORIZATION

Simple ERP · 기술 트러블슈팅

파일 권한 후속 보강 · 2026.08

첨부파일의 업무 귀속·열람 권한

01 문제 발생

비공개 결재 첨부를 게시글로 우회 열람

기안자·결재자만 볼 수 있는 첨부도, 다른 직원이 파일 ID를 자신의 게시글에 넣으면 다운로드 가능.

02 원인 분석

요청자가 만든 첨부 관계를 권한 근거로 신뢰

다운로드는 게시글 권한·첨부 목록만 확인. 등록은 업로더·기존 귀속 검증 없이 요청받은 파일 ID를 저장.

03 해결 아이디어 구상

아이디어 A검토 결과한계 확인

다운로드 시 문서 권한만 확인

문서 열람 권한과 첨부 목록을 확인. 다른 업무 파일도 목록에 넣으면 같은 검사를 통과.

아이디어 B검토 결과단독 사용 제외

연결 시 업로더 확인

타인 파일은 차단하지만, 본인이 이미 결재에 연결한 파일을 게시판에 다시 연결할 수 있음.

아이디어 C검토 결과해결안 채택

연결 귀속·열람 권한 분리

연결 시 업로더·기존 귀속 검증. 열람 시에도 업무 접근 권한과 실제 파일 귀속을 함께 확인.

04 검증 결과

Simple ERP · 기술 트러블슈팅

권한·검증 상세

다운로드 검사에 사용한 관계를 요청자가 만들 수 있었음

공통 업로드 API가 파일 ID를 먼저 반환하고, 게시글·결재 문서를 저장할 때 그 ID를 첨부 목록에 넣는 방식입니다. 결재 첨부는 기안자·결재자만 읽을 수 있지만, 게시판은 메뉴 접근 권한이 있는 직원이 함께 읽는 공간입니다. 같은 저장소를 쓰더라도 두 업무의 열람 범위는 다릅니다.

이전 게시글 저장은 요청에 담긴 attachmentFileIds를 그대로 기록했습니다. 다운로드에서는 게시글에 포함된 파일인지만 확인한 뒤 저장소에서 ID로 읽었습니다. 원래 결재 문서에서는 접근이 거절되는 파일도 자신의 게시글에 연결하면, 게시글의 정상 열람 검사로 읽을 수 있는 경로가 생겼습니다.

같은 비공개 첨부가 다른 업무의 열람 범위를 얻는 경로
요청기존 판단보강한 판단
비관련 직원의 결재 첨부 열람결재 관련자가 아니므로 거절
같은 ID를 자신의 게시글에 연결요청받은 첨부 목록 저장업로더·기존 귀속 불일치로 거절
게시글 경로로 첨부 열람게시글에 포함된 ID이므로 허용우회할 게시글·첨부 관계가 커밋되지 않음

파일 ID를 알아도 허용되지 않은 연결 관계를 만들 수 없어야 하므로, 첨부로 확정하는 시점부터 검증합니다.

연결 자격·업무 귀속·열람 자격을 분리

  1. 연결할 때에는 인증된 업로더 확인

    업로드 주체는 요청 본문의 직원 ID가 아니라 서버가 확인한 인증 직원입니다. 게시글을 작성하는 직원과 파일 업로더가 일치해야 처음 연결할 수 있습니다.

  2. 업무 레코드를 단일 소유자로 확정

    서버가 생성한 게시글 ID로 FileOwner(BOARD_POST, id)를 구성합니다. 미연결 PENDING 파일은 이 업무에 CLAIMED로 전환하고, 같은 소유자의 재요청은 허용하되 다른 문서로의 재귀속은 거절합니다. 업무 유형뿐 아니라 개별 레코드 ID까지 대조합니다.

  3. 읽을 때에도 업무 권한과 실제 귀속 대조

    업무 서비스가 결재 관련자·게시판 접근 등 각자의 열람 규칙을 확인합니다. 이어서 현재 문서에서 만든 expectedOwner를 저장소에 전달하고, 파일의 실제 귀속이 맞는 경우에만 읽습니다.

업로더 검사는 파일을 연결할 자격이지, 읽을 수 있는 사람 전체의 목록이 아닙니다. 정상 게시글의 다른 직원이나 결재 관련자까지 차단하지 않고, 해당 업무가 허용한 공유는 유지합니다.

여러 첨부와 동시 연결도 같은 경계에서 확정

업무 저장·파일 연결
게시글 ID를 확보한 뒤 같은 트랜잭션에서 claim합니다. 연결에 실패하면 이미 실행한 게시글 INSERT와 첨부 관계도 롤백합니다. 저장 호출 전에 검증을 모두 끝낸다는 뜻은 아닙니다.
다중 파일
정렬된 파일 ID를 PESSIMISTIC_WRITE로 읽고 모든 파일의 자격을 확인한 뒤 상태를 바꿉니다. 하나라도 연결할 수 없으면 앞쪽 파일만 먼저 귀속되는 부분 반영을 허용하지 않습니다.
동시 연결
같은 미연결 파일을 서로 다른 업무가 요청하면 행 잠금 뒤의 최신 상태로 판단합니다. 먼저 확정한 업무의 귀속을 뒤 요청이 덮어쓰지 않도록 합니다.
잘못된 참조의 읽기
문서의 첨부 목록에 ID가 있더라도 실제 FileOwner가 다르면 저장소에서 거절합니다. 다형적 owner가 모든 업무 테이블에 DB 외래 키를 건다는 뜻은 아니며, 업무 저장과 연결의 트랜잭션·읽기 대조가 함께 필요합니다.

우회 차단과 정상 공유를 함께 확인

2026.09 추가 검증에서는 실제 MariaDB와 임시 파일을 사용하고, 원본의 컨트롤러·메서드 보안·업무 서비스·트랜잭션 프록시·JPA·저장소를 연결했습니다. 합성 직원 A가 기안하고 C가 결재하는 문서의 첨부에 대해, 비관련 직원 B가 같은 파일 ID를 자신의 게시글에 연결하는 입력을 전후 각 5회 실행했습니다.

동일 입력의 최종 전후 각 5회에서 확인한 결과
검증 항목변경 전변경 후
원래 결재 경로404 · 접근 거절404 · 접근 거절
게시글 연결 요청200 · 저장 허용400 · FILE_CLAIM_NOT_ALLOWED
새 게시글·첨부 관계각 1개 커밋각 0개 · 롤백
게시글을 통한 원본 열람비공개 첨부와 동일한 바이트·해시우회할 새 연결이 만들어지지 않음
기존 결재·파일기존 참조와 파일 내용 보존
정상 직원 간 공유200 · 다른 직원도 열람200 · 같은 공유 유지

다른 업무로의 재연결 거절과 같은 소유자의 재요청 허용, 마지막 첨부만 부적합한 배치의 전체 롤백도 확인했습니다. 두 업무가 한 파일을 동시에 연결하는 조건에서는 INNODB_LOCK_WAITS로 실제 DB 대기를 관찰한 뒤, 한 업무만 커밋되고 뒤 요청은 거절되는 결과를 확인했습니다. 잘못된 참조를 DB에 직접 넣은 별도 fixture에서도 읽기 단계의 expectedOwner 대조로 404가 반환됐습니다.

실행 범위
전후 총 20회 시나리오 실행. MariaDB 11.8.6·Java25·실제 파일 사용. MockMvc로 MVC 경계를 호출한 검증이며 네트워크 부하 테스트는 아닙니다.
합성 경계
EmployeeApi·RoleApi와 인증 주체는 합성 fixture입니다. 메뉴 권한 판단과 업무 관련자·파일 귀속 검사는 원본 코드를 실행했지만, 실제 JWT·운영 필터 체인까지 검증한 것은 아닙니다.
관련 회귀
게시판·결재·파일 저장·기존 소유권 복원의 원본 테스트 108개 통과. 기존 소유권 복원은 단위 회귀 범위이며 실제 운영 데이터 마이그레이션 완료를 뜻하지 않습니다.

비공개 첨부 연결은 차단하고 업무 공유는 유지

비공개 결재 첨부와 정상 게시글 첨부의 전후 비교
검증 항목변경 전변경 후
비공개 첨부 우회연결·다운로드 허용연결 단계에서 거절
정상 게시글 공유다른 직원도 열람 가능다른 직원 열람 유지

거절 후 게시글·첨부 관계 미저장 · 기존 파일의 귀속·내용 보존동일 입력 전후 각 5회 · 정상 공유·원자적 연결·DB 잠금 경합 검증

OPENAT · SYSTEM FLOW

모듈 간 데이터 흐름도

회원·상품·주문·결제·정산 모듈이 어떤 요청과 이벤트로 연결되는지 정리한 세미 프로젝트 설계 자료입니다.

회원, 상품, 주문, 결제, 정산 모듈 사이의 요청과 이벤트, 상태 전이를 연결한 데이터 흐름도