Skip to content

Commit f1cbdf1

Browse files
authored
Revert "[Backend] fix: 에러 예외처리 수정 및 SSE CORS 설정"
1 parent 051c5ec commit f1cbdf1

File tree

8 files changed

+32
-58
lines changed

8 files changed

+32
-58
lines changed

backend/src/main/java/com/example/backend/analysis/controller/CaseStatsController.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import org.springframework.http.ResponseEntity;
88
import org.springframework.web.bind.annotation.*;
99

10+
import java.util.Collections;
1011
import java.util.List;
1112
import java.util.Map;
1213

@@ -22,6 +23,10 @@ public class CaseStatsController {
2223
public ResponseEntity<?> getOverview(HttpSession session) {
2324
// 결과가 없으면 404, 있으면 200
2425
CaseStatsOverviewResponse response = caseStatsService.getOverview(session);
26+
if (response == null) {
27+
return ResponseEntity.status(404)
28+
.body(Collections.singletonMap("message", "개요 정보가 없습니다."));
29+
}
2530
return ResponseEntity.ok(response);
2631
}
2732

@@ -31,6 +36,10 @@ public ResponseEntity<?> getHourlyCaseStats(@RequestParam("date") String date,
3136
@RequestParam(value = "category", required = false) String category,
3237
HttpSession session) {
3338
List<HourlyCaseStatsResponse> stats = caseStatsService.getHourlyCaseStats(date, category, session);
39+
if (stats.isEmpty()) {
40+
return ResponseEntity.status(404)
41+
.body(Collections.singletonMap("message", "시간대별 사건 정보가 없습니다."));
42+
}
3443
return ResponseEntity.ok(stats);
3544
}
3645

backend/src/main/java/com/example/backend/analysis/service/CaseStatsService.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ public CaseStatsOverviewResponse getOverview(HttpSession session) {
5656

5757
// 최근 한 달간 데이터를 기준으로 사건 건수가 가장 많은 CCTV 주소 조회
5858
String patrolRegionAddress = statsOverviewRepository.findAddressWithMostIncidentsLastMonth(officeId)
59-
.orElse("해당 지역에 순찰 강화 필요 구역이 없습니다.");
59+
.orElse("정보 없음");
6060

6161
return CaseStatsOverviewResponse.fromEntity(stats, patrolRegionAddress);
6262
}
Lines changed: 6 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,21 @@
11
package com.example.backend.common;
22

3+
import org.springframework.web.bind.annotation.ControllerAdvice;
4+
35
import jakarta.persistence.EntityNotFoundException;
4-
import jakarta.servlet.http.HttpServletResponse;
5-
import lombok.extern.slf4j.Slf4j;
66
import org.springframework.http.HttpStatus;
7-
import org.springframework.http.MediaType;
87
import org.springframework.http.ResponseEntity;
9-
import org.springframework.web.bind.annotation.ControllerAdvice;
108
import org.springframework.web.bind.annotation.ExceptionHandler;
119

12-
import java.io.IOException;
1310
import java.util.Collections;
1411
import java.util.NoSuchElementException;
1512

16-
@Slf4j
1713
@ControllerAdvice
1814
public class GlobalExceptionHandler {
1915

20-
// SSE 연결 종료 (브라우저에서 탭 닫거나, 연결 끊긴 경우)
21-
@ExceptionHandler(IOException.class)
22-
public void handleIOException(IOException e) {
23-
log.warn("SSE 연결 종료: {}", e.getMessage());
24-
}
25-
2616
@ExceptionHandler(IllegalStateException.class)
2717
public ResponseEntity<?> handleIllegalStateException(IllegalStateException e) {
28-
log.warn("IllegalStateException: {}", e.getMessage());
29-
if (e.getMessage().contains("로그인이 필요")) {
18+
if (e.getMessage().contains("로그인이 필요합니다.")) {
3019
return ResponseEntity.status(HttpStatus.UNAUTHORIZED)
3120
.body(Collections.singletonMap("message", e.getMessage()));
3221
}
@@ -47,19 +36,8 @@ public ResponseEntity<?> handleEntityNotFoundException(EntityNotFoundException e
4736
}
4837

4938
@ExceptionHandler(Exception.class)
50-
public void handleGenericException(Exception e, HttpServletResponse response) throws IOException {
51-
log.error("Unexpected error: ", e);
52-
if ("text/event-stream".equals(response.getContentType())) {
53-
// SSE 통신 도중 에러 → event-stream 포맷으로 전달
54-
response.getWriter().write("event: error\n");
55-
response.getWriter().write("data: " + e.getMessage() + "\n\n");
56-
response.getWriter().flush();
57-
} else {
58-
// 일반 요청 → JSON 에러 응답
59-
response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
60-
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
61-
response.getWriter().write("{\"message\": \"" + e.getMessage() + "\"}");
62-
response.getWriter().flush();
63-
}
39+
public ResponseEntity<?> handleGenericException(Exception e) {
40+
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
41+
.body(Collections.singletonMap("message", e.getMessage()));
6442
}
6543
}

backend/src/main/java/com/example/backend/config/CorsConfig.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ public void addCorsMappings(CorsRegistry corsRegistry) {
1616
corsRegistry.addMapping("/**")
1717
.allowedOrigins(allowedOrigins)
1818
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS", "HEAD")
19-
.allowedHeaders("Authorization", "Content-Type", "Last-Event-ID")
20-
.exposedHeaders("Authorization", "Content-Type", "Cache-Control", "Last-Event-ID")
19+
.allowedHeaders("Authorization", "Content-Type")
20+
.exposedHeaders("Authorization")
2121
.allowCredentials(true);
2222
}
2323
}

backend/src/main/java/com/example/backend/config/SecurityConfig.java

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
package com.example.backend.config;
22

3+
import java.util.Arrays;
4+
import java.util.List;
5+
36
import lombok.RequiredArgsConstructor;
47
import org.springframework.beans.factory.annotation.Value;
58
import org.springframework.context.annotation.Bean;
@@ -12,9 +15,6 @@
1215
import org.springframework.web.cors.CorsConfigurationSource;
1316
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
1417

15-
import java.util.Arrays;
16-
import java.util.List;
17-
1818
@Configuration
1919
@EnableWebSecurity
2020
@RequiredArgsConstructor
@@ -28,21 +28,22 @@ public SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Excepti
2828
return httpSecurity
2929
.csrf(AbstractHttpConfigurer::disable)
3030
.httpBasic(AbstractHttpConfigurer::disable)
31+
// CORS 설정을 수동으로 추가
3132
.cors(cors -> cors.configurationSource(corsConfigurationSource()))
3233
.build();
3334
}
3435

36+
// CORS 설정을 위한 Bean 정의
3537
@Bean
3638
public CorsConfigurationSource corsConfigurationSource() {
3739
CorsConfiguration configuration = new CorsConfiguration();
3840
configuration.setAllowedOrigins(List.of(allowedOrigins)); // 프론트엔드 도메인
3941
configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE", "OPTIONS", "HEAD")); // 허용할 HTTP 메서드
40-
configuration.setAllowedHeaders(Arrays.asList("Authorization", "Content-Type", "Last-Event-ID")); // 허용할 헤더
41-
configuration.setExposedHeaders(Arrays.asList("Authorization", "Content-Type", "Cache-Control", "Last-Event-ID")); // 응답에서 노출할 헤더
42+
configuration.setAllowedHeaders(Arrays.asList("Authorization", "Content-Type")); // 허용할 헤더
43+
configuration.setExposedHeaders(List.of("Authorization")); // 응답에서 노출할 헤더
4244
configuration.setAllowCredentials(true); // 자격 증명 포함 요청 허용
43-
4445
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
4546
source.registerCorsConfiguration("/**", configuration); // 모든 경로에 대해 CORS 설정 적용
4647
return source;
4748
}
48-
}
49+
}

