๐Ÿš€ PWA ๋„์ž… ๊ฒฝํ—˜๊ธฐ - ์•ฑ ์Šคํ† ์–ด ์—†์ด ์•ฑ ๋งŒ๋“ค๊ธฐ

sumi-0011ยท2025๋…„ 3์›” 16์ผ
3

๐Ÿฑ GitAnimals

๋ชฉ๋ก ๋ณด๊ธฐ
3/3
post-thumbnail

๊ณ ๋ฏผํ–ˆ๋˜ ๋ฐฐ๊ฒฝ

GitAnimals ํ”„๋กœ์ ํŠธ๋ฅผ ์ง„ํ–‰ํ•˜๋ฉด์„œ ํ•œ ๊ฐ€์ง€ ๊ณ ๋ฏผ์ด ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ์ด ์„œ๋น„์Šค๋Š” ๊นƒํ—ˆ๋ธŒ ์ปค๋ฐ‹์„ ํ†ตํ•ด ํฌ์ธํŠธ๋ฅผ ์–ป๊ณ  ๊ทธ ํฌ์ธํŠธ๋กœ ํŽซ์„ ๋ฝ‘์•„ ํ‚ค์šฐ๋Š” ์„œ๋น„์Šค์ธ๋ฐ์š”, ์ผํšŒ์šฉ์„ฑ ์ ‘๊ทผ์ด ์•„๋‹Œ ์‚ฌ์šฉ์ž ์ฐธ์—ฌ๊ฐ€ ์ง€์†์ ์œผ๋กœ ์ด๋ฃจ์–ด์ง€๋„๋ก ํ•˜๊ณ ์‹ถ์—ˆ์–ด์š”. ๋” ๋‚˜์€ ์‚ฌ์šฉ์ž ๊ฒฝํ—˜๊ณผ ์ ‘๊ทผ์„ฑ์„ ์œ„ํ•ด ์•ฑ ํ˜•ํƒœ๋กœ ์ œ๊ณตํ•˜๋Š” ๊ฒƒ์„ ๊ณ ๋ คํ•˜๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

์ฒ˜์Œ์—๋Š” RN์„ ์ด์šฉํ•œ ์›น ์•ฑ ๊ฐœ๋ฐœ์„ ๊ณ ๋ คํ–ˆ์ง€๋งŒ, ๋ช‡ ๊ฐ€์ง€ ํ˜„์‹ค์ ์ธ ์ œ์•ฝ์ด ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ๐Ÿค”

  1. GitHub ๋กœ๊ทธ์ธ๊ณผ ๊ณ„์ • ์—ฐ๋™์ด ํ•„์ˆ˜์ ์ธ๋ฐ, iOS ์•ฑ์˜ ๊ฒฝ์šฐ ์†Œ์…œ ๋กœ๊ทธ์ธ์„ ๊ตฌํ˜„ํ•˜๋ ค๋ฉด Apple ๋กœ๊ทธ์ธ ๊ธฐ๋Šฅ๋„ ํ•„์ˆ˜์ ์œผ๋กœ ์š”๊ตฌ๋ฉ๋‹ˆ๋‹ค.
  2. ๋ณต์žกํ•œ ์ธ์ฆ ํ”Œ๋กœ์šฐ๋กœ ์ธํ•ด ๊ฐœ๋ฐœ ์ผ์ •์ด ์ง€์—ฐ๋  ๊ฐ€๋Šฅ์„ฑ์ด ๋†’์•˜์Šต๋‹ˆ๋‹ค.
  3. ์•ฑ ์Šคํ† ์–ด ์‹ฌ์‚ฌ ๊ณผ์ •๊ณผ ๋ฐฐํฌ ์‹œ๊ฐ„๋„ ๋ถ€๋‹ด์œผ๋กœ ๋‹ค๊ฐ€์™”์Šต๋‹ˆ๋‹ค.

์ด๋Ÿฌํ•œ ๊ณ ๋ฏผ ์†์—์„œ "๊ผญ ์•ฑ์ด์–ด์•ผ ํ• ๊นŒ?"๋ผ๋Š” ์งˆ๋ฌธ์„ ํ•˜๊ฒŒ ๋˜์—ˆ๊ณ , ๊ทธ ๋Œ€์•ˆ์œผ๋กœ PWA(Progressive Web App)๋ฅผ ๋ฐœ๊ฒฌํ•˜๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

PWA๊ฐ€ ๋ญ๊ธธ๋ž˜?

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

