@PostMapping 메서드 안에서 정산 로직을 동기로 끝까지 돌리면 Tomcat 스레드가 그 시간만큼 묶입니다. 제출과 실행을 분리해야 합니다.
작업 상태를 컨트롤러의 지역 변수나 요청 스코프 빈에 두면, 상태 조회 요청은 다른 스레드·다른 요청이라 그 값을 볼 수 없습니다. Job 객체는 요청과 독립된 저장소(맵 또는 DB)에 둬야 합니다.
cancelRequested = true 로 설정만 하고 작업 루프에서 그 값을 확인하는 코드가 없으면 취소가 아무 효과도 없습니다. 매 반복마다 반드시 확인해야 합니다.
메모리든 DB 든, 서버가 죽으면 그 순간 RUNNING 이던 작업은 완료될 수 없습니다. 기동 시점에 오래된 RUNNING 행을 FAILED 로 정리하는 절차가 없으면 사용자 화면에 좀비 작업이 남습니다.
proxy_buffering off 와 X-Accel-Buffering: no 없이 SSE 를 붙이면 이벤트가 한참 뒤에 한꺼번에 몰려서 도착합니다. 실시간처럼 보이지 않으면 이 설정부터 확인합니다.
버튼 연타나 504 뒤 재시도로 같은 작업이 두 번 실행되면, 정산처럼 부작용이 있는 작업은 데이터가 꼬입니다. owner 기준 중복 체크나 멱등키 없이 배포하면 안 됩니다.
Executors.newCachedThreadPool() 을 작업 처리용으로 쓰면 동시 제출이 몰릴 때 스레드가 끝없이 늘어나 서버 전체 메모리와 CPU 를 잠식합니다. 고정 크기와 큐 한도를 둬야 합니다.
@Async 가 조용히 무시된다같은 클래스 안에서 this.비동기메서드() 로 호출하면 예외 없이 그냥 동기로 실행됩니다. 눈치채기 어려운 실수라 별도 빈으로 분리하는 습관이 필요합니다.