์ด๊ทผ๋‘ฅ
๊ทผ๋‘ฅ์ด์˜ ๋ธ”๋กœ๊ทธ
์ด๊ทผ๋‘ฅ
์ „์ฒด ๋ฐฉ๋ฌธ์ž
874,952
์˜ค๋Š˜
323
์–ด์ œ
187

๊ณต์ง€์‚ฌํ•ญ

  • ์ „์ฒด๋ณด๊ธฐ (107)
    • ์›น (9)
    • ์–ธ์–ด & ํ”„๋ ˆ์ž„์›Œํฌ (53)
      • JavaScript (7)
      • TypeScript (0)
      • Node.js (11)
      • Vue.js (3)
      • React (0)
      • React Native (0)
      • C & C++ (19)
      • Java & JSP (9)
      • Python (4)
    • ์ปดํ“จํ„ฐ ๊ณผํ•™ (3)
      • ์•Œ๊ณ ๋ฆฌ์ฆ˜ (0)
      • ์ž๋ฃŒ๊ตฌ์กฐ (3)
    • ๊ธฐํƒ€ (9)
      • Linux (1)
      • Git (2)
      • DialogFlow (4)
    • ์ผ์ƒ (13)
      • ๊ฒŒ์ž„ (13)
    • ์นผ๋Ÿผ (9)
      • ํšŒ๊ณ  (0)
      • ๋‚˜๋งŒ์˜ ๊ธ€ (0)
      • ์ œํ’ˆ ๋ฆฌ๋ทฐ (9)
    • __Dev__ (9)
      • Release (9)
๋ฐ˜์‘ํ˜•

