<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>hwa_haha.log</title>
        <link>https://velog.io/</link>
        <description>개발자로 차근차근</description>
        <lastBuildDate>Tue, 04 Jun 2024 15:30:50 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <copyright>Copyright (C) 2019. hwa_haha.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/hwa_haha" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[브라우저 구성요소 ]]></title>
            <link>https://velog.io/@hwa_haha/%EB%B8%8C%EB%9D%BC%EC%9A%B0%EC%A0%80-%EA%B5%AC%EC%84%B1%EC%9A%94%EC%86%8C</link>
            <guid>https://velog.io/@hwa_haha/%EB%B8%8C%EB%9D%BC%EC%9A%B0%EC%A0%80-%EA%B5%AC%EC%84%B1%EC%9A%94%EC%86%8C</guid>
            <pubDate>Tue, 04 Jun 2024 15:30:50 GMT</pubDate>
            <description><![CDATA[<h2 id="브라우저-구성요소">브라우저 구성요소</h2>
<p>사용자 인터페이스 : 주소표시줄, 이전/ 다음 버튼, 홈버튼, 새로고침/정지 버튼 등 요청 한 페이지를 보여주는 창 외에 사용자가 컨트롤 할수 있는 부분
브라우저 엔진: 사용자 인터페이스와 렌더링 엔진 사이에 동작을 제어한다. (서버로부터 가면 네트워트통신 낭비)
자료저장소에 캐싱기법을 사용한다. 
렌더링 엔진: URI 를 브라우저 엔진에게 받아서 server에게 요청한다. 서버로부터 받은 URI에 해당하는 데이터를 받아 파후 렌더링 한다 
통신: 렌더링 엔진으로부터 HTTP 요청등을 받아서 네트워크 처리후 응답을 전달한다.
자바스크립트 해석기: 자바 스크립트를 파싱한다 (크롬 v8)
자료저장소: 
UI백엔드 : 랜더 트리를 브라우저에 그리는 역할을 담당한다. </p>
<h2 id="csrclient-side-redering">CSR(client Side Redering)</h2>
<p>렌더링 주체가 클라이언트
클라이언트 (브라우저)</p>
<ul>
<li><p>장점
한 번만 로딩되면 빠른 UX제공
서버 부하적다</p>
</li>
<li><p>단점
페이지 로딩 시간 길다.
자바스크립트 활성화 필수
SEO최적화 힘듦.
보안에 취약</p>
</li>
</ul>
<h2 id="ssgstatic-site-generation">SSG(Static Site Generation)</h2>
<p>렌더링하는 주체자가 서버
빌드할때 렌더링 </p>
<ul>
<li><p>장점
페이지 로딩시간 빠름
자바스크립트 필요없음
SEO 최적화에 좋음
보안이 뛰어남
CDN에 캐시가 됨</p>
</li>
<li><p>단점
데이터가 정적임
사용자별 정보제공 어려움</p>
</li>
</ul>
<h2 id="ssrserver-side-redering">SSR(Server Side Redering)</h2>
<p>렌더링 주체가 서버
요청시 렌더링 됨</p>
<ul>
<li><p>장점
초기 진입 시 빠름
SEO 향상</p>
</li>
<li><p>단점 
화면 깜빡임 현상</p>
</li>
</ul>
<p>NEXT.js에서 하이브리드에서 사용할 수 있음.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[프론트엔드 개념]]></title>
            <link>https://velog.io/@hwa_haha/%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C-%EA%B0%9C%EB%85%90</link>
            <guid>https://velog.io/@hwa_haha/%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C-%EA%B0%9C%EB%85%90</guid>
            <pubDate>Tue, 04 Jun 2024 14:52:41 GMT</pubDate>
            <description><![CDATA[<h2 id="debounce와-throttle의-개념">debounce와 throttle의 개념</h2>
<p>일정 시간 동안 동일한 이벤트가 여러번 발생했을 떄 이벤트 핸들링 횟수를 1번으로 제한하는 기술
debounce는 키보드입력 이벤트처럼 짧은 시간내에 집약적으로 호출되는 이벤트, 마지막 입력
throttle는 첫 이벤트만 처리, 핸들링 로직에 나머지 입력값이 누락되는 이슈 발생할 수 있음.
이벤트에 따른 레이아웃 변경과 같은, 즉각적인 피드백이 필요한 경우 사용.</p>
<h2 id="dom의-개념">DOM의 개념</h2>
<p>마크업 언어로 작성된 문서를 프로그래밍 언어가 조작할 수 있도록 하는 인터페이스 
**마크업 언어란 태그 등을 이용하여 문서나 데이터의 구조를 명기하는 언어의 한 가지</p>
<p>DOM은 왜 필요한가요?
마크업 언어에는 자바스크립트가 element에 접근 가능한 인터페이스가 없기 때문
DOM을 통해 어떤 동작을 할 수 있는지 예를 들어주세요.
Element에 이벤트 핸들러를 추가하거나, Element를 문서에 추가, 제거, 수정할 수 있음
DOM은 왜 계층적 구조로 표현하는지 설명해주세요.
노드들 간의 관계를 명확히 정의할 수 있고, Event 처리에 유리한 구조이기 때문
이벤트 버블링:이벤트가 발생한 요소로부터 상위 요소로 이벤트가 전파되는 과정
이벤트 캡쳐링: 상위요소에서 발생한 이벤트가 하위요소로 전파되는 과정</p>
<h2 id="promise와-async-await의-개념">Promise와 async-await의 개념</h2>
<p>Promise란 비동기 연산의 상태를 나타내는 객체
비동기를 처리하는 함수에 성공 콜백과 실패 콜백을 각각 넘겨 처리하였음
그래서 코드의 가족성을 크게 저하시키는 콜백지옥이 문제가 생김. 
async-await란 Promise의 완료를 기다리기 위한 문법
fetch 동작이 완료될 때까지 이부분 실행이 안되면 에러핸들링은 try catch 블록에서 하며, 실행 흐름을 고려하여 적재적소에 써야함. 
순차적으로 실행될 필요가 없는 비동기 연산은 Promise.all을 사용하는 것이 적절함.</p>
<h2 id="key에-배열-index를-사용하면-안되는-이유">key에 배열 index를 사용하면 안되는 이유</h2>
<p>key는 리스트를 매핑하여 동일한 컴포넌트를 여러개 렌더링할때 각 컴포넌트에 전달되는 고유한 값입니다. 
재조정 단계에서 각Node의 key값을 비교하여 추가/ 삭제/ 순서가 변경된 Node를 식별하기 위함.
필요한 리랜더링을 수행하기 위해 사용합니다. 
컴포넌트의 순서가 변경되어도 동일한 key값이 유지되기 때문에 key값의 순서는 이전과 동일함으로 리랜더링 대상으로 식별되지 않는다. 
고유한 key값이 없는 경우 대체 방법은 다른 props를 적절히 조합하여 고유한 값을 만들거나 랜덤한 UUID를 사용(메모리 많이차지) </p>
<h2 id="비동기-함수와-callback-함수-그리고-event-loop에-대해-설명하시오">비동기 함수와 Callback 함수, 그리고 Event Loop에 대해 설명하시오</h2>
<p>자바스크립트는 싱글스레드 이다. 
처리시간이 긴 작업으로 인한 스레드 블락 이슈가 생겨 스레드 블락없이 처리할 방법이 필요함
자바스크립트는 메인스레드에서 처리안한다. 노드는 libuv라는 c++라이브러리에서 브라우저에서는 fetch와 같은 웹 api를 통해 백그라운드에서 처리한다. </p>
<p>자바스크립트와 자바스크립트 실행환경으로 구분되어 지는데 
자바스크립트 엔진, </p>
<p>백그라운드 (비동기 I/O매니저)</p>
<p>메인쓰레드에서 요청이 들어오면 백그라운드로 보내고 결과를 알기위해 콜백함수를 사용하고 보통 마지막 인자에 전달하게끔 되어 있다. </p>
<p>비동기 작업이 완료되엇을때 메인 쓰레드에서 실행할 함수는 callback함수이다. 
콜백함수는 잠시 백그라운드로 전출을 보낸건데 요청이 많아지면 시기를 정하는 체계가 필요하다.
이 역할을 담당하는 것이 바로 이벤트 루프입니당.
메인스레드에서 실행하는 모든 함수들은 call stack이라는 공간에 LIFO(Last In First Out)형태로 차곡차곡 쌓이게 됩니다. 네트워크 요청이 들어오면 바로 백그라운드로 넘겨지고 이벤트가 처리되면 콜백함수가 이벤트 큐에 FIFO(First In Fisrt Out) 구조로 쌓이게 됩니다. 
이벤트루프는 이벤트 큐에서 콜 스텍으로 콜백함수를 이동시켜주는 역할을 합니다. 
이벤트는 루프는 콜 스택이 완전히 비어져잇는지 호가인하고 푸시해주는 역할을 합니다. 이벤트 큐와 콜스텍 사이의 신호등이라고 할 수 있다. </p>
<ol>
<li>모든 함수 호출은 콜스택에  LIFO구조로 쌓인다.</li>
<li>비동기 함수는 콜스택에 들어오는 즉시 백그라운드로 보내진다</li>
<li>백그라운드에서 처리가 완료되면 콜스택 함수는 이벤트큐에 FIFO구조로 쌓인다.</li>
<li>이벤트 루프는 콜스택이 비어있는지 수시로 확인한다.</li>
<li>콜 스택이 비어있을 경우, 이벤트 루프는 이벤트 큐에서 콜백함수를 시프트한다.</li>
<li>시프트된 콜백 함수는 콜스택으로 옮겨진후 실행된다. </li>
</ol>
<h2 id="type-과-interface의-차이">Type 과 Interface의 차이</h2>
<p>둘다 섞어서 사용해도 좋다 </p>
<pre><code class="language-js">// 언제나 객체형태만 된다. 
interface User{
    name: string;
      age: number;
}
// 기본적인 타입, 유연하다. 상속할떄 &amp;을 붙인다 
type UserName = string;
      age: number;
}</code></pre>
<p>보안상의 이유도 필드에서 제외하고싶을떈 Omit
인터페이스는 같은 이름이생기면 심각한 에러를 야기할수 있다. 에러캐칭이 안됨. </p>
<p>특정한 객체의 타입을 선언할떄 객체 (oop)
그외에는 단순한 형태는 타입으로 선언 </p>
<h2 id="execution-context실행-컨텍스트-정의와-종류">Execution Context(실행 컨텍스트) 정의와 종류</h2>
<p>자바가 실행할떄 글로벌 실행 컨텍스트를 가지고 있음 </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[React 개념모음 ]]></title>
            <link>https://velog.io/@hwa_haha/React</link>
            <guid>https://velog.io/@hwa_haha/React</guid>
            <pubDate>Wed, 29 May 2024 05:54:56 GMT</pubDate>
            <description><![CDATA[<h2 id="🎈컴포넌트-최적화하기">🎈컴포넌트 최적화하기</h2>
<h3 id="📌reactmemo">📌React.memo</h3>
<p>고체 컴포넌트 
Prop Check를 통해 변화가 있는지를 체크하여 렌더링을 결정하여 재사용한다.
오직 Props 변화에만 의존하는 최적화 방법입니다. 
너무 무분별하게사용하면 메모리를 너무 많이 사용할수가 있다.</p>
<p>1) 컴포넌트가 같은 Props로 자주 렌더링 될때
2) 컴포넌트가 렌더링이 될떄마다 복잡한 로직을 처리해야될때</p>
<p>useState UseReducer useContext에서는 상태와 관련되면 다시 랜더링됨.
useMemo / useCallback</p>
<h3 id="📌reactfragment-">📌React.Fragment &lt;&gt;&lt;/&gt;</h3>
<p>엘리먼트들은 반드시 단 하나의 최상위 태그로 묶여있어야한다.
key props밖에 받지를 못한다. 
걍 의미없는 div가 많아지면 dom구조에문제가 될수 있어 React.Fragmen를 사용한다. 
제일 유용하게 사용될때는 css, 테이블구조,배열 에서 사용할때 div는 안되니깐 </p>
<h3 id="📌listkey의-중요성">📌List,key의 중요성</h3>
<p>list를 반환할때 props에 key를 넣어주어야 함
안그러면 어떤게 바꼇는지 몰라서 전부다 바꿔주엇는데,key값을 주면서 해당 항목만 변경 됨.
index값을 key로 주는건 지양해야함 동적인 항목은 안정적인 key값을 넣어줘야함 
만약에 중복된 key를 넣어야 하면 길이에 1 더하고 아이디를 문자열로 만든다.</p>
<h3 id="📌forwardref">📌ForwardRef</h3>
<p>부모컴포넌트로부터 자녀컴포넌트가 Ref를 전달받을수 있다.
하지만 ForwardRef를 사용해서 자녀 컴포넌트에 접근한다는 것은 캡슐화에 대한 장점을 없애버릴수있다.
그래서  focus, 애니메이션 관리할때 외에는 사용하지않는게 좋을것 같다. </p>
<pre><code class="language-js">//16.3버전이후부터 가능하다.
const testInput = (props,ref)=&gt; {
    return &lt;input ref={ref} /&gt;;
});
export default forwardRef(testInput);

