파이썬 requests 2FA OTP 폼 인증 완벽 가이드 – 중간 응답 처리와 헤더 쿠키 갱신
🧭 2단계 인증을 거치는 실제 로그인 흐름을 코드로 재현하고 세션 유지까지 한 번에 끝내는 방법
사이트마다 로그인 방식이 제각각이라서 스크립트 한 번에 딱 맞추기 어렵다는 경험, 한 번쯤 있으실 거예요.
OTP나 문자 코드까지 요구하는 2단계 인증이 더해지면 요청 순서와 세션 관리가 조금만 어긋나도 금세 차단되죠.
이 글은 파이썬 requests로 폼 전송부터 2FA/OTP까지 이어지는 인증 흐름을 안정적으로 처리하고, 중간 응답에서 토큰과 쿠키를 갱신해 세션을 유지하는 실전 관점을 담았습니다.
헤더 구성, 리다이렉트 추적, 상태코드 해석, 공통 실패 패턴까지 현업에서 바로 적용할 수 있도록 설명합니다.
한 번의 로그인 시도는 보통 폼 제출, 중간 단계 확인, OTP 검증, 세션 확정이라는 작은 단계들의 연속입니다.
각 단계마다 서버는 새로운 쿠키를 내려주거나 CSRF 토큰을 바꾸고, 때로는 추가 헤더를 요구합니다.
핵심은 중간 단계 응답을 놓치지 않고 필요한 값들을 정확히 수집한 뒤 다음 요청의 헤더와 쿠키를 올바르게 갱신하는 것입니다.
이 과정이 탄탄하면 2FA 환경에서도 불필요한 재시도 없이 정상 흐름을 재현할 수 있습니다.
본문에서는 체크리스트와 코드 스니펫 중심으로 실패 원인을 진단하는 방법도 함께 다룹니다.
📋 목차
🔗 파이썬 requests로 폼·인증 흐름 이해
웹 애플리케이션의 로그인은 보통 초기 진입 → 폼 로드 → 자격 증명 제출 → 2FA/OTP 확인 → 세션 확정의 순서로 이뤄집니다.
파이썬 requests로 이를 재현하려면 각 단계에서 내려오는 쿠키, CSRF 토큰, 리다이렉트, 상태코드를 올바르게 해석하고 반영해야 합니다.
여기서는 세션 객체 중심의 접근과 폼·인증 흐름을 안정적으로 따라가는 기본기를 정리합니다.
🧰 세션(Session)으로 쿠키와 리다이렉트 일관성 확보
세션은 서버가 내려주는 쿠키를 자동으로 이어받아 이후 요청에 재사용합니다.
로그인 흐름에서는 초기 진입에서 설정되는 세션 식별 쿠키가 다음 폼 제출까지 유지되어야 하므로 requests.Session()을 필수적으로 사용합니다.
또한 기본 리다이렉트 동작(3xx 추적)을 이해하고, 필요 시 allow_redirects를 조정해 중간 응답을 직접 확인할 수 있어야 합니다.
import re
from urllib.parse import urljoin
import requests
BASE = "https://example.com"
with requests.Session() as s:
# 1) 초기 진입: 기본 쿠키, CSRF 토큰 획득
r0 = s.get(urljoin(BASE, "/login"))
r0.raise_for_status()
# 페이지에서 CSRF 토큰 추출 (예: <input name="csrf" value="...">)
csrf = re.search(r'name="csrf" value="([^"]+)"', r0.text).group(1)
# 2) 아이디/비밀번호 제출: 중간 응답(OTP 요구 등) 확인
payload = {"username": "alice", "password": "secret", "csrf": csrf}
headers = {"Referer": r0.url, "Origin": BASE}
r1 = s.post(urljoin(BASE, "/login"), data=payload, headers=headers, allow_redirects=False)
# 302면 Location으로 다음 단계(예: /otp) 유도
if r1.is_redirect:
next_url = urljoin(BASE, r1.headers["Location"])
r2 = s.get(next_url) # OTP 입력 폼
# r2에서 새로운 CSRF/nonce/transactionId 등을 추출하여 다음 단계로 진행
# 이후 OTP 전송 API나 확인 API로 이어감
🧩 폼 파라미터와 토큰: 필수 값 식별
로그인 폼에는 사용자 입력 외에도 CSRF 토큰, state, relayState, transactionId, deviceId 같은 값이 포함될 수 있습니다.
이 값들은 보통 HTML의 숨김 필드, 메타 태그, 스크립트 변수, JSON 엔드포인트를 통해 제공됩니다.
페이지 로드 직후 반드시 파싱하여 다음 요청의 data나 헤더에 동일 키로 첨부해야 인증 흐름이 이어집니다.
- 🔎숨김 필드의 name과 value를 정확히 매칭.
- 🧾스크립트 내 window.__INIT__ 등 초기 상태 JSON을 파싱.
- 🔐도메인·경로 한정 쿠키가 있는지 확인하고 세션으로 유지.
💬 중요: CSRF 토큰은 단계 전환 시 갱신되는 경우가 많습니다.
폼 제출 후 응답에서 새 토큰이 보이면 반드시 다음 요청에 반영하세요.
🛰️ 상태코드와 리다이렉트: 흐름 분기 읽기
| 상태/헤더 | 의미와 액션 |
|---|---|
| 302 + Location:/otp | OTP 단계로 이동. allow_redirects=False로 잡아두고 중간 응답에서 토큰·쿠키를 수집. |
| 401/403 | 자격 증명 오류, CSRF 누락, 헤더 불일치 가능. Referer/Origin, 새 CSRF, 세션 쿠키 확인. |
| 200 + OTP 폼 | 중간 페이지에서 nonce/txnId 재발급. 해당 값을 OTP 제출 시 포함. |
💡 TIP: 브라우저 개발자도구의 네트워크 탭에서 실제 로그인 흐름을 캡처해 요청 순서, 폼 키 이름, 헤더, 쿠키를 그대로 옮기면 성공률이 높아집니다.
🧪 재현 가능한 최소 예제(MRE) 만들기
성공률을 높이려면 기능을 한 번에 모두 구현하지 말고 단계별로 검증하세요.
우선 GET /login에서 쿠키와 CSRF만 추출하는 스크립트를 만든 뒤, 폼 제출을 붙이고, 마지막으로 OTP 단계를 추가하는 식으로 확장합니다.
각 단계 사이에는 응답 본문과 헤더, 쿠키를 로그로 남겨 토큰 갱신 시점을 정확히 파악합니다.
def dump_response(r):
print("URL:", r.url)
print("STATUS:", r.status_code)
print("SET-COOKIE:", r.headers.get("Set-Cookie", ""))
# 필요한 토큰이 HTML에 있으면 정규식/파서로 추출
# print(r.text[:500])
# 사용 예
r = s.get(urljoin(BASE, "/login"))
dump_response(r)
⚠️ 주의: 서비스 약관을 위반하는 자동화는 법적·계정상 불이익이 있을 수 있습니다.
허용된 API 또는 테스트 계정으로만 실험하고, 민감 정보는 환경변수·비밀 저장소를 사용하세요.
🛠️ 2FA와 OTP 단계별 요청 흐름 지도
2단계 인증(2FA, Two-Factor Authentication) 또는 OTP(One-Time Password)는 로그인 이후 추가 검증을 요구해 보안을 강화하는 절차입니다.
이 절차를 자동화하거나 재현하려면 단순한 폼 제출 이상의 흐름 제어가 필요합니다.
각 단계마다 새로운 토큰·쿠키가 주어지고, 응답의 내용이나 코드가 달라지므로 요청을 세밀하게 추적해야 합니다.
📶 단계별 흐름의 구조적 이해
일반적으로 OTP 인증 과정은 다음과 같이 구성됩니다.
1단계 로그인 폼에서 아이디·비밀번호를 제출하고, 서버는 임시 세션과 OTP 요청 상태를 생성합니다.
2단계로 넘어가면 사용자의 기기 또는 이메일로 일회용 코드가 전송되며, 이 코드를 다시 서버로 제출해야 최종 세션이 발급됩니다.
| 단계 | 설명 |
|---|---|
| 1단계 | 로그인 폼 제출 → 임시 세션 생성 → OTP 페이지로 리다이렉트 |
| 2단계 | OTP 코드 입력 요청 → 사용자 기기로 OTP 전송 |
| 3단계 | OTP 코드 검증 → 인증 성공 시 새 세션 쿠키 발급 |
이 흐름에서 핵심은 서버의 응답 상태를 분기 기준으로 삼는 것입니다.
예를 들어, HTTP 302 리다이렉트가 발생하면 다음 페이지로 이동해 OTP 입력 폼을 가져와야 하고, 200 OK 응답으로 폼이 표시되면 그 안의 hidden 필드를 추출해야 합니다.
💬 OTP 입력 페이지를 파싱할 때는 input[type=”hidden”]뿐 아니라 script 내부 변수에도 주의해야 합니다.
많은 서비스가 토큰이나 시그니처를 JS 코드에 삽입합니다.
🧾 OTP 제출 요청 구성
OTP 검증 단계에서 자주 누락되는 요소는 Referer, Origin, X-Requested-With 헤더입니다.
이 값이 없으면 보안 필터가 요청을 차단할 수 있습니다.
또한 OTP 입력 시마다 새로운 csrf_token이나 transaction_id가 필요한 경우가 있으므로, OTP 폼 로드 직후 해당 값을 추출해 POST 요청에 반드시 포함시켜야 합니다.
# OTP 검증 단계 예시
otp_code = input("OTP 코드 입력: ")
otp_payload = {
"otp": otp_code,
"csrf_token": csrf,
"transaction_id": txn
}
otp_headers = {
"Referer": r2.url,
"Origin": BASE,
"X-Requested-With": "XMLHttpRequest"
}
r3 = s.post(urljoin(BASE, "/otp/verify"), data=otp_payload, headers=otp_headers)
if r3.status_code == 200:
print("인증 완료, 세션 유지 중")
else:
print("OTP 실패:", r3.status_code)
💡 자동 OTP 처리 전략
일부 내부 시스템이나 테스트 환경에서는 OTP가 API 응답, 이메일, SMS 모의 서버를 통해 자동으로 전달됩니다.
이때는 OTP 코드를 직접 입력받지 않고, 메시지 큐나 임시 저장소에서 읽어오는 로직을 구현할 수 있습니다.
단, 외부 서비스의 실제 OTP를 자동으로 가져오는 것은 개인정보보호 위반 소지가 있으므로, 테스트 환경에서만 사용해야 합니다.
⚠️ 주의: OTP 자동화는 반드시 허가된 테스트 서버나 QA 환경에서만 수행해야 합니다.
실제 사용자 계정의 OTP를 무단 요청하거나 수집하는 것은 법적으로 금지되어 있습니다.
💎 핵심 포인트:
2FA 단계에서 중요한 것은 응답 패턴을 “예측”하는 것이 아니라 “관찰”하는 것입니다. OTP 제출 이후의 헤더와 쿠키를 반드시 기록하고, 세션 갱신 여부를 확인하세요.
⚙️ 중간 단계 응답 처리와 세션 유지
로그인이나 인증 과정 중에는 종종 “중간 응답(intermediate response)”이 발생합니다.
이 응답들은 최종 페이지로 가기 전에 반드시 거쳐야 하는 확인 절차로, 올바르게 처리하지 않으면 세션이 무효화되거나 요청이 차단될 수 있습니다.
중간 응답은 보통 302 리다이렉트, JSON 응답, 혹은 OTP 입력폼 형태로 등장합니다.
🔄 중간 응답의 패턴 파악하기
중간 응답을 제대로 식별하려면 우선 서버가 어떤 형식으로 단계를 구분하는지 알아야 합니다.
대표적인 세 가지 형태는 다음과 같습니다.
| 응답 형태 | 설명 |
|---|---|
| 302 Redirect | 다음 단계로 이동. allow_redirects=False로 중간 응답을 직접 처리. |
| JSON Response | 상태 코드와 메시지로 단계 구분. 예: {“status”:”otp_required”}. |
| HTML Form | 새로운 입력 폼 표시. hidden 값 추출 후 다음 POST 요청에 포함. |
이러한 패턴을 구분한 뒤 응답별로 적절한 처리 로직을 작성해야 합니다.
예를 들어, 302 리다이렉트를 자동으로 따라가기 전에 Set-Cookie를 먼저 수집해 세션 쿠키를 업데이트한 후 수동으로 다음 요청을 보내야 합니다.
r = s.post(urljoin(BASE, "/login"), data=payload, allow_redirects=False)
if r.status_code == 302:
# Set-Cookie 갱신
if "Set-Cookie" in r.headers:
s.cookies.update(r.cookies)
next_url = urljoin(BASE, r.headers["Location"])
r_next = s.get(next_url)
elif r.headers.get("content-type", "").startswith("application/json"):
data = r.json()
if data.get("status") == "otp_required":
# 다음 단계로 분기
r_next = s.get(urljoin(BASE, "/otp"))
else:
print("예상치 못한 응답:", r.status_code)
🧠 세션 쿠키 갱신의 타이밍
많은 개발자가 놓치는 부분이 바로 쿠키 갱신 타이밍입니다.
중간 응답마다 서버가 세션을 재생성할 수 있으므로, response.cookies를 즉시 반영하지 않으면 이후 요청이 다른 세션으로 간주됩니다.
특히 OTP나 이메일 인증 절차 이후 새 세션 쿠키가 내려오는 경우가 많습니다.
💬 중간 응답 후 새 쿠키를 수동으로 update하지 않으면 인증이 실패합니다.
Set-Cookie 헤더를 감지할 때마다 s.cookies.update(r.cookies)를 습관적으로 호출하세요.
- 🍪응답에 Set-Cookie가 있는지 항상 체크
- 🔁r.cookies → s.cookies.update() 순서로 세션 반영
- 📡리다이렉트가 연속될 경우 각 응답별 쿠키를 누락 없이 갱신
- 🧩최종 세션이 확정되면 s.cookies.get_dict()로 저장 가능
🧩 세션 유지 실패 원인 진단
세션이 유지되지 않을 때는 다음의 원인을 의심할 수 있습니다.
- ❌서버에서 Domain이 다른 쿠키를 내려 세션이 분리된 경우
- ⚠️SameSite 정책 때문에 일부 쿠키가 차단된 경우
- 🕒CSRF 토큰이 만료되었는데 새 토큰을 반영하지 않은 경우
- 🔐헤더에서 Referer 또는 Origin 누락
💎 핵심 포인트:
모든 중간 응답은 잠재적으로 새로운 세션을 생성할 수 있습니다. 쿠키 갱신이 자동이라고 방심하지 말고, 수동으로 로그를 남겨 실제 쿠키가 변경되는 시점을 눈으로 확인하세요.
🔌 헤더와 쿠키 갱신 전략과 실전 패턴
중간 단계 응답을 정확히 처리하더라도, 헤더와 쿠키의 갱신 시점이 올바르지 않다면 인증은 곧바로 실패합니다.
특히 OTP 단계나 SSO 연동 환경에서는 브라우저와 동일한 헤더 조합이 필수입니다.
여기서는 실제 서비스 인증 흐름에서 안정적으로 동작하는 헤더 구성 패턴과 쿠키 갱신 전략을 정리합니다.
🧩 필수 헤더의 조합
일반적인 로그인 또는 2FA 요청에는 다음과 같은 공통 헤더가 필요합니다.
이 중 Referer, Origin, Content-Type이 누락되면 서버 보안 정책에 의해 차단될 수 있습니다.
| 헤더명 | 용도 |
|---|---|
| Referer | 이전 요청의 페이지를 명시. CSRF 보호 정책에 사용. |
| Origin | 도메인 일치 검증용. 보안 강화 헤더. |
| Content-Type | 폼 전송 시 application/x-www-form-urlencoded 또는 JSON 지정. |
| User-Agent | 브라우저와 동일하게 설정하여 봇 차단 우회. |
| X-Requested-With | Ajax 요청임을 명시. 일부 서버는 이 헤더가 없으면 거부함. |
서버는 이러한 헤더 조합을 통해 실제 사용자의 브라우저 요청과 동일한 맥락인지 판단합니다.
따라서 requests 스크립트에서도 이 헤더들을 반드시 포함시켜야 합니다.
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)",
"Referer": "https://example.com/login",
"Origin": "https://example.com",
"Content-Type": "application/x-www-form-urlencoded",
"X-Requested-With": "XMLHttpRequest"
}
r = s.post(urljoin(BASE, "/login"), data=payload, headers=headers)
🔁 쿠키 자동 관리와 수동 갱신의 병행
requests.Session()은 쿠키를 자동으로 관리하지만, Set-Cookie가 여러 도메인으로 분리되어 내려올 경우 일부만 반영될 수 있습니다.
이때는 r.cookies와 s.cookies.update()를 병행 사용해 수동으로 보강해야 합니다.
💎 핵심 포인트:
도메인이 서로 다른 서브 시스템(예: login.example.com → api.example.com)으로 리다이렉트될 경우,
쿠키의 Domain 속성을 확인하여 세션 쿠키를 명시적으로 재설정해야 합니다.
# 서브도메인 쿠키 수동 반영 예시
for c in r.cookies:
if ".example.com" in c.domain:
s.cookies.set(c.name, c.value, domain=".example.com")
🧮 헤더·쿠키 갱신 자동화 팁
반복되는 요청마다 헤더와 쿠키를 갱신하는 작업은 귀찮고 실수하기 쉽습니다.
이럴 때는 Session.hooks를 이용하면 모든 요청 직후 특정 함수를 자동 실행시켜 쿠키를 저장하거나 헤더를 업데이트할 수 있습니다.
def save_cookie_hook(response, *args, **kwargs):
with open("cookies.txt", "w") as f:
for c in response.cookies:
f.write(f"{c.name}={c.value}\\n")
s.hooks["response"] = [save_cookie_hook]
💡 TIP: 매 요청 후 쿠키를 파일로 저장해두면, 세션이 끊긴 후에도 빠르게 재사용할 수 있습니다. 단, 민감한 쿠키는 평문 저장을 피하고 암호화된 형태로 보관하세요.
⚠️ 주의: 헤더나 쿠키를 임의로 조작하는 과정에서 인증 토큰이나 세션 키를 외부 로그에 출력하지 않도록 주의해야 합니다. 로깅 시 민감한 값은 반드시 마스킹 처리하세요.
💡 CAPTCHA, 리다이렉트, CSRF 대응 체크리스트
요청 흐름을 완벽히 구현하더라도, CAPTCHA나 CSRF 검증 실패, 혹은 복잡한 리다이렉트 체인 때문에 인증이 끊길 수 있습니다.
이러한 장애 요소들은 단순히 코드 수정만으로 해결되지 않으며, HTTP 구조와 보안 메커니즘을 정확히 이해해야 극복할 수 있습니다.
아래는 현업 환경에서 자주 마주치는 세 가지 문제와 해결 포인트를 정리한 체크리스트입니다.
🤖 CAPTCHA 우회 또는 처리 전략
reCAPTCHA나 이미지 기반 CAPTCHA는 자동화 요청을 차단하기 위한 보호장치입니다.
일반적인 스크립트로는 해결이 어렵지만, 정상 인증 흐름을 시뮬레이션하거나 CAPTCHA가 등장하기 전의 단계만 자동화하는 방식으로 접근할 수 있습니다.
- 🎯자동화가 불가한 구간은 수동 입력을 허용하거나, Selenium 등 브라우저 제어형 라이브러리와 병행.
- 🧠CAPTCHA 발생 빈도가 높으면 User-Agent·IP 블록 단위로 차단된 것일 수 있음.
- 🧩“I’m not a robot” 유형의 v2 reCAPTCHA는 sitekey를 이용한 서버 요청 방식을 확인.
⚠️ 주의: CAPTCHA를 무단 우회하거나 자동으로 풀어내는 행위는 서비스 이용약관 위반이며, 법적으로 문제가 될 수 있습니다.
🔀 리다이렉트 체인 관리
리다이렉트는 종종 인증 상태를 유지하는 과정에서 쿠키를 교체하는 데 쓰입니다.
리다이렉트가 여러 번 연속으로 일어나면, 중간 단계의 쿠키를 놓칠 위험이 있습니다.
따라서 allow_redirects=False를 이용해 각 응답을 직접 확인하고 쿠키를 반영한 뒤 다음 요청을 수동으로 보내야 합니다.
r = s.get(urljoin(BASE, "/auth/start"), allow_redirects=False)
while r.is_redirect:
s.cookies.update(r.cookies)
next_url = urljoin(BASE, r.headers["Location"])
print("Redirecting to:", next_url)
r = s.get(next_url, allow_redirects=False)
print("최종 도착:", r.url)
이 방법을 통해 리다이렉트마다 세션 쿠키가 정상적으로 이어지는지 확인할 수 있습니다.
특히 OTP 인증 직후의 리다이렉트 구간에서 세션 쿠키가 재발급되는 경우가 많기 때문에 반드시 로그를 남겨야 합니다.
🧾 CSRF 토큰 재발급과 반영
CSRF(Cross-Site Request Forgery) 보호를 위해 대부분의 로그인 폼에는 csrf_token이나 _token 값이 포함됩니다.
이 값은 중간 단계나 OTP 입력 폼에서 변경되는 경우가 많기 때문에, 페이지마다 새로운 토큰을 파싱해 갱신해야 합니다.
- 🧬각 페이지 로드 후 input[name=”csrf”] 값 재파싱.
- 🧩응답 헤더에서 X-CSRF-Token이 존재하면 헤더에 반영.
- 🔁토큰 갱신 후 이전 요청의 payload를 새 값으로 교체.
- 🧠토큰 만료 시 서버는 보통 403을 반환하므로 이 응답을 재시도 기준으로 활용.
💬 CSRF 토큰이 매 단계 바뀌는 이유는 보안상 “재전송 공격”을 막기 위함입니다.
이 값은 세션보다 짧은 주기로 변경되므로 매 요청마다 최신 값을 갱신해야 합니다.
💎 핵심 포인트:
CAPTCHA, 리다이렉트, CSRF는 모두 자동화의 실패 지점입니다.
이 세 가지 요소를 사전에 점검하고 로깅 체계를 구축하면, 인증 실패율을 90% 이상 줄일 수 있습니다.
❓ 자주 묻는 질문 (FAQ)
requests로 OTP 입력 단계까지 자동화할 수 있나요?
OTP 입력 폼만 requests로 전송하는 것은 가능하지만, 실제 코드를 자동으로 가져오려면 테스트 환경에서만 수행해야 합니다.
세션이 자꾸 끊기는 이유가 무엇인가요?
s.cookies.update(r.cookies)를 각 응답 후 수행해 보세요.
OTP 인증 후 403 에러가 발생할 때는 어떻게 해야 하나요?
리다이렉트가 너무 많아 무한 루프처럼 보입니다.
서버가 세션 검증 중일 때 이런 현상이 자주 발생합니다.
requests.get으로는 로그인 상태가 유지되지 않는데요?
단순히 requests.get()을 새로 호출하면 세션이 새로 만들어집니다.
브라우저에서 되는 로그인 폼이 코드에서는 안 되는 이유는?
헤더와 숨은 필드를 모두 반영했는지 점검하세요.
세션 쿠키를 파일로 저장하고 다시 불러올 수 있나요?
2FA 인증을 테스트할 수 있는 공개 사이트가 있을까요?
테스트 용도로는 TwoFactorAuth.org에서 2FA가 적용된 서비스 리스트를 참고할 수 있습니다.
📘 2FA 인증 흐름 완성도를 높이는 실전 정리
파이썬 requests로 폼 기반 로그인과 2FA/OTP 인증까지 완성하려면, 단순히 요청만 보내는 수준을 넘어서 응답을 세밀히 읽고 세션 상태를 갱신해야 합니다.
중간 응답, 쿠키 교체, 헤더 재설정의 순서를 정확히 이해하면 웹 자동화의 안정성이 크게 향상됩니다.
특히 OTP 단계 이후 새로 내려오는 쿠키와 CSRF 토큰은 세션을 유지하는 데 결정적인 역할을 하므로 반드시 로깅과 검증을 병행해야 합니다.
이 과정을 습관화하면 인증 흐름이 긴 보안 사이트나 사내 시스템에서도 안정적으로 로그인 프로세스를 재현할 수 있습니다.
또한 CAPTCHA나 리다이렉트 체인 같은 장애 요인은 단순한 예외로 넘기지 말고, 요청 헤더와 응답 로그를 기준으로 명확히 진단해야 합니다.
중간 단계에서 요청이 실패하거나 세션이 끊기는 지점을 로그 기반으로 분석하면, 2FA 인증 자동화의 성공률을 90% 이상 끌어올릴 수 있습니다.
결국 핵심은 “응답을 예측하지 말고 관찰하는 것”이며, 모든 요청의 헤더·쿠키·상태코드를 꾸준히 추적하는 습관이 가장 강력한 디버깅 도구입니다.
🏷️ 관련 태그 : 파이썬requests, 세션관리, 2FA인증, OTP자동화, 폼로그인, CSRF토큰, 헤더쿠키갱신, 웹스크래핑, 로그인자동화, 인증흐름분석