CSRF XSS 차이: 프론트엔드 보안 공격 구분법 글 상단 요약 이미지
CS 지식

CSRF XSS 차이: 프론트엔드 보안 공격 구분법

2026.03.18·수정 2026.05.12·약 11분

주요 포인트 한눈에 보기

와 를 단순 정의가 아닌 공격 흐름과 책임 위치를 기준으로 정리합니다.
인증된 사용자의 요청을 악용하는 공격이고,
브라우저에서 악성 스크립트가 실행되는 공격이라는 차이를 중심으로 설명합니다.
실제 공격 예시 코드와 함께, 프론트엔드에서 토큰 처리·쿠키 설정·출력 방식을 어떻게 구현해야 하는지까지 다루어
공부용·면접 대비·실무 참고용으로 한눈에 정리할 수 있도록 구성했습니다.

CSRF XSS 차이: 프론트엔드 보안 공격 구분법 핵심 내용을 설명하는 본문 이미지

CSRF란 무엇인가

는 Cross-Site Request Forgery의 약자로,
사용자가 의도하지 않았음에도 불구하고 이미 인증된 상태를 이용해
서버로 특정 요청을 보내게 만드는 공격입니다.
이 공격의 핵심은 인증 정보가 탈취되지 않았다는 점입니다.

공격자는 아이디나 비밀번호를 훔치지 않습니다.
대신 사용자가 로그인한 상태로 다른 사이트를 방문하도록 유도한 뒤,
그 사이트에서 자동으로 요청이 전송되도록 설계합니다.
서버는 쿠키나 세션이 함께 전달된 요청을 정상 요청으로 판단하게 됩니다.

1. 사용자가 은행 사이트에 로그인
2. 로그인 상태 유지 (쿠키 저장)
3. 공격자가 만든 사이트 접속
4. 자동으로 송금 요청 전송
5. 서버는 정상 사용자 요청으로 처리

예를 들어, 사용자가 은행 사이트에 로그인한 상태에서
공격자가 만든 게시글이나 이메일 속 링크를 클릭하면
본인도 모르는 사이에 송금이나 정보 변경 요청이 전송될 수 있습니다.

<form action="https://bank.example.com/transfer" method="POST"> <input type="hidden" name="to" value="attacker" /> <input type="hidden" name="amount" value="100000" />
</form>
<script>document.forms[0].submit();</script>

이 코드에는 해킹처럼 보이는 요소가 없지만,
사용자의 인증 쿠키가 함께 전송되면서 공격이 성립됩니다.
따라서 는 요청에 사용자의 의도가 담겨 있는지를 검증하는 구조가 필요합니다.

사용자 로그인 상태 유지
→ 공격자가 만든 페이지 접속
→ 숨겨진 요청 자동 전송
→ 서버는 정상 요청으로 처리

서버 입장에서는 요청이 정상적인 사용자로부터 온 것처럼 보이기 때문에
별도의 검증 장치가 없다면 공격을 구분할 수 없습니다.

XSS란 무엇인가

는 Cross-Site Scripting의 약자로,
웹 페이지에 삽입된 악성 스크립트가
사용자의 브라우저에서 그대로 실행되는 공격입니다.
와 달리 실제 자바스크립트 코드가 실행된다는 점이 핵심입니다.

는 보통 입력값을 제대로 처리하지 못했을 때 발생합니다.
사용자가 입력한 문자열이 검증이나 이스케이프 없이
HTML로 그대로 출력되면 공격자가 코드를 주입할 수 있습니다.

<!-- 취약한 코드 예시 -->
<div>사용자 입력: <span id="output"></span></div>
<script> const userInput = "<script>alert('XSS')</script>"; document.getElementById('output').innerHTML = userInput;
</script>

위 코드에서는 사용자 입력값이 그대로 innerHTML에 삽입되면서
브라우저에서 실제 스크립트가 실행됩니다.
이로 인해 쿠키 탈취, 화면 변조, 피싱 페이지 삽입 등이 가능합니다.

// 상대적으로 안전한 출력 방식
const userInput = "<script>alert('XSS')</script>";
output.textContent = userInput;

이처럼 방어의 핵심은
입력값을 통제하는 것이 아니라
출력 시점에 브라우저가 코드를 해석하지 못하도록 막는 것입니다.

<script>
alert('XSS 공격');
</script>

이 스크립트는 게시글, 댓글, 검색어 같은 입력값을 통해 저장되거나
특정 URL을 통해 반사되어 실행될 수 있습니다.

구분 실행 위치
서버 요청
브라우저

CSRF와 XSS 비교 정리

와 를 가장 쉽게 구분하는 방법은
공격자가 무엇을 직접 조작하는지를 기준으로 생각하는 것입니다.
두 공격 모두 결과적으로는 사용자가 피해를 보지만,
공격이 시작되는 지점과 과정은 완전히 다릅니다.

는 사용자의 브라우저나 화면을 직접 건드리지 않습니다.
대신 사용자가 이미 로그인되어 있다는 사실을 이용해,
사용자의 의도와 무관한 요청을 서버로 보내게 만드는 공격입니다.
이때 서버는 쿠키나 세션을 통해 인증만 확인하기 때문에
요청이 정상인지 공격인지 구분하지 못합니다.

반면 는 서버로 보내는 요청 자체보다,
서버가 사용자에게 다시 돌려주는 화면을 노립니다.
입력값에 포함된 악성 스크립트가 HTML로 그대로 출력되면서
사용자의 브라우저에서 실제 자바스크립트 코드가 실행됩니다.

정리하면 는 “누가 이 요청을 보냈는가”의 문제이고,
는 “이 화면에서 어떤 코드가 실행되는가”의 문제입니다.
이 기준을 잡고 나면 두 공격은 헷갈릴 여지가 거의 없어집니다.

