πŸ› [νŠΈλŸ¬λΈ”μŠˆνŒ…] B2C 결제 cross-origin 이슈 ν•΄κ²° feat. window.postMessage()

μ΄μ„œΒ·2024λ…„ 1μ›” 23일
1

🌱 νšŒμ‚¬ log

λͺ©λ‘ 보기
1/2

κ°œμš”

Uncaught DOMException: Blocked a frame with origin "https://pac.domain.com" 
from accessing a cross-origin frame.
Uncaught SecurityError: Failed to read a named property 'parentSomethingProperty' 
on 'Window': Blocked a frame with origin "https://pac.domain.com" 
from accessing a cross-origin frame.

μ •μƒμ μœΌλ‘œ μ§„ν–‰λ˜λ˜ κ²°μ œμ—μ„œ κ°‘μžκΈ° μœ„μ™€ 같은 μ—λŸ¬λ‘œ κ²°μ œκ°€ λΆˆκ°€λŠ₯ν•œ 상황이 λ°œμƒν–ˆμ–΄μš”. μ½”λ“œκ°€ λ³€κ²½λœ 것도 μ—†μ—ˆλŠ”λ° κ°‘μžκΈ° μ™œ 이런 μ—λŸ¬κ°€ λ°œμƒλ˜μ—ˆμ„κΉŒμš”?

원인 뢄석

μœ„μ˜ μ—λŸ¬ λ©”μ‹œμ§€λ₯Ό 확인해보면 https://pac.domain.com μ£Όμ†Œμ˜ 접근이 μ°¨λ‹¨λ˜μ—ˆλ‹€λŠ” 것을 확인해볼 수 μžˆμ–΄μš”. μ—¬κΈ°μ„œ ν¬μΈνŠΈλŠ” cross-orginμ΄λΌλŠ” λ©”μ‹œμ§€μ—μš”.

cross-originμ΄λž€ ꡐ차 좜처λ₯Ό λœ»ν•˜κ³  CORS(Cross Origin Resource Sharing)λž€ ꡐ차 μΆœμ²˜μ—μ„œμ˜ μžμ› 곡유λ₯Ό λœ»ν•΄μš”. κ·Έλ ‡λ‹€λ©΄ μΆœμ²˜λž€ λ¬΄μ—‡μΌκΉŒμš”?

좜처의 κ°œλ…

https://leeseo.mydomain.com:443/post/search?page=1#CORSλž€
  • https://: Protocol
  • leeseo.mydomain.com: Host
  • 443: Port(μƒλž΅ κ°€λŠ₯)
  • /post/search: Path
  • ?page=1: Query String
  • #CORSλž€: Fragment

μœ„μ˜ URLμ—μ„œ Protocol, Host, Port 이 3가지가 동일할 λ•Œ 동일 좜처(Same-origin)라고 ν•΄μš”.

λ§Œμ•½ Protocol, Host, Port 쀑 단 ν•˜λ‚˜λΌλ„ λ‹€λ₯΄λ‹€λ©΄ ꡐ차 좜처(Cross-origin)둜 κ°„μ£ΌλΌμš”.

μ„œλ²„μ—μ„œ CORS 섀정은 이미 쑴재

κΈ°μ‘΄ μ„œλ²„μΈ‘ μ½”λ“œμ—μ„œλŠ” CORS에 κ΄€ν•œ μ½”λ“œκ°€ 이미 μž‘μ„±λ˜μ–΄ μžˆμ—ˆμ–΄μš”. κ·ΈλŸΌμ—λ„ λΆˆκ΅¬ν•˜κ³  μœ„μ™€ 같은 ꡐ차 좜처 λ¬Έμ œκ°€ λ°œμƒλ˜κ³  μžˆμ—ˆμ–΄μš”.

μš°λ¦¬κ°€ 많이 μ ‘ν•˜λŠ” CORSλŠ” ν”„λ‘ νŠΈμ™€ λ°±μ—”λ“œ μ„œλ²„μ˜ ν†΅μ‹ μ—μ„œ ꡐ차 좜처둜 인해 λ°œμƒλ˜λŠ” μ΄μŠˆκ°€ λ§Žμ•˜μ–΄μš”. μ΄λ‘œμΈν•΄ CORS와 κ΄€λ ¨λœ 검색을 ν•˜λ©΄ λŒ€λΆ€λΆ„ ν”„λ‘ νŠΈμ™€ μ„œλ²„μ˜ ν†΅μ‹ μ—μ„œ μ„œλ²„μ— CORS ν•΄μ œ 방법과 κ΄€λ ¨ν•œ μ •λ³΄λ§Œ 많이 λ‚˜μ™€ ν•΄λ‹Ή 이슈의 원인을 νŒŒμ•…ν•˜λŠ”λ° 어렀움이 μžˆμ—ˆμ–΄μš”.

