<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>ethan_world.log</title>
        <link>https://velog.io/</link>
        <description>효율매니아</description>
        <lastBuildDate>Tue, 02 Apr 2024 06:02:53 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>ethan_world.log</title>
            <url>https://velog.velcdn.com/images/ethan_world/profile/ba406bb0-2e41-4034-bb2e-5678f11c8442/image.jpeg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. ethan_world.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/ethan_world" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[app router에서 next-auth 활용하기]]></title>
            <link>https://velog.io/@ethan_world/app-router%EC%97%90%EC%84%9C-next-auth-%ED%99%9C%EC%9A%A9%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@ethan_world/app-router%EC%97%90%EC%84%9C-next-auth-%ED%99%9C%EC%9A%A9%ED%95%98%EA%B8%B0</guid>
            <pubDate>Tue, 02 Apr 2024 06:02:53 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>진행중인 프로젝트에서 discord Oauth를 구현할 필요가 생겼고, next-auth를 사용하며 리서치한 내용을 정리했습니다. 공식 문서에서는 Page router를 기준으로 설명하여 접근하기 어려웠던 경험이 있어 공유합니다 🧐</p>
</blockquote>
<h2 id="1-next-auth">1. next-auth</h2>
<ul>
<li>next-auth는 next.js를 사용한 서비스의 사용자 인증 및 세션 관리를 쉽게 구현할 수 있도록 도와주는 오픈소스 솔루션이다.</li>
</ul>
<h2 id="2-적용하기">2. 적용하기</h2>
<ol>
<li><code>npm install next-auth</code>을 프로젝트 터미널에 입력하여 필요한 라이브러리를 다운로드합니다.</li>
<li>app-router를 사용하는 프로젝트에서 app/api/auth/[...nextauth] 경로에 route.ts 파일을 생성합니다.<img src="https://velog.velcdn.com/images/ethan_world/post/ca2da059-2d5b-4cbd-93ad-ce32c4a0a953/image.png" width="250" height="300"></li>
<li>지금 당장은 callbacks를 무시하고 위의 providers에 사용할 인증업체를 작성하고 그 업체에서 부여한 ID와 Secret을 환경변수로 만들어 아래처럼 값을 넣어줍니다. <img src="https://velog.velcdn.com/images/ethan_world/post/b59ff7f9-3c93-4acc-9149-edfcf0041a01/image.png" width="450" height="300"></li>
<li>환경변수(.env)로 <code>NEXTAUTH_URL</code> <code>NEXTAUTH_SECRET</code> 값을 설정해줍니다. 개발단계에서는 URL은 일단 localhost:3000을 SECRET은 &quot;secret&quot;으로 부여해줬습니다. </li>
<li>인증업체에서 인증을 완료한 후 redirect 주소를 설정해줍니다. 디스코드 개발자 포탈에서 아래처럼 URL을 만들어줬습니다.<img src="https://velog.velcdn.com/images/ethan_world/post/c91cbd63-9b0a-457f-8d97-c0edee646467/image.png" width="600" height="300"></li>
<li>이제 session provider를 만들어 클라이언트에서도 세션정보를 확인할 수 있도록 해야합니다. 저는 다크모드를 관리하는 provider가 이미 있으니 providers 폴더를 만들어서 개별적으로 관리하겠습니다.<img src="https://velog.velcdn.com/images/ethan_world/post/7d63562e-d1cf-4c6f-8984-b4e5e18468a5/image.png" width="600" height="300">
이렇게 provider를 만들고, root layout을 감싸줬습니다. 이 provider에는 getServerSession() 함수를 사용하여 서버에서 받은 세션을 prop으로 내려주고 사용하는 하는 걸 볼 수 있습니다.
<img src="https://velog.velcdn.com/images/ethan_world/post/252f078d-159a-4ba5-9fe9-55d1fad55613/image.png" width="600" height="300">


</li>
</ol>
<h2 id="3-사용하기">3. 사용하기</h2>
<ol>
<li>사용을 위한 모든 준비를 했습니다. 이제 로그인과 로그아웃 버튼을 만들어서 next-auth에서 제공한 함수를 버튼에 붙혀주면 작업이 끝납니다.<img src="https://velog.velcdn.com/images/ethan_world/post/9000203d-c74a-4bae-b21f-67b2442e73fc/image.png" width="600" height="300">
AuthButton 이라는 컴포넌트를 만들었고 여기서 로그인 버튼을 만들었습니다. onClick 트리거 내부에 `signIn()` 이라는 next-auth 함수를 배치하고 인자로 `'discord'`를 넣어주면 모든 작업이 끝납니다. 이 버튼 컴포넌트에서 useSession을 통해 유저가 로그인을 완료하여 세션이 존재하면 로그아웃 버튼을 갖고있는 Profile 컴포넌트를 노출시키게 만들었습니다.


