Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
100 changes: 100 additions & 0 deletions keyword/chapter04/authentication-authorization.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
# <strong>인증(Authentication)</strong>과 <strong>인가(Authorization)</strong>

## 두 용어의 차이

- <strong>인증(Authentication)</strong>과 <strong>인가(Authorization)</strong>는 비슷해 보이나 역할이 다름
- <strong>인증</strong>은 <strong>누구인지 확인</strong>하는 과정임
- <strong>인가</strong>는 <strong>무엇을 할 수 있는지 결정</strong>하는 과정임
- 일반적으로 <strong>인증 → 인가</strong> 순서로 흐름이 이어짐

---

## 인증(Authentication)

### 인증이란

- <strong>인증</strong>은 <strong>사용자의 신원이 주장과 일치하는지 확인</strong>하는 절차임
- 웹 서비스에 접속한 사람이 실제로 그 계정의 소유자인지 검증하는 단계에 해당함
- 이 과정이 없으면 타인이 관리자를 사칭하거나 계정을 도용할 수 있음

### 인증 방법의 예시

1. <strong>아이디와 비밀번호</strong>
사용자가 입력한 자격 증명이 서버·DB에 저장된 값과 일치하는지 확인함

2. <strong>소셜 로그인(OAuth 2.0)</strong>
<a href="https://datatracker.ietf.org/doc/html/rfc6749">RFC 6749</a>에 정의된 위임·토큰 발급 흐름을 쓰는 방식임. 외부 인가 서버가 사용자 동의 하에 클라이언트에 액세스 토큰 등을 넘김

3. <strong>다단계 인증(MFA)</strong>
비밀번호 외 OTP·기기 등 추가 요소로 신원을 재확인함

4. <strong>생체 인증</strong>
지문·얼굴 인식 등 기기·플랫폼 API 수준에서 신원을 확인함

### 프론트엔드에서의 위치

- React 등 클라이언트에서는 <strong>로그인 UI</strong>를 통해 자격 증명을 수집하고 서버에 전달함
- 서버가 검증에 성공하면 <strong>세션 식별자</strong> 또는 <strong>토큰(JWT 등)</strong> 같은 <strong>인증 증표</strong>를 발급하는 경우가 많음
- 이후 요청에서 그 증표를 통해 <strong>이미 인증된 사용자</strong>임을 입증함

---

## 인가(Authorization)

### 인가란

- <strong>인가</strong>는 인증 이후 <strong>해당 주체가 특정 리소스·기능에 접근할 권한이 있는지 판단</strong>하는 과정임
- 인증이 <strong>신원 확인</strong>이라면, 인가는 <strong>역할·정책에 따른 허용 범위 결정</strong>에 가깝음

### 인가 방식의 예시

1. <strong>역할 기반(RBAC)</strong>
역할 단위로 허용 동작을 구분함

2. <strong>속성 기반(ABAC)</strong>
속성에 따라 접근을 제한함

3. <strong>정책 기반</strong>
시간·위치·기기 등 조건을 조합해 접근을 제어함

### 프론트엔드에서의 위치

- <strong>라우트 가드</strong>나 <strong>조건부 렌더링</strong>으로 권한 없는 페이지 접근을 막거나 안내 화면을 보여줄 수 있음
- 최종 판단은 <strong>항상 서버</strong>에서 수행해야 하며, 클라이언트 제어는 UX·노출 최소화용으로만 사용함

---

## 인증과 인가 비교

| 구분 | 인증(Authentication) | 인가(Authorization) |
| --- | --- | --- |
| 질문 | 누구인가 | 무엇을 할 수 있는가 |
| 순서 | 먼저 수행 | 인증 이후 수행 |
| 목적 | 신원 확인 | 접근·기능 허용 여부 결정 |
| 실패 시(HTTP, 관례) | <code>401 Unauthorized</code> | <code>403 Forbidden</code> |
| 예시 | 로그인 폼에서 자격 증명 검증 | 관리자 전용 API·페이지 접근 검사 |