μ €ν¬λŠ” μŠ€ν”„λ§ λΆ€νŠΈ(Spring Boot)와 μŠ€ν”„λ§ μ‹œνλ¦¬ν‹°(Spring Security)λ₯Ό μ‚¬μš© μ€‘μ΄μ—ˆλŠ”λ° ν•΄λ‹Ή κ΄€λ ¨ 정보도 μ „λΆ€ μŠ€ν”„λ§ μ‹œνλ¦¬ν‹°μ—μ„œ CORS κ΄€λ ¨ μ„€μ •ν•˜λŠ” λ°©λ²•μ΄λ‚˜ μŠ€ν”„λ§μ—μ„œ μ§€μ›ν•˜λŠ” @CrossOrigin을 ν™œμš©ν•˜λŠ” λ°©λ²•λ§Œ λ‚˜μ™”μ–΄μš”.

λ”°λΌμ„œ 관점을 λ‹¬λ¦¬ν•˜κ³  처음으둜 λŒμ•„κ°€ ν•΄λ‹Ή λ¬Έμ œμ— λŒ€ν•œ 근본적인 원인을 λ‹€μ‹œ νŒŒμ•…ν•΄λ³΄κΈ°λ‘œ ν–ˆμ–΄μš”.

μ½”λ“œ 뢄석

원인을 뢄석할 λ•Œ ꡐ차 μΆœμ²˜λΌλŠ” μ—λŸ¬ λ©”μ‹œμ§€μ˜ λ‚΄μš©λ§ŒμœΌλ‘œ νŒλ‹¨ν•˜μ—¬ ν•΄κ²°ν•˜λ € ν–ˆλ˜ 것이 νŒ¨μ°©μ΄μ—ˆμ–΄μš”. λ”°λΌμ„œ κΈ°μ‘΄ μ½”λ“œλ₯Ό λ‹€μ‹œ λΆ„μ„ν•˜κΈ°λ‘œ ν–ˆμ–΄μš”.

μ €ν¬μ˜ 결제 μ‹œμŠ€ν…œμ€ μ•„λž˜μ™€ 같은 μ‹œν€€μŠ€λ‘œ κ΅¬μ„±λ˜μ–΄ μžˆμ–΄μš”. 이해λ₯Ό 돕기 μœ„ν•΄ Pathλ‚˜ κ΄€λ ¨ 데이터 μ„ΈνŒ… 및 μ˜ˆμ™Έμ²˜λ¦¬ 등은 μƒλž΅ν•˜λ„λ‘ ν• κ²Œμš”.

  1. mydomain.comμ—μ„œ νŒμ—…μ„ μ˜€ν”ˆν•΄μš”.
// μš°μ„  빈 νŒμ—…μ„ μ˜€ν”ˆν•΄μš”.
window.open('about:blank', 'pay-popup', 'width=600,height=400');

// μžλ°”μŠ€ν¬λ¦½νŠΈλ₯Ό 톡해 λ™μ μœΌλ‘œ λ§Œλ“€μ–΄ ν˜ΈμΆœν•  μˆ˜λ„ μžˆμ–΄μš”.
// 이해λ₯Ό 돕기 μœ„ν•΄ html둜 μž‘μ„±ν• κ²Œμš”.
// 1차적으둜 κ²°μ œμ™€ κ΄€λ ¨ν•œ 데이터λ₯Ό μ…‹νŒ…ν•΄μš”.
// 저희 결제 μ„œλ²„μ— 데이터λ₯Ό μ „μ†‘ν•˜λŠ” form을 μž‘μ„±ν•΄μš”.
<form id="pay" action="https://pac.mydomain.com/requestPay" style="display: none;">
	<input id="info1" name="info1" value="info1" />
</form>

// pay-popup이 pac.mydomain.com으둜 μ΄λ™λΌμš”.
document.getElementByid("pay").submit();
  1. pac.mydomain.com μ„œλ²„μ—μ„œ 결제 κ΄€λ ¨ 데이터λ₯Ό μ„ΈνŒ…ν•˜κ³  결제 벀더사에 μš”μ²­ν•΄μš”.
