공공부하자개발 · 영어 학습 노트
자바
실무 확장Excel · 파일 업로드 · DB 연동0/22 완료
  • 01Excel(XLSX) 구조와 순수 JDK로 읽기/쓰기
  • 02Apache POI로 Excel 업로드/다운로드
  • 03파일 업로드/다운로드 서버 (HttpServer)
  • 04JDBC 기초와 트랜잭션 (H2)
  • 05MyBatis 어노테이션 매퍼로 쿼리 연동
  • 06MyBatis XML 매퍼 · Oracle 방언 · PageHelper · Spring Boot
  • 07REST API 서버와 JSON
  • 08Vue 3 SPA 와 Java 서버 연동
  • 09@Scheduled 운영
  • 10로깅 실무: 레벨·계층, MDC 추적, 예외·성능, 마스킹, 롤링, JSON 로그
  • 11외부 API 연동
  • 12테스트 실무
  • 13암호화·개인정보 보호
  • 14인코딩·한글 실무
  • 15@Transactional 심화
  • 16긴 작업 비동기 처리와 진행률
  • 17SFTP·FTP 파일 연계
  • 18로컬 캐시와 @Cacheable
  • 19메일·알림 발송
  • 20웹 보안 체크리스트
  • 21빌드 도구와 폐쇄망 의존성 반입
  • 22성능 측정: p50·p95·p99, 측정 계층, JFR, JMH 함정, 자체 부하 테스트, 병목 순위
사이트 소개개인정보처리방침연락처
© 2026 공부하자
홈 › 실무 확장 › 16 / 22

긴 작업 비동기 처리와 진행률

202 Accepted, 작업 상태, 폴링·SSE, 취소, 중복 방지, 완전 종료
섹션 7진행 0 / 22
1왜 배우는가2핵심 원리3코드 예제4응용 변형 예제5자주 하는 실수 (Tip)6연습 문제7정리‹ 이전다음 ›

5. 자주 하는 실수 (Tip)

실수 1: 긴 작업을 컨트롤러 메서드 안에서 그대로 처리한다

@PostMapping 메서드 안에서 정산 로직을 동기로 끝까지 돌리면 Tomcat 스레드가 그 시간만큼 묶입니다. 제출과 실행을 분리해야 합니다.

실수 2: 진행률 저장소로 요청 스코프 변수를 쓴다

작업 상태를 컨트롤러의 지역 변수나 요청 스코프 빈에 두면, 상태 조회 요청은 다른 스레드·다른 요청이라 그 값을 볼 수 없습니다. Job 객체는 요청과 독립된 저장소(맵 또는 DB)에 둬야 합니다.

실수 3: 취소 플래그만 켜고 스레드가 실제로 멈추는지 확인하지 않는다

cancelRequested = true 로 설정만 하고 작업 루프에서 그 값을 확인하는 코드가 없으면 취소가 아무 효과도 없습니다. 매 반복마다 반드시 확인해야 합니다.

실수 4: 서버 재기동 후 RUNNING 상태가 영원히 남는다

메모리든 DB 든, 서버가 죽으면 그 순간 RUNNING 이던 작업은 완료될 수 없습니다. 기동 시점에 오래된 RUNNING 행을 FAILED 로 정리하는 절차가 없으면 사용자 화면에 좀비 작업이 남습니다.

실수 5: nginx 뒤에서 SSE 를 켰는데 버퍼링 설정을 빼먹는다

proxy_buffering off 와 X-Accel-Buffering: no 없이 SSE 를 붙이면 이벤트가 한참 뒤에 한꺼번에 몰려서 도착합니다. 실시간처럼 보이지 않으면 이 설정부터 확인합니다.

실수 6: 중복 제출 방지를 하지 않는다

버튼 연타나 504 뒤 재시도로 같은 작업이 두 번 실행되면, 정산처럼 부작용이 있는 작업은 데이터가 꼬입니다. owner 기준 중복 체크나 멱등키 없이 배포하면 안 됩니다.

실수 7: 스레드 풀 크기를 무제한으로 둔다

Executors.newCachedThreadPool() 을 작업 처리용으로 쓰면 동시 제출이 몰릴 때 스레드가 끝없이 늘어나 서버 전체 메모리와 CPU 를 잠식합니다. 고정 크기와 큐 한도를 둬야 합니다.

실수 8: self-invocation 으로 @Async 가 조용히 무시된다

같은 클래스 안에서 this.비동기메서드() 로 호출하면 예외 없이 그냥 동기로 실행됩니다. 눈치채기 어려운 실수라 별도 빈으로 분리하는 습관이 필요합니다.

자주 하는 실수 (Tip)
  • 실수 1: 긴 작업을 컨트롤러 메서드 안에서 그대로 처리한다
  • 실수 2: 진행률 저장소로 요청 스코프 변수를 쓴다
  • 실수 3: 취소 플래그만 켜고 스레드가 실제로 멈추는지 확인하지 않는다
  • 실수 4: 서버 재기동 후 RUNNING 상태가 영원히 남는다
  • 실수 5: nginx 뒤에서 SSE 를 켰는데 버퍼링 설정을 빼먹는다
  • 실수 6: 중복 제출 방지를 하지 않는다
  • 실수 7: 스레드 풀 크기를 무제한으로 둔다
  • 실수 8: self-invocation 으로 @Async 가 조용히 무시된다
이전 섹션4 응용 변형 예제5 / 7다음 섹션6 연습 문제