실행 시간을 밀리초 단위로 가져와야 합니다.
나는 원래 2008년에 이 질문을 했습니다. 당시 받아들여진 대답은
new Date().getTime()
performance.now()
API를 사용하는 것이 더 적절하다는 데 동의할 수 있습니다. 따라서 나는 허용되는 답변을 이것으로 변경합니다.
질문자 :Julius A
실행 시간을 밀리초 단위로 가져와야 합니다.
나는 원래 2008년에 이 질문을 했습니다. 당시 받아들여진 대답은
new Date().getTime()
performance.now()
API를 사용하는 것이 더 적절하다는 데 동의할 수 있습니다. 따라서 나는 허용되는 답변을 이것으로 변경합니다.
var t0 = performance.now() doSomething() // <---- measured code goes between t0 and t1 var t1 = performance.now() console.log("Call to doSomething took " + (t1 - t0) + " milliseconds.")
Node.js
에서는performance
클래스를 가져와야 합니다.
console.time('doSomething') doSomething() // <---- The function you're measuring time for console.timeEnd('doSomething')
메모:
time()
및 timeEnd()
메서드에 전달되는 문자열은 일치해야 합니다.
( 타이머가 예상대로 종료되도록 ).
console.time()
문서:
getTime() 메서드는 1970년 1월 1일 자정 이후의 밀리초 수를 반환합니다.
전.
var start = new Date().getTime(); for (i = 0; i < 50000; ++i) { // do something } var end = new Date().getTime(); var time = end - start; alert('Execution time: ' + time);
<script> var a = performance.now(); alert('do something...'); var b = performance.now(); alert('It took ' + (b - a) + ' ms.'); </script>
작동:
IE 10++
파이어폭스 15++
크롬 24++
사파리 8++
오페라 15++
안드로이드 4.4++
console.time
당신을 위해 가능한 수 있지만, 그것은 비표준입니다 § :
이 기능은 비표준이며 표준 트랙에 없습니다. 웹을 접하는 프로덕션 사이트에서는 사용하지 마십시오. 모든 사용자에게 작동하는 것은 아닙니다. 또한 구현 간에 큰 비호환성 이 있을 수 있으며 향후 동작이 변경될 수 있습니다.
브라우저 지원 외에도 performance.now
console.time
버전인 것처럼 더 정확한 타이밍을 제공할 가능성 이 있는 것 같습니다.
<호언 장담> 또한, 이제까지 사용하지 마십시오 Date
가 "시스템 시간"변화에 영향 있기 때문에 아무것도. 즉, 사용자에게 정확한 시스템 시간이 없을 때 "음수 타이밍"과 같은 잘못된 결과가 나타 납니다.
년 10 월 2014 년 내 시스템 클럭 나는 Gmail을 열고 "분 전 보내"내 하루의 모든 이메일을 보았다 .... 엉망이를 가서 무엇을 생각한다. 그리고 Gmail은 Google의 세계적 수준의 엔지니어가 구축해야 한다고 생각했는데.......
(시스템 시계를 1년 전으로 설정하고 Gmail로 이동하여 우리 모두 즐겁게 웃을 수 있습니다. 아마도 언젠가는 JS Date
대한 수치 의 전당이 있을 것입니다.)
Google 스프레드시트의 now()
함수도 이 문제를 겪고 있습니다.
Date
사용하는 유일한 시간 은 사용자에게 시스템 시계 시간을 표시하려는 경우입니다. 아니 당신이 얻을하고자 할 때 시간 이나 측정 아무것도에 있습니다.
로컬 개발 머신에서 함수 실행 시간을 가져와야 하는 경우 브라우저의 프로파일링 도구를 사용하거나 console.time()
및 console.timeEnd()
와 같은 콘솔 명령을 사용할 수 있습니다.
모든 최신 브라우저에는 JavaScript 프로파일러가 내장되어 있습니다. 이러한 프로파일러는 함수의 실행 시간에 영향을 미칠 수 있는 기존 코드를 수정할 필요가 없기 때문에 가장 정확한 측정을 제공해야 합니다.
JavaScript를 프로파일링하려면:
또는 개발 머신 console.time()
및 console.timeEnd()
를 사용하여 코드에 계측을 추가할 수 있습니다. Firefox11+, Chrome2+ 및 IE11+에서 지원되는 이러한 함수는 console.time()
통해 시작/중지하는 타이머에 대해 보고합니다. time()
은 사용자 정의 타이머 이름을 인수로 사용하고 timeEnd()
는 타이머가 시작된 이후의 실행 시간을 보고합니다.
function a() { console.time("mytimer"); ... do stuff ... var dur = console.timeEnd("myTimer"); // NOTE: dur only works in FF }
timeEnd()
호출에서 경과 시간을 반환합니다. 다른 브라우저는 결과를 개발자 콘솔에 보고하기만 하면 됩니다. timeEnd()
의 반환 값은 정의되지 않습니다.
야생에서 함수 실행 시간을 얻으 려면 코드를 계측해야 합니다. 몇 가지 옵션이 있습니다. new Date().getTime()
을 쿼리하여 시작 및 종료 시간을 간단히 저장할 수 있습니다.
function a() { var start = new Date().getTime(); ... do stuff ... var end = new Date().getTime(); var dur = end - start; }
그러나 Date
객체는 밀리초 단위의 해상도를 가지며 OS의 시스템 시계 변경에 영향을 받습니다. 최신 브라우저에는 더 나은 옵션이 있습니다.
더 나은 옵션은 window.performance.now()
라고도 하는 고해상도 시간 을 사용하는 것입니다. now()
는 두 가지 중요한 면에서 Date.getTime()
보다 낫습니다.
now()
는 페이지 탐색 시작 이후 밀리초 수를 나타내는 밀리초 미만 해상도의 double입니다. 마이크로초 수를 분수로 반환합니다(예: 값 1000.123은 1초이고 123마이크로초임).
now()
는 단조롭게 증가하고 있습니다. Date.getTime()
이 후속 호출에서 앞으로 또는 뒤로 이동할 수 있기 때문에 중요합니다. 특히 OS의 시스템 시간이 업데이트되면(예: 원자 시계 동기화) Date.getTime()
도 업데이트됩니다. now()
는 항상 단조롭게 증가하는 것이 보장되므로 OS의 시스템 시간에 영향을 받지 않습니다. 항상 벽시계 시간이 됩니다(벽시계가 원자적이지 않다고 가정하면...).
now()
new Date().getTime()
, + new Date
및 Date.now()
가 있는 거의 모든 곳에서 사용할 수 있습니다. Date
는 unix-epoch (1970년 이후의 밀리초 수)를 now()
는 페이지 탐색이 시작된 이후의 밀리초 수를 기반으로 하기 Date
와 now()
시간이 혼합되지 않는다는 점은 예외입니다. Date
)보다 훨씬 작습니다.
now()
를 사용하는 방법의 예입니다.
function a() { var start = window.performance.now(); ... do stuff ... var end = window.performance.now(); var dur = end - start; }
now()
는 안정적인 Chrome, Firefox 15+ 및 IE10에서 지원됩니다. 또한 여러 폴리필을 사용할 수 있습니다.
야생에서 실행 시간을 측정하는 또 다른 옵션은 UserTiming 입니다. 유사하게 작동을 UserTiming console.time()
및 console.timeEnd()
,하지만 그 같은 고해상도 타임 스탬프를 이용하여 now()
사용 (당신은 하위 밀리 초 일정하게 증가하는 시계를 얻을 수 있도록), 그리고에 타임 스탬프 및 지속 시간을 절약 할 수 퍼포먼스 타임라인 .
UserTiming에는 표시 (타임스탬프) 및 측정 (기간)의 개념이 있습니다. 원하는 만큼 정의할 수 있으며 PerformanceTimeline 에 노출됩니다.
타임스탬프를 저장하려면 mark(startMarkName)
을 호출합니다. 첫 번째 표시 이후의 지속 시간을 얻으려면 간단히 measure(measurename, startMarkname)
호출하십시오. 그러면 기간이 표시와 함께 PerformanceTimeline에 저장됩니다.
function a() { window.performance.mark("start"); ... do stuff ... window.performance.measure("myfunctionduration", "start"); } // duration is window.performance.getEntriesByName("myfunctionduration", "measure")[0];
UserTiming은 IE10+ 및 Chrome25+에서 사용할 수 있습니다. 사용 가능한 polyfill도 있습니다(내가 작성한).
정확한 값을 얻으려면 Performance 인터페이스 를 사용해야 합니다. 최신 버전의 Firefox, Chrome, Opera 및 IE에서 지원됩니다. 다음은 사용 방법의 예입니다.
var performance = window.performance; var t0 = performance.now(); doWork(); var t1 = performance.now(); console.log("Call to doWork took " + (t1 - t0) + " milliseconds.")
Date.getTime()
또는 console.time()
은 정확한 실행 시간을 측정하는 데 적합하지 않습니다. 빠른 대략적인 견적이 귀하에게 적합한 경우 사용할 수 있습니다. 대략적인 추정에 따르면 실시간에서 15-60ms 시프트를 얻을 수 있습니다.
JavaScript에서 실행 시간 측정에 대한 이 멋진 게시물을 확인하십시오. 저자는 읽을 가치가 있는 JavaScript 시간의 정확성에 대한 몇 가지 링크도 제공합니다.
Firebug를 사용하고 콘솔과 Javascript를 모두 활성화하십시오. 프로필을 클릭합니다. 새로고침 프로필을 다시 클릭합니다. 보고서를 봅니다.
간단한 솔루션, 여기에서도 추가 연산자를 사용할 수 있습니다.
var start = +new Date(); callYourFunctionHere(); var end = +new Date(); var time = end - start; console.log('total execution time = '+ time + 'ms');
var StopWatch = function (performance) { this.startTime = 0; this.stopTime = 0; this.running = false; this.performance = performance === false ? false : !!window.performance; }; StopWatch.prototype.currentTime = function () { return this.performance ? window.performance.now() : new Date().getTime(); }; StopWatch.prototype.start = function () { this.startTime = this.currentTime(); this.running = true; }; StopWatch.prototype.stop = function () { this.stopTime = this.currentTime(); this.running = false; }; StopWatch.prototype.getElapsedMilliseconds = function () { if (this.running) { this.stopTime = this.currentTime(); } return this.stopTime - this.startTime; }; StopWatch.prototype.getElapsedSeconds = function () { return this.getElapsedMilliseconds() / 1000; }; StopWatch.prototype.printElapsed = function (name) { var currentName = name || 'Elapsed:'; console.log(currentName, '[' + this.getElapsedMilliseconds() + 'ms]', '[' + this.getElapsedSeconds() + 's]'); };
기준
var stopwatch = new StopWatch(); stopwatch.start(); for (var index = 0; index < 100; index++) { stopwatch.printElapsed('Instance[' + index + ']'); } stopwatch.stop(); stopwatch.printElapsed();
산출
Instance[0] [0ms] [0s] Instance[1] [2.999999967869371ms] [0.002999999967869371s] Instance[2] [2.999999967869371ms] [0.002999999967869371s] /* ... */ Instance[99] [10.999999998603016ms] [0.010999999998603016s] Elapsed: [10.999999998603016ms] [0.010999999998603016s]
performance.now() 는 선택 사항입니다. StopWatch 생성자 함수에 false를 전달하면 됩니다.
process.hrtime()은 Node.js 내에서 사용할 수 있습니다. 나노초 단위로 값을 반환합니다.
var hrTime = process.hrtime() console.log(hrTime[0] * 1000000 + hrTime[1] / 1000)
하나의 변수만 사용할 수 있습니다.
var timer = -performance.now(); // Do something timer += performance.now(); console.log("Time: " + (timer/1000).toFixed(5) + " sec.")
timer/1000
- 밀리초를 초로 변환
.toFixed(5)
- 추가 숫자를 자르기 위해
NodeJS에서 timeEnd를 값으로 반환하는 기능을 갖도록 vsync의 코드를 더 확장하려면 이 작은 코드를 사용하십시오.
console.timeEndValue = function(label) { // Add console.timeEndValue, to add a return value var time = this._times[label]; if (!time) { throw new Error('No such label: ' + label); } var duration = Date.now() - time; return duration; };
이제 다음과 같이 코드를 사용하십시오.
console.time('someFunction timer'); someFunction(); var executionTime = console.timeEndValue('someFunction timer'); console.log("The execution time is " + executionTime);
이것은 당신에게 더 많은 가능성을 제공합니다. 방정식에서 사용하거나 데이터베이스에 저장하거나 웹 소켓을 통해 원격 클라이언트로 전송하거나 웹 페이지에서 제공하는 등의 더 많은 용도로 사용하기 위해 실행 시간을 저장할 수 있습니다.
다음은 타이밍 기능을 위한 데코레이터입니다.
let timed = (f) => (...args)=>{ let start = performance.now(); let ret = f(...args); console.log(`function ${f.name} took ${(performance.now()-start).toFixed(3)}ms`) return ret; }
용법:
let test = ()=>{/*does something*/} test = timed(test) // turns the function into a timed function in one line test() // run your code as normal, logs 'function test took 1001.900ms'
비동기 함수를 사용하는 경우 timed
비동기를 만들고 f(...args) 전에 await
하나의 데코레이터가 동기화 및 비동기 기능을 모두 처리하도록 하려면 더 복잡해집니다.
이 목표를 달성하는 방법에는 여러 가지가 있습니다.
console.time 사용
console.time('function'); //run the function in between these two lines for that you need to //measure time taken by the function. ("ex. function();") console.timeEnd('function');
이것이 가장 효율적인 방법입니다. performance.now() 사용 , 예
var v1 = performance.now(); //run the function here for which you have top measure the time var v2 = performance.now(); console.log("total time taken = "+(v2-v1)+"milliseconds");
+(연산자 추가) 또는 getTime() 사용
var h2 = +new Date(); //or var h2 = new Date().getTime(); for(i=0;i<500;i++) { /* do something */} var h3 = +new Date(); //or var h3 = new Date().getTime(); var timeTaken = h3-h2; console.log("time ====", timeTaken);
다음은 단항 더하기 연산자를 Date 인스턴스에 적용하면 발생하는 일입니다. 해당 Date 인스턴스의 값을 가져옵니다. 이를 숫자로 변환합니다.
참고: getTime()
은 단항 + 연산자보다 더 나은 성능을 제공합니다.
console.time
및 performance.now
는 일부 주요 브라우저(예: IE10)에서 지원되지 않기 때문에 사용 가능한 최상의 방법을 활용하는 슬림 유틸리티를 만들었습니다. 그러나 잘못된 사용(초기화되지 않은 타이머에서 End()
호출)에 대한 오류 처리가 부족합니다.
그것을 사용하고 원하는대로 개선하십시오.
Performance: { Timer: {}, Start: function (name) { if (console && console.time) { console.time(name); } else if (window.performance.now) { this.Timer[name] = window.performance.now(); } else { this.Timer[name] = new Date().getTime(); } }, End: function (name) { if (console && console.time) { console.timeEnd(name); } else { var result; if (window.performance.now) { result = window.performance.now() - this.Timer[name]; } else { result = new Date().getTime() - this.Timer[name]; } console.log(name + ": " + result); } } }
도움이 될 수 있습니다.
var t0 = date.now(); doSomething(); var t1 = date.now(); console.log("Call to doSomething took approximate" + (t1 - t0)/1000 + " seconds.")
감사합니다. Achim Koellner가 답변을 좀 더 확장해 드리겠습니다.
var t0 = process.hrtime(); //Start of code to measure //End of code var timeInMilliseconds = process.hrtime(t0)[1]/1000000; // dividing by 1000000 gives milliseconds from nanoseconds
측정하려는 것 외에는 아무 것도 해서는 안 됩니다(예: console.log
도 실행하는 데 시간이 걸리며 성능 테스트에 영향을 줌).
비동기 함수 실행 시간을 측정하는 순서대로 var timeInMilliseconds = process.hrtime(t0)[1]/1000000;
콜백 내부. 예를 들어,
var t0 = process.hrtime(); someAsyncFunction(function(err, results) { var timeInMilliseconds = process.hrtime(t0)[1]/1000000; });
몇 달 전에 나는 Date.now()를 사용하여 함수를 곱하는 내 자신의 루틴을 만들었습니다. -in) 안정적인 Node.js 릴리스에서.
오늘 저는 좀 더 조사를 하다가 타이밍을 위한 다른 방법을 찾았습니다. Node.js 코드에서도 이것을 사용하는 방법을 찾았기 때문에 여기에 공유할 생각입니다.
다음은 w3c 및 Node.js 에서 제공하는 예제에서 결합됩니다.
function functionTimer() { performance.mark('start') functionToBeTimed() performance.mark('end') performance.measure('Start to End', 'start', 'end') const measure = performance.getEntriesByName('Start to End')[0] console.log(measure.duration) }
노트:
performance
개체를 사용하려는 경우 다음 요구 사항을 포함해야 합니다. const { performance } = require('perf_hooks')
서버 및 클라이언트(노드 또는 DOM)와 함께 작동하고 Performance
API를 사용합니다. 예를 들어 1000개의 데이터 개체를 처리하는 1000번이라는 함수에서 작은 주기가 많이 있지만 이 함수의 각 작업이 합계를 합산하는 방법을 확인하려는 경우에 좋습니다.
그래서 이것은 모듈 전역(싱글톤) 타이머를 사용합니다. 클래스 싱글톤 패턴과 동일하고 사용이 조금 더 간단하지만 이를 별도의 예를 들어 stopwatch.js
파일에 넣어야 합니다.
const perf = typeof performance !== "undefined" ? performance : require('perf_hooks').performance; const DIGITS = 2; let _timers = {}; const _log = (label, delta?) => { if (_timers[label]) { console.log(`${label}: ` + (delta ? `${delta.toFixed(DIGITS)} ms last, ` : '') + `${_timers[label].total.toFixed(DIGITS)} ms total, ${_timers[label].cycles} cycles`); } }; export const Stopwatch = { start(label) { const now = perf.now(); if (_timers[label]) { if (!_timers[label].started) { _timers[label].started = now; } } else { _timers[label] = { started: now, total: 0, cycles: 0 }; } }, /** Returns total elapsed milliseconds, or null if stopwatch doesn't exist. */ stop(label, log = false) { const now = perf.now(); if (_timers[label]) { let delta; if(_timers[label].started) { delta = now - _timers[label].started; _timers[label].started = null; _timers[label].total += delta; _timers[label].cycles++; } log && _log(label, delta); return _timers[label].total; } else { return null; } }, /** Logs total time */ log: _log, delete(label) { delete _timers[label]; } };
export default class Singleton { static myInstance: Singleton = null; _timers: any = {}; /** * @returns {Singleton} */ static getInstance() { if (Singleton.myInstance == null) { Singleton.myInstance = new Singleton(); } return this.myInstance; } initTime(label: string) { this._timers[label] = Date.now(); return this._timers[label]; } endTime(label: string) { const endTime = Date.now(); if (this._timers[label]) { const delta = endTime - this._timers[label]; const finalTime = `${label}: ${delta}ms`; delete this._timers[label]; return finalTime; } else { return null; } } }
InitTime는 관련 string
.
return Singleton.getInstance().initTime(label); // Returns the time init
return Singleton.getInstance().endTime(label); // Returns the total time between init and end
중첩되지 않은 여러 항목 사이의 시간을 측정하려면 다음을 사용할 수 있습니다.
function timer(lap){ if(lap) console.log(`${lap} in: ${(performance.now()-timer.prev).toFixed(3)}ms`); timer.prev = performance.now(); }
console.time()과 유사하지만 이전 타이머를 추적할 필요가 없는 경우 더 쉽게 사용할 수 있습니다.
console.time()의 파란색이 마음에 들면 이 줄을 대신 사용할 수 있습니다.
console.log(`${lap} in: %c${(performance.now()-timer.prev).toFixed(3)}ms`, 'color:blue');
// Usage: timer() // set the start // do something timer('built') // logs 'built in: 591.815ms' // do something timer('copied') // logs 'copied in: 0.065ms' // do something timer('compared') // logs 'compared in: 36.41ms'
제 경우에는 @ 문법 suger를 사용하고 babel로 컴파일하는 것을 선호합니다.
이 방법의 문제는 함수가 객체 내부에 있어야 한다는 것입니다.
샘플 JS 코드
function timer() { return (target, propertyKey, descriptor) => { const start = Date.now(); let oldFunc = descriptor.value; descriptor.value = async function (){ var result = await oldFunc.apply(this, arguments); console.log(Date.now() - start); return result; } } } // Util function function delay(timeout) { return new Promise((resolve) => setTimeout(() => { resolve(); }, timeout)); } class Test { @timer() async test(timout) { await delay(timout) console.log("delay 1"); await delay(timout) console.log("delay 2"); } } const t = new Test(); t.test(1000) t.test(100)
.babelrc(바벨 6용)
{ "plugins": [ "transform-decorators-legacy" ] }
가장 좋은 방법은 performance hooks
모듈을 사용하는 것입니다. 불안정하지만, 당신은 할 수 mark
코드의 특정 영역 및 measure
duration
표시 영역 사이를.
const { performance, PerformanceObserver } = require('perf_hooks'); const measures = [] const obs = new PerformanceObserver(list => measures.push(...list.getEntries())); obs.observe({ entryTypes: ['measure'] }); const getEntriesByType = cb => cb(measures); const doSomething = val => { performance.mark('beginning of the process'); val *= 2; performance.mark('after multiplication'); performance.measure('time taken', 'beginning of the process', 'after multiplication'); getEntriesByType(entries => { entries.forEach(entry => console.log(entry)); }) return val; } doSomething(4);
여기에서 시도
성능으로
NodeJs: 성능 클래스를 가져오기 위해 필요합니다.
var time0 = performance.now(); // Store the time at this point into time0 yourFunction(); // The function you're measuring time for var time1 = performance.now(); // Store the time at this point into time1 console.log("youFunction took " + (time1 - time0) + " milliseconds to execute");
console.time 사용
console.time('someFunction'); someFunction(); // Whatever is timed goes between the two "console.time" console.timeEnd('someFunction');
사용 console.time('some label here')
기능과 이전 console.timeEnd('some label here')
기능 후. 그것은 당신에게 기능의 실행 시간을 줄 것입니다.
console.time("myTimer");
console.timeLog("myTimer");
console.timeEnd("myTimer");
이에 대한 자세한 내용은 MDN 및 Node.js 문서 에서 읽을 수 있습니다.
Chrome, Firefox, Opera 및 NodeJS에서 사용할 수 있습니다. (Edge 또는 Internet Explorer에는 없음).
bigO 표기법에 대한 읽기도 고려해야 합니다. 무슨 일이 일어나고 있는지 이해하기 위해 타이밍 기능보다 더 나을 수 있습니다.
이전에 언급했듯이 내장 타이머를 확인하고 사용하십시오. 그러나 여기에 직접 작성하거나 작성해야 하는 경우 2센트가 있습니다.
//=-=|Source|=-=// /** * JavaScript Timer Object * * var now=timer['elapsed'](); * timer['stop'](); * timer['start'](); * timer['reset'](); * * @expose * @method timer * @return {number} */ timer=function(){ var a=Date.now(); b=0; return{ /** @expose */ elapsed:function(){return b=Date.now()-a}, start:function(){return a=Date.now()}, stop:function(){return Date.now()}, reset:function(){return a=0} } }(); //=-=|Google Advanced Optimized|=-=// timer=function(){var a=Date.now();b=0;return{a:function(){return b=Date.now()-a},start:function(){return a=Date.now()},stop:function(){return Date.now()},reset:function(){return a=0}}}();
허용된 답변이 잘못되었습니다 !
JavaScript는 비동기식이므로 허용된 답변의 변수 끝 값이 틀릴 수 있습니다.
var start = new Date().getTime(); for (i = 0; i < 50000; ++i) { // JavaScript is not waiting until the for is finished !! } var end = new Date().getTime(); var time = end - start; alert('Execution time: ' + time);
for의 실행은 매우 빨라서 결과가 잘못되었음을 알 수 없습니다. 일부 요청을 수행하는 코드로 테스트할 수 있습니다.
var start = new Date().getTime(); for (i = 0; i < 50000; ++i) { $.ajax({ url: 'www.oneOfYourWebsites.com', success: function(){ console.log("success"); } }); } var end = new Date().getTime(); var time = end - start; alert('Execution time: ' + time);
따라서 경고는 매우 빠르게 프롬프트가 표시되지만 콘솔에서는 ajax 요청이 계속되고 있음을 알 수 있습니다.
방법은 다음과 같습니다. https://developer.mozilla.org/en-US/docs/Web/API/Performance.now
출처 : http:www.stackoverflow.com/questions/313893/how-to-measure-time-taken-by-a-function-to-execute
Maven 프로젝트에 로컬 jar 파일을 추가하는 방법은 무엇입니까? (0) | 2022.03.22 |
---|---|
여러 열로 데이터 프레임을 정렬하는 방법 (0) | 2022.03.22 |
이전 커밋을 여러 커밋으로 나눕니다. (0) | 2022.03.22 |
application/x-www-form-urlencoded 또는 multipart/form-data? (0) | 2022.03.22 |
C#의 숨겨진 기능? [닫은] (0) | 2022.03.22 |