</li>
</ol>
<h2 id="4-엣지케이스">4. 엣지케이스</h2>
<ul>
<li>애초에 discord의 userId 값에 접근하기 위해 위 방식의 Oauth 진행을 시도했습니다. 하지만 로그인 후 받은 세션을 확인해보면 <img src="https://velog.velcdn.com/images/ethan_world/post/7e72dca4-08f7-404e-9a75-046b6d4f09c3/image.png" width="200" height="300">
아쉽게도 userId를 받아오지 못합니다. 이때 위에서 무시했던 callbacks를 사용하여 세션 정보를 수정할 수 있습니다.<img src="https://velog.velcdn.com/images/ethan_world/post/e67d0f73-1219-4ffe-80c1-7e727183e105/image.png" width="600" height="300">
userId를 갖고있는 token.sub를 session의 id로 선언해주면됩니다.</li>
</ul>
<blockquote>
<p>그냥 사용하면 type 에러가 발생합니다. session의 인터페이스는 위 사진처럼 id가 존재하지 않는 형태니깐요. 따라서 프로젝트 폴더에서 next-auth.d.ts를 생성하여 아래처럼 module의 인터페이스를 수정해줘야 type관련 에러를 해결할 수 있습니다.<img src="https://velog.velcdn.com/images/ethan_world/post/8026287a-bd07-4921-ad92-520e0dd9fb2b/image.png" width="400" height="300"></p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[디스코드 봇을 활용한 프론트엔드 프로젝트]]></title>
            <link>https://velog.io/@ethan_world/%EB%94%94%EC%8A%A4%EC%BD%94%EB%93%9C-%EB%B4%87%EC%9D%84-%ED%99%9C%EC%9A%A9%ED%95%9C-%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8</link>
            <guid>https://velog.io/@ethan_world/%EB%94%94%EC%8A%A4%EC%BD%94%EB%93%9C-%EB%B4%87%EC%9D%84-%ED%99%9C%EC%9A%A9%ED%95%9C-%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8</guid>
            <pubDate>Thu, 18 Jan 2024 06:31:07 GMT</pubDate>
            <description><![CDATA[<p>포트폴리오에 비슷비슷한 유형의 프로젝트들이 늘어가는 걸 인지하게 됐고, 조금 더 신선한 개발을 해보고 싶어서 고민하던 중에 디스코드 봇을 활용해서 스케줄링 서비스를 만들어보게 됐다.</p>
<p>요즘에 친구들이랑 발로란트를 자주 플레이하는데 총 10명을 필요로 하는 게임이기도 하고 인원들의 실력에 따라서 균형 있는 팀을 짜기도 쉽지 않은 일이라 생각했고, 이 점을 웹의 핵심 기능으로 만들면 좋을 거 같았다.</p>
<blockquote>
</blockquote>
<p>전체적인 로직 자체은 이렇다.</p>
<blockquote>
</blockquote>
<ol>
<li>친구들과 있는 디스코드 채널에 봇을 초대한다. </li>
<li>해당 봇의 명령어로 내전을 스케줄한다.</li>
<li>그 날짜에 참여가 가능한 인원 역시 명령어로 참여를 신청한다.</li>
<li>웹으로 위에 스케줄한 내전과, 인원들을 나열한다.</li>
<li>인원들의 실력지표를 입력한다. (Valorant API를 이용하기가 은근 귀찮아서..)</li>
<li>실력 지표에 따라서 팀을 만들고 내전을 즐긴다.</li>
</ol>
<h2 id="discordjs">Discord.js</h2>
<p>디스코드 봇을 어떻게 만들 수 있을지 열심히 구글링 해본 결과, discord.js 라는 라이브러리를 발견할 수 있었다. 프론트엔드 개발자라면 익숙한 node.js 기반으로 봇을 굴릴 수 있게 도움을 주는 라이브러리이고 사용법 또한 어렵지 않았다.</p>
<ol>
<li>먼저 <a href="https://discord.com/developers/docs/intro">Discord Dev Portal</a>에 들어가서 어플리케이션을 만들어준다.
<img src="https://velog.velcdn.com/images/ethan_world/post/2c86c742-f167-4500-b272-94192b769db5/image.png" alt="">
( client Id 와 Secret 값을 .env에 복붙하여 가지고 와야겠죠? )</li>
</ol>
<ol start="2">
<li><p>Discord.js의 문서를 보면 require 방식으로 모듈을 불러오는데 import로 통일하고 싶어서 package.json에 <code>&quot;type&quot;: &quot;module&quot;</code> 을 추가해주었다.</p>
</li>
<li><p>아래코드의 body에 내가 만든 커멘드를 불러와서 배열요소로 넣어주는 걸로 봇이 동작한다.
<img src="https://velog.velcdn.com/images/ethan_world/post/12ee8ac2-a215-4fc2-a5e1-d8c8ea44b528/image.png" alt=""></p>
</li>
<li><p>배포는 처음엔 <a href="https://cloudtype.io/">cloudtype</a> 서비스를 이용했으나, 최근에 운영이 바뀌면서 24시간 작동하는 프리티어가 사라졌다. (새벽시간에 봇이 꺼짐). 암튼 그래서 aws의 제품을 사용해야 할 거 같은데 아직 해보지는 않았다. cloudtype의 자동 배포 기능이 참 편하고 좋았는데 아쉽다.. </p>
</li>
</ol>
<hr>
<p>배포는 EC2로 진행해보려고 했고, 서버에 봇을 띄워서 가동은 해봤다. 슬프게도 문제가 발생했는데 cloudtype 서버 시간대로 작동하는 함수들이 있어서 제대로 돌아가지는 않았고, 이를 해결하기 위해서는 서버시간에 영향을 받는 함수들을 손봐야 했는데 서버시간을 상수로 선언하지 않았던게 참 아쉽다. 어쨌든 번거로운 과정을 거치기 싫어 일단 cloudtype으로 배포했다. </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[좋은 컴포넌트란?]]></title>
            <link>https://velog.io/@ethan_world/%EC%A2%8B%EC%9D%80-%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8%EB%9E%80</link>
            <guid>https://velog.io/@ethan_world/%EC%A2%8B%EC%9D%80-%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8%EB%9E%80</guid>
            <pubDate>Thu, 05 Oct 2023 08:27:18 GMT</pubDate>
            <description><![CDATA[<h2 id="컴포넌트의-정의">컴포넌트의 정의</h2>
<img src="https://velog.velcdn.com/images/ethan_world/post/924a656a-26e1-44c2-ac16-67e6e8fe87fa/image.png" width="600" height="400">

<p>개발을 하다보면 이 작업이 레고를 조립하는 것과 비슷하다고 생각이 든다.</p>
<p>레고를 다른 레고와 연결하여 성의 문을 만들고, 집을 만들고, 조명을 만들어서 하나의 큰 작품을 만들어내는 작업은 꽤나 개발과 비슷하다.</p>
<p>소프트웨어 개발에서의 <code>컴포넌트</code>라는 것은 위에서 말한 성의 문 또는 집과 같은 레고들의 한 뭉치를 뜻한다. 그리고 레고들의 한 뭉치는 UI의 요소가 된다.</p>
<p><img src="https://velog.velcdn.com/images/ethan_world/post/9e416714-7c89-4d32-950e-d7382a4218b8/image.png" alt=""></p>
<blockquote>
<p>컴포넌트는 특정 기능 혹은 View를 나타내는 UI 요소이다.</p>
</blockquote>
<p>UI는 더 큰 범주이긴 하지만, 좋은 UI에 대한 고민은 좋은 컴포넌트에 대한 고민과 같지 않을까?</p>
<p>그럼 좋은 컴포넌트란 무엇일까?</p>
<h2 id="good-component">Good Component</h2>
<p>소프트웨어 개발 부분에서 컴포넌트가 하는 일은</p>
<ol>
<li>외부에서 주입받은 데이터를 관리하여</li>
<li>UI로써 사용자들에게 데이터를 보여주고</li>
<li>사용자와 상호작용을 한다.</li>
</ol>
<img src="https://velog.velcdn.com/images/ethan_world/post/ee1621af-c37e-401f-b8f2-041b247a77e2/image.png" width="700" height="400">

<h3 id="관심사-분리">관심사 분리</h3>
<ul>
<li>데이터 추상화: 데이터와 UI를 분리하고, 데이터에 집중하여 모듈화를 할 수 있는 패턴이고 이를 Headless 라고 한다. 변경으로부터 격리할 수 있고, 한 가지 문제에만 집중 할 수있다.</li>
<li>상호작용 추상화: 사용자와 상호작용이 필요한 모듈을 따로 만들고, 이를 UI에 탈부착하는 형식으로 진행할 수 있다. 예를 들어 <code>button</code>으로 상호작용을 진행할 때 원하는 UI의 모습을 따로 관리하고, 해당 상호작용을 커스텀 훅을 만들어 UI로부터 분리할 수 있다. 결과적으로 <code>button</code> 모듈을 하나의 컴포넌트에서뿐만 아니라 다른 곳에서도 재사용 가능하게 만들어 줄 수 있다.</li>
</ul>
<blockquote>
<p>변경에 유연해지려면 (만들어둔 커스텀훅을 용이하게 재사용하려면) 그 모듈을 한 가지 일에만 집중하게 (단일 책임 원칙) 만드는게 중요하다. 이는 최적화를 꾀하지는 않지만, 코드 가독성이 좋아지는 단점과 장점도 갖고있다. </p>
</blockquote>
<ul>
<li>코드 예시:</li>
</ul>
<img src="https://velog.velcdn.com/images/ethan_world/post/c05f1f43-ee75-4e61-a0d9-8f5872d29281/image.png" width="400" height="300">

<p>Button 컴포넌트는 버튼을 보여주고 또 클릭될 때 호출할 이벤트 핸들러(onClick)를 전달 받는다.</p>
<img src="https://velog.velcdn.com/images/ethan_world/post/a7692ff8-1a40-41e0-9058-ed9e976ded67/image.png" width="400" height="300">

<p>위 코드에서 사용자 상호 작용을 처리한다. 버튼이 클릭될 때 handleButtonClick 함수가 실행되고 상태(count)를 업데이트한다.</p>
<p>이러한 방식으로 UI 컴포넌트와 사용자 상호 작용을 분리할 수 있다. UI 컴포넌트는 단순히 UI를 표시하고, 사용자 상호 작용은 별도의 이벤트 핸들러를 통해 처리된다. 이로써 코드의 가독성과 유지 보수성이 향상되며, UI 변경과 사용자 상호 작용 로직 변경을 쉽게 다룰 수 있다.</p>
<hr>
<p>컴포넌트는 가장 작은 단위의 UI에서부터 시작한다.</p>
<p>어디에나 조립할 수 있는 한 조각의 레고와 마찬가지로, 컴포넌트를 만들 때 처음부터 재사용성을 고려하며 만든 것과 그렇지 않은 것의 차이는 꽤 큰데. 여러 이유가 있다. </p>
<ul>
<li><p>컴포넌트의 재사용을 염두하고 만들게 된다면, 컴포넌트는 대부분의 경우 하나의 역할만을 맡게 된다. 이는 검증된 개념인 단일 책임 원칙과 관련 있다.</p>
</li>
<li><p>재사용할 수 있는 컴포넌트는 한 번 작성한 컴포넌트를 여러 프로젝트나 다른 부분에서 재사용할 수 있으므로 코드 수정 및 버그 수정이 단순화된다. 반대의 경우, 컴포넌트는 변경에 굉장히 취약하여 사이드 이펙트와 같은 문제가 발생하여 유지보수가 어려워진다. </p>
</li>
<li><p>재사용 가능한 컴포넌트는 여러 개발자 간의 협업을 더욱 원활하게 해준다. 컴포넌트가 단일 역할을 하고 예측할 수 있는 방식으로 작동하기 때문에 팀 전체에서 일관성을 유지하기가 더 쉬워진다.</p>
</li>
</ul>
<p>아직 개발하면서 좋은 컴포넌트는 재사용에 용이한 컴포넌트라고밖에 단정 짓지 못했다. 단일 책임 원칙, 관심사 분리, 확장성과 의존성 등의 개념들의 공통된 목적은 변경과 재사용에 용이한 컴포넌트를 만들기 위한 개념이라고 생각된다. 결국 좋은 컴포넌트는 서비스 전체적인 품질과 성능을 좌지우지하는 것이기 때문에 끊임없이 업데이트되는 개발 환경에서 계속해서 고민해고 개선해야 하는 주제라는 생각을 한다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[작업 프로세스 정리]]></title>
            <link>https://velog.io/@ethan_world/%EB%82%98%EB%A7%8C%EC%9D%98-%EC%9B%B9-%EA%B0%9C%EB%B0%9C-%EC%8B%9C%EC%8A%A4%ED%85%9C</link>
            <guid>https://velog.io/@ethan_world/%EB%82%98%EB%A7%8C%EC%9D%98-%EC%9B%B9-%EA%B0%9C%EB%B0%9C-%EC%8B%9C%EC%8A%A4%ED%85%9C</guid>
            <pubDate>Wed, 06 Sep 2023 07:52:31 GMT</pubDate>
            <description><![CDATA[<p>우리는 효율적으로 일을 하기 위해 반복적인 작업을 그룹화하여 처리한다. 웹 개발에서 사용하는 디자인 시스템 같은 걸 예로 들을 수 있겠다. 반복 작업들로 이루어진 그룹들을 또 전체로 묶어 시스템이라 명칭 하는데 이런 시스템은 일상의 어느곳에서든 적용할 수 있다. </p>
<p>이번 글을 통해서 나는 내가 갖고 있는 여러 가지 개발 습관을 분류하고 그룹화하여 앞으로 만날 여러 종류의 프로젝트들을 효율적으로 작업할 수 있길 바란다.</p>
<hr>
<h2 id="📝-기획-시스템">📝 기획 시스템</h2>
<p>내 작업의 목적을 짧게 정의하면 &quot;사용자에게 제공&quot;이라고 생각한다. 정해진 시간 내에 특정 서비스를 유저에게 사용하기 편리하고 보기 깔끔하게 만들어 전달해야 한다. 
그러기 위해선 기획 단계에서 서비스에 맞춰 내가 사용할 기술 스택을 고민만 하는 것뿐만 아닌, 더 나아가 어떤 라이브러리를 먼저 사용할지 나열하고 미리 필수 기능 테스트를 진행하는 과정을 추가하는 게 좋아 보인다. 악보의 정원 프로젝트 진행 중 음원을 조회하는 기능을 만들 때 기술 문제 때문에 작업이 지체된 적이 있었는데 이때 기획 단계에서 얘기했던 Spotify나 다른 음원 조회 api를 리스트업만 하는 것이 아닌 실행 가능성까지 파악하는 것이 미흡했었다.</p>
<p>그럼, 기획 작업을 어떻게 시스템화할 수 있을까? 아래에 타임라인별로 정리해보자.</p>
<h3 id="시작전">시작전</h3>
<ol>
<li><p>프로젝트 목표 설정:</p>
<ul>
<li>프로젝트 목표와 목적 설정</li>
<li>핵심 성공 지표 정의</li>
<li>주요 대상 사용자 그룹 식별</li>
<li>사용자 요구사항 및 기대치 문서화</li>
</ul>
</li>
<li><p>기술 스택 선택, 스코프 정의:</p>
<ul>
<li>프로젝트 범위 정의</li>
<li>기능 명세서 작성</li>
<li>사용할 기술 스택 및 도구 결정</li>
</ul>
</li>
<li><p>시간 계획:</p>
<ul>
<li>자원 할당 계획 수립</li>
<li>프로젝트 일정 세분화 및 마일스톤 정의 (미리 이슈또는 PR을 만들어서 작업하면 작업간 혼동을 최소화 할 수 있을 거 같다)</li>
</ul>
</li>
<li><p>요구사항 정의:</p>
<ul>
<li>상세한 요구사항 문서 작성</li>
<li>UI/UX 디자인과 데이터 모델링 작업 수행 (개인작업일 경우 아래에 작성한 디자인 시스템 사용)</li>
</ul>
</li>
<li><p>품질 관리 및 테스트 계획:</p>
<ul>
<li>테스트 계획 작성 (기술 스택과 요구사항 문서를 통해 사용해야하는 라이브러리, API 테스트)</li>
<li>테스트 케이스 및 품질 기준 정의</li>
</ul>
</li>
<li><p>프로젝트 관리 및 커뮤니케이션 계획 (팀단위 프로젝트):</p>
<ul>
<li>프로젝트 관리 방법론 선택</li>
<li>회의 일정 및 이슈 추적 방법 정의</li>
</ul>
</li>
<li><p>위험 관리:</p>
<ul>
<li>프로젝트 위험 식별</li>
<li>위험 관리 계획 수립</li>
</ul>
</li>
<li><p>관리 및 감독체계 (팀단위 프로젝트):</p>
<ul>
<li>팀원 역할과 책임 정의</li>
<li>의사 결정 프로세스 및 업무 흐름 설계</li>
</ul>
</li>
</ol>
<h3 id="진행중">진행중</h3>
<ol start="9">
<li><p>프로젝트 문서화:</p>
<ul>
<li>프로젝트 관련 모든 문서 정리 및 유지</li>
</ul>
</li>
<li><p>변경 관리:</p>
<ul>
<li>변경 요청 및 승인 프로세스 관리</li>
</ul>
</li>
<li><p>프로젝트 피드백 및 개선:</p>
<ul>
<li>팀원또는 이해관계자들로부터의 피드백 수용 및 개선사항 적용</li>
</ul>
</li>
</ol>
<h3 id="마무리">마무리</h3>
<ol start="12">
<li>완료 및 평가:<ul>
<li>프로젝트 완료 평가</li>
<li>성과 지표를 통한 목표 달성 여부 확인</li>
</ul>
</li>
</ol>
<p>위에 작성한 타임라인은 아무래도 노션 템플릿을 하나 만들어 놓는게 좋겠다.</p>
<h2 id="🎨-디자인-시스템-정리">🎨 디자인 시스템 정리</h2>
<p>프로젝트를 끝내고 돌이켜보면 가장 많이 떠오르는 게 좀 더 섬세한 디자인 시스템에 대한 욕심이다.
미적 감각이 떨어진다는 이유로 팀으로 작업 할 때는 피그마를 되도록 멀리했고, 혼자 작업할 때는 다른 레퍼런스를 카피하곤 했다. 앞으로 진행하고 싶은 사이드 프로젝트가 많은데 이걸 언제까지 외면할 수는 없다고 생각한다. 따라서 나의 디자인 시스템을 정리하고, 팀단위 프로젝트가 진행되고 얻은 인사이트로 조금씩 업데이트 해나가는 노력이 필요하다.</p>
<p>최초로 시도했던 노력은 악보의 정원 프로젝트를 진행할 때 했던 구체적인 Figma 작업과 storybook을 사용한 UI 테스트였다. 공들여 만들었기에 react component로 수월하게 만들어 낼 수 있었지만, Figma의 component 기능을 100% 활용하지 않고 생김새를 구현하는 데에 급급했던게 아쉽다고 생각한다. 시간을 조금 더 들여서 variant/property 같은 기능을 사용해 관리의 용이함을 얻었다면 팀원들과의 소통에도 도움되고 아토믹 디자인 패턴에 맞게 설계할 수 있었을 거 같다.</p>
<p>프로젝트 디자인의 일관성을 유지하고, 효율적인 개발 및 디자인 경험을 만들기 위해 Figma를 이해하고 데스크탑, 모바일에서 통용되는 여러 약속에 대한 지식 습득이 필요할 거 같다.</p>
<h2 id="🧑💻-개발-시스템-정리">🧑‍💻 개발 시스템 정리</h2>
<p>서비스를 개발할 때 어떻게 하면 더 효율적이고 유기적인 움직임을 가져갈 수 있을까?</p>
<p>개발하면서 마주치는 어려움 중 하나는 이미 작성된 코드를 수정해야할때 일겁니다.
그 코드가 단순한 코드여서 사이드 이펙트를 고려하며 수정하여도, 가끔은 완전히 그 영역을 커버하지 못 할 때가 있죠. 따라서 대다수의 개발자들은 코드수정에 꽤 예민한 편입니다 특히 동료가 내가 쓴 코드를 읽고 수정할 때..</p>
<p>또 영원히 수정이 필요없는 코드는 없죠, 끊임없이 리펙토링하고 새로운 기능을 추가하며 서비스를 계속 발전시키는게 저희의 임무입니다.</p>
<p>결국 효율적으로 개발하기 위해 우리는 가독성이 좋고 장기적인 유지보수에 용이한 코드를 작성해야 하는데 이를 위해서 코드를 작성하기 전 팀적으로 <code>약속</code> 을 만들곤 합니다. </p>
<p>가장 큰 뼈대인 소프트웨어 아키텍처부터 살펴보죠.</p>
<p>아키텍처는 소프트웨어의 기본적인 구성 요소, 그들 사이의 관계, 시스템의 동작 방식, 성능, 확장성 및 유지보수 가능성과 같은 다양한 측면을 다룹니다. 아키텍처는 소프트웨어 시스템의 기반을 제공하며 전체 개발 프로세스를 안내하고 조직의 비즈니스 요구 사항을 충족시키기 위한 청사진 역할을 합니다.</p>
<blockquote>
<p> 아키텍처에 관한 중요한 개념과 원칙은 다음과 같습니다</p>
</blockquote>
<p><strong>1. 모듈화:</strong> 시스템을 작은 모듈 또는 컴포넌트로 나누어야 합니다. 각 모듈은 특정 기능 또는 역할을 담당하며 독립적으로 테스트, 개발, 유지보수할 수 있어야 합니다.</p>
<blockquote>
</blockquote>
<p><strong>2. 관심사 분리:</strong> 시스템의 다른 부분들 간의 의존성을 최소화하고 각 부분이 자체적으로 특정 관심사에 집중하도록 설계해야 합니다. 예를 들어, 데이터 액세스와 사용자 인터페이스 로직을 분리하거나, 비즈니스 로직과 프레젠테이션 로직을 분리할 수 있습니다.</p>
<blockquote>
<p><strong>3. 단일 책임 원칙 (Single Responsibility Principle):</strong> 모듈이나 클래스는 단 하나의 책임을 가져야 합니다. 이것은 코드의 읽기 쉽고 이해하기 쉬운 구조를 유지하고 변경 사항에 대한 영향을 최소화하는 데 도움이 됩니다.</p>
<p><strong>4. 계층화:</strong> 소프트웨어 시스템을 여러 개의 레이어 또는 계층으로 나누어 구성합니다. 일반적으로는 데이터 계층, 비즈니스 로직 계층 및 프레젠테이션 계층으로 나누어 구성합니다.</p>
<p><strong>5. 확장성:</strong> 아키텍처는 시스템이 더 많은 요구 사항을 수용하고 더 큰 규모로 확장할 수 있는 방식으로 설계되어야 합니다. 이는 시스템의 성능을 향상시키고 사용자 수나 데이터 양이 증가할 때 대처하기 쉽도록 하는 중요한 고려 사항입니다.</p>
<p><strong>6. 보안:</strong> 아키텍처는 시스템의 보안을 고려해야 합니다. 데이터의 안전성과 개인 정보 보호를 위한 적절한 보안 메커니즘을 구현해야 합니다.</p>
<p><strong>7. 유지보수 용이성:</strong> 아키텍처는 시스템의 장기적인 유지보수를 고려해야 합니다. 변경이 필요한 경우 최소한의 노력으로 수정하고 확장할 수 있어야 합니다.</p>
</blockquote>
<p>그 다음은 디자인 패턴입니다.
큰틀에서 아키텍쳐 패턴을 정했다면, 개발단계에서 어떻게 실제 코드 구조를 짤지를 정하는 게 디자인 패턴입니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Next.js] StaticImageData]]></title>
            <link>https://velog.io/@ethan_world/%ED%8A%B8%EB%9F%AC%EB%B8%94-%EC%8A%88%ED%8C%85</link>
            <guid>https://velog.io/@ethan_world/%ED%8A%B8%EB%9F%AC%EB%B8%94-%EC%8A%88%ED%8C%85</guid>
            <pubDate>Thu, 13 Apr 2023 15:42:47 GMT</pubDate>
            <description><![CDATA[<p>Next.js 에서 이미지를 불러올 때 next에서 기본으로 제공하는 Image 모듈을 사용한다.</p>
<p>이것을 활용하여 이미지 레이아웃 아톰(아토믹 디자인 시스템)을 만들 때 src의 type 지정을 string 형식으로 했다가 트러블 슈팅이 발생했고, 해결 방법은 아래와 같다.</p>
<p><img src="https://velog.velcdn.com/images/ethan_world/post/18f664d2-41ea-4d4a-8c93-bf6c5fbfe196/image.png" alt=""></p>
<p><code>ImageLayoutProps</code> 인터페이스의 src 값을 <code>StaticImageData</code>로 지정해주면 되는데 이 타입은 Image 모듈을 불러온 &quot;next/Image&quot;에서 임포트 하면된다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[React] 악보 거래 프로젝트 | 악보의 정원]]></title>
            <link>https://velog.io/@ethan_world/React-%EC%95%85%EB%B3%B4-%EA%B1%B0%EB%9E%98-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EC%95%85%EB%B3%B4%EC%9D%98-%EC%A0%95%EC%9B%90-m85oo13b</link>
            <guid>https://velog.io/@ethan_world/React-%EC%95%85%EB%B3%B4-%EA%B1%B0%EB%9E%98-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EC%95%85%EB%B3%B4%EC%9D%98-%EC%A0%95%EC%9B%90-m85oo13b</guid>
            <pubDate>Mon, 20 Mar 2023 07:53:33 GMT</pubDate>
            <description><![CDATA[<p><a href="http://gardenmusic.s3-website.ap-northeast-2.amazonaws.com/">악보의 정원 바로가기</a></p>
<hr>
<h3 id="📝-게시글-crud">📝 게시글 CRUD</h3>
<p>파이어베이스에 익숙하지 않아서 Firestore의 collection과 document 구조를 짤 때 애를 많이 먹었다. 놓친 부분이 꽤나 치명적이라고 생각이 든다. 파이어스토어에서는 collection안에 Document를 만들고 그 안에 또 다른 collection을 만들어서 연관관계를 구축할 수 있다는 걸 놓쳤고, 우리의 파이어스토어는 user, music, instrument로 이루어진 3개의 메인 collection을 사용했다.</p>
<p><img src="https://velog.velcdn.com/images/ethan_world/post/e0c4d829-7ded-442c-b15d-30121ea120f6/image.png" alt=""></p>
<p>이 방법 (3개의 고립된 collection) 을 사용하면, 관련 필드 하나를 수정하기 위해 해당 데이터를 기반으로 다른 collection에서도 수동으로 수정해주어야 하는 문제가 있다. 이 작업은 구현하기 어렵지 않지만, 3개의 collection에 맞춰 3번 수행해야 한다는 점에서 꽤 비효율적이라고 생각된다. 코드를 보자면,</p>
<p><img src="https://velog.velcdn.com/images/ethan_world/post/85518304-f028-46e0-834e-f1234546107a/image.png" alt=""></p>
<p>유저가 작성한 게시글을 삭제한다면, 해당 악보에 있는 isDeleted 값을 true로 수정해야한다.</p>
<p>연관 관계로 구조를 짜는 법을 알았더라면, 한 번의 데이터 대조로 내부 user, music, inst collection에 접근하여 수정사항을 반영할 수 있지 않았을까? 라는 아쉬움이 남는다.</p>
<p>또 다른 에러사항은 데이터가 서로 값이 맞지않아서 버그가 발생할까 마음 졸이며 api 호출 개발을 했다는 것이다. 데이터 리셋이야 크게 어렵지 않고, 다시 채워넣으면 되는 일이지만 삭제될 우려를 하며 개발하는 것과 언제든 다시 데이터 싱크를 맞춰서 개발하는 것의 차이는 다르니깐...</p>
<p>위의 코드는 Batch 기능을 사용하여 기존의 데이터를 업데이트 했다면 아래의 코드는 firestore 내장 메서드인 updateDoc() 을 사용하여 진행했다.</p>
<p><img src="https://velog.velcdn.com/images/ethan_world/post/f250f7bd-51c2-41e1-b31d-9e2aac445c2a/image.png" alt=""></p>
<p>데이터 대조를 위해서 3번의 getDoc 함수를 사용하고 그 중 하나는 아예 상위 Collection에서 모든 document 스냅샷을 불러온다. 내가 만든 무식한 api 호출이지만 개발 당시에는 저렇게 성공하고 나서 안도의 한숨을 쉬었다... 어쨌든 처음으로 백엔드 없이 CRUD 했잖아!! 라며..</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[React] 악보 거래 프로젝트 | 악보의 정원]]></title>
            <link>https://velog.io/@ethan_world/React-%EC%95%85%EB%B3%B4-%EA%B1%B0%EB%9E%98-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EC%95%85%EB%B3%B4%EC%9D%98-%EC%A0%95%EC%9B%90</link>
            <guid>https://velog.io/@ethan_world/React-%EC%95%85%EB%B3%B4-%EA%B1%B0%EB%9E%98-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EC%95%85%EB%B3%B4%EC%9D%98-%EC%A0%95%EC%9B%90</guid>
            <pubDate>Mon, 13 Mar 2023 06:34:51 GMT</pubDate>
            <description><![CDATA[<p><a href="http://gardenmusic.s3-website.ap-northeast-2.amazonaws.com/">악보의 정원 바로가기</a></p>
<hr>
<h2 id="🎼-악보의-정원">🎼 악보의 정원</h2>
<p>처음 사이드 프로젝트를 진행해보고 나서 복잡한 폴더 구조와 컴포넌트의 재사용성을 고려하지 못해서 아쉬웠다. 구조 단계에서 이를 공감하고 해결하기 위한 센빠이님들의 노력을 찾아보니, <code>아토믹 디자인 패턴 (Atomic Design Pattern)</code>이라는 구조 방식이 있었다.</p>
<h3 id="🎨-아토믹-디자인-패턴">🎨 아토믹 디자인 패턴</h3>
<p>아토믹 디자인 패턴은 디자인 시스템 구축방법중 하나이다.
컴포넌트를 <code>가장 작은 구성 요소</code>로 쪼개고, 그런 요소들을 조합하여 하나의 페이지를 만드는 방식으로 디자인 시스템을 구성한다.</p>
<p>아토믹 디자인 패턴에는 5가지의 계층이 존재한다.</p>
<ol>
<li>Atoms : 가장 작은 단위로, 버튼, 입력 필드, 레이블 등과 같은 개별적인 요소들을 의미한다.</li>
<li>Molecules : 두 개 이상의 원자가 결합하여 만들어지는 구성 요소들입니다. 예를 들어, 검색 필드와 검색 버튼이 결합하여 만들어지는 검색 폼이 분자입니다.</li>
<li>Organisms : 분자들이 결합하여 만들어지는 구성 요소들입니다. 예를 들어, 헤더, 푸터, 메뉴 등과 같은 요소들이 유기체입니다.</li>
<li>Templates : 유기체들을 조합하여 만들어지는 레이아웃 템플릿을 의미합니다.</li>
<li>Pages : 실제로 사용자가 접하는 웹 페이지를 의미합니다. 페이지는 템플릿을 기반으로 구성되며, 유기체와 분자, 원자 등의 구성 요소들을 포함합니다.
<img src="https://velog.velcdn.com/images/ethan_world/post/309173c3-c4f4-4a64-a1c2-0d5ec863f206/image.png" alt=""></li>
</ol>
<blockquote>
<p>3명의 프론트엔드 개발자로 구성된 악보의 정원 프로젝트에서는 Templates 계층을 사용하지 않고 4가지로만 개발했다. Templates에서 데이터 fetching 만을 다루는 게 그닥 효율적으로 느껴지지 않았기 때문인데, 뒤돌아 생각해보면 스토리북에서 받아내는 API 호출 관련 에러들을 Templates단에서 정리해줄 수 있었을 거 같다.</p>
</blockquote>
<h3 id="🛠-기술-스택">🛠 기술 스택</h3>
<p>언어 : Typescript
프레임워크 : React.js
상태관리 : Redux Toolkit
디자인 : Scss
컴포넌트 테스트 : Storybook
데이터베이스 : Firebase
배포 : S3</p>
<h3 id="🤖-프로토타입-feat-피그마">🤖 프로토타입 feat. 피그마</h3>
<p><img src="https://velog.velcdn.com/images/ethan_world/post/782b9ace-4c75-4893-97c7-7157f43cd957/image.png" alt=""></p>
<p>먼저 PC버전의 page view를 작업하고 반응형을 고려하여 그 옆에 Mobile 버전으로도 만들어 줬다. 그리고 시작된 극한의 컴포넌트 쪼개기가 시작 됐다.
<img src="https://velog.velcdn.com/images/ethan_world/post/778a799b-130c-4840-9dfb-1f859a977a9a/image.jpeg" alt=""></p>
<p>온갖 형태의 버튼들과 인풋, 이미지 레이아웃으로 먼저 atoms를 만들었고, 유저에게 보여지는 텍스트들도 역시 atoms로 분류해놨다.</p>
<p>해당 atoms로 molucules를 제작했다. 여기서부터 팀원들이 이렇게 하는게 맞는 건가 긴가민가 했고 사용하는 atoms와 molecules의 재사용성을 고려하며 현자타임을 맞이했던 거 같다. 결과적으로 디자인 시스템이 어찌 됐든 재사용성을 고민하고 작업을 하는 건 어느 작업에서건 효율을 높이는 멋진 고민이라고 이때 생각이 들었다.</p>
<h3 id="🌲-컴포넌트-구조">🌲 컴포넌트 구조</h3>
<p><img src="https://velog.velcdn.com/images/ethan_world/post/cd8588e7-e215-49c8-b359-0f8f2cf0d3e1/image.png" alt=""></p>
<p>이전 프로젝트에서 아쉽게 느껴졌던 폴더 구조 (<del>components 폴더 안에 이것저것 넣어버리기..</del>) 에서 위 폴더 구조를 보니 참으로 선녀같다. </p>
<p>해당 폴더를 열어보면
<img src="https://velog.velcdn.com/images/ethan_world/post/9f24b592-e9e3-4d02-accc-302bff303937/image.png" alt=""></p>
<p>이렇게 css 모듈 파일, storybook export 파일, 기능 코드 파일 이렇게 3가지로 분류를 했다. 해당 폴더구조를 공부하고 도입한 팀원에게 무한한 박수를 👏</p>
<blockquote>
<p>아쉬웠던 점</p>
</blockquote>
<ul>
<li>Firebase 호출하는 로직파일이 Firebase.tsx 파일 하나에 모두 들어가있다. 기능에 따라 폴더를 세분화하는 작업이 필요한 걸 알고 있었기에 utils 폴더에 api collection 폴더를 만들었고, user의 authentication을 처리하는 파일을 만들었지만, 어찌 어찌 작업을 하다 보니깐 firebase.tsx의 코드 길이만 800줄이 됐다... </li>
</ul>
<h3 id="🔥-파이어베이스">🔥 파이어베이스</h3>
<p>처음엔 NestJS를 사용하여 백엔드 서버를 구축하려 했지만, 너무 프로젝트가 도전적이고 부담스러워 질 거 같아서 파이어베이스를 사용했다.</p>
<h4 id="👨💻-유저">👨‍💻 유저</h4>
<p>가장 먼저 유저의 authentication 처리를 진행했다.
<img src="https://velog.velcdn.com/images/ethan_world/post/5091b15e-76bb-4ed7-95a4-6e930d51a8b1/image.png" alt=""></p>
<p>firebase/auth 에서 <code>createUserWithEmailAndPassword()</code> 메서드를 사용했다. 유저가 작성한 이메일과 비밀번호의 유효성 검사는 프론트에서 한 번 regTest를 하여 걸러줬다. 해당 메서드는 user 정보를 리턴하는데 그 정보중 <strong>uid</strong>를 파이어베이스 user collection에 document 키 값으로 사용하여 유저 DB를 만들었다. 초기 필드로 <code>isActive : true</code>  <code>cash : 1,000,000</code> <code>cartItems=[]</code> 를 만들어줬다.
<img src="https://velog.velcdn.com/images/ethan_world/post/0b77349b-b980-42b3-a24a-55ae366e4bd8/image.png" alt=""></p>
<p>감사하게도 파이어베이스 메서드 <code>updateProfile()</code>를 사용하여 유저 본인의 정보에 접근이 가능했다. 랜덤으로 5개의 아바타중 하나를 추출하는 utils 함수를 만들어서 유저 프로필 사진으로 지정되게 만들어줬다.</p>
<p>마지막으로 반환된 유저정보에서 token을 뽑아내서 로컬스토리지에 저장해주고 로그인 시켜주는 걸로 마무리!</p>
<p><img src="https://velog.velcdn.com/images/ethan_world/post/233c7069-330e-4cec-9151-dfda7bf3d6c1/image.png" alt=""></p>
<p>로그인 역시 firebase/auth 를 사용하여 간단하게 처리할 수 있었다.</p>
<blockquote>
<p>핵심 기능인 게시글 CRUD는 너무 길어서 나중에 따로 블로깅 해야겠다.</p>
</blockquote>
<h3 id="🎵-스포티파이-api">🎵 스포티파이 API</h3>
<p>본인피셜 프로젝트에서 내가 맡은 기능 중에 가장 어려웠던 부분이다.</p>
<p>유저가 악보를 판매하기 위해 게시글을 작성할 때 해당 곡이 진짜 세상에 존재하는 곡인지 유효성 검사를 확인할 필요가 있다고 생각했다. (<del>샷건의 집현전</del> 방지). 또한 유저가 업로드 하려는 게시글의 곡이 이미 firebase document로 존재한다면, 해당 문서의 필드인 scores 배열에 추가가 되었으면 했다. 따라서 같은 음원이 <code>중복된 document key</code>로 들어갈 필요가 있었다. 우리는 <code>곡 이름 - 가수 이름</code> 이렇게 key 값을 처리해줬다.</p>
<p>위 유효성 검사를 진행하기 위해서는 많은 음원 정보를 가진 오픈 API를 찾아야 했는데 가장 처음으로 찾아본 게 <code>ManiaDB</code> 였다. 최신곡의 정보들이 올라가고 한국어를 지원하는 api여서 매력적이었지만, 마지막으로 api가 업데이트 된 시점이 2013년이고 도저히 api키 발급을 받기가 불가능에 가까웠다. 결국 음원시장의 대장인 <code>spotify</code>의 오픈 api를 사용하기로 했다.</p>
<p>계정 만들기 이런 자잘한 내용은 스킵하고, Dashboard에서 App을 만들면 Client ID, Client Secret이 발급된다. 음원 정보를 조회하기 위해서는 access token으로 api 요청을 보내야한다. 하지만 access token의 유통기한이 1시간이라 만료될 때 마다 refresh token을 사용하여 새로운 access token을 발급받아야한다. 여기까지 생각이 미치기까지 오래 걸리지 않았다. 하지만 여기서 가장 큰 문제는 유저가 token이 만료가 될 때마다 spotify의 팝업이 나오고 내 spotify 계정이 노출되며 access 버튼을 눌러야 한다는 것이였다! 이것을 해결하는 게 꽤 도전적이었다.</p>
<p>먼저 refresh의 유통기한이 엄청 길다는 걸 확인했다. 개발단계에서 refresh를 미리 받아놓고 환경변수로 만들어주고, 기존 Token이 만료될 때 꺼내서 갱신하도록 코딩했다. 반쪽짜리 답이긴하다. refresh마저 만료가 될 경우 개발자가 직접 refresh 토큰을 받아내서 새로 환경변수로 설정하고 deploy 브랜치에 머지를 해야 하는 번거로움이 있다. 그래도 답을 찾은 게 어디야 하하...
<img src="https://velog.velcdn.com/images/ethan_world/post/01e1eb8e-9d2b-43e0-82ce-021aa0ffe5d5/image.png" alt="">
<img src="https://velog.velcdn.com/images/ethan_world/post/4a74ec2f-13ca-42bc-9cc0-0e3e7aa19ef1/image.gif" alt=""></p>
<p><strong><em>2편에서 계속..</em></strong></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[스토리북] setIsFocused is not a function]]></title>
            <link>https://velog.io/@ethan_world/%EC%8A%A4%ED%86%A0%EB%A6%AC%EB%B6%81-setIsFocused-is-not-a-function</link>
            <guid>https://velog.io/@ethan_world/%EC%8A%A4%ED%86%A0%EB%A6%AC%EB%B6%81-setIsFocused-is-not-a-function</guid>
            <pubDate>Wed, 08 Mar 2023 05:48:18 GMT</pubDate>
            <description><![CDATA[<p>atom 요소인 Input 의 포커스 여부와 유저 인풋을 받기위한 setState 함수를 molecule단에서 만들어서 props로 내려줬다.</p>
<p>스토리북에서 해당 molecule은 정상작동 하지만, atom의 포커스를 넣으면 setIsFocused is not a function 라는 타입에러를 발생한다. 추측컨데 atom인 Input 에는 해당 setState 함수를 모르고 있는 거 같다. 해결 방법이 있을까?</p>
<ol>
<li>Input atom 안에서 setState 함수를 만들어준다?<ul>
<li>그럴 수 없다. placeholder 에 animation을 넣기위해 placeholder 속성이 아닌 label atom을 만들어 붙혔기 때문에 label atom도 focus 유무와 그 안에 유저인풋의 존재 여부를 알아야 하기 때문이다.
<img src="https://velog.velcdn.com/images/ethan_world/post/82db49de-a784-48c9-b1df-59fc1e8eae84/image.png" alt="">
해결 : molecule에서 props로 isFocused 등 state를 같이 내려준다.</li>
</ul>
</li>
</ol>
<ul>
<li>단점 : scss 에서 className + :focus 로 줬던 속성을 제거하고 focus일 때의 붙혀줄 모듈을 새로 만들어야 함<ul>
<li>해결 ⇒ css module을 이용해서 focus를 줌</li>
</ul>
</li>
</ul>
<hr>
<p>문제 : label atom 에서 isFocused 여부를 알아야 함. Input에서 onFocus 속성에 setState 함수를 넣어서 molecule의 state를 바꿔주고 해당 state 를 label 의 props로 넘겨줘서 진행헀음. 하지만 setState함수가 Input atom 에 없어서 위와 같은 애러가 발생하는 중. 
<img src="https://velog.velcdn.com/images/ethan_world/post/dad0938e-479f-4374-b89e-a82810fc86c2/image.png" alt=""></p>
<p>args에 setState 함수 부분을 () =&gt; undefined로 넣어줘서 문제 해결!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[메인프로젝트] CodeTech 개발 회고]]></title>
            <link>https://velog.io/@ethan_world/%EB%A9%94%EC%9D%B8%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-CodeTech-%EA%B0%9C%EB%B0%9C-%ED%9A%8C%EA%B3%A0</link>
            <guid>https://velog.io/@ethan_world/%EB%A9%94%EC%9D%B8%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-CodeTech-%EA%B0%9C%EB%B0%9C-%ED%9A%8C%EA%B3%A0</guid>
            <pubDate>Mon, 19 Dec 2022 08:26:47 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/ethan_world/post/03646744-5eb1-46a1-851b-13ad2dac19c7/image.gif" alt="">
📎 <a href="https://codetech.nworld.dev/">https://codetech.nworld.dev/</a>
🌿 <a href="https://github.com/codestates-seb/seb40_main_011">https://github.com/codestates-seb/seb40_main_011</a></p>
<hr>
<h2 id="메인페이지">메인페이지</h2>
<p><img src="https://velog.velcdn.com/images/ethan_world/post/81eaf75a-6684-4554-93e9-308fdfbc6f8f/image.png" alt="피그마 프로토타입"></p>
<p>위의 프로토타입을 바탕으로 필요 컴포넌트를 나눴다. 작업한 순서로 정리해볼까 한다.</p>
<h3 id="🖥-productlisttsx">🖥 ProductList.tsx</h3>
<p>메인페이지의 메인 view를 담당하는 주요 컴포넌트이다. 맨 처음 작업을 시작할 때 <code>json-server</code> 를 사용하여 더미데이터를 만들었고, 혹시 모를 상황에 (급작스러운 API문서 수정) 대비하기위해 백엔드 개발자분들과 상의하여 받을 응답객체를 정해놓고 작업했다.</p>
<blockquote>
<p><strong>아쉬운 점</strong></p>
</blockquote>
<ol>
<li>제품에 대한 데이터를 한 번에 다 받았다. API호출을 쿼리로 주고 받으면 데이터 세이빙과, 로딩시간을 개선할 수 있을 거 같다. 지금 시점에서는 제품 데이터가 많지 않아서 괜찮다.</li>
<li>제품을 더 불러오는 기능으로 <code>더 보기</code> 버튼을 만들었다. 처음엔 페이지네이션으로 프론트에서 offset등을 계산하여 좌우로 이동하게끔 구현했지만, 전직 디자이너셨던 팀원분께 의견을 여쭤보았는데 모바일에서의 view를 염두하고 계셔서 <code>더 보기</code> 버튼으로 구현을 헀다.</li>
</ol>
<blockquote>
<p><strong>개선한 점</strong></p>
</blockquote>
<ol>
<li>프로젝트 발표가 끝나고, 제일 먼저 수정을 했던 건 <code>useMemo, useCallback</code> 을 활용한 성능 최적화였다. 
<img src="https://velog.velcdn.com/images/ethan_world/post/cdc0a473-6abc-4f93-8942-09beb4c487a0/image.png" alt="">
처음 써보는 리엑트 훅이라 공부먼저 진행했고 <code>단테</code>님의 블로그가 도움이 많이 됐다. 값이나 함수가 변하지 않는다면, 그것들의 불필요한 렌더링을 막기 위한 메모이제이션 기법! </li>
</ol>
<h3 id="👍-bestreviewlisttsx">👍 BestReviewList.tsx</h3>
<ul>
<li><p>최상단에 위치하여 리뷰마다 가지고있는 Like의 오름차순으로 7개를 불러오는 컴포넌트이다. 이 컴포넌트를 작업할 때 재밌었던 건 백엔드분들이 리뷰가 캐러셀처럼 자동으로 옆으로 넘어가면 좋겠다고 하셔서 <code>setTimeout</code>을 사용하여 5초마다 옆으로 넘어가게 만들었다. 문제는 컴포넌트에 <code>setTimeout</code>을 <code>useEffect</code>나 다른 로직에 감싸서 넣은 게 아닌 plain하게 넣어버려서 다음 버튼을 누르면 고장(?)이 나버리는 것이였다. 기존에 사용하던 <code>setTimeout</code>이 아닌 <code>setInterval</code> 을 사용하여 이를 해결했다.
<img src="https://velog.velcdn.com/images/ethan_world/post/04258d0c-36ae-4a2f-a49d-f7f1ad00eb1b/image.png" alt=""></p>
</li>
<li><p>리뷰 컨텐츠가 마크다운 언어이다보니, 그대로 노출시킬 수 없었다. 변환은 아니고, 단순히 마크다운 문법을 제거하고 텍스트만 뽑아내는 작업을 하는 게 도전적이였고, 시간도 꽤 잡아먹었다. 정규표현식을 구글링하여 날먹(?)을 하고 싶었지만, 내 상황에 맞는 표현식이 없었기에<em><del>(찾지 못해서)</del></em> 새로 만들었다.
<img src="https://velog.velcdn.com/images/ethan_world/post/7b16b6d3-cb76-4e8a-9600-df2ca8f910ab/image.png" alt=""></p>
</li>
</ul>
<blockquote>
<p><strong>아쉬운 점</strong></p>
</blockquote>
<ul>
<li>해당 컴포넌트에 onHover시 리뷰가 넘어가는 걸 막는 함수를 아직 만들어주지 못했다. 프로젝트 기간에 미처 생각도 하지 못했던게 뼈아프다.</li>
</ul>
<blockquote>
<p><strong>개선한 점</strong></p>
</blockquote>
<ul>
<li>제품 리스트 컴포넌트와 마찬가지로 <code>useMemo</code>와 <code>react.memo</code>를 사용하여 성능 최적화를 진행했다. </li>
</ul>
<h3 id="❓-questionlisttsx">❓ QuestionList.tsx</h3>
<p>메인페이지 하단에 위치한 질문 리스트 컴포넌트는 유저들이 작성한 답변이 필요한 질문과, 답변이 작성된 질문 두 개를 묶어서 만들었다. 같은 주소로 속성만 다르게하여 API 호출을 두 번 하는 비효율적인 데이터 fetching을 개선했다.
<img src="https://velog.velcdn.com/images/ethan_world/post/c13bd703-1632-4860-923a-798b61a4e2bc/image.png" width="500" height="300">
<img src="https://velog.velcdn.com/images/ethan_world/post/93f16f81-311c-4e4b-a9a9-0ae55e9494f9/image.png" width="500" height="300"></p>
<p>Promise.all 을 부트캠프 진행하면서 딱 한 번 처음 배울 때 사용하고는 까맣게 잊고 지내다가 저 코드를 보고 한 번 대입해볼 기회라고 생각하여 작성해봤다. 이런 상황이 또 나온다면, 가독성을 위해 이전 코드로 작성해야 할까 아니면 최적화를 위해서 아래처럼 작성해야 할까?</p>
<hr>
<h2 id="상세-리뷰-페이지">상세 리뷰 페이지</h2>
<p>📎 <a href="https://codetech.nworld.dev/review/4">https://codetech.nworld.dev/review/4</a></p>
<blockquote>
<p><strong>어려웠던 점</strong></p>
</blockquote>
<center>
<img src="https://velog.velcdn.com/images/ethan_world/post/56728b91-08fc-4812-b83d-f3261f79ca86/image.png" width="600" height="300">
(좌에서 우로 수정하는 것 보다 그냥 우로 만드는게 더 쉽다...)
</center>


<p>기획단계에서 컴포넌트 계층을 고려하지 않고 프로토타입에 보이는 대로 만들다가 참사가 난 페이지였다.
view는 다르지만 동일한 기능 (댓글 대댓글 CRUD)을 구현할 때 뼈저리게 느꼈다. 공통 컴포넌트로 코멘트 기능 재사용을 염두해두고 만들었다면 내가 겪은 <code>props drilling</code> 들을 완화할 수 있지 않았을까?</p>
<p>한 컴포넌트에서 모든 API 데이터를 불러와 props로 넘겨주기 보단, 응답객체를 나눠서 받았다면 (review 전문 따로, 댓글 arr 따로) 작업에 더 수월했을 거 같다.
<img src="https://velog.velcdn.com/images/ethan_world/post/c586e49a-1806-420e-a364-4c756f53f6f0/image.png" width="300" height="300">
<img src="https://velog.velcdn.com/images/ethan_world/post/f4ae1a15-7535-47f5-baaa-a1a670846720/image.png" width="300" height="300">
저렇게 컴포넌트간 주고받는 props가 많다면, 다른 팀원이 내 작업을 도울 때 많이 힘들다. 나도 다른 팀원의 작업을 도울 때 그랬다.</p>
<blockquote>
<p><strong>재밌었던 점</strong></p>
</blockquote>
<p><code>Zustand</code>를 사용하여 리뷰 전문을 수정하는 기능 구현이 가장 재밌었다.
<img src="https://velog.velcdn.com/images/ethan_world/post/bdc66276-0f08-40f4-84ad-9620da032a48/image.gif" width="600" height="600"></p>
<p>이미 만들어진 <code>WriteReview</code> 컴포넌트에 간단한 props 하나를 넘겨 상태관리 툴을 조작하여 해당 데이터를 저 컴포넌트에서 불러오는 기능이 간단하지 않아보였지만, 막상 구현하고나니 이번 프로젝트에서 가장 간단한(?) 작업이지 않았을까 회고한다.</p>
<hr>
<h2 id="검색-결과-페이지">검색 결과 페이지</h2>
<p>📎 <a href="https://codetech.nworld.dev/search?search=%EB%A7%A5">https://codetech.nworld.dev/search?search=%EB%A7%A5</a></p>
<h3 id="🎨-searchresulttsx">🎨 SearchResult.tsx</h3>
<blockquote>
<p><strong>어려웠던 점</strong></p>
</blockquote>
<p>헤더에 있는 Search 인풋을 통해서 라우팅되는 페이지를 만들어야 했다. 라우팅이되는 키워드를 가지고 오기 위해서 <code>useLocation</code> 을 사용하여 URL에 접근했는데, 키워드가 한글일 경우 파싱이 필요한 걸 알았다.
따라서 <code>search=</code> 까지 짤라주고 <code>decodeURI</code> 메서드를 사용해서 해당 키워드를 성공적으로 뽑아왔다. 그렇게 받은 키워드는 아래의 두 컴포넌트의 props로 내려줬다.</p>
<h3 id="📝-searchreviewtsx">📝 SearchReview.tsx</h3>
<h3 id="💻-searchproducttsx">💻 SearchProduct.tsx</h3>
<p>전체적인 구조가 메인페이지의 제품리스트와 동일했기에 개발중에 크게 어려웠던 점은 없었다. 이 컴포넌트 안에 작은 컴포넌트들을 세분화하여 마지막 리턴문의 길이를 줄이는 것에 포커싱 해봤다. 
<img src="https://velog.velcdn.com/images/ethan_world/post/91e82c33-c713-4d47-89ee-c8d302b9fe16/image.png" width="600" height="600"></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[메인프로젝트] CodeTech 기획 회고]]></title>
            <link>https://velog.io/@ethan_world/%EB%A9%94%EC%9D%B8%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-CodeTech-%EA%B8%B0%ED%9A%8D-%ED%9A%8C%EA%B3%A0</link>
            <guid>https://velog.io/@ethan_world/%EB%A9%94%EC%9D%B8%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-CodeTech-%EA%B8%B0%ED%9A%8D-%ED%9A%8C%EA%B3%A0</guid>
            <pubDate>Fri, 09 Dec 2022 05:42:03 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/ethan_world/post/0db398a4-1deb-4d94-bec1-e08a616b45f3/image.gif" alt="">
