<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>summerjoy.log</title>
        <link>https://velog.io/</link>
        <description>💻 Hello world</description>
        <lastBuildDate>Wed, 26 Jul 2023 07:37:59 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>summerjoy.log</title>
            <url>https://velog.velcdn.com/images/ensun_p/profile/0c4a0ae3-91b5-4200-9c3e-2679d5aa3e35/image.jpg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. summerjoy.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/ensun_p" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[bitbucket 형상 관리 툴, repository 생성하기]]></title>
            <link>https://velog.io/@ensun_p/bitbucket-%ED%98%95%EC%83%81-%EA%B4%80%EB%A6%AC-%ED%88%B4-repository-%EC%83%9D%EC%84%B1%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@ensun_p/bitbucket-%ED%98%95%EC%83%81-%EA%B4%80%EB%A6%AC-%ED%88%B4-repository-%EC%83%9D%EC%84%B1%ED%95%98%EA%B8%B0</guid>
            <pubDate>Wed, 26 Jul 2023 07:37:59 GMT</pubDate>
            <description><![CDATA[<h3 id="bitbucket-소개">bitbucket 소개</h3>
<p><strong>형상 관리 툴이란?</strong></p>
<blockquote>
<p>&#39;형상 관리를 한다&#39;라는 말은 개발되는 소스들의 변화를 관리한다는 말이다.
개인의 작업이 아닌 팀으로서, 개발 프로젝트를 진행한다거나 아는 사람들과의 토이 프로젝트를 진행할 때, 어떤 사람이 커밋을 했고, 해당 소스를 병합 핟기도 하는 등, 소스 관리를 보다 편리하게 해주는 툴이다.</p>
</blockquote>
<p>프로젝트를 진행할 때마다 형상 관리 툴을 사용하게 되는데
최근 알게된(사용하게 된) 툴을 소개하려고 한다.</p>
<p><a href="https://bitbucket.org/">bitbucket</a></p>
<p>bitbucket은 최대 5명까지 무료 계정으로 사용할 수 있다.
빗버킷을 사용해 본 결과, 내가 느낀 장점들은 아래와 같다.</p>
<ol>
<li><p>config 파일을 기반으로 파이프라인을 구축할 수 있어서, 빌드/테스트/배포의 자동화를 구축할 수 있는 환경을 제공한다.</p>
</li>
<li><p>최대 5명까지 무료로 사용이 가능하다. 또한, 5명이 넘어가더라도 다른 저장소보다 경쟁력 있는 금액이라고 생각한다.</p>
</li>
<li><p>협업 툴이 다른 형상 관리 툴보다 많다. jandi, jira 등 많은 협업 툴과 웹 훅 정도의 연동을 굳이 개발하지 않더라도, 연동할 수 있도록 지원한다.</p>
</li>
<li><p>코드 리뷰를 지원하는 UI가 심플해서 보기가 편하다.</p>
</li>
</ol>
<h3 id="로컬-프로젝트를-repository에-올리기">로컬 프로젝트를 repository에 올리기</h3>
<ol>
<li>가입 후, Create Repository 클릭해서, 프로젝트 레퍼지토리를 생성한다.</li>
</ol>
<p><img src="https://velog.velcdn.com/images/ensun_p/post/f27b0ee0-677c-420a-8bd8-b560cc5ab8ea/image.png" alt=""></p>
<ol start="2">
<li>repository 정보를 입력한다.</li>
</ol>
<p><img src="https://velog.velcdn.com/images/ensun_p/post/90f79aa5-7f09-4aac-99f9-77f0b2c03833/image.png" alt=""></p>
<p><strong>Project</strong>
프로젝트 명 (repository 내부에 들어갈 프로젝트 명)</p>
<p><strong>Repository name</strong>
repository 이름 입력 ex) API_SERVER_EXAMPLE</p>
<p><strong>Access level</strong>
접근 레벨</p>
<p><strong>Default branch name</strong>
기본 브랜치 입력 (입력 안해도 상관없다.)</p>
<ol start="3">
<li>프로젝트를 생성한 repository에 import 시킨다.</li>
</ol>
<p>터미널을 열고 내 로컬 서버에서 개발한 프로젝트 경로로 이동한다.
나의 경우는 [/user/developer/project/&#39;프로젝트명&#39;] 경로에 내가 작업하는 프로젝트가 있다.
해당 경로로 이동하여 아래와 같이 명령어를 입력한다.</p>
<pre><code>git init - 깃 저장소 초기화
git add-all - 프로젝트 생성
git commit-m &quot;first bitbucket commit&quot; - 커밋 메세시 생성</code></pre><p>그러나 해당 명령어를 순서대로 입력하게 되면 
repository를 생성할 때 readme 파일을 생성해줬기 때문에 오류가 발생한다.</p>
<p><em>error : failed to push some refs ~~</em></p>
<ol start="4">
<li>다음은 해결 방법이다.
다음 명령어를 순서대로 입력한다.</li>
</ol>
<pre><code>git init

git pull origin master -allow-unrelated-histories
// 이미 bitbucket 브랜치에 독립적인 프로젝트가 있는 것으로 판단하기 때문에, 관련 없는 두 프로젝트를 병합하겠다는 명시

git add

git push -u origin master</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[swiper slide 재생/정지]]></title>
            <link>https://velog.io/@ensun_p/swiper-slide-%EC%9E%AC%EC%83%9D%EC%A0%95%EC%A7%80</link>
            <guid>https://velog.io/@ensun_p/swiper-slide-%EC%9E%AC%EC%83%9D%EC%A0%95%EC%A7%80</guid>
            <pubDate>Mon, 05 Jun 2023 01:39:35 GMT</pubDate>
            <description><![CDATA[<pre><code class="language-javascript">&lt;script&gt;
var mySwiper = new Swiper(&#39;.swiper-container&#39;, {
  // Optional parameters
  //direction: &#39;vertical&#39;,
  loop: true,
  autoplay:{
                delay:1000 //1초의 딜레이를 주고 자동 재생된다
            },


  // If we need pagination
  pagination: {
    el: &#39;.swiper-pagination&#39;,
  },

  // Navigation arrows
//   navigation: {
//     nextEl: &#39;.swiper-button-next&#39;,
//     prevEl: &#39;.swiper-button-prev&#39;,
//   },

  // And if we need scrollbar
  scrollbar: {
    el: &#39;.swiper-scrollbar&#39;,
  },
})
var sw = 0;
$(&#39;.btn_pause&#39;).click(function(){
    if(sw==0){
        $(&#39;.btn_pause&#39;).addClass(&#39;on&#39;);
        mySwiper.autoplay.stop();
        sw = 1;
    }else{
        $(&#39;.btn_pause&#39;).removeClass(&#39;on&#39;);
        mySwiper.autoplay.start();
        sw = 0;
    }
});

});

&lt;/script&gt;```</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[React] 사용자 입력 처리하기 - simpleDiary 프로젝트 1]]></title>
            <link>https://velog.io/@ensun_p/React-%EC%82%AC%EC%9A%A9%EC%9E%90-%EC%9E%85%EB%A0%A5-%EC%B2%98%EB%A6%AC%ED%95%98%EA%B8%B0-simpleDiary-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-1</link>
            <guid>https://velog.io/@ensun_p/React-%EC%82%AC%EC%9A%A9%EC%9E%90-%EC%9E%85%EB%A0%A5-%EC%B2%98%EB%A6%AC%ED%95%98%EA%B8%B0-simpleDiary-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-1</guid>
            <pubDate>Tue, 25 Apr 2023 09:14:39 GMT</pubDate>
            <description><![CDATA[<h3 id="1-리액트-프로젝트-생성">1. 리액트 프로젝트 생성</h3>
<p><img src="https://velog.velcdn.com/images/ensun_p/post/f3f62b75-f602-4863-9264-7a47e8d5c3ec/image.png" alt=""></p>
<pre><code>npx create-react-app simplediary</code></pre><p><img src="https://velog.velcdn.com/images/ensun_p/post/62a2f367-1286-4fda-ac5d-96873d5a9914/image.png" alt=""></p>
<p>사용하지 않을 로고 파일, 테스트 파일들을 지우고 App.js 임포트 정리까지 해줬다.</p>
<h3 id="2-오늘의-학습목표">2. 오늘의 학습목표</h3>
<p><img src="https://velog.velcdn.com/images/ensun_p/post/9f826e7e-6e2c-44d9-aad5-45892dc48c43/image.png" alt=""></p>
<h3 id="3-diaryeditor-컴포넌트-생성">3. diaryEditor 컴포넌트 생성</h3>
<pre><code class="language-javascript">import &#39;./App.css&#39;;
import DiaryEditor from &#39;./DiaryEditor&#39;;

function App() {
  return (
    &lt;div className=&quot;App&quot;&gt;
      &lt;h2&gt;일기장&lt;/h2&gt;
      &lt;DiaryEditor&gt;&lt;/DiaryEditor&gt;
    &lt;/div&gt;
  );
}

export default App;</code></pre>
<h3 id="4-한-줄-짜리-입력-받기">4. 한 줄 짜리 입력 받기</h3>
<p>사용자 입력값을 받을 수 있는 input값을 생성해주었다.</p>
<pre><code class="language-javascript">const DiaryEditor = () =&gt; {
    return (
    &lt;div className=&quot;DiaryEditor&quot;&gt;
        &lt;h2&gt; 오늘의 일기 &lt;/h2&gt;
        &lt;div&gt;
            &lt;input/&gt;
        &lt;/div&gt;
    &lt;/div&gt;
    )
}

export default DiaryEditor;</code></pre>
<h3 id="5-리액트의-usestate-import-하기">5. 리액트의 useState import 하기</h3>
<p>이제 이 값을 DiaryEditor 컴포넌트가 핸들링 할 수 있도록 <code>state</code>를 사용한다.</p>
<pre><code>import { useState } from &quot;react&quot;;</code></pre><p>useState를 import 해준다.</p>
<p>작성자를 저장할 것이기 때문에</p>
<pre><code>const [author, setAuthor] = useState(&quot;&quot;);</code></pre><p>useState기본값을 주고 author라는 state와 author 상태변화를 주도할 setAuthor 상태변화함수를 만들어주었다.
<strong>여기서 첫번째 값은 현재 상태, 두번째 값은 Setter함수</strong>이다</p>
<p>input의 입력값이 바뀌면 입력값이 바뀔때마다 setAuthor 상태변화함수를 이용하여 author에 저장하려고 한다.</p>
<p><img src="https://velog.velcdn.com/images/ensun_p/post/dd9f3e79-77b0-4508-b754-c3d1f337ddf9/image.png" alt=""></p>
<p>input의 값을 author로 설정해준 후 input이 수정되면 author의 값을 실시간으로 바꿔줄 수 있는 이벤트를 추가한다.</p>
<h3 id="6-onchange">6. onChange</h3>
<p>onChange props에 이벤트 객체 e를 매개변수로 사용하는 콜백함수를 전달해준다.</p>
<pre><code class="language-javascript">&lt;input value={author} 
       onChange={(e)=&gt;{
       console.log(e);
       }}/&gt;</code></pre>
<p>오늘의 일기 input에 값을 입력하면 console창에 change 이벤트 객체가 찍히는 것을 확인할 수 있다.
어떤 값을 입력했는지 확인하려면 타겟의 value 값을 적은 후 저장
console창을 확인해보면 input에 넣으려 하는 값이 뜬다.</p>
<h3 id="7-여러-줄-입력받기-onchange-이벤트를-사용하여-값-전달하기">7. 여러 줄 입력받기, onChange 이벤트를 사용하여 값 전달하기</h3>
<p>위에서 설명했던 input과 textarea는 state를 이용하는 방법이 동일하다.
value에 state이름, onChange에 e.target.value를 상태변화함수에 전달, 두 값이 가지는 자료형까지 똑같다.</p>
<h3 id="8-두-개의-state를-하나로-묶기">8. 두 개의 state를 하나로 묶기</h3>
<p>이럴 경우엔 state를 하나로 묶어주는 방법이 있다.
setState를 할 때 새로운 객체를 만들어서 변경시켜준다.
바뀔 부분은 값을 넣어주고, 유지해야 할 부분은 state를 해준다.</p>
<pre><code class="language-javascript">import { useState } from &quot;react&quot;;

const DiaryEditor = () =&gt; {

    const [state, setState] = useState({
        author: &quot;&quot;,
        content: &quot;&quot;
    });

    return (
    &lt;div className=&quot;DiaryEditor&quot;&gt;
        &lt;h2&gt; 오늘의 일기 &lt;/h2&gt;
        &lt;div&gt;
            &lt;input value={state.author} 
            onChange={(e)=&gt;{
                setState({
                    author: e.target.value,
                    content: state.content
                });
            }}/&gt;
        &lt;/div&gt;
        &lt;div&gt;
            &lt;textarea value={state.content} 
            onChange={(e)=&gt; {
                setState({
                    content: e.target.value,
                    author: state.author
                });
            }}/&gt;
        &lt;/div&gt;
    &lt;/div&gt;
    )
}

export default DiaryEditor;</code></pre>
<h3 id="9-state-같은-스프레드연산자">9. ...state 같은 스프레드연산자</h3>
<p>그러나.. 지금처럼 2개가 아니라 인자가 10개 20개일때는?
한 개만 바꾸려다가 코드량이 길어질 수 있다는 문제점이 있다.
이럴 때 사용할 수 있는 건</p>
<pre><code class="language-javascript">            onChange={(e)=&gt;{
                setState({
                    ...state,
                    author: e.target.value
                });
            }}/&gt;</code></pre>
<p>이때 주의해야 할 사항은 스프레드 연산자가 위에 위치해야 한다.
<strong>스프레드연산자가 밑에 위치하게 되면 업데이트한 값이 다시 state로 변경되기 때문</strong></p>
<h3 id="10-diaryeditor-컴포넌트가-핸들링-할-수-있는-감정-선택-select-만들기">10. DiaryEditor 컴포넌트가 핸들링 할 수 있는 감정 선택 select 만들기</h3>
<pre><code class="language-javascript">&lt;div&gt;
 오늘의 감정점수:
  &lt;select
        name=&quot;emotion&quot;
        value = {state.emotion}
        onChange={handleChangeState}
   &gt;
    &lt;option value={1}&gt;1&lt;/option&gt;
    &lt;option value={2}&gt;2&lt;/option&gt;
    &lt;option value={3}&gt;3&lt;/option&gt;
    &lt;option value={4}&gt;4&lt;/option&gt;
    &lt;option value={5}&gt;5&lt;/option&gt;
  &lt;/select&gt;
&lt;/div&gt;</code></pre>
<p><img src="https://velog.velcdn.com/images/ensun_p/post/c751a307-42d5-478b-a436-428fdd1f5844/image.png" alt=""></p>
<h3 id="11-저장-버튼을-생성하여-폼에-입력한-값-전달하기">11. 저장 버튼을 생성하여 폼에 입력한 값 전달하기</h3>
<pre><code class="language-javascript">    const handleSubmit = ()=&gt;{
        console.log(state);
        alert(&quot;저장 성공&quot;);
    }</code></pre>
<pre><code class="language-html"> &lt;button onClick={handleSubmit}&gt;일기 저장하기&lt;/button&gt;</code></pre>
<p>하단에 onClick이벤트를 넣은 버튼을 추가해주었다.</p>
<h3 id="12-약간의-css추가">12. 약간의 CSS추가</h3>
<p>가시성을 위해 약간의 style을 입혀주었다.</p>
<pre><code class="language-html">.DiaryEditor {
  border: 1px solid gray;
  text-align: center;
  padding: 20px;
}

.DiaryEditor input, textarea {
  margin-bottom: 20px;
  width: 500px;
  padding: 10px;
}

.DiaryEditor textarea {
  height: 150px;
}

.DiaryEditor select {
  width: 300px;
  padding: 10px;
  margin-bottom: 20px;
}

.DiaryEditor button {
  width: 500px;
  padding: 10px;
  cursor: pointer;
}</code></pre>
<h3 id="13-결과">13. 결과</h3>
<p><img src="https://velog.velcdn.com/images/ensun_p/post/74ff2361-44ee-4e95-8d87-40ce55392157/image.png" alt=""></p>
<p>완성된 화면 !</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Swiper - loop 모드에서 duplication이 제대로 안될때]]></title>
            <link>https://velog.io/@ensun_p/Swiper-loop-%EB%AA%A8%EB%93%9C%EC%97%90%EC%84%9C-duplication-%EC%9D%B4-%EC%A0%9C%EB%8C%80%EB%A1%9C-%EC%95%88%EB%90%A0-%EB%95%8C</link>
            <guid>https://velog.io/@ensun_p/Swiper-loop-%EB%AA%A8%EB%93%9C%EC%97%90%EC%84%9C-duplication-%EC%9D%B4-%EC%A0%9C%EB%8C%80%EB%A1%9C-%EC%95%88%EB%90%A0-%EB%95%8C</guid>
            <pubDate>Mon, 27 Mar 2023 06:38:21 GMT</pubDate>
            <description><![CDATA[<pre><code class="language-javascript">    var swiper = new Swiper(&#39;.swiper-container&#39;, {
        speed: 300,
        spaceBetween: 50,
        width:300,
        loop:true,
        loopedSlides: 1,
        pagination:{
            el:&quot;.swiper-scrollbar&quot;,
        },
    })</code></pre>
<p><strong>loopedSlides: 1</strong> 을 넣어주면 된다.</p>
<p><a href="github.com/nolimits4web/swiper/issues/2629">In loop mode, duplicate slides are not being updated when the contents of the original slides change</a>
<a href="https://somv12.tistory.com/16">swiper controller 연동 오류일 때</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[알고리즘] 백준 10869 javascript]]></title>
            <link>https://velog.io/@ensun_p/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-10869-javascript</link>
            <guid>https://velog.io/@ensun_p/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-10869-javascript</guid>
            <pubDate>Mon, 13 Mar 2023 09:26:13 GMT</pubDate>
            <description><![CDATA[<p>입출력과 사칙연산 9단계
<code>10869 - 사칙연산</code></p>
<p><strong>문제</strong>
두 자연수 A와 B가 주어진다. 이때, A+B, A-B, A*B, A/B(몫), A%B(나머지)를 출력하는 프로그램을 작성하시오.</p>
<hr>
<p><strong>입력</strong>
두 자연수 A와 B가 주어진다. (1 ≤ A, B ≤ 10,000)</p>
<hr>
<p><strong>출력</strong>
첫째 줄에 A+B, 둘째 줄에 A-B, 셋째 줄에 A*B, 넷째 줄에 A/B, 다섯째 줄에 A%B를 출력한다.</p>
<hr>
<p><strong>💻답</strong></p>
<pre><code class="language-javascript">const fs = require(&#39;fs&#39;);
const inputData = fs.readFileSync(&#39;/dev/stdin&#39;).toString().split(&#39; &#39;).map(Number);

const A = inputData[0];
const B = inputData[1];

console.log(A+B);
console.log(A-B);
console.log(A*B);
console.log(parseInt(A/B));
console.log(A%B);</code></pre>
<p>지금까지 풀었던 사칙연산을 총 복습하는 문제였다.
자바스크립트에는 몫을 구하는 연산자가 따로 없기 때문에
A/B 문제에서 나눗셈 결과를 <code>parseInt()</code> 처리해서 정수만 뽑아낸다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[알고리즘] 백준 1000 1001 javascript]]></title>
            <link>https://velog.io/@ensun_p/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%EB%B0%B1%EC%A4%80-1000-1001-javascript</link>
            <guid>https://velog.io/@ensun_p/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%EB%B0%B1%EC%A4%80-1000-1001-javascript</guid>
            <pubDate>Mon, 13 Mar 2023 09:04:10 GMT</pubDate>
            <description><![CDATA[<p>javascript로 입출력 알고리즘 문제를 풀려면 아래와 같이 해야한다.</p>
<pre><code class="language-javascript">const fs = require(&#39;fs&#39;); 
// node.js의 file system 모듈을 불러온다.

const inputData1 = fs.readFileSync(&#39;/dev/stdin&#39;).toString().split(&#39; &#39;);
// fs모듈의 readFileSync 함수를 통해 동기적으로 해당 경로의 파일 전체를 읽어들인다.
// 백준에서는 &#39;/dev/stdin&#39; 경로에 테스트 케이스 파일이 있다.
// 읽어들인 정보는 toString()함수를 통해 문자열로 변환해야 사용할 수 있다.
// 입력 받은 문자열을 split() 함수를 통해 배열화한다. (split(&#39; &#39;), split(&#39;\n&#39;) 등)
// 예) 2 3 입력시, inputData = [&#39;2&#39;, &#39;3&#39;]

const inputData2 = fs.readFileSync(0, &#39;utf8&#39;).split(&#39; &#39;);
// options으로 인코딩을 string 자료형으로 넘기는 경우, toString을 할 필요없이 문자열 반환</code></pre>
<h2 id="✔-1000-ab">✔ <a href="https://www.acmicpc.net/problem/1000">1000 A+B</a></h2>
<p><strong>문제</strong>
두 정수 A와 B를 입력받은 다음, A+B를 출력하는 프로그램을 작성하시오.</p>
<hr>
<p><strong>입력</strong>
첫째 줄에 A와 B가 주어진다. (0 &lt; A, B &lt; 10)</p>
<hr>
<p><strong>출력</strong>
첫째 줄에 A+B를 출력한다.</p>
<hr>
<p><strong>💻답</strong></p>
<pre><code class="language-javascript">const fs = require(&#39;fs&#39;);
const inputData = fs.readFileSync(0, &#39;utf8&#39;).toString().split(&#39; &#39;);

const A = parseInt(inputData[0]);
const B = parseInt(inputData[1]);

console.log(A+B);</code></pre>
<p><img src="https://velog.velcdn.com/images/ensun_p/post/58a6f74c-c3a1-4034-b34d-3079572e80c1/image.PNG" alt=""></p>
<h2 id="✔-1000-a-b">✔ <a href="https://www.acmicpc.net/problem/1001">1000 A-B</a></h2>
<p><strong>문제</strong>
두 정수 A와 B를 입력받은 다음, A-B를 출력하는 프로그램을 작성하시오.</p>
<hr>
<p><strong>입력</strong>
첫째 줄에 A와 B가 주어진다. (0 &lt; A, B &lt; 10)</p>
<hr>
<p><strong>출력</strong>
첫째 줄에 A-B를 출력한다.</p>
<hr>
<p><strong>💻답</strong></p>
<pre><code class="language-javascript">const fs = require(&#39;fs&#39;);
const inputData = fs.readFileSync(0, &#39;utf8&#39;).toString().split(&#39; &#39;);

const A = parseInt(inputData[0]);
const B = parseInt(inputData[1]);

console.log(A-B);</code></pre>
<p><img src="https://velog.velcdn.com/images/ensun_p/post/958e6d9f-952d-4b39-9314-ab18482f3ad8/image.PNG" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[반응형 비율에 맞춰 줄이기]]></title>
            <link>https://velog.io/@ensun_p/%EB%B9%84%EC%9C%A8%EC%97%90-%EB%A7%9E%EC%B6%B0-%EC%A4%84%EC%9D%B4%EA%B8%B0</link>
            <guid>https://velog.io/@ensun_p/%EB%B9%84%EC%9C%A8%EC%97%90-%EB%A7%9E%EC%B6%B0-%EC%A4%84%EC%9D%B4%EA%B8%B0</guid>
            <pubDate>Mon, 13 Mar 2023 07:00:30 GMT</pubDate>
            <description><![CDATA[<p>반응형 작업시
background 이미지가 비율에 맞춰 줄어들어야 할 때는</p>
<p><strong>100vw - 여백 * 비율(세로/가로)</strong></p>
<p><em>height: calc((100vw - 280px) * 0.6294); -&gt; 이런 형태의 값이 나온다</em></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[ .attr()와 .prop()의 차이]]></title>
            <link>https://velog.io/@ensun_p/.attr%EC%99%80-.prop%EC%9D%98-%EC%B0%A8%EC%9D%B4</link>
            <guid>https://velog.io/@ensun_p/.attr%EC%99%80-.prop%EC%9D%98-%EC%B0%A8%EC%9D%B4</guid>
            <pubDate>Tue, 07 Mar 2023 04:59:11 GMT</pubDate>
            <description><![CDATA[<pre><code>&lt;html&gt;
&lt;body&gt;
  &lt;a id=&quot;to_comments&quot; href=&quot;#comments&quot;&gt;내용&lt;/a&gt;
&lt;/body&gt;
&lt;script&gt;
  var $link = $(&#39;#to_comments&#39;);
  alert($link.attr(&#39;href&#39;));  // href 속성값 
  alert($link.prop(&#39;href&#39;));  // href 프로퍼티값
&lt;/script&gt;
&lt;/html&gt;</code></pre><pre><code>// 결과
.attr() → #to_comment
.prop() → http://example.com/path/to/page#to_comment</code></pre><pre><code>&lt;html&gt;
&lt;body&gt;
    &lt;h2&gt;체크박스 예제&lt;/h2&gt;
     &lt;checkbox id=&quot;private&quot; type=&quot;checkbox&quot; checked /&gt;
&lt;/body&gt;
&lt;script&gt;
  var $checkbox = $(&#39;#private&#39;);
  alert($checkbox.attr(&#39;checked&#39;));  // checked 속성 값 
  alert($checkbox.prop(&#39;checked&#39;));  // checked 프로퍼티 값
&lt;/script&gt;
&lt;/html&gt;</code></pre><pre><code>// 결과
.attr() → &quot;checked&quot;
.prop() → true / false</code></pre><p>checked=&quot;checked&quot;라는 attribute를 추가할 때
.attr(&#39;checked&#39;, &#39;checked&#39;); 또는 .prop(&#39;checked&#39;, true); 
checked=&quot;checked&quot;라는 attribute를 제거할 때
.removeAttr(&#39;checked&#39;); 또는 .prop(&#39;checked&#39;, false);</p>
<p>selected=&quot;selected&quot;라는 attribute를 추가할 때
.attr(&#39;selected&#39;, &#39;selected&#39;); 또는 .prop(&#39;selected&#39;, true);
checked=&quot;checked&quot;라는 attribute를 제거할 때
.removeAttr(&#39;selected&#39;); 또는 .prop(&#39;selected&#39;, false); </p>
<p><strong>자바스크립트 .attr()과 .prop() 차이 정리</strong></p>
<blockquote>
<p>.attr() : HTML의 속성을 취급
.prop() : JavaScript프로퍼티를 취급 </p>
</blockquote>
<p>이 두 개의 메소드는 취급하는 정보가 다름
<strong>.attr()는HTML의 속성(attribute)</strong>을,
<strong>.prop()는 JavaScript의 프로파티(property)</strong>를 취급하는 메소드임</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[시작, 그리고 기초의 중요성]]></title>
            <link>https://velog.io/@ensun_p/%EC%8B%9C%EC%9E%91-%EA%B7%B8%EB%A6%AC%EA%B3%A0-%EA%B8%B0%EC%B4%88%EC%9D%98-%EC%A4%91%EC%9A%94%EC%84%B1</link>
            <guid>https://velog.io/@ensun_p/%EC%8B%9C%EC%9E%91-%EA%B7%B8%EB%A6%AC%EA%B3%A0-%EA%B8%B0%EC%B4%88%EC%9D%98-%EC%A4%91%EC%9A%94%EC%84%B1</guid>
            <pubDate>Tue, 21 Feb 2023 06:56:07 GMT</pubDate>
            <description><![CDATA[<p>3월에 오픈을 앞둔 프로젝트가 어느새 마무리 되었고 다음 프로젝트까지 재정비할 여유가 조금 생겼다. 팀장님이 그 틈을 이용해 react 를 열심히 파고 계셨다. 내가 3시간 고민해도 해결할까 말까 한 에러를 내가 짠 개발새발의 난잡한 코드를 보고도 3분만에 해결할 수 있는 능력을 가진 팀장님도 계속 공부를 하신다. 
팀장님은 10년차고 나는 아직 2년차를 향해 달려가는 코드 잼민이일 뿐이지만 이길 수 없다면 따라하라고 했다(?..) 그렇게 react를 시작했다가 vanila js의 중요성을 깨달아버렸다. 역시 무슨 일이든 기초가 없으면 어려운 법이다.</p>
<p>회사에서 매일 쓰는 건데도 프로젝트의 완성(납기일 준수)만을 목적으로 한 실무였지 더 좋은 코드를 쓰기 위해선 별 노력을 하지 못했다. 그렇게 js를 기초의 중요성을 깨닫고 다시 입문자 강의부터 차근차근 듣는 중이다. 그 중에 가장 맘에 드는 (무료)강의는 생활코딩인데 선생님은 차분하고 좋은 목소리로 하나하나 핵심을 콕 집어 설명해주신다. <code>HTML</code>은 컨텐츠를 쓰는 언어, <code>CSS</code>는 컨텐츠를 디자인하는데 최적화된 언어, <code>JS</code>는 컨텐츠를 사용자와 상호작용 할 수 있게 만드는 언어라고 표현한 것이 인상적이었다. 개발을 시작한 이후로 나는 내가 쓰는 언어에 대해서 한 문장으로 정의해 본 적이 없었는데 아주 적절한 표현이라고 생각한다. 생활코딩 강의를 다 듣고 나서는 인프런에서 마음에 드는 react 입문 강의로 넘어갈 계획이다.
남들 다 하는 react <strong>야 너도</strong> 할 수 있어</p>
<p>요즘 나는 &#39;<a href="http://www.yes24.com/Product/Goods/105526047">물고기는 존재하지 않는다</a>&#39;라는 책을 읽고있다. 책을 좋아하지도, 열심히 읽는 편도 아니지만 이 책의 내용이 어느새 회사 점심시간의 토론 주제가 되어있었다. 호불호가 많이 갈리는 책이라는 평이 있길래 궁금해져서 구매했다.  아직 두번째 목차도 벗어나지 못한 나는 잘 모르겠다. 한문단, 한문장을 읽는데에 많은 시간을 쓰게 하는 책인 것 같다.</p>
<p>요즘 건강한 식단에 관심이 생겼다. 회사에서 도시락을 싸다니거나 사먹거나 두 집단으로 나뉘는데 나는 도시락파다. 매번 사먹는 것도 지겹고 또 나가서 식당을 찾아 기다렸다가 밥을 먹고 돌아오면 점심시간이 끝난다. 온전히 나의 자유시간을 위한 선택이었는데 그렇다고 나는 건강한 음식만 먹었던 것은 아니었고 주로 닭가슴살볶음밥(이라고 쓰고 인스턴트 볶음밥), 편의점 삼각김밥, 아니면 샐러드 정도였다. 매번 이렇게 먹다보니 걱정이 되기 시작했다. 매일 끼니를 이런 식으로 채워도 괜찮을지.. 좀 더 후레쉬한 식단 없을까? 검색하다가 오버나이트오트밀 이라는 식단을 알게 되었다. 오트밀을 우유에 불려 요거트와 각종 견과류, 과일 등을 올려먹는 그야말로 건강식처럼 보였다.
어떤 사람은 잼이나 피넛버터를 올려 먹는데 나는 안올려 먹을 거니까 건강식단 아닐까? 합리화하며 오트밀과 요거트를 잔뜩 구매했다. 오늘 저녁에 만들어 먹어볼 생각이다. <em>건강해져라 네게 가진 거라곤 몸뚱아리 하나 뿐이다.</em></p>
<p>앞으로의 공부 목표와 회사에서의 업무, 나의 일상 루틴을 가감없이 공개하려고 한다. (점점 회사 업무 외 공부하지 않는 나를 채찍질 하기 위함이다..)</p>
<p>오늘은 퇴근 후 병원을 갈 것이고 내일은 운동을 꼭 가야겠다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[position: sticky 왜 안먹는거죠]]></title>
            <link>https://velog.io/@ensun_p/position-sticky-%EC%99%9C-%EC%95%88%EB%A8%B9%EB%8A%94%EA%B1%B0%EC%A3%A0</link>
            <guid>https://velog.io/@ensun_p/position-sticky-%EC%99%9C-%EC%95%88%EB%A8%B9%EB%8A%94%EA%B1%B0%EC%A3%A0</guid>
            <pubDate>Fri, 27 Jan 2023 08:04:34 GMT</pubDate>
            <description><![CDATA[<p>position의 <code>sticky</code> 속성은 스크롤과 연동하여 특정 요소를 화면에 고정시킨다.</p>
<ol>
<li><code>sticky</code>속성을 갖는 요소는 상위 부모요소 안에서만 적용된다는 점</li>
<li>부모요소에 충분한 <strong>height</strong>값을 줘야 한다는 점</li>
<li><code>sticky</code>요소의 전체 부모요소 중에 <strong>overflow: auto, overflow: hidden, overflow: scroll</strong> 가 있으면 적용이 되지 않는다.</li>
</ol>
<pre><code class="language-javascript">    // gnb 스크롤 이벤트
    var fixScroll = 0;
    $(window).scroll(function(event){
         var scroll = $(this).scrollTop();
         if (scroll &gt; 2000){
              $(&quot;#gnb&quot;).addClass(&quot;fixed&quot;);
              $(&quot;html&quot;).css(&quot;overflow-x&quot;, &quot;visible&quot;);
         } else {
              $(&quot;#gnb&quot;).removeClass(&quot;fixed&quot;);
              $(&quot;html&quot;).css(&quot;overflow-x&quot;, &quot;hidden&quot;);
         }
         fixScroll = scroll;
    });
});</code></pre>
<p>로컬에서 혼자 작업하며 잘 되던 sticky가
프로젝트 개발서버에 업로드 이후부터 적용이 안되는 것이었다.</p>
<p>이유는 해당 프로젝트 폴더에 공통으로 쓰이는 css파일의 html 태그에 <code>overflow</code>가 적용되어 있어서였다.
공통파일이라 삭제할 수는 없었고.. 스크립트로 sticky속성이 적용되는 시점에 html의 overflow 속성값을 visible로 잠시 바꿔주었더니 해결되었다.</p>
<p><em>css를 수도 없이 작성하면서 몰랐던 사실.. 반성해..</em></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[클릭한 메뉴 활성화 유지하기]]></title>
            <link>https://velog.io/@ensun_p/js-%ED%81%B4%EB%A6%AD%ED%95%9C-%EB%A9%94%EB%89%B4-%ED%99%9C%EC%84%B1%ED%99%94-%EC%9C%A0%EC%A7%80%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@ensun_p/js-%ED%81%B4%EB%A6%AD%ED%95%9C-%EB%A9%94%EB%89%B4-%ED%99%9C%EC%84%B1%ED%99%94-%EC%9C%A0%EC%A7%80%ED%95%98%EA%B8%B0</guid>
            <pubDate>Fri, 27 Jan 2023 07:44:46 GMT</pubDate>
            <description><![CDATA[<pre><code class="language-javascript">const menu = document.querySelectorAll(&quot;.해당 class명&quot;);

     for(let i = 0; i &lt; menu.length; i++) {
          menu[i].addEventListener(&quot;click&quot;, act);
          function act(){
               for(let j = 0; j &lt; menu.length; j++){
                    menu[j].removeAttribute(&quot;class&quot;, &quot;on&quot;); // 추가하고자 하는 class명
               }
               this.setAttribute(&quot;class&quot;, &quot;on&quot;);
          }
     }</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[프로그래머스] javascript 풀이3]]></title>
            <link>https://velog.io/@ensun_p/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-javascript-%ED%92%80%EC%9D%B43</link>
            <guid>https://velog.io/@ensun_p/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-javascript-%ED%92%80%EC%9D%B43</guid>
            <pubDate>Wed, 18 Jan 2023 06:39:22 GMT</pubDate>
            <description><![CDATA[<h4 id="문제설명">문제설명</h4>
<p>이 문제에는 표준 입력으로 두 개의 정수 n과 m이 주어집니다. 별(*) 문자를 이용해 가로의 길이가 n, 세로의 길이가 m인 직사각형 형태를 출력해보세요.</p>
<h4 id="제한-조건">제한 조건</h4>
<ul>
<li>n과 m은 각각 1000 이하인 자연수입니다.</li>
</ul>
<h4 id="예시">예시</h4>
<p>입력</p>
<blockquote>
<p>5   3</p>
</blockquote>
<p>출력
<img src="https://velog.velcdn.com/images/ensun_p/post/368671f3-b91a-4e45-a5ae-897c4305a101/image.PNG" alt=""></p>
<h4 id="문제풀이">문제풀이</h4>
<pre><code class="language-javascript">
// 입력받은 숫자를 &#39;data&#39;에 받음
process.stdin.setEncoding(&quot;utf8&quot;);
process.stdin.on(&quot;data&quot;, (data) =&gt; {
  const n = data.split(&quot; &quot;);
  // data(입력받은 숫자)를 배열로 변경한다.
  const a = Number(n[0]),
    b = Number(n[1]);
  // a는 한줄에 별의 갯수, b는 몇줄을 출력할 것인지

  // 입력 값 b(3) 만큼 반복문을 돌린다.
  for (let i = 0; i &lt; b; i++) {
    // stars 변수를 초기화 해준다.
    let stars = &quot;&quot;;

    // 위 for문이 한번 돌아갈 때 마다 입력 값 a(5) 만큼 반복문을 돌린다.
    for (let j = 0; j &lt; a; j++) {
      // stars = stars + &quot;*&quot;
      stars += &quot;*&quot;;
    }

    // 콘솔창에 현재까지 저장된 stars 값을 찍는다. (*****)
    console.log(stars);

    // i가 b(3) 보다 작을 경우 맨 위로가 다시 for문을 실행한다.
  }
});</code></pre>
<p>별찍기는 대표적인 프로그래밍 문제 중 하나로 변수, 제어문을 이해하는 데 좋은 문제이다
보편적으로는 중첩 for문을 이용해 풀 수 있고, 자바스크립트의 경우 <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/repeat">repeat() 메서드-MDN</a>을 통해서도 풀 수 있지만 가장 보편적인 방법으로 풀어보았다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[프로그래머스] javascript - 풀이2]]></title>
            <link>https://velog.io/@ensun_p/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EC%86%8C%EC%88%98-%EA%B5%AC%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@ensun_p/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EC%86%8C%EC%88%98-%EA%B5%AC%ED%95%98%EA%B8%B0</guid>
            <pubDate>Wed, 18 Jan 2023 05:37:30 GMT</pubDate>
            <description><![CDATA[<h3 id="문제설명">문제설명</h3>
<p>주어진 숫자 중 3개의 수를 더했을 때 소수가 되는 경우의 개수를 구하려고 합니다. 숫자들이 들어있는 배열 nums가 매개변수로 주어질 때, nums에 있는 숫자들 중 서로 다른 3개를 골라 더했을 때 소수가 되는 경우의 개수를 return 하도록 solution 함수를 완성해주세요.</p>
<h3 id="제한사항">제한사항</h3>
<ul>
<li>nums에 들어있는 숫자의 개수는 3개 이상 50개 이하입니다.</li>
<li>nums의 각 원소는 1 이상 1,000 이하의 자연수이며, 중복된 숫자가 들어있지 않습니다.</li>
</ul>
<h3 id="입출력-예-설명">입출력 예 설명</h3>
<h4 id="입출력-예-1">입출력 예 #1</h4>
<p>[1,2,4]를 이용해서 7을 만들 수 있습니다.</p>
<h4 id="입출력-예-2">입출력 예 #2</h4>
<p>[1,2,4]를 이용해서 7을 만들 수 있습니다.
[1,4,6]을 이용해서 11을 만들 수 있습니다.
[2,4,7]을 이용해서 13을 만들 수 있습니다.
[4,6,7]을 이용해서 17을 만들 수 있습니다.</p>
<h3 id="문제풀이">문제풀이</h3>
<p>소수는 1과 자기 자신으로만 나누어지는 수를 의미한다.
먼저 소수인지 아닌지를 판별하는 함수를 하나 만들고, 전달받은 매개변수 값이 소수인지를 판별하기 위해서는 매개변수 값의 제곱근까지의 숫자들에 대해 나누어 떨어지는 값이 있다면 소수가 아니고, 없다면 소수라고 판단하여 반환한다.</p>
<p>매개변수 nums 배열에서 3가지 숫자를 더하여 새로운 수를 만들어내는 과정을 반복문을 사용하여 모든 숫자를 거치며 만들어낼 수 있는 숫자를 만들어내고, 만들어진 숫자를 미리 작성해둔 소수 판별 함수를 사용하여 소수인지 판별한다.</p>
<p>소수라면 answer의 값을 1씩 증가시켜준 뒤, 최종적으로 소수가 되는 경우의 개수를 반환한다.</p>
<h3 id="해답코드">해답코드</h3>
<pre><code class="language-javascript">function solution(nums) {
    let answer = 0;

    for (let i = 0; i &lt; nums.length; i++) {
        for (let j = i + 1; j &lt; nums.length; j++) {
            for (let k = j + 1; k &lt; nums.length; k++) {
                if (isPrime(nums[i] + nums[j] + nums[k])) {
                    answer++;
                }
            }
        }
    }

    return answer;
}

const isPrime = (n) =&gt; {
    for (let i = 2; i &lt;= Math.sqrt(n); i++) {
        if (n % i === 0) {
            return false;
        }
    }
    return true;
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[잘 이해하고 쓰면 좋을 flex]]></title>
            <link>https://velog.io/@ensun_p/%EC%9E%98-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B3%A0-%EC%93%B0%EB%A9%B4-%EC%A2%8B%EC%9D%84-flex</link>
            <guid>https://velog.io/@ensun_p/%EC%9E%98-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B3%A0-%EC%93%B0%EB%A9%B4-%EC%A2%8B%EC%9D%84-flex</guid>
            <pubDate>Thu, 12 Jan 2023 02:41:30 GMT</pubDate>
            <description><![CDATA[<h3 id="flex-items">flex-items</h3>
<p><code>order</code>
order의 숫자가 크면 클수록 정렬의 뒷 순서로 밀린다.
주의해야 할 점은 구조적으로는 바뀌지 않고 보여주는 순서만 바뀜</p>
<p><code>flex</code>
grow, shrink, basis의 단축속성이다.</p>
<p><code>flex-grow</code> 
기본 값은 0
기본 너비를 제외한 공백을 나누어 계산한다.
값이 클수록 값의 배수만큼 크기에서 상대적인 우위를 차지한다. 공백이 없을때에는 적용되지 X, 
그땐 _shrink_를 사용한다.</p>
<p>e.g. ( 1 / 2 / 1 ) =&gt; ( 25% : 50% : 25% )</p>
<p><code>flex-shrink</code> 
기본값은 1이다.
 값이 작을수록 커지며 flex-items들의 크기에서 숫자만큼의 우위를 차지한다.
감소의 유무(0,1)로 레이아웃을 잡는다. 줄어들지 않아야 하는 요소는 0으로 설정한다.</p>
<p><code>flex-basis</code> 
기본값은 auto이며 item의 기본 너비를 설정한다.
item들의 width 값이 100px라도 flex-basis를 통해 기본 너비를 단위만큼 만들어 비율을 설정할 수 있다.</p>
<p><code>align-self</code> 
개별 아이템의 수직 정렬을 만든다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Ajax (Asynchronous JavaScript and XML)]]></title>
            <link>https://velog.io/@ensun_p/Ajax-Asynchronous-JavaScript-and-XML</link>
            <guid>https://velog.io/@ensun_p/Ajax-Asynchronous-JavaScript-and-XML</guid>
            <pubDate>Thu, 08 Dec 2022 09:17:15 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>자바스크립트를 이용해서 비동기식으로 XML을 이용하여 서버와 통신하는 방식
최근에는 XML 보다  JSON을 더 많이 사용한다.
비동기식이란 여러가지 일이 동시적으로 발생한다는 뜻으로, 서버와 통신하는 동안 다른 작업을 할 수 있다는 의미</p>
</blockquote>
<h3 id="ajax의-동작방식">Ajax의 동작방식</h3>
<ol>
<li>요청 : 브라우저는 서버에 정보를 요청한다.  (브라우저는 Ajax요청을 담당하는 XMLHttpRequest 라는 객체를 구현하고 있다.)</li>
<li>응답 : 브라우저는 콘텐츠를 처리하여 페이지에 추가한다.</li>
</ol>
<h3 id="jquery를-이용한-ajax">jQuery를 이용한 Ajax</h3>
<p>jQuery에서 제공하는 $.ajax([settings])함수는 아래와 같은 구조로 구성되어 있다.</p>
<pre><code class="language-javascript">$.ajax ({
  // URL은 필수 요소이므로 반드시 구현해야 하는 Property입니다.
  url    : &quot;url&quot;, // 요청이 전송될 URL 주소
  type    : &quot;GET&quot;, // http 요청 방식 (default: ‘GET’)
  async : true,  // 요청 시 동기화 여부. 기본은 비동기(asynchronous) 요청 (default: true)
  cache : true,  // 캐시 여부
  timeout : 3000, // 요청 제한 시간 안에 완료되지 않으면 요청을 취소하거나 error 콜백을 호출.(단위: ms)
  data  : {key : value}, // 요청 시 포함되어질 데이터
  processData : true, // 데이터를 컨텐트 타입에 맞게 변환 여부
  contentType : &quot;application/json&quot;, // 요청 컨텐트 타입 
  dataType    : &quot;json&quot;, // 응답 데이터 형식 (명시하지 않을 경우 자동으로 추측)
  beforeSend  : function () {
    // XHR Header를 포함해서 HTTP Request를 하기전에 호출됩니다.
  },
  success : function(data, status, xhr) {
    // 정상적으로 응답 받았을 경우에는 success 콜백이 호출되게 됩니다.
    // 이 콜백 함수의 파라미터에서는 응답 바디, 응답 코드 그리고 XHR 헤더를 확인할 수 있습니다.
  },
  error    : function(xhr, status, error) {
        // 응답을 받지 못하였다거나 정상적인 응답이지만 데이터 형식을 확인할 수 없기 때문에 
        // error 콜백이 호출될 수 있습니다.
        // 예를 들어, dataType을 지정해서 응답 받을 데이터 형식을 지정하였지만,
        // 서버에서는 다른 데이터형식으로 응답하면  error 콜백이 호출되게 됩니다.
  },
  complete : function(xhr, status) {
    // success와 error 콜백이 호출된 후에 반드시 호출됩니다.
    // try - catch - finally의 finally 구문과 동일합니다.
  }
});</code></pre>
<h3 id="get과-post의-차이">GET과 POST의 차이</h3>
<p>데이터가 어디에 위치하는가에 있음. POST요청시에 URL에 파라미터가 보이지 않는 이유는 데이터가 요청 바디에 포함되기 때문.
그렇기 때문에 GET과 POST에 따라 데이터를 URL에 추가해야할지 요청 바디에 추가해야하는지를 알고 있어야 한다.</p>
<p><a href="https://developer.mozilla.org/ko/docs/Web/API/XMLHttpRequest">XMLHttpRequest</a>
<a href="https://api.jquery.com/jquery.ajax/">jQuery.ajax()</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[React State, re-rendering]]></title>
            <link>https://velog.io/@ensun_p/React-State-re-rendering</link>
            <guid>https://velog.io/@ensun_p/React-State-re-rendering</guid>
            <pubDate>Tue, 08 Nov 2022 08:07:24 GMT</pubDate>
            <description><![CDATA[<h3 id="state란">state란?</h3>
<p>데이터가 저장되는 곳</p>
<h3 id="버튼을-클릭하면-클릭수total-click를-화면에-렌더링하기">버튼을 클릭하면 클릭수(Total Click)를 화면에 렌더링하기</h3>
<h4 id="1-countup-함수-내에-render-함수를-넣어-버튼을-클릭할-때마다-렌더링-되도록-한다">1. countUp 함수 내에 render 함수를 넣어 버튼을 클릭할 때마다 렌더링 되도록 한다.</h4>
<pre><code class="language-javascript"> function countUp() {
    counter++;
    render();
}

function render() {
    ReactDOM.render(&lt;App /&gt;, root);
}</code></pre>
<p>이는 <code>렌더링할 요소가 많아질수록  매번 렌더링을 해줘야 한다는 불편함</code>이 있기 때문에 그다지 좋은 방법이 아니다.</p>
<h4 id="2-state를-사용한다">2. State를 사용한다.</h4>
<p>setCounter를 이용해 컴포넌트를 재생성하여 UI에 렌더 함수를 따로 추가하지 않아도 리렌더링이 가능하다.
<code>{State} 영역만 업데이트</code> 되기 때문에 보다 효율적인 방법이다.</p>
<pre><code class="language-javascript">function App() {
      const [counter, setCounter] = React.useState(0);
      const onClick = () =&gt; {
        setCounter(counter + 1);
        //리렌더링의 역할(컴포넌트 업데이트)
      };
      return (
        //컴포넌트
        &lt;div&gt;
          &lt;h3&gt; Total clicks : {counter} &lt;/h3&gt;
          &lt;button onClick={onClick}&gt; Click me &lt;/button&gt;
        &lt;/div&gt;
      );
    }

ReactDOM.render(&lt;App /&gt;, root);</code></pre>
<pre><code>&lt;h1 className=&quot;hi&quot;&gt; Super Converter &lt;/h1&gt;
&lt;label htmlFor=&quot;hours&quot;&gt; Hours &lt;/label&gt;</code></pre><p>JSX에서는 class(x) <code>clasName(O)</code> / for(x) <code>htmlFor(O)</code></p>
<pre><code>&lt;input
    value={flipped ? amount * 60 : amount}
    id=&quot;minutes&quot;
    placeholder=&quot;Minutes&quot;
    type=&quot;number&quot;
    onChange={onChange}
    disabled={flipped}
/&gt;
</code></pre><ul>
<li>삼항연산자 : flipped(default:false)가 true라면 flipped가 한 번 눌러졌다는 이야기, 즉 hours를 입력하고 그것을 분 단위로 바꿔야 한다.</li>
<li>disabled : true이면 해당 input에는 입력할 수 없다.</li>
<li>onChange : input에 변화가 생기면(사용자가 input에 값을 입력할 때) onChange 함수가 실행된다.</li>
<li>event.target.value를 얻게 되는데 바로 input의 value이다.</li>
<li>한 컴포넌트 안에서 다수의 컴포넌트를 렌더링할 수 있다.</li>
<li><strong>컴포넌트는 무조건 대문자로 시작해야 한다</strong> 잊지말기 </li>
</ul>
<pre><code class="language-javascript">&lt;body&gt;
    &lt;div id=&quot;root&quot;&gt;&lt;/div&gt;
&lt;/body&gt;
    &lt;script crossorigin src=&quot;https://unpkg.com/react@16/umd/react.production.min.js&quot;&gt;&lt;/script&gt;
    &lt;script crossorigin src=&quot;https://unpkg.com/react-dom@16/umd/react-dom.production.min.js&quot;&gt;&lt;/script&gt;
    &lt;script src=&quot;https://unpkg.com/@babel/standalone/babel.min.js&quot;&gt;&lt;/script&gt;
    &lt;script type=&quot;text/babel&quot;&gt;
        const root = document.getElementById(&quot;root&quot;);
        function App() {
            const [amount, setAmount] = React.useState(0);
            const [flipped, setFlipped] = React.useState(false);
            const onChange = (event) =&gt; {
                setAmount(event.target.value);
            };
            const reset = () =&gt; setAmount(0);
            const onFlip = () =&gt; {
                reset();
                setFlipped((current) =&gt; !current);
            }
            return (
                &lt;div&gt;
                    &lt;h1 className=&quot;hi&quot;&gt;Super Converter&lt;/h1&gt;
                    &lt;div&gt;
                        &lt;label htmlFor=&quot;minutes&quot;&gt;Minutes&lt;/label&gt;
                        &lt;input
                            value={flipped ? amount * 60 : amount}
                            id=&quot;minutes&quot;
                            placeholder=&quot;Minutes&quot; 
                            type=&quot;number&quot;
                            onChange={onChange}
                            disabled={flipped}
                        /&gt;
                    &lt;/div&gt;
                    &lt;div&gt;
                        &lt;label htmlFor=&quot;hours&quot;&gt;Hours&lt;/label&gt;
                        &lt;input
                            value={flipped ? amount : Math.round(amount / 60)}
                            id=&quot;hours&quot;
                            placeholder=&quot;Hours&quot;
                            type=&quot;number&quot;
                            disabled={!flipped}
                            onChange={onChange}
                        /&gt;
                    &lt;/div&gt;
                    &lt;button onClick={reset}&gt;Reset&lt;/button&gt;
                    &lt;button onClick={onFlip}&gt;Flip&lt;/button&gt;
                &lt;/div&gt;
            );
        }
        ReactDOM.render(&lt;App/&gt;, root);
    &lt;/script&gt;</code></pre>
<p><a href="https://nomadcoders.co/react-for-beginners/lectures/3272">노마드코더-react-basic</a>
<a href="https://ko.reactjs.org/docs/state-and-lifecycle.html">리액트 공식문서</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[React basic]]></title>
            <link>https://velog.io/@ensun_p/React-basic-01</link>
            <guid>https://velog.io/@ensun_p/React-basic-01</guid>
            <pubDate>Mon, 07 Nov 2022 07:15:01 GMT</pubDate>
            <description><![CDATA[<h3 id="01-react-js-reactdom-코드를-import하기">01. React JS, ReactDOM 코드를 import하기</h3>
<p>React 파일은 컴포넌트를 담당.
React DOM 파일은 실제 DOM에 렌더링을 담당.</p>
<pre><code>&lt;script crossorigin src=&quot;https://unpkg.com/react@16/umd/react.production.min.js&quot;&gt;&lt;/script&gt;
&lt;script crossorigin src=&quot;https://unpkg.com/react-dom@16/umd/react-dom.production.min.js&quot;&gt;&lt;/script&gt;</code></pre><ul>
<li>body 이후에 위치</li>
</ul>
<h3 id="02-reactdomrender">02. ReactDOM.render();</h3>
<p>React element들을 html내부에서 보여줌</p>
<pre><code class="language-javascript">ReactDOM.render(&lt;Container/&gt;, root);</code></pre>
<h3 id="03-jsx파일-babel을-이용해-변환해주기">03. JSX파일 babel을 이용해 변환해주기</h3>
<p><strong>React JSX</strong>: JavaScript언어의 확장. JavaScript에서 HTML형식을 그대로 사용할 수 있게 하는 등 XML과 같은 문법을 native JavaScript로 변환해줌.
<strong>Babel</strong>: 자바스크립트 컴파일러. 여러가지 브라우저를 지원하기 위해 ES6로 작성된 코드를 ES5로 변환해줌.</p>
<pre><code>&lt;script src=&quot;https://unpkg.com/@babel/standalone/babel.min.js&quot;&gt;&lt;/script&gt;</code></pre><p>이때, 우리가 코드를 넣는 script파일 type을 <code>text/babel</code>로 설정해줘야 에러가 나지 않는다.</p>
<h3 id="04-컴포넌트의-첫글자는-무조건-대문자">04. 컴포넌트의 첫글자는 무조건 대문자</h3>
<p>컴포넌트는 자바스크립트 클래스. 참조 시 &lt;컴포넌트명/&gt;형식으로 쓰임. 소문자로 쓰면 div나 span 같은 HTML 태그로 해석되기 때문에 반드시 대문자로 시작해야함.</p>
<p>TIL</p>
<pre><code class="language-javascript">&lt;body&gt;
    &lt;div id=&quot;root&quot;&gt;&lt;/div&gt;
&lt;/body&gt;
    &lt;script crossorigin src=&quot;https://unpkg.com/react@16/umd/react.production.min.js&quot;&gt;&lt;/script&gt;
    &lt;script crossorigin src=&quot;https://unpkg.com/react-dom@16/umd/react-dom.production.min.js&quot;&gt;&lt;/script&gt;
    &lt;script src=&quot;https://unpkg.com/@babel/standalone/babel.min.js&quot;&gt;&lt;/script&gt;
    &lt;script type=&quot;text/babel&quot;&gt;
        const root = document.getElementById(&quot;root&quot;);
        function Title() {
            return (
                &lt;h3 id=&quot;title&quot; onMouseEnter={() =&gt; console.log(&quot;mouse enter&quot;)}&gt;
                Hello i&#39;m a span
                &lt;/h3&gt;
            );
        }
        const Button = () =&gt; (
            &lt;button 
            style={{backgroundColor: &quot;tomato&quot;,
        }}
            onClick={() =&gt; console.log(&quot;im clicked&quot;)}
        &gt;
            Click me
            &lt;/button&gt;
        );
        const Container = () =&gt; ( // 이 부호는 function하고 괄호 열고 return 하는 것과 같은 의미
            &lt;div&gt;
                &lt;Title/&gt;
                &lt;Button/&gt;    
            &lt;/div&gt;
        );
        ReactDOM.render(&lt;Container/&gt;, root);
    &lt;/script&gt;</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[왓챠 클론코딩 (풀페이지 스크롤)]]></title>
            <link>https://velog.io/@ensun_p/%EC%99%93%EC%B1%A0-%ED%81%B4%EB%A1%A0%EC%BD%94%EB%94%A9-%ED%92%80%ED%8E%98%EC%9D%B4%EC%A7%80-%EC%8A%A4%ED%81%AC%EB%A1%A4</link>
            <guid>https://velog.io/@ensun_p/%EC%99%93%EC%B1%A0-%ED%81%B4%EB%A1%A0%EC%BD%94%EB%94%A9-%ED%92%80%ED%8E%98%EC%9D%B4%EC%A7%80-%EC%8A%A4%ED%81%AC%EB%A1%A4</guid>
            <pubDate>Mon, 31 Oct 2022 07:20:25 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/ensun_p/post/b67467cb-96d9-4002-afbe-51f079e5ea97/image.gif" alt=""></p>
<p>플러그인을 쓰지 않고 풀페이지 효과 구현해보기</p>
<pre><code class="language-javascript">window.addEventListener(&quot;wheel&quot;, function(e){
    e.preventDefault();
},{passive : false});
// 기본 이벤트 제거

var $html = $(&quot;html&quot;);
var page = 1;
var lastPage = $(&quot;.content&quot;).length;

$html.animate({scrollTop:0},10);
// 페이지 선언

$(window).on(&quot;wheel&quot;, function(e){

    if($html.is(&quot;:animated&quot;)) return;

    if(e.originalEvent.deltaY &gt; 0){
        if(page== lastPage) return;

        page++;
    }else if(e.originalEvent.deltaY &lt; 0){
        if(page == 1) return;

        page--;
    }
    var posTop = (page-1) * $(window).height();

    $html.animate({scrollTop : posTop});
  // 마우스 휠을 굴렸을 때 이벤트 추가

    $(window).scroll(function(){
        var scroll = $(window).scrollTop();
        if (scroll &gt; 1) {
          $(&quot;header&quot;).css(&quot;background&quot; , &quot;#000000&quot;);
        }
        else{
          $(&quot;header&quot;).css(&quot;background&quot; , &quot;transparent&quot;);   
        }
      })
 // 스크롤 하면 헤더 색상 변경 
});</code></pre>
<blockquote>
<p>추가해야 할 것</p>
</blockquote>
<ul>
<li>스크롤 될 때마다 active되는 pagenation</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[CSS | ellipsis 넘치는 텍스트 줄이기]]></title>
            <link>https://velog.io/@ensun_p/CSS-ellipsis-%EB%84%98%EC%B9%98%EB%8A%94-%ED%85%8D%EC%8A%A4%ED%8A%B8-%EC%A4%84%EC%9D%B4%EA%B8%B0</link>
            <guid>https://velog.io/@ensun_p/CSS-ellipsis-%EB%84%98%EC%B9%98%EB%8A%94-%ED%85%8D%EC%8A%A4%ED%8A%B8-%EC%A4%84%EC%9D%B4%EA%B8%B0</guid>
            <pubDate>Fri, 14 Oct 2022 03:29:11 GMT</pubDate>
            <description><![CDATA[<p>게시판 리스트 박스, 혹은 후기 박스를 만들면서 말 줄임표를 쓰거나 더보기 기능을
구현해야 하는 경우가 잦았다.
자주 구글링하게 되어 그 CSS 속성에 대해 정리해본다.</p>
<pre><code class="language-css">.reviewBoxTtl {
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
    word-break: break-all;
}</code></pre>
<p><code>overflow 속성은 hidden</code>으로 준다.
지금은 부모의 width값이 inherit되어 보이지 않지만 당연히 줄이고자 하는 div에
width property를 줘야 원하는 만큼 글을 줄이고 말 줄임표가 나오게 된다.
ellipsis 속성은 가장 간단하게 긴 글을 줄일 수 있는 방법이지만 1줄로 줄이는 것밖에는 되지 않는다.</p>
<p>여러줄로 줄이기 위해 다음과 같이 적용해보았다.</p>
<pre><code class="language-css">.reviewBoxTtl {
    max-height: 120px;
    overflow: hidden;
    white-space: normal;
    display: -webkit-box;
    -webkit-line-clamp: 4; // 글의 최대 라인수를 결정
    -webkit-box-orient: vertical;
    word-break: break-all;
}</code></pre>
<p><code>white-space는 normal</code>로 준다.
여기서 -webkit-line-clamp는 글의 최대 행 숫자이다. 
4로 설정하면 4줄까지만 나오고 말줄임표로 마무리 된다.</p>
<blockquote>
<p><code>-webkit</code>은 크로스브라우징을 위해 필요한데,
<code>-webkit</code>은 구글, 사파리 브라우저에서 사용 가능하다
적용할 때 브라우저 지원 범위를 확인하고 사용하기!</p>
</blockquote>
<p><strong>마치면서</strong></p>
<p><code>text-overflow</code> 속성은 <code>display</code> 속성이 블럭 형태인 경우에만 적용된다.
즉, inline의 경우는 적용되지 않음.
이를 적용하기 위해서는 반드시 아래와 같이 display를 <code>block</code> 또는 <code>inline-block</code>과 같이 설정해야만 적상적으로 작동한다는 것을 명심하자</p>
<p><em>구글링 그만하고 외워버리자..</em></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[element.scrollIntoView();]]></title>
            <link>https://velog.io/@ensun_p/element.scrollIntoView</link>
            <guid>https://velog.io/@ensun_p/element.scrollIntoView</guid>
            <pubDate>Fri, 14 Oct 2022 02:14:33 GMT</pubDate>
            <description><![CDATA[<pre><code class="language-html">    &lt;ul class=&quot;menu&quot;&gt;
        &lt;li data-link=&quot;#section1&quot;&gt;menu1&lt;/li&gt;
        &lt;li data-link=&quot;#section2&quot;&gt;menu2&lt;/li&gt;
        &lt;li data-link=&quot;#section3&quot;&gt;menu3&lt;/li&gt;
        &lt;li data-link=&quot;#section4&quot;&gt;menu4&lt;/li&gt;
    &lt;/ul&gt;
    &lt;div class=&quot;container&quot;&gt;
        &lt;div id=&quot;section1&quot; class=&quot;content&quot;&gt;&lt;/div&gt;
        &lt;div id=&quot;section2&quot; class=&quot;content&quot;&gt;&lt;/div&gt;
        &lt;div id=&quot;section3&quot; class=&quot;content&quot;&gt;&lt;/div&gt;
        &lt;div id=&quot;section4&quot; class=&quot;content&quot;&gt;&lt;/div&gt;
    &lt;/div&gt;</code></pre>
<pre><code class="language-javascript">        document.querySelector(&#39;.menu&#39;).addEventListener(&#39;click&#39;, e =&gt; {
            if(e.target.nodeName === &#39;LI&#39;) {
                let id_value = e.target.dataset.link;
                document.querySelector(id_value).scrollIntoView({behavior : &#39;smooth&#39;});
            }
        });</code></pre>
<p>괄호안에 {behavior : &#39;smooth&#39;} 코드 추가시
스크롤 이동이 ease-in-out과 같이 부드러워진다</p>
]]></description>
        </item>
    </channel>
</rss>