본문 바로가기

Java/Spring19

Spring) 평균 응답 시간 개선 현재 입찰 요청의 평균 응답 시간은 1300/ms이다. 일반적으로 클라이언트가 이용하기엔 매우 불편한 수치이다. 문제 원인 파악 현재 비동기로 이벤트를 발송하는 구조에서 많은 사용자가 연결 되었을 때, 내부적으로 이벤트를 전송하는 로직에 자원을 많이 사용하나? 라는 가설을 세우고 테스트를 진행해보았다. 연결을 하지 않고, 입찰 요청만 보냈을 때 응답 시간이 현저히 낮은 것을 확인했다. 입찰 요청의 문제가 아닌 연결 하고 이벤트를 발송할 때 생기는 문제라고 생각이 되었다. 이벤트 발송하는 로직에서 Emitter들이 유효한지 확인하는 반복문을 제거하여 테스트를 더 진행해 보았다. 응답시간이 줄어듦을 확인했다. 문제가 일어난 이유 SSE는 특성상 클라이언트가 접속을 끊었는지 확인하기 어렵다. 그러하여 이벤트를.. 2023. 8. 31.
Spring) Transaction 처리 속도 향상 scale-up을 하고도 Time out 에러가 발생했다. 서버의 자원은 아직 견딜 만 한데도 Time out이 발생한다. 이는 Transaction의 처리 속도가 느리니 Lock이 걸려있는 시간도 길어진다. 그러므로 Lock을 얻기위해 Connection 들은 기다린다. 그렇게 되며 병목현상이 발생하고, HandOffQueue에서 대기하는 Thread들의 시간이 30초를 넘으며 time out이 발생하는 것 같다. 문제 원인 파악 각각의 시간이 얼마나 걸리는지 로그를 찍어 확인해 보았다. 그 결과 발생하는 이벤트를 전송하는(Bid Update Send) 과정에서 처리하는 시간의 90% 이상을 차지한다. 문제가 발생한 원인 업데이트 된 입찰가를 연결되어있는 클라이언트들에게 보내는 과정에서 많은 시간이 소.. 2023. 8. 28.
Spring) 실시간 통신 방식 선정 WebSoket VS SSE(Server Sent Events) 실시간성이 높아야 하는 프로젝트의 특성상 Polling과 Long Polling 방식은 제외했다. WebSoket은 양방향 통신을 지원한다. 클라이언트가 서버로 요청을, 서버에서 클라이언트로 응답을 주고 받을 수 있다. 웹 소켓은 연결이 되면 웹소켓 프로토콜로 데이터를 주고 받는다. 사용자가 여러명일 경우 사용자의 수만큼 연결을 유지해야 하기 때문에 트래픽이 높을 수록 서버 자원을 많이 사용하게 된다. 반면에 SSE는 단방향 통신을 지원하며, 지속적인 연결을 유지하지 않아도 되므로 서버 자원을 효율적으로 사용할 수 있다. 웹소켓은 HTTP 프로토콜을 사용하지 않기 때문에 비교적 구현이 복잡하다. 현재 프로젝트에서는 단방향 통신이면 충분하고,.. 2023. 8. 8.
Spring) 비관적 락으로 인한 오류와 해결 문제 상황: Idea 테이블에 비관적 락을 걸고, 메서드 BidReservation과 findOneIdea를 실행하면 읽기 전용 트랙잭션에서는 SELECT FOR NO KEY UPDATE 명령을 실행할 수 없다고 뜬다. 하지만 똑같이 @Transaction(readOnly = true)가 걸려있는 전제 조회(findAllIdea)에선 정상적으로 실행 된다. 왜 이런 현상이 발생하는지 이유를 찾아보자!!!!! 문제가 일어난 이유: 현재 findById에 비관적 락을 걸어놨다. 비관적 락은 실행이 되면 DB레벨에서 해당 트랜잭션에 쓰기락을 걸어 다른 요청이 동시에 접근할 수 없고, 각 요청들이 동기방식으로 처리된다. 한마디로 findById를 사용한 로직에는 findById가 실행이 될 때 비관적 락이 걸리.. 2023. 8. 7.
Spring) 동시성 제어 동시성 제어 현재 프로젝트는 아이디어 경매라는 주제이다. 여기에서 입찰을 누르면 그 중 하나만 등록이 되어야 하기 때문에 동시에 입찰을 누르게 되면 문제가 발생한다. 이를 방지하고자 동시성 제어를 해주어야 한다. 동시성 제어 방안 크게 세가지로 분류할 수 있다. 1. synchronized를 활용하여 자바 내부에서 처리하기. 2. DB에 Lock을 걸어 해결하기. 3. Redis로 해결하기 Synchronized Synchronized는 한 스레드가 한개의 자원을 사용하고 있을 때 다른 스레드들이 접근하지 못하도록 막아주는 동기화 방식이다. 간단하고 직관적이게 데이터 무결성을 보장할 수 있지만, 단점이 크다. 입찰하는 기능은 여러 사용자가 동시에 접근하고 업데이트할 수 있는 공유 자원이다. 따라서 많은 .. 2023. 8. 6.
Spring) 테스트 코드 작성하기 테스트 코드는 왜 작성해야 하나? 더보기 Development: 개발 Unit Tests (단위 테스트): 개발자 테스트 QA Testing: 블랙박스 테스팅, 주로 QA팀이 Production 환경과 유사한 환경에서 테스팅 Production: 실 서비스 운영 환경 단위 테스트 더보기 단위 테스트는 작은 단위로 쪼개서 각 단위가 정확하게 동작하는지를 검사하는 테스트 기법이다. 테스트 애노테이션 더보기 출력 값: 테스트 꾸미기 더보기 @DisplayName: 테스트의 내용을 한눈에 알아볼 수 있게 네이밍 해줄 수 있다. @Test @DisplayName("테스트의 내용을 한눈에 알아볼 수 있게 네이밍 해줄 수 있습니다.") void test1() { System.out.println("테스트의 수행 내용.. 2023. 8. 3.
Spring) Spring Security Spring Security 더보기 Spring Security 인증 및 인가에 대해 많은 기능을 지원해주는 Spring 프레임 워크 Spring 에서 모든 호출은 DispatcherServlet을 통과하게 되고 이후에 각 요청을 담당하는 Controller 로 분배된다.이 때, 각 요청에 대해서 공통적으로 처리해야할 필요가 있을 때 DispatcherServlet 이전에 단계가 필요하며 이것이 Filter이다. Security는 기본적으로 세션 방식으로 동작 한다. JWT 방식으로 수정할 수 있다. @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOExcept.. 2023. 7. 24.
Spring) refresh token 왜 refresh token을 사용 하는가? 더보기 토큰 기반 인증 방식에서 토큰은 stateless하다. stateless(무상태)란 전달해야 하는 정보를 클라이언트 쪽에서 갖고 있는 것. stateful(상태 유지)란 요청의 정보를 서버가 기억 하는 것. https://roxy.iro.ooo/infra/protocol/http/http-stateful-stateless stateless 하므로 서버 쪽에서는 한번 탈취당한 토큰을 사용자인지, 해커인지 확인할 방법이 없다. Access Token에는 프론트엔드에서 사용되는 사용자의 정보가 담긴다. 물론 디코딩하면 값을 쉽게 알 수 있으니 민감한 정보를 담으면 안된다. Refresh Token을 온리쿠키로 보내면 클라이언트 쪽에서 정보를 열어볼 수 없기 .. 2023. 7. 23.
23.07.19) CORS 에러 해결 HTTPS로 배포하고 CI/CD로 구축 후 프론트엔드 분들과 연결해봤다. 연결하자마자 발생한 CORS에러. 난생 처음 보는 에러에 어떻게 해야 할 지 감조차 잡히지 않았다. 남은 시간은 2일. HTTPS배포와 CI/CD 파이프 라인 구축하는데 시간을 너무 많이 쓴 바람에 늦어졌다. 처음 발생한 에러에 이해하고 해결하기엔 시간이 너무 촉박했다. 그렇게 구글링을 하며, 해결방안을 여러 방면으로 시도를 했다. 상위 레벨인 Application에 @CrossOrigin 달아주기 프로젝트에서 다른 패키지들보다 상위 레벨인 Application의 main 메서드에 @CrossOrigin을 달아줌으로써, 서버가 시작 될 때 포트 권한을 열어주는 것이다. 이 방법은 테스트할 때를 제외하곤 열어두면 안될듯 싶다. pub.. 2023. 7. 19.