Fan-Out On Write

Fan-Out on Write: μ“°κΈ° μ‹œμ μ˜ νŒ¬μ•„μ›ƒ

"Fan-Out on Write"λŠ” Fan-Out ꡬ쑰λ₯Ό ꡬ체적으둜 μ“°κΈ° μ‹œμ μ— μ μš©ν•œ λ°©μ‹μž…λ‹ˆλ‹€.

μ΄λŠ” Fan-Out νŒ¨ν„΄μ˜ ν™•μž₯ λ˜λŠ” νŠΉμˆ˜ν™”λœ κ΅¬ν˜„μœΌλ‘œ λ³Ό 수 있으며, 데이터가 μƒμ„±λ˜λŠ” μ‹œμ (μ“°κΈ° μ‹œμ )에 미리 μ—¬λŸ¬ λŒ€μƒμ— 데이터λ₯Ό λΆ„λ°°ν•˜λŠ” 것을 μ˜λ―Έν•©λ‹ˆλ‹€.

λŒ€ν‘œμ μΈ 예둜 μ†Œμ…œ λ―Έλ””μ–΄λ₯Ό λ“€ 수 μžˆμŠ΅λ‹ˆλ‹€. μ‚¬μš©μžκ°€ 글을 μž‘μ„±ν•˜λ©΄(Write), κ·Έ 글이 μ¦‰μ‹œ λͺ¨λ“  νŒ”λ‘œμ›Œμ˜ νƒ€μž„λΌμΈ(ν”Όλ“œ)에 λ³΅μ œλ˜μ–΄ μ €μž₯λ©λ‹ˆλ‹€. 즉, 글을 μ“Έ λ•Œλ§ˆλ‹€ νŒ”λ‘œμ›Œ 수만큼 "fan-out"이 λ°œμƒν•˜λŠ” κ²ƒμž…λ‹ˆλ‹€.

(참고둜 이와 λ°˜λŒ€λ˜λŠ” 방식인 "Fan-Out on Read"λŠ” 읽기 μ‹œμ μ— μ—¬λŸ¬ κ³³μ—μ„œ 데이터λ₯Ό μ’…ν•©ν•΄ λ³΄μ—¬μ£ΌλŠ” λ°©μ‹μž…λ‹ˆλ‹€.)

νŠΈμœ„ν„°μ—μ„œ μ μš©λ˜λŠ” 방식

νŠΈμœ„ν„°μ—μ„œ ν•œ μ‚¬μš©μžκ°€ μƒˆ νŠΈμœ—μ„ μž‘μ„±ν•˜λ©΄, λ‹€μŒκ³Ό 같은 과정이 μΌμ–΄λ‚©λ‹ˆλ‹€.

  1. νŠΈμœ— μ €μž₯: μž‘μ„±λœ νŠΈμœ—μ€ DB에 μ €μž₯λ©λ‹ˆλ‹€.

  2. νŒ”λ‘œμ›Œ λͺ©λ‘ 쑰회: ν•΄λ‹Ή νŠΈμœ— μž‘μ„±μžλ₯Ό νŒ”λ‘œμš°ν•˜λŠ” λͺ¨λ“  μ‚¬μš©μžμ˜ λͺ©λ‘μ„ μ‘°νšŒν•©λ‹ˆλ‹€.

  3. νƒ€μž„λΌμΈ μ—…λ°μ΄νŠΈ: 쑰회된 νŒ”λ‘œμ›Œλ“€μ˜ "νƒ€μž„λΌμΈ" DB에 ν•΄λ‹Ή νŠΈμœ—μ„ μΆ”κ°€(μ“°κΈ°)ν•©λ‹ˆλ‹€.

  • νŠΉμ • μ‚¬μš©μžκ°€ ν”Όλ“œλ₯Ό μž‘μ„±ν•˜λ©΄ ν•΄λ‹Ή μ‚¬μš©μžλ₯Ό νŒ”λ‘œμš°ν•˜λŠ” νŒ”λ‘œμ›Œλ“€μ˜ νƒ€μž„λΌμΈμ— ν”Όλ“œκ°€ λ³΅μ œλ˜μ–΄ μ €μž₯λ©λ‹ˆλ‹€.

