<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>idojustdo_it.log</title>
        <link>https://velog.io/</link>
        <description>함께 일하고 싶어지는 동료가 되기를 원하는 프론트엔드 개발자입니다.</description>
        <lastBuildDate>Thu, 18 Jan 2024 01:10:33 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>idojustdo_it.log</title>
            <url>https://velog.velcdn.com/images/idojustdo_it/profile/07cd0575-1e1c-42fb-a3bc-150ea2e7392e/image.jpeg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. idojustdo_it.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/idojustdo_it" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[[리팩토링1] 모듈화 , 모달]]></title>
            <link>https://velog.io/@idojustdo_it/%EB%A6%AC%ED%8C%A9%ED%86%A0%EB%A7%811-%EB%AA%A8%EB%93%88%ED%99%94-%EB%AA%A8%EB%8B%AC</link>
            <guid>https://velog.io/@idojustdo_it/%EB%A6%AC%ED%8C%A9%ED%86%A0%EB%A7%811-%EB%AA%A8%EB%93%88%ED%99%94-%EB%AA%A8%EB%8B%AC</guid>
            <pubDate>Thu, 18 Jan 2024 01:10:33 GMT</pubDate>
            <description><![CDATA[<p> 회사 시즌중에는 굉장히 바빴기 때문에 프로젝트를 우선적으로 출시한다는 생각으로 빠르게 움직여, 3개의 프로젝트를 기한내에 마무리하고나니, 내가 잘하고있는가에 대한 의문과함께 리펙토링을 해야겠다는 생각이 강하게들어 리팩토링을 시작하였습니다.</p>
<p>나는 (사수가 없는)주니어인데, 리펙토링한다고 달라질까? 라는 의문이 있어 CTO님한테도 상담을 요청했었다.
CTO님은 그럼, 물론이지 지금의 너와 프로젝트 이전의 너는 다르다고 격려해주셨다.</p>
<p>(일단 가보자고, 현재 회사의 개발문화는 내가 선도한다.(패기))</p>
<h2 id="모듈화">모듈화</h2>
<blockquote>
<p>global하게 어디에나 부품처럼 사용될 수 있는 것</p>
</blockquote>
<p>모듈화에서 가장중요한 키워드는 <strong>재사용성</strong>, <strong>독립성</strong>이라 생각한다.</p>
<p>직관적으로 디자이너와 함께 가장 쉽게 자주 이야기한 컴포넌트인 모달 컴포넌트가 떠올라 모달 컴포넌트를 모듈화에 중점으로 리팩토링을 진행하였다.</p>
<p>굳이 나누자면 크게 2단계로 필터링 되었다.</p>
<p>재사용성과, 독립성을 둘다 생각하여 한번 걸르고, 한번 리팩토링된 코드를 보고 이게 최선인가? 라는 생각을 했다. (아무래도 첫 리팩토링이며, 기술적으로 부족하기에 더 꼼꼼해야한다.)</p>
<p>현재 모달컴포넌트는 다음과 같은 기능을 한다.</p>
<p><img src="https://velog.velcdn.com/images/idojustdo_it/post/9991c4d1-21d2-42a0-9726-8ed9194e6f97/image.png" alt=""></p>
<p>부모컴포넌트에서 제목, 본문 내용, 버튼1의 (이름,스타일), 버튼2(이름,스타일)의 데이터를 받고,
각 버튼 눌렀을 때 어떤 메서드가 실행되는지.</p>
<p>이전에는 하나하나 모든 요소를 매개변수로 받았다. 위 모달에 파란색으로 표시되는 부분도 따로 받았었다.</p>
<p>리팩토링할 때 보니 충분히 간소화 할 수 있겠다고 생각하여 다음 코드를 
<strong>Before</strong></p>
<pre><code>&lt;div class=&quot;comments&quot; v-html=&quot;comments1&quot; v-if=&quot;comments1.length&gt;0&quot; &gt;&lt;/div&gt;
&lt;div&gt;
&lt;span class=&quot;bluecomments&quot; v-if=&quot;bluecomments.length&gt;0&quot;&gt;{{bluecomments}}&lt;/span&gt; 
&lt;span v-if=&quot;comments2.length&gt;0&quot;&gt; {{comments2}} &lt;/span&gt;
&lt;/div&gt;  

&lt;div style=&quot;display: flex;justify-content: center; width: 100%;&quot;&gt;
  &lt;img  v-if=&quot;sub_img&quot; :src=&quot;sub_img&quot;/&gt;
&lt;/div&gt;</code></pre><p><strong>After</strong></p>
<pre><code>&lt;div class=&quot;comments&quot; v-html=&quot;comments1&quot; v-if=&quot;comments1.length&gt;0&quot; &gt;  &lt;/div&gt;
&lt;div style=&quot;display: flex;justify-content: center; width: 100%;&quot;&gt;
  &lt;img  v-if=&quot;sub_img&quot; :src=&quot;sub_img&quot;/&gt;
&lt;/div&gt;</code></pre><p>다음과 같이 간단해졌다.</p>
<ul>
<li>생각하지않고 코드를 짜다보니, 쉽게 할 수 있는 코드도 오히려 번거롭게 코드가 더 늘어나면서 가독성도 떨어지게 된 케이스의 대표적인 예시라고 생각한다.
vue에서 v-html사용해서 바인딩하여 매개변수의 값에서도 html 태그를 사용할 수 있도록하여 태그에 스타일을 추가했습니다.</li>
</ul>
<p>가독성을 위해 매개변수를 줄일 수는 없지만 수가 너무나도 많을때 어떻게해야 가독성이 올라갈까 고민을 하였는데, 나의 경우는 매개변수마다 숫자를 붙여 가독성과 어느정도의 효율성을 올렸다고 생각한다. (부모컴포넌트에서 필요한 매개변수만을 보내줄수 있도록)  </p>
<pre><code>    show: function(title_1, comments1_2,btn1_name_3,btn1_style_4,btn2_name_5,btn2_style_6,
    route_7,params_8,title_img_9,sub_img_10,callback_11) {
      this.show_it = true;  
      this.title = title_1;
      this.comments1 = comments1_2;
      this.btn1_name = btn1_name_3;
      this.btn1_style = btn1_style_4;
      this.btn2_name = btn2_name_5;
      this.btn2_style = btn2_style_6;
      this.title_img =title_img_9?  require(`../assets/${title_img_9}.png`) : &#39;&#39;
      this.sub_img =  sub_img_10?  require(`../assets/${sub_img_10}.png`): &#39;&#39;
      this.btn1_id = btn1_name_3;
      this.btn2_id = btn2_name_5;    

      this.route = route_7;         //route값에 http가 들어가면 새로운 브라우저 탭으로 연다.
      this.params = params_8        //리다이렉트 쿼리값으로 넘겨 로그인페이지의 경우 로그인후 리다이렉트 페이지로 보내준다.
      this.callback = callback_11;  //부모컴포넌트에서 필요한 메소드를 콜백함수로 받는다.(버튼클릭시 작동되게)
    },



//부모컴포넌트

 this.$refs.modal_popup.show(&#39;잠깐, 혜택을 포기하시나요?&#39;,&#39;지금 닫으면, 견적과 혜택이 사라질 수 있습니다.&lt;br/&gt;견적서룰 문자로 발송하여 내역을 저장하세요.&lt;br/&gt;&lt;span style=&quot;font-size:13px;&quot;&gt;(혜택은 조기종료될 수 있습니다.)&lt;/span&gt;&#39;,
&#39;견적서로 돌아가기&#39;,style1,&#39;닫기&#39;,style2,&#39;quatation&#39;,&#39;&#39;,&#39;warning&#39;,&#39;quatation/hook_reward&#39;)
</code></pre><p>위와같이 모든 매개변수를 보낼때 몇번째자리인지 인지하고 있어야 왔다갔다 하지않고 코드를 잘 적을 수 있다.</p>
<p>버튼1또는 버튼2를 눌렀을때 모달창이 닫히는 기능은 기본이었고, 모달컴포넌트가 속한 부모컴포넌트에따라 버튼을 눌렀을시 라우팅이되거나 리다이렉션, 또는 부모컴포넌트의 함수를 사용해야하는 상황들이 많이 일어났다. 
 리팩토링 이전에는 버튼명에 따라 라우팅을 다르게 하는 방식을 채택했는데, 그럼 부모컴포넌트에 대한 의존성이 굉장히 올라가서 매 상황마다 코드가 추가되는 상황이 벌어진다.
그래서 매개변수에 함수를 넣어 보내고 버튼을 클릭시 함수가 실행되고,
버튼 이름이아닌 받는 매개변수에서 라우팅을 할 수 있도록 코드를 짰습니다.</p>
<p><strong>Before</strong></p>
<pre><code>    signup_hide: function() {  //버튼 명에따라 라우팅하거나 다른 상황들을 매번 만들어야했다.
    if(this.btn2_name == &#39;회원가입&#39;||(this.query_value&amp;&amp;this.btn2_name == &#39;회원가입&#39;)){ 
        if(this.redirect){
        const new_query = {redirect_name: this.redirect,purpose:&#39;signup&#39;}
        const update_query ={...this.query_value,...new_query}
        return  this.$router.push({name:this.route ,query:update_query})
        }else{
          return  this.$router.push({name:this.route ,query:this.query_value})
        }
      } if(this.route) {
      if(this.redirect){
      const new_query = {redirect_name: this.redirect}
      const update_query ={...this.query_value,...new_query}
      return  this.$router.push({name:this.route ,query:update_query})
      }else{
      return  this.$router.push({name:this.route ,query:this.query_value})
      }}
      if(this.title == &#39;문자 발송 완료&#39;){
      return this.show_it = false;
      } if(this.title == &#39;온라인 계약신청 완료&#39;){ 
      return  this.$router.push({name:&#39;quatation&#39;})
      } if(this.btn1_name ==&#39;견적서로돌아가기&#39;){
      return  this.$router.push({name:&#39;quatation&#39;})
    } 
    if(this.title ==&#39;온라인 계약을 요청하시겠습니까?&#39;){
      return this.$parent.push_data(&#39;online_request&#39;);
      }
     else return this.show_it = false;
    },

  }
</code></pre><p><strong>after</strong></p>
<pre><code> redirect_check: function() {  //매개변수 확인후 각 매개변수에 맞게 라우팅, 매개변수가 함수라면 함수 실행한다.
      const update_query = { ...this.query_value, ...this.params };

      if (this.route &amp;&amp; this.params) {
        return this.$router.push({ name: this.route, query: update_query });
      }
      if(this.route &amp;&amp; !this.params){
        return this.$router.push({ name: this.route });
      }
    },

    signup_hide: function() {
      if (typeof this.callback === &#39;function&#39;) {
        return this.callback();
      }
      this.redirect_check();
      this.show_it = false;
      }

  }</code></pre><p>리팩토링후 코드가 약 40-50줄 줄었고, 가독성또한 좋아진게 보인다. </p>
<blockquote>
<p>*<em>모듈화 *</em></p>
</blockquote>
<ul>
<li>global하게 어디에서나 사용할 수 있다</li>
<li>어떤 특정한 상황에서도 의존성을 올리지 않는 방향으로 가야한다.
(굳이 해야한다면, Data또는 함수를 받아둘 자리만 만들어주는 방향으로..)</li>
</ul>
<blockquote>
<p><strong>리팩토링</strong></p>
</blockquote>
<ul>
<li>리팩토링 할 컴포넌트의 분석,다른 컴포넌트에 영향을 미친다면, 그 컴포넌트 또한 분석할 것 (JS, HTML, CSS(JS와연관되어있다면)</li>
<li>기능이 중복되는가? </li>
<li>숏코딩화 시켰지만 가독성이 올라가는가?</li>
<li>기능적으로 더 빠른 실행속도를 올릴 방법이 있는가?</li>
</ul>
<p>이번 리팩토링 작업으로 모듈화, 숏코딩과 가독성에 대해 실무에 있어 고민해보고 시도해보는 시간을 갖았는데, 리팩토링은 무조건 필요한 시간이라는 것, 기록과 회고에 대해 많은 관점이 바뀌게 되었다. 우리 모두 기록하고 성찰합시다 :) </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Oauth2.0의 기본 정리]]></title>
            <link>https://velog.io/@idojustdo_it/Oauth2.0%EC%9D%98-%EA%B8%B0%EB%B3%B8-%EC%A0%95%EB%A6%AC</link>
            <guid>https://velog.io/@idojustdo_it/Oauth2.0%EC%9D%98-%EA%B8%B0%EB%B3%B8-%EC%A0%95%EB%A6%AC</guid>
            <pubDate>Mon, 15 Jan 2024 02:21:37 GMT</pubDate>
            <description><![CDATA[<h1 id="oauth20">Oauth2.0</h1>
<blockquote>
<p>Oauth2.0 기술은 유저가 사용하려는 서비스에서 이미 유저가 가입되어있는 다른 서비스에게 유저인증과 유저리소스를 액세스 토큰을 사용하여 받는 기술.</p>
</blockquote>
<h3 id="oauth20의-구성요소">Oauth2.0의 구성요소</h3>
<pre><code>Resource Owner : 리소스의 주인, 보통 사용자. 
Client : 유저가 사용하려는 서비스 (여러 문서에 써드파티 서비스를 가르킨다.)
Authorization Server : 인증 서버 (유저가 이미 가입되어있는 서비스의) 
Resource Server : 리소스 서버 (유저가 이미 가입되어있는 서비스의)  사용자들의 여러 정보, 기능들이 들어가 있다.</code></pre><h3 id="구조-대표방식">구조 (대표방식)</h3>
<p><img src="https://velog.velcdn.com/images/idojustdo_it/post/09848488-9cb2-4760-9788-2185673e5939/image.png" alt=""></p>
<p>먼저, RFC6749에 근거한 다이어그램표를 보면, 이미 등록이 이뤄진 상태에서 다음과 같은 순서를 진행한다. 
  (클라이언트는 이미 인증서버에 인증을 한 이후를 나타낸다 그래서 아래와같은 등록과정을 추가했다.)</p>
<p>사전단계 ) Client를 이미 유저가 가입되어있는 서비스(네이버,구글,카카오톡,페이스북,애플,트위터..)에 등록. (각 서비스마다 등록하는 방식이 상이하다.)
등록과정에서 공통적으로 설정하는부분 redirect URI, 받아야하는 정보 Client_id , Client_secret, 해당서비스의 코드설정</p>
<ol>
<li><p>Client (우리의 서비스)에서 자격증명 요청을 보낸다. 
[로그인 버튼을 눌러 Resourcer Owner 에게 로그인 요청을 함, 이때 작은창으로 보통 authorization server와 연결된 로그인화면이 나옴]</p>
</li>
<li><p>Resourcer Owner는 자격 증명을 완료한 요청을 클라이언트에게 보낸다. 
[로그인 완료 이후 클라이언트한테 요청한다고한다, 내가 느낀점은 작은화면에서 authorization server와 Owner가 즉각적으로 소통하는 것으로 보임  보통 로그인화면에  URI안에 Client가 Authorization Server에게 보낼 정보가 담겨져있다.]</p>
</li>
<li><p>Client에서 자격증명 완료 되었다는 정보와함께 client정보를  Authorization Server로 보낸다.</p>
</li>
<li><p>Authorization Server에서 자격증명 완료 확인을 보고 Resource Server에서 자료를 받을 수 있는 Access Token을 Client한테 발급한다.</p>
</li>
<li><p>Client에서 Access Token을 갖고 Resource Server에 접근한다.
Resourcer Server는 Access Token을 확인하고 Client에게 Protected Resource를 전달한다.</p>
</li>
</ol>
<p>다음과 같이 Oauth 2.0에 기본 프로토콜 플로우가 진행이 된다고 설명된다. (카카오v1버전일때 위와같은 플로우로 진행되었었다.) </p>
<p><strong>액세스토큰을 받는 방식 4가지</strong></p>
<pre><code>Authorization Code Grant (권한부여 승인 코드)

Implicit Grant (암묵적 승인)

Resource Owner Password Credentials Grant (리소스 오너 자격증명)

Client Credentials Grant (클라이언트 자격증명)</code></pre><p> 자세한 예시는 RFC문서 또는 여러 좋으신 개발자분들의 기록일지를 보면 자세한구조와 설명이 서술되어있습니다.
<a href="https://datatracker.ietf.org/doc/html/rfc6749#section-4">https://datatracker.ietf.org/doc/html/rfc6749#section-4</a>
<a href="https://chipmaker.tistory.com/entry/OAuth20-%EC%A0%95%EB%A6%AC">https://chipmaker.tistory.com/entry/OAuth20-%EC%A0%95%EB%A6%AC</a></p>
<p>요즘은 대부분의 서비스에서 보안상의 이유로 Authorization Code Grant (권한부여 승인 코드) 방식을 취한다고 생각한다.</p>
<p><strong>Authorization Code(인가코드)를 사용할때 보안성이 더 뛰어난 이유</strong></p>
<ul>
<li>Access Token을 이전에 방식과달리 안전하게 통신하여 받을 수 있습니다.</li>
<li>Resource Owner의 ID와 PW가 Client에게 직접적으로 노출되지않으며 , Client는 Authorization Code(인가코드)만 받습니다.</li>
<li>Authorization Code(인가코드)의 수명이 짧아, 중간에 탈취 당하더라도 오용할 수 있는 기회를 막을 수 있게됩니다.</li>
<li>Authorzation Server와 권한 부여를 위해 상호작용하는 단계가 늘어남에따라 보안성이 더올라갑니다. </li>
<li>클라이언트 프론트가아닌 백엔드에서 통신하게되어 Resource Owner에게 직접적으로 Access Token을 주지 않아도 권한 부여를 받을 수 있어 더욱 안전합니다.</li>
</ul>
<h4 id="구현에서의-모호함">구현에서의 모호함?</h4>
<p>구현에있어서는 자유도가 높아 백엔드와 프론트의 확실한 소통이 필요하다고 생각합니다.
RFC문서나 여러 자료들을보면 구현하려는 우리의 서비스를 Client라고 명명하기에 프론트와 백엔드를 구분지어 생각하여 구현을 생각해야합니다.</p>
<p>다음과 같이 프로토콜 플로우를 수정할 수 있습니다.</p>
<p><img src="https://velog.velcdn.com/images/idojustdo_it/post/6213098e-639e-4bc8-84e7-bd5b6a00bd89/image.png" alt=""></p>
<p> 다음과 같이 로그인을 진행할 수 있지않을까 생각된다. 인가 코드를 받는 형태로 추가된다면 자격증명 완료 후 액세스토큰이아닌 인가코드를 받는 과정을 추가하여 
액세스토큰을 받는 방식으로 진행하면 되지 않을까 예상됩니다. </p>
<p>추후 카카오톡 또는 구글로그인을 이용한 Oauth 2.0 방식을 구현 하도록하겠습니다.(JAVA 공부를진행해서 풀스택을 향해)</p>
<p>참고 사이트 및 자료
<a href="https://opentutorials.org/course/3405">https://opentutorials.org/course/3405</a> (생활코딩)
<a href="https://datatracker.ietf.org/doc/html/rfc6749">https://datatracker.ietf.org/doc/html/rfc6749</a> (RFC문서)
<a href="https://chipmaker.tistory.com/entry/OAuth20-RFC6749-%EC%A0%95%EB%A6%AC-2">https://chipmaker.tistory.com/entry/OAuth20-RFC6749-%EC%A0%95%EB%A6%AC-2</a> 
<a href="https://hudi.blog/oauth-2.0/">https://hudi.blog/oauth-2.0/</a>  </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Web Push? (3) (feat. RFC 8030)]]></title>
            <link>https://velog.io/@idojustdo_it/Web-Push-3-feat.-RFC-8030</link>
            <guid>https://velog.io/@idojustdo_it/Web-Push-3-feat.-RFC-8030</guid>
            <pubDate>Fri, 11 Aug 2023 08:26:29 GMT</pubDate>
            <description><![CDATA[<p>이번 기술 세미나를 준비하면서, 웹푸시 기술에 대해 한문장으로 다음과 같이 정의 해보았습니다.</p>
<blockquote>
<p>*<em>웹푸시 기술은 웹서버가 실시간으로 실행가능한 알림과 메세지를 사용자 장치의 브라우저 내 웹페이지에서 안전하게 확인할 수 있게하는 기술. *</em></p>
</blockquote>
<p>RFC 8030 제목을 보면 알 수 있듯이 &#39;Generic Event Delivery using HTTP Push&#39; 제목 내에도 HTTP 통신을 한다고 이야기하고 있습니다. HTTP통신은 TCP 기반의 통신 프로토콜 중 하나이다. 그래서 HTTP는 L7 과 L4 계층에서 주로 작동한다는 것이기에 웹 푸시 기술은 주로 응용과 전송계층과 관련있다는 것을 알 수 있었습니다.</p>
<p><strong>웹푸시 작동구조</strong>
RFC 8030 문서에서는 작동구조를 다음과 같이 정리하고 있었다.<img src="https://velog.velcdn.com/images/idojustdo_it/post/4cb794c4-af9c-43dc-9144-6137ec400f19/image.png" alt="">
웹푸시를 이해하는 입장에서는 조금 부족한 구조도와 설명이라고 생각하였습니다.
유저와 푸시서비스는 서로 어떻게 모니터링을 하는건지 웹 서버에서 특정 그룹에게만 메세지를 보내려하는데 그 특정그룹을 어떻게 확인할 수 있는 건지와 같은 내용이 미흡 하여,
제가 공부하면서 이해한 바탕으로 구조도를 좀 더 보충하자면 다음 과같은 구조도가 나옵니다.</p>
<p><img src="https://velog.velcdn.com/images/idojustdo_it/post/2e2bd943-f796-417c-ba3c-1d22c3dd25cf/image.png" alt=""></p>
<p>서비스 워커를 등록할 때는 따로 클라이언트쪽에서 UI적으로 바뀌는게 없기때문에 눈치채기가 어렵다. 
등록 후, 구독 여부를 체크하여 구독 허용을 하게되면 푸시서비스로부터 자신의 구독정보를 받아 (이후 이 구독정보를 통해 구독상태를 변경할 수 있는 권한을 얻는다.) 웹 서버에서도 각 사용자의 구독여부를 알 수 있도록 구독정보를 전달 받고나게 되면, 푸시메세지를 보낼 수 있는 권한이 생겨 푸시메세지와 보내려는 유저의 구독정보를 푸시서비스에 전송하고 푸시서비스는 서비스워커에게 전달하면 서비스워커는 사용자의 활성 유무나 사용자가 받을 수 있는 상황인지 판단하여 브라우저에 메세지를 일시저장할지 푸시서비스에 저장할지 정하고 사용자가 받을 수 있는 상황에 메세지를 보내게됩니다.</p>
<p><strong>OSI 7계층에 대입</strong>
다음과 같은 플로우에서 RFC문서를 기반으로 크게 나누면 2가지 형식의 HTTP 통신으로 나뉘어지게 됩니다.</p>
<p>HTTP/1.1 과 HTTP/2로 나뉘게되는데 RFC 문서 맨처음에 Abstract을 보게되면 This scheme uses HTTP/2 server push. 다음과같은 한줄을 보게됩니다. 이 스키마는 HTTP/2 서버푸시를 사용하였다. 
서버 푸시는 클라이언트에서 먼저 request없이 서버에서 먼저 판단하여 마땅히 받아야할 파일들 (여기에선 메세지가 해당)을 미리 서버에서 먼저 클라이언트로 보내, 더빨리 데이터를 랜더링하여 로딩속도를 줄이는 등의 효율을 나타내는 기능입니다.</p>
<p>HTTP/2는 필수적으로 TLS 인증을 받야만하는것은 아니지만 여러 브라우저에서 HTTP/2를 사용하기위해선 HTTPS 프로토콜을 받아야만한다 라고 정해둬서 받아야만합니다.
TLS/SSL 인증은 표현 계층에 해당할 수 있습니다.</p>
<p>서비스 워커는 브라우저 백그라운드에서 작동하는 자바스크립트 파일인데 프록시 서버와 같은 역할을 할 수 있습니다. 서비스워커의 백그라운드에서 작동하는 것, 푸시알림과 캐싱기능은 응용계층이라 할 수 있고 웹서버와 브라우저 간에 네트워크 관리측면에서는 세션계층이라 할 수 있습니다.</p>
<p>그래서 웹푸시 기능은 4,5,6,7계층에서 작동한다고 이야기할 수 있습니다.</p>
<p>글을 다시 정리해봤는데요, 이 외에도 수정이나 추가할 내용이 있는지 확인해보시고, 궁금한 점이 있다면 언제든지 질문해주세요!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[랜딩페이지에 들어간 기능,(내가 보기위해..)]]></title>
            <link>https://velog.io/@idojustdo_it/%EB%9E%9C%EB%94%A9%ED%8E%98%EC%9D%B4%EC%A7%80%EC%97%90-%EB%93%A4%EC%96%B4%EA%B0%84-%EA%B8%B0%EB%8A%A5%EB%82%B4%EA%B0%80-%EB%B3%B4%EA%B8%B0%EC%9C%84%ED%95%B4</link>
            <guid>https://velog.io/@idojustdo_it/%EB%9E%9C%EB%94%A9%ED%8E%98%EC%9D%B4%EC%A7%80%EC%97%90-%EB%93%A4%EC%96%B4%EA%B0%84-%EA%B8%B0%EB%8A%A5%EB%82%B4%EA%B0%80-%EB%B3%B4%EA%B8%B0%EC%9C%84%ED%95%B4</guid>
            <pubDate>Thu, 18 May 2023 02:48:54 GMT</pubDate>
            <description><![CDATA[<h3 id="들어간-기능">들어간 기능?</h3>
<ol>
<li><p>원하는 요소 (이번 경우에는 서브헤더)가 일정 구간만큼 따라오는 기능</p>
</li>
<li><p>버튼 누르면 해당 요소로 스크롤 조정</p>
</li>
<li><p>캐러셀 (가로 슬라이드)</p>
</li>
<li><p>background-image, 이미지 사용하여 반응형 맞추기.</p>
</li>
</ol>
<h3 id="원하는-요소가-일정구간-만큼-따라오는-기능">원하는 요소가 일정구간 만큼 따라오는 기능.</h3>
<p>제가 원하는 요소가 원하는 구간만큼 위치가 고정되어 따라오는 기능을 구현하고 싶었니다.
그러기 위해선 
일정구간 만큼은 position: fixed, 으로 변했다가 그 구간이 지나면 static으로 바뀌어 일반적인 흐름을 따르게 되야만했습니다.</p>
<p>position과 관련되어 속성을 좀 더 찾아보니 position: sticky가 위와 같은 역할을 한다고 발견하게 되어 해당 영역을 설정만 해준다면 해당 영역에서만 fixed로 움직이는 것을 확인했습니다.
fixed로 움직이기때문에 top,right,bottom,left속성을 설정해줘야만 합니다</p>
<h3 id="버튼-누르면-해당-요소로-스크롤이-이동하는-기능">버튼 누르면 해당 요소로 스크롤이 이동하는 기능</h3>
<p>vue같은 경우에는 ref를 사용하여 scroll을 사용하게되면 굉장히 편하게 스크롤링할 수 있다.
내가 스크롤링하고 싶은 요소에 ref값을 주고 scrollIntoView()를 사용하게 되면 코드 한줄로 사용할 수 있게된다. </p>
<pre><code>this.$refs.event1.scrollIntoView({behavior:&quot;smooth&quot;})</code></pre><p>위와 같이쓰게 되면,event1에 스크롤링을 하는 코드입니다.
저는 모바일 환경에는 다른 요소로 보냈어야해서, 아래와 같이 코드를 짰습니다.</p>
<pre><code>      if (window.innerWidth &lt;= 800) {
        this.$refs.m_event1.scrollIntoView({behavior:&quot;smooth&quot;})
        this.isOpen = false;
      }else {
        this.$refs.event1.scrollIntoView({behavior:&quot;smooth&quot;})}},</code></pre><h3 id="캐러셀">캐러셀</h3>
<p>이번 랜딩페이지에서 필요했던 캐러셀의 기능은 자동 넘기기, 드래그, 페이지네이션 점표현,
캐러셀이 포함된 div안에서 각각의 슬라이더가 div의 테두리에 걸려서 다음 슬라이더가 보여서 콘텐츠가 많아보이게 하는 약 4가지의 기능이 필요하여 여러 캐러셀 모듈을 찾아 보던중 
vue-slick-carousel을 찾게되었고 참고 블로그쪽에 해당 깃허브 문서를 보면 사용법이 나옵니다.</p>
<h3 id="background-image-이미지-사용하기">background-image 이미지 사용하기</h3>
<p>backgound-image를 사용하여 흐릿하게 해상도가 깨지지 않으며, 반응형에 맞는 배경을 적용시키려고 여러 노력을 했습니다. vh를 사용하여 첫 시도를 하였지만, 모바일환경에서 url표시줄이나 자판이 나올때 스크롤이 유지가 되지않아서 vh를 포기하고, 결국 높이 고정값을 두고 width값을 대부분의 해상도의 최고값인 1920px을 생각하여 image를 디자이너에게 부탁하였습니다.
저희 콘텐츠들은 가운데에만 몰려있어서 가운데콘텐츠는 그대로 유지하고 콘텐츠의 뒷배경만 1920px으로 맞춰 진행을하여 이미지 원본에맞는 높이값을 적용해 이미지 해상도가 깨지지 않으며 출력되는 것을 확인 할 수 있었습니다.</p>
<pre><code>    background-image: url(주소);
    background-size: cover;
    background-position: center ;</code></pre><p>3가지 속성을 지정했을대 image크기에맞게 width값과 height값을 설정해주면 원하는 결과물을 얻을 수 있습니다.</p>
<p><img src="https://velog.velcdn.com/images/idojustdo_it/post/c7a9b7e1-80e6-4429-bece-09c3f1e21cfc/image.jpg" alt="">
<strong>첫번째 해상도는 맞췃지만 vh를 예측에 실패해서 비율을 못맞춘 랜딩페이지느낌</strong></p>
<p><img src="https://velog.velcdn.com/images/idojustdo_it/post/b6add85b-5cd3-43c2-a237-0289912335ef/image.jpg" alt="">
꼭 완벽한 반응형을 만들어보리라..!</p>
<p>참고 블로그</p>
<p><a href="https://tech.lezhin.com/2019/03/20/css-sticky">https://tech.lezhin.com/2019/03/20/css-sticky</a> postion:sticky 관련
<a href="https://github.com/gs-shop/vue-slick-carousel">https://github.com/gs-shop/vue-slick-carousel</a> 캐러셀 관련</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Vue Input창 동적추가]]></title>
            <link>https://velog.io/@idojustdo_it/Vue-Input%EC%B0%BD-%EB%8F%99%EC%A0%81%EC%B6%94%EA%B0%80</link>
            <guid>https://velog.io/@idojustdo_it/Vue-Input%EC%B0%BD-%EB%8F%99%EC%A0%81%EC%B6%94%EA%B0%80</guid>
            <pubDate>Thu, 20 Apr 2023 02:01:53 GMT</pubDate>
            <description><![CDATA[<h3 id="1-요청사항-테이블내에-input창-추가-행-추가-x">1. 요청사항 테이블내에 input창 추가 (행 추가 X)</h3>
<p>Input 창을 버튼을 누를때마다 1개씩 추가하거나 제거하는 기능을 요청받았습니다. 
현재 이미 테이블 내에서 반복으로 데이터를 보여주고 있었고, 테이블 전체행이 추가되는 것이아니라 input 창만 추가되는 기능이 필요했습니다.</p>
<h3 id="2-1-트러블-슈팅-행추가가-되어버림">2-1. 트러블 슈팅 (행추가가 되어버림)</h3>
<p> 블로그 글에서 원하는 기능을 보았지만, 같은 방식으로 진행 했을시 <img src="https://velog.velcdn.com/images/idojustdo_it/post/5b0039e6-c298-44b8-bbe7-e7c38f8521b2/image.png" alt="">
원치않는 행들이 같이 늘어났습니다 
이미 v-for 반복문으로 데이터를 받아서 보여주기때문에 제가 원하는 객체만 반복문을 한번 더 사용하여 이중 반복을 써야한다는 사실을 깨닫고 해당 객체부분만 반복문을 사용하였습니다.</p>
<pre><code>&lt;template&gt;
&lt;div&gt;
 &lt;template v-for=&quot;(item, index) in list&quot;&gt; 
 &lt;tr :class=&quot;index%2==1 ? &#39;gray_row&#39;:&#39;&#39;&quot; v-bind:key=&quot;item.key&quot; &gt;
          &lt;td :class=&quot;{need_to_send:item.ProgramOrderItem__status==&#39;order&#39;}&quot; style=&quot;text-align:center;&quot;&gt;{{item.id값}}&lt;/td&gt;
          &lt;td&gt;{{item.날짜}}/{{item.날짜}}&lt;/td&gt;
          &lt;td&gt;{{얻은 데이터}}&lt;/td&gt;
          &lt;td&gt;{{item.데이터}}&lt;/td&gt;
          ....
            &lt;td v-if=&quot;item.ProgramOrderItem__status==&#39;check&#39;&quot;&gt;&lt;b-form-input v-model=&quot;item.ProgramOrderItem__log_code&quot; placeholder=&quot;번호기입&quot;&gt;&lt;/b-form-input&gt;//반복을 한번더
              &lt;b-button class=&quot;sort_button&quot; variant=&quot;info&quot; @click=&quot;removeInput(index)&quot; &gt;제거&lt;/b-button&gt;
              &lt;b-button class=&quot;sort_button&quot; style=&quot;width:60%; margin: 0 10px;&quot; variant=&quot;info&quot; @click=&quot;addInput()&quot; &gt;추가&lt;/b-button&gt;

            &lt;/td&gt;
 &lt;/template&gt; 
&lt;/div&gt;
&lt;/template&gt;

 data: function() {
    return {
      and_param:{},
      list:[],
      codes:[{ProgramOrderItem__log_code:&#39;&#39;}],
    };
  },
  methods: {
    addInput(){
          this.list.push({ProgramOrderItem__log_code:&#39;&#39;}); //list가아니라 codes로 수정헸어야했다.
    },
    removeInput(index){
      console.log(this.codes.length)
      if (this.codes.length==1){
        alert(&#39;더 이상 제거 할 수 없습니다.&#39;)
      }else{
        this.codes.splice(index, 1);
      }
    },</code></pre><h3 id="2-2-트러블슈팅-2-인풋-창만추가-되었지만하나의-인풋-창처럼-작동-데이터-바인딩-오류">2-2 트러블슈팅 2 (인풋 창만추가 되었지만,하나의 인풋 창처럼 작동 데이터 바인딩 오류)</h3>
<p><img src="https://velog.velcdn.com/images/idojustdo_it/post/b8a8b767-1540-49b1-9f69-9ec258e7c905/image.png" alt="">
 하지만, input창은 늘어났지만 하나의 인풋 창처럼 작동하게되어 데이터 바인딩이 잘못되었다는 것을 인지하고 내가 원하는 객체의 인풋에 바인딩을 하니 아래와 같이 잘 작동하였다.</p>
<h3 id="3해결">3.해결</h3>
<p><img src="https://velog.velcdn.com/images/idojustdo_it/post/2991cc5e-ed99-4c07-893b-a31cddbd6b63/image.png" alt=""><img src="https://velog.velcdn.com/images/idojustdo_it/post/48832d27-ed2c-4c59-ae95-981cb891d174/image.png" alt="">
해당 배열인 codes를 보내면 됩니다 원래는 문자열이었는데 바꾸게되면서 [{}] 배열안 객체가 되었기때문에 api 수정을 해서 백엔드와 통신하게되면 마무리가 됩니다.</p>
<pre><code>&lt;template&gt;
&lt;div&gt;
 &lt;template v-for=&quot;(item, index) in list&quot;&gt; 
 &lt;tr :class=&quot;index%2==1 ? &#39;gray_row&#39;:&#39;&#39;&quot; v-bind:key=&quot;item.key&quot; &gt;
          &lt;td :class=&quot;{need_to_send:item.ProgramOrderItem__status==&#39;order&#39;}&quot; style=&quot;text-align:center;&quot;&gt;{{item.id값}}&lt;/td&gt;
          &lt;td&gt;{{item.날짜}}/{{item.날짜}}&lt;/td&gt;
          &lt;td&gt;{{얻은 데이터}}&lt;/td&gt;
          &lt;td&gt;{{item.데이터}}&lt;/td&gt;
          ....
            &lt;td v-if=&quot;item.ProgramOrderItem__status==&#39;check&#39;&quot;&gt;
              &lt;b-form-input v- &lt;div style=&quot;display: flex; flex-direction: column; justify-content: center; align-items: center;&quot;&gt;
              &lt;div v-for=&quot;(code,index) in codes&quot; :key=&quot;index&quot; style=&quot;display: flex; flex-direction: row; margin: 5px;&quot;&gt; // 인풋만 한번 더 반복
              &lt;b-form-input style=&quot;width: 100%; font-size: 13px; padding-left: 1px;&quot; v-model=&quot;code.ProgramOrderItem__log_code&quot; placeholder=&quot;번호 기입&quot;/&gt;
            &lt;div style=&quot;display: flex; flex-direction: column; justify-content: center; align-items: center;&quot; &gt;
            &lt;b-button class=&quot;sort_button&quot; variant=&quot;info&quot; @click=&quot;removeInput(index)&quot; &gt;제거&lt;/b-button&gt;
            &lt;/div&gt;
            &lt;/div&gt;
            &lt;b-button class=&quot;sort_button&quot; style=&quot;width:60%; margin: 0 10px;&quot; variant=&quot;info&quot; @click=&quot;addInput()&quot; &gt;추가&lt;/b-button&gt;
            &lt;/div&gt;

          &lt;/td&gt;
 &lt;/template&gt; 
&lt;/div&gt;
&lt;/template&gt;

 data: function() {
    return {
      and_param:{},
      list:[],
      codes:[{ProgramOrderItem__log_code:&#39;&#39;}],
    };
  },
  methods: {
    addInput(){
          this.codes.push({ProgramOrderItem__log_code:&#39;&#39;}); 
    },
    removeInput(index){
      console.log(this.codes.length)
      if (this.codes.length==1){
        alert(&#39;더 이상 제거 할 수 없습니다.&#39;)
      }else{
        this.codes.splice(index, 1);
      }
    },</code></pre><h4 id="참고-블로그">참고 블로그</h4>
<p><a href="https://aspdotnet.tistory.com/1978">https://aspdotnet.tistory.com/1978</a> (vue 인풋창추가) 
<a href="https://aspdotnet.tistory.com/1979">https://aspdotnet.tistory.com/1979</a> (예시 및 구조이해)</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[웹푸시란?(2) (with FCM,Vue)]]></title>
            <link>https://velog.io/@idojustdo_it/%EC%9B%B9%ED%91%B8%EC%8B%9C%EB%9E%802-with-FCMVue</link>
            <guid>https://velog.io/@idojustdo_it/%EC%9B%B9%ED%91%B8%EC%8B%9C%EB%9E%802-with-FCMVue</guid>
            <pubDate>Wed, 12 Apr 2023 04:27:26 GMT</pubDate>
            <description><![CDATA[<ol>
<li>FCM 적용기
1.1 적용 구조 
1.2 순서
1.3 트러블 슈팅</li>
<li>순수 웹푸시와 FCM 차이?</li>
</ol>
<p>저번 포스팅에는 웹푸시에 전반적인 개념에 대해 적었다면, 이번에는 Vue에 FCM을 적용하는 과정에대해 포스팅하려 합니다.</p>
<p>저는 프론트엔드를 시작한지 오래되지 않아 백엔드 서버가 없어 일단 임시로 한페이지 내에 웹푸시내에 구조에서 백엔드기능인 푸시메세지 만드는기능을 프론트 페이지에서 해결할 수 있도록 설계하였습니다. </p>
<p>그렇게되면,  원래 웹푸시에 순서맞는 아래와 같은 구조에서<img src="https://velog.velcdn.com/images/idojustdo_it/post/a2d91b81-7576-4d60-88c7-8e7f4b95f2e6/image.png" alt=""></p>
<p>이렇게 브라우저에서 메세지를 보내서 다시 되돌아오는 구조로 되버리는 것입니다. 하지만 postman 말고 Web내에서도 해보고 싶었기에 이대로 진행하였습니다.
<img src="https://velog.velcdn.com/images/idojustdo_it/post/d63bf511-ff9f-4355-9d4d-8f980af2025b/image.png" alt=""></p>
<p>FCM 서비스 내에세도 메세지를 보내 확인할 수 있습니다. 아래와 같은 구조입니다. 
<img src="https://velog.velcdn.com/images/idojustdo_it/post/d09eab96-7581-42db-85b8-e69387a970a4/image.png" alt=""></p>
<ul>
<li>FCM 서비스내에서 메세지를 생성할 수 있는 페이지 
<img src="https://velog.velcdn.com/images/idojustdo_it/post/31b84ecf-56ac-49ba-bb8a-04e2de895d3b/image.png" alt="">
(바로 메세지보내기를 하여도 약 5분? 정도에 차이가 있습니다.)</li>
</ul>
<h4 id="설정하는-큰-순서-다음과-같습니다">설정하는 큰 순서 다음과 같습니다.</h4>
<blockquote>
<ol>
<li>Vue-Cli 프로젝트 설치</li>
<li>Firebase 프로젝트 생성 및 웹앱 생성 및 설정</li>
<li>Firebase 프로젝트 Vue 프로젝트 연동</li>
<li>Firebase 프로젝트 내에 Cloudmessaging 서버키 추가와 웹푸시 인증서 코드를 Vue에 입력</li>
<li>메세지를 보낼 UI를 만들고, FCM과 Vue가 연동되도록 token 정보를 to에 넣어서 푸시 메세지를 생성하여 보낸다.</li>
</ol>
</blockquote>
<h4 id="1-vue-cli-프로젝트-설치">1. Vue-Cli 프로젝트 설치</h4>
<pre><code>npm install -g @vue/cli
# OR
yarn global add @vue/cli

vue create my-project
# OR
vue ui</code></pre><p>저는 회사에서 보통 vue2버전을 쓰기때문에 2버전으로 진행하였습니다.</p>
<h4 id="2-firebase-프로젝트-생성-및-웹앱-생성-및-설정">2. Firebase 프로젝트 생성 및 웹앱 생성 및 설정</h4>
<p><strong>프로젝트 생성</strong>
<img src="https://velog.velcdn.com/images/idojustdo_it/post/b000ba43-d449-4f02-8f4e-a55ab9905692/image.png" alt=""></p>
<p>프로젝트를 추가하여 나오는 순서대로 진행하면 됩니다. 애널리스틱추가는 선택입니다!(저는 간략하게 할 것이기에 추가하진 않았습니다.)</p>
<p><strong>웹앱 생성</strong>
<img src="https://velog.velcdn.com/images/idojustdo_it/post/fd6f8796-20c1-4974-aaa9-fb2f40e1b509/image.png" alt=""></p>
<p>vue와 연동할때 필요한 코드입니다.</p>
<h4 id="3-firebase-프로젝트-vue-프로젝트-연동">3. Firebase 프로젝트 Vue 프로젝트 연동</h4>
<p>2단계에 나온 firebase 모듈을 설치후 </p>
<pre><code>npm install firebase

firebase login  //로그인 아이디 비번

firbase init //저는 호스팅은 하지않아, config로 진행하였습니다. </code></pre><h4 id="4-firebase-프로젝트-내에-cloudmessaging-서버키-추가와-웹푸시-인증서-코드를-vue에-입력">4. Firebase 프로젝트 내에 Cloudmessaging 서버키 추가와 웹푸시 인증서 코드를 Vue에 입력</h4>
<p>브라우저가 꺼져도 메세지를 보낼수 있게 서비스워커파일 설정과 FCM 정보 연동을 진행하면됩니다.
서비스워커는 firebase-messaging-sw.js 파일명으로 진행하여 아래와같은 코드를 작성하였습니다.
서비스 워커는 public 파일안에 생성하였습니다.</p>
<pre><code>// Give the service worker access to Firebase Messaging.
// Note that you can only use Firebase Messaging here. Other Firebase libraries
// are not available in the service worker.
importScripts(&#39;https://www.gstatic.com/firebasejs/8.10.1/firebase-app.js&#39;);
importScripts(&#39;https://www.gstatic.com/firebasejs/8.10.1/firebase-messaging.js&#39;);

// Initialize the Firebase app in the service worker by passing in
// your app&#39;s Firebase config object.
// https://firebase.google.com/docs/web/setup#config-object
firebase.initializeApp({
    apiKey: &quot;&quot;,
    authDomain: &quot;&quot;,
    projectId: &quot;&quot;,
    storageBucket:&quot;&quot;,
    messagingSenderId: &quot;&quot;,
    appId: &quot;&quot;,
    measurementId: &quot;&quot;
});
// 2단계 config와 같게 진행
// Retrieve an instance of Firebase Messaging so that it can handle background
// messages.

const messaging = firebase.messaging();

// 브라우저가 꺼진후에도 진행되어질수 있도록하는 method
messaging.onBackgroundMessage((payload) =&gt; {   
    console.log(
      &#39;[firebase-messaging-sw.js] Received background message &#39;,
      payload
    );
    // Customize notification here  
    const notificationTitle = payload.notification.title;
    const notificationOptions = {
      body: payload.notification.body,
      icon: &#39;/icon.png&#39;
    };

    self.registration.showNotification(notificationTitle, notificationOptions);
  });
</code></pre><p>아래 사진에 나오는 서버키를 추가하고 웹푸시 인증서내에 키를 vapidKey에 입력합니다 
<img src="https://velog.velcdn.com/images/idojustdo_it/post/32e2ca98-ba2f-4710-b541-2b977f873ad0/image.png" alt="">
서버키는 푸시메세지 보낼때 header에 Authorization에 넣고 
vapidKey는 FCM 토큰을 받기위해 사용합니다.
아래코드를 먼저 진행하게되면 console.log 창에서 토큰 번호를 확인할 수 있습니다.</p>
<pre><code>&lt;template&gt;
  &lt;div id=&quot;app&quot;&gt;
    &lt;img alt=&quot;Vue logo&quot; src=&quot;./assets/logo.png&quot;&gt;
    &lt;div class=&quot;layout&quot;&gt;
      &lt;HelloWorld/&gt;
    &lt;/div&gt;

  &lt;/div&gt;
&lt;/template&gt;

&lt;script&gt;
import HelloWorld from &#39;./components/HelloWorld.vue&#39;
import { initializeApp } from &quot;firebase/app&quot;;
import { getMessaging, getToken, onMessage} from &quot;firebase/messaging&quot;;


const firebaseConfig = {
  apiKey: &quot;AIzaSyAZzKgjSkpgBme47W5g_jIecR7M5Msvjfo&quot;,
  authDomain: &quot;pwavue-f336e.firebaseapp.com&quot;,
  projectId: &quot;pwavue-f336e&quot;,
  storageBucket: &quot;pwavue-f336e.appspot.com&quot;,
  messagingSenderId: &quot;724390717780&quot;,
  appId: &quot;1:724390717780:web:b1c5f8305abb18e62c80c1&quot;,
  measurementId: &quot;G-1LZ7XN3LME&quot;
};

// Initialize Firebase
const app = initializeApp(firebaseConfig); //eslint-disable-line no-unused-vars



// Get registration token. Initially this makes a network call, once retrieved
// subsequent calls to getToken will return from cache.
const messaging = getMessaging();

getToken(messaging, { vapidKey: &#39;웹푸시 인증서&#39; }).then((currentToken) =&gt; {
  if (currentToken) {
    // Send the token to your server and update the UI if necessary
    console.log(&#39;Token:&#39;,currentToken);
    // ...
  } else {
    // Show permission request UI
    console.log(&#39;No registration token available. Request permission to generate one.&#39;);
    // ...
  }
}).catch((err) =&gt; {
  console.log(&#39;An error occurred while retrieving token. &#39;, err);
  // ...
});

onMessage(messaging, (payload) =&gt; {
  console.log(&#39;Message received. &#39;, payload);

    //  // Customize notification here
    // const notificationTitle = payload.notification.title;
    // const notificationOptions = {
    //   body: payload.notification.title.body,
    //   icon: &#39;/icon.png&#39;
    // };

    // self.registration.showNotification(notificationTitle, notificationOptions);


  let notificationPermission = Notification.permission;

  if (notificationPermission === &quot;granted&quot;) {
            //Notification을 이미 허용한 사람들에게 보여주는 알람창
           new Notification(payload.notification.title,{
                body:payload.notification.body,
                icon: &#39;/icon.png&#39;,
                image:payload.notification.image
                    });
        } else if (notificationPermission !== &#39;denied&#39;) {
            //Notification을 거부했을 경우 재 허용 창 띄우기
            Notification.requestPermission(function (permission) {
                if (permission === &quot;granted&quot;) {
                  new Notification(payload.notification.title, {
                body:payload.notification.body
                    });
                }else {
                    alert(&quot;알람 허용이 거부되었습니다.&quot;)
                }
            });
        }
});


export default {
  name: &#39;App&#39;,
  components: {
    HelloWorld
  }}

&lt;/script&gt;

&lt;style&gt;
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
.layout{
  display: flex;
  flex-direction:row;
  align-items: center;
  justify-content: center;
}
&lt;/style&gt;
</code></pre><p>토큰 코드를 받고 다음위치에 서버키와함께 작성해주면됩니다.</p>
<pre><code>&lt;template&gt;
  &lt;div class=&quot;hello&quot;  &gt;
    &lt;div class=&quot;textbox&quot;&gt;
      메세지 제목: 
    &lt;input class=&quot;logininput input_w_full&quot; v-model=&quot;message_title&quot;/&gt;
    &lt;/div&gt;
  &lt;div  class=&quot;textbox&quot;&gt;
   메세지 내용: 
    &lt;input class=&quot;logininput input_w_full&quot; v-model=&quot;message_decription&quot;/&gt;
   &lt;/div&gt;
  &lt;div class=&quot;imagebox&quot;&gt;
    &lt;span style=&quot;&quot;&gt;사진 업로드: &lt;/span&gt;
    &lt;div style=&quot;margin-left: 10px;&quot;&gt; 
      &lt;input type=&quot;file&quot;  accept=&quot;image/*&quot; ref=&quot;imageUploader&quot; @change=&quot;handleFileChange&quot; required multiple  &gt;
    &lt;/div&gt;
  &lt;/div&gt;
  &lt;img v-if=&quot;img_src&quot; :src=&quot;img_src&quot; width=&quot;128&quot; height=&quot;128&quot;&gt;
   &lt;div&gt;
    &lt;button type=&quot;button&quot; class=&quot;login_btn&quot;  @click=&quot;send&quot;&gt;보내기&lt;/button&gt;
   &lt;/div&gt;
  &lt;/div&gt;
&lt;/template&gt;

&lt;script&gt;

export default {
  name: &#39;HelloWorld&#39;,
  data(){
    return{
      saveData:{
        notification:{
          title:&#39;&#39;,
          description:&#39;&#39;,
          icon:&#39;&#39;,
          image:&#39;&#39;
        }
      },
    file: &quot;&quot;, 
    img_src: &quot;&quot;,
    img_file:&quot;&quot;,
    message_title:&#39;&#39;,
    message_decription:&#39;&#39;,
    }
  },
  methods:{
    handleFileChange(e) {
    //이미지 URL 생성
      let file = e.target.files[0];
      let name = file.name;
      this.file_name = file.name;
      this.file = file;
      if(name.endsWith(&#39;.jpg&#39;) || name.endsWith(&#39;.jpeg&#39;) || 
        name.endsWith(&#39;.png&#39;) || name.endsWith(&#39;.gif&#39;)){
          this.img_src = URL.createObjectURL(file);
        }
      else{
        this.img_src = &quot;&quot;
      }
    },
    send() {
      this.saveData.to =&quot;토큰코드&quot;
      this.saveData.notification.title = this.message_title;
      this.saveData.notification.body= this.message_decription;
      this.saveData.notification.image= this.img_src


      const headers = { 
    &quot;Authorization&quot;: &quot;key=서버키&quot;,
    &quot;Content-Type&quot;: &quot;application/json&quot;
  };

      this.$axios
        .post(&quot;https://fcm.googleapis.com/fcm/send&quot;,  this.saveData ,{headers})
        .then((res) =&gt; {
          console.log(res);
          //푸시 메세지 보내고 난뒤 전체 리셋
          this.message_title=&#39;&#39;;
          this.message_decription=&#39;&#39;;
          this.img_src=&#39;&#39;;
          this.$refs.imageUploader.value = &#39;&#39;
        })
        .catch((error) =&gt; {
          console.log(error);
        })
    },
  }
}
&lt;/script&gt;

&lt;!-- Add &quot;scoped&quot; attribute to limit CSS to this component only --&gt;
&lt;style scoped&gt;
h3 {
  margin: 40px 0 0;
}
ul {
  list-style-type: none;
  padding: 0;
}
li {
  display: inline-block;
  margin: 0 10px;
}
a {
  color: #42b983;
}
.textbox {
  display: flex;
  flex-direction: row;
  margin-top:10px;
  justify-content: center;
  align-items:center;
}
.logininput {
  margin-left: 10px;
  padding:11px 14px 11px 14px;
  border:1px solid #000;
  line-height: 100%;
}
.input_w_full {
  color:black;
  font-size: 18px;
  width: 300px;
  height: 20px;
  border-radius: 6px;
}
.imagebox {
  margin-top:15px ;
  display: flex;

}
.login_btn{
    margin-top:20px ;
    border-radius:4px;
    width:250px;
    height:61px;
    background-color: #3C3C3C;
    color:white;
    border:0;
    font:700 18px &#39;Inter&#39;;
    cursor: pointer;
  }
&lt;/style&gt;
</code></pre><h4 id="5-메세지를-보낼-ui를-만들고-fcm과-vue가-연동되도록-token-정보를-to에-넣어서-푸시-메세지를-생성하여-보낸다">5. 메세지를 보낼 UI를 만들고, FCM과 Vue가 연동되도록 token 정보를 to에 넣어서 푸시 메세지를 생성하여 보낸다.</h4>
<p><img src="https://velog.velcdn.com/images/idojustdo_it/post/e6c8805b-aa38-437b-965e-03dc5257bb4b/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/idojustdo_it/post/49a2611e-3f93-4914-b7b6-e943f8626e44/image.png" alt="">
다음과 같이 나오게됩니다.</p>
<h3 id="트러블-슈팅">트러블 슈팅</h3>
<p>가장 크게 오랫동안 맞닥드린 에러는 foreground(브라우저가 켜져있는상태)에서 메세지가 전달되지 않는다는 것이었습니다. 
background상태에서 썻던 메소드와 같은 메소드를 썼는데 다음과 
같은 에러가 떴습니다
Umcaught FirebaseError: messaging: this method is available in a window context/.</p>
<p><img src="https://velog.velcdn.com/images/idojustdo_it/post/ce3898ee-a95b-47fb-9254-f4c323f140d3/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/idojustdo_it/post/d1f339b0-ddb2-44d8-a6a3-e8a2c3ec1edc/image.png" alt=""></p>
<p>공신문서를 살펴보니 
<img src="https://velog.velcdn.com/images/idojustdo_it/post/b6e45ac3-c0e9-48a7-ba2f-7b909a03ee5f/image.png" alt="">
현재 FCMAPI가  web에서는 지원하지 않는다는 글을 보았다..!</p>
<p>그래서 JS에서 notification api를 살펴보며 다른방식으로 메소드를 사용하였습니다</p>
<pre><code>onMessage(messaging, (payload) =&gt; {
  console.log(&#39;Message received. &#39;, payload);

    //  // Customize notification here
    // const notificationTitle = payload.notification.title;
    // const notificationOptions = {
    //   body: payload.notification.title.body,
    //   icon: &#39;/icon.png&#39;
    // };

    // self.registration.showNotification(notificationTitle, notificationOptions);


  let notificationPermission = Notification.permission;

  if (notificationPermission === &quot;granted&quot;) {
            //Notification을 이미 허용한 사람들에게 보여주는 알람창
           new Notification(payload.notification.title,{
                body:payload.notification.body,
                icon: &#39;/icon.png&#39;,
                image:payload.notification.image
                    });
        } else if (notificationPermission !== &#39;denied&#39;) {
            //Notification을 거부했을 경우 재 허용 창 띄우기
            Notification.requestPermission(function (permission) {
                if (permission === &quot;granted&quot;) {
                  new Notification(payload.notification.title, {
                body:payload.notification.body
                    });
                }else {
                    alert(&quot;알람 허용이 거부되었습니다.&quot;)
                }
            });
        }</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[Web push란? (1)]]></title>
            <link>https://velog.io/@idojustdo_it/Web-push%EB%9E%80</link>
            <guid>https://velog.io/@idojustdo_it/Web-push%EB%9E%80</guid>
            <pubDate>Tue, 11 Apr 2023 08:51:16 GMT</pubDate>
            <description><![CDATA[<h2 id="webpush는">Webpush는</h2>
<p>브라우저에 푸시 메세지를 보내는 것을 말합니다.
푸시 메세지는 무엇일까요?
앱또는 브라우저와 연결,구독되어진 사용자에게 서비스와 관련된 정보를 전달해주는 것입니다.</p>
<p>앱과 같은 경우는 아래와 같은 형식으로 사용자들에게 보여집니다.
<img src="https://velog.velcdn.com/images/idojustdo_it/post/8ddc4fab-e815-4e54-8a80-b8123248797f/image.png" alt=""></p>
<p>브라우저와 같은 경우는 이런 식으로 사용자들에게 전달 되어집니다.
<img src="https://velog.velcdn.com/images/idojustdo_it/post/9d2e9ddd-a465-44d4-92cf-ebc5d9dc0474/image.png" alt=""></p>
<p>Webpush는 해당 서비스의 브라우저가 꺼져있어도 서비스 워커라는 자바스크립트 파일에 의해 푸시메세지를 보낼 수 있습니다. (단, 제가 FCM을 사용해본결과 브라우저가 꺼져있었다면, 메세지가 없다가 브라우저가 켜짐과 얼마지나지 않아 메세지가 전달되어집니다.)</p>
<p>장점은 LMS(문자)와 같은 기능을 할 뿐더러 가격적으로도 값싸다는 것(메세지 보내는 기능은 무료입니다.) 다른 채널과 이하수준의 기능을 하지 않는다는 점 여러 장점들이 많습니다.</p>
<h2 id="구조와-작동순서는-어떻게-될까요">구조와 작동순서는 어떻게 될까요?</h2>
<p>큰 구조로 본다면, 브라우저(클라이언트), 서비스 워커, 웹 서버 이렇게 3가지로 구성되어 있습니다.</p>
<blockquote>
<ol>
<li>브라우저는 웹푸시 알림을 구독하거나 취소하거나, 구독을 하게되면 웹푸시 메세지를 표시하고 클릭이벤트를 처리합니다. </li>
<li>서비스 워커는 서버와 브라우저(사용자) 사이에서 푸시메세지를 교환 처리하고 푸시메세지를 받았을 때 알림을 생성합니다 또한, 
웹브라우저의 백그라운드에서 실행되기 때문에 브라우저의 쓰레드와 별도로 실행되어
브라우저가 꺼져있어도 웹푸시 알림을 보낼 수 있게해줍니다.</li>
<li>웹 서버는 사용자의 구독정보와 푸시메세지를 처리하고 브라우저로 보낼 메세지를 생성하고 암호화를 통해 서비스 워커에 보내게 됩니다.</li>
</ol>
</blockquote>
<p>작동 순서는 다음과 같습니다.</p>
<blockquote>
<ol>
<li>브라우저에서 웹푸시 알림 허용 
=&gt; 서비스 워커에서 해당 유저의 구독정보 전달 
=&gt; 브라우저에서 웹서버로 자신의 구독정보 전달</li>
</ol>
<ol start="2">
<li>웹서버에서 푸시메세지를 생성하여 구독정보와 비공개키를 서비스워커에 전달</li>
<li>서비스워커에서 먼저 공개키로 유효성 검증과 검증된 경우 구독정보에 해당하는 브라우저로 푸시메세지를 전송하게 됩니다.  </li>
</ol>
</blockquote>
<p>작동 순서에서 나오는 공개키와 비공개키는 VAPID (Voluntary Application Server Identification)인 인증 프로토콜입니다. 이를 통해서 브라우저와 서버간 오고가는 푸시메시지 교환 과정에서 보안성을 더욱 강화할 수 있습니다.</p>
<p>VAPID는 공개키와 비공개키 한쌍을 사용하여 생성 됩니다.
그리고 위 작동 순서에 3번에서 볼 수 있듯이 서버에서 비공개키를 보내면 서비스워커에서 확인할수 있게됩니다.</p>
<p>웹 푸시는 이러한 구조를 통해 사용자가 구독한 정보와 푸시 메시지를 안전하고 빠르게 전달할 수 있습니다. 사용자가 구독한 정보는 브라우저에서 관리되며, 푸시 메시지는 서비스 워커를 통해 백그라운드에서 처리됩니다. 이를 통해 사용자는 브라우저를 실행하지 않아도 알림(Notification)을 받을 수 있으며, 서버에서 전송한 푸시 메시지는 브라우저가 종료되어도 표시됩니다
<img src="https://velog.velcdn.com/images/idojustdo_it/post/6c5e5398-a3c0-4a90-a7a3-cd56703e6dc5/image.png" alt=""></p>
<p>다음 글로는 Vue.js로 FCM과 연동하여 진행한 토이프로젝트와 관련된 글을 작성하도록 하겠습니다.</p>
<p>참조 블로그
<a href="https://uracle.blog/2021/09/24/webpush-2/">https://uracle.blog/2021/09/24/webpush-2/</a>
<a href="https://web.dev/push-notifications-web-push-protocol/">https://web.dev/push-notifications-web-push-protocol/</a>
<a href="https://geundung.dev/114">https://geundung.dev/114</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[매번의 미션을 기록하자, 일과사전..? ]]></title>
            <link>https://velog.io/@idojustdo_it/%EB%A7%A4%EB%B2%88%EC%9D%98-%EB%AF%B8%EC%85%98%EC%9D%84-%EA%B8%B0%EB%A1%9D%ED%95%98%EC%9E%90-%EC%9D%BC%EA%B3%BC%EC%82%AC%EC%A0%84</link>
            <guid>https://velog.io/@idojustdo_it/%EB%A7%A4%EB%B2%88%EC%9D%98-%EB%AF%B8%EC%85%98%EC%9D%84-%EA%B8%B0%EB%A1%9D%ED%95%98%EC%9E%90-%EC%9D%BC%EA%B3%BC%EC%82%AC%EC%A0%84</guid>
            <pubDate>Wed, 22 Mar 2023 02:59:15 GMT</pubDate>
            <description><![CDATA[<p>카페사장이었던 내가 개발자로 커리어 전환 후, 업무를 시작한지도 약 반년 정도가 지나가고 있다.</p>
<h2 id="계기">계기</h2>
<p> 첫 개발자로서의 역할을 회사내에서 충실히 해내고, 이제는 제법 1인분의 개발자 역할을 해나가고있다. 뿌듯함도 잠시, 회사의 사정으로 인해 다른 부서의 업무를 보게되었고, 그 업무를 충실히 다 해내고 다시 개발부서로 돌아왔을때, 내가 짠코드를 보며 이해하는데 약 20분정도 걸렸다..?!</p>
<p><img src="https://velog.velcdn.com/images/idojustdo_it/post/a7fe61af-e59e-4fcb-9930-41597fcd0e35/image.gif" alt="">
어떻게 이런 코드를 짰지..? 분명 내가 짠코드인데 어떻게 짰는지 일말의 기억조차 나지 않았다. 나는 갑자기 식은 땀이 났다. 물론 다기억나진 않는게 당연하지만, 신기할정도로 아무것도 기억이 나지 않았다. 물론 기본이 부족한게 가장 크다고 생각하고, 그 다음으로는 새로내가 습득하는 것들을 주어진 미션을 해결하는 것에 급급하다보니 미션이 완료되면 관련된 모든 자료들이 머릿속에서 휘발된다. (마치, 우리가 고등학교때 중간, 기말시험보면 와아아아시험끝이다 라는 말과함께 다 잊어먹는 것처럼말이다..)</p>
<h2 id="목표">목표</h2>
<p> 그래서 휘발되도 좋으니 나만의 기록물을 만들기로 하여 이름하야 일과사전이라는 기록사전을 도전해보려한다.</p>
<p>미션이 끝날때나 미션이 굉장히 길다면, 진행되는 도중에도 괜찮다. 상세하게 기록하는 것을 목적을 두고 진행할 것이다.</p>
<p><img src="https://velog.velcdn.com/images/idojustdo_it/post/b2e40e0c-69f8-47d4-bff8-c7a563e9a746/image.jpg" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[브라우저 기본지식 (2)]]></title>
            <link>https://velog.io/@idojustdo_it/%EB%B8%8C%EB%9D%BC%EC%9A%B0%EC%A0%80-%EA%B8%B0%EB%B3%B8%EC%A7%80%EC%8B%9D-2</link>
            <guid>https://velog.io/@idojustdo_it/%EB%B8%8C%EB%9D%BC%EC%9A%B0%EC%A0%80-%EA%B8%B0%EB%B3%B8%EC%A7%80%EC%8B%9D-2</guid>
            <pubDate>Wed, 18 Jan 2023 09:44:08 GMT</pubDate>
            <description><![CDATA[<h1 id="브라우저의-작동원리">브라우저의 작동원리</h1>
<ol>
<li><p>사용자가 주소표시줄에 URI를 검색하여 브라우저 엔진에 전달이 됩니다.</p>
</li>
<li><p>브라우저 엔진은 먼저 자료저장소로 달려가 URI에 해당하는 자료를 찾습니다.
(항상 웹서버에서 자료를 받아오게 되면 똑같은 자료를 계속 받아와야하는 불필요한 서버 통신이 이뤄지게 됩니다. 이러한 낭비를 방지하기위해 자료저장소에 자주 받아오는 데이터를 저장해두고 사용하기도합니다. (캐싱) 처음 받는 URI라면, 렌더링 엔진으로 넘겨줍니다.</p>
</li>
<li><p>렌더링엔진은 네트워크쪽엔 HTTP 통신요청을 이후 받은 데이터를 갖고 파싱과 Js해석기에 JS데이터를 주고 파싱을받고난뒤 랜더트리를 형성하게됩니다.</p>
</li>
<li><p>랜더트리가 형성되면 UI백엔드에서 브라우저에 그려주면서 유저에게 URI 데이터가 보이게 됩니다.</p>
</li>
</ol>
<p>전반적인 큰 작동은 이런식으로 이뤄집니다.</p>
<p>그 중 좀 더 중점적으로 봐야할 부분은 랜더링 엔진 부분이다.</p>
<h2 id="렌더링엔진">렌더링엔진</h2>
<p>현재 주요 브라우저에서 사용되는 랜더링 엔진은 크게 애플의 webkit 구글의 크로미움 , 파이어폭스의 게코가 있다. webkit은 보안강화, 크로미움은 최적화와 다중처리 속도, 게코는 웹ui뿐아니라 앱인터페이스까지 어느 정도 지원하는 기능적 특징을 갖고있습니다.</p>
<p>랜더링 엔진은 브라우저 구조에 있어서 중추역할을 한다고 생각한다. </p>
<p><img src="blob:https://velog.io/139152bc-d314-404f-957a-7038104d01f0" alt="업로드중.."></p>
<ol>
<li>돔트리 구축하기위한 HTML 파싱단계에선 HTML CSS, JS를 파싱하게되는데, content HTML문서를 파싱한후, content tree내부에서 태그(a, div)를 돔 노드로 변환하게되는데 여기서 돔노드는 document object model에 하나의 요소로 변환된다는 것입니다. 그다음은 css파일과함께 스타일 요소들을  파싱을해서 스타일 규칙을 만듭니다, 이러한 스타일 태그가 적용된 돔트리가 렌더트리가 구성됩니다.</li>
</ol>
<ol start="2">
<li><p>다음단계인 렌더트리 구축에서는 html과 css를 파싱해서 만들어진 렌더트리는 색상 또는 면적 등 시각적 속성을 갖는 부분들을 정해진 순서대로 렌더링을 하여 랜더트리를 구축하게되고, </p>
</li>
<li><p>이후 배치 단계로 넘어가면서 브라우저 창에서 렌더트리가  어떻게 배치될지는 렌더트리의 구성요소인 노드에 위치정보가 담겨져있어서  그위치 정보에 맞게 배치가 됩니다. </p>
</li>
<li><p>배치가 완료되면 백엔드 ui에서 각 노드들을 가로지르며 페인트 작업을 하게됩니다.</p>
</li>
</ol>
<p><img src="https://velog.velcdn.com/images/idojustdo_it/post/27c3420a-4de6-40ee-bb72-68563c6fec87/image.png" alt=""></p>
<p>1단계와  2,3,4단계는 다르게 보면 병렬적으로 진행이됩니다<br>돔트리는 돔노드라는 자식요소로 구성되어있고, 마찬가지로 렌더트리도 렌더 오브젝트라는 자식요소로 구성되어 있습니다. 근데 돔트리가 다구축되고 그이후 랜더트리로 전환되는 것이 아니고 돔트리의 구성요소인 하나의 노드들, 각각의 노드들이 새로 생성 되자마자 랜더트리의 구성요소인 렌더 오브젝트로 전환됩니다.  바로바로 변환 되는 이 과정을 통해서  렌더트리가 바로바로 생성이 되는 것입니다. </p>
<p>그러면 사용자들은? 돔트리가 완전히 완성될때까지 흰화면 만보는게 아니라, 돔트리가 완성되는 중간중간에 렌더트리가 구축되어 지기 때문에 바로바로 렌더트리가 배치되고 그려지게 되는 것입니다. 따라서 사용자는 돔트리가 완전하게 구축되어질때까지 기다릴 필요없이 렌더트리가 조금씩 구축됨과 동시에 그려져서 브라우저에 조금씩 조금씩 컨텐츠들을 확인할 수 있게되는 것입니다.</p>
<p>참조 자료
(가장 쉬운 웹개발 with Boaz)
<a href="https://www.youtube.com/watch?v=oLC_QYPmtS0&amp;list=PLpq56DBY9U2AZEPhHAbG7ZbfrXvqW1bX4&amp;index=22">https://www.youtube.com/watch?v=oLC_QYPmtS0&amp;list=PLpq56DBY9U2AZEPhHAbG7ZbfrXvqW1bX4&amp;index=22</a> </p>
<p><a href="https://www.youtube.com/watch?v=EBe-OHkf9w8&amp;list=PLpq56DBY9U2AZEPhHAbG7ZbfrXvqW1bX4&amp;index=21">https://www.youtube.com/watch?v=EBe-OHkf9w8&amp;list=PLpq56DBY9U2AZEPhHAbG7ZbfrXvqW1bX4&amp;index=21</a></p>
<p>(네이버O2)</p>
<p><a href="https://d2.naver.com/helloworld/59361">https://d2.naver.com/helloworld/59361</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[브라우저의 기본 지식 (1)]]></title>
            <link>https://velog.io/@idojustdo_it/%EB%B8%8C%EB%9D%BC%EC%9A%B0%EC%A0%80%EC%9D%98-%EA%B8%B0%EB%B3%B8-%EC%A7%80%EC%8B%9D-1</link>
            <guid>https://velog.io/@idojustdo_it/%EB%B8%8C%EB%9D%BC%EC%9A%B0%EC%A0%80%EC%9D%98-%EA%B8%B0%EB%B3%B8-%EC%A7%80%EC%8B%9D-1</guid>
            <pubDate>Wed, 18 Jan 2023 08:05:36 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/idojustdo_it/post/0d29e573-dd3f-4e37-95b5-2f9dbd689d0e/image.jpg" alt=""></p>
<h2 id="브라우저하면-가장-먼저-생각나는-건-무엇인가요">브라우저하면 가장 먼저 생각나는 건 무엇인가요?</h2>
<p>저의 경우 _<strong>크롬</strong>_을 가장 먼저 생각이 납니다.
<strong>익스플로러 7?8?</strong>을 쓰다가 처음 _<strong>크롬</strong>_으로 넘어갔을때 속도의 차이가 충격이었거든요.</p>
<p>엄청 UI도 단순했고, 깔끔하다라는 느낌을 처음 받았었습니다. 하지만 브라우저의 뜻이뭔지 구조가 어떻게되고 동작은 어떻게 이뤄지는 지에대한 생각조차 없었죠. 크롬을 알게되고 약14년?15년이 지나 개발자가 되고난 뒤에 궁금증이 생겨 이것저것 뒤져보려합니다.</p>
<h3 id="자-그렇다면-브라우저는-무엇일까요-">자, 그렇다면 브라우저는 무엇일까요 ?</h3>
<p>통상 브라우저라고하면 웹브라우저(web browser)를 지칭하고 글자그대로 직역하자면, 웹 탐색기, 웹열람기라고 해석할 수 있습니다. 기능적 정의는 월드 와이드 웹기반(WWW) 문서, 이미지나 동영상같은 멀티미디어 자료들을 검색하고 접근할 수 있게 해주는 응용프로그램입니다.
(도서관 같은곳)</p>
<p><img src="https://velog.velcdn.com/images/idojustdo_it/post/8b9bd30e-1e12-4780-be56-9e7fcb4c5e97/image.png" alt=""></p>
<h3 id="브라우저는-어떤-요소들이-구성하고-있을까요">브라우저는 어떤 요소들이 구성하고 있을까요??</h3>
<p>브라우저는 위에 보이는 그림과 같이 약 7가지의 구성요소로 이뤄져있습니다. </p>
<p>*<em>1. 사용자 인터페이스 *</em>
 브라우저 앱을 시작하면 가장먼저 보이는 것들, 주소 표시창, 새로고침, 뒤로가기 앞으로가기 버튼과 같은 사용자가 통제할 수 있는 것들이 대부분이다.</p>
<p><strong>2. 브라우저 엔진</strong>
 사용자 인터페이스에서 요청되어진 명령을 렌더링 엔진에 전달하는 역할과 데이터 저장소에서 먼저 저장되어진 데이터(캐시메모리)들이 있는 지 확인하여 데이터 낭비를 막는 역할을 한다.</p>
<p><strong>3. 데이터 저장소</strong>
 데이터 저장소는 쿠키등의 자료를 webDatabase에 저장하는 곳입니다. </p>
<p><strong>4. 렌더링엔진</strong>
사용자가 URI를 입력했을때 해당하는 데이터를 네트워크와 자바스크립트 해석기 UI백엔드에게 전달해주고, 각 파서들을 통해서, HTML,CSS를 파싱하고 이러한 총체적인 역할을 하는 것이 렌더링엔진입니다.</p>
<p><strong>5. 네트워킹</strong>
렌더링 엔진으로부터 HTTP 요청을 받으면, 요청에 맞게 실행후 받은 데이터를 다시 렌더링 엔진에게 전달해줍니다.</p>
<p><strong>6. 자바스크립트 해석기</strong>
 자바스크립트를 파싱하는 역할을 합니다.</p>
<p><strong>7. 백엔드 UI</strong>
 최종적으로 렌더링엔진에서 생성된 랜더트리를 브라우저에 그리는 역할을 합니다.</p>
<p> 다음에는 렌더링엔진의 역할에 대해 좀 더 중점적으로 이야기해보려합니다.</p>
<p>참고한 글 및 자료
(*위키 백과)
<a href="https://ko.wikipedia.org/wiki/%EC%9B%B9_%EB%B8%8C%EB%9D%BC%EC%9A%B0%EC%A0%80">https://ko.wikipedia.org/wiki/%EC%9B%B9_%EB%B8%8C%EB%9D%BC%EC%9A%B0%EC%A0%80</a></p>
<p><a href="https://parkjh7764.tistory.com/45">https://parkjh7764.tistory.com/45</a></p>
<p><a href="https://oneroomtable.tistory.com/entry/%EB%B8%8C%EB%9D%BC%EC%9A%B0%EC%A0%80%EC%9D%98-%EA%B0%9C%EB%85%90%EA%B3%BC-%EC%97%AD%ED%95%A0">https://oneroomtable.tistory.com/entry/%EB%B8%8C%EB%9D%BC%EC%9A%B0%EC%A0%80%EC%9D%98-%EA%B0%9C%EB%85%90%EA%B3%BC-%EC%97%AD%ED%95%A0</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[루틴만들기 2 (구체화작업_1)]]></title>
            <link>https://velog.io/@idojustdo_it/%EB%A3%A8%ED%8B%B4%EB%A7%8C%EB%93%A4%EA%B8%B0-2-%EA%B5%AC%EC%B2%B4%ED%99%94%EC%9E%91%EC%97%851</link>
            <guid>https://velog.io/@idojustdo_it/%EB%A3%A8%ED%8B%B4%EB%A7%8C%EB%93%A4%EA%B8%B0-2-%EA%B5%AC%EC%B2%B4%ED%99%94%EC%9E%91%EC%97%851</guid>
            <pubDate>Wed, 17 Aug 2022 16:18:26 GMT</pubDate>
            <description><![CDATA[<h1 id="루틴을-만들어보자">루틴을 만들어보자.</h1>
<h2 id="1-지식을-쌓기위해-면접스터디">1. 지식을 쌓기위해 면접스터디</h2>
<p>매일 아침 11시와 상황에따라서 밤에 한번 더 복습하는 시간을 갖는데,
(아직까지는 매일 3개씩 암기하고 이해하고, 매일 복습해왔다.)
<img src="https://velog.velcdn.com/images/idojustdo_it/post/a45f31ac-8468-46d1-a37d-3bf3e89ecc47/image.png" alt="">
(초췌한얼굴은... 지켜..)
<img src="https://velog.velcdn.com/images/idojustdo_it/post/023d4584-5be9-4229-a597-a6abcb4267d7/image.png" alt=""> (저녁복습시간)</p>
<h2 id="2부족한-부분-체크하여-채워넣기">2.부족한 부분 체크하여 채워넣기</h2>
<p>많은 시니어 또는 이미 현업에 계신 분들이 말씀하시길 지금 나의수준에선 코드를 무작정 써보는게 중요하다. 그리고 단순히 강의만듣거나, 클론코딩만! 하는 것은 실력이 성장하는데있어서 굉장히 더디다. 라는 말씀들을 많이 해주셨어서 코딩강의를 듣고 깃허브에 정리도하고, 따로 강의에서 배운 개념들을 써먹을 수 있는 기능을 붙이려고 노력하고있다. 
<img src="https://velog.velcdn.com/images/idojustdo_it/post/286cff45-e2bf-4900-bffb-55ae06cf8ed8/image.png" alt=""></p>
<p>타입스크립트를 이용한 CR D..u는 내일 업데이트를 하고 추가적으로 state관리를 하는 기능을 붙일 예정이다.</p>
<h2 id="3-내가해보고싶은-기능-프로젝트-만들기">3. 내가해보고싶은 기능 프로젝트 만들기</h2>
<p>사이드 프로젝트를 마음맞는사람을 찾아서 진행해볼 예정이다. 일단 구체적으로 정해진건 멤버정도여서 이후에 기술스텍이나 뭔가 갖춰지면 올릴예정..!정말 일벌리는거 좋아한다..</p>
<p><img src="https://velog.velcdn.com/images/idojustdo_it/post/6aa2f004-d853-4dc5-89d4-01a88e06afb3/image.jpg" alt=""></p>
<p>난 후회하지않겠다... 라는 다짐을하기위해 TIL을 적을 예정이다! </p>
<p>개발자분들 화이팅!!! </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[개발 루틴만들기!]]></title>
            <link>https://velog.io/@idojustdo_it/%EA%B0%9C%EB%B0%9C-%EB%A3%A8%ED%8B%B4%EB%A7%8C%EB%93%A4%EA%B8%B0</link>
            <guid>https://velog.io/@idojustdo_it/%EA%B0%9C%EB%B0%9C-%EB%A3%A8%ED%8B%B4%EB%A7%8C%EB%93%A4%EA%B8%B0</guid>
            <pubDate>Tue, 16 Aug 2022 16:24:03 GMT</pubDate>
            <description><![CDATA[<p>항해 99의 커리큘럼이 끝나고 그 누가 제어 해준다거나 그런 시스템은 이제없다. 내가 나를 이끌고 내가뭘 궁금해하는지 뭘 더 알아야하는지 메타인지를 높이고 나의 개발루틴을 만드는게 중요하다는 생각을 하게되었다.
<img src="https://velog.velcdn.com/images/idojustdo_it/post/a878f8b5-df76-49b3-8dfd-6c02266b08eb/image.jfif" alt=""></p>
<p>비전공생인 나에게 가장 절실하게 부족한건 CS지식이기에 실전프로젝트 주차쯔음에 시작했던 면접스터디를 시작으로 써보고싶었던 기술이나 부족한 기술들을 체크하는 강의나 프로젝트를 진행하고싶어 루틴을 짜고 매일매일 기록하려고한다! </p>
<p>BIG 루틴</p>
<ul>
<li><p>CS 지식을 위한 면접스터디 (단순 암기와 다르게 말하기위해 공부하다보니 이해하려고 노력한다)</p>
</li>
<li><p>개인 토이 프로젝트 또는 팀 구성의 사이드프로젝트 (Typescript와 전역관리에 recoil)</p>
</li>
<li><p>부족한 부분이라 생각되는 점 체크 (JS 와 리액트 쪽 문법 및 리액트 훅 체크 ) </p>
</li>
<li><p>운동 (크로스핏// 피티)</p>
</li>
</ul>
<p>루틴세분화를 진행해보자구.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[항해99후기 이스트블루의끝.]]></title>
            <link>https://velog.io/@idojustdo_it/%ED%95%AD%ED%95%B499%ED%9B%84%EA%B8%B0-%EC%9D%B4%EC%8A%A4%ED%8A%B8%EB%B8%94%EB%A3%A8%EC%9D%98%EB%81%9D-ofjw3eal</link>
            <guid>https://velog.io/@idojustdo_it/%ED%95%AD%ED%95%B499%ED%9B%84%EA%B8%B0-%EC%9D%B4%EC%8A%A4%ED%8A%B8%EB%B8%94%EB%A3%A8%EC%9D%98%EB%81%9D-ofjw3eal</guid>
            <pubDate>Mon, 15 Aug 2022 11:15:01 GMT</pubDate>
            <description><![CDATA[<p>99일간에 새로운 도전의 첫단추는 마무리가 되었다.
항해를 끝내고 난뒤에 느낌을 회고록으로 쓸지... 후기로하여금 부트캠프를 고민하고 있는 분들에게 도움이 될 분석글로 쓸지 고민하다가 내아이디idojustdo (이도저도)에 맞춰  짬뽕시키기로 했다. </p>
<p><img src="https://velog.velcdn.com/images/idojustdo_it/post/a6776740-8ec4-4de0-b192-49f4cacb2a47/image.jpg" alt="">
이제 이스트블루 끝이니... 더많은 대륙과 항해가 기다리고있다굿.</p>
<h2 id="항해99를-선택한-이유">항해99를 선택한 이유.</h2>
<pre><code> 1. 개발을 잘모르는 나에게도 납득이 될만한 합리적인 가격.
 2. 99일동안 성장할 또다른 나의모습 (능동성)
 3. 개발자를 꿈꾸는 사람에게 이상적인 마케팅 문구.
 4. 부트캠프를 수료하면 바로 취준에 성공할 것 같은 마켓팅.</code></pre><h2 id="그래서-나는-수료후-성장했는가">그래서 나는 수료후 성장했는가?</h2>
<p>일단, 성장했다. 성장하지 않을 수 없는 환경이 조성되어있었다.</p>
<h2 id="어떤점에서-성장했는가">어떤점에서 성장했는가?</h2>
<p>뭐 단순하게보면 CS지식, 토이프로젝트를 할수있는수준, 이런걸 이야기하겠지만, 가장 크게 성장한 건 삶은 대하는 태도다. 항해는 내게 개발은 성장하지 않으면 도태되는 분야라는것을 여실하게 알려줬다.<img src="https://velog.velcdn.com/images/idojustdo_it/post/c93c409e-4f8e-4f0e-8362-fac972b1d726/image.jpeg" alt=""></p>
<p>나는 적어도 도태되지 않기 위해서라도 99일동안 노력했다. 그냥 정신없이 주는데로 받아먹었고, 소화도 완전히 되지 않은 채로 새로운 것들을 계속해서 받아 먹고 있었다. 하지만 그게 결국 피가되고 살이되고 가죽이 되어가고 뼈대를 구축하고 있었다.</p>
<p>자, 이제 어떤점이 좋고 어떤점이 아쉬웠는가 이야기해보쟈</p>
<h2 id="일단-병🧴주고-아쉬웠던-점">일단 병🧴주고, 아쉬웠던 점.</h2>
<h3 id="--리액트-버전변화로-인한-약간-늦은-대응">- 리액트 버전변화로 인한 약간 늦은 대응.</h3>
<p>  [일단 제일먼저 리액트의 강의 가장 늦게 나왔고, 아무래도 함수형과 클래스형의 코드짜는 방식이 처음 내게 많은 차이를 보여 처음엔 예전 코드만 보면 바로 넘겼다. 그러다 보니 내가 볼 수 있는 자료는 적었다. 앞선 선배 기수들의 코드를 보고 익히려고했지만 대부분이 클래스형 컴포넌트 구성과 컴포넌트를 나눈 방식도 많이 달라서 참고조차 하지 못한 적이 많다.  ]</p>
<h3 id="-프론트-기준-부족한-커리큘럼">-프론트 기준 부족한 커리큘럼</h3>
<p>[(CSS 와 JS) 관련 커리큘럼css를 익히는 주간이있었다면)이나 전역관리로 리덕스 외에 다른 선택지도 있다는 것을 알려줬다면 좀더 좋았을 것이라 생각된다.]</p>
<h3 id="--방목과-능동성의-경계">- 방목과 능동성의 경계.</h3>
<p> [가끔 너무 우리에게 맡기는게 아닌가 라는 생각을 할때도 있었다, 정말 하나부터 열 아니 적어도 75까지 직접적으로 달려들지 않으면, 성장은 어렵다. 기술 멘토링이나 피드백시간후에 멘토님붙잡고, 모르는 걸 계속적으로 물어보지않으면, 그건 항해내내 모르게될 가능성이 생긴다. (실전프로젝트때는 어떻게되는 알게되긴하지만)]</p>
<h2 id="약🚑주자-좋았던-점">약🚑주자! 좋았던 점</h2>
<h3 id="--담임시스템">- 담임시스템</h3>
<p>[기술적인 질문을 구체적으로 할순 없지만, 우리가 잘하고 있는지, 어떤 고민이나 힘든점이 있는지 공감해주시고 들어주신다. 그런문제를 들어주는 것만으로도 마음의 위안이 된다.] </p>
<h3 id="-현업-개발자분들과의-주차별-멘토링-및-중간발표">-현업 개발자분들과의 주차별 멘토링 및 중간발표</h3>
<p>[내 프로젝트를 피피티를 만들어 발표하는것, 개발자가 갖춰야할 능력중 하나라고 생각한다.(내가 맡지 않는 부분도 왜이런지 다듣고 이해하려고 노력하고 시도조차할수 있게 될뿐아니라 보는 시야도 넓어진다), 현업자분들의 신랄하고 아주 매서운 비판 후에 성장이 또다르다 개인적으로 보는 것과는 정말 디테일하게보고 많은 관점을 갖고계신다는 것을 새삼 느끼게되고 약간 머리가 띵해지는 시간이기도 했다. ]</p>
<h3 id="-한두번이-아닌-4번에-걸쳐-이뤄지는-팀프로젝트">-한두번이 아닌 4번에 걸쳐 이뤄지는 팀프로젝트</h3>
<p>[매일 한주차마다 프로젝트를 진행하고 제출하고 발표하는 형식을 4번정도하고 그외에는 개인적으로 프로젝트를 진행하는 방식인데, 4번의 팀프로젝트는 협업능력, 소통능력이 가장 크게 두드러지는 부분이다. 내가 어떤부분이 부족한지 돌아볼수 있는 상황도 되지만 한편으로는 맞지않아서 이기간에 탈주하는 비율이 가장 높은 것 같다.(이때 개발자로서 내가 맞는지 안맞는지 확인할 수 있다. 나와맞지않는 팀원을 만났을때 어떻게 팀에서 역할을 잘 해낼것인지)]</p>
<p><img src="https://velog.velcdn.com/images/idojustdo_it/post/6b34887d-aaa9-4d04-940a-10f078457bce/image.jfif" alt=""></p>
<p>큰틀로보면 이렇게 정리할 수 있다. 디테일 적으로 들어가면 굉장히 할 이야기가 많지만 , 궁금하면 댓글남겨주세요 친절이 알려드릴꼐요! </p>
<p>전공생이거나 평소에 조금 독학을 했다면 굉장히 잘맞는 커리큘럼이라 생각한다. 아예 항해를 통해 처음 코딩을 접하고 시작하는 사람에게는 쉽지 않은 나날들의 연속이라 단언할 수 있다. 마치... 패기없는 루피...랄까?
<img src="https://velog.velcdn.com/images/idojustdo_it/post/073f47a3-9ad1-4f20-9f01-be609717cee2/image.jpg" alt=""></p>
<h2 id="내가-느낀-가장중요한것">내가 느낀 가장중요한것</h2>
<p> 부트캠프가끝나고 바로 취준하는 것도 좋다, 하지만 나의경우는 부족한것들을 다시돌아보는 기간을 1달정도 (프로젝트를진행하며)잡고 조금의 여유를 갖고 코딩을 대했으면 좋겠다. 우리는 이제시작이고 앞으로 쭈우우우욱 할꺼니까 나를 돌아보는 시간 중요는 것을 개발이라는 분야를 통해 더더욱 알게 되었고, 어떻게 나만의 방식으로 기록할 것인가 라는 걸 많이 고민하게 되었다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[프로젝트의 마무리에서... 새로운 시작.]]></title>
            <link>https://velog.io/@idojustdo_it/%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8%EC%9D%98-%EB%A7%88%EB%AC%B4%EB%A6%AC%EC%97%90%EC%84%9C...-%EC%83%88%EB%A1%9C%EC%9A%B4-%EC%8B%9C%EC%9E%91</link>
            <guid>https://velog.io/@idojustdo_it/%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8%EC%9D%98-%EB%A7%88%EB%AC%B4%EB%A6%AC%EC%97%90%EC%84%9C...-%EC%83%88%EB%A1%9C%EC%9A%B4-%EC%8B%9C%EC%9E%91</guid>
            <pubDate>Sun, 07 Aug 2022 07:28:29 GMT</pubDate>
            <description><![CDATA[<p>결론적으로 프로젝트는 성공적으로 마무리되었다.
이번 프로젝트에서
컨디션조절이 굉장히 중요하다는 것을 크게 느꼈다.. 코드를 짜는 사람은 나 자신인데 내 상태가 좋지 않다면 집중이 되지않아 코드도 잘안짜지고 진행도도 현저히 느려진 다는 것을 알게되어 각자에게 맞는 컨디션 조절법이 필요하다는것을 여실히 느꼈습니다. 그렇게 된다면 프로젝트 진행도, 팀원간의 사기 증진등 여러 이점들이 많을 걸로 예상된다!
이번 프로젝트를 통해 가장 크게 느낀건 구체적이고 디렉션이 확실한 소통 방식이 중요하다는 것을 크게 느꼈습니다. 각 포지션끼리에 소통도 소통이고, 프론트와 백간의 소통도 이렇게까지 구체적이고 확실해야하나 할 정도로 해야한다는 것, 그리고  프론트가 해줄수있는부분 백엔드가해줄수있는 부분 서로 해줄 수 있는 부분에서 최선을 다해 해주려고 노력하면 화기애애한 프로젝트가 될 수 있다는 것도 다시 한번 알게되었다. </p>
<p>본의 아니게 저와함께 직책을 맡은 오현님 책임감의 무게를 견디느라 고생많으셨습니다
MVP핵심기능을 어려운데도 잘 구현해준 끈기왕 성인님
CSS장인이시며 항상 어떤어려움있다고 말씀드리면 열심히 해결해주신 해결사 원희님 
저와 기능이 가장많이 겹쳐서 이번 프로젝트에 가장많은걸 느끼께해주신 예찬님 백엔드와 소통하는 방식을 많이 배웠습니다.. 묵묵하게 기능구현에 힘써주시고 생각치도 못한 드립으로 빵빵터뜨려주신 호욱님 덕분에 팀분위기가 더 좋았던것같습니다. </p>
<p>나는 팀에서 부리더라는 직책을 맡게 되어 저는 팀 분위기에 중점을 맞춰 진행했는데 제생각에는 큰 갈등없이 좋은 분위기에서 프로젝트를 마무리 한 것 같아 제 노력과 진심이 팀원들에게 잘 전해졌다고 생각한다.ㅎ  팀원들 모두 고생많으셨습니다! 4조 화이팅!</p>
<p>프로젝트가 마무리 되고 보니 시원하기도 했지만, 나를 어필할 수 있는 작은 미니 프로젝트를 하나 시작해야겠다는 생각이 들었다.
프로젝트내에서 각각의 역할을 잘 나눠서 성공적으로 했지만, 나자신을 온전히 어필할 수 있는 느낌은 받지 못했다. 새로운 개인프로젝트로 어떤걸할지 고민이든다 오픈소스를 사용하는느낌으로 webRTC를 mesh형식에서 SFU서버 방식으로 고도화를 시킬지 아니면 같은 mesh형식으로 작은 개인프로젝트를 새로할지..! 아마 전자가되지 않을까싶다!! 다시 화이팅해보자구!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[호랑이한테 잡혀가도 정신만차리면 살아돌아온다.]]></title>
            <link>https://velog.io/@idojustdo_it/%ED%98%B8%EB%9E%91%EC%9D%B4%ED%95%9C%ED%85%8C-%EC%9E%A1%ED%98%80%EA%B0%80%EB%8F%84-%EC%A0%95%EC%8B%A0%EB%A7%8C%EC%B0%A8%EB%A6%AC%EB%A9%B4-%EC%82%B4%EC%95%84%EB%8F%8C%EC%95%84%EC%98%A8%EB%8B%A4</link>
            <guid>https://velog.io/@idojustdo_it/%ED%98%B8%EB%9E%91%EC%9D%B4%ED%95%9C%ED%85%8C-%EC%9E%A1%ED%98%80%EA%B0%80%EB%8F%84-%EC%A0%95%EC%8B%A0%EB%A7%8C%EC%B0%A8%EB%A6%AC%EB%A9%B4-%EC%82%B4%EC%95%84%EB%8F%8C%EC%95%84%EC%98%A8%EB%8B%A4</guid>
            <pubDate>Thu, 04 Aug 2022 09:40:06 GMT</pubDate>
            <description><![CDATA[<p>원래 우리가 예상한 배포일은 적어도 7월29일 토요일이었지만 
일요일이 된 그날도.. 우리는 배포하지못했었다.
현재 되는 기능들을 총정리하려고 체크리스트를 작성했는데.<img src="https://velog.velcdn.com/images/idojustdo_it/post/c4191501-0697-45fa-9bc8-4a08b0a89db0/image.png" alt="">
결과는 암담했다.. 
기능을 만들고 확인하고 머지를 하면 다시안되는 사태가 계속 발생하니 진행속도가 현저하게 늦어지는 사태가 발생하였다..</p>
<p>💔멘탈이 바삭바삭해지기 시작하여 원래 배포하려고 했던 날짜에 배포하지 못하게 되니 조급함까지 더해져 굉장히 크리스피한 멘탈이 되었다 💔</p>
<p>지난주 5일밤낮을 새며 최선을 다했지만, 최선을 다한 노력에 비해 아웃풋이 나오지 않는다는 것에 대한 실망감과 조급함이 만들어낸 결과라 생각했다.
잠깐 1주전부터 더 열심히할껄이라는 후회를했지만, <img src="https://velog.velcdn.com/images/idojustdo_it/post/6963b718-3fd0-470f-a5a0-832b7f64832c/image.jpg" alt=""></p>
<p>조급함에 팀원들끼리도 답답해했지만, 갈등이나 싸움조차 나지않았다.
우리팀원들이 다들 동글동글한 성격인분들인 것과 평소에도 서로 건강체크하고 평화롭게 지내서 그런것들이 쌓여서 조급해도 각자의 선을 지키는게 아닌가 싶었다.</p>
<p>오늘 기술적으로 풀리지않았던 문제는 formdata에 대한 이해도가 떨어져서 
삽질은 오랜시간했다.. 
formdata 안에 배열이 들어가게되었을때 [&#39;a&#39;,&#39;b&#39;,&#39;c&#39;]를 넣어서 보내도 
[&#39;a,b,c&#39;] 이런식으로 배열속에 요소가 1개인 상태로 변하게되어 큰 어려움이 있어 for반복문도 돌려보고 다했지만, 결국 백엔드에서 분리시켜서 겨우 해결했다... </p>
<p>어떤 기능이나 기술을 사용하려면 그 기술에대한 개념먼저 충분히 익히는게 좋겠다. 
공식문서나 그외 개념익히기에 도움이 될만한 레퍼런스를 익히는 작업을 하는게 추후에 큰도움이 됩니다..ㅎ 배포까지 완벽히하는 그날까지 화이팅우리조  </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[DatePicker 날짜형식 바꾸기 정리.(input창 과 value값)(with React)]]></title>
            <link>https://velog.io/@idojustdo_it/DatePicker-%EB%82%A0%EC%A7%9C%ED%98%95%EC%8B%9D-%EB%B0%94%EA%BE%B8%EA%B8%B0-input%EC%B0%BD-%EA%B3%BC-value%EA%B0%92with-React</link>
            <guid>https://velog.io/@idojustdo_it/DatePicker-%EB%82%A0%EC%A7%9C%ED%98%95%EC%8B%9D-%EB%B0%94%EA%BE%B8%EA%B8%B0-input%EC%B0%BD-%EA%B3%BC-value%EA%B0%92with-React</guid>
            <pubDate>Sat, 30 Jul 2022 07:40:46 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/idojustdo_it/post/465ea8cf-9559-41b4-9156-e1f37ff608df/image.jfif" alt=""></p>
<p> 우리 팀 프로젝트에 기간을 설정해야하는 기능을 추가하기위해 알아보던중 Date Picker가 가장 잘 쓰인다기에 바로 사용해서 설정을 했는데
아무래도 처음 사용하는 모듈이다보니.. UI적인 커스터마이징이나 그외에    내가 원하는 값의 형식을 설정하는게 어려웠다. 중간에 다시는 쓰지말아야지..라는 생각을 했지만, 하나 하나씩알아내다보니 이제는 생각보다 편해졌다..!</p>
<p>자, 이제 내가 어떤과정을 거쳤는지 알아보자 🤸🏼‍♀️🤸🏼‍♂️</p>
<p>우리프로젝트에선 스터디 룸을 만드는데 몇일 부터 몇일까지 이방이 유지되는 식으로 만들 예정이라 시작날짜와 끝나는 날짜 2가지의 날짜 그리고 범위를 나타내주면 더 좋겠다 라는 생각에 그런 형식을 찾던 도중 발견!<img src="https://velog.velcdn.com/images/idojustdo_it/post/9475816c-6e9e-475f-9e3a-2c4983eaed45/image.png" alt="">
<a href="https://velog.velcdn.com/images/idojustdo_it/post/890c2bc3-b342-42c2-8d84-4a750ad4d29a/image.png"></a>
했다.
아주 딱이었다.
이제 input창과 창안에 있는 날짜형태를 한국 형식으로 바꿔서 표시하고 데이터 값도 같은 형식으로 나타냈어야했다. 그래서
데이트피커 속성 값과 import &quot;moment/locale/ko&quot;; 바꿔주었다</p>
<pre><code> &lt;DatePicker
       required
       selectsRange={true} 
       locale={ko} // 한글로 변경
       dateFormat=&quot;yyyy년MM월dd일(eee)&quot; // 시간 포맷 변경
       startDate={new Date()} 시작날짜 오늘로 고정
       endDate={endDate}
       minDate={new Date()} // 날짜를 선택할수 있는 최소 
       popperPlacement=&quot;auto&quot;  팝업 중간에 띄우기
       customInput={&lt;Input1 /&gt;} 커스텀한 스타일을 넣어주기
       onChange={(date) =&gt; {
       setDateRange(date);
       }}
       withPortal
              /&gt;</code></pre><p>그리고 날짜가 자꾸... <img src="https://velog.velcdn.com/images/idojustdo_it/post/e96257b6-0af0-47db-9f91-20c7f42cb64d/image.png" alt="">이런식으로 나와서 
데이트피커 내에서 어떻게 해보려고 엄청난 시간을 쏟아부었지만 어림도없었다...<img src="https://velog.velcdn.com/images/idojustdo_it/post/501de425-acdf-4850-85b6-4f465f72208c/image.gif" alt=""> 어림도없지!!</p>
<p>그래서 데이트피커로 나온 setstate 값인 dateRange 값을
moment모듈을 통해서 
<img src="https://velog.velcdn.com/images/idojustdo_it/post/b193344e-a382-4318-9510-02d62976ab57/image.png" alt="">
formData로 보내야해서 붙였지만 monent(dateRange[1]).format(&quot;YYYY년MM월DD일&quot;)형식으로 작성했는데, 
dateRange는 배열이라서 [시작일,종료일]이런식이라 종료일을 저런식으로표현해주었다.. 모두모두.. 제 글보고 쉽게 날짜형식 다루셨으면 좋겠습니다.. 모르시면 댓글 남겨주세오... 최대한빨리확인해서 알려드릴께오ㅎ</p>
<p>지나고나니 데이트피커.. 나름 잘 다룰수 있을 것만 같다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[SEO란 무엇인가?]]></title>
            <link>https://velog.io/@idojustdo_it/SEO%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%B8%EA%B0%80</link>
            <guid>https://velog.io/@idojustdo_it/SEO%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%B8%EA%B0%80</guid>
            <pubDate>Mon, 25 Jul 2022 01:43:48 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/idojustdo_it/post/7b8274f8-fb85-4e49-ba7e-f8d0acea71e9/image.png" alt=""></p>
<p><strong>정리</strong>
검색엔진 최적화란? 
Search Engine Optimization으로 
검색 사용자가의 의도에 맞게 웹페이지를 최적화하여 검색엔진의 평가를 높여 검색결과 페이지에서
노출을 늘림으로 자연유입 트래픽을 늘리는 방법, 지속가능한 마케팅 방안</p>
<p>쉽게말해 검색 = 소비자의 니즈(질문)
             콘텐츠 = 답</p>
<p>소비자가 질문을 할때 적절한 답을 즉각제공하는 것이 검색엔진 최적화이다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[var let const 의차이?]]></title>
            <link>https://velog.io/@idojustdo_it/var-let-const-%EC%9D%98%EC%B0%A8%EC%9D%B4</link>
            <guid>https://velog.io/@idojustdo_it/var-let-const-%EC%9D%98%EC%B0%A8%EC%9D%B4</guid>
            <pubDate>Mon, 25 Jul 2022 01:41:12 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/idojustdo_it/post/848546b2-4c50-4d2f-83ab-0c8ba4926d37/image.png" alt=""></p>
<p>var let const는 변수와 상수를 선언하는 키워드로 사용됩니다 .
let const는 es6문법으로 블록레벨스코프의 특징을 갖고, 호이스팅은 되지만 TDZ로 인한  초기화에러로 호이스팅이 되지않는걸로 착각 할 수 있습니다.
let은 변수에 재할당이 가능하지만, const의 경우 변수 재선언 재할당 모두 불가능합니다. 
var의 경우 함수레벨 스코프이며,  TDZ가 발생하지않아 초기화와 선언이 동시에 일어나 메모리는 적재되지만 할당단계가 일어나지않아 undefined로 값을 표현합니다. </p>
<p>TDZ란 ? 일시적으로 특정 변수에 접근할 수 없는 구간으로 
스코프의 시작 지점부터 해당 변수의 초기화 시작 지점까지의 구간
TDZ가 발생하면 선언과 초기화단계가 동시에 발생할수 없게됩니다. </p>
<p>TDZ는 JS가 동적언어이다 보니, runtime type check가 필요하여 발생하게 됩니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[typescript 사용목적 및 장점]]></title>
            <link>https://velog.io/@idojustdo_it/z8ocx5q4</link>
            <guid>https://velog.io/@idojustdo_it/z8ocx5q4</guid>
            <pubDate>Mon, 25 Jul 2022 01:39:43 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/idojustdo_it/post/242cdae5-9cdb-4d0d-af12-d2c25d47d293/image.png" alt=""></p>
<p>Typescript는 순수 자바스크립트와의다르게 Object의 타입을 명시하여
자바스크립트를 실제로 사용하기 전에 있을만한 타입 에러들을 미리잡기 위해 사용합니다. 
 개발자가 의도한 변수나 함수등의 목적을 더욱 명확하게 전달 가능하고 
전달된 정보를 기반으로 코드 자동완성이나 잘못된 변수/함수 사용에 대한 에러 와 같은 풍부한 피드백을 받을 수 있어,
생산성이 크게 올라갑니다.
그리고 느슨한 타입의 언어인 자바스크립트를 사용해 만든 프로젝트에서는 규모가 커질수록 코드가 복잡해지고, 
디버그와 테스트 공수가 증가하는 문제가 있어 이런 자바스크립트의 단점을 극복하고자 타입스크립트를 사용합니다.</p>
<p>사용장점</p>
<p><strong>정리</strong>
1.기존 자바스크립트 소스와의 호환
2.정적타입
사용하는 가장 큰 이유 중 하나는 정적타입을 지원한다는 것 컴파일단계에서 오류를 포착</p>
<p>3.VS코드와의 궁합
코드 피드백을 매우 잘 해주는데 특정 함수에서 어느 부분이 틀리게 작성되었다고 지적하는 것은 기본</p>
<p>4.npm 사용
Node.js의 npm 패키지들을 손쉽게 사용할 수 있으며, 타입스크립트 컴파일러 자체가 npm 패키지이기도 하다</p>
<ol start="5">
<li>백엔드와 프론트엔드 통합도가능하고 프론트엔드 단독 도가능</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[promise 와 callback 함수의 차이]]></title>
            <link>https://velog.io/@idojustdo_it/promise-%EC%99%80-callback-%ED%95%A8%EC%88%98%EC%9D%98-%EC%B0%A8%EC%9D%B4</link>
            <guid>https://velog.io/@idojustdo_it/promise-%EC%99%80-callback-%ED%95%A8%EC%88%98%EC%9D%98-%EC%B0%A8%EC%9D%B4</guid>
            <pubDate>Mon, 25 Jul 2022 01:38:29 GMT</pubDate>
            <description><![CDATA[<p><strong>정리</strong>
callback을 사용하면 비동기 로직의 결과값을 처리하기 위해서는 callback안에서만 처리를 해야하고, 
콜백 밖에서는 비동기에서 온 값을 알 수가 없으며, 매번 비동기를 실행해야지 그 값을 사용할 수 있습니다.
비동기 로직의 결과를 다음 비동기로 전달해서 실행해야 할 때 callback은 점점 깊어져서 가독성이 매우 안좋아지고,
코드를 작성할 때도 힘들어집니다.(콜백 지옥이라고도하죠)</p>
<p>하지만 promise를 사용하면 비동기에에서 온 값이 promise 객체에 저장되기 때문에 코드 작성이 용이해집니다.
 .then 메소드를 통해  저장되어 있는 값을 원하는 때에 사용할 수 있고,
코드의 깊이가 깊어지지 않아,가독성도 좋습니다</p>
]]></description>
        </item>
    </channel>
</rss>