CustomUserDetailService를 구현하다가 유저가 없는 경우에 UsernameNotFoundException을 던지게끔 처리했다. 그런데 계속 BadCredentialsException이 발생하는 것이 아닌가. 디버깅을 해보니 DaoAuthenticationProvider에서 UsernameNotFoundException를 핸들링할 때 mitigateAgainstTimingAttack이라는 메서드를 호출하고 있고, 그 후에 BadCredentialsException 으로 예외를 랩핑하는 식으로 처리하고 있었다. mitigateAgainstTimingAttack 메서드는 왜 실행하는 걸까? DaoAuthenticationProvider.java ... catch (UsernameNotFound..
Spring
이 글은 실시간 알림 기능을 구현하기 위해 풀링, 웹소켓, SSE 중에 어떤 방법이 가장 적절한지 비교하는 포스팅입니다. 요구사항은 서버에서 클라이언트에게 실시간 알림을 전송할 수 있으면 됩니다. 웹소켓은 하나의 TCP 접속에 전이중 통신(양방향 통신) 채널을 제공하는 컴퓨터 통신 프로토콜입니다. 웹소켓은 HTTP 포트 80과 443 위에 동작하도록 설계되었으며 HTTP 프록시 및 중간 층을 지원하도록 설계되었으므로 HTTP 프로토콜과 호환이 됩니다. 또한 HTTP 폴링과 같은 반이중방식에 비해 더 낮은 부하를 사용하고 서버와 클라이언트 간의 실시간 데이터 전송을 가능하게 합니다. 웹소켓 프로토콜을 사용하기 위해 웹소켓 핸드셰이크에서 HTTP 업그레이드 헤더를 사용하여 HTTP 프로토콜에서 웹소켓 프로토..
프로젝트 진행 중 로깅을 하고 로그를 저장할 방법이 필요했습니다. Spring의 인터셉터를 이용하여 로깅을 구현하였고 ThreadLocal을 통해서 트랜젝션 아이디를 기록했습니다. 먼저 인터셉터입니다. @Slf4j public class RequestInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { String uuid = UUID.randomUUID().toString(); // (1) String requestURI = request.getMeth..
1. Line Coverage 코드의 각 라인이 테스트 코드에 의해 검증되었는지 확인하는 커버리지이다. 2. Branch Coverage 코드의 각 분기문이 테스트 코드에 의해 검증되었는지 확인하는 커버리지이다. 3. Condition Coverage 코드에 각 조건문의 내부 조건문이 테스트 코드에 의해 true/false 인 경우가 모두 검증되었는지 확인하는 커버리지이다. 4. Decision Coverage 코드에 모든 조건문이 테스트 코드에 의해 true/false 인 경우가 모두 검증되었는지 확인하는 커버리지이다. 5. 가장 많이 사용되는 것은 Line Coverage 라인 커버리지를 사용하면 모든 시나리오를 테스트할 수 있다는 보장은 없지만 모든 코드를 검증해 볼 수 있다는 장점이 있다. 따라서..
준비 - 실행 - 검증 given-when-then given-when-then 패턴은 테스트 코드를 준비-실행-검증 세 단계로 나누는 패턴을 말한다. 예시 코드는 다음과 같다. given에서 테스트를 준비하고, when에서 검증하고자 하는 메서드를 호출하고, then에서 호출 결과를 검증한다. 너무나 간단하기 때문에 더 설명할 것도 없다. 사실 테스트 코드를 작성하기 전에 더 중요한 것은 어떻게 테스트하기 좋은 메서드를 작성하느냐 인 것 같다. 엔터프라이즈급 서비스는 비즈니스 로직이 굉장히 복잡할 수 있고, 메서드의 복잡도가 증가할 확률이 높을 것이다. 그때 테스트하기 좋은 코드로 잘 짜는 능력이 필요할 것이라고 생각한다. 그럼 테스트하기 좋은 코드(메서드)는 뭔데? 조심스럽게 내(초짜) 생각을 말해보..
Spring Security의 Form Login의 기본적인 사용과 동시성 세션 제어 이슈 해결을 함께 다루어 보았다. 시큐리티 설정하기 코드가 길기 때문에 나누어서 살펴보자. configure가 핵심적인 설정을 맡고 있다고 보면 좋을 것 같다. @Configuration @EnableWebSecurity(debug = true) public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http .sessionManagement() .invalidSessionUrl("/auth/invalid-session") .m..