OPEN HYPER STEP
← 목록으로 (stack-analysis)
STACK-ANALYSIS · 81 / 90
stack-analysis
CHAPTER 81 / 90
읽기 약 2
FUNCTION

소셜 플랫폼 아키텍처: 피드/팔로우/알림


핵심 개념

도메인 모델·읽기/쓰기 트래픽·확장 — Twitter·Instagram 패턴.

본문

핵심 도메인

📋 코드 (17줄)
[User] 사용자
- profile, followers, following

[Post] 게시물
- text, media, hashtags, mentions

[Feed] 피드 (홈 타임라인)
- 자신 + 팔로잉 게시물

[Engagement] 참여
- like, comment, share, save

[Notification] 알림
- new follower, mention, reply, like

[Discovery] 탐색
- explore, trending, search

트래픽 패턴 (Twitter 사례)

📋 코드 (12줄)
읽기 : 쓰기 = 100 : 1

[쓰기]
- 새 게시물: 분당 수백 건

[읽기]
- 피드 조회: 분당 수만 건
- 게시물 상세: 분당 수십만


→ 읽기 최적화 우선
→ 캐시 + CDN 적극

데이터 모델

SQL📋 코드 (40줄)
CREATE TABLE users (
  id UUID PRIMARY KEY,
  handle VARCHAR UNIQUE NOT NULL,    -- @alice
  name VARCHAR NOT NULL,
  bio TEXT,
  avatar_url VARCHAR,
  followers_count INT DEFAULT 0,     -- 비정규화 (캐시)
  following_count INT DEFAULT 0,
  posts_count INT DEFAULT 0,
  created_at TIMESTAMP DEFAULT NOW()
);

CREATE TABLE follows (
  follower_id UUID NOT NULL,
  followed_id UUID NOT NULL,
  created_at TIMESTAMP DEFAULT NOW(),
  PRIMARY KEY (follower_id, followed_id)
);

CREATE INDEX ON follows(followed_id, created_at DESC);
CREATE INDEX ON follows(follower_id, created_at DESC);


CREATE TABLE posts (
  id UUID PRIMARY KEY,
  user_id UUID NOT NULL,
  content TEXT,
  media JSONB,                       -- [{ url, type, ... }]
  parent_id UUID REFERENCES posts(id),  -- reply
  quote_id UUID REFERENCES posts(id),   -- quote post
  visibility VARCHAR DEFAULT 'public', -- public, followers, private
  likes_count INT DEFAULT 0,
  comments_count INT DEFAULT 0,
  shares_count INT DEFAULT 0,
  created_at TIMESTAMP DEFAULT NOW(),
  deleted_at TIMESTAMP
);

CREATE INDEX ON posts(user_id, created_at DESC) WHERE deleted_at IS NULL;
CREATE INDEX ON posts(parent_id) WHERE parent_id IS NOT NULL;

팔로우 + 카운터 갱신

TYPESCRIPT📋 코드 (40줄)
async function followUser(followerId: string, followedId: string) {
  if (followerId === followedId) {
    throw new BadRequestError('Cannot follow yourself');
  }

  return db.$transaction(async (tx) => {
    // 차단된 사용자인가?
    const blocked = await tx.block.findFirst({
      where: {
        OR: [
          { blockerId: followedId, blockedId: followerId },
          { blockerId: followerId, blockedId: followedId },
        ],
      },
    });
    if (blocked) throw new ForbiddenError('Blocked');

    await tx.follow.create({
      data: { followerId, followedId },
    });

    await tx.user.update({
      where: { id: followedId },
      data: { followersCount: { increment: 1 } },
    });
    await tx.user.update({
      where: { id: followerId },
      data: { followingCount: { increment: 1 } },
    });

    // 알림
    await notify({
      userId: followedId,
      type: 'new_follower',
      title: '새 팔로워',
      body: `@${followerHandle}님이 팔로우했습니다`,
      link: `/users/${followerHandle}`,
    });
  });
}

피드 모델 비교 (다음 챕터에서 자세히)

📋 코드 (15줄)
[Pull Model] (요청 시 계산)
- 피드 = 팔로잉 사용자의 최근 게시물 SELECT
- 쓰기 비용 0
- 읽기 비용 큼 (팔로잉 수 비례)

[Push Model] (Fan-out on write)
- 게시물 작성 시 모든 팔로워의 피드 캐시에 추가
- 읽기 빠름 (캐시만 조회)
- 쓰기 비용 큼 (팔로워 수 비례)


[Hybrid] (Twitter 방식)
- 일반 사용자: Push
- 메가 인플루언서 (팔로워 수만+): Pull
- 둘을 합쳐서 피드 구성

다음 챕터

CH.82 "뉴스피드: 팬아웃 vs 풀 모델".


AI 프롬프트
🤖 AI에게 잘 물어보는 법 — 모델·전략별 프롬프트
Claude

무료: Sonnet 4.6 / Pro $20/mo: Opus 4.6

내 프로젝트의 소셜 아키텍처 부분을 분석해서
실전 분석 + 개선 우선순위를 알려줘.
ChatGPT

무료: GPT-5.5 / Plus $20/mo: GPT-5.5 Pro

소셜 아키텍처 관련 실제 서비스 5개를
비교 분석해서 패턴 추출를 알려줘.
Gemini

무료: 2.5 Flash / Pro $19.99/mo: 3.1 Pro

내 코드베이스에서 소셜 아키텍처
최적화 가능 위치를 보고해줘.
Grok

무료: Grok 4.1 / SuperGrok $30/mo

2026년 한국 풀스택 시장의
소셜 아키텍처 트렌드를 솔직히 알려줘.

⭐ 이것만 기억하세요
소셜 플랫폼 아키텍처: 피드/팔로우/알림 이 3가지만 확실히 잡으세요
1.소셜 플랫폼은 읽기:쓰기 = 100:1 — 읽기 최적화 우선
2.카운터 캐싱(followers_count) — COUNT() 매번 X
3.Pull/Push/Hybrid — 팔로워 수에 따라 선택


공유하기
진행도 81 / 90