๐ 1. ์น ํ๋ก์ ํธ ํด๋ ๊ตฌ์กฐ - ๊ธฐ์ด โ ์ค๋ฌด โ ์ฌํ โ ์ค์ ์์
๐ 1-1. ๊ธฐ๋ณธ ๊ตฌ์กฐ (๊ธฐ์ด)
/project
โโโ index.html โ ๋ฉ์ธ ์ค๊ณ๋ ๐
โโโ css/
โ โโโ style.css โ ์ธํ
๋ฆฌ์ด ๋ฒฝ์ง ๐จ
โโโ js/
โ โโโ main.js โ ์ ๊ธฐ, ๊ธฐ๋ฅ ์ ์ด โก
โโโ images/
โโโ logo.png โ ๊ฐ๊ตฌ, ์ํ ๐๏ธ
๐ข ๋น์ :
- index.html โ ์ง ์ค๊ณ๋ ๐
- css/ โ ์ง์ ์ธํ
๋ฆฌ์ด ๋์์ธ ๐จ
- js/ โ ์ ๊ธฐ ๋ฐฐ์ , ๊ธฐ๋ฅ ์ ์ด โก
- images/ โ ์ํ, ๊ฐ๊ตฌ ๋ฐฐ์น ๐๏ธ
๐ 1-2. ์ค๋ฌดํ ๊ตฌ์กฐ (์ค๋ํ ํ๋ก์ ํธ)
/project
โโโ public/ โ HTML, favicon, robots.txt ๋ฑ ์ ์ ํ์ผ
โโโ src/
โ โโโ assets/ โ ์ด๋ฏธ์ง, ํฐํธ, ์์ด์ฝ, ์์ ๐จ
โ โโโ components/ โ ์ฌ์ฌ์ฉ ๊ฐ๋ฅํ UI ์กฐ๊ฐ ๐งฉ
โ โโโ pages/ โ ํ์ด์ง ๋จ์ ๊ตฌ์ฑ ๐
โ โโโ styles/ โ CSS, SCSS, ๋ชจ๋ํ๋ ์คํ์ผ ํ์ผ ๐
โ โโโ scripts/ โ API ํต์ , ์ ํธ ํจ์, JS ๊ธฐ๋ฅ ๐ง
โ โโโ tests/ โ ๋จ์ ํ
์คํธ, e2e ํ
์คํธ ๐งช
โ โโโ hooks/ โ ์ปค์คํ
ํ
, ์ํ ๊ด๋ฆฌ (React ๋ฑ) ๐
โโโ dist/ โ ๋น๋๋ ๋ฐฐํฌ์ฉ ํด๋ ๐ฆ
โโโ .gitignore โ ๋ถํ์ ํ์ผ ๋ฌด์ ์ค์ ๐ซ
โโโ package.json โ ํ๋ก์ ํธ ๋ฉํ ์ ๋ณด ๐ฆ
โโโ README.md โ ํ๋ก์ ํธ ์ค๋ช
์ ๐
โ
์ค๋ฌด ํต์ฌ ํฌ์ธํธ:
src/
โ ์ญํ ๋ณ ์ฒ ์ ํ ๋ถ๋ฆฌ (์ ์ง๋ณด์/ํ์
ํ์)
dist/
โ ๋ฐฐํฌ์ฉ ํด๋, ์ค์ ์๋ฒ์ ์ฌ๋ผ๊ฐ๋ ๊ฒฐ๊ณผ๋ฌผ
- ๋ชจ๋ํ & ์ฌ์ฌ์ฉ์ฑ โ, ํฐ ํ๋ก์ ํธ์ผ์๋ก ํ์
๐ 1-3. ์ฌํ: ๋ค์ด๋ฐ & ํ์
๊ท์น
๊ท์น |
์ค๋ช
|
์๋ฌธ์ + kebab-case |
๋์๋ฌธ์ ์ถฉ๋ ๋ฐฉ์ง, ํ ํต์ผ์ฑ ์ ์ง ๐ |
๊ธฐ๋ฅ๋ณ ํด๋ ๋ช
ํ ๋ถ๋ฆฌ |
assets, components, pages ๋ช
ํ ๊ตฌ๋ถ โ
|
README.md & docs ํด๋ |
ํด๋ ๊ตฌ์กฐ, ํ๊ฒฝ ๋ณ์, ์ธํ
๋ฒ ํ์ ๋ฌธ์ํ ๐ |
ํ๊ฒฝ๋ณ์ ๊ด๋ฆฌ |
.env ํ์ผ ๋ถ๋ฆฌ, .gitignore ๋ก ์์ธ ์ฒ๋ฆฌ ๐ |
๐ฅ 1-4. ์ค์ ํด๋ ์์ (React ๊ธฐ์ค)
/my-project
โโโ public/
โ โโโ index.html // ์ ์ HTML
โโโ src/
โ โโโ assets/ // ์ด๋ฏธ์ง, ํฐํธ
โ โโโ components/ // Button, Navbar ๋ฑ UI
โ โโโ pages/ // HomePage, AboutPage
โ โโโ hooks/ // useAuth, useFetch
โ โโโ styles/ // variables.scss, mixins.scss
โ โโโ scripts/ // api.js, utils.js
โโโ dist/ // ๋น๋ ๊ฒฐ๊ณผ
โโโ .env // ํ๊ฒฝ ๋ณ์ (API KEY ๋ฑ)
โโโ .gitignore
โโโ README.md
โโโ package.json
๐ฏ 1-5. ๊ธฐ์ ๋ฉด์ ๋๋น ์ง๋ฌธ
์ง๋ฌธ |
์ฌํ ๋ต๋ณ |
ํด๋ ๊ตฌ์กฐ ์ด๋ป๊ฒ ์ค๊ณ? |
src/dist ๊ตฌ๋ถ, ๊ธฐ๋ฅ/์ญํ ๋ณ๋ก ์ฒ ์ ํ ๋๋๊ณ , README & .env๋ก ํ์
ํธ์์ฑ ํ๋ณด |
๋ค์ด๋ฐ ๊ท์น? |
kebab-case, ์๋ฌธ์ ์ผ๊ด์ฑ, ํ ๋ด ๋ค์ด๋ฐ ๋ฃฐ ๋ฌธ์ํ |
ํ์
์ ์ด๋ป๊ฒ ํด๋ ๊ตฌ์กฐ ํต์ผ? |
docs์ ๋ช
ํํ ์ ์, Linter์ CI์์ ํด๋ ๊ท์น ๊ฒ์ฆ ๊ฐ๋ฅ |
๐ ์ค์ TIP!
๋ํ ํ๋ก์ ํธ ์์ ์ :
- ๐ README์ ํด๋ ๊ตฌ์กฐ, ๋ธ๋์น ์ ๋ต, ํ๊ฒฝ ์ธํ
๊ผญ ์์ฑ
.env.example
ํ
ํ๋ฆฟ ์ ๊ณต
- Prettier, ESLint ์ค์ ๊ณต์
โ ํ์
์๋๐, ์ ์ง๋ณด์์ฑ๐
๐ 2. ๋ฒ์ ๊ด๋ฆฌ (Git & GitHub) - ๊ธฐ์ด โ ์ค๋ฌด โ ์ฌํ โ ์ค์ ์์
โ
2-1. Git ๊ธฐ๋ณธ ๋ช
๋ น์ด (๊ธฐ์ด)
๋ช
๋ น์ด |
์ญํ |
์ค๋ช
|
git init |
์ด๊ธฐํ |
ํ์ฌ ํด๋๋ฅผ Git ๊ด๋ฆฌ ํด๋๋ก ์ค์ |
git add . |
์คํ
์ด์ง ์ถ๊ฐ |
์์ ๋ ํ์ผ๋ค ์ค๋น (์ค๋
์ท ์ ๋จ๊ณ) |
git commit -m "msg" |
์ปค๋ฐ |
ํ์ฌ ์ํ ์ ์ฅ (๋ณ๊ฒฝ ํ์คํ ๋ฆฌ ์์ฑ) |
git log |
์ปค๋ฐ ๋ด์ญ |
๊ณผ๊ฑฐ ์ปค๋ฐ ๊ธฐ๋ก ํ์ธ |
git status |
์ํ ํ์ธ |
๋ณ๊ฒฝ๋ ํ์ผ, ์คํ
์ด์ง ์ฌ๋ถ ํ์ธ |
git push/pull |
์๊ฒฉ ์ฐ๋ |
์๊ฒฉ ์ ์ฅ์์ ์
๋ก๋/๋ค์ด๋ก๋ |
๐ข ๋น์ :
git init
โ ๐ โ์๊ฐ์ฌํ ์์!โ
add
โ ๐ โ๋ณ๊ฒฝ๋ ๊ฒ๋ค ๊ฐ๋ฐฉ์ ๋ด๊ธฐโ
commit
โ ๐ธ โํ์ฌ ์ํ ์ฌ์ง ์ฐ๊ธฐโ
push/pull
โ ๐ โ์๋ฒ์ ์
๋ก๋ or ๊ฐ์ ธ์ค๊ธฐโ
๐ 2-2. GitHub ์ค๋ฌด ํ์
๊ตฌ์กฐ
ํญ๋ชฉ |
์ค๋ฌด ์ ๋ต |
Branch ์ ๋ต |
main (๋ฐฐํฌ), develop (ํตํฉ), feature/ , hotfix/ ์ฌ์ฉ |
PR (Pull Request) |
๊ธฐ๋ฅ ์๋ฃ โ ๋ฆฌ๋ทฐ ์์ฒญ โ ํ์ ์น์ธ โ Merge |
.gitignore |
node_modules , .env , dist ๋ฑ ๋ฌด์ |
README.md |
์ค์น ๋ฐฉ๋ฒ, ๋ธ๋์น ์ ๋ต, ํด๋ ๊ตฌ์กฐ ํ์ ์ค๋ช
|
Issue ๊ด๋ฆฌ |
์์
๋จ์๋ก ํ ์ผ ๊ด๋ฆฌ (GitHub Issue ํ์ฉ) |
๐ 2-3. ์ฌํ: Rebase, ์ถฉ๋ ํด๊ฒฐ, Stash
๐ฅ Git Rebase & Merge ์ฐจ์ด
๋น๊ต |
Merge |
Rebase |
์ปค๋ฐ ํ์คํ ๋ฆฌ |
๋ถ๊ธฐ์ ์ ์ง, ๋ณต์กํ ์ ์์ |
์ ํ, ๊น๋, ๋ธ๋์น ์ค๊ธฐ ํ๋๋ก |
ํ์
์ |
๋ค์๊ฐ ์์
ํ ๋ Merge ์์ |
Rebase โ ์ปค๋ฐ ๋ฎ์ด์ฐ๊ธฐ ์ฃผ์ |
์ฌ์ฉ์ฒ |
์ผ๋ฐ์ PR Merge |
๋ด ๋ก์ปฌ ๋ธ๋์น ์ ๋ฆฌํ ๋ ์ ์ฉ |
โ
Rebase ์ค์ ์์
# feature ๋ธ๋์น๋ก ์ด๋
git checkout feature/login
# ์ต์ develop๊ณผ ๋ด feature๋ฅผ ๊น๋ํ ํฉ์น๊ธฐ
git rebase develop
# ์ถฉ๋ ๋ฐ์ ์:
# 1๏ธโฃ ์ถฉ๋ ํ์ผ ์์
git add .
# 2๏ธโฃ Rebase ์ฌ๊ฐ
git rebase --continue
๐ก ์ถฉ๋ ํด๊ฒฐ ์ ํ
- VSCode GitLens + Diff ํด ํ์ฉ โ ์ถฉ๋ ๋ ๋ถ๋ถ ์ฝ๊ฒ ๋น๊ต ๊ฐ๋ฅ!
- Conflict markers:
<<<<<<< HEAD
ํ์ฌ ๋ธ๋์น ์ฝ๋
=======
๋ค๋ฅธ ๋ธ๋์น ์ฝ๋
>>>>>>> develop
โ
โ ๋ ์ค ํ์ํ ๋ถ๋ถ๋ง ๋จ๊ธฐ๊ณ ์ญ์ !
๐งณ Stash ํ์ฉ ์์
# ์์๋ก ํ์ฌ ๋ณ๊ฒฝ์ฌํญ ์ ์ฅ (๋ธ๋์น ์ ํ ์ )
git stash
# ๋ค์ ์ ์ฉ
git stash apply
๐ 2-4. ์ค์ ์์ (ํ์
์ํฉ)
# 1๏ธโฃ ์์
์์: develop์์ ์ต์ ํ --------------------------------------
git checkout develop # develop ๋ธ๋์น๋ก ์ด๋ (ํ์ฌ ์์
์์์ )
git pull origin develop # ์๊ฒฉ(origin)์ develop ๋ธ๋์น ์ต์ ๋ด์ฉ ๊ฐ์ ธ์์ ๋ก์ปฌ์ ๋ฐ์
# โ ํญ์ ์์
์ ์ต์ ์ฝ๋๋ก ๋ง์ถฐ์ค์ผ ์ถฉ๋ ์ต์ํ!
# 2๏ธโฃ feature ๋ธ๋์น ์์ฑ ---------------------------------------------
git checkout -b feature/signup
# feature/signup์ด๋ผ๋ ์๋ก์ด ๋ธ๋์น ์์ฑ + ์๋์ผ๋ก ๊ทธ ๋ธ๋์น๋ก ์ด๋
# ๋ธ๋์น ์ด๋ฆ ๊ท์น: ๋ณดํต feature/๊ธฐ๋ฅ๋ช
ํํ๋ก ์ฌ์ฉ (๊ฐ๋
์ฑ & ๊ด๋ฆฌ์ฉ์ด)
# 3๏ธโฃ ์์
ํ ์ปค๋ฐ -----------------------------------------------------
git add .
# ๋ณ๊ฒฝ๋ ๋ชจ๋ ํ์ผ ์คํ
์ด์ง ์์ญ์ ์ถ๊ฐ (์ปค๋ฐ ์ค๋น)
git commit -m "Add signup page"
# ๋ณ๊ฒฝ ๋ด์ฉ์ ์ปค๋ฐ โ ๋ฉ์์ง์๋ **๋ฌด์์ ํ๋์ง ๋ช
ํํ** ์์ฑ ("Signup ํ์ด์ง ์ถ๊ฐ")
# 4๏ธโฃ ์๊ฒฉ feature ๋ธ๋์น ์ฌ๋ฆฌ๊ธฐ --------------------------------------
git push origin feature/signup
# ๋ฐฉ๊ธ ๋ง๋ feature/signup ๋ธ๋์น๋ฅผ ์๊ฒฉ(origin) ์ ์ฅ์๋ก push
# โ ํ์๋ค๊ณผ ํ์
์ ์ํด ์๊ฒฉ ๋ธ๋์น๋ก ์ฌ๋ฆฌ๋ ๋จ๊ณ
# 5๏ธโฃ PR (Pull Request) โ ๋ฆฌ๋ทฐ ์์ฒญ & ๋จธ์ง ----------------------------
# GitHub, GitLab, Bitbucket ๋ฑ์์
# feature/signup ๋ธ๋์น๋ฅผ develop ๋ธ๋์น๋ก ๋ณํฉ(Merge) ์์ฒญ (Pull Request)
# โ ํ์์๊ฒ ์ฝ๋ ๋ฆฌ๋ทฐ ์์ฒญ, ์น์ธ๋๋ฉด develop์ ๋จธ์ง!
๐ฏ 2-5. ๊ธฐ์ ๋ฉด์ ๋๋น ์ง๋ฌธ
์ง๋ฌธ |
์ฌํ ๋ต๋ณ |
ํ์
์ ๋ธ๋์น ์ ๋ต? |
main , develop , feature/ , hotfix/ ๋ช
ํํ ๊ด๋ฆฌ + PR ํ๋ก์ธ์ค |
Merge์ Rebase ์ฐจ์ด? |
Merge๋ ๋ถ๊ธฐ์ ์ ์ง, Rebase๋ ๊น๋ํ ํ์คํ ๋ฆฌ โ ํ์
๋ Merge ์์ |
.gitignore ์ญํ ? |
๋น๋ ๊ฒฐ๊ณผ๋ฌผ, ํ๊ฒฝ ๋ณ์, ๊ฐ์ธ ์ค์ ํ์ผ ๋ฌด์กฐ๊ฑด ์ ์ธ โ ์ถฉ๋ ๋ฐฉ์ง |
Stash ์ธ์ ์ฌ์ฉ? |
๊ธด๊ธ ๋ธ๋์น ์ ํ, ์์ ๋ณ๊ฒฝ ์ ์ฅ ํ ๋ค์ ์ ์ฉํ ๋ ์ ์ฉ |
๐ ์ค๋ฌด ํฌ์ธํธ
์ํฉ |
์ค๋ฌด ํ |
ํ์
์ ์ถฉ๋ ๋น๋ฐ |
PR โ ๋ฆฌ๋ทฐ โ Merge ํ์คํ ๊ด๋ฆฌ + ์ถฉ๋ ๋ ์ฃผ์ ํ์ฉ |
๋ธ๋์น ๊ด๋ฆฌ |
Issue ๋ฒํธ ๊ธฐ๋ฐ์ผ๋ก ๋ธ๋์น ๋ค์ด๋ฐ โ ์ถ์ ์ฑ โ |
์ปค๋ฐ ๋ฉ์์ง ๊ท์น |
feat: , fix: , chore: Prefix ์ฌ์ฉ์ผ๋ก ๊ธฐ๋ก ๊ด๋ฆฌ |
๐ ์ ๋ฆฌ ์์ฝ
ํญ๋ชฉ |
์ค๋ฌด ์คํฌ |
๋ฉด์ ์ฌํ |
Branch ์ ๋ต |
main/develop/feature ๊ด๋ฆฌ |
๋ธ๋์น ์ถฉ๋ ์ ํด๊ฒฐ ์ ๋ต |
Rebase vs Merge |
์ํฉ ๋ง๊ฒ ๊ตฌ๋ถ |
ํ์คํ ๋ฆฌ ๊ด๋ฆฌ ์๋ฆฌ, ํ์
์ ์ฃผ์ |
PR ํ๋ก์ธ์ค |
๋ฆฌ๋ทฐ & ๋จธ์ง ํ์ |
๋ฆฌ๋ทฐ ํ๋ก์ธ์ค ์ค์์ฑ |
.gitignore |
๋ถํ์ ํ์ผ ์ ์ธ |
์ถฉ๋ ๋ฐฉ์ง & ๋ณด์ |
Stash |
์์ ์ ์ฅ ์คํฌ |
๊ธด๊ธ ๋์ ์ ๋ต |
โก 3. ์น ์ฑ๋ฅ ์ต์ ํ - ๊ธฐ์ด โ ์ค๋ฌด โ ์ฌํ โ ์ค์ ์์
๐๏ธ 3-1. ๊ธฐ๋ณธ ์ต์ ํ ๋ฐฉ๋ฒ (๊ธฐ์ด)
๊ธฐ๋ฒ |
์ค๋ช
|
Minify |
HTML, CSS, JS ๊ณต๋ฐฑ, ์ฃผ์ ์ ๊ฑฐ (ํ์ผ ์ฌ์ด์ฆโ) |
ํ์ผ ๋ณํฉ |
JS/CSS ์ฌ๋ฌ ํ์ผ โ 1~2๊ฐ๋ก ํฉ์ณ HTTP ์์ฒญ ์ โ |
Lazy Loading |
์ด๋ฏธ์ง, iframe ์คํฌ๋กค ์์ ์ ๋ก๋ฉ |
Gzip/Brotli |
์๋ฒ์์ ํ์ผ ์์ถํด ์ ์ก (๋์ญํญ ์ ์ฝ) |
โ
์ค์ ์ ์ฉ ์์:
<!-- HTML/CSS/JS Minify: ๋ถํ์ํ ๊ณต๋ฐฑ, ์ค๋ฐ๊ฟ, ์ฃผ์ ๋ฑ์ ์ ๊ฑฐํด ํ์ผ ์ฉ๋ โ, ๋ก๋ฉ ์๋ โ -->
<!-- ์์ถ(minify)๋ CSS ํ์ผ ๋ถ๋ฌ์ค๊ธฐ -->
<link rel="stylesheet" href="style.min.css">
<!-- ์์ถ(minify)๋ JS ํ์ผ ๋ถ๋ฌ์ค๊ธฐ -->
<script src="main.min.js"></script>
<!-- ์ด๋ฏธ์ง Lazy Loading: ์ฌ์ฉ์๊ฐ ํด๋น ์ด๋ฏธ์ง๊ฐ ๋ณด์ผ ๋๋ง ๋ก๋ฉ (์ด๊ธฐ ๋ก๋ฉ ์๋ โ, ์ฑ๋ฅ ์ต์ ํ) -->
<img src="product.jpg" loading="lazy" alt="Product Image">
<!-- alt ์์ฑ: ์ด๋ฏธ์ง ๋์ฒด ํ
์คํธ (์ ๊ทผ์ฑ, SEO ํฅ์) -->
๐ข ๋น์ :
- Minify โ ๐ ๋ฌธ์์์ ๊ณต๋ฐฑ๊ณผ ์ฃผ์ ์ซ ๋นผ์ ๋ ๊ฐ๋ฒผ์ด ์์ฝ๋ณธ
- ํ์ผ ๋ณํฉ โ ๋ฐฐ๋ฌ ํ ๋ฒ์ ์ฌ๋ฌ ๊ฐ ๋ฌถ์ด์ ๋ณด๋ด๊ธฐ
- Lazy Load โ ์๋ ์์ ๋๋ง ์์ ๋ด๋๊ธฐ
- Gzip โ ๋ฐ์ค ์ ๋ฌผ๊ฑด ์์ถํด์ ๋ฐฐ์ก ๐ฆ
๐ 3-2. ์ค๋ฌด ์ต์ ํ ์คํฌ
๊ธฐ๋ฒ |
๋๊ตฌ/๋ฐฉ๋ฒ |
Tree Shaking |
Webpack, ES6 ๋ชจ๋ โ ์์ฐ๋ JS ์ ๊ฑฐ |
Code Splitting |
Dynamic Import๋ก ํ์ด์ง๋ณ JS ๋ถ๋ฆฌ |
Critical CSS |
์์ชฝ CSS๋ง ๋จผ์ ๋ก๋ฉ, ๋๋จธ์ง ์ง์ฐ ์ฒ๋ฆฌ |
CDN ํ์ฉ |
Cloudflare, AWS CloudFront๋ก ์ ์ ์์ ์ ์ธ๊ณ ๋ฐฐํฌ |
โ
Tree Shaking ์ค์ ์์
// utils.js
// add ํจ์: ๋ ์๋ฅผ ๋ํด์ ๋ฐํ
export const add = (a, b) => a + b;
// subtract ํจ์: ๋ ์๋ฅผ ๋นผ์ ๋ฐํ
export const subtract = (a, b) => a - b;
// ๋ ํจ์ ๋ชจ๋ ES6 ๋ชจ๋ ๋ฐฉ์์ผ๋ก export (๊ฐ๋ณ ๋ด๋ณด๋ด๊ธฐ)
// ์ค์ํ ํฌ์ธํธ: ES6 ๋ชจ๋์ ์ ์ ๊ตฌ์กฐ โ Webpack์ด ์ฌ์ฉ ์ฌ๋ถ ์ฝ๊ฒ ๋ถ์ ๊ฐ๋ฅ (Tree Shaking ๊ฐ๋ฅ)
โ
Code Splitting ์ค์ ์์ (React ๊ธฐ์ค)
// routes.js
// React์์ lazy loading ๊ธฐ๋ฅ๊ณผ Suspense ์ปดํฌ๋ํธ ๊ฐ์ ธ์ค๊ธฐ
import React, { lazy, Suspense } from 'react';
// ---------------------------
// ์ปดํฌ๋ํธ "์ง์ฐ ๋ก๋ฉ(lazy loading)" ์ค์
// Home ์ปดํฌ๋ํธ: ํ์ํ ๋ ๋น๋๊ธฐ๋ก ๋ถ๋ฌ์ด โ ๋ฒ๋ค ์ด๊ธฐ ํฌ๊ธฐ โ
const Home = lazy(() => import('./pages/Home'));
// About ์ปดํฌ๋ํธ: ๋ง์ฐฌ๊ฐ์ง๋ก ํ์ํ ๋๋ง ๋น๋๊ธฐ๋ก ๋ถ๋ฌ์ด
const About = lazy(() => import('./pages/About'));
// ---------------------------
// ๋ฉ์ธ App ์ปดํฌ๋ํธ ์ ์
function App() {
return (
// Suspense: lazy๋ก ๋ก๋ฉ ์ค์ผ ๋ ๋ณด์ฌ์ค fallback UI ์ค์
<Suspense fallback={<div>Loading...</div>}>
{/* Home ์ปดํฌ๋ํธ๋ ์ค์ ๋ก ํ์ํ ๋ ๋ถ๋ฌ์ ๋ ๋๋ง๋จ */}
<Home />
{/* About ์ปดํฌ๋ํธ๋ ํ์ ์ ๋น๋๊ธฐ ๋ก๋ฉ๋จ */}
<About />
</Suspense>
);
}
// ---------------------------
// ๊ฒฐ๊ณผ:
// - Home & About ์ปดํฌ๋ํธ๋ ์ด๊ธฐ ๋ฒ๋ค์ ํฌํจ๋์ง ์๊ณ , ํ์ํ ๋ ๊ฐ๋ณ์ ์ผ๋ก ๋ก๋
// - ๋ก๋ฉ ์ค์ "Loading..." ๋ฉ์์ง๊ฐ ์ ๊น ํ์
// - **React์ ์ฝ๋ ์คํ๋ฆฌํ
+ ์ฑ๋ฅ ์ต์ ํ ํต์ฌ ํจํด!**
โ ํ์ํ ํ์ด์ง์์๋ง JS ๋ถ๋ฌ์ด โ ์ด๊ธฐ ๋ก๋ฉ ์๋โ
โ
Critical CSS ์ ์ฉ
<style>
/* ๐ข Critical CSS: ์ฒซ ํ๋ฉด์์ ๋ฐ๋ก ๋ณด์ฌ์ผ ํ๋ ํต์ฌ ์คํ์ผ๋ง ์ธ๋ผ์ธ์ผ๋ก ๋ฃ๊ธฐ */
header {
background: #fff; /* ํค๋ ๋ฐฐ๊ฒฝ ํฐ์ */
position: fixed; /* ์คํฌ๋กคํด๋ ๊ณ ์ */
top: 0; /* ํ๋ฉด ๋งจ ์์ ์์น */
}
/* โ Critical CSS๋ ๋ ๋๋ง ์ง์ฐ ์์ด ๋ฐ๋ก ์ ์ฉ๋๋ฏ๋ก LCP(์ต๋ ์ฝํ
์ธ ํ์ ์๊ฐ) ๊ฐ์ ! */
</style>
<!-- ๐ ์ธ๋ถ CSS ๋น๋๊ธฐ ๋ก๋ฉ -->
<link rel="stylesheet" href="style.css" media="print" onload="this.media='all'">
<!--
1๏ธโฃ media="print": ์ด๊ธฐ์ print ์ ์ฉ์ผ๋ก ์ค์ โ ํ๋ฉด ๋ ๋๋ง์ ์ํฅ X
2๏ธโฃ onload="this.media='all'": CSS ํ์ผ์ด ๋ค ๋ก๋๋ ํ์ media๋ฅผ 'all'๋ก ๋ฐ๊ฟ ์ ์ฉ
3๏ธโฃ ๊ฒฐ๊ณผ: ์ธ๋ถ CSS๊ฐ ๋น๋๊ธฐ๋ก ๋ก๋ โ ํ์ด์ง ๋ ๋๋ง ๋ธ๋กํน ๋ฐฉ์ง โ ์ฑ๋ฅ ์ต์ ํ ๐
-->
๐ 3-3. ์ฌํ: Critical Rendering Path ์ต์ ํ
๋จ๊ณ |
์ค๋ช
|
HTML ํ์ฑ |
DOM Tree ์์ฑ ๐ |
CSSOM ํ์ฑ |
CSS ํ์ฑ ํ CSSOM Tree ์์ฑ ๐จ |
JS ํ์ฑ |
JS๋ Blocking โ defer/async ํ์ |
Render & Paint |
๋ ๋๋ง ์๋ฃ โ ํ๋ฉด ํ์ |
โ
JS ๋น๋๊ธฐ ๋ก๋ฉ ์์
<!-- ์ธ๋ถ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋๋ ๊ณตํต ์คํฌ๋ฆฝํธ (๋ฒค๋ ์คํฌ๋ฆฝํธ) ๋ถ๋ฌ์ค๊ธฐ -->
<script src="vendor.js" defer></script>
<!--
โ
defer ์์ฑ: HTML ํ์ฑ์ด ๋๋ ํ์ ์คํฌ๋ฆฝํธ ์คํ
โ
HTML ๋ฌธ์ ๊ตฌ์กฐ๊ฐ ๋ชจ๋ ์ค๋น๋ ํ ์คํ โ DOM ์ฐจ๋จ X โ ํ์ด์ง ๋ก๋ฉ ์๋ ๊ฐ์
-->
<!-- ๋ฉ์ธ ์คํฌ๋ฆฝํธ ๋ถ๋ฌ์ค๊ธฐ -->
<script src="main.js" defer></script>
<!--
โ
main.js: ํ์ด์ง ๊ธฐ๋ฅ ๋ด๋นํ๋ ์คํฌ๋ฆฝํธ
โ
defer๋ก ์ธํด vendor.js โ main.js ์์ **๋ณด์ฅ**
โ
๋ ๋ค defer โ HTML ํ์ฑ๊ณผ ๋ณ๋ ฌ๋ก ๋ค์ด๋ก๋, ํ์ฑ ๋๋ ํ ์์๋๋ก ์คํ
-->
defer
โ HTML ํ์ฑ ๋๋๊ณ JS ์คํ
- ์ด๊ธฐ ํ๋ฉด ๋น ๋ฅด๊ฒ ๋์ฐ๊ธฐ!
๐ 3-4. ์ค๋ฌด ์ค์ ์ต์ ํ ๋ ์ํผ
๐ ๏ธ Webpack + ์ค์ ์ค์ ์์:
// webpack.config.js
module.exports = {
// ๐ฅ ํ๋ก๋์
๋ชจ๋ ์ค์
mode: 'production',
// โ ์๋์ผ๋ก JavaScript, CSS ๋ฑ ํ์ผ์ **Minify(์์ถ)** ํด์ค
// โ ์ฝ์ ๋ก๊ทธ ์ ๊ฑฐ, ์ต์ ํ ์ ์ฉ (ํ์ผ ํฌ๊ธฐ โ, ์ฑ๋ฅ โ)
optimization: {
// โ
์ฝ๋ ์คํ๋ฆฌํ
์ค์
splitChunks: { chunks: 'all' },
/*
โ ์ฌ๋ฌ JS ํ์ผ ๊ฐ์ ๊ณตํต์ผ๋ก ์ฌ์ฉ๋๋ ์ฝ๋๋ฅผ ๋ณ๋์ ํ์ผ๋ก ๋ถ๋ฆฌ
โ ๊ฒฐ๊ณผ:
- ์ค๋ณต ์ฝ๋ ์ ๊ฑฐ
- ์บ์ฑ ํจ์จ โ
- ์ด๊ธฐ ๋ก๋ฉ ์๋ ๊ฐ์
*/
// โ
Tree Shaking ํ์ฑํ
usedExports: true
/*
โ ES6 ๋ชจ๋์์ ์ฌ์ฉ๋์ง ์๋ export ์ฝ๋๋ฅผ ์๋์ผ๋ก ์ ๊ฑฐ
โ ๊ฒฐ๊ณผ:
- ๋ถํ์ํ ์ฝ๋ ์ค์ด๊ณ ๋ฒ๋ค ํฌ๊ธฐ โ
- **import๋ ์ฝ๋ ์ค ์ค์ ์ฌ์ฉํ๋ ๊ฒ๋ง ๋จ๊น**
*/
}
};
๐ CDN ์ค์ ๊ฐ๋จ ์์:
- Cloudflare, AWS S3 + CloudFront ๋ฐฐํฌ โ JS/CSS/Image ์ ์ธ๊ณ ์บ์ฑ
- DNS ์ค์ โ www.domain.com โ CDN ์ฐ๊ฒฐ
๐ฏ 3-5. ๊ธฐ์ ๋ฉด์ ๋๋น ์ง๋ฌธ
์ง๋ฌธ |
์ฌํ ๋ต๋ณ |
์น ์ฑ๋ฅ ์ต์ ํ ๋ฐฉ๋ฒ? |
Minify, Lazy Loading, Tree Shaking, Code Splitting, Critical CSS, CDN |
Critical Rendering Path๋? |
DOMโCSSOMโJS ํ์ฑโPaint, ๋ถํ์ํ Blocking ์ต์ํ |
Tree Shaking ์๋ฆฌ? |
ES6 ๋ชจ๋ export ๊ธฐ์ค, ์ฌ์ฉ๋์ง ์๋ ํจ์/๋ณ์ ์ ๊ฑฐ |
Code Splitting ์ธ์ ํ์? |
์ด๊ธฐ ๋ก๋ฉ ์ต์ ํ, ํ์ด์ง๋ณ ๊ธฐ๋ฅ ๋ณ๋ ๋ก๋ฉ |
๐ ์ค๋ฌด ํฌ์ธํธ ์ ๋ฆฌ
์ํฉ |
์ค์ ์ ์ฉ |
ํ์ด์ง ์ด๊ธฐ ๋ก๋ฉ ๋๋ฆผ |
Code Splitting + Critical CSS + Lazy Load |
JS ๋ฒ๋ค ์ฉ๋ โ |
Tree Shaking + Minify |
์ ์ธ๊ณ ์ ์ |
CDN ํ์ฉ ํ์ |
๋ ๋๋ง ์ง์ฐ |
defer, async + ์ด๋ฏธ์ง ์ต์ ํ |
๐ ์ ๋ฆฌ ์์ฝ
๐ ์ฃผ์ |
์ค๋ฌด ์คํฌ |
๋ฉด์ ์ฌํ |
Minify |
HTML/CSS/JS ๊ณต๋ฐฑ ์ฃผ์ ์ ๊ฑฐ |
๋น๋ ์ค์ ์ ํฌํจ ์ฌ๋ถ |
Lazy Load |
์ด๋ฏธ์ง ์ง์ฐ ๋ก๋ฉ |
loading=โlazyโ ์ ์ฉ ์กฐ๊ฑด |
Tree Shaking |
Webpack, ES6 ๋ชจ๋ ๊ธฐ๋ฐ |
์ฌ์ฉํ์ง ์๋ export ์ ๊ฑฐ ์๋ฆฌ |
Code Splitting |
Dynamic Import |
ํ์ด์ง๋ณ JS ๋๋๊ธฐ |
Critical CSS |
์์ชฝ CSS ๋จผ์ ๋ ๋ |
์คํ์ผ ์ถฉ๋ ์ต์ํ |
CDN |
์ ์ ์์ ์ ์ธ๊ณ ๋ฐฐํฌ |
์บ์ ์ ๋ต, DNS ์ค์ |
๐ 4. ์น ๋ณด์ ๊ฐ๋
๐ก๏ธ 4-1. XSS (Cross-Site Scripting)
๐จ XSS๋?
- ๊ณต๊ฒฉ์๊ฐ ์น ํ์ด์ง์ ์
์ฑ ์คํฌ๋ฆฝํธ ์ฝ์
- ์ฌ์ฉ์์ ๋ธ๋ผ์ฐ์ ์์ ํด๋น ์คํฌ๋ฆฝํธ๊ฐ ์คํ
- ์ธ์
ํ์ทจ, ํผ์ฑ ํ์ด์ง ์์ฑ, ์น์ฌ์ดํธ ๋ณ์กฐ ๋ฑ ๊ฐ๋ฅ
๐ฏ XSS ๋ฐ์ ์์ธ
์์ธ |
์ค๋ช
|
๐ ์
๋ ฅ๊ฐ ๊ฒ์ฆ ๋ฏธํก |
<script> ๊ฐ์ ํ๊ทธ๊ฐ ๊ทธ๋๋ก ๋ฐ์๋จ |
๐ innerHTML ๋ฑ ์ง์ DOM ์ฝ์
|
์ฌ์ฉ์ ์
๋ ฅ์ ๊ทธ๋๋ก DOM ์ฝ์
โ ์คํฌ๋ฆฝํธ ์คํ |
๐ ์ ๋ขฐํ ์ ์๋ ์ธ๋ถ ๋ฐ์ดํฐ ์ฒ๋ฆฌ |
API, ๋๊ธ, ๊ฒ์ํ ๋ฐ์ดํฐ์ ๋ํ ๊ฒ์ฆ ๋ถ์ฌ |
โ
XSS ๋ฐฉ์ด๋ฒ
๋ฐฉ๋ฒ |
์ค๋ช
|
โ๏ธ ์
๋ ฅ๊ฐ Escape ์ฒ๋ฆฌ |
< , > , ' , " โ < , > ๋ฑ์ผ๋ก ๋ณํํด ๋ฌด๋ ฅํ |
๐ CSP(Content Security Policy) |
์ ๋ขฐ๋ ์ถ์ฒ๋ง ์คํฌ๋ฆฝํธ ํ์ฉ (ex. ์ธ๋ถ ์คํฌ๋ฆฝํธ ์ฐจ๋จ) |
๐งผ DOM ์ฝ์
์ textContent ์ฌ์ฉ |
innerHTML ์ฌ์ฉ ์์ โ textContent , createTextNode ํ์ฉ |
๐ซ HttpOnly ์ฟ ํค ์ฌ์ฉ |
์ธ์
์ฟ ํค๋ฅผ JavaScript๋ก ์ ๊ทผ ๋ถ๊ฐํ๊ฒ ์ค์ |
โ
์
๋ ฅ๊ฐ Validation & Length ์ ํ |
์
๋ ฅ ๊ฐ๋ฅ ๊ธธ์ด์ ํฌ๋งท์ ์๊ฒฉํ ์ ํ |
๐ป ์ค์ ๋ฐฉ์ด ์์ (์ฃผ์ ํฌํจ)
// โ ์ทจ์ฝํ ์ฝ๋: ์คํฌ๋ฆฝํธ๊ฐ ๊ทธ๋๋ก ์คํ๋ ์ ์์
div.innerHTML = userInput;
// โ
์์ ํ ๋ฐฉ๋ฒ 1: textContent ์ฌ์ฉ
div.textContent = userInput; // ์คํฌ๋ฆฝํธ ์คํ ๋ถ๊ฐ, ๋จ์ ํ
์คํธ ์ฒ๋ฆฌ
// โ
์์ ํ ๋ฐฉ๋ฒ 2: Escape ์ฒ๋ฆฌ ํจ์ ์ฌ์ฉ
function escapeHTML(str) {
return str
.replace(/&/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/"/g, '"')
.replace(/'/g, ''');
}
div.innerHTML = escapeHTML(userInput);
<!-- โ
CSP ์ ์ฉ: ์ธ๋ถ ์คํฌ๋ฆฝํธ ์ฐจ๋จ, ์ธ๋ผ์ธ ์คํฌ๋ฆฝํธ ์ฐจ๋จ -->
<meta http-equiv="Content-Security-Policy" content="
default-src 'self';
script-src 'self';
object-src 'none';
frame-ancestors 'none';">
๐ข ๋น์ :
- XSS โ ๊ณ ๊ฐ์ด ๋ ์คํ ๋์ ์์ ์์์ ๋
๊ทน๋ฌผ ๋ฃ๋ ์ํฉ ๐
- Escape ์ฒ๋ฆฌ โ ๋
๊ทน๋ฌผ์ ํฌ์ฅํด์ ๋ชป ์ฐ๊ฒ ๋ง๋ฆ ๐งฏ
- CSP โ โ์ธ๋ถ ์์ ๋ฐ์
๊ธ์งโ ๊ท์น ๐
๐ 4-2. CSRF (Cross-Site Request Forgery)
๐จ CSRF๋?
- ์ฌ์ฉ์๊ฐ ๋ก๊ทธ์ธ๋ ์ํ์์ ์
์ฑ ์์ฒญ์ด ์๋ ์ ์ก
- ์ธ์
์ฟ ํค ์๋ ์ ์ก โ ๊ณต๊ฒฉ์๊ฐ ์ฌ์ฉ์์ ๊ถํ์ผ๋ก ์์กฐ ์์ฒญ ๊ฐ๋ฅ
๐ฏ CSRF ๋ฐ์ ์์ธ
์์ธ |
์ค๋ช
|
๐ช ์๋์ผ๋ก ์ ์ก๋๋ ์ธ์
์ฟ ํค |
๋ธ๋ผ์ฐ์ ๊ฐ ์์ฒญ๋ง๋ค ์ฟ ํค ์๋ ์ฒจ๋ถ |
๐ฏ ์์ฒญ ์ถ์ฒ ๊ฒ์ฆ ๋ฏธ๋น |
์์ฒญ์ด ์ด๋์ ์๋์ง ํ์ธ ์ ํจ |
โ
CSRF ๋ฐฉ์ด๋ฒ
๋ฐฉ๋ฒ |
์ค๋ช
|
๐ท๏ธ CSRF Token ๋ฐ๊ธ |
์์ฒญ๋ง๋ค ๊ณ ์ ํ ํฐ ํฌํจ โ ์๋ฒ์์ ๊ฒ์ฆ |
๐ SameSite ์ฟ ํค ์ค์ |
์ธ๋ถ ์ฌ์ดํธ ์์ฒญ ์ ์ฟ ํค ์ ์ก ์ ํ |
๐ Referer/Origin ๊ฒ์ฆ |
์์ฒญ ์ถ์ฒ๊ฐ ์ ์ ๋๋ฉ์ธ์ธ์ง ํ์ธ |
๐ฎ POST ์์ฒญ๋ง ํ์ฉ |
๋ฏผ๊ฐํ ์์
์ GET ๊ธ์ง, POST/PUT๋ง ์ฌ์ฉ |
๐ป ์ค์ ๋ฐฉ์ด ์์ (์ฃผ์ ํฌํจ)
<!-- โ
CSRF Token ํฌํจ -->
<form action="/updateProfile" method="POST">
<input type="hidden" name="csrfToken" value="secureRandomToken123">
<button type="submit">Update</button>
</form>
# โ
SameSite + Secure + HttpOnly ์ค์
Set-Cookie: sessionId=abc123;
SameSite=Strict; /* ์ธ๋ถ ์ฌ์ดํธ์์ ์ฟ ํค ์ ์ก ๋ถ๊ฐ */
Secure; /* HTTPS์์๋ง */
HttpOnly; /* JS์์ ์ ๊ทผ ๋ถ๊ฐ */
๐ข ๋น์ :
- CSRF โ ํ๋ฐฐ๋ฅผ ๋ด ์ด๋ฆ์ผ๋ก ๋๋์ด ๋ณด๋ ๐ฆ
- CSRF Token โ ๋ด๊ฐ ์ด ์๋ช
ํ์ธ ๐๏ธ
- SameSite=Strict โ ๋ค๋ฅธ ์ง(์ฌ์ดํธ)์์๋ ๋ด ํ๋ฐฐ ์ฃผ๋ฌธ ๋ชป ํจ ๐ซ
๐ 4-3. HTTPS ์ ์ฉ (SSL/TLS)
๐จ HTTPS๋?
- HTTP + SSL/TLS ์ํธํ
- ์ค๊ฐ์์ ๋ฐ์ดํฐ ํ์ทจ, ์๋ณ์กฐ, ์ค๋ํ ๋ฐฉ์ง
- ์ฌ์ฉ์์๊ฒ ์ ๋ขฐ ์ธ์ฆ์ ์ ๊ณต
โ
HTTPS ํจ๊ณผ
ํจ๊ณผ |
์ค๋ช
|
๐ ๋ฐ์ดํฐ ์ํธํ |
ํต์ ๋ด์ฉ ๋
ธ์ถ ๋ฐฉ์ง |
๐ข ์๋ฒ ์ ์ ์ธ์ฆ |
ํผ์ฑ, ์ค๊ฐ์ ๊ณต๊ฒฉ ๋ฐฉ์ง |
๐ SEO & ๋ธ๋ผ์ฐ์ ๊ฒฝ๊ณ ์ ๊ฑฐ |
HTTPS ๋ฏธ์ ์ฉ ์ ๋ธ๋ผ์ฐ์ ๊ฒฝ๊ณ , ์ ๋ขฐ๋โ |
๐ป ์ค์ ์ ์ฉ ์์ (์ฃผ์ ํฌํจ)
# โ
Nginx HTTPS ์ค์ (Let's Encrypt ์ธ์ฆ์)
server {
listen 443 ssl;
# SSL ์ธ์ฆ์ ์์น
ssl_certificate /etc/letsencrypt/live/domain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/domain.com/privkey.pem;
# HSTS: HTTPS ๊ฐ์
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
}
๐ข ๋น์ :
- HTTP โ ์ฝ์๋ก ๋ณด๋ด๋ ํธ์ง (๋ด์ฉ ํคํ ๋ณด์) ๐ฑ
- HTTPS โ ๋ดํฌ๋ก ๋ด์ธํ ๋น๋ฐ ํธ์ง โ๏ธ
๐ช 4-4. ์ฟ ํค ๋ณด์ ์์ฑ ์ฌํ
์์ฑ |
์ญํ |
์ฌํ ์ค๋ช
|
๐ Secure |
HTTPS ํ๊ฒฝ์์๋ง ์ฟ ํค ์ ์ก |
์ค๊ฐ์ ๊ณต๊ฒฉ ์ ๋
ธ์ถ ๋ฐฉ์ง |
๐ HttpOnly |
JS ์ ๊ทผ ๋ถ๊ฐ โ XSS ๋ฐฉ์ด |
document.cookie ์ฐจ๋จ |
๐ SameSite |
๋ค๋ฅธ ์ฌ์ดํธ ์์ฒญ ์ ์ฟ ํค ์ ํ |
Strict, Lax, None ์ธ๋ถ ๊ตฌ๋ถ ํ์ |
๐ป ์ค์ ์์ (์ฃผ์ ํฌํจ)
Set-Cookie: sessionId=abc123;
Secure; /* HTTPS ํ์ */
HttpOnly; /* JS ์ ๊ทผ ๋ถ๊ฐ */
SameSite=Strict; /* ๋ค๋ฅธ ์ฌ์ดํธ์์ ์ ์ก ๋ถ๊ฐ */
๐ข SameSite ์ต์
์ ๋ฆฌ:
์ต์
|
ํน์ง |
์ฌ์ฉ ์ |
Strict |
์ฒ ์ ์ฐจ๋จ (์ธ๋ถ ์์ฒญ ์ฟ ํค ๋ฌด์กฐ๊ฑด X) |
๋ก๊ทธ์ธ, ๊ฒฐ์ ๋ฑ ๋ฏผ๊ฐ ์์
|
Lax |
GET์ ํ์ฉ, POST๋ ์ฐจ๋จ |
๋ธ๋ก๊ทธ ๋๊ธ ๋ฑ |
None |
์ ์ฝ ์์, Secure ํ์ |
์ 3์ ์๋น์ค ํ์์ (ex. OAuth) |
๐ก๏ธ 4-5. ๊ธฐํ ๋ณด์ ํค๋ (์ฌํ)
ํค๋ |
์ญํ |
์ค๋ช
|
๐ผ๏ธ X-Frame-Options: DENY |
ํด๋ฆญ์ฌํน ๋ฐฉ์ง |
iframe์ ๋ด ํ์ด์ง ์ฝ์
์ฐจ๋จ |
๐ X-Content-Type-Options: nosniff |
MIME ํ์
์ค๋ํ ๋ฐฉ์ง |
๋ธ๋ผ์ฐ์ ๊ฐ ํ์
์๋ ์ถ์ธก ๋ชปํ๊ฒ |
๐ Strict-Transport-Security |
HTTPS ๊ฐ์ ์ ์ฉ |
๋ชจ๋ ์์ฒญ HTTPS๋ก ๋ฆฌ๋ค์ด๋ ํธ |
๐ป ์ค์ ์ค์ ์์
# ํด๋ฆญ์ฌํน ๋ฐฉ์ง
X-Frame-Options: DENY
# MIME ํ์
์ค๋ํ ๋ฐฉ์ง
X-Content-Type-Options: nosniff
# HSTS
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
๐ข ๋น์ :
- X-Frame-Options โ ๋ด ๊ฐ๊ฒ ์์ ๊ฐ์ง ๊ฐํ ๊ธ์ง
- nosniff โ ๋ธ๋ผ์ฐ์ ๊ฐ ๋ง์๋๋ก ํ๋จ ๊ธ์ง
- HSTS โ HTTP๋ก๋ ์
์ฅ ๊ธ์ง
๐ฏ 4-6. ๊ธฐ์ ๋ฉด์ ๋๋น ์ฌํ ์ง๋ฌธ
์ง๋ฌธ |
์ฌํ ๋ต๋ณ |
XSS ๋ฐฉ์ง ๋ฐฉ๋ฒ์? |
Escape ์ฒ๋ฆฌ, CSP, textContent ์ฌ์ฉ, HttpOnly, ์
๋ ฅ Validation, ์ธ๋ถ ์คํฌ๋ฆฝํธ ์ถ์ฒ ์ ํ |
CSRF ๋ฐฉ์ง๋ฒ์? |
CSRF Token, SameSite ์ฟ ํค, Referer ๊ฒ์ฆ, GET ์์ฒญ ์ ํ, Token ์ฃผ๊ธฐ์ ๊ฐฑ์ |
HTTPS ์ ์ฉ ์ด์ ๋? |
๋ฐ์ดํฐ ์ํธํ, ์๋ฒ ์ธ์ฆ์๋ก ์ ๋ขฐ์ฑ ํ๋ณด, SEO, ์ค๊ฐ์ ๊ณต๊ฒฉ ๋ฐฉ์ด |
์ฟ ํค ๋ณด์ ์์ฑ์? |
Secure โ HTTPS ์ ์ก, HttpOnly โ JS ์ ๊ทผ ์ฐจ๋จ, SameSite โ CSRF ๋ฐฉ์ด (Strict, Lax, None ์ฐจ์ด ์ค๋ช
) |
๊ธฐํ ํค๋ ์ ์ฉ ์ด์ ๋? |
ํด๋ฆญ์ฌํน(X-Frame), ํ์
์ค๋ํ(nosniff), HTTPS ๊ฐ์ (HSTS) ๋ฑ ๋ค์ธต ๋ณด์ ์ ๊ณต |
๐จ ์ค๋ฌด ๋ณด์ TIP ์ ๋ฆฌ
์ํฉ |
์ค์ ์ ์ฉ |
ํผ ์
๋ ฅ ์ฒ๋ฆฌ |
Escape + Validation + ๊ธธ์ด ์ ํ |
์ธ์ฆ/์ธ์
๊ด๋ฆฌ |
SameSite=Strict + Secure + HttpOnly ์ฟ ํค ํ์ |
์๋ฒ ๋ฐฐํฌ |
HTTPS + HSTS + ๋ณด์ ํค๋ |
์ธ๋ถ ์คํฌ๋ฆฝํธ |
CSP๋ก ์ถ์ฒ ์ ํ, ์ธ๋ผ์ธ ์คํฌ๋ฆฝํธ ์ต์ํ |
์ฝ๋ ๋ฆฌ๋ทฐ |
XSS, CSRF, HTTPS, ๋ณด์ ํค๋ ์ ๊ฒ ํฌํจ |
๐ ์ต์ข
์์ฝ
๐ ์ฃผ์ |
์ค๋ฌด ํฌ์ธํธ |
๋ฉด์ ์ฌํ |
XSS |
Escape, CSP, textContent ์ฌ์ฉ, HttpOnly |
DOM XSS, Reflected XSS, Stored XSS ์ฐจ์ด๊น์ง |
CSRF |
Token, SameSite, Referer ๊ฒ์ฆ |
์ฟ ํค ์๋ ์ ์ก ์๋ฆฌ, Token ๋ฐฉ์ ์ฅ๋จ์ |
HTTPS |
์ธ์ฆ์ ์๋ ๊ฐฑ์ , HSTS |
TLS ํธ๋์
ฐ์ดํฌ ๊ณผ์ ๊น์ง |
์ฟ ํค ๋ณด์ |
Secure, HttpOnly, SameSite ์ค์ |
์ธ๋ถ ์ต์
๋ฐ ๋ณด์ ํจ๊ณผ ์ค๋ช
|
๋ณด์ ํค๋ |
Frame, Content-Type, HSTS |
ํด๋ฆญ์ฌํน, MIME ์ค๋ํ ๊ณต๊ฒฉ ์๋ฆฌ๊น์ง |