-
Notifications
You must be signed in to change notification settings - Fork 1
[fix] 배포 시 에러 로그 사라지는 버그 수정, 예외 디스코드 알림 범위 수정, 프론트 요구사항 반영 #133
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
80b0ff2
0df86d8
7c93c29
d7cf1e1
4d4ee76
a6efa39
6341141
6075a52
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -38,7 +38,7 @@ public class GlobalExceptionHandler { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @ExceptionHandler(ApplicationException.class) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| public ResponseEntity<CommonResponse> handleApplicationException(ApplicationException e, WebRequest request) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // 비즈니스 예외 로그 기록 (간결하게) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| String path = ((ServletWebRequest) request).getRequest().getRequestURI(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| String method = ((ServletWebRequest) request).getRequest().getMethod(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -47,36 +47,31 @@ public ResponseEntity<CommonResponse> handleApplicationException(ApplicationExce | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| CommonResponse commonResponse = CommonResponse.error(e.getErrorCase()); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| HttpStatus status = HttpStatus.valueOf(e.getErrorCase().getHttpStatusCode()); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| //sendToDiscord(e, request, status); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return ResponseEntity | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .status(e.getErrorCase().getHttpStatusCode()) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .body(commonResponse); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @ExceptionHandler(value = MethodArgumentNotValidException.class) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| public ResponseEntity<CommonResponse> handleValidException(BindingResult bindingResult, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| MethodArgumentNotValidException ex, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| WebRequest request) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| String message = bindingResult.getAllErrors().get(0).getDefaultMessage(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @ExceptionHandler(MethodArgumentNotValidException.class) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| public ResponseEntity<CommonResponse> handleValidException(MethodArgumentNotValidException ex, WebRequest request) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| String message = ex.getBindingResult().getAllErrors().get(0).getDefaultMessage(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // 에러 로그 기록 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| String path = ((ServletWebRequest) request).getRequest().getRequestURI(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| String method = ((ServletWebRequest) request).getRequest().getMethod(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| String errorLocation = getErrorLocation(ex); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| log.error("Validation Exception 발생 - Method: {}, Path: {}, Message: {}, Location: {}", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| method, path, message, errorLocation, ex); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| log.warn("Validation Exception - Method: {}, Path: {}, Message: {}, Location: {}", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| method, path, message, errorLocation); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| CommonResponse commonResponse = CommonResponse.error(400, message); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| sendToDiscord(ex, request, HttpStatus.BAD_REQUEST); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return ResponseEntity | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .status(HttpStatus.BAD_REQUEST) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .body(commonResponse); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * 모든 예상하지 못한 예외 처리 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -107,6 +102,12 @@ private void sendToDiscord(Exception ex, WebRequest request, HttpStatus status) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // 특정 예외 타입 및 경로에 대한 Discord 알림 제외 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (shouldSkipDiscordNotification(ex, path)) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| log.debug("Discord 알림 제외 - Exception: {}, Path: {}", ex.getClass().getSimpleName(), path); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Embed 필드 구성 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| DiscordWebhookPayload.Embed embed = new DiscordWebhookPayload.Embed( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "🚨 서버 에러 발생", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -136,6 +137,108 @@ private void sendToDiscord(Exception ex, WebRequest request, HttpStatus status) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * Discord 알림을 보내지 않을 예외인지 판단 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private boolean shouldSkipDiscordNotification(Exception ex, String path) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| String exceptionName = ex.getClass().getSimpleName(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| String message = ex.getMessage(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // 1. NoResourceFoundException 제외 (static resource 요청) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if ("NoResourceFoundException".equals(exceptionName)) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return true; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // 2. 특정 경로 패턴 제외 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (isIgnoredPath(path)) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return true; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // 3. 봇이나 크롤러 요청으로 인한 에러 제외 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (isBotOrCrawlerRequest(message)) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return true; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // 4. 기타 불필요한 예외들 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (isIgnoredException(exceptionName, message)) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return true; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return false; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * 무시할 경로인지 확인 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private boolean isIgnoredPath(String path) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| String[] ignoredPaths = { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "/favicon.ico", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "/index.html", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "/robots.txt", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "/sitemap.xml", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "/apple-touch-icon", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "/.well-known/", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "/wp-admin/", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "/admin/", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "/phpmyadmin/", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "/xmlrpc.php", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "/.env", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "/config.php" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for (String ignoredPath : ignoredPaths) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (path.contains(ignoredPath)) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return true; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return false; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+170
to
+197
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion isIgnoredPath: 대소문자/널 안전성 보강 요청 경로가 null이거나 대문자 포함 시 매칭 누락 가능성이 있습니다. 소문자 변환 후 비교하도록 안전성 보강을 권장합니다. - private boolean isIgnoredPath(String path) {
- String[] ignoredPaths = {
+ private boolean isIgnoredPath(String path) {
+ if (path == null) return false;
+ String lowerPath = path.toLowerCase();
+ String[] ignoredPaths = {
"/favicon.ico",
"/index.html",
"/robots.txt",
"/sitemap.xml",
"/apple-touch-icon",
"/.well-known/",
"/wp-admin/",
"/admin/",
"/phpmyadmin/",
"/xmlrpc.php",
"/.env",
"/config.php"
};
- for (String ignoredPath : ignoredPaths) {
- if (path.contains(ignoredPath)) {
+ for (String ignoredPath : ignoredPaths) {
+ if (lowerPath.contains(ignoredPath)) {
return true;
}
}
return false;
}📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * 봇이나 크롤러 요청인지 확인 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private boolean isBotOrCrawlerRequest(String message) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (message == null) return false; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| String[] botIndicators = { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "No static resource", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "Could not resolve view", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "favicon", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "robots.txt" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for (String indicator : botIndicators) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (message.contains(indicator)) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return true; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return false; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+198
to
+219
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion 봇/크롤러 감지: 대소문자 불일치 보완 메시지 비교를 소문자 기준으로 수행해 탐지 누락을 줄이는 것을 권장합니다. - private boolean isBotOrCrawlerRequest(String message) {
- if (message == null) return false;
-
- String[] botIndicators = {
- "No static resource",
- "Could not resolve view",
- "favicon",
- "robots.txt"
- };
-
- for (String indicator : botIndicators) {
- if (message.contains(indicator)) {
- return true;
- }
- }
-
- return false;
- }
+ private boolean isBotOrCrawlerRequest(String message) {
+ if (message == null) return false;
+
+ String msg = message.toLowerCase();
+ String[] botIndicators = {
+ "no static resource",
+ "could not resolve view",
+ "favicon",
+ "robots.txt"
+ };
+
+ for (String indicator : botIndicators) {
+ if (msg.contains(indicator)) {
+ return true;
+ }
+ }
+
+ return false;
+ }📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * 무시할 예외인지 확인 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private boolean isIgnoredException(String exceptionName, String message) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // 클라이언트 연결 종료 관련 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if ("ClientAbortException".equals(exceptionName) || | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "BrokenPipeException".equals(exceptionName)) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return true; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // 타임아웃 관련 (너무 빈번한 경우) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (message != null && ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| message.contains("Connection timed out") || | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| message.contains("Read timed out") || | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| message.contains("Connection reset") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| )) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return true; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return false; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+220
to
+241
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion 무시 예외 케이스 보강: broken pipe 등 메시지 기반 추가, 대소문자 보완 실무에서 “Broken pipe”, “Connection reset by peer” 형태의 메시지가 자주 발생합니다. 메시지 기반 케이스를 소문자로 통일해 보강하세요. - private boolean isIgnoredException(String exceptionName, String message) {
+ private boolean isIgnoredException(String exceptionName, String message) {
// 클라이언트 연결 종료 관련
if ("ClientAbortException".equals(exceptionName) ||
"BrokenPipeException".equals(exceptionName)) {
return true;
}
// 타임아웃 관련 (너무 빈번한 경우)
- if (message != null && (
- message.contains("Connection timed out") ||
- message.contains("Read timed out") ||
- message.contains("Connection reset")
- )) {
- return true;
- }
+ if (message != null) {
+ String msg = message.toLowerCase();
+ if (msg.contains("connection timed out")
+ || msg.contains("read timed out")
+ || msg.contains("connection reset")
+ || msg.contains("connection reset by peer")
+ || msg.contains("broken pipe")) {
+ return true;
+ }
+ }
return false;
}📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * 예외의 스택트레이스에서 실제 에러 발생 위치를 추출 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -6,6 +6,7 @@ | |||||||||||||
| import com.wayble.server.explore.service.WaybleZoneRecommendService; | ||||||||||||||
| import jakarta.validation.Valid; | ||||||||||||||
| import lombok.RequiredArgsConstructor; | ||||||||||||||
| import org.springframework.security.core.context.SecurityContextHolder; | ||||||||||||||
| import org.springframework.validation.annotation.Validated; | ||||||||||||||
| import org.springframework.web.bind.annotation.*; | ||||||||||||||
|
|
||||||||||||||
|
|
@@ -24,8 +25,9 @@ public CommonResponse<List<WaybleZoneRecommendResponseDto>> getWaybleZonePersona | |||||||||||||
| @Valid @ModelAttribute WaybleZoneRecommendConditionDto conditionDto, | ||||||||||||||
| @RequestParam(name = "size", defaultValue = "1") int size) { | ||||||||||||||
|
|
||||||||||||||
| Long userId = (Long) SecurityContextHolder.getContext().getAuthentication().getPrincipal(); | ||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 보안 컨텍스트에서 userId 추출 시 타입 검증이 누락되었습니다. SecurityContextHolder에서 Principal을 Long으로 직접 캐스팅하고 있는데, 타입 안전성을 위해 instanceof 검증을 추가해야 합니다. UserController.java의 updateUserInfo 메서드에서는 이런 검증을 수행하고 있습니다. 다음과 같이 타입 검증을 추가하세요: - Long userId = (Long) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
+ Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
+ if (!(authentication.getPrincipal() instanceof Long)) {
+ throw new ApplicationException(UserErrorCase.FORBIDDEN);
+ }
+ Long userId = (Long) authentication.getPrincipal();📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||
| List<WaybleZoneRecommendResponseDto> result = waybleZoneRecommendService.getWaybleZonePersonalRecommend( | ||||||||||||||
| conditionDto.userId(), | ||||||||||||||
| userId, | ||||||||||||||
| conditionDto.latitude(), | ||||||||||||||
| conditionDto.longitude(), | ||||||||||||||
| size | ||||||||||||||
|
|
||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -18,13 +18,12 @@ | |||||||||||||
| import java.util.List; | ||||||||||||||
|
|
||||||||||||||
| @RestController | ||||||||||||||
| @RequestMapping("/api/v1/users/{userId}/places") | ||||||||||||||
| @RequestMapping("/api/v1/users/places") | ||||||||||||||
| @RequiredArgsConstructor | ||||||||||||||
| public class UserPlaceController { | ||||||||||||||
|
|
||||||||||||||
| private final UserPlaceService userPlaceService; | ||||||||||||||
|
|
||||||||||||||
|
|
||||||||||||||
| @PostMapping | ||||||||||||||
| @Operation(summary = "유저 장소 저장", description = "유저가 웨이블존을 장소로 저장합니다.") | ||||||||||||||
| @ApiResponses({ | ||||||||||||||
|
|
@@ -34,18 +33,9 @@ public class UserPlaceController { | |||||||||||||
| @ApiResponse(responseCode = "403", description = "권한이 없습니다.") | ||||||||||||||
| }) | ||||||||||||||
| public CommonResponse<String> saveUserPlace( | ||||||||||||||
| @PathVariable Long userId, | ||||||||||||||
| @RequestBody @Valid UserPlaceRequestDto request | ||||||||||||||
| ) { | ||||||||||||||
| Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); | ||||||||||||||
| if (!(authentication.getPrincipal() instanceof Long)) { | ||||||||||||||
| throw new ApplicationException(UserErrorCase.FORBIDDEN); | ||||||||||||||
| } | ||||||||||||||
| Long tokenUserId = (Long) authentication.getPrincipal(); | ||||||||||||||
| if (!userId.equals(tokenUserId)) { | ||||||||||||||
| throw new ApplicationException(UserErrorCase.FORBIDDEN); | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| Long userId = (Long) SecurityContextHolder.getContext().getAuthentication().getPrincipal(); | ||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 타입 안전성을 위한 instanceof 검증이 누락되었습니다. SecurityContextHolder에서 Principal을 Long으로 직접 캐스팅하고 있는데, UserController.java의 패턴을 따라 타입 검증을 추가해야 합니다. - Long userId = (Long) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
+ Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
+ if (!(authentication.getPrincipal() instanceof Long)) {
+ throw new ApplicationException(UserErrorCase.FORBIDDEN);
+ }
+ Long userId = (Long) authentication.getPrincipal();📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||
| userPlaceService.saveUserPlace(userId, request); // userId 파라미터로 넘김 | ||||||||||||||
| return CommonResponse.success("장소가 저장되었습니다."); | ||||||||||||||
| } | ||||||||||||||
|
|
@@ -61,16 +51,8 @@ public CommonResponse<String> saveUserPlace( | |||||||||||||
| @ApiResponse(responseCode = "403", description = "권한이 없습니다.") | ||||||||||||||
| }) | ||||||||||||||
| public CommonResponse<List<UserPlaceListResponseDto>> getUserPlaces( | ||||||||||||||
| @PathVariable Long userId | ||||||||||||||
| ) { | ||||||||||||||
| Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); | ||||||||||||||
| if (!(authentication.getPrincipal() instanceof Long)) { | ||||||||||||||
| throw new ApplicationException(UserErrorCase.FORBIDDEN); | ||||||||||||||
| } | ||||||||||||||
| Long tokenUserId = (Long) authentication.getPrincipal(); | ||||||||||||||
| if (!userId.equals(tokenUserId)) { | ||||||||||||||
| throw new ApplicationException(UserErrorCase.FORBIDDEN); | ||||||||||||||
| } | ||||||||||||||
| Long userId = (Long) SecurityContextHolder.getContext().getAuthentication().getPrincipal(); | ||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 타입 안전성을 위한 instanceof 검증이 누락되었습니다. 동일하게 이 메서드에서도 타입 검증이 필요합니다. - Long userId = (Long) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
+ Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
+ if (!(authentication.getPrincipal() instanceof Long)) {
+ throw new ApplicationException(UserErrorCase.FORBIDDEN);
+ }
+ Long userId = (Long) authentication.getPrincipal();📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||
| List<UserPlaceListResponseDto> places = userPlaceService.getUserPlaces(userId); | ||||||||||||||
| return CommonResponse.success(places); | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
검증 예외 메시지 추출 시 안전성 보강 (빈 에러/NPE 방지)
getAllErrors().get(0)는 드물게 비어 있을 수 있어IndexOutOfBoundsException가능성이 있습니다. 메시지가 null/blank인 경우도 대비해 기본 메시지를 두는 것이 안전합니다.다음과 같이 방어 로직을 적용해 주세요:
📝 Committable suggestion
🤖 Prompt for AI Agents