프론트엔드 방어 전략

와 는 모두 프론트엔드와 무관한 서버 보안 문제처럼 오해되기 쉽지만,
실제로는 프론트엔드 코드의 작성 방식에 따라 공격이 성립하거나 차단됩니다.
따라서 프론트엔드 개발자는 단순 구현자가 아니라
보안 흐름의 첫 관문이라는 인식을 가져야 합니다.

먼저 방어 전략입니다.
프론트엔드의 핵심 역할은 서버가 발급한 토큰을
모든 상태 변경 요청에 빠짐없이 포함시키는 것입니다.

<form method="POST" action="/profile/update"> <input type="hidden" name="csrfToken" value="{{CSRF_TOKEN}}" /> <input type="text" name="nickname" /> <button type="submit">저장</button>
</form>

이처럼 form 기반 요청에서는 hidden input으로 토큰을 포함시키며,
서버에서 내려준 값을 그대로 사용해야 합니다.

// fetch 요청에서 CSRF 토큰 포함
fetch('/profile/update', { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-Token': csrfToken }, body: JSON.stringify({ nickname: 'haebi' })
});

쿠키 설정 또한 중요한 방어 요소입니다.
SameSite 옵션은 다른 출처에서 발생한 요청에
쿠키가 자동 포함되는 것을 제한하여 를 완화합니다.

Set-Cookie: sessionId=abc123;
SameSite=Strict; Secure; HttpOnly

다음은 방어 전략입니다.
방어의 핵심은 입력값을 제한하는 것이 아니라
출력 시점에 브라우저가 코드를 해석하지 못하게 하는 것입니다.

// ❌ 위험한 방식
output.innerHTML = userInput; // ✅ 안전한 방식
output.textContent = userInput;

문자열을 HTML로 해석하는 API는
사용자 입력이 섞이는 순간 공격 지점이 됩니다.
특히 React의 dangerouslySetInnerHTML은
반드시 신뢰 가능한 데이터에만 사용해야 합니다.

// React에서 위험한 사용 예
<div dangerouslySetInnerHTML={{ __html: userInput }} />

결국 프론트엔드 방어 전략의 핵심은
데이터가 어디서 생성되고,
어떤 경로를 거쳐,
어떤 방식으로 화면에 출력되는지를
코드 단위에서 추적하는 것입니다.
이 흐름이 보이면 와 는 훨씬 명확해집니다.

면접에서 이렇게 설명하면 좋습니다

CSRF와 XSS 방어 전략의 요청 쿠키 입력 검증 CSP 흐름

면접에서는 정의를 길게 나열하기보다,
기준을 먼저 제시한 뒤 한 문장으로 정리하는 방식이 효과적입니다.
와 의 차이를 설명할 때도 동일합니다.

요청을 속여 보내는 공격인지,
브라우저에서 코드가 실행되는 공격인지를 기준으로 설명하면
면접관이 듣기에 명확하고 구조적으로 전달됩니다.

는 인증된 사용자의 권한을 악용해 의도하지 않은 요청을 서버로 보내는 공격이고,
는 웹 페이지에 삽입된 스크립트가 사용자 브라우저에서 실행되는 공격이라고 설명하면 됩니다.
이 한 문장만으로도 두 공격의 차이가 명확히 드러납니다.

면접 예상 질문과 답변

Q. 와 의 가장 큰 차이는 무엇인가요?
는 사용자를 속여 서버로 요청을 보내게 만드는 요청 위조 공격이고,
는 악성 스크립트를 사용자 브라우저에서 실행시키는 공격입니다.
즉는 요청의 출처 문제이고는 화면에 출력되는 코드의 문제입니다.

Q. SameSite 쿠키는 어떤 공격을 막아주나요?
SameSite 쿠키는 다른 사이트에서 발생한 요청에 쿠키가 자동으로 포함되는 것을 제한하여
공격을 완화하는 데 도움을 줍니다.
다만 처럼 동일 출처에서 실행되는 스크립트 공격까지 막아주지는 못합니다.

Q. 프론트엔드에서 를 방어하는 방법을 설명해보세요.
입력값을 그대로 화면에 출력하지 않고, 반드시 이스케이프 처리하는 것이 기본입니다.
또한 innerHTML이나 dangerouslySetInnerHTML 같은 위험한 API 사용을 최소화하고,
필요하다면 Content Security Policy를 설정해 스크립트 실행을 제한해야 합니다.

결론

와 는 모두 웹 보안에서 매우 중요한 공격 유형이지만,
목적과 동작 방식, 그리고 방어 전략이 전혀 다릅니다.
이 둘을 하나로 묶어 이해하면 원인도 해결책도 흐려집니다.

요청이 문제인지, 출력이 문제인지를 기준으로 나누어 사고하는 습관은
보안뿐 아니라 전체 웹 구조를 이해하는 데에도 큰 도움이 됩니다.
프론트엔드 개발자라면 이 구분을 반드시 명확히 인지하고 있어야 합니다.

FAQ

Q. 토큰이 있으면 도 막을 수 있나요?
아닙니다. 토큰은 요청 위조를 막기 위한 것이며, 스크립트 실행과는 관련이 없습니다.

Q. React를 사용하면 는 안전한가요?
기본적인 출력은 안전하지만, 위험한 API를 사용하면 가 발생할 수 있습니다.

Q. 면접에서 와 차이를 어떻게 설명하면 좋을까요?
는 요청 위조는 스크립트 실행이라는 기준으로 설명하면 명확합니다.

같이 읽으면 좋은 글

이 글이 마음에 드세요?

RSS 피드를 구독하세요!

댓글 남기기