즉, μ‚¬μš©μžκ°€ ν”Όλ“œλ₯Ό μž‘μ„±ν•  λ•Œλ§ˆλ‹€ νŒ”λ‘œμ›Œ 수만큼 μ“°κΈ°(fan-out)이 λ°œμƒν•˜κ²Œ λ©λ‹ˆλ‹€.

μ™œ νŒ”λ‘œμ›Œ 수만큼 μ“°κΈ°κ°€ λ°œμƒν•˜λŠ”κ°€?

κ²°λ‘ λΆ€ν„° λ§μ”€λ“œλ¦¬λ©΄, νŠΈμœ„ν„° 같은 SNSμ—μ„œ νŒ”λ‘œμ›Œλ“€μ΄ μ΅œμ‹  νŠΈμœ—μ„ μ¦‰κ°μ μœΌλ‘œ μžμ‹ μ˜ νƒ€μž„λΌμΈμ—μ„œ 보렀면,

λ‹¨μˆœνžˆ "읽기"λ§ŒμœΌλ‘œλŠ” ν˜„μž¬μ™€ 같은 μ‚¬μš©μž κ²½ν—˜μ„ μ œκ³΅ν•˜κΈ° μ–΄λ ΅κΈ° λ•Œλ¬Έμ— 좔가적인 μ“°κΈ° μž‘μ—…μ΄ ν•„μš”ν•©λ‹ˆλ‹€.

πŸ€” μ™œ "읽기"λ§ŒμœΌλ‘œλŠ” λΆ€μ‘±ν• κΉŒ? (Fan-Out on Read λ°©μ‹μ˜ 문제)

λ§Œμ•½ 'μ“°κΈ°' μž‘μ—… 없이 '읽기'둜만 νƒ€μž„λΌμΈμ„ κ΅¬ν˜„ν•œλ‹€λ©΄, λ‹€μŒ 상황을 κ°€μ •ν•΄ λ³Ό 수 μžˆμŠ΅λ‹ˆλ‹€.

이 방식은 λ‹¨μˆœν•΄ λ³΄μ΄μ§€λ§Œ, νŠΈμœ„ν„°μ™€ 같은 κ±°λŒ€ 규λͺ¨ μ„œλΉ„μŠ€μ—μ„œλŠ” λ‹€μŒκ³Ό 같은 μ‹¬κ°ν•œ λ¬Έμ œκ°€ λ°œμƒν•  수 μžˆμŠ΅λ‹ˆλ‹€.

circle-exclamation

μ“°κΈ°κ°€ ν•„μš”ν•œ 이유 (Fan-out on Write의 본질)

"Fan-Out on Write" 방식을 μ‚¬μš©ν•˜λŠ” μ΄μœ λŠ”, μ‚¬μš©μžκ°€ νƒ€μž„λΌμΈμ„ 읽을 λ•Œμ˜ 속도λ₯Ό κ·ΉλŒ€ν™”ν•˜κΈ° μœ„ν•΄μ„œμž…λ‹ˆλ‹€.

즉, 읽기 μž‘μ—…μ„ κ°„λ‹¨ν•˜κ³  λΉ λ₯΄κ²Œ λ§Œλ“€κΈ° μœ„ν•΄ μ“°κΈ° μ‹œμ μ— 미리 λͺ¨λ“  μ€€λΉ„ μž‘μ—…μ„ ν•΄λ‘λŠ” κ²ƒμž…λ‹ˆλ‹€.

