개발자 기술면접 대비 - 보안

 

질문 리스트

 
Cookie , Session, Token에 대해서 설명해주세요
Cookie, Session, JWT는 모두 인증과 사용자 상태 유지를 위해 사용되는 기술입니다. 
각각의 특징은 다음과 같습니다.

우선 Cookie는 클라이언트 브라우저에 설치되는 작은 데이터 파일입니다. 사용자가 서버에 요청을 보내면, 서버는 응답할 때 Set-Cookie 헤더를 통해 쿠키를 내려보내고, 이후 클라이언트는 요청할 때마다 저장된 쿠키를 함께 전송합니다. 쿠키는 사용자 식별이나 개인화된 광고 등에 활용되지만, 브라우저에 저장되기 때문에 보안에 다소 취약합니다.

Session은 민감한 인증 정보를 서버 측에 저장하는 방식입니다. 사용자가 로그인하면 서버는 고유한 Session ID를 생성해 브라우저에 저장하고, 이후 요청 시 이 Session ID를 통해 서버 메모리에 저장된 사용자 정보를 조회합니다. 보안성이 뛰어나지만, 서버 리소스를 소모한다는 단점이 있습니다.

JWT는 JSON Web Token의 약자로, 인증 정보를 담은 토큰입니다. 서버는 로그인 요청을 받은 후 Header, Payload, Signature를 생성하여 JWT를 만들고, 이를 클라이언트에게 전달합니다. 클라이언트는 JWT를 로컬 스토리지나 쿠키에 저장한 뒤, 이후 API 요청 시 Authorization 헤더에 담아 전송합니다. 서버는 토큰의 유효성을 검증하여 인증을 처리하고, 만약 Access Token이 만료되면 Refresh Token을 이용해 재발급을 받습니다. JWT는 서버가 별도 세션을 저장할 필요가 없어, 분산 시스템이나 MSA 환경에서 효율적입니다.
JWT는 왜 세션보다 확장성이 좋은가요?
JWT는 토큰 자체에 인증에 필요한 모든 정보를 포함하고 있어 서버가 별도로 사용자 상태를 저장하거나 조회할 필요가 없습니다. 반면, 세션 기반 인증은 서버가 사용자의 세션 정보를 메모리나 별도 저장소에 유지해야 합니다.

따라서 세션 방식은 서버에 요청이 몰릴수록 세션 저장소의 부하가 커지고, 서버를 수평 확장할 경우 세션 동기화(세션 스티키 세션이나 Redis 세션 저장)가 필요합니다. 반면 JWT는 클라이언트가 직접 토큰을 가지고 있기 때문에, 서버가 stateless하게 유지될 수 있습니다. 서버를 여러 대로 늘려도 추가적인 세션 공유 작업 없이 바로 확장할 수 있어, 확장성이 뛰어납니다.

또한, JWT는 클라이언트가 토큰만 가지고 있으면 인증이 가능하기 때문에, API 게이트웨이, 외부 API 서버, 다양한 서비스 간 연동에도 유용하게 활용할 수 있습니다. 이런 점에서 JWT는 특히 MSA 아키텍처나 모바일 백엔드에서 선호된다고 생각합니다.


🍭 요약
  • Session = 서버가 상태(state)를 관리해야 함 (scaling 어려움)
  • JWT = 서버는 상태를 관리하지 않음 (stateless → scaling 쉬움)
  • 추가 확장성 장점: API 게이트웨이, 여러 서버/서비스 간 인증에도 적합
JWT를 쓰면 무조건 좋은가요? 단점은 없나요?
JWT는 서버 확장성과 API 간 인증 연동에 매우 유리하지만, 무조건 장점만 있는 것은 아닙니다. 몇 가지 단점도 존재합니다.

