<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>devCecy</title>
        <link>https://velog.io/</link>
        <description>🌈그림으로 기록하는 개발자🌈</description>
        <lastBuildDate>Tue, 22 Mar 2022 07:00:56 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>devCecy</title>
            <url>https://images.velog.io/images/dev_cecy/profile/d77bbfba-1f6f-4c98-b663-f08824ddd6d2/이모지.jpeg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. devCecy. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/dev_cecy" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[[워드프레스] LET’S ENCRYPT로 HTTPS 적용하기]]></title>
            <link>https://velog.io/@dev_cecy/%EC%9B%8C%EB%93%9C%ED%94%84%EB%A0%88%EC%8A%A4-LETS-ENCRYPT%EB%A1%9C-HTTPS-%EC%A0%81%EC%9A%A9%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@dev_cecy/%EC%9B%8C%EB%93%9C%ED%94%84%EB%A0%88%EC%8A%A4-LETS-ENCRYPT%EB%A1%9C-HTTPS-%EC%A0%81%EC%9A%A9%ED%95%98%EA%B8%B0</guid>
            <pubDate>Tue, 22 Mar 2022 07:00:56 GMT</pubDate>
            <description><![CDATA[<p>워드프레스 블로그에 https를 적용해보자 !</p>
<p>본인이 사용하는 터미널을 연다.
ssh -i [발급받은 SSHKey] bitnami@ip주소를 입력해서 ssh에 접속해준다. 참고로 발급받은 SSHKey는 파일을 드래그 앤 드롭으로 가져오면 된다. 본인의 ip주소는 aws에 접속하면 확인할 수 있고, Static IP라고 되어있는 고정IP를 사용하면된다.
그럼 접속 완료 !</p>
<p><img src="https://images.velog.io/images/dev_cecy/post/6acd0955-16e6-4ef9-a8ea-f1dad0b66e02/%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-22%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.56.17.png" alt=""></p>
<p>처음에는 스위프트님 글 보면서 시도해봤는데, wget <a href="https://dl.eff.org/certbot-auto">https://dl.eff.org/certbot-auto</a> 404 Not Found가 떴다. 그래서 <a href="https://dl.eff.org/certbot-auto%EC%97%90">https://dl.eff.org/certbot-auto에</a> 들어가보니 페이지 자체가 Not Found 상태였다.
<img src="https://images.velog.io/images/dev_cecy/post/e65b97a4-5b73-481c-829b-ecc691277b57/%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-22%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.56.30.png" alt=""></p>
<p>그래서 서칭하다 Bitnami 애플리케이션용 Let’s Encrypt SSL 인증서 생성 및 설치 문서 발견!</p>
<ol start="4">
<li><p>sudo /opt/bitnami/bncert-tool 입력</p>
</li>
<li><p>Domain list 에 본인 도메인 주소 입력</p>
</li>
<li><p>Do you want to add them? Y 입력!</p>
</li>
</ol>
<p><img src="https://images.velog.io/images/dev_cecy/post/e1ee32e9-9ab6-44ef-9a45-b4bcae8404e5/%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-22%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.56.51.png" alt=""></p>
<p>도메인을 등록하고 나면 리다이렉션 여부를 설정한다. 나는 http로 접속시 https로, www입력시 non-www로 리다이렉션 되도록 설정했다!</p>
<ol start="7">
<li><p>HTTP 에서 HTTPS 로 리다이렉션 할래? y</p>
</li>
<li><p>non-www 에서 www 로 리다이렉션 할래? n</p>
</li>
<li><p>www 에서 non-www로 리다이렉션 할래? y
<img src="https://images.velog.io/images/dev_cecy/post/ebff6c09-f5b0-46e8-b430-f2049838ac7e/%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-22%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.57.34.png" alt=""></p>
</li>
<li><p>1~7번과 같이 변경될거야, 동의하니? y!
<img src="https://images.velog.io/images/dev_cecy/post/cf6d7c6f-77ec-4f07-8bfa-0cc553c98935/%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-22%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.58.08.png" alt=""></p>
</li>
<li><p>Let’s Encrypt Subscriber Agreement에 동의하니? y!</p>
</li>
<li><p>please be patient…… Success!</p>
</li>
</ol>
<p><img src="https://images.velog.io/images/dev_cecy/post/50793744-dfdb-46d8-9ad1-001b3483d256/%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-22%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.58.26.png" alt=""></p>
<ol start="10">
<li>설치완료! 워드프레스에 들어가보면 이제 자물쇠가 채워진걸 볼 수있다.</li>
</ol>
<p><img src="https://images.velog.io/images/dev_cecy/post/cda5fe6e-fc49-45c8-b456-1448aaee1927/%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-22%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.58.42.png" alt=""></p>
<p><img src="https://images.velog.io/images/dev_cecy/post/95196ee1-5b5f-461d-afd3-e46d02f301d5/%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-22%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.58.49.png" alt=""></p>
<p>http에서 https로 변경하기 끝!</p>
<p>22.03.22 덧붙이자면,,
워드프레스로 운영하던 블로그를 벨로그로 옮겨왔다. 워드프레스를 통해 나의 내 도멘으로 블로그를 개설해본것은 좋은 경험이였다. 그러나 여러가지 이유로(?) 가장 처음 시작했던 벨로그에서 다시 블로그를 이어나가야겠다 결정했다. 벨로그 정리좀 해야겠다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[NODE.JS] BCRYPT로 비밀번호 암호화하기]]></title>
            <link>https://velog.io/@dev_cecy/NODE.JS-BCRYPT%EB%A1%9C-%EB%B9%84%EB%B0%80%EB%B2%88%ED%98%B8-%EC%95%94%ED%98%B8%ED%99%94%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@dev_cecy/NODE.JS-BCRYPT%EB%A1%9C-%EB%B9%84%EB%B0%80%EB%B2%88%ED%98%B8-%EC%95%94%ED%98%B8%ED%99%94%ED%95%98%EA%B8%B0</guid>
            <pubDate>Tue, 22 Mar 2022 06:54:08 GMT</pubDate>
            <description><![CDATA[<p>앞서 회원가입 api를 만들었을때 비밀번호를 qwe123!@#으로 입력해주면 return 값과 MongoDB에 qwe123!@#라는 비밀번호의 값이 그대로 찍혔다. 이말은 즉, 어떤 웹 사이트에서 내가 회원가입을 하면 내 비밀번호를 DB를 통해 확인 가능하다는 말이다. 아주 위험하다!! 그래서 오늘은 Bcrypt라는 암호화 해시 함수를 통해 비밀번호를 암호화해서 저장해 줄 것이다.</p>
<p><img src="https://images.velog.io/images/dev_cecy/post/8b552fd7-29ce-488a-bb4d-48bf3e5b6635/%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-22%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.51.50.png" alt=""></p>
<h1 id="bcrypt-설치하고-적용해보자">bcrypt 설치하고 적용해보자</h1>
<p>먼저, bcrypt 설치해보자. package.json의 dependencies에 예쁘게 들어온걸 확인 할 수있다.</p>
<p><code>npm install bcrypt</code>
<img src="https://images.velog.io/images/dev_cecy/post/234dadb5-be0e-47a6-b94a-a17021320d03/%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-22%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.52.09.png" alt=""></p>
<p>이번에는 설치해준 bcrypt를 사용해 비밀번호를 암호화해주는 함수를 작성해보자. </p>
<pre><code class="language-js">const mongoose = require(&#39;mongoose&#39;);
const bcrypt = require(&#39;bcrypt&#39;); // bcrypt 임포트

const saltRounds = 10; // salt값을 10으로 정해주었다. 

const userSchema = mongoose.Schema({
  name: {
    type: String,
    maxLength: 50,
  },
  email: {
    type: String,
    maxLength: 50,
    trim: true, // space를 없애준다.
    // unique: 1, // 같은값은 하나만 존재할 수 있다.
  },
  password: {
    type: String,
    maxLength: 50,
  },
  role: {
    type: Number,
    default: 0, // 값이 정해지지 않았다면 디폴트로 0!
  },
  token: {
    type: String,
  },
  tokenExp: {
    type: Number,
  },
});

userSchema.pre(&#39;save&#39;, function (next) {  // userSchema가 save 되기 전에(pre) 실행할 함수function은~

  const user = this; //  this는 userSchema를 가르킨다. 

  if (user.isModified(&#39;password&#39;)) {   // password가 수정될때만 아래 코드 실행!
    bcrypt.genSalt(saltRounds, function (err, salt) {  //  saltRounds가 10인 salt를 generate 해주자. 
      if (err) return next(err); // 에러처리

      bcrypt.hash(user.password, salt, function (err, hash) {  // user.password를 salt로 변경해서 hash로 return하는 함수~
        if (err) return next(err); // 에러처리
        user.password = hash; // user.password 자리에 hash를 할당!
        next(); // pre에서 나가 다음 코드 실행!
      });
    });
   else {
       next(); // password 변경이 아닌 경우 바로 save코드 실행 
   }
  }
});

const User = mongoose.model(&#39;User&#39;, userSchema); // userSchema를 model로 만들어준다.

module.exports = { User };
</code></pre>
<p>위 처럼 코드를 비밀번호를 암호화해주는 코드를 작성 한 뒤, 포스트맨에서 비밀번호 입력하고 register api 호출해보자.
<img src="https://images.velog.io/images/dev_cecy/post/0d0578f6-3417-4a5b-a43b-a3d7768c1638/%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-22%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.53.19.png" alt=""></p>
<p>return 값의 password를확인해보니 암호화된 값이 잘들어왔다👍🏻</p>
<h1 id="참고">참고</h1>
<p>처음에는 salt가 10자리 인줄 알았는데 리턴값을 보니 그렇지 않았다. 그래서 위키트리에서 암호화된 비밀번호의 구조를 찾아보았다. 아직 Cost가 무엇인지 왜 Salt와 Hash로 나눠 주는지 모르겠지만 이렇게 보니 구조는 눈에 들어온다.
<img src="https://images.velog.io/images/dev_cecy/post/f2393a0a-03b7-47fa-8c46-54538ab5c5c4/%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-22%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.53.35.png" alt=""></p>
<p><em><a href="https://www.youtube.com/watch?v=fgoMqmNKE18&amp;list=PL9a7QRYt5fqkZC9jc7jntD1WuAogjo_9T">John Ahn님의 유튜브 강의</a>를 통해 공부하며 글을 작성했습니다😊</em></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[NODE.JS] 비밀 정보 보호하기 (FEAT. PROCESS.ENV.NODE_ENV & .GITIGNORE)]]></title>
            <link>https://velog.io/@dev_cecy/NODE.JS-%EB%B9%84%EB%B0%80-%EC%A0%95%EB%B3%B4-%EB%B3%B4%ED%98%B8%ED%95%98%EA%B8%B0-FEAT.-PROCESS.ENV.NODEENV-.GITIGNORE</link>
            <guid>https://velog.io/@dev_cecy/NODE.JS-%EB%B9%84%EB%B0%80-%EC%A0%95%EB%B3%B4-%EB%B3%B4%ED%98%B8%ED%95%98%EA%B8%B0-FEAT.-PROCESS.ENV.NODEENV-.GITIGNORE</guid>
            <pubDate>Tue, 22 Mar 2022 06:51:05 GMT</pubDate>
            <description><![CDATA[<p>node와 MongoDB를 연결했던 날로 돌아가보자. 두 아이를 연결해주기 위해 MongoDB에서 발급받았던 키와 그 안에 본인이 직접 설정했던 비밀번호를 넣어주어야했다. &lt;비밀번호!!&gt; 이 자리에 말이다.</p>
<p>이 코드는 github에 올린다면 어떻게 될까? 누구나 나의 MongoDB 비밀번호를 알 수 있게된다. 그렇기 때문에 외부에 노출되지 않아야 하는 코드가 있다면 잘 숨겨줄 방법이 필요하다.</p>
<pre><code>// index.js

...

// 몽구스 연결
const mongoose = require(&#39;mongoose&#39;);
mongoose
  .connect(&#39;mongodb+srv://devCecy:&lt;비밀번호!!&gt;@devcecy.dprgf.mongodb.net/myFirstDatabase?retryWrites=true&amp;w=majority&#39;, {
    // useNewUrlParser: true,
    // useUnifiedTopology: true,
    // useCreateIndex: true,
    // useFindAndModify: false,
  })
  .then(() =&gt; console.log(&#39;MongoDB conected&#39;))
  .catch((err) =&gt; {
    console.log(err);
  });

...</code></pre><p>개발환경과 배포환경 두가지 경우로 나눠 비밀정보를 숨겨주려고 한다. 오늘은 개발환경을 위해 비밀정보를 숨겨보자.</p>
<p>root 디렉토리에 config라는 폴더를 생성하고, 그 안에 development.js, key.js, production.js 3가지 파일을 생성했다.</p>
<p>development.js 파일에는 개발환경을 위한 비밀정보를 작성해 줄것이고, production.js파일에는 배포환경을 위한 비밀정보를 작성해 줄것이다. 그리고 key.js 파일에서 현재 어떤환경에 있는지 파악해 그에 맞는 환경을 위한 코드로 분기를 나눠줄 것이다.</p>
<p><img src="https://images.velog.io/images/dev_cecy/post/7f2067cf-b43a-463b-8116-eaff4b5fd3c2/%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-22%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.49.40.png" alt=""></p>
<p>자, 이제 숨겨주고 싶은 아래의 URI를 뽑아와보자. 물론 실제 코드에서는 &lt;비밀번호!!&gt; 이 자리에 실제 비밀번호가 들어있을 것이다.</p>
<pre><code>&#39;mongodb+srv://devCecy:&lt;비밀번호!!&gt;@devcecy.dprgf.mongodb.net/myFirstDatabase?retryWrites=true&amp;w=majority&#39;</code></pre><p>먼저, 개발환경을 위한 development.js 파일이다.</p>
<p>다른파일에서도 사용할 수 있도록 module.export로 감싸준뒤, 변수 mongoURI에 숨기고 싶은 정보를 넣어주었다.</p>
<pre><code>// development.js

module.exports = {
  mongoURI:
    &#39;mongodb+srv://devCecy:&lt;비밀번호!!&gt;@devcecy.dprgf.mongodb.net/myFirstDatabase?retryWrites=true&amp;w=majority&#39;,
};</code></pre><p>production.js파일도 개발환경과 마찬가지로 바깥 파일에서 사용할 수 있도록 export모듈로 감사준 후, 그 안에는 process.env.MONGO_URI 라는 환경변수를 넣어주었다.</p>
<p>배포환경는 개발환경과 달리 실제 배포 후에도 비밀정보를 사용해야 하므로 Heroku라는 사이트에 MONGO_URI 라는 변수에 숨기고 싶은 코드를 넣어주어 사용해 주었다. 나는 아직 배포단계가 아니여서 실제 Heroku라는 사이트는 이용하지 않고 코드만 작성해 주었다. (웹 환경에서도 환경변수를 사용하여 개발,테스트,배포 환경에 따라 파일을 작성해 정보를 숨겨주곤 하는데, 따로 사이트를 사용하진 않았다. 그래서 이 부분은 좀 더 서칭을 해보려고한다. )</p>
<pre><code>// production.js

module.exports = {
  mongoURI: process.env.MONGO_URI,
};</code></pre><p>key.js 파일에는 어떤 환경에 있는지 파악해 분기를 나눠주는 코드를 작성한다.</p>
<p>process.env.NODE_ENV 는 환경변수로 실제 서버를 실행했을때 개발환경이면 development, 배포환경이면 production 이 찍히는 걸 확인해볼 수 있다. 그걸 이용해서 아래와 같이 분기를 해주었다. (지금은 process.env.NODE_ENV를 찍어보면 undefined가 나오는데 그래서 분기가 else로 빠져 개발환경 코드를 사용하게 된다. )</p>
<pre><code>if (process.env.NODE_ENV === &#39;production&#39;) { // 배포환경이면, 
  module.exports = require(&#39;./production&#39;); // production.js 파일 코드를 사용하고,
} else { // 배포환경 이외의 환경이라면 (현재는 배포,개발환경 2가지이기때문에!)
  module.exports = require(&#39;./development&#39;); // development.js파일 코드를 사용한다. 
}</code></pre><p>분기를 해주었으므로, 다시 index.js 파일로 돌아와 비밀정보였던 URI자리에 방금 만든 key.js 코드를 넣어주자.</p>
<p>./config/key을 require로 가져온 후, 원래 URI가 있던 자리에 넣어주면 된다. key.js파일은 {}객체를 export하고 있는데, 실제로 사용하고 싶은건 그 객체안의 mongoURI이기 때문에 config.mongoURI로 가져오면 된다.</p>
<pre><code>...

// development와 production 분기
const config = require(&#39;./config/key&#39;);

...

// 몽구스 연결
const mongoose = require(&#39;mongoose&#39;);
mongoose
  .connect(config.mongoURI, {
    // useNewUrlParser: true,
    // useUnifiedTopology: true,
    // useCreateIndex: true,
    // useFindAndModify: false,
  })
  .then(() =&gt; console.log(&#39;MongoDB conected&#39;))
  .catch((err) =&gt; {
    console.log(err);
  });
</code></pre><p>마지막으로, 개발환경을 위한 development.js파일에는 여전히 비밀정보들이 들어있다. 그러므로 .gitignore 파일에 development.js파일을 넣어주면 github에 코드가 올리가지 않게 된다.</p>
<pre><code>// .gitignore

node_modules

development.js </code></pre><p><em><a href="https://www.youtube.com/watch?v=fgoMqmNKE18&amp;list=PL9a7QRYt5fqkZC9jc7jntD1WuAogjo_9T">John Ahn님의 유튜브 강의</a>를 통해 공부하며 글을 작성했습니다😊</em></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[NODE.JS] NODEMON 설치하기 (FEAT.서버코드 실시간 반영)]]></title>
            <link>https://velog.io/@dev_cecy/NODE.JS-NODEMON-%EC%84%A4%EC%B9%98%ED%95%98%EA%B8%B0-FEAT.%EC%84%9C%EB%B2%84%EC%BD%94%EB%93%9C-%EC%8B%A4%EC%8B%9C%EA%B0%84-%EB%B0%98%EC%98%81</link>
            <guid>https://velog.io/@dev_cecy/NODE.JS-NODEMON-%EC%84%A4%EC%B9%98%ED%95%98%EA%B8%B0-FEAT.%EC%84%9C%EB%B2%84%EC%BD%94%EB%93%9C-%EC%8B%A4%EC%8B%9C%EA%B0%84-%EB%B0%98%EC%98%81</guid>
            <pubDate>Tue, 22 Mar 2022 06:48:39 GMT</pubDate>
            <description><![CDATA[<p>서버를 만들면서 처음 불편함을 느낀것이 서버 코드를 수정했을때 수정된 내용이 실시간으로 반영되지 않는다는 것이였다😱 react와 next로 프론트 작업을 하던 나에게는 매우 충격적인 일…! 그러나 역시, 서버 수정사항을 실시간으로 반영해주는 nodemon이라는 아이가 있었다!</p>
<p>nodemon은 개발환경에서만 사용할것이므로 --save-dev 를 붙여 devDependencies에 설치해주었다.</p>
<pre><code>npm install nodemon --save-dev


// package.json

...
  &quot;devDependencies&quot;: {
    &quot;nodemon&quot;: &quot;^2.0.15&quot;
  }</code></pre><p>package.json에 nodemon이 잘 설치되었다면, nodemon을 통해 서버가 실행될 수 있도록 scripts를 작성해준다.</p>
<p><code>&quot;backend&quot; : &quot;nodemon index.js&quot;</code></p>
<pre><code> &quot;scripts&quot;: {
    &quot;start&quot;: &quot;node index.js&quot;,
    &quot;backend&quot;: &quot;nodemon index.js&quot;,
    &quot;test&quot;: &quot;echo \&quot;Error: no test specified\&quot; &amp;&amp; exit 1&quot;
  },</code></pre><p>이제 npm run backend로 서버를 실행해보면 nodemon이 잘 실행되는 것을 볼 수 있다.
<img src="https://images.velog.io/images/dev_cecy/post/750fb7ed-9f84-4dba-80ac-800c77432f02/%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-22%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.47.59.png" alt=""></p>
<p>hello word 옆에 🙂 적어주고 리프레시 해주니 바로 반영된 것을 확인할 수 있다. nodemon 👍🏻</p>
<pre><code class="language-app.get(&#39;/&#39;,">  res.send(&#39;hello world :-)&#39;);
});</code></pre>
<p><img src="https://images.velog.io/images/dev_cecy/post/18469a01-6813-4c9b-9e04-2e0774acc4b3/%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-22%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.48.14.png" alt=""></p>
<p><em><a href="https://www.youtube.com/watch?v=fgoMqmNKE18&amp;list=PL9a7QRYt5fqkZC9jc7jntD1WuAogjo_9T">John Ahn님의 유튜브 강의</a>를 통해 공부하며 글을 작성했습니다😊</em></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[NODE.JS] 회원가입 API 생성 (FEAT.POSTMAN)]]></title>
            <link>https://velog.io/@dev_cecy/NODE.JS-%ED%9A%8C%EC%9B%90%EA%B0%80%EC%9E%85-API-%EC%83%9D%EC%84%B1-FEAT.POSTMAN</link>
            <guid>https://velog.io/@dev_cecy/NODE.JS-%ED%9A%8C%EC%9B%90%EA%B0%80%EC%9E%85-API-%EC%83%9D%EC%84%B1-FEAT.POSTMAN</guid>
            <pubDate>Tue, 22 Mar 2022 06:46:51 GMT</pubDate>
            <description><![CDATA[<p>지난 포스팅에서 만들어둔 코드에 회원가입 api기능을 할 register api를 만들어보자. 그리고 아직 프론트 작업이 이루어지지 않았기 때문에 postman을 통해 api호출을 해보았다.</p>
<p>지난 포스팅까지 작성해 둔 코드위에 회원가입 api 생성을 위해 코드를 추가하고 볼드처리했다.</p>
<pre><code>const express = require(&#39;express&#39;); // express 임포트
const app = express(); // app생성
const port = 5000;


const { User } = require(&#39;./models/User&#39;); // 1. 지난 번 만들어 두었던 User.js(스키마) 임포트


app.use(express.urlencoded({ extended: true })); // application/x-www-form-urlencode

app.use(express.json()); // application/json


// 1.
app.get(&#39;/&#39;, function (req, res) {
  res.send(&#39;hello world&#39;);
});

// 2. register api
app.post(&#39;/register&#39;, (req, res) =&gt; {
  const user = new User(req.body); // 상단에서 require로 가져온 User 스키마에 req.body를 담아 user라는 인스턴스로 만든다.

  user.save((err, userInfo) =&gt; {
    if (err) return res.json({ success: false, err }); // err일 경우 return 값
    return res.status(200).json({
      //status가 200일 경우 return 값
      success: true,
      userInfo,
    });
  });
});

app.listen(port, () =&gt; console.log(`${port}포트입니다.`));

// 몽구스 연결
const mongoose = require(&#39;mongoose&#39;);
mongoose
  .connect(
    &#39;mongodb+srv://devCecy:algusl109@devcecy.dprgf.mongodb.net/myFirstDatabase?retryWrites=true&amp;w=majority&#39;,
    {
      // useNewUrlParser: true,
      // useUnifiedTopology: true,
      // useCreateIndex: true,
      // useFindAndModify: false,
    }
  )
  .then(() =&gt; console.log(&#39;MongoDB conected&#39;))
  .catch((err) =&gt; {
    console.log(err);
  });
</code></pre><p>postman은 먼저 <a href="https://www.postman.com/">https://www.postman.com/</a> 에서 다운받아주면된다. 웹버전, 데스크톱 버전 둘다 제공하고 있으며 나는 데스크톱에 다운받아 쓰고있다.</p>
<ol start="0">
<li><p>postman 상단은 request부분이고 하단이 response부분이다. request는 유저가 회원가입시 입력하는 자신의 정보라고 생각하면된다. response는 유저가 회원가입 버튼을 클릭하면 호출되어 그 결과를 알려주는 부분이라고 생각하면된다. 물론 실제 response는 개발자가 확인하여 회원가입 성공, 실패로 나누어 처리할거싱고, 유저는 회원가입 완료! 혹은 오류! 라는 문구를 보게되는 것이다.</p>
</li>
<li><p>회원가입은 request안에 데이터를 보내고 저장해야 하므로 post 메소드를 사용한다.</p>
</li>
<li><p>localhost로 테스중이기 때문에 <a href="http://localhost:5000/register">http://localhost:5000/register</a> 로 url을 만들어주고, (포트는 자신이 지정한 포트로 사용!)</p>
</li>
<li><p>body – raw – JSON 으로 선택해준뒤, json형태로 회원가입시 필요한 데이터를 넣어준다. (name, email, password, role)</p>
</li>
<li><p>send 버튼을 누르면 하단에 response가 온다. 나는 success:true, userInfo 가 들어오도록 했다. 데이터가 예쁘게 들어왔다!</p>
</li>
</ol>
<p><img src="https://images.velog.io/images/dev_cecy/post/4cccd359-dedf-4fe6-abb7-b4880b129d10/%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-22%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.45.54.png" alt=""></p>
<p>이제 MongoDB에 회원가입한 데이터가 잘 들어왔나 확인해보자! Browse Collections 를 클릭,</p>
<p><img src="https://images.velog.io/images/dev_cecy/post/8c4b2844-b2be-46c6-919b-49901d0ebdae/%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-22%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.46.07.png" alt="">
방금 보낸 회원가입 데이터가 DB에 잘 쌓여있다! 회원가입 성공!</p>
<p><img src="https://images.velog.io/images/dev_cecy/post/435da5dc-b9d0-4efb-b310-383b7a11960a/%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-22%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.46.15.png" alt=""></p>
<p><em><a href="https://www.youtube.com/watch?v=fgoMqmNKE18&amp;list=PL9a7QRYt5fqkZC9jc7jntD1WuAogjo_9T">John Ahn님의 유튜브 강의</a>를 통해 공부하며 글을 작성했습니다😊</em></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[NODE.JS] SSH KEY 발급 그리고 GITHUB 푸시]]></title>
            <link>https://velog.io/@dev_cecy/NODE.JS-SSH-KEY-%EB%B0%9C%EA%B8%89-%EA%B7%B8%EB%A6%AC%EA%B3%A0-GITHUB-%ED%91%B8%EC%8B%9C</link>
            <guid>https://velog.io/@dev_cecy/NODE.JS-SSH-KEY-%EB%B0%9C%EA%B8%89-%EA%B7%B8%EB%A6%AC%EA%B3%A0-GITHUB-%ED%91%B8%EC%8B%9C</guid>
            <pubDate>Tue, 22 Mar 2022 06:44:32 GMT</pubDate>
            <description><![CDATA[<p>SSH key를 발급받아 github에 연동한 뒤 지금까지 작성해 놓은 코드를 푸시해보자👊🏻</p>
<ol>
<li>터미널에 아래 명령어로 ssh key가 발급되어 있는지 먼저 확인한다.</li>
</ol>
<p>```$ ls -a ~/.ssh</p>
<blockquote>
<p>id_rsa  id_rea.pub // 두 디렉토리가 있다면 ssh key가 이미 발급되어 있는것이다. </p>
</blockquote>
<pre><code>![](https://images.velog.io/images/dev_cecy/post/74c69531-4f92-43eb-b1a8-3afa46b85e56/%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-22%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.41.16.png)

2. 없다면 만들어보자! 아래 명령어를 입력한뒤 엔터엔터엔터! 그럼 아래처럼 키의 랜덤아트 이미지가 확인된다.
</code></pre><p>ssh-keygen -t rsa -b 4096 -C &quot;<a href="mailto:your_email@example.com">your_email@example.com</a>&quot;</p>
<p>// ssh-keygen -t ed25519 -C &quot;<a href="mailto:im.ceciliaan@gmail.com">im.ceciliaan@gmail.com</a>&quot;</p>
<pre><code>![](https://images.velog.io/images/dev_cecy/post/6661fff7-df57-4c62-ac8e-375becd94d0f/%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-22%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.41.37.png)

3. 백그라운드에서 ssh-agent를 시작해준다.</code></pre><p>$ eval &quot;$(ssh-agent -s)&quot;</p>
<blockquote>
<p>Agent pid 20016</p>
</blockquote>
<pre><code>![](https://images.velog.io/images/dev_cecy/post/ea569870-3a4e-4efa-9b6e-a0771bead078/%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-22%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.42.04.png)

4. macOS Sierra 10.12.2 이상을 사용하는 경우 ~/.ssh/config 파일을 통하여 ssh-agent에 key를 자동으로 로드하고 키체인에 암호를 저장하도록 설정해주어야 한다. 파일 생성전 먼저 해당 파일이 먼저 있나 확인해 줬다.
</code></pre><p>$ open ~/.ssh.config</p>
<blockquote>
<p>The file /Users/ce._.cy/.ssh/config does not exist.</p>
</blockquote>
<pre><code>![](https://images.velog.io/images/dev_cecy/post/bdc6d88a-b9ae-4206-8c1a-bb0d74ce23f6/%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-22%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.42.24.png)

5. 파일이 존재하지 않으므로 하나 만들어준다. 그리고 파일을 열어 Host~ 부터의 코드를 작성해 준다.</code></pre><p>$ touch ~/.ssh/config
$ open ~/.ssh.config</p>
<p>// 오픈된 파일에 아래 코드를 넣어준다. 
Host *
  AddKeysToAgent yes
  UseKeychain yes
  IdentityFile ~/.ssh/id_ed25519</p>
<pre><code>
6. SSH key를 ssh-agent에 추가하고 키체인에 암호를 저장해준다.</code></pre><p>$ ssh-add -K ~/.ssh/id_ed25519</p>
<blockquote>
<p>Identity added: ~</p>
</blockquote>
<pre><code>![](https://images.velog.io/images/dev_cecy/post/3fcd777f-b36c-45fd-a02d-066b813fb305/%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-22%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.42.54.png)

7. 생성된 SSH key를 확인해보자. 터미널에 아래의 코드를 적고 엔터 치면 response는 없다. 대신 그 상태에서 메모장 같은곳에 붙여넣기를 하면 생성된 자신의 SSH key를 확인할수 있다.

```$ pbcopy &lt; ~/.ssh/id_ed25519.pub```

8. 생성된 SSH key를 이제 github에 연동해주어야 한다. github 프로필을 클릭하면 settings가 있고 거기서 SSH and GPGkeys 메뉴를 클릭해 준다.
![](https://images.velog.io/images/dev_cecy/post/92330e24-a865-4d67-8e4c-8961974832fb/%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-22%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.43.24.png)

9. title을 적고, key안에 복사한 자신의 SSH key를 붙여넣어주고 add SSH key 버튼을 클릭해준다.

![](https://images.velog.io/images/dev_cecy/post/bf2c8db5-0188-442c-87cc-f079fa54ab7f/%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-22%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.43.35.png)

10. 이제 node.js 프로젝트 코드를 안전하게 깃헙에 푸시할 수 있게 되었다! 프로젝트를 로컬에 먼저 저장한 후 remote 저장소인 github에 push 해주자. 그럼 끝 !👊🏻</code></pre><p>$ git add . 
$ git commit -m &quot;first commit&quot;
$ git branch -M main // 이건 필수는 아니지만 github도 master 브랜치를 main으로 변경해 쓰길권고하기 있기 때문에 변경해주었다. 
$ git remote add origin <a href="https://github.com/devCecy/boilet-plate-feat.node.js-.git">https://github.com/devCecy/boilet-plate-feat.node.js-.git</a>
$ git push -u origin main</p>
<pre><code>

_[John Ahn님의 유튜브 강의](https://www.youtube.com/watch?v=fgoMqmNKE18&amp;list=PL9a7QRYt5fqkZC9jc7jntD1WuAogjo_9T)와 [github에서 제공하는 문서](https://docs.github.com/en/authentication/connecting-to-github-with-ssh/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent)를 바탕으로 글을 작성했습니다._
</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[[NODE.JS] SCHEMA 작성하기]]></title>
            <link>https://velog.io/@dev_cecy/NODE.JS-SCHEMA-%EC%9E%91%EC%84%B1%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@dev_cecy/NODE.JS-SCHEMA-%EC%9E%91%EC%84%B1%ED%95%98%EA%B8%B0</guid>
            <pubDate>Tue, 22 Mar 2022 06:38:55 GMT</pubDate>
            <description><![CDATA[<p>지난번에는 node와 MongoDB를 연결했다. 오늘은 MongoDB에 저장할 데이터 구조 즉, schema를 작성하고 외부에서 사용할 수있도록 export까지 해보자.</p>
<p>schema는 데이터의 구조, 표현 방법, 데이터 간의 관계를 언어로 정의한 구조다. 쉽게말해 아래의 코드에서 const로 선언된 userSchemadml {} 안쪽 부분이 schema이다. 그리고 model은 그 schema를 감싸주는 역할을 한다.</p>
<p>코드로 확인해보자. root에서 Models 디렉토리를 만들고 그안에 User.js 파일을 생성했다.</p>
<pre><code class="language-js">// User.js

const mongoose = require(&#39;mongoose&#39;); // mongoose를 선언해주고,

const userSchema = mongoose.Schema({  // userSchema라는 이름의 schema를 작성해준다. 
  name: { 
    type: String,
    maxLength: 50,
  },
  emial: {
    type: String,
    maxLength: 50,
    trim: true, // space를 없애준다.
    unique: 1, // 같은값은 하나만 존재할 수 있다.
  },
  role: {
    type: Number,
    default: 0, // 값이 정해지지 않았다면 디폴트로 0!
  },
  token: {
    type: String,
  },
  tokenExp: {
    type: Number,
  },
});

const User = mongoose.model(&#39;User&#39;, userSchema); // userSchema를 model로 감싸준다. 

module.exports = { User }; // User라는 모델을 본 파일 밖에서도 사용할 수 있도록 export 구문을 작성해준다. </code></pre>
<p><em><a href="https://www.youtube.com/watch?v=fgoMqmNKE18&amp;list=PL9a7QRYt5fqkZC9jc7jntD1WuAogjo_9T">John Ahn님의 유튜브 강의</a>를 통해 공부하며 글을 작성했습니다😊</em></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[NODE.JS] MONGO DB 연동하기 (FEAT. EXPRESS & MONGOOSE )]]></title>
            <link>https://velog.io/@dev_cecy/NODE.JS-MONGO-DB-%EC%97%B0%EB%8F%99%ED%95%98%EA%B8%B0-FEAT.-EXPRESS-MONGOOSE</link>
            <guid>https://velog.io/@dev_cecy/NODE.JS-MONGO-DB-%EC%97%B0%EB%8F%99%ED%95%98%EA%B8%B0-FEAT.-EXPRESS-MONGOOSE</guid>
            <pubDate>Tue, 22 Mar 2022 06:36:06 GMT</pubDate>
            <description><![CDATA[<p>서버를 연동해서 진행해보고 싶은 프로젝트가 생겼다. 그래서 간단하게 서버를 만들어보려고한다.</p>
<p>node.js는 웹브라우저에서만 사용되던 javascript를 웹 외부에서도 실행할 수 있는 환경을 제공해준다. 그래서 node.js를 통해 서버를 생성할 수 있게 되는것이다. javascript 하나의 언어로 웹프론트와과 웹서버 모두를 만들 수 있기 때문에 많이 사용되고있다. 사실, 나도 그래서 선택했다.</p>
<p>node.js를 통해 웹 서버를 생성하기 위해서는 express 라는 node 웹 프레임워크를 설치해주면 된다.</p>
<p>실제 데이터를 저장할 곳은 Mongo DB로 MongoDB는 NoSQL(관계형 데이터베이스가 아닌 SQL) 데이터베이스다.</p>
<p>mongoose는 node.js와 Mongo DB를 연동해주는 라이브러리이다.</p>
<p>이제, node.js와 Mongo DB를 연동해보자.</p>
<h1 id="mongo-db-생성">Mongo DB 생성</h1>
<ol>
<li><p>Mongo DB 사이트에 접속한뒤, 아이디가 없다면 회원가입 후 로그인 한다.</p>
</li>
<li><p>로그인 후 Create 버튼을 클릭해주면,
<img src="https://images.velog.io/images/dev_cecy/post/d5a745b3-9b5b-464c-a587-4ba581e1078c/%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-22%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.29.47.png" alt=""></p>
</li>
<li><p>Create New Cluster페이지로 넘어간다. 나는 AWS를 사용할거기 때문에 AWS선택! 다른 클라우드를 사용할 예정이라면 그걸 선택하면 된다.
<img src="https://images.velog.io/images/dev_cecy/post/8f7539ff-2077-4863-8171-0a71e1aaae78/%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-22%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.30.05.png" alt=""></p>
</li>
<li><p>서울은 FREE TIER가 지원되지 않기 때문에 가장 가까운 도쿄로 선택해 주었다.
<img src="https://images.velog.io/images/dev_cecy/post/be9adf92-c0aa-47fc-bd00-2ca5893569d8/%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-22%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.30.27.png" alt=""></p>
</li>
</ol>
<p>5.M10 을 선택해준다. 이 상태로 최종 create을 해주면 1~5분 뒤 cluster가 생성된다.
<img src="https://images.velog.io/images/dev_cecy/post/aed6ae08-2bec-4fc4-87ec-3ff78e95558e/%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-22%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.30.43.png" alt=""></p>
<p>6.좌측 메뉴에서 Database를 클릭해보자. 아직 cluster가 생성중이라면 생성중 안내가 나올것이고, 완료되면 아래와 같은화면을 볼 수 있다.
<img src="https://images.velog.io/images/dev_cecy/post/0f38958b-ea01-43eb-9b8d-c01359c7de9e/%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-22%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.31.00.png" alt=""></p>
<ol start="7">
<li><p>Connect를 클릭해준다.
<img src="https://images.velog.io/images/dev_cecy/post/f641101f-223a-4a5a-8e56-7200080e8b12/%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-22%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.31.15.png" alt=""></p>
</li>
<li><p>1번의 Add Your Current IP Address를 클릭하면 이미 ip주소가 입력되어있을 것이다. 그럼 add 버튼을 눌러주기만 하면된다. 그리고 나는 User를 이미 입력해주어서 입력칸이 안나오는데, 2번에 username과 password를 입력해 주면된다. (추후 앱 연결에 필요하기 때문에 꼭 기억할것!)</p>
</li>
</ol>
<p><img src="https://images.velog.io/images/dev_cecy/post/865b28a6-3ad2-4953-bc3f-87a99c76a068/%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-22%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.31.34.png" alt=""></p>
<ol start="9">
<li><p>choose a connection method를 클릭하여 다음 스텝으로 넘어간다. 그리고 두번째 Connect your aplication을 클릭해준다.
<img src="https://images.velog.io/images/dev_cecy/post/cfdae599-bac4-42ee-810d-c95f29213ca4/%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-22%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.31.48.png" alt=""></p>
</li>
<li><p>2번의 코드를 복사한다!
<img src="https://images.velog.io/images/dev_cecy/post/78656330-7196-4a1e-b3bf-69c76860e519/%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-22%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.32.06.png" alt=""></p>
</li>
<li><p>MongoDB와 나의 app을 연결하기 위해 먼저 vscode에디터를 사용하여 프로젝트를 하나 생성해 놓았다.</p>
</li>
</ol>
<ul>
<li>express를 설치해준다. <code>npm install express</code></li>
<li>mongoose를 설치해준다. <code>npm install mongoose</code></li>
<li>Index.js에 아래와 같이 작성해준다.</li>
<li>mongoose.connect() 안쪽에는 MongoDB에서 복사해두었던 코드를 붙여넣어주면된다. 그리고 <code>&lt;password&gt;</code>부분에 역시나 MongoDB에서 지정해 주었던 비밀번호를 입력해준다. &lt;&gt;괄호 모두 제거하고 비밀번호만 넣어주어야한다!</li>
<li>몽구스의 useNewUrlPaser등의 옵션들은 에러 생성으로 잠시 주석 처리를 해놓았다. </li>
</ul>
<pre><code class="language-js"> // index.js
const express = require(&#39;express&#39;); // express 임포트
const app = express(); // app생성
const port = 5000;

app.get(&#39;/&#39;, function (req, res) {
  res.send(&#39;hello world!!&#39;);
});

app.listen(port, () =&gt; console.log(`${port}포트입니다.`));

// 몽구스 연결
const mongoose = require(&#39;mongoose&#39;);
mongoose
  .connect(
    &#39;mongodb+srv://devCecy:&lt;password&gt;@devcecy.dprgf.mongodb.net/myFirstDatabase?retryWrites=true&amp;w=majority&#39;,
    {
      // useNewUrlPaser: true,
      // useUnifiedTofology: true,
      // useCreateIndex: true,
      // useFindAndModify: false,
    }
  )
  .then(() =&gt; console.log(&#39;MongoDB conected&#39;))
  .catch((err) =&gt; {
    console.log(err);
  });
</code></pre>
<ol start="12">
<li>npm run start로 실행해주면 콘솔에 아래와같이 찍히는 걸 볼 수있다. (물론, package.json의 script에 &quot;start&quot;: &quot;node index.js&quot;를 추가해주어야 가능하다.)</li>
</ol>
<p>나의 앱과 몽고DB 첫 연결 성공!</p>
<p>  <img src="https://images.velog.io/images/dev_cecy/post/0fbdbd71-c54b-420a-a230-ee6955c6bd7e/%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-22%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.33.39.png" alt=""></p>
<h1 id="mongoose-옵션-에러">Mongoose 옵션 에러?</h1>
<p>서칭해보니 몽구스6.0이상의 버전에서는 지원하지 않는 옵션이라고 한다. 그래서 삭제해주었다!
<img src="https://images.velog.io/images/dev_cecy/post/ffd934f2-d047-4865-b445-fd5a48086648/%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-22%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.35.24.png" alt=""></p>
<p><em><a href="https://www.youtube.com/watch?v=fgoMqmNKE18&amp;list=PL9a7QRYt5fqkZC9jc7jntD1WuAogjo_9T">John Ahn님의 유튜브 강의</a>를 통해 공부하며 글을 작성했습니다😊</em></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[브라우저는 어떻게 렌더링 될까?]]></title>
            <link>https://velog.io/@dev_cecy/%EB%B8%8C%EB%9D%BC%EC%9A%B0%EC%A0%80%EB%8A%94-%EC%96%B4%EB%96%BB%EA%B2%8C-%EB%A0%8C%EB%8D%94%EB%A7%81-%EB%90%A0%EA%B9%8C</link>
            <guid>https://velog.io/@dev_cecy/%EB%B8%8C%EB%9D%BC%EC%9A%B0%EC%A0%80%EB%8A%94-%EC%96%B4%EB%96%BB%EA%B2%8C-%EB%A0%8C%EB%8D%94%EB%A7%81-%EB%90%A0%EA%B9%8C</guid>
            <pubDate>Tue, 22 Mar 2022 06:21:30 GMT</pubDate>
            <description><![CDATA[<p>앞서 웹의 동작방식을 알아보며, 클라이언트가 서버에 데이터를 요청하고 서버는 그 요청에 응답한다는 것을 알았습니다.</p>
<p>오늘은 클라이언트가 서버로부터 응답받은 데이터를 어떻게 브라우저에 렌더링하는지 그 과정에 대해 알아보겠습니다.</p>
<h1 id="브라우저의-렌더링-과정">브라우저의 렌더링 과정</h1>
<p>먼저, 브라우저의 렌더링 과정을 크게 나눠보면 아래와 같습니다.
<img src="https://images.velog.io/images/dev_cecy/post/18615f88-8f0e-41c6-9ac6-dc4d61d7d4f3/%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-22%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.14.13.png" alt=""></p>
<h2 id="브라우저의-렌더링-과정-1">브라우저의 렌더링 과정</h2>
<ol>
<li>브라우저는 HTML, CSS, 자바스크립트, 이미지, 폰트파일 등 렌더링에 필요한 리소스를 서버에 요청하고 응답을 받습니다. (여기까지는 웹의 동작방식에서 확인했습니다.)</li>
<li>브라우저의 렌더링 엔진은 서버로부터 응답받은 HTML과 CSS를 *파싱하여 DOM과 CSSOM을 생성하고, 이 둘을 결합하여 렌더트리를 생성합니다.</li>
<li>브라우저의 자바스크립트 엔진은 서버로부터 응답받은 자바스크립트를 파싱하여 AST(Abstract Syntax Tree)를 생성하고 바이트 코드로 변환하여 실행합니다. 만약 이때, 자바스크립트가 DOM API를 통해 DOM이나 CSSOM을 변경한다면, 변경된 DOM과 CSSOM은 다시 렌더트리로 결합됩니다.</li>
<li>결합된 렌더트리를 기반으로 HTML요소의 레이아웃을 계산하고 브라우저에 HTML요소를 페인팅 합니다.</li>
</ol>
<p>*파싱(pasing)은 문자열을 의미있는 토큰(token)으로 분해하고, 문법적 의미와 구조를 반영하여 트리형태의 자료구조인 파스 트리(parse tree)를 만드는 과정을 말합니다.</p>
<p>이제 위의 과정을HTML &gt; CSS &gt; Javascript 순서로 자세하게 뜯어보겠습니다.</p>
<h2 id="html파싱과-dom-생성">HTML파싱과 DOM 생성</h2>
<p>HTML문서를 파싱하여 그 결과물인 DOM을 구성하기까지의 과정은 아래와 같습니다.
<img src="https://images.velog.io/images/dev_cecy/post/f5c1a5a1-108b-4a4c-ac74-cecdf6778f88/%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-22%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.15.14.png" alt=""></p>
<ol>
<li>서버는 브라우저로부터 요청받은 HTML 파일을 읽어드린후 &gt; 메모리에 저장하고 &gt; 그 메모리에 저장된 바이트(2진수: 101101000100…)을 응답합니다.</li>
<li>브라우저는 응답받은 바이트 형태의 문서를 meta태그의 charset 어트리뷰트에 지정된 인코딩방식(UTF-8)에 따라 문자열로 반환합니다.</li>
<li>문자열로 변환된 HTML문서를 이번에는 문법적 의미를 갖는 코드의 최소 단위인 토큰(token)으로 분해합니다.</li>
<li>토큰은 객체로 변환하여 노드를 생성합니다.</li>
<li>생성된 노드는 HTML요소간의 부자관계에 따라 트리 자료구조 즉 DOM(Document Object Model)으로 구성됩니다.</li>
</ol>
<h2 id="css파싱과-cssom-생성">CSS파싱과 CSSOM 생성</h2>
<p>렌더링 엔진은 HTML문서를 한줄 한줄 순차적으로 파싱하며 DOM을 생성해 나갑니다. 그러다 CSS를 로드하는 link태그 혹은 style태그를 만나면 DOM생성을 중지한 후 CSS파싱의 결과물인 CSSOM을 생성하는 과정을 진행합니다.</p>
<pre><code class="language-js">&lt;!DOCTYPE html&gt;
&lt;html&gt;
 &lt;head&gt;
  &lt;meta charset=&quot;UTF-8&quot;&gt; // 여기까지 해석한후, 
  &lt;link rel=&quot;stylesheet&quot; href=&quot;style.css&quot;&gt; //link 태그를 만나면서 DOM생성을 중지하고 CSS파일을 서버에 요청한 후 응답받아 CSS파싱을 시작합니다. 

    ...</code></pre>
<p>CSS파싱 과정은 바이트 &gt; 문자 &gt; 토큰 &gt; 노드 &gt; CSSOM 생성 순으로 HTML의 파싱과정과 동일합니다.
<img src="https://images.velog.io/images/dev_cecy/post/d51ee730-39ab-4a9f-a721-483f1d1df281/%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-22%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.16.25.png" alt=""></p>
<h2 id="렌더트리-생성">렌더트리 생성</h2>
<p>지금까지 렌더링 엔진이 HTML과 CSS를 파싱하여 DOM과 CSSOM을 생성했습니다. 이제 이 둘을 렌더트리로 결합하여 레이아웃을 계산하고 브라우저에 그려내기만 하면 됩니다.
<img src="https://images.velog.io/images/dev_cecy/post/30b5ac49-4e92-47d0-8aa6-bbb537748877/%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-22%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.16.44.png" alt=""></p>
<p>렌더트리는 이름 그대로 렌더링을 위한 트리형태의 자료구조 입니다. 그렇기 때문에 화면에 렌더링 되지 않아야하는 노드들은 제외하여 보여줄 것들로만 렌더트리를 구성합니다. 예를 들면 HTML의 meta태그, script태그 혹은 CSS의 display: none과 같은 요소들은 포함되지 않습니다.</p>
<p>완성된 렌더트리는 HTML요소의 레이아웃을 계산하고, 브라우저에 픽셀을 렌더링 하는 페인팅 처리에 입력됩니다. 이렇게 우리가 렌더링 된 화면을 볼 수 있게 됩니다.</p>
<p><img src="https://images.velog.io/images/dev_cecy/post/f8c3f58a-4c6c-4e43-8018-b30634e9ff07/%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-22%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.17.05.png" alt=""></p>
<p>위의 렌더링 과정은 아래의 경우에 의해 반복 실행될 수 있습니다.</p>
<ul>
<li>자바스크립트에 의해 노드가 추가되거나 삭제되는 경우</li>
<li>브라우저 리사이징에 의한 뷰포트 크기가 변경되는 경우</li>
<li>레이아웃을 변경시키는 스타일이 변경되는 경우</li>
</ul>
<p>레이아웃 계산과 페인팅을 다시 실행하게 만드는 것은 반복되는 리렌더링을 만들어 내므로 성능에 악영향을 줄 수 있으므로 주의할 필요가 있습니다.</p>
<h2 id="자바스크립트-파싱">자바스크립트 파싱</h2>
<p>자바스크립트의 파싱은 CSS파싱과 마찬가지로 렌더링 엔진이 HTML 문서를 한줄 씩 읽어나가다 script태그를 만나면 자바스크립트 엔진에 제어권을 넘기며 시작됩니다.</p>
<p>자바스크립트 엔진은 CPU가 이해할 수 있는 저수준 언어로 자바스크립트 코드를 파싱하고 &gt; DOM, CSSOM과 같은 *AST(Abstract Syntax Tree, 추살적 구문 트리)를 생성하며 &gt; AST를 기반으로 바이트코드를 생성하여 &gt; 인터프리터가 실행될 수 있도록 만듭니다.
<img src="https://images.velog.io/images/dev_cecy/post/8ef0e003-8e45-491a-a97f-6c3109e45099/%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-22%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.17.50.png" alt=""></p>
<ul>
<li>AST는 토큰에 문법적 의미과 구조를 반영한 트리형태의 자료구조입니다.</li>
</ul>
<h2 id="리플로우와-리페인트">리플로우와 리페인트</h2>
<p>자바스크립트 코드가 실행되는 과정에서 DOM과 CSSOM을 변경하는 DOM API가 사용되면 변경된 DOM과 CSSOM이 다시 렌더트리로 결합되고 레이아웃과 페인트 과정을 거쳐 다시 렌더링 됩니다. 이 과정을 리플로우(reflow), 리페인트(repaint)라고 합니다.</p>
<p>리플로우는 레이아웃을 다시 계산하는 것이며, 리페인트는 재결합된 렌더트리를 기반으로 다시 페인트하는 것입니다. 리플로우는 노드의 추가/삭제, 요소의 크기/위치 변경, 윈도우의 리사이징 등 레이아웃에 영향을 주는 경우에만 실행되기 때문에 리플로우와 리페인트가 반드시 순차적으로 실행되는 것은 아닙니다. 레이아웃의 변화가 없다면 리페인트만 실행되기 때문입니다.
<img src="https://images.velog.io/images/dev_cecy/post/98c8f840-6d15-4b76-99c7-46737622b741/%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-22%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.18.12.png" alt=""></p>
<p>여기까지 브라우저의 렌더링 과정을 살펴보았으며 관련하여 함께 알아두면 좋을 사항도 살펴봅시다.</p>
<h1 id="더-알아두면-좋은-사항">더 알아두면 좋은 사항</h1>
<h2 id="자바스크립트-파싱에-의한-html-파싱의-중단">자바스크립트 파싱에 의한 HTML 파싱의 중단</h2>
<p>HTML, CSS, 자바스크립트를 처음에 배우게되면 script 태그를 바디의 가장 하단에 삽입하라고 배우셨을 것입니다. 그 이유에 대해서 자세히 알아봅시다.</p>
<p>렌더링 엔진과 자바스크립트 엔진 코드를 직렬적으로 파싱하게 됩니다. 즉, 위에서 아래로 한줄 한줄 동기적으로 읽는 다는 말이죠.</p>
<pre><code class="language-js">&lt;!DOCTYPE html&gt; 
 &lt;html&gt;  
  &lt;head&gt;   
   &lt;meta charset=&quot;UTF-8&quot;&gt;
   &lt;link rel=&quot;stylesheet&quot; href=&quot;style.css&quot;&gt; //HTML 파싱 중단 &gt; CSS 파싱 
   &lt;script src=&quot;app.js&quot;&gt;&lt;/script&gt; //HTML 파싱 중단 &gt; 자바스크립트 파싱/실행 
    ...
    ```
script 태가그 위의 코드와 같이 헤드안에 있을 경우 다음과 같은 문제가 발생할 수 있습니다.

1. DOM이 완성되지 않은 상태에서 자바스크립트의 코드가 DOM Api를 통해 DOM을 조작하면 에러가 발생할 수 있습니다.
2. 자바스크립트의 로딩/파싱/실행으로 인해 페이지의 로딩 시간이 길어질 수 있습니다.

그렇기때문에 script코드는 DOM이 모두 생성된 후 파싱/실행될 수 있도록 아래와 같이 바디의 가장 하단에 적어주면 DOM조작시 오류가 없고, HTML 파싱이 블로킹 없이 실행되어 페이지 로딩시간이 단축됩니다.

```js
&lt;!DOCTYPE html&gt; 
 &lt;html&gt;  
  &lt;head&gt;   
   &lt;meta charset=&quot;UTF-8&quot;&gt;
   &lt;link rel=&quot;stylesheet&quot; href=&quot;style.css&quot;&gt;
  &lt;/head&gt;
  &lt;body&gt;
   ....
   &lt;script src=&quot;app.js&quot;&gt;&lt;/script&gt;
  &lt;/body&gt;

    ...
    ```

## Script 태그의 async/defer 어트리뷰트
자바스크립트 파싱에 의한 HTML 파싱 블로킹현상을 근본적으로 해결하기 위해 HTML5부터 async와 defer 어트리뷰트가 추가되었습니다.

```js
&lt;script async src=&quot;script.js&quot;&gt;&lt;/script&gt;
&lt;script defer src=&quot;script.js&quot;&gt;&lt;/script&gt;</code></pre>
<p>async와 defer 어트리뷰트는 HTML파싱과 외부 자바스크립트 파일의 로드가 비동기적으로 동시에 진행되도록 만들어 줍니다. 하지만 두 어트리뷰트 사이에는 자바스크립트의 실행시점의 차이가 존재합니다.</p>
<p><code>async</code>
async 어트리뷰트는 HTML 파싱과 외부 자바스크립트 파일의 로드가 비동기적으로 동시에 진행됩니다. 단, 자바스크립트 파싱과 실행은 자바스크립트 파일이 로드되면 바로 진행되며 이때는 HTML파싱이 중단됩니다. 즉, async 어트리뷰트를 사용하면 자바스크립트 파일의 로드는 비동기적으로 진행할 수 있으나, 완료된 순서로 자바스크립트 파일이 실행되므로 실행 순서를 보장할 수는 없습니다.</p>
<p><img src="https://images.velog.io/images/dev_cecy/post/d55e5b03-7a86-4718-a8a3-6fa0b8f78b30/%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-22%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.19.44.png" alt=""></p>
<p><code>defer</code>
defer 어트리뷰트는 HTML파싱과 외부 자바스크립트 파일의 로드가 비동기적으로 진행된다는 점에서 async어트리뷰트와 동일합니다. 단, 자바스크립트 파싱과 실행은 HTML 파싱이 완료된 직후, 즉 DOM이 생성된 이후에 진행된다는 점이 다릅니다. DOM생성이 완료된 이후 실행되어야 하는 자바스크립트 파일에 유용하게 사용할 수 있습니다.
<img src="https://images.velog.io/images/dev_cecy/post/ffb02b2a-b3d2-40c3-81eb-351ced901221/%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-22%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.20.02.png" alt=""></p>
<h2 id="http-11과-http-2">HTTP 1.1과 HTTP 2</h2>
<p>HTTP는 웹에서 브라우저와 서버가 통신하기 위한 프로토콜 입니다. HTTP에 관한 내용은 다음 글에서 더자세히 알아보도록하고, 이번에는 간단하게 HTTP 1.1과 2.0의 차이만 확인해 보려고 합니다.</p>
<p>HTTP/1.1은 한번에 하나의 요청과 하나의 응답 만을 처리합니다. 즉, 여러개의 요청이나 응답을 한번에 처리할 수 없습니다. 그렇기 때문에 아래와 같이 HTML문서내의 여러 리소스 요청들이 한가지씩 요청되고 응답되며 이는 리소스 요청 개수에 비례하여 응답시간이 증가한다는 단점을 가지고 있습니다.
<img src="https://images.velog.io/images/dev_cecy/post/09c8892c-05bc-4f34-af94-3bbd08bc2290/%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-22%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.20.35.png" alt=""></p>
<p>HTTP/2는 한번에 여러개의 요청과 응답이 가능합니다. 따라서 여러 리소스들이 동시에 요청되고 응답받을 수 있어 구글에 따르면 HTTP/1.1에 비해 HTTP/2의 페이지 로드속도가 약 50%정도 빠르다고 합니다.
<img src="https://images.velog.io/images/dev_cecy/post/13b367c8-28fa-4c3c-87db-9f8f9895987e/%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-22%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.20.56.png" alt=""></p>
<p>오늘은 우리가 어떤 주소를 검색하고 브라우저를통해 그 출력물을 눈으로 보게되는 짧은 순간의 과정에 대해 알아보았습니다. 참 짧은 순간인데 그 시간 웹은 정말 바쁘게 움직이고 있네요.</p>
<p>다음글에서는 우리에게 너무 익숙하지만 막상 설명하자면 갸우뚱한 HTTP에 대해 알아보도록 하겠습니다.</p>
<p><em>이 글은 모던 자바스크립트 Deep Dive(이웅모님 저)의 38장’브라우저의 렌더링과정’을 학습하며 정리한 내용입니다. 본 장에는 브라우저 렌더링 과정이 아주 깔끔하게 정리되어 과정을 이해하는데 큰 도움이 되었습니다.</em></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[웹(WEB)은 어떻게 동작할까?]]></title>
            <link>https://velog.io/@dev_cecy/%EC%9B%B9WEB%EC%9D%80-%EC%96%B4%EB%96%BB%EA%B2%8C-%EB%8F%99%EC%9E%91%ED%95%A0%EA%B9%8C</link>
            <guid>https://velog.io/@dev_cecy/%EC%9B%B9WEB%EC%9D%80-%EC%96%B4%EB%96%BB%EA%B2%8C-%EB%8F%99%EC%9E%91%ED%95%A0%EA%B9%8C</guid>
            <pubDate>Tue, 22 Mar 2022 06:12:56 GMT</pubDate>
            <description><![CDATA[<h3 id="웹이란">웹이란?</h3>
<blockquote>
<p>웹(web)은 월드와이드웹(World Wide Web)의 줄임말입니다. 웹에는 클라이언트(clinent)와 서버(server)라는 두가지의 컴퓨터가 연결되어있습니다.</p>
</blockquote>
<p>클라이언트는 WI-FI와 같이 웹 사용자의 인터넷이 연결된 장치들 또는 크롬, 사파리와 같은 브라우저를 말하며, 서버는 클라이언트의 요청에 응답하기 위한 웹페이지, 사이트 또는 앱을 저장하는 컴퓨터를 말합니다.
<img src="https://images.velog.io/images/dev_cecy/post/4afde823-657b-4307-8805-94ce2ba9b7d4/%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-22%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.11.05.png" alt=""></p>
<h2 id="웹의-동작-방식">웹의 동작 방식</h2>
<p>만약 제가 브라우저에 웹 주소(devcecy.com)를 입력하면,</p>
<ol>
<li>브라우저(클라이언트)는 DNS로가서 서버의 진짜 주소(15.164.6.101)를 찾습니다.</li>
<li>그리고 브라우저는 웹사이트의 사본을 자신에게 전달해달라는 HTTP요청 메세지를 서버에 보냅니다. 이때, 요청 메세지와 웹사이트의 사본과 같은 모든 데이터는 *TCP/IP를 통해서 전송됩니다.</li>
<li>요청 메세지를 받은 서버는 200 ok 메세지를 클라이언트에 전송합니다.</li>
<li>그리고 서버는 *데이터 패킷이라는 작은 덩어리들로 웹사이트의 사본을 브라우저에 전송합니다.</li>
<li>브라우저는 전송 받은 데이터 패킷을 조립해서 웹사이트로 만들어낸후 저에게 devcecy.com의 첫화면을 보여 줍니다.</li>
</ol>
<h3 id="용어정리">용어정리</h3>
<ul>
<li><code>TCP/IP</code> – TCP는 Transmission Control Protocol (전송 제어 규약), IP는 Internet Protocol (인터넷 규약)의 약자로, ‘어떻게’ 웹을 통해 데이터를 전송할 것인지를 정의하는 통신 규약 입니다. 예를들어 우리가 배민에서 야식을 주문했다면 그 음식을 배달해주는 오토바이, 차, 자전거, 사람의 다리 등의 운송장치를 뜻하는 것입니다. 하나하나 좀 더 자세히 설명해 보겠습니다. IP는 패킷을 한곳에서 다른곳으로 옮겨는 줍니다. 그렇지만 IP를 사용하여 데이터를 전송한 송신자는 수신자가 메시지를 언제 받는지, 받기는했는지를 확인할 수 없습니다. 이에 반해, TCP는 IP 위에 만들어졌으며, 패킷이 제대로 전송이 되었는지를 확실하게 보장해줍니다.</li>
<li><code>데이터 패킷(Packet)</code> – 데이터를 주고받는 규칙으로, 네트워크를 통해서 전송되는 데이터조각을 말합니다. 기본적으로 수천개의 작은 덩어리들로 전송이 되어 데이터 트래픽이 정체되지 않고 빠르게 전달 될수 있습니다. 만약 데이터를 덩어리로 쪼개지 않고 한덩어리로 전달한다면 한번에 단 한사용자만 데이터를 다운받을 수 있는 비효율적은 상황이 발생할 것입니다.
다음 글에서는 웹의 클라이언트에 속하는 웹브라우저의 동작방식에 대해서 알아보겠습니다.</li>
</ul>
<p><a href="https://developer.mozilla.org/ko/docs/Learn/Getting_started_with_the_web/How_the_Web_works">MDN의 웹의 동작 방식</a> 를 읽고 스스로 정리한 글입니다.</p>
<p>TCP/IP 용어 설명의 일부분은 &#39;한권으로 읽는 컴퓨터구조와 프로그래밍(조너선 스타인하트)&#39;를 참고했습니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[인터넷은 어떻게 동작할까?]]></title>
            <link>https://velog.io/@dev_cecy/%EC%9D%B8%ED%84%B0%EB%84%B7%EC%9D%80-%EC%96%B4%EB%96%BB%EA%B2%8C-%EB%8F%99%EC%9E%91%ED%95%A0%EA%B9%8C</link>
            <guid>https://velog.io/@dev_cecy/%EC%9D%B8%ED%84%B0%EB%84%B7%EC%9D%80-%EC%96%B4%EB%96%BB%EA%B2%8C-%EB%8F%99%EC%9E%91%ED%95%A0%EA%B9%8C</guid>
            <pubDate>Tue, 22 Mar 2022 06:08:49 GMT</pubDate>
            <description><![CDATA[<p>인터넷이란 무엇인지 먼저 살펴보겠습니다.
인터넷은 수십억대의 컴퓨터들이 서로 통신할 수 있도록 만드는 거대한 네트워크입니다.</p>
<p>두 대의 컴퓨터가 서로 통신하기 위해서는 유선인 이더넷 케이블 혹은 무선인 WiFi나 Bluetooth 시스템을 통해 연결되어야 합니다.
<img src="https://images.velog.io/images/dev_cecy/post/effcbb5f-3a31-4ffd-9b77-e5d38ffcfb56/%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-22%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.05.06.png" alt=""></p>
<p>하지만, 모든 컴퓨터가 통신하기 위해 직접 연결되어야 한다면 아래 그림과 같이 복잡해질 것입니다. 컴퓨터 10대를 서로 연결하기 위해서 45개의 케이블이 필요하기 때문입니다.
<img src="https://images.velog.io/images/dev_cecy/post/246b7418-e330-4305-a773-ee6fe80030b8/%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-22%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.05.38.png" alt=""></p>
<p>이러한 문제를 해결하기 위해 소형 컴퓨터인 라우터가 사용됩니다. 라우터는 컴퓨터 간의 통신이 정확하게 이뤄지도록 하는 단하나의 작업만을 진행하는데 컴퓨터 A가 컴퓨터B로 메세지를 보낸다면 컴퓨터 C가 아닌 컴퓨터B로 전달되도록 하는 것입니다.</p>
<p>라우터를 이용하면 10대의 컴퓨터를 서로 연결하기 위해서 10개의 케이블만 있으면 됩니다.
<img src="https://images.velog.io/images/dev_cecy/post/a03964e1-e77c-4daf-883a-3b3d56279ea5/%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-22%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.06.05.png" alt=""></p>
<p>라우터 하나에 수십억대를 모두 연결하면 좋겠지만 단일 라우터에 그많은 컴퓨터를 모두 연결할 순 없습니다. 하지만 라우터또한 소형 컴퓨터이기 때문에 라우터와 라우터간의 연결이 가능하며 아래와 같이 무한하게 연결을 확장할 수 있게 됩니다.
<img src="https://images.velog.io/images/dev_cecy/post/e17ba4bd-bcc3-442c-9d84-7ed356293236/%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-22%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.06.27.png" alt=""></p>
<p>여기까지만 해도 충분하다 느낄 수 있지만, 제가 있는 서울과 부산 혹은 바다 건너 제주도에 있는 컴퓨터는 어떻게 연결될 수있을까요? 이 문제는 이미 많은 곳에 깔려있는 전화선을 통해 해결할 수 있었습니다. 대신 인터넷 네트워크과 전화 시설이 연결되기 위해서는 모뎀이라는 장비가 필요했으며 모뎀은 네트워크 정보를 전화시설에서 처리할 수있는 정보로 변환해 주었습니다.</p>
<p><img src="https://images.velog.io/images/dev_cecy/post/92b1433f-ef16-4e3e-a213-b4467bb0d5f4/%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-22%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.06.46.png" alt="">
이제 이렇게 연결된 네트워크를 인터넷 서비스 제공업체(Internet Service Provider, ISP)에 연결하면 끝입니다. ISP는 몇몇 특수한 라우터와 다른 ISP의 라우터에 액세스 할 수 있으며, 이렇게 컴퓨터간의 메세지를 전달 할 수 있게 되었습니다.
<img src="https://images.velog.io/images/dev_cecy/post/94222d50-4ced-4050-b4c5-55fd660151f4/internet-schema-7.png" alt=""></p>
<p><code>인터넷</code>과 <code>웹</code>은 같지 않습니다. 인터넷은 지금까지 알아 본것처럼 수십억대의 컴퓨터를 모두 연결 할 수 있는 인프라를 뜻하며, 웹은 그 인프라 위에 구축된 서비스를 말합니다.</p>
<p>그렇다면 다음으로 웹은 어떻게 동작하는지 알아보겠습니다.</p>
<p><a href="https://developer.mozilla.org/ko/docs/Learn/Common_questions/How_does_the_Internet_work">MDN의 인터넷은 어떻게 동작하는가?</a>를 읽고 스스로 정리한 글입니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[CES 2022]]></title>
            <link>https://velog.io/@dev_cecy/CES-2022</link>
            <guid>https://velog.io/@dev_cecy/CES-2022</guid>
            <pubDate>Tue, 22 Mar 2022 05:25:00 GMT</pubDate>
            <description><![CDATA[<p>간단하게 정리해보는 CES 2022
<img src="https://images.velog.io/images/dev_cecy/post/34fdf044-9c86-476b-a199-9e10c0046c05/%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-22%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%202.20.23.png" alt=""></p>
<ul>
<li><p>일정상 CES 마지막 날만 관람이 가능했다.</p>
</li>
<li><p>유명 기업 &gt; 현 회사와 협업가능하거나 참고할만한 기업 순으로 관람했다.</p>
</li>
<li><p>벤츠의 차량 외부 색이 변하는 차를 보았는데, 이제 자동차 흰색살까 검정색살까 혹은 튀는색 살까고민하지 않아도 되는 시대가 왔나보다. 벤츠는 야외에 부스를 세웠고, 차에 탑승해보거나 스피커 사운드만을 체험하는 부스를 따로 새워놓기도했다. 또, 음료를 무료로 제공하는 바와 야외 라운지를 만들어 관람객들이 벤츠 부스에서 더 많은 시간을 보낼 수 있도록 유도한 부분이 인상적이었다.</p>
</li>
<li><p>가장 큰 부스 사이즈로 참가한 삼성은 모든 제품을 끌어모아 나온 느낌이었다. 가전제품 매장인 듯한 느낌이 들어 아쉬웠던것 같기도하고.</p>
</li>
<li><p>개인적으로 SK의 부스가 가장 인상적이였다. CES 에서 전하고자 하는 것을 명확해 보였고, 내부 동선과 디자인, 영상미, 증강현실, NFC 직원들의 의상까지 전시회를 위해 많은 노력이 있었음을 느낄 수 있었다. 부스를 모두 관람하고 나오면 관람 중 얻는 포인트로 코인을 얻을 수있는데 이 코인으로는 라스베가스 답게(?) 카지노게임을 할 수 있다. 카지노 게임으로 얻은 쿠폰으로는 야외에서 meat-free 푸드트럭을 운영해 음식을 즐길 수 있게 해주었다.</p>
</li>
<li><p>Venetian 쪽에는 한국 기업들이 점령 했다고 말해도 과언이 아닐 정도로 많은 기업들이 참가했다.</p>
</li>
<li><p>NFC와 블록코딩, 마그네틱을 이용한 코딩 교육완구를 가지고 나온 한국기업이 있었는데 많은 영감과 자극을 받았다.</p>
</li>
<li><p>적고보니 전시 주최사에서 일했던 경험 때문인지 전시회 전반의 운영과 부스에 대한 생각을 많이 하며 봤구나 싶다.</p>
</li>
</ul>
<ul>
<li><p>좋았던점</p>
<ul>
<li>부스에서 참가기업들의 열정이 뿜어져 나와 나도 모르는새에 그 열정을 받아왔다.</li>
<li>생각하지 못했던 서비스와 아이템들을 관람 하면서 매몰되어있는 나만의 생각에서 한 발자국 떨어져 나올 수 있었다.</li>
</ul>
</li>
<li><p>아쉬운점</p>
<ul>
<li>코로나로 인해 메타, 아마존 같은 유명 기업이 참가하지 않아 아쉬웠다.</li>
<li>하루안에 모든 것을 보려니 여유롭고 꼼꼼하게 관람하는것이 불가능했다. North 관은 아예 관람하지 못했다</li>
</ul>
</li>
<li><p>CES에 가면서 세워둔 몇가지 목표가 있었다. 그 중 몇가지는 동료들과 깊은 대화를 나누고, 그들의 인간적 장점을 1개 이상 발견하는 것이었다. 결론적으로 말하면 나의 지극히 개인적인 목표는 모두 달성되었다. 새벽까지 대화하고 기록 하면서, 우리가 개발하는 서비스에 대한 고민과 애정을 가진 이들과 함께 일할 수 있어 감사하는 생각이 들었다.</p>
</li>
<li><p>CES발 코로나 확진자가 점점 늘어나고있다. CES 전시장 내부는 접종자와 음성확인서를 검사해서 안전하다고 생각했지만, 라스베가스 시내는 정말 코로나에 안걸리면 이상할정도로 시민들이 방역에 참여하고 있지 않았다. 정부정책이 없는것 같기도하고. 전시회가 끝나고 미국에서 pcr음성 1회와 호텔방에 머물며 자가진단 키트로 2번의 음성, 한국에 오자마자 pcr 음성을 받았음에도 여전히 불안한 마음이다. 같이 출장을 다녀온 분들도 격리면제자임에도 불구하고 모두 10일간 재택하며 집에서 스스로 격리하기로 했다. 매일 체크하기 위해 자가진단키트도 샀다. 많은 해외여행과 해외출장을 경험해봤지만 이번처럼 출국도 입국도 이렇게 힘든 적은 처음이다. 나로인해 나의 가족이 감염될까 걱정되기도하고, 스스로도 적지않은 스트레스를 받으며 이래저래 쉽지않은 순간들이다.</p>
</li>
<li><p>그렇기 때문에 CES에 다녀온 경험을 더 값지게 만들어야 겠다는 생각이든다.</p>
</li>
</ul>
<p>(22년 1월 13일에 적은 글입니다.)</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JAVASCRIPT] 배열의 중복 값 개수 구하기 – REDUCE()]]></title>
            <link>https://velog.io/@dev_cecy/JAVASCRIPT-%EB%B0%B0%EC%97%B4%EC%9D%98-%EC%A4%91%EB%B3%B5-%EA%B0%92-%EA%B0%9C%EC%88%98-%EA%B5%AC%ED%95%98%EA%B8%B0-REDUCE</link>
            <guid>https://velog.io/@dev_cecy/JAVASCRIPT-%EB%B0%B0%EC%97%B4%EC%9D%98-%EC%A4%91%EB%B3%B5-%EA%B0%92-%EA%B0%9C%EC%88%98-%EA%B5%AC%ED%95%98%EA%B8%B0-REDUCE</guid>
            <pubDate>Tue, 22 Mar 2022 05:12:21 GMT</pubDate>
            <description><![CDATA[<p>지난 글에서는 reduce() 기본쓰임과, 누적된 값(accumulator)을 인자로 받는 특성을 이용하여 배열의 원소를 모두 더해보았다.</p>
<p>이번에는 누적된 값과 initialValue를 지정할 수 있는 특성을 이용해 배열 내의 중복된 값이 몇 개 있는지 구해보자!</p>
<pre><code class="language-js">const array = [&#39;a&#39;, &#39;b&#39;, &#39;a&#39;, &#39;a&#39;, &#39;b&#39;];

const result = array.reduce((accu, curr) =&gt; { 
  console.log(&#39;accu&#39;,accu, &#39;curr&#39;, curr, accu[curr])
  accu[curr] = (accu[curr] || 0)+1; // 객체에서 curr key값을 찾아 value값이 있으면 그 value에서 1을 더하고, 없다면 0을 할당하고 거기에 1을 더해준다. 
  return accu;
}, {});

console.log(&#39;result&#39;,result); // &#39;result&#39; { a: 3, b: 2 }</code></pre>
<p>reduce()가 어떤식으로 배열을 순회하는지 보기위해 중간에 console.log을 찍어주었는데, console.log만 가져와서 뜯어보면 이런식이다.</p>
<pre><code class="language-js">console.log(&#39;accu&#39;,accu, &#39;curr&#39;, curr, accu[curr])

&#39;accu&#39; {} &#39;curr&#39; &#39;a&#39; undefined  // 1번
&#39;accu&#39; { a: 1 } &#39;curr&#39; &#39;b&#39; undefined // 2번
&#39;accu&#39; { a: 1, b: 1 } &#39;curr&#39; &#39;a&#39; 1 // 3번
&#39;accu&#39; { a: 2, b: 1 } &#39;curr&#39; &#39;a&#39; 2
&#39;accu&#39; { a: 3, b: 1 } &#39;curr&#39; &#39;b&#39; 1</code></pre>
<ol>
<li>initialValue 를 {}로 지정해주었기 때문에 accu(누적값)의 첫 값은 {}이다. 그리고 배열의 첫 값을 받는 curr는 ‘a’고, 빈 객체에서 ‘a’를 찾는 accu[curr]값은 undefined가 나온다. 아직 빈 객체라 ‘a’ key값의 value가 없기 때문이다.</li>
<li>1번에서 객체안에 ‘a’의 값이 없었기 때문에 0을 할당한 뒤 + 1해주었고, 두번째 curr값은 ‘b’다. 이번에도 역시 객체안에 ‘b’라는 key값은 존재하지 않기 때문에 accu[curr]값은 undefined다.</li>
<li>2번에서 ‘b’의 value값으로 0+1이 할당되었기 때문에 누적값은 {a: 1, b:1}이 되었다. 이후 부터는 객체안에 key값이 존재하면 그 value값에 1을 더해주고, 없다면 0을 할당한뒤 1을 더해주는 방식을 반복한다.</li>
</ol>
<p><img src="https://images.velog.io/images/dev_cecy/post/b672ac2d-516c-467f-a5a4-b910f0edd27f/%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-22%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%202.12.11.png" alt="">객체를 initialValue로 지정해주고 그 안에 key값이 있는지 확인해 value에 1씩 더해주는 방식으로 배열의 중복되는 원소 갯수를 구해보았다. 👊🏻</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JAVASCRIPT] ES6의 MAP(), SET() 알아보기]]></title>
            <link>https://velog.io/@dev_cecy/JAVASCRIPT-ES6%EC%9D%98-MAP-SET-%EC%95%8C%EC%95%84%EB%B3%B4%EA%B8%B0</link>
            <guid>https://velog.io/@dev_cecy/JAVASCRIPT-ES6%EC%9D%98-MAP-SET-%EC%95%8C%EC%95%84%EB%B3%B4%EA%B8%B0</guid>
            <pubDate>Tue, 22 Mar 2022 05:08:15 GMT</pubDate>
            <description><![CDATA[<p>hash 관련 알고리즘 문제를 풀다 어떤분이 Map과 Set을 사용하신 것을 발견했다. Map과 Set에 대해서는 ES6 문법이다, 정도만 알고있었는데 실제로 사용할 수 있었다면 풀이가 더 쉬웠을 것 같았다. 그래서 다음번에는 사용해보기 위해 Map과 Set을 알아보기로!</p>
<h1 id="set">Set()</h1>
<p>Set은 value들로 이루어져있는 컬렉션이다.</p>
<ul>
<li>new Set()으로 새로운 set을 만든다.</li>
<li>Set은 인덱스로 데이터를 조회할 수 없다.</li>
<li>set.size set이 가지고 있는 데이터의 개수를 조회한다.</li>
<li>set.has(value) value가 set안에 존재한다면 true를 반환한다. </li>
<li>indexOf()로 데이터를 찾는것 보다 빠르다.</li>
<li>set.add(value) value를 set에 추가한다. </li>
<li>Set에는 같은 데이터가 2번 존재할 수 없어, 데이터가 이미 존재한다면 추가되지 않는다.</li>
<li>set.delete(value) value를 set에서 제거한다.</li>
<li>set.clear() set안의 모든 데이터를 삭제한다.</li>
<li>set.keys(), set.values(), set.entries() 는 이터레이터들을 리턴하며, Map과의 호환성을 위해 존재한다.</li>
</ul>
<pre><code class="language-js">var users = new Set();

users.add(&#39;Ceci&#39;); 
users.add(&#39;Den&#39;)
console.log(&#39;users&#39;,users)  // Set [&#39;Ceci&#39;, &#39;Den&#39;]

users.delete(&#39;Charles&#39;) //false =&gt; Set안에 존재하지않아 삭제할 수 없기 때문에 false 반환
users.delete(&#39;Ceci&#39;); // true =&gt; Set안에 존재하는 값으로 삭제되었기 떄문에 true 반환

users.size //1 =&gt; Set의 길이를 반환 


users.has(&#39;Den&#39;) //true =&gt; Set안에 존재하는 값이기 때문에 true 반환 

users[0] // undefied =&gt; 인덱스로 값찾기 불가!

users.clear() //set데이터 모두삭제 </code></pre>
<h1 id="map">Map()</h1>
<p>Map은 key-value의 쌍으로 이루어져있는 컬렉션이다.</p>
<ul>
<li>new Map() 으로 새로운 map을 만든다.</li>
<li>map.set(key, value) map에 key와 value 를 추가한다. 같은 key값이 존재할 경우 기존 데이터를 덮어쓴다.</li>
<li>map.get(key) key와 관련된 value를 리턴한다.</li>
<li>map.has(key) key가 존재하는지 확인해 true, false를 반환한다.</li>
<li>map.size map의 엔트리 개수를 조회한다.</li>
<li>map.delete(key) key와 관련된 엔트리를 삭제한다.</li>
<li>map.clear() map의 모든 데이터를 삭제한다.</li>
</ul>
<pre><code class="language-js">let users = new Map();

users.set(&#39;name&#39;, &#39;Ceci&#39;) //추가, set은 같은 key가 존재하면 데이터를 덮어쓴다. 
users.set(&#39;nickname&#39;, &#39;devCecy&#39;) //추가

users.get(&#39;name&#39;) // &#39;Ceci&#39; =&gt; key와 관련된 value를 리턴한다.  


users.has(&#39;name&#39;) // true =&gt; key가 존재하는지 확인한다.
users.size //2 =&gt; 엔트리의 개수를 반환한다.
users.clear() // 모든 데이터 삭제 </code></pre>
<h2 id="map을-생성하는-3가지-방법">Map을 생성하는 3가지 방법</h2>
<pre><code>//1. 
let users = new Map();

//2.
let users = new Map([[&#39;age&#39;, &#39;29&#39;]]); 

//3. 
let users = new Map().set(&#39;age&#39;, &#39;29&#39;).set(&#39;phoneNumber&#39;, &#39;01012345678&#39;)</code></pre><h2 id="mapkeys-와-mapvalues">Map.keys() 와 Map.values()</h2>
<p>각각의 순회할 수 있는 모든 iterable object을 반환한다.</p>
<pre><code class="language-js">var users = new Map().set(&#39;name&#39;, &#39;Ceci&#39;).set(&#39;age&#39;, &#39;29&#39;)

console.log([...users.keys()]) //[ &#39;name&#39;, &#39;age&#39; ]
console.log([...users.values()]) //[ &#39;Ceci&#39;, &#39;29&#39; ]</code></pre>
<h2 id="map-순회하는-2가지-방법">Map 순회하는 2가지 방법</h2>
<pre><code class="language-js">var users = new Map().set(&#39;age&#39;, &#39;29&#39;).set(&#39;phoneNumber&#39;, &#39;010&#39;)

//for-of
for (let [key, value] of users) {
  console.log(key + &#39;:&#39; + value); 
}


//forEach ** value - key 순임!!
users.forEach((value, key, map) =&gt; {
  console.log(key + &#39;:&#39; + value);
});

// 둘다 아래와 같은 결과가 반환된다.  
// &#39;age:29&#39;
//&#39;phoneNumber:010&#39;</code></pre>
<h2 id="mapentries">Map.entries()</h2>
<p>map안의 모든 엔트리들을 순회할 수 있는 iterable object 반환한다.</p>
<pre><code class="language-js">let users = new Map().set(&#39;name&#39;, &#39;Ceci&#39;).set(&#39;age&#39;, &#39;29&#39;)
let iterObj  = users.entries();
console.log(&#39;iterObj&#39;,iterObj) 
//&#39;iterObj&#39; Iterator [Map Iterator] {
//  __proto__: { next: ƒ next() }
//}

console.log(iterObj.next()) //{ value: [ &#39;name&#39;, &#39;Ceci&#39; ], done: false }
console.log(iterObj.next()) //{ value: [ &#39;age&#39;, &#39;29&#39; ], done: false }
console.log(iterObj.next()) //{ value: undefined, done: true }()</code></pre>
<p>iterable 개념에 대해 알보고 다시 모질라 블로그를 읽어보면 좋을것 같다.
의문점은 set.add()와, set.delete()는 set객체 자신을 리턴한다고 모질라 블로그에서 말하는데, 실제로 실행해보면 true,false값을 반환했다..!</p>
<p>Mozilla 블로그와 <a href="https://medium.com/@hongkevin">Kevin Hong님의 블로그</a>를 보고 공부하며 작성했습니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JAVASCRIPT] 모든 배열의 요소 더하기 – REDUCE()]]></title>
            <link>https://velog.io/@dev_cecy/JAVASCRIPT-%EB%AA%A8%EB%93%A0-%EB%B0%B0%EC%97%B4%EC%9D%98-%EC%9A%94%EC%86%8C-%EB%8D%94%ED%95%98%EA%B8%B0-REDUCE</link>
            <guid>https://velog.io/@dev_cecy/JAVASCRIPT-%EB%AA%A8%EB%93%A0-%EB%B0%B0%EC%97%B4%EC%9D%98-%EC%9A%94%EC%86%8C-%EB%8D%94%ED%95%98%EA%B8%B0-REDUCE</guid>
            <pubDate>Tue, 22 Mar 2022 05:02:36 GMT</pubDate>
            <description><![CDATA[<p><img src="https://images.velog.io/images/dev_cecy/post/4403c1e1-4fae-4b33-aa4a-6252e06d12c5/%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-22%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%202.02.24.png" alt=""></p>
<h1 id="reduce">reduce()</h1>
<p>reduce()는 배열을 다루는 메소드로 누적값(accumulator)과 현재값(currentValue)을 인자로 가지고 있다는 특징이 있다. 이러한 특징으로 배열을 여러가지로 요리(?)할 수 있도록 만든다.</p>
<p>가장 간단한 예시는 모든 배열의 요소를 더하는 것으로 reduce의 속성을 이해하기에 좋다.</p>
<p><code>arr.reduce(callback[, initialValue])</code></p>
<pre><code class="language-const">const reducer = (accumulator, currentValue) =&gt; accumulator + currentValue;


// 1 + 2 + 3 + 4
console.log(numbers.reduce(reducer)); // 10 =&gt; 배열의 원소 1,2,3,4를 모두 더한 값을 반환한다. 

// 5 + 1 + 2 + 3 + 4
console.log(numbers.reduce(reducer, 5)); // 15 =&gt; initialValue로 5를 지정해주었기 때문에 accumulator의 첫 값은 5가 되고 나머지 1,2,3,4를 더해 15를 반환한다. </code></pre>
<ol>
<li>reduce()는 배열의 각 요소에 콜백함수를 한번씩 실행한다.</li>
<li>콜백함수는 1) accumulator, 2) currentValue, 3) currentIndex, 4) array, 총 4개의 인자 값을 받는다.</li>
</ol>
<ul>
<li>accumulator는 콜백의 반환값을 누적한다. </li>
<li>initialValue가 있는 경우 첫 accumulator값은 initialValue이다.</li>
<li>currentValue 처리할 현재 요소.</li>
<li>currentIndex (옵션) 처리할 현재 요소의 인덱스. initialValue가 있으면 0, 없다면 1부터 시작한다.</li>
<li>array (옵션) reduce()를 호출한 배열.</li>
<li>initialValue (옵션) 콜백의 최초 호출에서 첫 번째 인수에 제공하는 값. initialValue가 없다면 배열의 첫번째 요소를 최초 호출에 사용한다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JAVASCRIPT] 배열 자르기 – SLICE()]]></title>
            <link>https://velog.io/@dev_cecy/JAVASCRIPT-%EB%B0%B0%EC%97%B4-%EC%9E%90%EB%A5%B4%EA%B8%B0-SLICE</link>
            <guid>https://velog.io/@dev_cecy/JAVASCRIPT-%EB%B0%B0%EC%97%B4-%EC%9E%90%EB%A5%B4%EA%B8%B0-SLICE</guid>
            <pubDate>Tue, 22 Mar 2022 04:58:16 GMT</pubDate>
            <description><![CDATA[<h1 id="slice">Slice()</h1>
<p>slice()는 배열의 시작 인덱스부터 끝 인덱스(끝 인덱스 미포함)까지 얕은복사를 하여 새로운 배열로 반환한다. 새로운 배열을 반환하므로 원본배열은 변화하지 않는다.</p>
<h2 id="구문">구문</h2>
<p><code>arr.slice([begin[, end]])</code></p>
<h2 id="예시">예시</h2>
<pre><code>const names = [&#39;Cecilia&#39;, &#39;Den&#39;, &#39;Sherlock&#39;, &#39;John&#39;, &#39;Microft&#39;];

console.log(names.slice(2)) //[ &#39;Sherlock&#39;, &#39;John&#39;, &#39;Microft&#39; ] =&gt; 시작인덱스 2부터 끝가지 반환

console.log(names.slice(-2)) // [ &#39;John&#39;, &#39;Microft&#39; ] =&gt; 배열끝에서 요소 2개 반환

console.log(names.slice(5)) // [] =&gt; 원본 배열의 길이보다 길어서 빈 배열 반환

console.log(names.slice(2,4)) //[ &#39;Sherlock&#39;, &#39;John&#39; ] =&gt; 시작인덱스2부터 인덱스4전까지(=인덱스3) 반환

// const newNames = names.slice(2,-1) //[ &#39;Sherlock&#39;, &#39;John&#39; ] =&gt; 2번인덱스부터 끝에서 -1
// console.log(newNames) </code></pre><p>원본 배열과 새 배열은 동일한 객체를 참조한다. 그러므로 참조된 객체가 변경되면 새 배열도 참조된 객체에 따라 변경된다.</p>
<pre><code>const names = [&#39;Cecilia&#39;, &#39;Den&#39;, &#39;Sherlock&#39;, &#39;John&#39;, &#39;Microft&#39;]; //참조된 배열


const newNames = names.slice(2,4);
console.log(newNames);  //[ &#39;Sherlock&#39;, &#39;John&#39; ] =&gt; 새 배열


// names에서 &#39;Cecilia&#39;를 삭제하면(참조된 배열을 변경하면), 
console.log(newNames);  //[ &#39;John&#39; ] =&gt; 새 배열도 변경된다.</code></pre><h1 id="slice와-splice-간단비교">slice()와 splice() 간단비교</h1>
<p>slice()와 splice()와 비슷하게 생겨서(?) 헷갈리기도 하는데, 간단하게 비교해보자.</p>
<p><code>splice(start, deleteCount, addItem)</code></p>
<ul>
<li>start부터 deleteCount개 삭제한다.</li>
<li>addItem을 추가한다.</li>
<li>원본 배열을 수정해서 반환한다.</li>
</ul>
<p><code>slice(start, end)</code></p>
<ul>
<li>start부터 end까지 자른다.</li>
<li>원본 배열을 얕은 복사해서 새로운 배열로 반환한다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JAVASCRIPT] 배열의 요소 추가 및 삭제 – UNSHIFT(), PUSH(), SHIFT(), POP()]]></title>
            <link>https://velog.io/@dev_cecy/JAVASCRIPT-%EB%B0%B0%EC%97%B4%EC%9D%98-%EC%9A%94%EC%86%8C-%EC%B6%94%EA%B0%80-%EB%B0%8F-%EC%82%AD%EC%A0%9C-UNSHIFT-PUSH-SHIFT-POP</link>
            <guid>https://velog.io/@dev_cecy/JAVASCRIPT-%EB%B0%B0%EC%97%B4%EC%9D%98-%EC%9A%94%EC%86%8C-%EC%B6%94%EA%B0%80-%EB%B0%8F-%EC%82%AD%EC%A0%9C-UNSHIFT-PUSH-SHIFT-POP</guid>
            <pubDate>Tue, 22 Mar 2022 04:53:16 GMT</pubDate>
            <description><![CDATA[<p>알고리즘 문제를 풀기 시작하면서, 기본 자바스크립트 메서드들을 다시 한번 정리하면 좋을 것 같아 정리를 시작해 본다!</p>
<p>가장 먼저, 자바스크립트 배열의 요소를 추가 및 삭제 할 수 있는 메서드들을 알아보자.</p>
<ul>
<li>배열 요소 추가 unshift(), push()</li>
<li>배열 요소 삭제 shift(), pop()</li>
</ul>
<h1 id="1-배열에-요소-추가">1. 배열에 요소 추가</h1>
<h2 id="unshift">unshift()</h2>
<p>배열의 처음에 하나 이상의 요소를 추가하고, 배열의 길이를 반환한다.</p>
<pre><code class="language-js">const users = [&#39;Charles&#39;, &#39;Cecilia&#39;, &#39;Den&#39;];

const totalUsers = users.unshift(&#39;Sherlock&#39;, &#39;John&#39;); 


console.log(totalUsers); // 5 =&gt; 배열의 길이를 반환한다. 
console.log(users); // [&#39;Sherlock&#39;, &#39;John&#39;, &#39;Charles&#39;, &#39;Cecilia&#39;, &#39;Den&#39;] =&gt; Sherlock과 &#39;John&#39;이 배열의 첫부분에 추가되었다.</code></pre>
<h2 id="push">push()</h2>
<p>배열의 마지막에 하나 이상의 요소를 추가하고, 배열의 길이를 반환한다.</p>
<pre><code class="language-js">const users = [&#39;Charles&#39;, &#39;Cecilia&#39;, &#39;Den&#39;];

const totalUsers = users.push(&#39;Sherlock&#39;, &#39;John&#39;); 


console.log(totalUsers); // 5 =&gt; 배열의 길이를 반환한다. 
console.log(users); // [&#39;Charles&#39;, &#39;Cecilia&#39;, &#39;Den&#39;, &#39;Sherlock&#39;, &#39;John&#39;] =&gt; Sherlock과 &#39;John&#39;이 배열의 마지막에 추가되었다. </code></pre>
<h1 id="2-배열의-요소-삭제">2. 배열의 요소 삭제</h1>
<h2 id="shift">shift()</h2>
<p>배열의 첫 요소를 제거하고, 제거된 요소를 반환한다.</p>
<pre><code class="language-js">const users = [ &#39;Sherlock&#39;, &#39;John&#39;, &#39;Moriarty&#39; ];
const newUsers = users.shift();

console.log(newUsers); // &#39;Sherlock&#39; =&gt; 배열의 첫 번째 요소인 &#39;Sherlock&#39;가 반환된다. 
console.log(users); // [ &#39;John&#39;, &#39;Moriarty&#39; ]</code></pre>
<h2 id="pop">pop()</h2>
<p>배열의 마지막 요소를 제거하고, 제거된 요소를 반환한다.</p>
<pre><code class="language-js">const users = [&#39;Sherlock&#39;, &#39;John&#39;, &#39;Moriarty&#39;];
const newUsers = users.pop();

console.log(newUsers); // &#39;Moriarty&#39; =&gt; 배열의 마지막에 있는 &#39;Moriarty&#39;가 반환된다. 
console.log(users); // [ &#39;Sherlock&#39;, &#39;John&#39; ]</code></pre>
<h2 id="cpop과-shift로-배열의-요소-모두-제거하기">cpop()과 shift()로 배열의 요소 모두 제거하기</h2>
<p>shift(), pop()이 제거할 요소가 없는 경우 undefined를 반환하는 특성을 이용하여, 아래와 같이 배열의 요소를 모두 제거 할 수 있다.</p>
<pre><code class="language-js">let names = [&quot;Andrew&quot;, &quot;Edward&quot;, &quot;Paul&quot;, &quot;Chris&quot; ,&quot;John&quot;];

while( (i = names.pop()) !== undefined ) {
  console.log(&#39;제거된요소&#39;,i);
  console.log(&#39;변경된배열&#39;, names)
}

//console.log()의 결과 값들
&#39;제거된요소&#39; &#39;John&#39;
&#39;변경된배열&#39; [ &#39;Andrew&#39;, &#39;Edward&#39;, &#39;Paul&#39;, &#39;Chris&#39; ]
&#39;제거된요소&#39; &#39;Chris&#39;
&#39;변경된배열&#39; [ &#39;Andrew&#39;, &#39;Edward&#39;, &#39;Paul&#39; ]
&#39;제거된요소&#39; &#39;Paul&#39;
&#39;변경된배열&#39; [ &#39;Andrew&#39;, &#39;Edward&#39; ]
&#39;제거된요소&#39; &#39;Edward&#39;
&#39;변경된배열&#39; [ &#39;Andrew&#39; ]
&#39;제거된요소&#39; &#39;Andrew&#39;
&#39;변경된배열&#39; []
```![](https://images.velog.io/images/dev_cecy/post/8bc9fab9-8e9c-4e33-ab5e-301fb208c8ad/%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-22%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%201.53.02.png)</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JAVASCRIPT] 배열 중간에 요소 추가 및 삭제 – SPLICE()]]></title>
            <link>https://velog.io/@dev_cecy/JAVASCRIPT-%EB%B0%B0%EC%97%B4-%EC%A4%91%EA%B0%84%EC%97%90-%EC%9A%94%EC%86%8C-%EC%B6%94%EA%B0%80-%EB%B0%8F-%EC%82%AD%EC%A0%9C-SPLICE</link>
            <guid>https://velog.io/@dev_cecy/JAVASCRIPT-%EB%B0%B0%EC%97%B4-%EC%A4%91%EA%B0%84%EC%97%90-%EC%9A%94%EC%86%8C-%EC%B6%94%EA%B0%80-%EB%B0%8F-%EC%82%AD%EC%A0%9C-SPLICE</guid>
            <pubDate>Tue, 22 Mar 2022 04:48:54 GMT</pubDate>
            <description><![CDATA[<h1 id="splice">splice()</h1>
<blockquote>
<p>배열의 요소를 삭제, 교체하거나 새로운 요소를 추가하여 기존 배열을 변경한다. 그리고 변경된 배열을 반환한다.</p>
</blockquote>
<p>#<img src="https://images.velog.io/images/dev_cecy/post/8092a5ad-db16-42ac-a8a1-2dacd5bb5635/%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-22%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%201.48.42.png" alt=""> 구문
<code>array.splice(start[, deleteCount[, item1[, item2[, ...]]]])</code></p>
<h2 id="배열-중간의-요소-삭제">배열 중간의 요소 삭제</h2>
<pre><code>const totalUsers = users.splice(1,1); //1번 인덱스 요소부터 1개 삭제
console.log(totalUsers); // [ &#39;Cecilia&#39; ] =&gt; 삭제된 요소 반환
console.log(users); // [ &#39;Charles&#39;, &#39;Den&#39; ] =&gt; 변경된 배열 반환</code></pre><h2 id="배열의-중간에-요소-추가">배열의 중간에 요소 추가</h2>
<pre><code>const totalUsers = users.splice(1,0, &#39;Microft&#39;); //1번 인덱스 자리에 &#39;Microft&#39; 추가
console.log(totalUsers); // [] =&gt; 빈배열 반환, 삭제된 요소 없음
console.log(users); // [ &#39;Charles&#39;, &#39;Microft&#39;, &#39;Cecilia&#39;, &#39;Den&#39; ] =&gt; 변경된 배열 반환</code></pre><h2 id="배열의-중간에-한개-이상의-요소-추가">배열의 중간에 한개 이상의 요소 추가</h2>
<pre><code>const totalUsers = users.splice(1,0, &#39;Microft&#39;,&#39;Merry&#39;); //1번 인덱스부터 2개 요소 삭제
console.log(totalUsers); // [] =&gt; 빈배열 반환, 삭제된 요소 없음
console.log(users); // [ &#39;Charles&#39;, &#39;Microft&#39;, &#39;Merry&#39;, &#39;Cecilia&#39;, &#39;Den&#39; ] =&gt; 1번 인덱스부터 &#39;Microft&#39;,&#39;Merry&#39; 추가됨.</code></pre><h2 id="배열-중간-요소-삭제-후-새로운-요소-추가">배열 중간 요소 삭제 후 새로운 요소 추가</h2>
<pre><code>const totalUsers = users.splice(1,2, &#39;Microft&#39;); //1번 인덱스부터 2개 요소 삭제
console.log(totalUsers); // [ &#39;Cecilia&#39;, &#39;Den&#39; ] =&gt; 1,2인덱스 요소 삭제되어 반환
console.log(users); // [ &#39;Charles&#39;, &#39;Microft&#39; ] =&gt; 1번인덱스 자리에 &#39;Microft&#39; 추가됨</code></pre><h1 id="slice와-splice-간단비교">slice()와 splice() 간단비교</h1>
<p>slice()와 splice()와 비슷하게 생겨서(?) 헷갈리기도 하는데, 간단하게 비교해보자.</p>
<p><code>splice(start, deleteCount, addItem)</code></p>
<ul>
<li>start부터 deleteCount개 삭제한다.</li>
<li>addItem을 추가한다.</li>
<li>원본 배열을 수정해서 반환한다.</li>
</ul>
<p><code>slice(start, end)</code></p>
<ul>
<li>start부터 end까지 자른다.</li>
<li>원본 배열을 얕은 복사해서 새로운 배열로 반환한다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[프로그래머스] K번째 수 (정렬 LEVEL1)]]></title>
            <link>https://velog.io/@dev_cecy/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-K%EB%B2%88%EC%A7%B8-%EC%88%98-%EC%A0%95%EB%A0%AC-LEVEL1</link>
            <guid>https://velog.io/@dev_cecy/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-K%EB%B2%88%EC%A7%B8-%EC%88%98-%EC%A0%95%EB%A0%AC-LEVEL1</guid>
            <pubDate>Tue, 22 Mar 2022 04:35:11 GMT</pubDate>
            <description><![CDATA[<p><img src="https://images.velog.io/images/dev_cecy/post/854584a2-4423-412a-95a0-6425b0309001/%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-22%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%201.35.00.png" alt=""></p>
<h1 id="문제">문제</h1>
<p>배열 array의 i번째 숫자부터 j번째 숫자까지 자르고 정렬했을 때, k번째에 있는 수를 구하려 합니다.</p>
<p>예를 들어 array가 [1, 5, 2, 6, 3, 7, 4], i = 2, j = 5, k = 3이라면</p>
<p>array의 2번째부터 5번째까지 자르면 [5, 2, 6, 3]입니다.
1에서 나온 배열을 정렬하면 [2, 3, 5, 6]입니다.
2에서 나온 배열의 3번째 숫자는 5입니다.
배열 array, [i, j, k]를 원소로 가진 2차원 배열 commands가 매개변수로 주어질 때, commands의 모든 원소에 대해 앞서 설명한 연산을 적용했을 때 나온 결과를 배열에 담아 return 하도록 solution 함수를 작성해주세요.</p>
<h2 id="제한사항">제한사항</h2>
<p>array의 길이는 1 이상 100 이하입니다.
array의 각 원소는 1 이상 100 이하입니다.
commands의 길이는 1 이상 50 이하입니다.
commands의 각 원소는 길이가 3입니다.</p>
<h2 id="입출력-예">입출력 예</h2>
<p>array    commands    return
[1, 5, 2, 6, 3, 7, 4]    [[2, 5, 3], [4, 4, 1], [1, 7, 3]]    [5, 6, 3]</p>
<h1 id="나의-풀이">나의 풀이</h1>
<p>첫 시도에는 테스트 2번이 실패로 나왔는데 .sort()로만 적었기때문이였다. sort()에 관한 MDN문서를 보면 정식 구문은 arr.sort([compareFunction])으로, compareFunction을 입력하지 않으면 각 문자의 유니 코드 코드 포인트 값에 따라 정렬된다고 한다. 그러므로 확실하게 해주기 위해 .sort(function(a, b) { return a - b; })로 코드를 수정해 주었다. 그렇게 통과 !</p>
<pre><code class="language-js">function solution(array, commands) {
  var answer = [];

  for(let i =0; i&lt;commands.length; i++){
    const sortedArray = array.slice(commands[i][0]-1, commands[i][1])
    sortedArray.sort(function(a, b) {
  return a - b;
})
    answer.push(sortedArray[commands[i][2]-1])
  }

    return answer;
}</code></pre>
<h1 id="다른분의-풀이-1">다른분의 풀이 1</h1>
<p>비구조화 할당을 통해 코드를 가독성있게 만든 부분이 인상적이였다.</p>
<pre><code class="language-js">const [sPosition, ePosition, position] = command;

function solution(array, commands) {
    return commands.map(command =&gt; {
        const [sPosition, ePosition, position] = command
        const newArray = array
            .filter((value, fIndex) =&gt; fIndex &gt;= sPosition - 1 &amp;&amp; fIndex &lt;= ePosition - 1)
            .sort((a,b) =&gt; a - b)    

        return newArray[position - 1]
    })
}</code></pre>
<h1 id="다른분의-풀이-2">다른분의 풀이 2</h1>
<p>const 에 할당하지 않고 return 문으로 간결하게 코드를 작성해보자라고 다시 한번 생각할 수 있게 만들어준 코드.</p>
<p>다음 문제에는 꼭 실천해보자.</p>
<pre><code class="language-js">function solution(array, commands) {
    return commands.map(v =&gt; {
        return array.slice(v[0] - 1, v[1]).sort((a, b) =&gt; a - b).slice(v[2] - 1, v[2])[0];
    });
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[프로그래머스] 위장 (해시 LEVEL2)]]></title>
            <link>https://velog.io/@dev_cecy/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EC%9C%84%EC%9E%A5-%ED%95%B4%EC%8B%9C-LEVEL2</link>
            <guid>https://velog.io/@dev_cecy/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EC%9C%84%EC%9E%A5-%ED%95%B4%EC%8B%9C-LEVEL2</guid>
            <pubDate>Tue, 22 Mar 2022 04:31:33 GMT</pubDate>
            <description><![CDATA[<p>프로그래머스 코딩테스트 연습의 해시-위장 문제</p>
<h1 id="문제">문제</h1>
<p>스파이들은 매일 다른 옷을 조합하여 입어 자신을 위장합니다.</p>
<p>예를 들어 스파이가 가진 옷이 아래와 같고 오늘 스파이가 동그란 안경, 긴 코트, 파란색 티셔츠를 입었다면 다음날은 청바지를 추가로 입거나 동그란 안경 대신 검정 선글라스를 착용하거나 해야 합니다.</p>
<pre><code>종류    이름
얼굴    동그란 안경, 검정 선글라스
상의    파란색 티셔츠
하의    청바지
겉옷    긴 코트</code></pre><p>스파이가 가진 의상들이 담긴 2차원 배열 clothes가 주어질 때 서로 다른 옷의 조합의 수를 return 하도록 solution 함수를 작성해주세요.</p>
<h2 id="제한사항">제한사항</h2>
<p>clothes의 각 행은 [의상의 이름, 의상의 종류]로 이루어져 있습니다.
스파이가 가진 의상의 수는 1개 이상 30개 이하입니다.
같은 이름을 가진 의상은 존재하지 않습니다.
clothes의 모든 원소는 문자열로 이루어져 있습니다.
모든 문자열의 길이는 1 이상 20 이하인 자연수이고 알파벳 소문자 또는 ‘_’ 로만 이루어져 있습니다.
스파이는 하루에 최소 한 개의 의상은 입습니다.</p>
<h2 id="입출력-예">입출력 예</h2>
<pre><code>clothes    return
[[“yellowhat”, “headgear”], [“bluesunglasses”, “eyewear”], [“green_turban”, “headgear”]]    5
[[“crowmask”, “face”], [“bluesunglasses”, “face”], [“smoky_makeup”, “face”]]    3</code></pre><h1 id="나의-풀이-1">나의 풀이 1</h1>
<p>reduce()를 통해 의상 타입의 중복값이 몇개인지 구했다.
해시문제 첫번째에서 배운 자료구조를 이용해보고자 그 중복값을 Map으로 만들어줬다.
의상의 타입이 모두 같은 경우는 배열의 길이를 반환했다.
그 외의 경우는 (의상1x의상2x …의상n) + (의상1x의상2 …의상n)의 식을 이용해서 총 경우의 수를 반환했다.</p>
<pre><code class="language-js">function solution(clothes) {
   let answer;

   const result = clothes.reduce((accu,curr)=&gt; {  // 1번
      accu.set(curr[1], (accu.get(curr[1])||0) +1);
       return accu;
    },new Map());  // 2번


   if(result.size === 1){ //3번
      answer = clothes.length
   } else {
     let sum=0;
     let square =1;
     for (let [key, value] of result) {
       sum = sum +result.get(key) 
       square = square*value
   }

    answer = sum+square
  }
  return answer
}</code></pre>
<h1 id="나의-풀이-2">나의 풀이 2</h1>
<p>위와 같이 풀고나니 첫 2가지 테스트 케이스는 통과했지만, 실제 채점에서는 통과되지 않는 테스트 케이스가 있었다. 살펴보니 경우의 수를 구하는 식이 범용되지 않는것 같았다. 그래서 ((의상1+1)*..(의상n+1))-1로 식만 바꿔보니 통과되었다🎉</p>
<pre><code class="language-js">function solution(clothes) {
     let answer;

     const result = clothes.reduce((accu,curr)=&gt; {
      accu.set(curr[1], (accu.get(curr[1])||0) +1) ;
       return accu;
      },new Map());


     if(result.size === 1){
       answer = clothes.length
     } else {
      let initial=1;  // ((의상1+1)*..(의상n+1))-1로 경우의 수를 구하는 식을 변경해주었다. 
      for (let [key, value] of result) {
       initial = initial * (value+1) 
       answer = initial-1

      }
    }
   return answer
}</code></pre>
<h1 id="나의-풀이-3">나의 풀이 3</h1>
<p>해시 첫번째 문제에서 Map과 Set을 배웠기 때문에 써먹어봐야지! 하는 마음이 있었다. 그래서 의상의 중복값을 구할때 불필요하게 Map을 만들어준것 같았다. 그래서 initialValue에 Map을 제거하고 객체로 설정한 뒤 다시 풀어보았다.</p>
<pre><code class="language-js">function solution(clothes) {
  let answer;
 const newObject =  clothes.reduce((a,b)=&gt; {
  a[b[1]] = (a[b[1]] || 0)+1;
    return a
},{});
 const test = Object.values(newObject)
 const result = test.reduce((c,d)=&gt;{
  return c*(d+1)
},1)
  return answer = result -1
}</code></pre>
<h1 id="다른분의-풀이">다른분의 풀이</h1>
<p>배운점🙋🏻‍♀️</p>
<p>변수선언으로 값을 할당해서 쓰지않고 바로 return하여 그 값을 쓰는 방식도 생각해 볼 수 있다.
Object.values(object)을 통해서 열거가능한 값을 배열로 리턴 할 수 있다.</p>
<pre><code class="language-js">function solution(clothes) {
  return Object.values(clothes.reduce((a,b)=&gt; {
    a[b[1]] = (a[b[1]] || 0)+1;
      return a;
  },{})).reduce((c,d)=&gt;{
    return (c*(d+1));
  },1)-1
}</code></pre>
<p>풀었던 코드를 블로그로 옮기면서 다시 읽어보니 변수나 메소드 명을 제대로 지어주지 않은 것이 눈에 보였다. 연습에도 변수명 제대로 쓸것!🙆🏻‍♀️</p>
]]></description>
        </item>
    </channel>
</rss>