λΉ„μœ λ₯Ό λ“€μ–΄λ³΄κ² μŠ΅λ‹ˆλ‹€.

  • 읽기 방식 (Fan-out on Read)

    • μΉœκ΅¬μ—κ²Œ μ „ν™”λ₯Ό κ±Έ λ•Œλ§ˆλ‹€, κ·Έ μΉœκ΅¬κ°€ λ‹€λ₯Έ λͺ¨λ“  μΉœκ΅¬μ—κ²Œ 일일이 μ „ν™”ν•΄μ„œ 정보λ₯Ό λ¬Όμ–΄λ³Έ λ‹€μŒ, κ·Έ 정보λ₯Ό μ’…ν•©ν•΄μ„œ λ‚˜μ—κ²Œ λ§ν•΄μ£ΌλŠ” 것과 κ°™μŠ΅λ‹ˆλ‹€. (맀번 μ‹€μ‹œκ°„μœΌλ‘œ 정보λ₯Ό μˆ˜μ§‘ν•˜λŠ” 방식)

  • μ“°κΈ° 방식 (Fan-out on Write)

    • μΉœκ΅¬λ“€μ΄ μ€‘μš”ν•œ 일이 생길 λ•Œλ§ˆλ‹€ λ‚˜μ˜ 개인 λΉ„μ„œμ—κ²Œ κ·Έ λ‚΄μš©μ„ 미리 전달해 두고, λ‚΄κ°€ κΆκΈˆν•  λ•Œλ§ˆλ‹€ λΉ„μ„œκ°€ 이미 μ •λ¦¬λœ λ³΄κ³ μ„œλ₯Ό μ¦‰μ‹œ κ±΄λ„€μ£ΌλŠ” 것과 κ°™μŠ΅λ‹ˆλ‹€. (정보λ₯Ό 미리 κ°œμΈν™”λœ 곡간에 ν‘Έμ‹œν•΄λ‘λŠ” 방식)

μ—¬κΈ°μ„œ '개인 λΉ„μ„œ' 역할이 각 νŒ”λ‘œμ›Œμ˜ '개인 νƒ€μž„λΌμΈ μ €μž₯μ†Œ'이며, 여기에 νŠΈμœ—μ„ 미리 μ „λ‹¬ν•΄λ‘λŠ” ν–‰μœ„κ°€ λ°”λ‘œ νŒ”λ‘œμ›Œ 수만큼 λ°œμƒν•˜λŠ” μ“°κΈ° μž‘μ—…μž…λ‹ˆλ‹€.

μ΄λ ‡κ²Œ κ΅¬μ„±ν•˜λ©΄, μ‚¬μš©μžκ°€ νƒ€μž„λΌμΈμ„ μ—΄ λ•Œ λ‹¨μˆœνžˆ μžμ‹ μ˜ 개인 νƒ€μž„λΌμΈ μ €μž₯μ†Œμ—μ„œ 데이터λ₯Ό κ°€μ Έμ˜€κΈ°λ§Œ ν•˜λ©΄ λ˜λ―€λ‘œ, 맀우 λΉ λ₯΄κ²Œ 정보λ₯Ό λ³Ό 수 μžˆμŠ΅λ‹ˆλ‹€.

결둠적으둜, κ°œλ³„ μ €μž₯μ†Œμ— νŠΈμœ—μ„ 미리 'μ“°κΈ°' ν•΄λ‘λŠ” 것이 훨씬 효율적이라고 νŒλ‹¨ν•œ κ²ƒμž…λ‹ˆλ‹€. μ΄λŠ” 읽기 μ„±λŠ₯을 μœ„ν•΄ μ“°κΈ° λΆ€ν•˜λ₯Ό κ°μˆ˜ν•˜λŠ” μ „λž΅μž…λ‹ˆλ‹€.

Fan-Out on Write μ‹œμŠ€ν…œ ꡬ성 μ˜ˆμ‹œ

1. νŠΈμœ— μž‘μ„± μ„œλΉ„μŠ€ (Tweet Write Service)

  • μ—­ν• : μ‚¬μš©μžλ‘œλΆ€ν„° νŠΈμœ— μž‘μ„± μš”μ²­μ„ λ°›μ•„ μ²˜λ¦¬ν•©λ‹ˆλ‹€.

  • 기술: μ• ν”Œλ¦¬μΌ€μ΄μ…˜ μ„œλ²„λ‘œ API μ—”λ“œν¬μΈνŠΈ(예: POST /tweets)λ₯Ό κ΅¬ν˜„ν•©λ‹ˆλ‹€.

  • μž‘λ™ 방식:

    1. μ• ν”Œλ¦¬μΌ€μ΄μ…˜ μ„œλ²„κ°€ μ‚¬μš©μžλ‘œλΆ€ν„° νŠΈμœ— μž‘μ„± μš”μ²­μ„ λ°›μŠ΅λ‹ˆλ‹€.

    2. νŠΈμœ— λ‚΄μš©μ„ DB에 μ €μž₯ν•©λ‹ˆλ‹€.

    3. μ €μž₯ 성곡 ν›„, νŠΈμœ— κ΄€λ ¨ 정보(νŠΈμœ— ID, μž‘μ„±μž ID λ“±)λ₯Ό λ©”μ‹œμ§€ 브둜컀의 νŠΉμ • ν† ν”½(Topic)으둜 λ°œν–‰(publish)ν•©λ‹ˆλ‹€. (이 과정이 Fan-out on Writeλ₯Ό μ‹œμž‘ν•˜λŠ” 핡심 νŠΈλ¦¬κ±°μž…λ‹ˆλ‹€.)

    4. μ‚¬μš©μžμ—κ²Œ νŠΈμœ— μž‘μ„± 성곡 응닡을 λ°˜ν™˜ν•©λ‹ˆλ‹€.