첫째, 토큰 자체에 인증 정보를 담고 있기 때문에, 토큰이 탈취될 경우 내부 정보가 노출될 수 있습니다. 물론 Payload는 Base64 인코딩이라 쉽게 복호화할 수 있기 때문에, 민감한 개인정보는 토큰 안에 절대 담지 말아야 합니다.

둘째, 토큰이 발급되면 서버가 이를 직접적으로 '철회'할 수 없습니다. 세션 기반 인증은 서버에서 세션을 삭제하면 바로 로그아웃 처리가 가능하지만, JWT는 유효기간(expiration)이 끝나기 전까지는 유효한 것으로 간주됩니다. 이 때문에 만약 토큰이 유출되었을 경우, 즉시 차단하는 데 어려움이 있습니다.

셋째, 토큰 크기가 상대적으로 크기 때문에, 매 요청마다 Authorization 헤더에 토큰을 함께 보내야 하고, 이로 인해 트래픽이 약간 증가할 수 있습니다.

따라서 JWT는 서버 확장성이나 분산 시스템 환경에 적합한 반면, 보안 정책을 강화하거나 만료 기간 관리, 토큰 저장 방식 등을 신중하게 설계해야 한다고 생각합니다.
JWT Payload에 개인정보를 넣으면 안되는 이유는?
JWT의 Payload는 단순히 Base64로 인코딩되어 있을 뿐, 암호화되어 있는 것이 아닙니다. Base64는 누구나 쉽게 디코딩할 수 있기 때문에, 토큰을 탈취하거나 중간에서 가로채면 Payload 안에 담긴 내용을 쉽게 확인할 수 있습니다.

만약 개인정보나 민감한 데이터(예를 들면, 주민등록번호, 이메일, 핸드폰번호 등)가 Payload에 포함되어 있다면, 보안 사고로 이어질 수 있습니다. 특히 인터넷 환경에서는 요청이 노출되거나 저장 로그를 통해 탈취될 위험이 있기 때문에, 개인정보 보호법이나 GDPR 같은 법적 문제로까지 확장될 수 있습니다.

따라서 Payload에는 인증에 필요한 최소한의 정보만 넣어야 하며, 개인정보처럼 노출되면 안 되는 정보는 절대 포함하지 않는 것이 원칙입니다. 필요한 경우에는 서버에 저장하고, 토큰에는 서버에서 조회할 수 있는 식별자(예: userId) 정도만 담는 것이 안전하다고 생각합니다.
인증(Authentication)과 인가(Authorization)의 차이점을 설명해주세요.
인증(Authentication)과 인가(Authorization)은 보안 시스템에서 서로 다른 역할을 합니다.

먼저 인증은 '누군지 확인하는 과정'입니다. 
사용자가 시스템에 접근하려고 할 때, ID와 비밀번호를 입력하거나 OAuth 인증을 통해 본인이 누구인지 증명하는 과정을 말합니다. 즉, '당신이 정말 당신이 맞습니까?'를 확인하는 단계입니다.

반면 인가는 '권한을 부여하는 과정'입니다. 
인증이 완료된 사용자에 대해, 어떤 리소스나 기능을 사용할 수 있는지 결정하는 것을 의미합니다. 
예를 들어, 같은 사용자라도 관리자는 모든 데이터에 접근할 수 있지만, 일반 사용자는 일부 데이터만 볼 수 있는 것처럼, '당신이 무엇을 할 수 있습니까?'를 제어하는 과정입니다.

 

JWT에서 인증과 인가는 각각 어떻게 다루나요?
JWT에서는 인증(Authentication)과 인가(Authorization)이 명확히 구분되어 처리됩니다.

먼저 인증은 JWT를 발급하는 과정에서 이루어집니다. 사용자가 ID와 비밀번호 같은 자격 정보를 제출하면, 서버는 이를 검증하여 올바른 사용자임을 확인합니다. 인증이 성공하면, 서버는 사용자의 식별자나 기본 정보를 담은 JWT를 발급합니다. 이 JWT 자체가 '나는 인증된 사용자다'라는 증거 역할을 합니다.

