๋ฌธ์„œ ๋ฉ”๋‰ด
๋ฌธ์„œ ํ™ˆ
/ /
Atlas App Services
/

ํŠœํ† ๋ฆฌ์–ผ: ํŠธ๋ฆฌ๊ฑฐ, ํ•จ์ˆ˜ ๋ฐ ๊ฐ’์„ ์‚ฌ์šฉํ•˜์—ฌ ์„œ๋ฒ„๋ฆฌ์Šค GitHub ๊ธฐ์—ฌ ์ถ”์ ๊ธฐ ๋นŒ๋“œ

์ด ํŽ˜์ด์ง€์˜ ๋‚ด์šฉ

์˜ˆ์ƒ ์™„๋ฃŒ ์‹œ๊ฐ„: 30๋ถ„

์ด ํŠœํ† ๋ฆฌ์–ผ์—์„œ๋Š” Atlas App Services๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ GitHub ๋ฆฌํฌ์ง€ํ† ๋ฆฌ๋ฅผ ๋ชจ๋‹ˆํ„ฐ๋งํ•˜๊ณ  ๊ธฐ์—ฌ๋„๋ฅผ ์ถ”์ ํ•˜๋Š” ์„œ๋ฒ„๋ฆฌ์Šค ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋นŒ๋“œํ•ฉ๋‹ˆ๋‹ค.

๋นŒ๋“œํ•˜๋Š” App Services App์—๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ช‡ ๊ฐ€์ง€ ๊ธฐ๋Šฅ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

  • MongoDB Atlas ์ปฌ๋ ‰์…˜์—์„œ ํ”„๋กœ์ ํŠธ์— ๊ธฐ์—ฌํ•œ ์‚ฌ์šฉ์ž๋ฅผ ์ถ”์ ํ•˜์„ธ์š”.

  • ์ƒˆ๋กœ์šด ๊ธฐ์—ฌ์ž๊ฐ€ pull ์š”์ฒญ์„ ์—ด๊ฑฐ๋‚˜ ์ด์Šˆ๋ฅผ ์ œ๊ธฐํ•  ๋•Œ ํ™˜์˜ํ•˜๋Š” ๋Œ“๊ธ€์„ ๋‚จ๊ธฐ์„ธ์š”.

  • ๋ฆฌํฌ์ง€ํ† ๋ฆฌ์— ๋Œ€ํ•œ ๊ธฐ์—ฌ๋„๋ฅผ ์š”์•ฝํ•˜๋Š” ์ฃผ๊ฐ„ ๋ณด๊ณ ์„œ๋ฅผ ์ƒ์„ฑํ•˜์—ฌ ๋ณด๋ƒ…๋‹ˆ๋‹ค.

์ด ํŠœํ† ๋ฆฌ์–ผ์„ ์™„๋ฃŒํ•˜๋ฉด ๋‹ค์Œ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

์ด ํŠœํ† ๋ฆฌ์–ผ์„ ์‹œ์ž‘ํ•˜๋ ค๋ฉด ๋จผ์ € ๋‹ค์Œ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

๋˜ํ•œ ์ด ํŠœํ† ๋ฆฌ์–ผ์—์„œ๋Š” ๋ฐฐํฌ ์ดˆ์•ˆ ์›Œํฌํ”Œ๋กœ๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋ฐฐํฌ ์ดˆ์•ˆ์€ ๋‹จ์ผ ๋‹จ์œ„๋กœ ๋ฐฐํฌํ•˜๊ฑฐ๋‚˜ ์‚ญ์ œํ•  ์ˆ˜ ์žˆ๋Š” ์•ฑ ๋ณ€๊ฒฝ ์‚ฌํ•ญ์˜ collection์ž…๋‹ˆ๋‹ค. ๋ฐฐํฌ ์ดˆ์•ˆ์„ ๋น„ํ™œ์„ฑํ™”ํ•˜์ง€ ์•Š์€ ๊ฒฝ์šฐ ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ์ดˆ์•ˆ์— ์ €์žฅํ•œ ๋‹ค์Œ ์ˆ˜๋™์œผ๋กœ ๋ฐฐํฌํ•ด์•ผ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋จผ์ € App Services์—์„œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋งŒ๋“ค์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์•ฑ์„ ๋งŒ๋“ค๋ ค๋ฉด ๋‹ค์Œ์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

  1. cloud.mongodb.com์—์„œ Atlas ํ”„๋กœ์ ํŠธ๋ฅผ ์—ฝ๋‹ˆ๋‹ค.

  2. ์ƒ๋‹จ ํƒ์ƒ‰์—์„œ App Services ์„ ํด๋ฆญํ•ฉ๋‹ˆ๋‹ค.

  3. Create a New App๋ฅผ ํด๋ฆญํ•ฉ๋‹ˆ๋‹ค.

  4. ์•ฑ์˜ ์ด๋ฆ„์„ github-tracker-tutorial ์œผ๋กœ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค.

  5. cluster๋ฅผ ์„ ํƒํ•˜์—ฌ ์ƒˆ ์•ฑ์— ์—ฐ๊ฒฐํ•ฉ๋‹ˆ๋‹ค.

  6. Create App Service๋ฅผ ํด๋ฆญํ•ฉ๋‹ˆ๋‹ค.

GitHub ๋ฆฌํฌ์ง€ํ† ๋ฆฌ ์›นํ›… ์„ ์‚ฌ์šฉํ•˜์—ฌ ์•ฑ์„ GitHub ๋ฆฌํฌ์ง€ํ† ๋ฆฌ์— ์—ฐ๊ฒฐํ•ฉ๋‹ˆ๋‹ค. . ์›นํ›…์€ ๋ฆฌํฌ์ง€ํ† ๋ฆฌ์—์„œ ์ƒˆ ์ปค๋ฐ‹์ด๋‚˜ pull ์š”์ฒญ๊ณผ ๊ฐ™์€ ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•  ๋•Œ๋งˆ๋‹ค ์•ฑ์— ์ด๋ฅผ ์•Œ๋ฆฝ๋‹ˆ๋‹ค. ๊ฐ ์ด๋ฒคํŠธ๋Š” ์‘๋‹ต์œผ๋กœ ๋ฌด์—‡์ธ๊ฐ€๋ฅผ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๋Š” ์„œ๋ฒ„๋ฆฌ์Šค ํ•จ์ˆ˜๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.

์ด ํŠœํ† ๋ฆฌ์–ผ์—์„œ๋Š” GitHub REST API๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฆฌํฌ์ง€ํ† ๋ฆฌ์—์„œ ์ฒซ ๋ฒˆ์งธ pull ์š”์ฒญ ๋˜๋Š” ์ด์Šˆ๋ฅผ ์—ด ๋•Œ๋งˆ๋‹ค ๊ธฐ์—ฌ์ž์—๊ฒŒ ํ™˜์˜ ๋ฉ”์‹œ์ง€๋ฅผ ๋ณด๋ƒ…๋‹ˆ๋‹ค.