2. λ©”μ‹œμ§€ 브둜컀 (Message Broker)

  • μ—­ν• :

    • νŠΈμœ— μž‘μ„± 이벀트(λ©”μ‹œμ§€)λ₯Ό μˆ˜μ§‘ν•˜κ³ , 이λ₯Ό ν•„μš”λ‘œ ν•˜λŠ” λ‹€λ₯Έ μ„œλΉ„μŠ€(subscriber)에 μ „λ‹¬ν•©λ‹ˆλ‹€.

    • λΆ„μ‚° μ‹œμŠ€ν…œμ—μ„œ μ„œλΉ„μŠ€ κ°„μ˜ 비동기 톡신을 λ‹΄λ‹Ήν•©λ‹ˆλ‹€.

  • 기술: μ•„νŒŒμΉ˜ μΉ΄ν”„μΉ΄(Apache Kafka), RabbitMQ λ“±

  • μž‘λ™ 방식:

    • νŠΈμœ— μ„œλΉ„μŠ€λ‘œλΆ€ν„° 받은 νŠΈμœ— 이벀트λ₯Ό Topic(λ˜λŠ” Queue)에 μ €μž₯ν•˜κ³ , 이λ₯Ό κ΅¬λ…ν•˜λŠ” μ»¨μŠˆλ¨Έλ“€μ΄ κ°€μ Έκ°ˆ 수 μžˆλ„λ‘ λŒ€κΈ°μ‹œν‚΅λ‹ˆλ‹€.

