[๋ญํน ์๊ณ ๋ฆฌ์ฆ] - Hacker News Algorithm
๊ฐ์
๊ณต๊ฐ๋ Ranking Algorithm์๋ ๊ฐ์ฅ ์ธ๊ธฐ ์๋ ๊ฒ์๊ธ์ ์ ๋ณํ๊ฑฐ๋, ์ถ์ฒ์๋ฅผ ๋ฐํ์ผ๋ก ์์๋ฅผ ๋งค๊ธฐ๋ ์๊ณ ๋ฆฌ์ฆ, ํ์ ์ ๋ฐ๋ผ ์์๋ฅผ ๊ฒฐ์ ํ๋ ์๊ณ ๋ฆฌ์ฆ ๋ฑ ๋ค์ํ ๋ฐฉ์์ ๋ญํน ์๊ณ ๋ฆฌ์ฆ์ด ์กด์ฌํฉ๋๋ค. ์ด ์ค์์๋ Hacker News Ranking Algorithm, Reddit Ranking Algorithm, ๊ทธ๋ฆฌ๊ณ Highly Rated๊ฐ ๋ํ์ ์ธ๋ฐ, ์ด๋ฒ ๊ธ์์๋ ์ด๋ค ์ค์์๋ ์กฐํ์๋ฅผ ๋ฐํ์ผ๋ก ๊ฐํธํ๊ฒ ์ ์ฉํ ์ ์๋ Hacker News Algorithm์ ๋ํด ์์ธํ ์์๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค.
Hacker News Algorithm์ด๋?
Hacker News Algorithm์ Y Combinator๊ฐ ์ด์ํ๋ ๋ด์ค ๊ณต์ ์ฌ์ดํธ์ธ Hacker News์์ ์ฌ์ฉํ๋ ๋ญํน ์๊ณ ๋ฆฌ์ฆ์ ๋๋ค. ์ด ์๊ณ ๋ฆฌ์ฆ์ ๊ฒ์๋ฌผ์ ์์๋ฅผ ๊ฒฐ์ ํ๋ ๋ฐ ์ฌ์ฉ๋๋ฉฐ, ์ฌ์ฉ์๊ฐ ๊ฒ์๋ฌผ์ '์ถ์ฒ(upvote)'์ ํ๋ ํ๋๊ณผ ๊ฒ์๋ฌผ์ด ์์ฑ๋ ์๊ฐ์ ์ค์ฌ์ผ๋ก ํ๋๋ฐ ๊ณต์์ ์๋์ ๊ฐ์ต๋๋ค.
๊ฐ ๋ณ์๋ ๋ค์๊ณผ ๊ฐ์ ์๋ฏธ๋ฅผ ๊ฐ์ง๋๋ค. ๋ณ์ p๋ ์ถ์ฒ์ผ๋ก ํ์ ํ์ง๋ง ์กฐํ์, ๋๊ธ ์ ๋ฑ ๋ค์ํ ์์๊ฐ ๋ค์ด๊ฐ ์ ์์ต๋๋ค.
- p: ๊ฒ์๋ฌผ์ ๋ํ ์ถ์ฒ ์. 1์ ๋นผ๋ ์ด์ ๋ ์์ฑ์ ์์ ์ ๊ธ์ ์ถ์ฒํ๋ ๊ฒฝ์ฐ๋ฅผ ์ ์ธํ๊ธฐ ์ํจ
- t: ๊ฒ์๋ฌผ์ด ๊ฒ์๋ ์๊ฐ๊ณผ ํ์ฌ ์๊ฐ ์ฌ์ด์ ์ฐจ์ด. ์ด ๊ฐ์ ์๊ฐ ๋จ์๋ก ํ์๋๋ฉฐ, ๊ฒ์๋ฌผ์ด 2์๊ฐ ์ ์ ๊ฒ์๋์๋ค๋ฉด t๋ 2๊ฐ๋๋ค.
- G: ์ค๋ ฅ ๊ณ์๋ก, ์๊ฐ์ด ์ง๋จ์ ๋ฐ๋ผ ๊ฒ์๋ฌผ์ ์์๊ฐ ์ด๋ป๊ฒ ๋ณํํ ์ง๋ฅผ ๊ฒฐ์ ํ๋ค. Hacker News์์๋ ๊ธฐ๋ณธ์ ์ผ๋ก 1.8์ ๊ฐ์ ์ฌ์ฉ
Hacker News์ ๋ญํน ์๊ณ ๋ฆฌ์ฆ์ ๋จ์ํ ์ถ์ฒ์ ๋ง์ด ๋ฐ๋ ๊ฒ๋ง์ด ์๋๋ผ, ์๊ฐ์ ํ๋ฆ์ ๋ฐ๋ฅธ ์์ ๋ณ๋์ ๊ณ ๋ คํ์ฌ ๋์ฑ ๊ณต์ ํ ์์๋ฅผ ์ ๊ณตํฉ๋๋ค. ์ค๋ ฅ ๊ณ์์ ๊ฐ์ ์กฐ์ ํจ์ผ๋ก์จ ์๊ฐ์ด ์ง๋ ์๋ก ๊ฒ์๋ฌผ์ ์์๊ฐ ์ด๋ป๊ฒ ๋ณํ ์ง๋ฅผ ๊ฒฐ์ ํ ์ ์์ต๋๋ค.
์ ์ฌ์ฉํ ๊น?
"์ธ๊ธฐ ๊ฒ์๊ธ"์ด๋ผ๋ ๊ฐ๋ ์ ์๊ฐํด ๋ณด๋ฉด ๋จ์ํ ๊ฒ์๊ธ์ ์กฐํ์๊ฐ ๋์ ๊ฒ์ ์๋ฏธํ๋ ๊ฒ์ด ์๋๋ผ ๊ทธ ์๊ฐ ๊ฐ์ฅ ๋ง์ ๊ด์ฌ์ ๋ฐ๊ณ ์๋ ๊ฒ์๊ธ์ ์๋ฏธํฉ๋๋ค.
์ด๋ฐ ๊ด์ ์์, ์ธ๊ธฐ์ ๊ฒ์๊ธ์ ์กฐํ์๋ฅผ ๊ธฐ์ค์ผ๋ก TOP 3๋ฅผ ์ ์ ํ๋ค๊ณ ๊ฐ์ ํด ๋ด ์๋ค. ๊ทธ๋ฆฌ๊ณ ์ด์ ์ ์์ฑ๋ ๊ฒ์๊ธ ์ค์์ ์กฐํ์๊ฐ TOP1์ธ ๊ฒ์๊ธ์ด 100, TOP2๊ฐ 50, ๊ทธ๋ฆฌ๊ณ TOP3๊ฐ 30์ด๋ผ๊ณ ํด๋ด ์๋ค. ์ด๋ ์ง๊ธ ๋ง ํฐ ์ธ๊ธฐ๋ฅผ ๋๊ธฐ ์์ ํ ์๋ก์ด ๊ฒ์๊ธ์ด ๋ฑ์ฅํ๊ณ , ๊ธ๋ฐฉ ์กฐํ์๊ฐ 10์ด ๋์๋ค๊ณ ๊ฐ์ ํด ๋ด ์๋ค. ์ด ๊ฒ์๊ธ์ ์งง์ ์๊ฐ ๋์ ํฐ ๊ด์ฌ์ ๋ฐ์์์๋ ๋ถ๊ตฌํ๊ณ , ์กฐํ์๋ง์ ๊ธฐ์ค์ผ๋ก ํ๋ฉด ์์ง TOP3์ธ 30์ ๋์ง ๋ชปํด ์ด ๊ฒ์๊ธ์ TOP3์ ํฌํจ๋์ง ๋ชปํฉ๋๋ค.
์ด๋ฐ ๋ฐฉ์์ ์ค์๊ฐ์ผ๋ก ์ธ๊ธฐ ์๋ ๊ฒ์๊ธ์ ์ฌ์ฉ์๋ค์๊ฒ ๋ณด์ฌ์ฃผ๋ ๋ฐ ์ ํ์ด ๋ฉ๋๋ค. ๋ํ ์ด์ ์ ์์ฑ๋ ๊ฒ์๊ธ๋ค์ ์ง์์ ์ผ๋ก ๋ ธ์ถ๋๋ฉด์ ์กฐํ์๊ฐ ์ง์์ ์ผ๋ก ์ฆ๊ฐํ๊ฒ ๋๊ธฐ์, ๊ฒฐ๊ณผ์ ์ผ๋ก ์ธ๊ธฐ ๊ฒ์๊ธ ์์๋ ์ ๋์ ์ด์ง ์๊ณ ๊ณ ์ ๋์ด ๋ฒ๋ฆฌ๊ฒ ๋ฉ๋๋ค.
์ด๋ฐ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด Hacker News Algorithm์ด ์ฌ์ฉ๋ฉ๋๋ค. ์ด ์๊ณ ๋ฆฌ์ฆ์ ์ ์ฉํ๋ฉด ๋จ์ํ ์กฐํ์๋ง์ ๊ธฐ์ค์ผ๋ก ํ์ง ์๊ณ , ๊ฒ์๊ธ์ ์์ฑ ์๊ฐ๋ ๊ณ ๋ คํจ์ผ๋ก์จ ์ค์๊ฐ์ผ๋ก ์ธ๊ธฐ ์๋ ๊ฒ์๊ธ์ ์ฌ์ฉ์์๊ฒ ์ ๊ณตํ ์ ์์ต๋๋ค.
์๊ฐํ ํ์ธ
์๋๋ ์ ๊ฐ ์คํ์ ์ํด ์์ฑํ ์ฝ๋์ ๋๋ค. ํ์ด์ฌ์ ์ต์์น ์์ ๊ทธ๋ํ๋ฅผ ์ดํด๋ณด๋ ์ฉ๋๋ก ์์ฑํ์์ ๊ฐ์ํด ์ฃผ์๋ฉด ๊ฐ์ฌํ๊ฒ ์ต๋๋ค. ํ์ด์ฌ ์จ๋ผ์ธ IDE์์ ์๋ ์ฝ๋๋ฅผ ์คํํ์๋ฉด ์์ฝ๊ฒ ํ์ธํ์ค ์ ์์ต๋๋ค.
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
# ํด์ปค๋ด์ค ์ ์ ๊ณ์ฐ ํจ์
def calculate_hn_score(views, hours_since_posted, gravity):
return (views - 1) / pow((hours_since_posted + 2), gravity)
# ์กฐํ์ ๊ฐ
view_counts = [30, 60, 100] # ๊ธฐ์กด ๊ฒ์๊ธ๋ค
# ์ค๋ ฅ ๊ฐ์๋ ๊ฐ
gravity_value = 0.8
# ์ ์ ๊ณ์ฐ์ ์ํ DataFrame ์์ฑ (0์๊ฐ๋ถํฐ 48์๊ฐ๊น์ง, 4์๊ฐ ๊ฐ๊ฒฉ)
score_data = pd.DataFrame(index=np.arange(0, 49, 4)) # 0์๊ฐ๋ถํฐ 48์๊ฐ๊น์ง, 4์๊ฐ ๊ฐ๊ฒฉ
# ๊ธฐ์กด ๊ฒ์๊ธ๋ค์ ์ ์ ๊ณ์ฐ
for views in view_counts:
score_data[f'Views={views} with Algorithm'] = calculate_hn_score(views, score_data.index, gravity_value)
score_data[f'Views={views} without Algorithm'] = views
# ์ ๊ฒ์๊ธ ์กฐํ์ ๋ฐ ์ ์ ๊ณ์ฐ (12์๊ฐ ์ดํ๋ถํฐ ์์)
new_item_views = 40
for time in score_data.index:
if time >= 12:
hours_since_new_item_posted = time - 12
score_data.loc[time, f'New Item (Views={new_item_views}) after 12 hours'] = calculate_hn_score(new_item_views, hours_since_new_item_posted, gravity_value)
else:
score_data.loc[time, f'New Item (Views={new_item_views}) after 12 hours'] = np.nan
# ๊ทธ๋ํ ๊ทธ๋ฆฌ๊ธฐ
plt.figure(figsize=(15, 8))
# ๊ธฐ์กด ๊ฒ์๊ธ๋ค์ ๊ทธ๋ํ
for views in view_counts:
plt.plot(score_data.index, score_data[f'Views={views} with Algorithm'], label=f'Views={views} with Algorithm', linewidth=2)
plt.plot(score_data.index, score_data[f'Views={views} without Algorithm'], label=f'Views={views} without Algorithm', linestyle='--', linewidth=2)
# ์ ๊ฒ์๊ธ์ ๊ทธ๋ํ
plt.plot(score_data.index, score_data[f'New Item (Views={new_item_views}) after 12 hours'], label=f'New Item (Views={new_item_views}) after 12 hours', linewidth=2, linestyle=':', color='red')
# x, y ๋ ์ด๋ธ๊ณผ ์ ๋ชฉ ์ค์
plt.xticks(np.arange(0, 49, 4))
plt.xlabel('Hours Since Submission')
plt.ylabel('Score')
plt.title('Comparison of Item Exposure With and Without Hacker News Algorithm (0-48 Hours Interval)')
plt.legend()
plt.grid(True)
plt.show()
- x์ถ (Hours Since Submission): ๊ฒ์๋ ์๊ฐ๋ถํฐ ํ์ฌ๊น์ง์ ๊ฒฝ๊ณผ ์๊ฐ์ ๋ํ๋ ๋๋ค.
- y์ถ (Score): ๊ฒ์๊ธ์ ํด์ปค๋ด์ค ์ ์๋ฅผ ๋ํ๋ ๋๋ค. ์ ์๋ ํด์ปค๋ด์ค์ ์๊ณ ๋ฆฌ์ฆ์ ๋ฐ๋ผ ๊ณ์ฐ๋ฉ๋๋ค.
- ์ค์ : ๊ฐ ์ค์ ์ ์กฐํ์๊ฐ 30, 60, 100์ธ ๊ธฐ์กด ๊ฒ์๊ธ๋ค์ ํด์ปค๋ด์ค ์ ์๋ฅผ ๋ํ๋ ๋๋ค. ์ด ์ ์๋ ๊ฒ์ ์๊ฐ์ผ๋ก๋ถํฐ์ ๊ฒฝ๊ณผ ์๊ฐ์ ๋ฐ๋ผ ๋ฌ๋ผ์ง๋๋ค.
- ์ ์ : ๊ฐ ์ ์ ์ ์๊ณ ๋ฆฌ์ฆ์ด ์ ์ฉ๋์ง ์์์ ๋์ ๊ณ ์ ๋ ์กฐํ์๋ฅผ ๋ํ๋ ๋๋ค. ์ด๋ ์๊ณ ๋ฆฌ์ฆ ์ ์ฉ ์ ํ์ ์ ์ ์ฐจ์ด๋ฅผ ํ๋์ ๋น๊ตํ๊ธฐ ์ํด ์ถ๊ฐํ์ต๋๋ค.
- ํ์ : ์ด ์ ์ ์กฐํ์๊ฐ 40์ธ ์ ๊ฒ์๊ธ์ ์ ์ ๋ณํ๋ฅผ ๋ํ๋ ๋๋ค. ์ด ๊ฒ์๊ธ์ ์ ์ ๊ณ์ฐ์ 12์๊ฐ ์ดํ๋ถํฐ ์์๋๋ฏ๋ก, ๊ทธ ์ด์ ์๊ฐ์๋ ๋ฐ์ดํฐ๊ฐ ์์ต๋๋ค.
์ค์ ๋ก ํ์ด์ฌ์ ์ด์ฉํ์ฌ ์๊ณ ๋ฆฌ์ฆ์ ์ ์ฉํ ๊ฒฐ๊ณผ๋ฅผ ์๊ฐํํด ๋ณด๋ฉด, ์๊ฐ์ด ์ง๋ ์๋ก ๋ชจ๋ ๊ฒ์๊ธ์ ์ ์๊ฐ ์ ์ฐจ ๊ฐ์ํ๋ฉฐ, ๋น๊ต์ ๋ฆ๊ฒ ์์ฑ๋์์ง๋ง ์ฒ์๋ถํฐ ์กฐํ์๊ฐ 40์ธ ์๋ก์ด ๊ฒ์๊ธ์ด ์์ฑ๋ ์งํ์๋ ๊ธฐ์กด์ ์กฐํ์๊ฐ 30, 60, 100์ธ ๊ฒ์๊ธ์ ๋ชจ๋ ์์ง๋ฌ TOP1์ด ๋ ๊ฒ์ ํ์ธํ ์ ์์ต๋๋ค. ๊ทธ๋ฆฌ๊ณ ํด๋น ๊ฒ์๊ธ์ ๋ค์ ์๊ฐ์ด ์ง๋ ์๋ก ์ ์ ์ฒ์์ ์์๋ก ๋์๊ฐ๋ ๊ฒ์ ๋ณผ ์ ์์ต๋๋ค.
์๋๋ ๋ฐ์ง๋ ๋ถ๋ถ์ ํ๋ํ ์ฐจํธ์ ๋๋ค.
๋ง๋ฌด๋ฆฌ
์ ๋ง๋ก ์ธ๊ธฐ ์๋ ๊ฒ์๊ธ์ ์ฌ์ฉ์์๊ฒ ํจ๊ณผ์ ์ผ๋ก ๋ ธ์ถ์ํค๊ธฐ ์ํด์๋ ๊ฐ์ธํ๋ ์ถ์ฒ ์๊ณ ๋ฆฌ์ฆ์ ํตํ ์ถ์ฒ ์์คํ ์ด ํ์ํฉ๋๋ค. ํ์ง๋ง ์ด๋ ์ ๋ฌธ์ ์ธ ์ธ๋ ฅ๊ณผ ์ง์์ด ํ์ํ๋ฉฐ, ๋๋ถ๋ถ์ ํ๋ก์ ํธ์ ๋น์ฅ ๋์ ํ๊ธฐ๋ ์ด๋ ค์ธ ๊ฒ์ ๋๋ค. ๊ทธ๋ ๋ค๊ณ ๋จ์ํ ํน์ ๊ฐ, ์๋ฅผ ๋ค์ด ์กฐํ์๋ฅผ ๊ธฐ์ค์ผ๋ก ๊ฒ์๊ธ์ ๋ ธ์ถ์ํค๋ ๋ฐฉ์์ ์ด์ ์ ์์ฑ๋ ๊ฒ์๊ธ๋ค์ด ๊ณ์ํด์ ๋ ธ์ถ๋๋ฉด์ ์น ํ์ด์ง๊ฐ ์ ์ฒด๋ ๊ฐ๋ฅ์ฑ์ด ์์ต๋๋ค.
๋ฐ๋ผ์ ์ด๋ด ๋ Hacker News Algorithm์ ์ ์ฉํ๋ ๊ฒ์ด ์ข์ ์ ํ์ด ๋ ์ ์์ต๋๋ค.