<form id="pay-request" action="https://www.payment.com/blabla" style="display: none;">
	// κ²°μ œμ™€ κ΄€λ ¨λœ 데이터 μ…‹νŒ…
	<input id="returnUrl" 
		   name="returnUrl" 
	   	   value="https://pac.mydomain.com/returnPay" 
	/>
</form>

// 폼 λ°©μ‹μœΌλ‘œ ν˜„μž¬ νŒμ—…μ—μ„œ 벀더사에 결제 νŽ˜μ΄μ§€λ₯Ό μš”μ²­(submit)ν•΄μš”.
document.getElementById('pay-request').submit();
  1. 고객이 결제 벀더사 νŽ˜μ΄μ§€μ—μ„œ 결제λ₯Ό μ™„λ£Œν•˜λ©΄ returnUrl에 따라 저희 μ„œλ²„λ‘œ λ‹€μ‹œ μš”μ²­ν•΄μš”.
  2. pac.mydomain.com μ„œλ²„μ—μ„œ λ²€λ”μ‚¬μ˜ responseλ₯Ό λ°›μ•„ 성곡일 경우 λΆ€λͺ¨ νŽ˜μ΄μ§€μ˜ 결제 성곡 ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•΄μš”.
// 결제 응닡이 성곡일 경우 mydomain.com에 μžˆλŠ”
// successPaymentλ₯Ό ν˜ΈμΆœν•˜μ—¬ 결제 μ™„λ£Œ νŽ˜μ΄μ§€λ‘œ μ΄λ™ν•΄μš”.
parent.successPayment(data);

λ¬Έμ œλŠ” 4λ²ˆμ—μ„œ λ°œμƒλ˜μ—ˆμ–΄μš”. λ§Œμ•½ ν”„λ‘ νŠΈμ™€ μ„œλ²„μ˜ ꡐ차 좜처 λ¬Έμ œμ˜€λ‹€λ©΄ 결제 μ„œλ²„μ— μ‘΄μž¬ν•˜λŠ” μŠ€ν”„λ§ μ‹œνλ¦¬ν‹°μ—μ„œ CORS κ΄€λ ¨ ν•΄μ œ μ½”λ“œλ‘œ 해결이 λ˜μ—ˆμ„ κ±°μ—μš”. ν•˜μ§€λ§Œ μœ„μ˜ λ¬Έμ œλŠ” ν”„λ‘ νŠΈμ™€ λ°±μ—”λ“œ ν†΅μ‹ μ—μ„œ λ°œμƒν•˜λŠ” CORS λ¬Έμ œκ°€ μ•„λ‹ˆλΌ νŒμ—…μ—μ„œ λΆ€λͺ¨ νŽ˜μ΄μ§€μ˜ μžμ›μ— μ ‘κ·Όν•  λ•Œ λ°œμƒλ˜λŠ” ꡐ차 좜처 λ¬Έμ œμ˜€μ–΄μš”.

우리 ν™ˆνŽ˜μ΄μ§€(λΆ€λͺ¨ νŽ˜μ΄μ§€)λŠ” mydomain.com인데 결제 μ„œλ²„(νŒμ—…)λŠ” pac.mydomain.com으둜 κ΅¬μ„±λ˜μ–΄ 있기 λ•Œλ¬Έμ— ꡐ차 μΆœμ²˜κ°€ λ°œμƒλ˜μ–΄ νŒμ—…μ—μ„œ λΆ€λͺ¨ νŽ˜μ΄μ§€μ— μžˆλŠ” successPayment ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•˜μ§€ λͺ»ν•˜λŠ” κ²ƒμ΄μ—ˆμ£ . (MSA ꡬ쑰둜 ν™ˆνŽ˜μ΄μ§€ μ„œλ²„μ™€ 결제 μ„œλ²„κ°€ λΆ„λ¦¬λ˜μ–΄ μžˆμ–΄μš”.)

ν•˜μ§€λ§Œ μ™œ κ°‘μžκΈ° ꡐ차 좜처 λ¬Έμ œκ°€ λ°œμƒλ˜μ—ˆμ„κΉŒμš”? κΈ°μ‘΄μ—λŠ” μ™œ μ •μƒμ μœΌλ‘œ κ²°μ œκ°€ 진행 λ˜μ—ˆμ„κΉŒμš”?

