FrontEnd Roadmap 06 - 내가 궁금한 모음집(쿠키(cookies), PWA, Web Components)

SANGHYUN KIM·2025년 2월 16일
0

frontend-roadmap

목록 보기
6/9

MDN의 “Using HTTP Cookies”를 기반으로 작성되었습니다.

HTTP에서 cookie를 다루지 못 했다.
그래서 지금이라도 어떤 것인지, 어떻게 만들어 졌는지, 지금은 어떻게 쓰이는 지 알아본다.

A-1. Cookie의 필요성

HTTP통신은 무상태성(stateless)을 띈다.
무상태성이란 “서버가 클라이언트의 이전 요청 상태를 기억하지 못 한다”을 뜻한다.

그러면 왜 서버는 무상태성을 택했을까? 찾을 수는 없었지만 GPT와 대화를 통해서 무상태성을 가지게 되면서 다음 3가지 장점을 얻었다.

  • 서버 자원 효율성: 서버가 클라이언트 상태를 저장하지 않음으로써 서버 부하 경감
  • 확장성: 클라이언트의 상태를 기억할 필요가 없으므로 손쉽게 새로운 서버를 증설하여 요청 처리 가능
  • 단순성: 각 요청이 연관되어 있으면 복잡한 상태 로직이 들어가지만 요청이 독립적이므로 프로토콜의 설계와 구현이 단순

그래서 클라이언트의 상태를 전달받아야 했고 이를 보완하기 위해 cookie라는 저장소가 개발되었고 처음 용도는 사용자가 Netscape 페이지 “방문 여부 확인”을 체크하는 거였다.

A-2. Cookie의 특징

Cookie는 아래와 같이 설정을 포함해서 전달된다.

Set-Cookie: session_id=abc123; HttpOnly; Secure; Path=/
// cookie의 값은 session_id라는 key와 abc123이라는 value
// HttpOnly 및 Secure라는 보안 옵션
// path는 다음 위치에서 cookie 전송을 의미. 현재는 root 하위 모든 곳에서 전달
// 만약 /dashboard 하위에서만 cookie를 전송하고 싶으면 Path=/dashboard 설정

그리고 아래와 같은 기본적인 특징을 가지고 있다.

  • 저장위치: 클라이언트 브라우저
  • 전송: 요청마다 자동 전송
  • 크기: 4kb
  • 보안 옵션: HttpOnly, Secure, SameSite 지원
  • 사용용도: 웹 애플리케이션에서 사용자와 그들의 인증된 세션을 식별하기 위해 사용

A-2-1. 보안옵션(HttpOnly, Secure, SameSite)

A-2-1-1. HttpOnly

HttpOnly 옵션을 사용하면 cookie는 JavaScript로 접근할 수 없지만, 요청마다 자동으로 포함된다.
반대로 설정이 되어 있지 않다면 다음과 같은 코드로 cookie의 정보를 확인할 수 있다.

console.log(document.cookie)
// '_ga_tag=tag값; preferredlocale=ko;'
A-2-1-2. Secure

Secure 옵션은 오직 HTTPS 요청에만 전송될 수 있게 해주는 옵션이다. 그러나 HttpOnly 속성이 없다면 JavaScript로 여전히 접근이 가능하다

A-2-1-3. SameSite

SameSite 옵션은 cross-site 요청과 함께 전송되지 않게 만들어줘서 CSRF에 어느정도 방어를 할 수 있게 해준다.
SameSite 옵션은 총 3가지(Strict, Lax, None)로 나누어진다.

속성StrictLax(미설정 시 Chrome의 기본값)None
크로스 사이트 요청❌ 쿠키 전송 안됨✅ 링크 클릭 시 쿠키 전송됨✅ 모두 허용
POST 요청에서 쿠키 전송❌ 불가능❌ 불가능✅ 모두 허용
GET 요청에서 쿠키 전송❌ 불가능✅ 링크 클릭 후 이동 시 가능✅ 모두 허용
비고로그인 유지, 민감한 세션 데이터파트너 링크 추적, 기본적인 보안None으로 설정된 쿠기는 보안을 위해서 Secure 지정 필수
속성설명예제
Domain쿠키를 적용할 도메인을 지정Domain=example.com이면 example.comsub.example.com에서 유효
Path쿠키를 적용할 URL 경로를 지정Path=/docs이면 /docs/ 이하의 경로에서만 유효

