LoggingFilter
<aside>
package lh.h.config;
import java.io.IOException;
import jakarta.servlet.Filter;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.http.HttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
@Component
public class LoggingFilter implements Filter {
private static final Logger logger = LoggerFactory.getLogger(LoggingFilter.class);
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
// 1. 공인 IP (X-Forwarded-For)
String publicIp = req.getHeader("X-Forwarded-For");
if (publicIp == null || publicIp.isEmpty() || "unknown".equalsIgnoreCase(publicIp)) {
publicIp = req.getHeader("X-Real-IP"); // Nginx가 설정한 공인 IP
}
if (publicIp != null && publicIp.contains(",")) {
publicIp = publicIp.split(",")[0].trim(); // 여러 개일 경우 첫 번째 (공인 IP)
}
// 2. 내부 IP (Local IP)
String privateIp = req.getRemoteAddr();
// 요청 URL과 함께 IP 로그 기록
logger.info("Client Public IP: {}, Client Private IP: {}, Requested URL: {}",
publicIp, privateIp, req.getRequestURI());
chain.doFilter(request, response);
}
}
</aside>
logback-spring.xml
<aside>
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!-- 콘솔에 로그 출력 -->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - [PublicIP: %msg] [PrivateIP: %msg]%n</pattern>
</encoder>
</appender>
<!-- 로그를 파일에 저장 -->
<appender name="fileAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>logs/ip-requests.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>logs/ip-requests-%d{yyyy-MM-dd}.log</fileNamePattern>
<maxHistory>30</maxHistory> <!-- 30일간 로그 보관 -->
<totalSizeCap>100MB</totalSizeCap> <!-- 전체 로그 용량 제한 -->
</rollingPolicy>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - [PublicIP: %msg] [PrivateIP: %msg]%n</pattern>
</encoder>
</appender>
<!-- LoggingFilter 로그만 별도 파일에 저장 -->
<logger name="lh.h.config.LoggingFilter" level="INFO" additivity="false">
<appender-ref ref="fileAppender"/>
</logger>
<!-- 전체 애플리케이션 로그 설정 -->
<root level="INFO">
<appender-ref ref="console"/>
<appender-ref ref="fileAppender"/>
</root>
</configuration>
</aside>
/etc/nginx/sites-available/default
<aside>
location / {
proxy_pass <http://localhost:8083>; # 내부 애플리케이션 주소
proxy_http_version 1.1;
# 클라이언트의 실제 IP 전달
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
</aside>
/build/libs
<aside>
1. mkdir logs
2. chmod 777 logs
</aside>