# 공유 크롤러(카카오톡·트위터·페북 등) 판별 → /match/:id 만 백엔드 OG 프리렌더로. # 일반 사용자(JS 실행)는 0 → 기존 SPA 그대로. map $http_user_agent $is_share_crawler { default 0; "~*(kakaotalk|facebookexternalhit|facebot|twitterbot|slackbot|discordbot|telegrambot|whatsapp|line\\b|skypeuripreview|pinterest|redditbot|googlebot|bingbot|daumoa|yeti)" 1; } server { listen 80; server_name _; root /usr/share/nginx/html; index index.html; # API 는 백엔드(api 서비스)로 프록시 → 브라우저는 동일 출처로 호출(CORS 불필요). location /api/ { proxy_pass http://api:8000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } # 경기 공유 링크: 크롤러면 백엔드 OG 프리렌더, 사람이면 SPA. # (418 → 내부 named location 으로 우회: if + try_files 충돌 회피 정석 패턴) location /match/ { error_page 418 = @og_prerender; if ($is_share_crawler) { return 418; } try_files $uri /index.html; } location @og_prerender { proxy_pass http://api:8000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } # SPA 폴백 — 클라이언트 라우팅(/match/:id 등) location / { try_files $uri $uri/ /index.html; } }