์ด๋Ÿฐ ๊ฐ•๋ ฅํ•œ ๊ธฐ๋Šฅ๋“ค์€ ๋Œ€๋ถ€๋ถ„ '์„œ๋น„์Šค ์›Œ์ปค(Service Worker)'๋ผ๋Š” ๊ธฐ์ˆ  ๋•๋ถ„์— ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. ์›น์˜ ์ ‘๊ทผ์„ฑ๊ณผ ์•ฑ์˜ ์‚ฌ์šฉ์ž ๊ฒฝํ—˜์„ ๊ฒฐํ•ฉํ•œ ํ•˜์ด๋ธŒ๋ฆฌ๋“œ ์ ‘๊ทผ ๋ฐฉ์‹์ด๋ผ๊ณ  ์ƒ๊ฐํ•˜๋ฉด ์ดํ•ดํ•˜๊ธฐ ์‰ฌ์šธ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

์„œ๋น„์Šค ์›Œ์ปค๋ž€?
PWA์˜ ํ•ต์‹ฌ ๊ธฐ์ˆ ์ธ ์„œ๋น„์Šค ์›Œ์ปค๋Š” ์›น ํŽ˜์ด์ง€์™€ ๋ธŒ๋ผ์šฐ์ € ์‚ฌ์ด์—์„œ ๋™์ž‘ํ•˜๋Š” JavaScript ํŒŒ์ผ์ž…๋‹ˆ๋‹ค. ๋„คํŠธ์›Œํฌ ์š”์ฒญ์„ ๊ฐ€๋กœ์ฑ„๊ณ  ์บ์‹ฑ ์ „๋žต์„ ์ ์šฉํ•˜์—ฌ ์˜คํ”„๋ผ์ธ ์ž‘๋™, ์„ฑ๋Šฅ ํ–ฅ์ƒ, ๋ฐฑ๊ทธ๋ผ์šด๋“œ ๋™๊ธฐํ™”, ํ‘ธ์‹œ ์•Œ๋ฆผ ๋“ฑ์˜ ๊ธฐ๋Šฅ์„ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค. ์„œ๋น„์Šค ์›Œ์ปค ๋•๋ถ„์— ์›น์‚ฌ์ดํŠธ๊ฐ€ ์•ฑ์ฒ˜๋Ÿผ ๋™์ž‘ํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ด์ฃ !

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

PWA์˜ ์žฅ์ ๋“ค

PWA๋ฅผ ๊ฒ€ํ† ํ•˜๋ฉด์„œ ๊ฐ€์žฅ ๋Œ๋ ธ๋˜ ์žฅ์ ๋“ค์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

  1. ์•ฑ ์Šคํ† ์–ด ์šฐํšŒ โญ๏ธ - ์•ฑ ์Šคํ† ์–ด ์‹ฌ์‚ฌ ์—†์ด ๋ฐ”๋กœ ๋ฐฐํฌํ•  ์ˆ˜ ์žˆ์–ด ๋น ๋ฅธ ๊ฐœ๋ฐœ ์‚ฌ์ดํด์„ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  2. ํ‘ธ์‹œ ์•Œ๋ฆผ ๐Ÿ”” - ์›น์ธ๋ฐ๋„ ๋„ค์ดํ‹ฐ๋ธŒ ์•ฑ์ฒ˜๋Ÿผ ํ‘ธ์‹œ ์•Œ๋ฆผ์„ ๋ณด๋‚ผ ์ˆ˜ ์žˆ์–ด ์‚ฌ์šฉ์ž ์ฐธ์—ฌ๋ฅผ ์œ ๋„ํ•˜๊ธฐ ์ข‹์Šต๋‹ˆ๋‹ค.

์ด๋Ÿฐ ์žฅ์ ๋“ค์ด GitAnimals ํ”„๋กœ์ ํŠธ์˜ ํ˜„์žฌ ์ƒํ™ฉ๊ณผ ๋”ฑ ๋งž๋Š” ๊ฒƒ ๊ฐ™์•„ PWA ์ ์šฉ์„ ๊ฒฐ์ •ํ–ˆ์Šต๋‹ˆ๋‹ค.

GitAnimals ํ”„๋กœ์ ํŠธ์— PWA ์ ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•

