ESG 물리 기후 리스크 예측 프로젝트 - 백엔드_비동기

낭가인·2025년 12월 1일

SKALA최종프로젝트

목록 보기
2/9

비동기(Async) 작업 시스템의 문제들과 해결 전략 정리

대규모 계산 작업(E, V, AAL 계산 등)과 일반 API 요청이 섞여 있는 시스템에서는 비동기 처리를 도입하는 순간 동기 방식에서는 절대 겪지 않는 새로운 문제들이 튀어나온다.

아래에서는 실제로 ModelOps·AI Agent 구조에서 공통으로 부딪히는 문제들을 나누어 설명하고, 각 문제를 어떻게 설계 레벨에서 해결해야 하는지 정리한다.


1. 고전적 문제: API 요청과 Heavy 계산이 섞이면서 생기는 병목

비동기라 하더라도, 계산과 API 요청이 같은 프로세스 / 같은 워커에서 돌아가면
계산이 CPU를 오래 점유하며 API 응답이 밀리는 문제가 발생한다.

E,V,AAL 계산이 8초 걸리는 동안
연속으로 들어오는 /health or /status API조차 응답이 늦어짐

해결 전략

1) 계산 서버(Calc Service)와 API 서버를 분리한다

API 서버는 "job 생성"과 "결과 조회"만 담당
계산은 별도 FastAPI(혹은 워커)에서 수행

2) Compute 서버는 반드시 별도 쓰레드풀/워커 구조로 운영

FastAPI BackgroundTask
Celery worker
RQ worker
multiprocessing 기반 worker

→ API 이벤트 루프와 계산 이벤트 루프를 절대로 공유하지 않는다.


2. 중복 트리거 문제 (Double Trigger)

“같은 사이트/같은 시나리오/같은 연도”에 대해
중복으로 계산 요청(job)이 들어오는 문제.

해결 전략

1) (site_id, scenario, horizon) 조합에 Unique 제약 추가

UNIQUE(site_id, scenario, horizon)

이러면 중복 요청이 들어오면:

기존 job 리턴
or
"이미 계산 중" status만 줘도 됨

2) "Idempotency Token" 패턴 도입

API 호출 시 idempotency_key를 받고
같은 키면 같은 job 반환.


3. 비동기 처리에서 가장 흔한 문제: “이 계산이 끝났다는 것을 어떻게 아는가?”

LLM/Business 서버는 비동기 계산이 얼마나 걸릴지 모르고,
ModelOps는 계산 중인데, 프론트/Agent는 결과가 필요한 상황.

해결 전략

1) Job 테이블을 도입
job_id
  status = PENDING | RUNNING | COMPLETED | FAILED
  error_message
  started_at
  finished_at

Agent는 다음 API만 사용:

POST /jobs → job 생성
GET /jobs/{id} → 상태 조회
GET /sites/{id}/results → 결과 조회

Agent는 절대 계산 결과를 ModelOps API에서 직접 받지 않는다.


4. 작업 실패 처리 난이도 증가제

동기 시스템은 실패하면 API가 500을 그냥 내보내버린다.
하지만 비동기 시스템에서는:

워커가 실패했는지
실패했으면 재시도할 건지
실패 로그가 어딨는지
Agent가 실패를 사용자에게 어떻게 전달할지

관리 포인트가 늘어난다.

해결 전략

1) Job 상태를 FAILED로 기록
2) error_message/log_url 저장
3) Agent는 status를 기준으로 리포트 처리

FAILED면 “이번 분석은 실패했습니다. 나중에 다시 시도하세요.”
COMPLETED면 결과 조회 후 LLM 리포트 생성


5. Race Condition (경쟁 조건)

A와 B 두 요청이 같은 job에 접근해서 다음과 같은 문제가 생김:

A가 status를 RUNNING으로 변경
B도 거의 동시에 status를 RUNNING으로 변경
→ 중복 계산 발생
→ 결과가 엉킴

해결 전략

1) DB level Lock 사용 (SELECT FOR UPDATE)
2) Job state transition 로직을 원자적으로 설계
3) Unique 제약과 Double-start 방지 로직 강화


6. 작업 폭주 문제: 동시에 너무 많은 작업이 들어오는 상황

10명만 써도 동시에 “후보지 8개”씩 계산하면
ModelOps에 80개 job이 쌓임 → CPU 폭주 → 전체 시스템 지연.

해결 전략

1) Worker concurrency 제한
Celery → --concurrency=N
ThreadPool → max_workers 설정
2) Job 큐 길이 제한

Job을 넣기 전에 검증:

if current_running_jobs > MAX:
    return 429 Too Many Requests
3) Job 우선순위(Priority Queue)

사업장 분석 > 후보지 분석
최근 요청 > 오래된 요청


7. 결과 저장 전략의 혼란

비동기 시스템은 결과를 어디에 저장할 것인지도 난제다.

잘못된 패턴:
결과를 계산 API 리턴으로 주려고 함
→ 비동기와 완전히 충돌

해결 전략

E, V, AAL 결과는 반드시 DB(Site-level)로 저장해야 한다.

site_results
--------------
site_id
scenario
horizon
e_score
v_score
aal_value
risk_index
updated_at

Agent는 항상 DB만 읽는다.


정리: 안전한 아키텍처 패턴

    [User]
        ↓
   [AI Agent API]
        ↓  (트리거)
POST /jobs
        ↓
   [ModelOps API]
        ↓  (백그라운드/워커)
   Compute Worker
        ↓
     [DB]
        ↑
[AI Agent] ← GET /jobs/{id}, GET /results

핵심 요약

API와 계산이 섞임 -> 서버 분리 / 워커 사용
중복 계산 -> Unique key / idempotency
상태 추적 -> Job 테이블 도입
실패 -> FAILED 상태 관리
경쟁 조건 -> Lock 사용
작업 폭주 -> concurrency 제한
결과 저장 위치 ->DB 고정

마무리

비동기 작업 시스템은 성능 때문에 도입하지만,
성능보다 더 어려운 상태 관리와 일관성 문제가 새롭게 등장한다.

위의 문제와 해결책을 미리 고려하면
ModelOps–AI Agent–Backend가 섞인 복잡한 시스템에서도
안정적으로 “계산 요청 → 비동기 처리 → 결과 조회 → 보고서 생성”
전체 생산라인을 손대지 않고 확장할 수 있다.

profile
안녕하세요

0개의 댓글