본문 바로가기
C.W.K.
Stream
Lesson 06 of 06 · published

웹뷰가 네 헤더를 못 읽을 때

~13 min · tauri, cors, webview, networking

Level 0웹 관광객
0 XP0/56 lessons0/13 achievements
0/100 XP to next level100 XP to go0% complete
"네 프론트엔드는 여전히 브라우저야. fetch를 부르는 순간, 잊고 지내던 브라우저 규칙이 한꺼번에 돌아와 — CORS까지 포함해서."

함정: 웹뷰의 fetch는 브라우저 fetch야

잊기 쉬운데, 네 UI를 돌리는 웹뷰는 브라우저고 프론트엔드의 fetch()는 브라우저 보안을 그대로 따라 — CORS도 같이. 그중에서도 사람 미치게 하는 구석이 하나 있어. JavaScript는 서버가 Access-Control-Expose-Headers로 대놓고 허락한 응답 헤더만 읽을 수 있어. 요청은 성공하고, body도 멀쩡한데, response.headers.get("X-My-Custom")null을 돌려줘 — 헤더가 없어서가 아니라, 서버가 동의 안 하면 브라우저가 JS한테 숨기기 때문이야. 이게 Cinder의 디버깅 세션 하나를 통째로 잡아먹었어. 커스텀 헤더는 잘 오고 있었는데 웹뷰가 그냥 안 보여준 거지.

해결책 1: 헤더를 열어줘 (서버가 네 거면)

서버가 네 거면 헤더 이름을 Access-Control-Expose-Headers에 추가해. 그러면 웹뷰의 fetch가 읽을 수 있어. API가 네 손 안에 있으면 이게 올바른 해결책이야 — 그냥 평범한 CORS 설정이고, cross-origin API를 부르는 웹 앱이면 어차피 다 하는 일이니까.

해결책 2: Rust를 거쳐 가 (뒷문)

한 수 더 깊이 가면 이래. HTTP 호출을 웹뷰에서 아예 안 해. Rust에서 해 — command 안에서 reqwest나 공식 tauri-plugin-http로 — 그리고 데이터(나 네가 필요한 헤더)를 프론트엔드에 돌려줘. Rust 코어는 브라우저가 아니야. CORS가 걸리지 않아. 이러면 헤더 문제를 비껴가는 동시에 API 키 같은 비밀도 웹뷰 밖에 둘 수 있어. 프론트엔드 네트워킹이 CORS로 너랑 싸우기 시작하면, 그 요청이 사실은 Rust 쪽 일이 아닌지 물어봐.

Code

증상, 그리고 서버 쪽 해결책·text
// 헤더를 노출 안 한 서버 응답:
HTTP/1.1 200 OK
X-Request-Id: abc123
Access-Control-Allow-Origin: *

// 웹뷰에서:
const res = await fetch(url);
res.headers.get("X-Request-Id"); // → null  (헤더는 있는데 JS가 못 봄)

// expose_headers 있는 서버 응답:
Access-Control-Expose-Headers: X-Request-Id
// 이제 res.headers.get("X-Request-Id") → "abc123"
코어를 거쳐 CORS 비껴가기·rust
// 고침 2: Rust에서 요청 — CORS 없음, 헤더 완전 접근.
#[tauri::command]
async fn fetch_with_id(url: String) -> Result<(String, Option<String>), String> {
    let res = reqwest::get(&url).await.map_err(|e| e.to_string())?;
    let request_id = res
        .headers()
        .get("x-request-id")
        .and_then(|v| v.to_str().ok())
        .map(String::from);
    let body = res.text().await.map_err(|e| e.to_string())?;
    Ok((body, request_id)) // Rust가 자유롭게 읽은 헤더를 웹뷰에 건넴
}

External links

Exercise

커스텀 응답 헤더(X-Demo: hi)를 돌려주는 작은 로컬 서버를 아무거나 띄워. Tauri 프론트엔드에서 fetch하고 그 헤더를 읽어봐 — expose-headers 없이는 null인 걸 직접 확인해. 그다음 서버에 Access-Control-Expose-Headers를 추가하거나(또는 헤더를 읽어서 돌려주는 Rust command를 짜서) 이제 값이 보이는지 봐. 다신 이걸로 안 놀랄 거야.
Hint
Access-Control-Expose-Headers: X-Demo가 없으면 헤더가 보내졌어도 웹뷰에서 response.headers.get('X-Demo')는 null이야. Rust 쪽 길은 CORS를 통째로 비껴가 — reqwest는 어떤 헤더든 읽어.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.