diff --git a/.gitignore b/.gitignore index 55608a8..c1d7d74 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ HELP.md .gradle +logs/ build/ !gradle/wrapper/gradle-wrapper.jar !**/src/main/**/build/ diff --git a/build.gradle b/build.gradle index 3355b9c..de9c216 100644 --- a/build.gradle +++ b/build.gradle @@ -29,6 +29,7 @@ dependencies { implementation 'org.springframework.boot:spring-boot-starter-validation' implementation 'org.springframework.boot:spring-boot-starter-security' implementation 'org.springframework.boot:spring-boot-starter-jdbc' + implementation 'org.springframework.boot:spring-boot-starter-aop' implementation 'com.mysql:mysql-connector-j' implementation 'io.github.cdimascio:java-dotenv:5.2.2' implementation 'io.jsonwebtoken:jjwt-api:0.11.5' diff --git a/src/main/java/com/kert/Application.java b/src/main/java/com/kert/Application.java index a76573d..c010d49 100644 --- a/src/main/java/com/kert/Application.java +++ b/src/main/java/com/kert/Application.java @@ -2,12 +2,13 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.EnableAspectJAutoProxy; import org.springframework.data.jpa.repository.config.EnableJpaAuditing; @SpringBootApplication @EnableJpaAuditing +@EnableAspectJAutoProxy public class Application { - public static void main(String[] args) { SpringApplication.run(Application.class, args); } diff --git a/src/main/java/com/kert/config/LoggingAspect.java b/src/main/java/com/kert/config/LoggingAspect.java new file mode 100644 index 0000000..ba4792f --- /dev/null +++ b/src/main/java/com/kert/config/LoggingAspect.java @@ -0,0 +1,53 @@ +package com.kert.config; + +import org.aspectj.lang.annotation.AfterThrowing; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Before; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.stereotype.Component; +import jakarta.servlet.http.HttpServletRequest; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +@Aspect +@Component +public class LoggingAspect { + + + + private static final Logger logger = LoggerFactory.getLogger(LoggingAspect.class); + + @Pointcut("within(@org.springframework.web.bind.annotation.RestController *) || within(@org.springframework.stereotype.Controller *)") + public void controllerMethods() {} + + + @Before("controllerMethods()") + public void logBeforeRequest() { + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest(); + String clientIp = getClientIpAddress(request); + String uri = request.getRequestURI(); + String method = request.getMethod(); + logger.info("Request - Method: {}, URI: {}, Client IP: {}", method, uri, clientIp); + } + + @AfterThrowing(pointcut = "controllerMethods()", throwing = "exception") + public void logAfterThrowing(Exception exception) { + logger.error("An error occurred: {}", exception.getMessage()); + } + + // 클라이언트 IP를 확인하는 메서드 + private String getClientIpAddress(HttpServletRequest request) { + String clientIp = request.getHeader("X-Forwarded-For"); + if (clientIp == null || clientIp.isEmpty() || "unknown".equalsIgnoreCase(clientIp)) { + clientIp = request.getHeader("X-Real-IP"); + } + if (clientIp == null || clientIp.isEmpty() || "unknown".equalsIgnoreCase(clientIp)) { + clientIp = request.getRemoteAddr(); + } else { + clientIp = clientIp.split(",")[0]; // 여러 IP 값이 있을 경우 첫 번째 값만 사용 + } + return clientIp; + } +} \ No newline at end of file diff --git a/src/main/java/com/kert/controller/PostController.java b/src/main/java/com/kert/controller/PostController.java index 6b81ad8..58155c5 100644 --- a/src/main/java/com/kert/controller/PostController.java +++ b/src/main/java/com/kert/controller/PostController.java @@ -27,7 +27,7 @@ public ResponseEntity> getPosts( @RequestParam(defaultValue = "1") int page, @RequestParam(defaultValue = "10") int size) { - Page posts = postService.searchPosts(search, page, size); + Page posts = postService.searchPosts(search, page -1, size); return ResponseEntity.ok(posts); } diff --git a/src/main/java/com/kert/service/PostService.java b/src/main/java/com/kert/service/PostService.java index 8430799..038a326 100644 --- a/src/main/java/com/kert/service/PostService.java +++ b/src/main/java/com/kert/service/PostService.java @@ -41,7 +41,7 @@ private String extractTokenFromRequest(HttpServletRequest request) { public Page searchPosts(String search, int page, int size) { Pageable pageable = PageRequest.of(page, size); - if (search != null && !search.isEmpty()) { + if (search != null && !search.trim().isEmpty()) { return postRepository.findByTitleContainingOrTagContaining(search, search, pageable); } else { return postRepository.findAll(pageable); diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index f52d747..93610c2 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -10,4 +10,16 @@ spring.datasource.password=${MYSQL_ROOT_PASSWORD} spring.jpa.hibernate.ddl-auto=update spring.jpa.show-sql=true -spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQLDialect \ No newline at end of file +spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQLDialect + +# log level +logging.level.root=INFO +logging.level.com.kert.config.LoggingAspect=INFO + +# log path +logging.file.name=logs/application.log +logging.file.path=logs + +# log pattern +logging.pattern.console=%d{yyyy-MM-dd HH:mm:ss} - %msg%n +logging.pattern.file=%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n \ No newline at end of file