Gitaninmals๋Š” Next.js App router ํ™˜๊ฒฝ์œผ๋กœ ์ด๋ฃจ์–ด์ ธ์žˆ๋Š” ์„œ๋น„์Šค์ž…๋‹ˆ๋‹ค. Next.js๋กœ ๊ฐœ๋ฐœ๋œ ํ”„๋กœ์ ํŠธ์— PWA๋ฅผ ์ ์šฉํ•˜๋Š” ๊ณผ์ •์„ ๊ณต์œ ํ•ด๋ณด๋ ค๊ณ ํ•ฉ๋‹ˆ๋‹ค.

1. ํŒจํ‚ค์ง€ ์„ค์น˜ํ•˜๊ธฐ

์ฒซ ๋‹จ๊ณ„๋Š” ๊ฐ„๋‹จํ–ˆ์Šต๋‹ˆ๋‹ค. next-pwa ํŒจํ‚ค์ง€๋ฅผ ์„ค์น˜ํ•˜๋Š” ๊ฒƒ์ด์—ˆ์ฃ .

npm install next-pwa

์ด ํŒจํ‚ค์ง€๋Š” Next.js ํ”„๋กœ์ ํŠธ์— PWA๋ฅผ ์†์‰ฝ๊ฒŒ ์ ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค๋‹ˆ๋‹ค. ์ฒ˜์Œ์—๋Š” ์ง์ ‘ ์„œ๋น„์Šค ์›Œ์ปค๋ฅผ ๊ตฌํ˜„ํ•ด์•ผ ํ•˜๋‚˜ ๊ฑฑ์ •ํ–ˆ๋Š”๋ฐ, ์ด ํŒจํ‚ค์ง€ ๋•๋ถ„์— ๋งŽ์€ ๋ถ€๋ถ„์ด ์ž๋™ํ™”๋˜์–ด ํŽธ๋ฆฌํ–ˆ์Šต๋‹ˆ๋‹ค.

2. Next.js ์„ค์ • ํŒŒ์ผ ์ˆ˜์ •ํ•˜๊ธฐ

๋‹ค์Œ์œผ๋กœ next.config.mjs ํŒŒ์ผ์„ ์ˆ˜์ •ํ–ˆ์Šต๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ PWA์˜ ํ•ต์‹ฌ ์„ค์ •์„ ์ถ”๊ฐ€ํ•˜๋Š” ์ž‘์—…์ด์—ˆ์ฃ .

import createNextIntlPlugin from 'next-intl/plugin';
import NextPWA from 'next-pwa';

const withNextIntl = createNextIntlPlugin();
const withPWA = NextPWA({
  dest: 'public',
  disable: process.env.NODE_ENV === 'development' || process.env.DISABLE_PWA === 'true',
  register: true,
  skipWaiting: true,
});

const nextConfig = withNextIntl({
  // ๊ธฐ์กด ์„ค์ •๋“ค...
});

export default withPWA(nextConfig);

๊ฐœ๋ฐœ ๊ณผ์ •์—์„œ ํ•œ ๊ฐ€์ง€ ๊นจ๋‹ฌ์€ ์ ์€ ๊ฐœ๋ฐœ ํ™˜๊ฒฝ์—์„œ๋Š” PWA ๊ธฐ๋Šฅ์„ ๋น„ํ™œ์„ฑํ™”ํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค๋Š” ๊ฒƒ์ด์—ˆ์Šต๋‹ˆ๋‹ค. ์„œ๋น„์Šค ์›Œ์ปค๊ฐ€ ํ™œ์„ฑํ™”๋˜๋ฉด ์บ์‹ฑ ๋•Œ๋ฌธ์— ์ฝ”๋“œ ๋ณ€๊ฒฝ์‚ฌํ•ญ์ด ์ฆ‰์‹œ ๋ฐ˜์˜๋˜์ง€ ์•Š์•„ ๊ฐœ๋ฐœ ํšจ์œจ์ด ๋–จ์–ด์ง€๋”๋ผ๊ณ ์š”. ๊ทธ๋ž˜์„œ disable: process.env.NODE_ENV === 'development' ์˜ต์…˜์„ ์ถ”๊ฐ€ํ–ˆ์Šต๋‹ˆ๋‹ค.

3. PWA ์„ค์น˜ ์•ˆ๋‚ด ๋ฐฐ๋„ˆ ๋งŒ๋“ค๊ธฐ