A-3. Cookie의 동작방식

먼저 서버에서 클라이언트로 HTTP header에 cookie 정보를 담아서 클라이언트로 전달한다

HTTP/1.1 200 OK
Set-Cookie: session_id=abc123; Path=/; HttpOnly; Secure

이후 클라이언트의 모든 요청에는 cookie정보가 담긴 채로 서버로 전달된다

GET /dashboard HTTP/1.1
Host: example.com
Cookie: session_id=abc123

B. Progresive Web Apps(PWA)

많은 블로그글들의 제목을 통해서 눈에는 익었지만 정확히 어떤 것인 지 몰라서 이번 기회에 정리해본다.

B-1. PWA란?

B-1-1. 웹과 앱간의 경험적 차이

네이티브 앱은 “소장하는 경험”을 주면서 아래 장점을 제공한다.

  • 쉬운 접근성: 홈 화면에 아이콘이 보이고 클릭만 하면 접근
  • 오프라인 및 백그라운드 실행: 사용자가 화면을 보고 있거나 상호작용을 하고 있지 않더라도 기기 내부에서 동작 (예: 채팅앱의 메세지)
  • 세 번째로 전용 UI(Dedicated UI) 및 OS 통합성: 독자적인 UI도 가질 수 있으면서 host OS의 기능 및 디자인을 그대로 활용가능 (예: 카메라, GPS 기능 활용)
  • 앱 스토어 통합성: 앱 스토에서 언제든지 찾을 수 있으며 관리 용이

웹사이트는 브라우저를 통해서 “방문하는 장소”라는 경험을 주면서 아래 장점을 제공한다.

  • single codebase: 애플리케이션은 각자 제공하는 SDK에 부합하는 언어로 작성을 해야 하지만 웹사이트는 어느 기기에서든 사용 가능
  • 웹을 통한 배포: 검색엔진을 통해서 검색되고 URL 공유가 가능하며 앱 스토어 없이도 접근 가능

B-1-2. PWA가 주고자 하는 경험

MDN을 인용하자면 “웹 플렛폼 기술로 만들어졌지만 네이티브 앱(platform-specific apps) 경험을 제공하는 앱”이라고 한다. 즉, PWA는 설치 가능하면서도, 네이티브 앱처럼 강력한 기능을 갖춘 웹 애플리케이션이다.

두 개의 platform을 활용하기에 다양한 장점이 있지만 가장 큰 3가지 핵심요소(web.dev의 The three pillars of PWA design)는 아래와 같다.

핵심 요소설명예제
Capable (유능함)네이티브 앱과 유사한 기능 제공(계속 기능 추가 중)WebRTC(화상통화), 푸시 알림, WebAssembly
Reliable (안정성)빠른 로드와 오프라인에서도 실행 가능서비스 워커를 이용한 캐싱 데이터 활용
Installable (설치 가능)홈 화면에 앱 추가 가능OS의 앱 전환기 및 단축키 사용 가능

B-2. PWA 구성요소

PWA는 기본적으로 웹사이트이다. 웹사이트를 구성하는 모든 것이 필요하며 그 외 추가적인 것을 알아본다.

B-2-1. 웹페이지(웹앱) 구성요소(필수 요소)

웹 페이지이기에 HTML, CSS, JS는 필수이다.

B-2-2. Web App Manifest(필수 요소)

PWA를 다운받을 수 있게 해주고 앱과 같은 프레임을 가질 수 있게 해주는 필수적인 요소이다.
그리고 manifest에는 브라우저가 설치가 가능할 수 있게 충분한 정보를 제공해줘야 한다.

