Skip to content

BeforeSpring/01_SocialFeed

Repository files navigation

logo

통합 소셜 피드 서비스


Table of Contents


소개

여러 소셜 미디어 서비스에 올라온 게시물을 해시태그 기반으로 취합하여 통합 제공하는 서비스입니다.

기반 기술

Static Badge Static Badge Static Badge

  • 언어
    • Java 17
  • 웹 프레임워크
    • SpringBoot 2.7.17
  • DB 접근 기술
    • Spring Data JPA
    • Spring JDBC (Bulk Insert시 쿼리 성능을 위해 사용)
    • QueryDSL
  • DBMS
    • H2 (SpringBoot embedded)
    • (JPA와 ANSI표준 SQL문 사용으로, 대부분의 RDBMS와 호환될 것으로 생각됨.)

API Reference

작성예정

프로젝트 진행 및 이슈 관리

Notion GithubProject

구현과정(설계 및 의도)

무한 스크롤을 고려한 유저 맞춤 컨텐츠 조회 - click
  • 서비스 특성
    • 소셜미디어의 특성상 게시물이 자주 업데이트됨.
    • 일반적으로 무한스크롤 방식의 UX를 채택할 것임.
    • 모든 SNS 게시물을 전부 크롤링하여 저장 것은 것은 사실상 불가능함.
      • 본 서비스에서 관리하는 해시태그가 포함된 게시물에 한해서 저장하게 됨.
      • 때문에, 본 서비스에 데이터가 들어오는 순서는 실제 게시물이 게시된 순서와 전혀 다를 수 있음.(본 서비스에서 관리하는 PK 생성 방식과 관련하여 고려할 필요가 있음.)
  • 무한스크롤 구현
    • 구현 방법 결정(마지막 조회 결과 이후 시점부터 쿼리)
      • 단순 offset 사용은 적절하지 않다고 판단함.
        • 다음 페이지를 조회하기 전에 새로운 게시물이 올라온다면, 중복되는 게시물이 등장할 수 있음.
        • UX 측면에서, 스크롤을 내릴 때, 중복된 게시물이 등장하는 것은 좋지 못함.
      • 마지막 조회 결과를 바탕으로 그 이후의 결과를 조회할 필요가 있다고 결론을 냄.
    • 마지막 조회 결과를 DB에서 어떻게 특정할 것인가
      • Incremental, 혹은 Time-Based로 생성된 PK를 이용하는 것이 일반적이나, 본 서비스에서는 부적절하다고 판단함.
        • 여러 SNS의 게시물 ID 타입과 관리 체계가 다름. 때문에 본 서비스에서는 대리키PK를 사용하는 것이 좋다고 판단하였음.
        • SNS 게시물의 실제 게시 시점과, 본 서비스에서 DB에 저장한 시점은 다를 수 있음.
      • 위 문제는 정규화를 포기하고, 해시태그마다 Content를 중복 저장하는 방식으로 해결할 수 있기는 하지만, 보다 온건한 방법을 채택함.
        • 문제의 심각성에 비해서 해결방법이 너무 급진적이라고 판단함.
        • 통계 관련 기능 구현시 애로사항이 있을 수도 있다고 판단함.
      • 마지막 조회된 게시물을 특정하기 위해서 게시물 생성시점인 createdAt을 활용하기로 결정함.
  • 쿼리 성능 문제
    • 문자열 매칭 성능 문제
      • Content.hashtag를 공백 구분 문자열로 저장함.
      • like %tofind%로 검사할 경우, 인덱스를 활용할 수 없기 때문에 성능에 큰 문제가 발생함.
      • 해결방법
        • HashtagContent 엔티티(테이블)를 만들어 최적화를 시도하였음.
          • HashtagContent
            • Long id(대리키, PK)
            • String hashtag
            • Long contentId(외래키)
    • Join 쿼리 성능 문제
      • 인덱스를 적절히 활용할 수 없는 문제
        • 앞서 언급한 시간 기반으로 이전 게시물을 특정하기로 결정한 이후, 인덱스를 적절히 활용할수 없다는 점을 인지하였음.
      • 해결방법
        • 정규화를 조금 포기하고, HashtagContentcreatedAt 컬럼을 추가함.
          • join시, 드라이빙 테이블의 Row 수를 최소화하기 위해서임.
          • createdAtHashtagContent에 추가할 경우, 드라이빙 테이블에서 목록 컨텐츠 쿼리에 필요한 모든 조건을 완성할수 있음.
            • 쿼리 조건을 HashtagContent에 설정된 복합 인덱스 (hashtag, createdAt)를 통해 완전히 커버 가능함.
          • 드리븐 테이블의 값(이 경우 Content.createdAt)에 의존적이지 않기 때문에 쿼리 비용 예측이 쉬워짐.
  • 게시물 생성 시점의 세분성(granularity)과 관련된 문제
    • 외부 SNS에서 게시물 생성 시점을 얼마나 상세하게 제공하느냐에 따라서 쿼리 방식에 잠재적인 문제 발생이 가능함.
      • DB에는 수~수십ms 단위로 세분화된 시간 정보를 저장 가능하지만, 외부 서비스가 시간을 얼마나 자세히 제공하는지 고려하여야함.
      • 만약 API로 제공되는 게시물의 시간 단위가 1초, 1분과 같이 큰 단위로 제공된다면, 동일한 시간에 생성된 게시물이 여럿 존재할 수 있음.
        • 이 경우, createdAt을 기반으로 무한스크롤을 구현한 본 서비스에서, 동일한 결과만 지속적으로 쿼리되는 문제가 발생할 수 있음.
    • 해결방법
      • 쿼리 파라미터에 offset 조건을 추가하고, 다음 쿼리에 offset 설정이 필요한 경우(마지막 조회된 게시물의 생성시점과, 그 직후의 생성시점이 같은 경우), 이를 판단하여 반환하도록 api 스펙을 작성하였음.
      • createdAt 파라미터도 여전히 사용하기 때문에, 새 게시물로 인해서 중복된 결과가 조회되는 상황을 방지할수 있을 것으로 생각됨.
    • 추가로 고려해야할 점
      • offset의 특성상, 엄청나게 인기있는 해시태그를 처리해야할 경우, 쿼리 성능을 개선해야할 필요가 있을 수도 있음.
        • 쿼리 파라미터로 contentId까지 받고, 정렬 조건에 포함시킨 뒤, contentId 이후의 값을 불러오는 식으로 구현할수도 있을 것 같음.
        • 단, contentId 컬럼까지 인덱스에 포함될 경우, 인덱스의 크기가 커져서 전반적인 읽기 성능이 떨어지는 trade-off가 존재함.
        • 추후 sns에서 제공하는 시간 응답 값이 어떤지 확인하고, 실제 서비스의 유즈케이스를 고려하여 다른 방안을 생각해볼것.
외부 API 호출 추상화 - click
  • 외부 소셜미디어 서비스의 API를 호출하는 과정을 추상화하였습니다. 로그 메시지를 출력하는 구현체로 대체하였습니다.
  • 구현
    • ExternalApiHandler 인터페이스
      • ExternalApiHandler를 통해 각 소셜 미디어 플랫폼의 API 호출을 추상화했습니다.
        • InstagramApiHandler , FacebookpiHandler , TreadsApiHandler , TwitterApiHandler등의 구현체가 존재합니다.
      • getSourceType 메서드는 각 핸들러가 어떤 소셜 미디어의 API를 다루는지 식별합니다.
      • likeshare 메서드는 게시물에 좋아요 또는 공유를 수행합니다.
    • ExternalApiHandlerResolver
      • 내부에 ExternalApiHandler의 구현체가 매핑된 Map 인스턴스를 가지고 있으며, sourceType에 따라 적절한 ExternalApiHandler를 반환합니다.
      • 생성자에서 ExternalApiHandler를 구현한 클래스들을 주입받아 sourceType을 기준으로 핸들러 클래스들을 매핑합니다.

TIL 및 회고


Authors


References

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 4

  •  
  •  
  •  
  •  

Languages