κΈ°μ‘΄ μ½”λ“œ

κΈ°μ‘΄ μ½”λ“œμ—μ„œλŠ” ꡐ차 좜처 문제λ₯Ό ν•΄κ²°ν•˜κΈ° μœ„ν•΄ 결제 μ„œλ²„μ˜ μžλ°”μŠ€ν¬λ¦½νŠΈμ—μ„œ document.domain의 Setterλ₯Ό 톡해 ν•΄κ²°ν•˜κ³  μžˆμ—ˆμ–΄μš”.

document.domain 속성은 도메인 이름을 μ„€μ •ν•˜κ±°λ‚˜ κ°€μ Έμ˜¬ 수 μžˆλŠ” DOM μ†μ„±μ΄μ—μš”. 이λ₯Ό 톡해 λΆ€λͺ¨-μžμ‹ μ°½ 간에 μ„œλ‘œ λ‹€λ₯Έ 도메인을 λ™μΌν•œ λ„λ©”μΈμœΌλ‘œ μ„€μ •ν•¨μœΌλ‘œμ¨ 동일 좜처 μ •μ±…(Same-Origin Policy) μ œν•œμ„ ν”Όν•  수 μžˆμ—ˆμ–΄μš”. μ•„λž˜μ™€ 같은 μ½”λ“œλ‘œ 말이죠.

docuemnt.domain = "mydomain.com"

μœ„μ™€ 같이 domain을 β€œmydomain.com” 으둜 μˆ˜μ •ν•˜κ²Œ 되면 μ„œλ‘œ λ‹€λ₯Έ μ„œλΈŒ 도메인(Subdomain)을 κ°€μ§€μ§€λ§Œ λ™μΌν•œ eTLD+1(mydomain.com)을 κ°€μ§€κ²Œ λ˜μ–΄ 두 좜처λ₯Ό 동일 좜처인 κ²ƒμ²˜λŸΌ 취급이 κ°€λŠ₯ν–ˆμ–΄μš”.

  • 도메인: pac.mydomain.com
  • eTLD(Effective Top-Level Domain): .com
  • eTLD+1: mydomain.com

단, μœ„μ˜ κ²½μš°μ—λ„ κΈ°λ³Έ 도메인 μžμ²΄κ°€ λ‹€λ₯Έ κ²½μš°μ—λŠ” 적용이 λΆˆκ°€λŠ₯ν•΄μš”.

예1. ) pac.mydomain.com 을 documnet.domain = β€œmydomain.com” 으둜 λ³€κ²½ κ°€λŠ₯

예2. ) pac.super-mydomain.com을 document.domain = β€œmydomain.com” 으둜 λ³€κ²½ λΆˆκ°€

예3. ) super-mydomain.com을 document.domain = β€œmydomain.com” 으둜 λ³€κ²½ λΆˆκ°€

ν•˜μ§€λ§Œ document.domain setterλŠ” μ•„λž˜μ™€ 같은 λ¬Έμ œμ μ„ 가지고 μžˆμ–΄μš”.

document.domain Setter 문제점

  1. λ„λ©”μΈμ˜ 포트 번호λ₯Ό λ¬΄μ‹œν•΄μš”.
  2. 도메인을 λ³€κ²½ν•˜μ—¬ 동일 좜처 νŽ˜μ΄μ§€μ²˜λŸΌ μ ‘κ·Όν•˜μ—¬ 정보λ₯Ό νƒˆμ·¨ν•  수 μžˆμ–΄μš”.

document.domain Setter 지원쀑단(Deprecated)

μ΄λŸ¬ν•œ 문제점으둜 인해 Chrome 115 버전 λΆ€ν„°λŠ” document.domain을 λ³€κ²½ν•  수 μ—†κ²Œ λ˜μ—ˆμ–΄μš”. 크둬뿐만 μ•„λ‹ˆλΌ λ‹€λ₯Έ λΈŒλΌμš°μ €λ„ 점차 ν•΄λ‹Ή κΈ°λŠ₯을 μ œκ³΅ν•˜μ§€ μ•Šμ„ μ˜ˆμ •μ΄μ—μš”.

chrome deprecated

Chrome 115λΆ€ν„° 지원 쀑단

mdn deprecated

MDN Deprecated

