백엔드 개발 포트폴리오 | 오프라인 파티원 모집 플랫폼
내일배움캠프 4기 웹 개발 과정 Spring 트랙 수료생 최종 프로젝트 ‘새모임’을 소개합니다.
Aug 17, 2023
새로운(New) 모임, 새(Bird)처럼 자유로운 모임
모임관리, 추억 공유, 실시간 소통까지 함께할 수 있는 환경을 제공합니다.
- 서비스 둘러보기 : http://saemoim.site/
- Github Repository :
⚙️ 서비스아키텍처
⚒️ 기술적 의사결정
사용기술 | 기술설명 |
Redis
In-Memory DB | 엑세스 토큰 만료 후 재발급 할 때 로그인 시 발급된 엑세스 토큰과 리프레시 토큰을 매칭하여 같이 발급 된 정상 토큰인지 확인하기 위함. 토큰 같은 경우, 데이터가 날아가도 큰 문제 없기 때문에 속도적인 측면을 고려하여 RDB가 아닌 Redis 선택.
이메일 인증 코드 또한 휘발성 데이터이기 때문에 TTL설정 후 Redis에 저장. |
Redis Cache | 인기모임은 순위가 자주 바뀔 경우가 희박하기 때문에 매번 DB를 조회하지 않기 위해 캐싱 선택 |
Java MailSender | 회원가입 시 이메일 확인, 비밀번호 찾기 시 임시 비밀번호 발급을 위한 메일 발송을 위해 선택 |
OAuth2 | 소셜로그인을 통한 간편한 로그인/회원가입을 위해 선택 |
페이징
Page/Slice | 데이터 양이 많을 모임 조회의 경우엔 Slice를 사용하여 카운트쿼리가 실행되지 않게 하고 게시판의 경우엔 상대적으로 데이터 양이 적을 경우와 UI 측면에서 Page를 선택 |
STOMP | 모임 별 채팅방 생성을 위해 도입. 모임 id 정보로 토픽을 나누어 채팅 기능을 구현하였고, 채팅 메세지에 유저 id와 모임 id를 함께 저장해 DB에 저장 후 불러오기를 구현함. 통신 시 토큰 인증과정을 추가하여 보안을 강화하였음. |
SockJS | 기존 WebSocket 만으로는 브라우저 호환성 문제와 프록시 서버 연결 끊김 등의 문제가 발생하기 때문에, 이런 단점들을 보완한 WebSocketEmulation (SockJS)를 도입하여 WebSocket이 불가능한 경우 다른 대체 기술로 전환 가능 |
Github Action | 프로젝트 협업을 위한 코드 호스팅 툴로 Github를 사용하고 있는데 같은 환경에서 CI가 가능하고 익숙한 문법의 yml 파일로 동작 구성 가능 |
S3 | 이미지 파일 관리를 위해 도입
방안 서버, DB, 외부 저장소
의사결정 서버 비용 증가와 DB 성능저하를 고려해 금전적 비용 발생에도 불구하고
성능 저하 이슈 모면과 배포 등 추가 활용과 관리상 편의를 위해 S3 선택 |
지도API | 오프라인 모임을 모집하는 플랫폼이다 보니 모임 장소에 대한 정보를 보여줄 지도 api가 필요, 국내에서 주로 사용되는 서비스이고 기능적으로 큰 차이가 없는 카카오나 네이버 지도 중 더 친숙한 카카오 api를 선택 |
Rest Docs | API 문서 자동화를 위해 적용.
swagger와는 다르게 프로젝트 코드에 영향이 없고 테스트코드로 검증된 문서를 보장할 수 있다는 장점으로 선택 |
🖇️트러블슈팅
1. 서비스 간 의존성 문제
문제상황
1. 객체지향 원칙을 지키려 기능을 최대한 분리하려 했을 때
서비스가 다른 서비스를 의존하게 되는 경우 발생
해결방안
1. 같이 동작해야 하는 서비스라면 기능 분리하지 않음
2. 양방향 연관관계 사용
의사결정
1. 서비스의 책임을 생각하면서 기능 분리
2. 지연 로딩을 사용하고 문제점을 인식하고 사용, 서비스간의 의존성을 줄일 수도 있어서
같이 동작해야 한다면 연관 관계를 맺어주기로 결정1-1. JPA N+1문제
문제상황
연관 관계가 맺어진 테이블 조회 시 N+1문제 발생
해결방안
ManyToOne을 맺어준 테이블은 jpql Fetch Join을 사용하여 조회하고
OneToMany로 맺어준 테이블은 @Fetch(FetchMode.SUBSELECT)을 사용해서 쿼리가 적게 날아가도록 개선2. 모임 조회 시 참가자/좋아요 수 조회 카운트쿼리 중복
문제상황
참가자 테이블과 좋아요 테이블이 각 존재해 모임 조회 시 해당 수를 조회하기 위해
매번 각 테이블에 카운트 쿼리를 날려야 함
해결방안
모임 테이블에 참가자 수 필드, 좋아요 수 필드 생성
의사결정
정합성 문제 발생 가능성도 고려했지만
트랜잭션을 잘 사용하여 참가자/좋아요 컬럼 생성/삭제 시
모임의 필드 값을 바꿔주도록 해서 조회 시 카운트 쿼리가 매번 날라가지 않도록 결정3. S3 미사용 파일 축적 문제
문제상황
이미지 수정 시 기존 이미지가 삭제되지 않고 저장소에 남아 계속해서 쌓이게 됨
해결방안
이미지 수정 시 기존 파일을 삭제하는 메서드 추가
의사결정
s3 가 제공하는 life cycle을 통해 일정 기한이 되면 삭제되게 하는 것도 고려 했으나,
사용되는 이미지 객체 삭제 위험 가능성. life cycle이 동작하기 전까지 데이터가
계속 쌓이게 되는 문제는 여전하다 판단되어, 이미지 수정 시 기존 이미지는 즉시 삭제 되도록 함4. 반환 타입 ResponseEntity<T>로 통일
문제상황
반환값 없이 메세지만 반환할 땐 ResponseEntity<MessageDto>로 반환하고
반환값이 있는 경우엔 Dto객체로 반환하여 반환 타입 통일 필요성 발생
해결방안
ResponseEntity<T>로 통일, List와 String타입 또한 Dto에 담아서 ResponseEntity로 반환
의사결정
Http통신에서 커스텀헤더를 응답으로 내려줄 상황 고려,
RESTful하게 설계하여 ResponseEntity사용 결정5. 실시간 채팅 시 보안 문제
문제상황
웹소켓 연결 후 메세지 송수신 시 인증 체계가 없어,
외부에서 접속하여 userId 값만 변경하면 사칭이 가능
해결방안
메세지에 인증 토큰이 들어있는 헤더를 추가하고, 서버에서 인증 과정을 추가하여
로그인 된 사용자 외에는 채팅이 불가능하도록 적용Share article
Subscribe to our newsletter