HTTP 상태 코드 의미는 <a href="https://www.rfc-editor.org/rfc/rfc9110.html">RFC 9110</a> 및 아래 MDN 문서와 함께 보면 됨

---

## 흐름 도식

```mermaid
graph TD
A["사용자 요청 (로그인 시도)"] --> B{"인증 (Authentication)"}
B -->|실패| E["401 Unauthorized"]
B -->|성공| C{"인가 (Authorization)"}
C -->|권한 없음| F["403 Forbidden"]
C -->|권한 있음| D["정상 처리 · 리소스 접근"]
```

---

## 참고 자료

- <a href="https://developer.mozilla.org/ko/docs/Web/HTTP/Reference/Status/401">MDN — 401 Unauthorized</a>
- <a href="https://developer.mozilla.org/ko/docs/Web/HTTP/Reference/Status/403">MDN — 403 Forbidden</a>
- <a href="https://developer.mozilla.org/ko/docs/Web/HTTP/Reference/Status">MDN — HTTP 응답 상태 코드</a>
- <a href="https://www.rfc-editor.org/rfc/rfc9110.html">RFC 9110 — HTTP Semantics</a>
- <a href="https://datatracker.ietf.org/doc/html/rfc6749">RFC 6749 — OAuth 2.0</a>
167 changes: 167 additions & 0 deletions keyword/chapter04/client-storage-strategy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
# 클라이언트 저장소 전략

## 개요

- 로그인 후 발급된 <strong>토큰·세션 식별자</strong> 등을 <strong>어디에 둘지</strong>는 보안·UX·도메인·CORS 정책과 함께 결정해야 함
- 브라우저에서는 <strong>쿠키</strong>, <strong>localStorage</strong>, <strong>sessionStorage</strong>를 자주 비교함

---

## HTTP와 “상태”

- HTTP 자체는 요청마다 독립적인 메시지로 동작하는 <strong>무상태(stateless)</strong> 프로토콜로 설명됨
- “로그인 유지”는 서버가 세션을 두거나, 클라이언트가 토큰·쿠키를 들고 매 요청에 증표를 붙이는 식으로 <strong>응용 계층에서 상태를 모델링</strong>함
- 개념 정리: <a href="https://developer.mozilla.org/ko/docs/Web/HTTP/Guides/Overview#http은_상태는_없지만_세션은_있습니다">MDN — HTTP 개요(무상태와 세션)</a>

---

## 쿠키(Cookie)

### 특징

- 브라우저가 <strong>조건에 맞는 요청에 자동으로 전송</strong>할 수 있음
- <code>Domain</code>, <code>Path</code>, <code>Expires</code> / <code>Max-Age</code> 등으로 범위·수명을 제한함
- <code>HttpOnly</code>, <code>Secure</code>, <code>SameSite</code> 등 보안 관련 속성을 줄 수 있음

규격: <a href="https://datatracker.ietf.org/doc/html/rfc6265">RFC 6265</a>
설명: <a href="https://developer.mozilla.org/ko/docs/Web/HTTP/Cookies">MDN — HTTP 쿠키</a>

### 장점

- 자동 전송으로 클라이언트 코드가 단순해질 수 있음
- <code>HttpOnly</code>로 스크립트 접근을 막으면 XSS로 쿠키 문자열을 읽기 어렵게 할 수 있음

### 단점

- 자동 전송은 <strong>CSRF</strong> 대비(<code>SameSite</code>, CSRF 토큰, 의도한 메서드·Origin 검증 등)가 필요할 수 있음 — <a href="https://developer.mozilla.org/ko/docs/Glossary/CSRF">MDN — CSRF</a>

---

## localStorage

### 특징

