<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>ice-ame.log</title>
        <link>https://velog.io/</link>
        <description></description>
        <lastBuildDate>Wed, 01 Jun 2022 15:27:52 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>ice-ame.log</title>
            <url>https://velog.velcdn.com/images/ice-ame/profile/fa19c2f5-08ae-4c38-9138-79058c5b8928/image.jpeg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. ice-ame.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/ice-ame" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[Sequelize Association]]></title>
            <link>https://velog.io/@ice-ame/Sequelize-Association</link>
            <guid>https://velog.io/@ice-ame/Sequelize-Association</guid>
            <pubDate>Wed, 01 Jun 2022 15:27:52 GMT</pubDate>
            <description><![CDATA[<blockquote>
</blockquote>
<h2 id="알아두어야-할-맥락">알아두어야 할 맥락</h2>
<p><strong>1. migration &amp; model</strong></p>
<ul>
<li>migrations은 MySQL에 실제 이식될 테이블의 형태를 결정하며, models는 ORM을 통해 개발환경에서 MySQL를 다루기 위한 것이라고 생각하면 좋을 듯 하다.그렇기 때문에, migrations의 속성과 models의 속성은 동일해야 한다.
model과 migration을 직접 정의할수도있고 sequelize cli의 명령어를 통해서도 작성할수있다(cli이용할 것임)<br></li>
<li>Sequelize에서는 Model.init()및 sequelize.define() 두 가지 동등한 방법으로 모델을 정의할 수 있습니다.유일한 차이점은 하나는 객체 지향 프로그래밍 패턴을 따르고 다른 하나는 함수형 프로그래밍 패턴을 따른다는 것입니다.<br></li>
<li>모델명은 복수가 아닌 단수를 사용하고, 첫 글자는 대문자를 권장<blockquote>
</blockquote>
</li>
<li><em>2.Association*</em></li>
<li>연결관계는 각각의 모델들에 모두 정의해주어야 합니다(연결관계 메서드이용)<br></li>
<li>연결 관계를 정의하는 메서드사용시 함수를 호출하는 모델 객체가 source, 메서드 안에 인자로 전달되는 모델 객체가 target 입니다. 어떤 메서드를 사용하더라도 기본적으로 적용됩니다.
User.hasOne(Project).=&gt; User :source , Project:target<br></li>
<li>sequelize에서 외래 키는 모델 정의할 때에 만들어지는 것이 아니라, 두 모델의 연결 관계를 정의 할 때에, 연결 관계에 따라 Sequelize가 적절한 모델에 컬럼을 자동으로 만들어줍니다. 이 작업과 관련된 설정을 Sequelize에게 맡길 수도 있고, 몇몇 옵션(foreignkey)을 주어서 사용자가 제어할 수도 있습니다.</li>
</ul>
<blockquote>
</blockquote>
<h2 id="모델에서-1n-관계에-사용되는-메서드및-옵션">모델에서 1:N 관계에 사용되는 메서드및 옵션</h2>
<p><strong>1. 메서드</strong></p>
<ul>
<li><strong><code>BelongsTo</code></strong><ul>
<li>외래키가 source모델에 존재하는 연결관계</li>
</ul>
</li>
<li><strong><code>hasMany()</code></strong><ul>
<li>외래 키가 target모델에 존재하는 관계<blockquote>
</blockquote>
</li>
</ul>
</li>
<li><em>2. 옵션*</em></li>
<li><strong><code>as</code></strong> : target 모델의 별명<ul>
<li>include 사용 시 쿼리 결과 값이 모델명으로 지정되는데, 이는 foreignKey에서 AS 사용으로 include 에서도 같은 AS 명을 사용해야 함</li>
</ul>
</li>
<li><strong><code>foreignKey</code></strong> : 외래 키 정의, 생략 시 모델명 + Id 로 컬럼을 생성<ul>
<li>foreignKey 옵션을 주면, as 옵션을 모두 무시하고 foreignKey 옵션의 값에 따라 외래 키 컬럼을 이름짓습니다.(자동생성x)</li>
<li>foreignKey 설정 시 두 모델에서 동일한 설정이 필요, 하나의 모델에서만 정의하는 경우 자동으로 컬럼을 생성하여 중복 이슈가 일어남</li>
<li>외래 키 자동 생성의 대원칙은 [target 모델의 이름 + target 모델의 주요 키 이름]입니다</li>
<li>기본 명명 규칙은 camelCase이지만, source 모델이 underscored: true로 설정되어있다면, 외래 키는 snake_case로 명명됩니다.</li>
</ul>
</li>
<li><strong><code>onUpdate, onDelete</code></strong> <ul>
<li>RESTRICT, CASCADE, NO ACTION, SET DEFAULT, SET NULL 선택</li>
<li>1:N 관계로 이루어진 테이블에서 &#39;생성&#39;의 경우는 각각 테이블에 연결하여 생성하면 아무런 문제가 없지만 1의 관계에 있는 테이블 row가 삭제되는 경우 문제가 발생합니다.
cascade 옵션을 설정한 후 부모 테이블의 row를 제거하면 부모를 FK로 가진 자식 그리고 자식을 FK로 가지고 있는 자손 즉, 부모와 연결된 모든 테이블의 row는 자동으로 삭제됩니다</li>
<li>sequelize 및 다른 docs에서는 cascade는 하위(N)의 관계 옵션에 넣어줘야 한다고 합니다. 왜떄문에그런지 모르지만 부모와 자식 모두 옵션을 넣어줘야 정상작동하는경우가 있기때문에 가급적 모두 넣어주시는게 좋을듯</li>
</ul>
</li>
</ul>
<blockquote>
</blockquote>
<h2 id="모델코드">모델코드</h2>
<p><strong>1.모델 및 마이그레이션 생성</strong></p>
<pre><code># users
$ sequelize model:generate --name User --attributes email:string,password:string,name:string
&gt;
# reviews
$ sequelize model:generate --name Review --attributes users_id:integer,content:string</code></pre><blockquote>
</blockquote>
<p><strong>2.테이블간의 관계 생각해보기</strong>
예시인 users와 reviews 테이블 간의 관계는
하나의 유저는 여러 개의 리뷰를 가질 수 있으며,
 하나의 리뷰는 하나의 유저에 속함
** 1 : N 관계**</p>
<blockquote>
</blockquote>
<p><strong>3.작성코드</strong></p>
<ul>
<li><strong>user모델</strong><pre><code class="language-js">// models/user.js
&gt;
&quot;use strict&quot;;
const { Model } = require(&quot;sequelize&quot;);
module.exports = (sequelize, DataTypes) =&gt; {
class User extends Model {
  static associate(models) {
    this.hasMany(models.Review, {
      as: &quot;reviews&quot;,
      foreignKey: &quot;userId&quot;,
      // onUpdate: defaults to CASCADE
      onDelete: &quot;cascade&quot;,
    });
  }
}
User.init(
  {
    email: {
      type: DataTypes.STRING,
      unique: true,
      allowNull: false,
    },
    password: {
      type: DataTypes.STRING,
      allowNull: false,
    },
    name: {
      type: DataTypes.STRING,
      allowNull: false,
    },
  },
  {
    sequelize,
    modelName: &quot;User&quot;,
  }
);
return User;
};</code></pre>
<blockquote>
</blockquote>
</li>
<li><strong>Review모델</strong><pre><code class="language-js">// models/review.js
&gt;
&quot;use strict&quot;;
const { Model } = require(&quot;sequelize&quot;);
module.exports = (sequelize, DataTypes) =&gt; {
class Review extends Model {
  static associate(models) {
    this.belongsTo(models.User, {
      as: &quot;users&quot;,
      foreignKey: &quot;userId&quot;,
      onDelete: &quot;cascade&quot;,
    });
  }
}
Review.init(
  {
    userId: {
      field: &quot;users_id&quot;,
      type: DataTypes.INTEGER,
      allowNull: false,
    },
    content: {
      type: DataTypes.STRING,
      allowNull: false,
    },
  },
  {
    sequelize,
    modelName: &quot;Review&quot;,
  }
);
return Review;
};</code></pre>
</li>
</ul>
<blockquote>
</blockquote>
<h2 id="마이그레이션에서-1m-관계">마이그레이션에서 1:M 관계</h2>
<ul>
<li>references: {} 로 관계를 정의<pre><code class="language-js">references: {
  model : 참조하는 테이블 정의
  key : 참조하는 키 정의
} </code></pre>
</li>
</ul>
<blockquote>
</blockquote>
<h2 id="마이그레이션-코드">마이그레이션 코드</h2>
<ul>
<li><strong>user 마이그레이션</strong><pre><code class="language-js">// migrations/&lt;timestamp&gt;-create-user.js
&gt;
module.exports = {
up: async (queryInterface, Sequelize) =&gt; {
  await queryInterface.createTable(&quot;users&quot;, {
    id: {
      allowNull: false,
      autoIncrement: true,
      primaryKey: true,
      type: Sequelize.INTEGER,
      onDelete: &quot;cascade&quot;,
    },
    email: {
      allowNull: false,
      unique: true,
      type: Sequelize.STRING,
    },
    password: {
      allowNull: false,
      type: Sequelize.STRING,
    },
    name: {
      allowNull: false,
      type: Sequelize.STRING,
    },
  });
},
down: async (queryInterface) =&gt; {
  await queryInterface.dropTable(&quot;users&quot;);
},
};</code></pre>
<blockquote>
</blockquote>
</li>
<li><strong>review마이그레이션</strong><pre><code class="language-js">// migrations/&lt;timestamp&gt;-create-review.js
&gt;
module.exports = {
up: async (queryInterface, Sequelize) =&gt; {
  await queryInterface.createTable(&quot;reviews&quot;, {
    id: {
      allowNull: false,
      autoIncrement: true,
      primaryKey: true,
      type: Sequelize.INTEGER,
    },
    users_id: {
      allowNull: false,
      type: Sequelize.INTEGER,
      references: {
        model: &quot;users&quot;,
        key: &quot;id&quot;,
      },
      onDelete: &quot;cascade&quot;,
    },
    content: {
      allowNull: false,
      type: Sequelize.STRING,
    },
  });
},
down: async (queryInterface) =&gt; {
  await queryInterface.dropTable(&quot;reviews&quot;);
},
};</code></pre>
</li>
</ul>
<blockquote>
</blockquote>
<h2 id="reference">Reference</h2>
<ul>
<li><a href="https://velog.io/@cadenzah/sequelize-document-4">https://velog.io/@cadenzah/sequelize-document-4</a></li>
<li><a href="https://velog.io/@jiheon/Node.js-Sequelize-Associate">https://velog.io/@jiheon/Node.js-Sequelize-Associate</a></li>
<li><a href="https://velog.io/@josworks27/Back-end-Sequelize%EC%9D%98-cascade-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0">https://velog.io/@josworks27/Back-end-Sequelize%EC%9D%98-cascade-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0</a></li>
<li><a href="https://kyounghwan01.github.io/blog/etc/sequelize/sequelize-cascade/#mysql-config-%E1%84%83%E1%85%A6%E1%84%8B%E1%85%B5%E1%84%90%E1%85%A5-%E1%84%80%E1%85%AE%E1%84%89%E1%85%A5%E1%86%BC">https://kyounghwan01.github.io/blog/etc/sequelize/sequelize-cascade/#mysql-config-%E1%84%83%E1%85%A6%E1%84%8B%E1%85%B5%E1%84%90%E1%85%A5-%E1%84%80%E1%85%AE%E1%84%89%E1%85%A5%E1%86%BC</a></li>
<li><a href="https://velog.io/@josworks27/Sequelize-migration-%ED%95%98%EA%B8%B0">https://velog.io/@josworks27/Sequelize-migration-%ED%95%98%EA%B8%B0</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Git 정리]]></title>
            <link>https://velog.io/@ice-ame/git%ED%97%88%EB%B8%8C</link>
            <guid>https://velog.io/@ice-ame/git%ED%97%88%EB%B8%8C</guid>
            <pubDate>Mon, 30 May 2022 08:58:50 GMT</pubDate>
            <description><![CDATA[<hr>
<h1 id="git-기초">Git 기초</h1>
<hr>
<blockquote>
</blockquote>
<h2 id="깃-동작-원리와-과정">깃 동작 원리와 과정</h2>
<div>
<img width=80% src =https://velog.velcdn.com/images/ice-ame/post/a515012a-5099-47f2-93e6-a40fda5fe6e5/image.png>
</div>
>
-  **Working Directory**: 작업할 파일이 있는 디렉토리
-  **Staging Area** : 커밋을 수행 할 파일들이 올라가는 영역
-  **Local Repository**: 로컬 저장소
-  **Remote Repository** : 원격 저장소
-  **fetch + merge** =pull
- **git add <특정파일> **  //working directory=>staging area
- **git reset <특정파일>** //staging area=>working directory
- **git checkout -- <특정파일>** // 특정파일의 변경사항을 원래대로 돌려놓음

<blockquote>
</blockquote>
<h2 id="git-clone-vs-git-pull">git clone vs git pull</h2>
<p>git clone명령을 사용하면 로컬 저장소의 내용이 원격 저장소의 내용과 일치해진다.
기존에 작업중이었던 사람이 git명령을 사용해서 원격 저장소의 내용을 그대로 가져와버리면 기존에 작업했던 내용들은 직접 복구해야 한다. 즉, git clone은 프로젝트에 처음 투입될 때 사용되어야 하는 명령인 것이다.</p>
<blockquote>
</blockquote>
<p>반면 git pull명령은 원격 저장소의 내용을 가져와서 현재 브랜치와 병합(merge)까지 해주기 때문에, 기존에 작업했던 내용은 유지하면서 최신 코드로 업데이트할 수 있는 것이다</p>
<blockquote>
</blockquote>
<p>git pull명령은 병합과정도 포함되어 있기 때문에, pull을 하기 전에 commit을 하지 않으면 덮어쓰기 에러가 발생할 수 있다. 즉 기존 작업에 대해 commit을 미리 해두고 pull을 수행해주자.</p>
<blockquote>
</blockquote>
<p><strong>1.원격 저장소의 특정 브랜치만 클론하기</strong>
<code>git clone -b &lt;branch명&gt; &lt;remote_repo 주소&gt;</code></p>
<blockquote>
</blockquote>
<p>*<em>2. 클론후 원격저장소의 브랜치 가져오기+브랜치이동 *</em>
<code>git checkout -t &lt;원격저장소이름/브랜치이름&gt;</code></p>
<blockquote>
</blockquote>
<p><strong>3.원격 저장소의 특정 브랜치 로컬에 풀하기</strong>
<code>git pull &lt;원격저장소명&gt; &lt;브랜치이름&gt;</code></p>
<blockquote>
</blockquote>
<h2 id="git-commit">git commit</h2>
<p><strong>1.commit은 당시의 스냅샷이다
원한다면 그때의 시점으로 돌아갈수있다</strong></p>
<ul>
<li><strong><code>git reset --hard commithash</code></strong><ul>
<li>특정 커밋시점으로 돌아가고 그 이후는 다 지워버림</li>
<li>이경우 로컬저장소의 커밋지점이 바뀌고 원격저장소와는 커밋내역이다르기때문에 일반 push는 안됨</li>
<li><strong><code>git push -f &lt;원격저장소명&gt; &lt;브랜치명&gt;</code></strong>이용<blockquote>
</blockquote>
</li>
</ul>
</li>
<li><em>2.commit내역 수정*</em></li>
<li><strong><code>git commit --amend</code></strong> // commit내역 수정</li>
</ul>
<blockquote>
</blockquote>
<h2 id="git-log">git log</h2>
<img src =https://velog.velcdn.com/images/ice-ame/post/becaa5ba-b096-4c9b-8917-6e05f21f4e52/image.png>
>
**1. 엔터로 더 내려볼수있고 q로 나갈수있음**
**2.초록색은 로컬을 /빨간색은 원격을 뜻함**

<blockquote>
</blockquote>
<h2 id="branch-관련-명령어">branch 관련 명령어</h2>
<p><strong>1.로컬의 브랜치 삭제하기</strong>
다른브랜치로 이동후
<code>git branch -d &lt;branchname&gt;</code></p>
<blockquote>
</blockquote>
<p>*<em>2.원격 저장소의 브랜치 삭제하기 *</em>
<code>git push origin --delete &lt;브랜치명&gt;</code></p>
<blockquote>
</blockquote>
<p><strong>3.원격&amp;로컬의 모든 브랜치를 표시</strong>
<code>git branch -a</code></p>
<blockquote>
</blockquote>
<p><strong>4.git 브랜치가 목록에서 보이지 않을 때</strong>
<code>git remote update</code></p>
<blockquote>
</blockquote>
<p><strong>5.원격 브랜치만 표시</strong>
<code>git branch -r</code></p>
<blockquote>
</blockquote>
<p><strong>6.원격저장소의 해당 브랜치를 로컬에도 생성한 뒤 해당 브랜치로 이동</strong>
<code>git checkout -t &lt;원격저장소이름/브랜치이름&gt;</code></p>
<blockquote>
</blockquote>
<h2 id="remote-관련-명령어">remote 관련 명령어</h2>
<p><strong>1. 리모트 저장소 추가</strong>
<code>git retmote add &lt;원격저장소별칭&gt; &lt;원격저장소 주소&gt;</code></p>
<blockquote>
</blockquote>
<p><strong>2.리모트 저장소 이름 변경</strong>
<code>git remote rename &lt;전&gt; &lt;후&gt;</code></p>
<blockquote>
</blockquote>
<p><strong>3.리모트 저장소 삭제</strong>
<code>git remote rm &lt;저장소이름&gt;</code></p>
<hr>
<h1 id="git-branch-전략">Git branch 전략</h1>
<hr>
<blockquote>
</blockquote>
<h2 id="work-flow">work flow</h2>
<img width=80% src= https://velog.velcdn.com/images/ice-ame/post/b296a928-9db1-4389-baf6-f00951606363/image.png>
>
**1. 싱크맞추기**
- ```git pull upstream dev```
upstream/dev의 변경사항을 로컬과 맞추어준다
(브랜치가 devd인 상태에서)
>
**2.작업하기**
- 로컬에 feature브랜치 생성
  - ```git branch featrue```
- 로컬의 feature브랜치로 이동
  -  ```git checkout featrue```
- 이동한 feature 브랜치에서 작업하고 commit하기
  - ````git add .````
  - ```git commit -m "[커밋타입] 커밋메세지"```
- 작업한 내용 로컬의 dev로 머지시키기
  - ```git checkout dev```
  - ```git merge feature```
- 로컬의 commit내역 myrepo로 push
  - ```git push myrepo dev```
- feature 브랜치 삭제
  - ```git branch -d feature```
- pull request 생성
- 리뷰후 merge



]]></description>
        </item>
        <item>
            <title><![CDATA[인증 보안]]></title>
            <link>https://velog.io/@ice-ame/%EC%9D%B8%EC%A6%9D-%EB%B3%B4%EC%95%88</link>
            <guid>https://velog.io/@ice-ame/%EC%9D%B8%EC%A6%9D-%EB%B3%B4%EC%95%88</guid>
            <pubDate>Tue, 03 May 2022 18:29:09 GMT</pubDate>
            <description><![CDATA[<h2 id="achievement-goals">Achievement Goals</h2>
<ul>
<li>HTTP와 HTTPS의 차이점을 이해할 수 있다.</li>
<li>암호화와 hashing, salting 등의 개념을 이해할 수 있다.</li>
<li>권한 부여(Authorization)와 인증(Authentication)에 대해 이해할 수 있다.</li>
<li>쿠키의 작동 원리를 이해할 수 있다</li>
<li>세션 및 쿠키 / 토큰 / OAuth를 통해 인증 구현을 할 수 있다.</li>
<li>클라이언트, 서버, 데이터베이스의 전체 동작을 이해할 수 있다.</li>
<li>회원가입 및 로그인 등의 유저 인증에 대해 구현하고 이해한다.</li>
<li>서비스의 보안과 관련된 방법을 알아보고 원리 및 장점 및 단점을 이해한다.</li>
</ul>
<hr>
<h2 id="chapter-httphttpsssltls">chapter: HTTP/HTTPS/SSL(TLS)</h2>
<hr>
<blockquote>
</blockquote>
<h3 id="http와-https의-개념">HTTP와 HTTPS의 개념</h3>
<p><img src="https://velog.velcdn.com/images/ice-ame/post/0f767cb3-b4d7-4070-bb18-c93a951a3267/image.png" alt=""></p>
<ul>
<li><strong><code>HTTP(Hypertext Transfer Protoco)</code></strong>
: HTML을 전송하기위한 통신규약이다</li>
<li><strong><code>HTTPS(Hypertext Transfer Protocol over Secure Socket Layer)</code></strong>
:SSL(Secure Socket Layer)위에서 이루어진, 상대적으로 보안이 강화된 HTTP 통신규약이다<ul>
<li>SSL과 TLS는 같다고 생각해도 무관하다</li>
<li>만약 FTP위에서 HTTP가 동작하면 SFTP가 된다</li>
<li>좀더 풀어말하면 내가 사이트에 보내는 정보들을 제 3자로부터 보호<strong>(암호화)</strong>고 또 접속한 사이트가 믿을만한 곳인지<strong>(인증서)</strong>를 알려준다(SSL의 일련의 과정을통해). 덕분에 http보다 안전하다</li>
</ul>
</li>
</ul>
<blockquote>
</blockquote>
<h3 id="암호화">암호화</h3>
<ul>
<li>HTTPS 프로토콜의 특징 중 하나는 암호화된 데이터를 주고받기 때문에, 중간에 인터넷 요청이 탈취되더라도 그 내용을 알아볼 수 없습니다<blockquote>
</blockquote>
</li>
<li><em>1.대칭키의 암호화와 복호화*</em></li>
<li>하나의키로 암호화하고 암호화한 코드를 복호화 할 수 있다</li>
<li>만약 클라이언트와 서버측에 각대칭키를 가지고 암호화해 데이터를 주고받는다면 제3자는 암호화가되어있는 데이터에 접근할 수 없다</li>
<li>문제는 어떻게 애초에 대칭키를 양 쪽이 공유하느냐이다
결국 한쪽이 한쪽에게 키를 전송해야하는데 이과정중 키를 누군가가 탈취하게되면 암호화의 의미가 없어진다<blockquote>
</blockquote>
</li>
<li><em>2.비대칭키(공개키,비공개키)*</em></li>
<li>2개의 쌍을이룬 키가 사용되고 하나의키로 암호화하면 다른 하나의키만으로 복호화가 가능하다</li>
<li>서버측은 개인키를 비밀리에관리하고 대중에게는 공개키를 오픈한다. 사용자는 오픈되어있는 공개키를이용해 데이터를 암호화해 데이터를 서버측에 보낸다.비대칭키를 이용한 복호화는 서버측소유의 개인키만이 복호화 가능하기에 이는 안정성이 보장된다<blockquote>
</blockquote>
</li>
<li><em>3.실제 웹사이트의 보편적인 암호화방식*</em></li>
<li>공개키와 비공개키를통해 해당서버와 데이터를 주고받을수있지만,
이는 너무많은 비용을 요구한다. 해서 우리는 비대칭키와 대칭키를 혼합하여 사용한다</li>
</ul>
<blockquote>
</blockquote>
<h3 id="ssl-인증서">SSL 인증서</h3>
<ul>
<li>HTTPS 프로토콜의 또 다른 특징 중 하나는 브라우저가 응답과 함께 전달된 ssl인증서 정보를 확인할 수 있다는 점입니다. 이를 통해 신뢰할수있는 사이트인지 확인할 수 있다</li>
<li>ssl 인증서는 클라이언트와 서버간의 통신을 제 3자가 보증해주는 전자화된 문서이다</li>
<li>이 ssl 인증서는 ca라는 기관을통해 허가를 받는다</li>
<li>유저가사용하는 브라우저는 서버로부터 받은 인증서를 확인하고 인증서를 발급한 ca정보를 체크한다. ca가 발급한 인증서가 아니라면 아래와 같이 경고창을 띄워 서버와 연결이 안전하지 않다는 화면을 보여준다
검증이 완료되면 다음절차를 수행한다<ul>
<li>브라우저에는 certificate authority(ca)라는 회사들의 목록이 내장되어있다<img width=80% src=https://velog.velcdn.com/images/ice-ame/post/f43fbe5b-7dbf-4e0b-b4ae-c792446a4a1d/image.png>


</li>
</ul>
</li>
</ul>
<blockquote>
</blockquote>
<h3 id="ssl-통신과정https를-위한">SSL 통신과정(HTTPS를 위한)</h3>
<img src=https://velog.velcdn.com/images/ice-ame/post/da8caca4-3bdc-4892-8016-3abed5dbd3b4/image.png>
>
**1.hand shake **
  - 클라이언트는 서버측에 임의의 데이터를 보낸다(client hello)
  - 서버는 클라이언트측에 임의의 데이터와 함께 인증서를 보낸다(server hello)
- 인증서 확인
  - 클라이언트는 브라우저를 통해 서버측으로 전달받은 인증서가 정품인지를 체크한다
(ca에인증을받은 인증서라면 브라우저가 정품임을 인증을 해줄것이다)
  - 정품이인증되면 **공개키(비대칭키)**를 확인할 수 있다
- 비밀 키생성(대칭키)
  - 클라이언트는 Hand SHake시 **주고받은 데이터를 통해 새로운 키(session key/대칭키)를 생성**하고, **이 키를 서버측의 공개키(비대칭키)로 암호화**해 서버측에 전달한다
  - 서버측은 개인키로 복호화해 클라이언트측에서 보낸 키를 얻을 수 있고, 이제 대칭키 시스템을 통해 데이터를 안전하게 주고받을 수 있다
>
**2.Session**
- session key(대칭키)를 이용한 암호화 방식 통신
>
**3.End Session**
- seesion key(대칭키) 폐기(브라우저종료시)

<blockquote>
</blockquote>
<h3 id="사설-인증서-발급-및-https-서버-구현">사설 인증서 발급 및 HTTPS 서버 구현</h3>
<p><strong>0. 개요</strong></p>
<ul>
<li>HTTPS를 사용하여 브라우저에서 로컬로 실행되는 사이트를 열면 브라우저가 로컬 개발 서버의 인증서를 확인합니다.</li>
<li>인증서가 mkcert 생성 인증 기관에 의해 서명되었음을 확인하면 브라우저는 해당 인증서가 신뢰할 수 있는 인증 기관으로 등록되었는지 확인합니다.</li>
<li>mkcert는 신뢰할 수 있는 기관으로 등재되어 있으므로 브라우저가 인증서를 신뢰하고 HTTPS 연결을 만듭니다.<blockquote>
</blockquote>
</li>
<li><em>1.로컬 환경(localhost)에서 인증서를 생성하고, 인증서를 이용해 HTTPS 서버를 만들기*</em></li>
<li>mkcert설치<pre><code>$ brew install mkcert
(macOS 사용자의 경우, Homebrew를 통해 mkcert를 설치할 수 있습니다.)</code></pre></li>
<li>인증서 생성<ul>
<li>로컬을 인증된 발급기관으로 추가<pre><code>$ mkcert -install</code></pre></li>
<li>localhost로 대표되는 로컬 환경에 대한 인증서를  만들기<pre><code>$ mkcert -key-file key.pem -cert-file cert.pem localhost 127.0.0.1 ::1</code></pre><blockquote>
</blockquote>
</li>
</ul>
</li>
<li><code>cert.pem, key.pem</code> 이라는 파일이 생성됨<ul>
<li>key.pem의 경우 개인 키이므로 git에 커밋하지 않고, 암호처럼 다루어야 합니다</li>
<li>cert.pem은 공개키<blockquote>
</blockquote>
</li>
</ul>
</li>
<li><ul>
<li><ol start="3">
<li>💻 React 개발 서버 **
package.json을 다음과 같이 편집하고 {PATH}를 대체합니다.<pre><code class="language-js">&quot;scripts&quot;: {
&quot;start&quot;: &quot;HTTPS=true SSL_CRT_FILE={PATH} SSL_KEY_FILE={PATH} react-scripts start&quot;</code></pre>
<blockquote>
</blockquote>
</li>
</ol>
</li>
</ul>
</li>
<li><ul>
<li>2.HTTPS 서버 작성(express 이용)**<pre><code class="language-js">const https = require(&#39;https&#39;);
const fs = require(&#39;fs&#39;);
const express = require(&#39;express&#39;);
&gt;
const app = express();
&gt;
https
.createServer(
 {
   key: fs.readFileSync(__dirname + &#39;/key.pem&#39;, &#39;utf-8&#39;),
   cert: fs.readFileSync(__dirname + &#39;/cert.pem&#39;, &#39;utf-8&#39;),
 },
 app.use(&#39;/&#39;, (req, res) =&gt; {
   res.send(&#39;Congrats! You made https server now :)&#39;);
 })
)
.listen(3001);</code></pre>
<blockquote>
</blockquote>
<img src=https://velog.velcdn.com/images/ice-ame/post/0a34f92a-b3a1-430f-8bde-f29c73b2e515/image.png>


</li>
</ul>
</li>
</ul>
<hr>
<h2 id="chapter-hashing--cookie">Chapter :Hashing &amp; Cookie</h2>
<hr>
<blockquote>
</blockquote>
<h3 id="hashing">Hashing</h3>
<p><strong>0. 개요</strong></p>
<ul>
<li>암호화는 일련의 정보를 임의의 방식을 사용하여 다른 형태로 변환하여 해당 방식에 대한 정보를 소유한 사람을 제이하고 이해할 수 없도록 알고리즘을 이용해 정보를 관리하는 과정이다<ul>
<li>hashing은 암호화의 기본이다</li>
</ul>
</li>
<li>우리는 남이만들어놓은 훌륭한 hash함수(배포된)를 이용하면된다 (sha1 ,sha256)<blockquote>
</blockquote>
</li>
<li><em>1.plaintext*</em><img src =https://velog.velcdn.com/images/ice-ame/post/66853a2e-2c2d-42d0-8f24-88a63880afc2/image.png></li>
<li>데이터베이스에 비밀번호를 있는 그대로 저장해놓으면, 데이터베이스에 접근만할 수 있다면 누구든지 비밀번호를 알수있다. 이는 보안적으로 매우 좋지않다<blockquote>
</blockquote>
</li>
<li><em>2.hashing*</em><img src=https://velog.velcdn.com/images/ice-ame/post/67c0e8db-22af-42be-a86a-220c77d11ee9/image.png></li>
<li>hashing은 어떠한 문자열에 &#39;임의의 연산&#39;을 적용하여 다른 문자열로 변환하는 것이다<ul>
<li>모든 값에 대해 해시 값을 계산하는데 오래 걸리지 않아야 한다</li>
<li>동일한 입력값(input)에대한 동일한 출력값(output)을 갖고있다 =&gt; 입력값이 바뀌지 않으면, 출력값도 바뀌지 않는다</li>
<li>입력값(input)이 아주 살짝 변경되어도, 이에대한 출력값은 어마무시하게 바뀐다</li>
<li>해쉬함수는 항상 같은 방향,으로만 움직인다
1234 =&gt; hash f(x) =&gt; adfg823n48139(r38<em>(@
adfg823n48139(r38</em>(@ =&gt; hash f(x) !== 1234</li>
</ul>
</li>
<li>hash로 비밀번호를 암호화하면 어느정도 보안이 되지만, 레인보우 테이블이라는 것 때문에 이마저도 문제가된다<ul>
<li>레인보우 테이블은 해쉬값을 입력값이랑 매칭해놓은 테이블이다. 이를통해 비밀번호에 접근할 수 있다<blockquote>
</blockquote>
</li>
</ul>
</li>
<li><em>3.salt*</em><img src=https://velog.velcdn.com/images/ice-ame/post/4c933e67-119f-42b4-813b-649a7c4fa643/image.png></li>
<li>salt는  아주 조그만 랜덤 텍스트이다. 유저의 패스워드를 salt와 함께 해쉬(암호화)하면 이는 아주 랜덤한 결과값으로 이루어지고 레인보우 테이블에서 찾을수 없을 것이다<ul>
<li>salt는 유저와 패스워드 별로 유일한 값을 가져야 한다</li>
<li>사용자 계정을 생성할 때와 비밀번호를 변경할 때마다 새로운 임의의 salt를 사용해 해싱해야힌디</li>
<li>salt는 절대 재사용하지 말아야한다</li>
<li>salts는 db의 유저테이블에 같이 저장되어야 한다</li>
</ul>
</li>
</ul>
<blockquote>
</blockquote>
<h3 id="cookie">cookie?</h3>
<p><strong>1.개요</strong></p>
<ul>
<li>http요청은 statelsee(무상태성)인데 어떻게 우리의 정보가 유지가 될까? 쿠키를 이용한다면 마치 이용자를 기억하는 것 처럼 동작하게 할 수 있다.</li>
<li>쿠키란 어떤 웹사이트에 들어갔을때 서버가 일방적으로 클라이언트에 전달하는 작은 데이터 조각(보통은 의사를 묻지않지만 묻는경우도 있음)이다. <ul>
<li>쿠키에는 <strong>Token,Seesion Id 기타 등등 여러가지의 데이터를 담을 수 있고</strong> 이를통해 인증과 인가를 구현 할 수 있다
(또 다른 기능을 생각해 볼 수도 있다 
<code>ex</code>: 비로그인 유저의 장바구니 목록 같은 것)</li>
<li>쿠키에 직접적으로 인증,인가관련 데이터를 저장해 전달할수있지만 이는 매우 위험하다. 
(쿠키에 seesionId나 token을 담아 인증,인가를 구현하는 방법은 아래에서 후술하겠음)</li>
<li>한마디로 데이터를 저장(중요하지 않은)하거나 전달(sessionId or token을)하는 매개체인 셈이다.</li>
</ul>
</li>
<li>쿠키가 브러우저에 저장된후,브라우저는 쿠키를 자동으로 요청과 함께 서버측으로 보낸다<blockquote>
</blockquote>
</li>
<li><em>2. 쿠키옵션*</em></li>
<li><strong>Domain</strong><ul>
<li>서버와 요청의 도메인이 일치하는 경우 쿠키전송</li>
<li>요청해야 할 URL이 <code>http://www.localhost.com:3000/users/login</code> 이라 하면 여기에서 Domain은<code>localhost.com</code>이 됩니다<blockquote>
</blockquote>
</li>
</ul>
</li>
<li><strong>Path</strong><ul>
<li>서버와 요청의 세부경로가 일치하는 경우 쿠키 전송(세부 경로는 서버가 라우팅할 때 사용하는 경로입니다.)</li>
<li>만약 요청해야 하는 URL이 <code>http://www.localhost.com:3000/users/login</code> 인 경우라면 여기에서 Path, 세부 경로는 <code>/users/login</code>이 됩니다.<blockquote>
</blockquote>
</li>
</ul>
</li>
<li>*<em>MaxAge or Expires *</em><ul>
<li>쿠키의 유효기간 설정하는 옵션</li>
<li>MaxAge : 앞으로 몇 초 동안 쿠키가 유효한지 설정하는옵션</li>
<li>Expires :언제까지 유효한지 ```Date`` 지정</li>
<li>두 옵션이 모두 지정되지 않는 경우에는 브라우저의 탭을 닫아야만 쿠키가 제거될 수 있습니다.<blockquote>
</blockquote>
</li>
</ul>
</li>
<li><strong>HttpOnly</strong><ul>
<li>자바스크립트에서 브라우저의 쿠키에 접근 여부를 결정합니다.</li>
<li>만약 해당 옵션이 true로 설정된 경우, 자바스크립트에서는 쿠키에 접근이 불가합니다.</li>
<li>명시되지 않는 경우 기본으로 false로 지정되어 있습니다.</li>
<li>만약 이 옵션이 false인 경우 자바스크립트에서 쿠키에 접근이 가능하므로 &#39;XSS&#39; 공격에 취약합니다.<blockquote>
</blockquote>
</li>
</ul>
</li>
<li><strong>Secure</strong><ul>
<li>HTTPS 프로토콜에서만 쿠키 전송 여부 결정</li>
<li>만약 해당 옵션이 true로 설정된 경우, &#39;HTTPS&#39; 프로토콜을 이용하여 통신하는 경우에만 쿠키를 전송할 수 있습니다<blockquote>
</blockquote>
</li>
</ul>
</li>
<li><strong>SameSite</strong> <ul>
<li>CORS 요청을 받은경우 요청에서 사용한 메소드와 해당 옵션의 조합으로 서버의 쿠키 전송 여부를 결정하게 됩니다 </li>
<li>CSRF공격을 막는데 효과적이다</li>
<li><code>Lax</code> :Cross-Origin 요청이면 &#39;GET&#39; 메소드에 대해서만 쿠키를 전송할 수 있습니다.</li>
<li><code>Strict</code> : Cross-Origin이 아닌 same-site(요청을 보낸 Origin과 서버의 도메인이 같은 경우) 인 경우에만 쿠키를 전송 할 수 있습니다.</li>
<li><code>None</code>: 항상 쿠키를 보내줄 수 있습니다. 다만 쿠키 옵션 중 Secure 옵션이 필요합니다.<img src= https://velog.velcdn.com/images/ice-ame/post/297ae6ae-117c-41e8-b3b1-d2119a6ef93a/image.png>
></li>
</ul>
</li>
<li><em>3. node에서 쿠키설정 코드*</em> <div>
<img src =https://velog.velcdn.com/images/ice-ame/post/8d280b2d-7b29-49d9-8439-762cb8aa2bba/image.png>
<img src =https://velog.velcdn.com/images/ice-ame/post/daad1fae-2dc6-46a2-81af-6dfbd33fc675/image.png>
</div>

</li>
</ul>
<hr>
<h2 id="chapter-sessionid-based-authentication">chapter: SessionId-based Authentication</h2>
<hr>
<blockquote>
</blockquote>
<h3 id="session-sessionid-sessionid-based-authentication-">session? sessionId? SessionId-based Authentication ?</h3>
<ul>
<li>사용자가 브라우저를 닫아 서버와의 연결을 끝내는 시점까지를 session이라고 한다 또 사용자가 인증에 성공한 상태도 세션이라고 부릅니다</li>
<li>유저가 로그인시 세션 Db에는 해당유저의 세션을 생성하고 
seesionId를 부여한다.
이 seesionId는 쿠키를통해 전달되며 이를 통해 로그인상태를 기억 할 수 있다<ul>
<li>쿠키에는 오직 SessionId만 저장되고 데이터는 세션 DB에 저장된다</li>
</ul>
</li>
<li>사용자에 대한 정보를 서버에 두기 때문에 보안에 좋지만, 사용자가 많아질수록 서버 메모리를 많이 차지하게 됩니다.</li>
</ul>
<blockquote>
</blockquote>
<h3 id="세션기반-인증-session-based-authentication">세션기반 인증 (Session-based Authentication)</h3>
<p><strong>1.로그인</strong></p>
<blockquote>
</blockquote>
<ul>
<li>인증에 따라 리소스의 접근 권한(Authorization)이 달라집니다</li>
<li>인증(Authentication)된유저에게 권한을 인가(authorization)하려면 서버는 사용자가 인증에 성공했음을 알고 있어야하고, 클라이언트는 인증 성공을 증명할 수단을 갖고 있어야 합니다.</li>
<li>클라이언트가 로그인정보를 담은 Request를 보내면, 해당 서버의 엔진이 클라이언트에게 유일한 ID를 부여하는 데 이것이 세션 ID라하고 이는 쿠키를통해 다시 클라이언트에게 전달되며 또 매요청마다 쿠키에 담겨져 함께 보내진다</li>
<li>만약 클라이언트의 요청의 쿠키에 세션ID가 있다면,이를통해 클라이언트를 구분하고 해당 클라이언트를 인증되었다고 판단한다.</li>
<li>정리하면 세션 아이디가 담긴 쿠키를 주고받으며 로그인을 유지하고, 실제 데이터의 저장은 세션DB에서 이루어 집니다.<img src =https://joie-kim.github.io/assets/210206/Session_auth.jpeg>
<br>
></li>
<li><em>2.로그아웃*</em></li>
<li>로그아웃은 다음 두 가지 작업을 해야 합니다.<ul>
<li>서버의 세션 정보를 삭제해야 합니다.</li>
<li>클라이언트의 쿠키를 갱신해야 합니다</li>
</ul>
</li>
<li>서버가 클라이언트의 쿠키를 임의로 삭제할 수는 없습니다. 대신, set-cookie로 세션 아이디의 키값을 무효한 값으로 갱신해야 합니다.</li>
</ul>
<hr>
<h2 id="chapter-token-based-authentication">chapter: Token-based Authentication</h2>
<hr>
<blockquote>
</blockquote>
<h3 id="jwt">JWT</h3>
<p><strong>0. token? jwt?</strong></p>
<ul>
<li>token은 이상하게 생긴 긴~~텍스트 덩어리이다.</li>
<li>jwt는 대표적인 토큰중 하나이다<blockquote>
</blockquote>
</li>
<li><em>1. JWT의 종류*</em></li>
<li><strong>Access Token</strong><ul>
<li>access token은 보호된 정보들(유저의 이메일, 연락처, 사진 등)에 접근할 수 있는 권한부여에 사용합니다. 클라이언트가 처음 인증을 받게 될 때(로그인 시), access, refresh token 두 가지를 다 받지만, 실제로 권한을 얻는 데 사용하는 토큰은 access token입니다.</li>
<li>access token에는 비교적 짧은 유효 기간 을 주어 탈취되더라도 오랫동안 사용할 수 없도록 하는 것이 좋습니다.<blockquote>
</blockquote>
</li>
</ul>
</li>
<li><strong>Refresh Token</strong><ul>
<li>Access token의 유효기간이 만료된다면 refresh token을 사용하여 새로운 access token을 발급받습니다. 이때문에, 유저는 다시 로그인할 필요가 없습니다.</li>
<li>유효기간이 긴 refresh token 마저 악의적인 유저가 얻어낸다면 큰 문제가 될 것입니다
그렇기 때문에 유저의 편의보다 정보를 지키는 것이 더 중요한 웹사이트들은 refresh token을 사용하지 않는 곳이 많습니다. <blockquote>
</blockquote>
</li>
</ul>
</li>
<li><ul>
<li>3.JWT의 구조**<div>
<img align=left width=50% src=https://velog.velcdn.com/images/ice-ame/post/67c9ded2-18ff-4124-8663-8565c8760bfe/image.png>
<img width =50% src=https://velog.velcdn.com/images/ice-ame/post/c829a8f4-456e-47ea-ba88-599560fa4ea6/image.png>
</div>
<br>
></li>
</ul>
</li>
<li><strong>Header</strong>
어떤 종류의 토큰인지,어떤 알고리즘으로 sign(암호화)할지가 적혀있습니다.<pre><code class="language-json">{
&quot;alg&quot;: &quot;HS256&quot;,
&quot;typ&quot;: &quot;JWT&quot;
}</code></pre>
JSON 객체를 base64 방식으로 인코딩하면 JWT의 첫 번째 부분이 완성됩니다.<blockquote>
</blockquote>
</li>
<li><strong>Payload</strong>
Payload에는 정보가 담겨 있습니다
어떤 정보에 접근 가능한지에 대한 <strong>권한</strong>을 담을 수도 있고, <strong>사용자의 유저 이름</strong> 등 필요한 데이터는 이곳에 담아 Sign 시킵니다.** Payload 에는 민감한 정보(비밀번호같은)는 되도록 담지 않는 것이 좋습니다.**<pre><code class="language-js">{
&quot;sub&quot;: &quot;someInformation&quot;,
&quot;name&quot;: &quot;phillip&quot;,
&quot;iat&quot;: 151623391//iat: 토큰이 발급된 시간 (issued at)
// 이 값을 사용하여 토큰의 age 가 얼마나 되었는지 판단 할 수 있습니다.
}</code></pre>
JSON 객체를 base64로 인코딩하면 JWT의 두 번째 블록이 완성됩니다.<blockquote>
</blockquote>
</li>
<li><strong>Signature</strong>
Hather,Payload를 base64인코딩한 값과 salt값의 조합으로 함호화된값임
비밀키를 알지못하면 해독하는데 매우 힘듬<pre><code class="language-js">HMACSHA256(base64UrlEncode(header) + &#39;.&#39; + base64UrlEncode(payload), secret);</code></pre>
</li>
</ul>
<blockquote>
</blockquote>
<h3 id="token-based-authentication토큰기반인증">Token-based Authentication(토큰기반인증)</h3>
<p><strong>0. 개요</strong></p>
<ul>
<li><strong>token방식은 유저를 인증하는데 필요한 정보를 토큰에 담고 클라이언트에게 전달한다. 요청과 동시에 토큰이 서버에게 전달되고 서버는 해당 토큰이 유효한지만 체크한다</strong></li>
<li>매요청마다 데이터베이스를 접근하는 세션기반 방식에비해 서버측에 부담을 덜수있다</li>
<li>유저를 인증하는데 필요한 정보는 민감한 정보이기때문에 클라이언트측에 저장하는게 기본적으로는 위험하다. 해서 토큰을 암호화 되어있다(비밀번호 정보도 포함하지 않음)<blockquote>
</blockquote>
</li>
<li><em>1.토큰기반 인증 절차*</em><blockquote>
</blockquote>
<img src=https://velog.velcdn.com/images/ice-ame/post/76a2ce40-074f-4dac-be16-bb2d66ea5200/image.png>
></li>
<li><strong>클라이언트가 서버에 아이디/비밀번호를 담아 로그인 요청을 보낸다.</strong></li>
<li><strong>아이디/비밀번호가 일치하는지 확인하고, 클라이언트에게 보낼 Signature 된 토큰을 생성한다.</strong><ul>
<li>비밀번호 정보는 뺴도록 한다 가급적</li>
<li>이때 access/refresh 토큰을 모두 생성한다.</li>
<li>두 종류의 토큰이 같은 정보를 담을 필요는 없다 </li>
</ul>
</li>
<li><strong>토큰을 클라이언트에게 보내주면, 클라이언트는 토큰을 저장한다.(정답은 없다)</strong><ul>
<li>서버가 토큰을 쿠키에 담아 보낼 수 있다.
클라이언트는 쿠키에 접근 불가하다(httpOnly).따로 저장하는 일련의 코드를 작성하지 않아도 된다</li>
<li>서버가 토큰을 바디의 페이로드로보낸다면 클라이언트는 저장하는 위치를 생각 해 볼 필요가 있다. local storage,react의 state 등 다양하다.</li>
</ul>
</li>
<li><strong>클라이언트는 서버에 요청시 토큰을 같이 보낸다</strong><ul>
<li>cookie 에 저장했다면 자동으로 감</li>
<li>일반적으로 토큰은 요청 헤더의 Authorization 필드에 담아져 보내집니다.
<code>Authorization: &lt;type&gt; &lt;credentials&gt;</code>
토큰에는 많은 종류가 있고 서버는 다양한 종류의 토큰을 처리하기 위해 전송받은 type에 따라 토큰을 다르게 처리합니다.
JWT 혹은 OAuth에 대한 토큰을 사용하는경우 type은 <code>Bearer</code></li>
</ul>
</li>
<li>서버는 토큰을 해독하여 &quot;아 우리가 발급해 준 토큰이 맞네!&quot;라는 판단이 될 경우, 클라이언트의 요청을 처리한 후 응답을 보내준다.<blockquote>
</blockquote>
</li>
<li><em>3. 코드 보기*</em></li>
<li><strong>서버(노드)가 클라에게 토큰을 보낼때</strong><div>
<img src=https://velog.velcdn.com/images/ice-ame/post/99bcf844-14c8-4e22-8ff1-761d1b8f159b/image.png>
<img src= https://velog.velcdn.com/images/ice-ame/post/01c5b16f-c3d4-4b4e-833b-b08cae850b06/image.png>
</div>
<br>
></li>
<li><strong>클라(리액트)가 서버에게 토큰을 보낼때</strong>
쿠키가 있다면 자동으로 전달 된다 대신 아래와같은 처리를 해주어야함<img src=https://velog.velcdn.com/images/ice-ame/post/e40ee01f-200f-4218-ab38-6fe31b032bb2/image.png>

</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[ORM &  Sequelize]]></title>
            <link>https://velog.io/@ice-ame/ORM-Sequelize</link>
            <guid>https://velog.io/@ice-ame/ORM-Sequelize</guid>
            <pubDate>Mon, 02 May 2022 12:55:18 GMT</pubDate>
            <description><![CDATA[<hr>
<h2 id="chatper1-orm">chatper:1 ORM</h2>
<hr>
<blockquote>
</blockquote>
<h3 id="orm이란">ORM이란?</h3>
<p>ORM은 Object Relational Mapping 즉, 객체-관계 매핑의 줄임말이다. 
객체(클래스)와 테이블은 서로가 기존부터 호환가능성을 두고 만들어진 것이 아니기 때문에 불일치가 발생하는데, 이를 ORM을 통해 객체 간의 관계를 바탕으로 SQL문을 자동으로 생성하여 불일치를 해결한다. 
따라서 ORM을 이용하면 따로 <strong>SQL문을 짤 필요없이 객체를 통해 간접적으로 데이터베이스를 조작할 수 있게 된다.</strong></p>
<blockquote>
</blockquote>
<h3 id="orm의-특징">ORM의 특징</h3>
<ul>
<li>ORM을 이용하면 SQL문이 아닌 클래스의 메서드를 통해 데이터베이스를 조작할 수 있어,개발자가 객체 모델만 이용해서 프로그래밍을 하는 데 집중할 수 있게한다.</li>
<li>ORM을 사용하는 것은 매우 편리하지만 그만큼 신중하게 설계해야한다. 프로젝트의 복잡성이 커질 수록 난이도도 올라가고 부족한 설계로 잘못 구현되었을 경우 속도 저하 및 일관성을 무너뜨리는 문제점이 생길 수 있다. 또한 일부 자주 사용되는 대형 SQL문은 속도를 위해 별도의 튜닝이 필요하기 때문에 결국 SQL문을 써야할 수도 있다</li>
</ul>
<hr>
<h2 id="chatper2-sequelize">chatper2: Sequelize</h2>
<hr>
<blockquote>
</blockquote>
<p>sequelize는 Postgres, MySQL, MariaDB, SQLite 등을 지원하는 Promise에 기반한 비동기로 동작하는 Node.js ORM이다.
공식문서와 Sequelize를 이용한 스프린트를통해 살펴보자</p>
<blockquote>
</blockquote>
<h3 id="초기셋팅">초기셋팅</h3>
<p><strong>1.Sequelize 설치</strong></p>
<ul>
<li><a href="https://sequelize.org/">Sequelize ORM</a> 공식홈페이지 참고
<code>npm install --save sequelize</code><blockquote>
</blockquote>
</li>
<li><em>2.sequelize-cli 설치*</em>
<a href="https://sequelize.org/docs/v6/other-topics/migrations/">Sequelize - Migrations</a></li>
<li>데이터베이스 다루고 변경 사항을 추적할수있는 Migrations를 이용하기위해 sequelize-cli을 설치할 할것입니다.<ul>
<li>Sequelize의 migrations은 데이터의 이주를 수행(up)하거나 실행을 취소(down)를 지시하는 자바스크립트 파일이다</li>
<li>sequelize-cli를 설치하고 sequelize.query를 통해 migrations를 조작할 수 있다</li>
</ul>
</li>
<li><code>npm install --save-dev sequelize-cli</code>Sequelize CLI를 설치</li>
<li><code>npx sequelize-cli --help</code>를통해 명령의 종류를 파악할 수 있습니다.</li>
</ul>
<blockquote>
</blockquote>
<h3 id="orm-설정">ORM 설정</h3>
<p><strong>1.Project bootstrapping</strong></p>
<ul>
<li><code>npx sequelize-cli init</code>
커맨드 실행시 아래와 같은 폴더들이 생성된다</li>
<li><code>config</code>, 데이터베이스에 연결하는 방법을 CLI에 알려주는 구성 파일이 포함되어 있습니다.<ul>
<li>&quot;dialect&quot;옵션을 통해 데이터베이스서버를 선택할수 있다.default는 mysql<img src =https://velog.velcdn.com/images/ice-ame/post/a4d9392d-7e28-4398-ba85-73a5262c7264/image.png>
></li>
</ul>
</li>
<li><code>models</code> 프로젝트의 모든 모델을 포함합니다.<ul>
<li><code>npx sequelize-cli init</code>커맨드로 생성된 models 디렉토리에는 index.js(테이블 연결정의) 파일이 자동생성됨<img src=https://velog.velcdn.com/images/ice-ame/post/f09c8844-085c-4ae0-a437-d9d180fadfd4/image.png></li>
</ul>
</li>
<li><code>migrations</code> 모든 마이그레이션 파일 포함/빈폴더 생성</li>
<li><code>seeders</code> 모든 시드 파일을 포함합니다./빈 폴더 생성</li>
</ul>
<blockquote>
</blockquote>
<h3 id="데이터베이스-생성">데이터베이스 생성</h3>
<ul>
<li><code>npx sequelize db:create</code><ul>
<li>config.json에서 설정한 데이터베이스 이름 &quot;testgo&quot;가 스키마에 자동으로 추가<img src=https://velog.velcdn.com/images/ice-ame/post/c157d931-c271-4d94-8caf-cc5271952cfe/image.png>

</li>
</ul>
</li>
</ul>
<blockquote>
</blockquote>
<h3 id="모델생성">모델생성</h3>
<ul>
<li><code>npx sequelize-cli model:generate --name url --attributes url:string,title:string,visits:integer</code><ul>
<li><code>name</code>: 모델명
<code>attributes</code>: 모델 속성 목록입니다.<img src=https://velog.velcdn.com/images/ice-ame/post/d91cfb4f-19c4-409f-84a4-8ca5c8bb40c7/image.png></li>
</ul>
</li>
<li>models디렉토리에 url.js 생성됨<ul>
<li>id, createdAt, updatedAt 필드는 자동으로 생성됩니다.</li>
<li>필드가 가지는 특별한 요구 사항(기본값 등)은 모델 파일을 직접 수정해서 정의해야 합니다<img src=https://velog.velcdn.com/images/ice-ame/post/8637a668-07c8-440a-a1ac-66782576d35f/image.png></li>
</ul>
</li>
<li>migrations디렉토리에 파일생성됨<img src=https://velog.velcdn.com/images/ice-ame/post/7999a671-b9bf-48fe-9de5-4d204b65dd2c/image.png>

</li>
</ul>
<blockquote>
</blockquote>
<h3 id="migrations-실행">Migrations 실행</h3>
<ul>
<li>모델디렉토리가 해당 커맨드로 생성되었지만, 아직까지는 실제 데이터베이스에 삽입되지 않은 상태이기에 마이그레이션을 해주어야한다<ul>
<li><code>npx sequelize-cli db:migrate</code></li>
</ul>
</li>
<li>스키마 변경이 있을 때마다 마이그레이션을 실행해 줘야 합니다.<img src= https://velog.velcdn.com/images/ice-ame/post/5993100a-3281-4523-ac8e-d85083bb16e2/image.png>

</li>
</ul>
<blockquote>
</blockquote>
<h3 id="api">ApI</h3>
]]></description>
        </item>
        <item>
            <title><![CDATA[[node.js] MVC 디자인 패턴 & 데이터베이스 연결]]></title>
            <link>https://velog.io/@ice-ame/node.js-MVC-%EB%94%94%EC%9E%90%EC%9D%B8-%ED%8C%A8%ED%84%B4-%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%B2%A0%EC%9D%B4%EC%8A%A4-%EC%97%B0%EA%B2%B0</link>
            <guid>https://velog.io/@ice-ame/node.js-MVC-%EB%94%94%EC%9E%90%EC%9D%B8-%ED%8C%A8%ED%84%B4-%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%B2%A0%EC%9D%B4%EC%8A%A4-%EC%97%B0%EA%B2%B0</guid>
            <pubDate>Fri, 22 Apr 2022 21:55:13 GMT</pubDate>
            <description><![CDATA[<p><strong>MVC 패턴</strong></p>
<ul>
<li>MVC 디자인 패턴과 같이, 코드를 각각 다른 부분으로 나누어 작성해야 하는 이유를 이해할 수 있다.</li>
<li>Model, View, Controller가 각각 어떤 역할을 하는지 이해할 수 있다.</li>
</ul>
<p><strong>Cmarket Database</strong></p>
<ul>
<li>SQL을 Node.js 앱에서 쿼리할 수 있다.</li>
<li>클라이언트의 HTTP 요청에 따라 CRUD API를 구현할 수 있다. (CRUD: Create, Read, Update, Delete)</li>
</ul>
<hr>
<h2 id="chapter1-mvc-디자인패턴">chapter1: MVC 디자인패턴</h2>
<hr>
<blockquote>
</blockquote>
<ul>
<li>소프트웨어 개발 방법으로 사용되는 디자인패턴(Desigin Pattern)은 과거의 소프트웨어 개발 과정에서 발견된 설계의 노하우를 축적하여 그 방법에 이름을 붙여서 이후에 재사용하기 좋은 형태로 특정 규약을 만들어서 정리한 것입니다. 많은 디자인 패턴중 mvc패턴을 살펴보자<h3 id="mvc패턴">MVC패턴</h3>
<strong>1.개요</strong><ul>
<li>MVC란 Model-View-Controller의 약자로 애플리케이션을 세 가지 역할로 구분한 개발 방법론입니다. </li>
<li>Controller를 조작하면 Controller는 Model을 통해 데이터를 가져오고 그 데이터를 바탕으로 View를 통해 시각적 표현을 제어하여 사용자에게 전달하게 됩니다.</li>
<li>mvc패턴을 성공적으로 사용하면, 사용자 인터페이스로부터 비즈니스 로직을 분리하여 애플리케이션의 시작적 요소나 그 이면에서 실행되는 비즈니스 로직을 서로 영향 없이 쉽게 고칠 수 있는 애플리케이션을 만들 수 있게 됩니다.<img src= https://velog.velcdn.com/images/ice-ame/post/52f65be1-7f7f-41e8-a8be-bd283ca49d9a/image.png>
></li>
<li><em>2.각 파트의 특징*</em></li>
<li><strong>Model</strong></li>
<li>자신이 데이터를 가지고있는경우가있고 데이터베이스와 연결되어 데이터에 접근할수있다<blockquote>
</blockquote>
</li>
<li><strong>view</strong></li>
<li>유저가 보는 화면을 보여주게하는 역할을 담당한다<blockquote>
</blockquote>
</li>
<li><strong>controller</strong></li>
<li>뷰에서 일어나는 액션이나 이벤트에대한 값을받고 가공해 모델에게 전달</li>
<li>모델로부터받은 값을 다시 뷰에게전달<blockquote>
</blockquote>
</li>
<li><em>3.web example*</em><img src=https://velog.velcdn.com/images/ice-ame/post/7baaf41c-4e27-47f9-8ddb-1f1cd4d191e4/image.png>

</li>
</ul>
</li>
</ul>
<hr>
<h2 id="chapter2-데이터베이스-연결">chapter2: 데이터베이스 연결</h2>
<hr>
<blockquote>
</blockquote>
<p><strong>완성한 mvc패턴으로 작성한 스프린트의 코드를 뜯어보며 mysql npm을 통한 데이터베이스연결과정을 살펴보자</strong></p>
<blockquote>
</blockquote>
<p><strong>1.<code>.env</code>생성</strong>
<img src=https://velog.velcdn.com/images/ice-ame/post/42306fe4-6944-4c28-99d7-327d3bb7649a/image.png></p>
<blockquote>
</blockquote>
<p><strong>2.config객체 생성후 export</strong>
<img src=https://velog.velcdn.com/images/ice-ame/post/c10a1665-df8f-4cb2-8531-b0023c1cc8de/image.png></p>
<blockquote>
</blockquote>
<p><strong>3.db디렉토리 생성&amp;셋팅</strong></p>
<div>
<img src=https://velog.velcdn.com/images/ice-ame/post/013d47e7-662d-4b61-9f73-cf1cbb7a6bbd/image.png>
<img src=https://velog.velcdn.com/images/ice-ame/post/cbad84c7-0e9c-4a0d-bf5d-15cfbc947fc1/image.png>
</div>
>
- mysql npm 공식문서를 찾아보면 연결방법이 나와있음

<hr>
<h2 id="chapter3-sql파일-데이터베이스에-적용하기">chapter3: sql파일 데이터베이스에 적용하기</h2>
<hr>
<blockquote>
</blockquote>
<ul>
<li>배치작업은, 데이터를 실시간으로 처리하는게 아니라, 일괄적으로 모아서 처리하는 작업을 의미한다.</li>
<li>커맨드 창에 명령어를 하나하나 입력하는 방법과 다르게, 필요한 명령을 정리한 파일을 작성한 다음 배치모드로 실행 중인 MySQL 서버에 한 번에 적용합니다</li>
<li>배치모드로 데이터를 mysql서버에 한번에 적용하는 작업을 스프린트를통해 살펴보자<blockquote>
</blockquote>
</li>
<li><em>1.데이터베이스 생성*</em><pre><code class="language-mysql"># mysql에 접속한 뒤 입력
CREATE DATABASE cmarket;</code></pre>
<blockquote>
</blockquote>
</li>
<li><em>2.미리 작성된 schema.sql을 이용해 테이블 생성*</em><img src=https://velog.velcdn.com/images/ice-ame/post/592dbb6c-47f0-4e1b-9781-426dae03100c/image.png>
>
```sql
# CLI(터미널) 환경에서 레포지토리에 진입하여 커맨드를 입력
mysql -u root -p < server/schema.sql -Dcmarket
```
></li>
<li><em>3.미리 작성된 seed.sql을 이용해 데이터 저장*</em><img src=https://velog.velcdn.com/images/ice-ame/post/c2a08814-686a-474f-9f85-bed06d3e6b93/image.png>
>
```sql
# CLI(터미널) 환경에서 레포지토리에 진입하여 커맨드를 입력
mysql -u root -p < server/seed.sql -Dcmarket
```

</li>
</ul>
<hr>
<h2 id="chapter4-sql을-nodejs-앱에서-쿼리하기">chapter4: SQL을 Node.js 앱에서 쿼리하기</h2>
<hr>
<blockquote>
</blockquote>
<h3 id="일반-쿼리">일반 쿼리</h3>
<p><strong>1.공식문서 확인</strong>
<img src=https://velog.velcdn.com/images/ice-ame/post/f633f432-4802-4ced-807e-caaf06af177d/image.png></p>
<ul>
<li>쿼리를 수행하는 가장 기본적인 방법은 condection에서.query() 메서드를 호출하는 것입니다.</li>
<li>query()의 가장 간단한 형식은 .query(sqlString, callback)이며, 여기서 SQL 문자열은 첫 번째 인수이고 두 번째는 콜백입니다.</li>
<li>query()의 두번째 인수인 callback의 구조<pre><code class="language-js">function (error, results, fields) {
// error는 쿼리 중에 문제가 발생한 에러를 담고있음
// results 쿼리의 결과가 테이블에 어떤 영향을 미쳤는지에 대한 정보가 포함되어 있습니다.
// fields에는 반환된 결과 필드에 대한 정보가 포함됩니다(있는 경우).
});</code></pre>
<blockquote>
</blockquote>
</li>
<li><em>2.스프린트*</em></li>
<li>*<em>db/index.js *</em><img src=https://velog.velcdn.com/images/ice-ame/post/bedf202c-24b5-4fb7-9207-d1775c58c4b9/image.png></li>
<li><strong>models.indexjs</strong><img src =https://velog.velcdn.com/images/ice-ame/post/8ffebdfd-7e90-4aee-818c-cba89167f2de/image.png>
```js
const db= require('../db')//폴더를 인수로넣었기때문에 index.js로드
```

</li>
</ul>
<blockquote>
</blockquote>
<h3 id="여러개의-레코드-한번추가bulk-insert-하는쿼리">여러개의 레코드 한번추가(bulk insert) 하는쿼리</h3>
<p><strong><code>1.예시코드</code></strong></p>
<pre><code class="language-js">var mysql = require(&#39;mysql&#39;);
&gt;
var con = mysql.createConnection({
  host: &quot;localhost&quot;,
  user: &quot;yourusername&quot;,
  password: &quot;yourpassword&quot;,
  database: &quot;mydb&quot;
});
&gt;
con.connect(function(err) {
  if (err) throw err;
  console.log(&quot;Connected!&quot;);
  var sql = &quot;INSERT INTO customers (name, address) VALUES ?&quot;;
  var values = [
    [&#39;John&#39;, &#39;Highway 71&#39;],
    [&#39;Peter&#39;, &#39;Lowstreet 4&#39;],
    [&#39;Amy&#39;, &#39;Apple st 652&#39;],
    [&#39;Hannah&#39;, &#39;Mountain 21&#39;],
    [&#39;Michael&#39;, &#39;Valley 345&#39;],
    [&#39;Sandy&#39;, &#39;Ocean blvd 2&#39;],
    [&#39;Betty&#39;, &#39;Green Grass 1&#39;],
    [&#39;Richard&#39;, &#39;Sky st 331&#39;],
    [&#39;Susan&#39;, &#39;One way 98&#39;],
    [&#39;Vicky&#39;, &#39;Yellow Garden 2&#39;],
    [&#39;Ben&#39;, &#39;Park Lane 38&#39;],
    [&#39;William&#39;, &#39;Central st 954&#39;],
    [&#39;Chuck&#39;, &#39;Main Road 989&#39;],
    [&#39;Viola&#39;, &#39;Sideway 1633&#39;]
  ];
  con.query(sql, [values], function (err, result) {
    if (err) throw err;
    console.log(result);
//  fieldCount: 0,
//  affectedRows: 14,
//  insertId: 0, // 방금 insert한 레코드의 id    &lt;=!!!!!!!!중요!!!!!!!!
//  serverStatus: 2,
//  warningCount: 0,
//  message: &#39;\&#39;Records:14  Duplicated: 0  Warnings: 0&#39;,
//  protocol41: true,
//  changedRows: 0
  });
});</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[데이터베이스]SQL로  MYSQL 실습]]></title>
            <link>https://velog.io/@ice-ame/%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%B2%A0%EC%9D%B4%EC%8A%A4SQL%EB%A1%9C-MYSQL-%EC%8B%A4%EC%8A%B5</link>
            <guid>https://velog.io/@ice-ame/%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%B2%A0%EC%9D%B4%EC%8A%A4SQL%EB%A1%9C-MYSQL-%EC%8B%A4%EC%8A%B5</guid>
            <pubDate>Sun, 17 Apr 2022 18:04:56 GMT</pubDate>
            <description><![CDATA[<hr>
<h2 id="chapter-mysql-커맨드">chapter MySQL 커맨드</h2>
<hr>
<blockquote>
</blockquote>
<h3 id="mysql-구조">MySQL 구조</h3>
<p><strong>1.mySQL구조</strong></p>
<blockquote>
</blockquote>
<img src=https://velog.velcdn.com/images/ice-ame/post/86c5f674-7b93-4fb4-a69d-33ae80876d89/%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-04-09%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%2011.02.07.png>
>
- **```데이터베이스 서버(database server)```**
MySQL(데이터베이스가들이 저장되는 곳)
>
- **```데이터베이스(database,shema)```**
표들이 저장되는공간(파일의 폴더같은곳)
>
- **```표(table)```**
실질적으로 데이터가 저장되는 곳으로 사전에 정의된 열의 데이터 타입대로 작성된 데이터가 행으로 축적됩니다.
>
**2.TABLE구조**
>
<img src=https://velog.velcdn.com/images/ice-ame/post/e0ba188b-435f-477a-b085-b4949dffde9e/%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-04-09%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%2011.05.16.png>
>
**```칼럼(column)또는 필드(filed) ```**
테이블의 한 **열**을 가리킨다 (데이터의 타입)
**```로우(row) 또는 레코드(record)```**
테이블의 한 **행**을 카리킨다 (데이터자체)
**```키(key)//(위 사진의 id)```**
테이블의 각 레코드를 구분할 수 있는 값입니다. 각 레코드마다 고유한 값을 가집니다. 기본키(primary key)와 외래키(foreign key) 등이 있습니다.

<blockquote>
</blockquote>
<h3 id="mysql접속-및-데이터베이스-선택">MySQL접속 및 데이터베이스 선택</h3>
<p><strong>1.서버(MySQL)접속</strong></p>
<pre><code class="language-mysql">mysql -uroot -p</code></pre>
<img src=https://velog.velcdn.com/images/ice-ame/post/9ad14262-a4f2-4415-a484-845dc8d88884/%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-04-10%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%2012.17.25.png>
>
**2.데이터베이스 선택**
```SQL
USE 데이텁베이스 이름;
```
<img src=https://velog.velcdn.com/images/ice-ame/post/8fc6bfa6-a0ae-42eb-b2ae-456ce22bb024/%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-04-10%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%2012.28.16.png>

<blockquote>
</blockquote>
<h3 id="데이터베이스-crud">데이터베이스 CRUD</h3>
<p><strong>1. 데이터베이스 생성</strong></p>
<pre><code class="language-sql">CREATE DATABASE opentutorials ;</code></pre>
<img src=https://velog.velcdn.com/images/ice-ame/post/52aedeab-0098-4097-badf-691d4dfda534/%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-04-10%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%2012.21.44.png>
>
**2.데이터베이스 삭제**
```sql
DROP DATABASE opentutorials;
```
<img src=https://velog.velcdn.com/images/ice-ame/post/a6662067-a044-493e-8822-ba2a9cb28e8d/%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-04-10%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%2012.23.39.png>
>
**3.데이터베이스목록 조회**
```SQL
SHOW DATABASES;
```
<img width=30% src=https://velog.velcdn.com/images/ice-ame/post/8c353c03-d416-4d32-a103-7e6941c05075/%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-04-10%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%2012.25.49.png>

<blockquote>
</blockquote>
<h3 id="테이블의-crud">테이블의 CRUD</h3>
<p><strong>1.테이블 생성</strong></p>
<ul>
<li><strong>colum만 설정해주면 테이블이 생성됨</strong><pre><code class="language-sql">CREATE TABLE 테이블명(
컬럼명1 datatype ...,
컬럼명2 datatype ...,
...
);</code></pre>
<img witdh =50% src=https://velog.velcdn.com/images/ice-ame/post/82c213d1-b94a-4a3a-a178-80f2f7f7e3b0/%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-04-10%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%2012.48.51.png>
></li>
<li><em><code>id INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,</code>*</em>
column 이름은 id
데이터타입은 정수,11개까지 보여줌(괄호는 노출시킬범위)
빈값 허용하지 않음
테이블의 Primary key로 설정
id값은 자동 증가하도록 설정</li>
<li><em><code>title VARCHAR(100) NOT NULL,</code>*</em>
column 이름은 title
데이터타입은 문자열,100글자까지 보여줌 (괄호는 노출시킬범위)
빈값 허용하지 않음</li>
<li><em><code>description TEXT NULL,</code>*</em>
column 이름은 description
데이터타입은 문자열
빈값 허용함</li>
<li><em><code>created DATETIME NOT NULL,</code>*</em>
column 이름은 created
데이터타입은 날짜
빈값 허용안함</li>
<li>예시2<img src=https://velog.velcdn.com/images/ice-ame/post/1996b82b-e195-4493-a1c5-5a322cb13b9e/image.png>
></li>
<li><em>2.테이블 목록조회*</em><pre><code class="language-sql">SHOW TABLES</code></pre>
<blockquote>
</blockquote>
<img width=50% src=https://velog.velcdn.com/images/ice-ame/post/d41200dd-dedf-4c63-af74-c96a9e9db3d3/%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-04-10%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%2012.56.07.png>
></li>
<li><em>3.선택테이블 구조보기*</em><pre><code class="language-sql">DESC 테이블명</code></pre>
<img src=https://velog.velcdn.com/images/ice-ame/post/a2068f2d-f4c5-425b-96b4-df0cb952db62/%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-04-10%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%201.02.43.png>
></li>
<li><em>4.테이블 삭제*</em><pre><code class="language-sql">drop table 테이블명;</code></pre>
</li>
</ul>
<blockquote>
</blockquote>
<h3 id="데이터의-crud">데이터의 CRUD</h3>
<p><strong>1.테이블에 데이터 추가하기</strong></p>
<pre><code class="language-sql">INSERT INTO 테이블명(title,description,created,author,profile) VALUES(&#39;MySQL&#39;,&#39;MYSQL is&#39;,NOW(),&#39;egoing&#39;,&#39;developer&#39;);</code></pre>
<img src=https://velog.velcdn.com/images/ice-ame/post/b1413203-a8c7-460c-b186-6103c4d2208b/%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-04-10%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%201.14.01.png>
>
**2.테이블의 데이터 읽기**
- 모든컬럼 읽기
```sql
SELECT *FROM 테이블명;
```
<img src=https://velog.velcdn.com/images/ice-ame/post/506fe7e1-4c0f-406d-883a-35abb049de93/image.png>
>
- 선택컬럼만 읽기
```sql
SELECT 특성_1, 특성_2 FROM 테이블_이름 
```
>
<img src=https://velog.velcdn.com/images/ice-ame/post/a712d850-643e-40b2-8f5e-59176c53b92f/image.png>
>
- 선택컬럼만 읽기 + 특정 값과 동일한 데이터 찾기
```sql
SELECT 특성_1
FROM 테이블_이름
WHERE 특성_1 = "특정 값"
```
>
<img src=https://velog.velcdn.com/images/ice-ame/post/b9b94f15-21cc-48ca-84a0-991acf81a4fe/image.png>
>
- 선택 컬럼만 읽기 + 특정 값을 제외한 데이터 찾기
```sql
SELECT 특성_1, 특성_2
FROM 테이블_이름
WHERE 특성_2 <> "특정 값"
```
<img src=https://velog.velcdn.com/images/ice-ame/post/f9a2f49f-6194-4734-b409-59c7273e1e3a/image.png>
>
- 선택 컬럼의 특성이 대소비교가 가능할때
```sql
SELECT 특성_1, 특성_2
FROM 테이블_이름
WHERE 특성_1 > "특정 값"
>
SELECT 특성_1, 특성_2
FROM 테이블_이름
WHERE 특성_1 <= "특정 값"
```
- 선택 컬럼만 읽기 + 특정문자를 포함하는 데이터 찾기
```sql
SELECT 필드명
FROM 테이블명
WHERE 필드명
LIKE '% 특정 문자열%;
```
<img src=https://velog.velcdn.com/images/ice-ame/post/4e32a6a3-a319-4ac2-bb94-8316bab6f849/image.png>
>
++**like, in,is 더써봐야함**
>
- 내림차순 정렬
```sql
SELECT *
FROM 테이블_이름
ORDER BY 특성_1 DESC
````
<img src= https://velog.velcdn.com/images/ice-ame/post/fa266e63-846d-449d-beee-15d6c7da9f4f/image.png>
>
- 출력할 데이터 개수 정하기
```sql
SELECT *
FROM 테이블_이름
LIMIT 개수
```
<img src= https://velog.velcdn.com/images/ice-ame/post/75fa834c-a4d6-41a2-846e-ce885a358345/image.png>
>
**3.테이블의 데이터 수정**
<img src= https://velog.velcdn.com/images/ice-ame/post/6bf6b93f-a13f-472b-9d3c-63a953c7bfb8/image.png>
>
**4.테이블의 데이터 삭제**
<img src=https://velog.velcdn.com/images/ice-ame/post/5964fec6-4f27-4db3-9e64-cdbf33b49716/image.png>
>
**4.테이블의 컬럼 추가하기/컬럼 포인키설정**
<div>
<img src=https://velog.velcdn.com/images/ice-ame/post/42248538-839b-49ee-8026-07c3721b0b81/image.png >
<img src=https://velog.velcdn.com/images/ice-ame/post/3825bb58-0ae6-4574-ae98-a612ee8a1fa8/image.png>
</div>

<blockquote>
</blockquote>
<h3 id="테이블-합치기">테이블 합치기</h3>
<img src=https://velog.velcdn.com/images/ice-ame/post/96d96ddc-2902-4782-a49f-2a8a2226aef5/image.png>
>
**1.LEFT JOIN**
<img src=https://velog.velcdn.com/images/ice-ame/post/60f14b07-bf5a-4317-ba59-9587f222c653/image.png>
>
**2.INNER JOIN**
>
<img src=https://velog.velcdn.com/images/ice-ame/post/7b0317e2-60f4-416c-9437-dded9eb8abb9/image.png>



<blockquote>
</blockquote>
<h3 id="그밖에것들">그밖에것들</h3>
<p>1.select 실행순서
SELECT =&gt; FROM =&gt;WHERE =&gt; GROUP BY =&gt; HAVING =&gt; ORDER BY</p>
<blockquote>
</blockquote>
<p>2.groupy by
조인후 select된것들중 레코드가 공통된 것들끼리 묶어줌</p>
<blockquote>
</blockquote>
<p>3.내장함수이용</p>
<hr>
<h2 id="스키마-설계">스키마 설계</h2>
<hr>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Node.js] Express 프레임워크]]></title>
            <link>https://velog.io/@ice-ame/Node-Web-server-%EA%B8%B0%EC%B4%88</link>
            <guid>https://velog.io/@ice-ame/Node-Web-server-%EA%B8%B0%EC%B4%88</guid>
            <pubDate>Sun, 17 Apr 2022 17:39:47 GMT</pubDate>
            <description><![CDATA[<hr>
<h2 id="express-framework">Express framework</h2>
<hr>
<blockquote>
</blockquote>
<h3 id="들어가기전">들어가기전</h3>
<ul>
<li>Express는 서버개발에 유용한 프레임워크로 대다수가 사용할 정도로 대중적이고 인기가 가장 많습니다.
서버의 페이지 개수가 늘어나고 사이트가 커지면 코드가 복잡해집니다.Express 프레임워크는 코드의 양도 줄여주고 추후 유지보수가 쉽도록 만들어주기 때문에 사용합니다(성능은 생코드보다 떨어지지만 크게 영향은 없다)</li>
<li>http, path, fs, url 등의 모듈은 Node.js에서 기본 제공하는 패키지였기 때문에 설치할 필요가 없지만 Express는 Node.js가 아닌 다른 개인이나 단체가 만든 패키지이기 때문에 npm에서 다운로드받아야 합니다</li>
<li><a href="https://expressjs.com/ko/">공식문서</a></li>
<li>http모듈과 다른점 <ul>
<li>미들웨어 추가가 편리하다.</li>
<li>자체 라우터를 제공한다.</li>
</ul>
</li>
</ul>
<blockquote>
</blockquote>
<h3 id="express-설치">Express 설치</h3>
<p><strong>0.Node.js가 이미 설치되었다고 가정한 상태</strong></p>
<blockquote>
</blockquote>
<p><strong>1.애플리케이션을 보관할 디렉토리를 작성하고 그 디렉토리를 작업 디렉토리로 설정하십시오.</strong></p>
<blockquote>
</blockquote>
<p><strong>2.npm init 명령을 이용하여 애플리케이션에 대한 package.json 파일을 작성</strong></p>
<blockquote>
</blockquote>
<p><strong>3.렉토리에 Express를 설치한 후 종속 항목 목록에 저장</strong></p>
<pre><code>$ npm install express --save</code></pre><blockquote>
</blockquote>
<h3 id="간단한-웹-서버-만들고-실행하기">간단한 웹 서버 만들고 실행하기</h3>
<pre><code class="language-js">const express = require(&#39;express&#39;)
const app = express()//app은 express클래스의 인스턴스이다
const port = 3000
&gt;
app.get(&#39;/&#39;, (req, res) =&gt; {
  res.send(&#39;Hello World!&#39;)
})
&gt;
app.listen(port, () =&gt; {
  console.log(`Example app listening on port ${port}`)
})</code></pre>
<ul>
<li><code>node 해당파일</code>로 서버실행</li>
<li>listen 에의해 서버 시작</li>
<li>앱은 서버를 시작하며 3000번 포트에서 연결을 청취합니다</li>
<li>앱은 루트 URL(/) 또는 라우트에 대한 요청에 “Hello World!”로 응답합니다.</li>
<li>다른 모든 경로에 대해서는 404 Not Found로 응답합니다.</li>
</ul>
<blockquote>
</blockquote>
<h3 id="라우팅routing분기">라우팅(Routing===분기)</h3>
<p><strong>1.기본라우팅</strong></p>
<ul>
<li>라우팅은 URI(또는 경로) 및 특정한 HTTP 요청 메소드(GET, POST 등)인 특정 엔드포인트에 대한 클라이언트 요청에 애플리케이션이 응답하는 방법을 결정하는 것을 말합니다.</li>
<li>각 경로에는 경로가 일치할 때 실행되는 하나 이상의 처리기 기능이 있을 수 있습니다.</li>
<li>라우트는 이와같은 구조를 가진다 
<code>app.METHOD(PATH, HANDLER)</code><pre><code class="language-js"> app.get(&#39;/&#39;, function (req, res) {
  res.send(&#39;Hello World!&#39;);
});</code></pre>
<pre><code class="language-js">app.post(&#39;/&#39;, function (req, res) {
res.send(&#39;Got a POST request&#39;);
});</code></pre>
<blockquote>
</blockquote>
</li>
<li><em>2.라우트 경로(PATH)*</em></li>
<li>라우트 경로는, 요청 메소드와의 조합을 통해, 요청이 이루어질 수 있는 엔드포인트를 정의합니다. 라우트 경로는 문자열, 문자열 패턴 또는 정규식일 수 있습니다.<pre><code class="language-js">app.get(&#39;/&#39;, function (req, res) {
res.send(&#39;root&#39;);
});//라우트 경로는 요청을 루트 라우트 /에 일치시킵니다
&gt;
app.get(&#39;/about&#39;, function (req, res) {
res.send(&#39;about&#39;);
});//라우트 경로는 요청을 /about에 일치시킵니다</code></pre>
<blockquote>
</blockquote>
</li>
<li><em>3.라우트 핸들러(HANDLER)*</em></li>
<li>라우트는 하나 이상의 핸들러 함수를 가질 수 있으며, 이러한 함수는 라우트가 일치할 때 실행됩니다.</li>
<li><h2 id="미들웨어와-비슷하게-작동함차이점은있음여러-콜백-함수를-제공하여-요청을-처리할-수-있습니다next-호출해줘야함">미들웨어와 비슷하게 작동함(차이점은있음),여러 콜백 함수를 제공하여 요청을 처리할 수 있습니다.(next 호출해줘야함)</h2>
<pre><code class="language-js">app.get(&#39;/example/b&#39;, function (req, res, next) {
console.log(&#39;the response will be sent by the next function ...&#39;);
next();
}, function (req, res) {
res.send(&#39;Hello from B!&#39;);
});</code></pre>
</li>
<li>콜백을 배열로받을수도 있다<pre><code class="language-js">var cb0 = function (req, res, next) {
console.log(&#39;CB0&#39;);
next();
}
&gt;
var cb1 = function (req, res, next) {
console.log(&#39;CB1&#39;);
next();
}
&gt;
var cb2 = function (req, res) {
res.send(&#39;Hello from C!&#39;);
}
&gt;
app.get(&#39;/example/c&#39;, [cb0, cb1, cb2]);</code></pre>
<blockquote>
</blockquote>
</li>
<li><em>4.응답 메소드*</em></li>
<li>응답을 클라이언트로 전송하고 요청-응답 주기를 종료할 수 있습니다.</li>
<li><strong>라우트 핸들러로부터 응답 메소드가 호출되지 않는 경우, 클라이언트 요청은 정지된 채로 방치됩니다.</strong><blockquote>
</blockquote>
<code>res.send([body])</code>:다양한 유형의 응답을 전송합니다.</li>
<li><em>1)*</em> body 매개 변수는 Buffer 객체, String, 객체 또는 Array 일 수 있습니다</li>
<li><em>2)*</em> 매개변수가 a String일 때 메소드는 Content-Type&quot;text/html&quot;로 설정합니다.</li>
<li><em>3)*</em> 매개변수가 Array또는 Object인 경우 Express는 JSON 표현으로 응답합니다.<blockquote>
</blockquote>
<code>res.end()</code>:응답 프로세스를 종료합니다.(데이터 없이 응답을 빠르게 종료하는 데 사용합니다)<blockquote>
</blockquote>
<code>res.json([body])</code>:JSON 응답을 전송합니다.
(json 문자열로 변환된 데이터를 전송)</li>
<li><em>1)*</em> 매개변수는 객체, 배열, 문자열, 부울, 숫자 또는 null을 포함한 모든 JSON 유형이 될 수 있으며 다른 값을 JSON으로 변환하는 데 사용할 수도 있습니다.<img src=https://velog.velcdn.com/images/ice-ame/post/3a9cfa3c-cef3-43b4-9309-7821545bff9d/image.png>

</li>
</ul>
<blockquote>
</blockquote>
<p><strong>5.express.Router</strong>(미들웨어)</p>
<ul>
<li>라우터를 모듈로서 작성해,공통된 라우트끼리 묶을 수 있다<div>
<img align =left width=20% src=https://velog.velcdn.com/images/ice-ame/post/71b8c059-631c-416b-b59c-7600533b2395/image.png> <img  width=50% src=https://velog.velcdn.com/images/ice-ame/post/a7fbdff6-07e8-4b60-a6d8-313567d70feb/image.png>
<br>
<img width=80% src=https://velog.velcdn.com/images/ice-ame/post/ec1d54d6-cec3-4e68-a671-f6d51be1b60b/image.png> <img width =80% src=https://velog.velcdn.com/images/ice-ame/post/a329fbb4-f145-4a9c-9d84-e355f294bfe3/image.png>
<img  width =80% src=https://velog.velcdn.com/images/ice-ame/post/c1371905-f767-41c6-b3cb-a10271a353d4/image.png>
</div>

</li>
</ul>
<blockquote>
</blockquote>
<h3 id="미들웨어">미들웨어</h3>
<p><strong>1.개요</strong></p>
<ul>
<li>미들웨어는 자동차 공장의 공정과 비슷합니다. 컨베이어 벨트 위에 올라가 있는 요청에 필요한 기능을 더하거나, 문제가 발견된 불량품을 밖으로 걷어내는 역할을 합니다</li>
<li>미들웨어 함수의 인수는 요청 객체(req), 응답 객체 (res), 그리고 다음의 미들웨어 함수 대한 액세스 권한을 갖는 함수(next)입니다.</li>
<li>현재의 미들웨어 함수가 요청-응답 주기(응답메소드사용)를 종료하지 않는 경우에는 next()를 호출하여 그 다음 미들웨어 함수에 제어를 전달해야 합니다. 그렇지 않으면 해당 요청은 정지된 채로 방치됩니다.<img src=https://media.vlpt.us/images/ice-ame/post/acf668de-9587-4f0d-8202-d657b221d58f/%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-04-01%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%206.36.11.png>
></li>
<li><em>2.미들웨어 추가방법*</em>
1)특정 요청에대해 미들웨어 추가<pre><code class="language-js">const express = require(&#39;express&#39;);
const app = express();
const myLogger = function (req, res, next) {
 console.log(&#39;LOGGED&#39;); 
 next();//해줘야 그 다음 미들웨어 함수가 호출됩니다
};
&gt;
app.get(&#39;/&#39;,myLogger, function (req, res) {
 res.send(&#39;Hello World!&#39;);
});
&gt;
app.listen(3000);</code></pre>
<blockquote>
</blockquote>
2)모든요청에 대해 미들웨어 추가(<code>app.use()</code>이용)<pre><code class="language-js">const express = require(&#39;express&#39;);
const app = express();
&gt;
const myLogger = function (req, res, next) {
 console.log(&#39;LOGGED&#39;);
 next();
};
&gt;
app.use(myLogger);//모든 요청이 myLogger미들웨어를 거침
&gt;
app.get(&#39;/&#39;, function (req, res) {
 res.send(&#39;Hello World!&#39;);
});
&gt;
app.listen(3000);</code></pre>
<blockquote>
</blockquote>
</li>
<li><em>3. 자주 사용하는 미들웨어*</em>
1)모든 요청에 대해 url이나 메서드를 확인할 때(++query,parms)<pre><code class="language-js">const express = require(&#39;express&#39;);
const app = express();
&gt;
const myLogger = function (req, res, next) {
   console.log(
       `request method is +${req.method}&amp;`,
       `request URL is +${req.path}&amp;`,
       `request query is + ${req.query} &amp; `,
       `request params is + ${req.params} &amp; `,
       `request body is + ${req.body}`
   );
   next();
};
&gt;
app.use(myLogger);
&gt;
app.get(&#39;/&#39;, function (req, res) {
 res.send(&#39;Hello World!&#39;);
});
&gt;
app.listen(3000);</code></pre>
<blockquote>
</blockquote>
</li>
<li><em>2)POST 요청 등에 포함된 body(payload)를 구조화할 때(쉽게 얻어내고자 할 때)*</em><pre><code class="language-js">const jsonParser = express.json()
// 생략
app.post(&#39;/api/users&#39;, jsonParser, function (req, res) {
 // req.body에는 JSON의 형태로 payload가 담겨져 있습니다.
})</code></pre>
<blockquote>
</blockquote>
</li>
<li><em>3)모든 요청/응답에 CORS 헤더를 붙여야 할 때*</em><pre><code class="language-js">const cors = require(&#39;cors&#39;)
// 생략
app.use(cors()) // 모든 요청에 대해 CORS 허용</code></pre>
<blockquote>
</blockquote>
</li>
<li><em>4)요청 헤더에 사용자 인증 정보가 담겨있는지 확인할 때*</em><pre><code class="language-js">app.use((req, res, next) =&gt; {
 // 토큰 있니? 없으면 받아줄 수 없어!
 if(req.headers.token){
   req.isLoggedIn = true;
   next()
 } else {
   res.status(400).send(&#39;invalid user&#39;)
 }
})</code></pre>
</li>
</ul>
<blockquote>
</blockquote>
<h3 id="request-api">request API</h3>
<p><strong>1.<code>req.query</code></strong></p>
<pre><code class="language-js">//라우팅
app.get(&#39;flight&#39;, ((req, res) =&gt; {
&gt;
})
)
//user가 
//flight?departure_times=2021-12-03T12:00:00&amp;id=4
//의 경로로 접속했다면
//req.query==={departure_times: &#39;2021-12-03T12:00:00&#39;, id: &#39;4&#39;}</code></pre>
<blockquote>
</blockquote>
<p><strong>2.<code>req.parms</code></strong></p>
<pre><code class="language-js">//라우팅
app.get(&#39;flight/:id/:name&#39;, ((req, res) =&gt; {
&gt;
})
)
//user가
//flight/54/jiwoong 의 경로로 접속한다면
//req.params ==== {id:&#39;54&#39;,name:&#39;jiwoong&#39;}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[web server]  mini node server ]]></title>
            <link>https://velog.io/@ice-ame/web-server-mini-node-server</link>
            <guid>https://velog.io/@ice-ame/web-server-mini-node-server</guid>
            <pubDate>Sat, 16 Apr 2022 20:12:10 GMT</pubDate>
            <description><![CDATA[<hr>
<h2 id="mini-node-server">MINI NODE SERVER</h2>
<hr>
<blockquote>
</blockquote>
<ul>
<li>브라우저에는 서버에 요청을 보내기 위해 fetch 같은 HTTP 요청을 보내는 도구가 기본적으로 내장되어있고 이를통해 서버에 요청을 보낸다.</li>
<li>http 요청을 받은 서버는 알맞는 코드작성을 통해 요청을 처리하고 응답을 보내주어야하고 이를 웹 서버라고 부른다</li>
<li>node.js의 <strong><code>http</code></strong>모듈을 통해 웹서버를 만들 수 있다</li>
<li><a href="https://nodejs.org/ko/docs/guides/anatomy-of-an-http-transaction/">http 트렌잭션해부</a>페이지를 참고해 간단한 서버를 만드는 과정중 기억해야할부분을 기록으로남긴다 </li>
</ul>
<blockquote>
</blockquote>
<p><strong>1.서버객체만들기&amp;서버 실행하기</strong>
<img src=https://velog.velcdn.com/images/ice-ame/post/5840bfa2-bc2c-489a-9f3d-7f2142ad3cca/image.png></p>
<ul>
<li>1: http 모듈가져오기</li>
<li>3: 서버객체생성, 이 서버로 오는 HTTP요청마다 <strong><code>createServer</code></strong>에 전달된 함수가 한번씩 호출됨</li>
<li>7:<strong><code>server.listen</code></strong>메서드를통해 요청처리가능(포트번호전달)</li>
<li>node app.js 를통해 서버실행<blockquote>
</blockquote>
</li>
<li><em>2.메서드,URL,헤더 확인방법*</em></li>
<li>요청을 처리할 때, 우선은 메서드와 URL을 확인한 후 이와 관련된 적절한 작업을 실행하려고 할 것입니다. Node가 request 객체에 유용한 프로퍼티를 넣어두었으므로 이 작업은 비교적 쉽게 할 수 있습니다.<pre><code class="language-js">const { method, url,headers } = request;</code></pre>
<blockquote>
</blockquote>
</li>
<li><em>3.요청의 바디 확인방법*</em></li>
<li>POST나 PUT 요청을 받을 때 애플리케이션에 요청 바디는 중요할 것입니다<pre><code class="language-js">let body = [];
request.on(&#39;data&#39;, (chunk) =&gt; {
body.push(chunk);
}).on(&#39;end&#39;, () =&gt; {
body = Buffer.concat(body).toString();
// 여기서 `body`에 전체 요청 바디가 문자열로 담겨있습니다.
});</code></pre>
<blockquote>
</blockquote>
</li>
<li><em>4.cors 설정*</em><img src=https://velog.velcdn.com/images/ice-ame/post/17bbf80e-3784-4b4a-a425-f728529b2993/image.png>




</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[node.js 기초]]></title>
            <link>https://velog.io/@ice-ame/node.js-%EA%B8%B0%EC%B4%88</link>
            <guid>https://velog.io/@ice-ame/node.js-%EA%B8%B0%EC%B4%88</guid>
            <pubDate>Sat, 16 Apr 2022 18:13:16 GMT</pubDate>
            <description><![CDATA[<hr>
<h2 id="chater1-nodejs">chater1: node.js?</h2>
<hr>
<blockquote>
</blockquote>
<h3 id="런타임이란">런타임이란?</h3>
<ul>
<li>런타임이란 프로그래밍 언어가 구동되는 환경입니다. 런타임 이란 어떤 프로그램이 동작할 때, 프로그램이 동작하는 곳입니다</li>
</ul>
<blockquote>
</blockquote>
<h3 id="자바스크립트의-런타임">자바스크립트의 런타임</h3>
<ul>
<li>자바스크립트의 대표적인 런타임은 브라우저(웹 페이지)와 node.js(서버)가 있다</li>
<li><strong>HTML<code>&lt;script&gt;</code>태그 내에 자바스크립트를 작성하면 웹 브라우저가 동작하고, CIL환경에 node<file_name>명령어를 프롬프트에 입력하면 node.js가 동작한다.</strong></li>
<li>Node.js는 ** http서버가 내장되어 있기 때문에 보통은 서버로 많이 사용합니다**. 하지만 응용 프로그램을 실행하는 데 쓸 수도 있습니다. 웹팩, 바벨과 같은 도구들과 일렉트론 같이 자바스크립트로 데스크탑 프로그램을 만드는 프레임워크가 모두 Node.js를 기반으로 돌아갑니다</li>
</ul>
<hr>
<h2 id="chater2-nodejs-설치">chater2: node.js 설치</h2>
<hr>
<blockquote>
</blockquote>
<h3 id="nvm--nodejs-설치">nvm &amp; node.js 설치</h3>
<p><strong>0.nvm이란?</strong></p>
<ul>
<li>nvm은 node.js의 다양한 버전을 관리하는 프로그램이다</li>
<li>nvm을 사용하면 node.js의 다양한 버전을 쉽게 설치하고, 사용,관리 할 수 있습니다.<blockquote>
</blockquote>
</li>
<li><em>1.nvm (Node Version Manager)설치*</em>
1)    <a href="https://github.com/nvm-sh/nvm#install--update-script">nvm공식문서</a>에서 install링크를 터미널에 복붙<blockquote>
</blockquote>
2)    설치후 nvm-version  확인을 꼭 해야한다</li>
<li>버전이 잘 나온다면,NVM 설치 성공</li>
<li>저같은 경우는 *<em><code>zsh: command not found: nvm</code> *</em>만 출력되고 명령어가 먹지않아 구글링을통해 해결했습니다
<a href="https://velog.io/@palette/zsh-command-not-found-nvm-%EC%98%A4%EB%A5%98%ED%95%B4%EA%B2%B0%EB%B2%95"> zsh: command not found: nvm</a><img src=https://velog.velcdn.com/images/ice-ame/post/f3675ada-c50b-4376-86bd-17117ec81605/image.png>
></li>
<li><em>2.nvm을 이용한node.js 설치*</em>
1) nvm을 이용해 node.js 설치 </li>
<li>터미널에서  <strong><code>nvm install --lts</code></strong><blockquote>
</blockquote>
2) 설치확인<ul>
<li>터미널에서  <strong><code>node -v</code></strong></li>
</ul>
</li>
</ul>
<blockquote>
</blockquote>
<h3 id="nvm-간단-사용법">nvm 간단 사용법</h3>
<p> node.js는 많은 버전이 있고 ,개발을 하다 보면 node.js의 다양한 버전에 대응해야 할 경우가 있다.
 node를 업그레이드하는 경우 *<em><code>nvm install --lts</code> *</em>를 이용해 최신버전을 설치할 수 있다,
 이전 버전의 경우 nvm을 이용한다. nvm을 통해 간단한 명령어로 node를 설치하고, 다양한 버전을 손쉽게 옮겨 다닐 수 있다.</p>
<blockquote>
</blockquote>
<p><strong>1. 현재 설치한 node들의 버전 확인</strong>
<strong><code>nvm ls</code></strong></p>
<blockquote>
</blockquote>
<p><strong>2. 특정 node버전 설치</strong>
** <code>nvm install 버전넘버</code>**</p>
<blockquote>
</blockquote>
<p><strong>3. 다른 버전으로 변경하기</strong>
** <code>nvm use 버전넘버</code>**</p>
<hr>
<h2 id="chater3-npm-packgejson">chater3: npm&amp; packge.json</h2>
<hr>
<blockquote>
</blockquote>
<h3 id="npm">npm</h3>
<ul>
<li>Node.js에서는 자주 쓰이고 재사용되는 자바스크립트 코드들을 패키지로 만들어서 사용할 수 있고 그러한 패키지를 모아놓은 저장소가 npm이다</li>
<li>Node.js를 설치하면 자동으로 npm이 설치됩니다 </li>
<li>바퀴를 재발명하지 마라는 말처럼 우리는 npm을통해 필요에따라 기존에 만들어진 npm모듈들을 이용하면된다<blockquote>
</blockquote>
</li>
<li><em>1.npm 명령어*</em><blockquote>
</blockquote>
1)npm 버전확인</li>
<li><em><code>npm-v</code>*</em><blockquote>
</blockquote>
2)npm 최신버전으로 업데이트</li>
<li><em><code>npm update -g npm</code>*</em><blockquote>
</blockquote>
3)npm 모듈설치</li>
<li><em><code>npm install (모듈이름)</code>*</em><blockquote>
</blockquote>
4)package.json 만들기</li>
<li><em><code>npm init</code>*</em><blockquote>
</blockquote>
5)package.json에 작성한 script실행</li>
<li><em><code>npm run &lt;스크립트 이름&gt;</code>*</em></li>
</ul>
<blockquote>
</blockquote>
<h3 id="pacakgejson">pacakge.json</h3>
<p><strong>0.개요</strong></p>
<ul>
<li>pacakge.json에는 어떤 프로그램을 실행시키기 위해 필요한 모듈들이 무엇이고, 프로그램을 실행시키는 방법과 프로그램을 테스트하는 방법등(프로젝트에 관한 정보,CLI에서 사용가능한 명령,개발과 관련된 dependencye들)이 명시되어있다.즉 정보를 담아둔 곳이다</li>
<li>npm install 커맨드로 packge.json에 작성된 프로그램을 실행시키기 위해 필요한 모듈들을 설치할수있고, 실제 모듈은 node_modules이라는 폴더에 따로 저장된다<blockquote>
</blockquote>
</li>
<li><em>1.packge json의 이점*</em></li>
<li>프로젝트 코드를 전달할 때, 포함하고 있는 모든 모듈을 다 전달하지 않아도 된다.</li>
<li>협업시 packge.json을통해 필요한 모듈들이 무엇인지 다 파악할수있고, 간단한 커맨드로 설치도 편하게 할 수 있다<blockquote>
</blockquote>
</li>
<li><em>2.packge.json들여다보기*</em><blockquote>
</blockquote>
</li>
<li><em>1)devDependencies*</em><img src=https://velog.velcdn.com/images/ice-ame/post/281c996c-99d9-475c-b919-b33b4b13fa91/image.png></li>
<li>프로그램 실행과 관계없는 오로지 개발을 위해 필요한 모듈들이 작성되어있다 </li>
<li>키에 적힌 것은 모듈 이름입니다. 값은 버전입니다</li>
<li>npm install 이용시 --save-dev옵션과 함께 설치하면 자동으로 devDependencies에 추가됨<blockquote>
</blockquote>
</li>
<li><em>2)dependency(의존성 모듈)*</em><img src= https://velog.velcdn.com/images/ice-ame/post/85c6024b-2248-4457-b62b-9622c42de4eb/image.png></li>
<li>dependencies는 어떤 프로젝트가 동작하기위해 반드시 필요한 모듈들이 무엇인지 적혀있다</li>
<li>키에 적힌 것은 모듈 이름입니다. 값은 버전입니다</li>
<li>npm install 사용시 --save 옵션과 함께 설치하면 자동으로dependcies에 추가 된다(생략가능)<blockquote>
</blockquote>
</li>
<li><em>3)scripts 항목*</em><img src=https://velog.velcdn.com/images/ice-ame/post/82ba9ba9-0b91-4a49-ad92-fab5c0860b26/image.png></li>
<li>scripts항목은 CLI에서 사용가능한 명령이 적혀있다.</li>
<li>주로 실행,테스트.코드검사(lint)등을 기술한다.</li>
<li>이를 npm script라고 부른다</li>
<li>실행은 npm run&lt;스크립트 이름&gt;으로 실행한다</li>
</ul>
<hr>
<h2 id="chater4-nodejs-내장객체-알아보기">chater4: node.js 내장객체 알아보기</h2>
<hr>
<blockquote>
</blockquote>
<h3 id="__filename--__dirname">__filename &amp; __dirname</h3>
<ol>
<li><strong><code>__filename</code></strong>: 현재파일경로</li>
<li><strong><code>__dirname</code></strong> : 현재폴더(디렉토리)경로<img src=https://velog.velcdn.com/images/ice-ame/post/73aaff9a-11cf-4802-b5f1-ffbdfe0816c5/image.png>

</li>
</ol>
<blockquote>
</blockquote>
<h3 id="require--moduleexports">require &amp; module.exports</h3>
<p><strong>1.node.js에서는 모듈을 불러오기 위해 require()함수를 쓴다</strong></p>
<blockquote>
</blockquote>
<p><strong>2.require()는 module.exports를 리턴한다.</strong></p>
<blockquote>
</blockquote>
<p><strong>3.기본적으로 module.exports는 빈객체이다</strong></p>
<blockquote>
</blockquote>
<img width=90% src=https://velog.velcdn.com/images/ice-ame/post/05184a80-2413-402e-a3db-8d7e185fa165/image.png>
>
**4.exports는 module.exports를 refer하고 있으며, shortcut에 불과하다.**
<div>
<img align =left width=50% src=https://velog.velcdn.com/images/ice-ame/post/17f435f0-6079-45cc-b37e-f223e0eb9204/image.png>
<img width =50% src=https://velog.velcdn.com/images/ice-ame/post/c14fef89-32ea-4643-8548-1959648c99a5/image.png>
</div>

<blockquote>
</blockquote>
<h3 id="require의-인수가-파일인경우">require의 인수가 파일인경우</h3>
<p>모듈을 내보낼때는 ES6처럼 명시적으로 선언하는 것이아니라 <strong>특정 변수나 그 변수의 속성으로 내보낼 객체를 세팅해줘야한다.</strong></p>
<blockquote>
</blockquote>
<p><strong>1)여러개 내보내기/불러오기</strong></p>
<blockquote>
</blockquote>
<ul>
<li><strong>내보내기</strong><ul>
<li>currency-functions.js 파일내에는 3개의 함수가있는데 2개의 함수만 다른 파일에서 접근할 수 있도록 내보내기를 함<ul>
<li><strong><code>exports</code></strong>로 세팅<pre><code class="language-js">/* currency-functions.js */
&gt;
const exchangeRate = 0.91;
&gt;
function roundTwoDecimals(amount) {
return Math.round(amount * 100) / 100;
}
&gt; 
const canadianToUs = function (canadian) {
return roundTwoDecimals(canadian * exchangeRate);
};
&gt;
function usToCanadian(us) {
return roundTwoDecimals(us / exchangeRate);
}
&gt;
exports.canadianToUs = canadianToUs; // 내보내기 1
exports.usToCanadian = usToCanadian; // 내보내기 2</code></pre>
<blockquote>
</blockquote>
</li>
</ul>
</li>
</ul>
</li>
<li><strong>불러오기</strong><ul>
<li><code>require</code>키워드를 통해 한번에불러와 변수에 할당후 객체처럼 접근할 수 있음<pre><code class="language-js">/* test-currency-functions.js */
&gt;
const currency = require(&quot;./currency-functions&quot;);
&gt;
console.log(&quot;50 Canadian dollars equals this amount of US dollars:&quot;);
console.log(currency.canadianToUs(50));
&gt; 
console.log(&quot;30 US dollars equals this amount of Canadian dollars:&quot;);
console.log(currency.usToCanadian(30));</code></pre>
<blockquote>
</blockquote>
</li>
</ul>
</li>
<li><em>2)묶어서 하나로 내보내기*</em><blockquote>
</blockquote>
</li>
<li><strong>내보내기</strong><ul>
<li>내보낼 함수들을 한객체에 넣어서 내보냄</li>
<li><strong><code>module.exports</code></strong> 사용<pre><code class="language-js">/* currency-class.js */
&gt;
const exchangeRate = 0.91;
&gt;
// 안 내보냄
function roundTwoDecimals(amount) {
return Math.round(amount * 100) / 100;
}
&gt;
// 내보내기
const obj = {};
obj.canadianToUs = function (canadian) {
return roundTwoDecimals(canadian * exchangeRate);
};
obj.usToCanadian = function (us) {
return roundTwoDecimals(us / exchangeRate);
};
module.exports = obj;</code></pre>
<blockquote>
</blockquote>
</li>
</ul>
</li>
<li><strong>불러오기</strong><ul>
<li>내보내진 객체를 require해와 변수에할당후 객체처럼 사용<pre><code class="language-js">/* test-currency-object.js */
&gt;
const currency = require(&quot;./currency-object&quot;);
&gt;
console.log(&quot;50 Canadian dollars equals this amount of US dollars:&quot;);
console.log(currency.canadianToUs(50));
&gt;
console.log(&quot;30 US dollars equals this amount of Canadian dollars:&quot;);
console.log(currency.usToCanadian(30));</code></pre>
</li>
</ul>
</li>
</ul>
<blockquote>
</blockquote>
<h3 id="require의-인수가-폴더인경우">require의 인수가 폴더인경우</h3>
<ul>
<li>require 함수의 인수에는 파일뿐만 아니라 디렉터리를 지정할 수도 있습니다.<div>
아래와같은 파일구조가있다
<img src= https://velog.velcdn.com/images/ice-ame/post/0376dae0-b9d5-4b6d-b1c5-03600f1663e4/image.png>
만약 아래처럼 모듈을 명시하지 않고 require함수호출시(인수가 폴더인경우) 해당 디렉토리의 index.js를 로드한다
<img src=https://velog.velcdn.com/images/ice-ame/post/e8d1b8a8-6ecf-4d9b-b166-9d43dbd20aaf/image.png>
이때 로드되는 index.js 내에서 calc.js과 print.js를 require하면 한번의 require로 alc.js과 print.js의 모든 기능을 사용할 수 있겠죠
<img src=https://velog.velcdn.com/images/ice-ame/post/3ecf1b6d-4476-48db-9140-f41a6b40b45f/image.png>
<img src= https://velog.velcdn.com/images/ice-ame/post/1e1f4520-4a10-402c-90fe-5fab21a04231/image.png>
<img src= https://velog.velcdn.com/images/ice-ame/post/cb3b2774-2b00-438a-8f09-3cc702a0d87a/image.png>
<img src=https://velog.velcdn.com/images/ice-ame/post/4ca0c51b-0703-49b3-815f-a4f660697fc3/image.png>
</div>

</li>
</ul>
<hr>
<h2 id="chater5-nodejs-모듈-사용해보기">chater5: Node.js 모듈 사용해보기</h2>
<hr>
<blockquote>
</blockquote>
<h3 id="nodejs-내장-모듈사용하기">NODE.js 내장 모듈사용하기</h3>
<ul>
<li>Node.js 내장 모듈 목록은 다음 링크에서 찾을 수 있습니다.<ul>
<li><a href="https://nodejs.org/dist/latest-v14.x/docs/api/">Node.js v14.17.0 Documentation</a><blockquote>
</blockquote>
</li>
</ul>
</li>
<li><em>1.불러오기*</em><img src=https://velog.velcdn.com/images/ice-ame/post/ee15a251-bea2-4d26-934d-b9356be63056/image.png>
></li>
<li><em>2.공식문서를통해 메서드 확인후 사용하기*</em></li>
</ul>
<blockquote>
</blockquote>
<h3 id="3rd-party-모듈을-사용하기">3rd-party 모듈을 사용하기</h3>
<ul>
<li>공식적으로 제공하는 빌트인 모듈(built-in module)이 아닌 모든 외부 모듈을 일컫습니다<blockquote>
</blockquote>
</li>
<li><em>1.모듈 설치하기*</em></li>
<li><em><code>npm install 모듈이름</code>*</em><blockquote>
</blockquote>
</li>
<li><em>2.불러오기*</em></li>
<li><em><code>const 변수명 = require(&#39;모듈이름&#39;)</code>*</em><blockquote>
</blockquote>
</li>
<li><em>3.해당모듈의 공식문서를이용해 사용법 확인후 사용*</em></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[데이터베이스]입문]]></title>
            <link>https://velog.io/@ice-ame/%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%B2%A0%EC%9D%B4%EC%8A%A4-%EC%9E%85%EB%AC%B8</link>
            <guid>https://velog.io/@ice-ame/%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%B2%A0%EC%9D%B4%EC%8A%A4-%EC%9E%85%EB%AC%B8</guid>
            <pubDate>Thu, 07 Apr 2022 10:22:58 GMT</pubDate>
            <description><![CDATA[<hr>
<h2 id="3-tier-architecture">3 Tier Architecture</h2>
<hr>
<blockquote>
</blockquote>
<h3 id="3-tier-architecture란">3 Tier Architecture란?</h3>
<ul>
<li>클라이언트 서버 아키텍처(=2티어 아키텍처)에 데이터 베이스가 추가된 형태
<img src="https://velog.velcdn.com/cloudflare/ice-ame/6bd27453-8538-46f7-a3be-abe47db031a8/%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-04-07%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%206.09.05.png" alt=""></li>
</ul>
<hr>
<h2 id="데이터베이스의-정의와-필요한-이유">데이터베이스의 정의와 필요한 이유</h2>
<hr>
<blockquote>
</blockquote>
<h3 id="1-데이터베이스란">1. 데이터베이스란?</h3>
<p> 데이터베이스는 여러 사람이 공유하여 사용할 목적으로 구조화해 통합,관리하는 데이터의 집합이다. 일종의 데이터 저장 창고역할을 한다</p>
<blockquote>
</blockquote>
<h3 id="2-데이터베이스는-왜-필요한가">2. 데이터베이스는 왜 필요한가?</h3>
<ul>
<li>자바스크립트에서 변수를 만들어 저장한 경우, 프로그램이 종료될 때 해당 프로그램이 사용하던 데이터도 사라진다 =&gt;( 데이터가 프로그램의 실행에 의존한다)</li>
<li>파일에 데이터를 저장하는 방식에도 한계가 존재한다<ul>
<li>데이터가 필요할 때마다 전체 파일을 매번 읽어야 합니다. 파일의 크기가 커질수록 이 작업은 버겁고, 비효율적이어서 File I/O 방식의 큰 단점입니다.</li>
<li>파일이 손상되거나 여러 개의 파일들을 동시에 다뤄야 하거나 하는 등 복잡하고 데이터량이 많아질수록 데이터를 불러들이는 작업이 점점 힘들어집니다.</li>
</ul>
</li>
</ul>
<blockquote>
</blockquote>
<h3 id="3데이터베이스의-트랜잭션과-그-특성">3.데이터베이스의 트랜잭션과 그 특성</h3>
<p><strong>1)데이터 베이스의 트랜잭션</strong></p>
<ul>
<li>트랜잭션이란 여러개의 작업을 하나로 묶은 실행 유닛이다.<blockquote>
</blockquote>
</li>
<li><em>2)데이터베이스의 트랜잭션의 특성*</em></li>
<li><strong>Atomicity(원자성)</strong><ul>
<li>각 트랜잭션은 하나의 특정 작업으로 시작을 해 묶여 있는 모든 작업을 다 완료해야 정상적으로 종료합니다
작업이 하나라도 실패를 하게 되면 트랜잭션도 실패이고, 모든 작업이 성공적이면 트랜잭션 또한 성공입니다.   성공 또는 실패 라는 두 개의 결과만 존재하는 트랜잭션은, 미완료된 작업 없이 모든 작업을 성공해야 합니다.</li>
</ul>
</li>
<li><strong>Consistency(일관성)</strong><ul>
<li>하나의 트랜잭션 이전과 이후, 데이터베이스의 상태는 이전과 같이 유효해    야 합니다 .
트랜잭션이 일어난 이후의 데이터베이스는 데이터베이스의 제약이나 규칙을     만족해야 한다는 뜻입니다.
예를 들어 &#39;모든 고객은 반드시 이름을 가지고 있어야 한다&#39;는 데이터베이스의 제약이 있다고 가정하겠습니다.
다음과 같은 트랜잭션은 Consistency(일관성)를 위반합니다:</li>
</ul>
</li>
<li><em>!!이름 없는 새로운 고객을 추가하는 쿼리!!
!!기존 고객의 이름을 삭제하는 쿼리!!*</em></li>
<li><strong>Isolation(격리성, 고립성)</strong><ul>
<li>모든 트랜잭션은 다른 트랜잭션으로부터 독립되어야 한다</li>
</ul>
</li>
<li><strong>Durability(지속성)</strong><ul>
<li>Durability(지속성)는 하나의 트랜잭션이 성공적으로 수행되든 아니든, 해당 기록은 영구적이어야 한다는 뜻입니다.</li>
</ul>
</li>
</ul>
<hr>
<h2 id="데이터베이스의-종류">데이터베이스의 종류</h2>
<hr>
<blockquote>
</blockquote>
<h3 id="1-sql-구조화-쿼리언어">1. SQL (구조화 쿼리언어)</h3>
<ul>
<li>SQL(Structuerd Query Lanagauage)이란 데이터베이스와 대화하기위해 특별히 디자인된 언어라고생각하면 된다</li>
<li>데이터가 구조화된(structured) 테이블을 사용하는 데이터베이스에서 활용할 수 있습니다.(마치 엑셀처럼)</li>
<li>데이터베이스 세계에서 SQL은 데이터베이스 종류를 SQL이라는 언어 단위로 분류할 정도로 중요한 자리를 차지하고 있습니다.</li>
</ul>
<blockquote>
</blockquote>
<h3 id="2-데이터베이스-종류와-선택">2. 데이터베이스 종류와 선택</h3>
<ul>
<li>데이터베이스는 크게 두가지로 구분한다 
Relational(관계형데이터베이스) vs   Non-Relational(비 관계형 데이터베이스)
SQL기반                    vs   Non-SQL기반<blockquote>
</blockquote>
</li>
<li><em>1)Relational(관계형데이터베이스)*</em></li>
<li>SQL 기반이다</li>
<li>대표적인 소프트웨어로 MySQL, Oracle, SQLite, PostgreSQL 등이    있고 모두 sql(언어)를통해 명령 가능하다</li>
<li>관계형 데이터베이스에서는** 테이블의 구조와 데이터 타입 등을 사전에 정의하고**, 테이블에 정의된 내용에 알맞은 형태의 데이터만 삽입할 수 있습니다<ul>
<li>특정한 형식을 지키기 때문에, 데이터를 정확히 입력했다면 데이터를 사용할 때에는 매우 수월합니다 </li>
</ul>
</li>
<li>행(row)과 열(column)로 구성된 테이블에 데이터를 저장합니다. 각 열은 하나의 속성에 대한 정보를 저장하고, 행에는 각 열의 데이터 형식에 맞는 데이터가 저장됩니다.</li>
<li>관계형 데이터베이스에서는 SQL을 활용해 원하는 정보를 쿼리할 수 있습니다. 이 말은 관계형 데이터베이스에서는 <strong>스키마가 뚜렷하게 보인다</strong>는 말과 같습니다.<ul>
<li>다시 말해, 관계형 데이터베이스에서는 테이블 간의 관계를 직관적으로 파악할 수 있습니다.<blockquote>
</blockquote>
</li>
</ul>
</li>
<li><em>2) Non-Relational(비 관계형 데이터베이스)*</em></li>
<li>NOSQL 로데이터를 다룬다</li>
<li>대표적으로 몽고DB, Casandra 등이 있습니다.</li>
<li>데이터의 구조가 고정되어있지 않다</li>
<li>테이블을 사용하지 않고 데이터를 다른 형태로 저장합니다<ul>
<li>Key-Value 타입 </li>
<li>문서형(Document) 데이터베이스</li>
<li>Wide-Column 데이터베이스</li>
<li>그래프(Graph) 데이터베이스
(하나하나의 특징까지는 지금으로선 알 필요가 없을듯 하다)<blockquote>
</blockquote>
</li>
</ul>
</li>
<li><em>3)SQL과 NoSQL 중에서 어떤 것을 사용해야 하나요?*</em>
평범한 프로젝트 라면, 거의 모든 경우SQL로도 다 커버가 가능하다
NOSQL은 특별한경우, 특별한 이슈에 대응하기에 좋은 DB다, 시작은 SQL로  나중에 규모가 커진다면
그떄 NOSQL을 고민해도 좋을 거 같다<blockquote>
</blockquote>
</li>
<li><em>참고1.*</em></li>
<li>SQL 기반의 관계형 데이터베이스를 사용하는 케이스<ul>
<li>데이터베이스의 ACID 성질을 준수해야 하는 경우
 전자 상거래를 비롯한 모든 금융 서비스를 위한 소프트웨어 개발 같은경우</li>
<li>소프트웨어에 사용되는 데이터가 구조적이고 일관적인 경우</li>
</ul>
</li>
<li>NoSQL 기반의 비관계형 데이터베이스를 사용하는 케이스<ul>
<li>데이터의 구조가 거의 또는 전혀 없는 대용량의 데이터를 저장하는 경우</li>
<li>클라우드 컴퓨팅 및 저장 공간을 최대한 활용하는 경우</li>
<li>빠르게 서비스를 구축하는 과정에서 데이터 구조를 자주 업데이트하는 경우<blockquote>
</blockquote>
</li>
</ul>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[React] 데이터 흐름의 이해와 비동기 요청처리]]></title>
            <link>https://velog.io/@ice-ame/React-%EB%8D%B0%EC%9D%B4%ED%84%B0-%ED%9D%90%EB%A6%84%EC%9D%98-%EC%9D%B4%ED%95%B4%EC%99%80-%EB%B9%84%EB%8F%99%EA%B8%B0-%EC%9A%94%EC%B2%AD%EC%B2%98%EB%A6%AC</link>
            <guid>https://velog.io/@ice-ame/React-%EB%8D%B0%EC%9D%B4%ED%84%B0-%ED%9D%90%EB%A6%84%EC%9D%98-%EC%9D%B4%ED%95%B4%EC%99%80-%EB%B9%84%EB%8F%99%EA%B8%B0-%EC%9A%94%EC%B2%AD%EC%B2%98%EB%A6%AC</guid>
            <pubDate>Mon, 04 Apr 2022 17:13:22 GMT</pubDate>
            <description><![CDATA[<hr>
<h2 id="react-데이터-흐름">React 데이터 흐름</h2>
<hr>
<blockquote>
</blockquote>
<h3 id="리엑트의-데이터는-아래로-흐릅니다">리엑트의 데이터는 아래로 흐릅니다</h3>
<ul>
<li>리엑트의 각 컴포넌트는 데이터를 부모로부터 전달 받습니다(데이터 흐름이 하향식(top-down)임을 의미합니다.) 또 컴포넌트는 props를 통해 전달받은 데이터가 어디서 왔는지 전혀 알지 못합니다.</li>
<li>어떤 데이터를 같이 공유하고 있는 상황에, 하위 컴포넌트(NewTweetForm)에서의 클릭 이벤트가, 부모의 상태를 바꾸어야만 하는 상황이 있다면, 이를 어떻게 해결할 수 있을까요? 
이를 해결할 수 있는 키워드는 바로 <strong>&quot;State 끌어올리기(Lifting state up)&quot;</strong> 입니다.</li>
</ul>
<blockquote>
</blockquote>
<h3 id="상태-끌어올리기">상태 끌어올리기</h3>
<ul>
<li>하위 컴포넌트에서의 어떤 이벤트로 인해 상위 컴포넌트의 상태가 바뀌는 것은 마치 &quot;역방향 데이터 흐름&quot;과 같이 조금 이상하게 들릴 수 있습니다. React가 제시하는 해결책은 다음과 같습니다.</li>
<li>상위 컴포넌트의 &quot;상태를 변경하는 함수&quot; 그 자체를 하위 컴포넌트로 전달하고, 이 함수를 하위 컴포넌트가 실행한다. 이것을 상태 끌어올리기라고 한다</li>
</ul>
<hr>
<h2 id="effect-hook">Effect Hook</h2>
<hr>
<blockquote>
</blockquote>
<h3 id="side-effect부수효과">side Effect(부수효과)</h3>
<ul>
<li>함수 내에서 어떤 구현이 함수 외부에 영향을 끼치는 경우 해당 함수는 Side Effect가 있다고 이야기합니다.<pre><code class="language-js">let foo = &#39;hello&#39;;
&gt;
function bar() {
foo = &#39;world&#39;;
}
&gt;
bar(); // bar는 Side Effect를 발생시킵니다!</code></pre>
</li>
</ul>
<blockquote>
</blockquote>
<h3 id="pure-function순수-함수">Pure Function(순수 함수)</h3>
<ul>
<li>순수 함수란, 오직 함수의 입력만이 함수의 결과에 영향을 주는 함수를 의미합니다. 함수의 입력이 아닌 다른 값이 함수의 결과에 영향을 미치는 경우, 순수 함수라고 부를 수 없습니다. 또한 순수 함수는, 입력으로 전달된 값을 수정하지 않습니다.</li>
<li>순수 함수에는 네트워크 요청과 같은 Side Effect가 없습니다. </li>
<li>어떠한 전달 인자가 주어질 경우, 항상 똑같은 값이 리턴됨을 보장합니다. 그래서 예측 가능한 함수이기도 합니다.<pre><code class="language-js">function upper(str) {
return str.toUpperCase(); // toUpperCase 메소드는 원본을 수정하지 않습니다 (Immutable)
}
&gt;
upper(&#39;hello&#39;) // &#39;HELLO&#39;</code></pre>
</li>
</ul>
<blockquote>
</blockquote>
<h3 id="react의-함수-컴포넌트">React의 함수 컴포넌트</h3>
<ul>
<li>우리가 앞서 배운 React의 함수 컴포넌트는, props가 입력으로, JSX Element가 출력으로 나갑니다. 여기에는 그 어떤 Side Effect도 없으며, 순수 함수로 작동합니다<pre><code class="language-jsx">function SingleTweet({ writer, body, createdAt }) {
return &lt;div&gt;
  &lt;div&gt;{writer}&lt;/div&gt;
  &lt;div&gt;{createdAt}&lt;/div&gt;
  &lt;div&gt;{body}&lt;/div&gt;
&lt;/div&gt;
}</code></pre>
</li>
<li>하지만 보통 React 애플리케이션을 작성할 때에는, AJAX 요청이 필요하거나, LocalStorage 또는 타이머와 같은 React와 상관없는 API를 사용하는 경우가 발생할 수 있습니다. 또 어떤 이벤트로인해 side Effect를 만드는 경우도 있습니다</li>
<li>React는 Side Effect를 다루기 위한 Hook인 Effect Hook을 제공합니다.</li>
</ul>
<blockquote>
</blockquote>
<h3 id="effect-hook-1">Effect Hook</h3>
<ul>
<li>useEffect는 컴포넌트 내에서 Side effect를 처리할 수 있게 하는 Hook 입니다.(import해 쓰면 됨)</li>
<li>useEffect의 첫 번째 인자는 함수입니다. 해당 함수 내에서 side effect를 실행하면 됩니다. </li>
<li>useEffect는** 1)컴포넌트 생성후 처음 화면 렌더링시  ,2)컴포넌트에 새로은 props가 전달되며 렌더링시,3)컴포넌트에 상태가 바뀌며 렌더링시 실행된다**</li>
<li>최상위에서만 Hook을 호출해야합니다</li>
<li>React 함수 내에서 Hook을 호출합니다.<img src=https://media.vlpt.us/images/ice-ame/post/9fe94fd4-8267-4534-8747-03d4930d8a55/%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-04-05%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%201.39.33.png>
></li>
<li><em>1.조건부 side effectc 처리하기*</em><pre><code class="language-jsx">useEffect(함수, [종속성1, 종속성2, ...])</code></pre>
</li>
<li>배열 내의 어떤 값이 변할 때에만, (effect가 발생하는) 함수가 실행됩니다</li>
<li>ajax요청으로 어떤값이 변할때마다 처리해야하는 side effect를 처리할떄 사용<blockquote>
</blockquote>
</li>
<li><em>2.단 한 번만 실행되는 Effect 함수*</em><pre><code class="language-jsx">useEffect(함수, [])</code></pre>
</li>
<li>컴포넌트가 처음 생성될 때만 effect 함수가 실행됩니다.<ul>
<li>대표적으로 처음 단 한 번, 외부 API를 통해 리소스를 받아오고 더 이상 API 호출이 필요하지 않을 때에 사용할 수 있습니다.</li>
</ul>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Linux]심화]]></title>
            <link>https://velog.io/@ice-ame/Linux%EC%8B%AC%ED%99%94</link>
            <guid>https://velog.io/@ice-ame/Linux%EC%8B%AC%ED%99%94</guid>
            <pubDate>Mon, 04 Apr 2022 12:54:03 GMT</pubDate>
            <description><![CDATA[<hr>
<h2 id="폴더와-파일에-대한-사용권한">폴더와 파일에 대한 사용권한</h2>
<hr>
<blockquote>
</blockquote>
<ul>
<li>Linux에서 사용하는 폴더와 파일에는 권한이 있습니다. 그리고 그 권한은 읽기(Read), 쓰기(Write), 실행(Execute)으로 나뉩니다.<h3 id="확인방법">확인방법</h3>
</li>
<li><em>1. 명령어 <code>ls -l</code>*</em>
<img src="https://media.vlpt.us/images/ice-ame/post/d6b15aa8-5fee-43f2-8429-7f8c3b0c2a1b/%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-04-04%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%204.15.09.png" alt=""></li>
<li>맨앞에 d가붙으면 폴더/-이면 파일</li>
<li>r, w, x는 각각 read permission, write permission, execute permission으로 읽기 권한, 쓰기 권한, 실행 권한을 나타냅니다.<ul>
<li>읽기 권한(r): 파일읽기
파일에서 읽기 권한 =&gt; 파일을 복사 및 읽기가 가능
디렉토리에서 읽기 권한 =&gt; 디렉토리 읽기(ls)명령어 실행 가능</li>
<li>실행 권한(x)
디렉토리에서 실행권한=&gt; 접근권한의 여부를 뜻한다 cd명령어 사용가능</li>
</ul>
</li>
<li>3번에 걸쳐 나타나는 이유는 사용자와 그룹, 나머지에 대한 권한을 표시하기 때문입니다<blockquote>
</blockquote>
<img src="https://media.vlpt.us/images/ice-ame/post/6daeff24-766f-42cd-94ff-b043a2913ddd/%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-04-04%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%204.18.23.png" alt=""></li>
<li><code>user</code>
user는 파일의 소유자입니다. 기본적으로 파일을 만든 사람이 소유자가 됩니다. 따라서 user를 소유자라고 하기도 합니다.</li>
<li><code>group</code>
group에는 여러 user가 포함될 수 있습니다. 그룹에 속한 모든 user는 파일에 대한 동일한 group 액세스 권한을 갖습니다. 많은 사람이 파일에 액세스해야 하는 프로젝트가 있다고 가정합니다. 각 user에게 일일이 권한을 할당하는 대신에 모든 user를 group에 추가하고, 파일에 group 권한을 할당할 수 있습니다.</li>
<li><code>other</code>
파일에 대한 액세스 권한이 있는 다른 user입니다. 파일을 만들지 않은 다른 모든 user를 의미합니다. 따라서 other 권한을 설정하면, 해당 권한을 global 권한 설정이라고 볼 수도 있습니다.</li>
</ul>
<blockquote>
</blockquote>
<h3 id="변경방법">변경방법</h3>
<ul>
<li>OS에 로그인한 사용자와, 폴더나 파일의 소유자가 <strong>같을 경우</strong>에 <strong>명령어 chmod</strong> 로 폴더나 파일의 권한을 변경할 수 있습니다</li>
<li>OS에 로그인한 사용자와, 폴더나 파일의 소유자가 <strong>다를 경우</strong>에는 관리자 권한을 획득하는** 명령어 sudo** 를 이용해 폴더나 파일의 권한을 변경할 수 있습니다.<blockquote>
</blockquote>
</li>
<li><em>1. Symbolic method 변경방식*</em><div>
<img width =60% src=https://media.vlpt.us/images/ice-ame/post/ed71c2bf-90e6-4578-92a1-8b7494a4a36e/%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-04-04%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%204.33.07.png>
<img src=https://media.vlpt.us/images/ice-ame/post/9724326b-047f-40a3-8767-98cd0b98062a/%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-04-04%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%204.33.59.png>
<img src=https://media.vlpt.us/images/ice-ame/post/9ae6e554-73a1-4df7-9713-920346e150f7/%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-04-04%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%204.34.10.png>
</div>
></li>
<li><em>2. Absolute form 변경방식*</em><div>
<img align =left width =50% src =https://media.vlpt.us/images/ice-ame/post/a388c200-3bff-4683-9a8c-7a7875bc1067/%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-04-04%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%204.38.30.png>
<img algin =right width=50% src=https://media.vlpt.us/images/ice-ame/post/ed1b45ee-2a11-4c27-8b0e-88753bd10dcc/%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-04-04%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%204.39.09.png>
<img src=https://media.vlpt.us/images/ice-ame/post/1c51eb4b-abe6-4685-b6f7-3525fde4f8cb/%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-04-04%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%204.41.34.png>
</div>

</li>
</ul>
<hr>
<h2 id="환경변수">환경변수</h2>
<hr>
<blockquote>
</blockquote>
<h3 id="환경변수란">환경변수란?</h3>
<ul>
<li>운영체제가 굴러가는데 필요한 동적인값(변수)</li>
<li>환경변수를 이용해 API key, DB password와 같이 민감한 정보를 저장하고 관리할 수 있습니다. 그뿐만 아니라 서로 다른 PC 또는 여러 .env 파일에서, 같은 변수 이름에 다른 값을 할당할 수 있습니다.</li>
</ul>
<blockquote>
</blockquote>
<h3 id="export-환경변수-접근--환경변수-임시-적용">export: 환경변수 접근 &amp;&amp; 환경변수 임시 적용**</h3>
<ul>
<li><strong>Linux 기반의 운영체제의 PC에는 시스템 자체에 전역변수를 설정할 수 있습니다. 그리고 시스템에 설정한 전역변수를 환경변수라고 합니다.</strong> </li>
<li>Linux 운영체제에는 이미 많은 환경변수가 설정되어 있습니다. 터미널에 명령어 export 를 입력해, 기록된 환경변수를 확인할 수 있습니다.<img src=https://media.vlpt.us/images/ice-ame/post/f0184ba9-741b-4a27-9d51-2ca832e62e73/%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-04-04%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%207.25.33.png>
<br></li>
<li>명령어 export 를 이용하면, 새로운 환경변수를 추가할 수 있습니다<ul>
<li>명령어 export 로 적용한 환경변수는 현재 사용 중인 터미널에서만 임시로 사용이 가능합니다<img src=https://media.vlpt.us/images/ice-ame/post/223cac85-5bb4-469c-9ed1-fbb8e0c1dcc9/%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-04-04%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%207.23.39.png>
<br></li>
</ul>
</li>
<li>명령어 echo 와 함께 환경변수를 입력하면, 환경변수의 값을 확인할 수 있습니다. <img src=https://media.vlpt.us/images/ice-ame/post/72c6e2a5-674b-4e48-9478-ac4f5f29dce0/%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-04-04%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%207.24.17.png>

</li>
</ul>
<blockquote>
</blockquote>
<h3 id="dotenv-자바스크립트에서-환경변수에-접근">dotenv: 자바스크립트에서 환경변수에 접근</h3>
<p><strong>1.개요</strong></p>
<ul>
<li><code>npm 모듈 dotenv</code>를 사용하면, 자바스크립트에서 환경변수를 사용할 수 있습니다<ul>
<li>npm 모듈을 설치하고 사용하기 위해서, 새로운 폴더를 만들고 <code>npm init</code> 을 입력합니다.
(packgejson 생성)</li>
<li><code>npm install dotenv</code> 를 입력해 모듈을 설치합니다.
 이때 생성된 폴더는 설치할 모듈과 이름이 같아서는 안됩니다.</li>
</ul>
</li>
<li>설치한 dotenv를 이용해 환경변수에 접근할 수 있습니다<ul>
<li><code>process.env</code>=&gt;export로 확인한 내용과 동일한 내용을 객체로 출력
<img src="https://media.vlpt.us/images/ice-ame/post/47f164ec-bbbc-49bd-890c-3e665322f7af/image.png" alt=""></li>
</ul>
</li>
<li><code>.env 파일</code>을 생성하면 환경변수를 셋팅할수있다(export와 달리 영구적용)<ul>
<li>.env파일을 생성한후</li>
<li>.env 파일에 사용하고자 하는 환경변수를 입력한뒤 저장 후 사용<blockquote>
</blockquote>
</li>
</ul>
</li>
<li><em>2.실습*</em></li>
<li>아래서 실습한 방법은 CommonJs에서 dotenv를 사용하는방법이다</li>
<li>commonJs와 ES6의 차이점 <a href="https://hsp0418.tistory.com/147">여기</a> 참고<blockquote>
</blockquote>
</li>
<li><code>npm init</code> =&gt; <code>npm install dotenv</code><img src=https://media.vlpt.us/images/ice-ame/post/e71f13f2-19a8-45e1-84bb-27e7f02d6c37/%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-04-04%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%209.29.22.png>
<br></li>
<li><code>.env파일 생성</code>=&gt; <code>사용할변수 생성</code><img src=https://velog.velcdn.com/images/ice-ame/post/06b3ebf0-811e-4239-bb4c-133057c2ad26/image.png>
<br></li>
<li><code>사용하기</code><img src=https://velog.velcdn.com/images/ice-ame/post/53054f7d-7458-4b6c-9425-c6f5fc772c45/image.png>
- ```js
const dotenv= require('dotenv') //모듈불러온후 상수 dotenv에 할당
dotenc.config() //꼭해줘야함
```
>








</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[REST API &Open API & API key &postman ]]></title>
            <link>https://velog.io/@ice-ame/REST-API-Open-API-API-key-postman</link>
            <guid>https://velog.io/@ice-ame/REST-API-Open-API-API-key-postman</guid>
            <pubDate>Sat, 02 Apr 2022 09:04:37 GMT</pubDate>
            <description><![CDATA[<hr>
<h2 id="rest-api">REST API</h2>
<hr>
<blockquote>
</blockquote>
<h3 id="rest-api란">REST API란?</h3>
<ul>
<li>웹 애플리케이션에서는 HTTP 메서드를 이용해 서버와 통신합니다. GET을 통해 웹 페이지나 데이터를 요청하고, POST로 새로운 글이나 데이터를 전송하거나 DELETE로 저장된 글이나 데이터를 삭제할 수 있습니다.</li>
<li>REST(Representational State Transfer) API는 웹에서 사용되는 데이터나 자원(Resource)을 HTTP URI로 표현하고, HTTP 프로토콜을 통해 요청과 응답을 정의하는 방식이다<ul>
<li>쉽게말해 메소드와 uri를 통해 crud요청을하는거</li>
</ul>
</li>
</ul>
<blockquote>
</blockquote>
<h3 id="좋은-rest-api를-디자인하는-방법">좋은 REST API를 디자인하는 방법</h3>
<p><strong>1. HTTP 프로토콜을 사용하기</strong></p>
<blockquote>
</blockquote>
<p><strong>2. 적절한 엔드포인트사용</strong></p>
<ul>
<li>모든 자원은 개별 리소스에 맞는 엔드포인트(Endpoint)를 사용해야 한다는 것과, 요청하고 받은 자원에 대한 정보를 응답으로 전달해야 한다</li>
<li>엔드포인트 작성 시에는 동사, HTTP 메서드, 혹은 어떤 행위에 대한 단어 사용은 지양하고, <strong>리소스에 집중해 명사 형태의 단어로 작성하는 것이 바람직 방법</strong>입니다.</li>
<li>요청에 따른 응답으로 리소스를 전달할 때에도 사용한 리소스에 대한 정보와 함께 리소스 사용에 대한 성공/실패 여부를 반환해야 합니다.<blockquote>
</blockquote>
<strong>3.CRUD에 맞게 적절한 HTTP 메서드를 사용</strong></li>
<li><code>GET</code> :서버의 데이터를 변화시키지 않는 요청에 사용해야 합니다.(요청에 바디없음)</li>
<li><code>POST</code>:요청마다 새로운 리소스를 생성 (요청에 바디가있음)</li>
<li><code>PUT</code>:요청마다 같은 리소스를 반환합니다. 이렇게 매 요청마다 같은 리소스를 반환하는 특징을 멱등(idempotent)하다고 합니다. 그렇기 때문에 멱등성을 가지는 메서드 PUT과 그렇지 않은 POST는 구분하여 사용해야 합니다.</li>
<li>PUT 과 PATCH 도 구분하여 사용해야 합니다. PUT은 교체, PATCH는 수정의 용도로 사용합니다.</li>
<li><code>delete</code>: 내용은 엔드포인트로 하는게 더 낫다(물론 바디사용가능)
<img src="https://media.vlpt.us/images/ice-ame/post/95349404-6bae-458b-b5e2-277c5eb37a92/%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-04-02%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%205.52.38.png" alt=""></li>
</ul>
<blockquote>
</blockquote>
<h3 id="좀더-공부할-레퍼런스">좀더 공부할 레퍼런스</h3>
<ul>
<li><a href="https://blog.restcase.com/5-basic-rest-api-design-guidelines/">5가지의 기본적인 REST API 디자인 가이드</a></li>
<li>엔드포인트/Query Paramete</li>
</ul>
<hr>
<h2 id="open-api-api-key">open API &amp;API key</h2>
<hr>
<blockquote>
</blockquote>
<h3 id="open-api">open API</h3>
<p>공공데이터에 쉽게 접근할 수 있도록 정부는 OPEN API의 형태로 공고데이터를 제공하고있다
-<a href="https://www.data.go.kr/"> 공공데이터 포털</a></p>
<blockquote>
</blockquote>
<h3 id="api-key">API key</h3>
<ul>
<li>API를 이용하기 위해서는 API Key가 필요합니다.(가끔 API key가 필요하지 않은 경우도 있습니다.)</li>
<li>클라이언트의 요청에 따라 서버에서 응답한다는 말은 결국 서버를 운용하는 데에 비용이 발생하고, 따라서 서버 입장에서 아무런 조건 없이 익명의 클라이언트에게 데이터를 제공할 의무도, 이유도 없습니다. </li>
<li>로그인된 이용자에게만 자원에 접근할 수 있는 권한을 API Key의 형태로 제공하고, 데이터를 요청할 때 API key를 같이 전달해야만 원하는 응답을 받을 수 있습니다</li>
</ul>
<hr>
<h2 id="postman">postman</h2>
<hr>
<blockquote>
</blockquote>
<p>-웹 개발에서 사용하는 대표적인 클라이언트(요청의주체)는 브라우저입니다</p>
<ul>
<li>브라우저는 서버에 HTTP 요청을 보낼 수 있는 훌륭한 도구이지만, 주로 웹 페이지를 받아오는 GET 요청에 사용합니다</li>
<li>GET이 아닌 다른 요청을 보내려면, 개발자 도구의 콘솔 창에서 내장 함수 fetch를 사용해야 합니다.</li>
<li>태스트 요청을 보낼때 매번 코드를 작성하는 것 대신에, HTTP 요청을 테스트할 수 있는 다양한 도구중 postman을사용해보길 권장</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[토이]]></title>
            <link>https://velog.io/@ice-ame/%ED%86%A0%EC%9D%B4</link>
            <guid>https://velog.io/@ice-ame/%ED%86%A0%EC%9D%B4</guid>
            <pubDate>Sat, 26 Mar 2022 20:20:53 GMT</pubDate>
            <description><![CDATA[<blockquote>
</blockquote>
<ul>
<li>11번 문제 조합?<pre><code class="language-js">const powerSet = function (str) {
// 정렬
const sorted = str.split(&#39;&#39;).sort();
//[&#39;a&#39;,&#39;b&#39;,&#39;c&#39;]
&gt;
// 중복 제거
const deduplicated = sorted.reduce((acc, item) =&gt; {
  if (acc[acc.length - 1] === item) {
    return acc;
  } else {
    return acc.concat(item);
  }
});
&gt;
&gt;
&gt;
let subSets = [];
const pickOrNot = (idx, subset) =&gt; { //pickOrNot(0,&#39;&#39;) pic(1,&#39;&#39;) pic(2,&#39;&#39;)
  // base case
  if (idx === deduplicated.length) {
    // 마지막 문자까지 검토한 경우
    subSets.push(subset);
    return;
  }
  // recursive case
  // idx번째 문자가 포함되지 않는 경우
  pickOrNot(idx + 1, subset); // 
  // idx번째 문자가 포함되는 경우
  pickOrNot(idx + 1, subset + deduplicated[idx]);
};
&gt;
pickOrNot(0, &#39;&#39;);
&gt;
return subSets.sort();
};
&gt;
&gt;
// const powerSet = function (str) {
//   // TODO: 여기에 코드를 작성합니다.
//   const arr = str.split(&#39;&#39;).sort(); // 문자열을 분리해서 배열로 만들어주고 정렬해준다.
//   //[&#39;a&#39;,&#39;b&#39;,&#39;c&#39;]
//   const result = [&#39;&#39;]; // 결과가 담긴 배열 
&gt;
//   let aux = (target) =&gt; { // result에서 target을 추가한 인자들을 result에 추가해주는 함수
//     let copy = result.slice(); //[&#39;&#39;]
//     for(let el of copy) {
//       el += target;
//       result.push(el);
//     }
//   }
// //result =&gt; [&#39;&#39;]/ 
//   for(let el of arr) { // arr의 값들을 전부 넣어서 aux함수 실행 arr: [&#39;a&#39;, &#39;b&#39;, &#39;c&#39;]
//     if(result.indexOf(el) === -1) { // 중복값이아닌 경우에만 실시
//       aux(el);  
//     }
//   }
//   return result.sort(); // 결과를 정렬해서 반환 
// };</code></pre>
</li>
</ul>
<blockquote>
</blockquote>
<ul>
<li>13번 문제  bfs<pre><code class="language-js">let bfs = function (node) {
// TODO: 여기에 코드를 작성합니다.
let queue = [node];
const values = [];
while (queue.length &gt; 0) {
  const head = queue[0];
  queue = queue.slice(1);
&gt;
  values.push(head.value);
&gt;
  head.children.forEach((child) =&gt; queue.push(child));
}
return values;
};
&gt;
// 이 아래 코드는 변경하지 않아도 됩니다. 자유롭게 참고하세요.
let Node = function (value) {
this.value = value;
this.children = [];
};
&gt;
// 위 Node 객체로 구성되는 트리는 매우 단순한 형태의 트리입니다.
// membership check(중복 확인)를 따로 하지 않습니다.
Node.prototype.addChild = function (child) {
this.children.push(child);
return child;
};</code></pre>
</li>
</ul>
<blockquote>
</blockquote>
<ul>
<li>07번 dfs <pre><code class="language-js">let dfs = function (node) {
// TODO: 여기에 코드를 작성합니다.
let values = [node.value];
&gt;
node.children.forEach((n) =&gt; {
  values = values.concat(dfs(n));
});
&gt;
return values;
};
&gt;
// 이 아래 코드는 변경하지 않아도 됩니다. 자유롭게 참고하세요.
let Node = function (value) {
this.value = value;
this.children = [];
};
&gt;
// 위 Node 객체로 구성되는 트리는 매우 단순한 형태의 트리입니다.
// membership check(중복 확인)를 따로 하지 않습니다.
Node.prototype.addChild = function (child) {
this.children.push(child);
return child;
};</code></pre>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[HTTP/네트워크 ] 기초]]></title>
            <link>https://velog.io/@ice-ame/HTTP%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC-%EA%B8%B0%EC%B4%88</link>
            <guid>https://velog.io/@ice-ame/HTTP%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC-%EA%B8%B0%EC%B4%88</guid>
            <pubDate>Wed, 16 Mar 2022 18:51:19 GMT</pubDate>
            <description><![CDATA[<hr>
<h2 id="클라이언트서버">클라이언트&amp;서버</h2>
<hr>
<blockquote>
</blockquote>
<h3 id="클라이언트-서버-아키텍처">클라이언트-서버 아키텍처?</h3>
<p>인터넷 연결이 없다면 쇼핑몰 앱은 정상적으로 동작할 수 없습니다.
 상품 정보를 인터넷 어딘가에 존재하는 서버로부터 받아오기 때문</p>
<ul>
<li>클라이언트 서버 아키텍처(=2티어 아키텍처)란 리소스(앱내의 정보ex상품정보)가 존재하는 곳과 리소스를 사용하는 앱을 분리시킨 것을 말함</li>
<li>리소스를 사용하는곳 =&gt; 클라이언트 / 리소스를 제공하는곳 =&gt; 서버</li>
<li>클라이언트와 서버는 요청과 응답을 주고받는 관계입니다. 클라이언트-서버 아키텍처에서는 요청이 선행되고 그 후에 응답이 옵니다. 요청하지도 않았는데 응답이 오는 경우는 없습니다.</li>
<li>일반적으로 서버는 리소스를 전달해 주는 역할만 담당합니다<ul>
<li>소스를 저장하는 공간을 별도로 마련해 두는데 이 공간을 &quot;데이터베이스&quot;(창고역할)라고 부릅니다
(기존 2티어 아키텍처에 데이터베이스가 추가된 형태=&gt; 3티어 아키텍처)
<img src="https://images.velog.io/images/ice-ame/post/aa861b59-4c93-4cfd-852b-b61aba203dc0/%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-03-14%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.43.05.png" alt=""></li>
</ul>
</li>
</ul>
<blockquote>
</blockquote>
<h3 id="클라이언트와-서버의종류">클라이언트와 서버의종류</h3>
<ul>
<li>클라이언트는 보통 플랫폼에 따라 구분됨<ul>
<li>플랫폼=&gt; 브라우저라면 , 클라이언트=&gt;웹사이트,웹앱</li>
<li>플랫폼=&gt;스마트폰,태블릿 이라면=&gt; 클라이언트 =&gt; 앱</li>
</ul>
</li>
<li>서버는 업무에따라 종류가 달라짐<ul>
<li>파일서버 =&gt;파일제공하는앱</li>
<li>웹서버=&gt; 웹사이트에 필요로하는 정보를 제공하는 서버</li>
<li>메일서버 =&gt; 메일을 주고받을 수 있도록 도와주는 서버</li>
<li>데이터베이스=&gt; 데이터제공하는 서버
<img src="https://images.velog.io/images/ice-ame/post/994b613e-116d-438a-8177-c43031903ddc/%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-03-15%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%201.39.50.png" alt=""></li>
</ul>
</li>
</ul>
<blockquote>
</blockquote>
<h3 id="클라어언트와-서버의-통신방법과-api">클라어언트와 서버의 통신방법과 API</h3>
<p><strong>1.클라이언트와 서버의 통신방법</strong></p>
<ul>
<li><p>클라이언트-서버 아키텍처에서는 서버 마음대로 클라이언트에 리소스를 전달하지 않습니다</p>
</li>
<li><p>웹 애플리케이션 아키텍처에서는 서버가 제공하는 <code>API</code>를 통해 프로토콜(규약)에 따라 메세지를 주고 받으며 대화를 나눕니다(HTTP와 API는 아래에서 설명)</p>
</li>
<li><p>프로토콜의 종류(상식선에서만 알아두기)
<img src="https://images.velog.io/images/ice-ame/post/65567974-7c83-4d5f-a6a3-75495d259435/%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-03-14%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.55.00.png" alt=""></p>
<blockquote>
</blockquote>
<p><strong>2.API란?</strong></p>
<ul>
<li>클라이언트는 서버가 어떻게 구성되어있는지 알 방법이 없다. 서버는 클라이언트에게 리소스를 잘 활용해 올바른 요청을 하도록 인터페이스를 제공해줘야하고 이것을 <code>API</code>(** Application Programming Interface**)라고 한다.(프론트엔드 개발자가 제공된 API를 통해 서버에 어떤 요청을 할 수있는 것)</li>
<li>interface: 의사소통이 가능하도록 만들어진 접점</li>
</ul>
</li>
<li><p>즉 서버가 리소스 전달을 위한 메뉴판, 즉 API를 구축해놓아야 클라이언트가 이를 활용할 수 있습니다.</p>
</li>
</ul>
<hr>
<h2 id="브라우저의-작동원리보이지-않는곳">브라우저의 작동원리(보이지 않는곳)</h2>
<hr>
<blockquote>
</blockquote>
<h3 id="http">HTTP</h3>
<ul>
<li>HTTP는 HyperText Transfer Protocol의 줄임말로, HTML과 같은 문서를 전송하기 위한 Application Layer 프로토콜입니다. </li>
<li>인터넷에 있는 데이터를 요청할 때에는 주로 HTTP라는 프로토콜(규칙)을 사용하며, 이 HTTP의 주소(URL, URI)를 통해 요청에 접근할 수 있게 됩니다.(API서버가 적절한 URL을 제공)
<img src="https://images.velog.io/images/ice-ame/post/de7a35f5-4217-40ef-9c88-8b846c65d463/%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-03-15%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%202.00.43.png" alt=""></li>
<li>HTTP 요청에는 메소드라는 것이 존재하고, 이는 리소스를 이용해 하려는 행동에 맞게 적절하게 써야 합니다
<img src="https://images.velog.io/images/ice-ame/post/c143e4d2-ceaf-41eb-9b38-1a7d07802e04/%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-03-15%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%202.06.49.png" alt=""></li>
<li>클라이언트-서버 모델에서 클라이언트가 HTTP messages 양식에 맞춰 요청을 보내면, 서버도 HTTP messages 양식에 맞춰 응답합니다(API를 통해)</li>
<li><strong>HTTP는 특정 상태를 유지하지 않는 특징이 있습니다</strong><blockquote>
</blockquote>
<h4 id="http-messages">HTTP Messages</h4>
<img src="https://images.velog.io/images/ice-ame/post/883abd79-0532-4c57-8535-9c3bdcfd14eb/%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-03-17%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%201.08.37.png" alt=""></li>
<li>HTTP messages는 몇 줄의 텍스트 정보로 구성됩니다.</li>
<li>그러나 개발자는 이런 메시지를 직접 작성할 필요가 거의 없습니다(구성 파일, API, 기타 인터페이스에서 HTTP messages를 자동으로 완성합니다.)</li>
<li>HTTP message의 구성<ul>
<li><code>start line</code> : start line에는 요청이나 응답의 상태를 나타냅니다. 항상 첫 번째 줄에 위치합니다. 응답에서는 status line이라고 부릅니다.</li>
<li><code>HTTP headers</code> : 요청을 지정하거나, 메시지에 포함된 본문을 설명하는 헤더의 집합입니다.</li>
<li><code>empty line</code> : 헤더와 본문을 구분하는 빈 줄이 있습니다.</li>
<li><code>body</code> : 요청과 관련된 데이터나 응답과 관련된 데이터 또는 문서를 포함합니다. 요청과 응답의 유형에 따라 선택적으로 사용합니다.</li>
</ul>
</li>
<li>HTTP로 클라이언트와 서버가 통신을 주고받는 과정에서, HTTP가 클라이언트나 서버의 상태를 확인하지 않습니다(stateless=&gt;무상태성이 HTTP의 큰 특징중 하나이다)<blockquote>
</blockquote>
</li>
<li><em>1.Requests(요청) 부분*</em></li>
<li><em>1)start line부분*</em></li>
<li>수행할 작업(GET, PUT, POST 등)이나 방식(HEAD or OPTIONS) =&gt; HTTP method 를 나타냄</li>
<li>요청 형식( HTTP method 마다 다릅니다)<ul>
<li>origin 형식 : ?와 쿼리 문자열이 붙는 절대 경로입니다. POST,GET, HEAD, OPTIONS 등의 method와 함께 사용합니다.
<code>POST / HTTP 1.1</code>
<code>GET /background.png HTTP/1.0</code>
<code>HEAD /test.html?query=alibaba HTTP/1.1</code>
<code>OPTIONS /anypage.html HTTP/1.0</code><ul>
<li>absolute 형식 : 완전한 URL 형식으로, 프록시에 연결하는 경우 대부분 GET method와 함께 사용합니다.
<code>GET http://developer.mozilla.org/en-US/docs/Web/HTTP/Messages HTTP/1.1</code></li>
</ul>
</li>
<li>authority 형식 : 도메인 이름과 포트 번호로 이루어진 URL의 authority component 입니다. HTTP 터널을 구축하는 경우, CONNECT와 함께 사용할 수 있습니다
<code>CONNECT developer.mozilla.org:80 HTTP/1.1</code></li>
<li>asterisk 형식 : OPTIONS 와 함께 별표(*) 하나로 서버 전체를 표현합니다.<pre><code>OPTIONS * HTTP/1.1 </code></pre></li>
</ul>
</li>
<li>HTTP 버전에 따라 HTTP message의 구조가 달라집니다. 따라서 start line에 HTTP 버전을 함께 입력합니다.
<img src="https://images.velog.io/images/ice-ame/post/6364510f-e825-4176-9f42-f1d00fa6dc12/%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-03-17%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%202.32.00.png" alt=""><blockquote>
</blockquote>
</li>
<li><em>2)Headers*</em>
<img src="https://images.velog.io/images/ice-ame/post/4b38a1ba-2626-4b91-92b5-2cc69fb351bd/%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-03-17%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%202.00.56.png" alt=""></li>
<li><code>Request headers</code> : fetch를 통해 가져올 리소스나 클라이언트 자체에 대한 자세한 정보를 포함하는 헤더를 의미합니다. User-Agent, Accept-Type, Accept-Language과 같은 헤더는 요청을 보다 구체화합니다. Referer처럼 컨텍스트를 제공하거나 If-None과 같이 조건에 따라 제약을 추가할 수 있습니다.</li>
<li><code>General headers</code> : 메시지 전체에 적용되는 헤더로, body를 통해 전송되는 데이터와는 관련이 없는 헤더입니다.</li>
<li><code>Representation headers</code> : 이전에는 Entity headers로 불렀으며, body에 담긴 리소스의 정보(콘텐츠 길이, MIME 타입 등)를 포함하는 헤더입니다.<blockquote>
</blockquote>
</li>
<li><strong>3)Body*</strong></li>
<li>구조의 마지막에 위치하며 모든 요청에 body가 필요한 것은 아니다</li>
<li>GET, HEAD, DELETE, OPTIONS처럼 서버에 리소스를 요청하는 경우에는 본문이 필요하지 않습니다</li>
<li>POST나 PUT과 같은 일부 요청은 데이터를 업데이트하기 위해 사용합니다.</li>
<li>두종료로 나눌 수 있다<ul>
<li>Single-resource bodies(단일-리소스 본문) : 헤더 두 개(Content-Type과 Content-Length)로 정의된 단일 파일로 구성됩니다.</li>
<li>Multiple-resource bodies(다중-리소스 본문) : 여러 파트로 구성된 본문에서는 각 파트마다 다른 정보를 지닙니다. 보통 HTML form과 관련이 있습니다<blockquote>
</blockquote>
</li>
</ul>
</li>
<li><em>2.Responses(응답) 부분*</em></li>
<li><em>1)Status line*</em></li>
<li>응답의 첫 줄은 Status line이라고 부른다 </li>
<li>Status line은 <code>HTTP/1.1 404 Not Found.</code> 처럼 생겼습니다.<ul>
<li>현재 프로토콜의 버전
(HTTP/1.1)</li>
<li>상태 코드 - 요청의 결과를 나타냅니다. 
<code>200</code> : OK, 성공적으로 응답을 마침
<code>302</code> : Found, 리다이렉트할 URL을 확인함
<code>404</code> : Not Found, 클라이언트가 잘못된 페이지를 서버에 요청하여 페이지를 찾을 수 없음
<code>406</code> : Not Acceptable, 클라이언트가 응답 코드를 받을 수 없음
<code>500</code> : Internal Server Error, 서버에서 에러가 발생함</li>
<li>상태 텍스트 - 상태 코드에 대한 설명
(Not Found)
<img src="https://images.velog.io/images/ice-ame/post/058c64ed-5439-41e1-8db1-b88cfd9a4964/%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-03-17%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%202.33.58.png" alt=""><blockquote>
</blockquote>
</li>
</ul>
</li>
<li><em>2)Headers*</em></li>
<li>요청 헤더와 동일한 구조를 가지고 있습니다</li>
<li>General headers : 메시지 전체에 적용되는 헤더로, body를 통해 전송되는 데이터와는 관련이 없는 헤더입니다.</li>
<li>Response headers : 위치 또는 서버 자체에 대한 정보(이름, 버전 등)와 같이 응답에 대한 부가적인 정보를 갖는 헤더로, Vary, Accept-Ranges와 같이 상태 줄에 넣기에는 공간이 부족했던 추가 정보를 제공합니다.</li>
<li>Representation headers : 이전에는 Entity headers로 불렀으며, body에 담긴 리소스의 정보(콘텐츠 길이, MIME 타입 등)를 포함하는 헤더입니다.
<img src="https://images.velog.io/images/ice-ame/post/088aaf5a-7a4d-4df8-ba08-bead3fa48896/%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-03-17%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%202.12.25.png" alt=""><blockquote>
</blockquote>
</li>
<li><em>3)Body*</em></li>
<li>구조의 마지막에 위치하며 모든 응답에 body가 필요하지는 않습니다. 201, 204와 같은 상태 코드를 가지는 응답에는 본문이 필요하지 않습니다</li>
<li>두 종류로 나눌 수 있습니다</li>
<li><code>Single-resource bodies(단일-리소스 본문)</code> :<ul>
<li>길이가 알려진 단일-리소스 본문은 두 개의 헤더(Content-Type, Content-Length)로 정의합니다.</li>
<li>길이를 모르는 단일 파일로 구성된 단일-리소스 본문은 Transfer-Encoding이 chunked 로 설정되어 있으며, 파일은 chunk로 나뉘어 인코딩되어 있습니다.</li>
</ul>
</li>
<li><code>Multiple-resource bodies(다중-리소스 본문)</code> : 서로 다른 정보를 담고 있는 body입니다.<blockquote>
</blockquote>
<h4 id="http-요청-메서드">HTTP 요청 메서드</h4>
</li>
<li><code>GET</code>: 메서드는 특정 리소스의 표시를 요청합니다. GET을 사용하는 요청은 오직 데이터를 받기만 합니다.</li>
<li><code>HEAD</code>: 메서드는 GET 메서드의 요청과 동일한 응답을 요구하지만, 응답 본문을 포함하지 않습니다.</li>
<li><code>POST</code>: 메서드는 특정 리소스에 엔티티를 제출할 때 쓰입니다. 이는 종종 서버의 상태의 변화나 부작용을 일으킵니다.(새로운 리소스를 추가,생성하고자 할때)</li>
<li><code>PUT</code>:메서드는 목적 리소스 모든 현재 표시를 요청 payload로 바꿉니다.</li>
<li><code>DELETE</code>: 메서드는 특정 리소스를 삭제합니다.</li>
<li><code>CONNECT</code>: 메서드는 목적 리소스로 식별되는 서버로의 터널을 맺습니다.</li>
<li><code>OPTIONS</code>: 메서드는 목적 리소스의 통신을 설정하는 데 쓰입니다.</li>
<li><code>TRACE</code>: 메서드는 목적 리소스의 경로를 따라 메시지 loop-back 테스트를 합니다.</li>
<li><code>PATCH</code>: 메서드는 리소스의 부분만을 수정하는 데 쓰입니다.</li>
</ul>
<blockquote>
</blockquote>
<h3 id="url과-uri">URL과 URI</h3>
<ul>
<li>브라우저의 주소창에 이 URL을 입력하면, 서버가 제공되는 환경에 존재하는 파일의 위치를 나타냅니다</li>
<li>CLI 환경에서 폴더와 파일의 위치를 찾아 이동하듯이, 슬래시(/)를 이용해 서버의 폴더에 진입하거나 파일을 요청할 수 있습니다(기본적인 보안의 일환으로 외부에서 직접 접근이 가능한 경우는 거의 없습니다)</li>
<li><em>1. URL*</em></li>
<li>URL(Uniform Resource Locator) 네트워크 상에서 웹 페이지, 이미지, 동영상 등의 파일이 위치한 정보를 나타냅니다.</li>
<li>URL은 scheme, hosts, url-path로 구분할 수 있습니다<ul>
<li>scheme은 통신 방식(프로토콜)을 결정합니다(일반적인 웹 브라우저에서는 http(s)를 사용합니다)</li>
<li>hosts는 웹 서버의 이름이나 도메인, IP를 사용하며 주소를 나타냅니다</li>
<li>url-path는 웹 서버에서 지정한 루트 디렉토리부터 시작하여 웹 페이지, 이미지, 동영상 등이 위치한 경로와 파일명을 나타냅니다.
<img src="https://images.velog.io/images/ice-ame/post/b329e781-93be-4cb3-a0b9-181a2b9622ee/%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-03-15%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%202.28.15.png" alt=""><blockquote>
</blockquote>
</li>
</ul>
</li>
<li><em>2.URI*</em></li>
<li>브라우저의 검색창을 클릭하면 나타나는 주소가 URI입니다. URI는 URL을 포함하는 상위개념입니다</li>
<li>URI( Uniform Resource Identifier)는 일반적으로 URL의 기본 요소인 scheme, hosts, url-path에 더해 query, bookmark를 포함합니다.
<img src="https://images.velog.io/images/ice-ame/post/1566a19c-d4a5-4d6c-bd19-1660dab40bc5/%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-03-15%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%202.38.42.png" alt=""></li>
</ul>
<blockquote>
</blockquote>
<h3 id="ip와-port">IP와 Port</h3>
<p><strong>1.IP</strong></p>
<ul>
<li>네트워크에 연결된 특정 PC의 주소를 나타내는 체계를 IP address(Internet Protocol address, IP 주소)라고 하고 그 주소에 진입할 수 있는 정해진 통로를 prot라고 함</li>
<li>인터넷에 연결된 모든 PC는 IP 주소체계를 따라 네 덩이의 숫자로 구분되고 이를 <strong>IPv4</strong>( Internet Protocol version 4)라고 한다.<ul>
<li>IPv4는 각 덩어리마다 0부터 255까지 나타낼 수 있습니다</li>
<li><strong>localhost, 127.0.0.1: 현재 사용 중인 로컬 PC를 지칭합니다.</strong></li>
<li><strong>0.0.0.0, 255.255.255.255 : broadcast address, 로컬 네트워크에 접속된 모든 장치와 소통하는 주소입니다.</strong> 서버에서 접근 가능 IP 주소를 broadcast address 로 지정하면, 모든 기기에서 서버에 접근할 수 있습니다.</li>
</ul>
</li>
<li>개인 PC의 보급으로 전 세계의 누구나 PC를 이용해 인터넷에 접속하고, 각종 서비스를 위해 서버를 생산하면서 IPv4로 할당할 수 있는 PC가 한계를 넘어서게 되었습니다. 이를 위해 세상에 나오게 된 것이 <strong>IPv6(IP version 6)</strong> 입니다. IPv6는 표기법을 달리 책정하여 2^(128)개의 IP 주소를 표현할 수 있습니다.<blockquote>
</blockquote>
</li>
<li><em>2.PORT*</em>
<img src="https://images.velog.io/images/ice-ame/post/55a727cc-c9f0-4072-b8f3-6f841a58edd3/%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-03-15%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%203.03.33.png" alt=""></li>
<li>터미널에서 리액트를 실행하면 나타나는 화면에는, 로컬 PC의 IP 주소인 127.0.0.1 뒤에 :3000과 같은 숫자가 표현됩니다. 이 숫자는 IP 주소가 가리키는 PC에 접속할 수 있는 통로(채널)을 의미합니다. 리액트를 실행했을 때에는 로컬 PC의 IP 주소로 접근하여, 3000번의 통로를 통해 실행 중인 리액트를 확인할 수 있습니다. </li>
<li>이미 사용 중인 포트는 중복해서 사용할 수 없습니다. 만약 다른 프로그램에서 3000번 포트를 사용 중이라면, 다음과 같이 다른 포트 번호로 리액트가 실행됩니다.</li>
<li><strong><em>포트 번호는 0~ 65,535 까지 사용할 수 있습니다. 그중에서 0 ~ 1024번 까지의 포트 번호는 주요 통신을 위한 규약에 따라 이미 정해져 있습니다. 반드시 알아야 할 잘 알려진 포트 번호는 다음과 같습니다</em></strong><ul>
<li>22 : SSH</li>
<li>80 : HTTP</li>
<li>443: HTTPS</li>
</ul>
</li>
</ul>
<blockquote>
</blockquote>
<h3 id="도메인과-dns">도메인과 DNS</h3>
<p><strong>1.도메인과 DNS 개요</strong></p>
<ul>
<li>DNS(Domain name system)란 사람이 기억하기 쉬운 <code>www.naver.com</code>과 같은 도메인을 컴퓨터가 이해할 수 있는 ‘125.209.222.142`으로 변환하여 
요청이 원하는 곳에 도달할 수 있도록 도와주는 시스템입니다.<ul>
<li>명령어 <code>nslookup</code>로 codestates.com 의 IP 주소를 확인할 수 있습니다
<img src="https://images.velog.io/images/ice-ame/post/fc01d1c9-e21e-42c2-832a-07a974facd2a/%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-03-15%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%203.08.25.png" alt=""></li>
</ul>
</li>
<li>네트워크 상에 존재하는 모든 PC는 IP 주소가 있습니다. 그러나 모든 IP 주소가 도메인 이름을 가지는 것은 아닙니다</li>
<li>로컬 PC를 나타내는 127.0.0.1 은 localhost 로 사용할 수 있지만, 그 외의 모든 도메인 이름은 일정 기간 동안 대여하여 사용합니다. </li>
<li>브라우저의 검색창에 도메인 이름을 입력하여 해당 사이트로 이동하기 위해서는, 해당 도메인 이름과 매칭된 IP 주소를 확인하는 작업이 반드시 필요합니다. 네트워크에는 이것을 위한 서버가 별도로 있습니다.</li>
</ul>
<blockquote>
</blockquote>
<h3 id="크롬-브라우저-에러-읽기">크롬 브라우저 에러 읽기</h3>
<ul>
<li>전체 에러 메시지 목록은 크롬 브라우저의 검색창에 chrome://network-errors/를 입력하여 확인할 수 있습니다.
<img src="https://images.velog.io/images/ice-ame/post/8234b502-e25d-42a0-9446-23415b36c0d6/%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-03-15%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%203.15.14.png" alt=""></li>
</ul>
<hr>
<h2 id="브라우저의-작동원리-보이는-곳">브라우저의 작동원리 (보이는 곳)</h2>
<hr>
<blockquote>
</blockquote>
<h3 id="spa를-만드는-기술-ajax">SPA를 만드는 기술 :AJAX</h3>
<p><strong>1.AJAX란?</strong></p>
<ul>
<li>AJAX는 Asynchronous JavaScript And XMLHttpRequest의 약자로, JavaScript, DOM, Fetch, XMLHttpRequest, HTML 등의 다양한 기술을 사용하는 웹 개발 기법입니다.</li>
<li>웹페이지에서 일부분만 바꾸고 싶다면  AJAX를 사용합니다. 웹 페이지에 필요한 부분에 필요한 데이터만 비동기적으로 받아와 화면에 그려낼 수 있다는 것입니다.</li>
<li>검색창에 한 글자를 입력할 때마다, 해당 글자로 시작하는 단어들을 서버로부터 받아와, 그 바로 아래 추천검색어로 보여주게 됩니다. 다시 말해, 검색창에서는 필요한 데이터만 비동기적으로 받아와 렌더링되며, 여기에 AJAX가 사용됩니다.<img src="https://s3.ap-northeast-2.amazonaws.com/urclass-images/dy_rbvuA2Lpi8wUB24zGx-1632827356069.gif">
></li>
<li><em>2.2. AJAX의 핵심 기술*</em></li>
<li>AJSX이전에는 <code>&lt;form&gt;</code>태그를 이용해 서버에 데이터를 전송했다</li>
<li>AJAX를 구성하는 핵심 기술은 JavaScript와 DOM, 그리고 Fetch입니다.<ul>
<li>Fetch 이전에는 XHR(XMLHttpRequest)를 사용했습니다</li>
</ul>
</li>
<li>Fetch를 사용하면, 페이지를 이동하지 않아도 서버로부터 필요한 데이터를 받아올 수 있습니다</li>
<li>Fetch는 사용자가 현재 페이지에서 작업을 하는 동안 서버와 통신할 수 있도록 합니다. 즉, 브라우저는 Fetch가 서버에 요청을 보내고 응답을 받을 때까지 모든 동작을 멈추는 것이 아니라, 계속해서 페이지를 사용할 수 있게 하는 비동기적인 방식을 사용합니다.</li>
<li>자바스크립트에서 DOM을 사용해 조작할 수 있기 때문에, Fetch를 통해 전체 페이지가 아닌 필요한 데이터만 가져와 DOM에 적용시켜 새로운 페이지로 이동하지 않고 기존 페이지에서 필요한 부분만 변경할 수 있습니다.</li>
<li>Fetch 예제<pre><code class="language-js">// Fetch를 사용
fetch(&#39;http://52.78.213.9:3000/messages&#39;)
  .then (function(response) {
      return response.json();
  })
  .then(function (json) {
      ...
});</code></pre>
<blockquote>
</blockquote>
</li>
<li><em>3. AJAX의 장점*</em></li>
<li><code>유저 중심 애플리케이션 개발</code>: AJAX를 사용하면 필요한 일부분만 렌더링하기 때문에 빠르고 더 많은 상호작용이 가능한 애플리케이션을 만들 수 있습니다.</li>
<li>초기의 AJAX는 표준화되어있지 않았지만, 표준화된 XHR의 등장과 함께 브라우저에 상관없이 AJAX를 사용할 수 있게 되었고, 지금은 XHR을 개선한 Fetch API를 사용하여 편리하게 AJAX를 구현할 수 있게 되었습니다.</li>
<li><code>더 작은 대역폭</code>: 이전에는 서버로부터 완성된 HTML 파일을 받아와야 했기 때문에 한 번에 보내야 하는 데이터의 크기가 컸습니다. 그러나 AJAX에서는 필요한 데이터를 텍스트 형태(JSON, XML 등) 보내면 되기 때문에 비교적 데이터의 크기가 작습니다.(대역폭: 네트워크 통신 한 번에 보낼 수 있는 데이터의 크기)<blockquote>
</blockquote>
</li>
<li><strong>4.AJSX의 단점*</strong></li>
<li><code>Search Engine Optimization(SEO)에 불리</code>
AJAX 방식의 웹 애플리케이션은 한 번 받은 HTML을 렌더링 한 후, 서버에서 비동기적으로 필요한 데이터를 가져와 그려냅니다. 따라서, 처음 받는 HTML 파일에는 데이터를 채우기 위한 틀만 작성되어 있는 경우가 많습니다.
검색 사이트에서는 전 세계 사이트를 돌아다니며 각 사이트의 모든 정보를 긁어와, 사용자에게 검색 결과로 보여줍니다. 그런데** AJAX 방식의 웹 애플리케이션의 HTML 파일은 뼈대만 있고 데이터는 없기 때문에 사이트의 정보를 긁어가기 어렵습니다.**<blockquote>
</blockquote>
</li>
<li><code>뒤로가기 버튼 문제</code>
일반적으로 사용자는 뒤로가기 버튼을 누르면 이전 상태로 돌아갈 거라고 생각하지만, AJAX에서는 이전 상태를 기억하지 않기 때문에 사용자가 의도한 대로 동작하지 않습니다. 따라서 <strong>뒤로가기 등의 기능을 구현하기 위해서는 별도로 History API를 사용해야 합니다.</strong></li>
</ul>
<blockquote>
</blockquote>
<h3 id="ssr-vs-csr">SSR vs CSR</h3>
<h4 id="ssr">SSR</h4>
<ul>
<li>SSR(Server Side Rendering)은 웹 페이지를 브라우저에서 렌더링하는 대신에, 서버에서 렌더링합니다</li>
<li>브라우저가 서버의 URI로 GET 요청을 보내면 웹 페이지를 브라우저로 보내기 전에, 서버에서 완전히 렌더링한후 파일을 전송합니다</li>
<li>웹 페이지의 내용에 데이터베이스의 데이터가 필요한 경우, 서버는 데이터베이스의 데이터를 불러온 다음 웹 페이지를 완전히 렌더링 된 페이지로 변환한 후에 브라우저에 응답으로 보냅니다.</li>
<li>브라우저가 다른 경로로 이동할 때마다 서버는 이 작업을 다시 수행합니다.</li>
<li>SEO(Search Engine Optimization) 가 우선순위인 경우, 일반적으로 SSR(Server Side Rendering) 을 사용합니다.</li>
<li>웹 페이지의 첫 화면 렌더링이 빠르게 필요한 경우에도, 단일 파일의 용량이 작은 SSR 이 적합합니다.</li>
<li>웹 페이지가 사용자와 상호작용이 적은 경우, SSR 을 활용할 수 있습니다.<blockquote>
</blockquote>
<h4 id="csr">CSR</h4>
</li>
<li>CSR(Client Side Rendering)은 클라이언트에서 페이지를 렌더링합니다</li>
<li>브라우저의 요청을 서버로 보내면 서버는 웹 페이지를 렌더링하는 대신, 웹 페이지의 골격이 될 단일 페이지를 클라이언트에 보냅니다.</li>
<li>이때 서버는 웹 페이지와 함께 JavaScript 파일을 보냅니다. 클라이언트가 웹 페이지를 받으면, 웹 페이지와 함께 전달된 JavaScript 파일은 브라우저에서 웹 페이지를 완전히 렌더링 된 페이지로 바꿉니다.</li>
<li>웹 페이지에 필요한 내용이 데이터베이스에 저장된 데이터인 경우에는 데이터베이스에 저장된 데이터를 가져와서 웹 페이지에 렌더링을 해야 합니다. 이를 위해 API가 사용됩니다</li>
<li>브라우저가 다른 경로로 이동하면 브라우저는 브라우저가 요청한 경로에 따라 페이지를 다시 렌더링합니다. 이때 보이는 웹 페이지의 파일은 맨 처음 서버로부터 전달받은 웹 페이지 파일과 동일한 파일입니다.</li>
<li><em>CSR은 브라우저(클라이언트)에서 페이지를 렌더링합니다. 브라우저는 사용자가 다른 경로를 요청할 때마다 페이지를 새로고침 하지 않고, 동적으로 라우팅을 관리합니다.*</em></li>
<li>SEO 가 우선순위가 아닌 경우, CSR을 이용할 수 있습니다.</li>
<li>사이트에 풍부한 상호 작용이 있는 경우, CSR 은 빠른 라우팅으로 강력한 사용자 경험을 제공합니다.</li>
<li>웹 애플리케이션을 제작하는 경우, CSR을 이용해 더 나은 사용자 경험(빠른 동적 렌더링 등)을 제공할 수 있습니다.</li>
</ul>
<blockquote>
</blockquote>
<h3 id="cors">cors</h3>
<p><strong>1.cors 개요</strong></p>
<ul>
<li>cors(Cross-Origin Resource Sharing,)란 한 출처에서 실행 중인 웹 애플리케이션이 다른 출처의 선택한 자원에 접근할 수 있는 권한을 부여하도록 브라우저에 알려주는 체제입니다<ul>
<li>고도화 된 최근의 웹은 여러 곳에 있는 리소스를 활용할 필요가 생겼고, same origin 요청이아닌 cros origin 요청이 필요하게 되었다</li>
</ul>
</li>
<li>보안상에 이유로 브라우저는 CORS preflightf(OPITONS 메소드)를 통해 cross-origin 요청을 제안하다. 서버가 허락한 범위내에서 cross orgin요청을 허용한다<ul>
<li>Cors prefligth란 어떤 요청전에 발생되는 사전요청으로 브라우저에서 자동으로 발생된다</li>
<li>단순 요청(simple requests/GET, HEAD 등)은 CORS preflight 를 트리거하지 않습니다.
<img src="https://media.vlpt.us/images/ice-ame/post/5346b52a-5dbb-4a5c-bca2-91e174c42689/%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-04-02%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%204.36.30.png" alt=""></li>
</ul>
</li>
</ul>
<hr>
<h2 id="아직-정리-안된-부분">아직 정리 안된 부분</h2>
<hr>
<h3 id="chrome-network-tab-사용방법">chrome network tab 사용방법</h3>
<p> 네트워크 패널(탭)은 네트워크 리소스의 타이밍을 보고 http1또는 http2를 통해 다운로드 되었는지 여부와 같은 개별 리소스의 네트워크 속성을 검사하기 위한 진단도구로 유용하다
 나중에 더 공부하기</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[js 비동기 ]]></title>
            <link>https://velog.io/@ice-ame/js-%EB%B9%84%EB%8F%99%EA%B8%B0</link>
            <guid>https://velog.io/@ice-ame/js-%EB%B9%84%EB%8F%99%EA%B8%B0</guid>
            <pubDate>Sun, 13 Mar 2022 15:58:09 GMT</pubDate>
            <description><![CDATA[<hr>
<h2 id="동기와-비동기">동기와 비동기</h2>
<hr>
<blockquote>
</blockquote>
<h3 id="동기와-비동기란">동기와 비동기란?</h3>
<p><strong>1.동기적(synchrounus)</strong></p>
<ul>
<li>순차적으로 진행됨(하나의 작업이 끝나야, 그다음 작업을 진행함)</li>
<li>blocking(하나의 작업이 끝날 때까지,이어지는 작업을 &quot;막는 것&quot;)<blockquote>
</blockquote>
</li>
<li><em>2.비 동기적(Asynchronous)*</em></li>
<li>순차적으로 진행되지 않음(무거운 작업일경우 빼놓고,그다음 작업으로 넘어감)</li>
<li>non-blocking(어떤 작업이 끝나지 않아도, 그다음 작업으로 넘어가는 것을 막지않음)</li>
<li>*&lt;비동기의 주요 사례&gt;**</li>
<li>DOM Elemennt의 이벤트 핸들러<ul>
<li>마우스,키보드 입력(click,keydown 등)</li>
<li>페이지 로딩(DOMContentLoaded 등)</li>
</ul>
</li>
<li>타이머<ul>
<li>타이머 API(setTimeout등)</li>
<li>애니메이션 API(requestAnimationFrame)</li>
</ul>
</li>
<li>서버에 자원 요청 및 응답<ul>
<li>fetch API</li>
<li>AJAX(XHR)</li>
</ul>
</li>
</ul>
<blockquote>
</blockquote>
<h3 id="비동기적-실행이유와-작동원리">비동기적 실행이유와 작동원리</h3>
<img align=right width =50% src= "https://images.velog.io/images/ice-ame/post/326c98ae-7eeb-4819-bb84-aa7b00c06f0f/%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-03-13%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%207.54.35.png" >
<img align=left width =50% src=https://images.velog.io/images/ice-ame/post/9e680d94-a99b-44bc-9b60-4579096f28d8/%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-03-13%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%207.56.03.png>
`
>
**1. 이유**
>
- **자바스크립트는 기본적으로 싱글쓰레드 방식으로 동작**하기 때문에 한 번에 한 가지 일만 수행할 수 있다
- 현재의 웹은 너무나도 커지고 복잡해졌기 때문에 **사용자의 동시 다발적인 요청에 빠르게 응답하기 위하여 비동기적 프로그래밍이 불가피해졌다**.
- callback 또는 promise ,async awit를 이용해 구현할 수 있다
>
**2.작동원리(이벤트 루프)**
![](https://images.velog.io/images/ice-ame/post/d38ddadd-9f5c-4899-a480-49015e2a890b/%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-03-13%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%2011.22.49.png)
- 비 동기로 동작하는 핵심요소는 자바스크립트 언어가 아니라 브라우저가 가지고 있다.(Node에서는 libuv 라이브러리 등)
- 브라우저는 Web APIs, Callback Queue, Event Loop 등으로 구성된다
- 자바스크립트의 힙에는 메모리가 할당 되며(객체), call stack은 실행된 코드의 환경을 저장하는 자료구조이고 함수 호출치 call stack에 push된다
```js
setTimeout(function exec() {
  console.log('second')
}, 1000);
```
- 위 코드 실행시  setTimeout이 call stack에 들어와 실행되면 Browser API인 timer를 호출한후 call stack에서 제거된다 스케줄링한 시간이 지나면 callback queue에 추가되고 call stack이 모두 호출되어 비어있을 때 call stack으로 이동시킨다
>
**3.정리**
- 사용자의 동시 다발적인 요청에 빠르게 응답하기 위하여 비동기적 프로그래밍이 필요하다
- call back과 promise , async awit 를 이용해 비동기적으로 코드를 구현 할수있다 

<hr>
<h2 id="call-back과-promise">call back과 promise</h2>
<hr>
<blockquote>
</blockquote>
<h3 id="콜백으로만-코드작성하기-콜백지옥">콜백으로만 코드작성하기 =&gt;콜백지옥</h3>
<pre><code class="language-js">const f1 =(callback)=&gt;{
  setTimeout(()=&gt;{
    console.log(&quot;1번주문 완료&quot;);
    callback()
  },1000)
}
&gt;
const f2= (callback)=&gt;{
  setTimeout(()=&gt;{
    console.log(&quot;2번주문 완료&quot;);
    callback();
  },3000);
}
&gt;
const f3= (callback)=&gt;{
  setTimeout(()=&gt;{
    console.log(&quot;3번주문완료&quot;);
    callback();
  },2000)
}
//콜백지옥의 예시 &lt;= 좋지못함
console.log(&quot;시작&quot;)
f1(()=&gt;{
  f2(()=&gt;{
    f3(()=&gt;{
     console.log(&#39;끝&#39;)
    })
  })
})</code></pre>
<blockquote>
</blockquote>
<h3 id="promise-사용방법">promise 사용방법</h3>
<p><img src="https://images.velog.io/images/ice-ame/post/1ebec222-67e0-4597-97aa-679a39bb1996/%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-23%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%205.06.36.png" alt=""></p>
<pre><code class="language-js">//producer code
const pr = new Promise((resolve,reject)=&gt;{
  setTimeuute(()=&gt;{
    resolve(&#39;ok&#39;)
  //reject(new Error(&#39;err...&#39;))
  },1000)
});
//consumer code
pr
.then(result=&gt;{console.log(result)})//성공시(resolve()호출)에 실행됨
.catch(error=&gt;{console.log(error)})// 실패시(reject()호출)에 실행됨
.finally(()=&gt;{console.log(&#39;end&#39;)})//무조건 출력됨</code></pre>
<blockquote>
</blockquote>
<h3 id="callback-hell-promise로-바꾸기">callback hell promise로 바꾸기</h3>
<pre><code class="language-js">//producer code
const f1 =() =&gt;{
  return new Promise((resolve,reject)=&gt;{
    setTimeout(()=&gt;{
      resolve(&quot;1번주문완료&quot;)  
    },1000)
  });
};
&gt;
const f2 = (message) =&gt;{
  console.log(message);
  return new Promise((resolve,reject)=&gt;{
    setTimeout(()=&gt;{
      resolve(&quot;2번주문완료&quot;)  
    },3000)
  })
}
&gt;
const f3 =(message) =&gt;{
  console.log(message);
  return new Promise((resolve,reject)=&gt;{
    setTimeout(()=&gt;{
      resolve(&quot;3번주문완료&quot;)  
    },2000)
  })
}
//resolve()는 리턴이든 함수본문내에서든 호출만 되면된다
&gt;
//Consumer code
//promises chaining
f1()
.then(result =&gt;f2(result))
.then(result =&gt;f3(result))
.then(result =&gt;console.log(result))
.catch(error =&gt;console.log(error))
.finally(()=&gt;console.log(&quot;end&quot;))
//then의 인수에는 함수의 호출이아닌 함수자체를 전달해야한다
//then안의 함수의 인자는 resolve의 인자로 넘어온다
//만약 중간에 실패하면 중간 then을 넘어서 바로 cathch로간다
//finally는 실패하든 성공하든 실행된다
////전달되는 인자가 하나일때는 생략방법이있다
f1()
.then(f2)
.then(f3)
.then(console.log)
.catch(console.log)
.finally(()=&gt;console.log(&quot;end&quot;))</code></pre>
<blockquote>
</blockquote>
<h3 id="프러미스-체이닝promise-chaining-">프러미스 체이닝(promise chaining )</h3>
<pre><code class="language-js">const fetchNumber =new Promise((reslove,reject)=&gt;{
  setTimeout(()=&gt;reslove(1),1000);
});
&gt;
fetchNumber
.then(num =&gt; num*2)
.then(num=&gt; num*3)
.then(num=&gt;{
  return new Promise((resolve,reject)=&gt;{
     setTimeout(()=&gt;resolve(num-1),2000);
  });
})
.then(num=&gt;console.log(num))
//then에서 값을 다른 then으로 전달할때는 전달받은 인자를 함수에서 return시켜야한다
//promise.then은 promise를 리턴한다
//promise.then에서 새로운 프러미스를 전달해도된다</code></pre>
<blockquote>
</blockquote>
<h3 id="promise-all">promise all</h3>
<pre><code class="language-js">const f1 =() =&gt;{
  return new Promise((resolve,reject)=&gt;{
    setTimeout(()=&gt;{
      resolve(&quot;1번주문완료&quot;)  
    },1000)
  });
};
&gt;
const f2 = () =&gt;{
  return new Promise((resolve,reject)=&gt;{
    setTimeout(()=&gt;{
      resolve(&quot;2번주문완료&quot;)  
    },3000)
  })
}
&gt;
const f3 =() =&gt;{
  return new Promise((resolve,reject)=&gt;{
    setTimeout(()=&gt;{
      resolve(&quot;3번주문완료&quot;)  
    },2000)
  })
}
&gt;
Promise.all([f1(),f2(),f3()])
.then((reslove)=&gt;{console.log(reslove)})
//all의 인수로 배열을받는다
//all안의 작업들이 모두 끝이나면 결과를 담은 배열을 리턴한다
//모든작업이 동시에 진행되고, 모두 성공되어야만 결과를 리턴한다.
//하나라도 누락되면 안되는경우 사용하기 좋다</code></pre>
<blockquote>
</blockquote>
<h3 id="promiserace">promise.race</h3>
<pre><code class="language-js">const f1 =() =&gt;{
  return new Promise((resolve,reject)=&gt;{
    setTimeout(()=&gt;{
      resolve(&quot;1번주문완료&quot;)  
    },1000)
  });
};
&gt;
const f2 = () =&gt;{
  return new Promise((resolve,reject)=&gt;{
    setTimeout(()=&gt;{
      resolve(&quot;2번주문완료&quot;)  
    },3000)
  })
}
&gt;
const f3 =() =&gt;{
  return new Promise((resolve,reject)=&gt;{
    setTimeout(()=&gt;{
      resolve(&quot;3번주문완료&quot;)  
    },2000)
  })
}
&gt;
Promise.race([f1(),f2(),f3()])
.then(console.log)
//가장 빠르게 끝난 작업하나만 리턴한다</code></pre>
<hr>
<h2 id="async-awit">async &amp;awit</h2>
<hr>
<blockquote>
</blockquote>
<h3 id="async--awit-사용방법">async &amp; awit 사용방법</h3>
<pre><code class="language-js">async function getName1() {
  return &#39;Mike&#39;;
}
//async를 함수앞에 붙이면 이 함수는 프러미스를 반환한다
//state는 fulfilled가되고 result는 &quot;Mike&quot;가 된다
&gt;
async function getName2() {
  return Promise.resolve(&quot;Tom&quot;)
}
//state는 fulfilled가되고 result는 &quot;Tom&quot;이 된다
//앞에 async를 안붙여도 되더라 어느게 보편적이지?
// return Promise.resolve(&quot;Tom&quot;) vs (차이점이뭐지?)
//return new promise((resolve,reject)=&gt;{resolve(&quot;Tom&quot;)})
&gt;
async function getName3() {
  throw new Error(&#39;err&#39;)
}
getName3()
.catch(err=&gt;{console.log(err)})
//throw,try,catch공부</code></pre>
<blockquote>
</blockquote>
<pre><code class="language-js">function getName(name){
  return new Promise((resolve,reject)=&gt;{
      setTimeout(()=&gt;{
        resolve(name)
      },1000)
    })
}
&gt;
async function showName(){
  const result =await getName(&quot;Mike&quot;)
  console.log(result)
}
showName(); //1초후 &quot;Mike&quot;가 콘솔에 찍힘
//await키워드는 async함수 내부에서만 사용할 수 있다
//await키워드는 오른쪽으넨 promis가 오고 그 프로미스가 처리될때까지 기다린다</code></pre>
<blockquote>
</blockquote>
<h3 id="async-await로-콜백지옥-바꿔보기">async, await로 콜백지옥 바꿔보기</h3>
<pre><code class="language-js">const f1 =() =&gt;{
  return new Promise((resolve,reject)=&gt;{
    setTimeout(()=&gt;{
      resolve(&quot;1번주문완료&quot;)  
    },1000)
  });
};
&gt;
const f2 = (message) =&gt;{
  console.log(message);
  return new Promise((resolve,reject)=&gt;{
    setTimeout(()=&gt;{
      resolve(&quot;2번주문완료&quot;)  
    },3000)
  })
}
&gt;
const f3 =(message) =&gt;{
  console.log(message);
  return new Promise((resolve,reject)=&gt;{
    setTimeout(()=&gt;{
      resolve(&quot;3번주문완료&quot;)  
    },2000)
  })
}
//resolve()는 리턴이든 함수본문내에서든 호출만 되면된다
&gt;
async function order(){
  const result1 =await f1();
  const result2 =await f2(result1);
  const result3= await f3(result2)
  console.log(result3);
  console.log(&quot;종료&quot;)
}
//만약 reject가 호출되는경우
//async function order(){
//  try{
//    const result1 =await f1();
//    const result2 =await f2(result1);
//    const result3= await f3(result2)
//    console.log(result3); 
//  }catch(e){
//    console.log(e) 
// }
//  console.log(&quot;종료&quot;)
//}
order();</code></pre>
<ul>
<li>비동기적으로 실행되는 코드내부에서 마치 동기적인 실행처럼 볼 수 있어 가독성이 매우좋음</li>
</ul>
<blockquote>
</blockquote>
<h3 id="질문에-답해보기">질문에 답해보기</h3>
<ul>
<li>Promise 실행 함수가 가지고 있는 두 개의 파라미터 resolve 와 reject 는 각각 무엇을 의미하나요?<ul>
<li>성공시 resolve 실패시 reject를 이용해 값을 전달</li>
</ul>
</li>
<li>resolve, reject함수에는 인자를 넘길 수 있습니다. 이때 넘기는 인자는 어떻게 사용할 수 있나요?<ul>
<li>resolve,reject의 인자에 값을 넣으면 then이나 cahtch 로 받을 수 있다</li>
</ul>
</li>
<li>new Promise()를 통해 생성한 Promise 인스턴스에는 어떤 메서드가 존재하나요? 각각은 어떤 용도인가요?<ul>
<li>then,cahtch,finally등 컨슈머 코드에 사용된다</li>
</ul>
</li>
<li>Promise.prototype.then 메서드는 무엇을 리턴하나요?<ul>
<li>promise를 리턴하고 then 인자안의 함수에서 리턴된 값이 프러미스의 vlaue가 된다 상태는 fulfiled</li>
</ul>
</li>
<li>Promise.prototype.catch 메서드는 무엇을 리턴하나요?<ul>
<li>프러미스를 리턴하고 상태는 rejected/ catch로 전달받을 수 있다</li>
</ul>
</li>
<li>Promise의 세 가지 상태는 각각 무엇이며, 어떤 의미를 가지나요?<ul>
<li>pending 대기상태 ,fulfiled 이행된 상태 ,rejected 거부실패된 상태</li>
</ul>
</li>
<li>await 키워드 다음에 등장하는 함수 실행은 어떤 타입을 리턴할 경우에만 의미가 있나요?<ul>
<li>프러미스를 리턴하는 경우에만 의미가 있다</li>
</ul>
</li>
<li>await 키워드를 사용할 경우, 어떤 값이 리턴되나요?
프러미스가 리턴된다</li>
<li>Promise.all 의 인자는 어떠한 형태인가요?<ul>
<li>배열이다</li>
</ul>
</li>
<li>Promise.all 을 사용할 경우에 then 메서드의 파라미터는 어떠한 형태인가요?<ul>
<li>함수다</li>
</ul>
</li>
<li>Promise.all 에 두 개의 Promise 요청이 전달되고, 만일 그중 하나가 rejected 상태가 되는 경우, then 메서드를 따라가나요, 아니면 catch 메서드를 따라가나요?<ul>
<li>catch</li>
</ul>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Tree&Graph]]></title>
            <link>https://velog.io/@ice-ame/TreeGraph</link>
            <guid>https://velog.io/@ice-ame/TreeGraph</guid>
            <pubDate>Sun, 13 Mar 2022 10:37:45 GMT</pubDate>
            <description><![CDATA[<hr>
<h2 id="tree">Tree</h2>
<hr>
<blockquote>
</blockquote>
<h3 id="tree란">Tree란?</h3>
<ul>
<li>트리 구조는 데이터가 바로 아래에 있는 하나 이상의 데이터에 단방향으로 연결된 계층적 자료구조이다</li>
<li>데이터를 순차적으로 나열시킨 선형 구조가 아니라, 하나의 데이터 아래에 여러 개의 데이터가 존재할 수 있는 비선형 구조이다</li>
<li>트리 구조는 계층적으로 표현이 되고, 아래로만 뻗어나가기 때문에 사이클이 없다</li>
</ul>
<blockquote>
</blockquote>
<h3 id="tree구조의-용어">Tree구조의 용어</h3>
<p><img src="https://images.velog.io/images/ice-ame/post/e159be1d-7539-4009-af09-211f529c3a67/%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-03-12%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%208.09.09.png" alt=""></p>
<ul>
<li>노드(Node) : 트리 구조를 이루는 모든 개별 데이터</li>
<li>루트(Root) : 트리 구조의 시작점이 되는 노드</li>
<li>부모 노드(Parent node) : 두 노드가 상하관계로 연결되어 있을 때 상대적으로 루트에서 가까운 노드</li>
<li>자식 노드(Child node) : 두 노드가 상하관계로 연결되어 있을 때 상대적으로 루트에서 먼 노드</li>
<li>리프(Leaf) : 트리 구조의 끝 지점이고, 자식 노드가 없는 노드
<img src="https://images.velog.io/images/ice-ame/post/e0baea83-ebdd-4ec4-a40f-94b985b36fe7/%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-03-12%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%208.11.39.png" alt=""></li>
<li>깊이(depth):루트로부터 하위 계층의 특정 노드까지의 깊이</li>
<li>레벨(Level):같은 깊이를 가지고 있는 노드를 묶어서 레벨(level)</li>
<li>높이(Height):리프 노드를 기준으로 루트까지의 높이(height)</li>
<li>서브 트리(Sub tree):트리의 내부에, 트리 구조를 갖춘 작은 트리</li>
</ul>
<blockquote>
</blockquote>
<h3 id="binary-tree이진트리와-종류">binary Tree(이진트리)와 종류</h3>
<p><strong>1.Binary Tree</strong></p>
<ul>
<li>노드에 child가 2개씩 붙는 트리를 일컫는다<blockquote>
</blockquote>
</li>
<li><em>2.Full Bindary tree*</em></li>
<li>각 노드가 0 개 혹은 2 개의 자식 노드를 갖습니다.<blockquote>
</blockquote>
</li>
<li><em>3.Complete binary tree*</em></li>
<li>마지막 레벨을 제외한 모든 노드가 가득 차 있어야 하고, 마지막 레벨의 노드는 전부 차 있지 않아도 되지만 왼쪽이 채워져야 합니다.<blockquote>
</blockquote>
</li>
<li><em>4.Perfect Binary tree*</em></li>
<li>모든 리프 노드의 레벨이 동일하고, 모든 레벨이 가득 채워져 있는 트리입니다.<blockquote>
</blockquote>
</li>
<li><em>5.Binart Search Tree(이진 탐색트리)*</em></li>
<li>모든 왼쪽 자식의 값이 루트나 부모보다 작고, 모든 오른쪽 자식의 값이 루트나 부모보다 큰 값을 가진다</li>
<li>검색에 유용하다</li>
</ul>
<blockquote>
</blockquote>
<h3 id="tree-traversal">Tree traversal</h3>
<ul>
<li>특정 목적을 위해 트리의 모든 노드를 한 번씩 방문하는 것을 트리 순회라고 합니다<blockquote>
</blockquote>
</li>
<li><em>1. 트리의 순회 방식 3가지*</em>
<img src="https://images.velog.io/images/ice-ame/post/a4f36573-eea7-48a0-ac91-e8c2cbb699e7/%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-03-12%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%208.34.23.png" alt=""></li>
<li><em>1) 전위순회(preoder) MLR*</em>
A=&gt;B=&gt;D=&gt;H=&gt;I=&gt;E=&gt;J=&gt;K=&gt;C=&gt;F=&gt;L=&gt;M=&gt;G=&gt;N=&gt;O<blockquote>
</blockquote>
</li>
<li><em>2) 중위순회(inorder) LMR*</em>
H=&gt;D=&gt;I=&gt;B=&gt;J=&gt;E-&gt;K=&gt;A=&gt;L=&gt;F=&gt;M=&gt;C=&gt;N=&gt;G=&gt;O<blockquote>
</blockquote>
</li>
<li><em>3) 후위순회(postorder) LRM*</em>
H=&gt;I=&gt;D=&gt;J=&gt;K=&gt;E=&gt;B=&gt;L=&gt;M=&gt;F=&gt;N=&gt;O=&gt;G=&gt;C=&gt;A</li>
</ul>
<hr>
<h2 id="graph">Graph</h2>
<hr>
<blockquote>
</blockquote>
<h3 id="graph란">Graph란?</h3>
<ul>
<li>여러 개의 점들이 서로 복잡하게 연결되어 있는 관계를 표현한 자료구조<blockquote>
</blockquote>
<h3 id="graph구조의-용어">Graph구조의 용어</h3>
<img src="https://images.velog.io/images/ice-ame/post/dcb5a8a7-76c7-4f07-81d0-e5b9b911ab81/%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-03-13%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%201.19.14.png" alt=""></li>
<li>정점 (vertex): 노드(node)라고도 하며 데이터가 저장되는 그래프의 기본 원소입니다.</li>
<li>간선 (edge): 정점 간의 관계를 나타냅니다. (정점을 이어주는 선)</li>
<li>인접 정점 (adjacent vertex): 하나의 정점에서 간선에 의해 직접 연결되어 있는 정점을 뜻합니다.</li>
<li>가중치 그래프 (weighted Graph): 연결의 강도(추가적인 정보, 위의 예시에서는 서울-부산으로 가는 거리 등)가 얼마나 되는지 적혀져 있는 그래프를 뜻합니다.</li>
<li>비가중치 그래프 (unweighted Graph): 연결의 강도가 적혀져 있지 않는 그래프를 뜻합니다.</li>
<li>무(방)향 그래프 (undirected graph):서울에서 부산으로 갈 수 있듯, 반대로 부산에서 서울로 가는 것도 가능합니다. 하지만 단방향(directed,tree) 그래프로 구현된다면 서울에서 부산을 갈 수 있지만, 부산에서 서울로 가는 것은 불가능합니다(혹은 그 반대). 만약 두 지점이 일방통행 도로로 이어져 있다면 단방향인 간선으로 표현할 수 있습니다.</li>
<li>진입차수 (in-degree) / 진출차수 (out-degree): 한 정점에 진입(들어오는 간선)하고 진출(나가는 간선)하는 간선이 몇 개인지를 나타냅니다.</li>
<li>인접 (adjacency): 두 정점 간에 간선이 직접 이어져 있다면 이 두 정점은 인접한 정점입니다.</li>
<li>자기 루프 (self loop): 정점에서 진출하는 간선이 곧바로 자기 자신에게 진입하는 경우 자기 루프를 가졌다 라고 표현합니다. 다른 정점을 거치지 않는다는 것이 특징입니다.</li>
<li>사이클 (cycle): 한 정점에서 출발하여 다시 해당 정점으로 돌아갈 수 있다면 사이클이 있다고 표현합니다. 내비게이션 그래프는 서울 —&gt; 대전 —&gt; 부산 —&gt; 서울 로 이동이 가능하므로, 사이클이 존재하는 그래프입니다.</li>
</ul>
<blockquote>
</blockquote>
<h3 id="그래프의-표현방식">그래프의 표현방식</h3>
<p><img src="https://images.velog.io/images/ice-ame/post/78d7c717-a52f-429a-b070-8b698ece35c1/%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-03-13%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%201.22.26.png" alt="">
<strong>1.인접행렬(Adjacency matrix)</strong></p>
<ul>
<li>인접 행렬은 서로 다른 정점들이 인접한 상태인지를 표시한 행렬로 2차원 배열의 형태로 나타낸다</li>
<li>한 개의 큰 표와 같은 모습을 한 인접 행렬은 두 정점 사이에 관계가 있는지, 없는지 확인하기에 용이합니다</li>
<li>가장 빠른 경로(shortest path)를 찾고자 할 때 주로 사용됩니다.
<img src="https://images.velog.io/images/ice-ame/post/95fe3ff6-46d3-42a2-b780-718f7f577cba/%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-03-13%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%201.23.25.png" alt=""><blockquote>
</blockquote>
</li>
<li><em>2.인접 리스트(Adjacency list)*</em></li>
<li>순서 상관없이 해당 정점에 인접한 정점들을 나열하면됨(순서는 예외가있을 수 있음)</li>
<li>메모리를 효율적으로 사용하고 싶을 때 인접 리스트를 사용합니다.
(인접 행렬은 연결 가능한 모든 경우의 수를 저장하기 때문에 상대적으로 메모리를 많이 차지합니다.)</li>
</ul>
<p><img src="https://images.velog.io/images/ice-ame/post/3243d50a-af11-4da1-9e11-f1f017c96bb3/%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-03-13%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%201.29.59.png" alt=""></p>
<blockquote>
</blockquote>
<h3 id="그래프의-탐색bfsdfs">그래프의 탐색(BFS/DFS)</h3>
]]></description>
        </item>
        <item>
            <title><![CDATA[Stack & Queue]]></title>
            <link>https://velog.io/@ice-ame/Stack-Queue</link>
            <guid>https://velog.io/@ice-ame/Stack-Queue</guid>
            <pubDate>Sat, 12 Mar 2022 11:02:01 GMT</pubDate>
            <description><![CDATA[<hr>
<h2 id="stack">Stack</h2>
<hr>
<blockquote>
</blockquote>
<h3 id="1stack이란">1.stack이란?</h3>
<ul>
<li>데이터(data)를 순서대로 쌓는 자료구조</li>
<li>LIFO(last In, First Out)</li>
<li>스택은 아래의 두가지 연산을 가진 요소들의 집합인 추상 자료형
<img src="https://images.velog.io/images/ice-ame/post/fe910b8f-be5b-4cda-b2e2-43f0b85b6cdb/%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-03-12%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%207.09.07.png" alt=""></li>
<li>js에서는 배열의 push,pop,splice 등 을 이용해 구현할 수 있다.</li>
</ul>
<blockquote>
</blockquote>
<h3 id="2-stack을-이용해보았던-문제들">2. stack을 이용해보았던 문제들</h3>
<h4 id="1브라우저-뒤로-가기-앞으로-가기">1.브라우저 뒤로 가기 앞으로 가기</h4>
<p><strong>조건</strong></p>
<ul>
<li>새로운 페이지로 접속할 경우 prev 스택에 원래 있던 페이지를 넣고 next 스택을 비웁니다.</li>
<li>뒤로 가기 버튼을 누를 경우 원래 있던 페이지를 next 스택에 넣고 prev 스택의 top에 있는 페이지로 이동한 뒤 prev 스택의 값을 pop 합니다.</li>
<li>앞으로 가기 버튼을 누를 경우 원래 있던 페이지를 prev 스택에 넣고 next 스택의 top에 있는 페이지로 이동한 뒤 next 스택의 값을 pop 합니다.</li>
<li>브라우저에서 뒤로 가기, 앞으로 가기 버튼이 비활성화일 경우(클릭이 되지 않을 경우)에는 스택에 push 하지 않습니다.<blockquote>
</blockquote>
</li>
<li><em>입력*</em></li>
<li>인자 1: actions
String과 Number 타입을 요소로 갖는 브라우저에서 행동한 순서를 차례대로 나열한 배열</li>
<li>인자 2: start
String 타입의 시작 페이지를 나타내는 현재 접속해 있는 대문자 알파벳<blockquote>
</blockquote>
</li>
<li><em>출력*</em></li>
<li>Array 타입을 리턴해야 합니다.<blockquote>
</blockquote>
</li>
<li><em>주의사항*</em></li>
<li>만약 start의 인자로 string 자료형이 아닌 다른 자료형이 들어온다면 false를 리턴합니다.</li>
<li>새로운 페이지 접속은 알파벳 대문자로 표기합니다.</li>
<li>뒤로 가기 버튼을 누른 행동은 -1로 표기합니다.</li>
<li>앞으로 가기 버튼을 누른 행동은 1로 표기합니다.</li>
<li>다음 방문할 페이지는 항상 현재 페이지와 다른 페이지로 접속합니다.</li>
<li>방문한 페이지의 개수는 100개 이하입니다.</li>
<li>반환되는 출력값 배열의 첫 번째 요소 prev 스택, 세 번째 요소 next 스택은 배열입니다. 스택을 사용자 정의한다면 출력에서는 배열로 변환해야 합니다.<blockquote>
</blockquote>
</li>
<li><em>입출력 예시*</em><pre><code class="language-js">const actions = [&quot;B&quot;, &quot;C&quot;, -1, &quot;D&quot;, &quot;A&quot;, -1, 1, -1, -1];
const start = &quot;A&quot;;
const output = browserStack(actions, start);
&gt;
console.log(output); // [[&quot;A&quot;], &quot;B&quot;, [&quot;A&quot;, &quot;D&quot;]]
&gt;
const actions2 = [&quot;B&quot;, -1, &quot;B&quot;, &quot;A&quot;, &quot;C&quot;, -1, -1, &quot;D&quot;, -1, 1, &quot;E&quot;, -1, -1, 1];
const start2 = &quot;A&quot;;
const output2 = browserStack(actions2, start2);
&gt;
console.log(output2); // [[&quot;A&quot;, &quot;B&quot;], &quot;D&quot;, [&quot;E&quot;]]</code></pre>
<blockquote>
</blockquote>
</li>
<li><em>내 풀이*</em><pre><code class="language-js">function browserStack(actions, start) {
 // TODO: 여기에 코드를 작성합니다.
 if(typeof start!==&#39;string&#39;) return false
 let prev = []; //stack
 let next = [];//stack
 let nowPage = start;
 for (let i = 0; i &lt; actions.length; i++) {
   if(prev.length===0&amp;&amp;actions[i]===-1){ //prev가 빈경우
     continue 
   }
   if(next.length===0&amp;&amp;actions[i]===1){//next가 빈경우
     continue
   }
   if(typeof actions[i]===&#39;string&#39;){//새로운 페이지인경우
     prev.push(nowPage);
     nowPage= actions[i]
     next =[];
   }
   if(actions[i]===-1){//뒤로가기인 경우
     next.push(nowPage);
     nowPage=prev.pop()
   }
   if(actions[i]===1){//앞으로가기인 경우
     prev.push(nowPage);
     nowPage =next.pop()
   }
 }
return [prev,nowPage,next]//제출
}</code></pre>
</li>
</ul>
<hr>
<h2 id="2queue">2.Queue</h2>
<hr>
<blockquote>
</blockquote>
<h3 id="1queue란">1.Queue란?</h3>
<ul>
<li>자료구조 Queue는 Stack과 반대되는 개념으로</li>
<li>FIFO(First In First Out) 혹은 LILO(Last In Last Out) 을 특징으로 가지고 있다
<img src="https://images.velog.io/images/ice-ame/post/e0248111-7361-4007-ba73-20fa2e1c496c/%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-03-12%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%207.28.00.png" alt=""></li>
<li>js에서 배열의 unshift와 push,splice등 을 이용해 구현할 수 있다 </li>
</ul>
<blockquote>
</blockquote>
<h3 id="2-queue를-이용해보았던-문제들">2. Queue를 이용해보았던 문제들</h3>
<h4 id="1박스포장">1.박스포장</h4>
<p><strong>문제</strong></p>
<ul>
<li>마트에서 장을 보고 박스를 포장하려고 합니다. 박스를 포장하는 데는 폭이 너무 좁습니다. 그렇기에 한 줄로 서 있어야 하고, 들어온 순서대로 한 명씩 나가야 합니다.</li>
<li>불행 중 다행은, 인원에 맞게 포장할 수 있는 기구들이 놓여 있어, 모두가 포장을 할 수 있다는 것입니다. 짐이 많은 사람은 짐이 적은 사람보다 포장하는 시간이 길 수밖에 없습니다.</li>
<li>뒷사람이 포장을 전부 끝냈어도 앞사람이 끝내지 못하면 기다려야 합니다. 앞사람이 포장을 끝내면, 포장을 마친 뒷사람들과 함께 한 번에 나가게 됩니다.</li>
<li>만약, 앞사람의 박스는 5 개고, 뒷사람 1의 박스는 4 개, 뒷사람 2의 박스는 8 개라고 가정했을 때, 뒷사람 1이 제일 먼저 박스 포장을 끝내게 되어도 앞사람 1의 포장이 마칠 때까지 기다렸다가 같이 나가게 됩니다.</li>
<li>이때, 통틀어 최대 몇 명이 한꺼번에 나가는지 알 수 있도록 함수를 구현해 주세요.<blockquote>
</blockquote>
</li>
<li><em>입력*</em></li>
<li>인자 1 : boxes<ul>
<li>Number 타입을 요소로 갖는, 포장해야 하는 박스가 담긴 배열
1 ≤ 사람 수 ≤ 10,000
1 ≤ 박스 ≤ 10,000<blockquote>
</blockquote>
</li>
</ul>
</li>
<li><em>출력*</em></li>
<li>Number 타입을 리턴해야 합니다.<blockquote>
</blockquote>
</li>
<li><em>주의 사항*</em></li>
<li>먼저 포장을 전부 끝낸 사람이 있더라도, 앞사람이 포장을 끝내지 않았다면 나갈 수 없습니다.<blockquote>
</blockquote>
</li>
<li><em>예시*</em></li>
<li>만약 5, 1, 4, 6이라는 배열이 왔을 때, 5개의 박스를 포장하는 동안 1, 4 개의 박스는 포장을 끝내고 기다리게 되고, 6 개의 박스는 포장이 진행 중이기 때문에, 5, 1, 4 세 개가 같이 나가고, 6이 따로 나가게 됩니다. 그렇기에 최대 3 명이 같이 나가게 됩니다.<pre><code class="language-js">const boxes = [5, 1, 4, 6];
const output = paveBox(boxes);
console.log(output); // 3
&gt;
const boxes2 = [1, 5, 7, 9];
const output2 = paveBox(boxes);
console.log(output2); // 1</code></pre>
<blockquote>
</blockquote>
</li>
<li><em>나의 풀이*</em><pre><code class="language-js">function paveBox(boxes) {
 //몇명이 나가는지 값들 저장하기
 let result =[]
 //몇명인지 세는 함수 만들기
  function howManypeople(boxes){
   let howManypeople = 0
   for(let el of boxes){
     if(boxes[0]&gt;=el){
       howManypeople += 1
     }else{
       break
     }
   }
   return howManypeople
 }
 //박스의 선입 선출 조정
 for(;boxes.length&gt;0;){
   result.push(howManypeople(boxes));
   boxes.splice(0,howManypeople(boxes));
 }
 // 최대값 리턴
 return Math.max(...result)
}</code></pre>
<h4 id="2프린터">2.프린터</h4>
</li>
<li><em>문제*</em>
프린터의 인쇄 작업 목록의 크기와 최대 용량을 가정하고 각기 다른 용량의 문서를 차례대로 인쇄하여 모든 문서가 인쇄되는데 최소 몇 초가 걸리는지 테스트하기로 했습니다.
린터의 제한사항인 인쇄 작업 목록의 크기 bufferSize, 최대 용량 capacities가 주어집니다. 인쇄할 문서의 크기가 나열된 배열 documents가 모두 인쇄되는데 걸리는 최소 시간을 반환하는 솔루션을 만들어 주세요.</li>
<li><em>입력*</em></li>
<li>인자1: bufferSize<ul>
<li>Number 타입의 인쇄 작업 목록 크기</li>
</ul>
</li>
<li>인자 2: capacities<ul>
<li>Number 타입의 인쇄 작업 목록에 추가될 수 있는 최대 용량</li>
</ul>
</li>
<li>인자 3: documents<ul>
<li>Number 타입을 요소로 갖는 문서 크기가 나열된 배열</li>
</ul>
</li>
<li><em>출력*</em></li>
<li>Number 타입을 리턴해야 합니다.</li>
<li><em>제한사항*</em></li>
<li>인쇄 작업 목록은 칸으로 이루어져 있습니다.</li>
<li>각 칸에는 한 개의 문서만 위치할 수 있습니다.</li>
<li>문서는 1초에 한 칸만 이동할 수 있습니다.</li>
<li>인쇄 작업 목록의 크기는 bufferSize이고 최대 용량 capacities 만큼 문서를 담을 수 있습니다.</li>
<li><em>주의사항*</em></li>
<li>bufferSize는 1 이상 100 이하입니다.</li>
<li>capacities는 100Kib 이하입니다.</li>
<li>인쇄할 문서의 개수(배열의 길이) 1이상 100 이하입니다.</li>
<li>문서 하나의 크기는 capacities를 초과하지 않습니다.
1초가 지나면 인쇄 작업 목록에는 7Kib 크기의 문서가 추가됩니다.</li>
<li><em>예시*</em></li>
<li>1초가 지나면 인쇄 작업 목록에는 7Kib 크기의 문서가 추가됩니다.</li>
<li>2초일 때 인쇄 작업 목록의 최대 용량이 10Kib이기 때문에 4Kib 문서는 작업 목록에 들어갈 수 없습니다. 동시에 7Kib 문서는 작업 목록에서 1칸 앞으로 이동합니다.</li>
<li>3초일 때 7Kib 문서는 인쇄 작업 목록에서 나와 프린터가 인쇄합니다. 동시에 4Kib 문서는 인쇄 작업 목록에 추가됩니다.</li>
<li>4초일 때 4Kib 문서는 인쇄 작업 목록에서 1칸 앞으로 이동합니다. 동시에 5Kib 문서는 인쇄 작업 목록에 추가됩니다.</li>
<li>5초일 때 4Kib 문서는 인쇄 작업 목록에서 나와 프린터가 인쇄합니다. 동시에 5Kib 문서는 인쇄 작업 목록에서 1칸 앞으로 이동합니다. 최대 용량 10Kib 제한으로 6Kib 문서는 인쇄 작업 목록으로 추가될 수 없습니다.</li>
<li>6초일 때 5Kib 문서는 인쇄 작업 목록에서 나와 프린터가 인쇄합니다. 동시에 6Kib 문서가 인쇄 작업 목록에 추가됩니다.</li>
<li>7초일 때 6Kib 문서는 인쇄 작업 목록에서 1칸 앞으로 이동합니다.</li>
<li>8초일 때 6Kib 문서가 마지막으로 인쇄됩니다.</li>
<li><em>입출력 예시*</em><pre><code class="language-js">let bufferSize = 2;
let capacities = 10;
let documents = [7, 4, 5, 6];
let output = queuePrinter(bufferSize, capacities, documents);
console.log(output) // 8</code></pre>
</li>
<li><em>나의 풀이*</em><pre><code class="language-js">function queuePrinter(bufferSize, capacities, documents) {
 //업데이트변수
 let count = 0;
 //worklist (queue)
 const worklist = new Array(bufferSize).fill(null);
 //worklist에 null만있는지 확인하는함수
 function isallNull() {
   let allNull = true;
   for (let i = 0; i &lt; worklist.length; i++) {
     if (worklist[i] !== null) { allNull = false }
   }
   return allNull
 }
 //재귀시킬함수
 function replay(capacities, documents) {
   //재귀종료조건
   if (isallNull() &amp;&amp; documents.length === 0) return;
   //카운트 없데이트
   count += 1;
   //현재 worklist의 용량
   worklist.shift();
   let nowWorklistCapacities = worklist.reduce((pre, cur) =&gt; pre + cur,0);
   //작업수행
   if (nowWorklistCapacities + documents[0] &lt;=capacities) {
     worklist.push(documents[0]); 
     return replay(capacities, documents.slice(1))
   } else {
     worklist.push(null);
     return replay(capacities, documents)
   }
 }
 replay(capacities, documents);//재귀함수 실행
 return count//업데이트된 카운트 제출
}</code></pre>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[JS 자료구조 알고리즘]]></title>
            <link>https://velog.io/@ice-ame/JS-%EC%9E%90%EB%A3%8C%EA%B5%AC%EC%A1%B0-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98</link>
            <guid>https://velog.io/@ice-ame/JS-%EC%9E%90%EB%A3%8C%EA%B5%AC%EC%A1%B0-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98</guid>
            <pubDate>Sat, 12 Mar 2022 10:05:11 GMT</pubDate>
            <description><![CDATA[<blockquote>
</blockquote>
<h2 id="데이터와-자료구조">데이터와 자료구조</h2>
<ul>
<li>데이터는 분석하고 정리하여 활용해야만 의미를 가질 수 있습니다</li>
<li>데이터를 사용하려는 목적에 따라 형태를 구분하고, 분류하여 사용합니다</li>
<li>필요에 따라 데이터의 특징을 잘 파악(분석)하여 정리하고, 활용해야한다</li>
<li>데이터를 체계적으로 정리하여 저장해두는 게, 데이터를 활용하는 데 있어 훨씬 유리합니다.</li>
<li>자료구조란 여러 데이터의 묶음을 저장하고, 효율적으로 사용하는 방법을 정의한 것
<img src="https://images.velog.io/images/ice-ame/post/2de67c9b-28dd-4fda-919a-f09dfdd32f5c/%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-03-12%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%207.01.59.png" alt=""></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[JS JSON]]></title>
            <link>https://velog.io/@ice-ame/JS-JSON</link>
            <guid>https://velog.io/@ice-ame/JS-JSON</guid>
            <pubDate>Thu, 03 Mar 2022 12:08:43 GMT</pubDate>
            <description><![CDATA[<blockquote>
</blockquote>
<h3 id="json이란">JSON이란?</h3>
<ul>
<li>JSON은 (JavaScript Object Notation)데이터를 문자열의 형태로 나타내기 위해서 사용된다</li>
<li>웹 어플리케이션에서 데이터를 전송할 때 일반적으로 사용한다</li>
<li>자바스크립트에서는 JSON 포멧의 데이터를 간편하게 다룰 수 있도록 JSON이라는 객체를 내장하고 있습다</li>
<li>객체는 자바스크립트 코드를 브라우저에서 실행하든 Node.js 런타임에서 실행하든 상관없이 전역(global)에서 접근이 가능하다</li>
<li>JSON 내장 객체는 JavaScript 객체와 JSON 문자열 간의 상호 변환을 수행해주는 두 개의 메서드를 제공한다.</li>
</ul>
<blockquote>
</blockquote>
<h3 id="jsonstringfy-jsonparse">JSON.stringfy /JSON.parse</h3>
<pre><code class="language-js">const jiwoong ={
    age:27,
    name: &quot;jiwoong&quot;,
    first: &quot;hwang&quot;,
    contry:&#39;korea&#39;,
}
const stringfy=JSON.stringify(jiwoong);
//&#39;{&quot;age&quot;:27,&quot;name&quot;:&quot;jiwoong&quot;,&quot;first&quot;:&quot;hwang&quot;,&quot;contry&quot;:&quot;korea&quot;}&#39;
const restore =JSON.parse(stringfy);
//{age: 27, name: &#39;jiwoong&#39;, first: &#39;hwang&#39;, contry: &#39;korea&#39;}</code></pre>
]]></description>
        </item>
    </channel>
</rss>