backend/src/main/java/com/example/backend/dashboard/controller/CaseDetectController.java

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,7 @@
44
import com.example.backend.dashboard.dto.CaseDetectResponse;
55
import com.example.backend.dashboard.service.CaseDetectService;
66
import com.example.backend.dashboard.service.SseEmitterService;
7-
import jakarta.servlet.http.HttpServletResponse;
87
import lombok.RequiredArgsConstructor;
9-
import org.springframework.beans.factory.annotation.Value;
108
import org.springframework.http.ResponseEntity;
119
import org.springframework.web.bind.annotation.*;
1210
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
@@ -19,9 +17,6 @@ public class CaseDetectController {
1917
private final CaseDetectService caseDetectService;
2018
private final SseEmitterService sseEmitterService;
2119

22-
@Value("${cors.allowed-origins}")
23-
private String allowedOrigin;
24-
2520
@PostMapping("/detect")
2621
public ResponseEntity<?> detectAlarm(@RequestBody CaseDetectRequest request) {
2722
CaseDetectResponse response = caseDetectService.saveCase(request);
@@ -30,12 +25,7 @@ public ResponseEntity<?> detectAlarm(@RequestBody CaseDetectRequest request) {
3025
}
3126

3227
@GetMapping("/subscribe")
33-
public SseEmitter subscribe(HttpServletResponse response) {
34-
response.setHeader("Access-Control-Allow-Origin", allowedOrigin);
35-
response.setHeader("Access-Control-Allow-Credentials", "true");
36-
response.setHeader("Cache-Control", "no-cache");
37-
response.setHeader("Connection", "keep-alive");
38-
28+
public SseEmitter subscribe() {
3929
return sseEmitterService.createEmitter();
4030
}
4131

backend/src/main/java/com/example/backend/dashboard/controller/DashboardController.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import org.springframework.http.ResponseEntity;
88
import org.springframework.web.bind.annotation.*;
99

10+
import java.util.Collections;
1011
import java.util.List;
1112
import java.util.Map;
1213

@@ -21,6 +22,10 @@ public class DashboardController {
2122
@GetMapping("")
2223
public ResponseEntity<?> getCases(HttpSession session) {
2324
List<DashboardResponse> cases = dashboardService.getCases(session);
25+
if (cases.isEmpty()) {
26+
return ResponseEntity.status(404)
27+
.body(Collections.singletonMap("message", "사건이 없습니다."));
28+
}
2429
return ResponseEntity.ok(cases);
2530
}
2631

backend/src/main/java/com/example/backend/dashboard/service/DashboardService.java

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -66,10 +66,6 @@ public List<DashboardResponse> getCases(HttpSession session) {
6666
);
6767
List<CaseEntity> cases = dashboardRepository.findAllByOfficeIdAndStateInOrderById(officeId, targetStates);
6868

69-
if (cases.isEmpty()) {
70-
throw new NoSuchElementException("미확인, 확인 또는 출동 중인 사건이 없습니다.");
71-
}
72-
7369
return cases.stream()
7470
.map(DashboardResponse::fromEntity)
7571
.collect(Collectors.toList());
@@ -84,11 +80,6 @@ public Map<String, String> getCaseVideo(int id, HttpSession session) {
8480
throw new EntityNotFoundException("해당 사건에 대한 영상이 없습니다.");
8581
}
8682

87-
if (caseEntity.getState() == CaseEntity.CaseState.미확인) {
88-
caseEntity.setState(CaseEntity.CaseState.확인);
89-
dashboardRepository.save(caseEntity);
90-
}
91-
9283
return Collections.singletonMap("video", videoUrl);
9384
}
9485

0 commit comments

Comments
 (0)