์›นํ›…์€ ์•ฑ์ด ์ œ์–ดํ•˜๋Š” URL๋กœ ์ด๋ฒคํŠธ์— ๋Œ€ํ•œ ์š”์ฒญ์„ ์ „์†กํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค. ์›นํ›… ์š”์ฒญ์„ ์ˆ˜์‹ ํ•˜๊ณ  ์ฒ˜๋ฆฌํ•˜๋ ค๋ฉด ์•ฑ์—์„œ ๊ณ ์œ ํ•œ URL์ด ์žˆ๋Š” ์‚ฌ์šฉ์ž ์ง€์ • ์—”๋“œํฌ์ธํŠธ๋ฅผ ๋…ธ์ถœํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์—”๋“œํฌ์ธํŠธ๋ฅผ ์ƒ์„ฑํ•˜๋ ค๋ฉด ๋‹ค์Œ์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

  1. ์™ผ์ชฝ ํƒ์ƒ‰ ๋ฉ”๋‰ด์—์„œ HTTPS Endpoints ์„ ํด๋ฆญํ•ฉ๋‹ˆ๋‹ค.

  2. Add An Endpoint๋ฅผ ํด๋ฆญํ•ฉ๋‹ˆ๋‹ค.

  3. ์—”๋“œํฌ์ธํŠธ ๊ฒฝ๋กœ์˜ ์ด๋ฆ„์„ /greetNewContributors ์œผ๋กœ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค.

  4. HTTP ๋ฉ”์„œ๋“œ๋Š” POST ๋กœ ์„ค์ •๋œ ์ƒํƒœ๋กœ ๋‘ก๋‹ˆ๋‹ค.

  5. ๊ถŒํ•œ ๋ถ€์—ฌ๋ฅผ ์œ„ํ•ด Require a Secret ๋ฅผ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค.

  6. ์ƒˆ ์‹œํฌ๋ฆฟ ์ด๋ฆ„์„ ์ž…๋ ฅํ•˜๊ณ  Create ์„ ํด๋ฆญํ•˜์—ฌ ์ƒˆ ์‹œํฌ๋ฆฟ์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ๋‹ค์Œ ์‹œํฌ๋ฆฟ ๊ฐ’์œผ๋กœ tutorial ์„(๋ฅผ) ์ž…๋ ฅํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ์œ„ํ•ด์„œ๋Š” ๋“ค์–ด์˜ค๋Š” ๋ชจ๋“  ์š”์ฒญ์ด ์š”์ฒญ URL์— ์ฟผ๋ฆฌ ๋งค๊ฐœ๋ณ€์ˆ˜ secret=tutorial ์„(๋ฅผ) ํฌํ•จํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

  7. ์—”๋“œํฌ์ธํŠธ์— ๋Œ€ํ•œ ์ƒˆ Realm ํ•จ์ˆ˜ ์„ ๋งŒ๋“ค๊ณ  ์ด๋ฆ„์„ endpoints/greetNewContributors ์œผ๋กœ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค.

  8. ์ง€๊ธˆ์€ ๋‹ค๋ฅธ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜์ง€ ์•Š๊ณ  ์ˆ˜์‹  ํ˜ธ์ถœ์—๋งŒ ์‘๋‹ตํ•˜๋Š” ๊ธฐ๋ณธ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค. ๋‹ค์Œ ์ฝ”๋“œ๋ฅผ ํ•จ์ˆ˜ ๋ณธ๋ฌธ์— ๋ณต์‚ฌํ•ฉ๋‹ˆ๋‹ค.

    exports = async function greetNewContributors(request, response) {
    return response
    .setStatusCode(200)
    .setBody("Successfully received a GitHub webhook event")
    }
  9. Save ์„ ํด๋ฆญํ•˜๊ณ  ์—”๋“œํฌ์ธํŠธ๋ฅผ ๋ฐฐํฌํ•ฉ๋‹ˆ๋‹ค.

  10. Operation Type ์•„๋ž˜์—์„œ ์—”๋“œํฌ์ธํŠธ ์ฝœ๋ฐฑ URL์„ ๋ณต์‚ฌํ•ฉ๋‹ˆ๋‹ค. ๋‚˜์ค‘์— GitHub ์›นํ›…์„ ์„ค์ •ํ•˜๋Š” ๋ฐ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

์ด์ œ ์•ฑ์—์„œ ์—”๋“œํฌ์ธํŠธ๋ฅผ ๋งŒ๋“ค์—ˆ์œผ๋ฏ€๋กœ GitHub ์›นํ›…์ด ์ˆ˜๋ฝ๋˜๋„๋ก ์—”๋“œํฌ์ธํŠธ์˜ ํ•จ์ˆ˜์— ๋Œ€ํ•œ ์ธ์ฆ ์„ค์ •์„ ๋ณ€๊ฒฝํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

ํ•จ์ˆ˜์˜ ์ธ์ฆ ์„ค์ •์„ ์—…๋ฐ์ดํŠธํ•˜๋ ค๋ฉด ๋‹ค์Œ์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

  1. ์™ผ์ชฝ ํƒ์ƒ‰ ๋ฉ”๋‰ด์—์„œ Functions ์„ ํด๋ฆญํ•ฉ๋‹ˆ๋‹ค.

  2. ์—”๋“œํฌ์ธํŠธ ํ•จ์ˆ˜๋ฅผ ์ฐพ์•„ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค.

  3. Settings๋ฅผ ํด๋ฆญํ•ฉ๋‹ˆ๋‹ค.

  4. Authentication ์—์„œ ์ธ์ฆ ๋ฐฉ๋ฒ•์„ System ๋กœ ๋ณ€๊ฒฝํ•ฉ๋‹ˆ๋‹ค.

  5. ํ•จ์ˆ˜๋ฅผ ๋ฐฐํฌํ•˜๋ ค๋ฉด Save ์„ ํด๋ฆญํ•ฉ๋‹ˆ๋‹ค.