index.html 상위 내에 manifest의 경로를 기재를 해주며, 멀티 페이지 앱이라면 모든 html 내부에 기재를 해줘야 한다.


<!doctype html>
<html lang="en">
  <head>
    <link rel="manifest" href="manifest.json" />
    <!-- ... -->
  </head>
  <body></body>
</html>

Manifest는 JSON format으로 작성이 되며 형태는 아래와 같으며 이 중에 필수 적인 것은 아래와 같다.

{
  "short_name": "MDN", // 앱 이름 표기 공간이 적을 시 표출될 이름
  "name": "MDN Web Docs", // 설치될 앱의 이름
  "icons": [
   // 앱 아이콘으로 192px 및 512px 두 개의 사진 필수
    {
      "src": "/favicon-192x192.png",
      "sizes": "192x192",
      "type": "image/png"
    },
    {
      "src": "/favicon-512x512.png",
      "sizes": "512x512",
      "type": "image/png"
    }
  ],
  "start_url": ".", // 엡 시동 시 처음 시작할 url을 지정
  "display": "standalone", // 앱 시동 시 디스플레이 설정. 현재는 앱과 같은 별개의 창인 standalone
  "theme_color": "#000000",
  "background_color": "#ffffff"
}
속성설명필수 여부
name앱의 전체 이름✅ 필수
short_name축약된 앱 이름 (UI 공간 부족 시 사용)✅ 필수
icons앱 아이콘 (최소 192x192, 512x512 필요)✅ 필수
start_url앱 실행 시 시작할 URL✅ 필수
display실행 방식 (standalone, fullscreen, etc.)✅ 필수
theme_colorUI의 기본 색상⛔ 선택
background_color초기 로딩 화면 배경색⛔ 선택

정보가 전부 적혀 있다면 아래와 같은 설치 아이콘이 브라우저 검색창(URL) 노출이 된다.

PWA-download icon

B-2-3. HTTPS(필수 요소)

PWA가 설치가능하려면 필요한 요소 중 하나다. 그리고 MDN에 다음과 같은 문장을 발견했다.

“file:// URL에서 로드된 리소스를 안전한 것으로 간주하는 보안 컨텍스트보다 더 엄격한 요구 사항”
”This is a more stringent requirement than secure context, which considers resources loaded from file:// URLs to be secure”
MDN - “Making PWAs installable”

이 부에 대해서는 자세한 내역이나 검색 항목이 없기에 GPT의 도움을 받았다.

1️⃣ Secure Context(보안 컨텍스트)란?

웹 브라우저가 “이 사이트는 보안이 잘 유지되고 있다”고 판단하는 기준이야.

보안 컨텍스트에서는 일부 보안이 중요한 웹 API를 사용할 수 있어.

예를 들어, 웹캠, 마이크, 서비스 워커, 푸시 알림 같은 기능은 보안 컨텍스트에서만 작동해.

“보안 컨텍스트(Secure Context)“의 기본 조건

🔹 HTTPS에서 실행된 웹사이트 → ✅ 안전

🔹 localhost에서 실행된 웹사이트 → ✅ 안전

🔹 file://에서 실행된 로컬 파일 → ✅ 안전 (일반적으로)

📌 즉, 일반적인 보안 기준에서는 file://도 보안 컨텍스트로 인정됨.

2️⃣ file:// URL은 뭐야?

file://은 인터넷을 통해 접속하는 게 아니라, 내 컴퓨터에 있는 파일을 직접 여는 방식이야.

예를 들어, 컴퓨터에 저장된 HTML 파일을 직접 열면 브라우저 주소창에 file://C:/Users/.../index.html 같은 주소가 나옴.

이 방식은 보안 위협이 적다고 간주되기 때문에, 일반적인 “보안 컨텍스트”에서는 허용됨.

📌 즉, 보통 웹에서는 file://도 안전한 환경으로 취급함.