반면 인가는 JWT의 Payload 안에 있는 정보(Claims)를 통해 수행됩니다. Payload에는 사용자 권한(role), 접근 가능한 리소스 범위(scope) 같은 정보가 포함될 수 있습니다. 서버는 클라이언트 요청에 포함된 JWT를 검증한 뒤, Payload에 담긴 권한 정보를 바탕으로 요청을 허용할지 거부할지 결정합니다.
Access Token과 Refresh Token의 차이점은 무엇이고, 설계는 어떻게 하나요?
Access Token과 Refresh Token은 JWT 기반 인증 시스템에서 각각 다른 역할을 합니다.

Access Token은 사용자가 인증에 성공했을 때 서버가 발급해주는 토큰으로, 짧은 유효기간을 가집니다. 이 토큰을 API 요청 시 Authorization 헤더에 담아 보내면서 인증과 인가를 동시에 처리합니다. Access Token은 직접 노출되어 사용되기 때문에 탈취 위험에 대비해 비교적 짧은 만료시간을 설정하는 것이 일반적입니다.

반면 Refresh Token은 Access Token이 만료되었을 때, 사용자가 다시 로그인을 하지 않고도 새로운 Access Token을 발급받을 수 있게 해주는 장치입니다. Refresh Token은 훨씬 긴 유효기간을 가지며, 보안상 서버 측 저장소(예: DB나 Redis)에 안전하게 보관하고, 클라이언트 쪽에는 필요 최소한만 저장하도록 관리합니다.


* 심화 추가 질문 가능성

  • "Refresh Token도 JWT로 발급하나요?"
    네, 하지만 보안 고려해서 서버 저장/검증 구조를 추가합니다.
  • "Access Token과 Refresh Token 모두 탈취되면 어떻게 하나요?"
    Refresh Token까지 탈취되면 강제 로그아웃 처리 및 토큰 폐기 조치가 필요합니다.
HTTPS는 어떻게 안전한 통신을 보장하나요? (작동원리)
HTTPS는 HTTP 통신에 SSL/TLS 프로토콜을 추가하여, 데이터가 전송되는 구간을 암호화함으로써 안전한 통신을 보장합니다.

작동 과정은 다음과 같습니다.

1. 클라이언트가 서버에 HTTPS 요청을 보내면, 서버는 자신의 SSL 인증서를 클라이언트에게 전달합니다. 인증서에는 서버의 공개키와 함께 신뢰할 수 있는 인증 기관(CA)이 발급했다는 서명이 포함되어 있습니다.

2. 클라이언트는 서버가 보낸 인증서를 검증합니다. 인증서의 유효성, 발급자, 도메인 일치 여부 등을 확인하여, 신뢰할 수 있는 서버인지 판단합니다.

3. 인증서 검증이 완료되면, 클라이언트는 대칭키(세션 키)를 하나 생성하고, 서버의 공개키로 암호화한 뒤 서버에 전송합니다.

4. 서버는 자신의 비공개키로 이 대칭키를 복호화합니다. 이렇게 하면 클라이언트와 서버는 둘만 아는 동일한 대칭키를 공유하게 됩니다.

5. 이후부터는 이 대칭키를 사용하여 모든 HTTP 요청/응답을 암호화해서 주고받습니다.

이 과정을 통해 중간에서 데이터를 가로채더라도 암호화되어 있기 때문에 내용을 알 수 없으며, 통신 경로의 무결성과 기밀성이 보장됩니다.


* 심화 추가 질문 가능성

  • "HTTPS가 느리지 않은 이유는?"
    초반에만 공개키 암호화(비대칭)를 쓰고, 이후부터는 빠른 대칭키 암호화를 사용하기 때문입니다.
  • "SSL과 TLS의 차이는?"
    SSL은 초기 버전, 현재는 보안성이 강화된 TLS(Transport Layer Security)가 표준입니다.
  • "HTTPS는 완벽하게 안전한가요?"
    통신 구간은 안전하지만, 서버나 클라이언트 자체가 뚫리면(예: XSS, 악성코드) 데이터 유출 위험은 여전히 존재합니다.