////16.3버전이전이지만 권장하지않아
const testInput = ({inputRef})=&gt; {
    return &lt;input ref={inputRef} /&gt;;
});
export default testInput;</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[배열함수 ]]></title>
            <link>https://velog.io/@hwa_haha/%EB%B0%B0%EC%97%B4%ED%95%A8%EC%88%98</link>
            <guid>https://velog.io/@hwa_haha/%EB%B0%B0%EC%97%B4%ED%95%A8%EC%88%98</guid>
            <pubDate>Tue, 28 May 2024 13:43:15 GMT</pubDate>
            <description><![CDATA[<h3 id="📌find">📌find()</h3>
<p>배열에서 특정 조건을 만족하는 요소를 찾고싶을때 사용하는 함수이다. </p>
<pre><code class="language-javascript">const drinks = [
  { name:&#39;coke&#39;,price:100},
  { name:&#39;juice&#39;,price:500},
  { name:&#39;milk&#39;,price:200},
  { name:&#39;beer&#39;,price:800},
];

//find는 인자로 콜백함수를 하나 전달받아서 item에 넣어준다.
const item = drinks.find((drink, index)=&gt; {
    // 원하는 조건 : 가격이 200원인 음료 콜백함. 배열안을 돌면서 요소 마다 한번씩 콜백함수 실행
  if(drink.price === 200 &amp;&amp; index ===2){
    return true
  }
  return false
}) 
// 원하는 조건없으면 undefined나옴
console.log(item);</code></pre>
<h3 id="📌findindex">📌findIndex()</h3>
<p>배열에서 특정 조건을 만족하는 요소의 인덱스 값을 반환해주는 함수이다. </p>
<pre><code class="language-javascript">const drinks = [
  { name:&#39;coke&#39;,price:100},
  { name:&#39;juice&#39;,price:500},
  { name:&#39;milk&#39;,price:200},
  { name:&#39;beer&#39;,price:800},
];

const item = drinks.findIndex((drink, index)=&gt; {
  if(drink.price === 200){
    return true
  }
  return false
}) 
// 원하는 조건없으면 -1을 반환합니다.
console.log(item);</code></pre>
<h3 id="📌some">📌some()</h3>
<p>배열안에 특정조건을 만족하는 요소가 1개라도 있는지 확인할수 있는 함수이다. </p>
<pre><code class="language-javascript">const drinks = [
  { name:&#39;coke&#39;,price:100},
  { name:&#39;juice&#39;,price:500},
  { name:&#39;milk&#39;,price:200},
  { name:&#39;beer&#39;,price:800},
];

const doesExist = drinks.some((drink)=&gt; {
  if(drink.price &gt; 600){
    return true
  }
  return false
}) 
// 한개라도 있으면 참 true , 거짓 false
console.log(doesExist);</code></pre>
<h3 id="📌every">📌every()</h3>
<p>배열안에 있는 모든 요소들이 특정조건을 만족하는지 확인하는 함수이다. </p>
<pre><code class="language-javascript">const drinks = [
  { name:&#39;coke&#39;,price:100},
  { name:&#39;juice&#39;,price:500},
  { name:&#39;milk&#39;,price:200},
  { name:&#39;beer&#39;,price:800},
];

const isOver = drinks.every((drink)=&gt; {
  if(drink.price &gt; 50){
    return true
  }
  return false
}) 
// 다 만족해야 참 true , 거짓 false
console.log(isOver);</code></pre>
<h3 id="📌filter-">📌filter ()</h3>
<p>배열에서 특정 조건을 만족하는 요소들만 쏙뺴서 새로운 배열을 만들어주는 함수이다.  </p>
<pre><code class="language-javascript">const drinks = [
  { name:&#39;coke&#39;,price:100},
  { name:&#39;juice&#39;,price:500},
  { name:&#39;milk&#39;,price:200},
  { name:&#39;beer&#39;,price:800},
];

const cheapDrinks = drinks.filter((drink)=&gt; {
  if(drink.price &lt;= 20){
    return true
  }
  return false
}) 
// 원본배열을 건들이지않고 새로운 배열을 만든다는것
console.log(cheapDrinks);</code></pre>
<h3 id="📌map-">📌map ()</h3>
<p>원본배열을 요소들을 다른 형태로 변환하여 새로운 배열로 담아주는 함수이다.  </p>
<pre><code class="language-javascript">const drinks = [
  { name:&#39;coke&#39;,price:100},
  { name:&#39;juice&#39;,price:500},
  { name:&#39;milk&#39;,price:200},
  { name:&#39;beer&#39;,price:800},
];

// 원본배열을 건들이지않고 새로운 배열을 만든다.
const priceTags = drinks.map((drink)=&gt; {
  //요소를 어떤 식으로 변환할건지 적어준다
  return `${drinks.name}:${drinks.price}원`;
}) 

console.log(priceTags);</code></pre>
<h3 id="📌reduce-">📌reduce ()</h3>
<p>배열안에 있는 모든 요소들을 이용해서 하나의 최종 값으로 만들때 사용하는 함수이다.</p>
<pre><code class="language-javascript">const numbers = [1, 2, 3, 4];

 //forEach
let total = 0;

numbers.forEach(number =&gt; {
    total = total + number;
});

 //reduce
//accumulator 현재까지 누적됨 값 total역활
//currentValue 현재확인되는 요소 
const total = numbers.redece((accumulator, currentValue)=&gt;{
    return accumulator + currentValue
}, 0);
</code></pre>
<pre><code class="language-javascript">const numbers = [10, 4, 2, 8];

 //forEach
let samllest = numbers.reduce((accumulator, currentValue) =&gt; {
    if(accumulator&gt;currentValue){
      return currentValue;
    }
      return accumulator;
});

console.log(samllest);


let sumItem = cart.reduce((accumulator, currentValue) =&gt; {
      return accumulator + currentValue.price;
},0);
</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[jQuery]jQuery를 사용했던 이유]]></title>
            <link>https://velog.io/@hwa_haha/jQueryjQuery%EB%A5%BC-%EC%82%AC%EC%9A%A9%ED%96%88%EB%8D%98-%EC%9D%B4%EC%9C%A0</link>
            <guid>https://velog.io/@hwa_haha/jQueryjQuery%EB%A5%BC-%EC%82%AC%EC%9A%A9%ED%96%88%EB%8D%98-%EC%9D%B4%EC%9C%A0</guid>
            <pubDate>Tue, 28 May 2024 10:40:33 GMT</pubDate>
            <description><![CDATA[<h2 id="jquery">jQuery</h2>
<p>jquery가 붐이 였던 이유는 2006년에는 js가 안예쁘고 브라우저 호환성도어려웟다 간단하게 말하자면 제이쿼리가 좋은 라이브러리이기보다는 임시방편으로 사용했던 것이다. 
제이쿼리는 그당시에 DOM을 쉽게다를수 있고, 오류안나고, 브라우저 걱정안해도되고, 코드도 이뻣다
그러면서 연관된 유료/무료 라이브러리가 생기게 되었고, ajax로 비동기호출이 편리해졋다.</p>
<p>하지만 현재는 js가 제이쿼리가생겻던 원인들을 다 보완하였다 코드도 이뻐지게 되엇고 크로스 브라우징 이슈도 적어졌고,제이쿼리는 기존코드를 래핑해서 새롭게 만든 패키지로 래필리 지나치게 많고 무겁다. 
현재 버츄얼 돔의 인기로 리얼돔을 직접 조작할 필요가 없어졋고 대부분 기능은 바닐라js나 ts등으로 똑같이 구현할 수 있다. </p>
<h2 id="제이쿼리를-바닐라js로-옮기게-된-이유">제이쿼리를 바닐라js로 옮기게 된 이유</h2>
<h3 id="직접적인-dom-조작-최소화">직접적인 DOM 조작 최소화</h3>
<p>DOM 조작은 비교적 비용이 많이 드는 작업입니다. DOM을 변경할 때마다 브라우저는 렌더 트리를 다시 계산하고, 레이아웃을 재조정하며, 화면에 다시 그려야 합니다. 이러한 과정은 리플로우(reflow)와 리페인트(repaint)를 발생시키며, 특히 많은 요소를 자주 변경할 경우 성능 저하가 심해질 수 있습니다.
렌더링 엔진이 이를 처리하느라 성능이 떨어질 수 있습니다.
바닐라 JavaScript를 사용하면 직접적인 DOM 조작을 최소화하고, 더 나은 구조화와 분리된 로직을 유지할 수 있습니다. 이는 코드의 유지보수성과 테스트 용이성을 향상시킵니다.
반복적인 DOM 접근,불필요한 재계산</p>
<h3 id="메모리차지무겁다">메모리차지(무겁다)</h3>
<ul>
<li>기본적인 jQuery 파일의 크기가 크기 때문에 모바일 네트워크(특히 3G나 느린 네트워크)에서 로딩 속도가 느려질 수 있습니다.</li>
<li>$를 쓰는게 메모리와 CPU를 잡아먹습니다. 그리고 jQuery.data같은 함수는 DOM에 직접 읽고 쓰는 기능을 제공하는데, 덕분에 속도면에서도 느리고 변수를 Global에 노출시키게 됩니다.</li>
<li>리액트가 초기 메모리 사용량에서는 더 클 수 있지만, 복잡한 애플리케이션의 경우 더 나은 성능과 관리 용이성을 제공합니다. 모바일 환경에서도 올바르게 최적화하면 리액트의 장점을 충분히 활용할 수 있습니다. 반면, jQuery는 단순한 작업이나 작은 프로젝트에서 유리할 수 있지만, 복잡한 애플리케이션에서는 성능과 유지보수 측면에서 한계가 있을 수 있습니다.</li>
</ul>
<h3 id="속도저하">속도저하</h3>
<p>jQuery는 비교적 무거운 라이브러리로, 특히 저사양 모바일 기기에서는 성능 저하를 초래할 수 있습니다. DOM 조작과 애니메이션이 많은 페이지에서는 이 문제가 더 두드러집니다.</p>
<h3 id="모바일에서의-문제점">모바일에서의 문제점</h3>
<p>아직 모바일에서는 사용해본적이 없지만 jQuery는 기본적으로 터치 이벤트를 완벽하게 지원하지 않으며, 데스크탑 환경의 마우스 이벤트 중심으로 설계되었습니다. 이를 해결하기 위해 jQuery Mobile 등의 플러그인이 있지만, 이는 추가적인 파일 로드와 복잡성을 초래합니다 모바일 기기는 데스크탑에 비해 메모리가 제한적이므로, jQuery의 메모리 사용량이 문제가 될 수 있습니다. 이는 특히 오래된 모바일 기기에서 문제가 될 수 있습니다.</p>
<h3 id="의존성">의존성</h3>
<p>브라우저 버전에 따라 jQuery의 일부 기능이 제한될 수 있으므로, 목표하는 브라우저 환경에 맞는 jQuery 버전을 선택하는 것이 중요합니다.
jQuery와 함께 사용되는 다른 라이브러리나 프레임워크도 jQuery 버전에 의존할 수 있습니다. 이 경우 
기존 코드를 업데이트할 때 종속성 문제를 야기할 수 있습니다.</p>
<p>DOM은 테그들로 트리구조로 뼈대를 만들고 
랜더링은 살이 붙이는 과정이라고 할수 있다. </p>
<p>리액트는 버츄얼 돔이라는 가상돔이 있는데 이 가상돔이 상태가 바뀐애들을 기억하고 있다가 한번에 반영을 시켜줌
그래서 리액트는 제이쿼리보다 랜더링이 빠르고 DOM조작비용을 줄이고 불필요한 재계산을 줄일수 잇다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[TypeScript]]></title>
            <link>https://velog.io/@hwa_haha/TypeScript</link>
            <guid>https://velog.io/@hwa_haha/TypeScript</guid>
            <pubDate>Sun, 05 May 2024 11:32:34 GMT</pubDate>
            <description><![CDATA[<h2 id="typescript란">TypeScript란?</h2>
<blockquote>
<p>타입스크립트는 자바스크립트에 타입을 부여한 언어입니다. 
자바스크립트의 확장된 언어라고 볼 수 있습니다. 타입스크립티는 자바스크립트와 달리 브라우저에서 실행하려면 파일을 한번 변환해주어야 합니다. 이변환 과정을 우리는 컴파일이라고 부릅니다. </p>
</blockquote>
<h2 id="type-system">Type System</h2>
<ul>
<li>개발 환경에서 에러를 잡는 걸 도와줍니다.</li>
<li>type annotations를 사용해서 코드를 분석 할 수 있습니다.</li>
<li>오직 개발 환경에서만 활성화 됩니다.</li>
<li>타입 스크립트와 성능 향상과는 관계가 없습니다. </li>
</ul>
<h2 id="typescript-사용하는-이유">TypeScript 사용하는 이유?</h2>
<ul>
<li>TypeScript는 JavaScript 코드를 단순화하여 더 쉽게 읽고 디버그할 수 있도록 합니다.</li>
<li>TypeScript는 오픈소스입니다.</li>
<li>TypeScript는 정적 검사와 같은 JavaScript IDE 및 사례를 위한 매우 생산적인 개발도구를 제공합니다.</li>
<li>TypeScript를 사용하면 코드를 더 쉽게 읽고 이해할 수 있습니다.</li>
<li>TypeScript를 사용하면 일반 JavaScript보다 크게 개선할 수 있습니다.</li>
<li>TypeScript는 ES6의 모든 모든 이점과 더 많은 생산성을 제공합니다.</li>
<li>TypeScript는 코드 유형 검사를 통해 JavaScript를 작성할 떄 개발자가 일반적으로 겪는 버그를 피하는데 도움이 될 수 있습니다. </li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[자바스크립트 구조분해할당]]></title>
            <link>https://velog.io/@hwa_haha/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EA%B5%AC%EC%A1%B0%EB%B6%84%ED%95%B4%ED%95%A0%EB%8B%B9</link>
            <guid>https://velog.io/@hwa_haha/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EA%B5%AC%EC%A1%B0%EB%B6%84%ED%95%B4%ED%95%A0%EB%8B%B9</guid>
            <pubDate>Tue, 09 Apr 2024 12:50:55 GMT</pubDate>
            <description><![CDATA[<h2 id="📌구조분해할당">📌구조분해할당</h2>
<p>배열이나 객체를 분해해서 각각의 값을 변수에 담는 표현식이다. 
구조분해석을 쓰면 더욱 간결하고 가독성 좋게 사용할수 있습니다. </p>
<pre><code class="language-js">//배열 구조 분해 할당
const animals =[&quot;강아지&quot;,&quot;고양이&quot;,&quot;오리&quot;];
const dog = animals[0];
const cat = animals[2];

//존재하지않는 네번쨰 요소 
const [dog, cat, duck, cow = &quot;소&quot;] = animals;
console.log(dog, cat, duck);

//나머지 구분 
const [dog, cat, ...rest] = animals;

//TIP 1 -변수 값 교환하기 
let a = 1;
let b = 2;

[a, b] = [b ,a];</code></pre>
<pre><code class="language-js">//객체 구조 분해 할당
const animals = {
  dog : &quot;강아지&quot;,
  cat : &quot;고양이&quot;,
  duck : &quot;오리&quot;,
};

//const { cat, dog } = animals;
const { dog, ...rest} = animals;

// TIP1 반복문에서 구조 분호 할당하기
const users = [
  {name:&quot;철수&quot;, age: 25 },
  {name:&quot;영희&quot;, age: 30 },
];

for (const { name } of users) {
    console.log(name);
}

// TIP2 함수의 매개변수로 전달된 객체를 구조 분해 할당하기
const user = { name: &quot;철수&quot; , age: 25};

function printUser ({name, age}){
    console.log(`${name}님은 ${age}살 이예요`);
}
printUser(user);

</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[자바 vs. 노드 vs. 넥스트: 비교와 장단점]]></title>
            <link>https://velog.io/@hwa_haha/%EC%9E%90%EB%B0%94-vs.-%EB%85%B8%EB%93%9C-vs.-%EB%84%A5%EC%8A%A4%ED%8A%B8-%EB%B9%84%EA%B5%90%EC%99%80-%EC%9E%A5%EB%8B%A8%EC%A0%90</link>
            <guid>https://velog.io/@hwa_haha/%EC%9E%90%EB%B0%94-vs.-%EB%85%B8%EB%93%9C-vs.-%EB%84%A5%EC%8A%A4%ED%8A%B8-%EB%B9%84%EA%B5%90%EC%99%80-%EC%9E%A5%EB%8B%A8%EC%A0%90</guid>
            <pubDate>Tue, 09 Apr 2024 05:21:52 GMT</pubDate>
            <description><![CDATA[<h2 id="🚀java">🚀Java</h2>
<h4 id="언어-및-목적">언어 및 목적:</h4>
<p>자바 프로그래밍 언어로, 다양한 애플리케이션 및 시스템을 개발하는 데 사용됩니다.</p>
<h4 id="실행-환경">실행 환경:</h4>
<p>Java 가상 머신 (JVM) 위에서 실행됩니다.</p>
<h4 id="특징">특징:</h4>
<p>멀티스레딩을 통한 병렬 처리와 객체 지향 프로그래밍을 강조하며, 안정적이고 성숙한 기술과 큰 커뮤니티를 가지고 있습니다.</p>
<h2 id="🚀노드nodejs">🚀노드(Node.js)</h2>
<h4 id="언어-및-목적-1">언어 및 목적:</h4>
<p>자바스크립트를 사용하여 서버 사이드 및 네트워크 애플리케이션을 개발하는 데 사용됩니다.</p>
<h4 id="실행-환경-1">실행 환경:</h4>
<p>V8 JavaScript 엔진 위에서 실행됩니다.</p>
<h4 id="특징-1">특징:</h4>
<p>비동기식 이벤트 기반 아키텍처를 강조하여 높은 성능과 확장성을 제공하며, 단일 언어 사용으로 개발 생산성을 향상시킵니다.</p>
<h2 id="🚀nextjs">🚀Next.js</h2>
<h4 id="언어-및-목적-2">언어 및 목적:</h4>
<p>자바스크립트를 사용하여 리액트 기반의 서버 사이드 렌더링 및 앱 개발을 위한 프레임워크입니다.</p>
<h4 id="실행-환경-2">실행 환경:</h4>
<p>Node.js 런타임 위에서 실행됩니다.</p>
<h4 id="특징-2">특징:</h4>
<p>리액트 기반의 선도적인 웹 프레임워크로, 서버 사이드 렌더링 및 정적 사이트 생성을 용이하게 지원하여 개발 생산성을 향상시킵니다.</p>
<p>간단히 말씀드리자면, 자바는 다양한 애플리케이션 개발을 위한 안정적이고 성숙한 언어이며, 노드는 비동기식 이벤트 기반 아키텍처를 가진 JavaScript 런타임으로 빠른 서버 사이드 개발을 지원하며, 넥스트는 리액트 기반의 웹 프레임워크로 서버 사이드 렌더링과 정적 사이트 생성을 편리하게 제공합니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Virtual DOM ]]></title>
            <link>https://velog.io/@hwa_haha/Virtual-DOM</link>
            <guid>https://velog.io/@hwa_haha/Virtual-DOM</guid>
            <pubDate>Wed, 03 Apr 2024 06:55:22 GMT</pubDate>
            <description><![CDATA[<h2 id="virtual-dom-가상돔">Virtual DOM (가상돔)</h2>
<blockquote>
</blockquote>
<ul>
<li>Virtual DOM (VDOM)은 UI의 이상적인 또는 “가상”적인 표현을 메모리에 저장하고 ReactDOM과 같은 라이브러리에 의해 “실제” DOM과 동기화하는 프로그래밍 개념입니다. 이 과정을 재조정이라고 합니다.</li>
<li>virtual DOM은 브라우저 API 위에 있는 JavaScript 라이브러리에서 구현되는 개념입니다.</li>
</ul>
<p>리액트의 가상돔은 실제DOM의 복사본으로 두개의 복사본을 가진다.
이 복사본은 자바스크립트 객체 형태로 메모리상에 저장되어진다. 
첫번쨰는 랜더링 이전의 화면구조 이고 두번째는 랜더링 이후의 화면구조이다.
리액트트는state가 변경될때 마다 화면이 변경되는 때 이떄 두개의 가상돔을 비교해서 변경된 부분이 diffing 과정을 통해서 바뀐부분만 브라우저에 BatchUpdate로 한꺼번에 적용시켜줍니다. 이러한 과정은 Reconsiliation,재조정이라고 한다. </p>
<p>DOM (DocuementObjectModel)
hmtl 트리구조로 표현한것이다.</p>
<p>DOM의 구조 
브라우저가 현재페이지의 HTML을 탐색하면서 element들을 찾고 해당 element와 자녀 element를 제거한뒤 수정한다음에 교체해준다. UI를 다시 그려주는 작업은 꽤나 긴 작업이 된다. </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[일반함수와 화살표함수 ]]></title>
            <link>https://velog.io/@hwa_haha/%EC%9D%BC%EB%B0%98%ED%95%A8%EC%88%98%EC%99%80-%ED%99%94%EC%82%B4%ED%91%9C%ED%95%A8%EC%88%98</link>
            <guid>https://velog.io/@hwa_haha/%EC%9D%BC%EB%B0%98%ED%95%A8%EC%88%98%EC%99%80-%ED%99%94%EC%82%B4%ED%91%9C%ED%95%A8%EC%88%98</guid>
            <pubDate>Thu, 28 Mar 2024 03:51:08 GMT</pubDate>
            <description><![CDATA[<h2 id="일반함수--function">일반함수 -function</h2>
<h3 id="함수-선언식">함수 선언식</h3>
<p>함수 선언식으로 작성된 함수는 호이스팅이 됨.
호이스팅이란 함수의 선언을 코드의 최상위로 올리는것을 의미합니다. 
함수 선언식은 네임드 함수만 되고 익명 함수는 만들수 없음.</p>
<pre><code class="language-js">function main() {
    console.log(&quot;hello&quot;)
}

main()</code></pre>
<h3 id="함수-표현식">함수 표현식</h3>
<p>익명함수를 만들 수 있음.
호이스팅이 되지않아 참조에러가 발생 함.</p>
<pre><code class="language-js">const main = function() {
    console.log(&quot;hello&quot;)
}

main()</code></pre>
<h2 id="화살표-함수">화살표 함수</h2>
<blockquote>
</blockquote>
<p>() =&gt; {}
함수 표현식을 훨씬 간결하게 만들어준다. 
익명함수이다.</p>
<pre><code class="language-js">const main =()=&gt; {
    console.log(&quot;hello&quot;)
}
main()</code></pre>
<pre><code class="language-js">const add =(a, b)=&gt; {
    return a + b
}

//  중괄호, return 생략가능
const add =(a, b)=&gt; a + b

add()
</code></pre>
<h2 id="arguments">arguments</h2>
<p>함수가 전달받은 인자를 담고 있는 배열형태의 객체 
화살표함수는 arguments를 전달 받지 않음.
가변인자 처리 </p>
<pre><code class="language-js">const main = (...args) =&gt; {
    console.log(args)
}
main(1, 2, 3)
</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[객체]]></title>
            <link>https://velog.io/@hwa_haha/%EA%B0%9D%EC%B2%B4</link>
            <guid>https://velog.io/@hwa_haha/%EA%B0%9D%EC%B2%B4</guid>
            <pubDate>Thu, 28 Mar 2024 03:26:03 GMT</pubDate>
            <description><![CDATA[<pre><code class="language-js">const superman = {
    name :&#39;clark&#39;,
      age: 30,
}

superman.hair </code></pre>
<h2 id="🌱대문자로-시작하는-객체클래스">🌱대문자로 시작하는 객체(클래스)</h2>
<p>대문자로 시작하는 객체는 주로 생성자 함수로 사용됩니다. 이런 객체는 주로 객체 지향 프로그래밍의 클래스를 흉내내는 데 사용됩니다.
대문자로 시작하는 객체는 new 키워드를 사용하여 인스턴스를 생성할 수 있습니다. 즉, 이런 객체는 생성자 함수로서의 역할을 수행합니다.
일반적으로 생성자 함수를 사용하여 객체의 속성과 메서드를 정의하고, 이를 기반으로 인스턴스를 생성합니다.</p>
<pre><code class="language-js">function Person(name) {
  this.name = name;
}

Person.prototype.sayHello = function() {
  console.log(&#39;Hello, &#39; + this.name);
};

const person1 = new Person(&#39;Alice&#39;);
person1.sayHello(); // 출력: Hello, Alice
</code></pre>
<h2 id="🌱소문자로-시작하는-객체인스턴스">🌱소문자로 시작하는 객체(인스턴스)</h2>
<p>소문자로 시작하는 객체는 주로 생성자 함수로부터 생성된 인스턴스를 나타냅니다.
이러한 객체는 클래스(대문자로 시작하는 객체)의 인스턴스이며, 클래스에서 정의된 속성과 메서드를 상속합니다.
일반적으로 클래스의 인스턴스로서의 역할을 수행하며, 클래스의 행동을 수행하거나 클래스에서 정의된 속성을 저장합니다.</p>
<pre><code class="language-js">const person2 = new Person(&#39;Bob&#39;);
person2.sayHello(); // 출력: Hello, Bob</code></pre>
<p>따라서 대문자로 시작하는 객체는 주로 생성자 함수 또는 클래스로 사용되며, 소문자로 시작하는 객체는 이러한 생성자 함수나 클래스로부터 생성된 인스턴스를 나타냅니다. 이러한 관례는 코드를 읽고 이해하기 쉽게 만들어주며, 객체 지향 프로그래밍의 개념을 반영합니다.</p>
<h2 id="자주-사용하는-메소드">자주 사용하는 메소드</h2>
<h4 id="array-메서드">Array 메서드:</h4>
<p>forEach(): 배열의 각 요소에 대해 주어진 함수를 실행합니다.
map(): 배열의 각 요소에 대해 주어진 함수를 호출하고, 그 결과를 모아서 새로운 배열을 반환합니다.
filter(): 주어진 함수의 테스트를 통과하는 모든 요소를 포함하는 새로운 배열을 생성합니다.
reduce(): 배열의 각 요소에 대해 주어진 리듀서 함수를 실행하고, 단일 값으로 줄여서 반환합니다.</p>
<h4 id="string-메서드">String 메서드:</h4>
<p>charAt(): 문자열에서 지정된 인덱스에 있는 문자를 반환합니다.
substring(): 문자열의 일부분을 반환합니다.
split(): 문자열을 지정된 구분자를 기준으로 여러 개의 문자열로 분할하여 배열로 반환합니다.
indexOf(), lastIndexOf(): 문자열에서 특정 문자열의 인덱스를 찾습니다.
toLowerCase(), toUpperCase(): 문자열을 소문자나 대문자로 변환합니다.</p>
<h4 id="object-메서드">Object 메서드:</h4>
<p>keys(): 객체의 속성 이름들을 배열로 반환합니다.
values(): 객체의 속성 값들을 배열로 반환합니다.
hasOwnProperty(): 객체가 특정 속성을 가지고 있는지 여부를 확인합니다.</p>
<h4 id="math-메서드">Math 메서드:</h4>
<p>random(): 0과 1 사이의 난수를 반환합니다.
round(), ceil(), floor(): 숫자를 반올림, 올림, 내림합니다.
max(), min(): 주어진 숫자 중 최대값 또는 최소값을 반환합니다.</p>
<h4 id="promise-메서드">Promise 메서드:</h4>
<p>then(): Promise가 성공하면 실행할 콜백을 등록합니다.
catch(): Promise가 실패할 때 실행할 콜백을 등록합니다.</p>
<h4 id="dom-메서드">DOM 메서드:</h4>
<p>getElementById(): 지정된 ID를 가진 요소를 반환합니다.
querySelector(), querySelectorAll(): CSS 선택자를 사용하여 요소를 선택합니다.
addEventListener(): 이벤트를 요소에 바인딩합니다.
appendChild(), removeChild(): 요소를 추가하거나 제거합니다.</p>
<h2 id="jsonstringify">JSON.stringify()</h2>
<p>이 함수는 JavaScript 객체를 JSON 형식의 문자열로 변환합니다.</p>
<pre><code class="language-js">const data = {
  name: &#39;Alice&#39;,
  age: 25,
  city: &#39;Paris&#39;
};

const jsonString = JSON.stringify(data);

console.log(jsonString); // 출력: {&quot;name&quot;:&quot;Alice&quot;,&quot;age&quot;:25,&quot;city&quot;:&quot;Paris&quot;}</code></pre>
<p>대문자와 소문자 객체 
자주사용하는 메서드
JSON 데이터 파싱시 </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[동기와 비동기]]></title>
            <link>https://velog.io/@hwa_haha/%EB%B9%84%EB%8F%99%EA%B8%B0</link>
            <guid>https://velog.io/@hwa_haha/%EB%B9%84%EB%8F%99%EA%B8%B0</guid>
            <pubDate>Thu, 28 Mar 2024 03:25:03 GMT</pubDate>
            <description><![CDATA[<h2 id="📌동기">📌동기</h2>
<p>정해진 순서에 따라 순차적으로 한번에 하나씩 진행된다.</p>
<pre><code class="language-js">console.log(&quot;작업 1&quot;);
print();
console.log(&quot;작업 3&quot;);

function print() {
    console.log(&quot;작업 2&quot;);
};</code></pre>
<p>동기프로그램의 문제는 Blocking 발생하는 단점이 있다.</p>
<h2 id="📌비동기">📌비동기</h2>
<p>동시적으로 진행되서 순서를 알 수없다.
동시에 여러 개의 관계없는 요청을 보낼 때는 요청 수 제한을 고려하고, 병렬 처리를 통해 효율적으로 관리하며, 각 요청에 대한 응답과 에러를 적절히 처리해야 합니다.</p>
<h4 id="settimeout">setTimeout</h4>
<p>비동기 함수이다. 
콜백함수와, 시간값을 인자로 가진다. </p>
<pre><code class="language-js">console.log(&#39;1&#39;);

setTimeout(()=&gt;{
    console.log(&#39;2&#39;);
}, 3000);</code></pre>
<p>자바스크립트는 싱글스레드인데 한가지만 되는데 어떻게 동시에 처리를 할수 있는 이유는
자바스크립트 엔진의 Web API덕분이다. 
Web API 는 멀티쓰레드이며 setTimeout,fetch,DOM이 속해져있다.</p>
<h3 id="callback함수">callback함수</h3>
<p>콜백함수란 다른 함수의 인자로 전달되는 값이다.</p>
<pre><code class="language-js">function main(callback){
    callback();
}

main(function() { });</code></pre>
<h3 id="비동기-콜백이란">비동기 콜백이란?</h3>
<p>비동기 처리가 끝난다음에 후처리에 사용한다.</p>
<pre><code class="language-js">function getData(callback) {
    setTimeout(()=&gt;{
      console.log(&#39;나는 콜백이야&#39;);
      callback({name:&#39;콜백&#39;})
  }, 2000);
}

getData((data)=&gt;{
  console.log(data.name);
});</code></pre>
<p>작업이 의존하는 경우 </p>
<pre><code class="language-js">// 1.로그인
function login(username,callback) {
    setTimeout(()=&gt;{
      callback(username);
  }, 1000);
}
// 2. 장바구니에 넣기 
function addToCart(product,callback) {
    setTimeout(()=&gt;{
      callback(product);
  }, 1000);
}

// 2. 결제하기 
function makePayment(carNumber, product, callback) {
    setTimeout(()=&gt;{
      callback(carNumber, product);
  }, 1000);
}

// 콜백지옥 -&gt; 유지보수도 어렵다.
login(&#39;콜백&#39;,(username)=&gt;{
    console.log(`${username}님 로그인했습니다.`);
    addToCart(&#39;책&#39;,(product)=&gt;{
    console.log(`${product}가 장바구니에 추가되었습니다.`);
      makePayment(&#39;000000000&#39;, product,()=&gt;{
          console.log(`${carNumber.slice(0, 6)}로 ${product}를 구매했습니다.`);
      });
  });
});</code></pre>
<h2 id="📌promise">📌Promise</h2>
<p>비동기 처리에 사용되는 자바스크립트 객체(상태, 결과물)로 비동기 작업이 맞이할 성공과 실패를 나타낸다.
비동기 작업의 상태를 나타낸다고 할 수 있다.</p>
<ul>
<li>Pending: 대기 </li>
<li>Fulfilled: 성공</li>
<li>Rejected: 실패 </li>
</ul>
<pre><code class="language-js">
function getData() {
  const promise = new Promise((resolve, reject)=&gt; {
   setTimeout(()=&gt;{
       const data = { name: &#39;철수&#39;};
       if(data){     
         console.log(&#39;네트워크 요청 성공&#39;);
         resolve(data)
       } else{
         reject(new Error(&#39;네트워크 문제!!!&#39;));
       }
    }, 1000);
  });

  return promise
}

//then(). catch(). finally()
getData()
  .then((data)=&gt; {
      const naem = data.name;
    console.log(`${naem} 안녕하세요`);
  })
  .catch((error)=&gt; {
    console.log(&#39;에러처리를 했어요&#39;);
  })
  .finally(()=&gt; {
    console.log(&#39;마무리작업&#39;);
  });

//Promise Chaining 여러가지 비동기를 순차적으로 사용할수있다.
const promise = getDate();
promise
 .then((data)=&gt; {
    console.log(data);
      return getDate();
  })
 .then((data)=&gt; {
    console.log(data);
  })

// 콜백지옥 쇼핑몰 바꾸기
// 1.로그인
function login(username) {
  return new Promise((resolve, reject)=&gt; {
   setTimeout(()=&gt;{
       if(username){     
         resolve(username)
       } else{
         reject(new Error(&#39;아이디를 입력해주세요&#39;));
       }
    }, 1000);
}
// 2. 장바구니에 넣기 
function addToCart(product) {
    return new Promise((resolve, reject)=&gt; {
   setTimeout(()=&gt;{
       if(product){     
         resolve(product)
       } else{
         reject(new Error(&#39;물건을 입력해주세요&#39;));
       }
    }, 1000);
}

// 2. 결제하기 
function makePayment(carNumber, product) {
     return new Promise((resolve, reject)=&gt; {
           setTimeout(()=&gt;{
       if(carNumber.length !== 16 || !product){     
          reject(new Error(&#39;올바르지않아요&#39;));
         return;
       }
         resolve(product);
    }, 1000);
}

login(&#39;콜백&#39;)
    .then((username)=&gt; addToCart(&#39;책&#39;))
    .then((product)=&gt; makePayment(&#39;2222222222222222&#39;,product)
    .then((product)=&gt; makePayment(product)) 
    .catch((error)=&gt; console.log(error.message))
    .finally(()=&gt; console.log(&#39;마무리이&#39;));</code></pre>
<h4 id="promiseall">Promise.all</h4>
<p>여러 개의 비동기 작업을 효율적으로 처리하고, 모든 작업이 완료될 때까지 기다리는 기능을 제공합니다.</p>
<h4 id="promiserace">Promise.race</h4>
<p>여러 개의 비동기 작업 중에서 가장 빠르게 완료되는 작업을 선택하여 처리할 수 있습니다.</p>
<h2 id="async-await">Async/ Await</h2>
<p>async
await 프로미스가 완료될때까지 잠시 멈추어서 기다려준다.</p>
<p>비동기를 동기처럼 보여지게할수 있고, Promise Chaining 동작이 동일하며, 보다 가독성있다. </p>
<pre><code class="language-js">
// async -&gt; Promise 반환하는 비동기 함수로 변신한다.

function networkRequest() {
    return new Promise((resolve, reject)=&gt; {
   setTimeout(()=&gt;{
      console.log(&#39;데이터를 받아왔습니다&#39;);
     resolve();
    }, 1000);
}

async function getUser() {
    await networkRequest();
    return &#39;콜백&#39;;
}

async function getTodo() {
    await networkRequest();
  return[&#39;청소하기&#39;,&#39;밥먹기&#39;];
}

async function getData() {
  let user
  try{
      user = await getUser();
  }catch(error){
    console.log(error.message);
    user =&#39;익명&#39;

  }
      const toso = await getTodo();
    console.log(user);
}
</code></pre>
<p>Primise, async/ await차이는
Promise패턴
then이란 
setTimeout에 promise적용한다면?
동시에 여러개의 관계없는 요청을 한다면?
Micro task queue? 존재이유 </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Closure]]></title>
            <link>https://velog.io/@hwa_haha/Closure</link>
            <guid>https://velog.io/@hwa_haha/Closure</guid>
            <pubDate>Thu, 28 Mar 2024 03:21:14 GMT</pubDate>
            <description><![CDATA[<h2 id="📌closure란">📌Closure란?</h2>
<p>함수와 렉시컬 환경의 조합
함수가 생성될 당시의 외부 변수를 기억
생성 이후에도 계속 접근 가능</p>
<pre><code class="language-js">
const x = 1;

function outFunc() {
    const x = 10;

  function innerFunc() {
    console.log(x); //10
  }
  innerFunc(); 
}

outFunc();
</code></pre>
<p>자바스크립트 엔진은 함수를 어디서 호출했는지가 아니라 함수를 어디에 정의했는지에 따라 상위스코프를 결정한다. 이를 렉시컬스코프라 한다. </p>
<p>외부 함수보다 중첩 함수가 더 오래 유지되는 경우 중첩 함수는 이미 생명주기가 종료한다 외부 함수의 변수를 참조 할수 있다. 이러한 중첩 함수를 클로저라고 부른다, </p>
<p>클로저는 상태를 안전하게 변경하고 유지하기 위해 사용된다. 다시말해 상태가 의도치않게 변경되지 않도록 상태를 안전하게 은닉하고 특정 함수에게만 상태 변경을 허용하기 위해 사용된다. </p>
<p>정의
활용한 구현경험
커링
고차함수 </p>
<p>클로저 = scope</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Prototype이 뭐에요]]></title>
            <link>https://velog.io/@hwa_haha/Prototype%EC%9D%B4-%EB%AD%90%EC%97%90%EC%9A%94</link>
            <guid>https://velog.io/@hwa_haha/Prototype%EC%9D%B4-%EB%AD%90%EC%97%90%EC%9A%94</guid>
            <pubDate>Thu, 28 Mar 2024 03:18:22 GMT</pubDate>
            <description><![CDATA[<h2 id="prototype">Prototype</h2>
<blockquote>
</blockquote>
<p>자바스크립트에서 프로토타입(Prototype)은 객체 지향 프로그래밍에서 객체 간의 상속을 구현하는데 사용되는 메커니즘입니다.
모든 JavaScript 객체는 다른 객체로부터 상속된 프로토타입을 가지고 있습니다. 이 프로토타입은 객체가 가지고 있는 속성과 메서드의 집합입니다. 객체가 어떤 메서드나 속성을 호출할 때, 해당 객체에 해당 메서드나 속성이 없으면 자바스크립트는 이를 객체의 프로토타입 체인을 따라 상위 프로토타입에서 찾습니다.</p>
<p>1.
객체의 기반이 되는 템플릿: 프로토타입은 새로운 객체를 생성할 때 기본적인 템플릿 역할을 합니다. 새로운 객체는 해당 프로토타입을 상속받아 프로토타입의 속성과 메서드를 사용할 수 있습니다.</p>
<ol start="2">
<li><p>상속과 재사용성: 프로토타입을 사용하면 객체 사이에 상속 관계를 설정하여 코드를 재사용할 수 있습니다. 하위 객체는 상위 객체의 프로퍼티와 메서드를 상속받아 사용할 수 있습니다.</p>
</li>
<li><p>프로토타입 체이닝: 모든 객체는 자신의 부모 역할을 하는 프로토타입을 가지고 있습니다. 이런 프로토타입은 또다시 다른 객체의 프로토타입을 가질 수 있으며, 이러한 관계를 따라가면서 메서드나 속성을 찾는 것을 프로토타입 체이닝이라고 합니다.</p>
</li>
</ol>
<p>prototype은 유전자역활을 한다.</p>
<pre><code class="language-js">//여기에 쓰면 자식이 {q: &#39;strike&#39;} 직접가짐
function 기계(){
  this.q = &#39;strike&#39;;
  this.w = &#39;snowball&#39;;
}
//여기다가 쓰면 부모만 {name:&#39;kim&#39;}가짐
기계.prototype.name = &#39;kim&#39;
let nunu = new 기계()

var array =[4, 2, 1];
var array =new Array(4, 2, 1);
array.sort()
</code></pre>
<p>프로토타입은 JavaScript에서 객체 지향 프로그래밍을 구현하는 핵심적인 개념 중 하나이며, 이를 통해 코드의 재사용성을 높이고 상속 관계를 관리할 수 있습니다.</p>
<h3 id="functionbind">Function.bind</h3>
<p>Function.bind는 함수 객체의 메서드이며, 함수 객체의 프로토타입에 속하는 것이 아닙니다. 그러나 Function.prototype.bind로 정의된 메서드이므로 모든 함수 객체가 이 메서드를 상속합니다.</p>
<p>Function.bind 메서드는 함수의 this 값을 바인딩하고, 필요한 인수를 고정하여 새로운 함수를 생성합니다. 이 메서드는 함수를 호출할 때 함수 내부의 this가 특정한 값으로 고정되도록 할 수 있습니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[변수 호이스팅 ]]></title>
            <link>https://velog.io/@hwa_haha/%EB%B3%80%EC%88%98-%ED%98%B8%EC%9D%B4%EC%8A%A4%ED%8C%85</link>
            <guid>https://velog.io/@hwa_haha/%EB%B3%80%EC%88%98-%ED%98%B8%EC%9D%B4%EC%8A%A4%ED%8C%85</guid>
            <pubDate>Thu, 28 Mar 2024 03:09:07 GMT</pubDate>
            <description><![CDATA[<h2 id="📌호이스팅hoisting이란">📌호이스팅(hoisting)이란?</h2>
<blockquote>
</blockquote>
<p>자바스크립트는 런타임이 아니라 그 이전단계에서 선언한 변수와 함수를 가져가서 메모리에 기억을 해둡니다.함수가 실행되기 전 소스코드의 평가 과정에서 자바스크립트 엔진은 안에 있는 변수들을 범위의 최 상단으로 끌어올리는 것입니다. 
즉 변수선언문(뿐만 아니라 모든 식별자)이 코드의 선두로 끌어 올려진 것처럼 동작하는 자바스크립트 고유의 특징을 변수 호이스팅이라고 합니다. </p>
<p>var 키워드를 사용한 변수 선언은 선언단계와 초기화 단계가 동시에 진행된다.
선언단계를 통해 변수이름을 등록하고, 초기화 단계를 통해 암묵적으로undefine를 할당해 초기화 한다.</p>
<pre><code class="language-js">//a선언하기 전에 호출했음
consol.log(a) //undefind
var a = 1
consol.log(a) //1
var a = 2
consol.log(a)//2</code></pre>
<p>변수선언은 소스코드가 순차적으로 실행되는 시점인 런타임 이전에 먼저 실행되지만 값의 할당은 소스코드가 순차적으로 실행되는 시점인 런타임에 실행된다. </p>
<p>let은 Temporal Death Zone(TDZ)
a가 호이스팅되는건 알지만 a가 선언하기 전에는 접근할 수 없어(a의 초기화문이 필요)</p>
<pre><code class="language-js">//선언되지않앗다고 에러가 나옴
consol.log(a)
let a = 1
consol.log(a) 
let a = 2
consol.log(a)</code></pre>
<p>consts는 값을 재할당할 수 없어서 변수에 저장된 값을 변경할수 없다면 상수라고 한다. 
상수는 한번 정해지면 변하지않는 값, 즉 단 한번만 할당할 수 있는 변수다.</p>
<h2 id="🌱전역변수와-지역변수">🌱전역변수와 지역변수</h2>
<pre><code class="language-js">for(var i = 1; i&lt;5; i++) {
    consol.log(i)
}
//i = 5
consol.log(i)</code></pre>
<p>자바스크립트의 포용력...
var는 함수만 지역변수로 호이스팅이 되고 나머지는 다 전역변수로 올려버린다.</p>
<h2 id="🌱함수스코프">🌱함수스코프</h2>
<p>함수 스코프(Function Scope)는 변수의 유효 범위를 정의하는 개념입니다. 이는 변수가 함수 내에서 선언되었을 때 해당 함수 내에서만 유효하다는 것을 의미합니다.</p>
<p>JavaScript에서는 함수 내에서 선언된 변수는 함수 내에서만 접근할 수 있습니다. 함수 스코프는 또한 변수의 수명을 제어하고 외부 스코프에서 변수에 대한 접근을 제한함으로써 프로그램의 예측 가능성과 안정성을 높입니다.</p>
<h2 id="🌱블록스코프">🌱블록스코프</h2>
<p>블록 스코프(Block Scope)는 변수의 유효 범위를 정의하는 개념으로, 중괄호 {}로 둘러싸인 코드 블록 내에서 변수가 선언되면 해당 변수는 그 블록 내에서만 유효합니다.</p>
<p>자바스크립트에서 블록 스코프는 주로 if, for, while 등의 제어 구조나 함수 내부의 중괄호 블록에서 사용됩니다.</p>
<p>ES6(ECMAScript 2015)에서 도입된 let과 const 키워드는 블록 스코프를 가지고 있습니다. 이전에는 var 키워드를 사용하여 변수를 선언했을 때 함수 스코프가 적용되어 함수 내에서만 유효했지만, let과 const를 사용하면 블록 스코프가 적용되어 더욱 정확한 변수 유효 범위를 제공합니다.</p>
<h2 id="정리">정리</h2>
<p>var, let, const는 JavaScript에서 변수를 선언하는 세 가지 방법입니다. 이들 각각은 변수를 다르게 다루고 호이스팅과 관련하여 다른 동작을 합니다.</p>
<h4 id="var">var</h4>
<ul>
<li>var는 함수 스코프를 가집니다. 함수 내에서 선언된 변수는 함수 전체에서 유효합니다.</li>
<li>변수 호이스팅이 발생합니다. 즉, 선언 전에 변수를 참조해도 에러가 발생하지 않습니다. 선언은 호이스팅되어 함수 또는 스코프의 맨 위로 끌어올려집니다. 하지만 초기화는 그 자리에 남아있습니다.</li>
<li>재선언이 가능합니다. 이전에 선언된 변수를 다시 선언할 경우 경고가 발생하지 않고 새로운 값으로 덮어씁니다.</li>
</ul>
<h4 id="let">let</h4>
<ul>
<li>let은 블록 스코프를 가집니다. 중괄호 {} 내에서 선언된 변수는 그 블록 내에서만 유효합니다.
변수 호이스팅이 발생합니다. 선언은 호이스팅되지만 초기화는 호이스팅되지 않습니다. 즉, 변수가 - 선언되기 전에 참조하면 에러가 발생합니다.</li>
<li>재선언이 불가능합니다. 같은 스코프 내에서 같은 변수를 다시 선언하면 SyntaxError가 발생합니다.</li>
</ul>
<h4 id="const">const</h4>
<ul>
<li>const도 let과 마찬가지로 블록 스코프를 가집니다.</li>
<li>변수 호이스팅이 발생하지만 const로 선언한 변수는 선언과 동시에 초기화해야 합니다. 따라서 호이스팅된 변수에 접근하면 초기화 전까지 ReferenceError가 발생합니다.</li>
<li>재할당이 불가능합니다. 한 번 할당된 후에는 값을 변경할 수 없습니다. 하지만 객체와 배열 같은 참조형 변수의 경우에는 해당 객체나 배열 내부의 속성이나 요소를 변경하는 것은 가능합니다.</li>
</ul>
<p>따라서 var는 함수 스코프를 가지고 호이스팅 및 재선언이 가능하며, let과 const는 블록 스코프를 가지고 호이스팅은 하되 재선언이 불가능하고 const는 재할당이 불가능합니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[자바스크립트 this]]></title>
            <link>https://velog.io/@hwa_haha/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-this</link>
            <guid>https://velog.io/@hwa_haha/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-this</guid>
            <pubDate>Wed, 27 Mar 2024 11:01:11 GMT</pubDate>
            <description><![CDATA[<h2 id="📌this란">📌this란?</h2>
<blockquote>
</blockquote>
<p>JavaScript에서 함수의 this 키워드는 다른 언어와 조금 다르게 동작합니다. 
대부분의 경우 this의 값은 <strong>함수를 호출한 방법에 의해 결정됩</strong>니다. 실행중에는 할당으로 설정할 수 없고 함수를 호출할 때 마다 다를 수 있습니다. </p>
<pre><code class="language-js">// this는 함수가 호출될떄 결정이 된다.

const student = {
    name &#39;Lee&#39;,
    getNAme: function(){
        console.log(&quot;student getName&quot;,this)
    }
}

// student.getName(); student라는 객체가 호출한것이여서 this는 student(A.b)

const globaStudent = student.getName
// scope밖에서 불러서 최상단의 윈도우 객체가 불러져 옴 (b)
globaStudent();

const student2 = {
    name:&#39;Kim&#39;,
      getName: student.getName
}
// this값 &#39;Kim&#39;
student2.getName();</code></pre>
<p>예시에서도 할 수 있듯이 this는 호출될때 결정이 된다. </p>
<h2 id="📌bind-사용방법">📌.bind 사용방법</h2>
<pre><code class="language-js">// bind를 사용하여 호출하면 this의 값이 고정됨
cosnt bindGetname = student2.getName.bind(student);
bindGetname(); </code></pre>
<h2 id="📌화살표-함수-사용법">📌화살표 함수 사용법</h2>
<pre><code class="language-js">// 화살표함수에서의 this는 함수가 속해있는 곳의 this를 계승받는다.
const testStudent = {
    name:&#39;Park&#39;,
      getName:function(){
          // this값은 Park
        console.log(&quot;getName&quot;,this)
          const innerFunc = () =&gt; {
              // 외부 스코프값을 그대로 가져옴, main값을 그대로 가져와서 사용 함 
            console.log(&quot;innerFunc&quot;,this)
        }
          innerFunc()
    },
};

testStudent.getName()</code></pre>
<p>this는 일반 함수와 화살표 함수의 값이 다르다. 
화살표 함수는 .bind함수를 제공하지 않는다. </p>
<p>일반함수는 함수가 호출될때 this가 결정되는데 
화살표함수가 선언된 위치에서 this가 결정되고 호출하는 방법에 따라서는 변경되지 않음. </p>
<pre><code class="language-js">const ageTest= {
    unit: &quot;살&quot;,
      getList: [10, 20, 30],
      getAgeList: function() {
        const result = this.ageList.map((age)=&gt; {
            return age + this.unit;
        });

      console.log(result);
    },
};

ageTest.getAgeList();
</code></pre>
<p>this를 사용하고싶다면 일반함수를 사용하는게 .bind를 이용하여 예측하는게 쉽고
함수안에 있는 함수를 사용할 경우는 화살표함수로 그대로 받아지게 사용하는게 용이하다.</p>
<pre><code class="language-js">const Test= {
    name: &quot;시작&quot;,
      main: function() {
      //내부적인 상황에 따라 바꿔버리는 일반 함수 
        //setTimeout(function() {
      setTimeout(() =&gt; {
          console.log(this);
        }, 1000);
    },
};

ageTest.getAgeList();
</code></pre>
<h2 id="this를-변경">this를 변경</h2>
<p>call과 apply는 JavaScript에서 함수를 호출하는 데 사용되는 메서드입니다. 이 두 메서드를 사용하여 함수를 호출할 때 this의 값을 명시적으로 설정할 수 있습니다. 이는 함수의 컨텍스트를 변경하거나 원하는 객체를 this로 지정할 수 있도록 해줍니다.</p>
<h3 id="call">call</h3>
<p>함수를 호출하면서 첫 번째 매개변수로 전달된 객체를 해당 함수의 this로 설정합니다. 그리고 함수를 호출합니다. 이후 매개변수를 직접 받습니다.</p>
<h3 id="apply">apply</h3>
<p>call과 비슷하지만 매개변수를 배열 형태로 받습니다. 배열의 각 요소가 함수의 매개변수로 전달됩니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Git] Visual Studio에서 깃허브로 프로젝트 연동하는 법 ]]></title>
            <link>https://velog.io/@hwa_haha/Git-Visual-Studio%EC%97%90%EC%84%9C-%EA%B9%83%ED%97%88%EB%B8%8C%EB%A1%9C-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EC%97%B0%EB%8F%99%ED%95%98%EB%8A%94-%EB%B2%95-2koxmtb4</link>
            <guid>https://velog.io/@hwa_haha/Git-Visual-Studio%EC%97%90%EC%84%9C-%EA%B9%83%ED%97%88%EB%B8%8C%EB%A1%9C-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EC%97%B0%EB%8F%99%ED%95%98%EB%8A%94-%EB%B2%95-2koxmtb4</guid>
            <pubDate>Tue, 05 Mar 2024 09:32:48 GMT</pubDate>
            <description><![CDATA[<p>프로그래밍을 처음 공부할때 이클립스나 인텔리제이에서 깃허브를 연동하여 형상관리를 햇었는데 첫 직장에서는 SVN을 사용하여서 거의 1년 넘게 Git을 사용하지 않았다...개인프로젝트나 공부를 할떄는 깃으로 사용을 해봐야겟다 싶어서 정리를 해본다...자 그럼~Visual Studio Code에서 깃을 연동하는 방법에 대해 알아보도록 하겠습니다!</p>
<p><strong>이 글은 Git이 설치되어 있다는 것을 전제로 합니다.</strong></p>
<h3 id="비주얼-스튜디오-코드---깃허브github-연동-방법">비주얼 스튜디오 코드 - 깃허브(GitHub) 연동 방법</h3>
<p><img src="https://velog.velcdn.com/images/hwa_haha/post/51fea5cd-45cb-49a1-9c94-77542c09db8f/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/hwa_haha/post/31b1182a-6b24-4c2d-9315-e83de4689d7e/image.png" alt=""></p>
<p> [F1]을 눌러 명령어 창을 켠 뒤 git clone 명령어를 입력하면 아래 이미지와 같이 Clone form GitHub를 클릭합니다. </p>
<p> <img src="https://velog.velcdn.com/images/hwa_haha/post/f7853cec-188f-4877-9491-6bf6e72d0091/image.png" alt=""></p>
<p>Github 로그인을 해야한다는 팝업창이 뜨면 allow를 클릭합니다.
그러면 브라우저에 깃허브 로그인창이 뜨고 ID/ PW응 립력하고 로그인을 클릭합니다. </p>
<p><img src="https://velog.velcdn.com/images/hwa_haha/post/930057ab-53dd-406c-9e5c-1e8a7d7cd9bb/image.png" alt=""></p>
<p>Authorize Visual-Studio-Code 버튼을 클릭합니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[클론코딩] ReactJS로 영화 웹 서비스 만들기]]></title>
            <link>https://velog.io/@hwa_haha/%ED%81%B4%EB%A1%A0%EC%BD%94%EB%94%A9-ReactJS%EB%A1%9C-%EC%98%81%ED%99%94-%EC%9B%B9-%EC%84%9C%EB%B9%84%EC%8A%A4-%EB%A7%8C%EB%93%A4%EA%B8%B0</link>
            <guid>https://velog.io/@hwa_haha/%ED%81%B4%EB%A1%A0%EC%BD%94%EB%94%A9-ReactJS%EB%A1%9C-%EC%98%81%ED%99%94-%EC%9B%B9-%EC%84%9C%EB%B9%84%EC%8A%A4-%EB%A7%8C%EB%93%A4%EA%B8%B0</guid>
            <pubDate>Tue, 05 Mar 2024 09:29:03 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[[SpringBoot]스프링부트 쇼핑몰 프로젝트 with JPA(장바구니)]]></title>
            <link>https://velog.io/@hwa_haha/SpringBoot%EC%8A%A4%ED%94%84%EB%A7%81%EB%B6%80%ED%8A%B8-%EC%87%BC%ED%95%91%EB%AA%B0-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-with-JPA%EC%9E%A5%EB%B0%94%EA%B5%AC%EB%8B%88</link>
            <guid>https://velog.io/@hwa_haha/SpringBoot%EC%8A%A4%ED%94%84%EB%A7%81%EB%B6%80%ED%8A%B8-%EC%87%BC%ED%95%91%EB%AA%B0-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-with-JPA%EC%9E%A5%EB%B0%94%EA%B5%AC%EB%8B%88</guid>
            <pubDate>Fri, 25 Nov 2022 03:19:19 GMT</pubDate>
            <description><![CDATA[<h3 id="cartitemdto">CartItemDto</h3>
<pre><code class="language-java">package com.shop.shop.dto;

import lombok.Getter;
import lombok.Setter;

import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;

@Getter
@Setter
public class CartItemDto {

    @NotNull(message = &quot;상품 아이디는 필수 입력 값 입니다.&quot;)
    private  Long itemId;

    @Min(value = 1, message = &quot;최소 1개이상 담아주세요&quot;)
    private  int count;
}
</code></pre>
<h3 id="cart">Cart</h3>
<pre><code class="language-java">  public static Cart createCart(Member member){
        Cart cart = new Cart();
        cart.setMember(member);
        return cart;
    }</code></pre>
<h3 id="cartitem">CartItem</h3>
<pre><code class="language-java">   public static CartItem createCartItem (Cart cart, Item item, int count){
        CartItem cartItem = new CartItem();
        cartItem.setCart(cart);
        cartItem.setItem(item);
        cartItem.setCount(count);
        return cartItem;
    }

    public void  addCount(int count){
        this.count += count;
    }</code></pre>
<h3 id="cartrepository">CartRepository</h3>
<pre><code class="language-java">package com.shop.shop.repository;

import com.shop.shop.entity.Cart;
import org.springframework.data.jpa.repository.JpaRepository;

public interface CartRepository extends JpaRepository&lt;Cart, Long&gt; {

    Cart findByMemberId(Long memberId);


}</code></pre>
<h3 id="cartitemrepository">CartItemRepository</h3>
<pre><code class="language-java">package com.shop.shop.repository;

import com.shop.shop.entity.CartItem;
import org.springframework.data.jpa.repository.JpaRepository;

public interface CartItemRepository extends JpaRepository&lt;CartItem, Long&gt; {
    CartItem findByCartIdAndItemId(Long cartId, Long itemId);
}
</code></pre>
<h3 id="cartservice">CartService</h3>
<pre><code class="language-java">package com.shop.shop.service;


import com.shop.shop.dto.CartItemDto;
import com.shop.shop.entity.Cart;
import com.shop.shop.entity.CartItem;
import com.shop.shop.entity.Item;
import com.shop.shop.entity.Member;
import com.shop.shop.repository.CartItemRepository;
import com.shop.shop.repository.CartRepository;
import com.shop.shop.repository.ItemRepository;
import com.shop.shop.repository.MemberRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.EntityNotFoundException;

@Service
@RequiredArgsConstructor
@Transactional
public class CartService {

    private final ItemRepository itemRepository;
    private final MemberRepository memberRepository;
    private final CartRepository cartRepository;
    private final CartItemRepository cartItemRepository;

    public Long addCart(CartItemDto cartItemDto,String email){
        Item item = itemRepository.findById(cartItemDto.getItemId())
                .orElseThrow(EntityNotFoundException::new);
        Member member = memberRepository.findByEmail(email);

        Cart cart = cartRepository.findByMemberId(member.getId());
        if (cart == null){
            cart = Cart.createCart(member);
            cartRepository.save(cart);
        }

        CartItem savedCartItem =
                cartItemRepository.findByCartIdAndItemId(cart.getId(),item.getId());

        if (savedCartItem != null){ //장바구니에 기존 상품이 있을 경우
            savedCartItem.addCount(cartItemDto.getCount());
            return  savedCartItem.getId();
        }else {
            CartItem cartItem= CartItem.createCartItem(cart, item, cartItemDto.getCount());
            cartItemRepository.save(cartItem);
            return  cartItem.getId();
        }
    }
}</code></pre>
<h3 id="cartcontroller">CartController</h3>
<pre><code class="language-java">package com.shop.shop.controller;


import com.shop.shop.dto.CartItemDto;
import com.shop.shop.service.CartService;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.validation.Valid;
import java.security.Principal;
import java.util.List;

@Controller
@RequiredArgsConstructor
public class CartController {

    private  final CartService cartService;

    @PostMapping(value = &quot;/cart&quot;)
    public @ResponseBody ResponseEntity order(@RequestBody @Valid CartItemDto cartItemDto,
                                              BindingResult bindingResult, Principal principal) {

        if (bindingResult.hasErrors()) {
            StringBuilder sb = new StringBuilder();
            List&lt;FieldError&gt; fieldErrors = bindingResult.getFieldErrors();
            for (FieldError fieldError : fieldErrors) {
                sb.append(fieldError.getDefaultMessage());
            }
            return new ResponseEntity&lt;String&gt;(sb.toString(), HttpStatus.BAD_REQUEST);
        }

        String email = principal.getName();
        Long cartItemId;

        try {
            cartItemId = cartService.addCart(cartItemDto,email);
        }catch (Exception e){
            return  new ResponseEntity&lt;String&gt;(e.getMessage(),HttpStatus.BAD_REQUEST);
        }
        return  new ResponseEntity&lt;Long&gt;(cartItemId, HttpStatus.OK);
    }



}</code></pre>
<h3 id="itemdtlhtml-추가--뷰-출력-결과">itemDtl.html 추가-&gt; 뷰 출력 결과</h3>
<p><img src="https://velog.velcdn.com/images/hwa_haha/post/e9f86629-e92e-4141-a875-f35544c070c6/image.png" alt=""></p>
<h3 id="cartdetaildto">CartDetailDto</h3>
<pre><code class="language-java">package com.shop.shop.dto;


import lombok.Getter;
import lombok.Setter;

@Setter
@Getter
public class CartDetailDto {

    //hiden값으로 들어가짐 꼭 필요
    private  Long cartItemId;

    private  String itemNm;

    private  int price;

    private  int count;

    private  String imgUrl;

    public CartDetailDto(Long cartItemId, String itemNm, int price, int count, String imgUrl) {
        this.cartItemId = cartItemId;
        this.itemNm = itemNm;
        this.price = price;
        this.count = count;
        this.imgUrl = imgUrl;
    }
}
</code></pre>
<h3 id="cartitemrepository-1">CartItemRepository</h3>
<pre><code class="language-java">package com.shop.shop.repository;

import com.shop.shop.dto.CartDetailDto;
import com.shop.shop.entity.CartItem;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;

import java.util.List;

public interface CartItemRepository extends JpaRepository&lt;CartItem, Long&gt; {
    CartItem findByCartIdAndItemId(Long cartId, Long itemId);

    @Query(&quot;select new com.shop.shop.dto.CartDetailDto(ci.id, i.itemNm, i.price, ci.count, im.imgUrl) &quot; +
            &quot;from  CartItem  ci, ItemImg  im &quot; +
            &quot;join ci.item i &quot; +
            &quot;where  ci.cart.id = :cartId &quot; +
            &quot;and im.item.id = ci.item.id &quot; +
            &quot;and  im.repimgYn = &#39;Y&#39; &quot; +
            &quot;order by  ci.regTime desc&quot;
    )
    List&lt;CartDetailDto&gt; findCartDetailDtoList(Long cartId);
}</code></pre>
<p>CartDetailDto 생성자를 이용하여 DTO를 반환할 때 &quot;new com.shop.dto.CartDetailDto&quot;처럼 new 키워드와 해당 Dto의 패키지, 클래스명을 적어줍니다. 또한 생성자의 파라미터 순서는 DTO 클래스에 명시한 순으로 넣어주어야 합니다.</p>
<h3 id="cartservice-1">CartService</h3>
<pre><code class="language-java">   @Transactional(readOnly = true)
    public List&lt;CartDetailDto&gt; getCartList(String email){

        List&lt;CartDetailDto&gt; cartDetailDtoList = new ArrayList&lt;&gt;();

        Member member = memberRepository.findByEmail(email);
        Cart cart = cartRepository.findByMemberId(member.getId());
        if (cart == null){
            return cartDetailDtoList;
        }

        cartDetailDtoList =
                cartItemRepository.findCartDetailDtoList(cart.getId());

        return  cartDetailDtoList;
    }</code></pre>
<h3 id="cartcontroller-1">CartController</h3>
<pre><code class="language-java">  @GetMapping(value = &quot;/cart&quot;)
    public String orderHist(Principal principal, Model model) {
        List&lt;CartDetailDto&gt; cartDetailist =
                cartService.getCartList(principal.getName());
        model.addAttribute(&quot;cartItems&quot;,cartDetailist);
        return &quot;cart/cartList&quot;;
    }
</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[SpringBoot]스프링부트 쇼핑몰 프로젝트 with JPA(주문)]]></title>
            <link>https://velog.io/@hwa_haha/SpringBoot%EC%8A%A4%ED%94%84%EB%A7%81%EB%B6%80%ED%8A%B8-%EC%87%BC%ED%95%91%EB%AA%B0-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-with-JPA%EC%A3%BC%EB%AC%B8</link>
            <guid>https://velog.io/@hwa_haha/SpringBoot%EC%8A%A4%ED%94%84%EB%A7%81%EB%B6%80%ED%8A%B8-%EC%87%BC%ED%95%91%EB%AA%B0-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-with-JPA%EC%A3%BC%EB%AC%B8</guid>
            <pubDate>Thu, 24 Nov 2022 00:35:10 GMT</pubDate>
            <description><![CDATA[<p>고객이 상품을 주문하면 현재 상품의 재고에서 주문 수량만큼 재고를 감소 시켜야합니다.</p>
<p>상품의 주문수량보다 재고의 수가 적을 때 발생시킬 exception을 정의하겠습니다.
com.shop 패키지 아래에 exception 패키지를 생성한 후 runtimeExecprion을 상속받는 OutOfStockException클래스를 생성합니다.</p>
<h3 id="outofstockexception">OutOfStockException</h3>
<pre><code class="language-java">package com.shop.shop.exception;

public class OutOfStockException extends  RuntimeException{

    public  OutOfStockException(String message){
        super(message);
    }
}</code></pre>
<h3 id="item-추가">item 추가</h3>
<pre><code class="language-java">
 public void removeStock(int stockNumber){
        //상품의 재고수량에서 주문 후 남은 재고 수량을 구합니다.
        int restStock = this.stockNumber -stockNumber;
        if (restStock&lt;0){
        //상품의 재고가 주문 수량보다 작은 경우 재고 부족 예외를 발생시킵니다.
            throw new OptimisticLockException(&quot;상품의 재고가 부족합니다.(현재 재고 수량:&quot; + this.stockNumber +&quot;)&quot;);
        }
        //주문 후 남은 재고 수량을 상품의 현재 재고 값으로 할당합니다.
        this.stockNumber = restStock;
    }
</code></pre>
<h3 id="orderitem">OrderItem</h3>
<pre><code class="language-java">package com.shop.shop.entity;


import lombok.Getter;
import lombok.Setter;

import javax.persistence.*;
import java.time.LocalDateTime;

@Entity
@Getter
@Setter
public class OrderItem {

    @Id
    @GeneratedValue
    @Column(name = &quot;order_item_id&quot;)
    private Long id;

    @ManyToOne(fetch =FetchType.LAZY)
    @JoinColumn(name = &quot;item_id&quot;)
    private  Item item;

    @ManyToOne(fetch =FetchType.LAZY)
    @JoinColumn(name = &quot;order_id&quot;)
    private Order order;

    private int orderPrice;

    private int count;

    public  static  OrderItem createOrderItem(Item item,int count){
        OrderItem orderItem = new OrderItem();

        orderItem.setItem(item);//주문상품
        orderItem.setCount(count);//주문수량 
        //현재시간 기준으로 상품 가격을 주문 가격으로 세팅합니다. 상품 가격은 시간에 따라서 달라질수 있습니다. 또한 쿠폰이나 할인을 적용하는 케이스들도 있지만 여기서는 고려하지 않겠습니다.
        orderItem.setOrderPrice(item.getPrice());
        //주문수량만큼의 상품의 재고 수량을 감소시킵니다.
        item.removeStock(count);
        return  orderItem;
    }
    //주문가격과 주문 수량을 곱해서 해당 상품을 주문한 총 가격을 계산하는 메소드입니다.
    public  int getTotalPrice(){
        return  orderPrice * count;
    }
   // private  LocalDateTime regTime;
   // private  LocalDateTime updateTime;

}</code></pre>
<h3 id="order">Order</h3>
<pre><code class="language-java">package com.shop.shop.entity;

import com.shop.shop.constant.OrderStatus;
import lombok.Getter;
import lombok.Setter;

import javax.persistence.*;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

@Entity
@Table(name =&quot;orders&quot;)
@Getter
@Setter
public class Order {

    @Id
    @GeneratedValue
    @Column(name = &quot;order_id&quot;)
    private Long id;

    @ManyToOne(fetch = FetchType.LAZY)//주문만 알수있음 멤버도 내용을 알려면 양방향이 되어야한다.
    @JoinColumn(name = &quot;member_id&quot;)
    private Member member;

    private LocalDateTime orderDate; //주문일

    @Enumerated(EnumType.STRING)
    private OrderStatus orderStatus; //주문상태

    @OneToMany(mappedBy = &quot;order&quot;, cascade = CascadeType.ALL, orphanRemoval = true,fetch = FetchType.LAZY) //한개 삭제,한개 저장
    //주인이 아닌쪽은 연관관계매핑시 mappyBy속성의 값으로 연관관계의 주인설정(변수명)
    private List&lt;OrderItem&gt;  orderItems = new ArrayList&lt;&gt;();
    //객체선언하면 연관관계 매핑해주어야한다.

    private  LocalDateTime regTime;

    private  LocalDateTime updateTime;

    public  void  addOrderItem(OrderItem orderItem){
        orderItems.add(orderItem);
        orderItem.setOrder(this);
    }
    public  static  Order createOrder(Member member, List&lt;OrderItem&gt; orderItemList){
        Order order = new Order();
        order.setMember(member);
        for (OrderItem orderItem : orderItemList){
            order.addOrderItem(orderItem);
        }

        order.setOrderStatus(OrderStatus.ORDER);
        order.setOrderDate(LocalDateTime.now());
        return order;
    }

    public  int getTotalPrice(){
        int totalPrice = 0;
        for(OrderItem orderItem : orderItems){
            totalPrice += orderItem.getTotalPrice();
        }
        return  totalPrice;
    }

}
</code></pre>
<h3 id="orderdto">OrderDto</h3>
<pre><code class="language-java">import lombok.Getter;
import lombok.Setter;

import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;

@Getter
@Setter
public class OrderDto {

    @NotNull(message = &quot;상품 아이디는 필수 입력 값입니다.&quot;)
    private  Long itemId;

    @Min(value = 1, message = &quot;최소 주문 수량은 1개입니다.&quot;)
    @Max(value = 999,message = &quot;최대 주문 수량은 999개 입니다.&quot;)
    private int count;

}</code></pre>
<h3 id="orderservice">OrderService</h3>
<pre><code class="language-java">package com.shop.shop.service;


import com.shop.shop.dto.OrderDto;
import com.shop.shop.entity.Item;
import com.shop.shop.entity.Member;
import com.shop.shop.entity.Order;
import com.shop.shop.entity.OrderItem;
import com.shop.shop.repository.ItemImgRepository;
import com.shop.shop.repository.ItemRepository;
import com.shop.shop.repository.MemberRepository;
import com.shop.shop.repository.OrderRepository;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.EntityNotFoundException;
import java.util.ArrayList;
import java.util.List;

@Service
@Transactional
@RequiredArgsConstructor
public class OrderService {
    private  final ItemRepository itemRepository;
    private  final MemberRepository memberRepository;
    private  final OrderRepository orderRepository;
    private  final ItemImgRepository itemImgRepository;

    public  Long order(OrderDto orderDto, String email){
        Item item = itemRepository.findById(orderDto.getItemId())
                .orElseThrow(EntityNotFoundException::new);

        Member member = memberRepository.findByEmail(email);

        List&lt;OrderItem&gt; orderItemList = new ArrayList&lt;&gt;();
        OrderItem orderItem =
        OrderItem.createOrderItem(item, orderDto.getCount());
        orderItemList.add(orderItem);
        Order order = Order.createOrder(member, orderItemList);
        orderRepository.save(order);

        return  order.getId();

    }
}</code></pre>
<h3 id="ordercontroller">OrderController</h3>
<pre><code class="language-java">package com.shop.shop.controller;


import com.shop.shop.dto.OrderDto;
import com.shop.shop.service.OrderService;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.validation.Valid;
import java.security.Principal;
import java.util.List;

@Controller
@RequiredArgsConstructor
public class OrderController {
    private final OrderService orderService;

    @PostMapping(value = &quot;/order&quot;)
    public @ResponseBody ResponseEntity order (@RequestBody @Valid OrderDto orderDto,
                                               BindingResult bindingResult, Principal principal){
        if (bindingResult.hasErrors()){
            StringBuilder sb = new StringBuilder();
            List&lt;FieldError&gt; fieldErrors = bindingResult.getFieldErrors();
            for (FieldError fieldError : fieldErrors){
                sb.append(fieldError.getDefaultMessage());
            }
            return  new ResponseEntity&lt;String&gt;(sb.toString(), HttpStatus.BAD_REQUEST);
        }

        String email = principal.getName();
        Long orderId;
        try {
            orderId = orderService.order(orderDto,email);
        }catch (Exception e){
            return  new ResponseEntity&lt;String&gt;(e.getMessage(),HttpStatus.BAD_REQUEST);
        }
        return new ResponseEntity&lt;Long&gt;(orderId,HttpStatus.OK);
    }

}</code></pre>
<h2 id="주문취소">주문취소</h2>
<h3 id="item">Item</h3>
<pre><code class="language-java">
 public void  addStock(int stockNumber){
        this.stockNumber += stockNumber;
    }</code></pre>
<h3 id="orderitem-1">OrderItem</h3>
<pre><code class="language-java">   public  void cancel(){
        this.getItem().addStock(count);
    }</code></pre>
<h3 id="order-1">Order</h3>
<pre><code class="language-java">public  void  cancelOrder(){
        this.orderStatus = OrderStatus.CANCEL;

        for (OrderItem orderItem : orderItems){
            orderItem.cancel();
        }
    }</code></pre>
]]></description>
        </item>
    </channel>
</rss>