3️⃣ 그런데, PWA는 왜 file://을 안전하지 않다고 보는 거야?

PWA는 설치 가능한 웹앱이기 때문에, 일반 웹사이트보다 더 높은 보안 기준을 요구해.

🔹 “보안 컨텍스트”보다 PWA 보안 기준이 더 엄격한 이유

• PWA는 일반 웹사이트가 아니라, 앱처럼 기기에 설치되는 형태이기 때문.

→ 즉, “네이티브 앱처럼 실행되는 프로그램”이라 더 엄격한 보안 기준이 필요해.

• file://에서 실행되면, 원격 서버가 아니라 내 PC의 파일을 실행하는 거라 신뢰할 수 없는 소스일 가능성이 있음.

→ 예를 들어, file:// 환경에서는 누군가가 내 PC에 악성 파일을 심어놓고 실행할 수도 있음.

• 만약 file://에서 PWA가 설치 가능하다면, 악성 코드가 포함된 PWA가 쉽게 실행될 수 있음.

📌 즉, PWA는 “보안 컨텍스트”보다 더 강한 보안 기준을 요구하기 때문에 file://은 안전하지 않다고 판단함.

요약하자면, PWA는 더 강한 보안 기준을 요구하기에 평소 안전하다고 생각하는 local 파일의 실행도 제한한다는 거다.

그러면 PWA에서 보안이 왜 더 중요하게 보는 것일까?
다운로드는 무언가를 받고 사용자 환경에 설치되는 프로그램들이다. 이 프로그램들이 사용자의 정보에 접근하고 공격할 수 있다. 기존 웹과는 다르게 PWA가 앱의 특성도 가지고 있기에 더 엄격한 보안 기준을 가진다고 볼 수 있다.

B-2-4. Service Worker(옵션)

service worker overview

서비스 워커는 웹 워커 중 하나로써 웹 페이지와 네트워크 중간에서 proxy와 같은 역할을 해준다.
이들은 중간에 네트워커 요청을 중간에 가로채고 캐시에 접근 후 요청을 어떻게 처리할 지 판단한다. 또한, 브라우저가 오픈되어 있지 않아도 백그라운드에서 돌아가기에 PWA를 조금 더 네이티브 앱과 같은 경험을 가질 수 있게 해준다. 더 다양한 기능은 web.dev의 “Capabilities”를 참조하면 된다.

서비스워커는 다음과 같은 특징이 있다.

  • 스코프(scope):
    • 서비스 워커가 등록된 그 페이지 경로를 포함하여 하위에 전부 반영
    • 각 스코프마다 서비스 워커는 하나만 등록
    • FetchEvent를 통해 범위 내부의 모든 네트워크 요청을 가로채기 가능
  • 라이프사이클
    • 서비스워커가 등록되는 시점부터 시작(PWA의 시작과 다를 수 있음)
    • 등록된 순간부터 자동으루 수행이되며 별도의 쓰레드에서 수행
    • 각 브라우저마다 다르지만 비활동이 몇초 지속되면 꺼지고, 다시 이벤트 발생 시 활동을 다시 시작

또한, 서비스워커를 통하여 어떻게 캐싱을 하는지(web.dev의 “Caching”), 요청값을 캐싱에서 불러올 지 네트워크로 연결(web.dev의 “Serving”)할 지는 각각 링크에서 더 확인할 수 있다.

이런 강력한 기능을 제공해도 23년 통계를 확인했을 때 37%의 PWA만 서비스워커를 사용 중이다.

C. Web Components

웹 컴포넌트는 “기능을 나머지 코드로부터 캡슐화하여 재사용 가능한 커스텀 엘리먼트를 생성하고 웹 앱에서 활용할 수 있도록 해주는 다양한 기술들의 모음”이라고 한다.
MDN 기준으로 custom elements, shadow DOM, HTML templates로 총 3개로 분류한다.
(www.webcomponents.org에서는 ES Module을 추가하여 총 4개로 분류한다)

C-1. Custom Elements

