fetchë¡ ìì²ì ë³´ë´ê² ë ì¬ì´í¸ê° íì¬ ì ì ì¬ì´í¸ì ë¤ë¥´ë¤ë©´ ìì²ì´ ì¤í¨í ì ììµëë¤.
ì§ì http://example.comë¼ë ì¬ì´í¸ì ìì²ì ë³´ë´ë´
ìë¤.
try {
await fetch('http://example.com');
} catch(err) {
alert(err); // TypeError: Failed to fetch
}
ìì²ì´ ì¤í¨í ê²ì íì¸í ì ìë¤ì.
ì ìì²ì´ ì¤í¨íëì§ ì기 ìí´ì ëë©ì¸Â·íë¡í ì½Â·í¬í¸ ì¸ ê°ì§ì ìí´ ê²°ì ëë ì¤ë¦¬ì§(origin) ì´ë¼ë íµì¬ ê°ë ì ììì¼ í©ëë¤.
ëë©ì¸ì´ë ìë¸ëë©ì¸, íë¡í ì½, í¬í¸ê° ë¤ë¥¸ ê³³ì ìì²ì ë³´ë´ë ê²ì Cross-Origin Request(í¬ë¡ì¤ ì¤ë¦¬ì§ ìì²)ë¼ê³ í©ëë¤. í¬ë¡ì¤ ì¤ë¦¬ì§ ìì²ì ë³´ë´ë ¤ë©´ ë¦¬ëª¨í¸ ì¤ë¦¬ì§ìì ì ì¡ë°ì í¹ë³í í¤ëê° íìí©ëë¤.
ì´ë¬í ì ì± ì 'CORS(Cross-Origin Resource Sharing, í¬ë¡ì¤ ì¤ë¦¬ì§ 리ìì¤ ê³µì )'ë¼ê³ ë¶ë¦ ëë¤.
ì CORSê° íìíê°ì ëí ì§§ì ìì¬
CORSë ì ì를 ê°ì§ í´ì»¤ë¡ë¶í° ì¸í°ë·ì ë³´í¸í기 ìí´ ë§ë¤ì´ì¡ìµëë¤.
ì§ê¸ë¶í´ ì´ë¤ ì¬ê±´ ë문ì CORSê° ë§ë¤ì´ì¡ëì§ë¥¼ ì§§ì ìì¬ë¥¼ íµí´ ì´í´ë³´ê² ìµëë¤.
과거 ì ë ëì, í ì¬ì´í¸ì ì¤í¬ë¦½í¸ìì ë¤ë¥¸ ì¬ì´í¸ì ìë ì½í ì¸ ì ì ê·¼í ì ìë¤ë ì ì½ì´ ìììµëë¤.
ì´ë° ê°ë¨íì§ë§ ê°ë ¥í ê·ì¹ì ì¸í°ë· ë³´ìì ìí ê·¼ê°ì´ììµëë¤. ë³´ì ê·ì¹ ëë¶ì í´ì»¤ê° ë§ë ì¹ ì¬ì´í¸ hacker.comìì gmail.comì ìë ë©ì¼ ë°ì¤ì ì ê·¼í ì ìë ê²ì´ì£ . ì¬ëë¤ì ì´ë° ì ì½ ëë¶ì ìì íê² ì¸í°ë·ì ì¬ì©í ì ìììµëë¤.
ê·¸ë°ë° ì´ ë¹ìì ìë°ì¤í¬ë¦½í¸ë ë¤í¸ìí¬ ìì²ì ë³´ë¼ ì ìì ë§í ë©ìë를 ì§ìíì§ ìììµëë¤. ìë°ì¤í¬ë¦½í¸ë ì¹ íì´ì§ë¥¼ 꾸미기 ìí í ì´ ëê·ì§ ìì¤ì´ìì£ .
íì§ë§ ë§ì ì¹ ê°ë°ìë¤ì´ ê°ë ¥í 기ë¥ì ìí기 ììíë©´ì ìì ê°ì ì ì½ì í¼í´ ë¤ë¥¸ ì¹ ì¬ì´í¸ì ìì²ì ë³´ë´ê¸° ìí í¸ë¦ë¤ì ë§ë¤ê¸° ììíìµëë¤.
í¼ ì¬ì©í기
í¸ë¦ ì¤ íëë¡ <form>ì´ ì¬ì©ë곤 íìµëë¤. ê°ë°ìë¤ì <form>ìì <iframe>ì ë£ì´ <form>ì ì ì¡íìµëë¤. ì´ë ê² í´ íì¬ ì¬ì´í¸ì ë¨ììì¼ë©´ì ë¤í¸ìí¬ ìì²ì ë³´ëìì£ . ìì를 ì´í´ë´
ìë¤.
<!-- í¼ target -->
<iframe name="iframe"></iframe>
<!-- ìë°ì¤í¬ë¦½í¸ë¥¼ ì¬ì©í´ í¼ì ëì ì¼ë¡ ìì±íê³ ë³´ë-->
<form target="iframe" method="POST" action="http://another.com/â¦">
...
</form>
ì´ ë¹ìì ë¤í¸ìí¬ ê´ë ¨ ë©ìëê° ììì§ë§, í¼ì ì´ëë ë°ì´í°ë¥¼ ë³´ë¼ ì ìë¤ë í¹ì§ì ì´ì©í´ í¼ì¼ë¡ ë¤ë¥¸ ì¬ì´í¸ì GET, POST ìì²ì ë³´ëììµëë¤. íì§ë§ ë¤ë¥¸ ì¬ì´í¸ìì <iframe>ì ìë ì½í
ì¸ ë¥¼ ì½ë ê²ì ê¸ì§ëì기 ë문ì ìëµì ì½ë ê²ì ë¶ê°ë¥íìµëë¤.
ê°ë°ìë¤ì iframeê³¼ íì´ì§ ì쪽ì í¹ë³í ì¤í¬ë¦½í¸ë¥¼ ì¬ì´ ì´ë° ì ì½ ìì í¼í ì ìë í¸ë¦ì ë§ë¤ììµëë¤. ì´ë ê² iframeì ì¬ì©í í¸ë¦ì ì¤ë¦¬ì§ì´ ë¤ë¥¸ ì¬ì´í¸ê°ìë ìë°©í¥ íµì ì´ ê°ë¥íëë¡ í´ì£¼ìì£ . ì´ë¤ ì¤í¬ë¦½í¸ë¥¼ ì¬ì©íë©´ ê°ë¥íì§ì ëí´ì ë¤ë¤ë ìë¯¸ê° ì기 ë문ì ìì¸í ë´ì©ì ëì´ê°ëë¡ íê² ìµëë¤.
ì¤í¬ë¦½í¸ ì¬ì©í기
script í그를 ì¬ì©íë ê² ìì ì ì½ì í¼í기 ìí í¸ë¦ì´ììµëë¤. script íê·¸ì src ìì±ê°ì ëë©ì¸ ì ì½ì´ ì기 ë문ì
ëë¤. ì´ í¹ì§ì ì´ì©íë©´ ì´ëìë ì¤í¬ë¦½í¸ë¥¼ ì¤íí ì ììµëë¤.
script í그를 ì¬ì©í´ <script src="http://another.com/â¦"> ííë¡ another.comì ë°ì´í°ë¥¼ ìì²íê² ëë©´ 'JSONP(JSON with padding)'ë¼ ë¶ë¦¬ë íë¡í ì½ì ì¬ì©í´ ë°ì´í°ë¥¼ ê°ì ¸ì¤ê² ë©ëë¤.
ë¨ê³ë³ë¡ ì´í´ë³´ë©´ ë¤ìê³¼ ê°ìµëë¤.
ë ì¨ ì ë³´ê° ì ì¥ëì´ ìë http://another.comìì ë°ì´í°ë¥¼ ê°ì ¸ìì¼ íë¤ê³ ê°ì íê² ìµëë¤.
-
먼ì ìë²ìì ë°ìì¨ ë°ì´í°ë¥¼ ìë¹íë ì ì í¨ì
gotWeather를 ì ì¸í©ëë¤.// 1. ë ì¨ ë°ì´í°ë¥¼ ì²ë¦¬íëë° ì¬ì©ëë í¨ì를 ì ì¸ function gotWeather({ temperature, humidity }) { alert(`temperature: ${temperature}, humidity: ${humidity}`); } -
ë¤ìì¼ë¡
src="http://another.com/weather.json?callback=gotWeather"를 ìì±ì¼ë¡ ê°ë<script>í그를 ë§ëëë¤. 1ìì ë§ë í¨ì를 URL 매ê°ë³ìcallbackì ê°ì¼ë¡ ì¬ì©íììµëë¤.let script = document.createElement('script'); script.src = `http://another.com/weather.json?callback=gotWeather`; document.body.append(script); -
ë¦¬ëª¨í¸ ìë²
another.comì í´ë¼ì´ì¸í¸ìì íìí ë ì¨ ë°ì´í°ì í¨ê»gotWeather(...)를 í¸ì¶íë ì¤í¬ë¦½í¸ë¥¼ ëì ì¼ë¡ ìì±í©ëë¤.// ìë²ë¡ë¶í° ë¤ìê³¼ ê°ì ííì ìëµì´ í´ë¼ì´ì¸í¸ë¡ ì ì¡ë©ëë¤. gotWeather({ temperature: 25, humidity: 78 }); -
ë¦¬ëª¨í¸ ìë²ìì ë°ìì¨ ì¤í¬ë¦½í¸ê° ë¡ë ë° ì¤íëë©´
gotWeatherê° í¸ì¶ë©ëë¤.gotWeatherë íì¬ íì´ì§ìì ë§ë í¨ìì´ê³ ìë²ìì ë°ì ë°ì´í°ë ì기 ë문ì ìíë 결과를 ì»ì ì ììµëë¤.
ì´ë° ê¼¼ì를 ì°ë©´ ë³´ì ê·ì¹ì ì´ê¸°ì§ ìì¼ë©´ìë ìë°©í¥ì¼ë¡ ë°ì´í°ë¥¼ ì ë¬í ì ììµëë¤. ì쪽ìì ëìí ìí©ì´ë¼ë©´ í´í¹ë ìëì£ . ìì§ë ì´ë° ë°©ìì ì¬ì©í´ íµì ì íë ìë¹ì¤ê° ììµëë¤. ì´ ë°©ìì ì¤ëë ë¸ë¼ì°ì ë ì§ìí©ëë¤.
ê·¸ë¬ë ìì¤ì ë¸ë¼ì°ì 측 ìë°ì¤í¬ë¦½í¸ìë ë¤í¸ìí¬ ê´ë ¨ ë©ìëê° ì¶ê°ë©ëë¤.
ì²ì ë¤í¸ìí¬ ìì² ë©ìëê° ë±ì¥íì ëì í¬ë¡ì¤ ì¤ë¦¬ì§ ìì²ì´ ë¶ê°ë¥íìµëë¤. íì§ë§ 긴 ë ¼ì ëì í¬ë¡ì¤ ì¤ë¦¬ì§ ìì²ì íì©íê¸°ë¡ ê²°ì í©ëë¤. ëì í¬ë¡ì¤ ì¤ë¦¬ì§ ìì²ì ìë²ìì ëª ìì ì¼ë¡ í¬ë¡ì¤ ì¤ë¦¬ì§ ìì²ì âíê°â íë¤ë ê²ì ìë ¤ì£¼ë í¹ë³í í¤ë를 ì ì¡ë°ìì ëë§ ê°ë¥íëë¡ ì ì½ì ê±¸ê² ë©ëë¤.
ìì í ìì²
í¬ë¡ì¤ ì¤ë¦¬ì§ ìì²ì í¬ê² ë ê°ì§ ì¢ ë¥ë¡ 구ë¶ë©ëë¤.
- ìì í ìì²(safe request)
- ê·¸ ì¸ì ìì²(ìì í ìì²ì´ ìë ìì²)
ìì í ìì²ì ê·¸ ì¸ì ìì² ëë¹ ë§ë¤ê¸° ì½ìµëë¤. ê·¸ë¬ë 먼ì ìì í ìì²ë¶í° ì´í´ë³´ëë¡ í©ìë¤.
ìì í ìì²ì ë¤ìê³¼ ê°ì ë ê°ì§ ì¡°ê±´ 모ë를 충족íë ë§ ê·¸ëë¡ ìì í ìì²ì ëë¤.
- ìì í ë©ìë(safe method) â GETì´ë POST, HEAD를 ì¬ì©í ìì²
- ìì í í¤ë(safe header) â ë¤ì 목ë¡ì ìíë í¤ë
AcceptAccept-LanguageContent-Language- ê°ì´
application/x-www-form-urlencodedì´ëmultipart/form-data,text/plainì¸Content-Type
ë ì¡°ê±´ì 모ë 충족íì§ ìë ìì²ì 'ìì íì§ ìì(unsafe) ìì²âì¼ë¡ ì·¨ê¸ë©ëë¤. PUT ë©ìë를 ì¬ì©íê±°ë í¤ëì API-Keyê° ëª
ìë ìì²ì ê²½ì°ê°ì´ ë§ì´ì£ .
ìì í ìì²ê³¼ ê·¸ë ì§ ìì ìì²ì 근본ì ì¸ ì°¨ì´ë í¹ë³í ë°©ë²ì ì¬ì©íì§ ìê³ ë <form>ì´ë <script>를 ì¬ì©í´ ìì²ì ë§ë¤ ì ìë¤ë ì ì ììµëë¤.
ì주 ì¤ëë ì¹ ìë²ë¼ë ìì í ìì²ì ë¹ì°í ì²ë¦¬í ì ìì´ì¼ íë ê²ì´ì£ .
íì¤ì´ ìë í¤ëê° ë¤ì´ìê±°ë ìì íì§ ìì ë©ìë(DELETE ë±)를 ì¬ì©í ìì²ì ìì í ìì²ì´ ë ì ììµëë¤. ì주 ì¤ëì ìë ìë°ì¤í¬ë¦½í¸ë¥¼ ì¬ì©í´ ì´ë° ìì²ì ë³´ë´ë ê²ì´ ë¶ê°ë¥ íìµëë¤. ë°ë¼ì ì°ìì´ ì¤ëë ìë²ë ì´ë° ìì²ì ë°ì¼ë©´ âì¹ íì´ì§ë ì´ë° ìì²ì ë³´ë¼ ì ìì기 ë문ìâ ëê° í¹ë³í ê³³ìì ìì²ì´ ììê±°ë¼ í´ìíììµëë¤.
ê·¸ë°ë° ìê°ì´ ì§ëê³ ê°ë°ìê° ìë°ì¤í¬ë¦½í¸ë¥¼ ì¬ì©í´ ìì íì§ ìì ìì²ì ë³´ë¼ ì ìê²ëì, ë¸ë¼ì°ì ë ìì íì§ ìì ìì²ì ìë²ì ì ì¡í기 ì ì âpreflightâ ìì²ì 먼ì ì ì¡í´ 'ìë²ê° í¬ë¡ì¤ ì¤ë¦¬ì§ ìì²ì ë°ì ì¤ë¹ê° ëì´ìëì§ë¥¼ íì¸âí©ëë¤.
ì´ë ìë²ìì í¬ë¡ì¤ ì¤ë¦¬ì§ ìì²ì íì©íì§ ìëë¤ë ì 보를 ë´ì í¤ë를 ë¸ë¼ì°ì ì ìëµíë©´ ìì íì§ ìì ìì²ì ìë²ë¡ ì ì¡ëì§ ììµëë¤.
ì´ì ê°ê´ì ì¸ ì¤ëª ì´ ëë¬ì¼ë CORSì ëí´ ì¢ ë ìì¸í ììë´ ìë¤.
CORSì ìì í ìì²
í¬ë¡ì¤ ì¤ë¦¬ì§ ìì²ì ë³´ë¼ ê²½ì° ë¸ë¼ì°ì ë íì Originì´ë¼ë í¤ë를 ìì²ì ì¶ê°í©ëë¤.
https://javascript.info/pageìì https://anywhere.com/requestì ìì²ì ë³´ë¸ë¤ê³ ê°ì í´ ë´
ìë¤. í¤ëë ë¤ìê³¼ ê°ì ííê° ë©ëë¤.
GET /request
Host: anywhere.com
Origin: https://javascript.info
...
ë³´ìë¤ìí¼ Origin í¤ëì ìì²ì´ ì´ë¤ì§ë íì´ì§ ê²½ë¡(/page)ê° ìë ì¤ë¦¬ì§(ëë©ì¸Â·íë¡í ì½Â·í¬í¸) ì ë³´ê° ë´ê¸°ê² ë©ëë¤.
ìë²ë ìì² í¤ëì ìë Origin를 ê²ì¬íê³ , ìì²ì ë°ìë¤ì´ê¸°ë¡ ëìí ìíë¼ë©´ í¹ë³í í¤ë Access-Control-Allow-Origin를 ìëµì ì¶ê°í©ëë¤. ì´ í¤ëì íê°ë ì¤ë¦¬ì§(ì ìììì https://javascript.info)ì ëí ì ë³´ë *ì´ ëª
ìë©ëë¤. ì´ë ìëµ í¤ë Access-Control-Allow-Originì ì¤ë¦¬ì§ ì ë³´ë *ì´ ë¤ì´ìì¼ë©´ ìëµì ì±ê³µíê³ ê·¸ë ì§ ìì¼ë©´ ìëµì´ ì¤í¨íê² ë©ëë¤.
ì´ ê³¼ì ìì ë¸ë¼ì°ì ë ì¤ì¬ì¸ì ìí ì í©ëë¤.
- ë¸ë¼ì°ì ë í¬ë¡ì¤ ì¤ë¦¬ì§ ìì² ì
Originì ê°ì´ ì ëë¡ ì¤ì , ì ì¡ëìëì§ íì¸í©ëë¤. - ë¸ë¼ì°ì ë ìë²ë¡ë¶í° ë°ì ìëµì
Access-Control-Allow-Originì´ ìëì§ë¥¼ íì¸í´ì ìë²ê° í¬ë¡ì¤ ì¤ë¦¬ì§ ìì²ì íì©íëì§ ìëì§ë¥¼ íì¸í©ëë¤. ìëµ í¤ëìAccess-Control-Allow-Originì´ ìë¤ë©´ ìë°ì¤í¬ë¦½í¸ë¥¼ ì¬ì©í´ ìëµì ì ê·¼í ì ìê³ ìëë¼ë©´ ìë¬ê° ë°ìí©ëë¤.
ìë²ìì í¬ë¡ì¤ ì¤ë¦¬ì§ ìì²ì íì©í ê²½ì°, preflight ìì²ì ëí ìëµì ë¤ìê³¼ ê°ì íí를 ëëë¤.
200 OK
Content-Type:text/html; charset=UTF-8
Access-Control-Allow-Origin: https://javascript.info
ìëµ í¤ë
í¬ë¡ì¤ ì¤ë¦¬ì§ ìì²ì´ ì´ë¤ì§ ê²½ì°, ìë°ì¤í¬ë¦½í¸ë 기본ì ì¼ë¡ âìì íâ ìëµ í¤ëë¡ ë¶ë¥ëë í¤ëìë§ ì ìí ì ììµëë¤. âìì íâ ìëµ í¤ëë ë¤ìê³¼ ê°ìµëë¤.
Cache-ControlContent-LanguageContent-TypeExpiresLast-ModifiedPragma
ì´ ì¸ì ìëµ í¤ëì ì ê·¼íë©´ ìë¬ê° ë°ìí©ëë¤.
ì 리ì¤í¸ì Content-Length í¤ëë ììµëë¤!
Content-Lengthë ìëµ ë³¸ë¬¸ í¬ê¸° ì 보를 ë´ê³ ìë í¤ëì
ëë¤. 무ì¸ê°ë¥¼ ë¤ì´ë¡ëíëë°, ë¤ì´ë¡ëê° ëª í¼ì¼í¸ë ì§íëìëì§ íì¸íë ¤ë©´ ì´ í¤ëì ì ê·¼í ì ìì´ì¼ í©ëë¤. ê·¸ë°ë° ì´ í¤ëì ì ê·¼íë ¤ë©´ í¹ë³í ê¶íì´ íìí©ëë¤. ìì¸í ë´ì©ì ìëìì ë¤ë£¨ê² ìµëë¤.
ìë°ì¤í¬ë¦½í¸ë¥¼ ì¬ì©í´ ìì íì§ ìì ìëµ í¤ëì ì ê·¼íë ¤ë©´ ìë²ìì Access-Control-Expose-Headersë¼ë í¤ë를 ë³´ë´ì¤ì¼ë§ í©ëë¤. Access-Control-Expose-Headersì ìë°ì¤í¬ë¦½í¸ ì ê·¼ì íì©íë ìì íì§ ìì í¤ë 목ë¡ì´ ë´ê²¨ììµëë¤. ê° í¤ëë 콤ë§ë¡ 구ë¶ë©ëë¤.
ìì:
200 OK
Content-Type:text/html; charset=UTF-8
Content-Length: 12345
API-Key: 2c9de507f2c54aa1
Access-Control-Allow-Origin: https://javascript.info
Access-Control-Expose-Headers: Content-Length,API-Key
ì´ë ê² Access-Control-Expose-Headers í¤ëê° ìëµ í¤ëì ìì´ì¼ë§ ìë°ì¤í¬ë¦½í¸ë¡ ìëµ í¤ëì Content-Lengthì API-Key를 ì½ì ì ììµëë¤.
ìì íì§ ìì ìì²
ìì¦ì ìì²ì GET, POST ë¿ë§ ìëë¼ PATCH, DELETE ë± ì´ë¤ ë©ìëë ì¬ì©í ì ììµëë¤.
ê·¸ë°ë° 과거ì ì¹íì´ì§ìì GET, POST ì´ì¸ì HTTP ë©ìë를 ì¬ì©í´ ìì²ì ë³´ë¼ ì ììê±°ë ììì¡°ì°¨ í ì ìììµëë¤. ìì§ê¹ì§ë ì´ë° ë©ìë를 ë¤ë£° ì ìë ì¹ìë²ë 꽤 ìì£ . ì´ë° ìë²ë¤ì GET, POST ì´ì¸ì ë©ìë를 ì¬ì©í ìì²ì´ ì¤ë©´ 'ì´ê±´ ë¸ë¼ì°ì ê° ë³´ë¸ ìì²ì´ ìëì¼âë¼ê³ íë¨íê³ ì ê·¼ ê¶íì íì¸í©ëë¤.
ì´ë° í¼ëì¤ë¬ì´ ìí©ì í¼íê³ ì ë¸ë¼ì°ì ë âìì íì§ ììâ ìì²ì´ ì´ë¤ì§ë ê²½ì°, ìë²ì ë°ë¡ ìì²ì ë³´ë´ì§ ìê³ âpreflightâ ìì²ì´ë¼ë ì¬ì ìì²ì ìë²ì ë³´ë´ ê¶íì´ ìëì§ë¥¼ íì¸í©ëë¤.
preflight ìì²ì OPTIONS ë©ìë를 ì¬ì©íê³ ë í¤ëê° í¨ê» ë¤ì´ê°ë©°, 본문ì ë¹ì´ììµëë¤.
Access-Control-Request-Methodí¤ë â ìì íì§ ìì ìì²ìì ì¬ì©íë ë©ìë ì ë³´ê° ë´ê²¨ììµëë¤.Access-Control-Request-Headersí¤ë â ìì íì§ ìì ìì²ìì ì¬ì©íë í¤ë 목ë¡ì´ ë´ê²¨ììµëë¤. ê° í¤ëë ì¼íë¡ êµ¬ë¶ë©ëë¤.
ìì íì§ ìì ìì²ì íì©íê¸°ë¡ íìíìë¤ë©´ ìë²ë ë³¸ë¬¸ì´ ë¹ì´ìê³ ìí ì½ëê° 200ì¸ ìëµì ë¤ìê³¼ ê°ì í¤ëì í¨ê» ë¸ë¼ì°ì ë¡ ë³´ë ëë¤.
Access-Control-Allow-Originâ*ì´ë ìì²ì ë³´ë¸ ì¤ë¦¬ì§ ì´ì´ì¼ í©ëë¤(ì: https://javascript.info)Access-Control-Allow-Methodsâ íì©ë ë©ìë ì ë³´ê° ë´ê²¨ììµëë¤.Access-Control-Allow-Headersâ íì©ë í¤ë 목ë¡ì´ ë´ê²¨ììµëë¤.Access-Control-Max-Ageâ í¼ë¯¸ì ì²´í¬ ì¬ë¶ë¥¼ ëª ì´ê° ìºì±í´ ëìì§ë¥¼ ëª ìí©ëë¤. ì´ë ê² í¼ë¯¸ì ì 보를 ìºì±í´ ëì¼ë©´ ë¸ë¼ì°ì ë ì¼ì ê¸°ê° ëì preflight ìì²ì ìëµíê³ ìì íì§ ìì ìì²ì ë³´ë¼ ì ììµëë¤.
íìí ê°ë
ì ì¶©ë¶í ë¤ë¤ì¼ë ì´ì ì¤ì ìì íì§ ìì í¬ë¡ì¤ ì¤ë¦¬ì§ ìì²ì´ ì´ë»ê² ì´ë¤ì§ëì§ ìì를 íµí´ ì´í´ë´
ìë¤. ìììì PATCH ë©ìë를 ì¬ì©í´ ìì²ì ë³´ë´ê² ìµëë¤. ì°¸ê³ ë¡ PATCH ë©ìëë ë°ì´í°ë¥¼ ê°±ì í ë ì주 ì°ì
ëë¤.
let response = await fetch('https://site.com/service.json', {
method: 'PATCH',
headers: {
'Content-Type': 'application/json',
'API-Key': 'secret'
}
});
ì°¸ê³ ë¡ ì ìì²ì´ ìì íì§ ìì ìì²ì¼ë¡ ë¶ë¥ëë ë°ë ì¸ ê°ì§ ì´ì ê° ììµëë¤.
PATCHë©ìë를 ì¬ì©íê³ ììµëë¤.Content-Typeì´application/x-www-form-urlencodedëmultipart/form-data,text/plainê° ìëëë¤.- ë¹íì¤ í¤ë
API-Key를 ì¬ì©í©ëë¤.
1ë¨ê³(preflight ìì²)
본 ìì²ì ë³´ë´ê¸° ì ì ë¸ë¼ì°ì ë ìì²´ì ì¼ë¡ ë¤ìê³¼ ê°ì preflight ìì²ì ë³´ë ëë¤.
OPTIONS /service.json
Host: site.com
Origin: https://javascript.info
Access-Control-Request-Method: PATCH
Access-Control-Request-Headers: Content-Type,API-Key
- ë©ìë â
OPTIONS - ê²½ë¡ â 본 ìì²ê³¼ ëì¼í ê²½ë¡(
/service.json) - í¬ë¡ì¤ ì¤ë¦¬ì§ í¹ì í¤ë:
Originâ 본 ìì²ì ì¤ë¦¬ì§Access-Control-Request-Methodâ 본 ìì²ìì ì¬ì©íë ë©ìëAccess-Control-Request-Headersâ 본 ìì²ìì ì¬ì©íë ìì íì§ ìì í¤ë 목ë¡(콤ë§ë¡ 구ë¶)
2ë¨ê³(preflight ìëµ)
ìë²ë ìí ì½ë 200ê³¼ í¨ê» ë¤ìê³¼ ê°ì í¤ë를 ë´ì ìëµì ë³´ë ëë¤.
Access-Control-Allow-Methods: PATCHAccess-Control-Allow-Headers: Content-Type,API-Key
ì´ë ê² ìëµì´ ìì¼ ë¹ë¡ì 본 ìì²ì ë³´ë¼ ì ììµëë¤. ê·¸ë ì§ ìì¼ë©´ ìë¬ê° ë°ìí©ëë¤.
미ëì PATCH ì´ì¸ì ë©ìëì ë¤ìí í¤ë를 íì©í ì ìëë¡ ì¸í
íë ¤ë©´ Access-Control-Allow-Methodsì Access-Control-Allow-Headersì ìíë ë©ìëì í¤ë를 ì¶ê°í´ ëì¼ë©´ ë©ëë¤.
ìëì ê°ì´ ë§ì´ì£ .
200 OK
Access-Control-Allow-Origin: https://javascript.info
Access-Control-Allow-Methods: PUT,PATCH,DELETE
Access-Control-Allow-Headers: API-Key,Content-Type,If-Modified-Since,Cache-Control
Access-Control-Max-Age: 86400
ì´ë ê² ìë²ìì preflight ìëµì´ ì¤ë©´ ë¸ë¼ì°ì ë Access-Control-Allow-Methodsì PATCHê° ìë ê²ì íì¸íê³ , ì´ì´ì Access-Control-Allow-Headersì Content-Typeê³¼ API-Keyê° ìë ê²ì íì¸í©ëë¤. ë ë¤ ìë ê²ì íì¸í기 ë문ì ì´ì ë¸ë¼ì°ì ë 본 ìì²ì ìë²ì ë³´ë
ëë¤.
ì°¸ê³ ë¡ Access-Control-Max-Age í¤ëê° ìëµì¼ë¡ ì¤ë©´ preflight íì© ì¬ë¶ê° í¤ëì í¨ê» ìºì±ë기 ë문ì ë¸ë¼ì°ì ë í¤ë ê°ì ëª
ìí ì´ëì preflight ìì²ì ë³´ë´ì§ ììµëë¤. ë°ë¼ì ì ììì²ë¼ ìëµì´ ì¨ ê²½ì°ì í루ëì preflight ìì²ì ì ì¡íì§ ìê³ ë°ë¡ 본 ìì²ì´ ì ì¡ë©ëë¤.
3ë¨ê³(ì¤ì ìì²)
preflight ìì²ì´ ì±ê³µì ì¼ë¡ ì´ë¤ì§ íìì¼ ë¸ë¼ì°ì ë 본 ìì²ì ë³´ë ëë¤. ì§ê¸ë¶í°ì íë¡ì¸ì¤ë ìì í ìì²ì´ ì´ë¤ì§ëì ì ì°¨ì ëì¼í©ëë¤.
본 ìì²ì í¬ë¡ì¤ ì¤ë¦¬ì§ ìì²ì´ê¸° ë문ì Origin í¤ëê° ë¶ìµëë¤.
PATCH /service.json
Host: site.com
Content-Type: application/json
API-Key: secret
Origin: https://javascript.info
4ë¨ê³(ì¤ì ìëµ)
ìë²ìì 본 ìëµì Access-Control-Allow-Origin í¤ë를 ë°ëì ë¶ì¬ì¤ì¼ í©ëë¤. preflight ìì²ì´ ì±ê³µíëë¼ë ë§ì´ì£ .
Access-Control-Allow-Origin: https://javascript.info
ì´ ëª¨ë ê³¼ì ì´ ëëì¼ ìë°ì¤í¬ë¦½í¸ë¥¼ ì¬ì©í´ ì¤ì ìëµì ì½ì ì ììµëë¤.
preflight ìì²ì â무ë ë°ììâ ì¼ì´ë기 ë문ì ìë°ì¤í¬ë¦½í¸ë¥¼ ì¬ì©í´ ê´ì°°í ìë ììµëë¤.
ìë°ì¤í¬ë¦½í¸ë¡ë 본 ìì²ì ìëµì ë°ë ì¼ë§ í ì ììµëë¤. ìë²ìì í¬ë¡ì¤ ì¤ë¦¬ì§ ìì²ì íì©íì§ ìë ê²½ì°ì ìë¬ê° ë°ìí©ëë¤.
ì격 ì¦ëª
ìë°ì¤í¬ë¦½í¸ë¡ í¬ë¡ì¤ ì¤ë¦¬ì§ ìì²ì ë³´ë´ë ê²½ì°, 기본ì ì¼ë¡ ì¿ í¤ë HTTP ì¸ì¦ ê°ì ì격 ì¦ëª (credential)ì´ í¨ê» ì ì¡ëì§ ììµëë¤.
HTTP ìì²ì ê²½ì° ëê° ì¿ í¤ê° í¨ê» ì ì¡ëëë°, ìë°ì¤í¬ë¦½í¸ë¥¼ ì¬ì©í´ ë§ë í¬ë¡ì¤ ì¤ë¦¬ì§ ìì²ì ìì¸ì´ì£ .
ë°ë¼ì fetch('http://another.com')를 ì¬ì©í´ ìì²ì ë³´ë´ë another.com ê´ë ¨ ì¿ í¤ê° í¨ê» ì ì¡ëì§ ììµëë¤.
ì ê·¸ë´ê¹ì?
ì´ë° ìì¸ê° ì긴 ì´ì ë ì격 ì¦ëª ê³¼ í¨ê» ì ì¡ëë ìì²ì ê²½ì° ìí¥ë ¥ì´ ê°í기 ë문ì ëë¤. í¬ë¡ì¤ ì¤ë¦¬ì§ ìì² ì ì격 ì¦ëª ì í¨ê» ì ì¡í ì ìì¼ë©´ ì¬ì©ì ëì ìì´ ìë°ì¤í¬ë¦½í¸ë¡ 민ê°í ì ë³´ì ì ê·¼í ì ìê² ë©ëë¤.
ê·¸ë¼ìë ë¶êµ¬íê³ ìë²ìì ì´ë¥¼ íì©íê³ ì¶ë¤ë©´, ì격 ì¦ëª ì´ ë´ê¸´ í¤ë를 ëª ìì ì¼ë¡ íì©íê² ë¤ë ì¸í ì ìë²ì í´ì¤ì¼ í©ëë¤.
fetch ë©ìëì ì격 ì¦ëª
ì 보를 í¨ê» ì ì¡íë ¤ë©´ ë¤ìê³¼ ê°ì´ credentials: "include" ìµì
ì ì¶ê°íë©´ ë©ëë¤.
fetch('http://another.com', {
credentials: "include"
});
ì´ë ê² ìµì
ì ì¶ê°íë©´ fetchë¡ ìì²ì ë³´ë¼ ë another.comì ëìíë ì¿ í¤ê° í¨ê» ì ì¡ë©ëë¤.
ì격 ì¦ëª
ì ë³´ê° ë´ê¸´ ìì²ì ìë²ìì ë°ìë¤ì´ê¸°ë¡ ëìíë¤ë©´ ìë²ë ìëµì Access-Control-Allow-Origin í¤ëì í¨ê» Access-Control-Allow-Credentials: true í¤ë를 ì¶ê°í´ì ë³´ë
ëë¤.
ìì:
200 OK
Access-Control-Allow-Origin: https://javascript.info
Access-Control-Allow-Credentials: true
ì격 ì¦ëª
ì´ í¨ê» ì ì¡ëë ìì²ì ë³´ë¼ ë Access-Control-Allow-Originì *ì ì¸ ì ììµëë¤. ì ììììì²ë¼ Access-Control-Allow-Originì ì íí ì¤ë¦¬ì§ ì ë³´ë§ ëª
ìëì´ì¼ í©ëë¤. ì´ë° ì ì½ì´ ìì´ì¼ ì´ë¤ ì¤ë¦¬ì§ìì ìì²ì´ ìëì§ì ëí ì 보를 ìë²ê° ì 뢰í ì ì기 ë문ì
ëë¤.
ìì½
ë¸ë¼ì°ì ê´ì ìì í¬ë¡ì¤ ì¤ë¦¬ì§ ìì²ì ìì í(safe) í¬ë¡ì¤ ì¤ë¦¬ì§ ìì²ê³¼ ê·¸ë ì§ ìì í¬ë¡ì¤ ì¤ë¦¬ì§ ìì² ë ë¶ë¥ë¡ ëë©ëë¤.
ìì í ìì²ì ë¤ì ì¡°ê±´ì 모ë 충족íë ìì²ì ëë¤.
- ë©ìë: GETì´ë POST í¹ì HEAD
- í¤ë:
AcceptAccept-LanguageContent-Language- ê°ì´
application/x-www-form-urlencodedëmultipart/form-data,text/plainì¸Content-Type
ìì í ìì²ì ì주 ì¤ëì ë¶í° <form>ì´ë <script>í그를 ì¬ì©í´ë ê°ë¥íë ìì²ì¸ ë°ë©´ ìì íì§ ìì ìì²ì ë¸ë¼ì°ì ìì ë³´ë¼ ì ììë ìì²ì´ë¼ë ì ì´ ë ìì²ì 근본ì ì¸ ì°¨ì´ì
ëë¤.
ì¤ë¬´ ê´ì ìì ë ìì²ì ì°¨ì´ë ìì í ìì²ì Origin í¤ëì í¨ê» ë°ë¡ ìì²ì´ ì ì¡ëë ë°ë©´ ìì íì§ ìì ìì²ì ë¸ë¼ì°ì ìì 본 ìì²ì´ ì´ë¤ì§ê¸° ì ì preflight ìì²ì´ë¼ ë¶ë¦¬ë ì¬ì ìì²ì ë³´ë´ í¼ë¯¸ì
ì¬ë¶ë¥¼ 물ì´ë³¸ë¤ë ì ì
ëë¤.
ìì í ìì²ì ë¤ìê³¼ ê°ì ì 차를 ë°ë¦ ëë¤.
- â ì¤ë¦¬ì§ ì ë³´ê° ë´ê¸´
Originí¤ëì í¨ê» ë¸ë¼ì°ì ê° ìì²ì ë³´ë ëë¤. - â ì격 ì¦ëª
ì´ ìë ìì²ì ê²½ì°(기본), ìë²ë ìëì ê°ì ìëµì ë³´ë
ëë¤.
Originê°ê³¼ ëì¼íê±°ë*ì¸Access-Control-Allow-Origin
- â ì격 ì¦ëª
ì´ ìë ìì²ì ê²½ì° ìë²ë ìëì ê°ì ìëµì ë³´ë
ëë¤.
Originê°ê³¼ ëì¼íAccess-Control-Allow-Origin- ê°ì´
trueì¸Access-Control-Allow-Credentials
ìë°ì¤í¬ë¦½í¸ë¥¼ ì¬ì©í´ Cache-Controlì´ë Content-Language, Content-Type, Expires, Last-Modified, Pragma를 ì ì¸í ìëµ í¤ëì ì ê·¼íë ¤ë©´ ìëµ í¤ëì Access-Control-Expose-Headersì ì ê·¼ì íì©íë í¤ëê° ëª
ìë¼ ìì´ì¼ í©ëë¤.
ìì íì§ ìì ìì²ì ì ì°¨ë ë¤ìê³¼ ê°ìµëë¤. ì¬ì ìì²ì¸ âpreflightâ ìì²ì´ 본 ìì² ì ì ì ì¡ë©ëë¤.
- â ë¸ë¼ì°ì ë ëì¼í URLì
OPTIONSë©ìë를 ì¬ì©í preflight ìì²ì ë³´ë´ê² ëëë°, ì´ë í¤ëì ë¤ìê³¼ ê°ì ì ë³´ê° ë¤ì´ê°ëë¤.Access-Control-Request-Methodâ 본 ìì²ì ë©ìë ì ë³´ê° ë´ê¹Access-Control-Request-Headersâ 본 ìì²ì í¤ë ì ë³´ê° ë´ê¹
- â ìë²ë ìí ì½ë 200ê³¼ ìëì ê°ì í¤ë를 ë´ì ìëµì ì ì¡í©ëë¤.
Access-Control-Allow-Methodsâ íì©ëë ë©ìë 목ë¡ì´ ë´ê¹Access-Control-Allow-Headersâ íì©ëë í¤ë 목ë¡ì´ ë´ê¹Access-Control-Max-Ageâ ëª ì´ê° preflight ìì² ìì´ í¬ë¡ì¤ ì¤ë¦¬ì§ ìì²ì ë°ë¡ ë³´ë¼ì§ì ëí ì ë³´ê° ë´ê¹
- ì´íì 본 ìì²ì´ ì ì¡ëê³ , ì ì°¨ë âìì íâ ìì²ê³¼ ëì¼í©ëë¤.
ëê¸
<code>í그를, ì¬ë¬ ì¤ë¡ 구ì±ë ì½ë를 ì½ì íê³ ì¶ë¤ë©´<pre>í그를 ì´ì©íì¸ì. 10ì¤ ì´ìì ì½ëë plnkr, JSBin, codepen ë±ì ìëë°ì¤ë¥¼ ì¬ì©íì¸ì.