<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>___.log</title>
        <link>https://velog.io/</link>
        <description>_</description>
        <lastBuildDate>Thu, 10 Sep 2020 12:05:30 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>___.log</title>
            <url>https://images.velog.io/images/___/profile/1a2a5c40-7b86-475b-a5d1-7884c9a6da58/10308c4e0725cf7f7f56ab7c905cfa1a.jpg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. ___.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/___" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[라즈베리파이 - undefined reference to wiringPiSetup]]></title>
            <link>https://velog.io/@___/%EB%9D%BC%EC%A6%88%EB%B2%A0%EB%A6%AC%ED%8C%8C%EC%9D%B4-undefined-reference-to-wiringPiSetup</link>
            <guid>https://velog.io/@___/%EB%9D%BC%EC%A6%88%EB%B2%A0%EB%A6%AC%ED%8C%8C%EC%9D%B4-undefined-reference-to-wiringPiSetup</guid>
            <pubDate>Thu, 10 Sep 2020 12:05:30 GMT</pubDate>
            <description><![CDATA[<hr>
<p><a href="https://stdout.tistory.com/68">https://stdout.tistory.com/68</a></p>
<hr>
<p>$ gcc src.c -lwiringPi -lwiringPiDev</p>
<p>라이브러리 연결을 명시적으로 해야한다.</p>
<hr>
]]></description>
        </item>
        <item>
            <title><![CDATA[ICT]]></title>
            <link>https://velog.io/@___/ICT</link>
            <guid>https://velog.io/@___/ICT</guid>
            <pubDate>Mon, 13 Jul 2020 06:54:50 GMT</pubDate>
            <description><![CDATA[<hr>
<ul>
<li>ICT는, 정보 통신 기술(Information &amp; Communication Technology).</li>
</ul>
<p>정보 통신 기술(情報通信技術, ICT)은 정보기술(IT)의 확장형 동의어로 자주 사용되지만, </p>
<p>&quot;<u>통합 커뮤니케이션</u>&quot;의 역할과 원거리 <u>통신</u>(전화선 및 무선 신호), 컴퓨터, 더 나아가 정보에 접근,</p>
<p>그것을 <u>저장</u>하고 전송하고 <u>조작</u>할 수 있게 하는 필수적인 전사적 소프트웨어, 미들웨어, 스토리지, 오디오 비주얼 시스템.</p>
<ul>
<li>통합 커뮤니케이션(Unified communications, UC) :: </li>
<li><blockquote>
<p>전화, 팩스, 이메일, 핸드폰, 메신저, 영상통화, 음성메일 등 </p>
</blockquote>
</li>
<li><blockquote>
<p>기업 내 다양한 커뮤니케이션 도구를 단일 플랫폼을 통해 제공하는 것.</p>
</blockquote>
</li>
</ul>
<p>또, ICT라는 용어는 하나의 케이블 연결이나 링크 시스템을 통한</p>
<p>오디오 수준과 전화망을 컴퓨터 네트워크와 결합하는 의미.</p>
<hr>
]]></description>
        </item>
        <item>
            <title><![CDATA[nodejs - mysql :: Connection lost: The server closed the connection ]]></title>
            <link>https://velog.io/@___/nodejs-mysql-Connection-lost-The-server-closed-the-connection</link>
            <guid>https://velog.io/@___/nodejs-mysql-Connection-lost-The-server-closed-the-connection</guid>
            <pubDate>Fri, 26 Jun 2020 10:50:35 GMT</pubDate>
            <description><![CDATA[<hr>
<p><a href="https://enchoyism.github.io/2018/02/02/nodejs-mysql-connection-lost/">https://enchoyism.github.io/2018/02/02/nodejs-mysql-connection-lost/</a>
<a href="https://stackoverflow.com/questions/20210522/nodejs-mysql-error-connection-lost-the-server-closed-the-connection">https://stackoverflow.com/questions/20210522/nodejs-mysql-error-connection-lost-the-server-closed-the-connection</a></p>
<hr>
<p>nodejs로 만들고 있는 블로그의 db를 mysql로 구성하였다.</p>
<p>테스트용 서버에 올려두고 하룻밤 자고난 뒤에 자꾸 서버가 죽어있어서 로그를 찾아본 결과,</p>
<p><img src="https://images.velog.io/images/___/post/12363f19-89a6-4c5d-8a3f-c4b5910a901f/11.PNG" alt=""></p>
<p>그대로 구글에 찾아보았다.</p>
<p>결론부터 보면 nodejs server에서 db에 connection을 연결했는데 별다른 활동을 하지 않으면, mysql server 쪽에서 connection을 끊어버리는 것이다.</p>
<p><img src="https://images.velog.io/images/___/post/ce67c2d1-7522-4961-abaf-42537dc34779/%EC%BA%A1%EC%B2%98.PNG" alt=""></p>
<p>interactive_timeout, wait_timeout의 값이 활동하지 않은 connection의 대기시간이라고 한다.</p>
<p>내 db는 28000 sec = 8 hours 였다.</p>
<p>스택오버플로우에서 해결하는 방법을 보는데</p>
<pre><code class="language-js">setInterval(function () {
    db.query(&#39;SELECT 1&#39;);
}, 5000);</code></pre>
<p>내 server는 상시 연결해둬야 하도록 코드 구성이 되어있어 이런 방법이 간단하고 괜찮아 보였다.</p>
<p><img src="https://images.velog.io/images/___/post/5e489e34-4d88-4ddc-9aa5-96d2e8295f3b/22.PNG" alt=""></p>
<p>이 방법에 대한 의견 번역이 좀 과격하긴 한데..</p>
<p>다음과 같은 코드로 바꿔서 적용했다.</p>
<pre><code class="language-js">// db
const connectDummy = () =&gt; {
    connection.query(`select 1;`, (error, rows) =&gt; {
        // none..
    });
}

//---

// util js
const sendPingDB = () =&gt; {
    print(`sendPingDB()`);
    db.connectDummy();
    setTimeout(sendPingDB, 20000000);
}

const startSendPingDB = () =&gt; {
    setTimeout(sendPingDB, 20000000);
}

</code></pre>
<hr>
]]></description>
        </item>
        <item>
            <title><![CDATA[html - get 방식에서 한글 깨질 때]]></title>
            <link>https://velog.io/@___/html-get-%EB%B0%A9%EC%8B%9D%EC%97%90%EC%84%9C-%ED%95%9C%EA%B8%80-%EA%B9%A8%EC%A7%88-%EB%95%8C</link>
            <guid>https://velog.io/@___/html-get-%EB%B0%A9%EC%8B%9D%EC%97%90%EC%84%9C-%ED%95%9C%EA%B8%80-%EA%B9%A8%EC%A7%88-%EB%95%8C</guid>
            <pubDate>Tue, 23 Jun 2020 23:33:12 GMT</pubDate>
            <description><![CDATA[<hr>
<p><a href="https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/encodeuri">https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/encodeuri</a></p>
<hr>
<p>로그아웃 구현 때, 이전 주소로 돌아갈 때 url에 한글과 같은 문자가 포함되어 있는 구조로 블로그를 만들었는데, </p>
<p>로그아웃 후에 </p>
<pre><code class="language-js">location.href = `url...?prev_url?한글주소`;</code></pre>
<p>방식으로 query를 받아서 redirect 시키는 구조로 작성하였더니 인코딩 문제가 발생하였다.</p>
<pre><code class="language-js">const logout = () =&gt; {
    const prev_url = encodeURI(`${window.location.href}`);
    location.href = `/logout?prev_url=${prev_url}`;
}</code></pre>
<p>기본 내장된 encodeURI()를 사용하여 해결.</p>
<hr>
]]></description>
        </item>
        <item>
            <title><![CDATA[nodejs - app이 죽었을 때 재실행 module // forever]]></title>
            <link>https://velog.io/@___/nodejs-app%EC%9D%B4-%EC%A3%BD%EC%97%88%EC%9D%84-%EB%95%8C-%EC%9E%AC%EC%8B%A4%ED%96%89-module-forever</link>
            <guid>https://velog.io/@___/nodejs-app%EC%9D%B4-%EC%A3%BD%EC%97%88%EC%9D%84-%EB%95%8C-%EC%9E%AC%EC%8B%A4%ED%96%89-module-forever</guid>
            <pubDate>Sat, 20 Jun 2020 20:02:47 GMT</pubDate>
            <description><![CDATA[<hr>
<p><a href="https://github.com/foreversd/forever">https://github.com/foreversd/forever</a></p>
<hr>
<p>http web server를 nodejs로 서비스하면서 특정 에러 상황에 프로세스가 죽을 수 있다.</p>
<p>이 때, 다시 재가동하여 서비스하도록 해주는 모듈로 forever를 선택했다.</p>
<p>설치 :: npm install forever -g --save</p>
<p>실행 :: forever start index.js</p>
<p>forever에 등록한 실행중인 프로세스 조회 :: forever list</p>
<p>종료 :: forever stop index.js</p>
<hr>
]]></description>
        </item>
        <item>
            <title><![CDATA[nodejs - 동영상 스트리밍 구현 참고]]></title>
            <link>https://velog.io/@___/nodejs-%EB%8F%99%EC%98%81%EC%83%81-%EC%8A%A4%ED%8A%B8%EB%A6%AC%EB%B0%8D-%EA%B5%AC%ED%98%84-%EC%B0%B8%EA%B3%A0</link>
            <guid>https://velog.io/@___/nodejs-%EB%8F%99%EC%98%81%EC%83%81-%EC%8A%A4%ED%8A%B8%EB%A6%AC%EB%B0%8D-%EA%B5%AC%ED%98%84-%EC%B0%B8%EA%B3%A0</guid>
            <pubDate>Mon, 15 Jun 2020 08:00:43 GMT</pubDate>
            <description><![CDATA[<hr>
<p><a href="https://javafa.gitbooks.io/nodejs_server_basic/content/chapter11.html">https://javafa.gitbooks.io/nodejs_server_basic/content/chapter11.html</a></p>
<hr>
]]></description>
        </item>
        <item>
            <title><![CDATA[라즈베리파이 - LED 밝기 제어 시도 // PWM, fd]]></title>
            <link>https://velog.io/@___/%EB%9D%BC%EC%A6%88%EB%B2%A0%EB%A6%AC%ED%8C%8C%EC%9D%B4-LED-%EB%B0%9D%EA%B8%B0-%EC%A0%9C%EC%96%B4-%EC%8B%9C%EB%8F%84-PWM-fd</link>
            <guid>https://velog.io/@___/%EB%9D%BC%EC%A6%88%EB%B2%A0%EB%A6%AC%ED%8C%8C%EC%9D%B4-LED-%EB%B0%9D%EA%B8%B0-%EC%A0%9C%EC%96%B4-%EC%8B%9C%EB%8F%84-PWM-fd</guid>
            <pubDate>Wed, 03 Jun 2020 03:29:43 GMT</pubDate>
            <description><![CDATA[<hr>
<p>PWM(Pulse Width Modulation) ::</p>
<ul>
<li>펄스 폭 변조를 의미하는데, 한 주기에 있는 HIGH와 LOW 값의 비율로 출력되는 디지털 신호의 폭을 조절해서 값을 출력하는 방법.</li>
</ul>
<p>이 신호를 이용하여 LED의 밝기나 모터 속도 등을 제어할 수 있다고 한다.</p>
<p>duty :: PWM에서 한 주기동안 HIGH가 차지하고 있는 비율.</p>
<p>duty cycle :: 신호가 시스템이 살아 있는 특정 기간(period)의 백분율.</p>
<p><img src="https://images.velog.io/images/___/post/d9fa15df-7521-4ce6-aec4-33d9c0759d7d/20200603_112207.jpg" alt=""></p>
<hr>
<p>gpio를 파일 디스크립터로 직접 접근하여 LED의 밝기를 조절해 보았다.</p>
<p>duty가 1, 5, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100% 일때의 사진을 찍었는데, 눈으로 볼 때랑 카메라로 찍히는거랑 보이는 게 다르다.. 눈으로 직접 보면 LED 밝기의 차이가 눈에 보이는데, 카메라로 사진 촬영하면 LED 전체가 밝아 보인다.</p>
<p>붉은 LED의 빛이 뒤에 검은 지갑으로 비춰지는 정도로 그나마 사진에서 구별이 된다.</p>
<p>이정도면 성공한것으로 보인다.</p>
<p>아직 과제로 나오지는 않았지만, 과제로 나오면 fd 여는 것 말고 FILE*를 사용하여 구현하게 될 것 같다.</p>
<hr>
<p><img src="https://images.velog.io/images/___/post/6219f72c-80fa-49c6-9e6b-16a139a0619d/20200603_110445.jpg" alt=""></p>
<p>freq : 10000 [Hz]
duty : 0 [%]</p>
<hr>
<p><img src="https://images.velog.io/images/___/post/9482caed-9757-4a88-a027-6540d4a1c8de/20200603_110812.jpg" alt=""></p>
<p>freq : 10000 [Hz]
duty : 1 [%]</p>
<hr>
<p><img src="https://images.velog.io/images/___/post/47447ba6-78cf-4f1b-90ea-6d504b3a787b/20200603_110823.jpg" alt=""></p>
<p>freq : 10000 [Hz]
duty : 5 [%]</p>
<hr>
<p><img src="https://images.velog.io/images/___/post/ba1d0c07-2c50-4ea3-80c6-339ab1e6708f/20200603_110833.jpg" alt=""></p>
<p>freq : 10000 [Hz]
duty : 10 [%]</p>
<hr>
<p><img src="https://images.velog.io/images/___/post/14ba9fca-9643-4c16-9b01-5139e2ee7479/20200603_110844.jpg" alt=""></p>
<p>freq : 10000 [Hz]
duty : 20 [%]</p>
<hr>
<p><img src="https://images.velog.io/images/___/post/fbb5dcde-e6da-4523-b175-f9ffd3b292ab/20200603_110853.jpg" alt=""></p>
<p>freq : 10000 [Hz]
duty : 30 [%]</p>
<hr>
<p><img src="https://images.velog.io/images/___/post/b5f0ab02-7cf9-4f46-be8c-fe6974173e97/20200603_110903.jpg" alt=""></p>
<p>freq : 10000 [Hz]
duty : 40 [%]</p>
<hr>
<p><img src="https://images.velog.io/images/___/post/2a83b428-f6ba-4c46-bc67-27ddd2bf1dbf/20200603_110913.jpg" alt=""></p>
<p>freq : 10000 [Hz]
duty : 50 [%]</p>
<hr>
<p><img src="https://images.velog.io/images/___/post/ac82e455-2bf5-41e2-afbc-daa8b8f06551/20200603_110922.jpg" alt=""></p>
<p>freq : 10000 [Hz]
duty : 60 [%]</p>
<hr>
<p><img src="https://images.velog.io/images/___/post/d19d264c-84a7-4b0a-bb63-5cb803f82f28/20200603_110931.jpg" alt=""></p>
<p>freq : 10000 [Hz]
duty : 70 [%]</p>
<hr>
<p><img src="https://images.velog.io/images/___/post/f54b18f6-0a2b-4281-9dad-5e39ee6329a5/20200603_110940.jpg" alt=""></p>
<p>freq : 10000 [Hz]
duty : 80 [%]</p>
<hr>
<p><img src="https://images.velog.io/images/___/post/5a5d08a9-995f-40b4-b90f-c42f3ac7ee88/20200603_110948.jpg" alt=""></p>
<p>freq : 10000 [Hz]
duty : 90 [%]</p>
<hr>
<p><img src="https://images.velog.io/images/___/post/e52bfb1d-421b-4834-8751-72b1754c2a13/20200603_110957.jpg" alt=""></p>
<p>freq : 10000 [Hz]
duty : 100 [%]</p>
<hr>
]]></description>
        </item>
        <item>
            <title><![CDATA[nodejs - 로그아웃시, 세션쿠키 삭제 문제]]></title>
            <link>https://velog.io/@___/nodejs-%EB%A1%9C%EA%B7%B8%EC%95%84%EC%9B%83%EC%8B%9C-%EC%84%B8%EC%85%98%EC%BF%A0%ED%82%A4-%EC%82%AD%EC%A0%9C-%EB%AC%B8%EC%A0%9C</link>
            <guid>https://velog.io/@___/nodejs-%EB%A1%9C%EA%B7%B8%EC%95%84%EC%9B%83%EC%8B%9C-%EC%84%B8%EC%85%98%EC%BF%A0%ED%82%A4-%EC%82%AD%EC%A0%9C-%EB%AC%B8%EC%A0%9C</guid>
            <pubDate>Mon, 01 Jun 2020 15:20:16 GMT</pubDate>
            <description><![CDATA[<hr>
<p>passport로 로그인한 계정은 </p>
<pre><code class="language-js">req.logout();</code></pre>
<p>으로 로그아웃 시키라고는 하는데, 크롬 개발자 도구로 쿠키를 확인하면 </p>
<p>name : &quot;connect.sid&quot; 라는 세션 쿠키가 계속 남아있었다.</p>
<hr>
<p><a href="https://m.blog.naver.com/PostView.nhn?blogId=pjok1122&amp;logNo=221565964818">https://m.blog.naver.com/PostView.nhn?blogId=pjok1122&amp;logNo=221565964818</a></p>
<pre><code class="language-js"> req.logout();
    req.session.save(() =&gt; {
        res.redirect(&#39;/&#39;);
    });</code></pre>
<p>방법으로 세션을 저장하고 리다이렉트 시키면 된다고 하시는 분도 있다지만 나한테는 적용되지 않았다.</p>
<hr>
<p><a href="https://stackoverflow.com/questions/13758207/why-is-passportjs-in-node-not-removing-session-on-logout">https://stackoverflow.com/questions/13758207/why-is-passportjs-in-node-not-removing-session-on-logout</a></p>
<p>그래서 또 다른 방법으로</p>
<pre><code class="language-js">    req.session.destroy(() =&gt; {
        res.clearCookie(&#39;connect.sid&#39;);
        res.redirect(&#39;/&#39;);
    });</code></pre>
<p>쿠키를 강제로 날리니 잘 적용되기는 한다.</p>
<hr>
]]></description>
        </item>
        <item>
            <title><![CDATA[오늘 깨달은 날짜 표준 시간 문제]]></title>
            <link>https://velog.io/@___/%EC%98%A4%EB%8A%98-%EA%B9%A8%EB%8B%AC%EC%9D%80-%EB%82%A0%EC%A7%9C-%ED%91%9C%EC%A4%80-%EC%8B%9C%EA%B0%84-%EB%AC%B8%EC%A0%9C</link>
            <guid>https://velog.io/@___/%EC%98%A4%EB%8A%98-%EA%B9%A8%EB%8B%AC%EC%9D%80-%EB%82%A0%EC%A7%9C-%ED%91%9C%EC%A4%80-%EC%8B%9C%EA%B0%84-%EB%AC%B8%EC%A0%9C</guid>
            <pubDate>Mon, 01 Jun 2020 09:22:18 GMT</pubDate>
            <description><![CDATA[<hr>
<p>세션 쿠키가 왜 그렇게 빨리 뒤지나 했더니 호스트 컴퓨터 날짜 시간이랑 세션 만료 시간이랑 차이나서 그런거였다.</p>
<hr>
]]></description>
        </item>
        <item>
            <title><![CDATA[nodejs - passport.deserializeUser 가 호출되지 않는 문제]]></title>
            <link>https://velog.io/@___/nodejs-passport.deserializeUser-%EA%B0%80-%ED%98%B8%EC%B6%9C%EB%90%98%EC%A7%80-%EC%95%8A%EB%8A%94-%EB%AC%B8%EC%A0%9C</link>
            <guid>https://velog.io/@___/nodejs-passport.deserializeUser-%EA%B0%80-%ED%98%B8%EC%B6%9C%EB%90%98%EC%A7%80-%EC%95%8A%EB%8A%94-%EB%AC%B8%EC%A0%9C</guid>
            <pubDate>Mon, 01 Jun 2020 06:27:12 GMT</pubDate>
            <description><![CDATA[<hr>
<p><a href="https://stackoverflow.com/questions/26109556/req-session-passport-is-empty-deserializeuser-not-called-expressjs-passport/30293275#">https://stackoverflow.com/questions/26109556/req-session-passport-is-empty-deserializeuser-not-called-expressjs-passport/30293275#</a></p>
<hr>
<pre><code>On my local machine, I wasn&#39;t running over HTTPs so when cookie.secure is true, the session and user object were empty. When in dev mode and secure was false, it worked correctly.</code></pre><p><img src="https://images.velog.io/images/___/post/b33b0d72-5938-48e6-b756-e22a1d4f8997/%EC%BA%A1%EC%B2%98.PNG" alt=""></p>
<p>개발할 때는 false로.</p>
<hr>
]]></description>
        </item>
        <item>
            <title><![CDATA[nodejs - https 모듈 사용을 위한 인증서 발급을 했던 과정]]></title>
            <link>https://velog.io/@___/https-%EB%AA%A8%EB%93%88-%EC%82%AC%EC%9A%A9%EC%9D%84-%EC%9C%84%ED%95%9C-%EC%9D%B8%EC%A6%9D%EC%84%9C-%EB%B0%9C%EA%B8%89</link>
            <guid>https://velog.io/@___/https-%EB%AA%A8%EB%93%88-%EC%82%AC%EC%9A%A9%EC%9D%84-%EC%9C%84%ED%95%9C-%EC%9D%B8%EC%A6%9D%EC%84%9C-%EB%B0%9C%EA%B8%89</guid>
            <pubDate>Sat, 30 May 2020 10:03:51 GMT</pubDate>
            <description><![CDATA[<hr>
<p>학교 강의에서 프로젝트로 개인 블로그를 만들어야 하게 되었다.</p>
<p><img src="https://images.velog.io/images/___/post/ca717660-bca7-4e04-b6ee-1f22c91ce985/%EC%BA%A1%EC%B2%98.PNG" alt=""></p>
<p>기존의 수업과 교재 내용으로는 nodejs의 http 모듈을 사용하여 웹 서버를 공부했는데, 블로그를 프로젝트로 만들거면 로그인 기능도 필요한 마당에 아예 https 모듈로 갈아타서 기반부터 코드를 작성하는 것이 좋다 생각하였다.</p>
<pre><code class="language-js">...
https = require(&#39;https&#39;);

const server = https.createServer({
    cert: &quot;도메인 인증서 경로&quot;,
    key: &quot;도메인 비밀키 경로&quot;
}, serverApp);
...</code></pre>
<p>http 모듈에서 https 모듈로 교체하면 인증서와 그에 맞는 private key가 필요하다.</p>
<p>무료 인증서로 이름이 알려진 &quot;Let’s Encrypt&quot;를 사용하기로 했다.</p>
<p>발급을 받아보기 위해서 먼저 홈페이지(<a href="https://letsencrypt.org/ko/)%EB%A5%BC">https://letsencrypt.org/ko/)를</a> 들어가보았다.</p>
<p><img src="https://images.velog.io/images/___/post/7edd4c2f-e6d8-4f21-8238-21d892eb3892/1.PNG" alt=""></p>
<p>음 딱 봐도 시작하기를 누르면 될거같다.</p>
<p><img src="https://images.velog.io/images/___/post/44bd3e3b-2b0a-45e8-8278-ddb1f9b6da2f/2.PNG" alt=""></p>
<p>?? 뭔지 모르겠다.</p>
<p>사람들이 개인 블로그에 포스팅한 글을 검색하여 보았다.</p>
<p>&quot;letsencrypt 인증서 발급&quot; -&gt; 죄다 리눅스 기반 OS에서 인증서 발급하는 방법으로 범벅되어있다.</p>
<p>나는 윈도우를 쓴다.</p>
<p>&quot;letsencrypt 윈도우&quot; -&gt; &quot;win-acme&quot;라는 프로그램 또는 openSSL로 발급받는 설명이 주로 있다. </p>
<p>먼저 가장 많이 보이는 &quot;win-acme&quot;를 써보기로 한다.</p>
<p>blog 참고 : <a href="https://jimnong.tistory.com/845">https://jimnong.tistory.com/845</a>
win-acme : <a href="https://github.com/win-acme/win-acme/releases">https://github.com/win-acme/win-acme/releases</a></p>
<p><img src="https://images.velog.io/images/___/post/6bddc563-903b-4c3c-98d5-80da96dcf1bd/3.PNG" alt=""></p>
<p>이름이 좀 이상하지만 받았다.</p>
<p><img src="https://images.velog.io/images/___/post/8ffddc90-3b24-4291-bbf6-00cf1b5dc7a5/4.PNG" alt=""></p>
<p>뭔가 블로그 설명용 그림이랑 처음부터 다르다.</p>
<p>문장 상, &#39;N&#39;이나 &#39;M&#39;이다.</p>
<p><img src="https://images.velog.io/images/___/post/72182a0a-a17f-49bc-9206-ae3939ab6744/5.PNG" alt=""></p>
<p>&#39;C&#39;는 뒤로가기, &#39;1&#39;은 일단 아니고, &#39;3&#39;은 눌러보니 이상한거 뜨길래 &#39;2&#39;;</p>
<p><img src="https://images.velog.io/images/___/post/eefad4e1-6ad2-4c1e-b839-69f45c8def12/6.PNG" alt=""></p>
<p>발급 대상 도메인 입력. 사용중인거 입력했다.</p>
<p><img src="https://images.velog.io/images/___/post/1ee9d703-bf48-4e68-8342-7376df811297/7.PNG" alt=""></p>
<p>&#39;1&#39;,&#39;2&#39;,&#39;3&#39;은 아닌거 같아 &#39;4&#39;</p>
<p><img src="https://images.velog.io/images/___/post/9c982cd5-15a7-4588-95f0-228653b65068/8.PNG" alt=""></p>
<p>인증서 만들기 실패. 재시도 -&gt; 실패.</p>
<p>뭔가 도메인 접속하거나 해서 인증하는 과정이 있는 듯 하다. 근데 모르겠다.</p>
<p>검색 글 보면 하나같이 죄다 단번에 성공이다.</p>
<p><img src="https://images.velog.io/images/___/post/0a249c09-2570-4889-8bee-34193a73e94b/9.PNG" alt=""></p>
<p>?? 어떻게 지멋대로 쓰고 지울 수 있지?</p>
<p><img src="https://images.velog.io/images/___/post/c1da5612-6085-4e39-a856-152cf2d94315/10.PNG" alt=""></p>
<p>단순히 머리잡고 생각하면 지금 동작시키는 wace.exe 프로그램이 파일을 지멋대로 쓰고 그걸 인증하기 위해 도메인을 통해 연결해서 확인하는 듯하다.</p>
<p>지금 프로그램을 돌리는 컴퓨터가 개발용 컴퓨터이고, 서버는 별도의 서버용 컴퓨터에 포트 포워딩해두어서 그런거같다.</p>
<hr>
<p>방법을 바꿔볼 겸 openSSL로 바꿔보았다.</p>
<p>근데 방법을 따라해도 뭐가 무슨 파일인지 잘 몰라서 삽질하며 출력되는 파일들을 테스트용 nodejs - https 모듈 프로그램에 대입해보는데 오류만 계속 떠서 지워버렸다.</p>
<hr>
<p>다시 &quot;win-acme&quot;와 &quot;Let&#39;s encrypt&quot;로 돌아와 좀 더 찾아보니 80포트를 연결해두라고 한다.</p>
<p>서버 컴퓨터 쪽에서 &quot;Let&#39;s Encrypt&quot;의 인증서를 발급하는 과정을 해보았다.</p>
<p>근데 안된다.</p>
<p>5시간 정도 검색과 삽질한 결과,</p>
<h2 id="방화벽-및-국가-접속-제한">방화벽 및 국가 접속 제한</h2>
<p>그냥 방화벽 문제였다. 국가 제한이야 중국말곤 별로 문제 안돼서 그렇다 치고.</p>
<p>그 뒤에 바로 일어난  생각. OS를 윈도우즈 쓸 때 종종 깜빡하는 그것.</p>
<p><img src="https://images.velog.io/images/___/post/83cee2b9-8c83-49ff-a250-728d9833d118/11.PNG" alt=""></p>
<p>인바운드 규칙 ..</p>
<p>윈도우즈 컴퓨터로 동작시키어, 외부 80포트로 부터 연결한 내부 포트를 인바운드에서 열어주니까 된다.</p>
<p>되긴 되지만, 지금 사용하는 도메인이 연결된 서버에 맞게 하는게 좋겠지.</p>
<p>DSM의 힘을 빌려 최종적으로 공개키와 비밀키 pem 파일 2개를 얻었다.</p>
<ul>
<li>cert.pem</li>
<li>privkey.pem</li>
</ul>
<p>테스트용 nodejs - https 모듈 프로그램에 넣고 돌렸는데 잘 돌아간다.</p>
<p>이걸로 블로그 코드 작성해야지.</p>
<hr>
<p><a href="https://letsencrypt.org/ko/">https://letsencrypt.org/ko/</a>
<a href="https://jimnong.tistory.com/845">https://jimnong.tistory.com/845</a>
<a href="https://github.com/win-acme/win-acme/releases">https://github.com/win-acme/win-acme/releases</a>
<a href="https://jimnong.tistory.com/845">https://jimnong.tistory.com/845</a>
<a href="https://extrememanual.net/13002">https://extrememanual.net/13002</a></p>
<hr>
]]></description>
        </item>
        <item>
            <title><![CDATA[javascript/html - 로그인 페이지 구현]]></title>
            <link>https://velog.io/@___/javascripthtml-%EB%A1%9C%EA%B7%B8%EC%9D%B8-%ED%8E%98%EC%9D%B4%EC%A7%80-%EA%B5%AC%ED%98%84</link>
            <guid>https://velog.io/@___/javascripthtml-%EB%A1%9C%EA%B7%B8%EC%9D%B8-%ED%8E%98%EC%9D%B4%EC%A7%80-%EA%B5%AC%ED%98%84</guid>
            <pubDate>Thu, 28 May 2020 21:23:35 GMT</pubDate>
            <description><![CDATA[<hr>
<p>   <a href="https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/String/search">https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/String/search</a>
<a href="https://java119.tistory.com/71">https://java119.tistory.com/71</a></p>
<hr>
<p>과제로 로그인 페이지를 구현해보았다.</p>
<p><img src="https://images.velog.io/images/___/post/2f1677c6-f559-441e-acb8-26a1f516d935/%ED%85%8C%EC%8A%A4%ED%8A%B8.gif" alt=""></p>
<hr>
<p>HTML 코드 ::</p>
<pre><code class="language-html">&lt;!--
 * author : velog.io/@___
 * path : ./signup.html
--&gt;
&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot;&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;
    &lt;title&gt;로그인 페이지&lt;/title&gt;
    &lt;link rel=&quot;stylesheet&quot; href=&quot;./style.css&quot; type=&quot;text/css&quot; media=&quot;all&quot; /&gt;
    &lt;script src=&quot;./login.js&quot; type=&quot;text/javascript&quot;&gt;&lt;/script&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;div id=&quot;container&quot; class=&quot;main_container&quot;&gt;
        &lt;div style=&quot;padding: 20px;&quot;&gt;&lt;/div&gt;
        &lt;div class=&quot;login_container&quot;&gt;
            &lt;div class=&quot;form_container&quot;&gt;
                &lt;form name=&quot;login_form&quot; action=&quot;/cookie&quot; method=&quot;get&quot;&gt;
                    &lt;div class=&quot;form_title_div&quot;&gt;
                        &lt;p class=&quot;form_title_p&quot;&gt;Register With Us&lt;/p&gt;
                    &lt;/div&gt;
                    &lt;div&gt;
                        &lt;div&gt;
                            &lt;a class=&quot;form_item_name&quot;&gt;username&lt;/a&gt;
                        &lt;/div&gt;
                        &lt;div&gt;
                            &lt;input type=&quot;text&quot; name=&quot;username&quot; placeholder=&quot;name&quot; class=&quot;form_input&quot;/&gt;
                        &lt;/div&gt;
                        &lt;div class=&quot;form_text_alert_padding&quot;&gt;
                            &lt;div id=&quot;alert_username&quot; class=&quot;form_text_alert&quot;&gt;&lt;/div&gt;
                        &lt;/div&gt;
                    &lt;/div&gt;
                    &lt;div&gt;
                        &lt;div&gt;
                            &lt;a class=&quot;form_item_name&quot;&gt;Email&lt;/a&gt;
                        &lt;/div&gt;
                        &lt;div&gt;
                            &lt;input type=&quot;text&quot; name=&quot;email&quot; placeholder=&quot;E-mail&quot; class=&quot;form_input&quot;/&gt;
                        &lt;/div&gt;
                        &lt;div class=&quot;form_text_alert_padding&quot;&gt;
                            &lt;div id=&quot;alert_email&quot; class=&quot;form_text_alert&quot;&gt;&lt;/div&gt;
                        &lt;/div&gt;
                    &lt;/div&gt;
                    &lt;div&gt;
                        &lt;div&gt;
                            &lt;a class=&quot;form_item_name&quot;&gt;Password&lt;/a&gt;
                        &lt;/div&gt;
                        &lt;div&gt;
                            &lt;input type=&quot;password&quot; name=&quot;password&quot; placeholder=&quot;Enter password&quot; class=&quot;form_input&quot; /&gt;
                        &lt;/div&gt;
                        &lt;div class=&quot;form_text_alert_padding&quot;&gt;
                            &lt;div id=&quot;alert_password&quot; class=&quot;form_text_alert&quot;&gt;&lt;/div&gt;
                        &lt;/div&gt;
                    &lt;/div&gt;
                    &lt;div&gt;
                        &lt;div&gt;
                            &lt;a class=&quot;form_item_name&quot;&gt;Confirm Password&lt;/a&gt;
                        &lt;/div&gt;
                        &lt;div&gt;
                            &lt;input type=&quot;password&quot; name=&quot;password2&quot; onfocus=&quot;&quot; placeholder=&quot;Enter password again&quot; class=&quot;form_input&quot; /&gt;
                        &lt;/div&gt;
                        &lt;div class=&quot;form_text_alert_padding&quot;&gt;
                            &lt;div id=&quot;alert_password2&quot; class=&quot;form_text_alert&quot;&gt;&lt;/div&gt;
                        &lt;/div&gt;
                    &lt;/div&gt;
                    &lt;div style=&quot;height: 10px;&quot;&gt;&lt;/div&gt;
                    &lt;div&gt;
                        &lt;button type=&quot;button&quot; class=&quot;form_submit_button&quot; onclick=&quot;login()&quot;&gt;Submit&lt;/button&gt;
                    &lt;/div&gt;
                &lt;/form&gt;
            &lt;/div&gt;
        &lt;/div&gt;
    &lt;/div&gt;
&lt;/body&gt;
&lt;/html&gt;</code></pre>
<p>CSS 코드 :: </p>
<pre><code class="language-css">/**
 * author : velog.io/@___
 * path : ./style.css
 */

.main_container{
    border: 0px solid;
}

.login_container{
    width: 380px; 
    height: 520px; 
    margin: auto; 
    border-radius: 3px; 
    box-shadow: 0px 0px 20px #000;
}

.form_container{
    width: 300px;
    margin: auto;
}

.form_title_div{
    margin: auto; 
    text-align: center;
}

.form_title_p{
    font-weight: bold; 
    font-size: 22px; 
    display: inline-block; 
    padding-top: 8px;
}

.form_input{
    width: 98%; 
    height: 30px; 
    border: 1px solid; 
    border-radius: 3px; 
    border-color: gray;
}

.form_item_name{
    color: gray;
}

.form_text_alert{
    height: 20px;
}

.form_text_alert_padding{
    padding-bottom: 10px;
}

.form_submit_button{
    width: 100%; 
    height: 44px; 
    background-color: rgb(83, 154, 236); 
    border: 1px; 
    border-radius: 3px; 
    color: white; 
    font-size: 17px; 
    font-weight: 500;
}</code></pre>
<p>login.js 코드 :: </p>
<pre><code class="language-js">/**
 * author : velog.io/@___
 * path : ./login.js
 */

function login() {
    const form = document.login_form;
    const chkUsername = checkValidUsername(form);
    const chkEmail = checkValidEmail(form);
    const chkPw = checkValidPassword(form);
    const chkPw2 = checkValidPassword2(form);

    if (chkUsername) {
        document.getElementById(&#39;alert_username&#39;).innerText = &quot;&quot;;
        form.username.style.border = &#39;2px solid&#39;;
        form.username.style.borderColor = &#39;#00D000&#39;;
    } else {
        form.username.style.border = &#39;2px solid&#39;;
        form.username.style.borderColor = &#39;#FF0000&#39;;
        document.getElementById(&#39;alert_username&#39;).style.color = &#39;#FF0000&#39;;
    }

    if (chkEmail) {
        document.getElementById(&#39;alert_email&#39;).innerText = &quot;&quot;;
        form.email.style.border = &#39;2px solid&#39;;
        form.email.style.borderColor = &#39;#00D000&#39;;
    } else {
        form.email.style.border = &#39;2px solid&#39;;
        form.email.style.borderColor = &#39;#FF0000&#39;;
        document.getElementById(&#39;alert_email&#39;).style.color = &#39;#FF0000&#39;;
    }

    if (chkPw) {
        document.getElementById(&#39;alert_password&#39;).innerText = &quot;&quot;;
        form.password.style.border = &#39;2px solid&#39;;
        form.password.style.borderColor = &#39;#00D000&#39;;
    } else {
        form.password.style.border = &#39;2px solid&#39;;
        form.password.style.borderColor = &#39;#FF0000&#39;;
        document.getElementById(&#39;alert_password&#39;).style.color = &#39;#FF0000&#39;;
    }
    if (chkPw2) {
        document.getElementById(&#39;alert_password2&#39;).innerText = &quot;&quot;;
        form.password2.style.border = &#39;2px solid&#39;;
        form.password2.style.borderColor = &#39;#00D000&#39;;
    } else {
        form.password2.style.border = &#39;2px solid&#39;;
        form.password2.style.borderColor = &#39;#FF0000&#39;;
        document.getElementById(&#39;alert_password2&#39;).style.color = &#39;#FF0000&#39;;
    }

    if (chkUsername &amp;&amp; chkEmail &amp;&amp; chkPw &amp;&amp; chkPw2) {
        console.log(&#39;complete. form.submit();&#39;);
        //form.submit();
    }
}

function checkValidUsername(form) {
    if (form.username.value == &quot;&quot;) {
        document.getElementById(&#39;alert_username&#39;).innerText = &quot;Please enter username.&quot;;
        //form.username.focus();
        return false;
    }

    return true;
}

function checkValidEmail(form) {
    if (form.email.value == &quot;&quot;) {
        document.getElementById(&#39;alert_email&#39;).innerText = &quot;Please enter email.&quot;;
        //form.email.focus();
        return false;
    }

    const exptext = /^[A-Za-z0-9_\.\-]+@[A-Za-z0-9\-]+\.[A-Za-z0-9\-]+/;

    // &quot;ㅁ@ㅁ.ㅁ&quot; 이메일 형식 검사.
    if (exptext.test(form.email.value) === false) {
        document.getElementById(&#39;alert_email&#39;).innerText = &quot;Email is not valid.&quot;;
        //form.email.select();
        return false;
    }

    return true;
}

function checkValidPassword(form) {
    if (form.password.value == &quot;&quot;) {
        document.getElementById(&#39;alert_password&#39;).innerText = &quot;Please enter password.&quot;;
        //form.password.focus();
        return false;
    }

    const pw = form.password.value;
    // String.prototype.search() :: 검색된 문자열 중에 첫 번째로 매치되는 것의 인덱스를 반환한다. 찾지 못하면 -1 을 반환한다.
    // number
    const num = pw.search(/[0-9]/g);
    // alphabet
    const eng = pw.search(/[a-z]/ig);
    // special characters
    const spe = pw.search(/[`~!@@#$%^&amp;*|₩₩₩&#39;₩&quot;;:₩/?]/gi);

    if (pw.length &lt; 6) {
        // 최소 6문자.
        document.getElementById(&#39;alert_password&#39;).innerText = &quot;Password must be at least 6 characters.&quot;;
        return false;
    } else if (pw.search(/\s/) != -1) {
        // 공백 제거.
        document.getElementById(&#39;alert_password&#39;).innerText = &quot;Please enter your password without spaces.&quot;;
        return false;
    } else if (num &lt; 0 &amp;&amp; eng &lt; 0 &amp;&amp; spe &lt; 0) {
        // 한글과 같은 문자열 입력 방지.
        document.getElementById(&#39;alert_password&#39;).innerText = &quot;Password is not valid.&quot;;
        return false;
    }

    return true;
}

function checkValidPassword2(form) {
    if (form.password2.value == &quot;&quot;) {
        document.getElementById(&#39;alert_password2&#39;).innerText = &quot;Password2 is required.&quot;;
        //form.password.focus();
        return false;
    }

    if (form.password.value !== form.password2.value) {
        document.getElementById(&#39;alert_password2&#39;).innerText = &quot;Password and password2 is not match.&quot;;
        form.password.style.border = &#39;2px solid&#39;;
        form.password.style.borderColor = &#39;#FF0000&#39;;
        document.getElementById(&#39;alert_password&#39;).style.color = &#39;#FF0000&#39;;
        return false;
    }

    return true;
}</code></pre>
<hr>
]]></description>
        </item>
        <item>
            <title><![CDATA[dll 파일의 멀웨어 진단 문제]]></title>
            <link>https://velog.io/@___/dll-%ED%8C%8C%EC%9D%BC%EC%9D%98-%EB%A9%80%EC%9B%A8%EC%96%B4-%EC%A7%84%EB%8B%A8-%EB%AC%B8%EC%A0%9C</link>
            <guid>https://velog.io/@___/dll-%ED%8C%8C%EC%9D%BC%EC%9D%98-%EB%A9%80%EC%9B%A8%EC%96%B4-%EC%A7%84%EB%8B%A8-%EB%AC%B8%EC%A0%9C</guid>
            <pubDate>Mon, 25 May 2020 19:36:24 GMT</pubDate>
            <description><![CDATA[<hr>
<p><a href="https://m.blog.naver.com/PostView.nhn?blogId=sol9501&amp;logNo=70107857763">https://m.blog.naver.com/PostView.nhn?blogId=sol9501&amp;logNo=70107857763</a>
<a href="https://blesseddeveloper.tistory.com/56">https://blesseddeveloper.tistory.com/56</a></p>
<hr>
<p>게임 프로그램 하나 구동시키는데 필요한 dll 파일에 멀웨어 감지가 되어 자꾸 검역소로 간다.</p>
<p>현재 멀웨어 감지되는 dll 파일의 manifest 파일은 다음과 같다.</p>
<pre><code>&lt;assembly xmlns=&quot;urn:schemas-microsoft-com:asm.v1&quot; manifestVersion=&quot;1.0&quot;&gt;
  &lt;trustInfo xmlns=&quot;urn:schemas-microsoft-com:asm.v3&quot;&gt;
    &lt;security&gt;
      &lt;requestedPrivileges&gt;
        &lt;requestedExecutionLevel level=&quot;asInvoker&quot; uiAccess=&quot;false&quot;&gt;&lt;/requestedExecutionLevel&gt;
      &lt;/requestedPrivileges&gt;
    &lt;/security&gt;
  &lt;/trustInfo&gt;
&lt;/assembly&gt;</code></pre><p>혹시나 해서 다음의 권한 수정 구문을 지워보았더니 멀웨어 진단을 안한다..</p>
<pre><code>&lt;requestedExecutionLevel level=&quot;asInvoker&quot; uiAccess=&quot;false&quot;&gt;&lt;/requestedExecutionLevel&gt;</code></pre><p>다른 일반적으로 배포되는 프로그램들에 딸려오는 dll들은 어지간하면 안잡히던데 이 dll파일은 왜 그런걸까</p>
<hr>
]]></description>
        </item>
        <item>
            <title><![CDATA[translators]]></title>
            <link>https://velog.io/@___/translators</link>
            <guid>https://velog.io/@___/translators</guid>
            <pubDate>Fri, 22 May 2020 11:31:32 GMT</pubDate>
            <description><![CDATA[<hr>
<p><a href="https://translators.to/">https://translators.to/</a></p>
<hr>
]]></description>
        </item>
        <item>
            <title><![CDATA[라즈베리파이 - htop]]></title>
            <link>https://velog.io/@___/%EB%9D%BC%EC%A6%88%EB%B2%A0%EB%A6%AC%ED%8C%8C%EC%9D%B4-htop</link>
            <guid>https://velog.io/@___/%EB%9D%BC%EC%A6%88%EB%B2%A0%EB%A6%AC%ED%8C%8C%EC%9D%B4-htop</guid>
            <pubDate>Mon, 18 May 2020 03:04:54 GMT</pubDate>
            <description><![CDATA[<hr>
<p><a href="https://blog.ayukawa.kr/archives/1592">https://blog.ayukawa.kr/archives/1592</a></p>
<hr>
<p>실행중인 프로세스 상태를 보여주는 프로그램.</p>
<p>apt-get install htop</p>
<p>상-하 방향키 : 프로세스 리스트 아이템 이동하며 확인
좌-우 방향키 : 화면 스크롤</p>
<hr>
]]></description>
        </item>
        <item>
            <title><![CDATA[라즈베리파이 가설치]]></title>
            <link>https://velog.io/@___/%EB%9D%BC%EC%A6%88%EB%B2%A0%EB%A6%AC%ED%8C%8C%EC%9D%B4-%EA%B0%80%EC%84%A4%EC%B9%98</link>
            <guid>https://velog.io/@___/%EB%9D%BC%EC%A6%88%EB%B2%A0%EB%A6%AC%ED%8C%8C%EC%9D%B4-%EA%B0%80%EC%84%A4%EC%B9%98</guid>
            <pubDate>Mon, 18 May 2020 02:43:05 GMT</pubDate>
            <description><![CDATA[<hr>
<p><img src="https://images.velog.io/images/___/post/ce8e9890-cfb5-4bcb-80d6-dbf28676cbab/%E3%85%81.jpg" alt=""></p>
<p>위치가 어정쩡한데 둘 위치가 없다..</p>
<hr>
]]></description>
        </item>
        <item>
            <title><![CDATA[nodejs - nodemon]]></title>
            <link>https://velog.io/@___/nodejs-nodemon</link>
            <guid>https://velog.io/@___/nodejs-nodemon</guid>
            <pubDate>Fri, 15 May 2020 12:16:38 GMT</pubDate>
            <description><![CDATA[<hr>
<p><a href="https://www.npmjs.com/package/nodemon">https://www.npmjs.com/package/nodemon</a>
<a href="https://danco.tistory.com/53">https://danco.tistory.com/53</a>
<a href="https://blog.outsider.ne.kr/649">https://blog.outsider.ne.kr/649</a></p>
<hr>
<p>npm install nodemon -g</p>
<pre><code class="language-js">  &quot;scripts&quot;: {
    &quot;test&quot;: &quot;echo \&quot;Error: no test specified\&quot; &amp;&amp; exit 1&quot;,
    &quot;server&quot; : &quot;nodemon index&quot;
  },</code></pre>
<hr>
]]></description>
        </item>
        <item>
            <title><![CDATA[java - ConcurrentLinkedQueue]]></title>
            <link>https://velog.io/@___/java-ConcurrentLinkedQueue</link>
            <guid>https://velog.io/@___/java-ConcurrentLinkedQueue</guid>
            <pubDate>Thu, 14 May 2020 18:48:16 GMT</pubDate>
            <description><![CDATA[<hr>
<p><a href="https://sungjk.github.io/2016/11/02/Queue.html">https://sungjk.github.io/2016/11/02/Queue.html</a>
<a href="http://blog.naver.com/jjoommnn/130159854475">http://blog.naver.com/jjoommnn/130159854475</a></p>
<hr>
]]></description>
        </item>
        <item>
            <title><![CDATA[nodejs - logger.js]]></title>
            <link>https://velog.io/@___/nodejs-logger.js</link>
            <guid>https://velog.io/@___/nodejs-logger.js</guid>
            <pubDate>Wed, 13 May 2020 18:18:06 GMT</pubDate>
            <description><![CDATA[<hr>
<p><a href="https://www.npmjs.com/package/winston">https://www.npmjs.com/package/winston</a></p>
<hr>
<p>쓸만한 logger 모듈을 찾았다.</p>
<pre><code class="language-js">/**
 * logger.js
 */

const winston = require(&#39;winston&#39;);    // logger 모듈.
const moment = require(&#39;moment&#39;);    // 현재 시간 값 가져와 사용하기 편한 모듈.
const winstonRotate = require(&#39;winston-daily-rotate-file&#39;);    // 날짜 별로 로그를 구분하기 위해 별도로 사용하는 모듈.

const LOG_PATH = &quot;./log&quot;;

/*
const levels = { 
  error: 0,
  warn: 1,
  info: 2,
  http: 3,
  verbose: 4,
  debug: 5,
  silly: 6
};
/**/
const logger = new winston.createLogger({
    transports: [
      // console로 출력할 때
        new winston.transports.Console({
            level: &#39;debug&#39;,
            format: winston.format.printf(
                data =&gt; `${moment().format(`YYYY-MM-DD HH:mm:ss.SSS`)} [${data.level.toUpperCase()}] -&gt; ${data.message}`),
        }),
      // file output. 파일 저장 시간 별로 별도 저장.
        new winstonRotate({
            level: &#39;debug&#39;,
            filename: `${LOG_PATH}/log_`,
            maxsize: 100,   // byte 단위이나, 제대로 작동 안하는 듯 하다.
            maxFiles : 1024,
          // 기록되는 출력 포맷.
            format: winston.format.printf(
                data =&gt; `${moment().format(`YYYY-MM-DD HH:mm:ss.SSS`)} [${data.level.toUpperCase()}] -&gt; ${data.message}`),
        }),
    ]
});

module.exports = logger;</code></pre>
<hr>
]]></description>
        </item>
        <item>
            <title><![CDATA[nodejs - http server 퍼포먼스 측정]]></title>
            <link>https://velog.io/@___/nodejs-http-server-performance</link>
            <guid>https://velog.io/@___/nodejs-http-server-performance</guid>
            <pubDate>Mon, 11 May 2020 19:29:00 GMT</pubDate>
            <description><![CDATA[<hr>
<p><a href="https://behonestar.tistory.com/33">https://behonestar.tistory.com/33</a>
<a href="http://www.incodom.kr/Status_code">http://www.incodom.kr/Status_code</a>
<a href="https://velopert.com/287">https://velopert.com/287</a></p>
<hr>
<p>결과 :</p>
<p><img src="https://images.velog.io/images/___/post/2175ca4f-768c-421f-88b7-95f19a71c18a/a.gif" alt=""></p>
<hr>
<p>수행해야 할 내용 : </p>
<p><img src="https://images.velog.io/images/___/post/4e791274-aeb1-4e66-902d-8a1a683d9fcd/%EC%BA%A1%EC%B2%98.PNG" alt=""></p>
<hr>
<p>서버에서 첫 요청이 들어올 때부터 setTimeout()로 서버 강제 종료 전까지 총 10초동안 요청을 받은 횟수를 카운트 하고, 1초당으로 평균을 구하여 출력한다.</p>
<p>웹 서버 코드 ::</p>
<ul>
<li>index.js    // entry point.</li>
<li>web_server.js    // http 서버 구동을 위해.</li>
<li>_logger.js    // 후에 로그 기록을 위해 작성</li>
<li>_system.js    // 자주 사용하는 코드 모아둠.</li>
<li>server_config.json    // 서버 설정 파일 분리용도.</li>
</ul>
<p>퍼포먼스 측정 요청용 클라이언트 측 코드 ::</p>
<ul>
<li>client.js    // 약 10초간 지속적으로 서버에 요청.</li>
</ul>
<p>html 및 관련 파일 ::</p>
<ul>
<li>index.html</li>
<li>style.css</li>
<li>calc.js</li>
</ul>
<p>단, client.js 를 통해 요청할 때에는 index.js 파일만 요청하였다.</p>
<p>웹 브라우저로 테스트 하면 index.html의 내용 중에 구성하는데 필요한 js 파일과 css 파일 및 파비콘 파일도 별도로 요청을 하게 된다. </p>
<hr>
<p>// 서버 측 코드</p>
<pre><code class="language-js">/**
 * index.js, main()
 */

&quot;use strict&quot;;

// require()
//const { print, errPrint, parseCookies } = require(`./_system.js`);
//const logger = require(&#39;./_logger.js&#39;)
const server = require(&#39;./web_server.js&#39;);

// starting point.
server.start();</code></pre>
<pre><code class="language-js">/**
 * web_server.js
 */

&quot;use strict&quot;;

// require()
const { print, errPrint, getFile, parseCookies } = require(`./_system.js`);
const logger = require(&#39;./_logger.js&#39;)
const serverConfig = require(&#39;./properties/server_config.json&#39;);
const http = require(`http`);

// constants
const GATEWAY_IP = serverConfig.GATEWAY_IP;
const PORT = serverConfig.PORT;
const HTML_PATH = serverConfig.HTML_HOME_PATH;
const DEFAULT_REQUEST_FILE = serverConfig.DEFAULT_REQUEST_FILE;

// create server.
const server = http.createServer(requestListener);

let flag = true;
let check = true;
let count = 0;

function requestListener(req, res) {
    if(flag){
        flag = false;
        setTimeout(()=&gt;{
            check = false;
            print(`10초 요청 확인 종료. count : ${count}`);
            print(`1초당 요청 처리 횟수 : ${count/10}`);
            // 서버 강제 종료
            throw new Error(&#39;server turn off&#39;);
        }, 10000);
    }
    const ip = req.headers[&#39;x-forwarded-for&#39;] ||
        req.connection.remoteAddress ||
        req.socket.remoteAddress ||
        req.connection.socket.remoteAddress;
    let requestUrl = req.url;

    if (requestUrl === &#39;/&#39;)
        requestUrl = DEFAULT_REQUEST_FILE;

    //print(`${ip}에서 &#39;${req.url}&#39; 요청.`);
    logger.http(`${ip}에서 &#39;${req.url}&#39; 요청.`);

    if (requestUrl === &#39;/favicon.ico&#39;) {
        getFile(`${HTML_PATH}/favicon32.png`)
            .then((data) =&gt; {
                res.writeHead(200);
                res.end(data);
                print(`&#39;${req.url}&#39; 요청 &#39;${requestUrl}&#39; 응답 완료.`);
                if(check)++count;
            }).catch((error) =&gt; {
                errPrint(error);
                throw new Error(&#39;File not found.&#39;);
            });
    } else {
        getFile(`${HTML_PATH}/${requestUrl}`)
            .then((data) =&gt; {
                let html = data.toString();
                    res.writeHead(200);
                    res.end(html);
                    print(`&#39;${req.url}&#39; 요청 &#39;${requestUrl}&#39; 응답 완료.`);
                    if(check)++count;
            }).catch((error) =&gt; {
                errPrint(error);
                getFile(`${HTML_PATH}/error/page404.html`)
                .then((data) =&gt; {
                    res.writeHead(404);
                    res.end(data);
                    throw new Error(&#39;File not found.&#39;);
                });
            });
    }
}

function setCookies(request, response) {
    const cookies = parseCookies(request.headers.cookie);
    print(`${request.url}, ${cookies}`);
    response.writeHead(200, { &#39;Set-Cookie&#39;: &#39;mc=test&#39; })
}

function start() {
    // port open. server start.
    server.listen(PORT);

    // add event : listening
    server.on(`listening`, () =&gt; {
        print(`PORT : ${PORT} open. 응답 대기 중..`);
    });

    // add event : error
    server.on(`error`, (error) =&gt; {
        errPrint(`error event : ${error}`);
    });
}



module.exports = {
    start,
}</code></pre>
<pre><code class="language-js">/**
 * _system.js
 */

&quot;use strict&quot;;

const fs = require(`fs`);
const print = text =&gt; console.log(text);
const errPrint = text =&gt; console.error(text);

if (typeof alert === &quot;undefined&quot;) {
    //print(&quot;alert is undefined.&quot;);
    //function alert(text) { console.log(&quot;alert : &quot;, text) };
    var alert = text =&gt; print(&quot;alert : &quot; + text);
}


const getFile = (filename) =&gt; {
    return new Promise((resolve, reject) =&gt; {
        fs.readFile(filename, (error, data) =&gt; {
            if (error) {
                reject(error);
            } else {
                resolve(data);
            }
        });
    });
}

module.exports = {
    print,
    errPrint,
    alert,
    getFile,
}</code></pre>
<p>// ./properties/server_config.json</p>
<pre><code class="language-js">{
    &quot;GATEWAY_IP&quot; : &quot;127.0.0.1&quot;,
    &quot;PORT&quot; : 8080,
    &quot;HTML_HOME_PATH&quot; : &quot;./html&quot;,
    &quot;DEFAULT_REQUEST_FILE&quot; : &quot;index.html&quot;
}</code></pre>
<pre><code class="language-js">/**
 * _logger.js
 */

const winston = require(&#39;winston&#39;);
const moment = require(&#39;moment&#39;);
const winstonRotate = require(&#39;winston-daily-rotate-file&#39;);

const LOG_PATH = &quot;./log&quot;;

/*
const levels = { 
  error: 0,
  warn: 1,
  info: 2,
  http: 3,
  verbose: 4,
  debug: 5,
  silly: 6
};
/**/
const logger = new winston.createLogger({
    transports: [
        new winston.transports.Console({
            level: &#39;debug&#39;,
            format: winston.format.printf(
                data =&gt; `${moment().format(`YYYY-MM-DD HH:mm:ss.SSS`)} [${data.level.toUpperCase()}] -&gt; ${data.message}`),
        }),
        new winstonRotate({
            level: &#39;debug&#39;,
            filename: `${LOG_PATH}/log_`,
            maxsize: 100,   // byte 단위이나, 제대로 작동 안하는 듯 하다.
            maxFiles : 1024,
            format: winston.format.printf(
                data =&gt; `${moment().format(`YYYY-MM-DD HH:mm:ss.SSS`)} [${data.level.toUpperCase()}] -&gt; ${data.message}`),
        }),
    ]
});

module.exports = logger;</code></pre>
<hr>
<p>// 퍼포먼스 측정용 클라이언트 코드</p>
<pre><code class="language-js">/**
 * client.js
 */

&quot;use strict&quot;;

// require()
//const { print, errPrint } = require(`./_system.js`);
const http = require(`http`);
const serverConfig = require(&#39;./properties/server_config.json&#39;);

// constants
const PORT = serverConfig.PORT;

const options = {
    host: &#39;localhost&#39;,
    port: PORT,
    path: &#39;/&#39;,
};

if (true) {
    let timer = setInterval(() =&gt; {
        const req = http.request(options, (res) =&gt; {
            res.on(&#39;data&#39;, (data) =&gt; {
              // print(data);
            });
            res.on(&#39;end&#39;, () =&gt; {                
            });
        });
        req.end();
    }, 0.0001);
    setTimeout(()=&gt;{clearInterval(timer)}, 10001);
}</code></pre>
<hr>
<p>// html 파일 및 관련 파일들.</p>
<pre><code class="language-html">&lt;!--
    file name : index.html
    &lt;link rel=&quot;shortcut icon&quot; href=&quot;127.0.0.1:8080/favicon32.png&quot; type=&quot;image/x-icon&quot; /&gt;
--&gt;

&lt;!DOCTYPE html&gt;
&lt;html&gt;

&lt;head&gt;
    &lt;meta charset=&quot;utf-8&quot;&gt;
    &lt;title&gt;node.js web server&lt;/title&gt;
    &lt;link rel=&quot;stylesheet&quot; href=&quot;./themes/style.css&quot; type=&quot;text/css&quot; media=&quot;all&quot; /&gt;
    &lt;script src=&quot;./js/calc.js&quot; type=&quot;text/javascript&quot;&gt;&lt;/script&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;p&gt;&lt;/p&gt;
한글

&lt;/body&gt;
&lt;/html&gt;</code></pre>
<pre><code class="language-css">/**
* author : velog.io/@___
* path : ./themes/style.css
*/

@charset &quot;UTF-8&quot;;


.calc_table{
    position: relative;
    background-color: #FFFFFF;
    border: 1px solid;
    width: 100%;
    max-width: 202px;
    min-height: 320px;
    text-align: center;
    table-layout: fixed;
}

.calc_input{
    border: none;
    text-align: right;
}

td {
    border: 1px solid;
}

/**/
body { 
    /*
    background-color: #00FFFF;
    /**/
    background-image: url(&quot;https://media.vlpt.us/images/___/post/8322958b-7949-4b69-b28e-d2c02737e8df/%EB%B3%B4%EB%85%B8%EB%B3%B4%EB%85%B8200.png&quot;);
    background-repeat: repeat;
}
/**/

.main_container{
    position: absolute;
    width:100%; 
    /*
    top: 100px;
    /**/
}

.calc_area{
    position: relative;
    height: 100%;
    width: 202px;
}</code></pre>
<pre><code class="language-js">/**
* author : velog.io/@___
* path : ./js/calc.js
*
* .. 내용없음. html 로드 시, js 파일을 요청하는 테스트를 위해 만든 파일.
*/</code></pre>
<hr>
<p>일단 측정은 하고 멈추려고 서버를 강제로 내렸으나, 별로 좋은 방법으로 보이진 않는다.</p>
<p>근데 머리로 안되겠으면 일단이라도 이렇게 구현은 해야지.</p>
<hr>
]]></description>
        </item>
    </channel>
</rss>