기술 블로그 모음
국내 IT 기업들의 기술 블로그 글을 한 곳에서 모아보세요
들어가며 안녕하세요. Auth & Account Dev 팀의 김은찬, 김종민, 권기범, 정의엽, 허원영입니다. Auth & Account Dev 팀은 LY Corporation 그...
목차 소개 개선 목적 차량재배치 설명 카프카 스프링으로 변경된 아키텍처 및 코드 설명 4.1. 기존 코드 설명 4.2. 책임분리 테스트코드 작성 리팩터링과 전략패턴 마무리 1. 소개 안녕하세요. 쏘카 서비스 엔지니어링본부 애셋(Asset)팀 백엔드 개발자 원스톤입니다. 저는 쏘카 존과 차량 도메인을 개발하고 있습니다. 지속 성장하는 소프트웨어를 만들기...
들어가며 안녕하세요. UIT 팀 윤혜린입니다. LY Corporation Group에서는 헤드리스 CMS인 LandPress Content를 사내 임직원 대상으로 운영하고 있습니다...
안녕하세요. 네이버페이 회원&인증BE 의 최용화입니다.Spring Security는 강력한 보안 프레임워크로서, 애플리케이션의 인증과 인가 과정을 효율적으로 관리합니다. 저희 팀에서는 다음과 같은 기능을 구현하는 데에 Spring Security 를 사용하고 있습니다.인증 여부 확인 (인증이 안된 사용자일 경우 로그인 및 가입 유도 / 인증이 완료된 사용자일 경우 적절한 권한 부여), 권한을 이용한 접근 제어(권한이 없는 사용자일 경우 권한 획득을 위한 절차 수행), 보안 공격으로부터 보호(CSRF 공격 방지), PC / MOBILE 최적화 페이지 제공(사용자가 접근한 환경을 파악하여 최적화된 페이지 제공)이 글에서는 Spring Security의 인증(Authentication) 과정 전반을 살펴보고, 각 단계의 역할과 작동 방식을 자세히 알아보겠습니다.이 글은 Spring Security 6.3.0 공식문서를 기반으로 작성되었습니다.Spring Security 의 Filter 기반 동작 방식 이해Spring Security의 인증 수행을 이해하려면 Spring Security 의 구조에 대한 이해가 선행되어야 합니다. Spring Security는 Servlet Filter 기반으로 동작합니다. 여기서, 중요한 개념인 FilterChainProxy, SecurityFilterChain, 보안 필터(Security Filter)에 대해 알아봅니다.FilterChainProxy의 개념FilterChainProxy는 Spring Security에서 제공하는 특수한 Filter로 SecurityFilterChain을 사용하여 다양한 보안 필터가 동작하게 합니다.사실, Servlet Container의 라이프사이클과 Spring의 ApplicationContext 사이를 연결하는 DelegatingFilterProxy 라는 필터 구현체도 중요한 상위 개념이나 이 글에서는 설명을 생략합니다. 자세한 설명은 이 페이지를 참고하세요.SecurityFilterChain의 개념SecurityFilterChain은 Spring Security에서 보안 필터(Security Filter)의 체인을 정의하는 데 사용됩니다. 요청이 애플리케이션의 Servlet에 도달하기 전에 다양한 보안 검사를 수행하는 필터들이 있으며, 이를 보안 필터라고 부릅니다. SecurityFilterChain은 각 보안 필터가 순차적으로 실행되도록 하여 애플리케이션의 보안 설정을 체계적으로 관리할 수 있게 합니다.보안 필터(Security Filter)의 주요 기능SecurityFilterChain 에 선언된 다양한 보안 필터를 통해 아래의 기능을 수행하게 됩니다.인증(Authentication): 사용자의 신원을 확인합니다. 예를 들어, 사용자가 로그인 폼을 제출하면, 이를 처리하는 필터가 실행됩니다.인가(Authorization): 사용자가 요청한 리소스에 접근할 권한이 있는지 확인합니다.각종 보안 공격으로부터 보호(Protection Against Exploits): CSRF 공격, Session Fixation 공격, sniffing 공격, Clickjacking 등의 보안 공격으로부터 보호합니다.세션 관리: 사용자의 세션을 생성, 관리, 종료하는 과정입니다.기타 기능: HTTP 응답 헤더를 설정하여 보안을 강화하는 기능, Remember Me 기능 등을 지원합니다.보안 필터(Security Filter) 소개여러 개의 보안 필터가 있지만, 이 글에서 자주 보게 될 몇 가지 보안 필터만 가볍게 소개 드리려고 합니다. 나열된 순서대로 실행됩니다.UsernamePasswordAuthenticationFilter: 폼 기반 로그인 처리를 수행합니다.DefaultLoginPageGeneratingFilter: 기본 로그인 페이지를 생성합니다.ExceptionTranslationFilter: ExceptionTranslationFilter 의 다음 Filter 에서 발생한 Exception을 처리하고 이에 대한 적절한 응답을 반환합니다.AuthorizationFilter: 사용자가 요청한 리소스에 대해 접근 권한이 있는지 확인합니다. 권한이 없는 경우 접근을 거부하고, 적절한 에러 페이지를 반환하거나 예외를 발생시킵니다.Spring Security의 Form 기반 인증인증(Authentication)은 특정 리소스에 액세스하려는 주체(Principal)의 신원을 확인하는 과정입니다. Spring Security는 다양한 인증 방법을 지원하며, 이 글에서는 주로 폼 기반 인증(Form-Based Authentication)을 예로 들어 설명하겠습니다.인증 관련 주요 용어Spring Security 인증과 관련하여 자주 사용되는 용어에 대해 설명합니다.SecurityContextHolder: Spring Security가 인증된 사용자의 정보를 저장하는 곳입니다.SecurityContext: SecurityContextHolder에서 가져오며 현재 인증된 사용자의 인증정보(Authentication)를 포함합니다.Authentication: 사용자가 입력한 자격 증명(Pricipal과 Credentials)을 AuthenticationManager에 전달하는 용도로 사용되거나 SecurityContext에서 현재 사용자를 나타내는 용도로 사용되는 객체입니다.GrantedAuthority(Authorities): 인증된 사용자에게 부여된 권한을 나타내며, 역할(role)이나 범위(scope) 등을 포함합니다.AuthenticationManager: Spring Security의 필터가 인증을 수행하는 방법을 정의한 API(인터페이스)입니다.ProviderManager: AuthenticationManager 의 구현체입니다.AuthenticationProvider: ProviderManager가 여러 종류의 인증(Basic 인증, Form 인증 등)을 지원 및 수행하기 위해 사용하는 인터페이스입니다. 하나의 ProviderManager에 여러 개의 AuthenticationProvider를 등록하여 사용할 수 있습니다. 가장 흔히 사용되는 구현체는 DaoAuthenticationProvider입니다.Form 기반 인증 수행 과정 — UsernamePasswordAuthenticationFilter아래는 UsernamePasswordAuthenticationFilter 에서 수행하는 인증 과정에 대한 도식입니다.Form 기반 인증 요청에서 username과 password를 추출하여 UsernamePasswordAuthenticationToke 객체를 ProviderManager에 전달합니다. (여기서, UsernamePasswordAuthenticationToken은 위에서 설명한 Authentication 인터페이스의 구현체이고, ProviderManager는 위에서 설명한 AuthenticationManager 인터페이스의 구현체입니다.)ProviderManager는 DaoAuthenticationProvider 를 이용하여 인증을 수행합니다. (여기서, DaoAuthenticationProvider 는 위에서 설명한 AuthenticationProvider 인터페이스의 구현체입니다.)DaoAuthenticationProvider는 UserDetailsService를 이용해 전달받은 username과 일치하는 UserDetails(저장된 사용자 정보)를 조회합니다.DaoAuthenticationProvider는 PasswordEncoder를 이용해 전달받은 password와 3번 과정에서 조회한 UserDetails의 비밀번호가 일치하는지 검증합니다.4번 과정에서 비밀번호 검증까지 성공하면 사용자 인증은 성공한 것입니다. 이 때, 인증이 완료된 UsernamePasswordAuthenticationToken 을 반환하게 되며 이 구현체의 principal 값은 UserDetailsService에서 조회해온 UserDetails로 설정됩니다.최종적으로, 반환된 UsernamePasswordAuthenticationToken은 SecurityContextHolder에 설정됩니다.Form 기반 인증 수행 예시 — 예제 코드인증 수행 과정을 Spring Security 예제 코드와 TRACE 로깅을 통해 확인해봅니다.먼저, Gradle 의존성부터 설정합니다.dependencies { implementation 'org.springframework.boot:spring-boot-starter-security' implementation 'org.springframework.boot:spring-boot-starter-web'}리소스를 관리하는 ResourceController.java 입니다.@Controllerpublic class ResourceController { @GetMapping("/private") @ResponseBody public String loginSuccess() { return "Private Resource"; }}우리가 보호하려는 리소스에 대한 핸들러를 간단하게 명시하였습니다.다음으로 Spring Security 에서 제공하는 Form 기반 인증을 구성한 SecurityConfig.java 입니다.@EnableWebSecurity@Configurationpublic class SecurityConfig { @Bean public UserDetailsService userDetailsService() { InMemoryUserDetailsManager inMemoryUserDetailsManager = new InMemoryUserDetailsManager(); UserDetails user = User.withDefaultPasswordEncoder() .username("user") .password("12345") .authorities("READ") .build(); inMemoryUserDetailsManager.createUser(user); return inMemoryUserDetailsManager; } @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http.authorizeHttpRequests(authorize -> { authorize .requestMatchers("/private").hasAuthority("READ") .anyRequest().authenticated(); }); http.formLogin(Customizer.withDefaults()); return http.build(); }}이 구성에서 설정한 내용은 아래와 같습니다.사용자 정보 저장을 위해 메모리 저장소를 이용하며 사용자 정보를 추가해두었습니다. 사용자의 정보는 다음과 같습니다.username: userpassword: 12345권한: READ2. 보호할 리소스인 http://localhost:8080/private 리소스에 접근하기 위해서는 인증된 사용자여야 하며, 인증된 사용자가 가지는 권한 중 READ 권한이 있어야 함을 명시하였습니다.3. Spring Security 에서 기본적으로 제공하는 Form 기반 인증을 수행합니다.다음으로 Spring Security 에서 제공하는 로깅 기능을 명시한 application.properties 파일입니다.logging.level.org.springframework.security=TRACESecurity Filter가 수행되는 순서와 사용자 요청이 어떻게 처리되는지 로그를 통해 확인할 수 있습니다.Form 기반 인증 수행 예시 — 인증되지 않은 사용자가 리소스를 요청할 때흐름도인증되지 않은 사용자가 http://localhost:8080/private 리소스에 접근을 시도합니다.AuthorizationFilter에서 AccessDeniedException을 발생시켜 인증되지 않은 요청이 거부되었음을 알립니다.ExceptionTranslationFilter는 AuthorizationFilter 에서 발생한 AccessDeniedException 에 대한 처리로 아래의 과정을 수행합니다.SecurityContextHolder 에 저장된 Authentication 데이터가 지워집니다.추후에 인증 과정이 성공할 때, 현재 실패한 http://localhost:8080/private 요청을 바로 수행할 수 있도록 현재의 요청 정보가 담긴 HttpServletRequest 객체를 RequestCache에 저장해둡니다.AuthenticationEntryPoint에 구현된 인증되지 않은 사용자에게 자격 증명을 요청하는 기능을 수행합니다. 여기서 구현된 AuthenticationEntryPoint 객체는 LoginUrlAuthenticationEntryPoint 이므로 로그인 페이지(기본 설정 값은 http://localhost:8080/login)로 redirect 하는 작업을 수행하게 됩니다.4. 사용자의 브라우저는 redirect된 로그인 페이지 (기본 설정 값은 http://localhost:8080/login) 를 요청하게 됩니다.5. LoginController 에서 로그인 페이지(login.html)를 렌더링하여 응답합니다.로그 확인위 로그는 흐름도 상 1 ~ 2번까지의 과정에 대한 로그입니다. 인증되지 않은 사용자가 http://localhost:8080/private 요청을 호출할 때 발생하는 로그입니다. 로그를 통해 아래와 같은 사실을 알 수 있습니다.FilterChainProxy를 통해 15개의 보안 필터(Security Filter)가 수행됩니다.8번째 보안 필터로 UsernamePasswordAuthenticationFilter가 수행되지만, 로그인 요청(POST /login)이 아니기 때문에 실질적인 인증 과정은 수행되지 않습니다. Spring Security 내부 구현은 아래와 같습니다.UsernamePasswordAuthenticationFilter — 로그인 요청(POST /login) 이 아닐 경우, 인증 로직을 수행하지 않고 다음 보안 필터 호출UsernamePasswordAuthenticationFilter — 로그인 요청(POST /login) 인지 확인15번째 보안 필터로 AuthorizationFilter가 수행되지만, /private 리소스에 접근하려는 사용자가 인증되지 않은 사용자이기 때문에 AccessDeniedException 을 던집니다.14번째 보안 필터인 ExceptionTranslationFilter 는 15번째 보안 필터인 AuthorizationFilter에서 던지는 AcessDeniedException 을 잡아 이전 절에서 설명한 예외 처리 로직을 수행합니다. Spring Security 내부 구현은 아래와 같습니다.ExceptionTranslationFilter — 다음 보안 필터 수행 중 예외 발생 시, handleSpringSecurityException 메소드 호출handleSpringSecurityException 메소드 — 발생한 예외가 AccessDeniedException 일 경우, handleAceessDeniedException 메소드 호출handleAceessDeniedException 메소드 — 인증 정보가 AnonymousAuthentication이므로 sendStartAuthentication 메소드 호출SecurityContext 제거 / 기존 요청 저장 / 로그인 진입점으로 이동위 로그는 흐름도 상 3 ~ 5번까지의 과정에 대한 로그입니다.로그를 통해 아래와 같은 사실을 알 수 있습니다.14번째 보안 필터인 ExceptionTranslationFilter 에 의해 아래 작업이 수행됩니다.현재의 요청 정보가 담긴 HttpServletRequest 객체를 HttpSessionRequestCache에 저장해둡니다.AuthenticationEntryPoint 에 의해 로그인 페이지(http://localhost:8080/login)로 redirect 하게 됩니다.사용자가 인증을 위해 로그인 페이지(http://localhost:8080/login)를 요청하면, 9번째 보안 필터인 DefaultLoginPageGeneratingFilter 에 의해 기본 설정된 로그인 페이지를 응답합니다. Spring Security 내부 구현은 아래와 같습니다.DefaultLoginPageGeneratingFilter — 기본 로그인 페이지 생성 및 응답Form 기반 인증 수행 예시 — 인증 과정에서 실패할 때흐름도사용자가 username과 password를 제출하면 UsernamePasswordAuthenticationFilter는 HttpServletRequest 객체에서 username과 password를 추출하여 Authentication의 구현체인 UsernamePasswordAuthenticationToken을 생성합니다.다음으로 UsernamePasswordAuthenticationToken이 인증을 위해 AuthenticationManager 인스턴스로 전달됩니다.인증이 실패하면 아래 과정을 수행합니다.SecurityContextHolder 에 저장된 Authentication 데이터가 지워집니다.RememberMeServices.loginFail() 메소드가 호출됩니다. RememberMeService 를 설정하지 않은 경우, 어떤 작업도 수행되지 않습니다. 이 예제에서는 RememberMeService 기능을 별도로 설정하지 않았기 때문에 어떤 작업도 수행되지 않습니다.AuthenticationFailureHandler 에 구현된 onAuthenticationFailure() 메소드를 수행합니다. 기본적으로 설정되어 있는 AuthenticationFailureHandler의 구현체는 SimpleUrlAuthenticationFailureHandler 입니다. 인증이 실패하면 /login?error URL로 redirect합니다. 로그인 페이지에서는 error 파라미터의 값을 사용하여 인증 실패 메시지를 사용자에게 표시할 수 있습니다.로그 확인위 로그는 흐름도 상 1 ~ 2번까지의 과정에 대한 로그입니다.인증되지 않은 사용자가 POST http://localhost:8080/login 요청을 잘못된 인증 정보와 함께 전송 시, 발생하는 로그입니다. 로그를 통해 아래와 같은 사실을 알 수 있습니다.8번째 보안 필터로 UsernamePasswordAuthenticationFilter가 수행되고 ProviderManager 와 DaoAuthenticationProvider 가 순차적으로 수행되며 인증이 수행됩니다. Spring Security 내부 구현은 아래와 같습니다.UsernamePasswordAuthenticationFilter — AuthenticationManager 의 authenticate 메소드 호출AuthenticationManager 의 authenticate 메소드 — AuthenticationProvider의 authenticate 메소드 호출AuthenticationProvider의 authenticate 메소드 — 제출된 username과 일치하는 사용자 정보가 없어 BadCredentialException 메소드 호출위 로그는 흐름도 상 3번 과정에 대한 로그입니다. 로그를 통해 아래와 같은 사실을 알 수 있습니다.인증 실패 시, 아래 작업을 수행합니다.SecurityContextHolder 에 저장된 Authentication 데이터가 지워집니다.SimpleUrlAuthenticationFailureHandler 에 구현된 onAuthenticationFailure() 메소드를 수행합니다. /login?error URL로 redirect합니다. Spring Security 내부 구현은 아래와 같습니다.AuthenticationFailureHandler 의 onAuthenticationFailure 메소드 — 인증 실패 시, 로그인 페이지로 redirectForm 기반 인증 수행 예시 — 인증 과정에서 성공할 때흐름도사용자가 username과 password를 제출하면 UsernamePasswordAuthenticationFilter는 HttpServletRequest 객체에서 username과 password를 추출하여 Authentication의 구현체인 UsernamePasswordAuthenticationToken을 생성합니다.다음으로 UsernamePasswordAuthenticationToken이 인증을 위해 AuthenticationManager 인스턴스로 전달됩니다.인증이 성공하면 아래 과정을 수행합니다.새로운 로그인이 발생한 것을 SessionAuthenticationStrategy에 통지합니다.SessionAuthenticationStrategy는 새로운 로그인이 발생할 때, 세션 관련 작업을 수행하는 전략입니다. 이전 세션을 무효화하거나, 동시 로그인 방지 정책을 적용할 수 있습니다.SecurityContextHolder를 새롭게 인증이 완료된 Authentication 데이터로 설정합니다.RememberMeServices.loginSuccess() 메소드가 호출됩니다. RememberMeService 를 설정하지 않은 경우, 어떤 작업도 수행되지 않습니다. 이 예제에서는 RememberMeService 기능을 별도로 설정하지 않았기 때문에 어떤 작업도 수행되지 않습니다.ApplicationEventPublisher가 InteractiveAuthenticationSuccessEvent를 발행합니다.AuthenticationSuccessHandler의 onAuthenticationSuccess() 메소드가 호출됩니다. 기본적으로 설정되어 있는 AuthenticationSuccessHandler 의 구현체는 SavedRequestAwareAuthenticationSuccessHandler 입니다. 로그인 페이지로 redirect되기 전, ExceptionTranslationFilter에서 RequestCache에 저장해둔 원래의 요청을 꺼내와 해당 요청으로 redirect 합니다.로그 확인위 로그는 흐름도 상 1 ~ 3번 과정에 대한 로그입니다.인증되지 않은 사용자가 POST http://localhost:8080/login 요청을 정상적인 인증 정보와 함께 전송 시, 발생하는 로그입니다. 로그를 통해 아래와 같은 사실을 알 수 있습니다.8번째 보안 필터로 UsernamePasswordAuthenticationFilter가 수행되고 ProviderManager 와 DaoAuthenticationProvider 가 순차적으로 수행되며 정상적으로 인증이 수행됩니다.인증 성공 시, 아래 작업을 수행합니다.CompositeSessionAuthenticationStrategy 에서 2가지 세션 관련 작업을 수행합니다.ChangeSessionIdAuthenticationStrategy 를 이용하여 Session Fixation 공격을 방지하기 위한 세션 ID 변경 작업을 수행합니다.CsrfAuthenticationStrategy 를 이용하여 세션에 연결된 CSRF 토큰을 교체합니다.SecurityContextHolder를 새롭게 인증이 완료된 Authentication 데이터로 설정합니다.SavedRequestAwareAuthenticationSuccessHandler 에 구현된 onAuthenticationSuccess() 메소드를 수행합니다. 인증 이전에 요청했던 리소스인 http://localhost:8080/private?continue URL로 redirect 를 수행합니다. Spring Security 내부 구현은 아래와 같습니다.기존 요청을 RequestCache에서 꺼내와서 해당 요청을 다시 수행하도록 redirect위 로그는 인증이 완료된 사용자가 GET http://localhost:8080/private로 redirect 될 때, 발생하는 로그입니다. 로그를 통해 아래와 같은 사실을 알 수 있습니다.15번째로 수행되는 보안 필터인 AuthorizationFilter 에서 사용자의 권한을 확인하는 과정을 수행합니다. 사용자의 권한이 모두 확인되면 FilterChainProxy는 모든 보안 필터가 수행되었으므로 보안적인 절차를 수행되었다는 로그를 출력합니다. 최종적으로 인증을 수행하기 전, 처음 요청했던 리소스에 접근할 수 있게 됩니다.글을 마치며Spring Security의 인증 과정은 체계적이고 확장 가능하게 설계되어 있습니다. 각 구성 요소는 명확한 책임을 가지고 있으며 이를 통해 다양한 인증 요구 사항을 유연하게 처리할 수 있습니다. 이번에는 기본적인 폼 기반 인증 과정을 설명했지만, Spring Security는 OAuth2, JWT, LDAP 등 다양한 인증 방식을 지원하므로 애플리케이션의 보안 요구 사항에 맞춰 적절한 인증 방식을 선택할 수도 있습니다.이 글이 Spring Security의 전반적인 인증 과정과 인증에 필요한 구성 요소에 대한 이해에 도움이 되기를 바랍니다.참고자료https://docs.spring.io/spring-security/reference/servlet/architecture.htmlhttps://docs.spring.io/spring-security/reference/servlet/authentication/architecture.htmlhttps://docs.spring.io/spring-security/reference/servlet/authentication/passwords/form.htmlhttps://docs.spring.io/spring-security/reference/servlet/authentication/passwords/dao-authentication-provider.htmlhttps://docs.spring.io/spring-security/reference/servlet/authentication/session-management.htmlSpring Security 의 인증 알아보기 was originally published in NAVER Pay Dev Blog on Medium, where people are continuing the conversation by highlighting and responding to this story.
1년에 4번 정도 마주치는 워드프레스 업데이트 테스트 상황에 조금 더 편하게 대응하고 있습니다. 다만, 편하게 만나는 환경에 직면한 작업자는 저를 포함해 극소수밖에 되지 않아, 단순히 시간 효용을 계산하자면 큰 이득을 얻진 못했다고도 볼 수도 있습니다. 그래도 업데이트 테스트를... The post 워드프레스 백업과 복원은 웹 파일과 DB를 한 쌍으로...
…
안녕하세요. IT연구소 서비스개발팀 빌링파트 오명학입니다. 우연한 계기로 제로베이스라는 코딩 부트 캠프에서 취준생들을 위한 질문과 관련하여 인터뷰 제의가 들어와 진행하게 되었습니다. 대단한 내용은 없다 보니, 많이 부끄럽긴 하지만 개발자가 되기 위해 준비중인 취준생 분들께서 보신다면 좋을것같아 인터뷰 전문을 사람인 블로그를 통해 공유해보고자 합니다. ...
안녕하세요, 뱅크샐러드 웹 프론트엔드 챕터의 민찬기입니다. gRPC…
안녕하세요. 올리브영 스토어전시 스쿼드에서 백엔드 개발을 하고 있는 복스뮤직 입니다. 올리브영 전시에도 여러 스쿼드가 존재하지만, 스토어전시는 주로 메인, 홈, 오특 등 GNB(Global Navigation Bar…
…
애플리케이션, DB 모두 행복한 BULK 처리
안녕하세요. 쿠폰 스쿼드 포덕입니다. 지난 시간엔 어푸님께서 Sync 쿠폰 발급에서 Async로 전환하며 Redis Worker에 대해 포스팅 해주셨습니다. 이번 시간엔 지난 Redis Worker에서 Rabbit MQ…
안녕하세요.️ 쿠폰스쿼드 백엔드 개발자 어푸입니다! 쿠폰 스쿼드에서는 올리브영을 방문하시는 많은 고객님이 안정적으로 쿠폰 서비스를 받으실 수 있도록 개선 작업을 진행하고 있습니다. 지난번 레이 님이 올리브영 쿠폰 발급 개선 이야기를 통해 Redis…
안녕하세요. 줌인터넷 핀테크개발팀 김민수입니다. 사내에서는 문제를 개선하고 지속 가능한 서비스를 만들기 위한 많은 노력을 하고 있습니다. 회원 서비스의 세션 저장소를 교체하면서 Spring Session을 도입한 경험을 공유합니다. 이런 분들이 읽으면 더 도움이 됩니다. 분산 환경에서 세션 동기화 문제를 해결하고자 하는 분 Spring Session을...
공개 배포해야 하는 파일이 많은 서비스가 아니라면 WAS의 디렉터리 구조는 노출하지 않아야 합니다. 이번에는 WAS에서 디렉터리 인덱싱 취약점을 노출하지 않는 방법과 노출해야 하더라도 상위 디렉터리에 이동 제한을 설정해 접근할 수 없게 만드는 방법을 살펴보겠습니다. The post [여기보기] 적에게 내 WAS의 디렉터리와 파일을 알리지 말라, WAS...
어노테이션 기반으로 분산락을 사용하는 방법에 대해 소개합니다.
안녕하세요. IT연구소 서비스개발팀 빌링파트 최재우입니다. 2022년 12월 7일 사람인의 결제 및 상품을 담당하는 Order API 서버의 CPU, Memory과부하가 지속되는 이슈가 발생했었습니다. 해당 이슈를 통해 발생한 에러들과 원인이 무엇인지 분석한 것에 대해 공유해 드리고자 합니다. 원인이 무엇이었나 저희 Order API는 Spring B...
📖 Table of Contents 포스팅의 목차입니다. 캐시는 무엇인가요? LOCAL 캐시와 GLOBAL 캐시 ElastiCache 무엇인가요?? 캐시 적용하기! 안녕하세요. 올디브에서 Back-End…
안녕하세요. 사람인 HR IT 연구소 IT 전략팀 이창섭입니다. 저희 팀에서는 사람인 내부의 DB Trigger를 제거하고 이를 비동기 분산처리로 변환하는 작업을 진행했습니다. 그 중 Kafka를 통하여 메세지 처리 과정 중에 일부 문제가 있었던 부분을 Spring Cloud Stream을 이용하여 재시도 로직을 구현했습니다. 그 기술적인 구현 과정을...
Why Scala is a great match for developing game servers.
Scala가 게임 서버 개발에 왜 좋을까요? 그 이유를 알아봅니다.
'추석맞이 선물하기 재개발'에 차출되어 API 문서화를 위해 도입한 Spring REST Docs 를 소개합니다.
신규 메신저 서비스 배포두 메신저 서비스의 연동 및 데이터 마이그레이션을 마친 뒤, 대망의 신규 메신저 서비스의 배포가 시작됐습니다.이번 포스트에서는 사용자들에게 신규 메신저 서비스를 배포하고 기존 메신저 서비스를 비활성화 및 종료하는 과정을 정리해보겠습니다.점진적 서비스 배포 및 모니터링처음부터 전체 사용자를 대상으로 신규 메신저 서비스를 배포할 경...
메신저 서비스 연동 및 데이터 마이그레이션신규 메신저 서비스의 개발이 완료됐지만, 당시 구버전 앱뿐만 아니라 여러 서비스와 컴포넌트에서 기존 메신저 서비스를 사용하고 있었기 때문에 기존 메신저 서비스와 신규 메신저 서비스를 동시에 지원하면서 점진적으로 신규 메신저 서비스를 적용하는 기간이 필요했습니다.이때 두 메신저 서비스에서 사용자들에게 서로 동일한...
신규 메신저 서비스 개발현재의 개발 인력으로도 관리할 수 있는 새로운 메신저 서비스를 구현하기 위해서는 기존 메신저 서비스에서 개발 및 관리 비용이 많이 들어가는 부분들의 개선이 필요했는데,그 중 가장 많은 비용을 차지하는 실시간 통신 로직을 개선하기 위해 여러 서비스와 솔루션들을 찾던 중 Firebase의 Realtime Database와 Cloud...
메신저 서비스 이전 배경안녕하세요. 저는 번개장터에서 상점 간 거래 프로세스와 관련된 서비스를 개발 및 관리하는 Trade Lab에서 백엔드 소프트웨어 엔지니어로 근무 중인 김동현입니다.앞으로 총 4개의 포스트를 통해 번개장터에서 Firebase와 Cloud Firestore로 새로운 메신저 서비스를 구현하고 기존에 구현된 메신저 서비스와 교체하는 과...
마이쿠키런 신입 안드로이드 개발자의 Kotlin Coroutine 탐방기
데브시스터즈 서버 직군에서 코딩 면접을 보는 이유와 방향성에 대해서 말씀드리고 싶습니다.
안녕하세요. 부설연구소 & 빅데이터팀 Data Intelligence 파트의 류혜정입니다. 최근 줌포털 투자탭에 적용하기 위해 개발한 ‘투자줌 뉴스 카테고리 분류 모델’을 BentoML 로 패키징하여 서빙한 경험에 대해 공유하고자 합니다. 😇 0. 모델 배포와 서빙을 더 효율적으로 BentoML 의 공식 깃허브에서는 BentoML 을 아래와 같...