μ΄λ ‡κ²Œ 점차 λΈŒλΌμš°μ €μ—μ„œ μ—…λ°μ΄νŠΈλ¨μ— 따라 document.domain Setterκ°€ λ™μž‘ν•˜μ§€ μ•Šκ²Œ λ˜μ—ˆκ³ , 이둜 인해 μ–΄λ–€ 고객은 μ •μƒμ μœΌλ‘œ μ§„ν–‰λ˜κ³  μ΅œμ‹  λΈŒλΌμš°μ € 버전을 μ‚¬μš©ν•˜λŠ” 고객은 정상 진행이 λΆˆκ°€λŠ₯ν–ˆλ˜ κ²ƒμ΄μ—ˆμ–΄μš”. λˆ„κ΅¬λŠ” 정상 진행이 되고, λˆ„κ΅¬λŠ” 정상 진행이 λΆˆκ°€λŠ₯ν–ˆλ˜ μ΄μœ κ°€ 여기에 μžˆμ—ˆλ˜ κ²ƒμ΄μ—ˆμ£ .

사내PCμ—μ„œ ν•΄λ‹Ή ν˜„μƒ κ΅¬ν˜„κ³Ό νŒŒμ•…μ΄ μ–΄λ €μ› λ˜ μ΄μœ λŠ” λ³΄μ•ˆ 정책상 νμ‡„λ§μœΌλ‘œ 이루어져 ꡬ버전 λΈŒλΌμš°μ €λ₯Ό μ΄μš©ν–ˆκΈ° λ•Œλ¬Έμ— 원인을 λͺ¨λ₯΄λŠ” μƒνƒœμ—μ„œ 이슈 νŒŒμ•…μ— 더 μ–΄λ €μ› λ‹€κ³  μ‚¬λ£ŒλΌμš”. 이둜 인해 μ™ΈλΆ€λ§μ—μ„œλ§Œ ν•΄λ‹Ή ν˜„μƒμ΄ κ΅¬ν˜„λ˜λŠ” μ΄μœ λ„ μ„€λͺ…이 λ˜μ—ˆμ£ . (2024.01.03 외뢀망 Chrome Version: 120.0.6099.130)

νμ‡„λ§μœΌλ‘œ μΈν•œ Google Chrome μžλ™ 및 μˆ˜λ™ μ—…λ°μ΄νŠΈ λΆˆκ°€λŠ₯ν•œ μƒνƒœ.

ν•΄κ²°

μ΄λŸ¬ν•œ ꡐ처 μΆœμ²˜μ—μ„œ μ•ˆμ „ν•˜κ²Œ 동일 좜처 μ •μ±… μ œμ•½ 쑰건을 μš°νšŒν•  수 μžˆλŠ” κΈ°λŠ₯을 μžλ°”μŠ€ν¬λ¦½νŠΈμ—μ„œλŠ” window.postMessage()을 톡해 μ œκ³΅ν•˜κ³  μžˆμ–΄μš”. ν•΄λ‹Ή ν•¨μˆ˜λŠ” λΆ€λͺ¨ νŽ˜μ΄μ§€μ—μ„œ μƒμ„±λœ νŒμ—… κ°„μ˜ ν†΅μ‹ μ΄λ‚˜, νŽ˜μ΄μ§€μ™€ νŽ˜μ΄μ§€ μ•ˆμ˜ iframe κ°„μ˜ ν†΅μ‹ μ—μ„œ μ‚¬μš©ν•  수 μžˆμ–΄μš”.

window.postMessage() μ‚¬μš© 방법

  • μˆ˜μ‹  λΆ€λΆ„
// 방법 1.
window.onmesage = (event) => {
	console.log(event);
};

// 방법 2.
window.addEventListener('message', (event) => {
	console.log(event);
});

// 방법 3. Object dataλ₯Ό λ°›λŠ” 방법
window.onmessage = (event) => {
	console.log(JSON.parse(event.data));
};

event 객체 ν”„λ‘œνΌν‹°

  1. data: 전달 받은 데이터.
  2. origin: postMessage κ°€ 호좜될 λ•Œ λ©”μ‹œμ§€λ₯Ό λ³΄λ‚΄λŠ” μœˆλ„μš°μ˜ origin.
  3. source: λ©”μ‹œμ§€λ₯Ό 보낸 window μ˜€λΈŒμ νŠΈμ— λŒ€ν•œ μ°Έμ‘°.
  • λ°œμ‹  λΆ€λΆ„
// κΈ°λ³Έ 문법
targetWindow.postMessage(message, targetOrigin, [transfer]);