์—”๋“œํฌ์ธํŠธ ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•  ์ค€๋น„๊ฐ€ ๋˜๋ฉด GitHub ๋ฆฌํฌ์ง€ํ† ๋ฆฌ์—์„œ ์—”๋“œํฌ์ธํŠธ๋กœ ์ด๋ฒคํŠธ๋ฅผ ์ „์†กํ•˜๋Š” ์›นํ›…์„ ์„ค์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๋ฆฌํฌ์ง€ํ† ๋ฆฌ์— ์›นํ›…์„ ๋งŒ๋“ค๋ ค๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ํ•˜์„ธ์š”:

  1. ๋ฆฌํฌ์ง€ํ† ๋ฆฌ ์„ค์ •์„ ์—ด๊ณ  ์™ผ์ชฝ ํƒ์ƒ‰ ๋ฉ”๋‰ด์—์„œ Webhooks ์„(๋ฅผ) ์„ ํƒํ•ฉ๋‹ˆ๋‹ค.

  2. ์ƒˆ ์›นํ›… Payload URL ์ถ”๊ฐ€ ๊ทธ๋ฆฌ๊ณ  ์„(๋ฅผ) ๋ฐฉ๊ธˆ ์ƒ์„ฑํ•œ ์—”๋“œํฌ์ธํŠธ์˜ URL๋กœ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค. URL์€ ์•ฑ์˜ ๋ฐฐํฌ ๋ชจ๋ธ์— ๋”ฐ๋ผ ๋‹ค์Œ ์ค‘ ํ•˜๋‚˜์™€ ๊ฐ™์ด ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.

  3. ์›นํ›… ์ฝ˜ํ…์ธ  ์œ ํ˜•์„ application/json ์œผ๋กœ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.

  4. ์—”๋“œํฌ์ธํŠธ์— ๋Œ€ํ•ด ์ •์˜ํ•œ ๊ฒƒ๊ณผ ๋™์ผํ•œ ์‹œํฌ๋ฆฟ ๊ฐ’์ธ Secret ์„(๋ฅผ) ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค( tutorial.

  5. ๊ฐœ๋ณ„ ์ด๋ฒคํŠธ๋ฅผ ์„ ํƒํ•˜๋„๋ก ์„ ํƒํ•˜๊ณ  Issues ๋ฐ Pull requests ์— ๋Œ€ํ•œ ์ด๋ฒคํŠธ๋งŒ ์ „์†กํ•˜๋„๋ก ์›นํ›…์„ ๊ตฌ์„ฑํ•ฉ๋‹ˆ๋‹ค.

  6. Add webhook ์„ ํด๋ฆญํ•˜์—ฌ ์ƒˆ ์›นํ›…์„ ์ €์žฅํ•ฉ๋‹ˆ๋‹ค.

์›นํ›…์ด ์—”๋“œํฌ์ธํŠธ๋ฅผ ์„ฑ๊ณต์ ์œผ๋กœ ํ˜ธ์ถœํ•˜๋Š”์ง€ ํ™•์ธํ•˜๋ ค๋ฉด App Services์˜ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋กœ๊ทธ ์—์„œ ์œ ํ˜•์ด Endpoint ์ธ ํ•ญ๋ชฉ์„ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค. ์™ผ์ชฝ ํƒ์ƒ‰ ๋ฉ”๋‰ด์—์„œ Logs ์„ ํด๋ฆญํ•˜๋ฉด ํ•ด๋‹น ํŽ˜์ด์ง€๋กœ ์ด๋™ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์›นํ›…์˜ ์š”์ฒญ ๋กœ๊ทธ ๋ฅผ ํ™•์ธํ•  ์ˆ˜๋„ Recent Deliveries ์žˆ์Šต๋‹ˆ๋‹ค. ์›นํ›… ์„ค์ • ํŽ˜์ด์ง€์˜ ์•„๋ž˜ GitHub์—์„œ ์„ฑ๊ณตํ•œ ๊ฐ ์š”์ฒญ ์˜†์—๋Š” ๋…น์ƒ‰ ํ™•์ธ ํ‘œ์‹œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

ํ•‘ ์ด๋ฒคํŠธ์— ๋Œ€ํ•œ ์‚ฌ์šฉ์ž ์ง€์ • ์—”๋“œํฌ์ธํŠธ์˜ ์‘๋‹ต์„ ๋ณด์—ฌ์ฃผ๋Š” GitHub์˜ ๋กœ๊ทธ ํ•ญ๋ชฉ์ž…๋‹ˆ๋‹ค. ์‘๋‹ต์˜ ์ƒํƒœ ์ฝ”๋“œ๋Š” 200์ด๋ฉฐ ์‘๋‹ต ๋ณธ๋ฌธ์—๋Š” "GitHub webhook ์ด๋ฒคํŠธ๋ฅผ ์„ฑ๊ณต์ ์œผ๋กœ ์ˆ˜์‹ ํ–ˆ์Šต๋‹ˆ๋‹ค"๋ผ๊ณ  ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.

์ด์ œ ์›นํ›…์ด GitHub์—์„œ ์—”๋“œํฌ์ธํŠธ๋กœ ์ด๋ฒคํŠธ๋ฅผ ์ „์†กํ•˜๋„๋ก ์„ค์ •๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ GitHub API๋กœ ์—”๋“œํฌ์ธํŠธ์˜ ์ด๋ฒคํŠธ์— ์‘๋‹ตํ•˜๋ ค๋ฉด ์•ก์„ธ์Šค ํ† ํฐ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ์ด ํŠœํ† ๋ฆฌ์–ผ์—์„œ๋Š” ๊ฐœ์ธ ์•ก์„ธ์Šค ํ† ํฐ์„ ์‚ฌ์šฉํ•˜์ง€๋งŒ, GitHub ์•ฑ์„ ์„ค์ •ํ•˜์—ฌ ํ•ด๋‹น ํ† ํฐ์„ ๋Œ€์‹  ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ฐœ์ธ ์•ก์„ธ์Šค ํ† ํฐ์„ ์ƒ์„ฑํ•˜๋ ค๋ฉด ๋‹ค์Œ์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

  1. GitHub ์‚ฌ์šฉ์ž ์„ค์ •(๋ฆฌํฌ์ง€ํ† ๋ฆฌ ์„ค์ •์ด ์•„๋‹˜)์„ ์—ด๊ณ  ์™ผ์ชฝ ํƒ์ƒ‰ ๋ฉ”๋‰ด์—์„œ Developer settings ์„ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค.

  2. ์™ผ์ชฝ ํƒ์ƒ‰ ๋ฉ”๋‰ด์—์„œ Personal access tokens ์„(๋ฅผ) ์„ ํƒํ•œ ๋‹ค์Œ Generate new token ์„(๋ฅผ) ํด๋ฆญํ•ฉ๋‹ˆ๋‹ค.

  3. ์„ค๋ช…์ด ํฌํ•จ๋œ ์ด๋ฆ„๊ณผ ํ•ฉ๋ฆฌ์ ์ธ ๋งŒ๋ฃŒ ์‹œ๊ฐ„์„ ์‚ฌ์šฉํ•˜์—ฌ ํ† ํฐ์„ ๊ตฌ์„ฑํ•ฉ๋‹ˆ๋‹ค. ํŠœํ† ๋ฆฌ์–ผ์ด๋ฏ€๋กœ 7์ผ ํ›„์— ํ† ํฐ์„ ๋งŒ๋ฃŒํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.

  4. repo ๋ฒ”์œ„๋ฅผ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค.

  5. Generate token๋ฅผ ํด๋ฆญํ•ฉ๋‹ˆ๋‹ค.

  6. ํ† ํฐ์„ ๋‹ค์‹œ ์•ก์„ธ์Šคํ•  ์ˆ˜ ์žˆ๋Š” ์•ˆ์ „ํ•œ ๊ณณ์— ๋ณต์‚ฌํ•ฉ๋‹ˆ๋‹ค. ์ด ์  ์ดํ›„์—๋Š” Github์—์„œ ํ† ํฐ์„ ๋‹ค์‹œ ํ‘œ์‹œํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์•ฑ์œผ๋กœ ๋Œ์•„๊ฐ€์„œ ๋ฐฉ๊ธˆ ์ƒ์„ฑํ•œ ๊ฐœ์ธ ์•ก์„ธ์Šค ํ† ํฐ์„ ์ €์žฅํ•  ์ƒˆ ๊ฐ’์„ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค. ํ•จ์ˆ˜์— ํ† ํฐ์„ ํ•˜๋“œ์ฝ”๋”ฉํ•˜์ง€ ์•Š๊ณ ๋„ ์—”๋“œํฌ์ธํŠธ์—์„œ ๊ฐ’์„ ์ฐธ๊ณ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ฐ’์„ ์ƒ์„ฑํ•˜๋ ค๋ฉด ๋‹ค์Œ์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

  1. ์™ผ์ชฝ ํƒ์ƒ‰ ๋ฉ”๋‰ด์—์„œ Values ์„ ํด๋ฆญํ•ฉ๋‹ˆ๋‹ค.

  2. Create New Value๋ฅผ ํด๋ฆญํ•ฉ๋‹ˆ๋‹ค.

  3. ๊ฐ’์˜ ์ด๋ฆ„์„ GitHubAccessToken ์œผ๋กœ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค.

  4. ์œ ํ˜•์„ Value ์œผ๋กœ ์„ค์ •๋œ ์ƒํƒœ๋กœ ๋‘ก๋‹ˆ๋‹ค.

  5. ๊ฐœ์ธ ์•ก์„ธ์Šค ํ† ํฐ์„ ๊ฐ’์˜ ์ž…๋ ฅ์— ๋ถ™์—ฌ๋„ฃ์Šต๋‹ˆ๋‹ค. ๊ฐ’์€ ์œ ํšจํ•œ JSON์ด์–ด์•ผ ํ•˜๋ฏ€๋กœ ์ฃผ์œ„์— ๋”ฐ์˜ดํ‘œ๋ฅผ ๋„ฃ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

  6. Save๋ฅผ ํด๋ฆญํ•ฉ๋‹ˆ๋‹ค.

์—”๋“œํฌ์ธํŠธ๋Š” GitHub์˜ REST API์™€ ์ƒํ˜ธ ์ž‘์šฉํ•˜์—ฌ ๋Œ“๊ธ€์„ ๋‚จ๊น๋‹ˆ๋‹ค. ๋‚ด์žฅ๋œ ํด๋ผ์ด์–ธํŠธ ๋˜๋Š” ์™ธ๋ถ€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ API์— ์ง์ ‘ HTTP ์š”์ฒญ์„ ์ž‘์„ฑํ•˜๊ณ  ๋ณด๋‚ผ ์ˆ˜ context.http ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ด ํŠœํ† ๋ฆฌ์–ผ์—์„œ๋Š” Octokit ์ด๋ผ๋Š” GitHub์˜ ๊ณต์‹ Node.js ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. API๋ฅผ ๋ž˜ํ•‘ํ•ฉ๋‹ˆ๋‹ค. ์„ค์น˜๊ฐ€ ์™„๋ฃŒ๋˜๋ฉด ์•ฑ์˜ ๋ชจ๋“  ํ•จ์ˆ˜์—์„œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์•ฑ์— ์˜ฅํ† ํ‚ท ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์ถ”๊ฐ€ํ•˜๋ ค๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ํ•˜์„ธ์š”:

  1. ์™ผ์ชฝ ํƒ์ƒ‰ ๋ฉ”๋‰ด์—์„œ Functions ์„ ํด๋ฆญํ•ฉ๋‹ˆ๋‹ค.

  2. 0}Dependencies ํƒญ์„ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค.

  3. Add Dependency๋ฅผ ํด๋ฆญํ•ฉ๋‹ˆ๋‹ค.

  4. ํŒจํ‚ค์ง€ ์ด๋ฆ„ ์ž…๋ ฅ: @octokit/request.

  5. Add๋ฅผ ํด๋ฆญํ•ฉ๋‹ˆ๋‹ค.

  6. App Services์—์„œ ํŒจํ‚ค์ง€๋ฅผ ์„ค์น˜ํ•  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฝ๋‹ˆ๋‹ค. ์„ค์น˜๋Š” ๋ช‡ ์ดˆ ์•ˆ์— ์™„๋ฃŒ๋˜์ง€๋งŒ ์ตœ๋Œ€ 1๋ถ„ ์ •๋„ ๊ฑธ๋ฆด ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด์ œ ์•ก์„ธ์Šค ํ† ํฐ์ด ์žˆ๊ณ  ์˜ฅํ† ํ‚ท์„ ์„ค์น˜ํ–ˆ์œผ๋ฏ€๋กœ ์ด๋ฒคํŠธ๋ฅผ ์ˆ˜์‹ ํ•  ๋•Œ ์‹ค์ œ๋กœ ์–ด๋–ค ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋„๋ก ์—”๋“œํฌ์ธํŠธ ํ•จ์ˆ˜๋ฅผ ์—…๋ฐ์ดํŠธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ตฌ์ฒด์ ์œผ๋กœ, ํ•จ์ˆ˜๋Š” ๋‹ค์Œ์„ ์ˆ˜ํ–‰ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

  • ์ˆ˜์‹  ์›นํ›… ์ด๋ฒคํŠธ ๊ตฌ๋ฌธ ๋ถ„์„

  • MongoDB์— ๊ธฐ์—ฌ๋„ ๊ธฐ๋ก

  • GitHub API๋ฅผ ํ†ตํ•ด ๋Œ“๊ธ€ ์ถ”๊ฐ€

  • GitHub์— ์œ ์šฉํ•œ ์‘๋‹ต์„ ๋‹ค์‹œ ๋ณด๋‚ด๊ธฐ

