์ฝ๋ ์์ ์์ด ์๊ฒฉ ๋ธ๋ผ์ฐ์ ์ ์ฝ์ ๋ก๊ทธ ๊ฐ์ ธ์ค๊ธฐ โ HTML ์ฃผ์ + console ์ค๋ฒ๋ผ์ด๋
ํฐ๋๋ก ๋ก์ปฌ ์๋ฒ๋ฅผ ํฐ์ ๋์ ์ ๋,
์ ์ ๋ต๋ตํ ๊ฑด "ํฐ์์ ๋ญ๊ฐ ์๋ชป๋๋์ง ์ฝ์์ ๋ณผ ์ ์๋ค" ๋ ๊ฒ์ด์๋ค.
ํฐ ๋ธ๋ผ์ฐ์ ์ ๊ฐ๋ฐ์ ๋๊ตฌ๋ฅผ ์ฌ๋ ๊ฑด ๋ฒ๊ฑฐ๋กญ๋ค. ๊ทธ๋์ ๋ฃ์ ๊ธฐ๋ฅ์ด
์๊ฒฉ ์ฝ์ ๋ก๊ทธ ๋ชจ๋ํฐ๋ง โ ํฐ๋์ ํตํด ์ ์ํ ๋ธ๋ผ์ฐ์ ์ console.log๊ฐ
VSCode ์ฌ์ด๋๋ฐ์ ์ค์๊ฐ์ผ๋ก ๋ฌ๋ค.
์ฌ๊ธฐ์ ์งํจ ์์น ํ๋: ์ฌ์ฉ์(๊ฐ๋ฐ์)์ ์ฝ๋๋ ํ ์ค๋ ๊ฑด๋๋ฆฌ์ง ์๋๋ค.
์์ด๋์ด: ์๋ต HTML์ ์คํฌ๋ฆฝํธ๋ฅผ ๋ชฐ๋ ๋ผ์๋ฃ๊ธฐ
ํฐ๋์ ์ด์ฐจํผ ๋ชจ๋ ์๋ต์ด ๋ก์ปฌ ํด๋ผ์ด์ธํธ๋ฅผ ๊ฑฐ์ณ ๋๊ฐ๋ค. ๊ทธ๋ฌ๋ HTML ์๋ต์ผ
๋, </head> ์์ ์์ ์คํฌ๋ฆฝํธ๋ฅผ ์ฃผ์
ํ๋ฉด ๋๋ค. ๊ฐ๋ฐ์ ์ฝ๋๊ฐ ์๋๋ผ
ํฐ๋์ด ๋ฃ๋ ๊ฒ์ด๋ผ, ์ฌ์ฉ์๋ ์๋ฌด๊ฒ๋ ์ ํด๋ ๋๋ค.
if (response.status === 200 && ct.includes("text/html")) {
const script = `
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate">
<script data-tunnel-script="${Date.now()}">
/* ...์๋ ๋ด์ฉ... */
</script>`;
responseBody = responseBody.replace("</head>", script + "</head>");
}
HTML ํ์๋ฅผ ๋๋ฆฌ์ง ์๊ณ </head> ๋ฌธ์์ด๋ง ์ฐพ์ ๋ฐ๊พผ๋ค. ๋น ๋ฅด๊ณ ์ถฉ๋ถํ๋ค.
data-tunnel-script์ ํ์์คํฌํ๋ฅผ ๋ฐ๊ณ ์บ์ ๋ฐฉ์ง ๋ฉํ๋ฅผ ํจ๊ป ๋ฃ์ด, ๋ธ๋ผ์ฐ์ ๊ฐ
์ ์คํฌ๋ฆฝํธ๋ฅผ ์บ์ฑํ๋ ๊ฒ๋ ๋ง์๋ค.
ํต์ฌ: console์ ๊ฐ์ธ๋, ์๋ณธ์ ๋ณด์กดํ๋ค
์ฃผ์
๋ ์คํฌ๋ฆฝํธ๋ console.log ๊ฐ์ ๋ฉ์๋๋ฅผ ๊ฐ๋ก์ฑ์, ์๋ ๋์์
๊ทธ๋๋ก ํ๊ณ ์ถ๊ฐ๋ก ์๋ฒ์ ์ ์กํ๋ค. IIFE(์ฆ์ ์คํ ํจ์)๋ก ๊ฐ์ธ ์๋ณธ
์ฐธ์กฐ๋ฅผ ํด๋ก์ ์ ์์ ํ๊ฒ ๋ณด๊ดํ๋ค.
(function () {
var tunnelId = getCookie("tunnelId"); // ์ฟ ํค์์ ํฐ๋ ID
if (!tunnelId) return;
var original = { log: console.log, warn: console.warn,
error: console.error, info: console.info };
function sendLog(level, args) {
var message = Array.from(args).map(function (a) {
try { return typeof a === "object" ? JSON.stringify(a) : String(a); }
catch { return String(a); }
}).join(" ");
fetch(tunnelServerUrl + "/log", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ tunnelId: tunnelId, level: level, message: message }),
}).catch(function () {}); // ์คํจํด๋ ์ฑ์ ์ํฅ ์๊ฒ ์กฐ์ฉํ ๋ฌด์
}
console.log = function () { original.log.apply(console, arguments); sendLog("log", arguments); };
console.warn = function () { original.warn.apply(console, arguments); sendLog("warn", arguments); };
console.error = function () { original.error.apply(console, arguments); sendLog("error", arguments); };
console.info = function () { original.info.apply(console, arguments); sendLog("info", arguments); };
})();
ํฌ์ธํธ๊ฐ ๋ช ๊ฐ ์๋ค.
- ์๋ณธ์ ๋จผ์ ํธ์ถํ๋ค. ๊ทธ๋์ผ ์ค์ ์ฝ์์๋ ์ ์์ ์ผ๋ก ์ฐํ๋ค.
- ๊ฐ์ฒด ์ธ์๋
JSON.stringify๋ก ๋ฌธ์์ดํํ๋, ์ํ ์ฐธ์กฐ ๋ฑ์ผ๋ก ์คํจํ๋ฉดString()์ผ๋ก ํด๋ฐฑ. - ๋ก๊ทธ ์ ์ก(
fetch)์ด ์คํจํด๋.catch(()=>{})๋ก ์ผํจ๋ค. ๋ก๊น ๊ธฐ๋ฅ์ด ์ฑ ๋์์ ๋ฐฉํดํ๋ฉด ์ ๋๋๊น.
๋ก๊ทธ๊ฐ VSCode๊น์ง ๊ฐ๋ ๊ธธ
์ ์ก๋ ๋ก๊ทธ๋ ์ด๋ ๊ฒ ํ๋ฌ ์ฌ์ด๋๋ฐ์ ๋ฌ๋ค.
๋ธ๋ผ์ฐ์ console.log
โ fetch POST /log (ํฐ๋ IDยท๋ ๋ฒจยท๋ฉ์์ง)
โ ๊ณต๊ฐ ์๋ฒ: ํด๋น ํฐ๋์ WebSocket์ผ๋ก push
โ ๋ก์ปฌ ํด๋ผ์ด์ธํธ โ VSCode ํ์ฅ
โ Webview ์ฝ์ ํจ๋์ ์ค์๊ฐ ๋ ๋
Webview ์ชฝ์ ๋ ๋ฒจ(LOG/WARN/ERROR) ํํฐ์ ๊ฒ์, ๊ทธ๋ฆฌ๊ณ ์ฌ์ฉ์๊ฐ ์๋ก ์คํฌ๋กคํ๋ฉด ์๋ ์คํฌ๋กค์ ๋๊ณ , ๋งจ ์๋๋ก ์ค๋ฉด ๋ค์ ์ผ๋ ์ง๋ฅํ ์คํ ์คํฌ๋กค๋ ๋ฃ์๋ค. ๋ก๊ทธ ๋ทฐ์ด์์ "์ ๋ก๊ทธ ๋๋ฌธ์ ๋ณด๋ ์์น๊ฐ ํ๋" ํํ ์ง์ฆ์ ์์ค ๋ํ ์ผ์ด๋ค.
๋ฐฐ์ด ๊ฒ
-
๋ชฝํค ํจ์นญ(์๋ณธ ํจ์ ๊ฐ์ธ๊ธฐ) ์ ๊ฐ๋ ฅํ๋ค. ๋จ, "์๋ณธ์ ๋ฐ๋์ ๋จผ์ ํธ์ถ"ํ๊ณ "๋ถ๊ฐ ๊ธฐ๋ฅ ์คํจ๊ฐ ์๋ณธ์ ๋ง์น์ง ์๊ฒ" ํ๋ ๋ ์์น์ ์ง์ผ์ผ ์์ ํ๋ค.
-
์ฌ์ฉ์ ์ฝ๋๋ฅผ ์ ๊ฑด๋๋ฆฌ๊ณ ๊ธฐ๋ฅ์ ์น๋ ๋ฐฉ๋ฒ์ผ๋ก ์๋ต HTML ์ฃผ์ ์ ์์ฃผ ์ค์ฉ์ ์ด๋ค. (๊ฐ๋ฐ ๋๊ตฌ๋ค์ด ํํ ์ฐ๋ ์๋ฒ์ด๊ธฐ๋ ํ๋ค.)
-
๋ก๊น ยท๊ณ์ธก ๊ฐ์ ๋ถ๊ฐ ๊ธฐ๋ฅ์ ์ ๋ ๋ณธ์ฒด๋ฅผ ๋ฐฉํดํ๋ฉด ์ ๋๋ค. ์คํจ๋ ์กฐ์ฉํ ์ผํค๋ ๊ฒ ์ณ๋ค.
-
๊ด๋ จ ํ๋ก์ ํธ: Custom Tunnel