분류 전체보기

N + 1문제 문제 상황 문제가 발생하는 상품 목록 조회 API는 아래와 같은 상품들을 12개 씩 조회하는 API입니다. 문제점은 JPA 지연로딩으로 인해 상품에 걸려있는 입찰과 좋아요의 쿼리가 상품의 개수만큼 날아갑니다. 즉 상품이 12개라면 1( 상품들을 조회하기 위한 쿼리 ) + 12(상품 별 입찰 목록) + 12(상품 별 좋아요 목록) 총 25개의 쿼리가 날아가게 됩니다. 좋아요와 입찰 모두 1 대 N 관계이기 때문에 fetch join을 쓴다면 페이징 처리로 인해 OOM문제가 발생합니다. 해결책 1(Batch Size - in Query) Batch Size를 조정하여 조회한 상품 별로 입찰과 좋아요를 조회하는 것이 아닌 12개의 상품에 대한 좋아요와 입찰을 한 번에 가져옵니다. 즉, 1(상품 ..
문제 정의 1대1 채팅을 구현할 때 읽음 처리를 진행하기 위해서 고려해야 할 부분은 다음과 같습니다. 상대방이 채팅방에 들어왔을 때 -> 읽지 않은 메시지 읽음 처리 상대방이 채팅방에 접속중일 때 -> 보낸 메시지 즉각 읽음처리 상대방이 채팅방에 들어왔을 때 저는 웹소켓을 STOMP기반으로 사용하고 있어 Header의 COMMAND에서 CONNECT메시지 구분이 가능했습니다. 이를 이용해 CONNECT시 모든 채팅을 읽음 처리했으며, 화면 단의 변경을 위해 웹소켓으로 Update요청을 보내 처리했습니다. 상대방이 채팅방에 접속중일 때 기존 해결책 제가 처음에 선택했던 방식은 아래 흐름과 같습니다. 문제점 상대방이 접속해 있는것을 확인하기 위해서는 매번 리콜 처리해야 하며 이 때 DB Update또한 발생..
🍪문제 상황조회수 중복 증가 제어와 Refresh Token관리를 위해 쿠키를 도입했는데 쿠키가 서버로 전달이 안되는 문제를 접했습니다.처음에는 Local쪽에서 통신이 안되는 문제였으며 CORS와 withCredentials설정으로 인한 문제였습니다.다음으로는 서버로 배포 후 테스트 해봤는데 samesite에 의해 쿠키 전달이 안되는 문제였습니다.다들 쿠키를 손에 넣어봅시다.🍪CORS와 withCredentialsCORS저는 3000번 포트에 React 8080포트에 Spring을 띄워둔 상태였습니다. 포트가 다르기 때문에 CORS설정을 해주어야 했습니다.public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/..
문제점 이전까지 문제 없었던 GithubActions를 통한 CI/CD 과정이 Test를 작성하고부터 실패하는 것을 확인했습니다. -i 로 로그를 찍어봤을 때 레디스에 접근을 못하고 있는 문제였습니다. 깃헙액션은 별도의 서버를 통해 CI/CD를 진행합니다. -> 당연히 빌드를 시도하는 GithubActions 서버에도 사용할 수 있는 Redis 제공해야합니다. 해결방법 - Ubuntu서버에 Docker로 Redis를 띄운다. - Embedded Redis를 이용한다. GithubActions Server에 Redis 띄워주기 아래와 같은 구조를 만들어 줘야 하는거죠 Embedded Redis 저는 이전 프로젝트들에서는 모두 Embedded Redis를 이용했었습니다. 이유는 어떤 환경에서 동일하게 실행이..
😐정리 사용자 구분은 viewCount라는 이름으로 브라우저별 random 값을 가진 쿠키를 이용 상품에 대한 중복 접근 체킹은 브라우저별 랜덤 값을 Key로 Redis의 SET이용(itemId저장) 사용자 구분을 위한 쿠키와 중복 접근에 대한 내용을 저장하는 set의 Key값은 자정에 만료 Redis에서 itemId로 조회수를 저장 -> 일정 시간 후 DB반영 1. 저는 혹시 모를 상황에 대해 구현에서의 편의성을 가져가기 위해 Redis로 중복접근을 체킹했습니다. 하나의 쿠키에 중복접근에 대한 정보를 담았을 때 사용자가 게시글 1000개 이상을 읽는다면 문제 발생 -> 쿠키를 여러 개 이용하는 방식으로 확장해야 함 그러나 하루에 1000개 이상의 게시글을 읽는 경우가 생각보다 많이 발생하지 않을것이고 ..
클라이언트 단에서 SocketJS와 Stomp를 이용해 연결했으며 서버 단은 Spring으로 구성했습니다. 문제가 발생했을 당시 상황 아래와 같은 문제점들은 사실 로컬에서도 발생합니다. 보통 웹소켓 연결 endPoint를 잘못 매칭했거나 웹소켓 연결에 CORS설정을 해놓지 않아서 발생하기에 간단히 해결이 됐습니다. 여기서 저희 팀에서 했던 생각은 endPoint매칭 및 CORS에 대한 대처가 됐다 였습니다. 그러나 배포 환경에서 실행했을 때 Websocket connection failed와 CORS가 발생했습니다. Nginx사용 시 문제점 조금 검색해본 결과 nginx와 Websocket을 함께 사용할 시 주의해야 할 점으로 웹소켓 연결을 위해 아래의 헤더를 추가해줘야 한다는 것이었습니다. locati..
😐문제 정의 테스트 시 사용자 인증 정보를 세팅해야 하는데 저는 JWT를 통해 인증을 구현했기 때문에 매번 로그인 요청을 시도하고 이 때 얻은 토큰을 담아서 요청을 다시 보내야 하는 문제점이 있었습니다. 저는 Spring Security에서 지원하는 @WithUserDetails를 이용해 인증 정보를 세팅하기로 했으나 @BeforeEach를 이용해 DB에 데이터를 저장한 뒤 인증 세팅을 하는 과정에서도 NPE가 뜨는 문제가 발생했습니다... 😐@WithUserDetails와 @WithMockUser 동작원리 및 차이 사용하기에 앞서 둘의 차이를 알고 써야겠다 싶어 동작 원리를 공부해봤습니다. 요약 둘 모두 테스트에 사용하기 위한 가짜 인증 객체를 설정하기 위해 사용됩니다. (원래대로라면 토큰을 이용해서 ..
😐정리 - Websocket Handshake요청은 일반적인 HTTP요청을 잡는 HandlerInterceptor에 걸리지 않아 별도의 처리가 필요하다. - STOMP CLIENT에서 담는 헤더들은 웹소켓 연결 이후 STOMP 연결이 진행될 때부터 사용이 가능하다. 즉, Handshake Interceptor에서 토큰을 받아 인증을 진행할 수가 없음 - ChannelInterceptor 이용하자 -> COMMAND가 CONNECT일 때만 인증 여부 검증하도록 구현 - 위 방법은 인증을 여러번 진행하지는 않지만 메시지 전송시에도 토큰을 달고 다녀야 해서 전송 비용이 증가함 - 최종 해결책은 토큰을 쿠키로 관리하여 웹소켓 연결 시 동작하는 Handshake Interceptor에서 한번만 검사하도록 한다. ..
정리 오랜만에 테스트를 짜던 중 회원가입 부분에서 계속 비밀번호 매칭이 안되는 버그를 발견했습니다.. 결론부터 말하자면 비밀번호 비교는 passwordEncoder.matches(비밀번호, 암호화된 비밀번호) 를 이용해야합니다. Security내부 로직을 뜯어봤을 때 위처럼 비교하는 코드를 봤기 때문에 알고는 있었지만 그런가 보다 하고 지나쳤었던 로직인데 다 이유가 있던거였.... 테스트 과정 및 실패의 이유 분석 단순하게 생각해서 passwordEncoder로 암호화 시킨 비밀번호를 DB에 저장시킨것이기 때문에 똑같은 비밀번호를 암호화 시켜서 비교한다면 성공할거라고 생각했습니다. 아래처럼요..(member는 테스트 결과 값으로 다시 조회한 객체입니다.) Assertions.assertThat(membe..
1. 목표 로그인에 실패했을 때 권한이 없을 때 구체적인 예외처리 ex) "수정 권한이 없습니다.", "삭제 권한이 없습니다.", "로그인 후 이용할 수 있습니다." 공통 처리(코드 중복 제거를 통한 가독성 향상) 2. @PreAuthorize()의 한계 PreAuthorize() 는 로그인 여부나 권한체킹하는 것을 도와줍니다. success or fail로 동작하며 인증/인가 실패 시AccessDeniedException을 반환합니다. 여기서 문제점은 실패의 원인이 로그인을 안해서인지 권한이 없어서인지 등을 구분하기 어렵고 따로 구체적인 예외처리가 불가능합니다. 권한 체킹을 할 때 preAuthorize로 Role에 대해서 체크할 수 있지만 자신의 게시글인지와 같은 추가적인 권한 검증이 필요할 수 있습..
Seung__Yong
'분류 전체보기' 카테고리의 글 목록