์ธ๊ธฐ ๊ธ€

  • ์›น ํ‘ธ์‹œ ์•Œ๋ฆผ(Web Push Notification)
    2022.06.13
    ์›น ํ‘ธ์‹œ ์•Œ๋ฆผ(Web Push Notification)
  • [Tomcat] ์•„ํŒŒ์น˜ ํ†ฐ์บฃ ์„œ๋ฒ„ ํฌํŠธ ๋ณ€๊ฒฝํ•˜๊ธฐ
    2018.08.24
    [Tomcat] ์•„ํŒŒ์น˜ ํ†ฐ์บฃ ์„œ๋ฒ„ ํฌํŠธ ๋ณ€๊ฒฝํ•˜๊ธฐ
  • [Node.js] ์‹ค์‹œ๊ฐ„ ์ฑ„ํŒ… ์„œ๋น„์Šค ๋งŒ๋“ค๊ธฐ(5) - ์ฑ„ํŒ…โ‹ฏ
    2018.05.31
    [Node.js] ์‹ค์‹œ๊ฐ„ ์ฑ„ํŒ… ์„œ๋น„์Šค ๋งŒ๋“ค๊ธฐ(5) - ์ฑ„ํŒ…โ‹ฏ
  • [C/C++] ์ฝ˜์†”๊ฒŒ์ž„ ํ”„๋กœ๊ทธ๋ž˜๋ฐ (1) - ํ”„๋กœ์ ํŠธ ์ƒ์„ฑโ‹ฏ
    2017.12.19
    [C/C++] ์ฝ˜์†”๊ฒŒ์ž„ ํ”„๋กœ๊ทธ๋ž˜๋ฐ (1) - ํ”„๋กœ์ ํŠธ ์ƒ์„ฑโ‹ฏ
  • [Vue 3] Composition API์™€ ํ…œํ”Œ๋ฆฟ ์ฐธ์กฐ(โ‹ฏ
    2020.10.02
    [Vue 3] Composition API์™€ ํ…œํ”Œ๋ฆฟ ์ฐธ์กฐ(โ‹ฏ

ํƒœ๊ทธ

  • spread syntax
  • ์ž๋ฐ” ํ”„๋กœ์ ํŠธ
  • Java FX
  • ์ดํด๋ฆฝ์Šค
  • ES6
  • vue.js
  • ์›น ํ™•์žฅ
  • vue3
  • composition-api
  • ์ „๊ฐœ ๊ตฌ๋ฌธ
  • self
  • vue
  • ์ถœ๊ฐ„
  • ํ”„๋กœ๊ทธ๋ ˆ์‹œ๋ธŒ ์›น ์•ฑ
  • Hello World!
  • Composition API
  • java
  • WWDC20
  • pwa
  • Deemo
  • ์ดํŽ™ํŠธ
  • vue-next
  • vuex
  • ํŒŒํ‹ฐํด
  • Scanner
  • javascript
  • WWDC
  • Vue 3
  • AstroWar
  • ์ž๋ฐ”

์ตœ๊ทผ ๋Œ“๊ธ€

  • ์–ด๋””์—์„œ๋„ ์ด๋Ÿฐ ์นœ์ ˆํ•œ ์„ค๋ช…์€ ๋ฐ›์„ ์ˆ˜ ์—†์—ˆ์Šต๋‹ˆ๋‹ค. ์‘์šฉโ‹ฏ
    ๋ฏธ์ณค๋‹ค...
  • ์ •๋ง ๋„ˆ๋ฌด ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค ์„ ์ƒ๋‹˜ ๋งŽ์€ ๋„์›€์ด ๋˜๊ณ ์žˆ์Šต๋‹ˆ๋‹ค ์–ด๋–ปโ‹ฏ
    ๊น€์ค€ํƒœ
  • ์ปค์„œ ์œ„์น˜์ด๋™ ํ•จ์ˆ˜๊นŒ์ง€ ํ–ˆ๋Š”๋ฐ ์ปดํŒŒ์ผํ•˜๋ฉด Makefile.โ‹ฏ
    Qour94
  • iOS์˜ ๊ฒฝ์šฐ ์• ํ”Œ์—์„œ ๊ฐœ๋ฐœํ•˜๊ณ  ์žˆ๋Š” webkit ์—”์ง„์„ โ‹ฏ
    ์ด๊ทผ๋‘ฅ
  • android, IOS์—์„œ ๋œ๋‹ค๊ณ  ํ–ˆ๋Š”๋ฐ Notificaโ‹ฏ
    ์‚ฝ์ž๋ฃจ๋ถ€๋Œ€

์ตœ๊ทผ ๊ธ€

  • ์›น ํ‘ธ์‹œ ์•Œ๋ฆผ(Web Push Notification)
    2022.06.13
    ์›น ํ‘ธ์‹œ ์•Œ๋ฆผ(Web Push Notification)
  • ์Šคํƒ(Stack)
    2022.05.26
    ์Šคํƒ(Stack)
  • ๋ฐฐ์—ด(Array)
    2022.05.25
    ๋ฐฐ์—ด(Array)
  • C์–ธ์–ด๋กœ ๋ฐฐ์šฐ๋Š” ์ž๋ฃŒ๊ตฌ์กฐ
    2022.05.24
    C์–ธ์–ด๋กœ ๋ฐฐ์šฐ๋Š” ์ž๋ฃŒ๊ตฌ์กฐ
  • [Vue 3] Composition API์™€ ํ…œํ”Œ๋ฆฟ ์ฐธ์กฐ(โ‹ฏ
    2020.10.02
    [Vue 3] Composition API์™€ ํ…œํ”Œ๋ฆฟ ์ฐธ์กฐ(โ‹ฏ

๋ธ”๋กœ๊ทธ ๋ฉ”๋‰ด

  • ํ™ˆ
  • ๋ฏธ๋””์–ด๋กœ๊ทธ
  • ๋ฐฉ๋ช…๋ก
hELLO ยท Designed By ์ •์ƒ์šฐ.
์ด๊ทผ๋‘ฅ

๊ทผ๋‘ฅ์ด์˜ ๋ธ”๋กœ๊ทธ

์›น ํ‘ธ์‹œ ์•Œ๋ฆผ(Web Push Notification)
์›น

์›น ํ‘ธ์‹œ ์•Œ๋ฆผ(Web Push Notification)

2022. 6. 13. 04:38
๋ฐ˜์‘ํ˜•

๐Ÿ‘‰ ์‹œ์ž‘ํ•˜๋ฉด์„œ

์›น ํ‘ธ์‹œ ์•Œ๋ฆผ(Web Push Notification)์ด๋ž€, ๋ง ๊ทธ๋Œ€๋กœ ๋ธŒ๋ผ์šฐ์ € ํ™˜๊ฒฝ์—์„œ ํ‘ธ์‹œ ์•Œ๋ฆผ์„ ๋ฐ›์„ ์ˆ˜ ์žˆ๋Š” ๊ธฐ์ˆ ์„ ์˜๋ฏธํ•œ๋‹ค.

ํ‘ธ์‹œ ์•Œ๋ฆผ์ด๋ผ๊ณ  ํ•˜๋ฉด ๋„ค์ดํ‹ฐ๋ธŒ ์•ฑ์˜ ์ „์œ ๋ฌผ์ด๋ผ๊ณ  ๋А๋‚„ ์ˆ˜ ์žˆ์ง€๋งŒ, ์›น ํ‘ธ์‹œ ๊ธฐ์ˆ ์„ ํ†ตํ•ด ์›น์—์„œ๋„ ํ‘ธ์‹œ ์•Œ๋ฆผ ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•˜๊ณ  ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

๋ธŒ๋ผ์šฐ์ €์— ๊ตฌํ˜„๋˜์–ด์žˆ๋Š” Push API์™€ ์ž์„ธํ•œ ์ŠคํŽ™์€ ์•„๋ž˜ ๋ฌธ์„œ์—์„œ ํ™•์ธํ•ด๋ณผ ์ˆ˜ ์žˆ๋‹ค.

  • MDN Web Docs
  • W3 Spec

๋ณธ ํฌ์ŠคํŒ…์—์„œ๋Š” ์›น ํ‘ธ์‹œ๊ฐ€ ๋™์ž‘ํ•˜๋Š” ๋ฉ”์ปค๋‹ˆ์ฆ˜์— ๋Œ€ํ•ด ์กฐ๊ธˆ ์„ธ๋ถ€์ ์œผ๋กœ ์‚ดํŽด๋ณด๊ณ , ์ง์ ‘ ๋ฐ๋ชจ ์ฝ”๋“œ๋ฅผ ์‚ดํŽด๋ณด๋ฉฐ ์›น ํ‘ธ์‹œ์— ๋Œ€ํ•œ ์ „๋ฐ˜์ ์ธ ์ดํ•ด๋ฅผ ํ•  ์ˆ˜ ์žˆ๋„๋ก ์ง„ํ–‰ํ•  ์˜ˆ์ •์ด๋‹ค.
๋ถ„๋Ÿ‰์„ ์กฐ์ ˆํ•˜๊ธฐ ์œ„ํ•ด ๋ชจ๋“  API ๊ธฐ๋Šฅ์— ๋Œ€ํ•ด ์„ค๋ช…ํ•˜์ง„ ์•Š์œผ๋‹ˆ ์ž์„ธํ•œ ๋‚ด์šฉ์€ ๊ธ€ ์ค‘๊ฐ„์ค‘๊ฐ„์— ์ถ”๊ฐ€ํ•ด๋‘” ์ฐธ์กฐ ๋งํฌ(๋ฌธ์„œ)๋ฅผ ์ฐธ๊ณ ํ•˜๊ธธ ๋ฐ”๋ž€๋‹ค.

๋ณธ ํฌ์ŠคํŒ…์—์„œ ๋‹ค๋ฃจ๋Š” ๋Œ€๋ถ€๋ถ„์˜ ๋‚ด์šฉ์€ ๊ณผ๊ฑฐ์— ์ถœ๊ฐ„ํ–ˆ๋˜ ์ €์„œ์˜ ๋‚ด์šฉ๊ณผ ๋™์ผํ•˜๋ฉฐ, PWA์— ๊ด€์‹ฌ์ด ์žˆ๋‹ค๋ฉด ํ•œ ๋ฒˆ ์‚ดํŽด๋ณด๋ฉด ์ข‹์„ ๊ฒƒ ๊ฐ™๋‹ค.

 

[PWA] SNS ์•ฑ ์˜ˆ์ œ๋กœ ๋ฐฐ์šฐ๋Š” ํ”„๋กœ๊ทธ๋ ˆ์‹œ๋ธŒ ์›น ์•ฑ ์ถœ๊ฐ„!

์•ˆ๋…•ํ•˜์„ธ์š”~!! ์ด๋ฒˆ์— ํ”„๋กœ๊ทธ๋ ˆ์‹œ๋ธŒ ์›น ์•ฑ(PWA)์„ ์ฃผ์ œ๋กœ ํ•œ "SNS ์•ฑ ์˜ˆ์ œ๋กœ ๋ฐฐ์šฐ๋Š” ํ”„๋กœ๊ทธ๋ ˆ์‹œ๋ธŒ ์›น ์•ฑ" ์„ ์ถœ๊ฐ„ํ•˜๊ฒŒ ๋˜์–ด ๊ฐ„๋žตํžˆ ์†Œ๊ฐœํ•˜๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค! ๐ŸŽ‰ ๋ณธ ๋ธ”๋กœ๊ทธ์—๋„ ํ”„๋กœ๊ทธ๋ ˆ์‹œ๋ธŒ ์›น ์•ฑ์— ๋Œ€

geundung.dev

 

๐ŸŽ ์• ํ”Œ๊ณผ ์›น ํ‘ธ์‹œ

์•ˆ๋“œ๋กœ์ด๋“œ ๋ฐ Chromium ๊ธฐ๋ฐ˜ ๋ธŒ๋ผ์šฐ์ € ๋“ฑ์—์„œ๋Š” ๊ฝค ์˜ค๋ž˜์ „๋ถ€ํ„ฐ ์›น ํ‘ธ์‹œ๋ฅผ ์ง€์›ํ•ด์™”๊ธฐ ๋•Œ๋ฌธ์— ์›น์—์„œ ํ‘ธ์‹œ ์•Œ๋ฆผ์„ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ์—ˆ์œผ๋‚˜, ์• ํ”Œ์˜ Safari ๋ธŒ๋ผ์šฐ์ €๋Š” ์ด๋ฅผ ์ง€์›ํ•˜์ง€ ์•Š์•˜๋‹ค.

์‚ฌ์‹ค ๋ณธ์ธ์€ ์• ํ”Œ์ด PWA๋ฅผ ๋‚ด๋‹ค ๋ฒ„๋ฆฐ ์ค„ ์•Œ์•˜๋‹ค.
์• ํ”Œ์€ ํ•ญ์ƒ ํ์‡„์ ์ธ ๋ชจ์Šต์„ ๋ณด์ด๋Š”๋ฐ, ์›น์—๊ฒŒ ๋„ˆ๋ฌด ๋งŽ์€ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•˜์—ฌ ๋„ค์ดํ‹ฐ๋ธŒ ์•ฑ๊ณผ์˜ ๊ฒฝ๊ณ„๋ฅผ ํ—ˆ๋ฌผ๋ฆฌ ์—†๋‹ค๊ณ  ์ƒ๊ฐํ–ˆ๋‹ค.

์—ญ์‹œ๋‚˜ ์• ํ”Œ์€ ๊ตฌ๊ธ€๊ณผ ๋งˆ์ดํฌ๋กœ์†Œํ”„ํŠธ ๋“ฑ์˜ ์›น ์ƒํƒœ๊ณ„๋ฅผ ์ฃผ๋„์ ์œผ๋กœ ์ด๋Œ์–ด๊ฐ€๋Š” ์กฐ์ง๊ณผ ๋‹ค๋ฅด๊ฒŒ PWA ๊ด€๋ จ ๊ธฐ์ˆ (ํ‘ธ์‹œ ์•Œ๋ฆผ ํฌํ•จ)์— ๋Œ€ํ•ด ์ ๊ทน์ ์œผ๋กœ ๋Œ€์‘ํ•˜์ง€ ์•Š์•˜๊ณ , ๊ทธ ๊ฒฐ๊ณผ๋กœ Safari ๋ธŒ๋ผ์šฐ์ €์—์„œ๋งŒ ์ง€์›ํ•˜์ง€ ์•Š๋Š” API๊ฐ€ ์—ฌ๋Ÿฟ ์ƒ๊ธฐ๊ฒŒ ๋˜์—ˆ๋‹ค.

ํ˜„ ์ƒํ™ฉ์—์„œ macOS ๊ทธ๋ฆฌ๊ณ  iOS์™€ iPadOS ์œ ์ €๋“ค์ด ์‚ฌ์šฉํ•˜๋Š” Safari ๋ธŒ๋ผ์šฐ์ €์˜ ์ ์œ ์œจ์€ ๊ฒฐ์ฝ” ๋ฌด์‹œํ•  ์ˆ˜ ์—†๋Š” ์ˆ˜์ค€์ด๊ธฐ์—, ์›น(PWA)์ด ํž˜์„ ์–ป๊ณ  ์˜ํ–ฅ๋ ฅ์„ ํŽผ์น˜๋ ค๋ฉด Safari ๋ธŒ๋ผ์šฐ์ €์˜ ์ ๊ทน์ ์ธ PWA ์ง€์›์ด ํ•„์š”ํ•œ ์ƒํ™ฉ์ด์—ˆ๋‹ค.

PWA์— ๋Œ€ํ•ด ๊ด€์‹ฌ์ด ๋งŽ์•˜๋˜ ๋ณธ์ธ์€, WWDC20๋ถ€ํ„ฐ ์›น ํ‘ธ์‹œ์— ๋Œ€ํ•œ ๋‚ด์šฉ์„ ๊ธฐ๋‹ค๋ ค์™”์œผ๋‚˜ ํ•ญ์ƒ ๊ธฐ๋Œ€ํ–ˆ๋˜ ๊ฒƒ๊ณผ๋Š” ๋‹ค๋ฅธ ๋‚ด์šฉ๋งŒ ์–ป์—ˆ๊ธฐ์— ๋‹ค์†Œ ์•„์‰ฌ์›€์ด ๋งŽ์•˜๋‹ค. ๊ทธ๋Ÿฌ๋˜ ์ค‘ ์ตœ๊ทผ ์ง„ํ–‰๋˜์—ˆ๋˜ ์• ํ”Œ ๊ฐœ๋ฐœ์ž ํ–‰์‚ฌ์ธ WWDC22์˜ Meet Web Push for Safari ์„ธ์…˜์—์„œ ๋“œ๋””์–ด ์›น ํ‘ธ์‹œ์— ๊ด€ํ•œ ๋‚ด์šฉ์ด ์–ธ๊ธ‰๋˜์—ˆ๋‹ค.

Web Push is supported in Mac Safari beginning with macOS Ventura. And Web Push will be coming to iOS and iPadOS next year.

์ด๋ฒˆ์— ๋ฐœํ‘œํ•œ ๋‚ด์šฉ์— ๋”ฐ๋ฅด๋ฉด ์›น ํ‘ธ์‹œ๋ฅผ ์ง€์›ํ•˜๋Š” ์‚ฌํŒŒ๋ฆฌ ๋ฒ„์ „์€ ์•„๋ž˜์™€ ๊ฐ™๋‹ค.

  • Safari 16 (macOS 13, Ventura ๋ถ€ํ„ฐ)
  • iOS ๋ฐ iPadOS๋Š” ๋‚ด๋…„(2023๋…„)๋ถ€ํ„ฐ ์ง€์›

๋‹คํ–‰์ธ ์ ์€ ์• ํ”Œ ๋…์ž์ ์ธ ์›น ํ‘ธ์‹œ๊ฐ€ ์•„๋‹ˆ๋ผ, ๋‹ค๋ฅธ ๋ธŒ๋ผ์šฐ์ €๋“ค์—์„œ ๊ตฌํ˜„๋˜์–ด์žˆ๋Š” ์›น ํ‘ธ์‹œ ํ‘œ์ค€์„ ๋”ฐ๋ฅธ๋‹ค๊ณ  ํ•œ๋‹ค. (์• ํ”Œ์˜ ๋ณต์žกํ•œ ์ธ์ฆ์„œ ์—†์ด๋„ ๊ฐ„๋‹จํžˆ ํ‘ธ์‹œ ์•Œ๋ฆผ์„ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ๋‹ค)

์•„์ง MDN Web Docs์˜ ์›น ํ‘ธ์‹œ API ํ˜ธํ™˜์„ฑ ํ‘œ๊ฐ€ ์—…๋ฐ์ดํŠธ๋˜์ง€ ์•Š์•˜๋Š”๋ฐ, ๊ณง ์—…๋ฐ์ดํŠธ๋  ๊ฒƒ ๊ฐ™๊ณ  ๋‚ด๋…„์—๋Š” iOS Safari ์—๋„ ์ฒดํฌ ์•„์ด์ฝ˜์ด ์ƒ๊ธฐ๊ฒŒ ๋  ๊ฒƒ์œผ๋กœ ๋ณด์ธ๋‹ค.

์•„์ง ์—…๋ฐ์ดํŠธ ๋˜์ง€ ์•Š์€ Push API ํ˜ธํ™˜์„ฑ ํ‘œ

์กฐ๋งŒ๊ฐ„ ์œ„ ํ˜ธํ™˜์„ฑ ํ‘œ ์†์˜ Safari X ์•„์ด์ฝ˜์€ ์—ญ์‚ฌ ์†์œผ๋กœ ์‚ฌ๋ผ์งˆ ๊ฒƒ์ด๋‹ค.

์–ด์จŒ๋“ , ์• ํ”Œ์ด ํฌ๊ธฐํ•œ ์ค„๋งŒ ์•Œ์•˜๋˜ ์›น ํ‘ธ์‹œ๋ฅผ ์ง€์›ํ•ด์ค€๋‹ค๊ณ  ํ•˜๋‹ˆ ์•ž์œผ๋กœ์˜ ์›น ๊ธฐ์ˆ ์ด ์–ด๋–ป๊ฒŒ ๋ณ€ํ™”ํ• ์ง€ ๊ธฐ๋Œ€๊ฐ€ ๋œ๋‹ค.

๐Ÿ‘€ ์›น ํ‘ธ์‹œ ๋™์ž‘ ์‚ดํŽด๋ณด๊ธฐ

์›น ํ‘ธ์‹œ๊ฐ€ ์ „๋ฐ˜์ ์œผ๋กœ ์–ด๋–ป๊ฒŒ ๋™์ž‘ํ•˜๋Š”์ง€ ๋ฉ”์ปค๋‹ˆ์ฆ˜์— ๋Œ€ํ•ด ์‚ดํŽด๋ณด๋„๋ก ํ•˜์ž.

๐Ÿš€ ํ’€(Pull)๊ณผ ํ‘ธ์‹œ(Push)

๋จผ์ € ํ’€(Pull)๊ณผ ํ‘ธ์‹œ(Push)์˜ ์ฐจ์ด๋ฅผ ์•„๋ž˜ ๊ทธ๋ฆผ์„ ๋ณด๋ฉฐ ์‚ดํŽด๋ณด์ž.

์œ„: ํ’€(Pull), ์•„๋ž˜: ํ‘ธ์‹œ(Push)

ํ’€(Pull)์€ ๋Œ€๋ถ€๋ถ„์˜ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ์‰ฝ๊ฒŒ ์‚ดํŽด๋ณผ ์ˆ˜ ์žˆ๋Š” ๋™์ž‘ ๋ฐฉ์‹์ด๋‹ค.
ํด๋ผ์ด์–ธํŠธ ๊ธฐ์ค€์œผ๋กœ ๋ณด์•˜์„ ๋•Œ, ํ’€(Pull) ๋‹จ์–ด์˜ ์˜๋ฏธ์™€ ๋™์ผํ•˜๊ฒŒ ๋ฐ์ดํ„ฐ๋ฅผ ๋‹น๊ฒจ์˜ค๋Š” ๋ชจ์Šต์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.
์„œ๋ฒ„์— ์žˆ๋Š” ํŠน์ • ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›๊ธฐ ์œ„ํ•ด ๋จผ์ € ์š”์ฒญํ•˜๊ณ , ๊ทธ ๊ฒฐ๊ณผ๋ฅผ ๋Œ๋ ค๋ฐ›๋Š” ํ˜•ํƒœ๋ฅผ ์˜๋ฏธํ•œ๋‹ค.

ํ‘ธ์‹œ(Push)๋Š” ํ’€๊ณผ ๋™์ž‘ํ•˜๋Š” ๋ชจ์Šต์ด ์กฐ๊ธˆ ๋‹ค๋ฅด๋‹ค.
์„œ๋ฒ„์—์„œ ํด๋ผ์ด์–ธํŠธ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ€์–ด ๋„ฃ๋Š”(Push) ๋ชจ์Šต์„ ๋ณผ ์ˆ˜ ์žˆ์œผ๋ฉฐ, ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋จผ์ € ์š”์ฒญ์„ ๋ณด๋‚ด์ง€ ์•Š๋”๋ผ๋„ ์„œ๋ฒ„๊ฐ€ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ€์–ด ๋„ฃ์–ด์ฃผ๋Š” ํ˜•ํƒœ์ด๋‹ค.

๐Ÿ‘จ‍๐Ÿ‘ฉ‍๐Ÿ‘ง‍๐Ÿ‘ฆ ์›น ํ‘ธ์‹œ์˜ ๊ตฌ์„ฑ ์š”์†Œ

์›น ํ‘ธ์‹œ๊ฐ€ ๋™์ž‘ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ํ•„์š”ํ•œ ๊ตฌ์„ฑ ์š”์†Œ๊ฐ€ ์žˆ๋‹ค.

์›น ํ‘ธ์‹œ์˜ ๊ธฐ๋ณธ ๊ตฌ์„ฑ์š”์†Œ

  • ๋ธŒ๋ผ์šฐ์ € (์‚ฌ์šฉ์ž)
  • ํ‘ธ์‹œ ์•Œ๋ฆผ์„ ๋ฐœ์†กํ•  ์„œ๋ฒ„
  • ํ‘ธ์‹œ ์•Œ๋ฆผ์„ ์‚ฌ์šฉ์ž์—๊ฒŒ ์ „๋‹ฌํ•  ํ‘ธ์‹œ ์„œ๋น„์Šค

ํฌ๊ฒŒ ๋ณด๋ฉด ์ด 3๊ฐ€์ง€๋กœ ์ด๋ฃจ์–ด์ ธ ์žˆ๋‹ค.

์„œ๋ฒ„์—์„œ ์–ด๋–ค ์‚ฌ์šฉ์ž์—๊ฒŒ, ์–ด๋–ค ๋ฉ”์‹œ์ง€๋ฅผ ๋ณด๋‚ผ์ง€์— ๋Œ€ํ•œ ๋‚ด์šฉ์ด ๋‹ด๊ธด ๋ฉ”์‹œ์ง€ ๋ฐ์ดํ„ฐ๋ฅผ ํ‘ธ์‹œ ์„œ๋น„์Šค๋กœ ์ „๋‹ฌํ•˜๋ฉด, ํ‘ธ์‹œ ์„œ๋น„์Šค์—์„œ ์‚ฌ์šฉ์ž ์ •๋ณด๋ฅผ ์‹๋ณ„ํ•œ ํ›„ ๋ชฉ์ ์ง€๋กœ ์ „๋‹ฌํ•œ๋‹ค.
์›น ํ‘ธ์‹œ์ด๊ธฐ ๋•Œ๋ฌธ์— ์—ฌ๊ธฐ์„œ ์ด์•ผ๊ธฐํ•˜๋Š” ๋ชฉ์ ์ง€๋Š” ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ๋œ๋‹ค.

์–ด๋–ค ์š”์†Œ๋กœ ์ด๋ฃจ์–ด์ ธ ์žˆ๊ณ , ๋Œ€๋žต ์–ด๋–ค ํ๋ฆ„์ธ์ง€ ์•Œ ๊ฒƒ๋งŒ ๊ฐ™์€๋ฐ ๋ฐ‘์ค„๋กœ ๊ฐ•์กฐํ•œ ๋ถ€๋ถ„์— ๋Œ€ํ•ด์„  ์˜๋ฌธ์ ์ด ์ƒ๊ฒผ์„ ๊ฒƒ์ด๋‹ค.

์ด ๋ถ€๋ถ„์„ ์•Œ๊ธฐ ์œ„ํ•ด์„œ๋Š” ์›น ํ‘ธ์‹œ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•˜๊ธฐ ์œ„ํ•ด ์ •ํ•ด์ง„ ๊ทœ์•ฝ. ์ฆ‰, ์›น ํ‘ธ์‹œ ํ”„๋กœํ† ์ฝœ(Web Push Protocol)์— ๋Œ€ํ•ด ์•Œ์•„์•ผ ํ•œ๋‹ค.

๐Ÿค™ ์›น ํ‘ธ์‹œ ํ”„๋กœํ† ์ฝœ

์›น ํ‘ธ์‹œ ํ”„๋กœํ† ์ฝœ(Web Push Protocol)์€ ํ‘ธ์‹œ ์•Œ๋ฆผ์„ ์ˆ˜์‹ ํ•˜๋Š” ๋ธŒ๋ผ์šฐ์ €์™€ ๋ฐœ์†กํ•˜๋Š” ์„œ๋ฒ„๊ฐ€ ํ‘ธ์‹œ ์„œ๋น„์Šค์™€ ์ƒํ˜ธ์ž‘์šฉํ•˜๊ธฐ ์œ„ํ•ด ์ •ํ•ด๋†“์€ ๊ทœ์•ฝ์ด๋‹ค.

ํด๋ผ์ด์–ธํŠธ(๋ธŒ๋ผ์šฐ์ €) ์ •๋ณด๋ฅผ ๋“ฑ๋กํ•˜๊ณ , ์„œ๋ฒ„์—์„œ ๋ฉ”์‹œ์ง€๋ฅผ ๋ฐœ์†กํ•˜๊ณ , ์ตœ์ข…์ ์œผ๋กœ ์‚ฌ์šฉ์ž์—๊ฒŒ ๋„๋‹ฌํ•˜๊ธฐ๊นŒ์ง€ ์—ฌ๋Ÿฌ ์ ˆ์ฐจ๋ฅผ ๊ฑฐ์น˜๊ฒŒ ๋œ๋‹ค.
์ ˆ์ฐจ์— ๋Œ€ํ•œ ๋ถ€๋ถ„์€ ์•„๋ž˜ ๊ทธ๋ฆผ์„ ํ†ตํ•ด ๊ฐ„๋žตํžˆ ์‚ดํŽด๋ณผ ์ˆ˜ ์žˆ๋‹ค.

์›น ํ‘ธ์‹œ ์•„ํ‚คํ…์ณ


๋จผ์ € ํ‘ธ์‹œ๋ฅผ ์ˆ˜์‹ ํ•˜๊ฒŒ ๋  ํด๋ผ์ด์–ธํŠธ(๋ธŒ๋ผ์šฐ์ €)์—์„œ๋Š” ํ‘ธ์‹œ ์„œ๋น„์Šค๋กœ ๋‚ด๊ฐ€ ๋ˆ„๊ตฐ์ง€ ์•Œ๋ฆฐ๋‹ค.
์ด ๊ณผ์ •์„ ๊ตฌ๋…(Subscription)์ด๋ผ๊ณ  ํ•˜๋ฉฐ ์กฐ๊ธˆ ๋” ์ž์„ธํ•œ ์ ˆ์ฐจ๋Š” ์•„๋ž˜ ๊ทธ๋ฆผ๊ณผ ๊ฐ™๋‹ค.

ํ‘ธ์‹œ ์„œ๋น„์Šค ๊ตฌ๋…

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

๊ตฌ๋… ์ •๋ณด๋Š” ์„œ๋ฒ„์— ์ €์žฅํ•ด๋‘์—ˆ๋‹ค๊ฐ€, ํ‘ธ์‹œ ์•Œ๋ฆผ ๋ฐœ์†ก์ด ํ•„์š”ํ•  ๋•Œ ๊บผ๋‚ด์„œ ์‚ฌ์šฉํ•˜๋Š” ํ˜•ํƒœ๊ฐ€ ๋œ๋‹ค.

์—ฌ๊ธฐ๊นŒ์ง€์˜ ๊ณผ์ •์ด ๋งˆ๋ฌด๋ฆฌ๋˜์—ˆ๋‹ค๋ฉด, ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ํ‘ธ์‹œ ์•Œ๋ฆผ์„ ์ˆ˜์‹ ํ•˜๊ธฐ ์œ„ํ•œ ๊ณผ์ •์€ ๋ชจ๋‘ ๋๋‚ฌ๋‹ค.
์ด์ œ ์„œ๋ฒ„์—์„œ ํ‘ธ์‹œ ์„œ๋น„์Šค๋กœ ๊ตฌ๋… ์ •๋ณด์™€ ๋ฉ”์‹œ์ง€๋ฅผ ์ „๋‹ฌํ•˜๋ฉด ํ•ด๋‹นํ•˜๋Š” ๋ธŒ๋ผ์šฐ์ €๋กœ ํ‘ธ์‹œ ์•Œ๋ฆผ์ด ์ „๋‹ฌ๋  ๊ฒƒ์ด๋‹ค.

๐Ÿ” ์•ˆ์ „ํ•œ ๋ฉ”์‹œ์ง€๋ฅผ ์œ„ํ•œ VAPID

์šฐ๋ฆฌ๊ฐ€ ๋†“์น˜์ง€ ๋ง์•„์•ผ ํ•  ๋ถ€๋ถ„์€ ์„œ๋ฒ„์—์„œ ํ‘ธ์‹œ ๋ฉ”์‹œ์ง€๋ฅผ ์ „๋‹ฌํ•  ๋•Œ ๊ทธ๋ƒฅ ์ „๋‹ฌํ•˜์ง€ ์•Š๋Š”๋‹ค๋Š” ์ ์ด๋‹ค. ํ‘ธ์‹œ ๋ฉ”์‹œ์ง€๋Š” ๋ฏผ๊ฐํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์•ˆ์ „ํ•˜๊ฒŒ ์•”ํ˜ธํ™”๋˜์–ด์•ผ ํ•˜๊ณ , ๋ฉ”์‹œ์ง€๊ฐ€ ์–ด๋–ค ์„œ๋ฒ„์—์„œ ๋ฐœ์†ก๋˜์—ˆ๋Š”์ง€ ์•Œ ์ˆ˜ ์žˆ์–ด์•ผ ํ•œ๋‹ค.

์›น ํ‘ธ์‹œ์—์„œ๋Š” ์–ด๋–ค ์„œ๋ฒ„์—์„œ ๋ฉ”์‹œ์ง€๋ฅผ ๋ฐœ์†กํ–ˆ๋Š”์ง€ ์‹๋ณ„ํ•˜๊ธฐ ์œ„ํ•ด VAPID(Voluntray Application Server Identification) ์ธ์ฆ ๋ฐฉ์‹์„ ์‚ฌ์šฉํ•œ๋‹ค.

VAPID๋Š” ์ž๋ฐœ์ ์œผ๋กœ ์„œ๋ฒ„(ํ‘ธ์‹œ ๋ฉ”์‹œ์ง€๋ฅผ ๋ฐœ์†กํ•˜๋Š”)๋ฅผ ์‹๋ณ„ํ•˜๋Š” ์ธ์ฆ ๋ฐฉ์‹์ด๋‹ค.

 

VAPID๋Š” ๊ฐ„๋‹จํ•˜๊ฒŒ ๋ณด๋ฉด ๊ณต๊ฐœํ‚ค ์•”ํ˜ธํ™” ๋ฐฉ์‹์˜ ํ‚ค ์Œ์œผ๋กœ ๊ฒ€์ฆ ์ ˆ์ฐจ๋ฅผ ๊ฑฐ์น˜๋Š”๋ฐ, ๋จผ์ € ๊ณต๊ฐœํ‚ค ์•”ํ˜ธํ™” ๋ฐฉ์‹์— ๋Œ€ํ•ด ๊ฐ„๋žตํžˆ ์•Œ์•„๋ณด์ž.

๊ณต๊ฐœํ‚ค ์•”ํ˜ธํ™” ์˜ˆ์‹œ

๊ณต๊ฐœํ‚ค ์•”ํ˜ธํ™”๋Š” ๋น„๊ณต๊ฐœ ํ‚ค(Private Key)์™€ ๊ณต๊ฐœ ํ‚ค(Public Key) ์Œ์„ ๊ฐ–๋Š”๋‹ค.
๊ณต๊ฐœํ‚ค ์•”ํ˜ธํ™”์˜ ๊ฒฝ์šฐ ๋น„๊ณต๊ฐœ ํ‚ค์™€ ๊ณต๊ฐœ ํ‚ค์˜ ๊ฐ’์ด ์ผ์น˜ํ•˜์ง€ ์•Š๋Š” ๋น„๋Œ€์นญ ์•”ํ˜ธํ™” ๋ฐฉ์‹์ด๋‹ค.

์•”ํ˜ธํ™” ๊ณผ์ •์ด ์žˆ๋‹ค๋ฉด ๋ณตํ˜ธํ™”๋„ ํ•„์š”ํ•œ ๋ฒ•์ธ๋ฐ, ๊ณต๊ฐœ ํ‚ค๋กœ ์•”ํ˜ธํ™”ํ–ˆ๋‹ค๋ฉด ๋น„๊ณต๊ฐœ ํ‚ค๋กœ ๋ณตํ˜ธํ™”ํ•ด์•ผ ํ•˜๊ณ , ๋น„๊ณต๊ฐœ ํ‚ค๋กœ ์•”ํ˜ธํ™”ํ–ˆ๋‹ค๋ฉด ๊ณต๊ฐœ ํ‚ค๋กœ ๋ณตํ˜ธํ™”ํ•ด์•ผ ํ•œ๋‹ค.
์ด๋Ÿฌํ•œ ํŠน์„ฑ์œผ๋กœ ์ธํ•ด ์ „์ž ์„œ๋ช…์ด๋‚˜ ์ธ์ฆ์ด ํ•„์š”ํ•œ ๋ถ€๋ถ„์—์„œ ๋„๋ฆฌ ์‚ฌ์šฉ๋˜๊ณ  ์žˆ๋Š” ์•”ํ˜ธํ™” ๊ธฐ๋ฒ•์ด๋‹ค.


๋‹ค์‹œ ๋ณธ ๋‚ด์šฉ์œผ๋กœ ๋Œ์•„์™€์„œ, VAPID๋„ ๊ณต๊ฐœํ‚ค ์•”ํ˜ธํ™” ๋ฐฉ์‹์˜ ํ‚ค ์Œ์œผ๋กœ ์ด๋ฃจ์–ด์ ธ ์žˆ๋‹ค.

์„œ๋ฒ„์—์„œ ํ‘ธ์‹œ ์„œ๋น„์Šค๋กœ ๋ฉ”์‹œ์ง€๋ฅผ ์ „๋‹ฌํ•  ๋•Œ VAPID ๋ช…์„ธ์— ๋”ฐ๋ฅธ ์ •๋ณด๊ฐ€ ๋‹ด๊ธด JWT(JSON Web Token)์„ ํ•จ๊ป˜ ์ „๋‹ฌํ•˜๊ฒŒ ๋˜๋Š”๋ฐ, ์ด๋•Œ ์ด ํ† ํฐ์„ VAPID์˜ ๋น„๊ณต๊ฐœ ํ‚ค๋กœ ์„œ๋ช…(์•”ํ˜ธํ™”)ํ•œ๋‹ค.

์„œ๋ช…๋œ ํ† ํฐ์€ ๋ฐ˜๋Œ€๋กœ ํ‘ธ์‹œ ์„œ๋น„์Šค์—์„œ ๊ณต๊ฐœ ํ‚ค๋กœ ๋ณตํ˜ธํ™”ํ•˜์—ฌ ์œ ํšจ์„ฑ์„ ๊ฒ€์ฆํ•˜๊ฒŒ ๋œ๋‹ค.

์ด๋Ÿฌํ•œ ์ ˆ์ฐจ๋ฅผ ํ†ตํ•ด ํ‘ธ์‹œ ์„œ๋น„์Šค์—์„œ ์–ด๋–ค ์„œ๋ฒ„๋กœ๋ถ€ํ„ฐ ์ˆ˜์‹ ํ•œ ๋ฉ”์‹œ์ง€์ธ์ง€, ์œ ํšจํ•œ ๋ฉ”์‹œ์ง€์ธ์ง€ ๊ฒ€์ฆํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋œ๋‹ค.

์ง€๊ธˆ๊นŒ์ง€ ์‚ดํŽด๋ณธ ๋‚ด์šฉ์„ ๋ชจ์•„ ๋ณด๋ฉด ์•„๋ž˜์™€ ๊ฐ™์€ ํ๋ฆ„์œผ๋กœ ๋‚˜ํƒ€๋‚ผ ์ˆ˜ ์žˆ๋‹ค.

VAPID ์ธ์ฆ๊ณผ ํ‘ธ์‹œ ์•Œ๋ฆผ

  • (1) ๋ธŒ๋ผ์šฐ์ €์—์„œ ํ‘ธ์‹œ ์„œ๋น„์Šค ๊ตฌ๋… + VAPID ๊ณต๊ฐœ ํ‚ค ์ „๋‹ฌ
  • (2) ๊ตฌ๋… ์ •๋ณด ์ˆ˜์‹ 
  • (3) ๊ตฌ๋… ์ •๋ณด ์„œ๋ฒ„๋กœ ์ „๋‹ฌ
  • (4) ๊ตฌ๋… ์ •๋ณด + ๋ฉ”์‹œ์ง€ + VAPID ๋น„๊ณต๊ฐœ ํ‚ค๋กœ ์•”ํ˜ธํ™”๋œ JWT
  • (5) VAPID ๊ณต๊ฐœ ํ‚ค๋กœ ์œ ํšจ์„ฑ ๊ฒ€์ฆ & ๊ฒ€์ฆ๋œ ๊ฒฝ์šฐ ๊ตฌ๋… ์ •๋ณด์— ํ•ด๋‹นํ•˜๋Š” ๋ธŒ๋ผ์šฐ์ €๋กœ ํ‘ธ์‹œ ๋ฉ”์‹œ์ง€ ๋ฐœ์†ก

4, 5๋ฒˆ ๊ณผ์ •์—์„œ ๋ฐ์ดํ„ฐ๊ฐ€ ์œ„์กฐ๋˜๊ฑฐ๋‚˜, ํ‚ค๊ฐ€ ์ผ์น˜ํ•˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ ํ‘ธ์‹œ ๋ฉ”์‹œ์ง€๋Š” ์œ ํšจํ•˜์ง€ ์•Š์€ ์ƒํƒœ๊ฐ€ ๋˜์–ด ๋ธŒ๋ผ์šฐ์ €๊นŒ์ง€ ๋„๋‹ฌํ•˜์ง€ ๋ชปํ•˜๊ณ  ํ‘ธ์‹œ ์„œ๋น„์Šค์—์„œ ํ๊ธฐ๋œ๋‹ค.

๋”๋ณด๊ธฐ

VAPID ์ธ์ฆ ๊ณผ์ •์„ Node ํ™˜๊ฒฝ์—์„œ ๊ตฌํ˜„ํ•ด๋ณธ ์ฝ”๋“œ๊ฐ€ ์กด์žฌํ•˜๋Š”๋ฐ ๊ด€์‹ฌ์ด ์žˆ๋‹ค๋ฉด ํ•œ ๋ฒˆ ์‚ดํŽด๋ณด๋ฉด ์ข‹์„ ๊ฒƒ ๊ฐ™๋‹ค.


์›น ํ‘ธ์‹œ์˜ ์ „์ฒด์ ์ธ ํ๋ฆ„์€ ์ง€๊ธˆ๊นŒ์ง€ ์‚ดํŽด๋ณธ ๊ฒƒ๊ณผ ๊ฐ™๋‹ค.

๋ณต์žกํ•˜๊ฒŒ ๋А๊ปด์งˆ ์ˆ˜๋„ ์žˆ์ง€๋งŒ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๋‹ค๋ณด๋ฉด ํ›จ์”ฌ ์‰ฝ๊ฒŒ ์™€๋‹ฟ์„ ๊ฒƒ์ด๋‹ค.

๐Ÿ”ฅ ์›น ํ‘ธ์‹œ ๊ตฌํ˜„ํ•˜๊ธฐ

์›ํ™œํ•œ ์ง„ํ–‰์„ ์œ„ํ•ด ์›น ํ‘ธ์‹œ ๋ฐ๋ชจ ์ฝ”๋“œ๋ฅผ ์ค€๋น„ํ•˜์˜€๋‹ค.

์•„๋ž˜ ๊นƒํ—ˆ๋ธŒ ์ฃผ์†Œ์—์„œ ์ฝ”๋“œ๋ฅผ ๋‹ค์šด๋กœ๋“œ ๋ฐ›๊ณ , ์ฝ”๋“œ์™€ ๋™์ž‘์„ ํ™•์ธํ•ด๋ณด์ž.

https://github.com/leegeunhyeok/web-push

 

GitHub - leegeunhyeok/web-push: ๐Ÿ”” Web Push | Getting Started

๐Ÿ”” Web Push | Getting Started. Contribute to leegeunhyeok/web-push development by creating an account on GitHub.

github.com


README ํŒŒ์ผ์— ์ •๋ฆฌ๋˜์–ด์žˆ๋Š” ๋‚ด์šฉ๋Œ€๋กœ ํ™˜๊ฒฝ์„ ์„ธํŒ…ํ•˜๋„๋ก ํ•˜์ž.

์ค€๋น„๊ฐ€ ๋˜์—ˆ๋‹ค๋ฉด ๋ฐ๋ชจ ์„œ๋ฒ„๋ฅผ ์‹คํ–‰์‹œํ‚จ ํ›„ ํŽ˜์ด์ง€์— ์ ‘์†ํ•˜์—ฌ ๋‹ค์Œ ๋‚ด์šฉ๋“ค์„ ํ•˜๋‚˜์”ฉ ์‚ดํŽด๋ณด์ž.


์›น ํ‘ธ์‹œ ๊ธฐ๋Šฅ์€ ์›น ์›Œ์ปค ์ค‘ ํ•œ ์ข…๋ฅ˜์ธ ์„œ๋น„์Šค ์›Œ์ปค(Servier Worker)๋ฅผ ํ†ตํ•ด ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ๋ธŒ๋ผ์šฐ์ €์˜ ๋ฐฑ๊ทธ๋ผ์šด๋“œ ํ™˜๊ฒฝ์—์„œ ์ฒ˜๋ฆฌ๋œ๋‹ค.
(์„œ๋น„์Šค ์›Œ์ปค์— ๋Œ€ํ•œ ์ž์„ธํ•œ ๋‚ด์šฉ์€ ์ถ”ํ›„ ์ž‘์„ฑํ•  ์˜ˆ์ •์ด๋‹ค)

๋ชจ๋˜ ๋ธŒ๋ผ์šฐ์ €(์ด์   Safari ํฌํ•จ)์—๋Š” ์›น ํ‘ธ์‹œ ์•Œ๋ฆผ์„ ์ œ๊ณตํ•˜๊ธฐ ์œ„ํ•œ API๋“ค์ด ๊ตฌํ˜„๋˜์–ด์žˆ๋‹ค.
ํ‘ธ์‹œ ์„œ๋น„์Šค๋ฅผ ๊ตฌ๋…ํ•˜๊ณ , ๋ฉ”์‹œ์ง€๋ฅผ ์ˆ˜์‹ ํ•˜๊ธฐ ์œ„ํ•œ Push API, ๊ทธ๋ฆฌ๊ณ  ์•Œ๋ฆผ์„ ์‚ฌ์šฉ์ž์—๊ฒŒ ๋…ธ์ถœ์‹œํ‚ค๊ธฐ ์œ„ํ•œ Notification API๊ฐ€ ์žˆ๋‹ค.

์ด์— ๋Œ€ํ•œ ๋ถ€๋ถ„์„ ๊ฐ„๋žตํžˆ ์‚ดํŽด๋ณด๊ณ  ์ง€๋‚˜๊ฐ€๋„๋ก ํ•˜์ž.

๐Ÿ™‹ Notification API

๋ธŒ๋ผ์šฐ์ €์—์„œ ์‹œ์Šคํ…œ ์•Œ๋ฆผ์„ ๋„์šฐ๊ธฐ ์œ„ํ•œ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•œ๋‹ค. ์šฐ๋ฆฌ๋Š” ์ด๋ฅผ ํ†ตํ•ด ์—ฌ๋Ÿฌ ํ”Œ๋žซํผ(์œˆ๋„์šฐ, ๋งฅ, ๋ฆฌ๋ˆ…์Šค, ์•ˆ๋“œ๋กœ์ด๋“œ, iOS)์— ๋งž๋Š” ์‹œ์Šคํ…œ ์•Œ๋ฆผ์„ ์‰ฝ๊ฒŒ ๋„์šธ ์ˆ˜ ์žˆ๋‹ค.

Notification API๋ฅผ ํ†ตํ•ด ์ˆ˜ํ–‰ ๊ฐ€๋Šฅํ•œ ๋Œ€ํ‘œ์ ์ธ ๊ธฐ๋Šฅ์€ ์•„๋ž˜์™€ ๊ฐ™๋‹ค.

  • ์•Œ๋ฆผ ๊ถŒํ•œ ์š”์ฒญํ•˜๊ธฐ
  • ์•Œ๋ฆผ ๊ถŒํ•œ ์ƒํƒœ
  • ์•Œ๋ฆผ ๋„์šฐ๊ธฐ

(์ƒ‰์ƒ์œผ๋กœ ๊ฐ•์กฐํ•œ ๋ถ€๋ถ„์— ๋Œ€ํ•ด์„œ๋งŒ ๊ฐ„๋‹จํžˆ ์‚ดํŽด๋ณธ๋‹ค)

์•Œ๋ฆผ ๊ถŒํ•œ์€ ์•„๋ž˜์™€ ๊ฐ™์ด ์‰ฝ๊ฒŒ ํŒŒ์•…ํ•  ์ˆ˜ ์žˆ๋‹ค.

Notification.permission; // 'default', 'denied', 'granted'


๊ธฐ๋ณธ ์ƒํƒœ๋Š” default์ด๋ฉฐ, ์•„์ง ๋ธŒ๋ผ์šฐ์ €์—์„œ ์‚ฌ์šฉ์ž์—๊ฒŒ ๊ถŒํ•œ์„ ๋ฌผ์–ด๋ณด์ง€ ์•Š์€ ์ƒํƒœ๋ฅผ ์˜๋ฏธํ•œ๋‹ค.

๋ธŒ๋ผ์šฐ์ €์—์„œ ์‚ฌ์šฉ์ž์—๊ฒŒ ๊ถŒํ•œ์„ ๋ฌผ์–ด๋ณธ ํ›„ ์‚ฌ์šฉ์ž๊ฐ€ ์„ ํƒํ•œ ๋™์ž‘์— ๋”ฐ๋ผ ๋‘ ๊ฐ€์ง€ ์ƒํƒœ๋กœ ๋‚˜๋ˆ ์ง„๋‹ค.

์•Œ๋ฆผ ๊ถŒํ•œ ํ™•์ธ ๋ชจ์Šต

์‚ฌ์šฉ์ž๊ฐ€ ๊ฑฐ๋ถ€ํ•œ ๊ฒฝ์šฐ denied, ํ—ˆ๊ฐ€ํ•œ ๊ฒฝ์šฐ granted๊ฐ€ ๋˜๋ฉฐ, ์ด ์ƒํƒœ์—์„œ๋Š” ๋” ์ด์ƒ ๊ถŒํ•œ ๋ณ€๊ฒฝ์ด ๋ถˆ๊ฐ€ํ•˜๋‹ค. (์‚ฌ์šฉ์ž๊ฐ€ ์ง์ ‘ ๋ธŒ๋ผ์šฐ์ € ์„ค์ •์„ ํ†ตํ•ด ๋ณ€๊ฒฝํ•ด์•ผ ํ•œ๋‹ค.)

๊ถŒํ•œ์ด ํ—ˆ๊ฐ€ ์ƒํƒœ์ธ ๊ฒฝ์šฐ ์•Œ๋ฆผ์„ ๋„์šธ ์ˆ˜ ์žˆ๊ฒŒ ๋œ๋‹ค. ์•Œ๋ฆผ์„ ๋„์šฐ๋Š” ๋ฐฉ๋ฒ•์€ ํฌ๊ฒŒ ๋‘ ๊ฐ€์ง€๊ฐ€ ์žˆ๋Š”๋ฐ ์•Œ๋ฆผ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๊ฒƒ๊ณผ ์„œ๋น„์Šค ์›Œ์ปค์˜ showNotification ๋ฉ”์†Œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๊ฒƒ์ด๋‹ค. ์—ฌ๊ธฐ์„œ๋Š” ํ›„์ž ๋ฐฉ์‹์— ๋Œ€ํ•ด ์•Œ์•„๋ณธ๋‹ค.

๋จผ์ € ์•Œ๋ฆผ์„ ๋„์šฐ๋Š” ์ฝ”๋“œ๋ฅผ ์‚ดํŽด๋ณด์ž.

registration.showNotification(title, {
  body: 'Some message',
});

์„œ๋น„์Šค ์›Œ์ปค ๋“ฑ๋ก ๊ฐ์ฒด์—๋Š” ์•Œ๋ฆผ์„ ๋„์šธ ์ˆ˜ ์žˆ๋Š” showNotification ๋ฉ”์†Œ๋“œ๊ฐ€ ๊ตฌํ˜„๋˜์–ด์žˆ๋‹ค.

์ฒซ ๋ฒˆ์งธ ์ธ์ž๋กœ๋Š” ์•Œ๋ฆผ์˜ ์ œ๋ชฉ, ๋‘ ๋ฒˆ์งธ ์ธ์ž๋กœ๋Š” ์•Œ๋ฆผ์˜ ๋ณธ๋ฌธ ๊ทธ๋ฆฌ๊ณ  ๊ธฐํƒ€ ์˜ต์…˜๋“ค์ด ์ „๋‹ฌ๋œ๋‹ค.

์•Œ๋ฆผ ๊ถŒํ•œ์ด ๋ถ€์—ฌ(granted)๋˜์–ด์žˆ๋‹ค๋ฉด, ์ •์ƒ์ ์œผ๋กœ ์‹œ์Šคํ…œ ์•Œ๋ฆผ์ด ํ‘œ์‹œ๋  ๊ฒƒ์ด๋‹ค.

๐Ÿ”” Push API

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

์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ํ‘ธ์‹œ ๋ฉ”์‹œ์ง€๋ฅผ ์ˆ˜์‹ ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ํ™œ์„ฑํ™” ๋˜์–ด์žˆ๋Š” ์„œ๋น„์Šค ์›Œ์ปค๊ฐ€ ํ•„์š”ํ•˜๋‹ค.
์„œ๋น„์Šค ์›Œ์ปค๋Š” ๋ธŒ๋ผ์šฐ์ € ๋ฐฑ๊ทธ๋ผ์šด๋“œ ํ™˜๊ฒฝ์—์„œ ๋™์ž‘ํ•˜๊ณ , ํ‘ธ์‹œ ๋ฉ”์‹œ์ง€๋ฅผ ์ˆ˜์‹ ํ–ˆ์„ ๋•Œ ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ํ†ตํ•ด ์ˆ˜์‹ ํ•œ ๋ฉ”์‹œ์ง€๋ฅผ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค.

Push API์˜ ์ฃผ์š” ๊ธฐ๋Šฅ์„ ๋‚˜์—ดํ•ด๋ณด๋ฉด ์•„๋ž˜์™€ ๊ฐ™๋‹ค.

  • ํ‘ธ์‹œ ์„œ๋น„์Šค ๊ตฌ๋… ๋ฐ ํ•ด์ง€
  • ํ‘ธ์‹œ ๋ฉ”์‹œ์ง€ ์ˆ˜์‹ 

โš™๏ธ ์„œ๋น„์Šค ์›Œ์ปค ๋“ฑ๋กํ•˜๊ธฐ

ํ‘ธ์‹œ๋ฅผ ์ˆ˜์‹ ํ•˜๊ธฐ์— ์•ž์„œ ์„œ๋น„์Šค ์›Œ์ปค ๋“ฑ๋ก์ด ํ•„์š”ํ•˜๋‹ค. ์„œ๋น„์Šค ์›Œ์ปค๋Š” ๋‹ค๋ฅธ ์›น ์›Œ์ปค์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ์›Œ์ปค ์Šคํฌ๋ฆฝํŠธ๋ฅผ ๋กœ๋“œํ•˜์—ฌ ์„ค์น˜ & ํ™œ์„ฑํ™”์‹œํ‚ฌ ์ˆ˜ ์žˆ๋‹ค.

async function registerServiceWorker () {
  if (!('serviceWorker' in navigator)) return;

  // ์ด๋ฏธ ๋“ฑ๋ก๋˜์–ด์žˆ๋Š” ์ •๋ณด ๊ฐ€์ ธ์˜ค๊ธฐ
  let registration = await navigator.serviceWorker.getRegistration();
  if (!registration) {
    // ์—†์œผ๋ฉด ์„œ๋น„์Šค ์›Œ์ปค ๋“ฑ๋ก
    registration = await navigator.serviceWorker.register('/service-worker.js');
  }
}

navigator ๊ฐ์ฒด์— serviceWorker๊ฐ€ ์กด์žฌํ•˜๋Š”์ง€ ํ™•์ธํ•˜์—ฌ ํ˜„์žฌ ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ์„œ๋น„์Šค ์›Œ์ปค๋ฅผ ์ง€์›ํ•˜๋Š”์ง€ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

์กด์žฌํ•˜์ง€ ์•Š์„ ๊ฒฝ์šฐ ๊ธฐ๋Šฅ ์‚ฌ์šฉ์ด ๋ถˆ๊ฐ€ํ•˜๋‹ˆ ๋ถ„๊ธฐ ์ฒ˜๋ฆฌ๊ฐ€ ๋ฐ˜๋“œ์‹œ ํ•„์š”ํ•˜๋‹ค.

navigator.serviceWorker.getRegistration์„ ํ†ตํ•ด ์„œ๋น„์Šค ์›Œ์ปค์˜ ๋“ฑ๋ก ๊ฐ์ฒด๋ฅผ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ๋‹ค.
์•„์ง ์„œ๋น„์Šค ์›Œ์ปค๊ฐ€ ๋“ฑ๋ก๋˜์–ด์žˆ์ง€ ์•Š๋‹ค๋ฉด null์„ ๋ฐ˜ํ™˜ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๊ฐ’์˜ ์œ ๋ฌด๋ฅผ ํ†ตํ•ด ๊ธฐ์กด ๋“ฑ๋ก ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ• ์ง€, ์ƒˆ๋กœ ์„œ๋น„์Šค ์›Œ์ปค๋ฅผ ๋“ฑ๋กํ• ์ง€ ๊ฒฐ์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.

์„œ๋น„์Šค ์›Œ์ปค ๋“ฑ๋ก์€ navigator.serviceWorker.register๋ฅผ ํ†ตํ•ด ์ง„ํ–‰ํ•  ์ˆ˜ ์žˆ๋‹ค. ์ฒซ ๋ฒˆ์งธ ์ธ์ž์—๋Š” ์„œ๋น„์Šค ์›Œ์ปค ์Šคํฌ๋ฆฝํŠธ๊ฐ€ ์œ„์น˜ํ•œ ๊ฒฝ๋กœ๋ฅผ ๋ฌธ์ž์—ด๋กœ ์ „๋‹ฌํ•˜๋ฉด ๋˜๊ณ , ๋‹ค์šด๋กœ๋“œ์™€ ์„ค์น˜ ๊ณผ์ •์€ ๋ธŒ๋ผ์šฐ์ €์—์„œ ์•Œ์•„์„œ ์ฒ˜๋ฆฌํ•œ๋‹ค.

๐ŸŒ ํ‘ธ์‹œ ์„œ๋น„์Šค ๊ตฌ๋…ํ•˜๊ธฐ

์„œ๋น„์Šค ์›Œ์ปค๊ฐ€ ๋“ฑ๋ก๋˜์—ˆ๋‹ค๋ฉด ๋“ฑ๋ก ๊ฐ์ฒด๋ฅผ ํ†ตํ•ด ํ‘ธ์‹œ ๋งค๋‹ˆ์ €(Push Manager)์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋‹ค.

registration.pushManager;

์„œ๋น„์Šค ์›Œ์ปค ๋“ฑ๋ก ๊ฐ์ฒด์— pushManager๊ฐ€ ์—†๋‹ค๋ฉด, ํ‘ธ์‹œ ์•Œ๋ฆผ์„ ์ง€์›ํ•˜์ง€ ์•Š๋Š” ๋ธŒ๋ผ์šฐ์ €์ด๋‹ˆ ์ด ๋˜ํ•œ ์กฐ๊ฑด์„ ํ†ตํ•ด ๋ถ„๊ธฐ ์ฒ˜๋ฆฌ๊ฐ€ ๊ฐ€๋Šฅํ•˜๋‹ค.

์•ž์„œ ์‚ดํŽด๋ณด์•˜๋˜ ๋‚ด์šฉ ์ค‘ ํ‘ธ์‹œ ์•Œ๋ฆผ์ด ๋™์ž‘ํ•˜๋Š” ํ๋ฆ„์„ ๋˜์งš์–ด๋ณด๋ฉด, ์ฒซ ๋ฒˆ์งธ๋กœ ํด๋ผ์ด์–ธํŠธ(๋ธŒ๋ผ์šฐ์ €)์—์„œ ํ‘ธ์‹œ ์„œ๋น„์Šค๋ฅผ ๊ตฌ๋…ํ–ˆ๋˜ ๊ฒƒ์„ ๊ธฐ์–ตํ•  ๊ฒƒ์ด๋‹ค.

ํ‘ธ์‹œ ์„œ๋น„์Šค ๊ตฌ๋…์€ ํ‘ธ์‹œ ๋งค๋‹ˆ์ €๋ฅผ ํ†ตํ•ด ์ฒ˜๋ฆฌ ๊ฐ€๋Šฅํ•˜๊ณ , ์ฝ”๋“œ๋กœ ๊ตฌํ˜„ํ•˜์ž๋ฉด ์•„๋ž˜์™€ ๊ฐ™๋‹ค.

const subscription = await registration.pushManager.subscribe({
  applicationServerKey: VAPID_PUBLIC_KEY,
  userVisibleOnly: true,
});

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

๊ตฌ๋… ์š”์ฒญ์„ ์œ„ํ•ด subscribe๋ฅผ ํ˜ธ์ถœํ•  ๊ฒฝ์šฐ ๋ฐ˜๋“œ์‹œ ์‚ฌ์šฉ์ž ์ œ์Šค์ฒ˜๊ฐ€ ํ•„์š”ํ•œ๋ฐ, ์ด๋Š” ๊ฐœ๋ฐœ์ž๊ฐ€ ์•…์˜์ ์œผ๋กœ ํ‘ธ์‹œ ์„œ๋น„์Šค์— ๊ตฌ๋…ํ•˜๋Š” ๊ฒƒ์„ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•จ์ด๋‹ค. ์ฆ‰, ๋ฐ˜๋“œ์‹œ ์‚ฌ์šฉ์ž๊ฐ€ ์–ด๋– ํ•œ ํ–‰์œ„๋ฅผ ํ•ด์•ผ ๊ตฌ๋… ์š”์ฒญ์ด ํ—ˆ์šฉ๋œ๋‹ค. (์˜ˆ: ๋ฒ„ํŠผ ํด๋ฆญ ๋“ฑ)

๊ตฌ๋… ์š”์ฒญ์„ ๋ณด๋‚ด๊ธฐ ์œ„ํ•ด์„œ๋Š” ์„œ๋ฒ„๋ฅผ ์‹๋ณ„ํ•˜๊ธฐ ์œ„ํ•œ VAPID ๊ณต๊ฐœํ‚ค(applicationServerKey)์™€, ํ‘ธ์‹œ ๋ฉ”์‹œ์ง€๊ฐ€ ์‚ฌ์šฉ์ž์—๊ฒŒ ๋ณด์ด๋Š” ์šฉ๋„๋กœ ์‚ฌ์šฉ๋œ๋‹ค๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•˜๋Š” ํ”Œ๋ž˜๊ทธ ๊ฐ’(userVisibleOnly)์ด ํ•„์š”ํ•˜๋‹ค.

๋ฐ๋ชจ ์ฝ”๋“œ ํ™˜๊ฒฝ์„ ์ค€๋น„ํ•˜๋ฉด์„œ VAPID ํ‚ค ์Œ์„ ์ƒ์„ฑํ–ˆ์„ํ…๋ฐ default.json์— ์ •์ƒ์ ์œผ๋กœ ๋„ฃ์–ด๋‘์—ˆ๋‹ค๋ฉด, API๋ฅผ ํ†ตํ•ด ๊ณต๊ฐœํ‚ค๋ฅผ ๋ฐ›์•„์˜จ ํ›„ applicationServerKey ํ”„๋กœํผํ‹ฐ ๊ฐ’์œผ๋กœ ์‚ฌ์šฉ๋  ๊ฒƒ์ด๋‹ค.

userVisibleOnly ๊ฐ’์€ ๋ฐ˜๋“œ์‹œ true ์ด์–ด์•ผ ํ•˜๊ณ , ์ˆ˜์‹ ํ•œ ํ‘ธ์‹œ ๋ฉ”์‹œ์ง€๋Š” ์•Œ๋ฆผ์„ ํ†ตํ•ด ๋ฐ˜๋“œ์‹œ ์‚ฌ์šฉ์ž์—๊ฒŒ ๋ณด์—ฌ์ฃผ์–ด์•ผ ํ•จ์„ ์˜๋ฏธํ•œ๋‹ค.

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

{
  "endpoint": "https://web.push.apple.com/QHnG_a...BVMI",
  "keys": {
    "p256dh": "BC56...kSB9-Vcq8",
    "auth": "fz8...sA"
  }
}


๋ฐ๋ชจ ์ฝ”๋“œ๋ฅผ ์‚ดํŽด๋ณด๋ฉด ์•„๋ž˜์™€ ๊ฐ™์ด ๊ตฌ๋… ์ •๋ณด๋ฅผ ์„œ๋ฒ„๋กœ ์ „๋‹ฌํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

async function postSubscription (subscription?: PushSubscription) {
  ...
  
  const response = await fetch('/subscription', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({ userId, subscription }),
  });
}

๋ฐ๋ชจ ์ฝ”๋“œ์—์„œ๋Š” ์ „๋‹ฌํ•œ ๊ตฌ๋… ์ •๋ณด๋ฅผ ์‚ฌ์šฉ์ž ID์™€ ๋งคํ•‘ํ•˜์—ฌ ์„œ๋ฒ„ ์ธก์— ์ €์žฅํ•ด๋‘๊ฒŒ ๋œ๋‹ค.

๐ŸŒš ํ‘ธ์‹œ ์„œ๋น„์Šค ๊ตฌ๋… ์ทจ์†Œํ•˜๊ธฐ

ํ‘ธ์‹œ ์„œ๋น„์Šค ๊ตฌ๋… ์ทจ์†Œ๋Š” ๋” ๊ฐ„๋‹จํ•˜๊ฒŒ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.

ํ‘ธ์‹œ ์„œ๋น„์Šค ๊ตฌ๋… ํ›„ ์ „๋‹ฌ๋ฐ›์€ ๊ตฌ๋… ์ •๋ณด์— ๊ตฌํ˜„๋˜์–ด์žˆ๋Š” unsubscribe ๋ฉ”์†Œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๊ธฐ๋งŒ ํ•˜๋ฉด ๋œ๋‹ค.

const unsubscribed = await subscription.unsubscribe();

Promise ๊ฒฐ๊ณผ ๊ฐ’์œผ๋กœ๋Š” ์ทจ์†Œ ์„ฑ๊ณต ์—ฌ๋ถ€๋ฅผ boolean ๊ฐ’์œผ๋กœ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

๋ฐ๋ชจ ์ฝ”๋“œ์—์„œ๋Š” ๊ตฌ๋…์„ ์ทจ์†Œํ•œ ๊ฒฝ์šฐ ์„œ๋ฒ„์—๋„ ์ด ์‚ฌ์‹ค์„ ์•Œ๋ ค ์ €์žฅํ•ด๋‘์—ˆ๋˜ ์‚ฌ์šฉ์ž์˜ ๊ตฌ๋… ์ •๋ณด๋ฅผ ํ•จ๊ป˜ ์ œ๊ฑฐํ•˜๋„๋ก ๊ตฌํ˜„๋˜์–ด์žˆ๋‹ค.

โœ‰๏ธ ํ‘ธ์‹œ ๋ฉ”์‹œ์ง€ ๋ณด๋‚ด๊ณ  & ๋ฐ›๊ธฐ

ํ‘ธ์‹œ ๋ฉ”์‹œ์ง€๋ฅผ ๋ณด๋‚ด๊ธฐ ์œ„ํ•ด์„œ๋Š”, ์„œ๋ฒ„์—์„œ ์›น ํ‘ธ์‹œ ํ”„๋กœํ† ์ฝœ์— ๋”ฐ๋ผ ํ‘ธ์‹œ ์„œ๋น„์Šค๋กœ ๋ฉ”์‹œ์ง€๋ฅผ ์ „๋‹ฌํ•ด์•ผ ํ•œ๋‹ค.
์ง์ ‘ ๊ตฌํ˜„ํ•œ๋‹ค๋ฉด ์ƒ๋‹นํžˆ ๋ณต์žกํ•  ํ…๋ฐ, ๋‹คํ–‰ํžˆ ์›น ํ‘ธ์‹œ ํ”„๋กœํ† ์ฝœ ํ‘œ์ค€์— ๋งž๊ฒŒ ๊ตฌํ˜„๋˜์–ด์žˆ๋Š” ์—ฌ๋Ÿฌ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋“ค์ด ์กด์žฌํ•œ๋‹ค.

๋ฐ๋ชจ ์ฝ”๋“œ์—์„œ๋Š” web-push ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ตฌํ˜„ํ–ˆ์œผ๋‹ˆ ์ฐธ๊ณ  ๋ฐ”๋ž€๋‹ค.

์„œ๋ฒ„ ์ชฝ์—์„œ ํ‘ธ์‹œ ๋ฉ”์‹œ์ง€๋ฅผ ์–ด๋–ป๊ฒŒ ๋ณด๋‚ด๊ณ  ์žˆ๋Š”์ง€ ์ฝ”๋“œ๋ฅผ ํ™•์ธํ•ด๋ณด์ž.

import webpush from 'web-push';

webpush.setGCMAPIKey(GCM_KEY);
webpush.setVapidDetails(
  SUBJECT,
  VAPID_PUBLIC,
  VAPID_PRIVATE
);

webpush.sendNotification(subscription, JSON.stringify({
  title: 'Web Push | Getting Started',
  body: message || '(Empty message)',
}));

์„œ๋ฒ„ ์ฝ”๋“œ๋ฅผ ์‚ดํŽด๋ณด๋ฉด ์œ„์™€ ๊ฐ™์€ ์ฝ”๋“œ๊ฐ€ ์กด์žฌํ•˜๋Š”๋ฐ, web-push ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ํ†ตํ•ด ์•„์ฃผ ๊ฐ„๋‹จํžˆ ๋ฐœ์†ก ์ฝ”๋“œ๋ฅผ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.

ํ‘ธ์‹œ ์•Œ๋ฆผ์„ ๋ฐœ์†กํ•˜๊ธฐ ์ „์— ๊ธฐ๋ณธ์ ์ธ ๊ตฌ์„ฑ(GCM ํ‚ค ๋ฐ VAPID ํ‚ค ๋“ฑ๋ก)์„ ์ง„ํ–‰ํ•˜๊ณ , ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ˆ˜์ค€์— ๊ตฌํ˜„๋˜์–ด์žˆ๋Š” sendNotification ๋ฉ”์†Œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ํ‘ธ์‹œ ๋ฉ”์‹œ์ง€๋ฅผ ๋ฐœ์†กํ•œ๋‹ค.

๋ฐœ์†กํ•  ๋•Œ, ๊ตฌ๋… ์ •๋ณด์™€ ๋ฉ”์‹œ์ง€ ๋ฐ์ดํ„ฐ๋ฅผ ํ•จ๊ป˜ ์ „๋‹ฌํ•˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.


๋ฐœ์†กํ•œ ํ‘ธ์‹œ ๋ฉ”์‹œ์ง€๋Š” ํ‘ธ์‹œ ์„œ๋น„์Šค๋ฅผ ๊ฑฐ์ณ ๋ชฉ์ ์ง€์ธ ๋ธŒ๋ผ์šฐ์ €์— ๋„๋‹ฌํ•˜๊ฒŒ ๋œ๋‹ค.

๋ธŒ๋ผ์šฐ์ €์— ํ‘ธ์‹œ ๋ฉ”์‹œ์ง€๊ฐ€ ๋„๋‹ฌํ•œ ๊ฒฝ์šฐ ์„œ๋น„์Šค ์›Œ์ปค์˜ push ์ด๋ฒคํŠธ๋ฅผ ํ†ตํ•ด ์ด๋ฅผ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋Š”๋ฐ, ์„œ๋น„์Šค ์›Œ์ปค ์ฝ”๋“œ๋ฅผ ์ž ์‹œ ์‚ดํŽด๋ณด๋„๋ก ํ•˜์ž.

self.addEventListener('push', (event: PushEvent) => {
  const message = event.data?.json() as PushMessage;
  event.waitUntil(
    self.registration.showNotification(message.title, {
      body: message.body,
    })
  );
});

self.addEventListener('notificationclick', (event: NotificationEvent) => {
  self.clients.openWindow('https://github.com/leegeunhyeok/web-push');
});

์„œ๋น„์Šค ์›Œ์ปค ์ฝ”๋“œ์˜ ์ผ๋ถ€๋ถ„์„ ๊ฐ€์ ธ์™”๋‹ค.

์—ฌ๊ธฐ์„œ ํ™•์ธํ•  ๋ถ€๋ถ„์€ push ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ ๋ถ€๋ถ„์ด๋‹ค. push ์ด๋ฒคํŠธ๋Š” ํ‘ธ์‹œ ์„œ๋น„์Šค๋กœ๋ถ€ํ„ฐ ๋ฉ”์‹œ์ง€๋ฅผ ์ˆ˜์‹ ํ–ˆ์„ ๋•Œ ํŠธ๋ฆฌ๊ฑฐ ๋˜๋ฉฐ, ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ๋‹ซํ˜€์žˆ๋”๋ผ๋„ ์„œ๋น„์Šค ์›Œ์ปค์—์„œ ์ด๋ฅผ ์ˆ˜์‹ ํ•˜์—ฌ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค.

self.registration ๋ถ€๋ถ„์€ ์„œ๋น„์Šค ์›Œ์ปค ๋“ฑ๋ก ๊ฐ์ฒด๋ฅผ ์˜๋ฏธํ•˜๋ฉฐ, showNotification์€ ์•ž์„œ ์‚ดํŽด๋ณด์•˜๋˜ Notification API์˜ ๊ธฐ๋Šฅ ์ค‘ ํ•˜๋‚˜์ด๋‹ค. ์ฆ‰, ํ•ด๋‹น ์ฝ”๋“œ๋Š” ์ด๋ฒคํŠธ ๊ฐ์ฒด์—์„œ ์ˆ˜์‹ ํ•œ ๋ฉ”์‹œ์ง€ ๋ฐ์ดํ„ฐ๋ฅผ ๊บผ๋‚ด์˜จ ํ›„ ์•Œ๋ฆผ์„ ๋„์šฐ๋Š” ์ฝ”๋“œ๋ผ๊ณ  ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

์•„๋ž˜์˜ notificationclick ์ด๋ฒคํŠธ๋Š” ์ด๋ฒคํŠธ ๋ช…์—์„œ ์œ ์ถ”ํ•  ์ˆ˜ ์žˆ๋“ฏ์ด ์‚ฌ์šฉ์ž๊ฐ€ ์•Œ๋ฆผ์„ ๋ˆŒ๋ €์„ ๋•Œ ํŠธ๋ฆฌ๊ฑฐ๋˜๋Š” ์ด๋ฒคํŠธ์ด๋‹ค.
์‚ฌ์šฉ์ž๊ฐ€ ํ‘ธ์‹œ ์•Œ๋ฆผ์„ ์ˆ˜์‹ ํ•˜๊ณ , ์ด๋ฅผ ํด๋ฆญํ–ˆ์„ ๋•Œ ์–ด๋– ํ•œ ๋™์ž‘์„ ์ฒ˜๋ฆฌํ•ด์•ผ ํ•  ๋•Œ ํ•ด๋‹น ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ์—์„œ ๋กœ์ง์„ ๊ตฌํ˜„ํ•˜๋ฉด ๋œ๋‹ค.
(์˜ˆ: ํ‘ธ์‹œ ์•Œ๋ฆผ ํด๋ฆญ ์‹œ ํŠน์ • ์›น ํŽ˜์ด์ง€ ์—ด์–ด์ฃผ๊ธฐ)

โญ๏ธ ํ‘ธ์‹œ ์•Œ๋ฆผ ๋™์ž‘ ํ™•์ธํ•ด๋ณด๊ธฐ

์ง€๊ธˆ๊นŒ์ง€ ํ•ต์‹ฌ ๊ธฐ๋Šฅ๊ณผ ์ฝ”๋“œ๋ฅผ ์‚ดํŽด๋ณด์•˜๋‹ค.

ํ‘ธ์‹œ ์„œ๋น„์Šค๋ฅผ ๊ตฌ๋…ํ•˜๊ณ , ์‹ค์ œ๋กœ ํ‘ธ์‹œ ๋ฉ”์‹œ์ง€๋ฅผ ๋ฐ›์•„ ์‹œ์Šคํ…œ ์•Œ๋ฆผ์ด ๋œจ๋Š”์ง€ ์ „๋ฐ˜์ ์œผ๋กœ ํ™•์ธํ•ด๋ณด์ž.

๋ฐ๋ชจ ์„œ๋ฒ„๋ฅผ ์‹คํ–‰ํ•˜๊ณ  ํŽ˜์ด์ง€์— ์ ‘์†ํ•˜๋ฉด, ๋กœ๊ทธ์ธ ํ™”๋ฉด์œผ๋กœ ์ด๋™ํ•  ๊ฒƒ์ด๋‹ค. ์—ฌ๊ธฐ์—์„œ ์‚ฌ์šฉ์ž๋ฅผ ์‹๋ณ„ํ•˜๊ธฐ ์œ„ํ•ด ์ž„์˜์˜ ์•„์ด๋””๋ฅผ ์ž…๋ ฅํ•˜๊ณ  ํ™ˆ ํ™”๋ฉด์œผ๋กœ ์ด๋™ํ•˜์ž.

ํ™ˆ ํ™”๋ฉด

์œ ์ € ID๋ฅผ safari_user๋กœ ์ž…๋ ฅํ•œ ํ›„ ์ด๋™ํ•œ ํ™ˆ ํ™”๋ฉด ๋ชจ์Šต์ด๋‹ค.

๊ฐ ์„น์…˜์— ๋Œ€ํ•ด ๊ฐ„๋žตํžˆ ์†Œ๊ฐœํ•˜๋„๋ก ํ•˜๊ฒ ๋‹ค.

  • Status: ์„œ๋น„์Šค ์›Œ์ปค ๋“ฑ๋ก ์—ฌ๋ถ€, ํ‘ธ์‹œ ์•Œ๋ฆผ ์ง€์› ์—ฌ๋ถ€, ํ‘ธ์‹œ ์•Œ๋ฆผ ๊ถŒํ•œ ๊ทธ๋ฆฌ๋„ ๊ตฌ๋… ์ •๋ณด๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.
  • Subscribe: ํ‘ธ์‹œ ์„œ๋น„์Šค ๊ตฌ๋… & ํ•ด์ง€
  • Send Push Notification: ํŠน์ • ์‚ฌ์šฉ์ž ID๋กœ ํ‘ธ์‹œ ๋ฉ”์‹œ์ง€ ์ „์†ก
  • Logout: ๋กœ๊ทธ์ธ ํ™”๋ฉด์œผ๋กœ ์ด๋™

๋จผ์ € ํ‘ธ์‹œ ์„œ๋น„์Šค ๊ตฌ๋…์„ ์œ„ํ•ด Subscribe ๋ฒ„ํŠผ์„ ๋ˆŒ๋Ÿฌ๋ณด์ž. ๊ทธ๋Ÿฌ๋ฉด ์•„๋ž˜์™€ ๊ฐ™์ด ์•Œ๋ฆผ ๊ถŒํ•œ์„ ๋ฌผ์–ด๋ณผ ๊ฒƒ์ด๋‹ค. ๋™์ž‘์„ ํ™•์ธํ•  ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์— ํ—ˆ์šฉํ•ด์ฃผ๋„๋ก ํ•˜์ž.

(๋งŒ์•ฝ ๊ฑฐ๋ถ€ํ•˜๊ฑฐ๋‚˜ ์ทจ์†Œํ•œ ๊ฒฝ์šฐ ๊ถŒํ•œ์€ ๊ฑฐ๋ถ€(denied) ์ƒํƒœ๊ฐ€ ๋˜๋Š”๋ฐ, ๋ธŒ๋ผ์šฐ์ € ์„ค์ •์œผ๋กœ ์ด๋™ํ•˜์—ฌ ๊ถŒํ•œ์„ ์žฌ์„ค์ •ํ•œ ํ›„ ํŽ˜์ด์ง€๋ฅผ ์ƒˆ๋กœ ๊ณ ์นจ ํ•˜๋ฉด ๋œ๋‹ค)

์ •์ƒ์ ์œผ๋กœ ๊ตฌ๋…๋œ ๊ฒฝ์šฐ ์•„๋ž˜์™€ ๊ฐ™์ด ๊ตฌ๋… ์ •๋ณด๋ฅผ Status ์„น์…˜์—์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค. ํ˜„์žฌ ๋„์›Œ์ ธ ์žˆ๋Š” ๋ธŒ๋ผ์šฐ์ €๋Š” ํ‘ธ์‹œ ์•Œ๋ฆผ์„ ์ˆ˜์‹ ํ•  ์ˆ˜ ์žˆ๋‹ค.

Send Push Notification ์„น์…˜์—์„œ Target User ID ๋ถ€๋ถ„์— ํ˜„์žฌ ๋ณธ์ธ์˜ ์•„์ด๋””๋ฅผ ์ž…๋ ฅํ•œ ํ›„ Send ๋ฒ„ํŠผ์„ ๋ˆŒ๋Ÿฌ๋ณด์ž.

์„œ๋ฒ„๋ฅผ ํ†ตํ•ด ํ‘ธ์‹œ ์„œ๋น„์Šค๋กœ ๋ฉ”์‹œ์ง€๊ฐ€ ์ „๋‹ฌ๋˜๊ณ , ํ‘ธ์‹œ ์„œ๋น„์Šค์—์„œ ๋ณธ์ธ ๋ธŒ๋ผ์šฐ์ €๋กœ ํ‘ธ์‹œ ๋ฉ”์‹œ์ง€๋ฅผ ์ „๋‹ฌํ•˜์—ฌ ์•Œ๋ฆผ์ด ๋…ธ์ถœ๋  ๊ฒƒ์ด๋‹ค.


๋ฐ๋ชจ๋ฅผ ํ†ตํ•ด ๋ณธ์ธ์—๊ฒŒ ํ‘ธ์‹œ ๋ฉ”์‹œ์ง€๋ฅผ ์ „์†กํ•˜๊ฑฐ๋‚˜, ๋‹ค๋ฅธ ์‚ฌ์šฉ์ž์—๊ฒŒ ๋ฉ”์‹œ์ง€๋ฅผ ์ „์†กํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

๋‹ค๋ฅธ ์‚ฌ์šฉ์ž์—๊ฒŒ ํ‘ธ์‹œ ๋ฉ”์‹œ์ง€๋ฅผ ์ „์†กํ•˜๋Š” ๊ณผ์ •์€ ์•„๋ž˜ ์˜์ƒ์„ ์ฐธ๊ณ ํ•˜๋ฉด ์ข‹์„ ๊ฒƒ ๊ฐ™๋‹ค.


์ง€๊ธˆ๊นŒ์ง€ ์›น ํ‘ธ์‹œ์— ๋Œ€ํ•ด ์ „๋ฐ˜์ ์œผ๋กœ ์‚ดํŽด๋ณด์•˜๋‹ค.

๋„ค์ดํ‹ฐ๋ธŒ์—์„œ๋งŒ ๊ตฌํ˜„ ๊ฐ€๋Šฅํ•˜๋˜ ํ‘ธ์‹œ ์•Œ๋ฆผ์„ ์›น ํ™˜๊ฒฝ์—์„œ ๊ตฌํ˜„ํ•˜๊ณ , ์‚ฌ์šฉ์ž์—๊ฒŒ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ์€ ์›น์ด๋ผ๋Š” ํ”Œ๋žซํผ์— ํฐ ๋ฌด๊ธฐ๋ฅผ ์ฅ์–ด์ค€ ๊ฒƒ์ด๋ผ๊ณ  ์ƒ๊ฐํ•œ๋‹ค.

์ด๋ฒˆ์— ์•Œ์•„๋ณธ ํ‘ธ์‹œ ์•Œ๋ฆผ ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ๊ฒฐ์ œ ์š”์ฒญ, ์ƒ์ฒด ์ธ์ฆ, ํŒŒ์ผ ์‹œ์Šคํ…œ ๋“ฑ ์—ฌ๋Ÿฌ ๊ฐ€์ง€ API ์‚ฌ์–‘๋“ค์ด ํƒ„์ƒํ•˜๊ณ  ๊ตฌํ˜„๋˜๊ณ  ์žˆ๋Š” ๊ฐ€์šด๋ฐ, ์•ž์œผ๋กœ์˜ ์›น์ด ์–ด๋–ป๊ฒŒ ๋ณ€ํ™”ํ• ์ง€ ๋”์šฑ๋” ๊ถ๊ธˆํ•ด์ง„๋‹ค.

References

  • https://developer.apple.com/documentation/usernotifications/sending_web_push_notifications_in_safari_and_other_browsers
  • https://www.w3.org/TR/push-api
  • https://notifications.spec.whatwg.org
  • https://w3c.github.io/ServiceWorker
  • https://www.rfc-editor.org/rfc/rfc8292
๋ฐ˜์‘ํ˜•
์ €์ž‘์žํ‘œ์‹œ ๋น„์˜๋ฆฌ ๋™์ผ์กฐ๊ฑด
    '์›น' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€
    • [PWA] SNS ์•ฑ ์˜ˆ์ œ๋กœ ๋ฐฐ์šฐ๋Š” ํ”„๋กœ๊ทธ๋ ˆ์‹œ๋ธŒ ์›น ์•ฑ ์ถœ๊ฐ„!
    • [WWDC20] Safari Web Extension/์‚ฌํŒŒ๋ฆฌ ์›น ํ™•์žฅ ์‚ดํŽด๋ณด๊ธฐ
    • [PWA] ํ”„๋กœ๊ทธ๋ ˆ์‹œ๋ธŒ ์›น ์•ฑ ์‹œ์ž‘ํ•˜๊ธฐ (6) - Push, ํ‘ธ์‹œ ์•Œ๋ฆผ
    • [PWA] ํ”„๋กœ๊ทธ๋ ˆ์‹œ๋ธŒ ์›น ์•ฑ ์‹œ์ž‘ํ•˜๊ธฐ (5) - Push, ํ‘ธ์‹œ ์•Œ๋ฆผ
    ์ด๊ทผ๋‘ฅ
    ์ด๊ทผ๋‘ฅ
    ์ƒˆ๋กœ์šด ๊ฒƒ์„ ์ข‹์•„ํ•˜๋Š” ํ”„๋ก ํŠธ์—”๋“œ ๊ฐœ๋ฐœ์ž โœจ
    ๋Œ“๊ธ€์“ฐ๊ธฐ

    ํ‹ฐ์Šคํ† ๋ฆฌํˆด๋ฐ”