💻Front-End
요구사항 |
고려한 기술 |
기술 선택 이유 |
프로젝트 빌드 |
vite |
- ES 모듈 기반의 빌드 시스템을 사용하여 브라우저가 필요로 하는 코드만 빌드하므로 번들 크기를 최소화하고 초기로딩 속도를 향상시킨다. |
- 기존 cra는 사용하지 않는 기능까지 전부 설치되기 때문에 모듈 사이즈가 크다.
- 절대경로 설정이 편리하다. (별도의 라이브러리 추가 없이, vite.config.ts, tsconfig.json에서만 변경하면 된다.) |
| 프로젝트 언어 | TypeScript | - 정적 타입의 컴파일 언어로 코드 작성 단계에서 타입 에러를 잡아낼 수 있다.
- 변수나 함수의 타입을 명시해 작성자의 의도를 명확하게 전달할 수 있다.
- 정의된 타입은 이후 자동완성을 제공해 휴먼에러를 줄이고, 생산성을 향상시킨다.
- 서버로부터 받는 response와 같이 정해지지 않은 데이터에 대한 타입을 미리 명시할 수 있다. |
| 스타일링 라이브러리 | Styled-Components | - CSS-in-JS 형식으로 css파일이 해당 컴포넌트 범위로 한정되므로 전역 스코프의 스타일 충돌을 방지할 수 있다.
- prop으로 내려받아 동적인 css 스타일링이 가능하다.
- 스타일을 모듈화하여 재사용이 용이하고, 스타일컴포넌트를 확장하거나 변형할 때도 상속을 통해 간편하게 적용할 수 있다.
- 서버 사이드 렌더링을(ssr) 지원하여 초기 로딩 성능을 향상시킬 수 있다. |
| 서버 상태 관리 | Tanstack/React-Query | - 서버로부터 받는 데이터의 캐싱 및 캐싱 전략으로 서버와의 통신을 최소화할 수 있다.
- 라이브러리에서 제공하는 다양한 옵션으로 api요청 및 결과와 관련된 로직들을 간단하게 처리할 수 있다.
- 프론트 상태와 서버 상태를 분리해 관리할 수 있으며, 리덕스 사용 시 비동기 작업을 위한 코드 등의 추가 작업을 크게 줄일 수 있다. |
| 실시간 채팅 기능 | Sockjs-client | - SockJS는 웹소켓을 지원하지 않는 브라우저에 대한 *대체 방법을 제공하며, 클라이언트와 서버 간 통신을 가능하게 한다.
*대체 방법 : WebSocket을 지원하지 않는 경우에는 폴백(fallback) 메커니즘을 사용하여 다양한 트랜스포트(예: HTTP long polling)를 통해 통신
- SockJS-client와 StompJS를 사용하면 서버와의 소켓 연결 상태를 쉽게 관리할 수 있어,
연결이 성공했을 때와 실패했을 때의 처리, 연결이 끊겼을 때의 자동 재연결 등을 다룰 수 있다. |
| 실시간 채팅 기능 | Stompjs | - STOMP는 단순하고 텍스트 지향적인 메시징 프로토콜로, Spring과 호환되며 구독 방식을 통해 효과적인 통신을 제공한다.
- JavaScript에서 사용할 수 있도록 지원하는 라이브러리인 StompJS 라이브러리를 사용하였다.
- 서버의 특정 주제(topic)에 구독(subscribe)하여 메시지를 수신하고 처리할 수 있다. 이를 통해 실시간 업데이트나 이벤트 기반 통신을 구현할 수 있다. |
| 지도 기능 | react-kakao-maps-sdk | - 네이버 지도 api 와 비교해 공식문서가 잘 갖춰져 있으며, 관련 레퍼런스를 많이 확보할 수 있다.
- 카카오 맵 sdk를 사용할 경우 리액트 프로젝트에서 보다 쉽게 지도 기능을 적용할 수 있으며, 제공하는 API를 활용해 원하는 기능을 빠르게 구현할 수 있다. |
💻Back-End
요구사항 |
고려한 기술 |
기술 선택 이유 |
CI/CD |
- GithubActions |
|
- Jenkins
- Docker | ✅ GithubActions
- GithubActions는 잘 만들어진 템플릿을 통해 간단하게 CI/CD 설정이 가능했으며, 무엇보다 Github와 연동되어 접근성이 좋았습니다.
❌ Jenkins
- Jenkins는 참고할 자료가 다양했지만, 알아야 할 설정들이 많았습니다.
- 플러그인 의존성이 높아, 플러그인 업데이트가 있을 경우, 개발자가 업데이트를 추적하여 유지보수해야하는 단점이 존재했습니다.
- AWS Infra구성이 변경될 경우, 이에 따른 플러그인 추가 관리가 필요한 것으로 예상이 됩니다.
————————————————————————————————————————————————————————————-
✅ Docker
- 도커는 컨테이너화된 환경을 제공했기 때문에, 개발 환경과 운영 환경의 일관성을 유지할 수 있습니다.
- 또한, 컨테이너 기반으로 가볍게 배포할 수 있었기에, 해당 기술을 선택했습니다.
- Docker Hub를 통해 CI/CD 환경을 편리하게 구축할 수 있었습니다. |
| Refresh Token 저장 | - Redis | ✅ Redis(In-memory DB)
- RDB와는 다르게 TTL(Time-To-Live) 즉, 데이터의 만료일을 지정할 수 있습니다.
→ TTL을 토큰의 만료일과 똑같이 맞춰두고 관리하면 토큰 만료시 Redis에서 자동으로 삭제 되기 때문에 데이터 관리가 용이합니다.
- 리프레시 토큰은 액세스 토큰을 재발급 하는 과정에서 자주 호출하기 때문에, RDB에 저장하는 것보다 In-Memory DB에 저장하는 것이 훨씬 속도가 빠르기 때문에 Redis를 사용하는 것이 더 효율적입니다.
————————————————————————————————————————————————————————————-
❌ PostgreSQL(RDBMS)
- 현재 사용중인 데이터베이스에서는 리프레시 토큰을 만료시키기 위해 주기적으로 만료된 토큰에 대한 삭제 요청을 보내거나 스케쥴러를 사용해야하는데 이 작업이 비효율적입니다. |
| 위치 기반 모임 리스트 구현 | - PostgreSQL
- MySQL | ✅ PostgreSQL
- PostgreSQL 는 PostGIS extension 을 활용하여 다양한 위치 공간 조회가 가능하고, GiST 인덱싱을 사용하여 위치 관련 칼럼을 조회하는데에 용이합니다.
- PostgreSQL 의 jsonb 형식은 JSON 데이터를 이진 형식으로 저장하고 indexing 이 가능하여 반정규화된 데이터의 읽기 처리 성능을 최적화할 수 있습니다.
❌ MySQL
- MySQL은 설정과 관리가 상대적으로 간단하고, 초기 설정과 운영이 PostgreSQL보다 간단해 생태계가 넓고, 확장성이 뛰어납니다.
- PostgreSQL 와 달리, 복잡한 위치 타입이나 json 타입의 고급 쿼리 기능을 지원하지 않습니다. |
| 실시간 채팅 기능 구현 | - STOMP
- Long Polling | ✅ STOMP over WebSocket
- Spring 의 내장 spring-websocket 모듈 통해 쉽게 구현 가능합니다.
- 단순히 웹소켓을 사용할 때와는 다르게, STOMP에는 메시지의 형식, 유형, 내용 등을 정해져있어 별도로 개발자가 규격을 정하지 않아도 메시지를 쉽게 전달할 수 있습니다.
❌ Long Polling
- 클라이언트가 서버에 요청을 보내고 서버가 새로운 데이터가 있을 때까지 응답을 보류하는 방식입니다.
- 모임별 채팅의 양은 많을 것으로 예상되어, 서버 부하와 네트워크 오버헤드가 있을 것으로 예상됩니다. |
| 검색/ 조회 | - QueryDsl
- JPQL | ✅ QueryDsl
- 컴파일 시점에 타입을 체크하여 오타나 잘못된 속성을 사용하는 오류를 사전에 방지하여 안전한 쿼리 작성이 가능했습니다.
- 동적 쿼리를 쉽게 작성하고 변경할 수 있어서 유지보수가 용이하며, 코드의 가독성과 이해도를 높일 수 있었습니다.
- 복잡한 Join문과 Where 조건절을 간편하게 작성할 수 있었습니다.
✅ QueryMethod
- 간단한 쿼리는 QueryMethod를 통해 작성했습니다.
❌ JPQL
- 서비스 특성 상 특정 위치 기반 모임 조회 등 동적 쿼리를 자주 사용하는데에 반해, JPQL 은 문자열로 구성되어, 동적 쿼리를 구성하는 것이 어렵습니다.
- 가독성이 떨어져 유지 보수가 어렵습니다. |
| 로그인 | OAuth2.0 | ✅ Oauth2(소셜 로그인)
- 사용자가 가장 편안한 방법을 선택할 수 있어 사용자 경험 측면에서 이점이 있습니다.
- OAuth2 공급자(카카오, 네이버 등)가 제공하는 보안 메커니즘을 활용하여 자격 증명을 시스템에 노출하지 않고 사용자를 인증할 수 있습니다
- OAuth2는 비밀번호가 아닌 토큰을 사용하기 때문에 도용의 위험이 줄어듭니다.
❌ 일반 로그인
일반 로그인 시스템에는 일반적으로 사용자 이름/비밀번호 조합이 포함되고, 이는 비밀번호 추측, 피싱 공격, 무차별 공격과 같은 취약성에 취약할 수 있습니다. |
| 유저 모니터링 구축 | - Prometheus & Grafana
- Actuator
- NodeExport | ✅ Prometheus & Grafana
- 채팅 테스트를 진행하던 중 메모리가 상승하는 것을 알 수 있었습니다. 그 결과 서버가 다운되었고, 메모리와 CPU를 모니터링하기 위해 도입했습니다.
- 수집된 메트릭을 이용하여 모니터링을 진행해주는 Prometheus 와 시각화를 위해 Grafana를 사용하였습니다.
✅ Actuator
- 스프링에 메트릭을 수집하기 위해 스프링에서 제공하는 Actuator를 도입했습니다.
✅ NodeExport
- 애플리케이션 레벨이 아닌, 시스템 레벨 모니터링 필요했습니다.
- 인스턴스 서버의 리소스 정보를 확인하기 위해 도입했습니다. (Scale Up) |