🧑💻 개발 기간 : 2023.05.19 ~ 2023.06.30
👉 서비스 URL : https://www.study-hub.shop 🏅 항해14기 최고의 인기 프로젝트상 수상!
| 사용 기술 | 기술 설명 |
|---|---|
| Styled-Components | 다른 CSS-in-JS 라이브러리와 비교해 논의 후 Styled-Components를 사용한 이유는 가독성과 유지 관리를 개선하며, 고유한 클래스 이름을 생성해 충돌을 최소화할 수 있다는 장점이 있기 때문입니다. 또한, Styled-Components를 통해 컴포넌트에 props를 전달할 수 있어 스타일 속성의 동적인 사용이 용이하며, 이에 따라 개발의 유연성이 증가 하기에 사용하였습니다. |
| React Query | React Query는 웹 애플리케이션에 사용자 경험을 향상시키기 위해 도입된 기술입니다. 쿼리 캐싱 처리를 통해 서버 부하를 최소화하고 이미 요청한 데이터를 빠르게 불러올 수 있습니다. 사용자는 최신 데이터를 실시간으로 확인할 수 있으며 데이터 재로드할 필요가 없습니다. 이러한 장점들과 함께 isLoading과 isError를 사용하여 에러 처리를 유연하게 할 수 있어, 전반적인 데이터 처리를 최적화하여 사용자에게 더 나은 경험을 제공하기 위해 사용하였습니다. |
| Vercel | Vercel을 사용한 이유는 프로젝트를 더욱 원활하게 관리하고 배포를 최적화하기 위해서 입니다. Vercel은 GitHub에 푸시(pushing)될 때마다 자동으로 배포하는 기능을 제공하며, 이로 인해 개발 및 배포 프로세스가 매우 간단해지기에 사용하였습니다. |
| Axios | Axios를 사용한 이유는 Fetch와 비교하여 에러 객체를 통해 상세한 응답 정보를 제공할 수 있기 때문입니다. 또한, API 요청 시 토큰의 존재여부에 따라 토큰의 재발급 및 재요청 작업을 효율적으로 수행할 수 있는 Axios interceptor 기능이 제공되어 API 통신을 보다 효과적으로 구현할 수 있기에 사용을 하였습니다. |
| 사용 기술 | 기술 설명 |
|---|---|
| CI/CD - EC2 + GitHub Action | 프론트가 원활하게 작업하기 위해서는 최대한 빨리 서버가 띄워져야 한다고 생각했으며, dev branch에 코드가 merge 될 때마다 배포를 위해 반복적인 작업 최소화하고 서버 개발에만 집중할 수 있도록 CI/CD 환경을 구축하기로 결정하였습니다. Jenkins와 gitHub action + EC2 두 가지 선택지 중 GitHub Action이 GitHub 와의 연동이 편하고 빠른 시간 내에 배포할 수 있는 장점이 있으며 GitHub에서 발생하는 이벤트를 처리할 수 있다는 점을 통해 해당 선택지를 도입하게 되었습니다. |
| Nginx | 배포할 때마다 서버가 잠시 중단되는 상황에 의해 유저들이 서비스를 이용 중에 중단되는 불편함이 있어 무중단 배포인 Nginx를 도입하게 되었습니다. |
| OpenVidu | N대N 화상 채팅을 구현하기 위해서 시그널링 서버를 통해서 P2P로 연결하는 방식과 미디어 서버를 두는 방식이 존재하는데 P2P로 구현하기에는 클라이언트에 부담이 너무 크며, OpenVidu 플랫폼을 이용하여 미디어 서버를 둠과 동시에 시그널링 처리도 맡길 수 있기 때문에 결정하게 되었습니다. |
| Stomp | Stomp 프로토콜은 메시지 전송을 위한 프로토콜로써 pub/sub 기반으로 동작하며 메시지 헤더를 가지고 있기 때문에 메시지의 송신, 수신에 대한 처리를 명확하게 정의 할 수 있는 장점이 있습니다. 추가적인 작업 없이 메시지 발행 시 엔드포인트만 조정하여 쉬운 전송/수신 또한 가능하여 도입하게 되었습니다. |
| Oauth2 | 소셜 로그인을 도입하게 된 가장 큰 이유는 사용자의 편의성 증대를 위해서 입니다. 클릭 몇 번 만으로 로그인을 할 수 있는 편리성을 통해 사용자들이 이 웹을 더 찾을 수 있는 이유를 제공하기 위해서 입니다. |
| Sentry | 로컬에서 정상적으로 동작하는 경우도 서버에서는 그렇지 않은 경우가 매우 많았기 때문에 간편하게 서버의 에러 로그를 볼 수 있는 필요성을 느끼게 되었고 실시간 오류 모니터링 및 로깅 플랫폼으로서, 애플리케이션에서 발생하는 예외, 오류, 경고 등을 실시간으로 수집하고 중앙화된 대시보드에서 확인할 수 있도록 지원하는 Sentry를 도입하게 되었습니다. |
| Redis | 클라이언트와 계속 교류가 일어나는 토근 정보나 웹페이지 내에서 접근이 잦은 마이페이지 같은 부분에서 사용되는 데이터를 계속 DB에서 조회해오는 것이 비효율적이라고 생각되어 오픈 소스 인 메모리 키 값 데이터 구조 스토어인 Redis를 도입해 캐싱을 적용하였습니다. |
| Spring Batch | 특정한 시점에 스케줄러를 통해 자동화된 작업과 트랜잭션 관리와 함께 통계 처리를 효과적으로 하기 위해 대용량 일괄처리 편의를 위한 다양한 기능을 제공하는 Spring Batch를 도입하게 되었습니다. |
| JUnit5 + Mockito | 테스트 코드를 사용하면 개발 과정 중에 발생할 수 있는 예상치 못한 문제를 컴파일 시점에서 찾을 수 있습니다. 이는 런타임 오류를 방지하고, 버그를 사전에 발견하여 디버깅 시간을 절약할 수 있습니다. 또한 작성한 코드가 의도한 대로 동작하는지 확인할 수 있습니다. 테스트 코드는 예상되는 입력과 출력을 정의하고, 코드 실행 결과를 확인하여 코드의 정확성을 검증하는 역할을 합니다. 이를 통해 코드 변경이나 리팩토링 후에도 기능의 동작이 올바른지 확인할 수 있기 때문에 도입하게 되었습니다. |
💥 스터디룸 입장 시 openVidu 세션 연결 이슈
문제
스터디룸 입장 후 바로 마이크나 카메라를 끄면 openvidu 세션 연결이 되지 않는 오류가 발생
시도
Redirect 페이지를 방 입장후 setTimeOut을 적용하여 3초가 지난 후 스터디룸 페이지가 보이게 하여 마이크나 카메라에 대한 조작을 할 수 없게 하려고 하였다.
하지만 시간만 적용을 해주면 유저별 세션 연결 시간에 대한 편차가 있어서 redirect 페이지가 사라진 후에도 세션 연결이 안된 유저가 마이크나 카메라를 껐을 때 여전히 세션 연결이 되지않았다.
해결
스터디룸 입장 후 세션연결하는 코드안에 redirect 페이지를 넣어줘서 이전처럼 시간이 지난 후 스터디룸이 보이는 아니라 세션 연결이 완료 된 후 스터디룸 페이지가 보이도록 수정
💥 스터디룸에서 상대방의 카메라, 마이크 상태 확인 이슈
문제
OpenViduLogger(오픈비두 콘솔 메세지)는 상대방이 카메라나 마이크를 켜거나 끄는 작업(publish/unpublish)을 볼 수 없음.
유저는 자신이 수행한 카메라/마이크 상태 변경만 확인할 수 있으며, 상대방의 카메라/마이크 유무를 확인하지 못 하는 문제 발생
시도
'streamPropertyChanged' 오픈비두 이벤트를 사용하여 stream을 변경할 때만 상태를 업데이트 시도.
그러나 오픈비두는 내가 발행자이자 구독자이기 때문에 정확히 구분하는 방법이 어려워서 이 이벤트를 사용할 수 없
해결
'streamManager'를 사용하여 문제 해결, 'streamManager'를 통해 구독자와 발행자를 구분 가능.
'streamManager.stream.audioActive'와 'streamManager.stream.videoActive'를 사용하여
나와 상대방의 오디오 및 비디오 상태를 확인하고, UI를 업데이트할 수 있었다.
이렇게 함으로써 상대방이 마이크나 카메라를 끄거나 켤 때 이를 시각적으로 알 수 있게 됨.
해결 코드
💥 OpenVidu 세션이 종료되는 이슈
문제
OpenVidu 서버에 생성된 세션이 주기적으로 삭제되거나, 한번이라도 Connection이 발생한 후 Connection이 하나도 존재하지 않게될 경우 세션이 삭제되는 문제 발생
시도
- env 파일을 수정하여 OPENVIDU_SESSIONS_GARBAGE_INTERVAL 값을 0으로 수정하면 Garbage Collector가 비활성화됨과 동시에OPENVIDU_SESSIONS_GARBAGE_THRESHOLD 속성 또한 무효화가 되기 때문에 Interval 값을 0으로 수정
- 유저가 이미 삭제된 세션으로 접근할 경우 새로운 세션을 생성해서 해당 세션에 유저를 입장시키는 방법
해결
스터디룸에 유저 입장 -> OpenVidu 서버에 활성화되어 있는 세션 목록 로드 -> 입장하고자 하는 세션 ID가 존재할 경우 해당 세션으로 입장 -> 해당 세션이 없을 경우 입장하고자 했던 세션 ID와 똑같은 ID로 Custom 세션 생성 및 입장 과정을 통해 유저 입장에선 세션이 종료되지 않고 계속 존재하는 것처럼 인식할 수 있도록 수정하여 해결
해결 코드
💥 방 생성 및 방 입장 동시성 이슈
문제
- 한 방에 입장은 9명까지 가능
- 방 생성 시 한 유저 당 3개의 방을 생성 가능
- 방 입장 시 한 유저가 같은 방을 여러 번 입장할 수 없고, 이미 입장한 방 이외에 다른 방 입장 불가
위 조건들에 대한 예외 처리는 되어있지만, Jmeter를 이용한 동시성 테스트 결과 전부 동시성 제어가 되지 않아 원하는 대로 처리가 되지 않음
시도
- RabbitMQ와 같은 메세지 브로커를 이용하여 요청을 메세지 큐에 담아서 처리하고 요청 자체에 대한 동시성 제어를 시도
- 동기화 기법 및 DB Lock 사용
해결
Pessimistic Lock을 이용하여 DB에 동시 접근을 막아서 해결
해결 전, 후 테스트
❕마이페이지 조회 성능 개선을 위한 통계 쿼리 최적화 방안
기술 도입 배경
유저로부터 접근이 잦은 마이페이지를 조회할 때마다 통계를 계산하고 조회하는 쿼리가 생성되고 있는데 이를 개선할 수는 없을까?
기술 구현 과정
Redis에 통계 데이터를 저장하여 캐싱을 적용하고, 수정이 필요한 당일 데이터에 변경이 일어날 때만 통계 데이터에 값을 수정.
이에 따라, 마이페이지를 조회할 때마다 쿼리를 생성하지 않아도되고 데이터를 조회하는 속도 또한 향상될 수 있도록 하였다.
고민
단순히 Key Value 구조로만 저장하기에는 모든 멤버의 일별, 주별, 월별 데이터를 다른 멤버들과 구분되게 넣기가 어려운데, 어떤 방법이 있을까?
해결 방안
Redis가 제공하는 자료구조 중 Value로 또 다른 Key Value Map을 넣을 수 있는 Hash 자료 구조를 이용하여 모든 멤버들의 통계 데이터를 구분해서 넣을 수 있도록 하였다.
❕스터디 룸 만료 처리와 자동화된 통계 데이터 관리 방법
기술 도입 배경
만료기한이 된 스터디룸 처리와 함께 통계 데이터를 효과적으로 자동화해서 처리할 수 있는 방법이 무엇이 있을까?
기술 구현 과정
대용량 일괄처리 기능을 제공하는 Spring Batch와 작업을 자동화할 수 있는 Spring Schedular를 사용하였다. 스케줄러를 매일 자정에 한번 씩 수행되도록 설정하고 1. 만료된 방을 삭제 2. 사용되지 않는 OpenVidu 세션 삭제 3. 통계 데이터 저장 을 3개의 Step으로 구성하여 일괄 처리를 자동화하였다.
고민
처리 방식을 어떻게 정할 것인가?
해결 방안
실행할 작업이 복잡하고 읽기, 처리 쓰기와 관련된 작업을 수행해야하는 통계 작업은 Chunk 방식으로 처리하였고, 비교적으로 처리가 단순하고 처리량이 많지 않은 나머지 작업들은 Tasklet 방식으로 처리하였다.
| 강한빛 | 김시옥 | 🚩신민철 | 🚩김근보 | 박성우 | 한승희 |
|---|---|---|---|---|---|
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
| FRONT-END | FRONT-END | FRONT-END | BACK-END | BACK-END | BACK-END |

