ํ•จ์ˆ˜๋ฅผ ์—…๋ฐ์ดํŠธํ•˜๋ ค๋ฉด ๋‹ค์Œ์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

  1. ์™ผ์ชฝ ํƒ์ƒ‰ ๋ฉ”๋‰ด์—์„œ Functions ์„ ํด๋ฆญํ•ฉ๋‹ˆ๋‹ค.

  2. endpoints/greetNewContributors ์„(๋ฅผ) ํด๋ฆญํ•˜์—ฌ ์—”๋“œํฌ์ธํŠธ ํ•จ์ˆ˜ ํŽธ์ง‘๊ธฐ๋ฅผ ์—ฝ๋‹ˆ๋‹ค.

  3. ๊ธฐ๋ณธ ํ•จ์ˆ˜๋ฅผ ๋‹ค์Œ ์ฝ”๋“œ๋กœ ๋ฐ”๊ฟ‰๋‹ˆ๋‹ค.

    functions/endpoints/greetNewContributors.js
    exports = async function greetNewContributors(request, response) {
    // Parse the webhook event from the incoming request.
    const event = JSON.parse(request.body.text());
    // Don't do anything unless this is a new issue or pull request
    if (event.action !== "opened") {
    return response.setStatusCode(200);
    }
    // Get data from the GitHub webhook event.
    // Based on the webhook configuration the event will be one of the following:
    // - issues: https://docs.github.com/en/developers/webhooks-and-events/webhooks/webhook-events-and-payloads#issues
    // - pull_request: https://docs.github.com/en/developers/webhooks-and-events/webhooks/webhook-events-and-payloads#pull_request
    const sender = event.sender;
    const repo = event.repository;
    const contribution = event.issue || event.pull_request;
    const contribution_url = event.issue
    ? event.issue.url
    : event.pull_request.issue_url;
    const issue_number = contribution.number;
    // Record this contribution in the user's contributor document.
    // If this user hasn't contributed to the repo before, create a document for them.
    const atlas = context.services.get("mongodb-atlas");
    const contributors = atlas.db("community").collection("contributors");
    const contributor = await contributors.findOneAndUpdate(
    // Look up the user by their GitHub login
    { login: sender.login },
    // Add this issue or pull request to their list of contributions
    {
    $push: {
    contributions: {
    date: new Date(),
    type: event.issue ? "issue" : "pull_request",
    url: contribution_url,
    },
    },
    },
    // If they haven't contributed before, add them to the database
    { upsert: true, returnNewDocument: true }
    );
    // Send a welcome message to first time contributors on their issue or pull request
    const isFirstTimeContributor = contributor.contributions.length === 1;
    if (isFirstTimeContributor) {
    const octokit = require("@octokit/request");
    await octokit.request(
    "POST /repos/{owner}/{repo}/issues/{issue_number}/comments",
    {
    headers: {
    authorization: `token ${context.values.get("GitHubAccessToken")}`,
    },
    owner: repo.owner.login,
    repo: repo.name,
    issue_number: issue_number,
    body: `Hi there ${sender.login} ๐Ÿ‘‹ Thanks for your first contribution!`,
    }
    );
    }
    // Configure the HTTP response sent back to GitHub
    return response
    .setStatusCode(200)
    .setHeader("Content-Type", "application/json")
    .setBody(
    isFirstTimeContributor
    ? `This is ${sender.login}'s first contribution!`
    : `${sender.login} has contributed before.`
    );
    };
  4. Save ์„ ํด๋ฆญํ•˜๊ณ  ์—”๋“œํฌ์ธํŠธ๋ฅผ ๋ฐฐํฌํ•ฉ๋‹ˆ๋‹ค.

