메뉴

문서정보

목차

시나리오

주식회사 joinc는 다양한 패션용품을 판매하는 인터넷 전자 상거래 서비스를 운영하고 있다. 이 회사의 CTO는 전자 상거래 시장이 격화되면서, 서비스 경쟁력을 확보하는게 중요한 과제가 됐다.

CTO는 우선 과제로 개인화된 상품추천 서비스를 개발하기로 했다. 상품추천의 요구사항은 아래와 같다.
  1. 사용자의 활동(Activity)를 저장하고 분석할 수 있는 시스템을 구축한다.
  2. 분석된 결과를 사용자에게 실시간 혹은 배치로 제공 할 수 있는 추천 시스템을 구축한다.
  3. 검색 시스템을 구성한다.
  4. 사용자는 (Facebook의 Feed 같은)Feed를 받아본다. 이 Feed에는 사용자가 관심있어 할 만한 상품 정보를 포함 할 것이다.
솔류션 아키텍트는 서비스 개발자와 함께 위 요구사항을 만족하는 시스템을 구축해야 한다.

서비스 아키텍처

전체 서비스를 High-Level로 아키텍처링 한다.

 High-Level 서비스 아키텍처

Feed 서비스는 크게 3개 레이어로 구성된다.
  1. OnLine : 사용자의 요청이 있을 때, 즉시 Feed 서비스를 제공한다. 온라인 사용자에게 즉시 Feed를 전송한다.
  2. NearLine : OnLine에서 사용 할 수 있는 Feed 객체를 만든다. 온라인 사용자에게 새로 추가되는 Feed를 전송한다.
  3. OffLine : 서비스 사용자의 모든 활동(activity)은 Queue를 통해서 Feed Create 서비스로 전달된다. Feed Create 서비스는 NearLine Feed를 제공하는 알고리즘을 돌리는 한편, 분석 시스템에 보낸다. 분석 시스템은 Offline에서 활동을 분석해서 추천 Feed를 생성한다. 이렇게 생성된 Feed는 다시 Online과 Nearline으로 제공된다.

Feed 객체

사용자는 Feed 객체(데이터)를 받게 된다. 사용자 접점에서 서비스 되는 데이터이기 때문에, 빠르게 랜더링 할 수 있어야 한다. 따라서 가능한 그 자체로 완결성을 가지고 있어야 한다. 뭐냐면 한번의 Feed 요청 API로 이미지, Like, Comment 등을 가져올 수 있어야 한다. Feed 하나를 만들기 위해서 Like 목록가져오기, Comment 목록 가져오기 API 등 여러 개의 API를 호출하는 것은 백앤드 효율 측면과 고객 경험 측면 모두에서 좋은 방법이 아니다.

아래와 같이 Feed 데이터를 정의 할 수 있을 것이다. go struct로 정의 했다.
type Feed struct {
    ID            int64       `json:"ID"` 
    CreatedDate   string      `json:"createdDate"` 
    User          User        `json:"user"`
    Post          Post        `json:"post"`
    Like          []User      `json:"like"`
    Comment       []Comment   `json:"comment"`
}

type Post struct {
    ID        int64       `json:"id"`
    Title     string      `json:"title"`
    Text      string      `json:"text"`
    Image     []Image    `json:"image"
    User      User        `json:"user"`
}

type Image struct {
    ImageURL  string    `json:"imageURL"`
    Caption   string    `json:"caption"`
}

type User struct {
    ID       int64   `json:"ID"`
    Name     string  `json:"name"`
    ImageURL string  `json:"imageURL"`
    Home     string  `json:"home"`
}

type Comment struct {
    ID       int64   `json:"ID"`
    Text     string  `json:"text"`
    User     User    `json:"user"`
}
Feed를 구성하는 모든 요소를 다 포함하고 있다. 단지 Image만 호출하면 된다.

json으로 표혐하면 아래와 같을 것이다.
{
   "FeedID" : "Feed 일련 번호",
   "Post": { 
      "ID" : "Post ID",
      "Title" : "Post Title",
      "Text" : "Post 내용",
      "ImageUrl" : ["Post Image 01", "Post Image 02"],
      "CreatedDate": "2021-05-05 11:00:00",
      "Tag": ["Tag-1", "Tag-2"]
   }
   "User": {
      "ID": "user-001",
      "Name": "yundream",
      "ImageUrl": "Profil Image",
      "Home": "User Home"
   }
   "Likes": [
     {
        "ID": "user-100",
        "Name": "user-01",
        "ImageUrl": "Profil Image",
        "Home": "User Home"
     }
   ], 
   "Comments": [
      {
          "ID": "",
          "Text": "",
          "User": "..." 
      }
   ]
}

Feed 객체 관리

위의 Feed 객체를 서비스하려면 해결 해야 할 문제들이 있다.
  1. Feed 객체는 여러 유저에게 전송해야 할 것이다. 어떻게 전송 할 수 있을까 ?
  2. Feed 객체는 그 자체로 완결된 데이터인데, 이는 static 정보 임을 의미한다. 객체의 내용이 달라지는 것은 어떻게 반영 할 것인가 ? 예를 들어 내가 읽은 Feed에 새로운 Like가 발생하거나 Comment가 달렸다면 ?
Feed 객체의 전달은 Pub/Sub 모델을 따를 것이다. 따라서 하나의 원본으로 부터, 여러 유저에게 전송될 것이다. Pub/Sub을 구현 할 수 있는 여러 툴 들이 있겠는데, Redis(ElastiCache)의 List를 이용해서 구현하기로 했다.

... 계속

인프라 아키텍처