SSL과 TLS의 차이점을 설명해주세요.

SSL(Secure Sockets Layer)TLS(Transport Layer Security)는 모두 네트워크 통신을 암호화하여 안전하게 보호하는 프로토콜입니다.

SSL은 1990년대 초반에 개발되었지만, 여러 보안 취약점이 발견되면서 현재는 사용이 권장되지 않습니다. 반면 TLS는 SSL을 기반으로 보안성과 효율성을 강화해 발전시킨 표준 프로토콜입니다.

버전 차이뿐 아니라, 구체적으로 다음과 같은 기능적 차이가 있습니다.

1. 암호화 알고리즘 개선
TLS는 SSL보다 더 안전한 암호화 알고리즘을 사용합니다. SSL에서는 RC4, MD5 같은 취약한 알고리즘이 사용된 반면, TLS는 SHA-2 계열과 AEAD(Authenticated Encryption with Associated Data) 기반 알고리즘을 사용해 보안성을 높였습니다.

2. 핸드셰이크 절차 차이
SSL은 핸드셰이크 과정에서 더 많은 메시지 교환과 취약한 암호 스위트 협상이 있었지만, TLS는 핸드셰이크 과정을 간소화하고, 암호화 방식 협상(네고시에이션)을 명확히 표준화하여 중간자 공격(MITM)을 더 어렵게 만들었습니다. TLS 1.3에서는 핸드셰이크가 한 번의 왕복(Round Trip)만으로 끝나기 때문에 통신 속도도 빨라졌습니다.

3. 메시지 인증 방식 차이
SSL은 해시 함수를 이용한 MAC(Message Authentication Code) 검증을 통신 종료 시점에 수행하지만, TLS는 매 메시지마다 즉시 MAC 검증을 수행합니다. 이 덕분에 중간 변조 공격을 훨씬 빠르게 탐지할 수 있습니다.

4. 보안 취약점 관리
SSL은 POODLE, BEAST 같은 치명적인 취약점이 공개되었고, 패치로도 근본적인 문제가 해결되지 않았습니다. TLS는 초기 버전에서는 몇몇 취약점이 있었지만, TLS 1.2/1.3에서는 설계 자체를 강화하여 알려진 공격 기법들을 거의 차단할 수 있게 개선되었습니다.

XSS(Cross Site Scripting)란 무엇인가요?
XSS는 Cross Site Scripting의 약자로, 웹 애플리케이션이 사용자로부터 입력받은 데이터를 적절히 검증하거나 필터링하지 않고 그대로 출력할 때, 악성 스크립트가 삽입되어 실행되는 보안 취약점을 의미합니다.

공격자는 XSS를 통해 사용자의 브라우저에서 악성 스크립트를 실행시켜, 쿠키 탈취, 세션 하이재킹, 피싱 사이트 유도 등 다양한 공격을 할 수 있습니다.

XSS는 크게 세 가지 유형으로 나눌 수 있습니다.

Stored XSS: 악성 스크립트가 서버에 저장되어 여러 사용자에게 지속적으로 전파되는 유형입니다. 게시판, 댓글 같은 저장형 입력폼에서 주로 발생합니다.

Reflected XSS: 악성 스크립트가 서버에 저장되지 않고, 즉각적인 응답에 반영되어 발생합니다. 주로 URL 파라미터나 검색 결과 페이지에서 발견됩니다.

DOM-based XSS: 서버가 아니라 클라이언트 측 자바스크립트 코드에서 DOM 조작을 통해 악성 스크립트가 삽입되는 유형입니다.