PWA๋ฅผ ๊ตฌํ˜„ํ•˜๋ฉด์„œ ๊ฐ€์žฅ ํฐ ๋„์ „ ๊ณผ์ œ๋Š” ์„ค์น˜ ํ”„๋กœ์„ธ์Šค์˜€์Šต๋‹ˆ๋‹ค. ๊ธฐ๋ณธ ๊ธฐ๋Šฅ ๊ตฌํ˜„์€ next-pwa ํŒจํ‚ค์ง€ ๋•๋ถ„์— ์‰ฌ์› ์ง€๋งŒ, ์‚ฌ์šฉ์ž๋“ค์—๊ฒŒ "์ด ์›น์‚ฌ์ดํŠธ๋ฅผ ์•ฑ์œผ๋กœ ์„ค์น˜ํ•  ์ˆ˜ ์žˆ์–ด์š”"๋ผ๊ณ  ์•Œ๋ ค์ฃผ๊ณ  ๊ทธ ๊ณผ์ •์„ ์•ˆ๋‚ดํ•˜๋Š” ๊ฒƒ์€ ์˜จ์ „ํžˆ ์ œ ๋ชซ์ด์—ˆ์Šต๋‹ˆ๋‹ค.

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

'use client';
import { useEffect, useState } from 'react';
import { css } from 'panda/css';
import { flex } from 'panda/patterns';
import { AnimatePresence, motion } from 'framer-motion';

export const PWAInstallBanner = () => {
  const [showBanner, setShowBanner] = useState(false);
  const [showModal, setShowModal] = useState(false);
  
  useEffect(() => {
    // PWA ์„ค์น˜ ์ด๋ฒคํŠธ ๊ฐ์ง€
    window.addEventListener('beforeinstallprompt', (e) => {
      e.preventDefault();
      setShowBanner(true);
    });
    
    // ์ด๋ฏธ ์„ค์น˜๋œ ๊ฒฝ์šฐ ๊ฐ์ง€
    window.addEventListener('appinstalled', () => {
      setShowBanner(false);
    });
  }, []);

  const handleInstall = () => {
    setShowModal(true);
  };
  
  // ๋ฐฐ๋„ˆ UI ๋ Œ๋”๋ง ์ฝ”๋“œ
}

์ด ์ฝ”๋“œ์—์„œ ํ•ต์‹ฌ์€ beforeinstallprompt ์ด๋ฒคํŠธ๋ฅผ ๊ฐ์ง€ํ•˜๋Š” ๋ถ€๋ถ„์ž…๋‹ˆ๋‹ค. ๋ธŒ๋ผ์šฐ์ €๊ฐ€ "์ด ์‚ฌ์ดํŠธ๋Š” ์„ค์น˜ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค"๋ผ๊ณ  ํŒ๋‹จํ•  ๋•Œ ์ด ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•˜๊ณ , ์ด๋•Œ ์‚ฌ์šฉ์ž์—๊ฒŒ ๋ฐฐ๋„ˆ๋ฅผ ๋ณด์—ฌ์ฃผ๋Š” ๋ฐฉ์‹์œผ๋กœ ๊ตฌํ˜„ํ–ˆ์Šต๋‹ˆ๋‹ค.

4. ๋ธŒ๋ผ์šฐ์ €๋ณ„ ์„ค์น˜ ๊ฐ€์ด๋“œ ๊ตฌํ˜„๊ณผ ์„ค์น˜ ๊ณผ์ •์˜ ๋ณต์žกํ•จ ํ•ด๊ฒฐํ•˜๊ธฐ

๋จผ์ € ์„ค์น˜ ์•ˆ๋‚ด ๋ฐฐ๋„ˆ๋ฅผ ๋งŒ๋“  ํ›„, ๊ณง๋ฐ”๋กœ ๋” ํฐ ๋ฌธ์ œ๋ฅผ ๋ฐœ๊ฒฌํ–ˆ์Šต๋‹ˆ๋‹ค. PWA ์„ค์น˜ ๋ฐฉ๋ฒ•์ด ๋ธŒ๋ผ์šฐ์ €๋งˆ๋‹ค ์™„์ „ํžˆ ๋‹ค๋ฅด๋‹ค๋Š” ์ ์ด์—ˆ์ฃ . Chrome, Safari, Samsung Internet ๋“ฑ ๋ธŒ๋ผ์šฐ์ €๋ณ„๋กœ ์„ค์น˜ UI์™€ ๊ณผ์ •์ด ๋‹ฌ๋ผ์„œ ๋ชจ๋“  ์‚ฌ์šฉ์ž์—๊ฒŒ ์ ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ํ†ต์ผ๋œ ์•ˆ๋‚ด๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์—†์—ˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๋ž˜์„œ ์‚ฌ์šฉ์ž์˜ ๋ธŒ๋ผ์šฐ์ €๋ฅผ ์ž๋™์œผ๋กœ ๊ฐ์ง€ํ•˜๊ณ  ๋งž์ถคํ˜• ์„ค์น˜ ๊ฐ€์ด๋“œ๋ฅผ ์ œ๊ณตํ•˜๋Š” ๋ชจ๋‹ฌ์„ ๊ตฌํ˜„ํ–ˆ์Šต๋‹ˆ๋‹ค.

