diff --git a/build.gradle b/build.gradle index 4527d19f..678fa72c 100644 --- a/build.gradle +++ b/build.gradle @@ -90,6 +90,9 @@ dependencies { // Slack-Alarm implementation 'com.github.maricn:logback-slack-appender:1.6.1' + + // AOP + implementation 'org.springframework.boot:spring-boot-starter-aop' } tasks.named('test') { diff --git a/src/main/java/doldol_server/doldol/auth/dto/kakao/KakaoOAuth2Strategy.java b/src/main/java/doldol_server/doldol/auth/dto/kakao/KakaoOAuth2Strategy.java index 202f566c..f47686d8 100644 --- a/src/main/java/doldol_server/doldol/auth/dto/kakao/KakaoOAuth2Strategy.java +++ b/src/main/java/doldol_server/doldol/auth/dto/kakao/KakaoOAuth2Strategy.java @@ -12,9 +12,7 @@ import doldol_server.doldol.user.entity.SocialType; import feign.FeignException; import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -@Slf4j @Component @RequiredArgsConstructor public class KakaoOAuth2Strategy implements OAuth2ResponseStrategy { @@ -44,21 +42,15 @@ public void unlink(String socialId) { kakaoApiClient.withdraw(KAKAO_ADMIN_KEY + adminKey, KAKAO_TARGET_TYPE, Long.parseLong(socialId)); - log.info("카카오 사용자 연결 해제 성공. socialId: {}", socialId); } catch (NumberFormatException e) { - log.error("카카오 연결 해제 중 잘못된 socialId 형식. socialId: {}", socialId, e); throw new OAuth2UnlinkException(OAuth2ErrorCode.INVALID_SOCIAL_ID); } catch (FeignException.Unauthorized e) { - log.error("카카오 API 인증 실패. 관리자 키를 확인하세요. socialId: {}", socialId, e); throw new OAuth2UnlinkException(OAuth2ErrorCode.OAUTH2_UNAUTHORIZED); } catch (FeignException.BadRequest e) { - log.error("카카오 API 잘못된 요청. 유효하지 않은 socialId 또는 파라미터. socialId: {}", socialId, e); throw new OAuth2UnlinkException(OAuth2ErrorCode.OAUTH2_BAD_REQUEST); } catch (FeignException e) { - log.error("카카오 API 호출 실패. 상태코드: {}, socialId: {}", e.status(), socialId, e); throw new OAuth2UnlinkException(OAuth2ErrorCode.OAUTH2_API_ERROR); } catch (Exception e) { - log.error("카카오 연결 해제 중 예상치 못한 오류 발생. socialId: {}", socialId, e); throw new OAuth2UnlinkException(OAuth2ErrorCode.OAUTH2_UNLINK_FAILED); } } diff --git a/src/main/java/doldol_server/doldol/auth/filter/CustomLogoutFilter.java b/src/main/java/doldol_server/doldol/auth/filter/CustomLogoutFilter.java index 5bed2a6e..8489bfaa 100644 --- a/src/main/java/doldol_server/doldol/auth/filter/CustomLogoutFilter.java +++ b/src/main/java/doldol_server/doldol/auth/filter/CustomLogoutFilter.java @@ -18,9 +18,7 @@ import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -@Slf4j @RequiredArgsConstructor public class CustomLogoutFilter extends GenericFilterBean { @@ -49,8 +47,6 @@ private void doFilter(HttpServletRequest request, HttpServletResponse response, tokenProvider.deleteRefreshToken(id); - log.info("로그아웃 완료: userId={}", id); - ResponseUtil.writeNoContent( response, objectMapper, diff --git a/src/main/java/doldol_server/doldol/auth/filter/CustomUsernamePasswordAuthenticationFilter.java b/src/main/java/doldol_server/doldol/auth/filter/CustomUsernamePasswordAuthenticationFilter.java index 4086924e..73e5b310 100644 --- a/src/main/java/doldol_server/doldol/auth/filter/CustomUsernamePasswordAuthenticationFilter.java +++ b/src/main/java/doldol_server/doldol/auth/filter/CustomUsernamePasswordAuthenticationFilter.java @@ -25,9 +25,7 @@ import jakarta.servlet.FilterChain; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; -import lombok.extern.slf4j.Slf4j; -@Slf4j public abstract class CustomUsernamePasswordAuthenticationFilter extends UsernamePasswordAuthenticationFilter { private final AuthenticationManager authenticationManager; @@ -74,9 +72,6 @@ private void handleSuccessAuthentication(HttpServletResponse response, Authentic CustomUserDetails userDetails = (CustomUserDetails)authentication.getPrincipal(); - log.info("일반 로그인 성공: userId={}, role={}", - userDetails.getUserId(), userDetails.getRole()); - String userid = String.valueOf(userDetails.getUserId()); Collection authorities = authentication.getAuthorities(); @@ -104,7 +99,6 @@ private void handleSuccessAuthentication(HttpServletResponse response, Authentic private void handleFailureAuthentication(HttpServletRequest request, HttpServletResponse response) throws IOException { String attemptedId = extractAttemptedId(request); - log.warn("로그인 실패: 아이디='{}', 잘못된 아이디 또는 비밀번호", attemptedId); ResponseUtil.writeErrorResponse(response, objectMapper, AuthErrorCode.WRONG_ID_PW); } diff --git a/src/main/java/doldol_server/doldol/auth/filter/JwtAuthenticationFilter.java b/src/main/java/doldol_server/doldol/auth/filter/JwtAuthenticationFilter.java index cc29896e..f915c33a 100644 --- a/src/main/java/doldol_server/doldol/auth/filter/JwtAuthenticationFilter.java +++ b/src/main/java/doldol_server/doldol/auth/filter/JwtAuthenticationFilter.java @@ -21,9 +21,7 @@ import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -@Slf4j @RequiredArgsConstructor public class JwtAuthenticationFilter extends OncePerRequestFilter { @@ -46,22 +44,18 @@ protected void doFilterInternal( SecurityContextHolder.getContext().setAuthentication(authentication); } } catch (ExpiredJwtException e) { - log.warn("만료된 토큰으로 접근 시도: 토큰 만료"); SecurityContextHolder.clearContext(); ResponseUtil.writeErrorResponse(response, objectMapper, AuthErrorCode.TOKEN_EXPIRED); return; } catch (IncorrectClaimException e) { - log.warn("잘못된 클레임 토큰으로 접근 시도: {}", e.getMessage()); SecurityContextHolder.clearContext(); ResponseUtil.writeErrorResponse(response, objectMapper, AuthErrorCode.INCORRECT_CLAIM_TOKEN); return; } catch (UsernameNotFoundException e) { - log.warn("존재하지 않는 사용자 토큰으로 접근 시도: {}", e.getMessage()); SecurityContextHolder.clearContext(); ResponseUtil.writeErrorResponse(response, objectMapper, AuthErrorCode.USER_NOT_FOUND); return; } catch (Exception e) { - log.warn("유효하지 않은 토큰으로 접근 시도: {}", e.getMessage()); SecurityContextHolder.clearContext(); ResponseUtil.writeErrorResponse(response, objectMapper, AuthErrorCode.INVALID_TOKEN); return; diff --git a/src/main/java/doldol_server/doldol/auth/handler/CustomOAuth2FailureHandler.java b/src/main/java/doldol_server/doldol/auth/handler/CustomOAuth2FailureHandler.java index 5dac2fc5..c7d46518 100644 --- a/src/main/java/doldol_server/doldol/auth/handler/CustomOAuth2FailureHandler.java +++ b/src/main/java/doldol_server/doldol/auth/handler/CustomOAuth2FailureHandler.java @@ -10,9 +10,7 @@ import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -@Slf4j @Component @RequiredArgsConstructor public class CustomOAuth2FailureHandler extends SimpleUrlAuthenticationFailureHandler { @@ -24,8 +22,6 @@ public class CustomOAuth2FailureHandler extends SimpleUrlAuthenticationFailureHa public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException { - log.warn("소셜 로그인 실패: 오류={}", exception.getMessage()); - response.sendRedirect(frontendUrl); } } diff --git a/src/main/java/doldol_server/doldol/auth/handler/CustomOAuth2SuccessHandler.java b/src/main/java/doldol_server/doldol/auth/handler/CustomOAuth2SuccessHandler.java index 03d56e15..607c91ba 100644 --- a/src/main/java/doldol_server/doldol/auth/handler/CustomOAuth2SuccessHandler.java +++ b/src/main/java/doldol_server/doldol/auth/handler/CustomOAuth2SuccessHandler.java @@ -17,9 +17,7 @@ import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -@Slf4j @Component @RequiredArgsConstructor public class CustomOAuth2SuccessHandler extends SimpleUrlAuthenticationSuccessHandler { @@ -63,8 +61,6 @@ private void handleNewSocialUser(HttpServletResponse response, String socialId, private void handleExistingUser(HttpServletResponse response, CustomUserDetails userDetails, String registrationId) throws IOException { - log.info("소셜 로그인 성공: userId={}, socialType={}, role={}", - userDetails.getUserId(), registrationId.toUpperCase(), userDetails.getRole()); String userid = String.valueOf(userDetails.getUserId()); diff --git a/src/main/java/doldol_server/doldol/auth/service/AuthService.java b/src/main/java/doldol_server/doldol/auth/service/AuthService.java index 79c9e1f1..cf9adde2 100644 --- a/src/main/java/doldol_server/doldol/auth/service/AuthService.java +++ b/src/main/java/doldol_server/doldol/auth/service/AuthService.java @@ -24,9 +24,7 @@ import doldol_server.doldol.user.service.UserService; import io.jsonwebtoken.Claims; import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -@Slf4j @Service @Transactional(readOnly = true) @RequiredArgsConstructor @@ -46,7 +44,6 @@ public void checkIdDuplicate(String id) { boolean isIdExists = userRepository.existsByLoginId(id); if (isIdExists) { - log.warn("아이디 중복 확인: 이미 존재하는 아이디={}", id); throw new CustomException(AuthErrorCode.ID_DUPLICATED); } } @@ -81,18 +78,15 @@ public void validateVerificationCode(String email, String code) { Object result = redisTemplate.opsForValue().get(email); if (result == null) { - log.warn("인증 코드 만료: email={}", email); throw new CustomException(AuthErrorCode.EMAIL_NOT_FOUND); } String verificationCode = result.toString(); if (!verificationCode.equals(code)) { - log.warn("인증 코드 불일치: email={}, 입력코드={}", email, code); throw new CustomException(AuthErrorCode.VERIFICATION_CODE_WRONG); } - log.info("이메일 인증 완료: email={}", email); redisTemplate.opsForValue().set(email, EMAIL_VERIFIED_KEY, 30, TimeUnit.MINUTES); } @@ -109,9 +103,6 @@ public void register(RegisterRequest registerRequest) { .build(); userRepository.save(user); - - log.info("자체 회원가입 완료: userId={}, email={}, name='{}'", - user.getId(), user.getEmail(), user.getName()); } @Transactional @@ -127,9 +118,6 @@ public void oauthRegister(OAuthRegisterRequest oAuthRegisterRequest) { .build(); userRepository.save(user); - - log.info("소셜 회원가입 완료: userId={}, email={}, socialType={}", - user.getId(), user.getEmail(), user.getSocialType()); } @Transactional @@ -151,8 +139,6 @@ public ReissueTokenResponse reissue(String refreshToken) { UserTokenResponse newTokens = tokenProvider.createLoginToken(userId, user.getRole().getRole()); - log.info("토큰 재발급 완료: userId={}", userId); - return ReissueTokenResponse .builder() .accessToken(newTokens.accessToken()) @@ -169,22 +155,14 @@ public void withdraw(Long userId) { } if (user.getSocialId() != null) { - try { - OAuth2ResponseStrategy strategy = oAuthSeperator.getStrategy(user.getSocialType().name()); - strategy.unlink(user.getSocialId()); - user.deleteOAuthInfo(); - } catch (Exception e) { - log.error("소셜 계정 연동 해제 실패: userId={}, socialType={}, 오류={}", - userId, user.getSocialType(), e.getMessage(), e); - } + OAuth2ResponseStrategy strategy = oAuthSeperator.getStrategy(user.getSocialType().name()); + strategy.unlink(user.getSocialId()); + user.deleteOAuthInfo(); } user.updateDeleteStatus(); tokenProvider.deleteRefreshToken(String.valueOf(userId)); - - log.info("소셜 계정 연동 해제: userId={}, socialType={}", - userId, user.getSocialType()); } public void validateUserInfo(String name, String email, String phone) { @@ -227,8 +205,6 @@ public void resetPassword(String email) { user.updateUserPassword(passwordEncoder.encode(tempPassword)); emailService.sendEmailTempPassword(email, tempPassword); - - log.info("비밀번호 재설정 완료: email={}, userId={}", email, user.getId()); } public void checkRegisterInfoDuplicate(String email, String phone) { @@ -236,13 +212,10 @@ public void checkRegisterInfoDuplicate(String email, String phone) { boolean existsByPhone = userRepository.existsByPhone(phone); if (existsByEmail && !existsByPhone) { - log.warn("이메일 중복: email={}", email); throw new CustomException(AuthErrorCode.EMAIl_DUPLICATED); } else if (!existsByEmail && existsByPhone) { - log.warn("전화번호 중복: phone={}", phone); throw new CustomException(AuthErrorCode.PHONE_DUPLICATED); } else if (existsByEmail && existsByPhone) { - log.warn("이메일/전화번호 모두 중복: email={}, phone={}", email, phone); throw new CustomException(AuthErrorCode.EMAIL_PHONE_DUPLICATED); } } diff --git a/src/main/java/doldol_server/doldol/auth/service/CustomOAuth2UserService.java b/src/main/java/doldol_server/doldol/auth/service/CustomOAuth2UserService.java index 2dd10064..1e997edd 100644 --- a/src/main/java/doldol_server/doldol/auth/service/CustomOAuth2UserService.java +++ b/src/main/java/doldol_server/doldol/auth/service/CustomOAuth2UserService.java @@ -20,9 +20,7 @@ import doldol_server.doldol.user.repository.UserRepository; import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -@Slf4j @Service @RequiredArgsConstructor public class CustomOAuth2UserService extends DefaultOAuth2UserService { @@ -53,8 +51,6 @@ public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2Authentic } else if (socialLinkedUser.isPresent() && socialLinkedUser.get().isDeleted()) { - log.warn("탈퇴한 계정으로 소셜 로그인 시도: socialId={}, socialType={}", - oAuth2Response.getSocialId(), registrationId); throw new CustomOAuth2Exception(AuthErrorCode.ALREADY_WITHDRAWN); } diff --git a/src/main/java/doldol_server/doldol/auth/service/EmailService.java b/src/main/java/doldol_server/doldol/auth/service/EmailService.java index 429e75c7..3cb8d8ca 100644 --- a/src/main/java/doldol_server/doldol/auth/service/EmailService.java +++ b/src/main/java/doldol_server/doldol/auth/service/EmailService.java @@ -14,9 +14,7 @@ import jakarta.mail.MessagingException; import jakarta.mail.internet.MimeMessage; import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -@Slf4j @Service @RequiredArgsConstructor public class EmailService { @@ -31,9 +29,7 @@ public void sendEmailVerificationCode(String email, String verificationCode) { } try { sendToEmailCode(email, verificationCode); - log.info("인증 코드 이메일 발송 완료: email={}", email); } catch (MessagingException e) { - log.error("인증 코드 이메일 발송 실패: email={}, 오류={}", email, e.getMessage(), e); throw new CustomException(MailErrorCode.EMAIL_SENDING_ERROR); } } @@ -45,9 +41,7 @@ public void sendEmailTempPassword(String email, String password) { } try { sendToEmailTempPassword(email, password); - log.info("임시 비밀번호 이메일 발송 완료: email={}", email); } catch (MessagingException e) { - log.error("임시 비밀번호 이메일 발송 실패: email={}, 오류={}", email, e.getMessage(), e); throw new CustomException(MailErrorCode.EMAIL_SENDING_ERROR); } } diff --git a/src/main/java/doldol_server/doldol/auth/util/ResponseUtil.java b/src/main/java/doldol_server/doldol/auth/util/ResponseUtil.java index d1a7fc63..57ee7a84 100644 --- a/src/main/java/doldol_server/doldol/auth/util/ResponseUtil.java +++ b/src/main/java/doldol_server/doldol/auth/util/ResponseUtil.java @@ -14,9 +14,7 @@ import jakarta.servlet.http.HttpServletResponse; import lombok.AccessLevel; import lombok.NoArgsConstructor; -import lombok.extern.slf4j.Slf4j; -@Slf4j @NoArgsConstructor(access = AccessLevel.PRIVATE) public class ResponseUtil { diff --git a/src/main/java/doldol_server/doldol/common/config/LoggingAspect.java b/src/main/java/doldol_server/doldol/common/config/LoggingAspect.java new file mode 100644 index 00000000..67ae693d --- /dev/null +++ b/src/main/java/doldol_server/doldol/common/config/LoggingAspect.java @@ -0,0 +1,94 @@ +package doldol_server.doldol.common.config; + +import java.io.IOException; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Map; + +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; +import org.springframework.web.util.ContentCachingRequestWrapper; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import jakarta.servlet.http.HttpServletRequest; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Aspect +@Component +public class LoggingAspect { + private final ObjectMapper objectMapper = new ObjectMapper(); + private static final String START_LOG = "================================================NEW===============================================\n"; + private static final String END_LOG = "================================================END===============================================\n"; + + @Pointcut("execution(* doldol_server.doldol.*.controller..*(..)) || ( execution(* doldol_server.doldol.common.exception..*(..)) && !execution(* doldol_server.doldol.common.exception.GlobalExceptionHandler.handle*(..)))") + public void controllerInfoLevelExecute() { + } + + @Pointcut("execution(* doldol_server.doldol.common.exception.GlobalExceptionHandler.handle*(..))") + public void controllerErrorLevelExecute() { + } + + @Around("doldol_server.doldol.common.config.LoggingAspect.controllerInfoLevelExecute()") + public Object requestInfoLevelLogging(ProceedingJoinPoint proceedingJoinPoint) throws Throwable { + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest(); + final ContentCachingRequestWrapper cachingRequest = (ContentCachingRequestWrapper) request; + long startAt = System.currentTimeMillis(); + Object returnValue = proceedingJoinPoint.proceed(proceedingJoinPoint.getArgs()); + long endAt = System.currentTimeMillis(); + + log.info(getCommunicationData(request, cachingRequest, startAt, endAt, returnValue)); + return returnValue; + } + + @Around("doldol_server.doldol.common.config.LoggingAspect.controllerErrorLevelExecute()") + public Object requestErrorLevelLogging(ProceedingJoinPoint proceedingJoinPoint) throws Throwable { + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest(); + final ContentCachingRequestWrapper cachingRequest = (ContentCachingRequestWrapper) request; + long startAt = System.currentTimeMillis(); + Object returnValue = proceedingJoinPoint.proceed(proceedingJoinPoint.getArgs()); + long endAt = System.currentTimeMillis(); + + log.error(getCommunicationData(request, cachingRequest, startAt, endAt, returnValue)); + return returnValue; + } + + private String getCommunicationData( + HttpServletRequest request, + ContentCachingRequestWrapper cachingRequest, + long startAt, + long endAt, + Object returnValue + ) throws IOException { + StringBuilder sb = new StringBuilder(); + + sb.append(START_LOG); + sb.append(String.format("====> Request: %s %s ({%d}ms)\n====> *Header = {%s}\n", request.getMethod(), request.getRequestURL(), endAt - startAt, getHeaders(request))); + sb.append("=================> content type is ").append(request.getContentType()).append("\n"); + if ("POST".equalsIgnoreCase(request.getMethod())) { + sb.append(String.format("====> application/json Body: {%s}\n", objectMapper.readTree(cachingRequest.getContentAsByteArray()))); + } + if (returnValue != null) { + sb.append(String.format("====> Response: {%s}\n", returnValue)); + } + sb.append(END_LOG); + return sb.toString(); + } + + private Map getHeaders(HttpServletRequest request) { + Map headerMap = new HashMap<>(); + + Enumeration headerArray = request.getHeaderNames(); + while (headerArray.hasMoreElements()) { + String headerName = headerArray.nextElement(); + headerMap.put(headerName, request.getHeader(headerName)); + } + return headerMap; + } +} diff --git a/src/main/java/doldol_server/doldol/common/exception/GlobalExceptionHandler.java b/src/main/java/doldol_server/doldol/common/exception/GlobalExceptionHandler.java index 2b20e01e..6664f0c2 100644 --- a/src/main/java/doldol_server/doldol/common/exception/GlobalExceptionHandler.java +++ b/src/main/java/doldol_server/doldol/common/exception/GlobalExceptionHandler.java @@ -17,9 +17,7 @@ import org.springframework.web.bind.MissingServletRequestParameterException; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice; -import lombok.extern.slf4j.Slf4j; -@Slf4j @RestControllerAdvice public class GlobalExceptionHandler { @@ -29,7 +27,6 @@ public class GlobalExceptionHandler { @ExceptionHandler(value = CustomException.class) public ResponseEntity> handleCustomException(CustomException e) { ErrorCode errorCode = e.getErrorCode(); - log.warn("커스텀 예외 발생: 코드={}, 메시지={}", errorCode.getCode(), e.getMessage()); return ResponseEntity.status(errorCode.getHttpStatus()) .body(ErrorResponse.error(errorCode.getCode(), e.getMessage())); @@ -48,7 +45,6 @@ protected ResponseEntity>> handleMethodArgumen errors.put(fieldError.getField(), fieldError.getDefaultMessage()); } - log.warn("유효성 검사 실패: 필드 오류={}", errors); CommonErrorCode errorCode = CommonErrorCode.INVALID_VALUE; return ResponseEntity.status(errorCode.getHttpStatus()) @@ -60,7 +56,6 @@ protected ResponseEntity>> handleMethodArgumen */ @ExceptionHandler(AuthenticationException.class) public ResponseEntity> handleAuthenticationException(AuthenticationException e) { - log.warn("인증 예외 발생: {}", e.getMessage()); AuthErrorCode errorCode = AuthErrorCode.INVALID_TOKEN; return ResponseEntity.status(errorCode.getHttpStatus()) @@ -72,7 +67,6 @@ public ResponseEntity> handleAuthenticationException(Authent */ @ExceptionHandler(AccessDeniedException.class) public ResponseEntity> handleAccessDeniedException(AccessDeniedException e) { - log.warn("접근 권한 없음: {}", e.getMessage()); AuthErrorCode errorCode = AuthErrorCode.ACCESS_DENIED; return ResponseEntity.status(errorCode.getHttpStatus()) @@ -84,7 +78,6 @@ public ResponseEntity> handleAccessDeniedException(AccessDen */ @ExceptionHandler(IllegalArgumentException.class) public ResponseEntity> handleIllegalArgumentException(IllegalArgumentException e) { - log.warn("잘못된 인자: {}", e.getMessage()); CommonErrorCode errorCode = CommonErrorCode.INVALID_ARGUMENT; return ResponseEntity.status(errorCode.getHttpStatus()) @@ -96,7 +89,6 @@ public ResponseEntity> handleIllegalArgumentException(Illega */ @ExceptionHandler(RuntimeException.class) public ResponseEntity> handleRuntimeException(RuntimeException e) { - log.error("런타임 예외 발생: {}", e.getMessage(), e); CommonErrorCode errorCode = CommonErrorCode.RUNTIME_ERROR; return ResponseEntity.status(errorCode.getHttpStatus()) @@ -108,7 +100,6 @@ public ResponseEntity> handleRuntimeException(RuntimeExcepti */ @ExceptionHandler(Exception.class) public ResponseEntity> handleGeneralException(Exception e) { - log.error("예상치 못한 예외 발생: {}", e.getMessage(), e); CommonErrorCode errorCode = CommonErrorCode.INTERNAL_SERVER_ERROR; return ResponseEntity.status(errorCode.getHttpStatus()) @@ -121,7 +112,6 @@ public ResponseEntity> handleGeneralException(Exception e) { @ExceptionHandler(MissingServletRequestParameterException.class) public ResponseEntity> handleMissingServletRequestParameterException( MissingServletRequestParameterException e) { - log.warn("필수 파라미터 누락: 파라미터={}, 타입={}", e.getParameterName(), e.getParameterType()); CommonErrorCode errorCode = CommonErrorCode.MISSING_PARAMETER; return ResponseEntity.status(errorCode.getHttpStatus()) @@ -133,7 +123,6 @@ public ResponseEntity> handleMissingServletRequestParameterE */ @ExceptionHandler(OAuth2UnlinkException.class) public ResponseEntity> handleOAuth2UnlinkException(OAuth2UnlinkException e) { - log.error("OAuth2 연동 해제 실패: 코드={}, 메시지={}", e.getErrorCode().getCode(), e.getMessage(), e); return ResponseEntity.status(e.getErrorCode().getHttpStatus()) .body(ErrorResponse.error(e.getErrorCode().getCode(), e.getMessage())); diff --git a/src/main/java/doldol_server/doldol/common/filter/HttpContentCacheFilter.java b/src/main/java/doldol_server/doldol/common/filter/HttpContentCacheFilter.java new file mode 100644 index 00000000..cb537044 --- /dev/null +++ b/src/main/java/doldol_server/doldol/common/filter/HttpContentCacheFilter.java @@ -0,0 +1,25 @@ +package doldol_server.doldol.common.filter; + +import java.io.IOException; + +import org.springframework.stereotype.Component; +import org.springframework.web.filter.OncePerRequestFilter; +import org.springframework.web.util.ContentCachingRequestWrapper; +import org.springframework.web.util.ContentCachingResponseWrapper; + +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; + +@Component +public class HttpContentCacheFilter extends OncePerRequestFilter { + @Override + protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { + ContentCachingRequestWrapper wrappingRequest = new ContentCachingRequestWrapper(request); + ContentCachingResponseWrapper wrappingResponse = new ContentCachingResponseWrapper(response); + + filterChain.doFilter(wrappingRequest, wrappingResponse); + wrappingResponse.copyBodyToResponse(); + } +} diff --git a/src/main/java/doldol_server/doldol/rollingPaper/service/MessageService.java b/src/main/java/doldol_server/doldol/rollingPaper/service/MessageService.java index a817c8b1..b7020524 100644 --- a/src/main/java/doldol_server/doldol/rollingPaper/service/MessageService.java +++ b/src/main/java/doldol_server/doldol/rollingPaper/service/MessageService.java @@ -25,9 +25,7 @@ import doldol_server.doldol.user.entity.User; import doldol_server.doldol.user.service.UserService; import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -@Slf4j @Service @Transactional(readOnly = true) @RequiredArgsConstructor @@ -42,7 +40,6 @@ public MessageResponse getMessage(Long messageId, Long userId) { MessageResponse message = messageRepository.getMessage(messageId, userId); if (message == null) { - log.warn("존재하지 않는 메시지 조회 시도: messageId={}, userId={}", messageId, userId); throw new CustomException(MessageErrorCode.MESSAGE_NOT_FOUND); } @@ -105,10 +102,6 @@ public void createMessage(CreateMessageRequest request, Long userId) { .build(); messageRepository.save(message); - - log.info("메시지 작성 완료: messageId={}, paperId={}, 발신자={}, 수신자={}, 글자수={}", - message.getId(), paper.getId(), userId, request.receiverId(), - request.content().length()); } @Transactional @@ -120,7 +113,6 @@ public void updateMessage(UpdateMessageRequest request, Long userId) { } conditionalUpdate(request, message); - log.info("메시지 수정 완료: messageId={}, 수정자={}", request.messageId(), userId); } @Transactional @@ -133,8 +125,6 @@ public void deleteMessage(DeleteMessageRequest request, Long userId) { } message.updateDeleteStatus(); - - log.info("메시지 삭제 완료: messageId={}, 삭제자={}", request.messageId(), userId); } private Long getReceivedMessageCounts(Long paperId, Long userId) { @@ -165,8 +155,6 @@ private MessageResponse decryptMessageContent(MessageResponse messageResponse) { String decryptedContent = encryptor.decrypt(messageResponse.content()); return messageResponse.withDecryptedContent(decryptedContent); } catch (Exception e) { - log.error("메시지 복호화 실패: messageId={}, 오류={}", - messageResponse.messageId(), e.getMessage(), e); return messageResponse.withDecryptedContent("메시지 내용을 불러올 수 없습니다."); } } @@ -175,8 +163,6 @@ private void validateMessageCount(Paper paper, User fromUser, User toUser) { long messageCount = messageRepository.countByPaperAndFromAndToAndIsDeletedFalse( paper, fromUser, toUser); if (messageCount >= 5) { - log.warn("메시지 작성 제한 도달: paperId={}, 발신자={}, 수신자={}, 현재개수={}", - paper.getId(), fromUser.getId(), toUser.getId(), messageCount); throw new CustomException(MessageErrorCode.MESSAGE_LIMIT_EXCEEDED); } } diff --git a/src/main/java/doldol_server/doldol/rollingPaper/service/PaperService.java b/src/main/java/doldol_server/doldol/rollingPaper/service/PaperService.java index cadd6427..f56602e1 100644 --- a/src/main/java/doldol_server/doldol/rollingPaper/service/PaperService.java +++ b/src/main/java/doldol_server/doldol/rollingPaper/service/PaperService.java @@ -22,9 +22,7 @@ import doldol_server.doldol.rollingPaper.entity.Participant; import doldol_server.doldol.rollingPaper.repository.PaperRepository; import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -@Slf4j @Service @Transactional(readOnly = true) @RequiredArgsConstructor @@ -46,9 +44,6 @@ public CreatePaperResponse createPaper(PaperRequest request, Long userId) { participantService.addUser(userId, paper, true); - log.info("롤링페이퍼 생성 완료: paperId={}, 제목='{}', 생성자={}, 공개날짜={}", - paper.getId(), paper.getName(), userId, paper.getOpenDate()); - return CreatePaperResponse.of(paper); } @@ -64,9 +59,6 @@ public void joinPaper(JoinPaperRequest request, Long userId) { participantService.validateJoinable(userId, paper.getId()); participantService.addUser(userId, paper, false); - - log.info("롤링페이퍼 참여 완료: paperId={}, 참여자={}, 제목='{}'", - paper.getId(), userId, paper.getName()); } public PaperListResponse getMyRollingPapers(CursorPageRequest request, @@ -91,9 +83,6 @@ private String createInvitationCode() { private Paper getByInvitationCode(String invitationCode) { return paperRepository.findByInvitationCode(invitationCode) - .orElseThrow(() -> { - log.warn("유효하지 않은 초대 코드로 접근: invitationCode={}", invitationCode); - return new CustomException(PAPER_NOT_FOUND); - }); + .orElseThrow(() -> new CustomException(PAPER_NOT_FOUND)); } } diff --git a/src/main/java/doldol_server/doldol/rollingPaper/service/ParticipantService.java b/src/main/java/doldol_server/doldol/rollingPaper/service/ParticipantService.java index a72b4aa7..470d6fa2 100644 --- a/src/main/java/doldol_server/doldol/rollingPaper/service/ParticipantService.java +++ b/src/main/java/doldol_server/doldol/rollingPaper/service/ParticipantService.java @@ -17,12 +17,10 @@ import doldol_server.doldol.rollingPaper.repository.ParticipantRepository; import doldol_server.doldol.user.service.UserService; import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; @Service @Transactional(readOnly = true) @RequiredArgsConstructor -@Slf4j public class ParticipantService { private final ParticipantRepository participantRepository; @@ -38,9 +36,6 @@ public void addUser(Long userId, Paper paper, boolean isMaster) { paper.addParticipant(); participantRepository.save(participant); - - log.info("참여자 추가 완료: paperId={}, userId={}, 마스터여부={}", - paper.getId(), userId, isMaster); } public CursorPage getParticipants(Long paperId, @@ -78,14 +73,12 @@ public void validateJoinable(Long userId, Long paperId) { private void alreadyExistUser(Long userId, List participants) { if (participants.stream().anyMatch(participant -> participant.getUser().getId().equals(userId))) { - log.warn("이미 참여 중인 사용자의 중복 참여 시도: userId={}", userId); throw new CustomException(PARTICIPANT_ALREADY_EXIST); } } private void existPaper(List participants) { if (participants.isEmpty()) { - log.warn("존재하지 않는 롤링페이퍼 접근 시도"); throw new CustomException(PAPER_NOT_FOUND); } } diff --git a/src/main/java/doldol_server/doldol/user/service/UserService.java b/src/main/java/doldol_server/doldol/user/service/UserService.java index 4b919480..bd414e4d 100644 --- a/src/main/java/doldol_server/doldol/user/service/UserService.java +++ b/src/main/java/doldol_server/doldol/user/service/UserService.java @@ -11,9 +11,7 @@ import doldol_server.doldol.user.entity.User; import doldol_server.doldol.user.repository.UserRepository; import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -@Slf4j @Service @Transactional(readOnly = true) @RequiredArgsConstructor @@ -25,8 +23,7 @@ public class UserService { public User getById(Long userId) { return userRepository.findById(userId) .orElseThrow(() -> { - log.warn("존재하지 않는 사용자 조회 시도: userId={}", userId); - return new CustomException(UserErrorCode.USER_NOT_FOUND); + return new CustomException(UserErrorCode.USER_NOT_FOUND); }); } @@ -34,26 +31,11 @@ public User getById(Long userId) { public void changeInfo(UpdateUserInfoRequest request, Long userId) { User user = getById(userId); - boolean nameUpdated = false; - boolean passwordUpdated = false; - if (request.name() != null) { user.updateUserName(request.name()); - nameUpdated = true; } if (request.password() != null) { user.updateUserPassword(passwordEncoder.encode(request.password())); - passwordUpdated = true; - } - - if (nameUpdated && passwordUpdated) { - log.info("사용자 정보 수정 완료: userId={}, 수정항목=이름+비밀번호", userId); - } else if (nameUpdated) { - log.info("사용자 정보 수정 완료: userId={}, 수정항목=이름", userId); - } else if (passwordUpdated) { - log.info("사용자 정보 수정 완료: userId={}, 수정항목=비밀번호", userId); - } else { - log.warn("사용자 정보 수정 요청했으나 변경사항 없음: userId={}", userId); } } diff --git a/src/main/resources/config b/src/main/resources/config index 9ea556cf..6b657e41 160000 --- a/src/main/resources/config +++ b/src/main/resources/config @@ -1 +1 @@ -Subproject commit 9ea556cfd141817ae26515f8c321173eee7e483c +Subproject commit 6b657e41f6516bc7626358e252a70050ab2920f3 diff --git a/src/main/resources/logback-spring.xml b/src/main/resources/logback-spring.xml index 530d03db..82cf9fe3 100644 --- a/src/main/resources/logback-spring.xml +++ b/src/main/resources/logback-spring.xml @@ -1,15 +1,11 @@ - - - - + - @@ -17,7 +13,6 @@ - @@ -30,7 +25,6 @@ - @@ -39,8 +33,7 @@ - - + \ No newline at end of file diff --git a/src/main/resources/slack-dev-appender.xml b/src/main/resources/slack-dev-appender.xml index de6dca20..b42f8227 100644 --- a/src/main/resources/slack-dev-appender.xml +++ b/src/main/resources/slack-dev-appender.xml @@ -15,11 +15,15 @@ - - INFO + + + level == INFO || level == ERROR + + ACCEPT + DENY 0 - 512 + 256 false \ No newline at end of file diff --git a/src/main/resources/slack-prod-appender.xml b/src/main/resources/slack-prod-appender.xml index ea8e5896..6c713e85 100644 --- a/src/main/resources/slack-prod-appender.xml +++ b/src/main/resources/slack-prod-appender.xml @@ -1,60 +1,29 @@ - - - ${SLACK_PROD_WARN_WEBHOOK_URI} - #be-prod-warn-log - doldol-prod-warn - :warning: - true - - - WARNING %d{HH:mm:ss} %logger{20} - %msg - - - false - - - - - ${SLACK_PROD_ERROR_WEBHOOK_URI} - #be-prod-error-log - doldol-prod-error + + ${SLACK_PROD_WEBHOOK_URI} + #be-prod-log + doldol-prod :rotating_light: true - CRITICAL ERROR - Server: doldol-prod - Time: %d{yyyy-MM-dd HH:mm:ss} - Thread: %thread - Logger: %logger{36} - Message: %msg + [%level] %d{HH:mm:ss} %logger{20} - %msg - true - Production Error - Immediate Action Required - danger - PRODUCTION ERROR ALERT + false - - - - - WARN + + + + + level == INFO || level == ERROR + ACCEPT DENY - 20 + 0 256 false - - - - - - ERROR - ACCEPT - DENY - - 0 - 128 - true - - \ No newline at end of file +