방어 방법으로는 사용자 입력을 출력할 때 반드시 이스케이프 처리를 해주거나, 신뢰되지 않은 입력값은 절대 HTML에 직접 삽입하지 않는 방법이 있습니다. 또한 Content-Security-Policy(CSP)를 적용하여 허용된 소스 이외의 스크립트 실행을 차단할 수도 있습니다.


* 심화 추가 질문 가능성

  • "XSS 방어를 위해 Content-Security-Policy(CSP)는 어떻게 사용하나요?"
    특정 스크립트 출처만 허용하거나 inline script 실행을 차단하여 XSS 피해를 줄일 수 있습니다.
  • "React, Vue 같은 프레임워크는 XSS를 어떻게 방어하나요?"
    자동으로 HTML Escape 처리를 적용하여 기본적인 XSS 방어를 제공합니다.
CSRF(크로스사이트 요청 위조)란?
CSRF는 Cross Site Request Forgery의 약자로, 사용자가 자신의 의도와 다르게 공격자가 조작한 요청을 서버에 보내게 만드는 공격입니다.

주로 사용자가 사이트에 로그인한 상태를 악용합니다. 사용자가 인증된 세션이나 쿠키를 가지고 있을 때, 공격자가 만든 악성 링크나 스크립트를 클릭하게 되면, 사용자가 모르는 사이에 서버로 요청이 전송되어 중요한 작업(예: 비밀번호 변경, 송금)이 수행될 수 있습니다.

예를 들어, 사용자가 은행 사이트에 로그인한 상태에서 악성 사이트를 방문하면, 그 사이트가 사용자의 인증 정보를 이용해 은행 서버에 돈을 송금하는 요청을 보낼 수 있습니다. 서버는 요청이 정상 사용자로부터 온 것으로 인식하기 때문에 이를 막기 어렵습니다.

CSRF를 방어하는 방법으로는 다음과 같은 방법이 있습니다.
1) CSRF 토큰을 사용하여, 요청마다 고유한 토큰을 함께 전송하고 서버에서 검증하는 방법
2) SameSite 쿠키 속성을 설정하여, 다른 사이트에서 쿠키를 보내는 것을 제한하는 방법
3) 중요한 요청은 반드시 추가적인 사용자 인증(비밀번호 재입력 등)을 요구하는 방법
CSRF와 XSS의 차이는 무엇인가요?
CSRF와 XSS는 모두 웹 애플리케이션에서 발생하는 보안 취약점이지만, 공격 방식과 목표가 다릅니다.

우선 XSS(Cross Site Scripting)는 공격자가 웹사이트에 악성 스크립트를 삽입하고, 이를 통해 사용자의 브라우저에서 스크립트를 실행시키는 공격입니다. 주로 쿠키 탈취, 세션 하이재킹, 피싱 유도와 같은 사용자의 브라우저 데이터 탈취를 목표로 합니다. 공격의 대상은 사용자(Client)입니다.

반면 CSRF(Cross Site Request Forgery)는 사용자가 정상적으로 로그인된 세션을 이용해, 사용자가 의도하지 않은 요청을 서버로 보내게 만드는 공격입니다. 공격자는 사용자가 인증된 상태를 악용하여 서버에 부정한 요청을 보내고, 결국 서버가 잘못된 처리를 하도록 유도합니다. 공격의 대상은 서버(Server)입니다.
CSRF 방어를 위해 CSRF 토큰은 어떻게 동작하나요?
CSRF 토큰은 클라이언트가 서버에 요청을 보낼 때, 요청이 정상적인 사용자의 요청인지 확인하기 위해 사용되는 일회성 비밀 값입니다.

동작 흐름은 다음과 같습니다.

1. 사용자가 서버에 최초 요청을 보낼 때, 서버는 세션과 함께 무작위로 생성한 고유한 CSRF 토큰을 발급합니다. 이 토큰은 보통 HTML 폼 안에 hidden input으로 삽입하거나, 자바스크립트로 API 요청에 함께 담아 전송합니다.