์ด์ œ ํ™˜์˜ ๋ฉ”์‹œ์ง€ ์—”๋“œํฌ์ธํŠธ๊ฐ€ ์™„์ „ํžˆ ์„ค์ •๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์ž‘๋™ํ•˜๋Š”์ง€ ํ…Œ์ŠคํŠธํ•˜๋ ค๋ฉด ๋ฆฌํฌ์ง€ํ† ๋ฆฌ์—์„œ ์ƒˆ ์ด์Šˆ ๋˜๋Š” pull ์š”์ฒญ์„ ์—ฝ๋‹ˆ๋‹ค. ์ด ์ž‘์—…์„ ์ฒ˜์Œ ์ˆ˜ํ–‰ํ•  ๋•Œ๋Š” ์—”๋“œํฌ์ธํŠธ๊ฐ€ ์Šค๋ ˆ๋“œ์— ์ƒˆ ๋Œ“๊ธ€์„ ์ถ”๊ฐ€ํ•˜์ง€๋งŒ ์ดํ›„ ์‹œ๋„์—์„œ๋Š” ํ™˜์˜ ๋ฉ”์‹œ์ง€๋ฅผ ์ถ”๊ฐ€ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์—”๋“œํฌ์ธํŠธ์—์„œ ์ถ”๊ฐ€ํ•œ GitHub์˜ ํ™˜์˜ ๋Œ“๊ธ€์˜ ์˜ˆ์‹œ์ž…๋‹ˆ๋‹ค.

GitHub๋Š” ๋ฆฌํฌ์ง€ํ† ๋ฆฌ ์›นํ›… ์š”์ฒญ์„ ๊ธฐ๋กํ•˜๋ฏ€๋กœ GitHub์—์„œ ๋กœ๊ทธ ํ•ญ๋ชฉ์„ ํ™•์ธํ•˜์—ฌ ๋ชจ๋“  ๊ฒƒ์ด ์ œ๋Œ€๋กœ ์ž‘๋™ํ•˜๋Š”์ง€ ํ™•์ธํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ฐ ์š”์ฒญ ๋กœ๊ทธ์—๋Š” ์—”๋“œํฌ์ธํŠธ์˜ ์‘๋‹ต ๋ฉ”์‹œ์ง€๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

์ตœ์ดˆ ๊ธฐ์—ฌ์ž์— ๋Œ€ํ•œ ์‚ฌ์šฉ์ž ์ง€์ • ์—”๋“œํฌ์ธํŠธ์˜ ์‘๋‹ต์„ ๋ณด์—ฌ์ฃผ๋Š” GitHub์˜ ๋กœ๊ทธ ํ•ญ๋ชฉ

ํŒ

