<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>zekegarage.log</title>
        <link>https://velog.io/</link>
        <description>MAKE SOMETHING</description>
        <lastBuildDate>Sat, 19 Feb 2022 16:00:23 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <copyright>Copyright (C) 2019. zekegarage.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/yoonique_garage" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[🧑🏻‍💻 오픈조의 개발기]]></title>
            <link>https://velog.io/@yoonique_garage/openZo</link>
            <guid>https://velog.io/@yoonique_garage/openZo</guid>
            <pubDate>Sat, 19 Feb 2022 16:00:23 GMT</pubDate>
            <description><![CDATA[<h4 id="github주소-github_beb_02_openzo">&gt;&gt;&gt; Github주소 <a href="https://github.com/codestates/BEB_02_openZo">Github_BEB_02_openZo</a></h4>
<h4 id="notion주소-notion_openzo">&gt;&gt;&gt; Notion주소 <a href="https://www.notion.so/2-now/openZo-d13cf04a6aaa4f48a2c5e2f5dccd8bff">Notion_openZo</a></h4>
<h1 id="🚀-오픈씨opensea">🚀 오픈씨(Opensea)?</h1>
<p>오픈씨(Opensea)는 NFT거래소입니다.
Ethereum, klaytn, polygon 네트워크에서 발행되는 NFT들을 거래할 수 있습니다.</p>
<h1 id="🚀-개발목표">🚀 개발목표</h1>
<p>오픈씨의 기본 구조와 기능 중 일부를 개발하는 프로젝트를 진행하였습니다.
우선 1차 목표와 추가적인 목표를 나눠서 설정했습니다. 개발기간안에 1차목표를 구현하는 것을 목표로 잡고 이후 2차 목표를 달성을 계획하였습니다.</p>
<h3 id="팀1차-목표">팀1차 목표</h3>
<p><img src="https://images.velog.io/images/yoonique_garage/post/a7c34010-a1b4-44a7-9095-b6b965508e0f/%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-18%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%204.13.17.png" alt=""></p>
<h3 id="추가적인-목표">추가적인 목표</h3>
<p><img src="https://images.velog.io/images/yoonique_garage/post/ca842cfd-89c2-4b02-8c50-63bf9b0186e7/%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-18%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%204.16.38.png" alt=""></p>
<h1 id="🚀-아키텍쳐architecture">🚀 아키텍쳐(Architecture)</h1>
<p>서버와 DB의 필요성에 의문을 가지면서 Client 하나만을 구성하여 블록체인 노드를 통해 직접 데이터를 받아오는 구조를 생각했습니다.
<img src="https://images.velog.io/images/yoonique_garage/post/b3d45056-74b1-43a4-bd76-8d048b0cf259/%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-18%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%201.59.40.png" alt=""></p>
<p>1차 개발 이후 블록체인에서 바로 데이터를 가져오는건 사용자의 사용성을 불만족시키겠다는 생각이 들었습니다.
왜냐하면, 아무리 external view 함수에서 데이터를 읽어올 뿐이라도 DB에서 데이터를 가져오는 속도에 못미쳤기 때문입니다. 이후 서버와 DB를 포함한 구조로 방향을 틀었습니다. </p>
<h1 id="🚀-개발분담">🚀 개발분담</h1>
<p>개발은 크게 Front와 Backend와 Client-IPFS or Blockchain 을 구분지어 구현하였습니다.
저는 NFT를 Minting하는 기능과 Transfer하는 기능을 맡게 되었습니다.
자세한 내용은 오픈조의 노션페이지를 참고 해주세요. </p>
<h5 id="notion주소-notion_openzo-1">&gt;&gt;&gt; Notion주소 <a href="https://www.notion.so/2-now/openZo-d13cf04a6aaa4f48a2c5e2f5dccd8bff">Notion_openZo</a></h5>
<h1 id="🚀-개발결과">🚀 개발결과</h1>
<h3 id="createnft">CreateNFT</h3>
<p><img src="https://images.velog.io/images/yoonique_garage/post/d3b31374-d956-4db7-8e01-554aa0289827/createNFT.gif" alt="">
<img src="https://images.velog.io/images/yoonique_garage/post/cb38d319-578d-47e6-a99a-260ce26c4ff5/createList.gif" alt=""></p>
<h3 id="transfer">Transfer</h3>
<p><img src="https://images.velog.io/images/yoonique_garage/post/1e9d621c-c886-40a9-9071-6894cc098f64/transfer.gif" alt="">
<img src="https://images.velog.io/images/yoonique_garage/post/f7a3fdc7-324d-4166-b70e-bd89e1d6098a/ropsten.gif" alt=""></p>
<h1 id="🚀-개발회고">🚀 개발회고</h1>
<h3 id="keep">KEEP</h3>
<p>1️⃣ 개발을 하면서 항상 느끼는 부분은 해결방법은 항상 존재한다는 것입니다. 이번에도 여지 없이 어딘가에 있을 해결방안들을 찾아 많이 시도해보았습니다. 시도속에서 새로 알게 되는 것들과 많은 실패 끝에 결국 구현에 성공 해냈을 때 그 짜릿함이 계속 코딩을 하게 되는 원동력이 되지 않나 싶습니다.
답을 찾는 여정을 즐기고 문제에 대해 끝까지 부딪히며 해결하려는 의지가 앞으로 제가 계속 고수해 나가야할 근본 마음이라 생각합니다.</p>
<p>2️⃣ 팀원들과 협업시 지속적으로 서로 상황들을 공유하며 개발하였습니다. 이는 팀 프로젝트가 완성도 있게 마무리 될 수 있는 중요한 요소중 하나라 생각합니다.</p>
<h3 id="problem">PROBLEM</h3>
<h4 id="1️⃣-프로젝트-협업에-제일-중요한-github에서-merge때문에-몇-번-애먹은-적이-있었습니다-이로인해-깨달은-해결방안은-다음과-같습니다">1️⃣ 프로젝트 협업에 제일 중요한 GitHub에서 merge때문에 몇 번 애먹은 적이 있었습니다. 이로인해 깨달은 해결방안은 다음과 같습니다.</h4>
<ul>
<li>GitHub을 팀프로젝트 사용시에 Gitworkflow는 필수! 사전에 미리 브랜치의 규칙을 정하고 main branch가 아닌 dev브랜치로만 merge 할 수 있도록 하기</li>
<li>작업 하는 페이지를 미리 서로 언지하여 conflict를 사전에 방지</li>
<li>merge하는 시간 정해놓고, merge시 미리 해당 사항 공유</li>
<li>쉽게 내용을 피드백 할 수 있도록 디스코드와 GitHub 연동하기</li>
</ul>
<h4 id="2️⃣-이론으로만-습득한-지식을-코드로-구현할-때의-어려움을-깨달았습니다-컨트랙트를-불러오고-트랜잭션을-일으키기-위해서는-서명이-필요하고-가스비등의-금액을-지불해야하는데-이를-메타마스크와-연동하여-실행하는-코드를-이해하고-작성하는데-시간이-필요했습니다">2️⃣ 이론으로만 습득한 지식을 코드로 구현할 때의 어려움을 깨달았습니다. 컨트랙트를 불러오고, 트랜잭션을 일으키기 위해서는 서명이 필요하고, 가스비등의 금액을 지불해야하는데 이를 메타마스크와 연동하여 실행하는 코드를 이해하고 작성하는데 시간이 필요했습니다.</h4>
<ul>
<li><pre><code class="language-js">const tx = {
 from: userAddress,
 to: contractAddr,
 nonce: nonce,
 gas: 300000,
 data: contract.methods.mintNFT(userAddress, tokenUri).encodeABI(),
};</code></pre>
</li>
</ul>
<h4 id="3️⃣-contract를-truffle로-재배포시-이미-배포된-contract를-아무리-수정해도-재배포가-되지-않는-문제가-있었습니다-이는-저의-한없는-무지에서-비롯되었습니다">3️⃣ contract를 truffle로 재배포시 이미 배포된 contract를 아무리 수정해도 재배포가 되지 않는 문제가 있었습니다. 이는 저의 한없는 무지에서 비롯되었습니다.</h4>
<ul>
<li>Truffle init을 통한 폴더 초기화시 아래와 같이 migrations폴더가 존재합니다. 폴더 안에는 1_initial_migration.js 파일들이 존재하는데 truffle에서는 이 폴더의 앞에 붙여진 숫자를 찾아 이미 배포된 contract는 수정되었더라도 재배포 하지 않고, 아직 배포되지 않은 숫자의_initial_migration.js 파일부터 배포를 합니다.
따라서, contract를 수정 후 재배포 하길 원한다면 새로 숫자_initial_migration.js를 만들어서 배포할 contract를 명시해 주어야 합니다. 자세한 내용은 링크를 통해 확인이 가능합니다. <a href="https://trufflesuite.com/docs/truffle/getting-started/running-migrations.html">About migration</a>
<img src="https://images.velog.io/images/yoonique_garage/post/f95032bb-8b8e-4e38-b673-b992b4dc1d87/%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-18%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.39.02.png" alt=""></li>
</ul>
<h4 id="4️⃣-contract내-함수의-return-값을-받는-방법에-대한-고민이-있었습니다">4️⃣ Contract내 함수의 return 값을 받는 방법에 대한 고민이 있었습니다.</h4>
<p>web3통해 contract 객체 생성후, 컨트랙트내에 함수값을 리턴 받을 수 있는 방법을 모르고 있다는 것을 알게 되었고, 이를 검색 후 call()을 사용하면 컨트랙트 내에 함수 실행시 return값을 받을 수 있다는 것을 알게 되었습니다.</p>
<pre><code class="language-js">const tokenId = contract.methods.getTokenId().call();</code></pre>
<h4 id="5️⃣-web3js-사용시-webpack문제">5️⃣ web3.js 사용시 webpack문제</h4>
<p>create-react-app 버전이 5 이상인 경우 발생하는 문제로 아래 나와 있는 링크를 통해 필요한 부분을 설치 후 해결 가능합니다. <a href="https://github.com/ChainSafe/web3.js#web3-and-create-react-app">web3와 creat-react-app webpack버전 문제</a></p>
<h4 id="6️⃣-팀원들과-구조-설계시-시간이-좀-걸리더라도-충분한-리서치-후에-설계할-시간을-가지는-것이-좋겠다는-생각이-들었습니다">6️⃣ 팀원들과 구조 설계시 시간이 좀 걸리더라도 충분한 리서치 후에 설계할 시간을 가지는 것이 좋겠다는 생각이 들었습니다.</h4>
<h3 id="try">TRY</h3>
<p>1️⃣ 현재 속도 개선으로 인한 서버 연결 및 데이터 로드 작업이 진행중에 있습니다. 이 부분까지 완료하여 사용자 측에서 어플리케이션을 사용했을 때, 속도 지연으로 불만족을 해결할 수 있도록 할 예정입니다.</p>
<p>2️⃣ 리팩토링 진행 예정입니다. 코드를 동작하도록만 하는 것도 중요하지만 읽기 좋고 사용하기 좋은 코드는 있다고 생각합니다. 이를 위한 작업을 예정중입니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[🧑🏻‍💻 Mnemonic 지갑 개발기]]></title>
            <link>https://velog.io/@yoonique_garage/Mnemonic</link>
            <guid>https://velog.io/@yoonique_garage/Mnemonic</guid>
            <pubDate>Tue, 08 Feb 2022 18:01:59 GMT</pubDate>
            <description><![CDATA[<h4 id="github주소-github_mnemonicwallet">&gt;&gt;&gt; Github주소 <a href="https://github.com/YOONIQUE-GARAGE/MnemonicWallet">Github_MnemonicWallet</a></h4>
<h1 id="📌-개발목표">📌 개발목표</h1>
<p>오늘은 eth-lightwallet모듈에 있는 내장함수를 토대로 node.js를 이용한 서버개발과 react를 이용한 client개발로 기본 니모닉지갑 개발에 필요한 부분을 서버를 통해 응답받고 지갑주소를 보여주는 화면을 완성해볼 것입니다.</p>
<h1 id="📌-니모닉-이해하기">📌 니모닉 이해하기</h1>
<p>블록체인에서는 하나의 시드키(seed key)를 사용하여 여러 계정을 생성해 내는 지갑들이 존재하는데 이를 계층적 결정 지갑이라 합니다. 그 중 니모닉은 해싱되어 기억되기 어려운 구조를 가진 시드키를 기억하기 쉽도록 임의의 영단어로 치환하여 생성해주는 것을 말합니다. 니모닉으로 시드값을 생성하면 생성한 시드값에서 파생하여 여러 계정을 생성할 수 있게 됩니다.
<img src="https://images.velog.io/images/yoonique_garage/post/14010cfa-78fd-411b-a6de-b682ce46ef22/%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-08%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%206.39.52.png" alt=""></p>
<h1 id="📌-개발단계">📌 개발단계</h1>
<h2 id="개발셋팅">개발셋팅</h2>
<ol>
<li><p>공통</p>
<pre><code class="language-cmd">mkdir MnemonicWallet
mkdir server
creaete-react-app client</code></pre>
</li>
<li><p>client</p>
<pre><code class="language-cmd">cd client 
npm intall axios</code></pre>
</li>
<li><p>server</p>
<pre><code class="language-cmd">cd server
npm init
npm install express
npm install cors
npm install nodemon
npm install eth-lightwallet
touch index.js
mkdir routes
cd routes
touch index.js
cd ..
mkdir controllers
cd controllers
touch index.js</code></pre>
</li>
</ol>
<h2 id="개발과정-생각해보기">개발과정 생각해보기</h2>
<p><a href="https://github.com/ConsenSys/eth-lightwallet#readme">eth-lightwallet_Git페이지</a> 와 <a href="https://www.npmjs.com/package/eth-lightwallet">eth-ligthwallet_npm</a> 참고하여 개발과정 생각해보기</p>
<ol>
<li>client</li>
</ol>
<ul>
<li>응답 받은 니모닉 코드 출력  </li>
<li>니모닉코드 입력하고 비밀번호 입력시 생성된 지갑 출력 </li>
</ul>
<ol start="2">
<li><p>server
routes에서 새로운 mnemonic생성을 위한 엔트포인트 newmnemonic과 새로운 계정 생성 위한 newwallet으로 분기하기</p>
</li>
<li><p>폴더구조
<img src="https://images.velog.io/images/yoonique_garage/post/9ee667c0-8fba-4a29-a2d0-7396a48351eb/%E1%84%91%E1%85%A9%E1%86%AF%E1%84%83%E1%85%A5%E1%84%80%E1%85%AE%E1%84%8C%E1%85%A9.png" alt=""></p>
</li>
</ol>
<h2 id="주요코드">주요코드</h2>
<ol>
<li>client
클라이언트에서 server로 요청을 보내는 코드로 각각 Mnemonic 문장과 생성된 계정을 반환합니다.<pre><code class="language-js">// newMnemonic
axios
.post(&quot;http://localhost:4000/wallet/newmnemonic&quot;, {
headers: {
 &quot;Content-Type&quot;: &quot;application/json&quot;,
},
withCredentials: true,
})
.then((res) =&gt; {
setNewMnemonic(res.data);
});
</code></pre>
</li>
</ol>
<p>// newWallet
axios
.post(
  &quot;<a href="http://localhost:4000/wallet/newwallet&quot;">http://localhost:4000/wallet/newwallet&quot;</a>,
  {
    mnemonic: newMnemonic,
    pwd: pwd,
  },
  {
    headers: {
      &quot;Content-Type&quot;: &quot;application/json&quot;,
    },
    withCredentials: true,
  }
)
  .then((res) =&gt; {
  setAddress(res.data.address);
  setKeystore(res.data.keystore);
});</p>
<pre><code>
2. server
해당 엔드포인트로 요청이 오면 eth-lightwallet 이용해서 랜덤Seed를 생성하고, 생성된 Mnemonic과 사용자가 입력한 password를 바탕으로 새로운 계정이 생성됩니다.
```js
// newMnemonic
newmnemonic: {
    post: async (req, res) =&gt; {
      let mnimonic;
      try {
        mnemomic = lightwallet.keystore.generateRandomSeed();
        res.send(mnemomic);
      } catch (err) {
        console.log(err);
      }
    },
  }

// newWallet
newwallet: {
    post: async (req, res) =&gt; {
      const mnemonic = req.body.mnemonic;
      const password = req.body.pwd;
      console.log(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(` &gt;&gt;&gt; newWallet ${exception}`);
      }
    },
  }</code></pre><h2 id="결과">결과</h2>
<h3 id="생성된-keystore">생성된 keystore</h3>
<p><img src="https://images.velog.io/images/yoonique_garage/post/511b78c2-6fd1-4538-bd96-61f5d9452d57/keystore.png" alt=""></p>
<h3 id="웹화면-동작">웹화면 동작</h3>
<p><img src="https://images.velog.io/images/yoonique_garage/post/10c7dc53-4a2b-425d-9604-c71c74ed75fa/Mnemonic.gif" alt=""></p>
<h3 id="실행-방법">실행 방법</h3>
<p><a href="https://github.com/YOONIQUE-GARAGE/MnemonicWallet">Github 주소</a> 통해 실행 가능합니다.</p>
<h1 id="📌-개발회고">📌 개발회고</h1>
<h3 id="keep">KEEP</h3>
<p>니모닉 지갑 개발을 통해서 일단 모듈의 소중함과 만들어진 모듈들을 잘 이해하고 개발하는 과정의 중요성도 다시금 깨닫는 시간이 되었습니다. 모듈을 통해 니모닉 지갑이 어떤 과정으로 만들어 지는지 이론으로만 학습했던 내용을 적용해 볼 수 있게 되는 시간이었습니다.</p>
<h3 id="problem">PROBLEM</h3>
<p>CSS는 역시 어렵다는 생각이 들었습니다. 
데이터를 아무리 잘 가져와도 깔끔하게 보여줄 수 없다면 미완성의 느낌이 나겠다라는 느낌이 들어 구조적으로 CSS를 사용할 수 있게 추가적인 학습이 필요하다 생각했습니다.</p>
<h3 id="try">TRY</h3>
<p>추가적으로, keystore를 웹브라우저를 통해 다운 받아 저장할 수 있도록 할 예정입니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[🧑🏻‍💻 truffle 이용한 ERC-721개발기]]></title>
            <link>https://velog.io/@yoonique_garage/truffleERC721</link>
            <guid>https://velog.io/@yoonique_garage/truffleERC721</guid>
            <pubDate>Tue, 08 Feb 2022 12:42:05 GMT</pubDate>
            <description><![CDATA[<h4 id="github주소-github_truffleerc721">&gt;&gt;&gt; Github주소 <a href="https://github.com/YOONIQUE-GARAGE/truffleERC721">Github_truffleERC721</a></h4>
<h1 id="📌-개발목표">📌 개발목표</h1>
<p>오늘은 요즘 대세 중에 대세! 핫 한 NFT를 개발하고자 합니다.
truffle을 사용하여 기본 환경을 구축 한 후 오픈제플린 프레임워크를 이용하여 erc721기본 코드를 사용하고, 그림을 하나 골라 Ganache에서 테트스트 후 이더리움 Ropsten 테스트넷에 배포하여 이더스캔에서 해당 내역을 확인할 예정입니다.</p>
<p>먼저 기본 개발환경은 truffle을 이용하고 이미지를 무료 저장소인 NFTStorage에 업로드하여 이로 얻어진 tokenURI를 통해 유일무이한 토큰 ERC721를 만들어 보고자합니다.</p>
<h1 id="📌-ganache에-nft배포">📌 ganache에 NFT배포</h1>
<h3 id="1-truffle-이용한-개발환경-구축하기">1. truffle 이용한 개발환경 구축하기</h3>
<ul>
<li>먼저, 프로젝트 폴터를 생성한 후 truffle과 npm 초기화를 합니다.<pre><code class="language-cmd"># 폴더생성
mkdir truffleERC721
</code></pre>
</li>
</ul>
<h1 id="폴더진입">폴더진입</h1>
<p>cd truffleERC721</p>
<h1 id="truffle-초기화">truffle 초기화</h1>
<p>truffle init</p>
<h1 id="npm-초기화">npm 초기화</h1>
<p>npm init</p>
<pre><code>- 이 후 프로젝트 폴더에서 truffle-config.js 파일을 열어 솔리디티 컴파일 버전을 개인이 사용하는 버전과 맞춰주고, 네트워크를 설정해 주는데, 먼저 가나슈를 이용해 테스트 할 것 이므로 가나슈의 port 번호 7545를 입력해 줍니다.
![](https://images.velog.io/images/yoonique_garage/post/93fcbda8-aa4c-4bda-adb7-e36405e965de/%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-08%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%2010.07.19.png)

### 2. openzeppelin을 이용하여 NFT발행할 스마트 컨트랙트 작성하기
- openzeppelin 설치 
openzeppelin은 스마트 컨트랙트 라이브러리를 개발하는 회사로 해당 라이브러리를 사용하여 손쉽게 여러 토큰들을 발행할 수 있습니다.
```cmd
# openzeppelin 설치
npm install @openzeppelin/contracts</code></pre><p><img src="https://images.velog.io/images/yoonique_garage/post/3c62a3af-832a-4c5b-a96a-9f40d64ff018/%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-08%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%2010.42.15.png" alt=""></p>
<ul>
<li>contracts폴더 안에 스마트 컨트랙트 작성<pre><code class="language-solidity">// Contract based on [https://docs.openzeppelin.com/contracts/3.x/erc721]
// (https://docs.openzeppelin.com/contracts/3.x/erc721)
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;
</code></pre>
</li>
</ul>
<p>import &quot;@openzeppelin/contracts/token/ERC721/ERC721.sol&quot;;
import &quot;@openzeppelin/contracts/utils/Counters.sol&quot;;
import &quot;@openzeppelin/contracts/access/Ownable.sol&quot;;
import &quot;@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol&quot;;</p>
<p>contract MyNFTs is ERC721URIStorage, Ownable {
    using Counters for Counters.Counter;
    Counters.Counter private _tokenIds;</p>
<pre><code>constructor() public ERC721(&quot;zekeNFTs&quot;, &quot;ZNFT&quot;) {}

function mintNFT(string memory tokenURI)
    public onlyOwner
    returns (uint256)
{
    _tokenIds.increment();

    uint256 newItemId = _tokenIds.current();
    _mint(msg.sender, newItemId);
    _setTokenURI(newItemId, tokenURI);

    return newItemId;
}</code></pre><p>}</p>
<pre><code>
- 배포를 위해 migrations/1_initial_migration.js에 우리가 만든 컨트랙트 추가
```solidity
const Migrations = artifacts.require(&quot;Migrations&quot;);
const MyNFTs = artifacts.require(&quot;MyNFTs.sol&quot;);
module.exports = function (deployer) {
  deployer.deploy(Migrations);
  deployer.deploy(MyNFTs);
};</code></pre><h3 id="3-nftstorage이용하여-nft로-발행할-이미지-업로드하고-tokenuri가져오기">3. NFTStorage이용하여 NFT로 발행할 이미지 업로드하고 tokenURI가져오기</h3>
<ul>
<li><p><a href="https://nft.storage/">nft.storage</a>에 가입하고 APIKeys에서 키를 생성합니다.
<img src="https://images.velog.io/images/yoonique_garage/post/b5e0850c-2827-4a4a-9db8-d1300b3bc139/nft%E1%84%8F%E1%85%B5%E1%84%89%E1%85%A2%E1%86%BC%E1%84%89%E1%85%A5%E1%86%BC.png" alt=""></p>
</li>
<li><p>NFT로 발행할 이미지를 업로드합니다.
<img src="https://images.velog.io/images/yoonique_garage/post/6ea7c40e-050c-41c9-8033-9c25a4010a08/u3.png" alt=""></p>
</li>
<li><p>메타데이터를 nft.storage에 올려주기</p>
<pre><code class="language-cmd">npm install nft.storage</code></pre>
<p>프로젝트 폴더 안에 nft.js파일 생성하고 코드 삽입 </p>
<pre><code class="language-js">import { NFTStorage, File } from &quot;nft.storage&quot;;
import fs from &quot;fs&quot;;
</code></pre>
</li>
</ul>
<p>const apiKey = &quot;Your API KEY&quot;;
const client = new NFTStorage({ token: apiKey });</p>
<p>const metadata = await client.store({
  name: &quot;woodang&quot;,
  description: &quot;carrot is cute&quot;,
  image: new File([fs.readFileSync(&quot;./woodang.png&quot;)], &quot;woodang.png&quot;, {
    type: &quot;image/png &quot;,
  }),
  attributes: [
    { trait_type: &quot;skin&quot;, value: &quot;flash&quot; },
    {
      trait_type: &quot;face&quot;,
      value: &quot;frightened&quot;,
    },
  ],
});
console.log(metadata.url);
// ipfs://bafyreib4pff766vhpbxbhjbqqnsh5emeznvujayjj4z2iu533cprgbz23m/metadata.json</p>
<pre><code>생성된 메타데이터!!
![](https://images.velog.io/images/yoonique_garage/post/a5ea156a-7a49-4d33-bf90-afcc9978dabb/%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-08%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%201.15.15.png)

![](https://images.velog.io/images/yoonique_garage/post/6ced73c3-8a9c-40da-b4d9-359dd72b132e/%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-08%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%201.15.27.png)
생성된 당근!

![](https://images.velog.io/images/yoonique_garage/post/bb71578b-e221-473b-adc5-aa1daf98a245/%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-08%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%201.25.55.png)

### 4. 컴파일후 배포하기
```cmd 
# 컴파일
truffle compile
# 배포
truffle deployed
# 콘솔 접속하여 생성한 token metadata URI로 NFT발행
truffle console
truffle(ganache)&gt; instance = await MyNFTs.deployed
truffle(ganache)&gt; instance.name() // &#39;zekeNFTs&#39;
truffle(ganache)&gt; instance.symbol() // &#39;ZNFT&#39;</code></pre><p><img src="https://images.velog.io/images/yoonique_garage/post/7d212145-a30a-4d38-b02c-6e6fb5f839a3/%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-08%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%201.47.42.png" alt=""></p>
<p>배포완료!</p>
<hr>
<h1 id="📌-ropsten에-nft배포">📌 Ropsten에 NFT배포</h1>
<h3 id="1-ganache배포시-사용한-프로젝트에서-truffle-configjs수정">1. ganache배포시 사용한 프로젝트에서 truffle-config.js수정</h3>
<ul>
<li>니모닉 지갑 사용으로 인해 @truffle/hdwallet-provider 설치 필요<pre><code class="language-cmd">npm install @truffle/hdwallet-provider</code></pre>
</li>
<li>네트워크 수정<pre><code class="language-js">const HDWalletProvider = require(&quot;@truffle/hdwallet-provider&quot;);
const infuraKey = &quot;YOUR INFURA KEY&quot;;
</code></pre>
</li>
</ul>
<p>const fs = require(&quot;fs&quot;);
const mnemonic = fs.readFileSync(&quot;.secret&quot;).toString().trim();</p>
<pre><code>![](https://images.velog.io/images/yoonique_garage/post/1bd3c38c-b7cf-465b-8681-adfd613a53ad/%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-08%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%202.12.28.png)

### 2. truffle이용하여 배포
![](https://images.velog.io/images/yoonique_garage/post/da99f6e6-dd58-4a08-8dd9-fc6b2594fab6/%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-08%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%202.18.38.png)

### 3. 배포후 truffle console 실행하여 mintNFT함수로 NFT발행
![](https://images.velog.io/images/yoonique_garage/post/06c8505c-7367-4bd0-85f8-eca3bd3544ba/ropsten_mint.png)

Transaction Hash: 0x92a1325b955d26509d24f16421a1f5ce23e78e2f904f72ec6f0d583ddb9add70

![](https://images.velog.io/images/yoonique_garage/post/680abfdd-9fcb-42cf-89b3-05e710a856ca/truffle_ERC721.gif)

***
# 📌 개발회고
### KEEP
직접 개발을 하면 좋은점이 이론으로 알았을때와 비교해서 몸에 배는 지식들이 생긴다는 것입니다.
이번에도 이론으로 기본을 익인 후 직접 ganache와 ropsten을 통해 배포를 해봤는데, MyNFTs컨트랙트에서 mintNFT함수가 어떻게 생성이 되는지, 그리고 mintNFT에 들어가는 tokenURI는 어떻게 생성하는지에 대한 좋은 학습이 되었습니다. 
NFT를 직접 이더리움 네트워크에 저장하는 것이 아닌 IPFS라는 다른 분산 저장소에 저장하고 그 이미지에 대한 메타데이터 또한 저장하여 그 URI를 가져다 사용하는 방식으로 NFT를 생성하는 부분이 이번 학습에 가장 큰 배움이 아니었나 싶습니다.

### PROBLEM
배포하고선 수정하여 재배포가 불가능하게 막아져있다는 사실을 알았습니다. 코드를 잘 확인하여 컨트랙트를 다 밀고 다시 배포하는 일이 없게 할 것입니다.

### TRY
1. 오픈씨 테스트넷에도 배포하여 테스트넷에 NFT가 잘 올라오는지 확인하여 볼 예정입니다.
2. 여기서 멈추지 않고 다음에는 현재 핫🔥한 랜덤NFT에 대해 개발해보고 회고록을 작성 예정입니다.






</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[너는 누구냐, 인증과 보안]]></title>
            <link>https://velog.io/@yoonique_garage/%EB%84%88%EB%8A%94-%EB%88%84%EA%B5%AC%EB%83%90-%EC%9D%B8%EC%A6%9D%EA%B3%BC-%EB%B3%B4%EC%95%88</link>
            <guid>https://velog.io/@yoonique_garage/%EB%84%88%EB%8A%94-%EB%88%84%EA%B5%AC%EB%83%90-%EC%9D%B8%EC%A6%9D%EA%B3%BC-%EB%B3%B4%EC%95%88</guid>
            <pubDate>Fri, 17 Dec 2021 14:03:13 GMT</pubDate>
            <description><![CDATA[<h1 id="https">HTTPS</h1>
<p><span style="color:#586fab">HTTPS</span>은 프로토토콜의 종류로, &#39;HTTP + Secure&#39; 로 기존 HTTP프로토콜에 보안을 더한 개념이다.
기존의 HTTP요청은 서버에 전달되기 전에 누군가가 그 내용을 볼 수 있게 되어 개인정보나 중요정보가 노출 될 수 있다는 단점이 있다. 이를 예방하기 위해 HTTP프로토콜에 암호화를 시켜 암호에 대한 키를 가지고 있지 않은 누구도 저 내용을 볼 수 없게 만들었다.</p>
<h3 id="https-특징">HTTPS 특징</h3>
<ul>
<li>인증서(Certificate): 데이터를 제공한 서버가 정말 데이터를 전송한 서버인지 인증, 확인하는 용도로, 서버에 도메인 관련 정보를 담고 있기때문에 데이터 제공자의 인증을 용이하게 한다.
// 사진</li>
<li>CA(Certificate Authofity)
공인 인증서 발급 기관</li>
<li>비대칭 키 암호화
전혀다른 키 한쌍으로 암호화 및 복호화 가능하게 한다.</li>
</ul>
<h3 id="https-사용하기">HTTPS 사용하기</h3>
<h1 id="hashing">Hashing</h1>
<p>암호화란 일련의 정보를 임의의 방식으로 다른형태로 변환하여 해당 소유자 말고는 누구도 이해할 수 없도록 &#39;알고리즘&#39;을 통해 정보를 관리하는 과정이다.</p>
<h3 id="salt">Salt</h3>
<p>암호화해야 하는 값에 어떤 &#39;별도의 값&#39;을 추가하여 결과를 변형하는 것.
왜?🤔
.
.</p>
<ol>
<li>암호화만 해놓으면 늘 동일한 해쉬값</li>
<li>원본값 + 별도의 값 을 하면 기존의 늘 동일하던 해쉬값과 다른 값이 반환되어 알고리즘 노출시에도 원본의 값 안전하게 보호 가능<blockquote>
<p>기존:  원본값 =&gt; hash값
Salt사용:  원본값 + Salt값 =&gt; 다른 hash 값</p>
</blockquote>
</li>
</ol>
<p>(rainbowtable 검색하기)</p>
<p>Salt사용시 주의사항이 존재한다.</p>
<ol>
<li>유저와 패스워드 별로 유일한 값을 가져야한다.</li>
<li>사용자 계정을 생성할 때와 비밀번호를 변경할 때마다 새로운 임의의 Salt를 사용해서 해싱해야 한다.</li>
<li>Salt는 재사용 절대 금지</li>
<li>Salt는 DB의 유저테이블에 같이 저장되어야 한다.</li>
</ol>
<h1 id="cookie">Cookie</h1>
<h3 id="클라이언트에-정보를-저장하는-방식">&#39;클라이언트에 정보를 저장하는 방식&#39;</h3>
<p>NFT쇼핑을 하러 오픈씨에 구경을 갔다. 맘에 드는 상품들을 장바구니에 담아놓고 다시 구경을 하러 간다. 이때, 문득 생각이 났다.
HTTP 프로토콜의 제일 중요한 특징 중 하나가 무상태성(stateless)(붕어)인데 다른 페이지들을 구경 하러 다니는데에도 어떻게 내 장바구니에 담아논 NFT들이 유지가 되는 것일까? 
.
.
그 물에 대한 답이 바로 Cookie이다.
<span style="color:#586fab">Cookie</span>란 어떤 웹사이트에 들어갔을 때, 서버가 일방적으로 클라이언트에 전달하는 작은 데이터를 의미한다. 서버가 클라이언트의 데이터를 저장하는 하나의 방법이다. 해당 도메인에 대해 쿠키가 존재하면, 웹 브라우저는 도메인에게 http요청시 쿠키를 함께 전달.
쿠키는 삭제하지 않는다면 사라지지 않는다는 특징을 가지고 있다.
쿠키는 브라우저 설정창에서 금방 노출이 가능하기 때문에 중요한 정보는 해싱처리가 되어 있다.</p>
<p>쿠키는 한 번 저장하면 그 서버에 요청을 보낼때마다 같이 전달된다.
예로 내가 지정한 테마를 불러온다던지 자동로그인을 해준다던지 </p>
<h3 id="options">Options</h3>
<ul>
<li>Domain: 서버와 요청의 도메인이 일치하는 경우 쿠키 전송</li>
<li>Path: 서버와 요청의 세부경로가 일치하는 경우 쿠키 전송</li>
<li>MaxAge or Expires: 쿠키의 유효기간 설정</li>
<li>HttpOnly: 스크립트의 쿠키 접근 가능 여부 결정<ul>
<li>쿠키는 script태그로 접근이 가능하기 때문에 xss공격에 취약하다. <pre><code class="language-javascript">&lt;script&gt;alert(document.cookie)&lt;/script&gt;
// localhost:3001 내용: userid=zeke; email=dfdf.com...</code></pre>
</li>
</ul>
</li>
<li>Secure: true일 경우, HTTPS 프로토콜에서만 쿠키 전송 여부 결정</li>
<li>SameSite: CORS 요청의 경우 옵션 및 메서드에 따라 쿠키 전송 여부 결정
  -Lax: GET 메서드 요청만 쿠키 전송 가능
  -Strict: 쿠키 전송 불가
  -None: 모든 메서드 요청에 대해 쿠키 전송 가능-&gt; 이는 좀 위험하다 따라서 HTTPS프로토콜과, Secure옵션이 필수적으로 필요하다.이때 &#39;same-site&#39;는 요청을 보낸 Origin과 서버의 도메인이 같은 경우를 말한다.</li>
</ul>
<h3 id="사용방법">사용방법</h3>
<p>서버에서 클라이언트로 쿠키를 처음 전송하게 된다면 헤더에 Set-Cookie라는 프로퍼티에 쿠키를 담아서 보내게 된다.
이후 클라이언트 혹은 서버에서 쿠키를 전송해야 한다면 클라이언트는 헤더에 Cookie라는 프로퍼티에 쿠키를 담아 서버에 쿠키를 전송하게 된다. <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie">MDN Set-Cookie</a></p>
<p>이로써 stateless한 인터넷 연결을 유연하게 사용할 수 있게 되지만 오랜시간 유지될 수 있는 쿠키의 특성상 민감한 정보를 담는 것을 지양해야한다.</p>
<h1 id="session-방식">Session 방식</h1>
<h3 id="서버에-데이터를-저장하는-방식">&#39;서버에 데이터를 저장하는 방식&#39;</h3>
<p>서버가 Client에 유일하고 암호화된 ID를 부여, 중요 데이터는 서버에서 관리.
암호화 하는 과정 필요.
세션은 세션화된 데이터를 쿠키에 담아서 클라이언트에 전달</p>
<p>즉 찐 아이디가 아닌 세션화된 아이디로 클라이언트와 소통한다.</p>
<p>쿠키와는 다르게 서버에서 다양한 방식으로 검증을 거치기 때문에 쿠키보다는 좀 더 안전하다.
쿠키를 사용하고 있는 방식으로 XCC공격으로 개인정보 유출위험이 여전히 존재한다.</p>
<p>로그아웃시,</p>
<ol>
<li>서버의 세션스토어에 저장된 세션정보를 삭제</li>
<li>클라이언트의 쿠키를 갱신(이전의 저장된 세션정보 사라지도록)<ul>
<li>서버가 클라이언트의 쿠키를 임의로 삭제할 수는 없기때문에 
set-cookie로 세션 아이디의 키값을 무효한 값으로 갱신해야 합니다.</li>
</ul>
</li>
</ol>
<h3 id="express-session">express-session</h3>
<p>세션을 대신 관리해주는 모듈로 Express에서 세션을 다룰 수 있는 공간을 보다 쉽게 만들어 준다.
또한 필요한 경우 세션 아이디를 쿠키에 저장하고, 해당 세션 아이디에 종속되는 고유한 세션 객체를 서버 메모리에 저장할 수 있다.
이때 세션 객체는 서로 독립적인 객체이므로 각각 다른 데이터를 저장할 수 있다.</p>
<p>세션인증방식은 기본적으로 서버에 데이터를 저장하는 방식이라 했다. 이는 서버에서 인증하는 방식으로 세션과 db의 데이터의 일치 여부를 계속 확인해야 하여 서버의 부담을 가중시킨다.
이로 인해 Token이 등장했다.</p>
<h1 id="token-방식">Token 방식</h1>
<p><span style="color:#586fab">Token</span>은 기존에 세션기반인증에서 단점을 보안하고자 고안되었다. 토큰은 특정상황에서 사용하기로 약속 해논 증명서이다. 
클라이언트에서 토큰 저장하기 때문에 서버의 부하가 줄며, 서버에 무언가를 요청하는 상황에 사용자를 인증할 수 약속된 증명서가 된다.
무언가를 클라이언트쪽에 저장한다는건 상당히 위험한 일인데 괜찮을까? 🤔
.
.
모든 보안수단이 그렇듯, 완벽하진 않지만 상대적으로 안전하다.
토큰은 정보가 사실 그대로 저장되는게 아니라 암호화 되어 저장된다.</p>
<h3 id="장점">장점</h3>
<ol>
<li>Statelessness &amp; Scalability(무상태성 &amp; 확장성): 서버는 클라이언트의 정보를 저장하지 않고 토큰을 사용해 사용자에 대한 요청에 응답여부를 결정할 수 있다.</li>
<li>안정성: 암호환한 토큰을 사용한다.</li>
<li>어디서나 생성가능 : 응답서버와 토큰 발행 서버가 같을 필요는 없다.</li>
<li>권한 부여에 용이: Payload에 권한종류를 담을 수 있다.</li>
</ol>
<h3 id="jwt">JWT</h3>
<p><span style="color:#586fab">JWT</span>이란 Json Web Token의 약자로, Json 포맷으로 사용자에 대한 정보를 저장하는 대중화된 웹 토큰이다.
JWT의 구조는 Header,Payload, Signature로 구성되어있다.</p>
<ul>
<li>Header: 토큰의 종류, 알고리즘의 종류</li>
<li>Payload: 유저의 정보, 권한종류, 기타정보</li>
<li>Signature: Header, Payload를 base64인코딩한 값 + salt값</li>
</ul>
<p><img src="https://images.velog.io/images/yoonique_garage/post/9bd6d6f4-59b7-40b9-a04f-aaff77472550/jwt%E1%84%80%E1%85%AE%E1%84%8C%E1%85%A9%E1%84%80%E1%85%AE%E1%84%8C%E1%85%A9.png" alt=""></p>
<p>JWT토큰에는 두 가지 종류가 있는데, 실제로 권한부여(정보접근권한)에 사용하는 AccessToken과 새로운 accessToken을 받는데 사용하는 RefreshToken이 있다.</p>
<p>RefreshToken은 보통 AccessToken보다 유효기간이 길게 설정되어, 혹시나 모를 AccessToken 분실 사고에 대비하고 있다.</p>
<h3 id="실행순서">실행순서</h3>
<ol>
<li>클라이언트가 id+password를 담아 로그인 요청을 보낸다.</li>
<li>서버에서 id+password가 일치하는지 확인하고, 클라이어트에게 보낼 암호화되 토큰(ex.jwt)을 생성한다.
이 때, 한 번에 AccessToken과 RefreshToken을 모두 생성하며 둘이 같은 정보를 담을 필요는 없다.</li>
<li>서버는 클라이언트 응답에 토큰을 함께 보내고, 클라이언트는 이를 저장한다. ( 저장위치는 localStorage, cookie, react의 state...등등) <a href="https://developer.mozilla.org/ko/docs/Web/HTTP/Headers/Authorization">HTTP헤더 authorization</a></li>
<li>이후 요청부터는 클라이언트가 헤더에 해당 토믄을 담아 보낸다.</li>
<li>서버는 토큰을 해독하여 클라이언트 요청에 응답여부를 결정한다.</li>
</ol>
<h6 id="jwt출처-httpsbloghax0rinfo2017-12-29about-jwt-json-web-token">jwt출처 <a href="https://blog.hax0r.info/2017-12-29/about-jwt-json-web-token/">https://blog.hax0r.info/2017-12-29/about-jwt-json-web-token/</a></h6>
]]></description>
        </item>
        <item>
            <title><![CDATA[데이터들의 모임 ,  DATABASE]]></title>
            <link>https://velog.io/@yoonique_garage/Database</link>
            <guid>https://velog.io/@yoonique_garage/Database</guid>
            <pubDate>Thu, 16 Dec 2021 01:19:27 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>DB(Database)는 데이터들의 묶음이다.
DB를 사용하기 이전에는 In-Menory방식과 File I/O 방식을 이용하여 데이터를 다뤘는데, 이는 데이터의 보전성과 성능면에서 치명적이었다. 따라서 DB사용이 보편화되었다.</p>
</blockquote>
<h1 id="db종류">DB종류</h1>
<h3 id="관계형db">관계형DB</h3>
<p>SQL을 기반으로 하고, 테이블의 구조와 데이터 타입등을 미리 정의하고 정의된 내용을 바탕으로만 데이터의 삽입이 가능하다. 이로인해 테이블 간의 관계를 직관적으로 파악할 수 있다.(스키마가 뚜렷하게 보인다.)</p>
<blockquote>
<p>ex) MySQL, Oracle, SQLite, PostgresSQL, MariaDB</p>
</blockquote>
<h3 id="비관계형-db">비관계형 DB</h3>
<p>NoSQL을 기반으로 하고, 데이터가 고정되어 있지 않은 DB를 가르킨다. 관계형과 다르게 데이터를 읽어올 때 스키마에 따라 읽어온다.
이런 방식을 &#39;schema on read&#39;라고 한다.</p>
<blockquote>
<p>ex) 몽고DB, Casandra</p>
</blockquote>
<h1 id="sql">SQL</h1>
<p>JavaScript, Java, Python....등 쓰임새에 맞게 개발언어가 존재하는 것처럼 DB에서 사용하는 언어가 존재한다. 이를 SQL(Structured Query Language)이라 한다. 
말 그래도 구조화된 쿼리 언어인데, 여기서 쿼리는 질의문을 뜻한다고 보면 된다. 즉, 구조화된 질의문을 통해 DB에서 원하는 데이터를 가져오는 것이다. 이는 데이터의 구조가 고정되어 있는 DB에서만 사용이 가능하다. 
몇가지의 문법만 알면 원하는 데이터를 쏙쏙 뽑아올 수 있다.</p>
<h3 id="데이터베이스-명령어">데이터베이스 명령어</h3>
<ul>
<li>데이터베이스 생성<pre><code class="language-sql">CREATE DATABASE 데이터베이스이름;</code></pre>
</li>
<li>데이터베이스 사용<pre><code class="language-sql">USE 데이터베이스이름;</code></pre>
</li>
<li>데이터베이스 목록 검색<pre><code class="language-sql">SHOW DATABASES;</code></pre>
</li>
<li>데이터베이스 삭제<pre><code class="language-sql">DROP DATABASE 데이터베이스이름;</code></pre>
</li>
<li>테이블 생성<pre><code class="language-sql">CREATE TABLE 테이블이름(
컬럼 타입 속성,
컬럼 타입 속성,
.
.
);</code></pre>
</li>
<li>테이블 정보확인<pre><code class="language-sql">DESCRIBE 테이블이름;</code></pre>
</li>
<li>모든 테이블 확인<pre><code class="language-sql">SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = &#39;데이터베이스이름&#39;</code></pre>
<h3 id="sql-명령어">SQL 명령어</h3>
</li>
<li>Select: DB에서 원하는 데이터를 조회할 때 사용</li>
</ul>
<p>Where: 조건문이라고 이해할 수 있다. 원하는 조건을 걸때 사용(필터문)
And, Or, Not
Order By : 기본 오름차순 DESC(내림차순)
Limit: 결과로 가져올 데이터의 갯수를 지정. 쿼리문 맨 마지막에서 사용
Distinct: 중복제거하고 모두 추출
Insert Into: table에 데이터 넣기
Null Values
Update
Delete
Count
Like
Wildcards
Aliases
Joins
Inner Join
Left Join
Right Join
Group By</p>
<ul>
<li>INNER JOIN</li>
<li>LEFT JOIN</li>
<li>RIGTH JOIN</li>
<li>Group by</li>
<li>Having</li>
<li>COUNT()</li>
<li>SUM()</li>
<li>AVG()</li>
<li>MAX(), MIN()</li>
</ul>
<p>쿼리문 작성 순서:
CRUD명령어 -&gt; FORM절 -&gt; WHERE절 -&gt; GROUP BY -&gt; HAVING -&gt; ORDER BY
쿼리문 실행 순서</p>
<ol>
<li>FROM invoices: invoices 테이블에 접근을 합니다.</li>
<li>WHERE CustomerId &gt;= 10: CustomerId 필드가 10 이상인 레코드들을 조회합니다.</li>
<li>GROUP BY CustomerId: CustomerId를 기준으로 그룹화합니다.</li>
<li>HAVING SUM(Total) &gt;= 30: Total 필드의 총합이 30 이상인 결과들만 필터링합니다.</li>
<li>SELECT CustomerId, AVG(Total): 조회된 결과에서 CustomerId 필드와 Total 필드의 평균값을 구합니다.</li>
<li>ORDER BY 2: AVG(Total) 필드를 기준으로 오름차순 정렬한 결과를 리턴합니다.<h1 id="transaction">Transaction</h1>
</li>
</ol>
<p><span style="color:#f59525">트랜잭션(Transaction)</span>이란 여러개의 작업을 한 단위로 묶어놓은 것이다. 단위 안에 모든 작업들이 완료되야 비로소 정상적으로 종료한다.
즉, 하나라도 실패하면 트랜잭션도 실패고, 모두 성공일 때만 트랜잭션 또한 성공이다.
🤔 왜 이런 실행 묶음 단위가 필요할까??
.
.
트랜잭션이 없는 경우를 생각해보자.
내가 회사에서 일을 하고 월급을 받을 때,
회사에서는 먼저 나에게 월급만큼의 돈을 출금한다 -&gt; 내 계좌에 입금한다. 
이럴 때, 둘 중 하나의 작업만 완료된다면, 회사는 회사대로 돈을 잃게 되고, 나는 나대로 월급을 받지 못하게 된다. 😱</p>
<p>그래서 모두가 성공해야 작업이 완벽하게 완료되는 단위인 트랜잭션이 필요한 것이다.</p>
<h3 id="acid">ACID</h3>
<p><span style="color:#f59525">ACID</span>란 Atomicity Consistency Isolation Durability의 약자로, 트랜잭션의 안정성을 보장하기 위해 필요한 성질을 뜻한다.</p>
<ul>
<li>Atomicity: 하나의 트랜잭션 내에서는 모든 연산이 성공하거나 모두 실패해야 한다.</li>
<li>Consistency: 하나의 트랜잭션 전후에 데이터베이스의 상태가 일관되게 유지되야 한다.</li>
<li>Isolation: 각각의 트랜잭션은 서로 영향을 미치지 않는다.</li>
<li>Durability: 트랜잭션의 성공시 해당 기록은 영구적으로 기록되어야 한다.</li>
</ul>
<h1 id="schema--query-design">Schema &amp; Query Design</h1>
<ul>
<li>데이터간의 다양한 관계</li>
<li>데이터 간 관례를 기술하는 언어(sql)익히기</li>
<li>합리적이고 효율적인 방법으로 데이터베이스를 구성하는 방법이해</li>
<li>SQL쿼리 작성 방법</li>
</ul>
<h3 id="schema">Schema</h3>
<p>데이터베이스에서 데이터가 구성되는 방식과 서로 다른 엔티티간의 관계에 대한 설명 ( = 데이터베이스 도면 )</p>
<ul>
<li>etities: 정보의 단위(테이블단위라고 보면된다.)</li>
<li>fields: 엔티티에 열에 있는 내용</li>
<li>recodrs: 엔티티의 한 줄(행)을 의미</li>
</ul>
<h3 id="primarykey--foreignkey">PrimaryKey / ForeignKey</h3>
<p>PrimaryKey: 테이블의 기본키로(Primary Key) 자동으로 증가하는 값을 가진다.
ForeignKey: 외래키라 읽고, 다른 테이블의 기본키를 참조한 키이다.
보통 N의 테이블에 외래키로 1의 pk를 참조한다.</p>
<h3 id="관계형-데이터베이스-종류">관계형 데이터베이스 종류</h3>
<ul>
<li><p>1 : N
&#39;일대 다&#39;라고 보통 읽고, 테이블관의 관계를 수로 표현한 것이다.</p>
</li>
<li><p>N : N
한 학생이 여러수업을 듣는다
한 수업을 여러학생이 듣는다.
각각의 pk를 참조하는 하나의 테이블을 생성한다. -&gt; 1:N을 두번사용한 개념으로 join테이블이라 볼 수 있다. join테이블에도 반드시 pk가 존재해야 한다.</p>
</li>
<li><p>자기참조 관계
테이블 내에서의 관계를 의미한다. 일반적으로 테이블내에서 일대다 의 관계가 되는 경우는 다른 테이블을 사용하여 표현한다</p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[너와 나의 연결고리,  Network]]></title>
            <link>https://velog.io/@yoonique_garage/%EB%B3%B4%EC%9D%B4%EC%A7%80-%EC%95%8A%EB%8A%94-%EC%86%90-Network</link>
            <guid>https://velog.io/@yoonique_garage/%EB%B3%B4%EC%9D%B4%EC%A7%80-%EC%95%8A%EB%8A%94-%EC%86%90-Network</guid>
            <pubDate>Mon, 29 Nov 2021 12:35:37 GMT</pubDate>
            <description><![CDATA[<p>네트워크(Network)는 연결된 여러개의 컴퓨터들의 통신체계이다. 우리가 인터넷으로 무엇을 보는 것, 검색하는 것, 구매하는 것등의 모든 일련의 행동들이 이 네트워크 안에서 이뤄진다. 그럼, 대체 네트워크는 어떤 모양새로 생겼고, 이 안에서는 무슨일이 일어나길래 내가 원하는 정보가 나에까지 무사히 올 수 있는것일까?🧐</p>
<h1 id="🛰-network-architecture">🛰 Network Architecture</h1>
<p>Network Achitecture는 네트워크의 디자인이다. 수많은 컴퓨터와 장비들이 전송매체로 연결되어 데이터를 송수신하는 복잡한 시스템에서 통신의 최적화를 위해 의도적으로 만들어낸 네트워크의 모양새이다. </p>
<blockquote>
<p>복잡한 시스템 -&gt; 모듈화 -&gt; 계층화 -&gt; 추상화 -&gt; 아키텍처</p>
</blockquote>
<p>네트워크를 계층화해서 표현한 모형이 바로 OSI7계층이다</p>
<h3 id="통신계층">통신계층</h3>
<p><img src="https://images.velog.io/images/yoonique_garage/post/a9809e0c-5e28-40ec-ab15-86c0078df592/%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%202021-11-29%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.16.51.png" alt=""></p>
<ul>
<li>Appliction: </li>
<li>Presentation: 데이터의 변환, 압축, 암호화가 이루어지는 층으로 서로다른 통신기기간의 다른인코딩에 대한 대책</li>
<li>Session: 세션을 열고 닫는 기능</li>
<li>Transport: 서로 다른 두 네트워크 간의 전송을 담당(세그멘테이션, 흐름제어, 오류제어+오류복구)</li>
<li>Network: IP, 라우터장비가 속한 계층으로 호스트에 IP번호를 부여하고, 해당도착지IP까지 최적의 경로를 찾아주는 기능(라우팅)을 제공한다.</li>
<li>Datalink: 동일하 네트워크 간의 전송을 담당(오류제어, 흐름제어)</li>
<li>Physical: </li>
</ul>
<h3 id="2tier-architectrue">2Tier Architectrue</h3>
<p>클라이언트 서버 아키텍처라고 하며, 리소스(데이터)가 존재하는 쪽과, 리소스를 사용하는 곳을 분리시킨 구조이다. 여기서 리소스를 사용하는 쪽이 &#39;클라이언트&#39;, 리소스를 제공하는 쪽은 &#39;서버&#39;라고 한다. 항상 요청에 의한 응답만 존재한다.</p>
<h3 id="3tier-architectrue">3Tier Architectrue</h3>
<p>2Tier에서 리소스를 저장하는 공간인 데이터베이스가 추가된 구조이다. 클라이언트 - 서버 - 데이터베이스 이렇게 구성된다. 여기서 서버는 리소스를 전달하는 역할을 하고 그 리소스들이 실제로 존재하는 곳을 데이터베이스가 된다.</p>
<h1 id="🛰-protocol">🛰 Protocol</h1>
<p>프로토콜(Protocol)은 클라이언트와 서버가 통신하기 위한 규칙이다. 무언가를 제공하는 서버를 가게로 보고, 요청하는 클라이언트를 손님이라고 봤을 때, 한국에서는 보통 한국말을 사용해서 요청을 하고 응답을 받는다. 프로토콜은 한국말 같이 통신에 필요한 부분을 정해놓은 약속이며 수단이다. 통신계층마다 정해진 여러 프로토콜이 존재한다.
<img src="https://images.velog.io/images/yoonique_garage/post/81b11548-8971-4e46-9365-adf1225c5ad5/%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%202021-11-29%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.46.44.png" alt=""></p>
<blockquote>
<p>HTTP: 웹에서 HTML, JSON등의 정보를 주고 받는 프로토콜
HTTPS: HTTP에서 보안이 강화된 프로토콜
FTP: 파일전송 프로토콜
SMTP: 메일 전송하기 위한 프로토콜
SSH: CLI화면의 원격 컴퓨터에 접속하기 위한 프로토콜
RDP: Windows계열의 원격 컴퓨터에 접속하기 위한 프로토콜
WebSocket: 실시간 통신, Push 등을 지원하는 프로토콜
TCP: HTTP, FTP통신의 근간이 되는 양방향 인터넷 프로토콜
UDP: 빠르지만 신뢰성이 낮은 단방향 인터넷 프로토콜</p>
</blockquote>
<h1 id="🛰-http">🛰 HTTP</h1>
<p>HTTP(HyperText Transfer Protocol)로 문서를 전송하기 위해 만들어진 Application Layer의 프로토콜이다. 웹브라우저와 웹서버의 통신을 위해 디자인 되어 클라이언트가 HTTP messages 양식에 맞춰 요청을 보내면, 서버도 HTTP messages 양식에 맞춰 응답하는 형태를 가진다. </p>
<h3 id="http-messages">HTTP messages</h3>
<p>클라이언트와 서버 사이에서 데이터가 교환되는 방식으로 요청과 응답이 있다.
요청과 응답은 아래와 같이 비슷한 구조를 가진다.
<img src="https://images.velog.io/images/yoonique_garage/post/69bab117-0256-48fa-b15f-262310fceab2/%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%202021-11-30%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%202.30.36.png" alt=""></p>
<ul>
<li>star-line: 요청라인과 상태라인을 의미하고 요청이나 응답의 상태를 나타냄</li>
<li>HTTP headers: 메세지정보에 해당하고, 요청을 지정하거나, 메세지에 포함된 본문을 설명</li>
<li>empty line: 헤더와 본문을 구분하는 공백</li>
<li>body: 요청이나 응답에 관련된 데이터나 문서를 포함</li>
</ul>
<h4 id="요청-클라이언트가-서버에-보내는-메시지">요청: 클라이언트가 서버에 보내는 메시지</h4>
<ul>
<li>start-line: 수행할작업(GET, POST, ...),  요청대상, HTTP/버전</li>
<li>--&gt; POST     HTTP/1.1</li>
<li>--&gt; GET  <a href="http://developer.mozilla.org">http://developer.mozilla.org</a> HTTP/1.1 </li>
<li>Headers: 대소문자 구분 없는 문자열과 콜론(:), 값을 입력</li>
<li>--&gt; General headers: 메세지 전체에 적용</li>
<li>--&gt; Request headers: 요청을 구체화</li>
<li>--&gt; Entity headers: Content-Type, Content-Length</li>
<li>body: 구조의 마지막에 위치하고 선택적이다. 서버에 리소스의 조회를 요청하는 경우에는 필요치 않고 POST나 PUT과 같이 데이터의 변경을 요구할때 사용하며, Single-resource bodies(단일-리소스 본문)와 Multiple-resource bodies(다중-리소스 본문)가 있다.</li>
</ul>
<h4 id="응답-서버가-클라이언트-요구에-응답하는-메세지">응답: 서버가 클라이언트 요구에 응답하는 메세지</h4>
<ul>
<li>start-line: 현재프로토콜의 버전 / 상태코드 상태</li>
<li>--&gt; HTTP/1.1 200 OK</li>
<li>Headers</li>
<li>--&gt; General headers : 메시지 전체에 적용</li>
<li>--&gt; Response headers : 상태 줄에 넣기에는 공간이 부족했던 추가 정보를 제공</li>
<li>--&gt; Entity headers : Content-Length와 같은 헤더는 body에 적용 body가 비어있는 경우 전송되지 않음</li>
<li>body: 필요에 의해 선택적으로 전송됌</li>
</ul>
<p><span style="color:#3300FF">HTTP는 중요한 특성</span>을 가지는데 바로 <span style="color:#3300FF">상태를 가지지 않는다(Stateless)</span>는 것이다. HTTP로 통신하는 와중에는 클라이언트나 서버의 상태변화에 대해 일일이 체크하지 않고, 추적하지 않는다. 따라서 저장이 필요한 상태는 따로 쿠키-세션 등을 이용한다.</p>
<h1 id="🛰-작동원리---invisible">🛰 작동원리 - Invisible</h1>
<h3 id="url과-uri">URL과 URI</h3>
<p><span style="color:#3300FF">URL(Uniform Resource Locator)</span>은 네트워크 상에서 파일이 위치하는 정보를 나타낸다.
scheme + hosts + url-path의 결합으로 표기된다. </p>
<ul>
<li>schema: 프로토콜</li>
<li>hosts: 는 웹서버의 이름이나 도메인, IP주소이고, url-path </li>
<li>url-path: 웹서버에서 지정한 루트 디렉토리부터의 파일경로와 이름</li>
</ul>
<p><span style="color:#3300FF">URI(Uniform Resource Identifier)</span>은 URL에 query와 bookmark까지 포함한 주소이다.</p>
<ul>
<li>qeury: 클라이언트가 웹서버에 요구하는 추가적인 질문
프로토콜://주소/search?title=&#39;sexydressyJS&#39; 이런식으로 사용</li>
</ul>
<p>즉, URI가 URL을 포함하는 상위개념이다.</p>
<h3 id="ip와-port">IP와 Port</h3>
<p><span style="color:#3300FF">IP address(Internet Protocol address)</span>은 컴퓨터의 주소를 나태낼 때 사용하는 방식이다.
한국에 있는 무수히 많은 집들 중 내가 사는 집의 주소를 나타낼 때 도로명주소라는 체계를 사용하는 것처럼 네트워크 상에서 여러 컴퓨터들중 나의 컴퓨터가 있는 위치를 나타내기 위해 IP라는 체계을 사용한다. 즉, IP는 인터넷상에서 사용하는 주소체계이다.
그 중 IPv4는 4번째 버전을 의미한다. 보통 000.000.000.000 이렇게 표현되며, 0.0.0.0 ~ 255.255.255.255까지 나타낼 수 있다.
이 체계가 처음엔 문제되지 않았는데 점점 가정마다 컴퓨터 보급이 활발해지면서 사용할 수 있는 주소가 IPv4만으로는 감당 할 수 없게 되었다 그래서 나오게 된 것이 IPv6이다.</p>
<p><span style="color:#3300FF">Port</span>는 IP가 가르키는 PC에 접속 할 수 있는 통로이다. 한 통로를 이미 사용하고 있는 경우 중복해서 사용 할 수는 없다.
몇몇 포트번호는 주요 통신을 위한 규약으로 이미 정해져있다.</p>
<ul>
<li>22: SSH</li>
<li>80: HTTP</li>
<li>443: HTTPS</li>
</ul>
<h3 id="domain과-dns">Domain과 DNS</h3>
<p>우리가 인터넷상에서 특정 사이트로 이동할 때, 보통 IP주소를 사용하지 않고 해당 사이트의 이름으로 표기된 URL을 사용해서 접속한다. 이 이름이 바로 도메인이다. 즉 IP가 주소를 나타냈다면 <span style="color:#3300FF">Domain</span>은 그 주소에 실제로 존재하는 곳의 명칭을 나타낸다. 
즉, IP가 &#39;경기도 00시 00로&#39;라면 도메인은 평화아파트 같은 이름과 같다.</p>
<p>네트워크 상에 모든 PC는 IP주소가 있지만 모두 도메인을 가지고 있는건 아니다. 도메인은 일정 기간 동안 빌려서 사용하는 것으로 도메인과 각각의 IP를 연결하는 작업이 필요하다. 그럼 어떻게 IP와 도메인을 연결 할 수 있을까?🤔</p>
<p>이 때 등장하는 개념이 DNS(Domain Name System)이다. DNS는 도메인 이름을 IP 주소로 변환하거나 IP를 도메인으로 변화해 주는 역할을 하는 데이터베이스 시스템이다. 이를 이용하여 도메인이 있는 사이트를 IP가 아닌 도메인으로 검색하여 이용할 수 있다.</p>
<h1 id="🛰-작동원리---visible">🛰 작동원리 - Visible</h1>
<h3 id="ajax">AJAX</h3>
<p><span style="color:#3300FF">AJAX(Asynchronous Javascript And XMLHttpRequest)</span>은 동적인 웹페이지를 만들기 위한 하나의 개발 기법이다. 즉, 클라이언트와 서버간에 데이터를 주고 받는 기법을 의미한다. AJAX를 구성하는 핵심기술은 Javascript, DOM, Fetch이다.</p>
<p>🤔 왜 사용해?
.
.
웹페이지 보면 일부에서만 새로운 내용을 불러와야 하는 순간들이 있다. 그 일부분때문에 모든 페이지를 다시 다 불러오는건 시간낭비, 자원낭비, 돈낭비다. AJAX은 이럴때, 그 일부의 데이터만 불러와서 교체해주는 역할을 한다. 그러면 전체 페이지를 다시 불러오지 않고도 필요한 부분에서만 서버로부터 데이터를 가져와서 로딩한다. 매우 절약적이며, 사용자도 매번 전체 페이지가 로드 될 때까지 기다릴 필요 없으므로 편리하다.
다만, AJAX는 상태를 기억하지 않기 때문에 뒤로가기 버튼의 구현은 다른 API를 통해서만 가능하다.</p>
<ul>
<li>Fetch
AJAX의 핵심기술 중 현재 가장 많이 사용하고 있는 HTTP 요청 전송 기능을 제공하는 Web API이며, 자바스크립트의 내장 라이브러리 이다. 
서버와 비동기적으로 소통하며, 응답후의 수행할 로직을 .then으로 표현할 수 있다.</li>
</ul>
<pre><code class="language-javascript">// 함수선언형
fetch(&#39;api주소&#39;)
  .then(function(response){
    return response.json();
  })
  .then(function(response){
    // 응답후의 로직
  });

// arrow 함수형
fetch(&#39;api주소&#39;)
  .then(response =&gt; response.json())
  .then(response =&gt; {
     //응답후의 로직 
  });
</code></pre>
<h3 id="ssr과-csr">SSR과 CSR</h3>
<p>SSR과 CSR은 페이지가 렌더링 되는 위치로 구분된다.
<span style="color:#3300FF">SSR(Server Side Rendering)</span>은 웹페이지를 서버에서 렌더링을 해서 브라우저로 보낸다. 브라우저가 다른 경로로 이동할 때마다 서버는 이를 반복한다. 
<span style="color:#3300FF">CSR(Client Side Rendering)</span>은 브라우저의 요청을 서버로 보내면 웹페이지골격 + Javascript파일을 클라이언트인 브라우저로 보내게 되고 이를 브라우저에서 렌더링 한다. 브라우저가 다른 경로로 이동시에 서버가 웹페이를 다시 보내지 않고 처음 서버로부터 받은 웹페이지 파일을 이용하여 동적으로 라우팅을 관리한다.
여기서, 라우팅이란 네트워크 안에서 데이터를 보낼 때 최적의 경로를 선택하는 과정을 의미한다.
🤔 그럼 어떻게 구분해서 사용할까?
.
.
SSR은 </p>
<ol>
<li>SEO(Search Engine Optimization)가 우선순위일때</li>
<li>웹페이지의 첫 화면 렌더링이 빠르게 필요한 경우 ( 단일파일의 용량이 작기때문)</li>
<li>웹페이가 사용자가 상호작용이 적은경우
CSR은</li>
<li>지속적인 상호작용이 있는 경우</li>
<li>웹 애플리케이션 제작시 더 나은 사용자 경험 제공 가능.</li>
</ol>
<h1 id="🛰-api">🛰 API</h1>
<p><span style="color:#3300FF">API(Application Programming Interface)</span>는 형식이다.
우리가 한식전문점에 가서 파스타를 주문하지 않을 수 있는건 전문점에 이미 구비된 메뉴판 때문일 것이다. 메뉴판은 손님이 그 가게로부터 주문 할 수 있는게 무엇인지 눈으로 확인하여 알 수 있게 해준다. API도 이와 마찬가지이다. 특정 서버를 사용할 때, 그 서버에 무엇이 있는지 알아야 우리는 그 서버로부터 원하는 바를 요청할 수 있다. 이를 눈으로 확인 할 수 있도록 명시해 놓은 문서나 UI가 바로 API이다.
즉, API는 소프트웨어가 다른 소프트웨어로부터 지정된 형식으로 요청, 명령을 받을 수 있는 수단이다.</p>
<h3 id="rest-api">REST API</h3>
<p>웹 애플리케이션에서는 CRUD로 구성된 GET, POST, DELETE, PUT(PATCH)등의 HTTP 메소드를 이용해 서버와 통신한다. API가 빈 스케치북처럼 있는게 아니라 택배송장양식처럼 무엇을 어디에 어떻게 작성해야 하는지에 대한 규약이 존재한다.</p>
<blockquote>
<p>REST(Representational State Transfer) API는 그 규약중 장점을 최대한 활용할 수 있는 구조로 웹에서 사용되는 데이터나 자원(Resource)을 HTTP URI로 표현하고, HTTP 프로토콜을 통해 요청과 응답을 정의하는 방식이다.</p>
</blockquote>
<p>🤔 RESP API를 어떻게 작성해야 모든 사람들이 한 눈에 알기 쉽게 보고 사용하는 좋은 RESP API를 만들 수 있을까?
.
.
다음 리처드슨(Richardson)의 4단계 모델을 살펴보자. 
<img src="https://images.velog.io/images/yoonique_garage/post/6052049e-54dd-4461-a6a1-89b728c5e2c1/%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%202021-11-30%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%2010.57.30.png" alt=""></p>
<ul>
<li>0단계: HTTP프로토콜을 사용</li>
<li>1단계: 요청의 맨 끝부분인 엔트포인트는 요청하는 리소스에 따라 각각 다르게 사용
   ---&gt; 엔드포인트 작성시에는 동사, HTTP메소드, 행위에 대한 단어 - X, 요청하는 리소스에 대한 명사형태로 작성 - O</li>
<li>2단계: CRUD에 맞게 적절한 HTTP 메소드를 사용
  ---&gt; GET(READ), POST(CREATE), PUT &amp; PACTH(UPDATE), DELETE(DELETE)</li>
<li>3단계: HATEOAS(Hypertest As The Engine Of Application State) 적용한것으로 2단계에서 URI를 포함한 링크요소까지 삽입하여 작성</li>
</ul>
<p>3단계까지... 이러다 다죽어😵
.
.</p>
<p>보통 2단계까지 적용하면 대체적으로 잘 작성된 API라 여겨지고 3단계까지 적용된 경우는 극히 드물기때문에 3단계 적용은 선택적이다.</p>
<h3 id="open-api">Open API</h3>
<p>정부에서 제공하는 공공데이터에 접근할 수 있는 통로이다. <a href="https://www.data.go.kr/">공공데이터</a>에 접속해서 원하는 데이터를 API에 맞게 가져다 사용할 수 있다. </p>
<h3 id="api-key">API Key</h3>
<p>집 문을 열기 위해서 키나 비밀번호가 필요한것처첨 API를 이용하기 위해서는 보통 API Key가 필요하다. 클라이언트는 이 키를 가지고 필요한 서버의 문을 열어 원하는 리소스에 접근 할 수 있다.
🤔 그럼 왜? KEY가 왜 필요할까?
.
.
돈 때문이야~~🎶🎶 (✖️ 2) 
요청에 따라 서버가 응답 한다는 것은 결국 비용문제로 이어진다. 따라서 회원에게만 리소스를 제공 할 수 있도록 KEY를 발급하여 이용하도록 한다.</p>
<hr>
<h6 id="프로토콜-httpsvelogioleo-xeeed86b5ec8ba0ed9484eba19ced86a0ecbd9c">프로토콜 <a href="https://velog.io/@leo-xee/%ED%86%B5%EC%8B%A0%ED%94%84%EB%A1%9C%ED%86%A0%EC%BD%9C">https://velog.io/@leo-xee/%ED%86%B5%EC%8B%A0%ED%94%84%EB%A1%9C%ED%86%A0%EC%BD%9C</a></h6>
<h6 id="rest성숙도모델-httpsbrunchcokrpubjinson12">rest성숙도모델 <a href="https://brunch.co.kr/@pubjinson/12">https://brunch.co.kr/@pubjinson/12</a></h6>
<h6 id="httpmessage-httpsdeveloppapercomhttp-message">httpmessage <a href="https://developpaper.com/http-message/">https://developpaper.com/http-message/</a></h6>
<h6 id="http구조-httpsvelogioteddybearjunghttp-eab5aceca1b0-ebb08f-ed95b5ec8bac-ec9a94ec868c">http구조 <a href="https://velog.io/@teddybearjung/HTTP-%EA%B5%AC%EC%A1%B0-%EB%B0%8F-%ED%95%B5%EC%8B%AC-%EC%9A%94%EC%86%8C">https://velog.io/@teddybearjung/HTTP-%EA%B5%AC%EC%A1%B0-%EB%B0%8F-%ED%95%B5%EC%8B%AC-%EC%9A%94%EC%86%8C</a></h6>
]]></description>
        </item>
        <item>
            <title><![CDATA[Sexy dressy JS]]></title>
            <link>https://velog.io/@yoonique_garage/Sexy-JS</link>
            <guid>https://velog.io/@yoonique_garage/Sexy-JS</guid>
            <pubDate>Mon, 22 Nov 2021 17:09:44 GMT</pubDate>
            <description><![CDATA[<h1 id="🔥dom">🔥DOM</h1>
<p>DOM(Document Object Model)은 문서객체모델로, HTML을 아주 작은 부분까지 쪼개서 접근할 수 있게 만든 객체이다. HTML 문서의 내용과 구조가 객체 모델로 변환되어 계층적으로 나타난다. DOM을 이용하면 브라우저 환경에서 자바스크립트를 이용해 HTML을 조작할 수 있다.
<img src="https://images.velog.io/images/yoonique_garage/post/e72ec215-2666-4683-b798-c087f70c76c6/dom.png" alt=""></p>
<h3 id="dom과-html">DOM과 HTML</h3>
<p>DOM과 HTML은 같은 것일까? 🤔 
.
.
The anwser is NO!!!!!!
DOM이 HTML 문서로부터 생성되지는 것이다. 그렇기 때문에 당연히 HTML과는 다른 것이다. 또한 HTML로부터 생성되어 질지라도 HTML에서 잘못된 문법을 사용하거나, Javacript로 인해 DOM이 수정될 때 HTML과 DOM의 구조도 달라질 수 있다.</p>
<h3 id="왜-dom이-필요해🤔">왜? DOM이 필요해?🤔</h3>
<p>HTML과 단순히 문서의 구조를 잡는 역할만 한다. 처음 작성한 정적인 요소들만 화면에 표시해주기 때문에 단순하고 지루하다. DOM을 이용하면 세상 단순한 웹사이트를 HTML 요소를 조작해 내 마음대로 동적인 웹사이트 구현이 가능하다.</p>
<h3 id="js파일-삽입위치">JS파일 삽입위치</h3>
<p>HTML에 Javascript를 적용하는 위치는 대표적으로 두 가지가 있다. head태그 안에 넣느냐, body태그 끝나기 바로 전에 넣느냐이다. &#39;그럼 둘 중 아무데나 넣어도 상관 없지 않아?&#39;라고 묻는다면, 그렇긴 하지만 더 안정적으로 프로그램이 돌아갈 수 있는 위치가 있기때문에 별도의 이유가 있지 않는한 후자(body태그 끝나기 바로 전 위치)에 넣는 것을 권장한다.</p>
<p>이는 웹 브라우저가 해석하는 과정과 연관이 있는데, 웹 브라우저가 HTML를 해석하는 도중 script요소를 만나면 HTML해석을 멈추고 script요소를 먼저 실행하게 된다. 이는 script에서 아직 해석이 안된 HTML요소를 사용하는 경우가 발생할 수 있다는 것이고, 이 경우에 null이나 undefined 같은 오류를 야기한다. 이를 최대한 방지하고, 시간을 벌어주기 위해 script요소는 body태그 끝나기 바로 전에 삽입한다.</p>
<h3 id="consolelog-와-consoledir">console.log 와 console.dir</h3>
<p>consolse.log와 console.dir은 같은 역할을 하지만 후자가 객체의 모습으로 DOM을 출력하기 때문에 DOM요소를 확인 할 때는 console.dir을 사용하도록 하자!
<img src="https://images.velog.io/images/yoonique_garage/post/28428d31-6bad-456a-9c25-fbfff7f98e7a/%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%202021-11-22%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%2010.32.48.png" alt=""></p>
<h3 id="dom-구조">DOM 구조</h3>
<p>DOM은 트리형태의 구조로 부모 자식관의 관계를 가지고 있다. 
<img src="https://images.velog.io/images/yoonique_garage/post/bfdba71e-cc6a-461e-ada5-2589342e2920/%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%202021-11-22%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%2010.37.50.png" alt=""></p>
<h3 id="dom-crudcreatereadupdatedelete">DOM CRUD(CreateReadUpdateDelete)</h3>
<h4 id="create-dom트리에-element를-생성">CREATE: DOM트리에 element를 생성</h4>
<ul>
<li>createElement: 새로운 요소 생성</li>
</ul>
<pre><code class="language-javascript">    // appendChild를 사용하는 모든 상황에선 append사용가능. but, 반대는 안된다!!!!!!
    const elDiv = document.createElement(&#39;div&#39;);
    const elP = document.createElement(&#39;p&#39;); 
    document.body.append(elDiv);
    div.appendChild(elP);
    // &lt;body&gt;&lt;div&gt;&lt;p&gt;&lt;/p&gt;&lt;/div&gt;&lt;/body&gt;</code></pre>
<ul>
<li>append: 노드, 문자열, 여러노드 동시에 붙이기 가능(리턴값 없음)</li>
<li>appendChild: 오직 요소만 기존 요소에 붙임, 한 번에 하나의 요소만 가능(Node object를 리턴)</li>
<li>prepend: 기준의 맨 첫 번째에 생성
 🤔 기존 엘리먼트가 있는데, 같은 요소를 appendChild를 하면 복사인가? 이동인가?<pre><code>---&gt; 답은 이동! 한 노드가 문서상의 두 지점에서 동시에 존재할 수 없기 때문에!!</code></pre><pre><code class="language-html">     &lt;div class=&quot;dum&quot;&gt;
         나는 dum
     &lt;span&gt; more dum &lt;/span&gt;
     &lt;/div&gt;
     &lt;div class=&quot;dummer&quot;&gt;
         너는 dummer
     &lt;/div&gt;
  &lt;!-- 나는 dum more dum 
       너는 dummer --&gt;</code></pre>
<pre><code class="language-javascript">  const moreDum = document.querySelector(&#39;span&#39;);
  const dummer = document.querySelector(&#39;.dummer&#39;);
  dummer.appendChild(moreDum);
  // 나는 dum
  // 너는 dummner more dum</code></pre>
</li>
</ul>
<h4 id="read--기존-요소를-가져옴">Read : 기존 요소를 가져옴</h4>
<ul>
<li>querySelector: 해당하는 첫번째 요소를 가져옴</li>
<li>querySelectorAll: 해당하는 모든 요소를 유사배열(Array-like Object) 형태로 가져옴(for문  사용 가능)<pre><code> 🤔 querySelector의 첫번째 인자에 &#39;div&#39;를 넣으면 어떻게 될까? </code></pre>  ---&gt; 처음 검색되는 div를 뱉거나 없으면 null 리턴<pre><code> 🤔 querySelector를 통해서 더 복잡한 작업을 할 수 있을까?</code></pre>  ---&gt; so powerful. 복잡한 작업 가능
  🤔 querySelector의 부모는 꼭 document 객체여야만 할까?
  ---&gt; document 하위의 어떤 객체든 자식 엘리먼트를 가지고 있다면 querySelector의 부모가 될 수 있음<pre><code class="language-javascript">  // class: &#39;.class&#39; , id: &#39;#id&#39; 로 넣어줌
  const selDiv = document.querySelector(&#39;div&#39;);
  const selP = document.querySelector(&#39;p&#39;);
  // 모든 idv 요소를 가져옴
  const allDiv = document.querySelectorAll(&#39;div&#39;)</code></pre>
<h4 id="update--기존-요소의-내용이나-id-class-속성-등을-변경">Update : 기존 요소의 내용이나, id, class, 속성 등을 변경</h4>
</li>
<li>textContent: 엘리먼트 안에 문자열 삽입</li>
<li>classsList: class 속성 추가</li>
<li>setAttribute(&quot;속성이름&quot;,&quot;속성값&quot;): 속성과 속성값 추가<pre><code class="language-javascript">selDiv.textContext = &#39;dumdumdance&#39;; // &lt;div&gt;dumdumdance&lt;/div&gt;
selDiv.classList.add(&#39;dance&#39;) // &lt;div class=&#39;dance&#39;&gt;dumdumdance&lt;/div&gt;
selDive.setAttribute(&#39;id&#39;,&#39;dum&#39;) // &lt;div class=&#39;dance&#39; id=&#39;dum&#39;&gt;dumdumdance&lt;/div&gt;</code></pre>
<h4 id="delete--기존-요소나-내용을-삭제">Delete : 기존 요소나 내용을 삭제</h4>
</li>
<li>remove: 해당요소 자체를 삭제</li>
<li>removeChild: 요소의 자식요소를 삭제<pre><code class="language-javascript">  elP.remove();
  elP.removeChild(div.childNodes[0]); </code></pre>
</li>
<li>innerHTML = &quot;&quot;;</li>
<li>textContent = &quot;&quot;;
🤔 textContent와 innerHTML, innerText 차이는?</li>
<li>---&gt; textContent는 script,style 요소를 포함한 모든 요소의 콘텐츠를 가져온다. innerText는 오직 사람이 읽을 수 있는 요소만 반환한다. innerHTML은 이름 그대로 HTML을 반환한다.
🤔 innerHTML의 보안문제</li>
<li>---&gt; innerHTML은 크로스 사이트 스크립팅3 공격에 취약하다는 보안상의 허점이 있다. 문자열 자체의 수정이 가능하기 때문에 악의를 가진 해커가 script태그를 사용해 js로 조작할 수 있다. innerHTML의 사용을 자제하고 굳이 사용해야 할 경우 공격 경로를 방어할 수 있도록 추가적인 조치가 필요하다.</li>
</ul>
<h3 id="그-외">그 외</h3>
<h4 id="element와-node의-차이">element와 node의 차이</h4>
<p>node는 엘리먼트노드, 텍스트노드, 속성 노드 등이 있다. 노드는 엘리먼트의 상위 개념으로 태크노드와 텍스트노드 전체를 가리키고, Element는 텍스트 노드를 제외한 태그(ex.a, div,..)만 가리킨다.</p>
<h4 id="children과-childnodes의-차이">children과 childNodes의 차이</h4>
<p>children은 텍스트 노드를 제외한 태그를 가리키고, childNodes는 텍스트 노드도 포함한다.</p>
<h4 id="좌표--크기-정보">좌표 / 크기 정보</h4>
<p>offsetTop
offsetWidth</p>
<h1 id="🔥고차함수">🔥고차함수</h1>
<h3 id="함수">함수</h3>
<p>함수를 input값을 먹고 output을 뱉어낸다. input값을 함수에게 넣게 되면 함수 내부에 짜여진 일정한 동작에 의해 return으로 output값이 나오게 된다. 좀 더 알고 싶은사람 여기로 <a href="https://velog.io/@yoonique_garage/%EB%AA%A8.%EC%9E%90-DeepDive-09-%ED%95%A8%EC%88%98">JS함수</a>
<img src="https://images.velog.io/images/yoonique_garage/post/b29116fc-c380-4a78-a3bf-9db9d321615e/%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%202021-11-24%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%2012.23.50.png" alt=""></p>
<h3 id="일급객체first-class-citizen">일급객체(First-class citizen)</h3>
<p>자바스크립트에서는 함수도 함수객체로, 객체의 일부이다. 객체 중에서도 아주 특별하게 대우를 받는 일급객체이다.이는 <span style="color:#04B486">함수가 값으로 취급된다</span>는 아주 중요한 특징때문이다. 아래의 특징들은 함수가 값으로 취급되기 때문에 가능한 결과이다.</p>
<ul>
<li>변수에 할당할 수 있음 ---&gt; 배열의 요소나 객체의 속성값으로 저장 가능.</li>
<li>다른함수의 인자로 전달될 수 있음 </li>
<li>다른 함수의 결과로서 리턴될 수 있음 </li>
</ul>
<pre><code class="language-javascript">// 변수에 할당하는 경우
const plus = function (a,b) {
  return a + b;
};
plus(3,2) // 호출시 호출연산자 ()사용</code></pre>
<h3 id="고차함수higher-order-function">고차함수(higher order function)</h3>
<p>고차함수는 함수를 인자로 받을 수 있고, 함수의 형태로 리턴할 수 있는 함수이다. 정말 말 그대로 변수 값처럼 사용하기 때문에 가능한 일이다. 함수표현식을 통해 함수를 변수에 담에 인자로 전달하거나 함수 내부에서 변수에 할당해 리턴값으로 사용하거나 함수내부에서 함수를 바로 사용할 수 있다.</p>
<ul>
<li>콜백함수: 다른 함수의 인자로 전달되는 함수</li>
<li>커리함수: 함수를 리턴하는 함수 (고차함수는 커리함수를 아우르는 개념)<pre><code class="language-javascript">// 함수를 인자로 받는 경우
function add(num) {
return num+num;
}
function double(func, num) {
return func(num);
}
console.log(double(add, 2)); // 4
</code></pre>
</li>
</ul>
<p>// 함수를 리턴하는 경우
function add(added) {
  return function (num) {
    return num + added;
  };
};
console.log(add(4)(2)) // 6</p>
<pre><code>
### 고차함수의 종류
* map: 배열의 모든 요소마다 함수의 조건을 추가하여 반환. 본 배열을 변경하지 않음.
* filter: 
* reduce:
* mapreduce:
* forEach: 주어진 함수를 배열 요소 각각에 대해 실행
* sort: 
* some: 
* every: Boolean 값을 반환. 모든 배열 요소에 대해 참(truthy)인 값을 반환하는 경우 true. 그 외엔 다 false
* find: 주어진 판별 함수를 만족하는 첫 번째 요소의 값을 반환. 요소가 없으면 undefined 반환

### 그럼 대체 왜? 고차함수를 써야할까?🤔
우리 주변을 이루고 있는 대부분은 추상화의 개념으로 만들어졌다고 해도 과언이 아니다.
&gt; 추상화란 복잡한 어떤 것을 압축해서 핵심만 추출한 상태로 만드는것

냉장고에 음식을 넣으면 신선하게 보관되는 것, 메세지를 보내면 상대방한테 전달되는 것 등등 그 자세한 내막은 알지 못해도 하면 어떻게 된다라고 알고 있는 것들이 다 추상화 되었다고 볼 수 있다.
이는 프로그래밍에서도 적용이 되는데, 파라미터만 전달하면 덧셈을 해주는 함수가 있다고 할 때, 우리는 단순히 파라미터 값만 전달하면 내부에서 어떻게 함수가 작동하는지 알지 못해도 원하는 값을 얻을 수 있다. 이 또한 추상화의 일부이다. 
그럼 무언가를 추상화 시킨다는건 무엇일까?
.
.
동작을 묶어서 사용할 때 그 원리를 알지 못해도 사용이 가능하도록 묶음을 만들어 주는 일이라 볼 수 있다.
음식을 상하기 않게 보관이라는 것을 냉장고를 만들어 추상화 시킨것처럼.
프로그래밍에서는 자주 반복해서 사용하는 로직을 묶어서 별도로 보관하는 것이라 할 수 있다. 이런 개념은 바로 함수와 맞물린다. 
&gt; 고차함수 = 함수를 전달받거나 함수를 리턴한다 = 사고(함수)에 대한 복잡한 로직은 감추어져 있다 = 사고 수준에서의 추상화

추상화의 개념으로 이미 만들어진 무언가를 가져다 쓸수록 생산성도 증가하게 된다. 그 중 하나가 바로 고차함수이다. 고차함수를 사용할수록 생산성도 증가하게 된다.

***
###### gif출처 https://giphy.com/gifs/sexy-the-simpsons-homer-simpson-XQHN4wfaAcgTe
###### 사진출처: https://wit.nts-corp.com/2019/02/14/5522
###### 사진출처: https://poiemaweb.com/js-dom
###### 함수사진출처: https://pnal.kr/44










</code></pre>]]></description>
        </item>
    </channel>
</rss>