Custom elements에도 두 가지 타입이 있다.

  • Customized build-in elements: 기존 HTML tag에 기본 동작을 변형시키는 방식
    • 예) <p>태그에 어떤 기능을 추가
    • 그러나 iOS 진영(Safari 및 iOS Webview 환경)에서는 정의 불가능
  • Autonomous custom elements: 유저가 정의하는 HTML tag를 만드는 방식
    • 예) <custom-button>이라는 새로운 tag를 개발

두 방식 모두 아래와 같이 Class를 확장시키는 방식으로 정의를 한다

// Customized build-in elements
class WordCount extends HTMLParagraphElement {
  constructor() {
    super();
  }
  // Element functionality written in here
}

// Autonomous custom elements
class PopupInfo extends HTMLElement {
  constructor() {
    super();
  }
  // Element functionality written in here
}

C-1-1. Custom Elements에 대한 내 생각

개인적으로 vanilla 개발을 하거나, UI 라이브러리를 만들지 않는 이상 사용하지는 않을 것 같을 것 같다. GPT는 Safari가 Customized build-in elements을 지원하지 않기에 Autonomous custom elements를 추천하길 원하지만 프론트엔드에서 컴포넌트 단위로 개발을 주로 하기에 많이 쓰일 것 같지는 않다.

C-2. Shadow DOM

DOM트리에 영향을 주지 않고 독립적인 구조, 스타일, 이벤트를 가질 수 있게 해주는 DOM 트리를 생성하는 기술이라고 한다.

아래와 같은 형태로 표현되며 단어는 다음과 같다

shadow-dom overview

  • shadow host: shadow DOM이 연결될 DOM node
  • shadow tree: shadow DOM 내부의 DOM tree
  • shadow boundary: shadow DOM이 끝나면서 DOM이 시작되는 지점
  • shadow root: shadow tree의 root node

C-2-1. Shadow DOM 만들어보기

// HTML
<div id="host"></div>
<span>I'm not in the shadow DOM</span>

// JS
const host = document.querySelector("#host");
const shadow = host.attachShadow({ mode: "open" });
const span = document.createElement("span");
span.textContent = "I'm in the shadow DOM";
shadow.appendChild(span);

위와 같이 원하는 node를 선택하고 shadow Tree를 코드로 생성하고 attachShadow를 통하여 붙일 수 있다.

캡슐화 되어 있는 트리에 JS로 접근을 하려면 attachShadow({ mode: "open" });와 같이 open을 설정하면 페이지에서 아래와 같이도 접근할 수 있다. 만약 접근을 원하지 않는다면  {mode: "closed"}로 설정하면 된다

// HTML
<div id="host"></div>
<span>I'm not in the shadow DOM</span>
<br />

<button id="upper" type="button">Uppercase shadow DOM span elements</button>
<button id="reload" type="button">Reload</button>

// JS
const host = document.querySelector("#host");
const shadow = host.attachShadow({ mode: "open" });
const span = document.createElement("span");
span.textContent = "I'm in the shadow DOM";
shadow.appendChild(span);

const upper = document.querySelector("button#upper");
upper.addEventListener("click", () => {
  const spans = Array.from(host.shadowRoot.querySelectorAll("span"));
  for (const span of spans) {
    span.textContent = span.textContent.toUpperCase();
  }
});

const reload = document.querySelector("#reload");
reload.addEventListener("click", () => document.location.reload());

아래 질문들은 GPT와 같이 공부하면서 얻은 질문들입니다

C-2-1-Q1. shadow DOM은 SEO에 걸릴까?

결론부터 말하자면 SEO에 걸리지 않는다.
왜냐하면 shadow DOM은 HTML 내부에 숨겨져 있으며 검색엔진이 찾지 못하기 때문이다.

따라서, 만약에 SEO가 필요한 값이라면 shadow DOM을 사용하는 것은 추천하지 않는다

C-2-1-Q2. mode의 open과 closed는 언제 사용하는 것이 좋을까?