ํ…Œ์ŠคํŠธ๋ฅผ ์žฌ์„ค์ •ํ•˜๋ ค๋ฉด community.contributions ์—์„œ GitHub ์‚ฌ์šฉ์ž ์ด๋ฆ„์ด ํฌํ•จ๋œ ๋ฌธ์„œ๋ฅผ ์‚ญ์ œํ•ฉ๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์•ฑ์ด ์ด์ „์— ๊ธฐ์—ฌํ•œ ๋‚ด์šฉ์„ '์žŠ๊ณ ' ๋‹ค์Œ๋ฒˆ ๊ธฐ์—ฌ์—์„œ ํ™˜์˜ํ•ฉ๋‹ˆ๋‹ค.

์•ฑ์ด GitHub์— ์—ฐ๊ฒฐ๋˜๊ณ , ๊ธฐ์—ฌ์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ์ €์žฅํ•˜๊ณ , ์ƒˆ๋กœ์šด ๊ธฐ์—ฌ์ž๋ฅผ ํ™˜์˜ํ•ฉ๋‹ˆ๋‹ค. ์ด์ œ ์ด ๊ธฐ๋Šฅ์„ ํ™•์žฅํ•˜์—ฌ ๋ฆฌํฌ์ง€ํ† ๋ฆฌ์— ๋Œ€ํ•œ ๋ณด๊ณ ์„œ๋ฅผ ์ž๋™์œผ๋กœ ๋ถ„์„ํ•˜๊ณ  ์ƒ์„ฑํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

์•ฑ์—๋Š” ๋งค์ฃผ ์–ด๋–ค ๋ฆฌํฌ์ง€ํ† ๋ฆฌ๋ฅผ ์ƒ์„ฑํ•ด์•ผ ํ•˜๋Š”์ง€ ์•Œ ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ์ด ํŠœํ† ๋ฆฌ์–ผ์—์„œ๋Š” ๋ชฉ๋ก์„ Value.

๊ฐ์ฒด ๋ฐฐ์—ด์„ ํฌํ•จํ•˜๋Š” GitHubProjects ์ด๋ผ๋Š” ์ƒˆ ๊ฐ’์„ ๋งŒ๋“ญ๋‹ˆ๋‹ค. ๊ฐ ๊ฐ์ฒด๋Š” GitHub ๋ฆฌํฌ์ง€ํ† ๋ฆฌ์˜ owner ๋ฐ repo ์ด๋ฆ„์„ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค. ๋ฆฌํฌ์ง€ํ† ๋ฆฌ์— ๋Œ€ํ•œ ํ•ญ๋ชฉ์„ ํฌํ•จํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

values/projects.json
[
{ "owner": "<GitHub Username>", "repo": "<Repository Name>" }
]

๋ณด๊ณ ์„œ๋Š” ์ผ์ • ๊ธฐ๊ฐ„ ๋™์•ˆ ๋ฆฌํฌ์ง€ํ† ๋ฆฌ์— ๊ธฐ์—ฌํ•œ ๋‚ด์šฉ์„ ์š”์•ฝํ•œ ๋ฌธ์„œ์ž…๋‹ˆ๋‹ค. ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฆฌํฌ์ง€ํ† ๋ฆฌ์— ๋Œ€ํ•œ ์˜จ๋””๋งจ๋“œ ๋ณด๊ณ ์„œ๋ฅผ ์ƒ์„ฑํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

generateCommunityReport ์ด๋ผ๋Š” ์ƒˆ ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“ค๊ณ  ๋‹ค์Œ ์ฝ”๋“œ๋ฅผ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

functions/generateCommunityReport.js
exports = async function generateCommunityReport({ owner, repo, startDate }) {
// Look up issues and pull requests that had activity
const octokit = require("@octokit/request");
const { data: issuesWithActivity } = await octokit.request(
"GET /repos/{owner}/{repo}/issues",
{
headers: {
authorization: `token ${context.values.get("GitHubAccessToken")}`,
},
owner: owner,
repo: repo,
since: startDate,
}
);
// Look up users that contributed to the repo
const atlas = context.services.get("mongodb-atlas");
const contributors = atlas.db("community").collection("contributors");
const allContributors = await contributors
.find({
contributions: {
$elemMatch: {
date: { $gt: new Date(startDate) },
owner: owner,
repo: repo,
},
},
})
.toArray();
// Keep track of users who made their first contribution
const newContributors = allContributors.filter((c) => {
new Date(c.contributions[0].date) > new Date(startDate);
});
// Return a report with the data
return {
owner,
repo,
startDate,
issuesWithActivity,
allContributors,
newContributors,
};
};

๋ฐฉ๊ธˆ ์ƒ์„ฑํ•œ ํ•จ์ˆ˜๋Š” ์˜จ๋””๋งจ๋“œ ๋ฐฉ์‹์œผ๋กœ ๋ฆฌํฌ์ง€ํ† ๋ฆฌ์— ๋Œ€ํ•œ ๋ณด๊ณ ์„œ๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ด ์ ์—์„œ ์•„๋ฌด๊ฒƒ๋„ ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜์ง€ ์•Š์œผ๋ฉฐ ์ƒ์„ฑ๋œ ๋ณด๊ณ ์„œ๋Š” ์–ด๋””์—๋„ ์ €์žฅ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์‹ค์ œ๋กœ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด ๋งค์ฃผ ํ•œ ๋ฒˆ ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๊ณ  ์ƒ์„ฑ๋œ ๋ณด๊ณ ์„œ๋ฅผ ์—ฐ๊ฒฐ๋œ ํด๋Ÿฌ์Šคํ„ฐ์— ์ €์žฅํ•˜๋Š” ์˜ˆ์•ฝ๋œ Atlas Trigger๋ฅผ ์ƒ์„ฑํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

