<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>gidonge.log</title>
        <link>https://velog.io/</link>
        <description></description>
        <lastBuildDate>Wed, 06 Apr 2022 11:54:30 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>gidonge.log</title>
            <url>https://images.velog.io/images/gidong_e/profile/4d1f538c-46f2-432b-899c-03ed9a6b03a6/1CF5E4D3-8D64-4039-85F5-989642068A28.jpeg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. gidonge.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/gidong_e" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[가위바위보 게임 개선]]></title>
            <link>https://velog.io/@gidong_e/%EA%B0%80%EC%9C%84%EB%B0%94%EC%9C%84%EB%B3%B4-%EA%B2%8C%EC%9E%84-%EA%B0%9C%EC%84%A0</link>
            <guid>https://velog.io/@gidong_e/%EA%B0%80%EC%9C%84%EB%B0%94%EC%9C%84%EB%B3%B4-%EA%B2%8C%EC%9E%84-%EA%B0%9C%EC%84%A0</guid>
            <pubDate>Wed, 06 Apr 2022 11:54:30 GMT</pubDate>
            <description><![CDATA[<h3 id="개발-목적">개발 목적</h3>
<p>기존의 가위바위보 게임은 자신이 사용할 <code>가위</code> <code>바위</code> <code>보</code> 중 하나를 선택하여 방을 만들거나 들어가게 되는데 트랜잭션 Input <code>Data</code>를 통해 사전에 값을 확인할 수 있었다.
악용가능성이 있으므로 <code>Data</code>를 keccak256을 사용, 암호화하여 사전에 확인이 어렵게 수정했다.</p>
<h3 id="variable">Variable</h3>
<pre><code class="language-solidity">enum Hand {
    rock,
    paper,
    scissors
 }

enum PlayerStatus {
    STATUS_WIN,
    STATUS_LOSE,
    STATUS_TIE,
    STATUS_PENDING
 }

enum GameStatus {
    STATUS_NOT_STRTED,
    STATUS_STARTED,
    STATUS_COMPLETE,
    STATUS_ERROR
 }

 struct Player {
     address payble addr;
    uint256 playerBetAount;
    bytes32 hand;
    PlayerStatus playerStatus;
    uint result;
    uint count;
 }

 struct Game {
     Player originator;
    Player taker;
    uint256 betAmount;
    GameStatus gameStatus;
 }

 mappint(uint256 =&gt; Game) rooms;
 uint256 roomLen = 0;</code></pre>
<ul>
<li>Hand는 <code>rock</code> <code>paper</code> <code>scissors</code> 인덱스(0,1,2)로 구분한다.</li>
<li>Player는 전송가능한 payable 주소, 배팅금액, Hand, Player 상태등으로 구성한다.</li>
<li>Game은 방장, 참여자, 배팅금액의 합계, 게임 상태로 구성한다.</li>
<li>rooms는 방목록으로 방번호 및 Game의 구조를 값으로 받는다.</li>
<li>roomLen은 방번호로 사용되고 방이 만들어질 때 마다 방번호가 +1이 된다.</li>
</ul>
<h3 id="keccak256">keccak256</h3>
<pre><code class="language-solidity">function keccak(uint256 _hand, string memory _key) public pure returns(byte32) {
    return keccak256(abi.encodePacked(_hand, _key));
   }</code></pre>
<p>keccak256 함수에서 인자1은 hand, 인자2는 임의의 문자를 입력하면 암호화된 키 값이 반환된다.</p>
<h3 id="create-room-join-room">Create Room, Join Room</h3>
<pre><code class="language-solidity">function createRoom(bytes32 _hand) public payable returns (uint256 roomNum)
  {
    rooms[roomLen] = Game({
      betAmount: msg.value,
      gameStatus: GameStatus.STATUS_NOT_STRTED,
      originator: Player({
        hand: _hand,
        addr: payable(msg.sender),
        playerStatus: PlayerStatus.STATUS_PENDING,
        playerBetAmount: msg.value,
        result : 0,
        count : 0
      }),
      taker: Player({
        hand: 0,
        addr: payable(msg.sender),
        playerStatus: PlayerStatus.STATUS_PENDING,
        playerBetAmount: 0,
        result : 0,
        count : 0
      })
    });
    roomNum = roomLen;
    roomLen = roomLen + 1;
  }

 function joinRoom(uint256 roomNum, bytes32 _hand) public payable {
   require(msg.value == rooms[roomNum].betAmount);
    rooms[roomNum].taker = Player({
      hand: _hand,
      addr: payable(msg.sender),
      playerStatus: PlayerStatus.STATUS_PENDING,
      playerBetAmount: msg.value,
      result : 0,
      count : 0
    });
    rooms[roomNum].betAmount = rooms[roomNum].betAmount + msg.value;
  }</code></pre>
<p>암호화된 hand를 가지고 방을 생성하거나, 방에 입장한다.
단, 입장의 경우 방장이 낸 배팅금액과 같아야지만 입장이 가능하다.</p>
<h3 id="decryption">Decryption</h3>
<pre><code class="language-solidity">function useOriginator(uint256  _roomNum, uint256 _hand, string memory _secretKey) public {
    require(msg.sender == rooms[_roomNum].originator.addr);
    require(rooms[_roomNum].originator.hand == keccak(_hand,_secretKey));
    rooms[_roomNum].originator.result = _hand;
    rooms[_roomNum].originator.count = 1;
  }

    function useTaker(uint256  _roomNum, uint256 _hand, string memory _secretKey) public {
    require(msg.sender == rooms[_roomNum].taker.addr);
    require(rooms[_roomNum].taker.hand == keccak(_hand,_secretKey));
    rooms[_roomNum].taker.result = _hand;
    rooms[_roomNum].taker.count = 1;
  }</code></pre>
<p>방장 또는 참여자는 자신이 암호화한 패만을 풀수 있으며 result로 저장한다.</p>
<h3 id="comparehands-payout">CompareHands, Payout</h3>
<pre><code class="language-solidity"> function compareHands(uint256 roomNum) private {
    require(rooms[roomNum].taker.count==1 &amp;&amp; rooms[roomNum].originator.count ==1);
    uint8 originator = uint8(rooms[roomNum].originator.result);
    uint8 taker = uint8(rooms[roomNum].taker.result);

    rooms[roomNum].gameStatus = GameStatus.STATUS_STARTED;

    if (taker == originator) {

      rooms[roomNum].originator.playerStatus = PlayerStatus.STATUS_TIE;
      rooms[roomNum].taker.playerStatus = PlayerStatus.STATUS_TIE;
    } else if ((taker + 1) % 3 == originator) {

      rooms[roomNum].originator.playerStatus = PlayerStatus.STATUS_WIN;
      rooms[roomNum].taker.playerStatus = PlayerStatus.STATUS_LOSE;
    } else if ((originator + 1) % 3 == taker) {

      rooms[roomNum].originator.playerStatus = PlayerStatus.STATUS_LOSE;
      rooms[roomNum].taker.playerStatus = PlayerStatus.STATUS_WIN;
    } else {

      rooms[roomNum].gameStatus = GameStatus.STATUS_ERROR;
    }
  }

modifier isPlayer(uint256 roomNum, address sender) {
    require(
      sender == rooms[roomNum].originator.addr ||
        sender == rooms[roomNum].taker.addr
    );
    _;
  }

  function payout(uint256 roomNum) public payable
    isPlayer(roomNum, msg.sender)
  {
    compareHands(roomNum);
}</code></pre>
<h3 id="회고">회고</h3>
<p>처음 input data를 어떻게 숨길 수 있을까 고민을 했을때 단순히 트랜잭션에서 값을 숨기면 되는게 아닌가 싶었다.
열심히 구글링을 했지만 숨기는 방법은 없었고, keccak을 통해 암호화 하는 방법을 찾아보게 되었다.
사실 위의 코드는 다른분이 작성한 코드를 복붙하여 테스트했다.
아직 솔리디티의 개념과 문법이 어려워서 복붙하여 테스트하고 하나하나 찾아보면서 이해하는게 전부이다보니 많이 벅찬거같다.
좀 더 공부해서 다시 개발해 보겠다.</p>
<p><a href="https://github.com/Gidonge/RPS_Game/blob/main/game.sol">코드공유(Github)</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Mnemonic Wallet]]></title>
            <link>https://velog.io/@gidong_e/Mnemonic-Wallet</link>
            <guid>https://velog.io/@gidong_e/Mnemonic-Wallet</guid>
            <pubDate>Wed, 06 Apr 2022 03:38:55 GMT</pubDate>
            <description><![CDATA[<p>니모닉 지갑 개발이전에 니모닉(Mnemonic)에 대해 먼저 알아보자</p>
<h2 id="what-is-a-mnemonic">What is a Mnemonic?</h2>
<p>암호화폐 지갑은 비대칭키 암호 방식을 사용한다.
때문에 공개키와 개인키가 사용되는데, 이 개인키를 쓰기 편하게 만들어진 것이 <strong>니모닉</strong>이다.</p>
<p>니모닉은 12개의 단어를 순서대로 맞추는 것으로 니모닉 문자를 초기 설정 순서대로 맞추지 못하면 지갑을 열 수 없다.</p>
<blockquote>
<p><a href="http://wiki.hash.kr/index.php/%EB%8B%88%EB%AA%A8%EB%8B%89">More About Mnemonics</a></p>
</blockquote>
<h2 id="developing-mnemonic-wallet">Developing Mnemonic Wallet</h2>
<p><code>eth-lightwallet</code>을 이용하여 간단한 니모닉 지갑을 개발해 보았다.
사용한 모듈에 대해 더 알고 싶다면 <a href="https://github.com/ConsenSys/eth-lightwallet#readme">공식문서</a>를 참고하자.
실제로 <code>eth-lightwallet</code>모듈을 사용한 코드에 대해서만 정리해보자.</p>
<h3 id="mnemonic-api">Mnemonic API</h3>
<pre><code class="language-javascript">router.post(&#39;/newMnemonic&#39;, async(req, res) =&gt; {
  let mnemonic;

  try {
    mnemonic = lightwallet.keystore.generateRandomSeed();
    res.json({ mnemonic });
  } catch (err) {
    console.log(err)
    res.json({ message: err });
  }
});</code></pre>
<p><code>/newMnemonic</code>으로 post요청을 보내면 json 형태로 Mnemonic pharse를 응답한다.
<code>generateRandomSeed()</code>함수를 이용하여 니모닉 코드(Seed)를 랜덤하게 발행하고, 좀 더 보기 편하게 Mnemonic pharse로 변환했다.</p>
<h3 id="newwallet-api">newWallet API</h3>
<pre><code class="language-javascript">router.post(&#39;/newWallet&#39;, async(req, res) =&gt; {
    let password = req.body.password
    let mnemonic = req.body.mnemonic;

    try {
      lightwallet.keystore.createVault(
        {
          password: password, 
          seedPhrase: mnemonic,
          hdPathString: &quot;m/0&#39;/0&#39;/0&#39;&quot;
        },
        function (err, ks) {
          ks.keyFromPassword(password, function (err, pwDerivedKey) {
            ks.generateNewAddress(pwDerivedKey, 1);

            let address = (ks.getAddresses()).toString();
            let keystore = ks.serialize();

            res.json({ keystore: keystore, address: address });
          });
        }
      );
    } catch (exception) { 
      console.log(&quot;NewWallet ==&gt;&gt;&gt;&gt; &quot; + exception);
    }
});</code></pre>
<p>응답받은 Mnemonic pharse를 이용하여 지갑을 개설한다.
<code>/newWallet</code>으로 post 요청을 보내면 <code>key store</code>파일을 로컬에 저장하고 address를 응답받게 된다.</p>
<p><code>key store</code>로 만들기 위해 body에 password 와 mnemonic을 요청해야 하므로 <code>password</code>와 <code>mnemonic</code>변수를 만들어 값을 할당하고, <code>createVault</code> 함수를 사용하여 key store를 만든다.</p>
<h4 id="createvault">createVault</h4>
<ul>
<li>첫번째 인자로 요청할 password, mnemonic, option 을 객체로 묶어 값을 주어야한다.
option의 경우 hdPathString 값을 주어야하는데 디폴트 값 &quot;m/0&#39;/0&#39;/0&#39;&quot;을 주었다. (option에 대해서 더 알고 싶다면 <a href="https://github.com/ConsenSys/eth-lightwallet">공식문서</a>를 참고하자)</li>
</ul>
<ul>
<li><p>두번째 인자(callback)에는 key store를 인자로 사용하는 함수를 만든다. 만든 함수에는 첫번째 인자로 error를, 두번째 인자로는 createVault 함수에서 만든 key store를 받는다.</p>
</li>
<li><p>받은 key store를 이용하여 <code>keyFromPassword</code>함수를 이용, 새로운 주소를 받는다.</p>
</li>
</ul>
<h2 id="using-postman">Using Postman</h2>
<p>Postman을 이용하여 key store와 address의 응답테스트를 진행해보자.
<img src="https://velog.velcdn.com/cloudflare/gidong_e/2f0babb5-18ff-45a0-823c-afa35d1254f2/ezgif.com-gif-maker%20(1).gif" alt=""></p>
<p>서버를 실행시키고 Postman에서 POST를 선택하고 <code>http://localhost:3000/wallet/newMnemonic</code>를 입력 후 SEND를 눌러 서버로 요청을 보내면 니모닉 코드를 응답받을 수 있다.</p>
<p>응답받은 니모닉코드를 <code>mnemonic</code>이라는 키값으로, <code>password</code>에는 원하는 임의의 값으로 입력 후 <code>http://localhost:3000/wallet/newWallet</code> 엔드포인트로 SEND를 눌러 요청을 보낸다.</p>
<h2 id="개발회고">개발회고</h2>
<p>eth-lightwallet 모듈을 사용하여 지갑을 직접 개발해 보았다.
공식문서를 참고하여 함수의 사용법과 동작원리를 이해하고 개발을 하니 큰 어려움없이 진행할 수 있었던거 같다.
공식문서가 영어로 되어있어 보기 힘들고, 때론 보기 싫어 자주 참고하는 편은 아니었다.
이번 개발을 진행하면서 공식문서의 중요성을 알게 되었고, 앞으로도 공식문서를 참고하면서 개발 능력을 키워나가야겠다.</p>
<p><a href="https://github.com/Gidonge/MnemonicWallet/blob/main/mnemonic.js">코드공유(Github)</a></p>
<p>썸네일 이미지 출처</p>
<blockquote>
<p><a href="https://bytecoin.org/blog/hd-wallets-and-mnemonics">bytecoin.org</a></p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[SQL vs No SQL]]></title>
            <link>https://velog.io/@gidong_e/SQL-vs-No-SQL</link>
            <guid>https://velog.io/@gidong_e/SQL-vs-No-SQL</guid>
            <pubDate>Tue, 15 Feb 2022 11:18:33 GMT</pubDate>
            <description><![CDATA[<p>SQL과 NoSQL을 비교하기전 어떤놈들인지 먼저 알아보자...</p>
<h1 id="dbms">DBMS</h1>
<h3 id="database-management-system">DataBase Management System</h3>
<p>사용자와 데이터베이스 사이에서 사용자의 요구에 따라 데이터를 생성해주고 데이터베이스를 관리해주는 소프트웨어이다.</p>
<h1 id="sql">SQL</h1>
<h3 id="strucred-query-language">Strucred Query Language</h3>
<p>관계형 데이터베이스 시스템에서 데이터를 관리하기 위해 설계된 특수목적의 언어로, 자료의 검색과 관리, 스키마 생성과 수정, 데이터베이스 객체 접근 조정 관리를 위해 고안되었다.</p>
<h1 id="rdbms">RDBMS</h1>
<p>DBMS에서 R이 추가되었는데 여기서 R은 <code>Relation</code>의 약자로 관계를 뜻한다.
이름에서 알 수 있듯 관계형 데이터 모델을 기초로 두고 있으며, 모든데이터를 2차원 테이블 형태(행, 열)로 표현하는 데이터베이스이다. 따라서 관계형 데이터베이스는 다른 테이블들과 관계를 맺고 모여있는 집합체라고 볼 수 있다.
이런 관계를 나타내기 위해 <code>Foreign Key</code>(외래키)를 사용하여 테이블간 <code>JOIN</code>이 가능하다는게 큰 특징이다.</p>
<p><img src="https://images.velog.io/images/gidong_e/post/376a3386-a7c0-4fe1-9491-ae75f0b5be28/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-02-15%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%207.42.09.png" alt=""></p>
<p>이미지 출처 : <a href="https://oracletutes.com/rdbms-relational-database-management-system/">Oracle Tutoroals</a></p>
<h1 id="nosql">NoSQL</h1>
<h3 id="not-only-sql">Not Only SQL</h3>
<p>관계형 데이터베이스가 아닌 다른 형태의 데이터 저장기술로, 관계형 데이터베이스와는 다르게 테이블간 관계를 정의 하지 않기 때문에, 데이터테이블은 그냥 하나의 테이블로서 테이블간 <code>JOIN</code>이 불가능 하다.
빅데이터의 등장으로인해 트래픽이 기하급수적으로 증가함에 따라 RDBMS의 단점인 성능을 향상시키기 위해 등장했다. 
따라서 데이터의 일관성은 포기하되 비교적 비용이 적게드는 <code>Scale-Out</code>(데이터 분산)의 장점이 있다.</p>
<h3 id="key-value-database">Key-Value DataBase</h3>
<ul>
<li>Key-Value의 쌍으로 데이터가 저장된다.</li>
<li>Key 값은 어떠한 형태의 데이터라도 담을 수 있다 (이미지, 비디오 형식도 가능)</li>
<li>간단한 API를 제공하는 만큼 질의의 속도가 빠르다는 것이 장점이다.</li>
<li>Redis, Riak, Amazon Dynamo DB등이 있다.
<img src="https://d1.awsstatic.com/product-marketing/DynamoDB/PartitionKey.8dd0530a7f6d66d101f31de30db515564f4cf28a.png" alt=""></li>
</ul>
<p>이미지 출처 :<a href="https://aws.amazon.com/ko/nosql/key-value/">Amazon AWS</a></p>
<p><strong>파티션키는 물리적 공간인 파티션을 특정하는 키</strong></p>
<ul>
<li>스케일이 아무리 커져도 주소를 알고 있어서 빠르게 가져올 수 있다.</li>
<li>파티션키로는 일치하는 값만 가져올 수 있고, 조건문으로 작성할 수 없는 이유이기도 하다.</li>
</ul>
<p><strong>정렬키는 파티션 내에서 정렬하는 기준 값 (검색을 위한 최소의 조건)</strong></p>
<ul>
<li>Number, Binary, String 타입을 지원한다. String 이라면 utf-8 기준으로 정렬된다.</li>
<li>단순한 (문자열) 인덱스라고 생각하면 될 듯 하다.</li>
<li>단순정렬이기 때문에 파티션의 사이즈가 커도 빠르게 가져올 수 있다. (eq, lt, gt 등의 비교 조건과 between, begin_with 만 지원한다)</li>
</ul>
<h3 id="document-database">Document DataBase</h3>
<ul>
<li>key와 Document 형태로 저장</li>
<li>key-Value와 다른 점이라면 Value가 계층적인 형태로 저장된다.
객체 지향에서 객체와 유사하며, 하나의 단위로 취급되어 저장되기 때문에 하나의 객체를 여러개의 테이블에 나눠서 저장할 필요가 없다.</li>
<li>객체를 Docunment의 형태로 저장하기 때문에 객체-관계 매핑이 필요하지 않다.</li>
<li>Key-Value의 특징과 동일하게 검색에 최적화 되어있다.</li>
<li>단점으로는 사용이 번거롭고, 쿼리가 SQL과 다르다.</li>
<li>MongoDB, Couth등이 있다.</li>
</ul>
<p><img src="https://developer.couchbase.com/static/relational_vs_doc1-bcb37aacf0a51c8c73ec1439ad962e9a.png" alt=""></p>
<p>이미지 출처 : <a href="https://developer.couchbase.com/comparing-document-vs-relational/">CouchBase</a></p>
<h3 id="wide-column-database">Wide Column DataBase</h3>
<ul>
<li>Column-Family Model 기반의 데이터베이스이다.</li>
<li>key-Value 값을 이용해 필드를 결정하는 것과는 다르게 이 모델은 키에서 필드를 결정한다.
Key는 <code>Row</code>(키값)와 Column-Family, Column-Name을 가지며, 이렇게 저장된 데이터는 하나의 커다란 테이블로 표현이 가능하다.
질의는 Row, Column-Family, Column-Name을 통해 수행된다.</li>
<li>HBase, Hypertable등이 있다.</li>
</ul>
<p><img src="https://www.researchgate.net/profile/Michael-Mior/publication/264859776/figure/fig1/AS:668915290083333@1536493241409/Data-layout-in-wide-column-stores.png" alt=""></p>
<p>이미지 출처 : <a href="https://www.researchgate.net/figure/Data-layout-in-wide-column-stores_fig1_264859776">ResearchGate</a></p>
<h3 id="graph-database">Graph DataBase</h3>
<ul>
<li>데이터를 Node와 Edge, Properaty와 함께 그래프 구조를 사용하여 데이터를 표현하고 저장한다.</li>
<li>개채와 관계를 크래프 형태로 표현한 것이므로 관계형 모델이라고도 할 수있으며, 데이터 간의 관계가 탐색의 키일 경우게 적합하다.</li>
<li>페이스북이나 트위터같은 소셜네트워크에 적합하고, 연관된 데이터를 추천해주는 추천엔진등의 데이터베이스로도 적합하다고 볼 수 있다.</li>
<li>Neo4J등이 있다.</li>
</ul>
<p><img src="https://kr.mathworks.com/help/examples/database/win64/ExploreGraphDatabaseStructureLiveExample_01.JPEG" alt=""></p>
<p>이미지 출처 : <a href="https://kr.mathworks.com/help/database/ug/explore-the-graph-database-structure.html">MathWorks</a></p>
<h1 id="rdbms-와-nosql의-장단점">RDBMS 와 NoSQL의 장단점</h1>
<h2 id="rdbms-1">RDBMS</h2>
<h3 id="장점">장점</h3>
<ul>
<li>정해진 스키마에 따라 데이터를 저장해야 하기 때문에 명확한 데이터 구조(일관성)를 보장한다.</li>
<li>각 데이터를 중복없이 한번만 저장할 수 있다.<h3 id="단점">단점</h3>
</li>
<li>테이블간 관계를 맺고 있어 시스템이 커질경우 복잡한 쿼리가 만들어 질 수 있다.</li>
<li>성능향상을 위해 Scale-Up만을 지원하기 때문에 비용이 기하급수적으로 늘어날 수 있다.</li>
<li>스키마로 인해 데이터가 유연하지 못하고, 스키마가 변경될 경우 수정이 번거롭고 어렵다.</li>
</ul>
<h2 id="nosql-1">NoSQL</h2>
<h3 id="장점-1">장점</h3>
<ul>
<li>스키마가 없어 유연하고, 자유로운 데이터 구조를 가질 수 있다.</li>
<li>언제든 저장된 데이터를 조정하고 새로운 필드를 만들 수 있다.</li>
<li>데이터 분산이 용이하고 성능향상을 위해 Scale-Up뿐 아니라 Scale-out도 가능하다.<h3 id="단점-1">단점</h3>
</li>
<li>데이터 중복이 발생할 수 있으며, 중복된 데이터가 변경될 경우 모든 컬랙션에서 수정해야하는 번거로움이 있다.</li>
<li>스키마가 존재하지 않기 때문에 명확한 데이터 구조(일관성)를 보장하지 않아 데이터 구조를 결정하기가 어려울 수 있다.</li>
</ul>
<h1 id="그럼-무엇을-언제-써야할까">그럼 무엇을 언제 써야할까?</h1>
<h2 id="rdbms-2">RDBMS</h2>
<p>RDBMS는 데이터 구조가 명확(일관성)하기 때문에, 중복된 데이터가 없어 변경이 용이하기 때문에 관계를 맺고있는 데이터가 자주 변경이 이루어지는 시스템에 적합하다고 볼 수 있겠다.</p>
<h2 id="nosql-2">NoSQL</h2>
<p>NoSQL은 정확한 데이터 구조를 알 수 없고 데이터가 변경/확장이 될 수 있는 경우에 사용하는것이 좋다고 볼 수 있다. 하지만 데이터 중복이 발생할 수 있기 때문에 Update가 많이 이루어지지 않는 시스템이 좋다고 볼 수 있다. 또한 Scale-Out이 가능하다는 장점을 활용해 막대한 데이터를 저장해야하는 빅데이터 관련시스템에도 적합하다고 볼 수 있다.</p>
<h1 id="글을-마치며">글을 마치며</h1>
<p>지난 시간에는 SQL을 배우고 오늘은 NoSQL을 배우게 되었다.
아직 모든 NoSQL을 전부 공부해보고 직접 실습을 해본건 아니지만 둘의 차이점을 찾아보면서 장단점을 알게되었고, 앞으로 진행할 프로젝트에서 어떤 것을 사용해야 좋을지도 이제 감이 잡히는거 같다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[My SQL]]></title>
            <link>https://velog.io/@gidong_e/My-SQL</link>
            <guid>https://velog.io/@gidong_e/My-SQL</guid>
            <pubDate>Mon, 14 Feb 2022 11:32:31 GMT</pubDate>
            <description><![CDATA[<p>My SQL을 알아보기전 SQL에 대해 먼저 알아보자.</p>
<h2 id="1-what-is-sql">1. What is SQL?</h2>
<p><code>SQL</code>이란 Structured Query Language의 약어로 <code>Database</code>용 프로그래밍 언어이다.
데이터베이스에 쿼리를 보내 원하는 데이터를 가져오거나 삽입할 수 있다. 정리하면 <code>SQL</code>은 구조적 쿼리 언어를 의미함을 알 수 있다.</p>
<h3 id="query">Query?</h3>
<p>쿼리(query)란 <code>질의하다</code> 라는 뜻을 가지고있다. 따라서, 쿼리는 저장되어 있는 데이터를 필터하기 위한 질의문으로 이해하면 이해가 쉽다.</p>
<h2 id="2-what-is-rdbms">2. What is RDBMS?</h2>
<p><code>RDBMS</code>는 관계형 데이터베이스 관리 시스템의 약어이다.
RDBMS의 데이터는 테이블이라는 데이터베이스의 개체에 저장되며, 테이블은 관련 데이터 항목의 모음이라고 볼 수 있으며, 열과 행으로 구성된다.
대표적인 RDBMS는 <code>My SQL</code>, <code>Oracle</code>, <code>IBM DB2</code>등이 있다.</p>
<h2 id="3-sql-문법">3. SQL 문법</h2>
<p>모든 문법을 설명하기엔 양이 많아 기본적인 문법 몇가지만 다루고 나머지는 <a href="https://www.w3schools.com/sql/sql_syntax.asp">W3chools</a>을 참고 하면 된다.</p>
<h3 id="1-select">1) SELECT</h3>
<p><code>SELECT</code> 명령문은 데이터베이스에서 데이터를 선택하는데 사용되며, 반환된 데이터는 Result 테이블이 저장된다.</p>
<pre><code class="language-js">SELECT column1, column2, ... FROM table_name</code></pre>
<p>여기서 column1, column2, ...은 선택하고자 하는 데이터이고, 테이블의 모든 데이터를 선택하고자 한다면 <code>*</code>을 사용하면 된다.</p>
<h3 id="2-from">2) FROM</h3>
<p>테이블과 관련된 작업을 할 경우 반드시 입력해야 하며, FROM 뒤에는 결과를 도출해낼 테이블을 명시해야한다.</p>
<h3 id="3-where">3) WHERE</h3>
<p>필터 역할을 하는 쿼리문으로, 선택적으로 사용할 수 있다.</p>
<pre><code class="language-js">SELECT column1, column2, ...
FROM table_name,
WHERE condition;</code></pre>
<p>WHERE 조건</p>
<table>
<thead>
<tr>
<th align="left">술어</th>
<th align="center">연산자</th>
<th align="right">사용예시</th>
</tr>
</thead>
<tbody><tr>
<td align="left">비교</td>
<td align="center">=, &lt;&gt;, &lt;, &lt;=, &gt;, &gt;=</td>
<td align="right">price &lt; 100 //&lt;&gt;는 not Equal을 의미</td>
</tr>
<tr>
<td align="left">범위</td>
<td align="center">BETWEEN</td>
<td align="right">price BETWEEN 100 AND 200</td>
</tr>
<tr>
<td align="left">집합</td>
<td align="center">IN, NOT IN</td>
<td align="right">price IN (10, 20, 30)</td>
</tr>
<tr>
<td align="left">패턴</td>
<td align="center">LIKE</td>
<td align="right">LIKE &quot;%특정 문자열%&quot;</td>
</tr>
<tr>
<td align="left">NULL</td>
<td align="center">IS NULL, IS NOT NULL</td>
<td align="right">price IS NULL</td>
</tr>
<tr>
<td align="left">복합조건</td>
<td align="center">AND, OR, NOT</td>
<td align="right">(price &lt; 100) AND ( ... LIKE &quot;%특정문자열&quot;)</td>
</tr>
</tbody></table>
<h3 id="4-order-by">4) ORDER BY</h3>
<p><code>ORDER BY</code>는 결과를 오름차순 또는 내림차순으로 정렬하는데 사용된다. (Default는 오름차순이다)</p>
<pre><code class="language-js">SELECT * FROM Customers
ORDER BY Country;</code></pre>
<p>위의 예제는 <code>Costomers</code>테이블에서<code>Country</code>열을 기준으로 오름차순으로 정렬된  모든 데이터를 가져온다. 내림차순으로 정렬시엔 아래의 예제처럼 사용하면된다.</p>
<pre><code class="language-js">SELECT * FROM Customers
ORDER BY Country DESC;</code></pre>
<h3 id="5-inner-join">5) INNER JOIN</h3>
<p><code>INNER JOIN</code> 와 <code>JOIN</code> 은 같다. <code>JOIN</code>은 둘이상의 테이블 사이에 관련된 열을 기반으로 데이터를 결합하는데 사용된다.</p>
<p>아래의 예제를 보면 이해하기 쉽다.
(아래의 예제는 w3school에서 가져왔다)</p>
<p>Orders, Customer 테이블에 다음과 같이 데이터가 있다고 가정해보자. 자세히보면 Orders 테이블의 <code>CustomerID</code>열은 Customer 테이블의 <code>CustomerID</code>를 참조하는것을 볼 수 있다.
따라서 Orders, Customer 테이블의 관계는 <code>CustomerID</code> 임을 알 수 있다.
<img src="https://images.velog.io/images/gidong_e/post/289d93f2-e8ea-4409-ab0e-747c9c8ac381/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-02-14%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%207.59.59.png" alt=""></p>
<p><img src="https://images.velog.io/images/gidong_e/post/f866fb25-3469-4bc3-9f11-f32114652f40/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-02-14%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%208.00.11.png" alt=""></p>
<p><code>JOIN</code>은 위의 두 테이블에서 일치하는 값을 가진 데이터를 가져올 수 있다.</p>
<pre><code class="language-js">SELECT Orders.OrderID, Customers.CustomerName, Orders.OrderDate
FROM Orders
JOIN Customers ON Orders.CustomerID = Customers.CustomerID;</code></pre>
<p><img src="https://images.velog.io/images/gidong_e/post/8bef81c3-ce43-4c73-a318-1b7dbb37ee73/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-02-14%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%208.00.18.png" alt=""></p>
<p><code>Orders</code> 테이블의 <code>CustomerID</code>와 <code>Customers</code> 테이블의 <code>CustomerID</code>가 일치하는 데이터 중 <code>OrderID</code>, <code>CustomerName</code>, <code>OrderDate</code>열만 가져왔음을 알 수 있다.</p>
<h2 id="4-sql-vs-nosql">4. SQL vs NoSQL</h2>
<p>데이터베이스는 크게 관계형 데이터베이스와 비관계형 데이터베이스로 구분한다. 관계형 데이터베이스는 SQL을 기반으로 하고, 비관계형 데이터 베이스는 NoSQL로 데이터를 다루는데, 둘의 차이는 만들어진 방식, 저장하는 정보의 종류, 저장하는 방법이 있다.</p>
<h3 id="1-관계형-데이터베이스">1) 관계형 데이터베이스</h3>
<p>관계형 데이터베이스에서는 테이블의 구조와 데이터 타입등을 사전에 정의해야하며, 정의된 내용에 맞는 데이터만 삽입할 수 있다. 데이터베이스는 행과 열로 구성된 테이블에 데이터를 저장하며, 각열은 하나의 속성에 대한 정보를 저장하고, 행에는 각 열의 데이터 형식에 맞는 데이터가 저장한다. 특정한 형식을 지키기 때문에 관계형 데이터 베이스는 테이블 간의 관계를 직관적으로 파악할 수 있다.</p>
<h3 id="2-비관계형-데이터베이스">2) 비관계형 데이터베이스</h3>
<p>NoSQL은 주로 데이터가 고정되어 있지 않은 데이터베이스를 가르킨다. 관계형 데이터베이스는 데이터를 입력할때 스키마에 맞게 입력해야 하지만, NoSQL에서는 데이터를 읽어올 때 스키마에 따라 데이터를 읽어온다는 차이점이 있다.</p>
<h4 id="비관계형-데이터베이스의-구성">비관계형 데이터베이스의 구성</h4>
<ul>
<li><p>Key-Value : 속성을 <code>Key-Value</code>의 쌍으로 나타내는 데이터를 배열의 형태로 저장하며, Key는 속성의 이름을 뜻하고, Value는 속성에 연결된 데이터값을 의미한다
(Redis, Dynamo 등이 대표적인 데이터베이스이다)</p>
</li>
<li><p>Document : 데이터를 테이블이 아닌 문서처럼 저장하는 데이터베이스를 의미한다. 각각의 문서는 하나의 속성에 대한 데이터를 가지고 있고, 컬렉션이라고 하는 그룹으로 묶어서 관리한다.
(MongoDB가 대표적인 데이터베이스이다)</p>
</li>
<li><p>Wide-Column : 데이터베이스의 Column에 대한 데이터를 집중적으로 관리하는 데이터베이스로, 각 열에는 key-value 형식으로 데이터가 저장되거, 컬럼 패밀리라고 하는 열의 집합체 단위로 데이터를 처리할 수 있다. 데이터 처리에 필요한 열을 유연하게 선택할 수 있다는 점에서 규모가 큰 데이터 분석에 주로 사용된다.
(Cassandra, HBase 등이 대표적인 데이터베이스 이다)</p>
</li>
<li><p>Graph : 자료구조의 그래프와 비슷한 형식으로 데이터 간의 관계를 구성하는 데이터베이스로, 노드에 속성별로 데이터를 저장하며, 각 노드간 관계는 선으로 표현한다.
(Neo4J, InfiniteGraph 등이 대표적인 데이터베이스이다)</p>
</li>
</ul>
<h2 id="글을-마치며">글을 마치며</h2>
<p>자바스크립트를 배우기전 My SQL을 사용해본적이 있다. 정말 기본적인 문법만 몇가지 사용해봤기에 잘할수 있다고 말할수는 없지만 이번 과제를 풀기위해 다시 공부해 봤을때 도움이 많이 되었던거 같다. 아직은 정확하게 SQL - NoSQL의 차이점과 어떤것을 사용해야하는지 정확하게 알 수 없지만 NoSQL을 공부하고 이후에 다시금 정리 해봐야겠다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Node.js] Express]]></title>
            <link>https://velog.io/@gidong_e/Node.js-Express</link>
            <guid>https://velog.io/@gidong_e/Node.js-Express</guid>
            <pubDate>Thu, 03 Feb 2022 06:02:02 GMT</pubDate>
            <description><![CDATA[<p>이전 시간에 Node.js HTTP 모듈에 대해 배웠고, 오늘은 Express 모듈에 대해 설명해보려고 한다.</p>
<h2 id="what-is-express">What is Express?</h2>
<p><a href="https://expressjs.com/ko/">expressjs.com/ko/</a> 에서 설명하는 바는 다음과 같다.
&quot;Express는 웹 및 모바일 애플리케이션을 위한 일련의 강력한 기능을 제공하는 간결하고 유연한 Node.js 웹 애플리케이션 프레임워크 입니다.&quot;</p>
<p>쉽게 말해 Node.js를 사용하여 보다 쉽게 서버를 구성할 수 있게 만든 프레임 워크라고 보면 되겠다.
⭐️ 프레임 워크란?
클래스와 라이브러리의 집합체이다.</p>
<h2 id="express-install">Express Install</h2>
<p>Express 모듈을 사용하기전 설치 방법을 알아보자.</p>
<ol>
<li><code>npm init</code>을 통해 초기환경을 셋팅한다. (package.json)</li>
<li><code>npm install express</code>를 통해 express 패키지를 설치 한다.</li>
<li>-끝-</li>
</ol>
<h2 id="hello-world-예제">Hello world 예제</h2>
<p>왜 항상 예제는 Hello world인지 모르겠다.. 이쯤되면 지긋지긋하다.
그래도 <a href="https://expressjs.com/ko/starter/hello-world.html">공식 문서</a>를 보고 따라해보자...</p>
<pre><code class="language-javascript">const express = require(&#39;express&#39;)
const app = express()
const port = 3000

app.get(&#39;/&#39;, (req, res) =&gt; {
  res.send(&#39;Hello World!&#39;)
})

app.listen(port, () =&gt; {
  console.log(`Example app listening on port ${port}`)
})                  </code></pre>
<p>Express 모듈을 사용하기 위해선 require를 통해 가져와야 하는데 여기서 궁금증
왜 import-from이 아니라 require일까?</p>
<h4 id="import와-require의-차이점은-다음과-같다">import와 require의 차이점은 다음과 같다.</h4>
<p>기본적으로 <code>require</code>와 <code>import</code>는 모듈 키워드 이며, 외부 파일이나 라이브러리를 불러 올때 사용한다.
require는 Node.js에서 사용되고 있는 CommonJS 키워드이고, import는 ES2015에서 새롭게 도입된 키워드이다. 둘다 외부파일이나 라이브러리를 불러올때 사용하지만 다른 문법 구조를 지니고있다.</p>
<pre><code class="language-javascript">const library = require(&#39;library&#39;)</code></pre>
<pre><code class="language-javascript">import library from &#39;library&#39;</code></pre>
<p>정리하자면 새롭게 도입된 키워드 <code>import</code>는 아직까지 완전히 대체되어 사용되지 않기 때문에
CommonJS를 기본 모듈로 사용하는 Node.js의 경우 <code>require</code>키워드를 사용해야한다.</p>
<h4 id="express-불러오기">Express 불러오기</h4>
<p>위의 예제를 보면 알 수 있듯, <code>require</code>를 통해 express 모듈을 불러오고 <code>const app</code>변수를 통해 express를 실행해주면된다. 그리고 HTTP 모듈에서와 같이 <code>listen</code>을 통해 port를 설정해주고 끝내면된다.</p>
<h2 id="express-method">Express Method</h2>
<p>간단한 예제를 통해 express모듈을 불러오는법을 알았으니 이제 관련 메소드에 대해 알아보자.
공식 문서에서 알려주는 메소드는 여러가지가 있지만 간단하게 설명해보려고 한다. 더자세하게 알고싶으면 <a href="https://expressjs.com/ko/4x/api.html#app">공식문서</a>를 참조해보자.</p>
<p><img src="https://s3.ap-northeast-2.amazonaws.com/urclass-images/auEpUwrE7-1600964704103.png" alt="method"></p>
<p>그림에서 알 수 있듯 Endpoint가 <code>&#39;/&#39;</code>이고, 클라이언트로부터 GET요청을 받았을때 적용되는 미들웨어로, <code>req</code>는 request, <code>res</code>는 response, <code>next</code>는 다음 미들웨어를 실행하는 콜백인수로 이해하면된다.</p>
<h3 id="middleware란">Middleware란</h3>
<p><a href="https://ko.wikipedia.org/wiki/%EB%AF%B8%EB%93%A4%EC%9B%A8%EC%96%B4">위키백과</a>에서의 정의를 요약하자면 &quot;미들웨어는 양쪽을 연결하여 데이터를 주고 받을 수 있도록 중간에서 매개 역할을 하는 소프트웨어, 네트워크를 통해서 연결된 여러 개의 컴퓨터에 있는 많은 프로세서들에게 어떤 서비스를 사용할 수 있도록 연결해주는 소프트웨어를 말한다.&quot;</p>
<p><img src="https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbtJCof%2FbtqwBOAKG78%2FPgLeOyR4vaZW8BKyvUdtuk%2Fimg.png" alt="middleware">
Express에서의 미들웨어는 어떤 역할을 할까?
공식 문서에 따르면 아래와 같은 작업을 수행할 수 있다고 한다.</p>
<ul>
<li>모든 코드를 실행한다.</li>
<li>요청및 응답 개체를 변경한다.</li>
<li>요청-응답 주기를 종료한다.</li>
<li>스택에서 다음 미들웨어 함수를 호출한다.</li>
</ul>
<p>Express에서 제공하는 미들웨어는 <a href="https://expressjs.com/ko/resources/middleware.html">공식문서</a>를 참고하자.</p>
<h2 id="글을-마치며">글을 마치며...</h2>
<p>HTTP 모듈이후 Express모듈을 배우면서 많이 헤멧던거같다... 엘리누나의 온라인강의가 없었다면 아직도 헤메고 있지 않을까... 라고 생각된다 어느정도 express에 대해 감이 잡힌 이후론 HTTP보다 더 간결하고 재밌게 코딩을 할 수 있었던거같다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Node.js http 모듈 ]]></title>
            <link>https://velog.io/@gidong_e/Node.js-http-%EB%AA%A8%EB%93%88</link>
            <guid>https://velog.io/@gidong_e/Node.js-http-%EB%AA%A8%EB%93%88</guid>
            <pubDate>Fri, 28 Jan 2022 11:11:12 GMT</pubDate>
            <description><![CDATA[<p>Node.js http 모듈을 사용해 웹서버를 구축하는 과정을 알아보자
아래의 내용은 node.js의 HTTP 트랜잭션 해부 공식문서를 정리한 내용이다</p>
<h2 id="서버생성">서버생성</h2>
<p>모든 node웹 서버 애플리 케이션은 웹 서버 객체를 만들어야 하는데, <code>createServer</code>를 이용한다.</p>
<pre><code class="language-javascript">const http = require(&#39;http&#39;);

const server = http.createServer((request, response) =&gt; {
  // code...
});

server.listen(3000, () =&gt; {
    console.log(&#39;server running, Port 3000&#39;);
})</code></pre>
<p>모듈을 사용하기 위해 http 모듈을 <code>require</code>로 불러오고, <code>createServer</code>메소드를 통해 <code>request</code>, <code>response</code> 객체를 전달하고, <code>listen</code> 메소드를 통해 접속하는 포트를 할당한다.</p>
<h2 id="request">Request</h2>
<p>request는 서버로 보내는 요청에 대한 정보가 들어있으며, Header와 (optional)body로 구성되어 있다.</p>
<h4 id="header">Header</h4>
<pre><code class="language-javascript">const { headers } = request;
const userAgent = headers[&#39;user-agent&#39;];</code></pre>
<p>⭐️ 모든 header는 소문자로만 표현된다. 이는 어떤 목적이든 header를 파싱하는 작업을 간편하게 해준다.</p>
<h4 id="body">Body</h4>
<pre><code class="language-javascript">let body = [];

request.on(&#39;data&#39;, (chunk) =&gt; {
  body.push(chunk);
}).on(&#39;end&#39;, () =&gt; {
  body = Buffer.concat(body).toString();
});</code></pre>
<p>⭐️ body에 담긴 데이터는 Buffer 형태로 들어온다. 때문에 <code>chunk</code> 파라메터로 받아 문자열로 바꿔준다.</p>
<h4 id="error">Error</h4>
<pre><code class="language-javascript">request.on(&#39;error&#39;, (err) =&gt;{
  console.error(err.stack);
})</code></pre>
<p>⭐️ 단순히 error를 로깅만 하더라도 <code>error</code> 리스너를 추가해야 한다. &quot;만약 사용하지 않는다면 Node.js 프로그램을 종료시킬 수도 있는 오류를 던질것입니다.&quot; 라고 공식문서에 기재되어있다.</p>
<p>종합해보면 아래코드와 같다.</p>
<pre><code class="language-javascript">const http = require(&#39;http&#39;);

http.createServer((request, response) =&gt; {
  const { headers, method, url } = request;

  let body = [];

  request.on(&#39;error&#39;, (err) =&gt; {
    console.error(err);
  }).on(&#39;data&#39;, (chunk) =&gt; {
    body.push(chunk);
  }).on(&#39;end&#39;, () =&gt; {
    body = Buffer.concat(body).toString();
  });
}).listen(3000);
</code></pre>
<h2 id="response">Response</h2>
<p>response는 서버가 클라이언트에게 할 응답으로, request와 마찬가지로 header와 (optional)body로 구성되어 있다.</p>
<h4 id="statuscode-상태코드">statusCode (상태코드)</h4>
<p>따로 설정하지 않으면 상태코드는 항상 200이다. 경우에 따라 상태코드를 변경하기 위해선 statusCode를 사용한다.</p>
<pre><code class="language-javascript">response.statusCode = 404;</code></pre>
<table>
<thead>
<tr>
<th align="left"><span style="color:black"> <strong>Status Code</strong> </span></th>
<th align="center"><span style="color:black"><strong>Meaning</strong> </span></th>
</tr>
</thead>
<tbody><tr>
<td align="left"><span style="color:black"> 200 </span></td>
<td align="center"><span style="color:black">요청 성공 </span></td>
</tr>
<tr>
<td align="left"><span style="color:black">304 </span></td>
<td align="center"><span style="color:black">304 요청에 대한 응답이 수정되지 않음 </span></td>
</tr>
<tr>
<td align="left"><span style="color:black"> 400 </span></td>
<td align="center"><span style="color:black"> Bad request: 잘못된 문법으로 인해 서버가 요청을 이해할 수 없음 </span></td>
</tr>
<tr>
<td align="left"><span style="color:black">403 </span></td>
<td align="center"><span style="color:black"> Forbidden: 해당 Client가 접근 권한이 없음  </span></td>
</tr>
<tr>
<td align="left"><span style="color:black">404 </span></td>
<td align="center"><span style="color:black"> Not Found: Server가 요청받은 리소스를 찾을 수 없거나, 알수없는 url을 요청받음</span></td>
</tr>
<tr>
<td align="left"><span style="color:black"> 500</span></td>
<td align="center"><span style="color:black"> 서버가 처리할 수 없는 요청</span></td>
</tr>
<tr>
<td align="left">⭐️ 이외의 상태코드는 <a href="https://developer.mozilla.org/ko/docs/Web/HTTP/Status">여기</a>에서 확인해 볼 수 있다.</td>
<td align="center"></td>
</tr>
</tbody></table>
<h4 id="writehead">writeHead</h4>
<p>상태코드와 헤더를 같이 설정하는 메소드이다.
writeHead 메소드는 클라이언트에 보낼 response의 header라고 이해하면된다.</p>
<pre><code class="language-javascript">if(method === &#39;OPTIONS&#39;) {
  response.writeHead(200, defaultCorsHeader);
  response.end();
};

const defaultCorsHeader = {
  &#39;Access-Control-Allow-Origin&#39;: &#39;*&#39;,
  &#39;Access-Control-Allow-Methods&#39;: &#39;GET, POST, PUT, DELETE, OPTIONS&#39;,
  &#39;Access-Control-Allow-Headers&#39;: &#39;Content-Type, Accept&#39;,
  &#39;Access-Control-Max-Age&#39;: 10
};</code></pre>
<p><code>defaultCorsHeader</code>의 내용을 간략하게 설명하면 아래와 같다.</p>
<ul>
<li>모든 도메인(&#39;*&#39;)을 허용한다.</li>
<li>GET, POST, PUT, DELETE, OPTIONS&#39; =&gt; 메소드는 GET, POST, PUT, DELET, OPTION만 허용한다.</li>
<li>헤더에는 content-type과 accept만 허용 된다.</li>
<li>preflight request는 10초까지 허용 된다.
쉽게 말해 서버에서 클라이언트에게 보내는 메세지라고 보면되겠다.
끝으로 <code>response.end()</code>를 통해 보낼데이터를 body에 담아 전달하면된다.
⭐️ end 메소드를 쓰기전에 상태코드와 헤더가 설정되어 있어야 한다.</li>
</ul>
<h1 id="글을-마치며">글을 마치며...</h1>
<p>브라우저와 서버가 어떻게 통신을 하는지 알게 되었고, 모르는 내용을 구글링하면서 찾아보는 재미가 쏠쏠했던거 같다. 개인적으로 자바스크립트라는 언어는 정말 싫었는데 오늘 node.js http모듈을 공부하면서 조금씩 재미를 느끼는중이라 참 다행이라고 생각한다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[What is HTTP?]]></title>
            <link>https://velog.io/@gidong_e/What-is-HTTP</link>
            <guid>https://velog.io/@gidong_e/What-is-HTTP</guid>
            <pubDate>Tue, 25 Jan 2022 05:56:32 GMT</pubDate>
            <description><![CDATA[<h1 id="http-hypertext-transfer-protocol">HTTP (HyperText Transfer Protocol)</h1>
<p>텍스트 기반의 통신 규약으로 <span style="color:red">웹에서 HTML, JSON등의 정보를 주고받는 프로토콜</span>, 쉽게 말해 인터넷에서 데이터를 주고받을 수 있는 프로토콜이다.
이 규약에 맞춰 <code>Client</code>에서 서버로 요청(request)을 보내면 <code>Server</code>는 응답(response)을 보내는 통신을 할 수 있다.</p>
<h2 id="http-동작">HTTP 동작</h2>
<p>사용자(Client)가 브라우저를 통해 주소(URL, URI)를 통해 요청(request)을 하면 서버에서는 요청사항에 맞춰 응답(response)하는 형태로 동작하게 된다.
⭐️ HTML 만이 HTTP 통신을 위한 유일한 문서는 아니며 사용자에 요청에 맞춰 JSON, XML과 같은 형태의 정보를 주고 받을 수 있다.</p>
<p><img src="https://mdn.mozillademos.org/files/13827/HTTPMsgStructure2.png" alt="http 그림1"></p>
<blockquote>
<p>출처 : <a href="https://developer.mozilla.org/ko/docs/Web/HTTP/Messages">MDN</a></p>
</blockquote>
<p>요청(request)와 응답(response)는 비슷한 구조를 가진다.</p>
<ul>
<li>start line : start line에는 요청이나 응답의 상태를 나타내며 항상 첫번째 줄에 위치한다. (응답에서는 status line이라고 부름)</li>
<li>HTTP headers : 요청의 정보를 지정하거나, 메세지에 포함된 본문을 설명하는 헤더의 집합</li>
<li>empty line : 헤더와 본문을 구분하는 빈줄</li>
<li>body : 요청과 관련된 데이터나 응답과 관련된 데이터 또는 문서를 포함</li>
</ul>
<h3 id="1-요청request">(1) 요청(Request)</h3>
<h4 id="start-line">Start line</h4>
<p>HTTP 요청은 클라이언트가 서버에 보내는 메세지로 start line에는 세가지 요소가 있다.</p>
<ol>
<li>수행할 작업(GET, PUT, POST등)이나 방식(HEAD 또는 OPTIONS)을 설명하는 HTTP method</li>
<li>요청대상 또는 <code>프로토콜</code>, <code>포트</code>, <code>도메인</code>의 절대 경로는 요청 컨텍스트에 작성되며 HTTP method 마다 다르다.</li>
<li>HTTP 버전은 메세지의 다른 구조를 결정하므로 버전을 함께 입력</li>
</ol>
<h4 id="headers">Headers</h4>
<p><img src="https://mdn.mozillademos.org/files/13821/HTTP_Request_Headers2.png" alt="header"></p>
<blockquote>
<p>출처 : <a href="https://developer.mozilla.org/ko/docs/Web/HTTP/Messages">MDN</a></p>
</blockquote>
<p>요청에 들어가는 HTTP header는 헤더의 기본 구조를 따르며, 대소문자 구분없는 문자열 다음에 콜론<code>(:)</code>이 붙고, 뒤에 오는 값은 헤더에 따라 달라진다.</p>
<ol>
<li>General headers : 메세지 전체에 적용됨</li>
<li>Request headers : <code>User-Agent</code>, <code>Accept-type</code>, <code>Accept-Language</code> 같은 헤더는 요청을 구체화하며 <code>Referer</code>  처럼 컨텍스트를 제공하거나 <code>If-None</code>과 같이 조건에 따라 제약을 추가할 수있음</li>
<li>Entity headers : Content-Length와 같은 헤더는 body에 적용되며 body가 비어있는 경우 전송되지 않음</li>
</ol>
<h4 id="body">Body</h4>
<p>HTTP 구조의 마지막에 위치하며, 꼭 모든 요청에 body가 필요한 건 아니다. (<code>GET</code>,<code>HEAD</code>,<code>DELETE</code>,<code>OPTIONS</code>처럼 서버에 리소스를 요청하는 경우)
<code>POST</code>,<code>PUT</code>과 같은 일부 요청은 데이터를 업데이트하기 위해 사용하며 두가지 종류로 나눌 수 있다.</p>
<ul>
<li>Single-resource bodies(단일-리소스 본문) : 헤더 두개(Content-length, Contne-type)로 정의된 단일 파일로 구성</li>
<li>Multiple=resource bodies(다중-리소스 본문) : 각 파트마다 다른 정보로 구성</li>
</ul>
<h3 id="2-응답responses">(2) 응답(Responses)</h3>
<h4 id="status-line">Status line</h4>
<p>응답의 첫줄은 status line으로 부르며 아래의 정보를 포함한다.</p>
<ol>
<li>현재의 프로토콜 버전</li>
<li>상태코드(요청의 결과를 나타냄)</li>
<li>상태 텍스트(상태코드에 대한설명)</li>
</ol>
<h4 id="headers-1">Headers</h4>
<p><img src="https://s3.ap-northeast-2.amazonaws.com/urclass-images/CVLWG7X3Z-1620275557974.png" alt="header 2"></p>
<blockquote>
<p>출처 : <a href="https://urclass.codestates.com/00a00414-de2d-422d-a16b-1993784ebb72?playlist=862">MDN</a></p>
</blockquote>
<p>응답에 들어가는 HTTP header는 요청헤더와 동일한 구조를 가지고 있다.</p>
<ol>
<li>General headers : 메세지 전체에 적용됨</li>
<li>Response headers : <code>Vary</code>,<code>Accept-Ranges</code>와 같이 상태 줄에 넣기에 부족했던 추가정보</li>
<li>Entity headers : Content-length와 같은 헤더는 body에 적용되며 body가 비어있는 경우 전송 되지 않음</li>
</ol>
<h4 id="body-1">Body</h4>
<p>HTTP 구조의 마지막에 위치하며, 꼭 모든요청에 body가 필요한 건 아니다. (201, 204와 같은 상태코드)</p>
<ul>
<li>Single-resource bodies(단일-리소스 본문) :
길이가 알려진 단일-리소스 본문은 두 개의 헤더(Content-Type, Content-Length)로 정의,
길이를 모르는 단일 파일로 구성된 단일-리소스 본문은 Transfer-Encoding이 chunked 로 설정되어 있으며, 파일은 chunk로 나뉘어 인코딩되어 있다.</li>
<li>Multiple-resource bodies(다중-리소스 본문) : 서로 다른 정보를 담고 있는 body</li>
</ul>
<h2 id="마치며">마치며</h2>
<p>코딩을 배우기전 다니던 회사에서 RS-485통신 이더넷 통신등 많이 해봤던게 이번 HTTP를 배울때 많이 도움이 되었던거같다. 다만 모든 통신을 해보고싶지는 않다..... 지금 공부하는 걸로도 충분히 차고넘친다..
이제 Rest API를 배울텐데 막막하다🤪</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[JavaScript 비동기]]></title>
            <link>https://velog.io/@gidong_e/JavaScript-%EB%B9%84%EB%8F%99%EA%B8%B0</link>
            <guid>https://velog.io/@gidong_e/JavaScript-%EB%B9%84%EB%8F%99%EA%B8%B0</guid>
            <pubDate>Wed, 19 Jan 2022 13:26:06 GMT</pubDate>
            <description><![CDATA[<h3 id="들어가기전에">들어가기전에...</h3>
<h4 id="javascript는-동기식synchronous-언어이다">JavaScript는 동기식(Synchronous) 언어이다.</h4>
<p>자바스크립트는 한번에 하나의 작업을 수행하는데, <span style="color:red"><strong>한 작업이 실행되는 동안 다른 작업은 멈춰있고 자기 차례를 기다린다는 뜻이다.</strong></span>
이러한 동작을 싱글스레드, 동기라고 한다.</p>
<pre><code class="language-javascript">console.log(&quot;Hello&quot;)
console.log(&quot;Nice to meet you!&quot;)
console.log(&quot;Bye!!&quot;)

// 출력결과
// Hello
// Nice to meet you!
// Bye!!</code></pre>
<p>⭐️ 순서대로 출력되는것을 확인할 수 있다.</p>
<h3 id="왜이렇게-출력되는-것일까">왜이렇게 출력되는 것일까?</h3>
<p><img src="https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbMlLfs%2FbtqFQ9i1iD3%2FZQE2tqi7lx7LUhTwK1tDtK%2Fimg.png" alt="자바스크립트"></p>
<blockquote>
<p>출처 : <a href="https://blog.sessionstack.com/how-does-javascript-actually-work-part-1-b0bacc073cf">https://blog.sessionstack.com/how-does-javascript-actually-work-part-1-b0bacc073cf</a></p>
</blockquote>
<h4 id="memory-heap">Memory Heap</h4>
<p>변수와 객체의 메모리 할당을 담당한다.</p>
<h4 id="call-stack">Call Stack</h4>
<p>자바스크립트에서 함수를 호출하게 되면 Call Stack이라는 곳에  <span style="color:red">호출된</span> 순서로 쌓이게 되는데 Stack에서 맨마지막에 호출된 함수가 제일 먼저 반환하는 LIFO(List in, First out) 구조로 되어있다.</p>
<p>이렇게 순서대로 처음에 <code>console.log(Hello)</code>가 호출되어 콜스택에 먼저 쌓이고 <code>Hello</code>를 반환하면서 <code>console.log(Hello)</code>는 콜스택에서 사라지게된다. 
하지만, <code>Hello</code>를 반환하기 전까지 다음 작업을 수행할 수 없기 때문에 순서대로 <code>Hello</code>, <code>Nice to meet you!</code>, <code>Bye!!</code>출력되는 것이다.</p>
<h1 id="비동기asynchronous">비동기(asynchronous)</h1>
<p>위에서 자바스크립트는 단일스레드, 동기식으로 동작한다는 것을 알게 되었다.</p>
<h4 id="그럼-비동기란-무엇일까">그럼 비동기란 무엇일까?</h4>
<p>쉽게 말해 동기의 반대개념이라고 할 수 있다.
한 작업이 실행되는 동안 그 작업이 끝날때 까지 기다리는 것이 아니라, 작업 결과에 상관없이 바로 다음 작업이 실행되는 개념이라고 할 수 있다.</p>
<h4 id="자바스크립트에서의-비동기-처리">자바스크립트에서의 비동기 처리</h4>
<p>자바스크립트에서는 3가지 비동기 처리 방식이 존재한다.</p>
<ul>
<li>callback 함수 사용</li>
<li>Promise</li>
<li>async/await</li>
</ul>
<h3 id="promise">Promise</h3>
<p><code>Promise</code>를 사용하면 비동기 작업이 종료된 이후의 <code>결과값</code> 또는 <code>실패(Error)</code>에 대해 처리할수 있게된다.<br/><br/></p>
<ul>
<li>Promise 처리 흐름도
<img src="https://media.vlpt.us/images/change/post/0d91a327-d2dc-4039-9a4b-fa02a902e599/image.png" alt="Promise 흐름도"></li>
</ul>
<blockquote>
<p>출처 <a href="https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Promise#%EC%84%A4%EB%AA%85">MDN Web Docs</a></p>
</blockquote>
<p><br/><br/>
Promise는 아래중 하나의 상태를 가진다.</p>
<ul>
<li>대기(pending) : 이행하지도, 거부하지도 않은 초기 상태</li>
<li>이행(fulfilled) : 연산이 성공적으로 완료됨</li>
<li>거부(rejected) : 연산이 실패함</li>
</ul>
<h3 id="promise-선언방법">Promise 선언방법</h3>
<pre><code class="language-javascript">new Promise((resolve, reject) =&gt; {
  // code 작성
});</code></pre>
<p><code>new Promise</code>객체를 생성 후 콜백 함수를 선언할 수 있는데 인자는 <code>resolve</code>, <code>rejeck</code>를 사용한다.
<code>resolve</code>는 결과가 <code>성공인 Promise 객체</code>를 반환하고 <code>reject</code>는 결과가 실패인 <code>Promise</code> 객체를 반환하게 된다.</p>
<p>반환된 객체를 처리할때 성공시엔 <code>.then</code>을 사용하고 실패시엔<code>.catch</code>를 사용하면된다.</p>
<h3 id="promise-callback-함수는-비슷한거-같은데-왜-사용할까">Promise, callback 함수는 비슷한거 같은데 왜 사용할까?</h3>
<p><code>콜백함수</code>를 사용하게되면 code가 훨씬 길어지고 복잡해지겠지만 <code>Promise</code>를 사용해서 가독성을 높이고 <code>콜백함수를</code>사용 했을때 보다 code가 짧아진다.</p>
<h3 id="asyncawait">async/await</h3>
<p><code>async/await</code>은 <code>Promise</code>객체를 기반으로 사용한다.</p>
<h4 id="promise와-차이점">Promise와 차이점</h4>
<p>가장 큰 차이점은 <code>resolve</code>, <code>reject</code>, <code>then</code>, <code>catch</code> 를 사용하지 않는다.</p>
<blockquote>
<p>개빡친다....</p>
</blockquote>
<p><code>async/await</code>을 알게되면서 화가 많이났다.. 솔직히 <code>async/await</code>만 사용할거같다.</p>
<ul>
<li>async 사용 예<pre><code class="language-javascript">async function func() {
return &quot;Hi&quot;
}
</code></pre>
</li>
</ul>
<p>async function print(){
  let i = func();
  console.log(i);
}</p>
<p>print();</p>
<p>// 결과
//Promise { &quot;Hi&quot; }</p>
<pre><code>
위에서 `new Promise`를 선언했던것과 비교해보면 너무 어이가 없다...
그냥 메소드 앞에 `async`만 붙이면 `Promise 객체`가 된다. 하지만 객체로 반환되기 때문에 `String` 형태로 반환받기 위해서는 `await`을 쓰면된다.

- await 사용 예
```javascript
async function func() {
  return &quot;Hi&quot;
}

async function print(){
  let i = await func();
  console.log(i);
}

print();

// 결과
// Hi</code></pre><p><code>async</code>사용 예와 다른점은 <code>func</code>앞에 <code>await</code>키워드가 추가됐다. 
<code>await</code>키워드가 추가되면 <code>Promise</code>객체에서 <code>String</code>값을 뽑아 낸다고 보면된다.</p>
<hr>
<h1 id="글을-마치며">글을 마치며...</h1>
<p>자바스크립트 동기/비동기를 배우면서 많이 힘들었다..
자바스크립트에서 비동기 처리로 콜백함수를 사용한다고 하지만 나는 콜백함수 자체가 비동기적이다 라는거에 동의 하지 않는다.
그리고 앞으로 비동기 처리는 async/await만 쓸것이다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[고차 함수 (Higher order Function)]]></title>
            <link>https://velog.io/@gidong_e/%EA%B3%A0%EC%B0%A8-%ED%95%A8%EC%88%98-Higher-order-Function</link>
            <guid>https://velog.io/@gidong_e/%EA%B3%A0%EC%B0%A8-%ED%95%A8%EC%88%98-Higher-order-Function</guid>
            <pubDate>Tue, 18 Jan 2022 14:21:54 GMT</pubDate>
            <description><![CDATA[<h1 id="1-first-class-citizen">1. First-class Citizen</h1>
<p>고차함수를 알아보기 전에 알아볼것이 있다.
자바스크립트에서는 특별한 대우를 받는 일급 객체(first-class citizen)이 있다.
대표적으로 함수가 있는데, 자바스크립트에서 함수는 아래와 같이 취급된다.</p>
<ul>
<li>변수에 할당할 수 있다.</li>
<li>다른 함수의 인자(argument)로 전달할 수 있다.</li>
<li>다른 함수의 결과로서 리턴될 수 있다.</li>
</ul>
<h1 id="2-고차-함수란">2. 고차 함수란</h1>
<p>고차 함수는 함수를 인자(argument)로 받을 수 있고, 함수의 형태로 리턴할 수 있는 함수이다.
함수는 변수에 저장할 수 있으며 함수를 담은 변수를 인자로 전달받을 수 있다. 또한 함수 내부에서 변수 자체에 함수를 할당 할 수도 있다.</p>
<h3 id="1-함수를-인자로-받을-때">1) 함수를 인자로 받을 때</h3>
<pre><code class="language-javascript">function double(n) {
  return n * 2;
}

function num(func, n) {
  return func(n)
}

let result = num(double, 2);
console.log(result); // 4</code></pre>
<p>⭐️ 함수 num은 double 함수와 숫자를 인자로 받아 4를 출력한다.
⭐️ 함수 double은 num의 콜백 함수이다.
⭐️ 콜백 함수란
   다른 함수의 인자(argument)로 전달되는 함수를 콜백함수라고 하는데, 어떤 작업이 완료되었    을 떄 호출하는 경우가 많아, 답신 전화를 뜻하는 콜백이라는 이름이 붙여졌다. 콜백함수는 아예 호출하지 않을 수도 있고, 여러번 실행할 수 있고, 특정작업이 완료된 후에 호출하는 경우    도 있다.</p>
<h3 id="2-함수를-리턴하는-경우">2) 함수를 리턴하는 경우</h3>
<pre><code class="language-javascript">function add (addNum){
  return function (num) {
    return num + addNum;
  };
}

let result = add(2)(5);
console.log(result); // 7</code></pre>
<p>⭐️ add 함수는 다른 함수를 리턴하는 고차함수로 인자 한개를 받아서 함수(익명함수)를 리턴하고, 리턴되는 함수(익명함수)는 인자 한개를 받아서 addNum과 더한 값을 리턴한다.</p>
<h1 id="3-고차-함수를-사용하는-이유">3. 고차 함수를 사용하는 이유</h1>
<p>추상화란 복잡한 어떤 것들을 압축해서 핵심만 추출한 상태로 만드는 것으로, 추상화의 관점에서 고차함수가 갖는 이점이 있다.</p>
<h3 id="1-추상화--생산성의-향상">1) 추상화 =&gt; 생산성의 향상</h3>
<p>CPU는 0과 1만 이해하지만, 코드가 해석되고 복잡한것들은 자바스크립트가 대신해주기에 우리는 자바스크립트 문법을 올바르게 사용하는 것만으로도, 다양한 프로그램을 비교적 쉽게 작성할 수 있는데 이처럼 문제해결이 더 쉬워지는 것이 추상화의 이점이다.</p>
<h3 id="2-함수라는-추상화">2) 함수라는 추상화</h3>
<p>반복되는 로직은 별도의 함수로 작성하는것이 추상화의 좋은 사례로, 추상화의 관점에서 함수를 보게 되면 함수는 사고, 또는 논리의 묶음이기 때문이다.</p>
<h3 id="3-추상화를-한단계-높인-고차함수">3) 추상화를 한단계 높인 고차함수</h3>
<p>함수는 값을 전달받아 값을 리턴하고, 값에대한 로직은 감춰져있으며 값의 수준에서 추상화는 단순히 값을 받아 처리하는 수준이다.
하지만 고차함수를 사용했을 때 이수준을 사고의 추상화(함수를 전달받아 처리하는 수준) 수준으로 끌어 올릴수 있는데 고차함수는 함수를 전달받거나 함수를 리턴하고 함수에 대한 로직은 감춰져 있기 때문에 추상화의 수준이 높아지는 만큼 생산성도 높아지게 된다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[클로저 (Closure)]]></title>
            <link>https://velog.io/@gidong_e/%ED%81%B4%EB%A1%9C%EC%A0%80-Closure</link>
            <guid>https://velog.io/@gidong_e/%ED%81%B4%EB%A1%9C%EC%A0%80-Closure</guid>
            <pubDate>Tue, 18 Jan 2022 13:45:54 GMT</pubDate>
            <description><![CDATA[<h2 id="1-클로저closure의-개념">1. 클로저(Closure)의 개념</h2>
<p>클로저란 함수 내부에 만든 지역변수가 사라지지 않고 계속해서 값을 유지하고 있는 상태를 말한다.
일반 지역변수의 경우 함수 호출이 완료되면 그 값이 사라지는게 원칙이다.
하지만 클로저를 이용하면 함수 호출이 완료된 후에도 사라지지 않는 데이터 저장소를 만들 수가 있다.</p>
<ul>
<li><h3 id="클로저의-장점">클로저의 장점</h3>
1) 연관 있는 변수와 중첩함수를 하나의 함수로 묶어 독립적으로 실행할 수 있다.
2) 함수 내부에 데이터가 만들어지기 때문에 함수 외부에서 수정할 수 없는 보호된 데이터를 만들수 있다.</li>
</ul>
<h2 id="2-클로저-원리">2. 클로저 원리</h2>
<p>내부 함수의 실행 시점에서 외부함수가 종료된 시점이라 하더라도 가비지 셀렉터의 동작방식으로 인해 외부 함수의 Lexical Environment에 접근이 가능하다. (가비지 셀렉터는 어떤 값을 참조하는 변수가 하나라도 있다면 그 값은 수집대상에 포함하지 않는다)</p>
<p>이러한 원리로 외부함수에서 선언한 변수를 내부함수로 전달할 경우 외부함수가 종료된 이후에도 변수가 사라지지 않는다.</p>
<pre><code class="language-javascript">once = function (func) {

let called = false;
let result = 0;

return function (){
    if(!called){
        result = func(arguments);
        called = true;
      }
    return result;
  }
};
// --------------------------------------

const add = function (){ 
  num ++;
}

once(add);
once(add);
once(add);

console.log(once(add)); // 1 </code></pre>
<p>⭐️ once function에서 변수 called를 내부 함수로 전달해 내부함수에서 True로 값이 변경이 되었기 때문에 이후 once를 몇번을 호출해도 출력은 1이 된다.</p>
]]></description>
        </item>
    </channel>
</rss>