본문 바로가기

전체 글

(72)
Webflux를 이용한 응답 시간 단축 - 삽질중인 개발자 빅데이터 분석 서비스를 운영하면서 분석 API는 분석 조건에 따라 내부 API를 N개 호출하여 각 응답 값을 조합해 하나의 응답으로 반환하는 API형태로 운영이 되고 있었다. 기존에는 문제없이 동작하던 코드가 운영 정책의 변경으로 분석 조건 중 하나인 최대 분석 가능한 기간을 늘리면서 분석 요청에 대한 응답 시간이 너무 길어지는 문제가 발생하기 시작했다. 우선 이 문제를 파악하기 위해서 디버깅을 해본 결과 각각의 응답 속도가 다른 N개의 요청이 순차적으로 처리되면서 전체적으로 응답이 느려지고 있었다. ( ex) 5개의 API를 내부에서 호출하는데 1초, 5초, 10초, 15초, 4초가 걸린다고 가정하면 순차적인 처리로 인해 전체적으로는 35초가 걸린다 ) 이에 따라 사용자 입장에서 대기 시간이 너무 길어..
Transactional Outbox Pattern 을 이용한 로직 처리 - 삽질중인 개발자 구독형 서비스를 운영하는 과정에서 운영 비용 상승으로 인해 구독 서비스 요금 인상을 해야 하는 상황이 발생했다. 자연스러운 요금제 변경을 유도하기 위하여 정해진 정책은 다음과 같다 1. 적용 대상 - 현재 구독형 요금제를 사용 중인 고객2. 정책 내용 - 요금제 인상 사전 안내 및 동의 여부 확인 3. 적용 시나리오 - 동의한 경우 : 다음 정기 결제부터 인상된 요금 적용 & 사내 타 서비스의 기간제 이용권 추가 지급 - 미동의한 경우 : 다음 정기 결제일을 기준으로 구독 자동 해지 우선, 해당 기능을 구현하기 위해 필요한 사항을 정리해 보았다. 첫 번째로 요금제 인상에 대한 동의 여부 확인 폼을 구현을 해야 하는데 이 부분은 기존에 구현해서 사용 중인 서비스 중 설문 관련 서비스를 재사용..
분산 환경에서의 로깅 - 삽질중인 개발자 현재 운영 중인 서비스의 초기에는 하나의 서비스 내에서 모든 요청에 대한 처리를 할 수 있었지만 비즈니스가 복잡해지면서 각 서비스 간 연동이 많아졌고 그에 따라 로직 흐름을 파악하거나 장애 원인을 추적하기 위해 로깅의 중요성이 커졌다. 기존에 적용된 추적을 위한 로깅을 구현한 방식은 클라이언트로부터 요청이 Gateway에 들어오면 Gateway의 필터를 통해 x-transaction-id 헤더의 존재 여부를 확인한 후 해당 헤더가 없을 경우 새로 생성하여 요청에 추가하고 이미 존재하는 경우에는 그대로 요청을 전달한 이후 각 마이크로서비스에서는 이 헤더를 필터를 통해 MDC에 저장하여 로깅 시 트랜잭션 ID가 함께 출력되도록 구성해서 이슈에 대해서 추적을 하고 있었다. 위에서 구성한 방식으로는 단 한 번의..
MariaDB 모든 날짜 생성하기 - 삽질중인 개발자 - WITH RECURSIVE 구문을 사용하여 모든 날짜 데이터를 생성하는 방법 - MariaDB에서 더미용 모든 날짜를 생성하는 방법에 대해서 포스팅한다. WITH RECURSIVE 구문을 사용하여 데이터를 생성하는 건데 MariaDB 10.2.1 부터 WITH RECURSIVE 구문을 사용 할 수 있다 더미 데이터를 생성하는 SQL은 아래와 같은 형태이다. WITH RECURSIVE DT_TABLE AS ( SELECT ${시작일} dt, 1 lv FROM dual UNION all SELECT DATE_ADD('2020-09-12 00:00:00', INTERVAL DT_TABLE.lv ${시간/일 단위}) dt, DT_TABLE.lv+1 AS lv FROM DT_TABLE WHERE DT_TABL..
JPA N+1 문제 해결 방법 및 실무 적용 팁 - 삽질중인 개발자 - JPA N+1 문제 및 해결 방법 - JPA를 사용하다 보면 의도하지 않았지만 여러 번의 select 문이 순식간에 여러 개가 나가는 현상을 본 적이 있을 것이다. 이러한 현상을 N+1문제라고 부른다. 해당 포스트에서는 N+1 문제가 왜 발생하게 되는지와 해결 방법 및 실무에서 어떤 식으로 적용을 해야 하는지에 대하여 설명을 할 것이다. N+1 문제란? 연관 관계가 설정된 엔티티를 조회할 경우에 조회된 데이터 갯수(n) 만큼 연관관계의 조회 쿼리가 추가로 발생하여 데이터를 읽어오는 현상 현상 재현 DB 구조는 유저(USER)는 한개의 팀(TEAM)에만 속할 수 있고 팀(TEAM) 하나는 여러 명의 유저(USER)가 가입할 수 있다. 테스트 데이터로는 4개의 팀당 유저 4명씩 총 20명의 유저를 추가했..
Spring Security - AnonymousAuthenticationFilter란 - AnonymousAuthenticationFilter 란 - 스프링 시큐리티에서 AnonymousAuthenticationFilter는 익명 사용자의 요청에 대해 처리해주는 필터로 인증을 하지 않은 요청인 경우 인증 객체를 익명 권한이 들어가 있는 객체를 만들어 SecurityContextHolder에 넣어 주는 역할을 한다. 기본적으로 스프링 시큐리티 필터에 포함이 되어 있는 필터이며 만들어지는 객체는 아래와 같은 값을 가지고 있다. pricial : anonymousUser authorities : ROLE_ANONYMOUS // 기본 생성자 public AnonymousAuthenticationFilter(String key) { this(key, "anonymousUser", Authority..
Spring Security - RememberMeAuthenticationFilter 란 - RememberMeAuthenticationFilter 란 - 스프링 시큐리티에서는 RememberMe라는 기능을 지원해준다. 이 RememberMe라는 기능은 세션이 만료된 뒤에도 서버에서 클라이언트의 인증 값을 기억하고 있어 주는 기능이다. 보통 cookie에 Remember Me 기능을 해줄 수 있는 특정한 쿠키 키-값을 세팅해서 구현을 한다. 이 복잡한 과정을 시큐리티에서는 간단한 설정으로 제공을 해주며 해당 기능을 사용하기 위해서는 해당 기능을 아래와 같은 형태로 활성화시켜야 한다. @Override protected void configure(HttpSecurity http) throws Exception { http.formLogin(); http.rememberMe(); } 위와 같이 ..
Spring Security - LogoutFilter 란 - LogoutFilter 란- LogoutFilter란 로그아웃에 대한 처리를 담당하는 필터로 사용자가 로그아웃 요청을 했을 경우에만 적용되는 필터이다. LogoutFilter는 세션 무효화, 인증 토큰 삭제, SecurityContext에서 해당 토큰 삭제, 쿠키 삭제 및 로그인 페이지로 리다이렉트를 시켜주는 기능이 있다. LogoutFilter의 필터 기능이 구현된 코드를 보면 아래와 같다. private void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException { if (this.requiresLogout(request, res..