[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..
[BAW] Express + PostgreSQL 트랜잭션 처리 도입기
·
Project/Node.js & React
* 현재 ORM 도입 없이 PostgreSQL 드라이버인 pg를 사용하여 데이터베이스와 연결하고 있습니다. 기존 코드  기존 CommentService의 코드입니다. commentId를 받아와서 댓글 하나를 삭제합니다.이 로직 한 번에 총 4번의 DB 쿼리가 날아가게 됩니다. 1. commentId로 comment를 찾아옵니다.2. 해당 comment의 부모 댓글을 찾아 recomment_count를 1 감소시킵니다.3. 해당 comment가 달린 article을 찾아 comment_count를 1 감소시킵니다.4. 만일 대댓글이 달린 댓글이라면 해당 댓글에 deleted를 마킹하고, 그렇지 않다면 해당 댓글을 테이블에서 바로 삭제합니다. 현재 트랜잭션 처리가 되어있지 않아 2~4번 과정에서 에러가 발생..
[BAW] 중간점검 .. 프로젝트 모듈 구조화
·
Project/Node.js & React
문제 상황현재 redux 모듈 디렉토리 구조입니다. 일단 보자마자 article 안에 왜 articles과 editor가 또 있는거지?..  싶고요 ㅎㅎ그리고 domain별로 디렉토리가 나누어져있지만 auth, user 디렉토리 안에는 ducks 패턴으로 작성된 파일이 있고, 나머지는 Type, Action, Reducer, Saga 파일이 전부 나누어져있는 짬뽕 구조입니다. (해맑게 웃는다)  이 외에도 파일 구조 상 정형화 되지 않은 부분들이 많아서 이를 좀 정리 해볼까 합니다.정리 좀 해볼까요 ..1. Redux 상태 사용, 기능별로? 데이터별로?현재 프로젝트에서는 글을 조회하여서 article 데이터를 받아오는 로직이 서로 다른 기능에서 중복 되고 있는 상황입니다. 즉, 같은 데이터 구조의 데이터..
[Express + React] OAuth2 로그인 구현 : Kakao 로그인에 닉네임이 반드시 필요하다면?
·
Project/Node.js & React
배경프로젝트를 진행하면서 OAuth2를 사용하여 소셜 로그인(Naver, Kakao, Google)을 구현하게 되었다.이전 졸업 작품 등에서도 OAuth2로 소셜 로그인을 구현한 경험은 있지만, 전부 Java/Springboot를 이용하여 구현하여서 Express를 사용하여 구현한 것은 처음이었다!그치만 Springboot에서 Express로의 변경에 의해 야기된 큰 차이점은 없었다. 단, 이번에 OAuth2 로그인을 구현하면서 고려해야할 점은 다음과 같았다.닉네임(nickname) 정보가 반드시 필요하다.닉네임이 unique값이어야 한다. (즉, 겹치면 안 된다.)그런데, 다음과 같은 문제가 있었다.Provider로부터 얻어온 정보에 닉네임 정보가 없는 경우가 존재한다.얻어온 닉네임의 unique함이 ..
[FBTB] 4. 로그인 유지 기능 구현 (UI)
·
Project/FromBookToBook
웹 전체적인 UI도 좀 더 웹페이지 같게 바꾸었다. 여전히 아직 뭔가 수상한 웹처럼 보이지만 그래도 그 전보다는 나아진 것 같다. 로그인 완료시 헤더에 로그인 중인 사용자의 이름이 뜬다. 계정을 선택해서 성공적으로 로그인 되면 다시 이전 화면으로 돌아온다. 로그인 된 경우 local storage를 살펴보면 access token과 로그인 중인 사용자의 email, name 등이 들어가있는 것을 확인할 수 있다. 아직 하나도 안 꾸몄다 ㅋ 이렇게 로그인 유지 기능 구현 끝 ~~~~
[FBTB] 4. 로그인 유지 기능 구현 (OAuth2/JWT 관련 API)
·
Project/FromBookToBook
관련 도메인 OAuth2UserInfo package com.frombooktobook.frombooktobookbackend.security.user; import java.util.Map; public abstract class OAuth2UserInfo { // 키-값 쌍의 일반 Map에서 사용자의 필수 세부 사항을 가져오는데 사용 protected Map attributes; public OAuth2UserInfo(Map attributes) { this.attributes = attributes; } public Map getAttributes() { return attributes; } public abstract String getId(); public abstract String getEm..
[FBTB] 4. 로그인 유지 기능 구현 [1]
·
Project/FromBookToBook
드디어 로그인 유지 기능 구현 ! 이 부분에서 정말 많은 시간을 보냈다. 헤매기도 많이 헤매고 조금 힘들었지만 그만큼 다 해냈을 때 성취감은 말로 이룰 수 없었다. 일단 이전 로그인 구현은 react-google-login이라는 라이브러리를 사용해서 프론트단에서 access-token을 바로 얻게되었다. 하지만 이전 포스팅에도 적어놨듯이 이게 여간 찝찝한게 아니었다 .. 구현은 되긴 하는데 (비록 이메일과 이름만 받아오는거긴 하지만) 보안상으로도 엄청난 실수를 하는 느낌. (그치만 이 라이브러리가 존재하는 이상 어떻게 어떻게 안전하게 구현할 수 있는 방법이 있을 것 같기는 하다.) 그래서 google server에서 authorization code를 받은 뒤 백엔드 서버에 보내고, 백엔드단에서 goog..
[Error] UserControllerTest 중 Error
·
Project/FromBookToBook
- UserCreateRequestDto.java @Getter @Builder public class UserCreateRequestDto { private String email; private String nickname; private String password; public User toEntity() { return User.builder() .email(email) .nickname(nickname) .password(password) .build(); } } - UserControllerTest.java @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) public class UserControllerT..