// string 전솑
targetWindow.postMessage('message');

// 객체 전솑
const data = { message: 'my message' };
targetWindow.postMessage(JSON.stringify(data));

// targetOrigin 지정
targetWindow.postMessage('message', 'https://mydomain.com');
  1. targetWindow: λ©”μ‹œμ§€λ₯Ό 전달 받을 window의 μ°Έμ‘°.
    • window.opener: μƒˆ 창을 λ§Œλ“  windowλ₯Ό μ°Έμ‘°ν•  λ•Œ.
    • window.parent: μž„λ² λ””λ“œλœ iframe ν˜Ήμ€ νŒμ—…μ—μ„œ ν•œλ²ˆ 더 submit을 톡해 λ Œλ”λ§ 된 경우 submitν•œ νŽ˜μ΄μ§€μ˜ window 객체λ₯Ό μ°Έμ‘°ν•  λ•Œ.
  2. message: λ‹€λ₯Έ window에 λ³΄λ‚΄μ§ˆ 데이터.
  3. targetOrigin: targetWindow의 origin을 지정. β€˜*’일 경우 λ³„λ„λ‘œ μ§€μ •ν•˜μ§€ μ•ŠμŒμ„ 의미.
    • νŒ¨μŠ€μ›Œλ“œμ™€ 같은 μ€‘μš”ν•œ λ°μ΄ν„°μ˜ 경우 λ°˜λ“œμ‹œ μ§€μ •ν•˜μ—¬ μ•…μ˜μ μΈ 제 3μžκ°€ κ°€λ‘œμ±„μ§€ λͺ»ν•˜λ„둝 μ„€μ •ν•˜λŠ” 것이 맀우 μ€‘μš”ν•΄μš”.
  • μ½”λ“œ 적용 μ˜ˆμ‹œ
// λΆ€λͺ¨ νŽ˜μ΄μ§€
const popup = window.open('about:blank', 'pay-popup', 'width=600,height=400');

// 데이터 μ…‹νŒ… ν›„ submit, ν¬μŠ€νŒ… 상단 λΆ€λΆ„ μ˜ˆμ‹œ μ°Έμ‘°

window.onmessage((event) => {
	if (event.origin !== 'https://pac.mydomain.com') return;

	const { code, data } = JSON.parse(event.data);
	if (code !== 'success') return;
	successPayment(data);
});

function successPayment(data) {
	// 결제 ν›„μ²˜λ¦¬ 둜직
}

// μ°Έκ³ . λ§Œμ•½ λΆ€λͺ¨ νŽ˜μ΄μ§€μ—μ„œ νŒμ—…μ— λ©”μ‹œμ§€λ₯Ό μ „λ‹¬ν•˜κ³  싢을 경우.
// popup.postMessage('message');
// νŒμ—…
const data = {
	code: 'success',
	data: { ... }, // μƒλž΅
};

opener.postMessage(JSON.stringify(data));

window.postMessage() μ‚¬μš© 방법에 λŒ€ν•΄μ„œ λ”μš± μžμ„Έν•œ μ„€λͺ…은 μ•„λž˜ λ§ν¬μ—μ„œ 확인 κ°€λŠ₯ν•΄μš”.

Window.postMessage() - Web API | MDN

κ²°κ³Ό

As-Is

ν•˜λ£¨ 평균 μ•½ 2,000 ~ 3,000 건 둜그 적재

2024.01.02 00:00:00 ~ 2024:01.02 23:59:59 κΈ°μ€€: 3,074 건

kibana_as-is

To-Be

2024.01.03 17:00:00 ~ 2024:01.04 15:00:00 κΈ°μ€€: 0건

kibana_to-be

참고 자료

μ•„λž˜ λ§ν¬μ—μ„œ ν¬μŠ€νŒ…μ—μ„œ λ‹€λ£¨μ—ˆλ˜ 정보λ₯Ό 보닀 μžμ„Έν•˜κ²Œ 확인할 수 μžˆμ–΄μš”.

  1. Chrome 버전 μ—…λ°μ΄νŠΈ
  1. Chrome document.domain deprecated κ΄€λ ¨ λΈ”λ‘œκ·Έ 포슀트
  1. URL ꡬ쑰 κ΄€λ ¨ 포슀트
profile
πŸŽοΈπŸ’¨ Beep Beep

0개의 λŒ“κΈ€