[Springboot] AWS SQS를 이용한 알림 시스템 구현하기 - 메시지 발행 로직
·
Project/Spring
서론기존에는 Spring의 `ApplicationEventPublisher`와 Redis의 Pub/Sub 구조를 활용해 알림 기능을 구현하고 있었다.이 구조는 내부 서버간 이벤트 전파와 브라우저 클라이언트로의 SSE 알림 전송에 효과적이었지만, 알림 수가 많아질수록 처리에 병목이 생길 수 있으며 실패시 재처리가 어렵다는 문제가 있었다.이러한 한계를 해결하고자 AWS SQS를 도입하여 알림 시스템을 재구성하게 되었다. 이 글에서 구조 설계, 고민했던 부분들과 해결 방안을 중심으로 알림 시스템 전환 과정을 정리하고자 한다.SQS를 도입하게 된 이유기존에는 웨이팅 호출 시 해당 웨이팅의 사용자에게 알림을 보내는 기능만 있었지만, 이후 쿠폰 이벤트가 시작되면 해당 가게를 찜한 사용자 전체에게 알림을 발송해야 하..
[SpringBoot] SSE를 이용한 실시간 알림 전송 구현기 (feat. Redis Pub/Sub)
·
Project/Spring
1. 들어가며음식점 웨이팅 프로젝트를 진행하면서, 사용자의 웨이팅이 호출되었을 때 실시간 알림을 전송해야 했다.알림을 전송하는 기능은 처음 구현해보았기에 기록해본다.2. 기술 선택 배경▶ SSE + Redis Pub/Sub 조합을 선택했다, 그 이유는?다음과 같이 적용 가능한 다양한 기술들을 비교해보았다.기술설명장점단점프로젝트 기준 평가SSE서버 → 클라이언트 단방향 스트리밍 (HTTP 기반)구현 간단, 브라우저 지원, HTTP 기반이라 인프라 변경 최소양방향 불가, 커넥션 관리 필요 (브라우저마다 약 6개)✅ 현재 단방향 알림 구현 중이므로 적합함웹소켓서버 ↔ 클라이언트 양방향 실시간 통신강력한 실시간성, 양방향 가능, 낮은 지연인프라 구성 부담 (로드밸런서 설정 필요 등), 연결 유지 비용 ↑단방향 ..
[SpringBoot] AWS S3를 이용한 프로필 이미지 업로드 로직 구현기
·
Project/Spring
1. ProfileImage 설계사용자는 하나의 프로필 사진을 갖는다. → OneToOneProfileImage에서 사용자를 참조할 일은 없다 → 단방향S3에서 객체를 삭제하기 위해서는 버킷에 저장된 이름이 필요하다.S3에서 제공하는 객체 url로 이미지에 접근한다.``객체 url``과 함께 저장할 ``버킷에 저장된 이름`` 정보가 필요하므로 해당 정보를 담은 테이블을 추가하기로 결정했다.✓ ProfileImage 엔티티다음과 같이 ProfileImage 엔티티를 추가해주었다.@Getter@Entity@NoArgsConstructor@Table(name = "profile_images")public class ProfileImage { @Id @GeneratedValue(strategy = G..
[Spring] 회원탈퇴, Soft Delete로 구현하기 (JPA)
·
Project/Spring
회원탈퇴를 구현하며 ...일정 관리 Develop 과제를 수행하다가 Delete User, 즉 회원탈퇴를 구현해야 하는 상황이 왔다.현재 User는 Todo와 Comment의 FK로써 연관관계를 가진다. (그렇지만 Comment는 아직 기능을 구현하지 않았다.)데이터의 삭제를 구현하는 방법은 두 가지가 있다.Hard Delete데이터베이스의 User 테이블에서 실제로 해당 유저의 데이터를 물리적으로 삭제하는 방법이다. 이 경우 외래 키 관계를 주의해서 다루어야 한다. 예를 들어 User 테이블을 삭제하려고 한다면 Todo 테이블에 해당 사용자의 데이터가 남아있다면 DB에서 무결성 오류를 던진다. 이런 오류를 방지하기 위해서는 FK로 연결된 데이터를 먼저 삭제해주거나, 혹은 ``ON DELETE CASCA..
SpringBoot + QueryDSL 적용 살펴보기
·
Project/Spring
QueryDslConfig.javapackage com.lettrip.lettripbackend.configuration;import com.querydsl.jpa.impl.JPAQueryFactory;import jakarta.persistence.EntityManager;import jakarta.persistence.PersistenceContext;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;@Configurationpublic class QueryDslConfig { @PersistenceContext private EntityMan..