export const PWAInstallGuideModal = ({ onClose }: { onClose: () => void }) => {
  const [currentSlide, setCurrentSlide] = useState(0);
  const [browserType, setBrowserType] = useState('unknown');
  
  useEffect(() => {
    // ๋ธŒ๋ผ์šฐ์ € ํƒ์ง€
    const userAgent = navigator.userAgent.toLowerCase();
    if (/iphone|ipad|ipod/.test(userAgent)) {
      setBrowserType('safari');
    } else if (/android/.test(userAgent)) {
      if (/samsung/.test(userAgent)) {
        setBrowserType('samsung');
      } else if (/kakao/.test(userAgent)) {
        setBrowserType('kakao');
      } else if (/naver/.test(userAgent) || /whale/.test(userAgent)) {
        setBrowserType('whale');
      } else {
        setBrowserType('chrome');
      }
    }
  }, []);
  
  // ๋ธŒ๋ผ์šฐ์ €๋ณ„ ์„ค์น˜ ๊ฐ€์ด๋“œ ์Šฌ๋ผ์ด๋“œ ๊ตฌ์„ฑ
  const slides = [
    // ์ธํŠธ๋กœ ์Šฌ๋ผ์ด๋“œ
    {
      title: '์•ฑ์œผ๋กœ ์„ค์น˜ํ•˜๊ธฐ',
      description: 'ํ™ˆ ํ™”๋ฉด์— ์„ค์น˜ํ•˜์—ฌ ๋” ๋น ๋ฅด๊ฒŒ ์ ‘๊ทผํ•˜๊ณ  ์˜คํ”„๋ผ์ธ์—์„œ๋„ ์‚ฌ์šฉํ•ด๋ณด์„ธ์š”!',
      image: '/images/pwa-intro.png',
      isIntro: true,
    },
    // ๋ธŒ๋ผ์šฐ์ €๋ณ„ ๊ฐ€์ด๋“œ ์Šฌ๋ผ์ด๋“œ...
  ];
  
  // ์Šฌ๋ผ์ด๋“œ UI ๋ฐ ๋„ค๋น„๊ฒŒ์ด์…˜ ์ฝ”๋“œ
}

PWA์˜ ๊ฒฝ์šฐ ๋ธŒ๋ผ์šฐ์ €๋งˆ๋‹ค ์„ค์น˜ ๊ณผ์ •์ด ๋‹ค๋ฅด๊ณ , ์‚ฌ์šฉ์ž๊ฐ€ ์—ฌ๋Ÿฌ ๋‹จ๊ณ„๋ฅผ ๊ฑฐ์ณ์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‹ค๋ณด๋‹ˆ ์‚ฌ์šฉ์ž๊ฐ€ ์•ฑ ์„ค์น˜๋ฅผ ํ•˜๋Š” ์ ‘๊ทผ์„ฑ์ด ์ข‹์ง€ ์•Š๋‹ค๊ณ  ์ƒ๊ฐํ•˜์˜€๊ณ , ์šฐ์„ ์ ์œผ๋กœ ํ•ด๊ฒฐํ•ด์•ผํ•˜๋Š” ๋ฌธ์ œ๋ผ๊ณ  ์ƒ๊ฐํ–ˆ์–ด์š”.

