GitAnimals ํ๋ก์ ํธ๋ฅผ ์งํํ๋ฉด์ ํ ๊ฐ์ง ๊ณ ๋ฏผ์ด ์์์ต๋๋ค. ์ด ์๋น์ค๋ ๊นํ๋ธ ์ปค๋ฐ์ ํตํด ํฌ์ธํธ๋ฅผ ์ป๊ณ ๊ทธ ํฌ์ธํธ๋ก ํซ์ ๋ฝ์ ํค์ฐ๋ ์๋น์ค์ธ๋ฐ์, ์ผํ์ฉ์ฑ ์ ๊ทผ์ด ์๋ ์ฌ์ฉ์ ์ฐธ์ฌ๊ฐ ์ง์์ ์ผ๋ก ์ด๋ฃจ์ด์ง๋๋ก ํ๊ณ ์ถ์์ด์. ๋ ๋์ ์ฌ์ฉ์ ๊ฒฝํ๊ณผ ์ ๊ทผ์ฑ์ ์ํด ์ฑ ํํ๋ก ์ ๊ณตํ๋ ๊ฒ์ ๊ณ ๋ คํ๊ฒ ๋์์ต๋๋ค.
์ฒ์์๋ RN์ ์ด์ฉํ ์น ์ฑ ๊ฐ๋ฐ์ ๊ณ ๋ คํ์ง๋ง, ๋ช ๊ฐ์ง ํ์ค์ ์ธ ์ ์ฝ์ด ์์์ต๋๋ค. ๐ค
์ด๋ฌํ ๊ณ ๋ฏผ ์์์ "๊ผญ ์ฑ์ด์ด์ผ ํ ๊น?"๋ผ๋ ์ง๋ฌธ์ ํ๊ฒ ๋์๊ณ , ๊ทธ ๋์์ผ๋ก PWA(Progressive Web App)๋ฅผ ๋ฐ๊ฒฌํ๊ฒ ๋์์ต๋๋ค.
PWA๋ ์น ๊ธฐ์ ์ ์ฌ์ฉํ์ฌ ๊ฐ๋ฐ๋์ง๋ง ๋ค์ดํฐ๋ธ ์ฑ๊ณผ ์ ์ฌํ ์ฌ์ฉ์ ๊ฒฝํ์ ์ ๊ณตํ๋ ์น ์ ํ๋ฆฌ์ผ์ด์ ์ ๋๋ค. ์น์ฌ์ดํธ๋ฅผ ๋ชจ๋ฐ์ผ ๊ธฐ๊ธฐ์ ํ ํ๋ฉด์ ์ค์นํ ์ ์๊ณ , ์คํ๋ผ์ธ์์๋ ์๋ํ๋ฉฐ, ์ฌ์ง์ด ํธ์ ์๋ฆผ๊ณผ ๊ฐ์ ๋ค์ดํฐ๋ธ ์ฑ์ ์ฃผ์ ๊ธฐ๋ฅ๋ ํ์ฉํ ์ ์์ต๋๋ค.
์ด๋ฐ ๊ฐ๋ ฅํ ๊ธฐ๋ฅ๋ค์ ๋๋ถ๋ถ '์๋น์ค ์์ปค(Service Worker)'๋ผ๋ ๊ธฐ์ ๋๋ถ์ ๊ฐ๋ฅํฉ๋๋ค. ์น์ ์ ๊ทผ์ฑ๊ณผ ์ฑ์ ์ฌ์ฉ์ ๊ฒฝํ์ ๊ฒฐํฉํ ํ์ด๋ธ๋ฆฌ๋ ์ ๊ทผ ๋ฐฉ์์ด๋ผ๊ณ ์๊ฐํ๋ฉด ์ดํดํ๊ธฐ ์ฌ์ธ ๊ฒ ๊ฐ์ต๋๋ค.
์๋น์ค ์์ปค๋?
PWA์ ํต์ฌ ๊ธฐ์ ์ธ ์๋น์ค ์์ปค๋ ์น ํ์ด์ง์ ๋ธ๋ผ์ฐ์ ์ฌ์ด์์ ๋์ํ๋ JavaScript ํ์ผ์ ๋๋ค. ๋คํธ์ํฌ ์์ฒญ์ ๊ฐ๋ก์ฑ๊ณ ์บ์ฑ ์ ๋ต์ ์ ์ฉํ์ฌ ์คํ๋ผ์ธ ์๋, ์ฑ๋ฅ ํฅ์, ๋ฐฑ๊ทธ๋ผ์ด๋ ๋๊ธฐํ, ํธ์ ์๋ฆผ ๋ฑ์ ๊ธฐ๋ฅ์ ๊ฐ๋ฅํ๊ฒ ํฉ๋๋ค. ์๋น์ค ์์ปค ๋๋ถ์ ์น์ฌ์ดํธ๊ฐ ์ฑ์ฒ๋ผ ๋์ํ ์ ์๋ ๊ฒ์ด์ฃ !
์ฒ์ PWA ๊ฐ๋ ์ ์ ํ์ ๋๋ ์๊ตฌ์ฌ์ด ๋ค์์ง๋ง, ์์๋ณผ์๋ก ์ค์ฉ์ ์ธ ๊ธฐ์ ์ด๋ผ๋ ์๊ฐ์ด ๋ค์์ต๋๋ค. ํนํ ์ฑ ์คํ ์ด์ ์ฌ์ฌ ๊ณผ์ ์์ด๋ ์ฑ๊ณผ ๊ฐ์ ๊ฒฝํ์ ์ ๊ณตํ ์ ์๋ค๋ ์ ์ด ๋งค๋ ฅ์ ์ด์์ต๋๋ค.
PWA๋ฅผ ๊ฒํ ํ๋ฉด์ ๊ฐ์ฅ ๋๋ ธ๋ ์ฅ์ ๋ค์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
์ด๋ฐ ์ฅ์ ๋ค์ด GitAnimals ํ๋ก์ ํธ์ ํ์ฌ ์ํฉ๊ณผ ๋ฑ ๋ง๋ ๊ฒ ๊ฐ์ PWA ์ ์ฉ์ ๊ฒฐ์ ํ์ต๋๋ค.
Gitaninmals๋ Next.js App router ํ๊ฒฝ์ผ๋ก ์ด๋ฃจ์ด์ ธ์๋ ์๋น์ค์ ๋๋ค. Next.js๋ก ๊ฐ๋ฐ๋ ํ๋ก์ ํธ์ PWA๋ฅผ ์ ์ฉํ๋ ๊ณผ์ ์ ๊ณต์ ํด๋ณด๋ ค๊ณ ํฉ๋๋ค.
์ฒซ ๋จ๊ณ๋ ๊ฐ๋จํ์ต๋๋ค. next-pwa
ํจํค์ง๋ฅผ ์ค์นํ๋ ๊ฒ์ด์์ฃ .
npm install next-pwa
์ด ํจํค์ง๋ Next.js ํ๋ก์ ํธ์ PWA๋ฅผ ์์ฝ๊ฒ ์ ์ฉํ ์ ์๊ฒ ํด์ค๋๋ค. ์ฒ์์๋ ์ง์ ์๋น์ค ์์ปค๋ฅผ ๊ตฌํํด์ผ ํ๋ ๊ฑฑ์ ํ๋๋ฐ, ์ด ํจํค์ง ๋๋ถ์ ๋ง์ ๋ถ๋ถ์ด ์๋ํ๋์ด ํธ๋ฆฌํ์ต๋๋ค.
๋ค์์ผ๋ก 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'
์ต์
์ ์ถ๊ฐํ์ต๋๋ค.
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
์ด๋ฒคํธ๋ฅผ ๊ฐ์งํ๋ ๋ถ๋ถ์
๋๋ค. ๋ธ๋ผ์ฐ์ ๊ฐ "์ด ์ฌ์ดํธ๋ ์ค์น ๊ฐ๋ฅํฉ๋๋ค"๋ผ๊ณ ํ๋จํ ๋ ์ด ์ด๋ฒคํธ๊ฐ ๋ฐ์ํ๊ณ , ์ด๋ ์ฌ์ฉ์์๊ฒ ๋ฐฐ๋๋ฅผ ๋ณด์ฌ์ฃผ๋ ๋ฐฉ์์ผ๋ก ๊ตฌํํ์ต๋๋ค.
๋จผ์ ์ค์น ์๋ด ๋ฐฐ๋๋ฅผ ๋ง๋ ํ, ๊ณง๋ฐ๋ก ๋ ํฐ ๋ฌธ์ ๋ฅผ ๋ฐ๊ฒฌํ์ต๋๋ค. 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 ๋์ ๊ณผ์ ์ ๊ธฐ์ ์ ์ ์ฝ ์์์ ์ฐฝ์์ ์ธ ํด๊ฒฐ์ฑ ์ ์ฐพ์๊ฐ๋ ์ฌ์ ์ด์์ต๋๋ค. ์๋ฒฝํ ์๋ฃจ์ ์ ์๋์ง๋ง, ํ์ฌ ์ํฉ์์ ์ต์ ์ ์ ํ์ ํ๊ธฐ ์ํ ํ์ ๊ณผ์ ์ด์๋ค๊ณ ์๊ฐํฉ๋๋ค. ์์ผ๋ก์ ๋ฐ์ ๊ณผ์ ๋ ๊ธฐํ๊ฐ ๋๋ฉด ๊ณต์ ํ๊ฒ ์ต๋๋ค.