Skip to content
J_Coder edited this page Dec 2, 2024 · 54 revisions

🎍 개발자들의 이야기가 자라나는 곳, 데나무

💪 기술적 도전

Important

더 자세한 내용은 NOTION에서 확인이 가능해요! 보러 가시겠어요? 팀 노션 보러가기

RSS 기반 블로그 구독

RSS 기반 FEED 크롤링 이미지

Note

RSS 링크만으로 간편하게 블로그를 등록할 수 있어요. 등록된 블로그의 새로운 글이 30분 간격으로 자동 업데이트되어 데나무에 노출되어요.

🗝️: Crawling, RSS, Cron

RSS Crawler

  1. 클라이언트로부터 블로그 등록 기능을 통해 블로그 신청 받기
  2. 관리자 권한으로 신청된 블로그 승인/거절을 통해 결과 HTML 이메일 발송
  3. 승인 시, 서비스 DB에 RSS URL 저장
  4. PM2의 CRON 기능을 이용하여 30분 마다 서비스 DB에 저장되어 있는 RSS URL에서 XML 획득
  5. XML 파싱을 한 후 30분 이내의 게시글만 필터링 할 수 있도록 시간 연산을 통해 필터링
  6. 게시글 작성 시간 순으로 정렬 후 서비스 DB에 게시글 정보들 저장
  7. 최신으로 가져온 피드들은 Redis에 저장하여 Long Polling으로 데이터를 가져갈 때, 더 빠르게 접근할 수 있도록 최적화

무한 스크롤

무한 스크롤 GIF

Note

모든 컨텐츠를 휠 스크롤 하나로 제공받을 수 있어요. 시간 상관 없이 데나무 서비스에 등록되었던 오래된 게시글 또한 확인할 수 있어요.

🗝️: React Query Caching, Pagination, lazy Loading

FE

  • React Query Caching을 통해 컴포넌트 로드 시간 단축
  • Image Lazy Loading을 도입하여 웹 사이트의 로딩 시간 단축
  • 무한 스크롤 도입

BE

  • 페이지 네이션에서 중간에 사라지는 데이터로 인해 제공이 안 되는 데이터가 있을 수 있기에 OFFSET를 사용하는 것 보다는 lastId를 이용하여 제공한 게시글의 마지막 게시글로부터 LIMIT를 걸어 사용자에게 유실된 데이터 없이 모든 데이터를 제공할 수 있도록 구현

최신 피드 제공

최신 피드 제공 Polling

Note

새로고침 없이도 Long Polling 통신 방식을 이용하여 30분 간격으로 새로운 피드가 탐지될 경우 클라이언트에게 제공해줘요.

🗝️: 자체 조회수, Long Polling

FE [최신 피드 제공]

Long Polling vs Server Sent Event

  • 선택 결과: Long Polling
  • 최신 피드는 서버에서 30분에 한 번씩만 업데이트 되기 때문에 Server Sent Event를 적용하기에는 접속 유지를 30분 동안 하고 있어야 하기에 낭비라고 판단했다. 오히려 30분의 긴 시간이라면 Long Polling이 더 효율적이라 판단했다.

BE [자체 조회수]

  • 조회수 기반으로 트렌드를 제공하는데, 사용자 판별을 하지 않는다면 부정한 방법으로 조회수 획득 가능
  • 비회원 사용자를 100% 가려내는 것은 불가능하다고 판단
  • 쿠키, 로컬 스토리지로 저장하기에는 사용자가 브라우저 단에서 컨트롤하면 결국 새로운 사용자로 인식
  • Browser Finger Print를 사용하면 사용자끼리 브라우저 설정이 같은 사람이 있을 수도 있고, 설정 값 하나만 바꿔도 새로운 사용자로 인식
  • 공인 IP를 이용하여 사용자를 파악하기로 판단
  • 쿠키에는 사용자가 읽은 게시글의 ID를 저장하게 하고, 만약 조회수를 증가하는 API로 요청이 왔을 때, 쿠키에 조회하고자 하는 게시글 ID가 존재한다면 DB에 접근하지 않기에 DB 접근 최적화로 속도 향상

실시간 트렌드 제공

실시간 트렌드 제공 애니메이션 GIF

Note

30초마다 업데이트되는 트렌딩 포스트를 통해 인기 있는 글을 실시간으로 확인할 수 있어요. IP와 쿠키를 활용한 중복 조회 방지 시스템으로 통계를 제공하고, 매일 자정에 트렌드가 초기화되어요.

🗝️: 자체 조회수, SSE, 비회원 식별, Cron

Server Sent Event vs Long Polling

  • 선택 결과: Server Sent Event
  • 트렌드라는 건 시간에 민감하기에 자주 변경이 되어야 한다. Long Polling 보다는 Server Sent Event가 데이터 통신상 HTTP 연결, 연결 해제를 매번 안 해도 되기에 훨씬 효율적이라 판단
  • 양방향 통신을 하지 않아도 된다. Long Polling 같은 경우 Body나 Query에 데이터를 포함하여 클라이언트 -> 서버, 서버 -> 클라이언트로 요청, 응답을 매번 반복하는 형식이다. 하지만, 트렌드는 단순히 서버 -> 클라이언트로 응답만 해주면 된다. 그렇기에 Server Sent Event 처럼 서버 -> 클라이언트 방식이 더 적합한 방식이라 판단
  • 랭킹이 변동되었을 때만 데이터를 전송하면 되기에 데이터 통신에서도 더 효율적이다. Long Polling 같은 경우 주기적인 요청에 강제적으로 응답을 해줘야 하지만, SSE는 서버 내에서 이벤트가 발생했을 때, 클라이언트로 데이터를 보낼 수 있다. 필요없는 시간 대에 데이터를 전송하지 않아도 되기에 통신상 더 최적화된 방식이라 판단