<a href="https://codetech.nworld.dev/">https://codetech.nworld.dev/</a></p>
<hr>
<h2 id="기획">기획</h2>
<h3 id="👨💻-rnr">👨‍💻 RnR</h3>
<p>팀장직을 원하는 인원이 없어 룰렛을 돌렸고 <strong>내가 이 팀의 팀장이 됐다.</strong> 사실 팀원분들에게 말씀은 못 했지만, 설레고 즐거웠다! 팀장 역할이 부담스럽고 큰 책임감이 필요하지만, 팀 플랜을 공유할 때 팀원들이 그 계획에 살을 붙여주는 과정이 참 즐거웠다. 정말 감사하게 모든 팀원분이 맡은 작업에 책임감을 느끼고 열심히 참여해주셔서 뿌듯한 결과물을 만들어냈다. 팀원 개인의 의견과 팀의 진행 방향을 융합하는 대에 최선을 다했다고 생각한다. 
<br>
<br></p>
<h3 id="💡-아이디어-미믹">💡 아이디어 미믹</h3>
<p>팀 RnR 구성이 끝나고 서로 아이디어를 공유하면서 프로젝트 주제를 선정했다. 안건으로 나왔던 모든 아이디어에 PLUS, MINUS 의견으로 따로 종합하여 실현이 어려운 아이디어는 배제해나갔다.
<img src="https://velog.velcdn.com/images/ethan_world/post/f72b28e6-af51-48d5-9c27-758cafc6a2d2/image.png" width="500" height="300"></p>
<center>내가 제시한 아이디어도 예외는 아니였다!</center>
<br>