- <a href="https://developer.mozilla.org/ko/docs/Web/API/Window/localStorage">MDN — Window.localStorage</a>에 따르면, 출처(origin) 단위로 데이터가 유지되는 저장소임
- <strong>요청 헤더에 자동으로 붙지 않음</strong> — 필요 시 스크립트가 읽어 <code>Authorization</code> 등에 넣어야 함

### 장점

- API가 단순하고(<code>setItem</code> / <code>getItem</code>) 용량이 쿠키보다 넉넉한 편임

### 단점

- 동일 출처 스크립트가 읽을 수 있어 <strong>XSS</strong> 시 토큰 유출 위험이 큼 — <a href="https://developer.mozilla.org/ko/docs/Web/Security/Attacks/XSS">MDN — XSS</a>

---

## sessionStorage

### 특징

- <a href="https://developer.mozilla.org/ko/docs/Web/API/Window/sessionStorage">MDN — Window.sessionStorage</a>에 따르면, 페이지 세션이 유지되는 동안만(탭 단위) 보관되는 저장소임
- API는 localStorage와 유사함

### 장점

- 탭을 닫으면 사라지므로 <strong>짧게만 유지</strong>할 값에 맞출 수 있음

### 단점

- “다음 방문 시에도 로그인 유지”에는 부적합한 경우가 많음
- 역시 스크립트 접근 가능 → XSS 위험은 남음

---

## 저장소 비교 표

| 저장소 | 자동 전송 | 수명 | HttpOnly 등 | 스크립트 접근 | CSRF 관점 |
| --- | --- | --- | --- | --- | --- |
| 쿠키 | 조건부 자동 | 속성으로 제어 | 가능 | HttpOnly 시 제한 | 자동 전송 시 주의 |
| localStorage | 없음 | 브라우저·출처 단위 지속 | 없음 | 가능 | 헤더 수동 첨부 시 패턴에 따름 |
| sessionStorage | 없음 | 탭/세션 단위 | 없음 | 가능 | 동일 |

※ 실무에서는 <strong>Refresh는 HttpOnly 쿠키</strong>, <strong>Access는 메모리</strong> 등 조합을 쓰는 경우가 많음(팀 보안 가이드 따름)

---

## 정리 과제(공식 문서 기준 답안 가이드)

### HTTP 무상태와 로그인 유지

1. <strong>HTTP가 무상태로 기술되는 이유</strong>
요청 간 연결 상태를 프로토콜이 강제하지 않아 서버 구현·캐싱·프록시가 단순해짐 — 위 MDN HTTP 개요 참고

2. <strong>무상태와 “사용자 상태”</strong>
연속된 사용자 맥락은 쿠키·세션 ID·Bearer 토큰 등으로 애플리케이션이 별도 설계함

3. <strong>쿠키 Domain</strong>
어떤 호스트에 쿠키를 보낼지 범위를 정함 — <a href="https://developer.mozilla.org/ko/docs/Web/HTTP/Reference/Headers/Set-Cookie#domaindomain-value">MDN — Set-Cookie / Domain</a>

4. <strong>쿠키 Path</strong>
URL 경로 prefix가 일치할 때만 전송되도록 제한 — <a href="https://developer.mozilla.org/ko/docs/Web/HTTP/Reference/Headers/Set-Cookie#pathpath-value">MDN — Set-Cookie / Path</a>

5. <strong>세션 쿠키 vs 지속 쿠키</strong>
<code>Max-Age</code>나 <code>Expires</code>가 없으면 세션 쿠키로 동작하는 것이 일반적임 — <a href="https://developer.mozilla.org/ko/docs/Web/HTTP/Cookies#define_the_lifetime_of_a_cookie">MDN — 쿠키 수명</a>

6. <strong>HttpOnly / Secure / SameSite</strong>
MDN <a href="https://developer.mozilla.org/ko/docs/Web/HTTP/Cookies#restrict_access_to_cookies">쿠키 제한</a> 및 <a href="https://developer.mozilla.org/ko/docs/Web/HTTP/Reference/Headers/Set-Cookie">Set-Cookie</a> 참고