ํŠธ๋ฆฌ๊ฑฐ๋ฅผ ์ƒ์„ฑํ•˜๋ ค๋ฉด ๋‹ค์Œ์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

  1. ์™ผ์ชฝ ํƒ์ƒ‰ ๋ฉ”๋‰ด์—์„œ Triggers ์„ ํด๋ฆญํ•ฉ๋‹ˆ๋‹ค.

  2. Add a Trigger๋ฅผ ํด๋ฆญํ•ฉ๋‹ˆ๋‹ค.

  3. trigger ์œ ํ˜•์œผ๋กœ Scheduled ๋ฅผ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค.

  4. trigger ์ด๋ฆ„ ์ง€์ • generateAndSaveCommunityReports

  5. Advanced ์ผ์ • ์œ ํ˜• ์„ ํƒ

  6. ๋‹ค์Œ ํฌ๋ก  ์ผ์ •์„ ์ž…๋ ฅํ•˜์—ฌ ์ผ์ฃผ์ผ์— ํ•œ ๋ฒˆ ์›”์š”์ผ ์˜ค์ „ 5์‹œ(UTC)์— ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.

    0 5 * * 1
  7. ํŠธ๋ฆฌ๊ฑฐ์— ๋Œ€ํ•œ ์ƒˆ ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“ค๊ณ  ์ด๋ฆ„์„ triggers/generateAndSaveCommunityReports ์œผ๋กœ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค.

  8. Add Dependency ์„ ํด๋ฆญํ•˜๊ณ  moment ์„ ์„ค์น˜ํ•ฉ๋‹ˆ๋‹ค.

  9. ๋‹ค์Œ ์ฝ”๋“œ๋ฅผ ํ•จ์ˆ˜ ๋ณธ๋ฌธ์— ๋ณต์‚ฌํ•ฉ๋‹ˆ๋‹ค.

    functions/Atlas Triggers/generateAndSaveCommunityReports.js
    exports = async function generateAndSaveCommunityReports() {
    const projects = context.values.get("GitHubProjects");
    const lastMonday = getLastMonday(); // e.g. "2022-02-21T05:00:00.000Z"
    // Generate a report for every tracked repo
    const reportsForLastWeek = await Promise.all(
    // Call the `generateCommunityReport` function for each project
    projects.map(async (project) => {
    return context.functions.execute("generateCommunityReport", {
    owner: project.owner,
    repo: project.repo,
    startDate: lastMonday,
    });
    })
    );
    // Save the generated reports in Atlas
    const atlas = context.services.get("mongodb-atlas");
    const reports = atlas.db("community").collection("reports");
    return await reports.insertMany(reportsForLastWeek);
    };
    // Get an ISO string for last Monday at 5AM UTC
    function getLastMonday() {
    const moment = require("moment");
    return moment(new Date().setUTCHours(5, 0, 0, 0))
    .utc()
    .day(1 - 7)
    .toISOString();
    }
  10. Save๋ฅผ ํด๋ฆญํ•ฉ๋‹ˆ๋‹ค.

  11. ์ด ํŠœํ† ๋ฆฌ์–ผ ์•ž๋ถ€๋ถ„์˜ ์ƒˆ ์—”๋“œํฌ์ธํŠธ์˜ ํ•จ์ˆ˜์™€ ์ผ์น˜ํ•˜๋„๋ก ์ƒˆ ํ•จ์ˆ˜์˜ ์ธ์ฆ ์„ค์ • ์„ ์—…๋ฐ์ดํŠธํ•ฉ๋‹ˆ๋‹ค.

์ด์ œ ์•ฑ์ด ๋งค์ฃผ ์ž๋™์œผ๋กœ ๋ณด๊ณ ์„œ๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ์ €์žฅํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๋ณด๊ณ ์„œ๋ฅผ ๋ณด๋Š” ์‚ฌ๋žŒ์ด ์—†๋‹ค๋ฉด ๋ณด๊ณ ์„œ๋Š” ๊ทธ๋‹ค์ง€ ์œ ์šฉํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ƒˆ ๋ณด๊ณ ์„œ๋ฅผ ์ˆ˜์‹ ํ•˜๊ณ  ์ตœ์ข… ์‚ฌ์šฉ์ž์—๊ฒŒ ๋ณด๋‚ผ ์ˆ˜ ์žˆ๋Š” ํ˜•์‹์˜ ๋ฉ”์‹œ์ง€๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ํŠธ๋ฆฌ๊ฑฐ๋ฅผ ์ƒ์„ฑํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

๋ฉ”์‹œ์ง€๋ฅผ ์„ค์ •ํ•˜๋ ค๋ฉด ๋‹ค์Œ์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

  1. ์™ผ์ชฝ ํƒ์ƒ‰ ๋ฉ”๋‰ด์—์„œ Triggers ์„ ํด๋ฆญํ•ฉ๋‹ˆ๋‹ค.

  2. Add a Trigger๋ฅผ ํด๋ฆญํ•ฉ๋‹ˆ๋‹ค.

  3. trigger ์œ ํ˜•์„ Database ๋กœ ์„ค์ •๋œ ์ƒํƒœ๋กœ ๋‘ก๋‹ˆ๋‹ค.

  4. ํŠธ๋ฆฌ๊ฑฐ์˜ ์ด๋ฆ„์„ sendCommunityReport๋กœ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค.

  5. trigger๋ฅผ community.reports collection์— ์ถ”๊ฐ€ํ•˜๊ณ  Insert ์ด๋ฒคํŠธ๋ฅผ ์ˆ˜์‹  ๋Œ€๊ธฐํ•ฉ๋‹ˆ๋‹ค.

  6. ํŠธ๋ฆฌ๊ฑฐ ํ•จ์ˆ˜์— ์ „๋‹ฌ๋œ ๋ณ€๊ฒฝ ์ด๋ฒคํŠธ์— ๊ฐ๊ฐ์˜ ์ƒˆ ๋ณด๊ณ ์„œ ๋ฌธ์„œ๋ฅผ ํฌํ•จํ•˜๋ ค๋ฉด Full Document๋ฅผ ํ™œ์„ฑํ™”ํ•ฉ๋‹ˆ๋‹ค.

  7. ํŠธ๋ฆฌ๊ฑฐ์— ๋Œ€ํ•œ ์ƒˆ ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“ค๊ณ  ์ด๋ฆ„์„ triggers/sendCommunityReport ์œผ๋กœ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค.

  8. ๋‹ค์Œ ์ฝ”๋“œ๋ฅผ ํ•จ์ˆ˜ ๋ณธ๋ฌธ์— ๋ณต์‚ฌํ•ฉ๋‹ˆ๋‹ค.

    functions/Atlas Triggers/sendCommunityReport.js
    exports = async function sendCommunityReport(changeEvent) {
    // Pull out the report document from the database change event
    const report = changeEvent.fullDocument;
    // Format values from the report to include in the message
    const projectName = `${report.owner}/${report.repo}`;
    const moment = require("moment");
    const formattedDate = moment(report.startDate).utc().format("MMMM Do, YYYY");
    const numIssuesWithActivity = report.issuesWithActivity.length;
    const numContributors = report.allContributors.length;
    const numNewContributors = report.newContributors.length;
    // Create a message string that describes the data in the report
    const message = [
    `# Community contributions to ${projectName} since ${formattedDate}`,
    `Last week, there was activity on ${numIssuesWithActivity} issues and pull requests.`,
    `We had ${numContributors} people contribute, including ${numNewContributors} first time contributors.`,
    ].join("\n");
    // For this tutorial we'll just log the message, but you could use a
    // service to send it as an email or push notification instead.
    console.log(message);
    };
  9. Save ์„ ํด๋ฆญํ•˜๊ณ  trigger๋ฅผ ๋ฐฐํฌํ•ฉ๋‹ˆ๋‹ค.