<p><strong>결과적으로 우리 팀은 테크기기들의 리뷰 서비스를 진행하기로 했다.</strong></p>
<p>기존에 널리 알려진 테크 정보 웹 서비스는 상당히 방대한 양의 컨텐츠와 복잡한 UI로 인해서 사용자의 경험이 부정적이었다는 점을 파고들었다.</p>
<p>컴팩트한 사용 후기를 보여주기 위해 별점을 줄 수 있는 한 줄 리뷰 페이지를 구현하기로 했고, 깔끔한 리뷰를 작성하고 싶어 하는 유저를 위해 마크다운 에디터 라이브러리를 사용하기로 했다.
<br>
<br></p>
<h3 id="⏰-컨벤션">⏰ 컨벤션</h3>
<p>프로젝트 기간 동안 유지관리를 위해서 GitFlow 방식으로 깃 컨벤션을 정했다.</p>
<ol>
<li>어떤 작업을 진행하는 지 Issue 작성</li>
<li>feature 브랜치 생성 후 해당 이슈 이름과 넘버 기재</li>
<li>dev 브랜치 PR시 코드리뷰</li>
<li>commit에 이슈 넘버 기재</li>
</ol>
<p>프로젝트 후반기에 들어서서 다들 빠르게 작업하고 테스트하느라 완벽하게 지켰다고 할 수 없지만, 협업에서 이러한 컨벤션이 왜 중요하고, 귀찮지만 지켜나가는 게 프로젝트 유지관리에 어떤 도움이 되는지 느낄 수 있었다. 아직 프로젝트 repo에는 30개가 넘는 이슈들이 쌓여있다..
<br>
<br></p>
<h3 id="🖼-와이어-프레임--프로토-타입">🖼 와이어 프레임 &amp; 프로토 타입</h3>
<p>화면 정의서를 만들기 위해 발사믹 (Balsamiq) 이라는 툴을 사용했고, 
프로토 타입은 피그마를 사용하여 만들었다. 
팀원중 피그마를 굉장히 잘 쓰시는 분이 있어서 제작 과정에서 큰 시간을 아낄 수 있었다.</p>
<p>나중에 디자인 작업을 진행할 때 디자인 시스템과 컬러 팔레트가 없어서 아쉬웠다고 생각한다. </p>
<p><img src="https://velog.velcdn.com/images/ethan_world/post/a70798c9-e9ac-4b46-8816-988c73195fa0/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/ethan_world/post/16b15cec-9341-424f-8e67-999f246aa072/image.png" alt=""></p>
<br>
<br>