7. <strong>쿠키만으로의 한계</strong>
크기 제한·스코프 규칙·비브라우저 클라이언트 등으로 토큰 헤더 전송·서버 세션과 병행하는 설계가 흔함

### XSS

1. <strong>XSS</strong>
신뢰되는 사이트 맥락에서 공격자 스크립트가 실행되게 만드는 취약점·공격 — MDN XSS 문서 참고

2. <strong>방어(요지)</strong>
출력 인코딩, <a href="https://developer.mozilla.org/ko/docs/Web/HTTP/Reference/Headers/Content-Security-Policy">CSP</a>, HttpOnly 쿠키 등 다층 방어

### 세션 하이재킹

1. <strong>의미</strong>
세션 토큰·쿠키·Bearer 토큰 등 <strong>인증 증표를 탈취</strong>해 사용자를 사칭하는 공격으로 이해하면 됨(용어는 보안 문서에서 세션 하이재킹으로 묶어 설명하는 경우가 많음)

2. <strong>완화 방향</strong>
XSS·네트워크 스니핑·피싱 등 탈취 경로별 대응(HTTPS, 쿠키 속성, 토큰 수명, 재인증 등)

### CSRF

1. <strong>CSRF</strong>
사용자가 의도하지 않은 상태 변경 요청을 다른 출처가 유발하는 공격 — MDN CSRF 용어 참고

2. <strong>방어</strong>
<code>SameSite</code>, CSRF 토큰, <code>Origin</code>·<code>Referer</code> 검증, 중요 작업 재인증 등

3. <strong>CSRF 토큰</strong>
요청마다 예측하기 어려운 값을 요구해 위조 요청을 어렵게 함

4. <strong>CAPTCHA</strong>
자동화된 남용을 줄이기 위한 보조 수단(표준은 아니나 업계에서 흔히 병행)

### 쿠키 vs Authorization 헤더

1. <strong>쿠키</strong>
브라우저가 스코프 규칙에 따라 자동 첨부 — RFC 6265, MDN 쿠키

2. <strong>헤더(Bearer 등)</strong>
애플리케이션이 명시적으로 붙임 — RFC 6750, MDN Authorization

3. <strong>크로스 오리진</strong>
<code>fetch</code>의 <a href="https://developer.mozilla.org/ko/docs/Web/API/Request/credentials"><code>credentials</code></a>와 CORS 응답 헤더가 맞아야 쿠키가 포함됨

---

## 참고 자료

- <a href="https://developer.mozilla.org/ko/docs/Web/HTTP/Guides/Overview">MDN — HTTP 개요</a>
- <a href="https://developer.mozilla.org/ko/docs/Web/HTTP/Cookies">MDN — HTTP 쿠키</a>
- <a href="https://developer.mozilla.org/ko/docs/Web/API/Window/localStorage">MDN — localStorage</a>
- <a href="https://developer.mozilla.org/ko/docs/Web/API/Window/sessionStorage">MDN — sessionStorage</a>
- <a href="https://developer.mozilla.org/ko/docs/Web/HTTP/Guides/CORS">MDN — CORS</a>
- <a href="https://developer.mozilla.org/ko/docs/Web/Security/Attacks/XSS">MDN — XSS</a>
- <a href="https://developer.mozilla.org/ko/docs/Glossary/CSRF">MDN — CSRF</a>
- <a href="https://datatracker.ietf.org/doc/html/rfc6265">RFC 6265 — HTTP State Management Mechanism</a>
- <a href="https://datatracker.ietf.org/doc/html/rfc6750">RFC 6750 — Bearer Token Usage</a>
- <a href="https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html">OWASP — CSRF Prevention Cheat Sheet</a>
- <a href="https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html">OWASP — XSS Prevention Cheat Sheet</a>
117 changes: 117 additions & 0 deletions keyword/chapter04/custom-hook.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
# Custom Hook

