<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>codename-602</title>
        <link>https://velog.io/</link>
        <description>프론트엔드 개발자 지망생</description>
        <lastBuildDate>Mon, 02 Jan 2023 10:00:00 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>codename-602</title>
            <url>https://velog.velcdn.com/images/codename-602/profile/0af06563-40d7-4c69-9156-8c26c4cd1ed3/image.jpg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. codename-602. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/codename-602" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[👍 GtOdOD]]></title>
            <link>https://velog.io/@codename-602/%EC%9A%B0%EB%8B%B9%ED%83%95%ED%83%95FE-2022-04</link>
            <guid>https://velog.io/@codename-602/%EC%9A%B0%EB%8B%B9%ED%83%95%ED%83%95FE-2022-04</guid>
            <pubDate>Mon, 02 Jan 2023 10:00:00 GMT</pubDate>
            <description><![CDATA[<h2 id="📜-프로젝트-소개">📜 프로젝트 소개</h2>
<blockquote>
<h5 id="기간--202209-1주">기간 : 2022.09 (1주)</h5>
<h5 id="인원--1인">인원 : 1인</h5>
<h5 id="주제--to-do-list">주제 : to do list</h5>
<h5 id="사용-스택-reactjs-redux-mui-scss-spring-boot-spring-security">사용 스택: React.js, Redux, MUI, scss, Spring boot, Spring security</h5>
</blockquote>
<p>전의 한솥도시락 클론코딩과 마찬가지로 개인 프로젝트라 전반적으로 설계하고 개발하였지만 프론트엔드 회고록인만큼 프론트엔드 중점으로 회고하겠다. GtoOdOD 프로젝트는 좋은 투두리스트라는 의미로 GOOD과 todo를 적절하게 섞어서 지은 제목이다.
<br></p>
<h3 id="🤩-scss">🤩 SCSS!</h3>
<p>저번 한솥도시락 클론코딩 프로젝트를 진행할 때 많은 html 요소가 나와서 마크업을 하기가 너무 힘들었다. 해소할 수 있는 방법을 찾다가 scss를 알게 되었다. scss는 중첩하여 css를 작성할 수 있고, 색상 또한 변수로 선언하여 불러올 수 있기 때문에 작업하기가 매우 편했다. scss를 컴파일하면 css 파일이 생기는데, 이 css 파일을 import하여 마크업하였다. 앞으로 많은 요소가 있는 페이지를 작성할 때 scss를 사용해야겠다고 생각했다.</p>
<table>
<thead>
<tr>
<th>scss</th>
<th>css</th>
</tr>
</thead>
<tbody><tr>
<td><img src="https://velog.velcdn.com/images/codename-602/post/e85de0cd-118d-45b1-be14-f4effa5f934a/image.png" alt=""></td>
<td><img src="https://velog.velcdn.com/images/codename-602/post/0a12361e-28ee-4c51-b01d-1ad4c8f67263/image.png" alt=""></td>
</tr>
</tbody></table>
<p>scss를 사용하여 색상변수를 지정한 것을 토대로 투두리스트의 카테고리 색상을 고를 수 있도록 했다.
<img src="https://velog.velcdn.com/images/codename-602/post/2b96e114-30fd-48e2-9e45-6af7b916b766/image.png" alt=""></p>
<br>

<h3 id="🤓-와-아토믹">🤓 와! 아토믹!</h3>
<p>프로젝트를 진행하다가 아토믹 디자인 설계에 관한 포스트를 보게 되었다. 컴포넌트 분리를 즐거워하는 나에게는 매우 흥미로운 주제였고 다음 프로젝트에 꼭꼭 적용해봐야겠다고 생각했다. 본격적으로 적용하였던 다음 프로젝트 까마귀버스 회고에서 제대로 소개하겠다.
<br></p>
<h3 id="👩💻-프로젝트를-마치며">👩‍💻 프로젝트를 마치며...</h3>
<p>이번 프로젝트는 교육에서 스프링부트와 스프링 시큐리티를 다루기 위해 간단한 CRUD를 적용할 수 있는 투두리스트를 실습 주제로 잡은 것이다. 기본 기능만 해도 됐었지만 욕심이 생겨 기능을 이것저것 추가해 보았다. 추가한 기능은 카테고리와 날짜 미루기 기능이며, 구동 영상은 <a href="https://www.youtube.com/watch?v=nSYQCyOJc94">여기</a>서 확인할 수 있다. 개인적으로 UI가 마음에 드는 프로젝트이고, 2023년에 GtOdOD의 기능을 안정화하고, ts로 리팩토링 해 볼 예정이다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[🍱 한솥도시락 클론코딩]]></title>
            <link>https://velog.io/@codename-602/%EC%9A%B0%EB%8B%B9%ED%83%95%ED%83%95FE-2022-03</link>
            <guid>https://velog.io/@codename-602/%EC%9A%B0%EB%8B%B9%ED%83%95%ED%83%95FE-2022-03</guid>
            <pubDate>Wed, 28 Dec 2022 15:09:57 GMT</pubDate>
            <description><![CDATA[<h2 id="📜-프로젝트-소개">📜 프로젝트 소개</h2>
<blockquote>
<h5 id="기간--202209-1주">기간 : 2022.09 (1주)</h5>
<h5 id="인원--1인">인원 : 1인</h5>
<h5 id="주제--한솥도시락-사이트-클론-코딩">주제 : 한솥도시락 사이트 클론 코딩</h5>
<h5 id="사용-스택-reactjs-redux-bootstrap-express-oracledb">사용 스택: React.js, Redux, Bootstrap, Express, OracleDB</h5>
</blockquote>
<p> 졸업 전에 프론트엔드 분야를 더 공부하고자 휴학했는데, 마침 그 시기에 열린 교내 웹 교육 프로그램에서 진행한 개인 공통 프로젝트이다. 개인 프로젝트라 전반적으로 설계하고 개발하였지만 프론트엔드 회고록인만큼 프론트엔드 중점으로 회고하겠다.</p>
<br>

<h3 id="🤓-리액트를-똑똑하게">🤓 리액트를 똑똑하게!</h3>
<p>지난 학기에 진행하였던 Movie In Memory에서 컴포넌트 분리를 체계적으로 하지 않아서 불편함을 겪었었다. 고급웹프로그래밍 수업의 텀프로젝트였던 영화관 클론코딩 미니 프로젝트에서도 교수님께 페이지 새로고침에 대해서 지적을 들었었다.</p>
<p>페이지 새로고침 같은 경우에는 window.location.href를 남발했기 때문에 발생한 문제였다. 컴포넌트에서 수정이 발생하면 그 컴포넌트만 새로고침을 하면 되는데 페이지 전체를 새로고침함으로써 컴포넌트가 새로고침 된 것이였다. 학기 중에는 완성에 급급해서 이러한 것들을 신경쓰지 않았는데, 꼭 개선하고 가야 할 부분이었다. 컴포넌트 분리와 부분 리랜더링이 리액트의 장점이라고 생각하는데, 장점을 하나도 제대로 이용하지 못하고 있었다. 앞으로 리액트를 똑똑하게 사용해봐야겠다고 다짐하였고, 한솥 클론코딩은 이런 마음가짐으로 맞이하는 첫 리액트 프로젝트이다.</p>
<p>컴포넌트는 도메인에 따라서 나누어 보았다. MIM 프로젝트를 진행할 때는 페이지를 구성하는 작은 부분들을 전부 component 폴더 하나 안에 때려넣어서 찾기가 많이 힘들었다. 한솥 프로젝트와 같이 도메인별로 폴더를 분리한다면 사진에서 보이는 부분들은 common이나 admin 폴더를 만들어서 폴더 분리를 할 수 있겠다. <img src="https://velog.velcdn.com/images/codename-602/post/eb0efd92-3af3-48c2-aed1-aa1004874ce8/image.png" alt=""><img src="https://velog.velcdn.com/images/codename-602/post/9343efd2-b7bf-4129-8e93-e759310c98ca/image.png" alt=""></p>
<br>

<h3 id="🤩-리덕스">🤩 리덕스!</h3>
<p>교육에서 프론트엔드를 배우면서 상태 관리라는 개념과 리덕스를 알게 되었다. 일반적으로 리액트에서는 useState를 통해 컴포넌트의 상태를 관리한다. 하지만 컴포넌트 안에서만 공유가능하기 때문에 다른 컴포넌트에서도 그 상태를 사용하려면 props로 상태값과 상태변경값을 넘겨줘야 했다. hook이라는 개념을 이때는 몰랐었기 때문에 MIM 프로젝트때부터 나름 고민해왔던 사항이였다. 또 useState를 남발하니 코드도 너무 길어져서 눈에 잘 들어오지 않았다.
리덕스를 사용하면 하나의 store에 상태들을 저장할 수 있기 때문에 이러한 고민거리들을 해소할 수 있었다. 나에겐 매우 신세계였고 다음에 리액트 프로젝트를 진행하게 된다면 리덕스를 꼭 사용해야겠다고 결심하게 되었다.</p>
<br>

<h3 id="😶🌫️-리덕스">😶‍🌫️ 리덕스...?</h3>
<p>그렇게 적용한 리덕스는 신세계이면서도 조금 혼란스러웠다. 상태를 관리하려면 초기 데이터를 가지고 있어야하니까 db에서 데이터를 들고와서 가지고 있어야 하지 않나?에서 시작한 꼬리에 꼬리를 무는 의문이 생겨났다. 회고를 하고 보니 hook을 몰랐어서 그런 것 같다. 그래서 이때의 나는 리덕스의 액션으로 데이터를 패치하는 액션도 만들었다. 너무 많은 액션을 만들어서 함수 찾기가 너무 힘들고 헷갈려서 고생 좀 했다. 다시 보니까 함수도 액션이랑 이름이 다르네 이러니까 해맸지...<img src="https://velog.velcdn.com/images/codename-602/post/91002129-1f65-443a-a0de-5d5770552d75/image.png" alt=""></p>
<br>

<h3 id="👩💻-프로젝트를-마치며">👩‍💻 프로젝트를 마치며...</h3>
<p>의문점이 전부 해소된 것은 아니지만 그래도 과거보다는 리액트를 조금 더 똑똑하게 사용한 것 같아서 뿌듯했다. 이 포스팅을 작성하는 지금도 개선해야 할 사항이 보인다. 그래서 개발자들이 항상 프로젝트를 마치면 회고를 하는 것 같다. <a href="https://sizxero.github.io/hansot/">여기</a>에서 1주의 개발 기간 중 무려 하루를 갈아넣어 만든 홈 화면을 확인할 수 있다. 밑의 사진을 클릭하면 DB까지 연동되어 사이트가 어떻게 구동되는지를 확인할 수 있다.</p>
<p><a href="https://youtu.be/D_Samxj5WxI"><img src="https://img.youtube.com/vi/D_Samxj5WxI/3.jpg" alt="예제"></a> </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[TypeScript] typescript 설치 & 실행]]></title>
            <link>https://velog.io/@codename-602/TypeScript-typescript-%EC%84%A4%EC%B9%98-%EC%8B%A4%ED%96%89-kh3reafh</link>
            <guid>https://velog.io/@codename-602/TypeScript-typescript-%EC%84%A4%EC%B9%98-%EC%8B%A4%ED%96%89-kh3reafh</guid>
            <pubDate>Fri, 23 Dec 2022 07:20:09 GMT</pubDate>
            <description><![CDATA[<h2 id="🧵-패키지-설치">🧵 패키지 설치</h2>
<h3 id="①-typescript">① typescript</h3>
<p>npm i -g typescript</p>
<h3 id="②-ts-node">② ts-node</h3>
<p>npm i -g ts-node</p>
<p><img src="https://user-images.githubusercontent.com/51533341/209078015-75f5578e-4514-4501-b981-cfeda371d4e9.png" alt="image"></p>
<p>*한꺼번에 설치할 시 : npm i -g typescript ts-node</p>
<h2 id="🧵-실행">🧵 실행</h2>
<pre><code class="language-jsx">// 1222_01.ts
let hello: string = &quot;hello TS&quot;;
console.log(hello);</code></pre>
<h3 id="①-파일-직접-실행">① 파일 직접 실행</h3>
<p>ts-node &lt;파일명&gt; </p>
<p><img src="https://user-images.githubusercontent.com/51533341/209078098-b0e6c804-5312-45dd-8c0b-ce03f5ef3447.png" alt="image"></p>
<h3 id="②-파일-컴파일-실행">② 파일 컴파일 실행</h3>
<p><strong>&gt;tsc &lt;파일명&gt;</strong></p>
<p>컴파일된 js 파일이 생성된다.</p>
<p><img src="https://user-images.githubusercontent.com/51533341/209078195-431e3293-ad66-4ff5-b98f-7ba524195141.png" alt="image"></p>
<pre><code class="language-jsx">// 1222_01.js
var hello = &quot;hello TS&quot;;
console.log(hello);</code></pre>
<p><strong>&gt;node &lt;파일명&gt;</strong></p>
<p><img src="https://user-images.githubusercontent.com/51533341/209078270-5be9f6e0-f6ca-43a1-8045-23bf74a88887.png" alt="image"></p>
<h2 id="📚-references">📚 References</h2>
<p><a href="https://juntcom.tistory.com/157">https://juntcom.tistory.com/157</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JavaScript] 일급 객체]]></title>
            <link>https://velog.io/@codename-602/JavaScript-%EC%9D%BC%EA%B8%89-%EA%B0%9D%EC%B2%B4</link>
            <guid>https://velog.io/@codename-602/JavaScript-%EC%9D%BC%EA%B8%89-%EA%B0%9D%EC%B2%B4</guid>
            <pubDate>Wed, 21 Dec 2022 12:05:56 GMT</pubDate>
            <description><![CDATA[<h2 id="🏅-일급-객체">🏅 일급 객체</h2>
<p>프로그래밍 언어에서 타입을 전달, 반환 및 할당할 수 있는 경우 해당 타입을 일급 객체로 간주한다. JavaScript는 함수형 프로그래밍으로, 함수를 인수로 받거나 함수를 반환하는 고차 함수를 만들 수 있다. 일급 객체는 다음 세 가지 조건을 만족하는데, 자바스크립트의 함수는 이 조건들을 모두 만족하기 때문에 일급 객체이다.</p>
<h3 id="①-변수나-데이터에-할당할-수-있어야-함">① 변수나 데이터에 할당할 수 있어야 함</h3>
<pre><code class="language-jsx">const func = function () {
    ...
};</code></pre>
<pre><code class="language-jsx">const movie = {
    name: &#39;아바타 2&#39;,
    director: &#39;제임스 카메론&#39;,
    show: function() {
        console.log(`${this.name}의 감독은 ${this.director}`);
    }
}</code></pre>
<h3 id="②-객체의-인자로-넘길-수-있어야-함">② 객체의 인자로 넘길 수 있어야 함</h3>
<pre><code class="language-jsx">function showText(e) {
    ...
}

$(&#39;form&#39;).on(&#39;submit&#39;, showText);
$(&#39;a&#39;).on(&#39;click&#39;, showText);</code></pre>
<h3 id="③-리턴값으로-사용할-수-있어야-함">③ 리턴값으로 사용할 수 있어야 함</h3>
<pre><code class="language-jsx">function add(a) {
    return function(b) {
        return a + b;
    }
}
const add3 = add(3);
const add5 = add(5);

add3(2); // 5
add5(2); // 7</code></pre>
<h2 id="🥇-고차함수">🥇 고차함수</h2>
<p>ex) forEach(), find(), filter(), map(), reduce(), sort(), some(), every(), …</p>
<p>함수를 인자로 전달받거나 연산의 결과로 반환해주는 함수이다. 고차함수는 인자로 받은 함수를 필요한 시점에 호출하거나 클로저를 생성하여 반환한다. 또 외부 상태 변경이나 가변 데이터를 피하고 불변성을 지향하는 함수형 프로그래밍에 기반을 두고 있다.</p>
<p>고차함수는 함수를 통해 얻은 추상화를 한 단계 높혔다. 고차함수는 함수를 전달받거나 리턴하기 때문에 함수에 대한 복잡한 로직은 감춰져있다. 따라서 사고 수준에서 추상화가 되어있고, 추상화의 수준이 높아진 만큼 생산성도 높아진다.</p>
<h2 id="📚-references">📚 References</h2>
<p><a href="https://soeunlee.medium.com/javascript%EC%97%90%EC%84%9C-%EC%99%9C-%ED%95%A8%EC%88%98%EA%B0%80-1%EA%B8%89-%EA%B0%9D%EC%B2%B4%EC%9D%BC%EA%B9%8C%EC%9A%94-cc6bd2a9ecac">https://soeunlee.medium.com/javascript에서-왜-함수가-1급-객체일까요-cc6bd2a9ecac</a></p>
<p><a href="https://poiemaweb.com/js-array-higher-order-function">https://poiemaweb.com/js-array-higher-order-function</a></p>
<p><a href="https://hanamon.kr/javascript-%EA%B3%A0%EC%B0%A8%ED%95%A8%EC%88%98%EC%99%80-%EC%BD%9C%EB%B0%B1-%EC%9D%BC%EA%B8%89%EA%B0%9D%EC%B2%B4%EB%9E%80/">https://hanamon.kr/javascript-고차함수와-콜백-일급객체란/</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[React] Hook]]></title>
            <link>https://velog.io/@codename-602/React-Hook</link>
            <guid>https://velog.io/@codename-602/React-Hook</guid>
            <pubDate>Tue, 13 Dec 2022 02:31:31 GMT</pubDate>
            <description><![CDATA[<h2 id="🪝-hook이란">🪝 Hook이란?</h2>
<p>Hook은 <strong>props, state, context, ref, lifecycle</strong>과 같은 react 개념에 좀 더 직관적인 API를 제공한다. 또한 hook은 이 개념들을 엮기 위해 새로운 방법을 제공한다. Hook은 계층의 변화 없이 상태 관련 로직을 재사용할 수 있도록 도와준다. Hook을 통해 서로 비슷한 것을 하는 작은 함구의 묶음으로 컴포넌트를 나누는 방법을 사용할 수 있다. Hook은 함수 컴포넌트에서 React state와 생명주기 기능을 연동할 수 있게 해주는 함수이다. </p>
<p>최상위에서만 Hook을 호출해야 한다. 반복문, 조건문, 중첩된 함수 내에서 Hook은 실행할 수 없다. react 함수 컴포넌트 내에서만 Hook을 호출해야 한다. 단, custom hook 내에서는 Hook을 호출할 수 있다.</p>
<h2 id="🪝-usestate">🪝 useState</h2>
<pre><code class="language-jsx">const [count, setCount] = useState(0);</code></pre>
<p>state는 함수형 컴포넌트 내에 다음과 같이 추가할 수 있는데, 이 state는 컴포넌트가 다시 렌더링 되어도 그대로 유지된다. useState는 현재의 state값과 이 값을 업데이트 하는 함수를 쌍으로 제공한다. 이 함수를 이벤트 핸들러나 다른 곳에서 호출함으로써 state를 변경가능하게 한다. 인자로 들어가는 값(위의 예시에서는 0)은 초기의 state값이다.</p>
<h2 id="🪝-useeffect">🪝 useEffect</h2>
<p>컴포넌트 안에서 데이터를 가져오거나 구독하고, DOM을 직접 조작하는 작업을 side effects라고 한다. 이것은 다른 컴포넌트에 영향을 줄 수도 있고, 랜더링 과정에서는 구현할 수 없는 작업이기 때문이다. useEffect는 이러한 side effects를 함수 컴포넌트 내에서 할 수 있도록 하는 hook이다. React class의 componentDidMount, componentDidUpdate, componentWillUnmount와 같은 목적으로 제공되지만 하나의 API로 통합된 것이다.</p>
<p>useEffect를 사용하면 React는 DOM을 바꾼 뒤에 effect 함수를 실행할 것이다. effects는 컴포넌트 내에 선언되어 있기 때문에 props와 state에 접근할 수 있다. effect는 해제할 필요가 있다면 해제하는 함수를 반환할 수 있다.</p>
<p>useEffect는 우리가 react에게 컴포넌트가 렌더링 이후에 어떤 일을 수행해야 하는지를 말한다. 첫번째 렌더링과 이후의 모든 update에서 수행이 된다. effect가 수행되는 시점에서 이미 DOM이 업데이트 되었음을 보장한다.</p>
<p>effect에 정리가 필요한 경우에는 함수를 반환한다. React는 컴포넌트가 마운트 해제될 때 정리를 실행한다. effect는 랜더링이 실행될 때마다 실행되기 때문에, React가 다음 차례의 effect를 실행하기 전에 이전의 렌더링에서 파생된 effect를 정리할 필요가 있다.</p>
<pre><code class="language-jsx">useEffect(() =&gt; {
    function handleStatusChange(status) {
        setIsOnline(status.isOnline);
    }
    ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
    return() =&gt; {
        ChatAPI.unsubscribeToFriendStatus(props.friend.id, handleStatusChange);
    };
});</code></pre>
<pre><code class="language-jsx">componentDidMount() {
    ChatAPI.subscribeToFriendStatus(
      this.props.friend.id,
      this.handleStatusChange
    );
  }

  componentDidUpdate(prevProps) {
    // 이전 friend.id에서 구독을 해지합니다.
    ChatAPI.unsubscribeFromFriendStatus(
      prevProps.friend.id,
      this.handleStatusChange
    );
    // 다음 friend.id를 구독합니다.
    ChatAPI.subscribeToFriendStatus(
      this.props.friend.id,
      this.handleStatusChange
    );
  }

  componentWillUnmount() {
    ChatAPI.unsubscribeFromFriendStatus(
      this.props.friend.id,
      this.handleStatusChange
    );
  }</code></pre>
<pre><code class="language-jsx">// { friend: { id: 100 } } state로 마운트
ChatAPI.subscribeToFriendStatus(100, handleStatusChange);   // 첫 번째 effect

// { friend: { id: 200 } } state로 업데이트
ChatAPI.unsubscribeToFriendStatus(100, handleStatusChange); // 이전 effect 정리
ChatAPI.subscribeToFriendStatus(200, handleStatusChange);   // 다음 effect

// { friend: { id: 300 } } state로 업데이트
ChatAPI.unsubscribeToFriendStatus(200, handleStatusChange); // 이전 effect 정리
ChatAPI.subscribeToFriendStatus(300, handleStatusChange);   // 다음 effect

// 마운트 해제
ChatAPI.unsubscribeToFriendStatus(300, handleStatusChange); // 마지막 effect 정리</code></pre>
<p>반환하지 않는 경우는 이렇게 선언한다.</p>
<pre><code class="language-jsx">useEffect(() =&gt; {
    document.title = `You clicked ${count} times`;
});</code></pre>
<p>만약 effect를 건너뛰고 싶다면 다음과 같이 선언한다. count의 값이 변할 때만 랜더링이 된다. 클래스형 컴포넌트에서 저런 요구사항은 흔하므로, useEffect에 이미 내재되어 있다. 만약 effect 실행과 정리를 마운트와 마운트 해제시에 딱 한번씩만 실행하고 싶다면, 빈 배열을 두 번째 인수로 넘기면 된다.</p>
<pre><code class="language-jsx">useEffect(() =&gt; {
    document.title = `You clicked ${count} times`;
}, [count]);</code></pre>
<pre><code class="language-jsx">componentDidUpdate(prevProps, prevState) {
  if (prevState.count !== this.state.count) {
    document.title = `You clicked ${this.state.count} times`;
  }
}</code></pre>
<h2 id="📚-references">📚 References</h2>
<p><a href="https://ko.reactjs.org/docs/hooks-intro.html">https://ko.reactjs.org/docs/hooks-intro.html</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[FrontEnd] Rendering]]></title>
            <link>https://velog.io/@codename-602/FrontEnd-Rendering</link>
            <guid>https://velog.io/@codename-602/FrontEnd-Rendering</guid>
            <pubDate>Mon, 12 Dec 2022 07:52:31 GMT</pubDate>
            <description><![CDATA[<h2 id="🚩-rendering이란">🚩 Rendering이란?</h2>
<p>서버로부터 html, css, javascript 파일 등을 받아 브라우저에 그래픽 형태로 뿌려주는 작업이다.</p>
<h3 id="중요-랜더링-경로-critical-rendering-path">중요 랜더링 경로 (Critical Rendering Path)</h3>
<p><img src="https://user-images.githubusercontent.com/51533341/206687910-1aa446c8-08f3-4d26-8819-1919a19babc1.png" alt="image"></p>
<p>랜더링 엔진의 동작 과정은 다음과 같이 크게 4단계로 이루어져 있다. 각 단계에서 리소스를 로드하는 순서나 작성한 스크립트의 내용에 따라 웹 페이지의 반응 속도가 달라질 수 있기 때문에 최적화를 하는 것이 중요하다.</p>
<h3 id="①-dom-cssom-생성">① DOM, CSSOM 생성</h3>
<p><img src="https://user-images.githubusercontent.com/51533341/206687982-66c90736-246a-4e06-a116-4db456de3643.png" alt="image"></p>
<p>서버로부터 HTML과 CSS를 받아 Object Model을 생성한다. DOM(Document Object Model)은 우리가 실제로 사용할 수 있는 HTML 요소의 정보가, CSSOM(CSS Object Model)에는 스타일, 규칙, 선택자 등의 정보가 노드에 들어가게 된다.</p>
<h3 id="②-render-tree-생성">② Render Tree 생성</h3>
<p><img src="https://user-images.githubusercontent.com/51533341/206688038-811ee52c-8fa0-47e8-9a10-009c71257abb.png" alt="image"></p>
<p>랜더 트리는 위의 DOM과 CSSOM이 합쳐져서 구성된다. 화면에 나타나는 요소들을 결정하는 트리이며, 화면에 그려지지 않는 요소들은 트리에 나타나지 않는다.</p>
<h3 id="③-layout-또는-reflow">③ Layout 또는 Reflow</h3>
<p>레이아웃 단계에서는 랜더 트리에서 계산되지 않았던 노드들의 크기와 위치, 레이어 간 순서와 같은 정보를 계산하여 좌표에 나타낸다. 이 과정은 HTML의 루트 오브젝트로부터 재귀적으로 실행된다.</p>
<h3 id="④-paint">④ Paint</h3>
<p>페인트 단계는 레이아웃 단계를 통해 화면에 배치된 요소들에 색을 입히고 레이어의 위치를 결정하는 단계이다. 이 단계 역시 루트 오브젝트로부터 재귀적으로 실행된다. z-index가 낮은 순서대로 먼저 페인팅 된다.</p>
<h3 id="⑤-reflow-and-repaint">⑤ Reflow and Repaint</h3>
<p>자바스크립트에 따른 액션과 이벤트 조작이 있을 시, 그에 영향을 받는 자식 노드나 부모 노드를 포함하여 다시 layout 과정을 수행한다. 이 과정이 reflow이며, reflow 뒤에는 repaint도 다시 일어난다. 이것은 서버와 http 통신을 하고 request와 response를 주고 받은 다음 일어나는 과정이다. 많아지는 reflow, repaint로 인한 re-rendering cost를 해소하기 위해 등장한 것이 ajax, jQuery, React, Angular와 같은 라이브러리/프레임워크이다.</p>
<h2 id="🚩-csr-client-side-rendering">🚩 CSR (Client Side Rendering)</h2>
<p><img src="https://user-images.githubusercontent.com/51533341/206989618-1cbca077-449e-463e-b30f-21ffca009952.png" alt="image"></p>
<p>처음 브라우저에서 애플리케이션을 렌더링할 때 비어 있는 html을 응답받고 클라이언트 단에서 자바스크립트를 사용하여 DOM을 조작, 직접 렌더링 하는 것을 의미한다. 서버에서 처리 없이 클라이언트로 보내주기 때문에 자바스크립트가 모두 다운로드 되고 실행이 끝나기 전까지 사용자는 볼 수 있는 것이 없다.</p>
<p>네트워크가 빠를 때, 서버의 성능이 좋지 않을 때, 사용자에게 보여줘야 하는 데이터의 양이 많을 때, 메인 스크립트가 가벼울 때, 웹 어플리케이션에 사용자와 상호작용할 것들이 많을 때 CSR을 사용한다.</p>
<h2 id="🚩-ssr-server-side-rendering">🚩 SSR (Server Side Rendering)</h2>
<p><img src="https://user-images.githubusercontent.com/51533341/206989661-1ed15a2d-fe22-4121-b898-2fe5bffff934.png" alt="image"></p>
<p>브라우저가 서버에 페이지를 요청하면 서버가 기존에 정의된 데이터로 html을 구성하여 브라우저에 응답하고, 브라우저는 이를 그대로 화면에 렌더링하는 방식이다. 서버에서 이미 렌더 가능한 상태로 클라이언트에 전달되기 때문에, 자바스크립트가 다운로드 되는 동안 사용자는 무언가를 보고 있을 수 있다.</p>
<p>네트워크가 느릴 때, 검색 엔진 최적화가 필요할 때, 최초 로딩이 빨라야 하는 사이트를 개발할 때, 메인 스크립트가 크고 로딩이 매우 느릴 때, 웹 사이트가 상호작용이 별로 없을 때 SSR을 사용한다.</p>
<h2 id="🚩-ssg-static-site-generation">🚩 SSG (Static Site Generation)</h2>
<p><img src="https://user-images.githubusercontent.com/51533341/206989747-104cd0d8-058f-4158-b94b-86aa9397f0c3.png" alt="image"></p>
<p>raw 데이터와 템플릿 세트를 바탕으로 완전히 정적인 html 웹 사이트를 생성하는 방법이다. 웹 사이트의 모든 페이지를 미리 렌더링하고 클라이언트의 요청에 따라 페이지를 제공한다. 내용이 거의 변하지 않는 웹사이트인 경우에 SSG를 사용한다.</p>
<h2 id="🚩-isr-incremental-static-regeneration">🚩 ISR (Incremental Static Regeneration)</h2>
<p><img src="https://user-images.githubusercontent.com/51533341/206989784-384083f4-72f7-4137-932e-c06473a3049a.png" alt="image">
전체 사이트를 재빌드할 필요 없이 페이지별로 정적 생성을 한다. 블로그나 개인 웹사이트처럼 콘텐츠가 동적이지만 자주 변경되지 않는 사이트의 경우 ISR을 사용한다.</p>
<h2 id="📚-references">📚 References</h2>
<p><a href="https://yozm.wishket.com/magazine/detail/1338/">https://yozm.wishket.com/magazine/detail/1338/</a></p>
<p><a href="https://velog.io/@jeromecheon/%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C%EB%9D%BC%EB%A9%B4-%EB%B0%98%EB%93%9C%EC%8B%9C-%EC%95%8C%EC%95%84%EC%95%BC-%ED%95%A0-Rendering%EA%B3%BC-%EC%84%B8%EA%B0%80%EC%A7%80-%EA%B0%9C%EB%85%90-CSR-SSR-SSG">https://velog.io/@jeromecheon/프론트엔드라면-반드시-알아야-할-Rendering과-세가지-개념-CSR-SSR-SSG</a></p>
<p><a href="https://proglish.tistory.com/216">https://proglish.tistory.com/216</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JavaScript] Function]]></title>
            <link>https://velog.io/@codename-602/JavaScript-Function</link>
            <guid>https://velog.io/@codename-602/JavaScript-Function</guid>
            <pubDate>Thu, 08 Dec 2022 13:51:50 GMT</pubDate>
            <description><![CDATA[<h2 id="🖨️-함수-선언식-function-declarations">🖨️ 함수 선언식 (Function Declarations)</h2>
<p>일반적인 프로그래밍 언어에서의 함수 선언과 비슷한 형식</p>
<p>함수명이 정의되어 있고, 별도의 할당 명령이 없다.</p>
<pre><code class="language-jsx">function func() {
    ...
}</code></pre>
<h2 id="🖨️-함수-표현식-function-expressions">🖨️ 함수 표현식 (Function Expressions)</h2>
<p>유연한 자바스크립트 언어의 특징을 활용한 선언 방식</p>
<p>정의한 function을 별도의 변수에 할당한다.</p>
<pre><code class="language-jsx">const func = function () {
    ...
};</code></pre>
<h2 id="🖨️-함수-선언식-vs-함수-표현식">🖨️ 함수 선언식 vs 함수 표현식</h2>
<p><em>함수 선언식은 호이스팅에 영향을 받지만, 함수 표현식은 호이스팅에 영향을 받지 않음</em></p>
<p>함수 선언식은 함수 전체를 호이스팅하며, 정의된 범위의 맨 위로 호이스팅 되서 선언 전에 함수를 사용할 수 있다. 반면 함수 표현식은 별도의 변수에 할당하게 되어서 변수의 선언부만 호이스팅하게 된다.</p>
<pre><code class="language-jsx">sum(50, 50);   // 100
minus(50, 50); // Uncaught TypeError: minus is not a function

// 함수 선언식
function sum(a, b) {
    return a + b;
}

// 함수 표현식
var minus = function(a, b) {
    return a - b;
}</code></pre>
<p>위의 코드에서 호이스팅이 마치게 되면 다음과 같이 표현된다.</p>
<pre><code class="language-jsx">// 함수 표현식
function sum(a, b) {
    return a + b;
}

// 함수 표현식: 선언부 호이스팅
var minus;

sum(50, 50);   // 100
minus(50, 50); // Uncaught TypeError: minus is not a function

// 함수 표현식: 할당부
function (a, b) {
    return a - b;
}</code></pre>
<p>함수 표현식을  코드를 호출하는 부분 위에 작성하면 에러 없이 정상적으로 출력된다. 함수 선언식으로 작성한 함수는 함수 전체가 호이스팅 되기 때문에 전역적으로 선언 시 중복적으로 동명의 함수를 쓰게 될 때 원치 않는 결과가 나올 수 있다. 따라서 함수 표현식으로 작성하여 이를 방지하는 것이 좋다.</p>
<h2 id="🖨️-화살표-함수">🖨️ 화살표 함수</h2>
<p>자바스크립트는 함수를 1급 객체로 취급하고 값으로 대입 가능하기 때문에 함수의 인자값으로 함수를 넘긴다. 그리고 함수 내부에서 그 인자값으로 들어온 함수를 호출하는 <strong>콜백 함수</strong>를 코드 작성 시에 자주 이용하기 때문에 함수를 작성해야 할 일이 많다. 특히 콜백 함수를 인자값으로 넘길 때는 한 번만 사용될 것이기 때문에 익명함수를 작성해야 하는데, 그 익명함수를 간단하게 작성하도록 해주는 것이 화살표 함수이다.</p>
<pre><code class="language-jsx">const add = function (a, b) {
    return a+b;
}

// 화살표 함수로 축약
const add = (a, b) =&gt; a+b;</code></pre>
<p>화살표 함수와 일반 함수의 큰 차이점은 this이다.</p>
<p>일반 함수의 this는 함수가 쓰인 위치에 따라서 내부의 this값이 변하지만 화살표 함수는 어디에서든지 this값을 변화시키지 않는다. 화살표 함수에서의 this는 자기가 정의된 스코프에 존재하는 this를 가르킨다. 그렇기 때문에 객체의 메소드를 화살표 함수로 정의하면 자신의 상위에 있는 스코프의 this를 가르키기 때문에 처음부터 this가 window이다.</p>
<pre><code class="language-jsx">var obj1 = {
    name: &#39;obj1&#39;,
    func1 : function(){ console.log(this.name) }
}
var obj2 = {
    name: &#39;obj2&#39;,
    func2 : () =&gt; console.log(this.name) 
}

obj1.func1();  // obj1
obj2.func2();  // undefined</code></pre>
<p>따라서 화살표 함수는 일반 함수를 대체할 수 있는 문법이 아니다.</p>
<h2 id="📚-references">📚 References</h2>
<p><a href="https://joshua1988.github.io/web-development/javascript/function-expressions-vs-declarations/">https://joshua1988.github.io/web-development/javascript/function-expressions-vs-declarations/</a>
<a href="https://taenami.tistory.com/86">https://taenami.tistory.com/86</a>
<a href="https://pgh268400.tistory.com/490">https://pgh268400.tistory.com/490</a>
<a href="https://sangjuntech.tistory.com/24">https://sangjuntech.tistory.com/24</a>
<a href="https://codingapple.com/unit/es6-3-arrow-function-why/">https://codingapple.com/unit/es6-3-arrow-function-why/</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JavaScript] var, let, const]]></title>
            <link>https://velog.io/@codename-602/JavaScript-var-let-const</link>
            <guid>https://velog.io/@codename-602/JavaScript-var-let-const</guid>
            <pubDate>Wed, 30 Nov 2022 15:05:51 GMT</pubDate>
            <description><![CDATA[<p>학부 3학년 때 친구들과 모여서 웹 프로그래밍 과목의 과제를 하던 중이였다. 친구 두 명이 let과 const 중 어떤 걸로 변수를 선언해야 하는지 토론하고 있었다. 그저 과제를 완성하기 급급했던 나는 한 마디를 던졌다. </p>
<p>&quot;그냥 var 쓰면 되지 않나?&quot;</p>
<p>그러자 의견이 좁혀지지 않던 친구들의 의견이 하나로 좁혀졌다. </p>
<p>&quot;야! var는 그냥 생각하기 싫을 때 쓰는거야~&quot;</p>
<p>진짜 생각하기 싫었던 나는 그냥 var를 써서 과제를 제출했고, 그 시절의 일화가 생각나서 작성해보는 오늘의 TIL 컨텐츠는 var, let, const 완전 정복이다.
<br><br></p>
<h2 id="🌼-변수의-생성-과정">🌼 변수의 생성 과정</h2>
<p><strong>① 선언 단계(Declaration phase)</strong> : 변수 객체에 변수를 등록함</p>
<p><strong>② 초기화 단계(Initialization phase)</strong> : 변수 객체에 등록된 변수를 메모리에 할당함. 이 단계에서 undefined로 초기화됨.</p>
<p><strong>③ 할당 단계(Assignment phase)</strong> : undefined로 초기화된 변수에 실제값을 할당함
<br></p>
<h2 id="🌼-var">🌼 var</h2>
<p>ES5까지는 변수를 var 키워드로만 선언을 할 수 있었다. var의 특징은 함수 레벨 스코프, var 키워드 생략 가능, 변수 중복 선언 허용, 변수 호이스팅이 가능하다.</p>
<h3 id="함수-레벨-스코프">함수 레벨 스코프</h3>
<p>함수의 코드 블록만을 스코프로 인정한다. 따라서 전역 함수 외부에서 생성된 변수는 모두 전역 변수이다. for문의 변수 선언문에서 선언한 변수를 for문 바깥에서 참조할 수 있다.</p>
<h3 id="호이스팅">호이스팅</h3>
<p>호이스팅이란 모든 선언문이 해당 스코프의 선두로 옮겨진 것처럼 동작하는 특성이다. 따라서 자바스크립트는 모든 선언문이 선언되기 이전에 참조가 가능하다. 그렇기 때문에 다음과 같은 코드에서 undefined를 출력한다.</p>
<pre><code class="language-jsx">console.log(foo); // ReferenceError를 예상하지만 undefined가 출력됨
var foo = 123;</code></pre>
<p>var 키워드로 선언된 변수는 선언 단계와 초기화 단계가 한번에 이루어진다. 따라서 변수 선언문 이전에 변수에 접근하여도 변수객체에 변수가 존재하기 때문에 에러가 발생하지는 않지만 undefined를 반환한다.</p>
<h3 id="전역-객체와-var">전역 객체와 var</h3>
<p>전역 객체(global object)는 모든 객체의 유일한 최상위 객체를 의미하며 일반적으로 brower-side에서는 window 객체, server-side(Node.js)에서는 global 객체를 의미한다. var키워드로 선언된 변수를 전역 변수로 사용하면 전역 객체의 프로퍼티가 된다.</p>
<pre><code class="language-jsx">var foo = 123; // 전역 변수
console.log(window.foo); // 123</code></pre>
<p>유효 범위가 넓어서 사용이 편리하다는 장점이 있지만, 유효범위가 넓기에 어디에서 어떻게 사용될 것인지 파악하기 힘들며 의도치 않게 변경될수도 있기 때문에 복잡성을 증가시킨다. 따라서 변수의 스코프는 좁을수록 좋다. 이러한 var의 단점을 보완하기 위해서 ES6에서는 let과 const 키워드를 도입했다.
<br></p>
<h2 id="🌼-let">🌼 let</h2>
<p>대부분의 프로그래밍 언어는 블록 레벨 스코프를 따르지만 자바스크립트는 함수 레벨 스코프를 따른다. ES6는 블록 레벨 스코프를 따르는 변수를 선언하기 위해 let 키워드를 제공한다.</p>
<h3 id="블록-레벨-스코프">블록 레벨 스코프</h3>
<p>모든 코드 블록 내에서 선언된 변수는 코드 블록 내에서만 유효하며 코드 블록 외부에서는 참조할 수 없다. 즉, 코드 블록 내부에서 선언된 변수는 지역 변수이다.</p>
<pre><code class="language-jsx">let foo = 123; // 전역 변수
{
    let foo = 456; // 지역 변수
    let bar = 456; // 지역 변수
}
console.log(foo); // 1234
console.log(bar); // ReferenceError: bar is not defined</code></pre>
<h3 id="호이스팅-1">호이스팅</h3>
<p>let 키워드로 선언된 변수는 선언문 이전에 참조하면 참조 에러가 발생한다. 스코프의 시작에서 변수의 선언까지 일시적 사각지대(Temporal Dead Zone; TDZ)에 빠지기 때문이다. 또한 선언 단계와 초기화 단계가 분리되어 진행되므로, 초기화 이전에 변수에 접근하려고 하면 참조 에러가 발생한다.</p>
<pre><code class="language-jsx">console.log(foo); // ReferenceError: foo is not defined

let foo; // 변수 선언에서 초기화가 됨
console.log(foo); // undefined

foo = 1; // 할당문에서 할당 단계가 실행
console.log(foo); // 1</code></pre>
<pre><code class="language-jsx">let foo = 1; // 전역 변수
{
    console.log(foo); // ReferenceError: foo is not defined
    let foo = 2; // 지역 변수
}</code></pre>
<h3 id="전역-객체와-let">전역 객체와 let</h3>
<p>let 키워드로 선언된 변수를 전역 변수로 사용하는 경우, let 전역 변수는 전역 객체의 프로퍼티가 아니다. 즉, window.foo와 같이 접근할 수 없다. let 전역 변수는 보이지 않는 개념적인 블록 내에 존재하게 된다.</p>
<pre><code class="language-jsx">let foo = 123; // 전역 변수
console.log(window.foo); // undefined</code></pre>
<br>

<h2 id="🌼-const">🌼 const</h2>
<p>const는 상수를 위해 사용한다. 하지만 반드시 상수만을 위해 사용하지는 않는다. const의 특징은 let과 거의 동일하지만 const 고유의 특징들은 다음과 같다.</p>
<h3 id="선언과-초기화">선언과 초기화</h3>
<p>const는 반드시 선언과 동시에 할당이 이루어져야한다. 그렇지 않으면 문법 에러가 발생한다. 재할당이 금지되고, 재할당을 하게 되면 타입 에러가 발생한다.</p>
<pre><code class="language-jsx">const FOO = 123;
FOO = 456; // TypeError: Assignment to constant variable

const BAR; // SyntaxError: Missing initializer in const declaration

{
    const FOOBAR = 10;
    console.log(FOOBAR); // 10
}
console.log(FOOBAR); // ReferenceError: FOOBAR is not defined</code></pre>
<h3 id="const와-객체">const와 객체</h3>
<p>const 변수의 타입이 객체일 경우, 객체에 대한 참조를 변경하지 못한다. 하지만 이때 객체의 속성은 보호되지 않는다. 따라서 재할당은 불가능하지만 할당된 객체의 내용(프로퍼티의 추가, 삭제, 변경)은 변경가능하다. 객체의 내용이 변경되더라도 객체 타입 변수에 할당된 주소값은 변경되지 않기 때문에 객체 타입 변수 선언에는 const를 사용하는 것이 좋다. </p>
<pre><code class="language-jsx">const user = { name: &#39;Lee&#39; };
user.name = &#39;Kim&#39;;
console.log(user); // { name: &#39;Kim&#39; }</code></pre>
<br>

<h2 id="📚-references">📚 References</h2>
<p><a href="https://poiemaweb.com/es6-block-scope">https://poiemaweb.com/es6-block-scope</a>
<a href="https://poiemaweb.com/js-data-type-variable#24-%EB%B3%80%EC%88%98-%ED%98%B8%EC%9D%B4%EC%8A%A4%ED%8C%85variable-hoisting">https://poiemaweb.com/js-data-type-variable#24-변수-호이스팅variable-hoisting</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[🎬 Movie In Memory]]></title>
            <link>https://velog.io/@codename-602/%EC%9A%B0%EB%8B%B9%ED%83%95%ED%83%95FE-2022-02</link>
            <guid>https://velog.io/@codename-602/%EC%9A%B0%EB%8B%B9%ED%83%95%ED%83%95FE-2022-02</guid>
            <pubDate>Wed, 30 Nov 2022 14:21:02 GMT</pubDate>
            <description><![CDATA[<h2 id="📜-프로젝트-소개">📜 프로젝트 소개</h2>
<blockquote>
<h5 id="기간--202203202206-약-3개월-반">기간 : 2022.03~2022.06 (약 3개월 반)</h5>
<h5 id="인원--4명-프론트엔드-1명-백엔드-3명-api-자연어-모델-캡셔닝-모델">인원 : 4명 (프론트엔드 1명, 백엔드 3명: API, 자연어 모델, 캡셔닝 모델)</h5>
<h5 id="주제--넷플릭스-영화-문장-질의-서비스-및-커뮤니티">주제 : 넷플릭스 영화 문장 질의 서비스 및 커뮤니티</h5>
<h5 id="나의-기여--사이트-디자인-웹-퍼블리싱-프론트엔드-구현">나의 기여 : 사이트 디자인, 웹 퍼블리싱, 프론트엔드 구현</h5>
<h5 id="사용-스택---reactjs-javascript">사용 스택 :  React.js, Javascript</h5>
</blockquote>
<p>학부에서의 마지막 전공필수 수업에 진행한 팀 프로젝트이다. 처음으로 피그마와 리액트를 사용해 본 프로젝트!</p>
<h3 id="🤩-첫-피그마-그리고-손그림과의-이별">🤩 첫 피그마! 그리고 손그림과의 이별</h3>
<p>처음에는 &#39;Samsung Galaxy Book Flex Alpha&#39; 유저답게 손그림으로 설계를 했었다. 하지만 이제 데이터의 한계상 도메인을 영화로 한정하고 프로젝트의 취지가 바뀌면서 달라진 UI를 피그마에 표현했다. 수정하면서 문서화를 해야했기 때문에 기존의 러프한 손그림 설계를 figma로 옮기게 되었다. 피그마에서 내가 제일 좋아하는 기능은 그룹화이다. 그룹화를 함으로써 마크업이 설계과정에서도 모양이 대강 잡히는 점이 매력적인 것 같다. 컴포넌트 분리 덕후로서 &#39;컴포넌트를 이렇게 구성해야겠다&#39; 하는 것들이 보여서 너무 설렜고, 결과물이 깔끔하게 만들어지는 점이 마음에 들어서 나는 이 이후로 UI설계를 피그마로 진행하게 되었다. 밑의 사진들을 보면은 확실히 피그마가 깔끔하게 만들어진다.
<img src="https://velog.velcdn.com/images/codename-602/post/6dd00601-122e-4fa1-a497-94f95342d225/image.png" alt="">
<img src="https://velog.velcdn.com/images/codename-602/post/c4464733-3a8a-4fe8-8685-70d04cd942d0/image.png" alt=""></p>
<br>

<h3 id="🤩-첫-리액트">🤩 첫 리액트!</h3>
<p>이번에는 첫 프로젝트였었던 가족회사 플랫폼 구축 프로젝트와 다르게 리액트를 사용했다. 프론트엔드에 관심이 생기면서 당연히 가장 인기가 많은 리액트에도 관심이 생겼다. 리액트는 내가 프론트엔드에 도전하기 전부터 이름을 들어서 익히 알고 있었던 라이브러리인데, 정확히 어떤 것인지는 알지 못했다. 그래서 이번에도 직접 부딪혀보면서 익힌 것 같다. 지금와서 생각해보면 익혔다고 말하기에도 민망한 수준으로 미흡하긴 하다. 일단 리액트로도 마크업 하듯이 진행했다. 리액트를 사용하지 않을 때와 다른 점이 없었다. 그렇게 마크업을 다 하고나서 문제는 발생했다...</p>
<br>

<h3 id="😶🌫️-첫-리액트">😶‍🌫️ 첫 리액트...?</h3>
<p>마크업을 다 하면 API 연동을 해야한다. 리액트 같은 경우에는 3000포트로 새롭게 서버가 열리기에 백엔드 API 서버와 연동을 하려면 proxy를 추가하고 API로 데이터를 불러와서 사용하면 된다. 저번 프로젝트에서는 html 파일 안에 script 태그를 넣어서 그 안에서 ajax 요청을 하였다. 지난 프로젝트때도 생각을 했었던 부분이지만 html 코드마다 넣기엔 너무 코드가 지저분했다. 그리고 컴포넌트 내에서 script 태그를 사용하기에도 좀 이상했다. 컴포넌트 자체가 js라서 스크립트인데, 또 script 태그를 사용한다고? 싶었다. 그리고 어찌저찌 진행해도 데이터 랜더링부분에서 문제가 발생했다. 무한 get 요청이 보내졌고, 이걸 막고자 async await를 넣었는데 promise 객체로 넘어와서 데이터가 pending 상태였다. 게다가 처음으로 리액트를 다뤄보는 거라서 구글링을 하면서 개발을 진행했는데 설명한 블로그에 따라 어떤 건 함수형 컴포넌트, 어떤 건 클래스형 컴포넌트로 선언되는 등 통일성이 없었다. 아주 산 넘어 산이였다.
<br></p>
<h3 id="👯♀️-고마운-친구">👯‍♀️ 고마운 친구</h3>
<p>이런 어려움에 처했을 때 내가 도움을 요청했던 건, 리액트를 여러 번 다뤄 본 동기 친구였다. 친구도 전공필수 팀프로젝트를 하고 있어서 바쁜데도 불구하고 나를 도와주었다. 이 친구는 내가 위에서 서술했었던 리액트에서 API 통신을 깔끔하게 하는 법을 알려주었다. 각 API를 이용하는 부분을 함수로 만들어서 모듈화를 한 후, 불러오는 방식이였다. 자바스크립트를 능동적으로 활용하지 못한 나는 모듈화라는 방식을 미처 생각하지 못한 것이었다. 친구가 알려준 이 아이디어는 나에게 큰 깨달음으로 다가왔고, 이 아이디어를 응용하여 앞으로의 개발에서도 axios 객체, 쿠키, util 등을 모듈화하여 조금이나마 똑똑하게 자바스크립트를 사용하게 되었다. 바쁜 와중에도 자기 일처럼 도와주고 같은 직군으로서 고민도 들어주는 친구한테 너무 고마웠다.</p>
<br>

<h3 id="👍-팀장님한테-한-수-배우다">👍 팀장님한테 한 수 배우다</h3>
<p>저번 프로젝트도 그렇고 팀 프로젝트를 하게 되면 같은 팀 동료에게서 배워가는 것이 많은 것 같다. 이번에는 API를 개발하는 백엔드(팀장이었음)와 페어로 작업을 주로 했었는데, swagger로 API 문서를 작성한 후 배포하여 나는 그것을 보고 작업하였다. 데이터를 불러오는 부분에서 API를 여러 번 호출해서 데이터를 패치해도 되는데, 나는 저 생각을 미처 못하고 한 번에 데이터가 다 오도록 요청을 했다. 기껏 백엔드 쪽에서 프론트 쪽을 생각하며 API를 설계했는데 계속해서 번복하니 이런 내가 괘씸했을 것 같다. 이런 나의 요구가 반복되니까 지금은 내가 프론트엔드가 거의 처음이니 이렇게 해 주지만 앞으로는 주어진 API 내에서 활용하여 쓰는 연습을 해 보라고 조언을 해주셨다. 그 조언으로 API를 수동적으로만 따라갔었던 나의 태도를 반성하고 능동적으로 API를 활용해보게 되었다.
그리고 커뮤니티 기능이 들어가다 보니까 프론트엔드의 작업량이 많았는데, 팀장님이 진도 체크를 하고 내가 좀 빡세 보이니까 범위를 조정했다. 본인이 프론트엔드를 어느 정도 다룰 수 있었기에 일부 기능을 구현해주셨다. 이를 통해 팀장의 역할과 리더십을 배웠고, 타인의 컴포넌트 분리와 데이터 패치, props 활용을 보면서 또 한 수 배워갔다. 원래 오류는 남이 더 잘 찾는다고 하던가. 반나절 동안 막혔었던 부분도 발견해주셔서 해결할 수 있었다. 그렇게 나는 종교가 생겼다. 우리 팀장님 만만세!</p>
<br>

<h3 id="🫂-이것이-team">🫂 이것이 &#39;Team&#39;...?</h3>
<p>팀장 뿐만 아니라 다른 팀원들에게도 고마운 점이 많다. 이 프로젝트가 전공 프로젝트였기 때문에 개발 단계별로 발표를 해야 했다. 그 중 최종 발표는 이 프로젝트의 다양한 시행착오들과 사용한 기술을 소개하고 데모까지 진행해야 했기 때문에 꽤 중요한 발표였다. 그 중요한 발표를 내가 하게 되었다. 딥러닝을 사용하는 프로젝트의 세부 로직에서 벗어난 프론트엔드 작업만을 했었기 때문에 준비가 막막하였지만 팀원들은 이런 나를 위해 특강을 열어줬다. A부터 Z까지 다 알려줬고, 모르거나 헷갈리는 부분도 내가 궁금증이 해소될 때까지 다 알려주셨다. 덕분에 발표 준비를 잘 할 수 있었고, 질의응답도 잘 해쳐나갈 수 있었다. 결과 또한 좋게 나왔다. 별 탈 없이 발표를 진행하고 프로젝트를 잘 마무리한 것이 팀원들 덕분인 것 같아서 나는 우리 팀원들한테 너무 고맙다.</p>
<br>

<h3 id="😍-프론트엔드의-매력을-알게-되다">😍 프론트엔드의 매력을 알게 되다</h3>
<p>조언대로 API를 능동적으로 사용하다보니 프론트엔드가 재미있었다. 처음에는 마크업만 재밌었던 나라면 이제는 API로 백엔드를 사용하는 게 제일 재밌다. 나는 프론트엔드가 재밌어졌다. 프론트엔드 공부를 하면서 생기는 물음표가 느낌표로 변하는 순간들이 너무 짜릿하다. 아직 부족한 부분이 많지만 그만큼 느낌표로 변할 물음표가 많다고 생각하니 하루하루가 설레기 시작했다. 열심히 공부해서 꼭 멋진 프론트엔드 개발자가 되야지!
<br></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[👩‍👧‍👧 가족회사 플랫폼]]></title>
            <link>https://velog.io/@codename-602/%EC%9A%B0%EB%8B%B9%ED%83%95%ED%83%95FE-2022-01</link>
            <guid>https://velog.io/@codename-602/%EC%9A%B0%EB%8B%B9%ED%83%95%ED%83%95FE-2022-01</guid>
            <pubDate>Mon, 21 Nov 2022 05:56:31 GMT</pubDate>
            <description><![CDATA[<h2 id="📜-프로젝트-소개">📜 프로젝트 소개</h2>
<blockquote>
<h5 id="기간--202201202202-약-2개월">기간 : 2022.01~2022.02 (약 2개월)</h5>
<h5 id="인원--4명-프론트엔드-2명-백엔드-2명">인원 : 4명 (프론트엔드 2명, 백엔드 2명)</h5>
<h5 id="주제--학교랑-협력하는-회사와-진행하는-프로젝트를-관리하는-시스템-구축">주제 : 학교랑 협력하는 회사와 진행하는 프로젝트를 관리하는 시스템 구축</h5>
<h5 id="나의-기여--사이트-디자인-웹-퍼블리싱-일부-기능회원-관리-회사-관리-프론트엔드-구현">나의 기여 : 사이트 디자인, 웹 퍼블리싱, 일부 기능(회원 관리, 회사 관리) 프론트엔드 구현</h5>
<h5 id="사용-스택---html-css-javascript-jquery-thymeleaf-bootstrap">사용 스택 :  HTML, CSS, JavaScript, jQuery, thymeleaf, bootstrap</h5>
</blockquote>
<p>처음으로 프론트엔드로서 참여하게 된 프로젝트이다. 모자란 부분이 많았지만 교수님과 동료들의 당근과 채찍으로 잘 헤쳐나갈 수 있었다!</p>
<br>

<h3 id="🎨-디자인의-즐거움을-알다">🎨 디자인의 즐거움을 알다</h3>
<p>평소 낙서를 끄적이는 것을 좋아했던 나는, 디자인 툴이 있었지만 직접 손으로 그려서 UI를 설계하였다. 나는 &#39;Samsung Galaxy Book Flex Alpha&#39; 유저였기 때문에 노트북을 태블릿처럼 사용할 수 있었다. 밑의 사진 두 장은 그 때 당시 나의 설계이다.
<img src="https://velog.velcdn.com/images/codename-602/post/b8d744ad-acad-4d4e-be5c-8255c26cf820/image.png" alt=""><img src="https://velog.velcdn.com/images/codename-602/post/991806c4-f687-4c16-8ee7-30051a870cd9/image.png" alt=""></p>
<p>이와 같이 손그림으로 UI 설계를 진행하였는데 현재 Figma를 유용하게 사용하는 지금에서야 보니 너무 가독성이 좋지 않게 설계한 것 같다. 당시 이 설계를 프로젝트를 진행하시던 교수님한테 보여드렸는데, 화 한 번 안 내시고 잘했다고 칭찬해주셔서 기 죽지 않고 지금까지 프론트엔드를 하고 있는 것 같아서 교수님께 감사하다. 교수님은 디자인이 마음에 드셨는지 반려하지 않고 설계 문서에 저 그림들을 삽입하셨고, 내 지도교수님께도 칭찬을 하셔서 두 배로 칭찬을 받았다. 칭찬은 고래도 춤추게 한다고 하던가. 교수님과 여러 번 미팅을 가져가면서 의욕적으로 UI를 설계하였고, 피드백을 받으며 개선되는 디자인을 보니 뿌듯하고 즐거웠다. 
<br></p>
<h3 id="🤓-jquery와-thymeleaf를-사용해보다">🤓 jQuery와 thymeleaf를 사용해보다</h3>
<p>jQuery는 $로 엘리먼트를 찾아서 조작할 수 있게 해주는 자바스크립트 라이브러리이다. 이 때까지만 해도 나는 바닐라 자바스크립트만 이용했었기 때문에 jQuery가 매우 신선했다. 처음 다뤄보는 기술이라 도서관에서 책을 빌려서 이해가 되지 않는 부분은 예시를 동작시켜보면서 공부했다. 바닐라 자바스크립트보다 jQuery를 이용했을 때 코드 가독성이 좋아서 마음에 들었다.</p>
<p>thymeleaf는 학부 3학년 때 다뤘었던 jsp에서의 jstl과 유사하다고 느꼈다. 그런데 이제 문법이 처음이다보니 구글링을 해가면서 다뤄보았다. thymeleaf에서 fragment로 나누어서 구현하고 조각을 합치는 것이 인상 깊었다. 이 때부터 컴포넌트 분리에 매력을 느끼게 된 것 같다. 그리고 컨트롤러에서 데이터를 바로 받아서 적용을 한다는 것도 매력적인 것 같다.</p>
<br>


<h3 id="🙇♀️-고마운-동료">🙇‍♀️ 고마운 동료</h3>
<p>이 프로젝트는 관심사를 두 개로 분리하여 각각 백엔드와 프론트엔드를 1명씩 배정하여 진행해였다. 나와 백엔드 1명이 회원 관리 및 가족회사 관리를 담당하였고, 다른 프론트엔드와 백엔드는 산학 협력 관리 및 메인 화면을 담당하였다. </p>
<p>이 시절 나라는 사람은 웹에 관련해서 정말 무지했고, 협업이 참 힘든 프론트엔드 개발자였다. API 문서를 보고 개발을 진행해도 오타가 나서 연결이 안되는 것은 물론, 데이터를 주고 받는 원리도 몰랐고 개발 속도도 느렸기에 나랑 페어였던 백엔드 개발자분이 많이 답답해하셨다. </p>
<p>거의 초면이고 잘 모르는 사람한테 충고나 조언을 하는 것이 힘들 수도 있는데, 나한테 기꺼이 문제점을 말씀을 해주셔서 문제점을 알고 개선할 수 있었다. 처음에는 이런 말을 들으면 나의 부족함이 너무 잘 느껴져서 허탈하고 속상했지만 이 분이 나에게 쌓인 불만을 표출하지 않고 속으로 삭히셨다면 개선이 없었을 것 같다. 너무 상대에게 민폐를 끼친 것 같아서 미팅 때 그 분에게 죄송하다고 했지만 미안해하지 않아도 된다고 말해주셔서 오히려 나는 감사했다. 원래는 부정적인 피드백을 받으면 나의 모자람이라고 생각하고 위축이 드는 편이였지만, 이 경험 이후로는 나를 변화시킬 절호의 기회라고 생각하여 신이 났다.</p>
<br>

<h3 id="🪜-웹-퍼블리셔와-프론트엔드-그-사이">🪜 웹 퍼블리셔와 프론트엔드 그 사이</h3>
<p>이때까지만 해도 웹 퍼블리싱에는 자신이 있었지만 프론트엔드 역할에는 자신이 없었다. 교수님께서 나에게 이 프로젝트에서 프론트엔드를 제안하셨던 것도 웹 퍼블리싱이 인상 깊어서였고, 디자인이 즐거웠고 그 때 당시 프론트엔드로서의 한계점이 있는 인력이였기에 프론트엔드 개발자를 할 수 있을지 스스로 의문이 들었다. 그래도 한계점을 알게 된 이상, 그것을 극복하고 싶어져서 더 악착같이 프론트엔드 개발자가 되고 싶었다. 멋진 프론트엔드 개발자가 되기 위해 계속해서 노력할 것이다!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[📜 예비 프론트엔드 개발자의 기록]]></title>
            <link>https://velog.io/@codename-602/%EC%9A%B0%EB%8B%B9%ED%83%95%ED%83%95FE</link>
            <guid>https://velog.io/@codename-602/%EC%9A%B0%EB%8B%B9%ED%83%95%ED%83%95FE</guid>
            <pubDate>Tue, 15 Nov 2022 00:45:14 GMT</pubDate>
            <description><![CDATA[<p>이 시리즈에서는 내가 프론트엔드로서 진행하였던 프로젝트를 소개하면서 배웠던 점과 느꼈던 점들을 적어볼까 한다. </p>
<h2 id="📂-2022">📂 2022</h2>
<p> 내가 프론트엔드 분야를 접한 지도 어느새 1년이 다 되어간다. 학부 생활 3년을 하면서 프론트엔드 쪽 개발을 다뤄보지 않은 것 같아서 마지막 학년인 4학년이 되고서야 도전한 분야였다. 짧다면 짧고 길다면 긴 1년이란 시간동안 나는 많은 것을 배워갔고, 앞으로도 접하고 배울 것이 가득하다. 시작 계기는 사소하다 말할 수 있어도 여러 프로젝트를 진행하면서 이 설렘 가득한 분야의 매력에 흠뻑 빠져버렸다.</p>
<h3><a href="https://velog.io/@codename-602/%EC%9A%B0%EB%8B%B9%ED%83%95%ED%83%95FE-2022-01">
  👩‍👧‍👧 가족회사 플랫폼
</a></h3>
<h3><a href="https://velog.io/@codename-602/%EC%9A%B0%EB%8B%B9%ED%83%95%ED%83%95FE-2022-02">
  🎬 Movie In Memory
</a></h3>
<h3><a href="https://velog.io/@codename-602/%EC%9A%B0%EB%8B%B9%ED%83%95%ED%83%95FE-2022-03">
  🍱 한솥도시락 클론코딩
</a></h3>
<h3><a href="https://velog.io/@codename-602/%EC%9A%B0%EB%8B%B9%ED%83%95%ED%83%95FE-2022-04">
 👍 GtOdOD
</a></h3>
<h3><a href="https://velog.io/@codename-602/%EC%9A%B0%EB%8B%B9%ED%83%95%ED%83%95FE-2022-05">
 🚌 까마귀버스
</a></h3>
<h3><a href="https://velog.io/@codename-602/%EC%9A%B0%EB%8B%B9%ED%83%95%ED%83%95FE-2022-06">
 💧 공개水배
</a></h3>

<hr>

<h2 id="📂-2023">📂 2023</h2>
<h3>
🕹️ 테트리스
</h3>
<h3>
👍 GtOdOD ver.2
</h3>
<h3>
⚾ WindUp ver.2
</h3>
<h3>
🔥 SIXZERO
</h3>


]]></description>
        </item>
    </channel>
</rss>