<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>dohun_08.log</title>
        <link>https://velog.io/</link>
        <description></description>
        <lastBuildDate>Fri, 09 May 2025 09:19:24 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>dohun_08.log</title>
            <url>https://velog.velcdn.com/images/dohun_08/profile/30582f0e-47b4-45cc-a4f3-937ada5da150/image.webp</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. dohun_08.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/dohun_08" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[자바스크립트는 어떻게 작동하는가?]]></title>
            <link>https://velog.io/@dohun_08/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8%EB%8A%94-%EC%96%B4%EB%96%BB%EA%B2%8C-%EC%9E%91%EB%8F%99%ED%95%98%EB%8A%94%EA%B0%80</link>
            <guid>https://velog.io/@dohun_08/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8%EB%8A%94-%EC%96%B4%EB%96%BB%EA%B2%8C-%EC%9E%91%EB%8F%99%ED%95%98%EB%8A%94%EA%B0%80</guid>
            <pubDate>Fri, 09 May 2025 09:19:24 GMT</pubDate>
            <description><![CDATA[<h1 id="자바스크립트-이벤트-루프-동작원리">자바스크립트 이벤트 루프 동작원리</h1>
<p>자바스크립트는 싱글 스레드 언어이지만 사용자 인터랙션, Ajax요청 등 다양한 비동기 작업을 논리적으로 병렬처리하는것처럼 보인다.
이 모든것은 <code>이벤트 루프(Event Loop)</code> 라는 시스템 덕분이다.</p>
<h2 id="자바스크립트-런타임의-주요-구성-요소">자바스크립트 런타임의 주요 구성 요소</h2>
<h3 id="자바스크립트-엔진">자바스크립트 엔진</h3>
<p>자바스크립트 엔진은 자바스크립트 코드를 해석하고 실행하는 프로그램이다.
다음과같은 두가지 구성 요소가 있다.</p>
<blockquote>
<p><code>콜스택(Call Stack)</code> : 함수 호출을 관리하는 스택 구조로, 현재 실행중인 함수와 그 호출 순서를 추적한다.</p>
</blockquote>
<blockquote>
<p><code>힙(Heap)</code> : 동적으로 할당된 메모리를 저장하는 공간으로, 객체와 함수 등이 저장된다.</p>
</blockquote>
<h3 id="web-api">Web API</h3>
<p>Web API는 브라우저나 Node.js와 같은 런타임 환경에서 제공하는 API로,
자바스크립트 엔진 외부에서 비동기 작업을 처리하고(setTimeout, 타이머 요청 등) 비동기 작업의 완료 시점을 관리한다.</p>
<h3 id="콜백-큐callback-que">콜백 큐(Callback Que)</h3>
<p>콜백 큐는 비동기 작업이 완료된 후 실행될 콜백 함수들을 대기시키는 큐로,
setTimeout의 콜백함수나 이벤트 핸들러 같은 함수들이 큐에 들어와 FIFO구조를 실행한다.
이벤트 루프</p>
<p>콜백 큐에는 세가지 종류가 있다.</p>
<table border="1" style="margin:0 auto;">
  <tr>
    <th>큐종류</th>
        <th>대표 API</th>
        <th style="width : 70px">우선순위</th>
        <th>실행시점</th>
  </tr>
  <tr>
    <td>마이크로 테스크 큐</td>
    <td><span style="color:green">Promise.then, queueMicrotask</span></td>
        <td>가장높음</td>
        <td>현재 테스크 종료 직후</td>
  </tr>
  <tr>
    <td>매크로 테스크 큐</td>
    <td><span style="color:green">setTimeout, setInterval</span></td>
        <td>중간</td>
        <td>마이크로 테스크 큐가 모두 실행되었을때</td>
  </tr>
  <tr>
    <td>렌더 큐</td>
    <td><span style="color:green">requestAnimationFrame</span></td>
        <td>낮음</td>
        <td>브라우저 렌더 직전</td>
  </tr>

  </table>

 <br/>

<h3 id="이벤트루프">이벤트루프</h3>
<p>이벤트루프는 <code>콜 스택</code>이 비어 있을 때 <code>콜백 큐</code>에서 대기 중인 <code>콜백 함수</code>를 <code>콜 스택</code>으로 이동시켜 실행한다. 
이러한 메커니즘을 통해 자바스크립트는 비동기 작업을 처리하면서도 싱글 스레드 환경을 유지할 수 있는것이다. </p>
<h3 id="이벤트루프-동작방식">이벤트루프 동작방식</h3>
<ol>
<li>자바스크립트 코드는 Call Stack에 코드가 실행되며 함수들이 쌓임. 
이때 바로 해결할 수 있는 동기코드는 바로 실행해서 보내버림</li>
<li>비동기 함수(예: setTimeout, fetch 등)가 호출되면, 해당 작업은 Web API로 전달</li>
<li>비동기를 처리해주고 관리해주는 Web API는 비동기 작업이 완료되면, 그에 대한 콜백 함수가 테스크 큐에 추가됩니다.
이때 테스크 큐에 들어가는 기준은 위에 보았던 표와 같다.</li>
<li>Event Loop는 Call Stack이 비는 순간을 기다림.</li>
<li>Call Stack이 비면, Callback Queue에서 가장 오래된 콜백을 Call Stack으로 옮겨 실행.</li>
</ol>
<p>예시로 알아보도록 하자</p>
<pre><code class="language-js">console.log(&#39;1&#39;);

setTimeout(() =&gt; {
  console.log(&#39;2&#39;);     // 매크로태스크
}, 0);

Promise.resolve().then(() =&gt; {
  console.log(&#39;3&#39;);     // 마이크로태스크
});

console.log(&#39;4&#39;);</code></pre>
<h4 id="코드설명">코드설명</h4>
<p>먼저 console.log(“1”) 이 스택으로 이동한 후 실행된다.</p>
<p>setTimeout이 스택으로 이동하고 콜백함수가 Web API로 이동한 후 비동기 처리시 매크로 태스크 큐로 이동한다.</p>
<p>Promise가 실행되고 Web APIs로 이동했다가 비동기 처리시 .then()은 마이크로 테스크 큐로 이동한다.</p>
<p>스택에 console.log(“4”) 가 스택으로 이동하여 실행된다.</p>
<p>마이크로 테스크에 있는 then() 이 실행되고 마지막으로 매크로 테스크 큐에 있는 setTimeout() 이 실행된다.</p>
<blockquote>
<p>실행 결과 :  1 - 4 - 3 - 2</p>
</blockquote>
<h2 id="너무-바쁘면-안좋은거-아닌가">너무 바쁘면 안좋은거 아닌가?</h2>
<h3 id="블로킹">블로킹</h3>
<p>JavaScript에서 어떤 작업이 끝날 때까지 다음 코드 실행이 멈추는 현상을 말한다.</p>
<p>블로킹의 예시</p>
<pre><code class="language-js">function waitSync(ms) {
  const start = Date.now();
  while (Date.now() - start &lt; ms) {
    // 아무것도 하지 않지만, CPU는 계속 돌아갑니다
  }
}

console.log(&quot;작업 시작&quot;);
waitSync(3000); // 3초 동안 블로킹 발생
console.log(&quot;작업 완료&quot;);</code></pre>
<p>이 코드를 실행하면 “작업 시작”이 출력되고, 3초 동안 멈춘 뒤 “작업 완료”가 출력된다.</p>
<p>이 3초 동안은 사용자 인터페이스(UI)도 멈추고, 클릭이나 입력 같은 이벤트도 무시되는데 이런 현상을 블로킹이라고한다.</p>
<h3 id="해결">해결</h3>
<p>블로킹을 해결하기위해서 비동기 기술을 적용해야한다.</p>
<pre><code class="language-js">console.log(&quot;시작&quot;);

setTimeout(() =&gt; {
  console.log(&quot;3초 뒤 실행&quot;);
}, 3000);

console.log(&quot;끝&quot;);</code></pre>
<p>출력</p>
<blockquote>
</blockquote>
<p>시작
끝
3초 뒤 실행</p>
<p>이처럼 비동기 작업은 다른 코드 실행을 막지 않는다.
이렇게 비동기를 적절히 사용하여 블로킹을 피해보자</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Rest VS Rest Ful]]></title>
            <link>https://velog.io/@dohun_08/Rest-VS-Rest-Ful</link>
            <guid>https://velog.io/@dohun_08/Rest-VS-Rest-Ful</guid>
            <pubDate>Fri, 18 Apr 2025 15:09:07 GMT</pubDate>
            <description><![CDATA[<h2 id="rest-api는-뭐야">Rest API는 뭐야?</h2>
<h3 id="rest란">Rest란?</h3>
<blockquote>
<p>HTTP를 기반으로 클라이언트가 서버의 리소스에 접근하는 방식을 규정한 <strong><code>아키텍처</code></strong></p>
</blockquote>
<h3 id="http-메서드와-rest의-관계">HTTP 메서드와 REST의 관계</h3>
<table border=1 style="margin:0 auto;">
  <tr>
    <th>메서드</th>
    <th>의미</th>
  </tr>
   <tr>
    <td>GET</td>
    <td>조회</td>
  </tr>
   <tr>
    <td>POST</td>
    <td>생성</td>
  </tr>
   <tr>
    <td>PUT</td>
    <td>전체 수정</td>
  </tr>
   <tr>
    <td>PATCH</td>
    <td>부분 수정</td>
  </tr>
   <tr>
    <td>DELETE</td>
    <td>삭제</td>
  </tr>
  </table>

<h3 id="rest-api는">Rest API는?</h3>
<blockquote>
<p>REST를 기반으로 서비스 API 구현한 것</p>
</blockquote>
<h3 id="특징">특징</h3>
<p>   1) HTTP URI 를 사용</p>
<pre><code> - 사용형식 :   ‘/groups/:group_id’ 처럼 사용한다. (HTTP URI)

 -  URI 를 사용해 자원(데이터)에 진입할 수 있고, 데이터 조작하려면 Server에 요청한다</code></pre><p>  2)  HTTP Method  사용</p>
<pre><code> - 서버 연결시 HTTP 프로토콜의 Method를 사용

 -  URI 와 메소드로 CRUD 를 한다. (GET, POST, PUT, DELETE 메소드)</code></pre><h3 id="구성">구성</h3>
<table border=1 style="margin:0 auto;">
  <tr>
    <th>구성 요소</th>
    <th>내용</th>
    <th>표현 방법</th>
  </tr>
  <tr>
    <th>자원(resource)</th>
    <td>자원</td>
    <td>URI(엔드 포인트)</td>
  </tr>
  <tr>
    <th>행위(verb)</th>
    <td>자원에 대한 행위</td>
    <td>HTTP 요청 메서드</td>
  </tr>
  <tr>
    <th>표현(representations)</th>
    <td>자원에 대한 행위의 구체적 내용</td>
    <td>페이로드 1</td>
  </tr>
  </table>

<p>REST는 자체 표현 구조로 구성되어 REST API 만으로
HTTP 요청의 내용을 이해할 수 있다.</p>
<h2 id="restful-과의-차이">Restful 과의 차이</h2>
<h3 id="restful-이란">Restful 이란?</h3>
<p>: <strong>REST의 기본 원칙을 성실히 지킨 서비스 디자인</strong></p>
<p>쉽게말해서 <code>Rest API</code> 설계원칙대로 잘 짜여진 디자인을 <code>Restful</code> 이라고 한다.
그래서 <code>Restful API</code> 가 되기 위해서는 <code>Rest API</code> 설계원칙을 잘 지켜야한다.</p>
<h3 id="rest-api-설계원칙">Rest API 설계원칙</h3>
<p>REST에서 가장 중요한 기본적인 원칙은 두 가지다.</p>
<p>  ① URI는 리소스를 표현하는데 집중해야 한다
  ② 행위에 대한 정의는 HTTP 요청 메서드를 통해 해야 한다</p>
<p>  위 두 규칙이 RESTful API를 설계하는 중심 규칙이다.</p>
<h4 id="1-uri는-리소스를-표현해야-한다">1) URI는 리소스를 표현해야 한다</h4>
<p>URI는 리소스를 표현하는 데 중점을 두어야 한다. 리소스를 식별할 수 있는 이름은 <strong><code>동사</code></strong>보다는 <strong><code>명사</code></strong>를 사용한다.</p>
<p>따라서 리소스 이름에 get 같은 행위에 대한 표현이 들어가서는 안 된다.</p>
<p>리소스에 대한 행위는 HTTP 요청 메서드로 표현한다</p>
<table border=1 style="margin : 0 auto">
  <tr>
    <th>HTTP 요청 메서드</th>
    <th>종류</th>
    <th>목적</th>
    <th>페이로드</th>
  </tr>
  <tr>
    <td>GET</td>
    <td>index/retrieve</td>
    <td>모든/특정 리소스 취득</td>
    <td>x</td>
  </tr>
  <tr>
    <td>POST</td>
    <td>create</td>
    <td>리소스 생성</td>
    <td>O</td>
  </tr>
  <tr>
    <td>PUT</td>
    <td>replace</td>
    <td>리소스의 전체 교체</td>
    <td>O</td>
  </tr>
  <tr>
    <td>PATCH</td>
    <td>modify</td>
    <td>리소스 일부 수정</td>
    <td>O</td>
  </tr>
  <tr>
    <td>DELETE</td>
    <td>delete</td>
    <td>모든/특정 리소스 삭제</td>
    <td>X</td>
  </tr>

</table>    

<p>리소스에 대한 행위는 HTTP 요청 메서드를 통해 표현하며 URI에 표현하지 않는다. 
행위(HTTP 요청 메서드)를 통해 리소스에 대한 명확히 표시를 해야 한다.</p>
<blockquote>
<p><strong>bad</strong>
GET /todos/delete/1</p>
</blockquote>
<blockquote>
<p><strong>good</strong>
DELETE /todos/1</p>
</blockquote>
<h4 id="2--http요청-메서드-요청">2.  HTTP요청 메서드 요청</h4>
<p>  클라이언트가 서버에게 요청을 보낼 때 이 요청들을 크게 4가지 성격으로 분류할 수 있다.</p>
<p>  CRUD라고 불리는 이 4가지 대표적인 요청에 대해 살펴보자.</p>
<p>   (1) Create = POST
     - create는 서버에 정보를 올려달라는 요청이다. ( 생성 )
    - create는 POST 메서드를 사용해 해당 URI를 요청하면 리소스를 생성한다.</p>
<p>(2) Read = GET</p>
<ul>
<li>read는 서버에서 정보를 불러오는 요청이다. ( 읽기 ) </li>
</ul>
<ul>
<li>read는 GET 메서드를 사용해 리소스를 조회하고 데이터를  가지고 온다.</li>
</ul>
<p> (3) Update = PUT
    - update는 정보를 바꾸는 요청이다. ( 수정 ) </p>
<pre><code>- update는 PUT 은 데이터 전체를 바꾸고 싶을 때, PATCH는 데이터의 일부만 수정하고 싶을 때 사용한다.</code></pre><p>(4) Delete = DETELE
    - delete는 정보를 지우는 요청이다. ( 삭제 )</p>
<pre><code>- delete는 DELETE 메서드를 사용해 리소스를 삭제할 수 있다</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[리액트 비동기처리]]></title>
            <link>https://velog.io/@dohun_08/%EB%A6%AC%EC%95%A1%ED%8A%B8-%EB%B9%84%EB%8F%99%EA%B8%B0%EC%B2%98%EB%A6%AC</link>
            <guid>https://velog.io/@dohun_08/%EB%A6%AC%EC%95%A1%ED%8A%B8-%EB%B9%84%EB%8F%99%EA%B8%B0%EC%B2%98%EB%A6%AC</guid>
            <pubDate>Fri, 18 Apr 2025 03:01:52 GMT</pubDate>
            <description><![CDATA[<h2 id="📖-비동기-처리의-개념">📖 비동기 처리의 개념</h2>
<p>간단하게 말하면 <strong>일을 시키고 결과가 나오기전에 다른일을 먼저하고있기</strong> 이다.
쉽게 예를들어서 설명하면</p>
<h3 id="동기란">동기란</h3>
<p><strong>라면을 끓이고 있는 동안 계속 냄비만 바라보는 것</strong>
-&gt;  <strong>물이 끓기 전엔 아무것도 못함.</strong></p>
<h3 id="비동기란">비동기란</h3>
<p><strong>라면을 끓이는 동안 다른 일을 하다가, 물이 끓으면 알려달라고 해놓는 것</strong>
-&gt; <strong>물을 끓이는 동안 다른 일을 함.</strong></p>
<p>기본으로 동기적으로 실행되지만 
    •    버튼 클릭
    •    이미지 로딩
    •    API 요청
    등등의 요인으로 인하여 비동기처리가 필요하다.</p>
<h2 id="👷♂️js에서-비동기작업을-다루는-방법-세가지">👷‍♂️JS에서 비동기작업을 다루는 방법 세가지</h2>
<h3 id="🤙-callback">🤙 Callback</h3>
<p>Callback 이란?
-&gt; <strong>“나중에 호출될 함수”</strong> 를 매개변수로 넘기는 함수
쉽게말해서 그냥 이 함수 실행하고 그 다음으로 실행할 함수를 Callback 함수라고 한다.</p>
<p>왜 사용해?
<strong>“비동기적인 작업의 완료 시점에 맞춰 원하는 작업을 실행하기 위해”</strong> 사용된다.</p>
<p>어떻게 써?</p>
<pre><code class="language-js">// 동기적인 콜백함수 활용
function greet(name, callback) {
  console.log(&quot;안녕 &quot; + name + &quot;!&quot;);
  callback();  // 나중에 실행됨
}

function sayBye() {
  console.log(&quot;잘 가~&quot;);
}

greet(&quot;철수&quot;, sayBye);

/* 출력
    안녕 철수!
    잘 가~
*/
</code></pre>
<pre><code class="language-js">// 비동기적인 콜백함수 활용
function fetchData() {
  setTimeout(() =&gt; {
    console.log(&quot;🛬 데이터 도착!&quot;);
  }, 2000);
}

console.log(&quot;1. 요청 보냄&quot;);
fetchData();
console.log(&quot;2. 다음 작업&quot;);
/*출력
    1. 요청 보냄
    2. 다음 작업
    🛬 데이터 도착!
*/</code></pre>
<p>단점: 콜백 지옥(callback hell) → 가독성↓, 디버깅 어렵
그렇기에 지금은 비동기처리로 Callback 보다는 <code>Promise</code> 와 <code>Async/await</code> 을 더 많이 사용한다.</p>
<h3 id="🐣-promise-객체">🐣 Promise (객체)</h3>
<ul>
<li><p>Promise 객체란 
Promise는 비동기 작업의 최종 완료 또는 실패를 나타내는 <strong>객체</strong>
쉽게말해서 <strong>&quot;나중에 어떤 값이 도착할 거니까, 도착하면 .then()으로 그 값을 써줘!&quot;</strong> 라고 할 수 있다</p>
</li>
<li><p>Promise 상태 3가지 
<code>대기</code> : 아직 결과가 결정되지 않은 초기 상태.
<code>성공</code> : 작업이 성공적으로 완료되어 결과값을 반환한 상태.
<code>실패</code> : 작업이 실패하거나 오류가 발생한 상태.
흐름  :대기(Pending) → 성공(Fulfilled) or 실패(Rejected)</p>
</li>
</ul>
<ul>
<li>Promise 사용 문법과  기본예제
기본문법<pre><code class="language-jsx">const myPromise = new Promise((resolve, reject) =&gt; {
// 비동기 작업 수행    
if (성공조건) {
  resolve(결과값);
} else {
  reject(에러메시지);
}
});</code></pre>
<pre><code>비동기 작업을 수행하는 코드를 넣고 성공했을때와 실패했을때를
정의하여 넣어줍니다.
</code></pre></li>
</ul>
<h4 id="예제">예제</h4>
<pre><code class="language-jsx">function checkEvenNumber(num) {
  return new Promise((resolve, reject) =&gt; {
    if (num % 2 === 0) {
      resolve(`${num}은 짝수입니다.`);
    } else {
      reject(`${num}은 홀수입니다.`);
    }
  });
}

checkEvenNumber(4)
  .then((res) =&gt; console.log(res))   // 4은 짝수입니다.
  .catch((err) =&gt; console.error(err));</code></pre>
<p>  .then과 .catch 를 이용하여 성공했을때 수행과 실패했을때의 수행을 명시해줍니다.</p>
<h3 id="🐴-asyncawait-키워드">🐴 Async/await (키워드)</h3>
<ul>
<li><p>Async/await 의 역할
  •    <code>Promise</code> 를 더 간결하고 직관적인 방식으로 다루기 위해 나온 문법
 •    <code>then/catch</code> 체인 없이도 비동기 처리 흐름을 동기처럼 읽을 수 있음
<img src="https://velog.velcdn.com/images/dohun_08/post/3592282d-178a-4b1e-b71f-2f1db8688817/image.png" alt=""></p>
</li>
<li><p>Async/await의 기본 문법 및 기본 예제 </p>
<h4 id="기본-문법">기본 문법</h4>
<pre><code class="language-jsx">async function 함수이름() {
try {
 const result = await 비동기함수();
 console.log(result);
} catch (error) {
 console.error(error);
}
}</code></pre>
</li>
</ul>
<h4 id="예제-1">예제</h4>
<pre><code class="language-jsx">async function check() {
  try {
    const result = await checkEvenNumber(3);
    console.log(result);
  } catch (error) {
    console.error(error); // 3은 홀수입니다.
  }
}

check();</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[TeachMon이 BugMon 으로 되었던건에 대하여]]></title>
            <link>https://velog.io/@dohun_08/TeachMon%EC%9D%B4-BugMon-%EC%9D%B4-%EB%90%98%EC%97%88%EB%8D%98%EA%B1%B4%EC%97%90-%EB%8C%80%ED%95%98%EC%97%AC</link>
            <guid>https://velog.io/@dohun_08/TeachMon%EC%9D%B4-BugMon-%EC%9D%B4-%EB%90%98%EC%97%88%EB%8D%98%EA%B1%B4%EC%97%90-%EB%8C%80%ED%95%98%EC%97%AC</guid>
            <pubDate>Sun, 13 Apr 2025 06:02:17 GMT</pubDate>
            <description><![CDATA[<h2 id="🥹-프로젝트-시작">🥹 프로젝트 시작</h2>
<p>프로젝트는 작년 디자인 프로젝트 수행평가에서 시작하였다.
자습감독이 구글시트로 시행되고 있고 힘들다는 것을 해결하기위해서 이 프로젝트는 기획되었다.
디자인을 직접해보고 디자인 선생님께 실력늘었다고 칭찬들은건 아직도 기억난다.
하지만
이건 또 어케 만들지 이건 어케하지 하면서 불안 반 기대 반 이었다.
일단 우리는 팀을 구했고 총 5명이 모이게 되었다. 하지만
자습감독이 어떻게 이루어지는지부터 설명하고 티치몬을 이해했어야해서 처음부터 순조롭지는 않았던 것 같다.</p>
<h2 id="🐴-제작과정">🐴 제작과정</h2>
<p>일단 제작기한이 2월 10일까지 모든 기능구현을 원하셨다. 그때부터 테스트를 해보며 진행해야 실제로 3월달부터 쓰일 수 있다고 하셔서이다. 
그렇다보니 아직 tsx는 미숙해서 공부를하며 사용하기에는 시간이 오래걸릴것같아서 그냥 jsx로 개발을 진행하였다.(솔직히 미숙하게나마라도 ts쓸걸 후회하고 있다.) 
그래도 처음으로 zustand 와 React-Query 를 써보면서 뿌듯하기도하고 관리하기도 훨씬 쉬워서 너무 편리했다.</p>
<pre><code class="language-jsx">import { create } from &#39;zustand&#39;;

const useLocation = create((set) =&gt; ({
    place: &#39;&#39;,
    setPlace: (newPlace) =&gt; set({ place: newPlace }),
}));

export default useLocation;</code></pre>
<blockquote>
<p>간단한 장소 상태저장 </p>
</blockquote>
<hr/>


<pre><code class="language-jsx">export const usePatchMovement = () =&gt;{
    const queryClient = useQueryClient();
    return useMutation({
        mutationFn : (props)=&gt; API.patchMovement(props),
        onSuccess:(_, variables)=&gt;{
            queryClient.invalidateQueries([&#39;getMovement&#39;, variables.day]);
        },
        onError:(err)=&gt;{
            console.error(&quot;수정 실패 &quot;, err);
        }
    })
}</code></pre>
<blockquote>
<p>훅을 활용한 이석 수정 쿼리</p>
</blockquote>
<p>현재는 또 어떻게해야 더 효율적으로 관리할 수 있을까를 생각해보고있다.
하지만 제일 힘들게했던건 구글 로그인이었던것 같다...
백엔드 전체부담으로해서 내가 할 수 있는게 없어서 답답하기도하고 선배분까지 부르면서 도움을 요청해서 겨우 해냈다. 🙇‍♂️ (하지만 나중에 알게된건 구현한 구글로그인 방식이 잘못되어서 수정을해야 했었다...)
그렇게 어찌저찌 2월 10일까지 자습감독 자동배정빼고는 완료했던것 같다.
자동배정도 몇일정도만 있으면 만들 수 있어서 걱정은 없었다.</p>
<h2 id="🎂-완성">🎂 완성</h2>
<p>일정이 늦어지긴했지만 결국엔 2월 26일까지는 테스트를 완료하고 개발을 완성했다. 이때까지만해도 모든기능들을 테스트해보며 <strong>이게 진짜 되네??</strong> 하며 느낌이 굉장히 좋았다. 배포하는 과정도 docker-compose 를 이용하고 하면서 docker에대한 많은 공부가 되었던 것 같다.</p>
<h2 id="🔗-운영">🔗 운영</h2>
<p>실제로 3월달부터 사용하기위해 우리는 필요한 데이터들을 사이트에 적용시켰다.(학생, 선생님, 방과후 데이터)
우리도 운영하면서 에러 몇개나올것이라고 생각을했다. 하지만 나의 예상은 훨신 초월했다...</p>
<h4 id="🐞-bugmon출현">🐞 BugMon출현</h4>
<p><code>자습감독 교체 에러</code>, <code>학생들 자습상태 중복생성 에러</code>, <code>메인 달력 에러</code>, <code>학생 제거</code>, <code>방과후 동기화에러</code>, <code>방과후 업로드에러</code>, <code>방과후 저장에러</code>, <code>이석작성 에러</code>,
등등의 에러가 있었다.
거기에 선생님들께서 학교 구글계정이 아닌데 로그인 시도를 하셔서 오류가 났다고 하시거나 학교 방과후데이터가 학생이 겹치게 되면서 로직이 꼬이거나 하기도 하여서 우리의 신뢰는 바닥을치게 되었다.
우리딴에서도 이상함을 느꼇다 분명 테스트를 해보고 기능들을 통과시켰는데 왜 이렇게 되는건지.. 사실 티치몬이 운영되기 전에 우리의 로직이 바뀌었기 때문이었다. 
<strong>우리는 우리가 알고있는 자습감독 로직대로 코드를 짰었지만 학교에서의 자습감독 방식이 바뀌어버렸다.</strong> 그래서 다 만들었던 기능들을 다시 만들고 수정하느라 좀 더 시간이 걸렸던 것 같다. 
*<em>거기에 운영 2일전에는 학생들 자습에대해서 소통 오류까지 있었다. *</em>
하지만 그 부분은 우리에게 엄청난 타격이었다. 자습 로직을 수정해서 그 부분때문에 앞서말한 에러의 80%는 그 부분때문에 일어났다.
그렇게 티치몬은 에러덩어리의 버그몬소리를 듣게된것이다.</p>
<h2 id="느낀점">느낀점</h2>
<p>이 프로젝트를 하기전에는 대회용이나 공부용으로 팀원들과 프로젝트를 해보았지만 실제로 운영할 목적으로 만든건 티치몬 프로젝트가 처음이었다. 기대에 부푼마음으로 개발하고 운영해보았지만
솔직히 운영 초기엔 너무 절망적이었다. 기대의 티치몬이 이렇게 되다니...왜 이렇게 된거지 도대체 왜 라고 생각하며 스트레스를 겁나 받았다. + (선생님들께 너무 죄송했음..)(진짜 죽고싶었음..ㅋㅋ)<img src="https://velog.velcdn.com/images/dohun_08/post/cebf6bb2-ccee-4465-b19b-03c2b6a58a99/image.png" alt=""></p>
<p>하지만 다시 생각해보고나니 이것들은 다 우리의 미숙함때문이었다는것을 깨달았다. 시스템 수정이 있어도 오류가나면 코드잘못짠 놈들 잘못이지 지시의 문제는 아니기때문이다..소통의 오류는 걍 내잘못이다... 참... 그걸 확인했어야지 뭘 하는건지... 
테스트의 중요함과 소통의 중요함은 무엇보다 뼈저리게 느끼게 된것 같다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[리액트 컴포넌트 생명주기]]></title>
            <link>https://velog.io/@dohun_08/%EB%A6%AC%EC%95%A1%ED%8A%B8-%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8-%EC%83%9D%EB%AA%85%EC%A3%BC%EA%B8%B0</link>
            <guid>https://velog.io/@dohun_08/%EB%A6%AC%EC%95%A1%ED%8A%B8-%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8-%EC%83%9D%EB%AA%85%EC%A3%BC%EA%B8%B0</guid>
            <pubDate>Fri, 11 Apr 2025 14:36:42 GMT</pubDate>
            <description><![CDATA[<h2 id="🤒-컴포넌트-생명주기">🤒 컴포넌트 생명주기</h2>
<blockquote>
<p>컴포넌트 생명주기란? </p>
</blockquote>
<p>컴포넌트가 화면에 <strong><code>등장</code></strong>하고, <strong><code>변경</code></strong>되며, <strong><code>사라지는</code> *<em>과정을 말합니다.
모든 React *</em>컴포넌트는 라이프 사이클 이벤트</strong>가 있으며, 라이프사이클 이벤트는 컴포넌트가 수행한 작업이나 앞으로 수행할 작업에 따라 특정 시점에 실행된다.</p>
<p><strong>이 생명주기 동안 특정 메서드들을 사용할 수 있으며, 주로 다음과 같은 3단계로 나뉩니다.</strong></p>
<h3 id="🛠️-마운트">🛠️ 마운트</h3>
<p>컴포넌트가 DOM에 삽입될때 발생하며 한 번만 실행된다.</p>
<h4 id="클래스형">클래스형</h4>
<pre><code class="language-jsx">constructor() // 초기 state 설정, 바인딩 등
componentDidMount() // 렌더링 완료 후 실행(DOM 접근, API 호출등)
static getDerivedStateFromProps() // props로부터 state를 동기화
render()// jsx 반환</code></pre>
<h4 id="함수형">함수형</h4>
<pre><code class="language-jsx">useEffect(() =&gt; {}, [])
// 컴포넌트 처음 렌더링될때 실행</code></pre>
<hr/>

<h3 id="🧭-업데이트">🧭 업데이트</h3>
<p>props 또는 state 가 변경될때 실행한다.</p>
<h4 id="클래스형-1">클래스형</h4>
<pre><code class="language-jsx">static getDerivedStateFromProps() // props 변화 감지
shouldComponentUpdate() // 리렌더링 여부 결정
render() // 화면 다시 그림
getSnapshotBeforeUpdate() // DOM 업데이트 전 값을 가져옴
componentDidUpdate() // 업데이트 후 실행(API 재요청 등)
</code></pre>
<h4 id="함수형-1">함수형</h4>
<pre><code class="language-jsx">useEffect(() =&gt; {}, [deps])
// 특정 값(deps)가 변경될때 실행</code></pre>
<hr/>

<h3 id="😵-언마운트">😵 언마운트</h3>
<p>컴포넌트가 DOM에서 제거될때 발생한다.</p>
<h4 id="클래스형-2">클래스형</h4>
<pre><code class="language-jsx">componentWillUnmount() // 타이머 정리, 이벤트 정리 등 컴포넌트 종료 수행</code></pre>
<h4 id="함수형-2">함수형</h4>
<pre><code class="language-jsx">useEffect(() =&gt; { return () =&gt; {} }, [])
//컴포넌트가 사라질때 정리해주는 작업으로 처리된다</code></pre>
<hr/>
<h3>📚 정리</h3>

<p><img src="https://velog.velcdn.com/images/dohun_08/post/c9545933-1ece-475d-9e3b-2210d1220b98/image.png" alt=""></p>
<blockquote>
<p>다음과같이
컴포넌트가** 처음 나타날 때** API 요청을 보내고 싶거나,
데이터가 <strong>변경될 때</strong>마다 무언가를 처리하고 싶거나,
컴포넌트가 <strong>사라질 때</strong> 정리를 하고 싶을때 사용할 수 있어요.</p>
</blockquote>
<p>클래스형은 사용할 메서드들이 많지만 
함수형에서는 훅으로 다 처리할 수 있기때문에 편리하다.
그렇기 때문에 클래스형 컴포넌트보다는 함수형 컴포넌트가 더 권장되고있다.</p>
<hr/>


<h2 id="💨-hooks을-이용해-생명주기-관리">💨 Hooks을 이용해 생명주기 관리</h2>
<pre><code class="language-jsx">useEffect(() =&gt; {
  // 마운트 시 실행 (처음 1회만)
  return () =&gt; {
    // 언마운트 시 실행
  };
}, []); // 업데이트 조건</code></pre>
<h3 id="🛠️-마운트-1">🛠️ 마운트</h3>
<pre><code class="language-jsx">import React, { useEffect } from &#39;react&#39;;

function Welcome() {
  useEffect(() =&gt; {
    console.log(&#39;컴포넌트가 마운트되었습니다!&#39;);
    // API 요청, 초기 설정 등
  }, []);

  return &lt;h1&gt;환영합니다!&lt;/h1&gt;;
}</code></pre>
<blockquote>
<p>초기 렌더링 되었을때 useEffect 안의 내용을 실행한다.</p>
</blockquote>
<hr/>

<h3 id="🧭-업데이트-1">🧭 업데이트</h3>
<pre><code class="language-jsx">import React, { useEffect, useState } from &#39;react&#39;;

function Counter() {
  const [count, setCount] = useState(0);

  useEffect(() =&gt; {
    console.log(`🔄 count가 ${count}로 변경됨`);
  }, [count]); // count가 바뀔 때마다 실행됨

  return (
    &lt;div&gt;
      &lt;p&gt;현재 값: {count}&lt;/p&gt;
      &lt;button onClick={() =&gt; setCount(count + 1)}&gt;+1&lt;/button&gt;
    &lt;/div&gt;
  );
}</code></pre>
<blockquote>
<p>useEffect의 의존성배열([count])에 count 값을 넣어두어서 해당 값이 바뀌어서 
재렌더링될때 useEffect가 다시 실행되게 된다.</p>
</blockquote>
<hr/>

<h3 id="😵-언마운트-1">😵 언마운트</h3>
<pre><code class="language-jsx">import React, { useEffect } from &#39;react&#39;;

function Timer() {
  useEffect(() =&gt; {
    const id = setInterval(() =&gt; {
      console.log(&#39;⏰ 매초 실행 중...&#39;);
    }, 1000);

    return () =&gt; {
      clearInterval(id); // 컴포넌트가 사라질 때 타이머 제거
      console.log(&#39;🧹 컴포넌트가 언마운트됨. 타이머 제거 완료!&#39;);
    };
  }, []);

  return &lt;p&gt;타이머가 작동 중입니다.&lt;/p&gt;;
}</code></pre>
<blockquote>
<p>useEffect 에서 return 을 시키면서 컴포넌트가 제거될때 실행된다. 
예시에서는 setInterval 이벤트를 처리하기 위해서 사용된다.!</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[리액트 보고서 (배열함수와 조건부렌더링)]]></title>
            <link>https://velog.io/@dohun_08/%EB%A6%AC%EC%95%A1%ED%8A%B8-%EB%B3%B4%EA%B3%A0%EC%84%9C-%EB%B0%B0%EC%97%B4%ED%95%A8%EC%88%98%EC%99%80-%EC%A1%B0%EA%B1%B4%EB%B6%80%EB%A0%8C%EB%8D%94%EB%A7%81</link>
            <guid>https://velog.io/@dohun_08/%EB%A6%AC%EC%95%A1%ED%8A%B8-%EB%B3%B4%EA%B3%A0%EC%84%9C-%EB%B0%B0%EC%97%B4%ED%95%A8%EC%88%98%EC%99%80-%EC%A1%B0%EA%B1%B4%EB%B6%80%EB%A0%8C%EB%8D%94%EB%A7%81</guid>
            <pubDate>Sun, 30 Mar 2025 09:15:54 GMT</pubDate>
            <description><![CDATA[<h1 id="map-filter-메소드-사용"><strong>[Map, filter 메소드 사용]</strong></h1>
<h2 id="map">map()</h2>
<h3 id="🧐-내용">🧐 내용</h3>
<p><strong>배열을 순회하며 새로운 배열을 반환</strong>하는 JavaScript 메서드.</p>
<p>주로 리스트로 되어있는 컴포넌트를 렌더링할때 사용됨.</p>
<h3 id="🛠️-문법">🛠️ 문법</h3>
<p>Array 자료형에서 .map()을 사용하여 새로운 배열을 반환함.</p>
<p>괄호안에는 화살표 함수가 삽입되며, 함수의 첫 번째 인자는 리스트의 요소, 두 번째는 요소의 index, 세 번째는 array 자체.</p>
<p>요소들을 변경시킬 수 있음.</p>
<p>예시</p>
<pre><code class="language-jsx">export default function CommentList(){
    const comments = [
        {
            name : &#39;김민성&#39;,
            comment : &#39;하이 나 김민성&#39;
        },
        {
            name : &#39;박다온&#39;,
            comment : &#39;리액트로 프로제트 만들고 있어요&#39;
        },
        {
            name : &#39;백도준&#39;,
            comment : &#39;리액트 재밋다&#39;
        },
    ]
    const [data, setData] = useState(comments)
    function deleteComment(id){
        setData(data.filter(item=&gt;item.name !== id))
    }
    return(
        &lt;div className=&quot;contentontainer&quot;&gt;
            {data.map(item=&gt;
                &lt;Comment comment = {item} deleteComment={deleteComment} /&gt;
            )}
        &lt;/div&gt;
    )
}</code></pre>
<p>Comment에 다른 props를 주면서 반복적으로 컴포넌트를 생성할 수 있습니다.</p>
<h3 id="👍🏾-장점">👍🏾 장점</h3>
<aside>
💡

<p>가독성 향상</p>
<p>: for문보다 간결하게 사용하여 가독성이 높아짐</p>
</aside>

<aside>
💡

<p>원본배열 유지</p>
<p>: 새로운 배열을 반환하여서 원본배열을 유지할 수 있음</p>
</aside>

<aside>
💡

<p>체이닝 가능</p>
<p>: 다른 배열함수와도 같이 쓰일 수 있음(map, filter, reduce 등등)</p>
</aside>

<hr>
<h2 id="filter">filter()</h2>
<h3 id="🧐-내용-1">🧐 내용</h3>
<p><strong>배열에서 특정 조건을 만족하는 요소만 필터링하여 새로운 배열을 반환</strong>하는 JavaScript 메서드.</p>
<p>주로 조건에 맞는 요소만 걸러내어 새로운 배열을 만들 때 사용됨.</p>
<h3 id="🛠️-문법-1">🛠️ 문법</h3>
<p>Array 자료형에서 .filter()을 사용하여 새로운 배열을 반환함.</p>
<p>호안에는 화살표 함수가 삽입되며, 함수의 첫 번째 인자는 리스트의 요소, 두 번째는 요소의 index, 세 번째는 array 자체.</p>
<p>return 문과 조건식을 세워서 어떤 요소들을 반환할지 찾을 수 있음.</p>
<pre><code class="language-jsx">array.filter((element, index, array) =&gt; {
  return 조건식;  // true인 요소만 남김
});</code></pre>
<p>예시</p>
<pre><code class="language-jsx">const numbers = [1, 2, 3, 4, 5, 6];

const evenNumbers = numbers.filter(num =&gt; num % 2 === 0);

console.log(evenNumbers); // [2, 4, 6]</code></pre>
<p>numbers 라는 배열에서 짝수들만 반환하도록 할 수 있음.</p>
<h3 id="👍🏾-장점-1">👍🏾 장점</h3>
<aside>
💡

<p>가독성 향상</p>
<p>: for문보다 간결하게 사용하여 가독성이 높아짐</p>
</aside>

<aside>
💡

<p>원본배열 유지</p>
<p>: 새로운 배열을 반환하여서 원본배열을 유지할 수 있음</p>
</aside>

<aside>
💡

<p>체이닝 가능</p>
<p>: 다른 배열함수와도 같이 쓰일 수 있음(map, filter, reduce 등등)</p>
</aside>

<aside>
💡

<p>간단 필터링</p>
<p>: if문 같은것을 사용하지 않고도 간단하게 필터링가능(조건부 렌더링도 가능)</p>
</aside>

<hr>
<h2 id="조건부-렌더링과-input"><strong>[조건부 렌더링과 input]</strong></h2>
<ol>
<li>리액트에서 입력한 input 데이터를 useState를 사용하여 가져온 후 출력하는 방법을 작성하고,</li>
</ol>
<p>사용 예를 정리하시오.</p>
<h3 id="조건부-렌더링">조건부 렌더링</h3>
<h3 id="조건부-렌더링이란">조건부 렌더링이란?</h3>
<p><strong>if 문, &amp;&amp; 연산자, 삼항 연산자, filter()</strong> 등을 활용하여 <strong>조건에 따라 컴포넌트 또는 HTML 요소를 표시하거나 숨길 수 있는 기능</strong></p>
<p>예시</p>
<pre><code class="language-jsx">export default function ConditionR(){
    const [isLogin, setLogin] = useState(false);
    return(
        &lt;div className={&#39;box&#39;}&gt;
            {!isLogin ? &lt;button className={&#39;btn1&#39;} onClick={()=&gt;setLogin(!isLogin)}&gt;로그인&lt;/button&gt; :  &lt;div&gt;
                &lt;p&gt;환영합니다~~&lt;/p&gt;
                &lt;button className={&#39;btn2&#39;} onClick={()=&gt;setLogin(!isLogin)}&gt;로그아웃&lt;/button&gt;
            &lt;/div&gt;}

            &lt;hr /&gt;
            &lt;p&gt;모두함께 리액트 공부&lt;/p&gt;

        &lt;/div&gt;
    )
}</code></pre>
<p>해당 코드에서는 useState로 isLogin 상태를 관리하면서 isLogin이 true라면 환영합니다를 보여주고</p>
<p>isLogin이 false 라면 로그인 버튼을 화면에 표시해줍니다.</p>
<h2 id="input">input</h2>
<h3 id="🧐-내용-2">🧐 내용</h3>
<p>input 태그에있는 useState 로 관리하기 위해서는 value와 onChange props를 활용해야합니다.</p>
<p>useState 선언 → value = {state} , onChange = {(e)⇒setState(e.target.value)} → state 태그에 삽입(p태그, div태그 등등)</p>
<ul>
<li>이때 onChange 에는 화살표함수가 들어가야합니다.</li>
</ul>
<p>예시</p>
<pre><code class="language-jsx">import &#39;./style.css&#39;
import {useState} from &quot;react&quot;;

function InputText() {
    const [value, setValue] = useState(&#39;&#39;);
    const handleClick = ()=&gt;{
        setValue(&#39;&#39;);
    }
  return (
    &lt;&gt;
        &lt;div&gt;
            &lt;input
                type={&quot;text&quot;}
                value={value}
                onChange={(e) =&gt; setValue(e.target.value)}
            /&gt;
            &lt;button type={&quot;button&quot;} onClick={handleClick}&gt;초기화&lt;/button&gt;
        &lt;/div&gt;
        {value &amp;&amp;
            &lt;div className={&quot;modal&quot;}&gt;
                &lt;p&gt;입력한 값은 &lt;span style={{color:&#39;red&#39;}}&gt;{value}&lt;/span&gt; 입니다&lt;/p&gt;
            &lt;/div&gt;}

    &lt;/&gt;
  )
}

export default InputText
</code></pre>
<p>useState에 빈 문자열을 선언 후 </p>
<p>  value={value}
  onChange={(e) =&gt; setValue(e.target.value)}</p>
<p>로 값을 업데이트하고</p>
<p> 태그안 <span> 태그에 값을 삽입하였습니다.![](https://velog.velcdn.com/images/dohun_08/post/fb8820c3-89a3-4787-b6d8-d086782fdd83/image.png)
]]></description>
        </item>
        <item>
            <title><![CDATA[리액트 보고서 (19, 오리앤테이션)]]></title>
            <link>https://velog.io/@dohun_08/%EB%A6%AC%EC%95%A1%ED%8A%B8-%EB%B3%B4%EA%B3%A0%EC%84%9C-19-%EC%98%A4%EB%A6%AC%EC%95%A4%ED%85%8C%EC%9D%B4%EC%85%98</link>
            <guid>https://velog.io/@dohun_08/%EB%A6%AC%EC%95%A1%ED%8A%B8-%EB%B3%B4%EA%B3%A0%EC%84%9C-19-%EC%98%A4%EB%A6%AC%EC%95%A4%ED%85%8C%EC%9D%B4%EC%85%98</guid>
            <pubDate>Sun, 30 Mar 2025 09:13:00 GMT</pubDate>
            <description><![CDATA[<h2 id="react-orientation">React Orientation</h2>
<h2 id="🛠️-리액트의-특징">🛠️ 리액트의 특징</h2>
<blockquote>
<p><strong>1. 컴포넌트 기반</strong></p>
<p>리액트는 UI를 <strong>컴포넌트</strong>라는 독립적인 조각으로 나누어 개발합니다. 이를 통해 코드의 재사용성과 유지 보수성을 높입니다.</p>
</blockquote>
<blockquote>
<p><strong>2. 가상 DOM(Virtual DOM)</strong></p>
<p>리액트는 <strong>가상 DOM</strong>을 사용하여 실제 DOM 조작을 최소화합니다. 상태가 변경될 때마다 가상 DOM에서 업데이트를 수행한 후, 변경된 부분만 실제 DOM에 적용하여 성능을 향상시킵니다.</p>
</blockquote>
<blockquote>
<p><strong>3. 단방향 데이터 흐름</strong></p>
<p> 데이터가 부모 컴포넌트에서 자식 컴포넌트로 전달되고, 자식 컴포넌트에서 부모 컴포넌트의 상태를 직접 변경할 수 없습니다. </p>
</blockquote>
<blockquote>
<p><strong>4. JSX</strong></p>
<p>리액트는 <strong>JSX</strong>(JavaScript XML)라는 문법을 사용하여 HTML과 JavaScript를 함께 작성할 수 있습니다. </p>
<pre><code class="language-jsx">const element = &lt;h1&gt;Hello, World!&lt;/h1&gt;;</code></pre>
</blockquote>
<blockquote>
<p><strong>5. 상태 관리(State Management)</strong></p>
<p>리액트는 각 컴포넌트의 상태(state)를 관리할 수 있는 기능을 제공합니다. 상태가 변경되면 해당 컴포넌트가 다시 렌더링되어 UI가 자동으로 업데이트됩니다. </p>
</blockquote>
<blockquote>
<p><strong>6. Hook 을 이용한 관리</strong></p>
<p>함수형 컴포넌트에서 상태와 생명주기를 쉽게 관리할 수 있도록 해줍니다. 기본적으로 제공되는 Hook 외에도 사용자 정의 Hook을 만들어 복잡한 상태 로직을 관리할 수 있습니다.</p>
</blockquote>
<blockquote>
<p><strong>7. 풍부한 생태계</strong></p>
<p>리액트는 <strong>리액트 라우터(React Router)</strong>, <strong>리덕스(Redux)</strong> 등 다양한 라이브러리와 함께 사용되어 애플리케이션의 구조와 상태 관리를 보다 쉽게 할 수 있습니다. 또한 많은 사람들이 사용하는 라이브러리 입니다.</p>
</blockquote>
<hr>
<h2 id="🔂-리액트-18-→-19-에서-달라진점">🔂 리액트 18 → 19 에서 달라진점</h2>
<h3 id="auto-batching"><strong>Auto Batching</strong></h3>
<p><strong>리액트 18</strong>: 자동 배치 기능이 도입되어 여러 상태 업데이트를 한 번의 렌더링으로 처리할 수 있게 되었습니다.</p>
<p><strong>리액트 19</strong>: 자동 배치가 더욱 강화되어 비동기 작업에서도 상태 업데이트가 자동으로 배치됩니다. 이로 인해 성능이 개선되고, 불필요한 렌더링이 줄어듭니다.</p>
<p>→ 이제는 비동기 작업에서도 상태 업데이트가 자동으로 배치되어 불필요한 렌더링이 줄어듭니다.</p>
<h3 id="concurrent-rendering"><strong>Concurrent Rendering</strong></h3>
<p><strong>리액트 18</strong>: Concurrent Mode의 기초가 도입되었으며, startTransition API가 추가되었습니다.</p>
<p><strong>리액트 19</strong>: Concurrent Rendering이 더욱 발전하여, 더 많은 기능과 최적화가 추가되었습니다. 이로 인해 더 나은 사용자 경험을 제공할 수 있습니다.</p>
<p>→ startTransition API를 통해 비동기 업데이트의 우선 순위를 조정할 수 있어, 애플리케이션의 반응성을 높일 수 있습니다.</p>
<h3 id="새로추가된-hook">새로추가된 Hook</h3>
<ul>
<li><strong>useId 훅</strong></li>
</ul>
<p>컴포넌트의 고유한 ID를 생성하여 클라이언트와 서버 간에 일관성을 유지할 수 있도록 돕습니다.</p>
<pre><code class="language-jsx">import React, { useId } from &#39;react&#39;;

const MyComponent = () =&gt; {
  const id = useId(); // 고유한 ID 생성

  return (
    &lt;div&gt;
      &lt;label htmlFor={id}&gt;Name:&lt;/label&gt;
      &lt;input id={id} type=&quot;text&quot; /&gt;
    &lt;/div&gt;
  );
};

export default MyComponent;</code></pre>
<ul>
<li><strong>useSyncExternalStore 훅</strong></li>
</ul>
<p>리액트 애플리케이션에서 외부 데이터 소스와 동기화하여 상태를 관리하는 데 사용됩니다. 이를 통해 외부 저장소의 상태를 React 상태처럼 관리할 수 있습니다.</p>
<pre><code class="language-jsx">import React, { useSyncExternalStore } from &#39;react&#39;;

// 예시 외부 저장소
const store = {
  subscribers: new Set(),
  state: { count: 0 },

  subscribe(callback) {
    this.subscribers.add(callback);
    return () =&gt; this.subscribers.delete(callback);
  },

  getSnapshot() {
    return this.state;
  },

  setCount(newCount) {
    this.state.count = newCount;
    this.subscribers.forEach(callback =&gt; callback());
  }
};

const Counter = () =&gt; {
  // 외부 저장소와 동기화된 상태 사용
  const { count } = useSyncExternalStore(store.subscribe, store.getSnapshot);

  return (
    &lt;div&gt;
      &lt;h1&gt;Count: {count.count}&lt;/h1&gt;
      &lt;button onClick={() =&gt; store.setCount(count.count + 1)}&gt;Increment&lt;/button&gt;
      &lt;button onClick={() =&gt; store.setCount(count.count - 1)}&gt;Decrement&lt;/button&gt;
    &lt;/div&gt;
  );
};

export default Counter;</code></pre>
<h3 id="suspense"><strong>Suspense</strong></h3>
<p><strong>액트 18</strong>: Suspense의 사용이 개선되어 비동기 작업에서의 대기 상태를 더 잘 처리할 수 있게 되었습니다.</p>
<p><strong>리액트 19</strong>: Suspense의 기능이 추가적으로 확장되어, 더 많은 상황에서 사용할 수 있으며, 서버 컴포넌트와의 통합이 개선되었습니다.</p>
<p>→ 이를 통해 비동기 데이터 로딩 시 UI를 더욱 매끄럽게 처리할 수 있습니다.</p>
<p>이외에도 다양한 기능들이 개선되고 추가되었습니다.</p>
<hr>
<h2 id="🎯-jsx의-기본-규칙-작성-후-예제">🎯 jsx의 기본 규칙 작성 후 예제</h2>
<h3 id="jsx-의-규칙">jsx 의 규칙</h3>
<ol>
<li>모든 태그는 반드시 닫혀 있어야 하며, 빈 태그는 /로 닫아야 합니다.</li>
<li>JSX는 항상 단일 루트 엘리먼트를 반환해야 합니다. 여러 요소를 반환하려면 하나의 부모 엘리먼트로 감싸야 합니다.</li>
<li>JSX 내부에서는 중괄호 {}를 사용하여 JavaScript 표현식을 포함할 수 있습니다. 이를 통해 변수나 함수 결과를 동적으로 렌더링할 수 있습니다.</li>
<li>JSX에서 HTML 속성은 camelCase로 작성해야 합니다. 예를 들어, class는 className으로, tabindex는 tabIndex로 작성해야 합니다.</li>
<li>JSX 내에서 조건부 렌더링을 사용할 수 있습니다. 일반적으로 &amp;&amp; 또는 삼항 연산자를 사용하여 조건부로 요소를 렌더링합니다.</li>
</ol>
<h3 id="예제">예제</h3>
<ul>
<li>모든 태그는 닫힌 태그</li>
</ul>
<pre><code class="language-jsx">// 올바른 빈 태그
const element = &lt;br /&gt;; 

// 잘못된 예
const element = &lt;br&gt;; </code></pre>
<ul>
<li>JSX는 항상 단일 루트 엘리먼트를 반환</li>
</ul>
<pre><code class="language-jsx">// 올바른 예
const element = (
  &lt;div&gt;
    &lt;h1&gt;Hello&lt;/h1&gt;
    &lt;p&gt;Welcome to JSX&lt;/p&gt;
  &lt;/div&gt;
);

// 잘못된 예
const element = (
  &lt;h1&gt;Hello&lt;/h1&gt;
  &lt;p&gt;Welcome to JSX&lt;/p&gt; // 오류 발생
);</code></pre>
<ul>
<li>javascript 표현식 포함</li>
</ul>
<pre><code class="language-jsx">const name = &quot;React&quot;;
const element = &lt;h1&gt;Hello, {name}!&lt;/h1&gt;; // &quot;Hello, React!&quot; 출력</code></pre>
<ul>
<li>camelCase 로 작성하기</li>
</ul>
<pre><code class="language-jsx">const element = &lt;div className=&quot;container&quot; tabIndex={0}&gt;Hello&lt;/div&gt;;</code></pre>
<ul>
<li>조건부 렌더링</li>
</ul>
<pre><code class="language-jsx">const isLoggedIn = true;
const element = (
  &lt;div&gt;
    {isLoggedIn ? &lt;h1&gt;Welcome back!&lt;/h1&gt; : &lt;h1&gt;Please log in.&lt;/h1&gt;}
  &lt;/div&gt;
);</code></pre>
<h2 id="🪞-리액트에서-렌더링의-정의와-초기렌더링과-리렌더링의-차이점">🪞 리액트에서 렌더링의 정의와 초기렌더링과 리렌더링의 차이점</h2>
<h3 id="렌더링이란">렌더링이란?</h3>
<p>리액트에서 컴포넌트를 화면에 표시하는 과정입니다. </p>
<p>즉, React가 상태나 속성이 변경될 때 UI를 업데이트하여 사용자가 볼 수 있도록 하는 것을 의미합니다.</p>
<h3 id="렌더링과정">렌더링과정</h3>
<ol>
<li><strong>컴포넌트 호출</strong>: React 컴포넌트가 호출되면 JSX 코드가 실행됩니다.</li>
<li><strong>가상 DOM 생성</strong>: JSX 코드에 따라 가상 DOM이 생성됩니다. 가상 DOM은 실제 DOM의 메모리 내 표현입니다.</li>
<li><strong>변경 사항 감지</strong>: 상태(state)나 속성(props)이 변경되면, React는 새로운 가상 DOM을 생성하여 이전 가상 DOM과 비교합니다.</li>
<li><strong>Diffing</strong>: React는 두 가상 DOM을 비교하여 변경된 부분을 찾습니다. 이를 통해 최소한의 변경 사항만 실제 DOM에 적용할 수 있습니다.</li>
<li><strong>실제 DOM 업데이트</strong>: 변경된 부분만 실제 DOM에 적용하여 사용자에게 새로운 UI를 보여줍니다.</li>
</ol>
<h3 id="초기렌더링과-리렌더링의-차이점">초기렌더링과 리렌더링의 차이점</h3>
<p>초기 렌더링 : 컴포넌트가 처음으로 화면에 나타나는 과정으로 컴포넌트의 초기 상태와 속성(props)에 따라 UI가 설정됩니다. </p>
<p>리렌더링 : 상태(state)나 속성(props)이 변경되어 컴포넌트가 다시 렌더링되는 과정으로 변경된 데이터에 따라 UI가 업데이트됩니다.</p>
<aside>

<p>초기렌더링은 초기 상태와 속성(props)에 따라 UI가 설정되는데 리렌더링은 렌더링과정 3번부터 실행되어 새로운 가상 DOM을 생성하여 이전 가상돔과 비교하여 실제 DOM 을 업데이트합니다.</p>
</aside>

<h2 id="props-와-state">Props 와 State</h2>
<h2 id="📖-props-의-개념과-특징">📖 Props 의 개념과 특징</h2>
<p>Props란? </p>
<p>React 의 부모 컴포넌트에서 자식 컴포넌트로 데이터를 전달하는데 사용되는 객체입니다.</p>
<p>특징 : 읽기전용, 데이터 전송, 컴포넌트 재사용성</p>
<blockquote>
<p>부모 컴포넌트로부터 데이터 전송받아서 사용할 수 있습니다.</p>
</blockquote>
<blockquote>
<p>props의 값은 변경하지 못하고 읽기 전용입니다.</p>
</blockquote>
<blockquote>
<p>각각의 컴포넌트에 다른 값을 줄 수 있어서 코드의 중복성을 줄일 수 있습니다.</p>
</blockquote>
<p>사용법</p>
<ul>
<li><p>기본</p>
<pre><code class="language-jsx">  // Profile 컴포넌트에서 Avatar 컴포넌트로 Props 보내기
  export default function Profile() {
   return (
     &lt;Avatar
       person={{ name: &#39;Lin Lanying&#39;, imageId: &#39;1bX5QH6&#39; }}
       size={100}
     /&gt;
   );
  }

  // Avatar 컴포넌트에서 Props 읽기
  function Avatar(props) {
   // props.size, props.name 으로 사용가능
  }

  function Avatar({ person, size = 100 }) {
   // 구조분해할당으로 사용가능
   // 기본값은 size prop이 없거나 size={undefined}로 전달될 때 사용됩니다.
  }</code></pre>
</li>
<li><p>모든 props</p>
<pre><code class="language-jsx">  function Profile({ person, size, isSepia, thickBorder }) { //계속 반복해서 전달하는 경우
   return (
     &lt;div className=&quot;card&quot;&gt;
       &lt;Avatar
         person={person}
         size={size}
         isSepia={isSepia}
         thickBorder={thickBorder}
       /&gt;
     &lt;/div&gt;
   );
  }

  모든 Props 전달가능

  function Profile(props) {
   return (
     &lt;div className=&quot;card&quot;&gt;
       &lt;Avatar {...props} /&gt;
     &lt;/div&gt;
   );
  }</code></pre>
</li>
<li><p>jsx</p>
<pre><code class="language-jsx">  import Avatar from &#39;./Avatar.js&#39;;

  // 자식으로 jsx를 보낼때

  function Card({ children }) {
    return (
      &lt;div className=&quot;card&quot;&gt;
        {children}
      &lt;/div&gt;
    );
  }

  export default function Profile() {
    return (
      &lt;Card&gt;
        &lt;Avatar
          size={100}
          person={{
            name: &#39;Katsuko Saruhashi&#39;,
            imageId: &#39;YfeOqp2&#39;
          }}
        /&gt;
      &lt;/Card&gt;
    )
  }</code></pre>
</li>
</ul>
<p>리하면</p>
<aside>

<p>Props는 부모컴포넌트에서 자식 컴포넌트로 데이터를 전달할때 사용되는 객체로, 자식컴포넌트에서 데이터를 읽고 사용할 수 있지만 데이터의 값을 수정할 수 는 없습니다.</p>
</aside>

<hr>
<h2 id="🔗-hook-의-개념과-규칙-종류">🔗 Hook 의 개념과 규칙, 종류</h2>
<p>개념 : Hook은 함수형 컴포넌트에서 상태와 생명주기 기능을 사용할 수 있게 해주는 특별한 함수들입니다. </p>
<p>규칙 : </p>
<ol>
<li><p>최상위 컴포넌트에서 호출</p>
<ol>
<li>Hook은 컴포넌트에서만 호출가능하고 최상위에서 호출해야 합니다. (if문, for문 안에서 호출불가능)</li>
</ol>
</li>
<li><p>함수형 컴포넌트에서만 사용가능</p>
<ol>
<li>Hook은 함수형 컴포넌트 내에서만 사용할 수 있습니다. class 형 X</li>
</ol>
</li>
<li><p>use 로 시작하기</p>
<ol>
<li>Hook은 use로 시작하는 이름을 가져야 합니다.</li>
</ol>
</li>
</ol>
<p>종류 </p>
<ul>
<li>내장 Hook<ul>
<li>useState, useEffect, useRef 등등등</li>
</ul>
</li>
<li>사용자 정의 Hook<ul>
<li>use로 시작하는 함수로, 기본 Hook을 조합하여 특정한 로직을 캡슐화할 수 있습니다.</li>
</ul>
</li>
</ul>
<p>정리하면</p>
<aside>

<p>Hook은 함수형 컴포넌트에서 상태와 생명주기 기능을 사용할 수 있게해주는 특별한 함수로</p>
<p>use로 시작하여 함수형컴포넌트의 최상위에서만 호출가능합니다.</p>
<p>종류로는 내장 Hook 과 사용자 정의 Hook 이있는데 때에 따라서 상황에 맞는 Hook을 사용하면됩니다.</p>
</aside>

<hr>
<h2 id="🤪-usestate-사용문법과-사용예제">🤪 useState 사용문법과 사용예제</h2>
<p>사용하는법</p>
<p>리액트 라이브러리에서 useState 를 불러와줍니다.</p>
<p>함수형 컴포넌트의 최상위에서 useState를 이용해서 값을 설정해줍니다.</p>
<p>자료형을 설정해주고 대괄호, 첫번째 요소는 값을 담을 변수, 두번째 요소는 값을 변경할 함수를 설정해줍니다.</p>
<p>예제 </p>
<p>input 박스의 값을 관리한다고 가정했을때</p>
<pre><code class="language-jsx">import {useState} from &#39;react&#39;

export default function Login(){
    const [id, setId] = useState(&#39;&#39;);
    //&#39;&#39; 는 초기값
    return(
        &lt;input type=&#39;text&#39; value = id onChange={e=&gt;setId(e.target.value)} /&gt;
    )
}</code></pre>
<hr>
<h2 id="🧱-함수를-이용하여-컴포넌트-작성하기">🧱 함수를 이용하여 컴포넌트 작성하기</h2>
<ol>
<li>기본 함수형컴포넌트</li>
</ol>
<p>기본사용법</p>
<pre><code class="language-jsx">function MyComponent() {
  return (
    &lt;div&gt;
      &lt;h1&gt;Hello, Function Component!&lt;/h1&gt;
    &lt;/div&gt;
  );
}

export default MyComponent;</code></pre>
<p>함수형은 export default 를 function 앞에 붙일 수 있습니다.</p>
<pre><code class="language-jsx">export default function MyComponent() {
  return (
    &lt;div&gt;
      &lt;h1&gt;Hello, Function Component!&lt;/h1&gt;
    &lt;/div&gt;
  );
}</code></pre>
<ol>
<li>화살표함수형 컴포넌트</li>
</ol>
<p>기본사용법</p>
<pre><code class="language-jsx">const MyComponent = () =&gt; {
  return (
    &lt;div&gt;
      &lt;h1&gt;Hello, Arrow Function Component!&lt;/h1&gt;
    &lt;/div&gt;
  );
};

export default MyComponent;
```![](https://velog.velcdn.com/images/dohun_08/post/7f89ec8d-e6c5-417e-af96-0867ac372b46/image.png)</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[컴퓨터 구조 08 - 1 장치 컨트롤러와 장치 드라이버]]></title>
            <link>https://velog.io/@dohun_08/%EC%BB%B4%ED%93%A8%ED%84%B0-%EA%B5%AC%EC%A1%B0-08-1-%EC%9E%A5%EC%B9%98-%EC%BB%A8%ED%8A%B8%EB%A1%A4%EB%9F%AC%EC%99%80-%EC%9E%A5%EC%B9%98-%EB%93%9C%EB%9D%BC%EC%9D%B4%EB%B2%84</link>
            <guid>https://velog.io/@dohun_08/%EC%BB%B4%ED%93%A8%ED%84%B0-%EA%B5%AC%EC%A1%B0-08-1-%EC%9E%A5%EC%B9%98-%EC%BB%A8%ED%8A%B8%EB%A1%A4%EB%9F%AC%EC%99%80-%EC%9E%A5%EC%B9%98-%EB%93%9C%EB%9D%BC%EC%9D%B4%EB%B2%84</guid>
            <pubDate>Fri, 06 Dec 2024 11:27:19 GMT</pubDate>
            <description><![CDATA[<h2 id="⛳️-시작하며">⛳️ 시작하며..</h2>
<p>컴퓨터에는 <code>CPU</code>, <code>메모리</code>만 있는 것이 아닌 <code>스피커</code>, <code>모니터</code>, <code>키보드</code>, <code>마우스</code>등등의 <strong>입출력장치</strong>와 외장 하드 디스크나 USB메모리 등 <strong>보조기억장치</strong>가 컴퓨터에 달려있습니다. 
다양한 <strong>외부 장치</strong>가 <strong>컴퓨터 내부</strong>와 어떻게 연결되고 소통하는지를 알아봅시다.</p>
<h3 id="🤮-입출력-장치의-까다로움">🤮 입출력 장치의 까다로움</h3>
<h4 id="1-입출력장치에는-종류가-너무나도-많다">1. 입출력장치에는 종류가 너무나도 많다</h4>
<p>입출력 장치만 하더라도 <code>키보드</code>, <code>모니터</code>, <code>USB 메모리</code>, <code>마우스</code>, <code>프린터</code> 등등 매우 많습니다. 장치가 이렇게 다양하면 장치마다 속도, 데이터 전송 형식 등도 다양합니다. 
따라서 </p>
<blockquote>
<p><strong>다양한 입출력 장치와 정보를 주고받는 방식을 규격화하기가 어렵습니다.</strong></p>
</blockquote>
<hr />

<h4 id="2-cpu와-메모리의-데이터-전송률은-높지만-입출력-장치의-전송률은-낮다">2. CPU와 메모리의 데이터 전송률은 높지만 입출력 장치의 전송률은 낮다</h4>
<p><code>CPU</code>와 <code>메모리</code>처럼 <strong>전송률</strong>이 높은 장치는 1초에도 수많은 데이터를 주고받을 수 있지만, <code>키보드</code>나 <code>마우스</code>와 같이 상대적으로 <strong>전송률</strong>이 낮은 장치는 같은 시간 동안 데이터를 조금씩만 주고받을 수 있습니다. 
따라서</p>
<blockquote>
<p><strong>전송률의 차이는 CPU와 메모리, 입출력장치 간의 통신을 어렵게합니다.</strong></p>
</blockquote>
<p><code>전송률</code> : 데이터를 얼마나 빨리 교환할 수 있는지를 나타낸 지표</p>
<hr />

<h2 id="🎮-장치-컨트롤러">🎮 장치 컨트롤러</h2>
<p><img src="https://velog.velcdn.com/images/dohun_08/post/a4973f67-c3d9-49b3-88e8-94f8d1a8497f/image.png" alt="">
위의 문제들을 해결하기위해
<code>입출력장치</code>는 컴퓨터에 직접 연결되지 않고 <strong>장치 컨트롤러</strong>라는 하드웨어를 통해 연결됩니다.</p>
<blockquote>
<p>장치 컨트롤러를 연결하기위한 <strong>하드웨어</strong>적인 통로    </p>
</blockquote>
<h3 id="🎒-역할">🎒 역할</h3>
<ul>
<li><p><strong>CPU와 입출력장치 간의 통신중개</strong>
<code>입출력장치</code>의 말들을 <code>CPU</code>가 받아들일 수 있도록 <strong>변환</strong>해줍니다.</p>
</li>
<li><p><strong>오류 검출</strong>
장치 컨트롤러는 자신과 연결된 <code>입출력장치</code>에 문제는 없는지 <strong>오류를 검출</strong>합니다.</p>
</li>
<li><p><strong>데이터 버퍼링</strong>
<code>버퍼링</code>이란? 전송률이 높은 장치와 낮은 장치 사이에 주고받는 데이터를 <strong>버퍼</strong>라는 임시 저장 공간에 저장하여 <strong>전송률을 비슷하게 맞추는 방법</strong></p>
</li>
</ul>
<img src = "https://velog.velcdn.com/images/dohun_08/post/5e17d351-0911-4fd0-a254-115ee24daa79/image.png" width="400" style="margin: 0 auto">

<p><code>버퍼링</code>을 이용하여 <strong>버퍼에 데이터를 조금씩 모았다가 한꺼번에 내보내거나</strong>, <strong>데이터를 한 번에 많이 받아 조금씩 내보내는 방법</strong>으로 <code>CPU</code>와 전송률이 낮은 <code>입출력장치</code>와의 전송률 차이를 완화시켜줍니다.</p>
<blockquote>
<p><strong>이러한 역할들을 통하여 입출력 장치의 까다로운점들을 모두 해결!</strong></p>
</blockquote>
<h3 id="🛠️-내부-구조">🛠️ 내부 구조</h3>
<p><img src="https://velog.velcdn.com/images/dohun_08/post/cef22677-4004-42b8-a3f6-fb00490185c6/image.png" alt=""></p>
<ul>
<li><p><strong>데이터 레지스터</strong></p>
</li>
<li><p><em>버퍼링*</em>을 위해 <code>CPU</code>와 <code>입출력장치</code> 사이에 주고받을 <strong>데이터가 담기는 레지스터</strong>.
데이터를 모았다가 전달하는 <strong>버퍼역할</strong>을 해줌</p>
</li>
<li><p><strong>상태 레지스터</strong>
<code>입출력장치</code>가 입출력 작업을 할 준비가 되었는지, 입출력 작업이 완료되었는지, <code>입출력장치</code>에 오류는 없는지 등의 <strong>상태 정보가 저장</strong>됩니다.</p>
</li>
<li><p><strong>제어 레지스터</strong>
<code>입출력장치</code>가 수행할 내용에 대한 <strong>제어 정보와 명령을 저장</strong>합니다.</p>
</li>
</ul>
<h2 id="🪛-장치-드라이버">🪛 장치 드라이버</h2>
<p><img src="https://velog.velcdn.com/images/dohun_08/post/5246f6b1-da89-44d1-9154-3d431ed95153/image.png" alt=""></p>
<p>장치 컨트롤러의 동작을 감지하고 제어함으로써 장치 컨트롤러가 컴퓨터 내부와 정보를 주고받을 수 있게 하는 <code>프로그램</code>입니다. 
장치 드라이버를 인식하고 실행할 수 있다면 어디회사의 제품이건 사용할 수 있습니다. 
반대로 장치 드라이버를 인식하지 못한다면 <code>입출력장치</code>를 사용할 수 없습니다.</p>
<blockquote>
<p>입출력 장치를 연결하기 위한 <strong>소프트웨어</strong>적인 통로</p>
</blockquote>
<h3 id="💻-장치-드라이버를-실행시키는-주체">💻 장치 드라이버를 실행시키는 주체</h3>
<p>...그것은 <code>운영체제</code>
<strong>운영체제가 장치 드라이버를 인식하고 실행할 수 있다면 입출력장치와 컴퓨터 내부의 정보를 주고받을 수 있습니다.</strong>
운영체제에 기본적으로 깔려있는 장치 드라이버들도 있지만 
장치 제작자가 장치 드라이버를 따로 제공하는 경우 입출력장치는 해당 드라이버를 <strong>직접 설치해야만 사용이 가능합니다.</strong></p>
<h2 id="마무리">마무리..</h2>
<p>아두이노를 노트북이 인식을 못했던 경험이 있었는데 그걸 해결할려고 CH340이라는 프로그램을 깔아서 실행시켰던 경험이 있습니다. 이때는 이해가되지 않았지만 이제는 이해가되어 다른 입출력장치를 사용할때도 고려해봐야겠습니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[해싱에대해 알아보기]]></title>
            <link>https://velog.io/@dohun_08/%ED%95%B4%EC%8B%B1%EC%97%90%EB%8C%80%ED%95%B4-%EC%95%8C%EC%95%84%EB%B3%B4%EA%B8%B0-with-%EC%83%81%ED%99%94%EC%8C%A4</link>
            <guid>https://velog.io/@dohun_08/%ED%95%B4%EC%8B%B1%EC%97%90%EB%8C%80%ED%95%B4-%EC%95%8C%EC%95%84%EB%B3%B4%EA%B8%B0-with-%EC%83%81%ED%99%94%EC%8C%A4</guid>
            <pubDate>Wed, 20 Nov 2024 03:36:33 GMT</pubDate>
            <description><![CDATA[<h2 id="🔑-해싱이란">🔑 해싱이란?</h2>
<p><img src="https://velog.velcdn.com/images/dohun_08/post/15bf0afb-5792-4492-8102-067ec66b088b/image.png" alt=""></p>
<p><strong>키에 산술적인 연산을 적용하여</strong> 항목이 저장되어 있는 테이블의 주소를 계산하여 항목에 접근한다. 
이렇게 <strong>키에 대한 연산에 의해 직접 접근이 가능한 구조를 해시 테이블이라 부르며, 해시 테이블을 이용한 탐색을 해싱이라 한다.</strong></p>
<blockquote>
<h3 id="현상">현상</h3>
</blockquote>
<ul>
<li><strong>충돌</strong>
서로 다른 키를 갖는 항목들이 같은 해시주소를 가지는 현상이다.</li>
<li><strong>오버플로우</strong>
충돌이 발생하고, 해시 주소에 더이상 빈 버킷이 남아 있지 않으면 발생한다. 오버플로우가 발생하면 해시테이블에 항목을 더 이상 저장하는 것이 불가능해진다.</li>
</ul>
<h2 id="해싱방법">해싱방법</h2>
<h3 id="선형조사법">선형조사법</h3>
<p><img src="https://velog.velcdn.com/images/dohun_08/post/c98a6fae-59d6-4337-9301-0df02ed41f64/image.png" alt=""></p>
<p><strong>만약 충돌이 ht[k]에서 발생했다면 ht[k+1]이 비어 있는지를 살펴본다.</strong>
만약 비어있지 않다면 ht[k+2]를 살펴본다. 이런 식으로 비어있는 공간이 나올 때까지 계속하여 조사하는 방법이다.
만약 테이블의 끝에 도달하게 되면 다시 테이블의 처음으로 간다.
만약 조사를 시작했던 곳으로 되돌아오게 되면 테이블이 가득 찬 것으로 판단한다.</p>
<blockquote>
<h4 id="문제점">문제점</h4>
<p><strong><code>클러스터링문제</code></strong> : 저장된 숫자들이 모여있을때 탐색횟수가 늘어나게되는 문제</p>
</blockquote>
<h3 id="이차조사법">이차조사법</h3>
<p><img src="https://velog.velcdn.com/images/dohun_08/post/f5fe33a7-78e5-4b09-89c5-aa333d8659ef/image.png" alt=""></p>
<p>이차조사법에서는 만약 충돌이 ht[k]에서 발생했다면 ht[k+1]이 비어 있는지를 살펴본다. 만약 비어있지 않다면 ht[k+4]를 살펴본다.
<strong>이런 식으로 비어있는 공간이 나올 때까지 k+n제곱으로 계속하여 조사하는 방법이다.</strong>
만약 테이블의 끝에 도달하게 되면 다시 테이블의 처음으로 간다.
만약 조사를 시작했던 곳으로 되돌아오게 되면 테이블이 가득 찬 것으로 판단한다.</p>
<blockquote>
<h4 id="문제점-1">문제점</h4>
<p><strong><code>클러스터링문제</code></strong> : 2차 클러스터링 문제 -&gt; 집중되어지는 slot을 중심으로 클러스터링이 발생될 확률이 여전히 높다</p>
</blockquote>
<h3 id="이중해싱법">이중해싱법</h3>
<p><img src="https://velog.velcdn.com/images/dohun_08/post/98629f2f-c4d1-470d-aa06-b23937dc4a4d/image.png" alt=""></p>
<p><strong>이중해싱법에서는 만약 충돌이 ht(k)에서 발생했다면 (h(k)+1*h&#39;(k))이 비어 있는지를 살펴본다.</strong>
만약 비어있지 않다면 (h(k)+2*h&#39;(k))를 살펴본다.
이런 식으로 비어있는 공간이 나올 때까지 계속하여 조사하는 방법이다.
만약 테이블의 끝에 도달하게 되면 다시 테이블의 처음으로 간다.
만약 조사를 시작했던 곳으로 되돌아오게 되면 테이블이 가득 찬 것으로 판단한다.</p>
<h3 id="체인법">체인법</h3>
<p><img src="https://velog.velcdn.com/images/dohun_08/post/5abd111d-16e4-4bf2-be06-d171773b6f2e/image.png" alt=""></p>
<p>*<em>충돌을 해결하는 두 번째 방법은 해시 테이블의 구조를 변경하여 각 버킷이 하나 이상의 값을 저장할 수 있도록 하는 것이다. *</em>
즉, 각 버킷에 고정된 슬롯을 할당하는 것이 아니라 각 버킷에 삽입과 삭제가 용이한 연결 리스트를 할당한다. 
물론 버킷 내에서는 원하는 항목을 찾을 때는 연결 리스트를 순차 탐색한다.</p>
<blockquote>
<h4 id="문제점-2">문제점</h4>
<p>링크 공간의 필드가 필요하다</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[합병정렬 알고리즘 with 상화쌤]]></title>
            <link>https://velog.io/@dohun_08/%ED%95%A9%EB%B3%91%EC%A0%95%EB%A0%AC-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-with-%EC%83%81%ED%99%94%EC%8C%A4</link>
            <guid>https://velog.io/@dohun_08/%ED%95%A9%EB%B3%91%EC%A0%95%EB%A0%AC-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-with-%EC%83%81%ED%99%94%EC%8C%A4</guid>
            <pubDate>Wed, 13 Nov 2024 03:19:08 GMT</pubDate>
            <description><![CDATA[<h2 id="🧐-합병정렬이란">🧐 합병정렬이란?</h2>
<blockquote>
<p><strong>분할 정복 알고리즘!</strong></p>
</blockquote>
<p><strong>하나의 리스트</strong>를 <strong>두 개의 균등한 크기</strong>로 <strong><code>분할</code></strong>하고 분할된 부분 리스트를 정렬한 다음, 
두 개의 <strong>정렬된 부분 리스트</strong>를 <strong><code>합하여</code></strong> 전체가 정렬된 리스트를 얻고자 하는 것</p>
<h2 id="☑️-장단점">☑️ 장단점</h2>
<h3 id="장점">장점</h3>
<ul>
<li><p><strong>빠른속도를 자랑합니다.</strong>
데이터의 영향을 작게받아서 <code>최악</code>, <code>평균</code>, <code>최선</code>의 경우 모두 <strong>O(n log n)</strong>의 시간 복잡도를 가집니다.</p>
</li>
<li><p><strong>큰 데이터 정렬에 적합합니다.</strong> 
메모리에 다 담을 수 없는 큰 파일을 정렬해야 할 때, 하드 디스크 등의 외부 저장 장치를 활용해 부분적으로 나눠서 정렬한 후 병합하는 방식으로 사용할 수 있습니다</p>
</li>
</ul>
<h3 id="단점">단점</h3>
<ul>
<li><p><strong>작은 데이터에서는 오히려 비효율적</strong>
작은 데이터에서는 오히려 비효율적이어서 삽입 정렬 같은 알고리즘보다 느릴 수 있습니다.</p>
</li>
<li><p><strong>병합 과정에서 추가적인 연산 필요</strong>
병합 과정에서 추가적인 연산 필요하여 배열을 쪼개고 병합하는 과정이 많아 캐시 효율성이 떨어질 수 있습니다.</p>
<h2 id="🛠️-방법">🛠️ 방법</h2>
<p><img src="https://velog.velcdn.com/images/dohun_08/post/0748edde-b7b2-45f7-bfeb-01cc0435fdca/image.png" alt=""></p>
</li>
</ul>
<ol>
<li><p><strong>분할</strong> : 입력 배열을 같은 크기의 <strong><code>2개의 부분 배열</code></strong>로 분할한다. </p>
</li>
<li><p><strong>정복</strong> : 부분 <strong><code>배열을 정렬</code></strong>한다. 부분 배열의 크기가 충분히 작지 않으면 순환 호출을 이용하여 다시 분할 정복 기법을 적용한다.</p>
</li>
<li><p><strong>결합</strong> : 정렬된 부분 배열들을 <strong><code>하나의 배열</code></strong>에 통합한다.</p>
</li>
</ol>
<h3 id="코드">코드</h3>
<pre><code class="language-c">#include &lt;stdio.h&gt;
int sorted[100],count;

void merge(int list[], int left,int mid, int right)
{
    int i,j,k,l;
    i=left;
    j=mid+1;
    k=left;
    while(i&lt;=mid &amp;&amp; j&lt;=right)
    {
        if(list[i]&lt;=list[j])
        {
            sorted[k++]=list[i++];
        }
        else
        {
            sorted[k++]=list[j++];
        }
    }
    if(i&gt;mid)
    {
        for(l=j; l&lt;=right; l++)
        {
            sorted[k++]=list[l];
        }
    }
    else
    {
        for(l=i; l&lt;=mid; l++)
        {
            sorted[k++]=list[l];
        }
    }
    for(l=left; l&lt;=right; l++)
    {
        list[l]=sorted[l];
    }
}

void mergesort(int list[], int left,int right)
{
    int mid;
    if(left&lt;right)
    {
        mid=(left+right)/2;
        mergesort(list,left,mid);
        mergesort(list,mid+1,right);
        merge(list,left,mid,right);
    }
}

int main()
{
    int list[4]={27,12,20,25};
    mergesort(list,0,3);
    for(int i=0; i&lt;4; i++)
    {
        printf(&quot;%d &quot;,list[i]);
    }
    return 0;
}</code></pre>
<h2 id="마무리">마무리</h2>
<p>퀵정렬, 합병정렬등 상황에 맞게 써야겠다</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Recoil 정리하기]]></title>
            <link>https://velog.io/@dohun_08/Recoil-%EC%A0%95%EB%A6%AC%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@dohun_08/Recoil-%EC%A0%95%EB%A6%AC%ED%95%98%EA%B8%B0</guid>
            <pubDate>Wed, 06 Nov 2024 15:00:28 GMT</pubDate>
            <description><![CDATA[<h2 id="recoil이란">Recoil이란?</h2>
<blockquote>
<p>전역 <strong>상태</strong>를 관리해주는 라이브러리입니다.
<code>props</code>로만 상태를 주고받는 불편함을 없애주기 위해서 생겼습니다.</p>
</blockquote>
<h3 id="atom">atom</h3>
<p>리코일에서 상태를 정의할 때 사용되는 <strong>가장 작은 단위</strong>입니다.
<strong>값을 저장</strong>하고 <strong>컴포넌트에서 불러와 사용</strong>할 수 있습니다.</p>
<h3 id="selector">selector</h3>
<p>셀렉터는 아톰이나 다른 셀렉터의 값을 기반으로 파생된 상태를 <strong>계산하는 함수</strong>입니다.
<strong>아톰의 값을 가공</strong>하거나 <strong>여러 아톰을 조합</strong>해서 새로운 값을 만들 때 사용됩니다.</p>
<h2 id="왜-쓰는건데">왜 쓰는건데?</h2>
<p><img src="https://velog.velcdn.com/images/dohun_08/post/436766b6-8bc4-434f-81aa-06f1990d1ccd/image.png" alt=""></p>
<ul>
<li>원래는 <code>props</code>로 전달해서 컴포넌트끼리 상태를 계속 주고받았다면 리코일을 사용하여 <strong>전역으로 상태를 관리</strong>할 수 있어서 편리합니다.</li>
<li>배우기도 <strong>쉽고</strong> <strong>간편</strong>하여 바로 배우고 써먹을 수도 있습니다.(리액트 <code>useState</code> 사용과 유사)</li>
<li><strong>렌더링 수를 최소화</strong> 할 수 있습니다.<h2 id="사용방법">사용방법</h2>
<h3 id="라우터-감싸기">라우터 감싸기</h3>
<img src="https://velog.velcdn.com/images/dohun_08/post/d814956d-f847-4598-a358-52459217a19b/image.png" alt="">
<code>RecoilRoot</code>로 상태를 사용할 <strong>컴포넌트를 감싸줍니다.</strong><h3 id="아톰-생성하기">아톰 생성하기</h3>
<img src="https://velog.velcdn.com/images/dohun_08/post/6f502f98-6569-4c78-97ce-2614bf62256f/image.png" alt="">
아톰을 생성할때는 지정 <code>key</code>가 필요합니다.
<code>key</code>는 아톰의 고유한 <strong>속성</strong>을 나타내줍니다.
<code>default</code>에는 <strong>아톰의 값</strong>들이 들어있습니다.
<code>default</code>를 <strong>객체나 리스트</strong>로 선언해서 사용하는것도 쌉가능!</li>
</ul>
<h3 id="아톰-사용하기">아톰 사용하기</h3>
<p><img src="https://velog.velcdn.com/images/dohun_08/post/2f7439ee-9102-432a-a34a-12683295d18f/image.png" alt=""></p>
<p>아톰을 <code>useRecoilState</code>를 이용해 불러옵니다.
<code>countAtom</code>을 <code>import</code>해와서 생성했던 아톰을 불러와줍니다. 
<code>default</code>에 있는 <strong>값들을 사용</strong>할 수 있습니다.
<code>setCount</code>같이 <code>defualt</code>의 값들을 <strong>업데이트</strong> 시킬 수도 있습니다.</p>
<blockquote>
<p>⭐️ <code>useRecoilState</code> 아니여도 값만 사용하고 싶다면 <code>useRecoilValue</code>를 추천합니다.</p>
</blockquote>
<h3 id="셀렉터-생성하기">셀렉터 생성하기</h3>
<p><img src="https://velog.velcdn.com/images/dohun_08/post/615cedcc-122e-40d3-bff8-93e7d00cbdd9/image.png" alt="">
셀렉터에도 고유한 <code>key</code>를 선언해줍니다.
<code>get</code>으로 아톰의 값을 가져와서 <strong>값을 가공시켜 리턴</strong>해줄 수 있습니다.
<code>setCount</code>같은거를 <strong>미리 선언</strong>할 수 있다고 볼 수 있죠.</p>
<h3 id="셀렉터-사용하기">셀렉터 사용하기</h3>
<p><img src="https://velog.velcdn.com/images/dohun_08/post/64cbdb80-d563-40b6-bd87-8d0a47955ef9/image.png" alt="">
<code>isEvenState</code>를 <code>useRecoilValue</code>를 이용<img src="https://velog.velcdn.com/images/dohun_08/post/49503ec6-dee1-4d4a-8f04-80f76b5233b5/image.png" alt="">
해 <strong>값만</strong> 불러올 수 있습니다.
<code>isEven</code>에는 카운트될때마다 Odd, Even이 번갈아가며 나타나게됩니다.
<strong>셀렉터로는 이밖에도 비동기식도 처리할 수 있습니다.</strong></p>
<h2 id="마무리">마무리</h2>
<p>이 리코일을 이용해서 전역상태를 깔끔하게 관리해봅시당 ㅎㅎㅎㅎㅎㅎ</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[퀵 정렬, 정리하기 (with상화T)]]></title>
            <link>https://velog.io/@dohun_08/%ED%80%B5-%EC%A0%95%EB%A0%AC%EC%9D%84-%EC%A0%95%EB%A6%AC%ED%95%B4%EB%B3%B4%EC%9E%90-with%EC%83%81%ED%99%94T</link>
            <guid>https://velog.io/@dohun_08/%ED%80%B5-%EC%A0%95%EB%A0%AC%EC%9D%84-%EC%A0%95%EB%A6%AC%ED%95%B4%EB%B3%B4%EC%9E%90-with%EC%83%81%ED%99%94T</guid>
            <pubDate>Wed, 06 Nov 2024 02:46:21 GMT</pubDate>
            <description><![CDATA[<h2 id="🏆-퀵정렬이란">🏆 퀵정렬이란?</h2>
<blockquote>
<p>평균적으로 매우 빠른 수행 속도를 자랑하는 정렬 방법입니다.</p>
</blockquote>
<ul>
<li><p>전체리스트를 2개의 부분 리스트로 <code>분할</code>하고, 각가의 부분 리스트를 다시 <code>퀵정렬</code>하는 전형적인 <code>분할정복법</code>을 사용.</p>
</li>
<li><p><code>피벗</code>을 설정하고 <code>피벗</code>을 기준으로 좌우에 <strong>작은값</strong>, <strong>큰값</strong>을 놓는 방법을 반복합니다.</p>
</li>
<li><p>시간복잡도 : <strong>O(nlogn)</strong></p>
</li>
</ul>
<blockquote>
<p>⭐️ <span style="color:red;"><strong>분활정복법</strong></span>이란? 
문제를 조금씩 나눠가면서 문제를 푼 다음 마지막에 합쳐서 문제를 해결</p>
</blockquote>
<h2 id="🛠️-퀵정렬-방식">🛠️ 퀵정렬 방식</h2>
<blockquote>
<ol>
<li><strong>피벗선택</strong></li>
<li><strong>Low, High 지정 후 교환</strong></li>
<li><strong>피벗과 High값을 교환</strong></li>
<li><strong>왼쪽, 오른쪽에 있는 리스트에 1~4의 과정반복</strong></li>
</ol>
</blockquote>
<p>*이 방식은 왼쪽을 피벗으로 선택하여하는 퀵정렬입니다.</p>
<h3 id="피벗선택">피벗선택</h3>
<p><img src="https://velog.velcdn.com/images/dohun_08/post/723f71be-5590-4b1d-893b-dc295227abf9/image.png" alt="">
<strong><code>피벗</code></strong>과 <strong><code>low</code></strong>, <strong><code>high</code></strong>값들을 지정해줍니다.
<strong><code>피벗</code></strong>은 제일 첫번째 요소로 지정해줍니다.
초기의 <strong><code>low</code></strong>는 <strong><code>피벗</code></strong>보다 + 1
초기의 <strong><code>high</code></strong>는 <code>right</code>와 같이 합니다.</p>
<h3 id="low-high-지정">Low High 지정</h3>
<p><img src="https://velog.velcdn.com/images/dohun_08/post/7d5839e5-a621-44c9-894f-379766893f2d/image.png" alt="">
왼쪽에 <strong><code>피벗</code></strong>보다 작은값, 오른쪽에는 <strong><code>피벗</code></strong>보다 큰값으로 넣기위해서
low는 <strong><code>피벗</code></strong>보다 작은값이라면 +1을 해주며 옮깁니다.
high는 <strong><code>피벗</code></strong>보다 큰값이라면 -1을 해주며 옮깁니다.
만약 low가 <strong><code>피벗</code></strong>보다 큰값을만나면 멈추고 high도 <strong><code>피벗</code></strong>보다 작은값을만나면 멈춥니다.
멈춘둘은 값을 교환해줍니다.</p>
<h3 id="피벗과-high-교환">피벗과 High 교환</h3>
<p><img src="https://velog.velcdn.com/images/dohun_08/post/8e6e8b98-b6ab-45eb-899b-1db731db593e/image.png" alt="">
위의 작업을 반복하면 그림과 같이 <span style="background:#67B5FF; border-radius: 5px; padding:5px; color:white; font-weight:600;">low &gt; high</span> 의 상황이 생깁니다. 
이때 high의 값과 <strong><code>피벗</code></strong>의 값을 교환해줍니다.
그렇게 된다면 <strong><code>피벗</code></strong>의 왼쪽에는 <strong><code>피벗</code></strong>보다 작은값들이, 
<strong><code>피벗</code></strong>의 오른쪽에는 <strong><code>피벗</code></strong>보다 큰 값들이 있을것입니다.</p>
<h3 id="반복">반복</h3>
<p><strong><code>피벗</code></strong>보다 작은쪽에 있는 값들로 위의 과정을 반복하고
<strong><code>피벗</code></strong>보다 큰쪽에 있는 값들로 위의 과정을 반복합니다.
반복했을때 마지막에는 정렬됩니다.</p>
<h4 id="코드">코드</h4>
<pre><code class="language-c">#include &lt;stdio.h&gt;
#define swap(x,y,t) ((t)=(x), (x)=(y), (y)=(t))
int partition(int list[], int left,int right)
{
    int pivot,temp,low,high;
    low = left;
    high= right+1;
    pivot=list[left];
    do
    {
        do
        {
            low++;
        }while(list[low]&lt;pivot &amp;&amp; low&lt;=right);
        do
        {
            high--;
        }while(list[high]&gt;pivot);

        if(low&lt;high)
        {
            swap(list[low],list[high],temp);
        }
    }while(low&lt;high);
    swap(list[left],list[high],temp);
    return high;
}

void quicksort(int list[], int left,int right)
{
    if(left&lt;right)
    {
        int q=partition(list, left, right);
        quicksort(list,left,q-1);
        quicksort(list,q+1,right);
    }
}

int main()
{
    int list[6]={10,2,20,7,50,1};
    quicksort(list,0,5);
    for(int i=0; i&lt;6; i++)
    {
        printf(&quot;%d &quot;,list[i]);
    }
    return 0;
}</code></pre>
<h2 id="퀵정렬의-장단점">퀵정렬의 장단점</h2>
<h3 id="🙆♂️-장점">🙆‍♂️ 장점</h3>
<ol>
<li><p><strong>정렬된 상태가 아닌 이상 시간복잡도가 O(nlogn)이라서 속도가 매우 빠릅니다.</strong></p>
</li>
<li><p><strong>추가 메모리를 거의 사용하지 않기에 대규모 데이터를 다룰 때 메모리 사용량이 상대적으로 적습니다.</strong></p>
</li>
</ol>
<h3 id="🙅♂️-단점">🙅‍♂️ 단점</h3>
<ol>
<li><p>** 특정 조건(정렬된 상태) 하에 성능이 급격하게 떨어진다. (O(n2))**</p>
</li>
<li><p><strong>퀵 정렬은 재귀적으로 구현되기 때문에, 배열이 매우 클 경우 스택 오버플로우가 발생할 수 있습니다.</strong> </p>
<h2 id="마무리">마무리</h2>
<p><img src="https://velog.velcdn.com/images/dohun_08/post/200dd403-9db2-4e26-a5d8-82b14d3ff074/image.png" alt=""></p>
<blockquote>
<p><img src="https://velog.velcdn.com/images/dohun_08/post/e036673e-9275-4c3d-ad67-90114870ecb8/image.png" alt="">
근데 킹갓 파이썬에서는 딸깍 몇번으로 퀵정렬 할 수 있습니다...네...감사합니다</p>
</blockquote>
</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[리액트에서 Proxy 설정에대해 알아보자!]]></title>
            <link>https://velog.io/@dohun_08/%EB%A6%AC%EC%95%A1%ED%8A%B8%EC%97%90%EC%84%9C-Proxy-%EC%84%A4%EC%A0%95%EC%97%90%EB%8C%80%ED%95%B4-%EC%95%8C%EC%95%84%EB%B3%B4%EC%9E%90</link>
            <guid>https://velog.io/@dohun_08/%EB%A6%AC%EC%95%A1%ED%8A%B8%EC%97%90%EC%84%9C-Proxy-%EC%84%A4%EC%A0%95%EC%97%90%EB%8C%80%ED%95%B4-%EC%95%8C%EC%95%84%EB%B3%B4%EC%9E%90</guid>
            <pubDate>Sun, 27 Oct 2024 08:11:18 GMT</pubDate>
            <description><![CDATA[<h2 id="proxy가-뭐야">Proxy가 뭐야?</h2>
<p>영어단어로 <code>Proxy</code>란 대리 라는 의미를 가지고 있습니다.
<code>프론트</code>에서의 요청을 받고 <code>서버</code>대신 데이터를 전달해주는 의미로 볼 수 도 있습니다.</p>
<blockquote>
</blockquote>
<p>a 가 <code>프론트</code>, c가 <code>서버</code>일때 원래는 a - c 이렇게 데이터를 주고받았다면
<code>프록시</code> b 를 통해서 a - b - c 형태로 주고받을 수 있습니다.</p>
<h2 id="하면-좋은점들">하면 좋은점들</h2>
<h3 id="1-cors-문제-해결">1. CORS 문제 해결</h3>
<p><code>Proxy</code>는 다른 도메인 간의 <code>데이터</code> 요청 시 발생하는 <code>CORS</code> 문제를 우회할 수 있게 해줍니다. <code>Proxy</code>를 사용하면 <code>서버</code>끼리의 통신으로 간주하여 제한을 피할 수 있습니다.</p>
<h3 id="2-간편한-개발-환경-설정">2. 간편한 개발 환경 설정</h3>
<pre><code class="language-js">//프록시 설정없이
const addTodo = async () =&gt; {
      const response = await axios.post(&quot;http://localhost:8080/user/insert&quot;, {
          task:newTodo
      })
};
//프록시 설정 on
const addTodo = async () =&gt; {
      const response = await axios.post(&quot;/user/insert&quot;, {
          task:newTodo
      })
};</code></pre>
<p>간단하게 할일을 추가하는 axios문 입니다. <code>Proxy</code> 설정으로 인해 axios문마다 굳이 <a href="http://localhost:8080">http://localhost:8080</a> 해주지 않아도 처음으로 자신의 <code>url</code>에 있나 확인 후 없다면 <code>Proxy</code>에 있는 <code>url</code>을 사용하여 api요청을 보냅니다.</p>
<h3 id="3-보안-및-로깅-기능-강화">3. 보안 및 로깅 기능 강화</h3>
<p><code>Proxy</code> 서버는 데이터 요청을 중간에서 <code>필터링</code>할 수 있기 때문에, <code>요청 기록</code>(log) 관리와 <code>보안 필터링</code> 기능을 제공합니다. 이를 통해 애플리케이션 보안을 강화하거나 요청 데이터를 더 잘 추적할 수 있습니다.</p>
<h3 id="4속도-개선">4.속도 개선</h3>
<p><code>캐싱 기능</code>을 설정해 같은 요청에 대한 응답을 <code>Proxy</code> 서버에 <code>저장</code>함으로써 다음 요청에 대해 더 <code>빠르게</code> 응답을 제공하여 불필요한 연산을 줄여줍니다.</p>
<p>이밖에도 다양한 좋은기능들이 있을겁니다. 네</p>
<h2 id="리액트에-적용시켜보자">리액트에 적용시켜보자</h2>
<h3 id="pakagejson-방법">pakage.json 방법</h3>
<pre><code class="language-js">//pakage.json
{
  ...(다양한 스크립트들),
  &quot;proxy&quot;: &quot;http://localhost:5000&quot;  // 프록시 추가
}
</code></pre>
<blockquote>
<p>pakage.json에 스크립트로 프록시를 추가하면 프록시 설정 끝
간단하쥬?</p>
</blockquote>
<h3 id="라이브러리-활용하기">라이브러리 활용하기</h3>
<ol>
<li><p><code>http-proxy-middleware</code> 라이브러리 설치하기</p>
<pre><code class="language-bash">npm install http-proxy-middleware --save</code></pre>
</li>
<li><p><code>src/setupProxy.js</code> 파일 생성
src 폴더에 setupProxy.js 파일을 만듭니다. 이 파일이 존재하면 create-react-app에서 자동으로 인식하여 프록시 설정을 적용합니다.</p>
</li>
<li><p><code>프록시 설정</code> 코드 추가</p>
<pre><code class="language-js">// src/setupProxy.js
const { createProxyMiddleware } = require(&#39;http-proxy-middleware&#39;);
</code></pre>
</li>
</ol>
<p>module.exports = function (app) {
  app.use(
    createProxyMiddleware({
      target: &#39;<a href="http://localhost:5000&#39;">http://localhost:5000&#39;</a>, // 백엔드 서버 주소
      changeOrigin: true,
    })
  );
};</p>
<pre><code>이렇게하면 설정 끝~

## 마치며
앞으로 프록시서버를 잘 이용해서 개발해보도록 하겠습니다. 감사합니다.</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[TypeScript 기본 사용 정리]]></title>
            <link>https://velog.io/@dohun_08/TypeScript-%EA%B8%B0%EB%B3%B8-%EC%82%AC%EC%9A%A9-%EC%A0%95%EB%A6%AC</link>
            <guid>https://velog.io/@dohun_08/TypeScript-%EA%B8%B0%EB%B3%B8-%EC%82%AC%EC%9A%A9-%EC%A0%95%EB%A6%AC</guid>
            <pubDate>Sat, 26 Oct 2024 08:29:05 GMT</pubDate>
            <description><![CDATA[<h2 id="왜-사용하지">왜 사용하지?</h2>
<p><code>타입스크립트</code>는 기본적으로 <code>변수</code>나 <code>함수</code>의 <code>타입</code>을 지정해줄 수 있습니다. </p>
<blockquote>
<p>데이터를 주고받을때 데이터의 <code>타입</code>이 객체여야하는데 <code>문자열</code>로 와서 오류를 일으킨다?</p>
</blockquote>
<blockquote>
<p>오류가나서 오류메시지를 확인했더니 다른곳을 가르키면서 여기 오류났다고 알려준다?</p>
</blockquote>
<blockquote>
<p>props로 받아왔는데 이 prop이 어떤 prop인지 어케알아? - 그렇기에 propsType을 사용함...</p>
</blockquote>
<p>이러한 상황을 방지하기위해서 타입스크립트를 써야합니다.
걍 유용합니다. 얼른 js에서 갈아탑시다.</p>
<h2 id="기본으로-알아야할것들">기본으로 알아야할것들</h2>
<p>타입을 지정해주는 방법으로 크게 type과 interface가 있습니다.
user의 데이터 타입을 정의해 보겠습니다. </p>
<h3 id="type">type</h3>
<p><img src="https://velog.velcdn.com/images/dohun_08/post/d0b3df15-daef-45a7-94ab-fff8984a5818/image.png" alt=""></p>
<p>기본적으로 type 이름과 함께 타입을 정의해주시면 됩니다.
배열은 type 이름 = 타입[]; 한다면 해당타입의 배열을 지정해줄 수 있습니다.
객체는 중괄호!
또한 |이나 &amp; 타입을 활용하여 설정해주기도 가능!!</p>
<h3 id="interface">interface</h3>
<p><img src="https://velog.velcdn.com/images/dohun_08/post/36ea4bcf-7523-438c-997f-8cf06f7b96b2/image.png" alt="">
객체의 형태로 만들어져 객체의 타입을 지정하는데 유리합니다.
interface에 interface를 상속받아서 User에는 live라는게 없지만 상속을 통해 있는것으로 간주합니다.</p>
<blockquote>
<p><strong><code>type</code>과 <code>interface</code>의 차이점</strong>
<code>type</code>: <code>유니언</code>(|) 및 <code>교차</code>(&amp;) 타입을 쉽게 사용할 수 있어, 여러 타입을 결합하거나 선택적 타입을 설정할 때 유용합니다.
<code>interface</code>: 주로 <code>객체</code>의 구조를 설명하는 데 특화되어 있습니다.
또한 <code>extends</code>를 사용해 다른 인터페이스를 <code>상속</code>받습니다.
<strong>정리</strong>
<code>interface</code>는 <code>객체</code>를 정의하는데 유리
<code>type</code>은 여러 타입을 조합할때 유리</p>
</blockquote>
<h3 id="pick-omit">Pick, Omit</h3>
<h4 id="pick">Pick</h4>
<pre><code class="language-typescript">interface User {
  id: number;
  name: string;
  age: number;
  email: string;
}

// User 타입에서 id와 name 속성만 선택
type UserPreview = Pick&lt;User, &quot;id&quot; | &quot;name&quot;&gt;;

const user: UserPreview = {
  id: 1,
  name: &quot;Alice&quot;
  // age나 email을 추가하면 오류 발생
};</code></pre>
<p>Pick은 원래있던 인터페이스에서 골라올 수 있습니다. 내가 사용하고 싶은 인터페이스에서 조금만 골라내면될때 굳이 다시 선언을 하지않더라도 쓸 수 있는 유용한친구입니다.</p>
<h4 id="omit">Omit</h4>
<pre><code class="language-typescript">interface User {
  id: number;
  name: string;
  age: number;
  email: string;
}

// User 타입에서 id와 email 속성을 제외
type UserWithoutContactInfo = Omit&lt;User, &quot;id&quot; | &quot;email&quot;&gt;;

const user: UserWithoutContactInfo = {
  name: &quot;Alice&quot;,
  age: 25
  // id나 email을 추가하면 오류 발생
};</code></pre>
<p>Omit은 Pick과 반대로 몇개만 빼고싶을때 쓸 수 있습니다.</p>
<h3 id="제네릭">제네릭</h3>
<p><img src="https://velog.velcdn.com/images/dohun_08/post/38dff150-4eb8-48ba-9d59-766d56f47dbd/image.png" alt=""></p>
<p>제네릭은 타입계의 변수같은느낌? 어떤 타입이 올지 모를때는 제네릭을 활용하여 선언해주면 개꿀딱지 ㅎㅎ</p>
<h2 id="타입-설정하기">타입 설정하기</h2>
<h3 id="타입">타입</h3>
<p><img src="https://velog.velcdn.com/images/dohun_08/post/457e23d2-46fa-4e43-a1e9-b389a07db17c/image.png" alt=""></p>
<blockquote>
<p>타입안에 타입을 선언하기도 쌉가능!!!
이것으로 반복되는 코드들을 줄일 수 있어서 행복합니다 ㅎㅎ</p>
</blockquote>
<h3 id="변수">변수</h3>
<p><img src="https://velog.velcdn.com/images/dohun_08/post/4aed4023-1752-4886-96c8-ce573ff32bc6/image.png" alt=""></p>
<blockquote>
<p>number, string, 등등 선언해줄 수 있습니다.
위에서 선언해주었던 type도 이용해서 선언할 수 있습니다.</p>
</blockquote>
<h3 id="함수">함수</h3>
<p><img src="https://velog.velcdn.com/images/dohun_08/post/650bd13a-ca55-43f6-ab7a-f78426ec59ca/image.png" alt=""></p>
<blockquote>
<p>function 형태든 화살표 형태든 매개변수에 타입지정 후 리턴값에도 타입지정해주기!</p>
</blockquote>
<h3 id="배열">배열</h3>
<p><img src="https://velog.velcdn.com/images/dohun_08/post/b45554ea-131d-4ce3-a858-b6a5f45b936b/image.png" alt=""></p>
<blockquote>
<p>배열을 여러형태의 배열로도 저장할 수 있습니다.</p>
</blockquote>
<h3 id="객체">객체</h3>
<p><img src="https://velog.velcdn.com/images/dohun_08/post/05924aa9-ccf2-4ff7-b27f-6f87b4a53ddc/image.png" alt=""></p>
<blockquote>
<p>interface를 활용하여 객체의 타입지정해주기</p>
</blockquote>
<h3 id="훅">훅</h3>
<p><strong>useState</strong> : 제네릭을 활용하여 설정하기</p>
<pre><code class="language-typescript">const [user, setUser] = useState&lt;string&gt;();</code></pre>
<hr>

<p><strong>useEffect</strong> : 매개변수에도 타입설정, 반환값에도 타입을 설정해주기</p>
<pre><code class="language-typescript">useEffect((num:number):number =&gt; {
    return num;
}, [user]);</code></pre>
<hr>

<p><strong>useRef</strong> : useRef에서는 HTML요소나 null 설정해준 후 넣기 혹은 useState처럼 제네릭을 이용해서 설정해주기</p>
<pre><code class="language-typescript">const divRef = useRef&lt;HTMLDivElement | null&gt;(null);
const countRef = useRef&lt;number&gt;(0);</code></pre>
<hr>

<p><strong>useContext</strong> : createContext에서 타입을 지정해주면 자동으로 useContext로 불려올때 타입이 지정되서 옴.</p>
<pre><code class="language-typescript">interface User {
    name: string;
    age: number;
}

const UserContext = React.createContext&lt;User | null&gt;(null);

const MyComponent = ():User =&gt; {
    // useContext에서 `user`가 `User | null`로 추론됨
    const user = useContext(UserContext);
    return user;
};</code></pre>
<hr>

<h3 id="마치며">마치며..</h3>
<p>이밖에도 typescript의 유용한 문법들은 정말 많습니다. 더욱 공부하여 사용하면 좀 더 편안한 개발을 할 수 있을겁니다(아마..?)감사합니다</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[알고리즘] Union-Find 알고리즘을 알아보자 with(상화 T)]]></title>
            <link>https://velog.io/@dohun_08/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-Union-Find-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98%EC%9D%84-%EC%95%8C%EC%95%84%EB%B3%B4%EC%9E%90-with%EC%83%81%ED%99%94-T</link>
            <guid>https://velog.io/@dohun_08/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-Union-Find-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98%EC%9D%84-%EC%95%8C%EC%95%84%EB%B3%B4%EC%9E%90-with%EC%83%81%ED%99%94-T</guid>
            <pubDate>Wed, 25 Sep 2024 03:30:05 GMT</pubDate>
            <description><![CDATA[<h2 id="union-find-알고리즘이-뭐야">Union-Find 알고리즘이 뭐야?</h2>
<blockquote>
<p>:  <code>유니온 파인드</code> 알고리즘은 대표적인 그래프 알고리즘 중 하나로, 주어진 그래프의 <code>노드</code>들을 서로 다른 <code>집합</code>으로 분리하거나, 두 개의 <code>노드</code>가 같은 <code>집합</code>에 속하는지 <code>여부</code>를 판단하는 데 사용됩니다.</p>
</blockquote>
<h2 id="union-find-알고리즘의-과정">Union-Find 알고리즘의 과정</h2>
<blockquote>
<p><code>과정</code>은 총 3단계로 이루어져 있습니다. </p>
</blockquote>
<h3 id="set">Set()</h3>
<p><code>초기화</code>를 담당해주는 함수</p>
<ul>
<li><code>union</code> 과 <code>find</code> 연산을 하기전에 <code>노드</code>들을 하나의 <code>집합</code>으로 초기화해주는 함수입니다.<h3 id="union">Union()</h3>
<code>더하기</code>를 담당해주는 함수</li>
<li>받은 두 <code>집합</code>을 합쳐줍니다.<h3 id="find">Find()</h3>
<code>찾는것</code>을 담당해주는 함수</li>
<li>주어진 <code>노드</code>에 따라 대표 <code>노드</code>를 반환해준다.</li>
</ul>
<h2 id="예시">예시</h2>
<h4 id="문제">문제</h4>
<p>오늘은 새학기날이다. 현수네 반 학생은 N명이다. 현수는 각 학생들의 친구관계를 알고 싶다. 모든 학생은 1부터 N까지 번호가 부여되어 있고, 현수에게는 각각 두 명의 학생은 친구 관계 가 번호로 표현된 숫자쌍이 주어진다. 만약 (1, 2), (2, 3), (3, 4)의 숫자쌍이 주어지면 1번 학 생과 2번 학생이 친구이고, 2번 학생과 3번 학생이 친구, 3번 학생과 4번 학생이 친구이다. 그리고 1번 학생과 4번 학생은 2번과 3번을 통해서 친구관계가 된다. 학생의 친구관계를 나타내는 숫자쌍이 주어지면 특정 두 명이 친구인지를 판별하는 프로그램 을 작성하세요. 두 학생이 친구이면 “YES&quot;이고, 아니면 ”NO&quot;를 출력한다.</p>
<p>▣ 입력설명 첫 번째 줄에 반 학생수인 자연수 N(1&lt;=N&lt;=1,000)과 숫자쌍의 개수인 M(1&lt;=M&lt;=3,000)이 주어지고, 다음 M개의 줄에 걸쳐 숫자쌍이 주어진다. 마지막 줄에는 두 학생이 친구인지 확인하는 숫자쌍이 주어진다.</p>
<blockquote>
<p><code>정리</code> : 친구관계를 입력받고 친구의 친구면은 친구가 된다..!
<code>입력 예시</code> : {1, 2} {2, 3} {3, 4} 면은 1,2는 친구, 2,3은 친구, 3,4는 친구일때 2,3이 친구여서 1,4도 친구가 된다. 사람두명을 입력받아서 친구인지 아닌지 판단해주는 문제!</p>
</blockquote>
<h4 id="풀이-과정">풀이 과정</h4>
<blockquote>
</blockquote>
<p>입력 : 4 3 {1, 2} {2, 3} {3, 4} {1, 4}
4 = 학생 수
3 = 입력받을 갯수({}중괄호당 1개)
마지막 {1, 4}는 확인받고 싶은 친구 관계
출력 : Yes</p>
<hr>

<h4 id="전체-코드">전체 코드</h4>
<pre><code class="language-c">#include&lt;stdio.h&gt;

int n, parent[1001];

int Find(int v)
{
    if (parent[v] == v)
        return v;
    else
        return parent[v] = Find(parent[v]);
}

void Union(int x, int y)
{
    x = Find(x);
    y = Find(y);

    if (x != y)
        parent[x] = y;
}

void Set()
{
    int i;

    for (i = 1; i &lt;= n; i++)
        parent[i] = i;
}

int main(void)
{

    int m, i,a, b;

    scanf(&quot;%d %d&quot;, &amp;n, &amp;m);

    Set();

    for (i = 0; i &lt; m; i++)
    {
        scanf(&quot;%d %d&quot;, &amp;a, &amp;b);

        Union(a, b);
    }

    scanf(&quot;%d %d&quot;, &amp;a, &amp;b);
    if (Find(a) == Find(b))
        printf(&quot;YES\n&quot;);
    else
        printf(&quot;NO\n&quot;);

    return 0;
}</code></pre>
<hr>

<h4 id="과정1">과정1</h4>
<img src = "https://velog.velcdn.com/images/dohun_08/post/8874f4e8-ba95-4afa-a88b-82f3ff398e52/image.png" />

<pre><code class="language-c">//배열을 인덱스의 값으로 초기화 하고있음
void Set(){
    for(int i=0; i&lt;=n; i++){
        parent[i]=i;
    }
}</code></pre>
<blockquote>
<p>부모 배열을 하나 만들어주고 set함수를 이용하여 노드들의 값을 하나의 집합으로 초기화 시켜줍니다.</p>
</blockquote>
<hr>

<h4 id="과정2">과정2</h4>
<img src = "https://velog.velcdn.com/images/dohun_08/post/2ea0cd86-a666-4c59-8ba8-9cb6209236d6/image.png" />

<pre><code class="language-c">void Union(int x, int y){
    x = Find(x);
    y = Find(y);

    if(x!=y)
        parent[x] = y;
}</code></pre>
<blockquote>
<p>union 함수로 받은 값들이 원래 있던 값인지 확인해준 후 리턴해줍니다.</p>
</blockquote>
<hr>

<h4 id="과정3">과정3</h4>
<p><img src="https://velog.velcdn.com/images/dohun_08/post/1b2a0829-27df-44fa-ad23-1050b8d03206/image.png" alt=""></p>
<pre><code class="language-c">int Find(int v){
    if(parent[v] == v){ //부모와 값이 같다면 그대로 리턴하여 유니온함수의 x,y값 지정
        return v;
    }
    else{ //부모의 값을 계속 리턴받으며 친구 관계를 확인
        return parent[v] = Find(parent[v]);
    }
}</code></pre>
<blockquote>
<p>find 함수로 확인하고 싶은 친구 관계를 확인해줍니다.</p>
</blockquote>
<h2 id="정리">정리</h2>
<p><code>Union</code> 알고리즘은 여러 개의 <code>집합</code>을 하나로 합쳐서 작업을 처리하는 방법입니다. <code>집합</code>과 <code>노드</code>들을 이용해서 사용해보세요 ㅎㅎ</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[리액트 hooks 정리(State, Effect, Context, Ref, Memo, Callback)]]></title>
            <link>https://velog.io/@dohun_08/%EB%A6%AC%EC%95%A1%ED%8A%B8-hooks-%EC%A0%95%EB%A6%AC</link>
            <guid>https://velog.io/@dohun_08/%EB%A6%AC%EC%95%A1%ED%8A%B8-hooks-%EC%A0%95%EB%A6%AC</guid>
            <pubDate>Thu, 19 Sep 2024 15:00:55 GMT</pubDate>
            <description><![CDATA[<h2 id="usestate">useState()</h2>
<p><img src="https://velog.velcdn.com/images/dohun_08/post/ae37c20f-636c-485c-82cd-724047c90474/image.png" alt=""></p>
<p>우리의 효자 <code>useState</code>.
이친구는 내가 본 변수중에 제일 저장하기 좋은 <code>변수</code>입니다. <code>count</code>에 변수를 저장해뒀다가 <code>setCount</code>로 <code>count</code>의 수를 바꿔줍니다.
그러면 엥? 그냥 count = 1, count++ 해주면 더 간편한거 아닌가? 싶지만 노노노 </p>
<blockquote>
<p>화면에있는 값까지 같이 <code>렌더링</code>시켜주면서 변수의 값을바꿔주기 때문에 좋다 이말이야</p>
</blockquote>
<h2 id="useeffect">useEffect()</h2>
<p><img src="https://velog.velcdn.com/images/dohun_08/post/54fe52ac-0ed7-4f4a-b165-5eac04f3ffe5/image.png" alt="">
<code>의존성배열</code>을 활용하여 <code>useEffect</code> 사용하기</p>
<blockquote>
<p>컴포넌트가 <code>렌더링</code>될때만 함수를 실행시키고싶다면 <code>useEffect</code>를 써야합니다.(<code>의존성배열</code>은 빈배열이 됨)
또한 <code>조건</code>이 충족될때 <code>렌더링</code> 되게하고싶다면 <code>useEffect</code>를 사용해줍니다.</p>
</blockquote>
<h2 id="usecontext">useContext()</h2>
<p><img src="https://velog.velcdn.com/images/dohun_08/post/5c8a9639-f9b1-4e92-ad6e-9cad6c6dc001/image.png" alt="">
우리는 보통 다른 컴포넌트로 데이터를 보낼때 <code>props</code>를 사용합니다.
하지만 데이터를 사용하지 않는 컴포넌트 또한 <code>props</code>로 받아야 필요한 다른 컴포넌트로 전달할 수 있습니다. 이런 번거로움을 해결하고자 <code>useContext()</code>를 사용해줍니다.</p>
<blockquote>
<h4 id="사용방법">사용방법</h4>
<p><img src="https://velog.velcdn.com/images/dohun_08/post/30fdeb01-142f-4fbc-b94a-0e368c1febe8/image.png" alt="">
 <code>createContext</code>로 Context를 만들어 준 후 
<img src="https://velog.velcdn.com/images/dohun_08/post/db3e6f55-8ac6-4cce-b4de-36374ad86714/image.png" alt="">
 <code>데이터</code>를 담아 <code>호출</code>해줍니다.
<img src="https://velog.velcdn.com/images/dohun_08/post/81386b51-60c9-4b97-ae2c-6751e01bfcc8/image.png" alt="">
 이렇게 불러와서 사용할 수 있습니다.</p>
</blockquote>
<h2 id="useref">useRef</h2>
<p><code>useRef</code> 의 기능으로는 두가지가있습니다.</p>
<h4 id="첫번째-저장공간으로서의-기능입니다">첫번째 저장공간으로서의 기능입니다.</h4>
<p><img src="https://velog.velcdn.com/images/dohun_08/post/91afa71e-de1b-4396-926b-4074357ee5d2/image.png" alt="">
 자주 바뀌는 값을 <code>state</code> 로 설정해둔다면 바뀔때마다 <code>렌더링</code> 되므로 <code>비효율</code>적입니다. 그렇기에 자주바뀌지 않는값을 <code>Ref</code>로 지정해둡니다.</p>
<blockquote>
<p> 어? 근데 이러면 그냥 <code>let</code> 쓰면 되는거 아니에요? 할 수 도  있지만 <code>let</code>변수를 선언하고 <code>state</code>를 이용해서 렌더링 시킨다면 <code>let</code>변수는 다시 <code>0</code>으로 <code>초기화</code>
되어서 사용할 수 가 없습니다.</p>
</blockquote>
<blockquote>
<h4 id="사용방법-1">사용방법</h4>
<p><img src="https://velog.velcdn.com/images/dohun_08/post/6ef452e6-0eff-4e5a-95ce-df5920bd56ad/image.png" alt="">
 <code>Ref</code>는 <code>오브젝트</code>형식으로 값을 저장해줍니다. 값을 <code>current</code>에 담을 수 있으며 불러올때 또한 <code>current</code>를 이용해 줍니다.</p>
</blockquote>
<h4 id="두번째-돔요소-조정으로서의-기능입니다">두번째 돔요소 조정으로서의 기능입니다.</h4>
<p><img src="https://velog.velcdn.com/images/dohun_08/post/b4f08bbc-2a2b-4389-8450-f8d93f229439/image.png" alt="">
<code>돔요소</code>를 <code>Ref</code> 변수에 담을수도 있습니다!</p>
<blockquote>
<h4 id="사용방법-2">사용방법</h4>
<p>예제 : 렌더링됐을때 <code>인풋박스</code>로 <code>포커스</code>해두기
<img src="https://velog.velcdn.com/images/dohun_08/post/660813d0-49b2-49c0-880e-f89ba4415431/image.png" alt="">
<img src="https://velog.velcdn.com/images/dohun_08/post/a2c800d9-ba2a-422d-ab49-a55265d46f76/image.png" alt="">
<code>돔 요소</code>에 <code>ref</code> 속성을 추가하여 <code>Ref</code>변수를 넣어줍니다. 그렇다면 <code>Ref</code>의 <code>current</code>에 <code>돔요소</code>가 담기게됩니다.
요소의 <code>value</code>와 <code>focus</code>등등을 이용하여 기능을 만들수도 있습니다!</p>
</blockquote>
<h2 id="usememo">useMemo</h2>
<p><code>useMemo</code>는 값을 지정해서 <code>메모리</code>에 저장시켜주는 <code>훅</code>입니다.
<code>useEffect</code>의 상위호환같은 느낌???
useMemo는 값의 메모이제이션을 위해 사용됩니다.
내가 이 <code>state</code>가 변할때 얘는 실행안시키고 다른 <code>함수</code>만 실행시키고 싶은데...싶을때 딱좋은 친구
*<code>메모제이션</code> : <code>메모리</code>에 저장시켜뒀다가 써먹는 그거 맞음 ㅇㅇ</p>
<blockquote>
<h4 id="사용방법-3">사용방법</h4>
<p><img src="https://velog.velcdn.com/images/dohun_08/post/f4a2165d-d695-4de3-8d20-a51781e69abe/image.png" alt="">
<code>10000</code>을 더해주는 <code>함수</code>와 <code>1</code>을 더해주는 <code>함수</code>입니다. <code>10000</code>을 더해주는 <code>함수</code>는 <code>for문</code>이 돌아서 오지게 느립니다. state가 바껴서 렌더링될때마다 이런 <code>함수</code>를 계속 실행시켜주면 큰일나겠죠?
<img src="https://velog.velcdn.com/images/dohun_08/post/5f31b2ba-e269-49ab-85da-a784a905c1a4/image.png" alt="">
그래서 <code>useMemo</code>를 이용하여 <code>state</code>인 <code>hardNum</code>이 바뀔때만 <code>hardSumf()</code> 가 실행되도록 하였습니다. </p>
</blockquote>
<p>이러면 그냥 <code>useEffect</code> 쓰는거랑 뭐가다르냐 하실 수 있지만 <code>hardNum</code>이 <code>object</code>라고 생각해봅시다.</p>
<blockquote>
<p> <code>hardNum</code>에는 <code>주소</code>가 들어간다는거 알고계시죠? 네, 그때 <code>useEffect</code>를 쓴다면 <code>hardNum</code>에 들어있는 <code>주소</code>는 바뀌지 않기 때문에 아무리 <code>object</code>안에 <code>값</code> 이 변해도 인식을 못한다~ 이말이야 하지만 우리의 <code>useMemo</code> 는 그런것까지 다 인식해준다 이말이야^^ </p>
</blockquote>
<h2 id="usecallback">useCallback</h2>
<p><code>useCallback</code>은 <code>useMemo</code>와 비슷하게 컴퓨터 <code>메모리</code>에 저장시켜주는 <code>훅</code> 입니다.
그렇기 때문에 꼭 <code>렌더링</code>될때 함수가 새로 생성되지 않도록해주는 <code>훅</code>입니다.
주로 자식 <code>컴포넌트</code>에 콜백 함수를 전달할 때, 불필요한 <code>렌더링</code>을 막기 위해 사용됩니다.</p>
<blockquote>
<h4 id="사용방법-4">사용방법</h4>
<p><img src="https://velog.velcdn.com/images/dohun_08/post/31994fc1-64bb-4b0b-8bae-da11c9ad4c55/image.png" alt="">
다음과같은 <code>변수</code>가 있다고 할때 <code>someNum</code>에는 함수들이 객체로 저장되어 함수가 들어있는것이 아닌 <code>주소</code>를 가지고 있는것입니다. 그렇기때문에 <code>state</code>가 바뀌어서 새로 <code>렌더링</code>이 될때마다 다른 <code>주소값</code>을 가지게 됩니다.
그러면은 또 <code>렌더링</code>될때마다 값이같은 함수실행하고 의미가 없죠?
<img src="https://velog.velcdn.com/images/dohun_08/post/f775cb53-a5e3-4d6a-9493-e202c53333b7/image.png" alt="">
그래서 <code>useCallback</code>을 사용하여 <code>num</code>이 바뀔때만 해당 함수가 실행되도록 하였습니다.</p>
</blockquote>
<h2 id="마지막">마지막</h2>
<p>솔직히 모르겠으면 강의 찾아보는게 ㄹㅇ 개꿀딱지
<a href="https://www.youtube.com/@starcoding">https://www.youtube.com/@starcoding</a> 이분꺼 보고 내꺼 다시보면 아하 이래서~ 그냥 나옴;;</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[리액트에서 왜 굳이 key를 지정해줘야하지???]]></title>
            <link>https://velog.io/@dohun_08/%EB%A6%AC%EC%95%A1%ED%8A%B8%EC%97%90%EC%84%9C-%EC%99%9C-%EA%B5%B3%EC%9D%B4-key%EB%A5%BC-%EC%A7%80%EC%A0%95%ED%95%B4%EC%A4%98%EC%95%BC%ED%95%98%EC%A7%80</link>
            <guid>https://velog.io/@dohun_08/%EB%A6%AC%EC%95%A1%ED%8A%B8%EC%97%90%EC%84%9C-%EC%99%9C-%EA%B5%B3%EC%9D%B4-key%EB%A5%BC-%EC%A7%80%EC%A0%95%ED%95%B4%EC%A4%98%EC%95%BC%ED%95%98%EC%A7%80</guid>
            <pubDate>Wed, 18 Sep 2024 13:27:48 GMT</pubDate>
            <description><![CDATA[<h3 id="예시코드">예시코드</h3>
<p><img src="https://velog.velcdn.com/images/dohun_08/post/7f55aed6-846d-4d25-8314-7798a0709a45/image.png" alt=""></p>
<h2 id="key를-지정하지않는다면">key를 지정하지않는다면?</h2>
<p><img src="https://velog.velcdn.com/images/dohun_08/post/133f7e21-a9a8-41fa-8315-2c1c9fe94967/image.png" alt="">
<code>key</code>를 지정해주지 않는다면 <code>배열함수</code>가 돌아갈때 모든 요소들을 <code>렌더링</code>시켜버립니다. 위 코드로 <code>예시</code>를 들자면 새로운 <code>요소</code>가 추가될때마다 원래 있던 <code>요소</code>를 기억하지못하여 다시 모든 <code>리스트</code>들을 생성해냅니다.
만약 리스트가 <code>1000</code>개, <code>10000</code>개가 있는데 추가될때마다 생성되면 욕도 오지게 생성되겠죠잉?</p>
<h2 id="잘못된-key를-지정한다면">잘못된 key를 지정한다면?</h2>
<h4 id="index는">index는?</h4>
<blockquote>
<p>근데 그럼 <code>key</code>로 <code>index</code>값 주면 끝 아니야? 할 수 있습니다. 하지만 <code>index</code>도 무적은 아닙니다. <code>추가하기</code>가 됐을때 <code>인덱스</code>값이 밀려나면서 새로추가된 친구가 <code>인덱스</code> 0을 가지게되요. 이러면은 위에랑 똑같겠죠?</p>
</blockquote>
<h4 id="중복된다면">중복된다면?</h4>
<blockquote>
<p>중복된 <code>key</code>를 가지게 된다면? 당연히 이상해질거같지만 결과는 <code>요소</code>가 <code>복제</code>가 되거나 업데이트가 이상하게 될수도 있습니다. 당연히 하지말아야겠죠?</p>
</blockquote>
<h2 id="key를-지정하는-올바른-방법">key를 지정하는 올바른 방법</h2>
<p>네, 그래서 올바르게 주기위해서는 
<img src="https://velog.velcdn.com/images/dohun_08/post/4a042d3a-3b78-46a2-858b-2e209035ffed/image.png" alt="">
<code>state</code>를 <code>오브젝트</code> 형식으로 제작하여 <code>id</code>라는 <code>key</code>를 만들어줍니다. 
<img src="https://velog.velcdn.com/images/dohun_08/post/a6988420-9248-4772-9db2-94247698947b/image.png" alt="">
<code>key</code>를 <code>id</code>로 겹치지않게 지정해줍니다.</p>
<h3 id="느낀점">느낀점</h3>
<p>솔직히 나도 <code>key</code>? 귀찮은데 안해야징ㅎ 이였지만
 음 해야할것같다 안그러면 나중에 어어...? 이거 왜 안되지 왜 복사가 되지??? 하면서 GPT도와줘 ㅠㅠㅠ 할거 뻔함.
안그러기 위해서는 내가 똑똑해져야지 에효 그냥 <code>key</code>귀찮더라도 지정해주자~~</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[var와 let, const의 차이]]></title>
            <link>https://velog.io/@dohun_08/var%EC%99%80-let-const%EC%9D%98-%EC%B0%A8%EC%9D%B4</link>
            <guid>https://velog.io/@dohun_08/var%EC%99%80-let-const%EC%9D%98-%EC%B0%A8%EC%9D%B4</guid>
            <pubDate>Sun, 18 Aug 2024 07:39:05 GMT</pubDate>
            <description><![CDATA[<h2 id="선언의-차이">선언의 차이</h2>
<h3 id="var">var</h3>
<p><code>var</code>는 중복선언을 허용합니다. </p>
<pre><code class="language-js">var num = 10;
console.log(num);

var num = 20;
console.log(num);</code></pre>
<p>하지만
만약 같은 프로젝트를 진행하는 A개발자가 <code>var</code> 키워드로 <code>num</code>변수를 사용했습니다.
그런데 B개발자가 <code>var</code> 키워드로 <code>num</code>변수를 선언하여 사용한다면 값이 바뀌게되어 프로그램이 엉망이됩니다.</p>
<h3 id="let">let</h3>
<p><code>let</code>은 중복선언이 되지않는다.</p>
<pre><code class="language-js">let num = 10;
console.log(num);

let num = 20;
console.log(num);</code></pre>
<p>이렇게 한다면 에러가나며 진행되지않습니다. 이렇게 중복선언을 막아줍니다.</p>
<pre><code>let num = 10;
console.log(num);

num = 20;
console.log(num);</code></pre><h3 id="const">const</h3>
<p><code>const</code> 는 <code>상수</code>로 분류되어 선언을 한 후 값을 바꿀려하면 오류가난다.
(변수라고 부르지않음)</p>
<pre><code class="language-js">const id = &quot;name&quot;
const pw = 1234

id = &quot;id&quot; //오류
pw = 4321 //오류</code></pre>
<h2 id="호이스팅">호이스팅</h2>
<h3 id="호이스팅이란">호이스팅이란?</h3>
<p>인터프리터가 코드를 실행하기 전에 <code>함수</code>, <code>변수</code>, <code>클래스</code> 또는 <code>임포트</code>의 선언문을 해당 범위의 맨 위로 끌어올리는 것처럼 보이는 현상을 뜻합니다</p>
<h3 id="var-1">var</h3>
<pre><code class="language-js">console.log(a) //-&gt; undefined
var a = 1;
console.log(a) //-&gt; a</code></pre>
<p>이렇게 작성해도 에러가나지않고 변수 <code>a</code>를 코드실행전에 변수가 있다는것을 인지하고 값이 선언되지않아 <code>undefined</code>가 뜨게 된다.</p>
<p><code>var</code>의 호이스팅은 모든 호이스팅이 <code>전역변수</code>로 지정된다.</p>
<h3 id="let-const">let, const</h3>
<pre><code class="language-js">console.log(a) 
let a = 1;
console.log(a) </code></pre>
<p><code>let</code>의 경우 호이스팅이 되지만 <code>TDZ</code>_(Temporal Dead Zone)_가 있어 에러가 나며 <code>a</code>를 선언하기전까지는 실행해주지 않는다.(<code>const</code>도 동일)</p>
<h2 id="스코프">스코프</h2>
<h3 id="var-2">var</h3>
<h4 id="함수스코프란">함수스코프란?</h4>
<blockquote>
<p><code>함수스코프</code>는 <code>함수</code>안에서 <code>변수</code>가 선언되었다면 활용할 수 있습니다.</p>
</blockquote>
<p><code>var</code>의 경우 <code>함수스코프</code>로 되어있어 <code>if문</code> 밖에서 정의된 변수 <code>x</code>는 <code>if문</code> 안에서도 사용할 수 있습니다.</p>
<pre><code class="language-js">function main(){
    if(ture){
        var x = 0; 
    }
    console.log(x);
}</code></pre>
<p>또다른 문제</p>
<pre><code class="language-js">function main(){
      var x = 1;
    if(ture){
        var x = 0;
        console.log(x) // -&gt; 0
    }
      console.log(x); // -&gt; 0
}</code></pre>
<p>다음과 같이 <code>var</code>는 <code>함수스코프</code>이기 때문에
같은 함수에서 값을 다시 선언한다면 그대로 적용이 됩니다.</p>
<h3 id="let-1">let</h3>
<h4 id="블록스코프란">블록스코프란?</h4>
<blockquote>
<p><code>블록스코프</code>는 <code>중괄호</code>({})를 기준으로 선언된 <code>변수</code>를 활용할 수 있습니다.</p>
</blockquote>
<p><code>let</code>의 경우 <code>블록스코프</code>로 되어 있어 <code>if문</code>에서 정의된 변수 <code>x</code>는 밖에서 <code>consol.log(x)</code>하지 못합니다.</p>
<pre><code class="language-js">function main(){
    if(ture){
        let x = 0; 
    }
    console.log(x);  //오류
}</code></pre>
<pre><code class="language-js">function main(){
    if(ture){
        let x = 0;
        console.log(x); //x
    }
}</code></pre>
<p>또다른 문제</p>
<pre><code class="language-js">function main(){
      let x = 1;
    if(ture){
        let x = 0;
        console.log(x) // -&gt; 0
    }
      console.log(x); // -&gt; 1
}</code></pre>
<p>다음과 같이 <code>let</code>은 <code>블록스코프</code>이기 때문에
같은 블록에서 선언된것만 취급한다.</p>
<p>대부분의 언어에서 <code>블록스코프</code>를 <code>사용</code>하고 있습니다.</p>
<h2 id="정리">정리</h2>
<table>
  <tr>
    <th style="width: 200px;">범위</th>
    <th style="width: 200px;">var</th>
    <th style="width: 200px;">let</th>
    <th style="width: 200px;">const</th>
  </tr>
  <tr style="border-top:3px solid gray;">
    <td>선언</td>
    <td>중복 O</td>
    <td>중복 X</td>
    <td>중복 X</td>
  </tr>
  <tr>
    <td>호이스팅</td>
    <td>O</td>
    <td>O</td>
    <td>O</td>
  </tr>
  <tr>
    <td>스코프</td>
    <td>함수레벨</td>
    <td>블록레벨</td>
    <td>블록레벨</td>
  </tr>
</table>


]]></description>
        </item>
        <item>
            <title><![CDATA[배열함수]]></title>
            <link>https://velog.io/@dohun_08/%EB%B0%B0%EC%97%B4%ED%95%A8%EC%88%98</link>
            <guid>https://velog.io/@dohun_08/%EB%B0%B0%EC%97%B4%ED%95%A8%EC%88%98</guid>
            <pubDate>Fri, 16 Aug 2024 13:50:49 GMT</pubDate>
            <description><![CDATA[<h2 id="배열함수들">배열함수들</h2>
<p>이용할 배열</p>
<p><img src="https://velog.velcdn.com/images/dohun_08/post/832d58e1-c03c-4340-bf65-f997746646ea/image.png" alt=""></p>
<h3 id="foreach">forEach</h3>
<pre><code class="language-jsx">names.forEach(element =&gt; {
    console.log(element);
});</code></pre>
<p>결과
{ id: &#39;a&#39;, name: &#39;kim&#39; }
{ id: &#39;b&#39; }
{ id: &#39;c&#39; }
{ id: &#39;d&#39; }
{ id: &#39;e&#39; }
{ id: &#39;f&#39; }
{ id: &#39;g&#39; }
{ id: &#39;h&#39;, name: &#39;kim&#39; }</p>
<blockquote>
</blockquote>
<p>names의 값을 모두 반환해준다.
함수 안에서 실행되고 있는것이 뽀.인.트</p>
<h3 id="map">map</h3>
<pre><code class="language-jsx">let data = names.map((element)=&gt;{
    return element.id
})
console.log(data); //배열로 return 됨</code></pre>
<p>결과
[
  &#39;a&#39;, &#39;b&#39;, &#39;c&#39;,
  &#39;d&#39;, &#39;e&#39;, &#39;f&#39;,
  &#39;g&#39;, &#39;h&#39;
]</p>
<blockquote>
<p>리턴을 해주어야하고 배열로 리턴되는것이 뽀.인.트</p>
</blockquote>
<h3 id="filter">filter</h3>
<pre><code class="language-jsx">data = names.filter((element)=&gt;{
    return element.id==&quot;a&quot;
})
console.log(data);</code></pre>
<p>결과
[ { id: &#39;a&#39;, name: &#39;kim&#39; } ]</p>
<blockquote>
<p>리턴하면서 조건을 달아줄 수 있다.
이걸 이용해서 리턴할 요소들을 걸러준다. + 배열로 리턴해준다.
(map에서 동일하게 실행해준다면 True, False 로 나온다.)</p>
</blockquote>
<h3 id="some">some</h3>
<pre><code class="language-jsx">data = names.some((element)=&gt;{
    return element.id == &quot;a&quot;
})
console.log(data);</code></pre>
<p>결과
true</p>
<blockquote>
<p>리턴되는 조건이 있는지 없는지 true, false 로 출력해준다.</p>
</blockquote>
<h3 id="every">every</h3>
<pre><code class="language-jsx">data = names.every((element)=&gt;{
    return element.id ==&quot;a&quot;
})
console.log(data);</code></pre>
<p>결과
false</p>
<blockquote>
<p>리턴되는 조건이 모두 해당하는지 살펴봐준다.</p>
</blockquote>
<h3 id="find">find</h3>
<pre><code class="language-jsx">data = names.find((element) =&gt; {
    return element.name==&quot;kim&quot;
})
console.log(data);</code></pre>
<p>결과
{ id: &#39;a&#39;, name: &#39;kim&#39; }</p>
<blockquote>
<p>filter처럼 리턴에 해당하는 조건의 값을 리턴해준다.
find에서는 스트링으로 리턴하고, 해당하는 값중 먼저있는 값을 리턴해준다.</p>
</blockquote>
<h3 id="정리">정리</h3>
<p>모두 각자의 장점이 있는 배열함수들이였다.
비슷한 함수들로는 find와 filter, every와 some이 있었지만
각자의 차이점이 뚜렷하여 적절한 때에 잘사용해야겠다^^</p>
<blockquote>
<p>find → 스트링값으로 리턴, 처음에 가까운 값을 리턴
filter -&gt; 배열로 조건에 해당하는 값 모두 리턴해준다.</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[2024 1학기 BSSM 여름 AI 해커톤 회고]]></title>
            <link>https://velog.io/@dohun_08/2024-1%ED%95%99%EA%B8%B0-BSSM-%EC%97%AC%EB%A6%84-AI-%ED%95%B4%EC%BB%A4%ED%86%A4-%ED%9A%8C%EA%B3%A0%EB%A1%9D</link>
            <guid>https://velog.io/@dohun_08/2024-1%ED%95%99%EA%B8%B0-BSSM-%EC%97%AC%EB%A6%84-AI-%ED%95%B4%EC%BB%A4%ED%86%A4-%ED%9A%8C%EA%B3%A0%EB%A1%9D</guid>
            <pubDate>Wed, 24 Jul 2024 10:49:32 GMT</pubDate>
            <description><![CDATA[<h2 id="시작">시작</h2>
<h3 id="팀-편성">팀 편성</h3>
<p>나름 조금은 알던 애들이 있어서 나쁘지 않은데? 였고 후에 보니 잘하는 친구도 한명 껴있어서 너무 좋다 ^^ 였다.</p>
<h3 id="아이디어-회의">아이디어 회의</h3>
<p>처음 아이디어 회의는 참 순조로웠다. 이것저것 아이디어가 나오며 괜찮은데? 괜찮은데? 하며 디자인까지 팀원이 틀을 잡아놓겠다고하여 기분좋게 시작하였다.</p>
<blockquote>
<p>다가올 앞길은 모른채..그저 기대반 설렘반 이였던....</p>
</blockquote>
<h2 id="첫째날">첫째날</h2>
<h3 id="아이디어-갈아엎기">아이디어 갈아엎기</h3>
<p>디자인하고 한대로 개발을 하고있던중 선생님들과 선배님들께서 우리의 아디이어를 듣고 피드백해주셨다. 하지만 들어보니 참신하지만 심사위원분들이 좋아할것같지 않은 아이디어, 너희하고 비슷한 아이디어 5팀넘게 있었다. 등의 얘기를 들었습니다. </p>
<p>확인해보니 진짜 다 거기서 거기 였습니다 ㅋㅋㅋㅋ 그래서 첫째날은 거의 아이디어 생각하는 시간 이였던것 같습니다. 여기 수정하고 저기 수정하고 이건어때? 저건어때? 하면서말이죠...</p>
<blockquote>
<p>수정 -&gt; 갈아엎기 -&gt; 다시돌아가기 -&gt; 수정 반복 후 결국엔 원래의 아이디어에서 조금 수정한 버전으로 들고갔습니다. (시간이 순삭되었던...)</p>
</blockquote>
<h2 id="둘째날">둘째날</h2>
<h3 id="비상">비상</h3>
<p>아이디어에 시간을 많이 쏟아서 밤새 계속해서 개발을 진행하였습니다. 그래서 저희는 열심히 개발을하며 시간을 보냇지만 저는 백엔드와 프론트를 어떻게 연결해서 사용하는지, AI는 어떻게 활용하는지 전혀 몰랐기 때문에 큰 도움이 되지 못한것같습니다.... (이때 진짜 슬펏음)</p>
<h3 id="망했다-ㅋㅋ">망했다 ㅋㅋ</h3>
<p>결국 잘하는 친구 한명이서는 한계가 있었고 심지어 제가 맡은 화면조차 친구에게 넘겨주었더니 폰트가 깨지고 비율이 이상하고 했습니다. 선배님께 물어보니 각각의 컴퓨터마다 기본적인 css가 다를 수 있다고 하였습니다. (근데 사파리에서 실행이랑 구글에서 실행도 다르더라..ㅋㅋ)
<img src="https://velog.velcdn.com/images/dohun_08/post/79490434-66dc-492f-ba9b-e5664b8f0164/image.png" alt="">
<img src="https://velog.velcdn.com/images/dohun_08/post/26524df7-a8d6-4b73-b36e-aa75d988a03a/image.png" alt=""></p>
<h3 id="발표">발표</h3>
<p>결국에 우리는 구현해내지 못하고 피그마로만 디자인을 보여주며 발표했다.. 발표형식은 각각팀의 부스를 돌면서 심사위원이 평가하는것이였고 우리는 간단한 ppt를 준비해서 말빨로라도 좀 밀고 가야겠다 싶었다.. 다른 몇몇의 사람들은 발표를 들으며 떠드는걸 즐겨하셨지만 심사위원분들과 교장쌤께는 욕만 얻어먹고 말았다 ㅠㅠㅠ(나였어도 이건 좀 할듯 ㅇㅇ) 억울하거나 그런점은 없다. 내가 더 잘했으면 내가 더 열심히 했다면 결과는 바뀌었을 테니까</p>
<h2 id="느낀점">느낀점</h2>
<p><img src="https://velog.velcdn.com/images/dohun_08/post/b4c82076-1e52-403d-856b-02be5fe7cdd0/image.png" alt=""></p>
<blockquote>
<p>이번 해커톤으로 인해서 깨달은점이 많은것 같습니다. 
정말 제 자신이 어느정도인지 알게되고 아이디어가 정말 중요하구나.
내가 심사위원이였어도 쩝 다 비슷하네 이런 반응이 나올거같더군요..ㅋㅋ
그렇기에 아이디어가 참 중요한 것 같습니다. 또한 개발을 위해서 중요한것은 역시 첫째는 소통 두번째는 커뮤니케이션 세번째는 대화가 아닐까 싶습니다. 그리고 저의 개발 실력을 많이 키워야겠다고 다짐합니다. AI딱대. 너 딱 기다려.</p>
</blockquote>
<p>⭐️---------------------------------------------------------------------------
<strong>아이디어.
소통.
기술.</strong>
⭐️---------------------------------------------------------------------------
그리고 디자인좀 잘하고싶다...</p>
]]></description>
        </item>
    </channel>
</rss>