결론부터 말하자면 open은 외부에서 컨트롤이 가능하기에 보안이 필요 없는 것에 사용하고 closed는 보안에 필요한 것에 사용하면 된다.

“C-2-1. Shadow DOM 만들어보기”에서 봤던 코드를 다시 보면 open으로 설정 시 page 내부 JS에서 접근이 가능하다. 이를 통해서 다른 사용자가 구조를 수정하고 확장할 수 있을 때 유용할 것이다.

그러나, 접근을 하지 않게 만드려면 closed를 사용하면 된다.

C-2-2. shadow DOM 사례

실제로 어느 부분에서 적용되고 우리가 혜택을 받고 있는 지 궁금해서 찾아봤다.

input 태그에 type=”rage”을 적용시키면 아래와 같이 나오며 slider가 shadow DOM으로 작성된 것을 알 수 있다.

input type ragne

shadow DOM에 대한 정보를 보고 싶으면 chrome developer tools의 설정에서 Preference 탭 아래 Elements 그룹 하위에 “Show user agent shadow DOM”을 클릭하면 아래와 같이 DOM tree 내부에서 볼 수 있다.

shadow DOM on chrome dev tools

<input />이외에도 video의 버튼이나 슬라이더, <select /><option/> 또한 shadow DOM을 활용하여 만들어진 tag들이다

C-3. Templates

이 기술은 반복되는 markup을 표현하기 위해서 사용되는 기술이다.
<template>을 활용하여 작성할 수 있고 DOM에 렌더링 되지는 않지만 JS의 참조를 통해서 화면에 노출된다.

아래 MDN의 예제를 보면 활용법을 바로 알 수 있다.

// HTML
<template id="custom-paragraph">
  <p>My paragraph</p>
</template>

// JS
let template = document.getElementById("custom-paragraph");
let templateContent = template.content;
document.body.appendChild(templateContent);

추가적으로 <slot />이라는 tag가 있는데 <template />와는 다르게 web components 내부에 동적으로 추가할 수 있는 공간을 만들어 놓는다고 한다.

<template /><slot />을 비교하자면 아래와 같다.

비교 항목templateslot
역할미리 정의된 정적 HTML을 DOM에 동적으로 삽입컴포넌트 내부에서 동적 콘텐츠를 삽입할 자리
렌더링 여부초기에는 렌더링되지 않음 (스크립트로 추가해야 함)부모 요소에서 삽입하면 자동으로 반영
사용 위치HTML 어디서든 사용 가능웹 컴포넌트 내부에서만 사용 가능
주요 사용 예템플릿을 미리 정의하고 필요할 때 복제하여 사용웹 컴포넌트의 유연성을 높이기 위해 동적 콘텐츠 추가
<my-card>
  <h2 slot="title">동적으로 넣을 제목</h2>
  <p slot="content">이 내용은 slot을 통해 들어감</p>
</my-card>

<script>
  class MyCard extends HTMLElement {
    constructor() {
      super();
      const shadow = this.attachShadow({ mode: "open" });

      shadow.innerHTML = `
        <style>
          .card { border: 1px solid #ddd; padding: 10px; }
        </style>
        <div class="card">
          <slot name="title"></slot>  <!-- 동적 콘텐츠 삽입 공간 -->
          <slot name="content"></slot> <!-- 동적 콘텐츠 삽입 공간 -->
        </div>
      `;
    }
  }

  customElements.define("my-card", MyCard);
</script>

참조

Cookie

Using HTTP cookies - HTTP | MDN

Help And Training Community

SameSite 쿠키 설명  |  Articles  |  web.dev

PWA

Progressive web apps | MDN

Making PWAs installable - Progressive web apps | MDN

Service workers  |  web.dev

Web Components

Using custom elements - Web APIs | MDN

Using shadow DOM - Web APIs | MDN

HTML <input type=

Using templates and slots - Web APIs | MDN

profile
꾸준히 공부하자

0개의 댓글