2. 사용자가 폼을 제출하거나 요청을 보낼 때, 클라이언트는 이 CSRF 토큰을 함께 서버에 전송합니다.

3. 서버는 요청을 받을 때, 세션이나 저장소에 저장된 CSRF 토큰과 요청에 실려온 토큰 값을 비교합니다.

4. 두 토큰 값이 일치하면 요청을 정상 처리하고, 일치하지 않으면 요청을 차단하거나 에러를 반환합니다.

이 방식을 통해 공격자는 단순히 사용자의 세션을 악용해 요청을 보내는 것만으로는 서버를 속일 수 없습니다. 왜냐하면, CSRF 토큰은 예측이 불가능하고, 클라이언트에만 발급되며, 매 요청마다 함께 검증되기 때문입니다.
SameSite 쿠키 설정이란 무엇인가요?
SameSite는 쿠키의 동작 범위를 제한하는 HTTP 쿠키 속성입니다.

원래 브라우저는 어떤 사이트에서 요청을 보내든 해당 사이트의 쿠키를 무조건 같이 보내기 때문에, CSRF와 같은 공격이 가능했습니다.
SameSite 속성은 이러한 쿠키 자동 전송을 제어하여, 다른 사이트에서 오는 요청에는 쿠키를 자동으로 보내지 않도록 막는 기능을 합니다.

SameSite 속성에는 세 가지 모드가 있습니다.

Strict
오직 같은 사이트의 요청에서만 쿠키가 전송됩니다. 다른 사이트에서 넘어온 모든 요청에는 쿠키를 절대 전송하지 않습니다. 가장 강력하지만 사용자 경험에 제약이 있을 수 있습니다.

Lax
기본값이며, 같은 사이트 요청에는 쿠키를 보내고, 다른 사이트에서 넘어오는 경우에도 'GET 방식의 안전한 요청'에는 쿠키를 허용합니다. 로그인 페이지 리다이렉션 등 일반적인 시나리오를 지원하면서 대부분의 CSRF를 막을 수 있습니다.

None
다른 사이트에서도 쿠키를 전송할 수 있도록 허용합니다. 하지만 이 경우 쿠키는 반드시 Secure 속성과 함께 설정되어야 해서, HTTPS 통신에서만 사용 가능합니다.

SameSite 속성을 적절히 설정하면, 다른 사이트에서 강제로 요청을 보내더라도 브라우저가 인증 쿠키를 붙이지 않기 때문에, CSRF 공격을 근본적으로 차단할 수 있습니다.

* 심화 추가 질문 가능성

  • "SameSite=Strict를 무조건 쓰면 안 되나요?"
    Strict는 로그인 리다이렉션이나 SNS 공유 후 자동 로그인 같은 플로우를 깨뜨릴 수 있어, 상황에 따라 Lax나 None을 선택해야 합니다.
  • "SameSite=None이 왜 Secure랑 같이 써야 하나요?"
    외부 사이트 요청까지 쿠키를 허용하는 만큼, 반드시 HTTPS를 강제하여 중간자 공격(쿠키 탈취)을 막기 위해서입니다.
  • "SameSite 속성 없이도 CSRF 토큰은 필요한가요?"
    네, SameSite는 보조적인 방어선이고, 완전한 방어를 위해서는 여전히 CSRF 토큰이 필요합니다.
SQL Injection이란 무엇인가요?
SQL Injection은 사용자가 입력한 악성 SQL 구문이 그대로 실행되면서 발생하는 공격입니다.

공격자는 입력란에 SQL 구문을 조작해서 삽입하고, 이를 통해 데이터베이스에 의도하지 않은 명령을 실행할 수 있습니다. 예를 들어, 로그인 폼에서 아이디나 비밀번호 입력값에 ' OR '1'='1 같은 코드를 삽입하면, 인증을 우회하거나, 데이터베이스 정보를 조회·수정·삭제하는 등의 심각한 피해를 일으킬 수 있습니다.