편리한 검색 시스템

검색 결과 GIF

Note

원하는 키워드로 기술 블로그 글을 쉽게 찾아볼 수 있어요. 연관성이 높은 게시글이 상단에 노출되는 유사도 기반 검색을 지원하고, 무한 스크롤로 끊김 없이 글을 탐색할 수 있어요.

🗝️: MySQL Full Text Index, Pagination, debounce

FE

  • debounce 를 통해 매번 입력에 대한 검색 API를 호출하는 것이 아닌, API 호출 최적화
  • 페이지 네이션과 검색 결과의 키워드 강조를 통해 사용자에게 판단하기 쉬운 검색 결과 제공

BE

  • MySQL의 Full Text Index를 사용하여 검색 기능 구현
  • 검색 토큰 개수를 설정하여 검색 연관도 증가
  • 페이지 네이션을 이용하여 검색 결과 반환

개발자 채팅

개발자 채팅 GIF

Note

실시간 채팅을 통해 다른 개발자들과 자유롭게 소통할 수 있어요. 관심 있는 기술에 대해 바로 피드백을 주고받으며 함께 성장할 수 있어요.

🗝️: Web Socket

FE

  • WebSocket을 이용한 실시간 통신
  • avvvatars-react 라이브러리를 이용한 사용자 랜덤 프로필 제작

BE

  • @woowa-babble/random-nickname 라이브러리를 이용한 사용자 랜덤 닉네임 제작
  • IP에 따라 사용자 닉네임을 24시간동안 저장
  • 24시간 후 다른 닉네임을 제공받도록 구현
  • 채팅 히스토리 20개 Redis에 저장하여 채팅 히스토리 접근 속도 개선

통계와 분석

통계 그래프 GIF

Note

일별, 전체 조회수 통계를 통해 인기 있는 콘텐츠를 한눈에 파악할 수 있어요. 블로그 플랫폼별 통계를 통해 어느 개발 플랫폼이 활발한지 확인할 수 있어요.

🗝️: Graph, Statistic API

FE

  • 일일, 전체 조회수 통계, 블로그 플랫폼별 회원 통계를 그래프로 출력

완성도

테스트 결과

Note

서버 예외를 최대한 막으려고 테스트 코드를 꼼꼼히 짰어요. 이를 통해 사용자 경험과 생산성을 증진시킬 수 있었어요.

🗝️: Test, Exception

FE

  • React Testing Library, Vitest 테스트 구축
  • 컴포넌트 테스트로 하위 컴포넌트들에 대한 단위 테스트 작성
  • Lazy Image, Avatar 같은 공통 UI 컴포넌트, custom hook들은 Mock 객체 처리
  • lucide-react 외부 라이브러리 Mocking 처리
  • 테스트 유틸리티 헬퍼 함수 구현

BE

  • toStrictEqual vs 필요 속성만 검증의 테스트 범위 결정

    • toStrictEqual 사용의 장점
      • 응답 객체에 개발자가 예상하지 못 한 속성이 들어갈 수 있다. 이 케이스도 테스트를 통해 발견할 수 있다.
    • toStrictEqual 사용의 단점
      • 객체의 순서를 맞춰야하는 추가 비용이 발생할 수 있다.
    • 필요 속성 테스트만의 장점
      • 결과를 검증할 수 있는 최소 조건만을 검증할 수 있기에 유지보수 측면에서 빠르게 대응할 수 있다.
    • 필요 속성 테스트만의 단점
      • 응답 객체에 개발자가 의도하지 않은 속성이 들어갈 수 있다. 이는 민감 정보에 해당할 수도 있다. 하지만, 이는 E2E 테스트에는 부적합하다고 판단한다.
    • 결론: 테스트는 간단 명료해야 하고, 테스트 코드 또한 유지 보수의 대상이다. 그렇기에, 필요 속성만 테스트를 하여 결과를 검증할 수 있는 최소 조건으로 검증한다.
  • 앱을 최초로 1회 초기화하는 방식을 통해 테스트 코드 최적화

  • Nest class-validator의 값 검증을 이용하여 API 안정성 향상

  • Jest 핵심 비즈니스 로직은 E2E 테스트, 입력 값 검증은 DTO 테스트로 분리하여 유지보수 쉬운 테스트 코드를 지향

  • 테스트 픽스처를 활용하여 유연한 데이터 변경에 대응

👥 팀원 역할

Backend Backend Frontend Backend Frontend
박무성 안성윤 정명기 조민석 채준혁
J103 박무성 J152 안성윤 J222 정명기 J235 조민석 J249 채준혁
당일 팀 활동 요약 담당 팀장
오프라인 미팅 장소 담당
노션 & Github Wiki 동기화 담당 멘토링 활동 담당
Github Project 칸반 보드 담당
노션 정리 담당

소개

팀 문화

회의록

1주차

2주차

3주차

4주차

5주차

6주차

기술 공유

박무성

안성윤

정명기

조민석

채준혁

팀 회고

멘토링 일지

Clone this wiki locally