<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>Jony_develop.log</title>
        <link>https://velog.io/</link>
        <description>알면 알수록 모르는 코태계</description>
        <lastBuildDate>Fri, 30 Aug 2024 10:03:21 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>Jony_develop.log</title>
            <url>https://velog.velcdn.com/images/dalbyeol-_-11/profile/25d68113-7637-4557-b52e-66e629a5feb9/image.jpg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. Jony_develop.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/dalbyeol-_-11" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[TIL]]></title>
            <link>https://velog.io/@dalbyeol-_-11/TIL-531hte8p</link>
            <guid>https://velog.io/@dalbyeol-_-11/TIL-531hte8p</guid>
            <pubDate>Fri, 30 Aug 2024 10:03:21 GMT</pubDate>
            <description><![CDATA[<h1 id="해커톤-시작">해커톤 시작</h1>
]]></description>
        </item>
        <item>
            <title><![CDATA[TIL]]></title>
            <link>https://velog.io/@dalbyeol-_-11/TIL-n1dygsny</link>
            <guid>https://velog.io/@dalbyeol-_-11/TIL-n1dygsny</guid>
            <pubDate>Thu, 18 Jul 2024 14:34:22 GMT</pubDate>
            <description><![CDATA[<h2 id="최종-프로젝트">최종 프로젝트</h2>
<ol>
<li><p>필수 항목 페이지
1) 회원가입/로그인 페이지
2) 메인 페이지
3) 디테일 페이지
4) 프로필/마이 페이지</p>
</li>
<li><p>취합 후 수렴된 의견
1) 음식 관련 사이트
2) 렌탈 사이트
3) 중계 사이트</p>
</li>
<li><p>주제 선정 기준
1) 수익성이 있는지
2) 현실성이 있는지
3) 흥미성이 있는지</p>
</li>
</ol>
<p>크게 이렇게 큰 틀을 잡고 진행했고 고민하던 끝에 mvp 전에 할 것과 후에 할 것들도 대충 구분지어놔야 후에 편할 듯 싶어 정해놓기로 하였다.</p>
<p>결과적으로 팀원들과의 상의 끝에 결정한 프로젝트는
<code>AI 활용한 식단 관리 서비스</code>를 만들기로 했다.</p>
<p>직접적으로 영양사와 운동 전문가를 컨택할 수는 없었기에 대체로 선택했다.</p>
<p>물론 최신 기술이기에 채택한 점도 있다.</p>
<p>참고 레퍼런스:
<a href="https://shipdan.me/">https://shipdan.me/</a>
<a href="https://www.yundiet.com/">https://www.yundiet.com/</a>
<a href="https://www.ko-noom.com/">https://www.ko-noom.com/</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[TIL]]></title>
            <link>https://velog.io/@dalbyeol-_-11/TIL-ogr5dx8z</link>
            <guid>https://velog.io/@dalbyeol-_-11/TIL-ogr5dx8z</guid>
            <pubDate>Wed, 17 Jul 2024 12:47:32 GMT</pubDate>
            <description><![CDATA[<h2 id="최종-프로젝트">최종 프로젝트</h2>
<p>각 팀원들에게 전에 작업해보지 못한 기능이라던지 해보고 싶은 기능과 어떤 페이지를 만들어보고 싶었는지도 물어보았다.</p>
<p>쇼핑몰, 이커머스 서비스, 동행인 서비스, 예약 서비스(음식점 등), 룩북 공유 서비스, 마켓 플레이스 등 다양하게 의견들이 나왔고 중복되는 기능들을 취합해 나열 해보기도 했다. </p>
<p>회원가입/로그인, CRUD(등록,조회,수정,삭제), API, 결제 등으로 크게 분류를 해봤다.
이후 추가되는 기능과 페이지도 있을테고 삭제도 될 예정이라 우선은 이렇게만 틀을 잡아 놓기로 했다.</p>
<p>아직 구체적이진 않기에 차차 다듬도록 하기로 했다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[TIL]]></title>
            <link>https://velog.io/@dalbyeol-_-11/TIL-t4yepww6</link>
            <guid>https://velog.io/@dalbyeol-_-11/TIL-t4yepww6</guid>
            <pubDate>Tue, 16 Jul 2024 00:27:34 GMT</pubDate>
            <description><![CDATA[<h2 id="최종-프로젝트">최종 프로젝트</h2>
<p>최종 프로젝트 첫 날
배정된 팀원들과 그리고 디자이너와도 같이 인사를 했다.
UX/UI 디자이너와 협업이라니..!</p>
<p>걱정이 없진 않았지만 그럼에도 기대감이 더 컸던지 2달 여간의 일정이 꽤나 기대된다.</p>
<p><code>7/16(화)~7/19(금)</code>까지 기획하는 기간을 가지고 충분하고 다양한 의견들을 나눠보기로 했다.</p>
<p><em>어떤 결과물이 나올지 굉장히 기대된다!</em></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[TIL]]></title>
            <link>https://velog.io/@dalbyeol-_-11/TIL-tsx3vtsb</link>
            <guid>https://velog.io/@dalbyeol-_-11/TIL-tsx3vtsb</guid>
            <pubDate>Thu, 13 Jun 2024 23:56:41 GMT</pubDate>
            <description><![CDATA[<h1 id="react---팀-프로젝트-회고2뉴스피드-주제-mylog">React - 팀 프로젝트 회고2(뉴스피드, 주제: Mylog)</h1>
<br>

<h3 id="🔖-envlocal을-사용하는-이유-">🔖 .env.local을 사용하는 이유 ! <img src="https://velog.velcdn.com/images/dalbyeol-_-11/post/c40fd653-7661-4cc5-8f5b-ae91f81620d1/image.JPG" alt=""></h3>
<blockquote>
</blockquote>
<p> 개발을 하다보면 Api키 등과 같이 민감한 개인 정보들이 포함되는 경우가 존재한다. 또한 여러 api에서 사용하는 서버 IP와 같은 반복되는 변수가 존재할 수도 있다.
 이러한 경우들 때문에 환경변수들로 만들어 해결하면 된다.</p>
<blockquote>
<p>프로젝트 루트 디렉토리에 생성하여 사용하면 되고 
 kEY = VALUE 형식으로 정의된다.</p>
</blockquote>
<pre><code> .env                # 모든 경우에 로드됨
.env.local          # 모든 경우에 로드되지만 Git에서는 무시됨
.env.[mode]         # 지정한 모드에서만 로드됨
.env.[mode].local   # 지정한 모드에서만 로드되지만 Git에서는 무시됨</code></pre><blockquote>
<h4 id="환경변수-load">환경변수 load</h4>
</blockquote>
<ul>
<li>우리가 사용하고 있는 Vite에선 <code>import.meta.env</code>객체를 통해 환경변수에 접근이 가능하다.</li>
<li>전역적으로 사용되는 정보들을 편리하게 관리할 수 있다.<blockquote>
<blockquote>
</blockquote>
</blockquote>
<ul>
<li><code>import.meta.env.MODE</code> : {string} 애플리케이션이 실행중인 모드</li>
<li><code>import.meta.env.BASE_URL</code> : {string} 애플리케이션이 제공되는 기본 URL</li>
<li><code>import.meta.env.PROD</code> : {boolean} 애플리케이션이 프로덕션 모드로 실행 중인지 여부</li>
<li><code>import.meta.env,DEV</code> : {boolean} 애플리케이션이 개발 모드로 실행 중인지 여부</li>
<li><code>import.meta.env.SSR</code> : {boolean} 애플리케이션이 서버에서 실행중인지 여부</li>
</ul>
</li>
</ul>
<blockquote>
</blockquote>
<h4 id="❗주의점">❗주의점</h4>
<ul>
<li>구문 - 환경 변수 파일은 key=value 형식으로 환경 변수를 정의합니다. 키와 값 사이에는 등호(=)를 사용하며, 공백을 넣지 않는다.</li>
<li>특수 문자 및 공백 - 환경 변수 값에 특수 문자나 공백이 포함된 경우 이스케이프(Escape) 시퀀스를 사용하여 처리해야 한다.</li>
<li>일반적으로 <code>.env.local</code> 파일의 환경 변수가 가장 높은 우선순위이다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[TIL]]></title>
            <link>https://velog.io/@dalbyeol-_-11/TIL-wy9fricy</link>
            <guid>https://velog.io/@dalbyeol-_-11/TIL-wy9fricy</guid>
            <pubDate>Thu, 13 Jun 2024 23:56:02 GMT</pubDate>
            <description><![CDATA[<h1 id="react---팀-프로젝트-회고3뉴스피드-주제-mylog">React - 팀 프로젝트 회고3(뉴스피드, 주제: Mylog)</h1>
<ul>
<li><h3 id="issue">Issue</h3>
</li>
</ul>
<ol>
<li><p>게시글 (내가 작성한 글) 영역 병합 후 작업여부</p>
<blockquote>
</blockquote>
<p>Supabase table에서 게시글 관련 저장된 데이터 불러와 작업을 해주면 된다.</p>
</li>
<li><p>github 사용 시에 모르기에 실수한 부분이 있는데 팀원들과 같이 개발을 할 경우, 팀원들이 dev 브랜치에 올린 코드들을 pr 후 때마다 내 브랜치로 pull을 해서 적용 시켜가면서 작업을 해야한다.!!</p>
<blockquote>
</blockquote>
<p>생각치도 못하고 단순히 한 번에 pull 받으면 되겠지라는 착각에 pull을 받으니 병합 충돌과 여러 문제들이 발생해서 꽤나 애먹었다. 
그래도 한 편으로는 이번에 실수를 함으로 어떻게 해야하는지를 알았기에 다행이라고도 생각한다.</p>
</li>
<li><p>router 컴포넌트에서 route 안 element 설정 차이</p>
<blockquote>
</blockquote>
<p>props-driling일 때는 route 안 element를 넣지만 redux로 작업할 때는 다른 공간(파일)에 넣어 사용해주면 된다.</p>
</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[TIL]]></title>
            <link>https://velog.io/@dalbyeol-_-11/TIL-fhmk77if</link>
            <guid>https://velog.io/@dalbyeol-_-11/TIL-fhmk77if</guid>
            <pubDate>Wed, 12 Jun 2024 01:51:17 GMT</pubDate>
            <description><![CDATA[<h1 id="react---팀-프로젝트-회고2뉴스피드-주제-mylog">React - 팀 프로젝트 회고2(뉴스피드, 주제: Mylog)</h1>
<ul>
<li><h3 id="issue">Issue</h3>
</li>
</ul>
<ol>
<li>프로필 사진을 첨부 했음에도 유효성 검사에서 걸러내지 못함.
=&gt; 유효성 검사 로직에 문제가 있었고 이미지Url을 저장하는 storage 내 buckets 저장소가 없었던 문제도 있었다. (같은 파트를 담당했던 팀원과 소통의 오류가 있었다.) 수정 되기 전의 코드를 따로 저장하지 못한 점이 아쉽다.. </li>
</ol>
<pre><code class="language-jsx">const handleImageChange = async (file) =&gt; {
    if (!file) return;

    const { data, error } = await supabase
    .storage
    .from(&#39;images&#39;)
    .upload(`/${uuidv4()}`, file);

    if (error) {
      console.log(error);
      return;
    }
    // 업로드 이미지url 가져오기
    const { data: imageUploadData, error: imageUploadError } = supabase
      .storage
      .from(&#39;images&#39;)
      .getPublicUrl(data.path);

      if (imageUploadError) {
       console.log(imageUploadError);
       return;
    }
    setPreviewUrl(URL.createObjectURL(file));
    setPicture(imageUploadData.publicUrl);
    return imageUploadData;
  };
</code></pre>
<blockquote>
<p>문제였던 부분(bucket 생성)을 해결하고 supabase에서 제공하는 인용코드를 사용해 연결하여 저장되도록 연결했다.
<img src="https://velog.velcdn.com/images/dalbyeol-_-11/post/07885d4a-9047-4b28-83d4-8752a4aac876/image.JPG" alt=""></p>
</blockquote>
<ol start="2">
<li>useNavigate 훅을 사용하여 뒤로가기 버튼 활성화</li>
</ol>
<pre><code class="language-jsx">  const handleBack = () =&gt; {
    navigate(-1);
  };</code></pre>
<blockquote>
<p>프로필 페이지로 넘어가게 해준다. 이 부분은 사전 작업만 해주면 쉬운 부분이다.</p>
</blockquote>
<ol start="3">
<li><p>일반 로그인, 소셜 로그인 시, 유효성 검사 여부 </p>
<pre><code class="language-jsx">const handleChangeProfile = async () =&gt; {
const newErrors = {};

try {
  if (!name) {
    newErrors.general = &#39;모든 필드를 입력해주세요.&#39;;
    throw new Error(&#39;모든 필드를 입력해주세요.&#39;);
  }

  const { data: userData, error: userError } = await supabase
    .from(&#39;Users&#39;)
    .select(&#39;password, social&#39;)
    .eq(&#39;userId&#39;, user.id)
    .single();

  if (userError) {
    newErrors.general = &#39;사용자의 정보를 가져오는 중 오류가 발생했습니다.&#39;;
    throw new Error(&#39;사용자 정보를 가져오는 중 오류가 발생했습니다.&#39;);
  }

  if (!userData.social) {
    if (!validatePasswordFormat(currentPassword)) {
      newErrors.password = &#39;비밀번호는 영문 대소문자, 특수문자를 포함하여 8자리 이상이어야 합니다.&#39;;
      throw new Error(&#39;비밀번호는 영문 대소문자, 특수문자를 포함하여 8자리 이상이어야 합니다.&#39;);
    }

    if (!validatePasswordMatch(currentPassword, userData.password)) {
      newErrors.unPassword = &#39;비밀번호가 일치하지 않습니다&#39;;
      throw new Error(&#39;비밀번호 불일치&#39;);
    }
  }

  const { data, error } = await supabase
    .from(&#39;Users&#39;)
    .update({
      name: name,
      nickname: nickname,
      password: currentPassword,
      reason: mylogReason,
      ...(picture ? { imageUrl: picture } : {})
    })
    .eq(&#39;userId&#39;, user.id);

  if (error) {
    console.error(&#39;업데이트에 문제가 발생했습니다.&#39;, error);
  } else {
    alert(&#39;업데이트가 완료 됐습니다!&#39;, data);
    navigate(&#39;/profile&#39;);
  }
} catch (err) {
  setErrors(newErrors);
  console.log(err);
}
};```

</code></pre>
</li>
</ol>
<blockquote>
</blockquote>
<p>유효성 검사 부분 여러 오류가 있었는데 대표적으로 소셜 로그인 부분과 연결에 있어서 꽤나 애 먹은 부분들이 있어서 다시 해보라고 하면 기피하고 싶다..ㅎㅎ</p>
<ol start="4">
<li>탈퇴하기 기능</li>
</ol>
<pre><code class="language-jsx">const handleDeleteAccount = async () =&gt; {
    if (confirm(&#39;정말로 계정을 삭제하시겠습니까?&#39;)) {
      const { error } = await supabase.from(&#39;Users&#39;).delete().eq(&#39;userId&#39;, user.id);

      if (error) {
        alert(&#39;계정 삭제 중 오류가 발생했습니다: &#39;);
      } else {
        const { error } = await supabase.auth.signOut();
        if (error) {
          alert(&#39;로그아웃 중 오류가 발생했습니다&#39;);
        } else {
          dispatch(logout());
          alert(&#39;계정이 성공적으로 삭제되었습니다.&#39;);
          navigate(&#39;/&#39;);
        }
      }
    } else {
      alert(&#39;계정 삭제가 취소되었습니다.&#39;);
    }
  };</code></pre>
<blockquote>
</blockquote>
<p>처음 탈퇴하기 기능을 만들 때 DB 내의 데이터는 삭제가 됐는데 메인 페이지 화면에 아직 로그인이 되있다고 표출되어 있어서 이 부분도 같이 수정했다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[TIL]]></title>
            <link>https://velog.io/@dalbyeol-_-11/TIL-5jhkurh2</link>
            <guid>https://velog.io/@dalbyeol-_-11/TIL-5jhkurh2</guid>
            <pubDate>Tue, 11 Jun 2024 01:08:00 GMT</pubDate>
            <description><![CDATA[<h1 id="react---팀-프로젝트-회고뉴스피드-주제-mylog">React - 팀 프로젝트 회고(뉴스피드, 주제: Mylog)</h1>
<h3 id="담당한-파트는-프로필-프로필-수정-페이지를-담당했다">담당한 파트는 프로필, 프로필 수정 페이지를 담당했다.</h3>
<ul>
<li><h4 id="셋업-설정">셋업 설정</h4>
</li>
</ul>
<ol>
<li>prettierrc 파일 생성</li>
<li>supabase 셋업</li>
<li>환경변수(.env.local) 셋업 </li>
</ol>
<p>-&gt; 계정 정보 숨기기
4. git 브랜치 관리
-&gt; 개인이 작업할 feature브랜치를 생성하여 작업</p>
<p><img src="https://velog.velcdn.com/images/dalbyeol-_-11/post/3e22b5f8-c96f-4866-994d-f62da6fafa29/image.JPG" alt=""></p>
<p>이렇게 전체적인 폴더와 파일들을 관리해주면 된다.</p>
<hr>
<p><img src="https://velog.velcdn.com/images/dalbyeol-_-11/post/475d0636-1f16-4b44-9b43-c7519dd06c61/image.JPG" alt=""></p>
<p>1.supabase key를 작성할 때, 띄워쓰기x, key만 들어가야한다.</p>
<ol start="2">
<li>fetchData로 받아올 때, from(&#39;&#39;) 즉, 테이블 이름이 들어와야한다.</li>
</ol>
<p><img src="https://velog.velcdn.com/images/dalbyeol-_-11/post/808d99f2-da7f-4629-865a-f7c8d84808a1/image.JPG" alt="">
Table Editer를 클릭하여 들어가면 생성한 테이블들이 있다.</p>
<p><img src="https://velog.velcdn.com/images/dalbyeol-_-11/post/536235c3-e94b-4e57-b0f9-9a49b51b13af/image.JPG" alt=""></p>
<blockquote>
<p>supabase 테이블 생성과 기타 관련해선 따로 다루도록 할 예정이다.</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[TIL]]></title>
            <link>https://velog.io/@dalbyeol-_-11/TIL-lztpakxm</link>
            <guid>https://velog.io/@dalbyeol-_-11/TIL-lztpakxm</guid>
            <pubDate>Sun, 09 Jun 2024 14:57:38 GMT</pubDate>
            <description><![CDATA[<h1 id="react---팀-프로젝트-회고뉴스피드-주제-mylog">React - 팀 프로젝트 회고(뉴스피드, 주제: Mylog)</h1>
<p>다시 찾아온 팀 프로젝트 기간
이번 팀 프로젝트는 기획부터 시작해서 결과물을 만드는 과정까지 A to Z의 과정을 전부 겪어가며 진행해야 했기에 여러 부분에서 밀도있게 작업한 듯 하다. (1주일의 기간을 줬는데 너무 너무 짧았다..) </p>
<p>생각하기엔 개인 프로젝트는 내 실력을 실전 경험으로 실력을 증진시킨다 생각하고 팀 프로젝트는 그 기반으로 팀원들과 합심하여 하나의 웹을 만드는 것이라고 본다. </p>
<p>한 가지 걱정은 아직 react에 대한 사용성과 이해도가 부족하여 팀활동에서 뒤쳐질까 걱정도 많았다. </p>
<p>그럼에도 불구하고 운이 좋게 문제를 해결함에 있어 다같이 합심하고 궁금한 건 답해주고 적극적으로 임해줘서 고마울 뿐이였다. </p>
<p>이전 조의 팀원들도 좋은 사람들이였는데 이번에도 고맙게 팀원드로가 합이 잘 맞았다. (심적으론 부담이 안 된건 아니지만..) </p>
<p>무엇을 할까 고민하던 중 무난하고 필수 적용 기술을 넣을 수 있는 velog를 오마주한 블로그를 작성하기로 했다. </p>
<p>개인적으로 많은 난항을 겪었고 어디가 부족하고 채워야하는지 깨달을 수 있는 기간이였기에 꽤나 보람찼고 이제야 시작이라는 걸 생각하는 시간이기도 했다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[TIL]]></title>
            <link>https://velog.io/@dalbyeol-_-11/TIL-ng1dj1ce</link>
            <guid>https://velog.io/@dalbyeol-_-11/TIL-ng1dj1ce</guid>
            <pubDate>Sun, 09 Jun 2024 09:16:26 GMT</pubDate>
            <description><![CDATA[<h1 id="react---개인-숙련-프로젝트accountbook-회고">React - 개인 숙련 프로젝트(AccountBook) 회고</h1>
<br>

<p>수정 페이지와 연결되는 부분인 컴포넌트에 대해서 살펴보자</p>
<blockquote>
</blockquote>
<ol>
<li>입력되어 보내진 데이터를 날짜 순으로 정렬한다.</li>
<li>해당 월의 데이터를 필터링한다.</li>
<li>필터링된 데이터를 날짜 순으로 정렬해준다.</li>
<li>정렬된 데이터를 반복하면서 각 항목에 렌더링 해준다.</li>
</ol>
<hr>
<p>1.
<img src="https://velog.velcdn.com/images/dalbyeol-_-11/post/fda46c54-d3b7-4dc2-ab9f-5ac2d989118e/image.JPG" alt=""></p>
<blockquote>
</blockquote>
<p>sort()로 위치 정렬 후 getTime()을 사용하여 지정된 날짜의 시간에 해당하는 숫자값을 반환 시켜준다.</p>
<p>2.
<img src="https://velog.velcdn.com/images/dalbyeol-_-11/post/b8e1c5b6-5ad4-40a9-97b3-82e2211cda1a/image.JPG" alt=""></p>
<blockquote>
</blockquote>
<p>코드를 살펴보면  <code>~~Months</code>라고 있는 부분 <code>~~</code>는 double tilde 연산자이다. tilde 연산자는 비트연산자로, NOT이기 때문에 0과 1을 뒤집는다. 그렇기에 <code>~~</code> 는 두번 반복해 주는 것이다. 대신에 Math.floor()를 사용할 수 있다. </p>
<p><img src="https://velog.velcdn.com/images/dalbyeol-_-11/post/9f4ce397-9c0e-4638-ac7d-f3c1e6eaf487/image.JPG" alt=""></p>
<blockquote>
<p>map() 매서드를 사용하여 정렬된 데이터를 반복하면서 각 항목을 렌더링 해주면 원하는 값들이 나오게 된다.</p>
</blockquote>
<p>다른 컴포넌트보다 어려웠던 항목 수정 컴포넌트는
custom 훅을 사용하였고 페이지 간 이동할 수 있는 useNavigate 훅, useParams를 추가적으로 사용하여 정확한 정보를 받아와 수정, 삭제, 저장까지 할 수 있게 해주었다.</p>
<p><img src="https://velog.velcdn.com/images/dalbyeol-_-11/post/aeeeaade-dad5-46ae-b274-830d9ac62a03/image.JPG" alt=""></p>
<p><img src="https://velog.velcdn.com/images/dalbyeol-_-11/post/94ee4c83-90d4-44ca-b7be-a8fc3e08153a/image.JPG" alt=""></p>
<p><img src="https://velog.velcdn.com/images/dalbyeol-_-11/post/97960034-1c00-4e65-aa91-a85b190f5ba1/image.JPG" alt=""></p>
<blockquote>
</blockquote>
<p>유효성 검사와 spread Operater를 사용, 배열을 순회하며 일치하는 항목을 수정해줍니다.</p>
<p><img src="https://velog.velcdn.com/images/dalbyeol-_-11/post/ada420ea-63a9-455d-b670-992719118017/image.JPG" alt=""></p>
<blockquote>
<p>배열에서 현재 파라미터와 일치하는 항목을 제외한 나머지 항목들로 구성된 새로운 배열을 생성하게 해준다.
navigate(&#39;/&#39;)는 이전 페이지로 돌아가는 역할을 해준다.</p>
</blockquote>
<hr>
<h4 id="막상-주관적인-설명을-하고-싶지만-매서드의-사용에-대한-응용부분이-모자라고-인풋값과-아웃풋의-값이-나오는-부분이-이번-프로젝트를-통해-미숙해-보였다">&gt; 막상 주관적인 설명을 하고 싶지만 매서드의 사용에 대한 응용부분이 모자라고 인풋값과 아웃풋의 값이 나오는 부분이 이번 프로젝트를 통해 미숙해 보였다.</h4>
<h4 id="custom-훅을-사용하여-정보들을-모아주고-뿌려주는-방법을-사용하니-확실히-코드양이-조금은-줄어들고-사용함에-있어-용이하다는-것을-배웠다">custom 훅을 사용하여 정보들을 모아주고 뿌려주는 방법을 사용하니 확실히 코드양이 조금은 줄어들고 사용함에 있어 용이하다는 것을 배웠다.</h4>
<h4 id="어찌저찌해서-성공은-했다지만-아직은-많이-사용해보지-않아-미숙하기에-앞으로의-과정에서-자주-사용해-익숙해-나가면-지금처럼-버벅이지는-않을거라고-생각해본다">어찌저찌해서 성공은 했다지만 아직은 많이 사용해보지 않아 미숙하기에 앞으로의 과정에서 자주 사용해 익숙해 나가면 지금처럼 버벅이지는 않을거라고 생각해본다.</h4>
<h4 id="그리고-context와-redux-리펙토링에-대해-적어보자면-전역상태-관리를-하기-때문에-코드의-간소화는-분명히-있고-그-간소화된-코드는-컴포넌트를-따로-생성하여-그-안에-입력해준-뒤-각-사용에-맞는-컴포넌트에-뿌려주면-되는-방식이다">&gt;그리고 Context와 Redux 리펙토링에 대해 적어보자면 전역상태 관리를 하기 때문에 코드의 간소화는 분명히 있고 그 간소화된 코드는 컴포넌트를 따로 생성하여 그 안에 입력해준 뒤 각 사용에 맞는 컴포넌트에 뿌려주면 되는 방식이다.</h4>
<h4 id="그러나-redux와-tk-사용에-대한-지금도-어려워서-꾸준한-관심이-필요하다고-느낀다">그러나 Redux와 T/K 사용에 대한 지금도 어려워서 꾸준한 관심이 필요하다고 느낀다..</h4>
<h4 id="어려웠음에도-불구하고-배우고-얻은게-있어-꽤나-보람찼던-프로젝트였다고-말하고-싶다">어려웠음에도 불구하고 배우고, 얻은게 있어 꽤나 보람찼던 프로젝트였다고 말하고 싶다.</h4>
]]></description>
        </item>
        <item>
            <title><![CDATA[TIL]]></title>
            <link>https://velog.io/@dalbyeol-_-11/TIL-wzi1pncv</link>
            <guid>https://velog.io/@dalbyeol-_-11/TIL-wzi1pncv</guid>
            <pubDate>Sun, 09 Jun 2024 08:10:52 GMT</pubDate>
            <description><![CDATA[<h1 id="react---개인-숙련-프로젝트account-book-회고">React - 개인 숙련 프로젝트(Account-Book) 회고</h1>
<br>

<h3 id="이번-개인-프로젝트는-총-3단계에-걸쳐-코드를-propsdriling-context-redux-순서로-만든다-전역관리에-대한-이해를-위해서인지는-몰라도-생각-보다-빡셌다는-것만-기억에-남는다-하하">이번 개인 프로젝트는 총 3단계에 걸쳐 코드를 propsDriling, Context, Redux 순서로 만든다. 전역관리에 대한 이해(?)를 위해서인지는 몰라도 생각 보다 빡셌다는 것만 기억에 남는다.. 하하..</h3>
<p>제일 기본이 되고 저번 프로젝트에도 써먹었던 propsDriling으로 제일 먼저 시작했다.</p>
<p>이전에 컴포넌트 분리에 대해 많은 어려움을 겪었고 당시 TIL을 쓰는 와중에도 이해에 대한 부분이 많이 낮았었지만, 지금은 이전보단 꽤나 이해가 잘 되고 있어 한 편으론 다행이다라고 생각한다.</p>
<p>주된 설명은 propsDriling으로 하면서 Context,Redux로 작성된 코드는 핵심적 요소만 다루도록 하겠다.
(다 하면 너무 많아..)</p>
<pre><code class="language-jsx">import React, { useEffect, useState } from &quot;react&quot;;
import { Route, Routes } from &quot;react-router-dom&quot;;
import Home from &quot;./pages/Home&quot;;
import Detail from &quot;./pages/Detail&quot;;
import fakeData from &quot;../public/fakeData.json&quot;;
const App = () =&gt; {
  // 이 함수 컴포넌트는 전체 애플리케이션의 진입점 역할을 합니다.
  const [accountBook, setAccountBook] = useState(fakeData.itemLists);
  // 이 부분은 회계 데이터를 관리하는 state를 초기화합니다. 초기값은 빈 배열입니다.
  useEffect(() =&gt; {
    const storedAccountBook = JSON.parse(localStorage.getItem(&quot;accountBook&quot;));
    if (JSON.stringify(storedAccountBook) !== JSON.stringify(accountBook)) {
      localStorage.setItem(&quot;accountBook&quot;, JSON.stringify(accountBook));
    }
  }, [accountBook]);
  // 이 useEffect 훅은 accountBook 데이터가 변경될 때마다 localStorage에 저장합니다.
  // 의존성 배열에 accountBook이 포함되어 있어, accountBook이 변경될 때마다 effect 함수가 실행됩니다.
  // 먼저 localStorage에서 저장된 accountBook 데이터를 가져오고, 현재 accountBook 데이터와 비교하여 다르면 localStorage에 업데이트합니다.

  const [selectedMonth, setSelectedMonth] = useState(null);
  // 이 부분은 선택된 월을 관리하는 state를 초기화합니다. 초기값은 null입니다.

  return (
    &lt;Routes&gt;
      {/* React Router를 사용하여 두 개의 경로를 정의합니다. */}
      &lt;Route
        path=&quot;/&quot;
        element={
          &lt;Home
            accountBook={accountBook}
            setAccountBook={setAccountBook}
            selectedMonth={selectedMonth}
            setSelectedMonth={setSelectedMonth}
          /&gt;
        }
      /&gt;
      {/* 루트 경로 &#39;/&#39;에 대해 Home 컴포넌트를 렌더링합니다.
          Home 컴포넌트에 accountBook, setAccountBook, selectedMonth, setSelectedMonth 를 props로 전달합니다. */}
      &lt;Route
        path=&quot;/:id&quot;
        element={
          &lt;Detail accountBook={accountBook} setAccountBook={setAccountBook} /&gt;
        }
      /&gt;
      {/* 동적 경로 &#39;/:id&#39;에 대해 Detail 컴포넌트를 렌더링합니다.
          Detail 컴포넌트에 accountBook, setAccountBook를 props로 전달합니다. */}
    &lt;/Routes&gt;
  );
};

export default App;</code></pre>
<blockquote>
<p>코드에 대한 설명은 주석으로 처리해서 적어놨다 
아직은 코드를 보자마자 리뷰가 안 되기에 기재해놔서 눈에 익을 수 있게 해보았다.</p>
</blockquote>
<p>useEffect 훅을 사용해 의존성 배열에 accountBook을 넣어 데이터가 변경될 때마다  localStorage에 저장할 수 있게 해보았다.</p>
<p><img src="https://velog.velcdn.com/images/dalbyeol-_-11/post/023fb758-8d87-44e2-b909-e44b065bee29/image.JPG" alt=""></p>
<blockquote>
<p>이 부분은 localStorage에 저장하는 것이기에 기본적인 코드 방식만 알면 생각보다 쉽게 적용할 수 있다.</p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/dalbyeol-_-11/post/4b75f53e-21b3-4f5a-9815-803f3bb42e72/image.JPG" alt=""></p>
<blockquote>
<p>useState 훅을 사용해서 월을 관리하는 state의 초기값을 <code>null</code>로 초기화 해주면 된다. 쉽죠~~?</p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/dalbyeol-_-11/post/2b422bf6-4e4c-4f14-af5d-52d30e4932d4/image.JPG" alt=""></p>
<blockquote>
<p>제일 중요하다고 생각한 부분!! 
react-router를 사용해서 두 컴포넌트를 이어준다
accountBook,setAccountBook,selectedMonth,setSelectedMonth 4개를 props로 Home 컴포넌트에 전달해주고 Detail 컴포넌트에 필요한 accountBook, setAccountBook을 props로 전달하면서  path 경로를 통해 컴포넌트를 렌더링 해주면 된다~! </p>
</blockquote>
<p>Home 컴포넌트엔 가계부 정보를 입력하는 HomeForm,Month,MonthItem 3개의 컴포넌트가 있고</p>
<p>App.jsx에서 해줬던 방식과 비슷하게 각 컴포넌트로 뿌려주면 된다.
<img src="https://velog.velcdn.com/images/dalbyeol-_-11/post/6045750f-3929-43bc-b81b-d1cf1ad030a3/image.JPG" alt=""></p>
<blockquote>
<p>주석에도 써 있듯이  주어진 데이터에서 특정 월의 데이터를 필터링 후 반환해주게 한다.</p>
</blockquote>
<p>Form 컴포넌트에서 사용된 부분들을 간단하게 살펴보자면
<img src="https://velog.velcdn.com/images/dalbyeol-_-11/post/99334857-a3eb-40fe-a52f-d4eb4536e76e/image.JPG" alt=""></p>
<blockquote>
<p>구조분해 할당을 이용하여 하나의 객체로 만들어준다.
유효성 검사와 form 태그를 사용했기에 <code>PreventDefault()</code>는 늘 따라오는 것이니 다시 한 번 기억 해주자!
새로운 가계부 정보를 담은 객체를 선언하고 콜백 함수를 사용하여 기존 가계부 정보에 새로운 정보를 추가 해준다.
<img src="https://velog.velcdn.com/images/dalbyeol-_-11/post/2094ec07-b594-4787-97ff-4fbbb907a88e/image.JPG" alt="">
<img src="https://velog.velcdn.com/images/dalbyeol-_-11/post/a1cd61c6-db03-4bbb-a74e-76f02523d3fe/image.JPG" alt="">
그러기 위해선 초기값 함수 호출 <code>handleInputReset()</code>은 필수인 거 아시죠~? </p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/dalbyeol-_-11/post/1c0ac371-b869-4fba-8319-a3bff05f4089/image.JPG" alt=""></p>
<blockquote>
<p>input 창 안의 부분도 각각 입력해준다.
이 외에 다른 항목엔 ref를 제외한 형식이 똑같으니 각각에 맞는 값을 입력하여 작성해주면 된다.</p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/dalbyeol-_-11/post/d6cd60e6-1ab5-4897-9d45-cc1fd81a86c8/image.JPG" alt=""></p>
<blockquote>
<p>Month 컴포넌트에서는 먼저 1~12월 까지의 배열을 선언해주고, 각 월을 선택했을 때 실행될 수 있게 함수를 만들어준다. 이 부분은 생각보다 간단해서 당황한 부분이 없지 않았다..</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[TIL]]></title>
            <link>https://velog.io/@dalbyeol-_-11/TIL-wfvqsg6c</link>
            <guid>https://velog.io/@dalbyeol-_-11/TIL-wfvqsg6c</guid>
            <pubDate>Tue, 04 Jun 2024 22:18:10 GMT</pubDate>
            <description><![CDATA[<h1 id="redux">Redux</h1>
<br>
: JS 상태관리 라이브러리{상태(state)=데이터} = 전역상태 라이브러리
: Single source of truth => 1)동일한 데이터는 항상 같은 곳에서 가져온다. = store라는 하나의 데이터 공간
: State is read-only => 리액트에선 setState 메서드를 활용해야만 상태 변경 가능, 리덕스에선 `액선`이라는 객체를 통해서만 상태 변경 가능.
: Change are made with pure functions => 변경은 순수 함수로만 가능, reducer와 연관있다, (store - action - reducer)

<hr>
<p><img src="https://velog.velcdn.com/images/dalbyeol-_-11/post/72b86f94-75ca-40da-ae99-6709ff018a20/image.JPG" alt=""></p>
<ul>
<li><h3 id="store">Store</h3>
<h4 id="-상태-관리-공간">: 상태 관리 공간</h4>
<h4 id="-필요한-상태를-담는다">: 필요한 상태를 담는다.</h4>
<h4 id="-컴포넌트에서-상태-정보가-필요할-때-접근한다">: 컴포넌트에서 상태 정보가 필요할 때 접근한다.</h4>
<img src="https://velog.velcdn.com/images/dalbyeol-_-11/post/b2fb4a2b-c3d5-4025-a6cb-49444d0b015d/image.JPG" alt=""></li>
</ul>
<ul>
<li><h3 id="action">Action</h3>
<h4 id="-앱에서-store에-운반할-데이터주문서">: 앱에서 store에 운반할 데이터(=주문서)</h4>
<h4 id="-js-객체-형식으로-구성">: JS 객체 형식으로 구성</h4>
</li>
<li><h3 id="reducer">Reducer</h3>
<h4 id="-action을-store에-바로-전달하는-것이-아니고-reducer에-전달해야-한다">: action을 store에 바로 전달하는 것이 아니고 reducer에 전달해야 한다.</h4>
<h4 id="-주문한-데이터를-보고-store의-상태를-업데이트">: 주문한 데이터를 보고 store의 상태를 업데이트</h4>
<h4 id="-action을-reducer에-전달하기-위해선-dispatch-매서드를-사용해야-한다">: action을 reducer에 전달하기 위해선 dispatch() 매서드를 사용해야 한다.</h4>
</li>
<li><h3 id="dispatch">Dispatch</h3>
<h4 id="-store의-내장함수-중-하나로-action을-발생시킨다">: store의 내장함수 중 하나로 action을 발생시킨다.</h4>
<h4 id="-action을-파라미터로-전달하고-reducer를-호출한다">: action을 파라미터로 전달하고 reducer를 호출한다.</h4>
</li>
</ul>
<p><img src="https://velog.velcdn.com/images/dalbyeol-_-11/post/6670b5b7-a19c-4932-bf86-d8185546f491/image.JPG" alt=""></p>
<hr>
<ul>
<li><h3 id="장점">장점</h3>
<ul>
<li>유지보수에 용이</li>
<li>디버깅에 유리</li>
<li>예측 가능</li>
</ul>
</li>
</ul>
<blockquote>
</blockquote>
<p>전역상태 관리가 필요하거나 로직이 복잡할 때, 상태가 자주 업데이트 될 때 사용하면 좋다고 한다.
그러나 이해하기 어렵다.. 너무 어렵다..ㅠㅠ
정말 봐도봐도 어렵다..</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[TIL]]></title>
            <link>https://velog.io/@dalbyeol-_-11/TIL</link>
            <guid>https://velog.io/@dalbyeol-_-11/TIL</guid>
            <pubDate>Mon, 03 Jun 2024 21:27:54 GMT</pubDate>
            <description><![CDATA[<h1 id="custom-hook">Custom hook</h1>
<p>: 사용자(개발자)가 직접 만드는 hook이다.
: 사용시 use를 앞에 붙인다.
: useState, useEffect와 같은 내장 훅을 사용한다.
: 코드의 중복과 재사용성, 효율적 관리를 위해 사용
: 배열 또는 obj를 리턴한다</p>
<blockquote>
<p>왜 사용하냐에 대해서 생각해 봤을 때, 같은 로직을 반복적으로 사용하는 것에 대한 귀찮음?이 큰 부분을 차지해  한 곳에 몰아놓고 필요할 때 꺼내 사용하게 하는 기능인 듯 싶다. </p>
</blockquote>
<ul>
<li>커스텀 훅들은 따로 hooks라는 폴더 안에서 관리하는 방식으로 디렉토리 구조를 설계한다.</li>
</ul>
<p><a href="https://ko.legacy.reactjs.org/docs/hooks-custom.html">리액트 공식문서</a>를 참고하면 왜 사용하는가에 대한 이해가 쉽다.</p>
<p>예시&gt;</p>
<pre><code class="language-jsx">import { useState } from &#39;react&#39;;

// 커스텀 훅 정의
function useCounter(initialValue = 0) {
  const [count, setCount] = useState(initialValue);
  // count를 증가시키는 함수
  function increment() {
    setCount(count + 1);
  }
  // count를 감소시키는 함수
  function decrement() {
    setCount(count - 1);
  }
  // count를 리셋하는 함수
  function reset() {
    setCount(initialValue);
  }
  // 현재 count와 관련된 값을 반환하는 함수
  function getCount() {
    return count;
  }

  return {
    count,
    increment,
    decrement,
    reset,
    getCount,
  };
}
// 커스텀 훅 사용 예제
function Counter() {
  const counter = useCounter(0);

  return (
    &lt;div&gt;
      &lt;p&gt;Count: {counter.count}&lt;/p&gt;
      &lt;button onClick={counter.increment}&gt;증가&lt;/button&gt;
      &lt;button onClick={counter.decrement}&gt;감소&lt;/button&gt;
      &lt;button onClick={counter.reset}&gt;리셋&lt;/button&gt;
    &lt;/div&gt;
  );
}

export default Counter;</code></pre>
<blockquote>
<p>간략하게 예시 코드를 통해서 custom 훅이 어떻게 사용 되는지 알 수 있다. 
위와 같은 코드는 간략해서 크게 체감하지 못하지만 코드의 양이 많거나 복잡한 코드가 작성되어 있을 때 확실한 효과를 볼 수 있다고 생각한다.</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[TIL]]></title>
            <link>https://velog.io/@dalbyeol-_-11/24.05.31-TIL</link>
            <guid>https://velog.io/@dalbyeol-_-11/24.05.31-TIL</guid>
            <pubDate>Sat, 01 Jun 2024 12:40:27 GMT</pubDate>
            <description><![CDATA[<h1 id="memoization">memoization</h1>
<br>

<ul>
<li><h3 id="리렌더링의-조건">리렌더링의 조건</h3>
<h4 id="-컴포넌트에서-state가-변경됐을-때">: 컴포넌트에서 state가 변경됐을 때</h4>
<h4 id="-컴포넌트가-내려받은-props가-변경됐을-때">: 컴포넌트가 내려받은 props가 변경됐을 때</h4>
<h4 id="-부모-컴포넌트가-되어-자식-컴포넌트-모두-됐을-리렌더링-됐을-때">: 부모 컴포넌트가 되어 자식 컴포넌트 모두 됐을 리렌더링 됐을 때</h4>
</li>
<li><h4 id="불필요한-렌더링이-발생하지-안도록-최적화를-해줘야-한다">불필요한 렌더링이 발생하지 안도록 최적화를 해줘야 한다.</h4>
<h4 id="1-memoreactmemo---컴포넌트-캐싱">1. memo(React.memo) - 컴포넌트 캐싱</h4>
<h4 id="2-usecallback---함수-캐싱">2. useCallback - 함수 캐싱</h4>
<h4 id="3-usememo---값을-캐싱">3. useMemo - 값을 캐싱</h4>
</li>
</ul>
<hr>
<h4 id="1-memoreactmemo">1. memo(React.memo)</h4>
<p>:리렌더링의 발생 조건 중, 부모 컴포넌트가 리렌더링되면 자식 컴포넌트는 모두 리렌더링이 된다.</p>
<p><img src="https://velog.velcdn.com/images/dalbyeol-_-11/post/10e3c986-355b-4e9f-8a8a-66f4884859ac/image.JPG" alt="">
1번이 리렌더링 되면 2~7번 모두 리렌더링 된다.
4번이 리렌더링 되면 6,7번 모두 리렌더링 된다.</p>
<p>변경 사항 없는 컴포넌트가 때 리렌더링을 건너뛰는 것이 React.memo 도구다.</p>
<hr>
<h4 id="2-usecallback">2. useCallback</h4>
<p>: 인자로 들어오는 함수 자체를 메모이제이션한다.
: 두개의 인자를 받는다 
( 첫 번째 인자 - 메모이제이션 해 줄 콜백함수
두 번째 인자 - 의존선 배열 )</p>
<p>예&gt;</p>
<pre><code class="language-jsx">const calculate = useCallback((num) =&gt; {
    return num + 1;
}, [item])</code></pre>
<blockquote>
</blockquote>
<ol>
<li>calculate 함수를 useCallback으로 감싸준다.</li>
<li>calculate 함수는 메모이제이션된 함수를 가지고 있게된다.</li>
<li>의존성 배열 내부에 있는 값이 변경되지 않는 이상 다시 초기화 되지 않는다.</li>
<li>만약 의존성 배열 내부 값이 변경되면, calculate함수는 새로 만들어진 함수 객체로 초기화 된다.</li>
</ol>
<hr>
<h4 id="3-usememo">3. useMemo</h4>
<p>: 동일한 값을 리턴하는 함수를 반복적으로 호출할 경우, 처음 값을 메모리에 저장, 필요 시 메모리에서 꺼내 재사용 한다.
: 즉, 저장한 어떤 값이 필요할 때마다 캐시에서 꺼내 사용하는 것이다</p>
<ul>
<li>사용방법<pre><code class="language-jsx">// as-is
const value = 반환할_함수();
</code></pre>
</li>
</ul>
<p>// to-be
const value = useMemo(()=&gt; {
    return 반환할_함수()
}, [dependencyArray]);</p>
<pre><code>&gt; 
`dependencyArray`값이 변경 될 때만 `반환할_함수()`가 호출된다.]
그 외엔 메모이제이션 해놨던 값을 가져오면 된다.

---
&lt;br&gt;


예시&gt;

``` jsx
import React, { useEffect, useState } from &quot;react&quot;;

function ObjectComponent() {
  const [isAlive, setIsAlive] = useState(true);
  const [uselessCount, setUselessCount] = useState(0);

  const me = {
    name: &quot;Ted Chang&quot;,
    age: 21,
    isAlive: isAlive ? &quot;생존&quot; : &quot;사망&quot;,
  };

  useEffect(() =&gt; {
    console.log(&quot;생존여부가 바뀔 때만 호출해주세요!&quot;);
  }, [me]);

  return (
    &lt;&gt;
      &lt;div&gt;
        내 이름은 {me.name}이구, 나이는 {me.age}야!
      &lt;/div&gt;
      &lt;br /&gt;
      &lt;div&gt;
        &lt;button
          onClick={() =&gt; {
            setIsAlive(!isAlive);
          }}
        &gt;
          누르면 살았다가 죽었다가 해요
        &lt;/button&gt;
        &lt;br /&gt;
        생존여부 : {me.isAlive}
      &lt;/div&gt;
      &lt;hr /&gt;
      필요없는 숫자 영역이에요!
      &lt;br /&gt;
      {uselessCount}
      &lt;br /&gt;
      &lt;button
        onClick={() =&gt; {
          setUselessCount(uselessCount + 1);
        }}
      &gt;
        누르면 숫자가 올라가요
      &lt;/button&gt;
    &lt;/&gt;
  );
}

export default ObjectComponent;</code></pre><blockquote>
</blockquote>
<p>useEffect 훅을 사용해 me의 정보가 바뀔때만 실행되게 dependency array를 넣었지만 애석하게도 count증가button을 클릭하면 계속해서 console.log가 찍힌다.</p>
<blockquote>
<blockquote>
</blockquote>
<p>이유에 대해선 불변성과 관련이 있다.
 버튼이 선택되어 <code>uselessCount state</code>가 변경되면</p>
</blockquote>
<ol>
<li>리렌더링</li>
<li>컴포넌트 함수 호출</li>
<li>me객체 재할당</li>
<li>useEffect의 dependency array에 의해 me객체가 변경됐는지 확인한다.</li>
<li>그러나 React의 입장에선 me객체가 변경됐다고 인식하고 useEffect 내부 로직이 호출되기에 console.log에 표시된 것이다.</li>
</ol>
<pre><code class="language-jsx">const me = useMemo(() =&gt; {
  return {
    name: &quot;Ted Chang&quot;,
    age: 21,
    isAlive: isAlive ? &quot;생존&quot; : &quot;사망&quot;,
  };
}, [isAlive]);</code></pre>
<blockquote>
<p>useMemo()를 써주면 uselessCount가 증가하더라도 영향을 받지 않게된다.</p>
</blockquote>
<ul>
<li>주의사항 : useMemo의 사용 빈도수가 많게되면 별도의 메모리 확보가 과하게 되어 성능이 악화될 수 있으니 필요한 상황에만 사용하면 좋을 듯 싶다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[TIL]]></title>
            <link>https://velog.io/@dalbyeol-_-11/24.05.30-TIL</link>
            <guid>https://velog.io/@dalbyeol-_-11/24.05.30-TIL</guid>
            <pubDate>Thu, 30 May 2024 12:27:08 GMT</pubDate>
            <description><![CDATA[<h1 id="usecontext">useContext</h1>
<h5 id="-쉬운-전역-데이터-관리">: 쉬운 전역 데이터 관리</h5>
<ul>
<li><h4 id="createcontext--context-생성"><code>createContext</code> : context 생성</h4>
</li>
<li><h4 id="usecontext--context를-구독하고-해당-context의-현재값을-읽는다"><code>useContext</code> : context를 구독하고 해당 context의 현재값을 읽는다</h4>
</li>
<li><h4 id="provider--context를-하위-컴포넌트에게-전달"><code>Provider</code> : context를 하위 컴포넌트에게 전달</h4>
</li>
</ul>
<blockquote>
</blockquote>
<p>context로 관리 시, context파일을 생성하여 하위 파일을 생성 후 관리하면 된다.</p>
<ul>
<li>예시 코드&gt;<pre><code class="language-jsx">// React와 필요한 훅들을 불러온다
import React, { createContext, useContext, useState } from &#39;react&#39;;
// 컨텍스트 생성: 테마 관련 정보를 전역적으로 관리하기 위한 컨텍스트를 생성
const ThemeContext = createContext();
// ThemeProvider 컴포넌트: 테마 관련 상태와 함수를 제공하는 컴포넌트
const ThemeProvider = ({ children }) =&gt; {
// 테마 상태를 &#39;light&#39;로 초기화
const [theme, setTheme] = useState(&#39;light&#39;);
// 테마를 전환하는 함수 현재 테마가 &#39;light&#39;이면 &#39;dark&#39;로, &#39;dark&#39;이면 &#39;light&#39;로 전환
const toggleTheme = () =&gt; {
  setTheme((prevTheme) =&gt; (prevTheme === &#39;light&#39; ? &#39;dark&#39; : &#39;light&#39;));
};
// ThemeContext.Provider를 사용하여 테마 상태와 토글 함수를 자식 컴포넌트에게 전달
return (
  &lt;ThemeContext.Provider value={{ theme, toggleTheme }}&gt;
    {children}
  &lt;/ThemeContext.Provider&gt;
);
};
// ThemedComponent 컴포넌트: 실제로 테마를 사용하는 컴포넌트
const ThemedComponent = () =&gt; {
// useContext 훅을 사용해 ThemeContext에서 테마 관련 정보를 가져온다
const { theme, toggleTheme } = useContext(ThemeContext);
// 현재 테마에 따라 스타일을 조정하여 렌더링
//테마 전환 버튼을 포함
return (
  &lt;div style={{ background: theme === &#39;light&#39; ? &#39;#fff&#39; : &#39;#333&#39;, color: theme === &#39;light&#39; ? &#39;#000&#39; : &#39;#fff&#39; }}&gt;
    &lt;p&gt;현재 테마: {theme}&lt;/p&gt;
    &lt;button onClick={toggleTheme}&gt;테마 변경&lt;/button&gt;
  &lt;/div&gt;
);
};
// App 컴포넌트: 애플리케이션의 루트 컴포넌트 ThemeProvider로 ThemedComponent를 감싸 테마 기능을 제공
const App = () =&gt; {
return (
  &lt;ThemeProvider&gt;
    &lt;ThemedComponent /&gt;
  &lt;/ThemeProvider&gt;
);
};
</code></pre>
</li>
</ul>
<p>export default App;</p>
<pre><code>
&gt; 이 부분을 이해를 못해서 정말 많이 헤메고 고민도 많이 했던 훅이였다.. 지금도 100프로의 이해는 없고 5-60프로 정도 이해하지 않았나 싶다.. 
단순히 개념을 보는 것 보다 코드 연습을 통해서 익숙해지는 게 좋은 방법이 아닐까 싶다.</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[TIL]]></title>
            <link>https://velog.io/@dalbyeol-_-11/24.05.29-TIL</link>
            <guid>https://velog.io/@dalbyeol-_-11/24.05.29-TIL</guid>
            <pubDate>Thu, 30 May 2024 11:14:24 GMT</pubDate>
            <description><![CDATA[<h1 id="useref">useRef</h1>
<h5 id="-리렌더링과-상관없이-값을-기억하기-위해-사용">: 리렌더링과 상관없이 값을 기억하기 위해 사용</h5>
<h5 id="-dom-api를-직접-사용하지-않고-요소를-다루기-위한-용도">: DOM API를 직접 사용하지 않고 요소를 다루기 위한 용도</h5>
<ul>
<li>state : 리렌더링이 꼭 필요한 값을 다룰 때 사용</li>
<li>ref : 리렌더링을 발생시키지 않는 값을 저장할 때 사용</li>
</ul>
<pre><code class="language-jsx">import React, { useEffect, useRef } from &quot;react&quot;;

const App3 = () =&gt; {

const idRef = useRef(&#39;&#39;)

useEffect(() =&gt; {
idRef.current.focus();
} ,[])

  return (
    &lt;div&gt;
      &lt;div&gt;
        id: &lt;input type=&quot;text&quot; ref={idRef} /&gt;
      &lt;/div&gt;
      &lt;div&gt;
        pw: &lt;input type=&quot;password&quot; /&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  );
};

export default App3;</code></pre>
<p><code>&lt;input /&gt;</code> 태그에 ref라는 속성으로 DOM 요소에 접근할 수 있다.</p>
<p>=&gt; useRef를 사용하여 포커싱 주기
화면이 렌더링 되면 input 텍스트 타입에 포커스가 들어간다.</p>
<blockquote>
<p>state와 비슷한 만큼 유의해서 사용해야 하기 때문에 주의할 필요성이 있어보인다.</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[TIL]]></title>
            <link>https://velog.io/@dalbyeol-_-11/24.05.28-TIL</link>
            <guid>https://velog.io/@dalbyeol-_-11/24.05.28-TIL</guid>
            <pubDate>Wed, 29 May 2024 00:57:11 GMT</pubDate>
            <description><![CDATA[<h1 id="useeffect">useEffect</h1>
<h5 id="-컴포넌트가-렌더링-된-이후-특정-작업을-수행-하도록-설정할-수-있는-hook">: 컴포넌트가 렌더링 된 이후, 특정 작업을 수행 하도록 설정할 수 있는 hook</h5>
<h5 id="-렌더링-된-이후에-실행된다">: 렌더링 된 이후에 실행된다</h5>
<pre><code class="language-jsx">import React, { useState, useEffect } from &#39;react&#39;;

function StatusComponent() {
  const [status, setStatus] = useState(&#39;inactive&#39;);

  useEffect(() =&gt; {
    console.log(`Status changed to: ${status}`);
  }, [status]);
  return (
    &lt;div&gt;
      &lt;p&gt;Current status: {status}&lt;/p&gt;
      &lt;button onClick={() =&gt; setStatus(&#39;active&#39;)}&gt;Activate&lt;/button&gt;
      &lt;button onClick={() =&gt; setStatus(&#39;inactive&#39;)}&gt;Deactivate&lt;/button&gt;
    &lt;/div&gt;
  );
}

export default StatusComponent;</code></pre>
<blockquote>
<p>위 코드를 예로 설명 하면</p>
</blockquote>
<ol>
<li>useState 훅을 사용하여 status라는 상태 변수를 선언</li>
<li>초기값은 <code>&#39;inactive&#39;</code></li>
<li>useEffect 훅을 사용하여 status가 변경될 때마다 특정 작업을 수행</li>
<li>의존성 배열은 status를 주어 변경될 때마다 useEffect 내부의 콜백 함수가 실행</li>
<li>console.log로 상태 변화 메세지를 출력</li>
<li>return 부분에서 렌더링을 진행
6-1 status 상태 값을 표출
6-2 버튼을 이용하여 지정한 setStatus 값이 호출되어 status 상태가 변경
의 순서대로 코드가 실행된다.</li>
</ol>
<ul>
<li><h4 id="의존성-배열">의존성 배열</h4>
<h5 id="-배열-안-값을-입력하면-해당-값이-변경될-때만-useeffect를-실행">: 배열 안 값을 입력하면 해당 값이 변경될 때만 useEffect를 실행</h5>
<h5 id="-컴포넌트가-렌더링-된-후-한번만-실행하고-싶을-때--빈-배열로-놓으면-된다">: 컴포넌트가 렌더링 된 후 한번만 실행하고 싶을 때 &#39;[]&#39; 빈 배열로 놓으면 된다.</h5>
<h5 id="-배열-안-value-값을-넣을-경우엔-빈-배열과는-반대로-계속적으로-실행된다">: 배열 안 value 값을 넣을 경우엔 빈 배열과는 반대로 계속적으로 실행된다.</h5>
</li>
</ul>
<blockquote>
<p>코드 상황에 맞게 적절히 사용해주면 굉장히 유용해 보인다.</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[TIL]]></title>
            <link>https://velog.io/@dalbyeol-_-11/24.05.27-TIL</link>
            <guid>https://velog.io/@dalbyeol-_-11/24.05.27-TIL</guid>
            <pubDate>Mon, 27 May 2024 14:46:38 GMT</pubDate>
            <description><![CDATA[<h1 id="react-타임어택">React 타임어택</h1>
<p>1.claculator 만들기(20분)
2.Todo-list 만들기(40분)</p>
<ol>
<li>문제 풀이</li>
</ol>
<pre><code class="language-jsx">import { useState } from &quot;react&quot;;


const App = () =&gt; {

  const [count, setCount] = useState(0);
  const [number, setNumber] = useState(0)

  const handleCountUp = (el) =&gt; {
    if ( !count) return (&#39;숫자를 입력해 주세요&#39;)

    setCount(count =&gt; count + el)
  }
  const handleCountDown = (el) =&gt; {
    setCount(count =&gt; count - el)
  }

  const handleCountReset = () =&gt; {
    setCount(&#39;&#39;)
  }
console.log(useState)
  return (
    &lt;div&gt;
      &lt;h1&gt;덧셈과 뺄셈이 가능한 앱 만들기&lt;/h1&gt;
      &lt;div&gt;
        &lt;input /&gt; 만큼을
        &lt;button onClick={handleCountUp}&gt;더할게요&lt;/button&gt;
        &lt;button onClick={handleCountDown}&gt;뺄게요&lt;/button&gt;
        &lt;button onClick={handleCountReset}&gt;초기화&lt;/button&gt;
      &lt;/div&gt;
      &lt;hr /&gt;
      &lt;div&gt;
        &lt;h3&gt;결과&lt;/h3&gt;
        &lt;p&gt;0&lt;/p&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  );
}

export default App</code></pre>
<hr>
<ul>
<li>다른 문제 풀이</li>
</ul>
<pre><code class="language-jsx">const [originNum, setOriginNum] = useState(0);
const [inputNum, setInputNum] = useState(0);
const [resultNum, setResultNum] = useState(0);

const onChangeNum = (e) =&gt; {
  setInputNum(Number(e.target.value));
};

const addNum = () =&gt; {
  const newResult = originNum + inputNum;
  setResultNum(newResult);
  setOriginNum(newResult);
};

const subtractNum = () =&gt; {
  const newResult = originNum - inputNum;
  setResultNum(newResult);
  setOriginNum(newResult);
};

const resetNum = () =&gt; {
  setOriginNum(0);
  setInputNum(0);
  setResultNum(0);
};

return (
  &lt;div&gt;
    &lt;h1&gt;덧셈과 뺄셈이 가능한 앱 만들기&lt;/h1&gt;
    &lt;div&gt;
      &lt;input onChange={onChangeNum} value={inputNum} type=&quot;text&quot; /&gt; 만큼을{&quot; &quot;}
      &lt;button onClick={addNum}&gt;더하기&lt;/button&gt;{&quot; &quot;}
      &lt;button onClick={subtractNum}&gt;빼기&lt;/button&gt;
      &lt;button onClick={resetNum}&gt;리셋&lt;/button&gt;
    &lt;/div&gt;
    &lt;hr /&gt;
    &lt;div&gt;
      &lt;h3&gt;결과&lt;/h3&gt;
      &lt;p&gt;{resultNum}&lt;/p&gt;
    &lt;/div&gt;
  &lt;/div&gt;
);</code></pre>
<blockquote>
</blockquote>
<p>리액트 입문 후 첫 타임어택이라 긴장도 많이했고 
첫 문제였던 계산기 만들기는 <code>input</code>을 만들어 그 안에 숫자를 입력, 값을 넣어 반환을 했어야 했기에 단지 counter 만드는 문제의 응용 부분이였다.
다만 그 응용문제에 내가 가지고 있던 지식을 적용하지 못해 풀지 못한 것이라고 본다.<br>응용적인 부분에 있어서 취약한 것을 잘 알기에 이 부분에 대해 반복적인 학습과 타이핑을 통해 손과 머리에 익히는 방향을 잡아야겠다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[TIL]]></title>
            <link>https://velog.io/@dalbyeol-_-11/2024.05.24-TIL</link>
            <guid>https://velog.io/@dalbyeol-_-11/2024.05.24-TIL</guid>
            <pubDate>Mon, 27 May 2024 14:33:35 GMT</pubDate>
            <description><![CDATA[<h1 id="알고리즘-타임어택">알고리즘 타임어택</h1>
<ul>
<li><h3 id="문제-일관된-문자열의-개수-세기">문제: 일관된 문자열의 개수 세기</h3>
</li>
<li><h4 id="문제-요구사항-정의">문제 요구사항 (정의)</h4>
</li>
</ul>
<p>주어진 문자열 allowed와 문자열 배열 words가 있습니다. allowed 문자열은 서로 다른 문자들로 이루어져 있습니다.
각 words 배열의 문자열이 allowed에 있는 문자들만 포함하고 있을 때, 그 문자열을 &quot;일관된 문자열&quot;이라고 합니다.
여러분의 목표는 words 배열에서 일관된 문자열의 개수를 세는 것입니다.</p>
<ul>
<li><h4 id="인풋-아웃풋-예시">인풋 아웃풋 예시</h4>
</li>
<li><h5 id="예제-1">예제 1</h5>
</li>
</ul>
<blockquote>
<p>입력 : allowed = &quot;ab&quot; ,  words = [&quot;ad&quot;, &quot;bd&quot;, &quot;aaab&quot;, &quot;baa&quot;, &quot;badab&quot;]
출력 : 2</p>
<blockquote>
<p>설명 : &quot;aaab&quot;와 &quot;baa&quot;가 일관된 문자열입니다. 이들은 &#39;a&#39;와 &#39;b&#39;만 포함하고 있습니다.</p>
</blockquote>
</blockquote>
<ul>
<li><h5 id="예제-2">예제 2</h5>
</li>
</ul>
<blockquote>
<p>입력 :  allowed = &quot;abc&quot; , words = [&quot;a&quot;, &quot;b&quot;, &quot;c&quot;, &quot;ab&quot;, &quot;ac&quot;, &quot;bc&quot;, &quot;abc&quot;]
출력 : 7</p>
<blockquote>
<p>설명 : 모든 문자열이 일관된 문자열입니다. 모두 &#39;a&#39;, &#39;b&#39;, &#39;c&#39;로만 구성되어 있습니다.</p>
</blockquote>
</blockquote>
<ul>
<li><h5 id="예제-3">예제 3</h5>
</li>
</ul>
<blockquote>
<p>입력 :allowed = &quot;cad&quot;, words = [&quot;cc&quot;, &quot;acd&quot;, &quot;b&quot;, &quot;ba&quot;, &quot;bac&quot;, &quot;bad&quot;, &quot;ac&quot;, &quot;d&quot;]
출력 : 4</p>
<blockquote>
<p>설명 : &quot;cc&quot;, &quot;acd&quot;, &quot;ac&quot;, &quot;d&quot;가 일관된 문자열입니다.</p>
</blockquote>
</blockquote>
<ul>
<li>나의 문제 풀이</li>
</ul>
<pre><code class="language-jsx">function countConsistentStrings(allowed, words) {
    // 허용된 문자들을 set으로 만들어 빠른 검색이 가능하게 만든다
    const allowedSet = new Set(allowed);
    let count = 0;

    // words 배열의 각 문자열을 확인
    for (let word of words) {
        // 문자열의 모든 문자가 allowedSet에 포함되어 있는지 확인
        if (word.split(&#39;&#39;).every(char =&gt; allowedSet.has(char))) {
            count += 1;
        }
    }

    return count;</code></pre>
<ul>
<li>튜터님 문제 풀이</li>
</ul>
<pre><code class="language-jsx">function countConsistentStrings(allowed, words) {
    const allowedSet = new Set(allowed);
    return words.filter(word =&gt; [...word].every(char =&gt; allowedSet.has(char))).length;
}

function testCountConsistentStrings() {
    function runTestCase(allowed, words, expected) {
        const result = countConsistentStrings(allowed, words);
        const passed = result === expected;
        console.log(`allowed: &quot;${allowed}&quot;, words: ${JSON.stringify(words)}, expected: ${expected}, got: ${result} - ${passed ? &#39;PASSED&#39; : &#39;FAILED&#39;}`);
    }</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[TIL]]></title>
            <link>https://velog.io/@dalbyeol-_-11/24.05.23-TIL</link>
            <guid>https://velog.io/@dalbyeol-_-11/24.05.23-TIL</guid>
            <pubDate>Thu, 23 May 2024 12:39:57 GMT</pubDate>
            <description><![CDATA[<h1 id="react5">React(5)</h1>
<ul>
<li><h3 id="styled-components">styled-components</h3>
<img src="https://velog.velcdn.com/images/dalbyeol-_-11/post/95727481-bfea-49bd-937e-007a8bf77a8e/image.JPG" alt=""><blockquote>
<p>함수 선언을 하고 그 원하는대로 스타일을 꾸며주면 된다. 이 때 백틱(``)을 사용해야 한다.
이러한 방법의 장점은 css파일을 따로 생성하지 않고 JSX 페이지 내에서 한 번에 해결 할 수 있다는 것이다. </p>
</blockquote>
</li>
</ul>
<hr>
<p>전역 스타일링 =&gt; 프로젝트 전체에 공통적으로 들어가야 하는 경우</p>
<pre><code class="language-javascript">import { createGlobalStyle } from &quot;styled-components&quot;;

const GlobalStyle = createGlobalStyle`
  body {
    font-family: &quot;Helvetica&quot;, &quot;Arial&quot;, sans-serif;
    line-height: 1.5;
  }
`;

export default GlobalStyle;</code></pre>
<blockquote>
<p>createGlobalStyle 을 import해주고  스타일을 적용해주면 된다.</p>
</blockquote>
<hr>
<p><img src="https://velog.velcdn.com/images/dalbyeol-_-11/post/bcad8ee5-f2aa-4ff6-8ee8-1a9f9ad79da5/image.JPG" alt=""></p>
<blockquote>
</blockquote>
<p><code>&lt;styleBox&gt;</code>라는 컴포넌트 안에 변수를 넣어 원하는 스타일을 입혀주게 해주면 된다. 작명의 고통이 물론 수반되긴 한다..</p>
<blockquote>
</blockquote>
<p>한가지 더 곁들이자면 reset.css는 앞으로의 모든 작업 파일에서 필수적으로 들어간다.
디폴트 값으로 스타일이 적용된 경우가 있기에 이것 조차 초기화를 시켜주는 의미에서 넣어주는 것이니 숨쉬듯 적용해주면 된다.</p>
]]></description>
        </item>
    </channel>
</rss>