์•ฑ์ด ๋งค์ฃผ ๋ณด๊ณ ์„œ๋ฅผ ์ž๋™์œผ๋กœ ์ƒ์„ฑ, ์ €์žฅํ•˜๊ณ  ์ „์†กํ•˜๋„๋ก ์„ค์ •๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ๋ชจ๋“  ๊ฒƒ์ด ์ œ๋Œ€๋กœ ์ž‘๋™ํ•˜๋Š”์ง€ ํ™•์ธํ•˜๋ ค๋ฉด ์ด ๋ณด๊ณ ์„œ ํ๋ฆ„์„ ์ˆ˜๋™์œผ๋กœ ์‹คํ–‰ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

์˜ˆ์•ฝ๋œ ํŠธ๋ฆฌ๊ฑฐ triggers/generateAndSaveCommunityReports ์— ๋Œ€ํ•œ ํ•จ์ˆ˜ ํŽธ์ง‘๊ธฐ๋ฅผ ์—ฐ ๋‹ค์Œ Run ๋ฒ„ํŠผ์„ ํด๋ฆญํ•ฉ๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด GitHubProjects ๊ฐ’์— ๋‚˜์—ดํ•œ ๋ชจ๋“  ๋ฆฌํฌ์ง€ํ† ๋ฆฌ์— ๋Œ€ํ•œ ์˜จ๋””๋งจ๋“œ ๋ณด๊ณ ์„œ๊ฐ€ ์ƒ์„ฑ๋˜๊ณ  ์ €์žฅ๋ฉ๋‹ˆ๋‹ค.

ํ™•์ธํ•˜๋ ค๋ฉด ๋‹ค์Œ์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

  1. ์ƒˆ ๋ณด๊ณ ์„œ ๋ฌธ์„œ๋Š” community.reports ์„(๋ฅผ) ํ™•์ธํ•˜์„ธ์š”.

  2. ์•ฑ์˜ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค trigger ๋กœ๊ทธ๋ฅผ ํ™•์ธํ•˜์—ฌ ๊ฐ ๋ณด๊ณ ์„œ์— ๋Œ€ํ•ด ํ˜•์‹์ด ์ง€์ •๋œ ๋ฉ”์‹œ์ง€๋ฅผ ์ฐพ์Šต๋‹ˆ๋‹ค.

์ถ•ํ•˜ํ•ฉ๋‹ˆ๋‹ค! ์„œ๋ฒ„๋ฆฌ์Šค GitHub ๊ธฐ์—ฌ ์ถ”์ ๊ธฐ๋ฅผ ์„ฑ๊ณต์ ์œผ๋กœ ์„ค์ •ํ•˜๊ณ  ์ด ํŠœํ† ๋ฆฌ์–ผ์„ ์™„๋ฃŒํ–ˆ์Šต๋‹ˆ๋‹ค.

๊ณ„์† ๊ฐœ๋ฐœํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด ํŠธ๋ž˜์ปค์— ๋ช‡ ๊ฐ€์ง€ ์ƒˆ๋กœ์šด ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ•ด ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • issue_comment ์™€ ๊ฐ™์€๋” ๋งŽ์€ ์›นํ›… ์ด๋ฒคํŠธ ์œ ํ˜•์„ ์ฒ˜๋ฆฌํ•˜๋„๋ก ์—”๋“œํฌ์ธํŠธ๋ฅผ ์—…๋ฐ์ดํŠธํ•ฉ๋‹ˆ๋‹ค. ๋˜๋Š” pull_request_review.

  • GitHub API์˜ ๋” ๋งŽ์€ ์ •๋ณด๋ฅผ ํฌํ•จํ•˜๋„๋ก ์ฃผ๊ฐ„ ๋ณด๊ณ ์„œ๋ฅผ ์—…๋ฐ์ดํŠธํ•ฉ๋‹ˆ๋‹ค.

  • Twilio ์™€ ๊ฐ™์€ ์™ธ๋ถ€ ์„œ๋น„์Šค์— ์—ฐ๊ฒฐ ๋˜๋Š” SendGrid ๊ธฐ๋กํ•˜๋Š” ๋Œ€์‹  ์ด๋ฉ”์ผ์ด๋‚˜ SMS๋ฅผ ํ†ตํ•ด ์‹ค์ œ๋กœ ๋ณด๊ณ ์„œ๋ฅผ ๋ณด๋‚ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

App Services์—๋Š” ์•ฑ์„ ๊ฐ•ํ™”ํ•  ์ˆ˜ ์žˆ๋Š” ๋งŽ์€ ์„œ๋น„์Šค๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ์„œ๋น„์Šค์™€ ์‚ฌ์šฉ ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ์ž์„ธํžˆ ์•Œ์•„๋ณด๋ ค๋ฉด ๋‚˜๋จธ์ง€ ์„ค๋ช…์„œ๋ฅผ ํ™•์ธํ•˜์„ธ์š”.

์šฐ๋ฆฌ๋Š” ํ•ญ์ƒ ๋ฌธ์„œ์™€ ํŠœํ† ๋ฆฌ์–ผ์„ ๊ฐœ์„ ํ•˜๊ธฐ ์œ„ํ•ด ๋…ธ๋ ฅํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ํŠœํ† ๋ฆฌ์–ผ๊ณผ ๊ด€๋ จํ•˜์—ฌ ์ œ์•ˆ ์‚ฌํ•ญ์ด ์žˆ๊ฑฐ๋‚˜ ๋ฌธ์ œ๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ ์ด ํŽ˜์ด์ง€ ํ•˜๋‹จ์˜ Give Feedback ๋ฅผ ํด๋ฆญํ•˜์—ฌ ํŠœํ† ๋ฆฌ์–ผ์„ ํ‰๊ฐ€ํ•˜๊ณ  ๋Œ“๊ธ€์„ ๋ณด๋‚ด์ฃผ์„ธ์š”.

๊ณต์‹ MongoDB Community ํฌ๋Ÿผ ์€ ๋‹ค๋ฅธ ๊ฐœ๋ฐœ์ž๋ฅผ ๋งŒ๋‚˜๊ณ  ์งˆ๋ฌธํ•˜๊ณ  ๋‹ต๋ณ€ํ•˜๊ณ  ์ตœ์‹  App Services ๊ธฐ๋Šฅ ๋ฐ ๋ฆด๋ฆฌ์Šค์— ๋Œ€ํ•œ ์ตœ์‹  ์ •๋ณด๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ๋Š” ์ข‹์€ ์žฅ์†Œ์ž…๋‹ˆ๋‹ค.

์ด ํŽ˜์ด์ง€์˜ ๋‚ด์šฉ