빌드노트
쿠키 파일은 생겼는데 다음 curl 요청에는 쿠키가 없다
--cookie-jar는 쿠키 저장용이고 --cookie는 파일 읽기용이다. 새 curl 프로세스의 실제 Cookie 헤더를 비교해 로딩 누락과 Path 불일치를 구분하고, 갱신된 쿠키를 다음 실행에 보존할 옵션을 고른다.
curl --cookie-jar로 쿠키를 저장했는데, 다음 curl 요청에서는 다시 비로그인 응답을 받는다. 파일이 만들어졌더라도 새 curl 프로세스가 그 파일을 자동으로 읽지는 않는다. --cookie-jar(-c)는 저장할 파일을 정하고, --cookie(-b)는 읽을 파일을 정한다. 다음 요청을 만드는 명령에 읽기 옵션이 있는지 먼저 확인한다.
curl 공식 매뉴얼 (새 탭에서 열림)은 --cookie-jar의 파일을 출력 전용으로 설명한다. 두 옵션 모두 쿠키 처리 기능을 켜지만, -c만으로 기존 파일을 읽는 것은 아니다. 같은 curl 실행 안에서 받은 쿠키를 후속 요청에 쓰는 동작과, 종료 후 새 프로세스에서 파일을 읽는 동작을 구분해야 한다.
다음 요청에 읽을 파일을 지정한다
이미 쿠키를 저장했다면 다음 요청에 --cookie와 그 파일을 전달한다. 아래는 Windows의 curl.exe와 PowerShell 7을 쓰는 명령이다. $jarPath에는 앞서 저장한 jar의 실제 절대경로를, $requestUrl에는 그 쿠키를 받아야 하는 서비스의 URL을 넣는다. 예시의 경로와 도메인은 자신의 값으로 바꾼다.
이 블록은 파일이 있는지 확인한 뒤, 그 파일을 읽어 요청하도록 바꾼다.
$jarPath = 'C:\work\curl-session.cookies.txt'
$requestUrl = 'https://api.example.com/account/me'
if (-not (Test-Path -LiteralPath $jarPath -PathType Leaf)) {
throw 'Cookie file does not exist.'
}
curl.exe -q --silent --show-error --max-time 5 --cookie "$jarPath" "$requestUrl"
if ($LASTEXITCODE -ne 0) { throw 'curl request failed.' }
파일이 없으면 Cookie file does not exist.에서 멈춘다. 매뉴얼의 읽기 옵션 설명 (새 탭에서 열림)에 따르면 존재하지 않는 입력 파일은 무시되므로, 쿠키 없이 요청한 결과를 로그인 실패로 오해하지 않도록 먼저 검사한 것이다. 절대경로를 쓰면 명령을 실행한 폴더가 달라져 다른 파일을 가리키는 혼동도 줄일 수 있다.
요청이 끝나면 서비스의 응답 본문이 출력되며 내용은 서비스마다 다르다. 응답만으로 쿠키 전송을 단정하지 말고, 같은 요청을 받은 서버에서 필요한 쿠키 이름의 존재 여부를 확인한다. 실제 세션 값이나 jar 전체를 로그에 남길 필요는 없다. -q는 첫 옵션으로 두어 기본 curl 설정 파일의 영향을 제외했고, --max-time 5는 이 진단 요청을 5초로 제한한 값이다. 서비스의 응답 시간에 맞게 조정한다.
파일 로딩과 Path를 따로 비교했다
실제 로그인 대신 합성 쿠키 하나를 발급하는 새 HTTP 서버로 비교했다. Windows 11, Python 3.12.10, curl 8.21.0에서 서버를 127.0.0.1에만 열었다. /issue의 응답은 Set-Cookie: lab_session=seed; Path=/account; HttpOnly였고, 첫 curl 실행에서 --cookie-jar로 저장했다. 이 쿠키에는 만료 속성을 넣지 않았다.
저장 직후 jar에 쿠키 항목 하나가 있는 것을 확인했다. 저장 옵션만 비교할 때는 그 jar의 별도 복사본을 사용했고, 읽기 비교에서는 원래 파일을 유지했다. 아래는 줄마다 새 curl 프로세스로 요청한 뒤, 옵션·목적 경로·서버가 받은 Cookie 헤더만 추린 결과다. (absent)는 서버의 헤더 조회 결과가 없었다는 표시다.
--cookie-jar 복사본 /account/echo Cookie: (absent)
--cookie 원본 /account/echo Cookie: lab_session=seed
--cookie 원본 /other/echo Cookie: (absent)
--cookie 원본 /account/echo Cookie: lab_session=seed
저장 옵션만 준 첫 요청에는 쿠키가 없었다. 같은 경로에 읽기 옵션을 준 두 번째 요청에는 쿠키가 도착했다. 아무 쿠키 옵션도 주지 않은 별도 요청 역시 헤더가 없었다. 이 비교에서는 새 프로세스에 파일 읽기를 지정하는 것이 차이를 만들었다.
첫 요청이 끝난 뒤 복사본 파일은 남아 있었지만 쿠키 항목 수는 1개에서 0개로 바뀌었다. 그 요청의 응답은 새 쿠키를 발급하지 않았다. 기존 파일을 읽지 않아 메모리에 쿠키가 없는 상태에서 빈 내용을 저장한 결과다. 다음 요청에도 같은 -c만 붙이는 방식은 세션을 이어 주지 못하고, 저장해 둔 항목까지 지울 수 있다. 파일 존재 여부만으로 저장된 쿠키가 있다고 판단하면 안 된다.
세 번째 요청은 읽기 옵션을 넣었어도 Path=/account 바깥인 /other/echo여서 쿠키가 빠졌다. 같은 원본 파일로 /account/echo를 다시 요청하자 전송됐다. curl의 쿠키 설명 (새 탭에서 열림)은 쿠키가 설정된 도메인과 경로 범위에 맞는 후속 요청에 전송된다고 설명한다. 파일을 지정했는데도 빠진다면 파일 로딩과 실제 요청 URL의 적용 범위를 따로 확인해야 한다. 이 결과를 보고 쿠키의 Path를 무조건 /로 넓힐 이유는 없다.
응답에서 바뀐 쿠키도 다음 실행으로 넘기려면
읽기만 필요하면 --cookie로 충분하지만, 서버가 갱신한 쿠키까지 파일에 남겨야 한다면 저장 옵션도 함께 쓴다. 같은 파일을 입력과 출력으로 지정할 수 있다. 앞서 확인한 $jarPath와 $requestUrl을 그대로 쓰면서, 응답의 쿠키 변경을 다음 curl 실행에 전달하려는 명령이다.
curl.exe -q --silent --show-error --max-time 5 --cookie "$jarPath" --cookie-jar "$jarPath" "$requestUrl"
if ($LASTEXITCODE -ne 0) { throw 'curl request failed.' }
추가 비교에서 /account/refresh는 같은 이름과 Path로 값을 refreshed로 바꿔 발급했다. --cookie만 쓴 경우, 다음 새 프로세스가 파일을 읽어 보낸 값은 여전히 seed였다. 읽기와 저장을 함께 쓴 경우에는 다음 새 프로세스가 lab_session=refreshed를 보냈다. 응답에서 받은 변경을 이번 실행의 메모리에서 처리하는 것과 파일에 보존하는 것도 별개다.
직접 확인한 범위는 같은 호스트의 로컬 HTTP에서 합성 쿠키를 파일로 저장하고 새 curl 프로세스에 전달하는 과정이다. PowerShell 7.6.6에서도 위 읽기 명령의 구문과 파일 누락 시 중단을 확인했다. 실제 로그인·서버 세션의 유효성, HTTPS의 Secure 조건, 다른 호스트, 브라우저의 쿠키 정책, 여러 프로세스의 동시 jar 갱신은 검증하지 않았다. 쿠키 이름이 서버에 도착했는데도 인증이 실패한다면, 이번에 확인한 파일 로딩 누락만으로 설명할 수 없다.