3. νŒ”λ‘œμ›Œ μ„œλΉ„μŠ€ / νƒ€μž„λΌμΈ 생성 μ„œλΉ„μŠ€ (Timeline Generation Service)

  • μ—­ν• :

    • λ©”μ‹œμ§€ λΈŒλ‘œμ»€λ‘œλΆ€ν„° νŠΈμœ— 이벀트λ₯Ό ꡬ독(subscribe)ν•©λ‹ˆλ‹€.

    • νŠΈμœ— μž‘μ„±μžμ˜ νŒ”λ‘œμ›Œλ“€μ„ μ°Ύμ•„ 각 νŒ”λ‘œμ›Œμ˜ 개인 νƒ€μž„λΌμΈμ„ μ—…λ°μ΄νŠΈν•©λ‹ˆλ‹€. (이 μ„œλΉ„μŠ€κ°€ Fan-out on Write의 핡심적인 "μ“°κΈ°" 뢀뢄을 λ‹΄λ‹Ήν•©λ‹ˆλ‹€.)

  • 기술: μ• ν”Œλ¦¬μΌ€μ΄μ…˜ μ„œλ²„(컨슈머)μ—μ„œ λ©”μ‹œμ§€ 브둜컀의 이벀트λ₯Ό μ†ŒλΉ„(consume)ν•  수 있게 κ΅¬μ„±ν•©λ‹ˆλ‹€.

  • μž‘λ™ 방식:

    1. λ©”μ‹œμ§€ λΈŒλ‘œμ»€λ‘œλΆ€ν„° μƒˆλ‘œμš΄ νŠΈμœ— 이벀트 λ©”μ‹œμ§€λ₯Ό μˆ˜μ‹ ν•©λ‹ˆλ‹€.

    2. λ©”μ‹œμ§€μ— ν¬ν•¨λœ μ‚¬μš©μž IDλ₯Ό ν™œμš©ν•˜μ—¬ 'νŒ”λ‘œμš° DB'(예: Redis, RDB λ“±)μ—μ„œ ν•΄λ‹Ή μž‘μ„±μžλ₯Ό νŒ”λ‘œμš°ν•˜λŠ” λͺ¨λ“  μ‚¬μš©μžμ˜ λͺ©λ‘μ„ μ‘°νšŒν•©λ‹ˆλ‹€. (이 DBλŠ” νŒ”λ‘œμš°/νŒ”λ‘œμž‰ 관계λ₯Ό 효율적으둜 μ‘°νšŒν•  수 μžˆλ„λ‘ μ΅œμ ν™”λ˜μ–΄ μžˆμ–΄μ•Ό ν•©λ‹ˆλ‹€.)

    3. 쑰회된 각 νŒ”λ‘œμ›Œμ— λŒ€ν•΄, νŠΈμœ— 정보λ₯Ό νŒ”λ‘œμ›Œμ˜ '개인 νƒ€μž„λΌμΈ DB'(주둜 NoSQL)에 μ €μž₯(μ“°κΈ°)ν•©λ‹ˆλ‹€. (Redis의 Sorted Set, Cassandra의 Wide Column Store 같은 ꡬ쑰가 이 μš©λ„μ— νš¨μœ¨μ μž…λ‹ˆλ‹€.)

    4. 이 과정은 νŒ”λ‘œμ›Œ μˆ˜κ°€ λ§Žμ„ 경우(예: 수백만 λͺ…) λΆ€ν•˜κ°€ 클 수 μžˆμœΌλ―€λ‘œ, λ™μ‹œμ„± 및 λΆ€ν•˜ 관리가 μ€‘μš”ν•©λ‹ˆλ‹€. 병렬 처리 λ˜λŠ” 비동기 처리(예: Spring의 @Async, WebFlux)λ₯Ό 적극적으둜 ν™œμš©ν•΄μ•Ό ν•©λ‹ˆλ‹€.

4. νƒ€μž„λΌμΈ 쑰회 μ„œλΉ„μŠ€ (Timeline Read Service)

  • μ—­ν• : μ‚¬μš©μžκ°€ μžμ‹ μ˜ νƒ€μž„λΌμΈ 쑰회λ₯Ό μš”μ²­ν•  λ•Œ, 미리 λ§Œλ“€μ–΄μ§„ 개인 νƒ€μž„λΌμΈ 데이터λ₯Ό μ‘°νšŒν•˜μ—¬ λ°˜ν™˜ν•©λ‹ˆλ‹€.

  • 기술: μŠ€ν”„λ§ λΆ€νŠΈ μ• ν”Œλ¦¬μΌ€μ΄μ…˜ μ„œλ²„μ—μ„œ API μ—”λ“œν¬μΈνŠΈ(예: GET /timeline)λ₯Ό κ΅¬ν˜„ν•©λ‹ˆλ‹€.

  • μž‘λ™ 방식:

    1. μ• ν”Œλ¦¬μΌ€μ΄μ…˜ μ„œλ²„κ°€ μ‚¬μš©μžλ‘œλΆ€ν„° νƒ€μž„λΌμΈ 쑰회 μš”μ²­μ„ λ°›μŠ΅λ‹ˆλ‹€.

    2. μ‚¬μš©μž IDλ₯Ό 기반으둜 '개인 νƒ€μž„λΌμΈ DB'(NoSQL)μ—μ„œ ν•΄λ‹Ή μ‚¬μš©μžμ˜ 미리 κ΅¬μ„±λœ νŠΈμœ— λͺ©λ‘μ„ μ‘°νšŒν•©λ‹ˆλ‹€.

    3. 쑰회된 νŠΈμœ— λͺ©λ‘μ„ μ‚¬μš©μžμ—κ²Œ λ°˜ν™˜ν•©λ‹ˆλ‹€.

    4. 이 μ‹œμ μ—λŠ” λ³΅μž‘ν•œ μ‘°μΈμ΄λ‚˜ μ •λ ¬ 없이 λ‹¨μˆœν•œ '읽기'만 λ°œμƒν•˜λ―€λ‘œ 맀우 λΉ λ₯Έ 응닡 속도λ₯Ό 보μž₯ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

Last updated