<h3 id="🍕-분업">🍕 분업</h3>
<p>팀장 겸 프론트엔드 팀장을 맡았기에 일정관리를 위해서 팀원들에게 작업을 분배할 필요가 있었다. 화면정의서 상 코드테크 프로젝트는 총 9개의 페이지가 있었고 일부 페이지는 외부 라이브러리(Toast-UI) 의존성이 매우 컸다. 따라서 그 라이브러리 사용에 욕심이 있는 팀원을 먼저 선별하였고, 나머지는 그 페이지의 기능 구현에 뜻이 있는 팀원들을 배정했다. Toast-UI 사용 경험이 있는 팀원과 그렇지 않은 팀원을 페어로 하여 작업을 부탁드렸다.</p>
<blockquote>
<p><strong>아쉬웠던 점</strong> 😢</p>
<p>공통 컴포넌트들을 정하지 않았다는게 뼈아픈 실수였다.
버튼, 모달과 같은 컴포넌트들은 재사용성을 염두하고 다 같이 초반에 작업을 완료했더라면, 각자 맡은 페이지 구현에서도 해당 컴포넌트들을 더하고 뺄 때 큰 부담이 없었을 텐데 그렇지 않아서 특정 props를 내려주거나 하는 상황에서는 그 컴포넌트를 복붙하여 다시 깎아서 만들어 냈다는 게 참 효율적이지 못한 작업을 했다고 생각한다.</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[응애 개발자의 zustand 사용 후기]]></title>
            <link>https://velog.io/@ethan_world/%EC%9D%91%EC%95%A0-%EA%B0%9C%EB%B0%9C%EC%9E%90%EC%9D%98-zustand-%EC%82%AC%EC%9A%A9-%ED%9B%84%EA%B8%B0</link>
            <guid>https://velog.io/@ethan_world/%EC%9D%91%EC%95%A0-%EA%B0%9C%EB%B0%9C%EC%9E%90%EC%9D%98-zustand-%EC%82%AC%EC%9A%A9-%ED%9B%84%EA%B8%B0</guid>
            <pubDate>Sat, 03 Dec 2022 10:15:55 GMT</pubDate>
            <description><![CDATA[<p>CodeTech 서비스 개발을 시작하면서 사용할 상태관리툴을 정할 때 <code>@reduxjs/toolkit</code> 과 <code>zustand</code> 를 두고 팀원들과 고민했었습니다.</p>
<p>먼저 npm trends를 살펴보면
<img src="https://velog.velcdn.com/images/ethan_world/post/bc168f9e-7a59-4a94-b466-6d3427e5037a/image.png" alt=""></p>
<p><code>@reduxjs/toolkit</code>은 압도적으로 상태관리 라이브러리를 이끌고 있습니다. </p>
<p>만약 <code>@reduxjs/toolkit</code>를 쓰지 않는다면 <code>zustand</code> 와 <code>recoil</code> 중에서 정해야했고, Facebook이 서포트하는 <code>recoil</code>은 매력적이였지만 npm trend에서 <code>zustand</code>보다 밀리는 경향이 있었습니다. 이와 같은 이유로 <code>zustand</code>, <code>@reduxjs/toolkit</code> 을 비교하기로 했습니다.</p>
<p><code>@reduxjs/toolkit</code>의 단점이라면 다른 상태관리 툴에 비해서 요구되는 많은 양의 boiler plate가 있습니다. 1분, 1초가 아쉬운 sprint 프로젝트에서 상태 관리를 위해 많은 코드를 적기 쉽지않다고 생각했습니다. <code>@reduxjs/toolkit</code>이 redux보다 사용하기엔 편하지만, 그럼에도 해당 툴을 팀 프로젝트 단위 작업에서 사용해본 사람이 없는 상황이니 개발 과정에서 혼선을 겪으면 많은 시간 소모 우려가 있지 않을까? 라는 의견으로 통일이 됐고. 비교적 배우기 쉽고 코드량이 적은 <code>zustand</code>를 사용해 상태관리를 하기로 했습니다.</p>
<p>그 결정은 옳았습니다.</p>
<p>로그인 로직을 담당한 팀원이 먼저 로그인 상태관리를 위해 로직을 짜고 store 폴더에 모듈로 만드신 걸 저를 포함해서 다른 팀원들은 그 모듈 코드를 보고 <code>zustand</code>는 이렇게 사용하는 구나! 바로 이해할 수 있었습니다. 결과적으로 모두가 전역 상태관리를 어디서든 손쉽게 진행 할 수 있었습니다. 
<img src="https://velog.velcdn.com/images/ethan_world/post/071cc01d-34e4-4787-b986-f8d46b9dd08b/image.png" alt=""></p>
<center> 검색중에 발견한 어떤 블로거의 샷아웃👍  </center>
 <br>

<hr>
<p><code>zustand</code>를 프로젝트에서 개인적으로 사용해본 경험은 유저의 컨텐츠 수정부분을 구현하면서 사용했습니다.</p>
<p>유저가 컨텐츠를 수정할 때 이미 존재한 컨텐츠를 상태를 지정하고 구현되어 있는 editor 페이지에서 수정할 컨텐츠를 불러와 알맞은 위치에 넣어주고 수정이 끝나면 그 상태를 initial state로 만들기까지 정말 간단하게 작업할 수 있었고 <strong>다른 팀원들이 해당 코드를 쉽게 이해했다는 것에서 큰 만족을 느꼈습니다.</strong></p>
<p><img src="https://velog.velcdn.com/images/ethan_world/post/6e5048b9-6121-4080-bca3-e95d844ea3e5/image.png" alt=""></p>
<center>정말 쉽다!</center>
]]></description>
        </item>
        <item>
            <title><![CDATA[[TypeScript] 타입스크립트 노트 02]]></title>
            <link>https://velog.io/@ethan_world/TypeScript-%ED%83%80%EC%9E%85%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EB%85%B8%ED%8A%B8-02</link>
            <guid>https://velog.io/@ethan_world/TypeScript-%ED%83%80%EC%9E%85%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EB%85%B8%ED%8A%B8-02</guid>
            <pubDate>Tue, 15 Nov 2022 06:28:55 GMT</pubDate>
            <description><![CDATA[<h3 id="1-call-signature">1. call signature</h3>
<ul>
<li>이걸 사용하면, 함수에 직접 타입을 표기할 필요가 없다. (가독성)</li>
<li>함수의 타입을 작성하고나서 코드를 구현하게 된다.</li>
</ul>
<pre><code>type Add = (a: number, b:number) =&gt; number;

const add:Add = (a,b) =&gt; a + b // good</code></pre><h3 id="2-overloading">2. overloading</h3>
<ul>
<li>오버로딩형식의 함수를 작성할 일은 많지 않다. 하지만 외부 라이브러리가 많이 사용하여 어떻게 생겼는지 알 필요가있다.</li>
<li>모양이 다르고 여러개의 call signature가 있다면 그게 ovld.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/ethan_world/post/210f7e33-eb0d-4c87-9280-8e0a9a68504d/image.png" alt=""></p>
<ul>
<li>⬆️ parameter들의 타입 중 optional한 parameter는 <code>?</code> 기호를 써준다.</li>
</ul>
<pre><code>type Config = {
    path : string,
    state : object
    }
type Push = {
    (path : string): void
    (config : Config): void
    }

const push:Push = (config) =&gt; {
    if(typeof config === &quot;string&quot;){ // parameter config
    console.log(config)
    } else {
    console.log(config.path) // type Push config
    }
} // good</code></pre><h3 id="3-polymorphism">3. polymorphism</h3>
<h3 id="4-generics">4. generics</h3>
<h3 id="5-리턴-된-구조분해할당-배열에-타입-지정하기">5. 리턴 된 구조분해할당 배열에 타입 지정하기</h3>
<p><img src="https://velog.velcdn.com/images/ethan_world/post/55d2b467-a385-4680-ac7b-0e5b04961995/image.png" alt=""></p>
<ul>
<li><p>call signature로 타입을 만들어주고 해당 타입을 구조분해할당을 리턴하는 함수에 지정해준다. </p>
</li>
<li><p>사진에는 없지만 리턴문은 아래처럼 작성 되어있다.</p>
<pre><code>return [data, isPending, error] </code></pre><p><img src="https://velog.velcdn.com/images/ethan_world/post/543b5473-d15d-409a-b972-cf6f364ec9a8/image.png" alt=""></p>
</li>
<li><p>useFetch 함수를 받아와서 사용할 때 구조 분해 할당에서 에러가 없는 모습. useState 옆에 제네릭 타입 넣는 부분에서 해맸다.</p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[TypeScript] 타입스크립트 노트 01]]></title>
            <link>https://velog.io/@ethan_world/TypeScript-%ED%83%80%EC%9E%85%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EB%85%B8%ED%8A%B8-01</link>
            <guid>https://velog.io/@ethan_world/TypeScript-%ED%83%80%EC%9E%85%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EB%85%B8%ED%8A%B8-01</guid>
            <pubDate>Mon, 14 Nov 2022 13:06:32 GMT</pubDate>
            <description><![CDATA[<h3 id="타입스크립트를-쓰는-이유">타입스크립트를 쓰는 이유</h3>
<ul>
<li>에러의 사전 방지</li>
<li>코드 자동 완성과 가이드</li>
</ul>
<hr>
<h3 id="implicit암시적--explicit명시적">implicit(암시적) &amp; explicit(명시적)</h3>
<ul>
<li>타스는 암시와 명시를 짬뽕한 언어.
일반적인 자바스크립트처럼 변수를 만들고 진행해도 되고, 혹은 해당 변수의 타입을 명시하여 (타스를 쓰는 이유) 내가 지정한 타입에 위배되는 행동을 하면 자바스크립트보다 명료한 에러를 확인할 수 있다
<img src="https://velog.velcdn.com/images/ethan_world/post/bd4c5f05-644c-4665-aef0-8d98218f6084/image.png" alt=""></li>
<li>⬆️ 타입스크립트가 추론한 내가 선언한 변수의 타입</li>
</ul>
<p><img src="https://velog.velcdn.com/images/ethan_world/post/73408bcb-07df-4820-9c38-32760f5c85c1/image.png" alt=""></p>
<ul>
<li>⬆️ 타입스크립트는 변수의 타입을 기억한다. number type을 넣었을 때 반환하는 에러</li>
</ul>
<p><img src="https://velog.velcdn.com/images/ethan_world/post/b819cb0d-c9fd-49ac-aeed-1176ee047628/image.png" alt=""></p>
<ul>
<li>⬆️ 타입스크립트는 변수의 타입을 명시하는 방법. colon을 선언문 이름 옆에 쓰고 원하는 타입 입력</li>
</ul>
<hr>
<h3 id="타입스크립트-활용">타입스크립트 활용</h3>
<h4 id="1-배열을-만들-때-해당-배열의-요소가-어떤-타입인지-같이-명시해야한다">1. 배열을 만들 때 해당 배열의 요소가 어떤 타입인지 같이 명시해야한다.</h4>
<pre><code>let a : string[] = [&quot;hi&quot;]

a.push(123) // error</code></pre><h4 id="2-만약-객체-요소에서-특정-키의-유무가-확실하지-않을-때는-해당-키의-타입-지정-부분에서--사인을-넣어서-타입스크립트에게-그-키는-undefined일-수도-있다고-정보를-줄-수-있다">2. 만약 객체 요소에서 특정 키의 유무가 확실하지 않을 때는, 해당 키의 타입 지정 부분에서 ? 사인을 넣어서 타입스크립트에게 그 키는 &quot;undefined&quot;일 수도 있다고 정보를 줄 수 있다.</h4>
<pre><code>const author : {
    name : string,    
    age?: number // optional parameter 라고 한다.
} = {
    name : &quot;Murakami Haruki&quot;,
}

if(author.age &gt; 50) // error
if(author.age &amp;&amp; author.age &gt; 50) // good</code></pre><h4 id="3-객체의-타입지정이-반복-될-경우-별칭alias타입을-생성하여-반복을-해소한다">3. 객체의 타입지정이 반복 될 경우 별칭(alias)타입을 생성하여 반복을 해소한다.</h4>
<pre><code>type Author = { // 별칭은 대문자로 시작
    name : string,    
    age?: number
}

const haruki : Author = {
    name: &quot;Murakami Haruki&quot;,
    age: 73
}

const coelho : Author = {
    name: &quot;Paulo Coelho&quot;
}</code></pre><h4 id="4-함수의-타입지정">4. 함수의 타입지정</h4>
<pre><code>function authorMaker(name:string) Author { // Author Type 지정
    return {
        name
    }
}

const coelho = authorMaker(&quot;coelho&quot;)

Coelho.age = 75 // good</code></pre><h4 id="5-readonly">5. readonly</h4>
<ul>
<li>React에서 state hook을 사용하면 원본 데이터의 불변성을 유지시켜야 하는데 이때 해당 state앞에 readonly를 넣어 불변성 위배를 방지하여 쓸 수 있겠다.<pre><code>type Author = {
  readonly name : string,    
  age?: number
}
</code></pre></li>
</ul>
<p>const haruki : Author = {
    name: &quot;Murakami Haruki&quot;,
    age: 73
}</p>
<p>haruki.name : &quot;Norwegian Wood&quot; // error</p>
<pre><code></code></pre><p>/* array example */</p>
<p>const authors : readonly string [] = [
    &quot;Haruki&quot;, &quot;Coelho&quot;
]</p>
<p>authors.push(&quot;Hesse&quot;) // error</p>
<pre><code>
#### 6. Tuple
- 인덱스들의 타입이 지정된 배열. 
push 메서드로 지정한 배열의 규칙을 무시하고 요소를 추가할 수 있다는 점을 유의하자.</code></pre><p>const author : [string, number] = [&quot;Haruki&quot;, 73]
author[0] = true // error</p>
<pre><code></code></pre><p>const author : [string, number] = [&quot;Haruki&quot;, 73]
author.push(&quot;hello&quot;) // [&quot;Haruki&quot;, 73, &quot;hello&quot;] </p>
<pre><code>
#### 7. unknown
- API를 호출하거나 내가 실행한 함수의 리턴값의 타입을 알기가 쉽지 않을 때 사용하는 타입</code></pre><p>let a : unknown</p>
<p>let b = a + 1 // error</p>
<p>if(typeof a === &quot;number&quot;){
    let b = a + 1 // good
}</p>
<pre><code></code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[[SEB FE] SECTION 4 회고]]></title>
            <link>https://velog.io/@ethan_world/SEB-FE-SECTION-4-%ED%9A%8C%EA%B3%A0</link>
            <guid>https://velog.io/@ethan_world/SEB-FE-SECTION-4-%ED%9A%8C%EA%B3%A0</guid>
            <pubDate>Wed, 19 Oct 2022 07:02:33 GMT</pubDate>
            <description><![CDATA[<p>!youtube[3bVJFgvUZHg]</p>
<p>이번 섹션을 함께한 노래🎶</p>
<hr>
<h2 id="회고-요약">회고 요약</h2>
<p>시간이 빠르게 지나갔다. 배우는 것도 어렵지만 놓치면 정말 크게 후회할 거 같아서 최선을 다해서 따라가는 중이다. 비유하자만 마라톤에서 페이스 유지를 간신히 하는 느낌에서 이젠 힘겹게 달리며 몰아 붙히고 있다. 무엇보다 이런 첼린징이 즐거워서 좋다. 오프라인 모각코와 담주부터 시작하는 알고리즘 스터디에도 가입했다!</p>
<p><strong>이제 팀 프로젝트 단계이다. 각오 단단히!</strong></p>
<h3 id="1-목표-상기하기">1. 목표 상기하기</h3>
<p>팀 프로젝트 기간 동안 개인적인 노션을 적극적으로 쓰고 싶다. 보다 좀 더 계획적으로 오답들을 처리하고 새로운 내용을 정리하기에 노션이 안성 맞춤인듯 하다. 또 타입스크립트를 공부할 건데 아무래도 사이드 프로젝트를 만들어 보면서 공부해야겠죠? 바쁜 나날이 이어진다 @_@ !  </p>
<h3 id="2-keep-problem-작성하기">2. keep, problem 작성하기</h3>
<ul>
<li>KEEP </li>
</ul>
<ol>
<li>쇠질하는 시간과 함께 운동하는 시간(풋살) 중에서 하나를 포기해야 할 거 같아서 쿨하게 쇠질을 보내줬다. 시간의 품질 향상을 위해서! 잠시만 안녕!</li>
<li>어떻게 하면 좀 더 알찬 하루를 보낼 수 있을까 라는 고민을 달고 산다. 미라클 모닝이라는 책도 사서 해보고 있는데.. 쉽지 않다. 생산적인 고민을 하는 습관을 놓치말자!</li>
<li>저번 섹션에서는 스스로를 몰아 붙이지 못해 놓치는 기회가 많아 아쉬워했다. 이번엔 일을 좀 벌려보았으니 열심히 참여해야겠다.</li>
</ol>
<ul>
<li>PROBLEM</li>
</ul>
<ol>
<li>좀 사소하지만,,,, 날이 춥다. 저번에 온수매트와 한 몸이 되어 늦잠을 자 결국 지각을 했는데... 포근한 아침에 눈을 뜨기가 어렵더라.</li>
<li>효율적인 복습을 하지 못해서 아쉽다. 블로그에 배운 내용을 정리하여 올릴 때 점점 임시저장 혹은 비공개로 올리고 &quot;아 나중에 다시 정리해서 올려야지~&quot; 하며 마무리한다. 그렇게 지금 쌓여 있는 글들이 너무 많다. 어쩌지..?</li>
</ol>
<h3 id="3-try-작성하기">3. try 작성하기</h3>
<ol>
<li>노션을 사용해서 깔끔하고 시각적으로 보기 편한 일지를 작성하기</li>
<li>깃과 더 친해지기.</li>
<li>타입스크립트 개인 공부하기.</li>
</ol>
<h3 id="4-우선순위-정하기">4. 우선순위 정하기</h3>
<ol>
<li>팀 프로젝트 &amp; 커뮤니케이션 (soft skill &amp; git)</li>
<li>&#39;프로그래머의 뇌&#39; 라는 책을 읽고 싶다.</li>
<li>미라클 모닝을 위한 컨디션 조절</li>
<li>개인 공부 (타입스크립트, next.js,)</li>
</ol>
<p><img src="https://velog.velcdn.com/images/ethan_world/post/806fc4aa-01fb-4ec9-89c9-52f3bf207a9c/image.png" alt=""></p>
<center>다들 프로젝트도 화이팅이에요!</center>
]]></description>
        </item>
        <item>
            <title><![CDATA[[최적화] lighthouse]]></title>
            <link>https://velog.io/@ethan_world/%EC%B5%9C%EC%A0%81%ED%99%94-lighthouse</link>
            <guid>https://velog.io/@ethan_world/%EC%B5%9C%EC%A0%81%ED%99%94-lighthouse</guid>
            <pubDate>Fri, 07 Oct 2022 07:50:27 GMT</pubDate>
            <description><![CDATA[<h2 id="lighthouse의-opportunity">Lighthouse의 opportunity</h2>
<ul>
<li>lighthouse가 말하는 <code>Opportunities</code>는 <strong>오답노트</strong>이며, 해당 문제들을 해결했을 때 개선되는 시간 수치를 보여주는 기능이다. 
<img src="https://velog.velcdn.com/images/ethan_world/post/6cd39612-796e-47c5-a4ae-18a988eeca1f/image.png" alt=""></li>
</ul>
<center>위의 사진은 벨로그의 메인페이지를 돌려봤을 때 보여지는 `Opportunities`이다.</center>


<ol>
<li>properly size images : 페이지의 각 이미지에 대해 Lighthouse는 렌더링된 이미지의 크기를 실제 이미지의 크기와 비교합니다. 해결 방법으로는 해당 이미지를 반응형으로 만들어 낭비되는 공간 없이 사용이 가능하다.
<img src="https://velog.velcdn.com/images/ethan_world/post/baf8962a-13b5-4ced-a7a8-67aac8aa4e2d/image.png" alt=""></li>
</ol>
<ol start="2">
<li><p>Serve images in next-gen formats : PNG와 JPEG 형식에 비해 WebP 와 AVIF 형식을 사용하면 좀 더 나은 압축률을 보여준다.</p>
</li>
<li><p>Use video formats for animated content : 큰 GIF 파일들은 에니메이션 콘텐츠를 전달할 때 비효율적이다. MPEG4/WebM 형식의 비디오를 사용하여 최적화 할 수 있다.</p>
</li>
<li><p>Reduce unused JavaScript : 사용하지 않은 자바스크립트 코드를 제거하여 네트워크 활동 속도를 증가 시킬 수 있다.
<img src="https://velog.velcdn.com/images/ethan_world/post/ccf378d7-4e69-4ce3-a551-da4526616073/image.png" alt=""></p>
<center>친절한 등대는 필요없는 코드들의 위치를 알려준다.</center>


</li>
</ol>
<hr>
<h3 id="개인적인-생각">개인적인 생각</h3>
<p>기존에 만든 웹페이지(main.com) 가 있고 여기에 새로운 페이지(main.com/user)를 추가했을 때, 새로운 페이지의 성능(사용자에게 보여지는 시간)이 기존보다 빠르면 참 난처할 것이다. 메인 페이지의 성능을 끌어 올릴 때 lighthouse는 훌륭한 가이드라인이 될 거 같다.  </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[REACT] bundling & webpack]]></title>
            <link>https://velog.io/@ethan_world/REACT-bundling-webpack</link>
            <guid>https://velog.io/@ethan_world/REACT-bundling-webpack</guid>
            <pubDate>Mon, 26 Sep 2022 08:48:32 GMT</pubDate>
            <description><![CDATA[<h2 id="번들링">번들링</h2>
<ul>
<li>여러 제품이나, 코드, 프로그램을 묶어서 패키지로 제공하는 행위를 의미</li>
<li>개발자에게 번들링은 사용자에게 웹 애플리케이션을 제공하기 위한 파일 묶음을 의미</li>
</ul>
<h3 id="장점">장점</h3>
<ul>
<li>두 개의 .js 파일에서 같은 변수를 사용할 때 충돌을 방지해준다.</li>
<li>코드의 용량을 최적화하여 인터넷 환경이 좋지 않아도 빠르게 코드를 불러온다.</li>
<li>작성한 코드를 이용하여 새로운 배포 파일을 만들어준다.</li>
</ul>
<hr>
<h3 id="webpack">webpack</h3>
<ul>
<li>Webpack이란 여러 개의 파일을 하나의 파일로 합쳐주는 모듈 번들러다. </li>
<li>모듈 번들러란 HTML, CSS, JavaScript 등의 자원을 전부 각각의 모듈로 보고 이를 조합해 하나의 묶음으로 번들링(빌드)하는 도구이다.</li>
</ul>
<h3 id="사용법">사용법</h3>
<ul>
<li>webpack의 config파일을 만들어 속성을 설정해야한다.</li>
<li>속성 값으로는 <code>Entry</code> <code>Output</code> <code>Loaders</code> <code>Plugins</code> 등이 있다.</li>
</ul>
<ol>
<li>Entry : 코드의 “시작점&quot;을 의미. 여러개의 entry point를 지정할 수 있다.</li>
<li>Output : 생성된 번들을 내보낼 위치와 이 파일의 이름을 지정하는 속성키다. 
<code>path</code>속성을 사용할 때는 path 모듈을 사용해야한다.</li>
<li>Loaders : webpack은 기본적으로 자바스크립트와 JSON 파일만 이해한다. 보편적으로 css를 번들링에 포함시키기 위해 쓰는 듯 하다. 여기서 test와 use 속성은 필수 속성이다. 또 exclude 속성값으로 node_modules를 제외해야한다.</li>
<li>Plugins : Plugins를 사용하면 번들을 최적화하거나 에셋을 관리하고, 또는 환경변수 주입 등의 광범위한 작업을 수행할 수 있다. 대표적으로 html-webpack-plugin 를 사용하여 생성된 모든 번들을 자동으로 삽입하여 애플리케이션용 HTML 파일을 생성해준다. </li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[[자료구조/알고리즘] 기초]]></title>
            <link>https://velog.io/@ethan_world/%EC%9E%90%EB%A3%8C%EA%B5%AC%EC%A1%B0%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%EA%B8%B0%EC%B4%88</link>
            <guid>https://velog.io/@ethan_world/%EC%9E%90%EB%A3%8C%EA%B5%AC%EC%A1%B0%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%EA%B8%B0%EC%B4%88</guid>
            <pubDate>Sat, 24 Sep 2022 06:37:52 GMT</pubDate>
            <description><![CDATA[<h2 id="자료구조">자료구조</h2>
<ul>
<li>여러 데이터의 묶음을 저장하고, 사용하는 방법을 정의한 것</li>
</ul>
<h2 id="자료구조의-분류">자료구조의 분류</h2>
<ul>
<li>주어진 데이터들과 상황에 효율적으로 사용가능한 자료구조 중 <code>선형구조</code>와 <code>비선형구조</code> 를 배웠다.</li>
<li>선형구조의 <code>스택</code> <code>큐</code> 비선형구조의 <code>트리</code> <code>그래프</code>는 알고리즘 테스트에서 가장 많이 쓰이는 자료구조이다.</li>
</ul>
<hr>
<h2 id="stack의-특징">Stack의 특징</h2>
<ol>
<li>LIFO (last in first out) 후입선출 : 가장 나중에 추가된 데이터가 먼저 배출된다.</li>
<li>데이터를 하나씩 넣고 뺌 : 한꺼번에 여러 개를 넣거나 뺄 수 없습니다.</li>
<li>하나의 입출력 방향을 가짐 : 입출력 방향이 여러개면 <code>Stack</code> 구조가 아니다.</li>
<li>스택에 쌓이는 데이터는 유한하고 정적이여야 함 : 정적할당이란 변수선언을 통해 필요한 메모리를 할당하는 방법</li>
<li>스택의 크기는 제한되어있다 (넘치면 stack overflow)</li>
</ol>
<h4 id="stack-사용예시">stack 사용예시</h4>
<ol>
<li>브라우저의 뒤로 가기, 앞으로 가기 기능</li>
<li>문서작업의 ctrl + z </li>
</ol>
<hr>
<h2 id="queue의-특징">Queue의 특징</h2>
<ol>
<li>FIFO (first in first out) 선입선출 : 가장 먼저 추가된 데이터가 먼저 추가된다.</li>
<li>데이터를 하나씩 넣고 뺌 : 한꺼번에 여러 개를 넣거나 뺄 수 없습니다.</li>
<li>두개의 입출력 방향을 가짐 : 데이터의 입력, 출력 방향이 다릅니다. 만약 입출력 방향이 같다면 Queue 자료구조라고 볼 수 없습니다.</li>
</ol>
<h4 id="queue-사용예시">queue 사용예시</h4>
<ol>
<li>프린터기의 인쇄 대기열</li>
<li>은행창구의 번호표 대기</li>
<li>너비 우선 탐색 알고리즘 (BFS)</li>
</ol>
<h2 id="tree의-특징">Tree의 특징</h2>
<ul>
<li>트리는 노드로 구성된 계층적 자료구조다. 최상위 노드(루트)를 만들고, 루트 노드의 child를 추가하고, 그 child에 또 child를 추가하는 방식으로 트리 구조를 구현할 수 있다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[SEB FE] SECTION3 회고]]></title>
            <link>https://velog.io/@ethan_world/SEB-FE-SECTION3-%ED%9A%8C%EA%B3%A0</link>
            <guid>https://velog.io/@ethan_world/SEB-FE-SECTION3-%ED%9A%8C%EA%B3%A0</guid>
            <pubDate>Mon, 19 Sep 2022 07:59:16 GMT</pubDate>
            <description><![CDATA[<p>!youtube[En2seea1l2k]</p>
<p>이번 섹션을 함께한 노래😎🎶</p>
<hr>
<h2 id="회고-요약">회고 요약</h2>
<p>우선순위를 잘 지키지 못한 아쉬움과 그래도 열심히하려고 발버둥 친 나는 기특함 8:2</p>
<p><img src="https://velog.velcdn.com/images/ethan_world/post/23f9efb6-17eb-4085-803e-a55f17cac7fd/image.png" alt=""></p>
<p><strong>어려웠다.</strong></p>
<p>같이 코스를 뛰는 다른 분들도 어렵다고 하셨지만 그래도 공부의 어려움 보다는 내가 너무 나태해지지 않았나 반성하게 된다. 
<img src="https://velog.velcdn.com/images/ethan_world/post/3f2f6017-4974-4ba5-979d-f7f5f5325ba7/image.png" width="100px" height="100px"></p>
<p><strong>뿌듯함</strong></p>
<ol>
<li>운동보다는 밖에서 활동을 더 많이 했다. 조금 더 사람다운(?) 섹션을 보냈다.</li>
<li>처음에 정한 루틴을 잘 따르고 있다. 이젠 여유가 좀 생겼다.</li>
<li>Figma에 대해서 공부하고 있다. 기획단계에서 신경써야하는 부분 (State 예측이라던지)에 집중하니 정리가 잘 이루어지는 듯 하다.</li>
</ol>
<p><strong>아쉬움</strong></p>
<ol>
<li>일단 코플릿을 통한 알고리즘 문제가 너무 낯설어서 진짜 놔버렸다. 레퍼런스를 보고 이해하는 시간을 가지다가 포기하는 빈도가 늘어났고 이게 너무 싫다.</li>
<li>저녁을 대부분 배달음식으로 먹어서 건강하지 않은 식습관을 2-3주간 유지했다.</li>
<li>토이프로젝트 완성을 하지 못했다. 마감기한이 없으니 마구마구 미루게 된다.</li>
</ol>
<h3 id="1-목표-상기하기">1. 목표 상기하기</h3>
<blockquote>
</blockquote>
<ul>
<li>SECTION 2 목표 상기 :
이번 SECTION 3의 회고를 작성할 때 제 깃허브에 2개 이상의 토이프로젝트 repo를 만들거다.
1번 repo는 지금까지 배운 것들을 사용하여 만들고
2번 repo는 앞으로 활용하고 싶은 스택을 사용하여 만들자!<blockquote>
</blockquote>
</li>
</ul>
<hr>
<blockquote>
</blockquote>
<ul>
<li>SECTION 3 목표 상기 :
알고리즘에 더 집중하고싶다. 모의 코딩테스트를 진행하면 너무 무력감에 휩싸인다. 깨부시고 싶다! 진행중인 토이프로젝트를 SECTION 4에서는 꼭 완성하고 싶다.</li>
</ul>
<h3 id="2-keep-problem-작성하기">2. keep, problem 작성하기</h3>
<blockquote>
</blockquote>
<ul>
<li>SECTION 2 Keep :
요즘 잠들기가 어려워서 카페인을 줄이고 있다. 운동하며 생각하고, 집에와서 복습하고 노곤하게 잠들 곤 했는데 오전부터 커피를 3잔씩 마시니 노곤하게 잠들지 못하고 있었다. 
물처럼 커피를 마시지 말자!
밀키트를 주문해서 이제 설거지가 거의 없다.
간식대신 과일먹기를 시작했다. (복숭아!)<blockquote>
</blockquote>
</li>
</ul>
<hr>
<blockquote>
</blockquote>
<ul>
<li>SECTION 3 Keep :
점심마다 쭈니랑 산책하고 6시에 코스 일과가 끝나면 운동하러간다. 지금 체력의 원동력이 된 거 같아서 타협없이 힘이 닿을때까지 이렇게 살고싶다.</li>
</ul>
<blockquote>
</blockquote>
<ul>
<li>SECTION 2 Problem :
토이 프로젝트를 만들 때 내게 잘맞는 효율적인 구조를 찾지 못했다. 가령 컴포넌트들의 배치라던가,,, 선배 기수분들의 깃허브 프로젝트를 보면 아직 배우지 않은 타입스크립트 일 때가 많아서, 이해가 어려워 부족함을 느꼈다.<blockquote>
</blockquote>
</li>
</ul>
<hr>
<blockquote>
</blockquote>
<ul>
<li>SECTION 3 Problem :
프로젝트를 기획할 때 무식하게 일을 잘 벌린다. 스스로 프로젝트에 대한 기대감이 높아지다 보니 자꾸 욕심을 부리다 루틴이 한 번 무너졌었다. 아무리 혼자 진행하는 프로젝트라도 조금 신중하게 진행해야 겠다. <code>내일의 나야 부탁해!</code>는 이제 그만🤯!</li>
</ul>
<h3 id="3-try-작성하기">3. try 작성하기</h3>
<blockquote>
</blockquote>
<ul>
<li>SECTION 2 Try :
환경에 나를 집어넣을 용기가 나질 않았다. 정말 감사한 페어 분께서 자신이 속한 스터디에서 같이 공부하자고 권유하셨지만, 나름의 핑계를 대며 얼버무렸다. 벌써부터 스스로 압박받는 상황 속에 나를 집어넣지 않는다면, 성장할 기회를 놓치게 될 것이다. SECTION 3에서는 내가 많이 부족하다 느껴진다고 할 지라도 능동적으로 더 몰아붙이고 싶다.<blockquote>
</blockquote>
</li>
</ul>
<hr>
<blockquote>
</blockquote>
<ul>
<li>SECTION 3 Try : 
어쩌면 능동적으로 나를 고립시켰던 거 같다. 스스로 스트레스를 주어 극복하기보단, 주어진 환경(스터디?)을 이용해서 쫌 더 스마트하게 몰아붙혀야겠다. </li>
</ul>
<h3 id="4-우선순위-정하기">4. 우선순위 정하기</h3>
<blockquote>
</blockquote>
<ul>
<li>SECTION 2 우선순위 정하기 :
복습을 했다면 써먹어야 내것이 된다. 주말 시간에 VScode를 키고 배운 내용들로 기능 구현을 해보자
카페인을 줄여서 잠에 드는 시간을 줄이자☕️ 나는 시간이 부족하다..!
필독 도서 꾸준하게 읽자<blockquote>
</blockquote>
</li>
</ul>
<hr>
<blockquote>
</blockquote>
<ul>
<li>SECTION 3 우선순위 정하기 :
카페인을 줄이지 말자! 시간의 품질을 늘려야 한다..! (잠에 드는 시간 개선완료)
앞으로 어려운 공부가 지나면 팀 프로젝트를 해야한다. 누가 되지 않기 위해서라도 수업시간이 끝나면 Section 2의 첫 유닛부터 복습할 생각이다!</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[기술면접]]]></title>
            <link>https://velog.io/@ethan_world/%EA%B8%B0%EB%A9%B4</link>
            <guid>https://velog.io/@ethan_world/%EA%B8%B0%EB%A9%B4</guid>
            <pubDate>Mon, 19 Sep 2022 02:28:49 GMT</pubDate>
            <description><![CDATA[<ul>
<li><h4 id="재귀">재귀</h4>
</li>
</ul>
<p>Q. 재귀를 활용하기 좋은 상황은 언제인지 예시를 들어 설명해주세요.
A. 
주어진 문제를 비슷한 구조의 더 작은 문제로 나누는 경우나, 중첩된 반복문이 많거나 그 중첩횟수를 예측하기 어려운 경우에 사용합니다. 예를들면 마트료시카인형처럼 객체안에 객체 패턴이 얼마나 많은지 알기 위해 사용할 수 있습니다.</p>
<hr>
<ul>
<li><h4 id="uiux">UI/UX</h4>
</li>
</ul>
<p>Q. UI, UX의 개념과 두 개념의 관계에 대해서 설명해주세요.
A. UI는 사람들이 컴퓨터와 상호 작용하는 시스템을 의미합니다. 모니터 스크린속 그래픽요소들 뿐만 아니라 마우스와 키보드같은 물리적 요소도 포함됩니다. UX는 사용자가 직•간접적으로 이용하면서 느끼고 생각하는 총체적 경험입니다. 총체적 경험은 서비스에 대한 경험은 물론, 홍보, 접근성, 사후 처리 등 직간접적으로 관련된 모든 경험을 의미합니다. UX는 UI를 포함합니다. 또한 좋은 UX가 좋은 UI를 의미하거나, 좋은 UI가 항상 좋은 UX를 보장하지는 않습니다. 하지만, 나쁜 UI는 보통 나쁜 UX를 유발합니다.</p>
<hr>
<ul>
<li><h4 id="custom-component">Custom Component</h4>
</li>
</ul>
<p>Q. Styled Components를 사용해보면서 느낀 장점을 이야기해주세요.
A. 클래스 네임을 중복해서 사용 시 생기는 버그 방지, 구조적으로 컴포넌트와 스타일이 묶여 있어 관리하기 용이합니다. 
더 나아가 React를 이용한 웹 개발은 통상적으로 컴포넌트들을 만들고 그것들을 조합하여 하나의 웹 페이지를 구상하는데, 일반적으로 CSS파일을 따로 만들어서 import하는 개발 방법이 말씀드린 Component 방식으로 개발하는 것과는 어울리지 않다라는 생각이 들었습니다. Styled-components를 이용해서 리액트 친화적인 개발을 할 수 있는게 큰 장점이라 생각합니다.</p>
<p>Q. useRef가 필요한 상황을 예시를 들어 설명해주세요.
A. 인풋박스에서 이벤트가 발생하여 focus를 사용할 때 useRef hook을 사용하여 이벤트의 근원지 DOM주소를 조작할 수 있습니다.</p>
<hr>
<ul>
<li><h4 id="redux">Redux</h4>
</li>
</ul>
<p>Q. 상태관리 라이브러리의 필요성에 대해서 설명해주세요.
A. 컴포넌트간 데이터를 전달시켜줄 때 props를 사용하여 보냈지만, 전달하는 용도로만 사용하는 컴포넌트들을 거치면서, 코드 가독성이 심하게 떨어지고 유지보수 또한 어려워집니다. 이를 해결하기 위해 상태관리 라이브러리를 사용하여, 전역 상태를 관리하여 해결할 수 있습니다.</p>
<p>Q. Redux의 주요 개념들과 연결 관계를 설명해주세요.
A. Redux는 Action → Dispatch → Reducer → Store 순서로 데이터가 단방향으로 흐르게 된다.</p>
<blockquote>
<ol>
<li>상태가 변경되어야 하는 이벤트가 발생하면, 변경될 상태에 대한 정보가 담긴 Action 객체가 생성된다.</li>
<li>이 Action 객체는 Dispatch 함수의 인자로 전달된다.</li>
<li>Dispatch 함수는 Action 객체를 Reducer 함수로 전달해준다.</li>
<li>Reducer 함수는 Action 객체의 값을 확인하고, 그 값에 따라 전역 상태 저장소 Store의 상태를 변경한다.</li>
<li>상태가 변경되면, React는 화면을 다시 렌더링 한다.</li>
</ol>
</blockquote>
<hr>
<ul>
<li><h4 id="웹-표준--웹-접근성">웹 표준 &amp; 웹 접근성</h4>
</li>
</ul>
<p>Q. Semantic HTML의 필요성을 예시를 들어 설명해주세요.
A. 의미있는 html tag를 사용하면 개발자간 소통이 보다 원활해집니다. semantic하게 작성된 html을 읽을 때 그렇지 않은 html보다 훨씬 더 이해가 빠르고, id와 class를 사용해서 일일히 표기하면, 각 요소의 기능을 정의하느라 비용(시간)이 든다.</p>
<hr>
<ul>
<li><h4 id="네트워크-심화">네트워크 심화</h4>
</li>
</ul>
<p>Q. IP 프로토콜의 한계에 대해서 설명해주세요.
A. IP의 한계로는 비연결성과 비신뢰성이 있습니다.
패킷을 받을 대상이 없어도 이를 인지하지 못하여 그대로 패킷을 전송합니다. 그리고 중간에 패킷이 사라져도 클라이언트는 확인할 방법이 없습니다. 쪼개진 패킷으로 전달하게 될 경우 서로 다른 노드를 통해 전달될 수 있어, 의도와 다른 순서대로 도착할 수 있습니다.</p>
<p>Q. HTTP 프로토콜의 특징에 대해 설명해주세요.
A. 서버에 대한 요청과 서버가 클라이언트에게 하는 응답이 있습니다. 비상태성이라 요청이 증가해도 서버를 투입하여 처리할 수 있습니다. 하지만 상태정보를 요구하는 기능을 활용할 수 없어 이는 쿠키나 세션을 통해서 처리합니다. 비연결성이라 최소한의 작업으로 요청을 처리합니다. 하지만 큰 규모의 서비스를 운영할 때에는 연결을 반복하는 게 비효율적이라, 헤더에 keep-alive라는 옵션을 추가하여 연결을 지속시킬 수 있습니다.</p>
<hr>
<ul>
<li><h4 id="인증--보안">인증 / 보안</h4>
</li>
</ul>
<p>Q. Cookie의 MaxAge, Expires 옵션이 무엇인지, 설정하지 않으면 어떻게 되는지 설명해주세요.
A. expires/max-age 는 쿠키의 만료 시간을 정해줍니다. 이 옵션이 없으면 브라우저가 닫힐 때 쿠키도 같이 삭제되는데 이런 쿠키를 세션 쿠키라고 하고, 옵션이 설정되어 브라우저가 닫혀도 옵션만큼 사용가능한 쿠키를 영속성 쿠키라고 합니다.  </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[사용자 친화 웹] 웹 표준 & 접근성]]></title>
            <link>https://velog.io/@ethan_world/%EC%82%AC%EC%9A%A9%EC%9E%90-%EC%B9%9C%ED%99%94-%EC%9B%B9-%EC%9B%B9-%ED%91%9C%EC%A4%80-%EC%A0%91%EA%B7%BC%EC%84%B1</link>
            <guid>https://velog.io/@ethan_world/%EC%82%AC%EC%9A%A9%EC%9E%90-%EC%B9%9C%ED%99%94-%EC%9B%B9-%EC%9B%B9-%ED%91%9C%EC%A4%80-%EC%A0%91%EA%B7%BC%EC%84%B1</guid>
            <pubDate>Wed, 07 Sep 2022 07:17:46 GMT</pubDate>
            <description><![CDATA[<h4 id="웹-표준-내용-요약">웹 표준 내용 요약</h4>
<ul>
<li>웹은 <code>공간</code>이다.</li>
<li>웹은 문서, 이미지 영상 등 다양한 정보를 여러 사람들과 공유할 수 있는 <code>공간</code>이다.</li>
<li>2000년대 초에 많은 브라우저들이 만들어졌고, 개발자들은 각 브라우저마다 따로 개발을 해주어야 했다.</li>
<li>이런 수고를 없애고 웹 개발의 형식을 통일 시킨 것이 <code>웹 표준</code>이다.</li>
</ul>
<ul>
<li><p>웹 표준이란 W3C에서 권고하는 규칙으로, 사용자가 서로 다른 운영체제나 브라우저를 사용하더라도 웹페이지가 동일하게 보이고 정상적으로 작동할 수 있는 제작 기법을 담고있다.</p>
</li>
<li><p>사용자가 사용하는 특정 브라우저에 너무 의존적이지 않기위해 웹 표준을 준수하여 개발해야 한다.</p>
</li>
</ul>
<hr>
<h4 id="웹-표준의-장점">웹 표준의 장점</h4>
<ol>
<li>유지 보수의 용이성</li>
</ol>
<ul>
<li>HTML, CSS, JS의 영역이 분리되면서 유지 보수가 용이해졌고, 트래픽 비용이 감소했다.</li>
</ul>
<ol start="2">
<li>웹 호환성 확보 / 접근성 향상</li>
</ol>
<ul>
<li>웹 표준을 준수하면 브라우저의 종류나 버전, 운영체제나 사용 기기 종류에 상관없이 동일한 결과를 얻는다.</li>
</ul>
<ol start="3">
<li>검색 효율성 증대</li>
</ol>
<ul>
<li>웹 표준에 맞추면 검색 엔진에서 더 높은 우선 순위로 노출될 수 있다.</li>
</ul>
<hr>
<h2 id="semantic의미있는-html">Semantic(의미있는) HTML</h2>
<ul>
<li>웹 표준에서 강조하는 것들 중 하나가 바로 HTML을 의미있게 작성하는 것이다.</li>
<li><code>&lt;div&gt;</code>와 <code>&lt;span&gt;</code>만으로도 화면을 만들 수 있지만, 각자의 역할이 붙어있는 올바른 태그를 사용하면, 어떤 내용이 그 안에 담기는 지 보다 명확하게 알 수 있다.</li>
</ul>
<h4 id="필요성">필요성</h4>
<ol>
<li>개발자간 소통</li>
</ol>
<ul>
<li>semantic하게 작성된 html을 읽을 때 그렇지 않은 html보다 훨씬 더 이해가 빠르다.</li>
<li>id와 class를 사용해서 일일히 표기하면, 각 요소의 기능을 정의하느라 비용(시간)이 든다.</li>
</ul>
<ol start="2">
<li>검색 효율성</li>
</ol>
<ul>
<li>semantic한 html은 어떤 요소에 더 중요한 내용이 들어있을지 우선 순위를 정할 수 있고, 이는 SEO 향상에 도움을 준다.</li>
</ul>
<ol start="3">
<li>웹 접근성</li>
</ol>
<ul>
<li>스크린리더를 사용하는 사람들에게 보다 더 정확한 요소의 의미를 전달할 수 있다.</li>
</ul>
<h4 id="자주-사용하는-종류">자주 사용하는 종류</h4>
<center><img src="https://velog.velcdn.com/images/ethan_world/post/132b4642-a99e-4ad7-97de-b39848886021/image.png" width="400" height="300"></center>


<h4 id="자주-틀리는-형식">자주 틀리는 형식</h4>
<ol>
<li>인라인 요소에 블록 요소를 넣기</li>
</ol>
<ul>
<li>대표적인 인라인 요소로는 <code>&lt;span&gt;</code>, 블록 요소로는 <code>&lt;div&gt;</code> 가 있다. 인라인 요소는 항상 블록 요소 안에 들어가야 한다.</li>
</ul>
<ol start="2">
<li><code>&lt;b&gt;</code>  <code>&lt;i&gt;</code> 요소 사용하기</li>
</ol>
<ul>
<li>위 요소는 semantic하지 않기 때문에 각각 <code>&lt;strong&gt;</code> <code>&lt;em&gt;</code> 태그를 사용한다.</li>
</ul>
<ol start="3">
<li><code>&lt;hgroup&gt;</code> <code>&lt;br/&gt;</code> 을 남발하고, 글자 크기를 작게 하는 용도로 쓰기</li>
</ol>
<ul>
<li>사용자에게 잘못된 화면 구조 정보를 전달할 수 있다.</li>
</ul>
<hr>
]]></description>
        </item>
    </channel>
</rss>