์ด๋Ÿฐ ๋ฌธ์ œ๋“ค์„ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ์—ฌ๋Ÿฌ ์ „๋žต์„ ์ ์šฉํ•ด๋ณด์•˜์Šต๋‹ˆ๋‹ค.

  • ๋งž์ถคํ˜• ์•ˆ๋‚ด: ์ฃผ์š” ๋ธŒ๋ผ์šฐ์ € ๊ฐ๊ฐ์— ๋Œ€ํ•ด ๋งž์ถคํ˜• ์„ค์น˜ ๊ฐ€์ด๋“œ๋ฅผ ๋งŒ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค.
  • ์‹œ๊ฐ์  ์ž๋ฃŒ ํ™œ์šฉ: ๊ฐ ๋‹จ๊ณ„๋ฅผ ์Šคํฌ๋ฆฐ์ƒท๊ณผ ํ•จ๊ป˜ ์ œ๊ณตํ•˜์—ฌ ์‚ฌ์šฉ์ž๊ฐ€ ์ง๊ด€์ ์œผ๋กœ ๋”ฐ๋ผํ•  ์ˆ˜ ์žˆ๋„๋ก ํ–ˆ์Šต๋‹ˆ๋‹ค.
  • ์„ค์น˜ ํ˜œํƒ ๊ฐ•์กฐ: "์•ฑ์œผ๋กœ ์„ค์น˜ํ•˜๋ฉด ๋” ๋น ๋ฅด๊ฒŒ ์ ‘๊ทผํ•˜๊ณ  ์˜คํ”„๋ผ์ธ์—์„œ๋„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์–ด์š”"์™€ ๊ฐ™์€ ๊ตฌ์ฒด์ ์ธ ์ด์ ์„ ๊ฐ•์กฐํ–ˆ์Šต๋‹ˆ๋‹ค.

ํŠนํžˆ iOS Safari์˜ ๊ฒฝ์šฐ PWA ์„ค์น˜๊ฐ€ ์ง๊ด€์ ์ด์ง€ ์•Š๊ณ  ์ˆจ๊ฒจ์ ธ ์žˆ์–ด์„œ ๋‹จ๊ณ„๋ณ„ ๊ฐ€์ด๋“œ๊ฐ€ ํ•„์ˆ˜์ ์ด์—ˆ์Šต๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž๊ฐ€ "๊ณต์œ " ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๊ณ , ์Šคํฌ๋กค์„ ๋‚ด๋ ค "ํ™ˆ ํ™”๋ฉด์— ์ถ”๊ฐ€" ์˜ต์…˜์„ ์ฐพ๊ณ , ์„ค๋ช…์„ ์ฝ๊ณ , "์ถ”๊ฐ€" ๋ฒ„ํŠผ์„ ๋ˆŒ๋Ÿฌ์•ผ ํ•˜๋Š” ๋ณต์žกํ•œ ๊ณผ์ •์„ ๊ฑฐ์ณ์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๊ทธ๋Ÿผ์—๋„ ๋ถˆ๊ตฌํ•˜๊ณ  ์ด์ƒ์ ์ธ ์„ค์น˜ ๊ฒฝํ—˜์—๋Š” ์—ฌ์ „ํžˆ ๋ฏธ์น˜์ง€ ๋ชปํ•œ๋‹ค๋Š” ์ƒ๊ฐ์ด ๋“ญ๋‹ˆ๋‹ค. ์•ฑ ์Šคํ† ์–ด์—์„œ ํ•˜๋‚˜์˜ "์„ค์น˜" ๋ฒ„ํŠผ์œผ๋กœ ๋๋‚˜๋Š” ๋‹จ์ˆœํ•จ๊ณผ ๋น„๊ตํ•˜๋ฉด, PWA ์„ค์น˜ ๊ณผ์ •์€ ์—ฌ์ „ํžˆ ์ง„์ž… ์žฅ๋ฒฝ์ด ๋†’์Šต๋‹ˆ๋‹ค. ์ด ๋ถ€๋ถ„์€ PWA ๊ธฐ์ˆ  ์ž์ฒด์˜ ํ•œ๊ณ„์ด๊ธฐ๋„ ํ•˜๋ฉฐ, ์•ž์œผ๋กœ ๋ธŒ๋ผ์šฐ์ €๋“ค์ด ๋” ์ผ๊ด€๋˜๊ณ  ์ง๊ด€์ ์ธ ์„ค์น˜ ๊ฒฝํ—˜์„ ์ œ๊ณตํ•˜๊ธฐ๋ฅผ ๊ธฐ๋Œ€ํ•ด ๋ด…๋‹ˆ๋‹ค.

์•„์ง ๋‚จ์€ ๊ณ ๋ฏผ๋“ค

PWA ๊ตฌํ˜„์„ ์ง„ํ–‰ํ•˜๋ฉด์„œ ์—ฌ์ „ํžˆ ๋ช‡ ๊ฐ€์ง€ ํ•ด๊ฒฐ๋˜์ง€ ์•Š์€ ๊ณ ๋ฏผ์ด ๋‚จ์•„์žˆ์Šต๋‹ˆ๋‹ค.

