Fashion Cloud — PoC 이후

jeonghyeon kim
6 min readNov 25, 2023

--

이전 글 — 프로젝트 소개글

⛅ Fashion Cloud — 지금 여기 날씨, 지금 우리 스타일

패션클라우드는 날씨가 비슷한 다른 지역 사람들과 데일리룩을 공유하여,

오늘 날씨에 가장 적합한 패션을 파악할 수 있게 돕는 서비스이다.

이번 글에서는 추가된 기능과 기술 포인트, 또한 PoC전후로 달라진 부분에 대해서 기술하고자 한다.

추가 기능

기존 PoC단계에는 없었던 스토리 기능, 인증 및 인가 기능, 사용자 타임라인 기능, 팔로우 기능 등을 추가로 구현했다.

기획이 변경되어 이전 소개글에서 설명했던 기능 중 일부는 제외되었다.

🔓 Spring Security를 이용한 로그인 기능 구현

sns서비스 특성상, 기존 PoC단계에서 제외했던 로그인 기능을 구현할 필요가 있었다. 이를 위해 JwtAuthenticationFilter 필터로 토큰을 검증하는 로직을 추가하였다.

Filter Chain 로직을 중복으로 거치게 되는 경우를 막기 위하여 GenericFilterBean이 아닌 OncePerRequestFilter를 상속받아 Filter를 구현했다.

로그인한 유저의 정보가 필요한 경우 @AuthenticationPrincipal을 사용해 받아온 정보를 가지고 User엔티티를 로드하는 로직이 중복 발생하는 점을 개선하고, 더 직관적인 네이밍을 사용하기 위해 이를 담당하는 @LoginUser 어노테이션을 사용하였다.

🔗 Spring Security 인증 과정, GenericFilterBean vs OncePerRequestFilter

🔓 Next.js로의 마이그레이션, 상태관리 라이브러리 변경

PoC이후, API훅 분리 작업을 진행하고 바로 Next.js로의 마이그레이션을 진행했다. 이 때 Recoil을 사용할 때의 문제점이 발생했다. 바로 Next.js의 핫리로드 동작에서 발생하는 문제였다.

Next.js는 개발 중 파일이 변경되면 해당 파일을 다시 build하는데, 이 때 atom으로 만든 state가 재선언된다. 항상 고유해야 하는 key값이 이 재선언 과정에서 재사용되므로, Recoil의 Atom key가 중복되는 문제가 발생한다.

이를 해결하기 위해 RecoilEnv를 통한 환경변수 재설정 혹은 atom key에 난수를 사용하는 방법이 있으나, 우리는 Zustand로 변경하여 해결했다.

🔗 Next.js의 동적 렌더링, React -> Next.js로의 마이그레이션

🟥 캐싱 1. — 조회수 기능에 Look Aside + Write back 캐싱 적용

DB로의 잦은 쓰기 작업은 디스크의 쓰기 비용에 부담을 준다. 따라서 쓰기 작업이 잦은 조회수 기능의 경우, 많은 서비스들이 후기입 방식을 채택하고 있다. Youtube역시 조회수를 캐시에 저장하고, 주기적으로 DB에 동기화하는 방식으로 동작한다.

이 때 업데이트 주기를 길게 설정하면 단일 Redis노드를 사용하다가 장애가 발생하여 추가 조회수 카운트가 유실됐을 때 실제 조회수와 차이가 커지므로, 5분 단위로 설정하기로 했다.

추가로 조회수 중복 방지에 대한 논의가 있었다. 한 사용자가 집중적으로 조회수를 올리는 경우를 방지하기 위해 일반적으로 ip주소나 쿠키를 사용한 중복 방지를 사용하는데, 쿠키의 경우 사용자가 쿠키를 삭제하거나 다른 브라우저를 사용할 때 조작이 가능하다는 문제점이 있었다.

ip주소를 사용하는 경우 역시 ip주소가 유동적이라는 점 때문에, 조회수 중복 방지를 정확하게 구현할 수 없다.

논의 끝에 우리는 조회수의 중복이 크게 중요하지 않은 서비스이며, 빠르게 작업해야하는 기능이 있었으므로 조회수 중복을 구현하지는 않았다.

🟥 캐싱 2. — key구성 변경하기, 단위 분리하기

기존에 스케줄러를 이용해 캐시된 데이터를 업데이트하는 작업이 있었다. 이는 매우 비효율적인 작업이었는데, 이 방식을 채택함으로서 발생하는 오버엔지니어링이 엄청났기 때문이다.

또한 기존에는 두 개의 open api를 호출한 뒤 하나로 결합한 결과물을 캐싱했었다. 이 때 둘 중 하나의 api에서 문제가 발생한다면 정상적으로 응답을 받은 api response도 사용할 수 없다는 문제가 발생한다.

위 두 가지의 문제점을 key에 baseTime을 설정해 hit된 데이터의 유효성을 보장하는 방법과, response dto로 결합되기 전 분리된 각각의 데이터를 따로 저장하는 방법으로 해결했다.

🔗 Redis key만으로 오버엔지니어링 줄이기

💻 배포 환경 변경

기존에는 AWS EC2 인스턴스에 전체를 Docker 컨테이너로 빌드하여 배포하였고, 따라서 배포 자동화 역시 해당 EC2 인스턴스에서 rebuild하는 방식이었다.

[🔗 Github Action + Docker를 통한 EC2 인스턴스 배포 자동화]

Next.js로 마이그레이션한 이후, vercel로 재배포했다.

📈 조회 API 무한호출 문제 수정

데일리룩을 조회할 때 체감기온을 설정한다. 기존에는 슬라이더의 온도 조절 버튼을 하나로 두어 선택한 온도에서 +-1도 범위를 검색하도록 했다.

이 때 슬라이더를 움직이는 과정에서 슬라이더를 조절할 때마다 api가 연속적으로 계속하여 호출되는 문제가 발생했다.

이를 해결하기 위해 기온 조절 슬라이더와 날씨 선택 드롭다운을 묶어, 확실히 날씨를 선택한 후에 검색 버튼을 눌러서 검색하도록 변경했다.

또한 슬라이더에서 온도를 선택할 때 최저-최고기온을 선택하도록 하여, 온도 선택의 폭을 넓혔다.

--

--