## React 훅과의 관계

- React <strong>내장 훅</strong>(<code>useState</code>, <code>useEffect</code>, <code>useRef</code>, <code>useContext</code> 등)은 함수 컴포넌트에서 <strong>상태·부수 효과·참조·전역 값</strong>을 선언적으로 다루기 위한 표준 도구임
- <strong>Custom Hook</strong>은 이런 훅들을 <strong>조합해 특정 로직을 함수 하나로 묶은 것</strong>임
- 규칙: 이름은 <strong><code>use</code>로 시작</strong>해야 하며, 다른 훅과 마찬가지로 <strong>컴포넌트 최상위에서 조건부 호출 없이</strong> 호출해야 함

---

## Custom Hook을 쓰는 이유

1. <strong>중복 제거</strong> — 여러 화면에서 같은 패턴의 상태·이펙트를 반복하지 않음
2. <strong>관심사 분리</strong> — UI와 데이터·동기화 로직을 나누어 읽기·수정이 쉬움
3. <strong>유지보수</strong> — 동작 변경 시 훅 파일 한곳을 고치면 연결된 컴포넌트에 반영하기 쉬움
4. <strong>테스트</strong> — UI 없이 로직만 검증하기 수월한 편임
5. <strong>의존성 표현</strong> — <code>useEffect</code> 의존성 배열 등으로 <strong>언제 실행·정리할지</strong>를 한곳에 모을 수 있음

---

## 파일 위치 관례

- 재사용 훅은 보통 <code>src/hooks/</code> 아래에 둠

```
src/
├── components/
├── hooks/
│ ├── useFetch.ts
│ ├── useLocalStorage.ts
│ ├── useDebounce.ts
│ ├── useAuth.ts
│ └── useTheme.ts
├── pages/
└── App.tsx
```

- 실제 프로젝트에서는 팀 규칙에 따라 <code>features/</code> 단위로 두기도 함

---

## 기본 문법

```tsx
import { useState } from 'react';

function useCustomHook() {
const [value, setValue] = useState('');

const updateValue = (newValue: string) => setValue(newValue);

return { value, updateValue };
}

export default useCustomHook;
```

- 함수 이름은 <strong><code>use</code> 접두사</strong> 필수
- 내부에서 다른 훅을 <strong>항상 같은 순서</strong>로 호출해야 함

---

## 예시: useToggle

### useState만 쓸 때의 아쉬운 점

- 토글마다 <code>setState((prev) => !prev)</code> 패턴이 반복됨
- 나중에 <strong>모든 토글에 로깅</strong>을 넣어야 하면 파일마다 수정해야 함

### Custom Hook으로 분리

```tsx
import { useState } from 'react';

function useToggle(initialValue: boolean = false) {
const [state, setState] = useState(initialValue);

const toggle = () => setState((prev) => !prev);

return [state, toggle] as const;
}

export default useToggle;
```

### 사용

```tsx
import useToggle from '../hooks/useToggle';

const ToggleExample = () => {
const [isOpen, toggle] = useToggle(false);

return (
<div>
<h1>{isOpen ? '열림' : '닫힘'}</h1>
<button type="button" onClick={toggle}>
토글
</button>
</div>
);
};

export default ToggleExample;
```

### 기대 효과

- 토글 구현이 <strong>한 파일에 모임</strong> → 로깅·추적 로직을 <code>useToggle</code> 안에만 추가하면 됨
- 컴포넌트는 <code>const [isOpen, toggle] = useToggle(false)</code> 한 줄로 의도가 드러남

---

## 참고 자료

- <a href="https://react.dev/learn/reusing-logic-with-custom-hooks">React — Reusing Logic with Custom Hooks</a>
- <a href="https://react.dev/reference/rules/rules-of-hooks">React — Rules of Hooks</a>
Loading