SQL Injection을 방어하는 방법으로는 다음이 있습니다:
1) 사용자 입력값을 직접 쿼리에 연결하지 않고, Prepared Statement(파라미터 바인딩) 를 사용하는 방법
2) 입력값에 대해 화이트리스트 방식으로 검증하거나, 특수 문자를 이스케이프 처리하는 방법
3) 데이터베이스 권한을 최소화하여, 공격이 성공하더라도 피해를 줄이는 방법 등이 있습니다.


* 심화 추가 질문 가능성

  • "Prepared Statement가 SQL Injection을 막는 이유는?"
    SQL 구문과 데이터 값을 분리하여 처리하기 때문에, 입력값이 SQL 코드로 해석되지 않고 단순 데이터로 취급됩니다.
  • "ORM을 쓰면 SQL Injection을 막을 수 있나요?"
    ORM(Object-Relational Mapping)은 기본적으로 Prepared Statement를 사용하기 때문에 상당 부분 막을 수 있지만, Raw Query를 직접 사용할 경우 여전히 주의가 필요합니다.
  • "Blind SQL Injection은 무엇인가요?"
    서버가 에러 메시지를 직접 반환하지 않아도, 참/거짓 응답 차이를 분석해서 데이터베이스를 공격하는 기법입니다.

 

암호화와 해싱의 차이에 대해 설명해주세요.
암호화(Encryption)와 해싱(Hashing)은 모두 데이터를 변환하는 기술이지만, 목적과 동작 방식에 본질적인 차이가 있습니다.

암호화
데이터를 제3자가 볼 수 없도록 변환하는 과정입니다.
하지만 암호화는 기본적으로 복호화(Decryption)를 전제로 합니다.
즉, 인가된 사용자나 시스템은 복호화 키를 사용해서 원본 데이터를 다시 복원할 수 있습니다.
예를 들어 HTTPS 통신에서는 클라이언트와 서버가 데이터를 암호화해서 전송하고, 서로 복호화하여 원본 내용을 확인합니다.

해싱
일방향성(one-way) 변환입니다. 
데이터를 고정된 길이의 해시값으로 변환하지만, 원본 데이터를 해시값만으로 복원할 수 없습니다. 
해싱은 주로 데이터 무결성 검사나 비밀번호 저장에 사용됩니다. 
예를 들어, 사용자의 비밀번호를 데이터베이스에 평문으로 저장하는 대신 해시값으로 저장하고, 로그인 시 입력값을 다시 해싱해서 비교합니다.

* 심화 추가 질문 가능성

  • "해시 충돌(Hash Collision)이란 무엇인가요?"
    서로 다른 입력값이 같은 해시값을 가지는 현상입니다. 안전한 해시 함수는 충돌 확률이 매우 낮아야 합니다.
  • "암호화에 대칭키와 비대칭키 차이는 뭔가요?"
    대칭키는 암호화와 복호화에 같은 키를 사용하고, 비대칭키는 공개키/개인키 쌍을 이용해 암호화와 복호화를 나누어 수행합니다.
  • "비밀번호 저장할 때 해시만 하면 충분한가요?"
    아니요, 추가로 Salt(랜덤값 추가)와 함께 해싱하여 무작위성을 높이고, 공격을 어렵게 만들어야 안전합니다.
암호화에서 대칭키와 비대칭키의 차이를 설명해주세요.
대칭키 암호화와 비대칭키 암호화는 모두 데이터를 암호화하는 방식이지만, 
키를 사용하는 방식에 근본적인 차이가 있습니다.

대칭키 암호화(Symmetric Encryption)
암호화와 복호화에 같은 키를 사용합니다.
발신자와 수신자가 동일한 비밀 키를 공유해야 하며, 이 키로 데이터를 암호화하고 복호화합니다.
대표적인 알고리즘으로는 AES, DES가 있습니다.
대칭키 방식은 속도가 빠르고 처리량이 많지만, 키를 안전하게 공유하는 것이 어렵다는 단점이 있습니다.