์ฒซ์งธ, ํ‘ธ์‹œ ์•Œ๋ฆผ ๊ถŒํ•œ์ž…๋‹ˆ๋‹ค. PWA์—์„œ ํ‘ธ์‹œ ์•Œ๋ฆผ์„ ๋ณด๋‚ด๋ ค๋ฉด ์‚ฌ์šฉ์ž์˜ ๊ถŒํ•œ์ด ํ•„์š”ํ•œ๋ฐ, ์ด ๊ณผ์ •๋„ ๋ธŒ๋ผ์šฐ์ €๋งˆ๋‹ค ๋‹ค๋ฆ…๋‹ˆ๋‹ค. ํŠนํžˆ iOS์—์„œ๋Š” ์•Œ๋ฆผ ๊ถŒํ•œ ํš๋“์ด ๋” ๊นŒ๋‹ค๋กญ๊ณ , ์‚ฌ์šฉ์ž๊ฐ€ ๊ฑฐ๋ถ€ํ•œ ๊ฒฝ์šฐ ๋‹ค์‹œ ์š”์ฒญํ•˜๊ธฐ๊ฐ€ ์–ด๋ ต์Šต๋‹ˆ๋‹ค.

๋‘˜์งธ, iOS ์ œ์•ฝ์‚ฌํ•ญ์ž…๋‹ˆ๋‹ค. iOS Safari์˜ PWA ์ง€์›์€ Android Chrome๋ณด๋‹ค ์ œํ•œ์ ์ž…๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ๋ฐฑ๊ทธ๋ผ์šด๋“œ ๋™๊ธฐํ™”๋‚˜ ์ผ๋ถ€ ์›น API๊ฐ€ ์ œํ•œ๋˜์–ด ์žˆ์–ด์„œ ์™„์ „ํ•œ ์•ฑ ๊ฒฝํ—˜์„ ์ œ๊ณตํ•˜๊ธฐ ์–ด๋ ต์Šต๋‹ˆ๋‹ค. ์ด๋Š” Apple์ด ์•ฑ ์Šคํ† ์–ด ์ƒํƒœ๊ณ„๋ฅผ ๋ณดํ˜ธํ•˜๊ธฐ ์œ„ํ•œ ์ „๋žต์œผ๋กœ ๋ณด์ด์ง€๋งŒ, ๊ฐœ๋ฐœ์ž ์ž…์žฅ์—์„œ๋Š” ์ œ์•ฝ์ด ๋งŽ์Šต๋‹ˆ๋‹ค.

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

์ด๋Ÿฐ ๊ณ ๋ฏผ๋“ค์ด ์žˆ์ง€๋งŒ, ๊ทธ๋ž˜๋„ PWA๋Š” ๋„ค์ดํ‹ฐ๋ธŒ ์•ฑ ๊ฐœ๋ฐœ ๋ฆฌ์†Œ์Šค๊ฐ€ ์ œํ•œ์ ์ธ ์ƒํ™ฉ์—์„œ ๊ดœ์ฐฎ์€ ํƒ€ํ˜‘์ ์ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ํŠนํžˆ GitAnimals ๊ฐ™์€ GitHub ํ†ตํ•ฉ ์„œ๋น„์Šค์—์„œ๋Š” ๋„ค์ดํ‹ฐ๋ธŒ ์•ฑ์˜ ์ธ์ฆ ๋ณต์žก์„ฑ์„ ์šฐํšŒํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ์ด ํฐ ์žฅ์ ์ž…๋‹ˆ๋‹ค.

์•ž์œผ๋กœ์˜ ๊ณ„ํš

PWA ๋„์ž…์€ ์•„์ง ์ดˆ๊ธฐ ๋‹จ๊ณ„์ด์ง€๋งŒ, ์•ž์œผ๋กœ ๋ช‡ ๊ฐ€์ง€ ๊ณ„ํš์„ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

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

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

