Spring 7

STOMP를 사용하여 webSocket 채팅 구현 1

처음에 헷갈렸던 것이 어디까지가 프론트단에서 해결해야할 문제이고 어디서부터 백엔드가 해결해야할 문제인지였다. 클라이언트가 서버로 요청(request)하고 서버가 클라이언트로 응답(response)하는 기존의 stateless한 http 통신 메커니즘이 익숙하다 보니 더 헷갈렸던 것 같다. 그렇기에 http 통신은 실시간으로 데이터를 주고받아야하는 상황에서는 한계가 있다.웹소켓은 TCP기반의 웹앱과 서버의 연결이 지속적으로 유지되는 양방향 통신 프로토콜로써 실시간으로 데이터를 주고받는 상황에서 강점을 갖고있다. 웹소켓 Stomp를 구현하기위해 동작과정을 이해하는 것이 우선적이라고 생각했다. 1. 우선 프론트에서 wss://example/chat 경로로 웹소켓 연결을 한다. 2. 이후 /sub/chat/r..

Spring 2025.05.29

Jmeter를 통해 웹소켓 Stomp 부하 테스트 하기

실시간 채팅 서비스는 WebSocket으로 요청하여 WebSocket으로 응답 받는다.경매의 실시간 입찰 서비스는 Http로 요청하여 WebSocket으로 응답 받는다.이 두 서비스의 요청과 응답을 어디서 확인 해볼 수 있을까 고민했다. 요청과 응답을 받아보려면 프론트 코드를 작성하여 확인하는 방법 뿐이라고 생각했다.(실제로 튜터분들이나 현직자 분들께서도 프론트 코드를 작성해서 확인하는 방법뿐이라고...) 그래서 인터넷을 뒤져서 만들어보고 아 ~ 그래도 내가 작성한 코드가 동작은 하는구나..? 를 느꼈다. 근데 부하 테스트는...? 그렇다. WebSocket Stomp를 부하 테스트 하는 것 자체가 문제였다. 어느날 Jmeter로 가능하다는 사실을 알게 되어 테스트를 진행 할 수 있게 되었다. 밑은 미..

Spring 2025.05.29

게시글 조회 시 게시글 조회수 카운팅 Redis vs DB

공연 게시글을 요청하면 조회수를 증가시키고 조회하여 공연 정보와 조회수를 응답하는 API의 성능 개선 레디스로 조회수 저장 및 조회 기능을 구현하기 전에 데이터베이스에 저장하여 관리했을 때와의 성능 차이가 얼만큼 벌어지는 지 확인하고자 했다. 게시글 조회수 기능은 정확성 보다는 응답 속도가 중요하다고 생각하여 Redis 캐시를 사용하고 동시성 제어는 생략했다.실제 트래픽 환경을 고려한 멀티스레드 테스트보다는, 단일 요청 기반의 응답 속도를 비교하여 시스템 부하 개선 효과를 측정해 보고자 한다.  우선 DB로 관리하는 방식은 ViewCount 엔티티를 만들어 유저ID와 공연ID를 유니크 키로 설정하여 어뷰징을 막고 공연 조회마다 저장 후 공연 ID로 count하여 조회수를 가져오는 로직으로 구현하였고,  ..

Spring 2025.03.27

대용량 데이터 읽기 속도 개선

유저 데이터를 대략 1_000_000개 생성해 주고 유저의 닉네임으로 유저를 검색할 때의 처리 속도를 개선해 볼 예정이다. 우선 아래와 같은 방식으로 테스트 코드를 통해 100만개의 유저 데이터를 생성했다.private static final int BATCH_SIZE = 1000;@Testvoid 유저_100만개_생성(){ List users = new ArrayList(); for (int i = 0; i  아래와 같은 방식으로 유저의 닉네임을 통해 데이터를 받아왔다.최초 조회 시간은 538.02ms가 나왔고, 두번째부터 5번 조회의 평균 시간은 368ms(377, 369, 363, 371, 360) 가 나왔다.  public UserResponse getUserWithNickname(St..

Spring 2025.03.21

N+1문제를 해결하고 인덱스를 걸어보자

요기요, 배달의 민족, 쿠팡이츠와 같은 서비스를 구현하는 프로젝트를 진행중이다.리뷰 도메인을 맡아 모든 리뷰를 가져오는 코드를 작성중에 문제를 인식하였다. 리뷰를 작성할 때 사진도 저장할 수 있는데, 리뷰 도메인에 s3 url을 저장하지 않고 Photo 테이블을 만들어 그곳에 리뷰에서 저장되는 사진, 가게의 사진, 메뉴의 사진이 저장을 할 수 있게 따로 엔티티를 작성하였다.  Photo 엔티티에는 도메인타입(Review, Store, Menu)과 각 도메인의 pk를 저장하는 domianKey 필드가 있다.위 두 필드로 특정 도메인의 특정 id를 기준으로 사진을 가져올 수 있다.@Entity@Getter@NoArgsConstructor@Table(name = "photo")public class Photo..

Spring 2025.03.07

JWT Refresh Token에 대한 생각정리

프로젝트에 적용하기 위해 처음 jwt를 공부하고 적용하면서 드는 의문들을 프로젝트가 끝나고 정리해보았다.나의 생각정리를 위한 글이기에 확실한 정보가 아님을 밝힌다. 리프레쉬 토큰을 서버에 저장하는것은 stateful한것이 아닌가?-> 액세스 토큰이 만료가 되었을 경우에만 stateful해지는 것이지 평소에는 stateless한 이점을 가질 수 있다. 리프레쉬 토큰은 디비에 저장할 때 멤버테이블과 분리하는것이 좋다.사실 못할건 없지만 토큰 로테이션을 사용할 경우 리프레쉬 토큰은 주기적으로 재발급, 갱신 되기 때문에 이를 멤버 테이블에 같이 저장하면 불필요한 테이블 잠금 및 SQL 업데이트가 발생할 수 있다. 멤버 테이블은 소중하다.분리하는것이 추후에 후회할 일 없고 유지보수에 좋다.분리하면 깔끔하고 안전..

Spring 2025.02.10

Spring Security와 JWT를 활용한 로그인 구현

본 포스트는 필자의 개인적인 프로젝트에 첫 로그인 기능을 구현한 후 생각을 정리하기 위한 포스트이다. 구현하기에 앞서 처음 로그인 방식에 대해 세션 기반 인증으로 할 지 JWT 기반 인증으로 할 지 고민을 했다.두 방식 모두 장단점을 가지고 있어서 상황에 맞게 적용하는 것이 중요했다. 세션 기반 인증세션 기반 인증은 서버가 상태 정보를 직접 관리하는 Stateful 방식이다. 사용자가 로그인하면 서버는 세션 ID를 생성하여 클라이언트에 전달하고, 서버의 메모리에 세션과 관련된 상태 정보를 저장한다. 세션 기반 인증의 동작 원리 1. 사용자가 로그인 요청을 하면 서버는 세션 ID를 생성한다. 2. 이 세션 ID는 클라이언트의 브라우저 쿠키에 저장된다. 3. 클라이언트가 서버에 요청을 보낼 때마다 세션 ID..

Spring 2025.02.06