프로젝트 목차
1. 프로젝트 개요
2. 담당 역할
3. 트러블 슈팅
4. API 명세서
5. ERD
6. 아키텍처 설계
1. 프로젝트 개요
프로젝트 정보
● 프로젝트 명 : EduWithMe
● 인원 : 4명
● 작업 기간 : 총 28일 ( 2024.07.20 ~ 2024.08.20 )
● Project / Git-Hub : https://github.com/five-star-school/eduWithMe-backend
서비스 설명
모든 연령과 배경의 사용자들이 언제 어디서나 접근할 수 있는 개인 맞춤형 학습을 통해 성장하며, 선생님과 학생 간의
상호작용을 강화하고 학습 동기를 높이는 교육 플랫폼입니다.
2. 담당 역할
[1] 실시간 채팅 기능
1. 실시간 채팅 기능 구현 목적
- 실시간 사용자 상호작용 필요성:
- 사용자들이 실시간으로 문제 해결을 논의하고 협업할 수 있도록 실시간 채팅 기능을 도입했습니다. - 서비스 경쟁력 강화:
- 사용자들이 플랫폼 내에서 더 오래 머무르며 적극적으로 참여할 수 있도록 실시간 채팅 기능을 추가하여 서비스의 가치를 높이고, 사용자 경험을 올릴 수 있다고 생각합니다.
2. 구현 기술 스택
- 백엔드: WebSocket / STOMP(Simple Text Oriented Messaging Protocol)
- Spring WebSocket을 사용해 실시간 양방향 통신을 구현했습니다.
- STOMP 프로토콜을 활용하여 메시지의 발행/구독(Pub/Sub) 모델을 통해 효율적인 메시지 브로드 캐스팅을 구현했습니다. - 프론트엔드: React.js / SockJS / Stomp.js
- React.js를 통해 사용자 인터페이스 개발
- SockJS와 Stomp.js를 통해 클라이언트에서 서버와 실시간 연결 구현 - 데이터베이스: MySQL
- 실시간 메시지와 채팅 기록을 저장하고 관리하기 위해 MySQL을 사용했습니다.
- 데이터의 일관성과 트랜잭션의 ACID 지원해주는 MySQL이 이에 적합하다고 판단 했습니다.
3. 구체적인 구현 내용
- 채팅 방 생성:
- 방 생성 후 채팅 모달을 누르게 되면 소켓 프로토콜 연결을 하게 된다. 해당 방에 대한 방 번호를 통해 채팅방 생성 또는 기존의 데이터가 존재할 시 불러오는 방식입니다. - 메시지 발행/구독 모델 구현:
- STOMP 프로토콜을 사용해 특정 채팅 방에 속한 모든 사용자에게 메시지가 실시간으로 전달되도록 Pub/Sub 구조를 구현했습니다.
4. 성과 및 결과
- 성장 기여:
- 실시간 채팅 기능에 대한 편리하다는 만족도가 전체 서비스 만족도의 20%를 차지 하며 많은 관심을 받았습니다.
[2] 배포 및 CI/CD 구축
1. 배포 및 CI/CD 구현 목적
- 배포의 필요성:
- 배포를 통해 클라이언트의 피드백을 받아 서비스의 개선점을 찾아서 보완하려는 목적에 도입을 하게 되었습니다.
- CI/CD의 필요성:
- 일일이 빌드를 직접하고 push하고 배포하는 반복적인 작업에 소요되는 시간이 많아 도입을 하게 되었습니다.
2. 구현 기술 스택
- 배포: AWS EC2 / Route 53 / https / Docker / Docker-Hub / Docker-Compose
- CI/CD: Git-Hub Actions
3. 구체적인 구현 내용
- AWS EC2:
- AWS EC2를 활용해 하나의 EC2 서버에 백엔드 서버 & 프론트 서버 & DB 배포하였습니다. - Route 53:
- https 인증서 발급을 위해 Route 53 도메인 서비스를 활용해 도메인을 구입해 이용하였습니다. - https:
- Certbot을 활용하여 SSL 인증서를 발급받아 https를 적용 시켰습니다. - Docker / Docker-Hub / Docker-Compose:
- 1. 작업하는 백엔드와 프론트엔드에 Dockerfile을 통해 이미지화를 시킨 후 Docker-Hub에 업로드
- 2. EC2 서버의 Dockerfile을 Docker-Hub에서 받아와 최신화
- 3. Docker-Compose를 통해 받아온 이미지들을 한 번에 전부 컨테이너화 시켜 띄웠습니다. - Git-Hub Actions:
- Git-Hub Actions 환경 변수 기능 사용하여 중요 정보에 대한 노출을 방지 하였습니다.
- 1. main branch에 push 되는 작업 트리거 설정
- 2. 백엔드 build / Docker image build 및 Docker-Hub push 설정
- 3. EC2 정보를 토대로 SSH를 이용해 EC2 접속 설정
- 4. Docker-Hub pull 작업 설정 및 Docker-Compose 명령어 수행 설정
4. 성과 및 결과
- 성장 기여:
- 배포를 통해 클라이언트의 피드백을 받아 서비스의 개선점을 찾아서 보완할 수 있었습니다.
- CI/CD구축을 통해 배포와 같이 반복적인 작업에 소요되는 시간이 줄어들어 AI 기능을 도입할 수 있었습니다.
3. 트러블 슈팅
[1] 조회 시 N + 1 문제
1. 문제 정의
- 발생 상황:
- 백엔드 로그를 확인하던 중 DB 조회 과정에서 N + 1 문제를 발견하게 됨.
- 문제의 대한 영향:
- 서비스에 대한 사용자가 적어 속도에 대한 큰 차이는 못느꼈지만, 불필요한 쿼리문이 남발되는 것에 대한 리소스 낭비가 추후에 문제를 일으킬 수 있다고 판단하게 되었습니다.
2. 문제 원인 분석
- 지연 로딩(Lazy Loading):
- 처음 즉시로딩을 이용하면 조회를 할 때 연관된 데이터를 한꺼번에 조회하기 때문에 성능 문제를 초래한다고 판단을 하여 지연 로딩 옵션을 추가 해주었습니다. 하지만, 지연 로딩 옵션 때문에 연관 된 데이터 조회 시 조인이 아닌 쿼리문을 하나씩 조회한다는 원인을 찾게되었습니다.
3. 문제 해결 과정
- fetch join:
- 필요할 때 연관된 엔티티를 한 번의 쿼리로 모두 가져올 수 있게 도와주는 fetch join을 이용해 문제를 해결했습니다.
4. 해결 결과
- 개선된 점:
- 불필요한 쿼리의 조회가 없어져, 성능 향상이 되었다고 판단하였고 향후 생길 문제를 방지하였습니다.
4. 배운 점 및 성찰
- 배운 점:
- 문제를 해결하는 과정에서 엔티티의 N:1 관계에서 N의 List와 N + 1 문제의 연관성을 자세히 배울 수 있었습니다.
- List를 지연로딩으로 설정하면, List에 저장된 연관된 엔티티를 실제로 사용할 때마다 개별 쿼리가 실행된다는 점을 알게되었습니다. 이때 발생하는 개별 쿼리가 N + 1 문제라는 점을 배웠습니다.
- 성찰:
- 대충알고 지나갔던 부분에서 이러한 성능적으로 큰 문제가 발생할 수 있다는 걸 알게되었고, 앞으로는 기술을 사용할 때에는 확실히 알고 써야되겠다고 생각을 하게 되었습니다.
[2] JPA 연관 관계 Foreign Key Constraint 오류
1. 문제 정의
- 발생 상황:
- 회원탈퇴시 회원이 탈퇴가 안되는 현상 발생
- 로그 확인 Cannot delete or update a parent row: a foreign key constraint fails 오류 확인
2. 문제 원인 분석
- JPA 외래키 제약조건:
- 해당 문제의 대한 로그를 분석해본 결과 외래키 제약조건의 오류로 확인을 했으며, 문제의 원인으로는 회원 엔티티와 연관 관계가 맺어져있던 다른 엔티티가 존재했으며, 해당 부모 엔티티인 회원 엔티티를 제거하려다 생긴 문제임을 알게 되었습니다.
3. 문제 해결 과정
- CASCADE 옵션 추가:
- 부모 엔티티가 삭제 될 시 자식 엔티티의 데이터도 함께 자동으로 삭제 해주는 CASCADE 옵션을 추가해주어 문제를 해결하였습니다.
4. 해결 결과
- 개선된 점:
- 불필요한 쿼리의 조회가 없어져, 성능 향상이 되었다고 판단하였고 향후 생길 문제를 방지하였습니다.
4. 배운 점 및 성찰
- 배운 점:
- 엔티티간 연관관계를 맺으면 자동으로 FK 즉, 외래키 제약조건이 맺어진다는 사실을 깨닫게 되었습니다.
- CASCADE 옵션을 추가해주어 문제를 해결해주었지만, 해당 옵션을 남발하여 이용을 하게 되면, 한 번의 실수로 중요한 데이터가 함께 삭제되어 날라갈 수 있기 때문에 상황에 맞게 사용을 해야한다는 점을 알 수 있었습니다.
- 성찰:
- 간단한 문제이지만, 해당 문제를 해결하며 JPA에 대한 많은 점을 알 수 있었던 계기가 되었고 기술을 이용해 구현하는것도 중요하지만, 더욱 중요한건 기술에 대한 이해라는 점을 깨닫게 되었습니다.
4. API 명세서
Notion Link
5. ERD
6. 아키텍처 설계
'내일배움캠프 Spring 5기' 카테고리의 다른 글
내일배움캠프 62일차 TIL - JPA(CascadeType, OrphanRemoval) (0) | 2024.07.16 |
---|---|
내일배움캠프 61일차 TIL - 쿼리 최적화 (0) | 2024.07.13 |
내일배움캠프 60일차 TIL - Security 예외처리 (0) | 2024.07.13 |
내일배움캠프 59일차 TIL - 심화 프로젝트 설계 (0) | 2024.07.10 |
내일배움캠프 58일차 TIL - Redis (0) | 2024.07.09 |