비대칭키 암호화(Asymmetric Encryption)
서로 다른 두 개의 키, 즉 공개키(Public Key)와 비공개키(Private Key)를 사용합니다.
공개키로 암호화한 데이터는 비공개키로만 복호화할 수 있고,
반대로 비공개키로 서명한 데이터는 공개키로 검증할 수 있습니다.
대표적인 알고리즘은 RSA, ECC입니다. 비대칭키 방식은 키를 미리 공유할 필요가 없어 안전하지만, 연산이 복잡해서 속도가 느리다는 단점이 있습니다.

실제 시스템에서는 보통 두 방식을 조합합니다. 
예를 들어 HTTPS 통신에서는 초기 연결 시 비대칭키로 세션 키를 교환한 뒤, 이후 데이터 통신은 속도가 빠른 대칭키 방식으로 암호화합니다."
OAuth2 인증 흐름에 대해 설명해주세요.
OAuth2는 외부 애플리케이션이 사용자 자원(Resource)에 접근할 수 있도록 권한을 위임하는 인증 프로토콜입니다.
즉, 사용자가 자신의 아이디와 비밀번호를 직접 제공하지 않고, 신뢰할 수 있는 인증 서버를 통해 권한을 부여하는 방식입니다.

대표적인 OAuth2 흐름은 다음과 같습니다.

1. Authorization Request
클라이언트(애플리케이션)가 인증 서버에 사용자의 권한을 요청합니다. (ex: Google 로그인 버튼 클릭)

2. Authorization Grant 발급
사용자가 인증 서버에서 로그인하고 권한을 승인하면, 인증 서버가 'Authorization Code'를 클라이언트에게 전달합니다.

3. Access Token 발급
클라이언트는 이 Authorization Code를 이용해 다시 인증 서버에 요청을 보내고, 인증 서버는 Access Token을 발급합니다.

4. Resource Access
클라이언트는 Access Token을 가지고 리소스 서버에 요청을 보내서 사용자 정보를 얻거나 서비스를 이용할 수 있습니다.

추가로, Access Token의 만료 이후를 대비해서 Refresh Token을 함께 발급해주는 경우도 많습니다.
OAuth2는 특히 외부 서비스 연동(구글 로그인, 카카오 로그인 등)에 널리 사용되고 있습니다.
Replay Attack(재전송 공격)이란 무엇이고, 방어 방법은 무엇인가요?
Replay Attack은 통신 과정에서 합법적으로 주고받은 데이터를 공격자가 가로채고, 이를 그대로 재전송하여 인증을 통과하거나 동일한 요청을 반복 실행시키는 공격입니다.

예를 들어, 사용자가 서버에 정상적으로 로그인하거나 결제 요청을 보낼 때, 공격자가 이 트래픽을 중간에서 가로챈 후 그대로 다시 서버에 보내면, 서버는 이를 정상 요청으로 오인하고 처리를 해버릴 수 있습니다.

Replay Attack을 방어하는 방법은 다음과 같습니다.
1) 요청마다 Nonce(일회성 난수) 또는 Timestamp(타임스탬프)를 포함시켜, 같은 요청을 재전송하면 서버가 식별하고 거부할 수 있게 합니다.
2) 세션 키나 토큰에 유효 기간을 짧게 설정하여, 유효한 요청 기간을 제한합니다.
3) 서버는 이전에 처리된 요청 ID를 저장하고, 동일한 요청이 다시 들어오면 차단하는 방식(Replay Detection)을 사용할 수 있습니다.

특히 OAuth2 같은 프로토콜에서도 Authorization Code나 Access Token이 재사용되지 않도록 일회성으로 관리하여 Replay Attack을 방지합니다.