diff --git a/week09/keyword/keyword.md b/week09/keyword/keyword.md new file mode 100644 index 0000000..ad9190b --- /dev/null +++ b/week09/keyword/keyword.md @@ -0,0 +1,67 @@ +- OAuth 2.0 + + OAuth 2.0은 사용자의 비밀번호를 직접 공유하지 않고도 다른 애플리케이션이 사용자의 정보에 접근할 수 있도록 권한을 부여하는 개방형 표준 프레임워크이다. + + **OAuth의 4가지 주요개념** + + 1. Resoucre Owner + + : 리소스 소유자를 의미하고, 여기서 리소스란 외부 소셜 서비스(API)를 의미한다. 즉, 해당 서비스에서 리소스를 소유하고 있는 사용자를 의미하고, 서비스의 유저를 의미한다. + + 2. Authorization Server + + : Resource Owner를 인증하고, 서비스에게 Access Token을 발급해주는 서버인, 외부 플랫폼 리소스에 접근할 수 있는지 인증하는 서버를 의미한다. + + 3. Resouce Server + + : 실제 데이터가 있는 서버를 의미한다. (ex. 구글 API 서버, 카카오 API 서버 등) + + 4. Client + + : 권한을 얻고 싶은 서비스를 의미한다. 즉, 사용자가 만든 서비스를 의미한다. + + + **OAuth 2.0의 흐름** + + 1. 사용자가 클라이언트 앱에서 로그인 요청 + 2. 클라이언트는 사용자를 인증 서버로 리다이렉션 + 3. 사용자가 승인하면 인증 서버가 Authroization Code를 클라이언트에게 전달 + 4. 클라이언트는 이 코드를 사용해 Access Token을 발급받음 + 5. 이후 클라이언트는 이 토큰으로 Resource Server에 접근 +- JWT + + JWT는 당사자 간에 정보를 JSON 객체로 안전하게 전송하기 위한 개방형 표준이다. 주로 인증(Authentication)과 정보 교환에 사용되며, 자가 수용적(Self-contained)이라는 특징이 있다. + + **핵심 특징** + + - **Self-contained :** 토큰 자체가 필요한 모든 정보(유저 ID, 권한, 만료 시간 등)를 포함하고 있어, 서버가 별도의 세션 저장소를 조회할 필요가 없다. + - **Stateless :** 서버는 클라이언트의 상태를 저장하지 않고, 들어오는 요청의 토큰만 검증하면 된다. + + **JWT의 3가지 구조** + + JWT는 점(`.`)으로 구분된 세 부분으로 구성된다. (`aaaaa.bbbbb.ccccc`) + + 1. **Header (헤더)** + - 토큰의 타입(JWT)과 해싱 알고리즘(HMAC SHA256 or RSA) 정보가 들어간다. + 2. **Payload (페이로드)** + - 실제 전달하려는 데이터(Claim)가 담긴다. + - 사용자 ID, 유효기간(exp), 발급자(iss) 등의 정보를 포함한다. + - *주의: 암호화되지 않고 Base64로 인코딩만 되므로 민감한 정보(비밀번호 등)는 담으면 안 된다.* + 3. **Signature (서명)** + - 데이터 위변조를 막기 위한 서명 부분이다. + - `Header` + `Payload` + `서버만 아는 비밀키(Secret Key)`를 조합하여 생성한다. +- Bearer Token + + Bearer Token은 OAuth 2.0에서 리소스에 접근하기 위해 사용하는 토큰의 유형 중 하나이다. Bearer는 소지자라는 뜻으로, 이 토큰을 가진 사람에게 권한을 부여한다는 의미를 가진다. + + **핵심 개념** + + - **소유 기반 인증:** 토큰을 가지고 있는 것만으로도 해당 리소스에 접근할 수 있는 권한이 인정된다. + - **현금과 유사:** 마치 현금과 같아서, 잃어버리면 그것을 주운 사람이 사용할 수 있다. (따라서 HTTPS와 같은 암호화된 통신 위에서 사용해야 안전하다.) + - **편의성:** 복잡한 암호화 증명 과정 없이 헤더에 토큰을 넣어 보내는 것만으로 인증이 처리된다. + + **사용 예시 (HTTP Header)** + + 클라이언트가 서버로 요청을 보낼 때, `Authorization` 헤더에 다음과 같은 형식으로 전송한다. + + `Authorization: Bearer ` \ No newline at end of file diff --git a/week09/mission/mission.md b/week09/mission/mission.md new file mode 100644 index 0000000..db204ea --- /dev/null +++ b/week09/mission/mission.md @@ -0,0 +1,128 @@ +# 1️⃣ 하드 코딩 부분 수정 + +해당 없음 + +--- + +# 2️⃣ 이미 존재하는 사용자도 정보 갱신 가능 + +```jsx +export const getUserByEmail = async (email) => { + return prisma.user.findUnique({ where: { email } }); +}; + +export const updateUser = async (userId, data) => { + const user = await prisma.user.findUnique({ where: { id: userId } }); + if (!user) { + throw new NotFoundError("사용자를 찾을 수 없습니다."); + } + await prisma.user.update({ where: { id: userId }, data }); +}; + +export const deleteUserPreferences = async (userId) => { + await prisma.userFavorCategory.deleteMany({ where: { userId } }); +}; +``` + +user.repository.js + +```jsx +export const userSignUp = async (data) => { + const existingUser = await getUserByEmail(data.email); + let userId; + + if (existingUser) { + await updateUser(existingUser.id, { + name: data.name, + gender: data.gender, + birth: data.birth, + address: data.address, + detailAddress: data.detailAddress, + phoneNumber: data.phoneNumber, + }); + await deleteUserPreferences(existingUser.id); + userId = existingUser.id; + } else { + userId = await addUser({ + email: data.email, + name: data.name, + gender: data.gender, + birth: data.birth, + address: data.address, + detailAddress: data.detailAddress, + phoneNumber: data.phoneNumber, + }); + } + + for (const preference of data.preferences) { + await setPreference(userId, preference); + } + + const user = await getUser(userId); + const preferences = await getUserPreferencesByUserId(userId); + const access_token = generateAccessToken(user); + const refresh_token = generateRefreshToken(user); + + return responseFromUser({ + user: { ...user, access_token, refresh_token }, + preferences, + }); +}; +``` + +user.service.js + +```jsx +export const responseFromUser = ({ user, preferences }) => { + if (!user) throw new NotFoundError("사용자 정보를 찾을 수 없습니다."); + + const preferFoods = (preferences ?? []) + .map((preference) => preference.foodCategory?.name ?? preference.name) + .filter(Boolean); + + return { + access_token: user.access_token, + refresh_token: user.refresh_token, + profile: { + email: user.email, + name: user.name, + preferCategory: preferFoods, + }, + }; +}; +``` + +user.dto.js + +--- + +# 3️⃣ JWT를 기존 API들에 적용 (로그인한 사용자만 쓸 수 있도록) + +```jsx +import jwt from "jsonwebtoken"; +import { prisma } from "../configs/db.config.js"; +import { asyncHandler } from "../utils/async-handler.js"; +import { UnauthorizedError } from "../utils/errors.js"; + +export const requireAuth = asyncHandler(async (req, res, next) => { + const raw = (req.get("Authorization") ?? "").trim(); + const parts = raw.split(/\s+/).filter(Boolean); + const token = parts.length > 1 ? parts[parts.length - 1] : parts[0]; + if (!token) throw new UnauthorizedError("Authorization 헤더가 필요합니다."); + + const secret = process.env.JWT_SECRET; + if (!secret) throw new UnauthorizedError("서버 JWT 설정이 되어 있지 않습니다."); + + let payload; + try { payload = jwt.verify(token, secret); } + catch { throw new UnauthorizedError("유효하지 않은 토큰입니다."); } + + const user = await prisma.user.findUnique({ where: { id: payload.id } }); + if (!user) throw new UnauthorizedError("사용자 정보를 찾을 수 없습니다."); + + req.user = user; + next(); +}); +``` + +auth.middleware.js \ No newline at end of file diff --git a/week10/keyword/keyword.md b/week10/keyword/keyword.md new file mode 100644 index 0000000..9b8a625 --- /dev/null +++ b/week10/keyword/keyword.md @@ -0,0 +1,127 @@ +- CI/CD + + ### 1) 정의 + + - **CI (Continuous Integration, 지속적 통합)** + + 개발자들이 코드를 자주(하루에도 여러 번) 공용 저장소에 **통합(push)** 하고, + + 그때마다 **자동으로 빌드 + 테스트**를 돌려서 문제를 빨리 찾는 방식. + + - **CD (Continuous Delivery / Deployment, 지속적 전달/배포)** + + 테스트를 통과한 코드를 **자동으로 배포 가능한 상태**까지 가져가거나, + + 더 나아가 **실제 운영 환경까지 자동 배포**하는 프로세스 + + + > 한 줄로: 코드 변경 → 자동 빌드/테스트 → 자동 배포까지 이어지는 파이프라인 + > + + ### 2) 특징 / 속성 + + - **자동화**: 빌드, 테스트, 배포를 스크립트/파이프라인으로 자동화 + - **작은 단위 배포**: 작은 변경을 자주 배포 → 롤백/문제 파악이 쉬움 + - **지속적인 피드백**: 테스트 실패, 품질 이슈를 빠르게 알 수 있음 + - **DevOps 문화의 핵심**: 개발+운영 협업을 전제로 함 + + ### 3) 장점 + + - 버그를 **빨리 발견** → 수정 비용 감소 + - 배포가 **일상 업무**가 되어서, 릴리스 공포(“배포 공포증”) 줄어듦 + - 기능 출시 속도 ↑, 제품 품질 ↑ + + ### 4) 단점 / 도입 시 고려사항 + + - 파이프라인 구축 초기에 **시간/노력/인프라 비용**이 듦 + - 테스트/자동화가 허술하면 **문제를 더 빨리 퍼뜨리는 파이프라인**이 되어버릴 수도 있음 + - 조직 문화(코드 리뷰, 브랜칭 전략 등)가 같이 정비되어야 효과가 큼 +- GitHub Actions + + ### 1) 정의 + + - GitHub에서 제공하는 **CI/CD 및 자동화 플랫폼**. + + 리포지토리 안에 `.github/workflows/*.yml` 파일로 **워크플로우**를 정의해서 + + push, PR, cron 등 이벤트에 따라 **빌드/테스트/배포/기타 작업**을 자동 실행. + + + ### 2) 특징 / 속성 + + - **GitHub에 내장**: 별도 서버 없이 GitHub-hosted runner 사용 가능 [GitHub Docs](https://docs.github.com/en/actions/get-started/continuous-integration?utm_source=chatgpt.com) + - **이벤트 기반**: `push`, `pull_request`, `schedule(cron)`, `workflow_dispatch(수동 실행)` 등 트리거 지원 + - **Marketplace**: 수많은 오픈소스 액션들(예: `actions/checkout`, `actions/setup-node`) 조합해서 사용 + - **YAML 기반 설정**: 인프라 as code 느낌으로 파이프라인 정의 + + ### 3) 장점 + + - GitHub랑 **밀착 통합** → PR, Issue, Checks 탭 연동이 자연스러움 + - 소규모/개인 프로젝트는 **무료 티어**로도 시작하기 쉬움 + - 온프레/자체 서버에서 돌리고 싶으면 **self-hosted runner**도 지원 + + ### 4) 단점 / 한계 + + - GitHub 생태계에 의존 → GitLab/Jenkins 등과 비교해 멀티-vcs 전략에는 제약 + - 빌드 시간이 길어지면 **요금/시간 제한** 이슈 + - 고급 시나리오(모노레포 대규모 캐싱, 복잡한 매트릭스 전략)는 설계 난이도 ↑ +- Reverse Proxy + + ### 1) 정의 + + - 클라이언트(브라우저) 앞에 있는 게 아니라, **웹 서버 앞에 서 있는 프록시 서버**. + + 클라이언트 요청을 먼저 받고, 내부의 실제 웹 서버들로 **대신 전달·분배**한 뒤 응답을 돌려주는 중간자. + + + ### 2) 주요 역할 / 속성 + + - **로드 밸런싱**: 여러 백엔드 서버로 트래픽 분산 + - **캐싱**: 정적/동적 콘텐츠를 캐시해서 백엔드 부하 감소, 응답 속도 향상 + - **보안 향상**: 실제 서버 IP/구조를 숨기고, 악성 트래픽 필터링, WAF 연동 등 + - **SSL/TLS 종료(termination)**: HTTPS 복호화를 프록시에서 처리하고, 내부는 HTTP로 통신 가능 + - **URL/경로 기반 라우팅**: `/api`는 A서비스, `/static`은 B서버 등 L7 라우팅 + + ### 3) 장점 + + - 웹 서버 앞단에서 **성능/보안/운영 관리**를 한곳에 집중시킬 수 있음 + - 서버 교체/증설 시, 클라이언트에서 도메인/주소를 바꿀 필요가 줄어듦 + - SSL 인증서 관리, 접근 제어, 로깅 등을 중앙에서 처리 + + ### 4) 단점 / 주의점 + + - 프록시 자체가 단일 장애 지점(SPOF)이 될 수 있어서 이중화 필요 + - 설정이 복잡해지면 디버깅이 어려움 (특히 헤더/리다이렉트, 리버스 프록시 체인 등) + - 잘못 구성하면 오히려 레이턴시 증가 + 보안 구멍이 될 수 있음 +- HTTPS + + ### 1) 정의 + + - **HTTPS (HyperText Transfer Protocol Secure)** + + 기존 HTTP 위에 **TLS(예전 이름 SSL)** 암호화를 입힌 프로토콜. + + *“HTTP over TLS/SSL”* 이라고도 부름. + + - 브라우저와 웹 서버 사이 데이터를 **암호화·무결성·서버 인증**을 제공 + + ### 2) 특징 / 속성 + + - **암호화(Confidentiality)**: 제3자가 패킷을 훔쳐봐도 내용을 알 수 없음 + - **무결성(Integrity)**: 전송 중 데이터가 변조되면 탐지 가능 + - **서버 인증(Authentication)**: 브라우저가 서버 인증서(SSL/TLS cert)를 검증해서 + + 진짜 해당 도메인의 서버인지 확인 + + - 현재는 **웹 표준** 수준: 브라우저가 HTTP 사이트에 “Not Secure” 표시하기도 함 + + ### 3) 장점 + + - 로그인 정보, 개인정보, 결제 정보 등 **민감한 데이터 보호** + - SEO 측면에서도 유리 (검색 엔진이 HTTPS 사이트를 선호) + - 사용자가 “자물쇠 아이콘” 보고 심리적 신뢰 ↑ + + ### 4) 단점 / 고려사항 + + - TLS 핸드셰이크/암호화로 인해 약간의 **성능 오버헤드** (요즘은 거의 무시 수준) + - 인증서 발급/갱신/관리 필요(요즘은 Let’s Encrypt + 자동 갱신으로 많이 해결) \ No newline at end of file diff --git a/week10/mission/mission.md b/week10/mission/mission.md new file mode 100644 index 0000000..c5f141a --- /dev/null +++ b/week10/mission/mission.md @@ -0,0 +1,23 @@ +![image.png](attachment:97473f15-37f1-47c1-bfd0-9081b8058458:image.png) + +![image.png](attachment:340e0844-c3aa-4c88-b32b-667086a3e1ca:image.png) + +![image.png](attachment:130043fa-9f75-432f-889e-e17297cd5858:image.png) + +![image.png](attachment:ae1a42a8-d8cc-48d4-84a7-0b6068108d3b:image.png) + +![image.png](attachment:121a87fb-dd83-4a5a-8630-9ef656a7500b:image.png) + +![image.png](attachment:4d649a07-e52e-41a9-ae4b-bfa028344211:image.png) + +![image.png](attachment:2eddb007-ee13-4169-bd5f-b99d8c334837:image.png) + +실습 5번까지 진행 후 Instance가 터지는 문제 발생 + +새로 Instance 생성 후 진행해봤지만 처음엔 잘 되다가 재접속 시 또 안됨 + +![image.png](attachment:c9babe35-ba54-4e34-be5c-b7fd1fee265e:image.png) + +![image.png](attachment:531a2810-bd35-4fec-b890-b4c3be3bda51:image.png) + +![image.png](attachment:3482c593-329f-4c5d-86ec-a2f8ce4634a2:image.png) \ No newline at end of file