PWA ํ‘ธ์‹œ ์•Œ๋ฆผ ํŒ
iOS 16.4๋ถ€ํ„ฐ Safari์—์„œ๋„ PWA ์›น ํ‘ธ์‹œ ์•Œ๋ฆผ์ด ์ง€์›๋˜๊ธฐ ์‹œ์ž‘ํ–ˆ์Šต๋‹ˆ๋‹ค. ๋‹จ, iOS์—์„œ๋Š” ์‚ฌ์šฉ์ž๊ฐ€ ๋จผ์ € PWA๋ฅผ ์„ค์น˜ํ•œ ํ›„์—๋งŒ ํ‘ธ์‹œ ์•Œ๋ฆผ ๊ถŒํ•œ์„ ์š”์ฒญํ•  ์ˆ˜ ์žˆ์œผ๋‹ˆ ์š”์ฒญ ํƒ€์ด๋ฐ์— ์ฃผ์˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค!

๋ฌด์—‡๋ณด๋‹ค ์ค‘์š”ํ•œ ๊ฑด ์‚ฌ์šฉ์ž ๊ฒฝํ—˜์ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ์ˆ ์ ์ธ ๊ตฌํ˜„ ๋ฐฉ์‹๋ณด๋‹ค๋Š” ์‚ฌ์šฉ์ž๋“ค์ด GitAnimals๋ฅผ ์–ผ๋งˆ๋‚˜ ํŽธ๋ฆฌํ•˜๊ฒŒ ์ด์šฉํ•  ์ˆ˜ ์žˆ๋Š”์ง€๊ฐ€ ํ•ต์‹ฌ์ด๋‹ˆ๊นŒ์š”. PWA๋“  ๋„ค์ดํ‹ฐ๋ธŒ ์•ฑ์ด๋“ , ์ตœ์ข…์ ์œผ๋กœ๋Š” ์‚ฌ์šฉ์ž๋“ค์—๊ฒŒ ๊ฐ€์žฅ ์ข‹์€ ๊ฒฝํ—˜์„ ์ œ๊ณตํ•˜๋Š” ๋ฐฉํ–ฅ์œผ๋กœ ๊ฒฐ์ •ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์‚ฌ์‹ค ํ˜„์žฌ๋Š” ํ”„๋กœ์ ํŠธ์˜ ์ƒํ™ฉ์— ๋งž์ถฐ PWA๋ฅผ ์„ ํƒํ–ˆ์ง€๋งŒ, ์žฅ๊ธฐ์ ์œผ๋กœ๋Š” Apple ๋กœ๊ทธ์ธ์„ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋Š” ๋ฆฌ์†Œ์Šค๊ฐ€ ํ™•๋ณด๋œ๋‹ค๋ฉด ๊ฒฐ๊ตญ ์•ฑ ์Šคํ† ์–ด ์‹ฌ์‚ฌ๋ฅผ ๊ฑฐ์น˜๋Š” ๋„ค์ดํ‹ฐ๋ธŒ ์•ฑ ๋ฐฉํ–ฅ์œผ๋กœ ๋ณ€๊ฒฝํ•˜๊ฒŒ ๋  ๊ฐ€๋Šฅ์„ฑ๋„ ์žˆ์Šต๋‹ˆ๋‹ค. PWA๋Š” ์™„๋ฒฝํ•œ ํ•ด๊ฒฐ์ฑ…์ด๋ผ๊ธฐ๋ณด๋‹ค๋Š” ํ˜„์žฌ ์ƒํ™ฉ์—์„œ์˜ ์ ์ ˆํ•œ ํƒ€ํ˜‘์ ์ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

์ด๋ฒˆ PWA ๋„์ž… ๊ณผ์ •์€ ๊ธฐ์ˆ ์  ์ œ์•ฝ ์†์—์„œ ์ฐฝ์˜์ ์ธ ํ•ด๊ฒฐ์ฑ…์„ ์ฐพ์•„๊ฐ€๋Š” ์—ฌ์ •์ด์—ˆ์Šต๋‹ˆ๋‹ค. ์™„๋ฒฝํ•œ ์†”๋ฃจ์…˜์€ ์•„๋‹ˆ์ง€๋งŒ, ํ˜„์žฌ ์ƒํ™ฉ์—์„œ ์ตœ์„ ์˜ ์„ ํƒ์„ ํ•˜๊ธฐ ์œ„ํ•œ ํƒ์ƒ‰ ๊ณผ์ •์ด์—ˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ์•ž์œผ๋กœ์˜ ๋ฐœ์ „ ๊ณผ์ •๋„ ๊ธฐํšŒ๊ฐ€ ๋˜๋ฉด ๊ณต์œ ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

profile
์•ˆ๋…•ํ•˜์„ธ์š” ๐Ÿ˜š

0๊ฐœ์˜ ๋Œ“๊ธ€