1. 배경
기존 SI 프로젝트에서 삭제 기능을 AJAX로 호출하면서
Spring Controller에서는 다음과 같이 화면을 리턴하고 있었다.
return alertAndRedirect(model, "삭제되었습니다.", "/list.do");
프론트에서는
$.ajax({ dataType: "json", ... });
즉, AJAX는 JSON을 기대하는데 서버는 HTML/JSP를 내려주는 구조였다.
2. 실제 발생한 문제
1) JSON 파싱 에러
AJAX는 HTML을 JSON으로 파싱하려다 parsererror 발생
→ success가 아닌 error 콜백으로 떨어짐
하지만 DB는 이미 삭제 완료
사용자 화면: "삭제 실패"
실제 DB: 삭제 완료
2) 중복 삭제/운영 사고
사용자는 실패한 줄 알고 다시 클릭
→ 이미 삭제된 데이터
→ 2차 에러, 문의 발생
3) redirect 무력화
Spring에서 redirect를 반환해도
AJAX 요청에서는 브라우저 화면이 이동하지 않음.
XHR 내부에서만 redirect가 처리됨.
서버: 로그인 페이지로 보냈다고 생각
클라이언트: 그냥 HTML 문자열 받음
4) 상태코드 의미 상실
- 실패여도 HTTP 200
- 성공여도 HTTP 200
AJAX에서는 성공/실패를 정확히 구분할 수 없음
→ 프론트 로직, 모니터링, 로그 분석 전부 어려워짐
3. 구조적 원인
계층기대
| AJAX | JSON + HTTP Status |
| Controller | JSP + redirect |
통신 계약(Contract) 자체가 깨져 있는 구조
4. 개선 방향
AJAX 요청은 무조건:
JSON + HTTP 상태코드
로 통신하도록 구조를 분리했다.
5. 개선된 Controller
@PostMapping("ND_deletePlntClinicApply.do")
@ResponseBody
public ResponseEntity<Map<String,Object>> delete(ApplicationVO vo){
Map<String,Object> res = new HashMap<>();
UserLoginVO u = (UserLoginVO) getUserSession();
if(u == null){
res.put("success", false);
res.put("message", "로그인이 필요합니다.");
return ResponseEntity.status(401).body(res);
}
vo.setUserId(u.getUserId());
int cnt = service.delete(vo);
if(cnt < 1){
res.put("success", false);
res.put("message", "삭제 실패");
return ResponseEntity.status(404).body(res);
}
res.put("success", true);
return ResponseEntity.ok(res);
}
6. 개선된 AJAX
success: function(res){
if(res.success){
alert("삭제되었습니다.");
location.href="/list.do";
}else{
alert(res.message);
}
},
error: function(xhr){
if(xhr.status===401) alert("로그인 필요");
else alert("서버 오류");
}
7. 개선 효과

8. 핵심 교훈
AJAX 요청에 화면을 리턴하는 순간,
시스템은 논리적으로 이미 깨진 구조다.
9. 정리
- 화면 이동은 Controller가 아니라 JavaScript가 담당
- Controller는 데이터만 책임
- HTTP 상태코드는 API의 계약
10. 한 줄 요약
AJAX 요청에 JSP를 리턴하던 구조를 JSON 기반 REST 구조로 개선하면서,
사용자 오류 인식, 중복 처리, 운영 사고, 모니터링 불가 문제를 근본적으로 해결할 수 있었다.
LIST
'Developer > Spring & Backend' 카테고리의 다른 글
| 공공기관 SI 프로젝트 시스템 설계 방식 (0) | 2026.01.28 |
|---|---|
| Legacy System 및 Spring Boot Migration 및 Cloud 전환 전략 (0) | 2026.01.28 |
| MIT License 유래와 핵심 정리 (1) | 2026.01.12 |
| Apache License 2.0 — 유래와 핵심 정리 (0) | 2026.01.12 |
| 🤖 AI 무료 vs 유료, 정말 돈 낼 가치 있을까? (0) | 2025.12.30 |