<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>lee_geon_woo4336.log</title>
        <link>https://velog.io/</link>
        <description>주니어 개발자 이건우 입니다 .</description>
        <lastBuildDate>Thu, 25 Sep 2025 02:34:49 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>lee_geon_woo4336.log</title>
            <url>https://images.velog.io/images/lee_geon_woo4336/profile/0d52357a-f8ff-482b-bb66-f4672d8bfff4/social.jpeg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. lee_geon_woo4336.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/lee_geon_woo4336" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[NNZZ 사이드 프로젝트(1)]]></title>
            <link>https://velog.io/@lee_geon_woo4336/NNZZ-%EC%82%AC%EC%9D%B4%EB%93%9C-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B81</link>
            <guid>https://velog.io/@lee_geon_woo4336/NNZZ-%EC%82%AC%EC%9D%B4%EB%93%9C-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B81</guid>
            <pubDate>Thu, 25 Sep 2025 02:34:49 GMT</pubDate>
            <description><![CDATA[<p><strong>작년 8월 14일부터 시작해서 1년이 넘는 시간 동안 진행한 사이드 프로젝트에 대한 회고(아직 ~ing)를 시작합니다.</strong></p>
<blockquote>
<p>현재 웹 버전은 완성되어 유지보수를 진행하고 있고, 이제 앱으로 포팅을 준비하는 단계에서 그동안의 여정을 정리해보고자 합니다.</p>
</blockquote>
<h4 id="사이드-프로젝트를-시작한-계기">사이드 프로젝트를 시작한 계기</h4>
<p>2024년 08월 12일 지인의 제안으로 시작된 사이드 프로젝트, 지인의 놀라운 섭외력으로 우린 스타트업과 맞먹는 인재들이 모였습니다 .</p>
<p>구성원으로는 프론트엔드 개발자(나), 백엔드 개발자, 기획자, 프로덕트 디자이너, 3D 에셋 디자이너, 마케터로 구성되었고 추진력 좋은 기획자가 모두를 모아 어떤 사이드 프로젝트를 할 것 이란 이야기와 프로젝트 논의를 시작했습니다</p>
<h1 id="1팀-규칙">1.팀 규칙</h1>
<h3 id="정기회의일">정기회의일</h3>
<p><strong>주 2회</strong></p>
<ul>
<li>수요일 **시</li>
<li>일요일 **시</li>
</ul>
<h3 id="규칙">규칙</h3>
<ul>
<li>당일 불참시 공금에 5천원씩 입금</li>
<li>맘 상하면 아무말 대잔치에 남기기</li>
</ul>
<h1 id="2-프로젝트-선정">2. 프로젝트 선정</h1>
<p>회의 결과 우리 모두 직장인이고 매일매일 하는 고민을 해결 하고 싶어 했습니다</p>
<h3 id="문제-정의">문제 정의</h3>
<ul>
<li>직장인들은 한정된 점심시간을 점심 메뉴를 고민하는데에 낭비하고 있음<ul>
<li>매번 가는 곳만 가게 됨</li>
<li>오늘 고민한다고 해서 내일 안해도 되는 고민이 아님</li>
<li>그렇다고 매번 똑같은 건 먹고 싶지 않음<h3 id="타겟">타겟</h3>
</li>
</ul>
</li>
</ul>
<p>점심을 주로 <strong>밖에서 사먹지만</strong> <strong>매번 똑같은 식당에 가기는 싫은</strong> <strong>직장인</strong></p>
<h3 id="mvp-범위">MVP 범위</h3>
<ul>
<li><strong>지도 범위 : 강남역 역삼역 부근</strong></li>
<li><strong>식당리스트 : (평일 점심에 운영하는) 식당</strong></li>
<li><strong>타겟 : 강남역 역삼역 부근에서 점심식사를 하는 직장인</strong>
<a href="https://www.figma.com/slides/MZMHBF84Dlqfe0KfV4LRZ7/%F0%9F%8D%BD%EF%B8%8F?node-id=12-221&amp;t=rvzbYZDrQAMosWhY-1">🍽️</a></li>
</ul>
<h3 id="mvp-기능">MVP 기능</h3>
<ol>
<li><p><strong>사용자 등록 및 로그인</strong></p>
<ul>
<li>소셜 로그인(구글)</li>
</ul>
</li>
<li><p><strong>메뉴 선택 기능</strong></p>
<ul>
<li>사용자가 먹고 싶은 메뉴와 안 먹고 싶은 메뉴를 선택할 수 있는 스와이프 UI 제공</li>
</ul>
</li>
<li><p><strong>이전 식사 기록</strong></p>
<ul>
<li>사용자가 이전에 먹었던 메뉴와 식당을 저장하고 조회할 수 있는 기능</li>
</ul>
</li>
<li><p><strong>식당 추천 알고리즘</strong></p>
<p> 사용자의 선호도와 이전 식사 데이터를 기반으로 식당을 추천</p>
</li>
<li><p><strong>위치 기반 필터링</strong></p>
<p> 회원의 위치와 가까운 식당만 추천하는 기능</p>
</li>
<li><p><strong>반응형 웹 디자인</strong></p>
<p> 다양한 화면 크기에서 최적화된 UI 제공</p>
</li>
<li><p><strong>기본적인 피드백 시스템</strong></p>
<p> 사용자가 추천 식당 및 메뉴에 대한 피드백을 제공할 수 있는 기능</p>
</li>
</ol>
<p><img src="https://velog.velcdn.com/images/lee_geon_woo4336/post/f1a08fb4-047d-455c-b9a1-ae895e746d9f/image.png" alt=""></p>
<h1 id="3-프로덕트-컨셉">3. 프로덕트 컨셉</h1>
<aside>
💌  메뉴계의 틴더

<p>오늘의 당신과 매칭될 메뉴는 무엇일까요? 지금 바로 확인해보세요!</p>
</aside>

<p><img src="https://velog.velcdn.com/images/lee_geon_woo4336/post/642caaa8-f389-4a06-b8f4-fdba74ca779f/image.png" alt=""></p>
<h1 id="4--프론트엔드-스팩">4.  프론트엔드 스팩</h1>
<h3 id="1배포-github-actions--vercel">1.배포: GitHub Actions + Vercel</h3>
<p> 사이드 프로젝트에서 가장 중요한 것은 간단하고 빠른 연결이라고 생각했다. 복잡한 CI/CD 파이프라인을 구축할 시간도, 서버를 관리할 여유도 없었기 때문에 최소한의 설정으로 자동화된 배포가 필요했다.</p>
<ul>
<li>제로 컨피그: Vercel과 GitHub 연결만으로 자동 배포 완성</li>
<li>무료 티어: 사이드 프로젝트 규모에 충분한 무료 사용량
즉시 반영: 코드 푸시 후 1-2분 내 배포 완료</li>
<li>Preview 배포: PR마다 자동으로 미리보기 URL 생성</li>
<li>롤백 용이성: 클릭 한 번으로 이전 버전 복구 가능</li>
</ul>
<h3 id="2스타일링-tailwind-css">2.스타일링: Tailwind CSS</h3>
<p>CSS-in-JS 대신 Tailwind를 선택한 이유
처음에는 styled-components나 emotion 같은 CSS-in-JS를 고려했지만, 빠른 프로토타이핑과 일관된 디자인이 더 중요했다. 또한 디자인 파일과 tailwind config 파일에서 변수명을 일치 시키면 디자이너와의 협업에도 용이하고 컬러나 타이포그래피를 디자인 토큰을 가져와 한번에 적용 시키기 때문에 빠르게 디자인 설정을 끝낼 수 있었다. 또한 디자인 QA를 할 때에도 같은 변수명을 사용하기에 디자인 QA도 빠르게 진행 할 수 있었다.</p>
<h3 id="프레임워크-nextjs--typescript">프레임워크: Next.js + TypeScript</h3>
<p>복잡한 라우팅 요구사항
음식 선택 앱의 특성상 다음과 같은 복잡한 라우팅이 필요했다:
/onboarding -&gt; /food-selection -&gt; /preferences -&gt; /results -&gt; /details/[id]
Next.js를 선택한 핵심 이유</p>
<ol>
<li><p>파일 기반 라우팅의 직관성
pages/
├── onboarding/
│   ├── index.tsx      // /onboarding
│   └── preferences.tsx // /onboarding/preferences
├── food-selection.tsx  // /food-selection<br>├── results.tsx        // /results
└── details/
   └── [id].tsx       // /details/123</p>
</li>
<li><p>이미지 최적화</p>
</li>
</ol>
<ul>
<li>음식 이미지가 많은 앱에서 Next.js의 Image 컴포넌트는 필수적이었다.</li>
</ul>
<h3 id="앱으로-개발--웹으로-개발-">앱으로 개발 ? 웹으로 개발 ?</h3>
<blockquote>
<p>앱과 web을  많이 고민했는데 아직은 앱은 만들어본적이 없어서 기간내에 완성 할 수 없을 것 같다는 판단데 web기반 앱인 pwa로 개발하기로 했습니다.</p>
</blockquote>
<p><em>PWA 최적화 전략</em></p>
<ol>
<li><p>캐싱 전략</p>
<p>NetworkFirst: 최신 데이터 우선, 네트워크 실패 시 캐시 사용
음식 이미지와 사용자 선택 데이터의 효율적인 캐시 관리</p>
</li>
<li><p>오프라인 지원</p>
<p>사용자가 음식 선택 과정에서 네트워크가 끊어져도 계속 진행 가능
네트워크 복구 시 자동으로 서버와 동기화</p>
</li>
<li><p>개발 환경 최적화</p>
<p>Next.js와의 시너지 효과
자동 최적화</p>
<p>Next.js의 이미지 최적화 + PWA 캐싱 = 빠른 로딩 속도
정적 에셋의 자동 사전 캐싱</p>
<p>SEO + 앱 경험</p>
</li>
</ol>
<p>검색 엔진 최적화와 네이티브 앱 같은 UX를 동시에 확보
웹에서 접근 후 홈 화면 추가로 앱처럼 사용 가능</p>
<h3 id="fetch-기반-api">Fetch 기반 API</h3>
<p>토큰 기반 인증 분리</p>
<p>사용자 인증이 필요한 API와 그렇지 않은 API를 명확히 구분하여 관리했다.</p>
<pre><code>typescript// 회원가입, 로그인 등 토큰 불필요
export function fetchWithoutToken(url: string, options: RequestInit = {}): Promise&lt;Response&gt; {
    return customFetch(url, options, false);
}

// 사용자 데이터 토큰 필요  
export function fetchWithToken(url: string, options: RequestInit = {}): Promise&lt;Response&gt; {
    return customFetch(url, options, true);
}</code></pre><p>URL 생성 유틸리티
복잡한 쿼리 파라미터를 처리하기 위한 공통 함수를 구현했다.</p>
<p>abstract class BaseApi {
    public static generateSearchUri(url: string, params: Record&lt;string, any&gt;): string {
        let queryString = &quot;&quot;;
        if (Object.keys(params).length === 0) {
            return url;
        }</p>
<pre><code>    for (const key in params) {
        if (!key || !params[key]) continue;
        if (key === &quot;search&quot;) {
            for (const searchKey in params[key]) {
                if (!searchKey || !params[key][searchKey]) continue;
                queryString += `&amp;${searchKey}=${encodeURIComponent(params[key][searchKey])}`;
            }
            continue;
        }
        queryString += `&amp;${key}=${encodeURIComponent(params[key])}`;
    }

    return url.includes(&quot;?&quot;) ? url + queryString : url + `?${queryString}`;
}</code></pre><p>}</p>
<p>이렇게 2024 8월에 6차례에 걸친 회의끝에 사이드 프로젝트의 MVP , 기능, 컨셉, 개발 스팩 등이 정해졌다. 나는 웹 개발자이기 떄문에 앱 개발에 망설임은 있었다 그래도 도전하고 싶었기에 우리는 PWA로 먼저 개발을 하고 나중에 앱으로 전환하기로  했다.  </p>
<p>계속된 회의와 협업을 통해 프로젝트 팀원들에 대한 고마움이 많았다. 팀원들은 굉장히 능동적이고 의견 표현이 명확해서 같이 하면 뭐든 만들 수 있을 것 같다는 느낌이 들었었다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[select 태그 없이 드롭다운을 구현 해보자 ! ]]></title>
            <link>https://velog.io/@lee_geon_woo4336/select-%ED%83%9C%EA%B7%B8-%EC%97%86%EC%9D%B4-%EB%93%9C%EB%A1%AD%EB%8B%A4%EC%9A%B4%EC%9D%84-%EA%B5%AC%ED%98%84-%ED%95%B4%EB%B3%B4%EC%9E%90</link>
            <guid>https://velog.io/@lee_geon_woo4336/select-%ED%83%9C%EA%B7%B8-%EC%97%86%EC%9D%B4-%EB%93%9C%EB%A1%AD%EB%8B%A4%EC%9A%B4%EC%9D%84-%EA%B5%AC%ED%98%84-%ED%95%B4%EB%B3%B4%EC%9E%90</guid>
            <pubDate>Wed, 02 Mar 2022 07:03:18 GMT</pubDate>
            <description><![CDATA[<p><img src="https://images.velog.io/images/lee_geon_woo4336/post/3e3ae454-1f00-4e8d-bb3d-4d9336ce1987/image.png" alt=""></p>
<blockquote>
<p>div 태그로 Drop down 구현하기  </p>
</blockquote>
<p>보통의 경우 Drop down 을 사용 할 때에는 select 태그를 사용해서 구현을 합니다 .
하지만 일반 태그로도 구현 해 볼 수 있습니다 .
사실 굳이 할 필요는 없지만 그래도 한번 만들어 보았습니다 .</p>
<p><strong>select 태그로 구현한 drop down</strong></p>
<pre><code class="language-js">const selectList = [&quot;카테고리를 설정해 주세요&quot;,&quot;All&quot;, &quot;games&quot;, &quot;shopping&quot;, &quot;works&quot;, &quot;music&quot;, &quot;etc&quot;, &quot;private&quot;]

return (
                &lt;Select value = {isSelected} onChange = {handleSelect} &gt;
                {selectList.map((item) =&gt; (
                    &lt;option value={item} key={item}&gt;
                      {item}
                      {console.log(isSelected)}
                 &lt;/option&gt;
                ))}
                &lt;/Select&gt;
)</code></pre>
<p><strong>div로 구현한 drop down</strong></p>
<pre><code class="language-js.">  const [selectChild, setSelectChild] = useState&lt;boolean&gt;(true);
  const chooseHandler = (e: selectType): void =&gt; {
    setIsChonsen(e);
    setSelectChild(!selectChild);
  };
  const selectArray = [&quot;카테고리를 설정해 주세요&quot;,&quot;All&quot;, &quot;games&quot;, &quot;shopping&quot;, &quot;works&quot;, &quot;music&quot;, &quot;etc&quot;, &quot;private&quot;];
return (
              &lt;div className={selectChild ? &quot;selected&quot; : &quot;unselected&quot;}&gt;
                {selectArray.map((e, idx) =&gt; (
                  &lt;div
                    className = {isChosen.key === e.key ? &#39;selected-item&#39; : &#39;select-item&#39;}
                    key={`idx-${idx}`}
                    onClick={() =&gt; chooseHandler(e)}
                  &gt;
                    {e}
                  &lt;/div&gt;
)</code></pre>
<p>이렇게 구현을 했고 태그를 클릭하면 true , false가 되는 on off로 만들고 그에따라 className을 바꾸어 주면서 </p>
<pre><code class="language-js">  .selected{
      position: absolute;
    height: 160px;
    width: 180px;
    font-family: gmarket;
    line-height: 27px;
    right: 20px;
    background-color: $gray;
    z-index: 10;
  }

    .unselected{
    display: none;
  }</code></pre>
<p>Drop down을 구현해 주었습니다 .</p>
<p><img src="https://images.velog.io/images/lee_geon_woo4336/post/28dcb99e-deb3-4674-a4c5-c6ddaa5e62be/dropdowgif.gif" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Lazyloading을 구현 하면서 찾은 지식 Intersection Observer...]]></title>
            <link>https://velog.io/@lee_geon_woo4336/Lazyloading%EC%9D%84-%EA%B5%AC%ED%98%84-%ED%95%98%EB%A9%B4%EC%84%9C-%EC%B0%BE%EC%9D%80-%EC%A7%80%EC%8B%9D-Intersection-Observer</link>
            <guid>https://velog.io/@lee_geon_woo4336/Lazyloading%EC%9D%84-%EA%B5%AC%ED%98%84-%ED%95%98%EB%A9%B4%EC%84%9C-%EC%B0%BE%EC%9D%80-%EC%A7%80%EC%8B%9D-Intersection-Observer</guid>
            <pubDate>Wed, 02 Mar 2022 06:49:35 GMT</pubDate>
            <description><![CDATA[<p><img src="https://images.velog.io/images/lee_geon_woo4336/post/ab3c1244-0115-4033-8597-a9bb81b87693/image.png" alt=""></p>
<blockquote>
<p>Intersection Observer는 Infinitiscroll, Lazyloading 등 다양하게 사용이 되는데 Intersection Observer를 사용하지 않는 대부분의 경우 3가지의 값을 비교 하게 된다 . </p>
</blockquote>
<p>_1. scrollHeight - 화면에 보이지 않는 총 높이까지 포함된 페이지의 높이
2. scrollTop - 이미 스크롤되어서 보이지 않는 구간의 높이
3. clientHeight - 사용자에게 보여지는 페이지의 높이 _</p>
<p>위 값중에서 scrollTop과 clientHeight을 합친 값이 scrollHeight 보다 크다면 스크롤 페이지의 끝에 닿았다고 판단을 하게 된다 .</p>
<p>그래서 scroll이벤트를 감지하는 event listner를 통해 스크롤이 끝에 닿았을 때에 추가 데이터를 받아 오는 방식이다 .</p>
<p>하지만 이벤트로 동작 시키게 되면 스크롤 이벤트가 발생 할 때마다 요청이 발생해서 엄청나게 요청이 많이 가게 된다 . 그래서 리소스 낭비를 막고자 두가지의 방법이 있는데 하나는 throttle을 사용하는 방법이고 다른하나는</p>
<pre><code class="language-js"> window.addEventListener(&quot;scroll&quot;, scrolling);
    return () =&gt; {
      window.removeEventListener(&quot;scroll&quot;, scrolling);
    };</code></pre>
<p>이렇게 removeEventListener로 다시 지워주는 것이다 . 둘중에 편한 방법을 사용 하면 될 것 같다 .
나는 이 방법을 사용했다 . 
하지만 이 방법 둘 다 완전히 최적화 했다고 보기에는 어렵다 어쨋건 이벤트가 발생은 하는 것이니까 </p>
<p>그래서 이방법 보다는 Intersection  Observer를 추천 하긴 한다 </p>
<p><strong>Intersection Observer</strong> 는 
MDN의 내용에 따르면 <strong><em>타겟으로 관찰하고 있는 엘리먼트와 그 엘리먼트의 부모 혹은 상위 엘리먼트의 뷰포트가 교차되는 부분을 비동기적으로 관찰하는 API</em></strong> 라고 정의 되어 있다 .
Intersection Observer란 화면 상에 내가 지정한 타깃이 보이고 있는지를 관찰할 수 있도록 기능을 제공하는 API 인것이다 .</p>
<h4 id="intersection-observer의-장점-">Intersection Observer의 장점 ?</h4>
<ul>
<li><p>Intersection Observer는 Scroll 이벤트와 달리 비동기적으로 실행되기 때문에, 디바운스나 쓰로틀을 구현하지 않아도 되어서 훨씬 나은 퍼포먼스를 보여준다.</p>
</li>
<li><p>또한 매번 화면을 계산해서 그리는 reflow 현상을 일으키지 않기 때문에, 메인스레드에 주는 부담을 줄일 수 있다.</p>
</li>
</ul>
<h4 id="intersection-observer-객체에서-사용-가능한-메서드">Intersection Observer 객체에서 사용 가능한 메서드</h4>
<ol>
<li><p>observe(파라미터로 targetElement)
파라미터로 넘긴 타겟 요소에 대한 관측을 담당한다. 동일한 옵저버 객체로 여러번 호출을 해서 다양한 타겟 요소에 대해 관측이 가능하다.</p>
</li>
<li><p>unobserve(파라미터로 targetElement)
타겟 요소에 대한 관측을 중지하는 역할을 담당.</p>
</li>
<li><p>disconnect
모든 타겟 요소에 대한 관측을 중지한다.</p>
</li>
<li><p>takeRecord
현재 관측 중인 모든 타겟 요소들을 배열 형태로 반환한다.</p>
</li>
</ol>
<p><strong>Intersection Observer API 사용 방법</strong></p>
<pre><code class="language-js">// 타겟 요소 관측 시, 실행될 콜백 함수
const callback = (entries, observer) =&gt; {
  console.log(&#39;콜백함수&#39;);
};

// Observer 선언
const observer = new IntersectionObserver(callback, options);

// 타겟 요소 관측 시작
observer.observe(TargetElement);

// 타겟 요소 관측 중단
observer.unobserve(TargetElement);

// 모든 요소 관측 중단
observer.disconnect();

// 관측 중인 모든 요소를 배열 형태로 반환
observer.takeRecords();</code></pre>
<p><strong>Intersection Observer 의 기본구조</strong></p>
<pre><code class="language-js">// 기본구조는 콜백함수와 옵션을 받는다.
const io = new IntersectionObserver(callback[, options])</code></pre>
<p>Parameters
callback: 타겟 엘리먼트가 교차되었을 때 실행할 함수</p>
<ul>
<li><p>entries: IntersectionObserverEntry 객체의 리스트. 배열 형식으로 반환하기 때문에 forEach를 사용해서 처리를 하거나, 단일 타겟의 경우 배열인 점을 고려해서 코드를 작성해야 합니다.</p>
</li>
<li><p>observer: 콜백함수가 호출되는 IntersectionObserver</p>
</li>
</ul>
<p>options: option </p>
<pre><code class="language-js">const option = {
  root: null,
  rootMargin: 0px, 0px, 0px, 0px,
  threshold: 0,
}</code></pre>
<p><strong>root(viewport)</strong> : 타겟 요소와 교차 영역을 정의하기 위해 사용하는 상위 요소 프로퍼티다. 만약 값을 넣지 않거나 null일 경우에는 브라우저의 viewport(보여지고 있는 요소)가 root로 지정된다.</p>
<p><strong>rootMargin</strong> : root 요소에 적용되는 margin 값을 정의하기 위한 프로퍼티. 지정한 값만큼 교차 영역이 계산되며 루트의 범위가 축소하게 된다.</p>
<p><strong>thresholds</strong> : 콜백함수를 실행시키기 위한 루트 영역과 타겟 요소와의 교차 영역 비율을 지정하는 프로퍼티.
0.0과 1.0 사이의 값으로 지정한다. 값이 0이라면 타겟 요소가 교차 영역에 진입했을 때를 의미하며, 0.5라면 타겟 요소의 절반이 교차 영역에 들어왔을 때, 1.0이라면 완전히 교차 영역에 진입했을 때 콜백 함수가 실행된다.</p>
<p>📌 Intersection Observer 객체는 처음 생성될 때 타겟으로 지정한 요소 관측 시에 실행할 콜백 함수와 옵션 내용이 포함된 객체를 파라미터로 받는다. 옵션 객체는 문자 그대로 옵션이기 때문에 선택사항이며, 파라미터로 넘기지 않을 시 기본값이 적용된다.</p>
<p>📌 Intersection Observer는 화면에 띄어준 콘텐츠 중에 맨 마지막 요소를 관측해 콜백함수를 실행하는 원리로 무한스크롤을 구현하게 된다.</p>
<p>📌 타겟이 관측되었다면, 실행되는 콜백 함수 내에서 해당 요소에 대한 관측을 중지하고,
새로운 콘텐츠를 리스트에 추가한다. 그리고 다시 마지막 콘텐츠에 대해 관측을 시작하는 것이다.</p>
<p>📌 가장 보편적으로 사용되는 방법으로 list요소의 가장 아래에 빈 div요소를 생성하고, 그 요소에 ref를 달아주는 방법을 시용할 것이다. 이 ref를 통해서 교차시점을 확인할 수 있다.</p>
<p>👆 관찰자 생성 </p>
<pre><code class="language-js">const defaultOption = {
  root: null,
  threshold: 0.5,
  rootMargin: &#39;0px&#39;
};

const observer = new IntersectionObserver(checkIntersect, {
        ...defaultOption,
        ...option
      }
</code></pre>
<p>✌ 관찰 대상 지정해주기</p>
<p> return (
    <Wrap>
      <Nav>
        ...
      </Nav>
      <ul>
        ...
      </ul>
      {isLoading &amp;&amp; <p ref={loadingRef}>Loading...</p>}
    </Wrap></p>
<p> KeyPoint - 리스트 맨 아래에 ref로 관찰 대상을 만들어 주는 것이다</p>
<p>👌 관찰자를 만든다 .</p>
<pre><code class="language-js">const checkIntersect = useCallback(([entry], observer) =&gt; {
    if (entry.isIntersecting) {
      onIntersect(entry, observer);
    }
  }, []);</code></pre>
<p>관찰 대상은 하나이므로 콜백함수의 인자로 들어오는 [entry]와 observer를 파라미터로 전달해주었다. 그리고 이 entry의 속성인 isIntersecting을 이용해 조건을 검사하고, 조건에 해당하면 콜백 함수를 실행한다.</p>
<p>isIntersectig: 관찰 대상의 교차 상태를 boolean 값으로 반환한다.</p>
<p>🖖 useEffect를 통해 관찰 대상 수시로 변경해주기 .</p>
<ol>
<li>useEffect를 사용해 데이터를 로드한다.</li>
<li>데이터를 로드하며 전역에서 관리하고 있는 isLoaded 상태 값을 바꿔준다.</li>
<li>화면 최하단에 있는 엘리먼트를 ref로 잡아 isLoaded 상태 값에 따라 랜더링시켜준다.</li>
<li>useEffect를 사용해 타겟 요소의 상태 변경을 감지한다.</li>
<li>useEffect내에서 Intersection Observer 인스턴스를 생성한다.</li>
</ol>
<pre><code class="language-js"> useEffect(() =&gt; {
    let observer; // (1)beserver 변수를 선언해주고
    if (ref) { // (2) 관찰대상이 존재하는지 체크한다.
      observer = new IntersectionObserver(checkIntersect, { 
        ...defaultOption,
        ...option
      }); // (3) 관찰대상이 존재한다면 관찰자를 생성한다.
      observer.observe(ref); // (4) 관찰자에게 타겟을 지정한다.
    }
    return () =&gt; observer  &amp;&amp; observer.disconnect(); // 의존성에 포함된 값이 바뀔때 관찰을 중지한다.
  }, [ref, option.root, option.threshold, option.rootMargin, checkIntersect]);</code></pre>
<h1 id="참조">참조</h1>
<ul>
<li><a href="http://blog.hyeyoonjung.com/2019/01/09/intersectionobserver-tutorial/">http://blog.hyeyoonjung.com/2019/01/09/intersectionobserver-tutorial/</a></li>
<li><a href="https://velog.io/@yunsungyang-omc/React-%EB%AC%B4%ED%95%9C-%EC%8A%A4%ED%81%AC%EB%A1%A4-%EA%B8%B0%EB%8A%A5-%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0-used-by-Intersection-Observer-2">https://velog.io/@yunsungyang-omc/React-%EB%AC%B4%ED%95%9C-%EC%8A%A4%ED%81%AC%EB%A1%A4-%EA%B8%B0%EB%8A%A5-%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0-used-by-Intersection-Observer-2</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Provider를 사용하지 않고 SCSS로 다크모드를 구현해보자 ]]></title>
            <link>https://velog.io/@lee_geon_woo4336/Provider%EB%A5%BC-%EC%82%AC%EC%9A%A9%ED%95%98%EC%A7%80-%EC%95%8A%EA%B3%A0-SCSS%EB%A1%9C-%EB%8B%A4%ED%81%AC%EB%AA%A8%EB%93%9C%EB%A5%BC-%EA%B5%AC%ED%98%84%ED%95%B4%EB%B3%B4%EC%9E%90</link>
            <guid>https://velog.io/@lee_geon_woo4336/Provider%EB%A5%BC-%EC%82%AC%EC%9A%A9%ED%95%98%EC%A7%80-%EC%95%8A%EA%B3%A0-SCSS%EB%A1%9C-%EB%8B%A4%ED%81%AC%EB%AA%A8%EB%93%9C%EB%A5%BC-%EA%B5%AC%ED%98%84%ED%95%B4%EB%B3%B4%EC%9E%90</guid>
            <pubDate>Wed, 02 Mar 2022 06:46:29 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/lee_geon_woo4336/post/42dc50ef-8ddb-45ab-a1d3-aa1298fadf9b/image.png" alt=""></p>
<p><em>사이드 프로젝트를 만들던 도중에 다크모드를 구현을 해보았었는데 
그때는 Styled-Components를 ThemeProvider를 사용하여 구현하였다. 
이렇게 구현하는 것도 장점이 있지만  theme의 값을 전부 props로 넘겨줘야 하니
내가 느끼기에는 살짝 번거롭다는 생각이 들었다</em></p>
<p><em>그래서 다른 방법으로 구현 해보면 어떨까 라는 생각에 SCSS <code>prefers-color-scheme</code>을 사용해서 구현을 해보았다</em></p>
<blockquote>
<p>SCSS <code>prefers-color-scheme</code>로 다크모드 구현하는 방법</p>
</blockquote>
<ul>
<li><code>prefers-color-scheme</code> 미디어 쿼리르르 사용해서 적용 할 수 있는데
각 해상도에 따라 미디어쿼리를 적용하는 방식과 크게 다르지 않습니다 .</li>
</ul>
<p>저의 경우에는 App.scss 파일에서 
아래와 같이 </p>
<pre><code class="language-js">:root {
  --background: #96D9B9;
  --textcolor: black;
  --messageBackground: #5496fa;
  --AppTheme: #fff;
  --interngram: #6480A3;
  --chatListback: #fff;
  --chatHeader: rgb(250, 170, 170);
  --chatbackground: skyblue;
}</code></pre>
<p>변수명에 처음으로 설정 할 기본 값과 </p>
<pre><code class="language-js">@media (prefers-color-scheme: dark) {
  :root {
    --background: #181a50;
    --textcolor: #fff;
    --messageBackground: rgb(51, 15, 179);
    --AppTheme: rgb(12, 12, 48);
    --interngram: #F0DE7A;
    --chatListback: rgb(10, 51, 104);
    --chatHeader: rgb(19, 2, 82);
    --chatbackground: rgb(51, 15, 179);
  }
}</code></pre>
<p>다크모드 일 때의 값을 넣어 주었습니다 .</p>
<pre><code class="language-js">:root {
  --background: #96D9B9;
  --textcolor: black;
  --messageBackground: #5496fa;
  --AppTheme: #fff;
  --interngram: #6480A3;
  --chatListback: #fff;
  --chatHeader: rgb(250, 170, 170);
  --chatbackground: skyblue;
}

@media (prefers-color-scheme: dark) {
  :root {
    --background: #181a50;
    --textcolor: #fff;
    --messageBackground: rgb(51, 15, 179);
    --AppTheme: rgb(12, 12, 48);
    --interngram: #F0DE7A;
    --chatListback: rgb(10, 51, 104);
    --chatHeader: rgb(19, 2, 82);
    --chatbackground: rgb(51, 15, 179);
  }
}

.background{
  background-color: var(--AppTheme);
  height: 1200px;
}
</code></pre>
<p>그 뒤에 헤더에 있는 토글 스위치에 아래와 같은 함수를 넣고 다크모드와 라이트 모드를 설정 해주었습니다 .</p>
<pre><code class="language-js">  function switchTheme(e: React.MouseEvent&lt;HTMLInputElement&gt;) {
    const etarget = e.target as HTMLInputElement;

    if (etarget.checked) {
      localStorage.setItem(&quot;theme&quot;, &quot;dark&quot;);
      document.documentElement.setAttribute(&quot;data-theme&quot;, &quot;dark&quot;);
    } else {
      localStorage.setItem(&quot;theme&quot;, &quot;light&quot;);
      document.documentElement.setAttribute(&quot;data-theme&quot;, &quot;light&quot;);
    }
  }</code></pre>
<p>테마의 상태 값은 localStorage에 저장 해놓았습니다 .</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Localstorage에 대해 알아보자]]></title>
            <link>https://velog.io/@lee_geon_woo4336/Localstorage%EC%97%90-%EB%8C%80%ED%95%B4-%EC%95%8C%EC%95%84%EB%B3%B4%EC%9E%90</link>
            <guid>https://velog.io/@lee_geon_woo4336/Localstorage%EC%97%90-%EB%8C%80%ED%95%B4-%EC%95%8C%EC%95%84%EB%B3%B4%EC%9E%90</guid>
            <pubDate>Wed, 02 Mar 2022 06:45:39 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/lee_geon_woo4336/post/09a34845-2097-4351-a3ce-5edeac0b3c96/image.png" alt=""></p>
<blockquote>
<p><strong>localStorage란 ?</strong></p>
</blockquote>
<ul>
<li>데이터를 사용자 로컬에 보존 하는 방식.</li>
<li>데이터를 저장, 덮어쓰기, 삭제등 CRUD가 가능</li>
<li>자바스크립트(Javascript)로 조작.</li>
<li>모바일에서 사용 가능</li>
</ul>
<p>위와 같은 특징이 있습니다 . </p>
<p><em>자바스크립트나 자바스크립트 기반의 프레임워크로 Web을 구현 하면서 화면 이동이 있거나 영구적으로 저장해야하는 경우 DB에 값을 저장하거나 임시적인 경우에는 쿠키를 사용하기도 합니다 . 
이때 localStorage 라는 WebStorage API도 사용 할 수 있습니다 .</em></p>
<h4 id="localstorage와-쿠키와의-차이점-">localStorage와 쿠키와의 차이점 ?</h4>
<ul>
<li>유효 기간이 없고 영구적으로 이용 가능</li>
</ul>
<ul>
<li><p>5MB까지 사용 가능 (쿠키는 4KB까지)</p>
</li>
<li><p>필요할 때 언제든 사용 가능 (쿠키는 서버 접속시에 자동 송신)</p>
</li>
</ul>
<h4 id="어떤-데이터들을-localstorage에-저장하면-좋을까-">어떤 데이터들을 localStorage에 저장하면 좋을까 ?</h4>
<p><em>자바스크립트로 웹 개발을 하다보면 아무리 간단한 애플리케이션이라도 데이터를 어딘가에 저장해야 할 일이 생깁는데. 
보통 이럴 때 데이터베이스(DB) 서버나 클라우드(Cloud) 플랫폼에 데이터를 저장하게 됩니다 .</em></p>
<p>_하지만 저장해야할 데이터가 별로 중요하지 않거나, 
유실되도 무방할 데이터라면 서버 단에 데이터를 저장하는 것이 낭비일 수가 있습니다 . _</p>
<p><em>로컬 스토리지는 웹페이지의 세션이 끝나도 데이터가 지워지지 않습니다. 
즉 로컬 스토리지는 여러 탭이나 창 간에 데이터가 서로 공유되며 탭이나 창을 닫아도 데이터는 브라우저에 그대로 남아 있습니다.
따라서 저장 해야 할 데이터가 별로 중요하지 않거나 , 
유실되도 무방한 데이터라면 로컬 스토리지에 저장 해도 무방합니다 . 
localStorage의 위치는 개발자 도구를 열고 Application 탭을 누르면 Storage에 Local Storage에서 확인이 가능합니다</em></p>
<blockquote>
<p>localStorage 는 어떻게 사용 할까 ?</p>
</blockquote>
<ul>
<li><p>localStorage의 기본 구성</p>
<ul>
<li><p>키(key)와 값(value)을 하나의 세트로 저장.</p>
</li>
<li><p>도메인과 브라우저별로 저장.</p>
</li>
<li><p>값은 반드시 문자열로 저장.</p>
<ul>
<li><p>주의 할 점 ❗<br>데이터 저장 형식이 오직 문자형(string) 데이터 타입만 지원 하기때문에 다른 타입의 데이터를 저장 하려 할 경우 문자형으로 변환을 하기 때문에 객체형 데이터나 숫자형 데이터를 저장 할 때에 주의 해야 합니다 </p>
<p>✔ 해결 방법  ?
JSON 형태로 데이터를 읽고 쓰기 ! </p>
<pre><code class="language-js">   &gt; localStorage.setItem(&#39;json&#39;, JSON.stringify({a: 1, b: 2}))
     undefined
      &gt; JSON.parse(localStorage.getItem(&#39;json&#39;))
 {a: 1, b: 2}</code></pre>
<p>위와같은 방법으로 배열 , 숫자, 객체형 타입의 데이터를 저장할 때에 사용 할 수 있습니다 .</p>
</li>
</ul>
</li>
</ul>
</li>
<li><p>기본 문법</p>
</li>
</ul>
<pre><code class="language-js">// 키에 데이터 쓰기
localStorage.setItem(&quot;key&quot;, value)

// 키로 부터 데이터 읽기
localStorage.getItem(&quot;key&quot;)

// 키의 데이터 삭제
localStorage.removeItem(&quot;key&quot;)

// 모든 키의 데이터 삭제
localStorage.clear()

// 저장된 키/값 쌍의 개수
localStorage.length</code></pre>
<p>이상으로 포스팅 마치겠습니다 .</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[라이브러리 없이 Lazyloading을 구현 ]]></title>
            <link>https://velog.io/@lee_geon_woo4336/%EB%9D%BC%EC%9D%B4%EB%B8%8C%EB%9F%AC%EB%A6%AC-%EC%97%86%EC%9D%B4-Lazyloading%EC%9D%84-%EA%B5%AC%ED%98%84</link>
            <guid>https://velog.io/@lee_geon_woo4336/%EB%9D%BC%EC%9D%B4%EB%B8%8C%EB%9F%AC%EB%A6%AC-%EC%97%86%EC%9D%B4-Lazyloading%EC%9D%84-%EA%B5%AC%ED%98%84</guid>
            <pubDate>Wed, 02 Mar 2022 06:45:15 GMT</pubDate>
            <description><![CDATA[<p><img src="https://images.velog.io/images/lee_geon_woo4336/post/361c18df-16ce-4150-b7e6-f0ee7e10b60a/image.png" alt=""></p>
<h4 id="lazyloading-이란-">Lazyloading 이란 ?</h4>
<ul>
<li>페이지에 액세스 할 때 모든 콘텐츠를 대량으로 로드하는 대신 사용자가 필요한 페이지의 일부에 엑세스 할 때에 콘텐츠를 로드 할 수 있게 하는 것 입니다 . </li>
<li>페이지를 읽어 들이는 시점에 중요하지 않은 리소스 로딩을 추 후에 하는 기술입니다 . 대신에 중요하지 않은 리소스들은 필요할 때 로드가 되어야 합니다 .</li>
</ul>
<h4 id="lazy-loading의-장점-">lazy loading의 장점 ?</h4>
<ul>
<li>lazy loading은 콘텐츠 전달 최적화와 최종 사용자 간의 경험을 간소화 하는 균형을 맞춥니다.</li>
<li>사용자가 처음 열 때 웹 사이트의 일부만 다운로드 해야하므로 사용자에게 콘텐츠를 더 빨리 제공합니다.</li>
<li>콘텐츠가 지속적으로 사용자에게 공급되므로 사용자가 웹사이트를 이탈할 확률을 낮출 수 있습니다.</li>
<li>사용자가 한 번에 필요로 하는 경우에만 콘텐츠를 불러오므로 리소스 비용(사용자의 배터리, 시간, 시스템 리소스)이 낮아집니다</li>
</ul>
<h4 id="lazy-loading의-단점-">lazy loading의 단점 ?</h4>
<ul>
<li><p>lazy loading은 검색 엔진 순위에 영향을 미칠 수 있습니다 . 웹사이트를 크롤링하는 검색엔진은 리소스의 내용을 잘못 해석하거나 무시 할 수 있습니다 .</p>
</li>
<li><p>블로그 게시물과 같은 웹페이지의 전체 구성 요소를 느리게 로드하면 검색 엔진이 해당 구성 요소를 우회하여 콘텐츠가 인덱싱 되지 않아 검색 엔진 결과가 줄어들 수 있습니다.</p>
</li>
<li><p>이러한 문제를 극복하는 한 가지 요령은 lazy load하는 콘텐츠에 대한 링크를 제공하는 것입니다.</p>
</li>
</ul>
<blockquote>
<p>lazy loading 구현 방법 ?</p>
</blockquote>
<p>_lazyloading을 구현하는 방법에는 IntersectionObserver 를 이용한 infinity scrole을 구현 할 수 있고 다른 방법들도 있지만 저는 다른 방법으로 구현해 보았습니다 . _</p>
<p>_lazyloadinig을 구현 하기 위한 방법으로는 어떠한 경우에 사용자에게 필요한 정보의 타입에 따라 필요한 정보를 보여줄 지를 생각해보아야 합니다 . 저는 쌓여있는 글들을 사용자가 스크롤을 내려서 가장 마지막 글을 볼 때 쯔음에 데이터를 추가해주는 방법으로 구현해 보았습니다 .  _</p>
<blockquote>
<p>Code</p>
</blockquote>
<ol>
<li><p>우선 유저의 스크롤을 감지해서 Footer의 길이를 제거 하고 가장 아래로 왔을 때에 isLoading을 false에서 true로 바꾸어서 로딩을 보여준다 . </p>
</li>
<li><p>로딩중일 때에 데이터를 10개씩 넘겨주고 다시 로딩을 true 에서 false로 바꾸어준다 . </p>
</li>
<li><p>만일 데이터를 전부 불러와서 없는 경우에는 데이터를 더 불러오지 않는다 . </p>
</li>
</ol>
<p><strong>code</strong></p>
<pre><code class="language-js"> useEffect(()=&gt; {
    function scrolling() {
      let scrollHeight = Math.max(
        document.documentElement.scrollHeight,
        document.body.scrollHeight
      );
      let scrollTop = Math.max(
        document.documentElement.scrollTop,
        document.body.scrollTop
      );

      let clientTop = document.documentElement.clientHeight;
      // 여기까지가 가장 아래의 스크롤을 구하기 위한 변수
      // scrollHeight : 화면에 보이지 않는 총 높이까지 포함된 페이지의 높이
      // scrollTop : 이미 스크롤되어서 보이지 않는 구간의 높이
      // clientHeight : 사용자에게 보여지는 페이지의 높이
      if(footerref &amp;&amp; footerref.current?.clientHeight){
        const footerRealHeight = footerref.current.clientHeight
         //footerRealHeight는 footer의 높이
        if (scrollTop + clientTop &gt;= scrollHeight - footerRealHeight) {
        //footer의 높이를 제외한 전체 스크롤 높이보다 scrollTop과 clientTop의 합의 높이가 같거나 더 크면 
            setPage(storageData.slice(0, pageNum + 10));
        //데이터를 추가해주고
            setTimeout(() =&gt; {
             if (pageNum &lt; storageData.length + 9) {
               //만약 데이터 전체의 길이가 storageData에 9를 더한값 (뒷자리가 1인경우 예를 들어 11인경우도 대비해 9를 더해준다.)
                setPageNum(pageNum + 10);
               //데이터 추가
              } else {
                return;
                //만약 pageNum이 큰경우에는 아무것도 하지 않는다 . 
              }
            }, 10);
        } else {
          return
        }
      }
    }
    window.addEventListener(&quot;scroll&quot;, scrolling);
    return () =&gt; {
      //스크롤을 감지하고
      window.removeEventListener(&quot;scroll&quot;, scrolling);
      //스크롤 이벤트가 계속 반복되는걸 방지하기 위함
    };
  }, [storageData, pageNum]);</code></pre>
<p>CommentList.tsx 에서는</p>
<pre><code class="language-js">  useEffect((): void =&gt; {
    if (props.page.length === props.storageData.length) {
      props.setIsLoading(false);
    // localstorage에 저장된 데이터와 실질적으로 쓰이는 데이터의 길이가 같다면 로딩을 false로 만들어주고
    }
    if (props.storageData.length &lt;= 10) {
      props.setPage(props.storageData);
      props.setPageNum(10);
      props.setIsLoading(false);  
      //localstorage의 데이터가 10개 이하인 경우에도 실질적으로 쓰이는 데이터인 page를 setPage를 통해 갱신시키고 pageNum을 10으로 맞춰준 뒤에 로딩또한 false로 해둔다 
    } else {
      props.setPage(props.storageData.slice(0, props.pageNum));
      //위의 조건을 통과하지 않을 경우에는 storageData를 pageNum 만큼 slice 한 값으로 채워준다 
    }
  }, [props.storageData, props.page.length]);</code></pre>
<pre><code class="language-js"> {props.page.map((el: storageType, index: number) =&gt; {
          if (index &gt; props.page.length * 10 - 1) {
            return &lt;react.Fragment key={`index-${index}`} /&gt;;
// 그 뒤에 page를 map 해서 보여준다 .
          }</code></pre>
<p><img src="https://images.velog.io/images/lee_geon_woo4336/post/bf227483-aa14-45ed-85e4-ecc8780c8552/lazy.gif" alt=""></p>
<p>스크롤바를 집중적으로 봐주세요 !</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[타입스크립트 공부 하자..]]></title>
            <link>https://velog.io/@lee_geon_woo4336/%ED%83%80%EC%9E%85%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EA%B3%B5%EB%B6%80-%ED%95%98%EC%9E%90</link>
            <guid>https://velog.io/@lee_geon_woo4336/%ED%83%80%EC%9E%85%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EA%B3%B5%EB%B6%80-%ED%95%98%EC%9E%90</guid>
            <pubDate>Thu, 30 Dec 2021 06:08:36 GMT</pubDate>
            <description><![CDATA[<ul>
<li>회사 과제를 해결하기 위한 타입스크립트 공부기 ....</li>
</ul>
<ol>
<li>Typescript로 함수형 컴포넌트 생성
함수형 컴포넌트를 생성 할 때에는 React.FC (Functional Component의 약자) 라는 타입을 사용 한다 .</li>
</ol>
<pre><code class="language-js">import React, {useState} from &#39;recat&#39;;

const App: React.FC = () =&gt; {
    // 변수에 타입지정하기

    let hungry: string = &quot;hangry&quot;
    // 변수명: 타입명의 형태로 변수의 타입을 지정해 줄 수 있다 .

    //배열과 객체의 타입지정 
    let hamburgerKing : string[] = [&quot;Mc.donald&quot;, &quot;BigMac&quot;]
    let pizzaStore: {store: string} = {store: &quot;pizzaHut&quot;}

   //Typescript 에서 useState 타입 부여하기
   consst [name, setName]: [string | null , any] = useState(null)
                            // name에는 문자열 또는 null값을 부여하고 , setName 에는 아무 타입이나 들어올 수있게 했습니다 .
                // | 연산자는 또는 이라는 의미

    let nestedProp = obj.first?.second;
    //optional chaing 을 사용하면 지정한 타입의 값이 들어오지 않아도 오류를 내지 않고 undefined만 반환한다 
    //optional chaing을 사용하지  않으면 지정한 타입이 들어오지 않으면 오류가 발생한다 .


    const handleInput: ReactChangeHandler&lt;HTMLInputElement&gt; = (e) =&gt; {
        setName(e.target.value)
    }

    const handleClick: React.MouseEventHandler&lt;HTMLDivElement&gt; = () =&gt; {

    }
    // 이런식으로 이벤트 함수들 또한 타입을 부여 해줄 수 있습니다 .

   // 함수가 반환하는 값의 타입 지정


    const foo = (num1: number, num2: number) =&gt; {
        return num1 + num2; // number
    };
    // num1 넘버타입 num2 넘버타입

    //혹은 함수가 반환하는 값의 타입을 직접 지정

    const foo = (num1: number, num2: number): string =&gt; {
        return num1 + num2; // 에러 발생!
    };
    // 매개변수가 끝나는 지점에서 타입을 정해주면 된다 . 이 경우에는 전달 받는 두 매개변수가 num 타입인데 string타입으로 반환하려고 하니 애러가 발생한다 .


    //보이드 함수 


    const greetMaker = (phrase: string): void =&gt; {
    console.log(phrase);
    };
    //보이드 함수는 아무것도 반환하지 않는 함수 입니다 .
    // greetMaker 함수는 아무것도 반환하지 않습니다. 이렇게 아무것도 반환하지 않는 함수에 void타입을 지정하게 됩니다. 그리고 void가 지정된 함수는 undefined를 반환하게 됩니다. 앞서 함수에 타입을 지정할 때 처럼 타입스크립트 스스로 아무것도 반환하지 않는 함수에 void타입을 지정해줍니다. 그러니 void 타입을 별도로 지정해주지 않으셔도 됩니다.


    const greetMaker = (phrase: string): undefined =&gt; {
        console.log(phrase);
        return;
    };


    // 타입을 undefined로 지정해주기 위해 return 까지 써주어야 하고 이렇게 해도 되지만 void로 지정해준 방법이 더 깔끔하다 . 
}
</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[React 에서의 가상돔의 이해]]></title>
            <link>https://velog.io/@lee_geon_woo4336/React-%EC%97%90%EC%84%9C%EC%9D%98-%EA%B0%80%EC%83%81%EB%8F%94%EC%9D%98-%EC%9D%B4%ED%95%B4</link>
            <guid>https://velog.io/@lee_geon_woo4336/React-%EC%97%90%EC%84%9C%EC%9D%98-%EA%B0%80%EC%83%81%EB%8F%94%EC%9D%98-%EC%9D%B4%ED%95%B4</guid>
            <pubDate>Thu, 16 Dec 2021 10:37:41 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>Dom 이란 ?</p>
</blockquote>
<ul>
<li>문서 객체란 html, head, body와 같은 태그들을 javascript가 이용할 수 있는 (메모리에 보관할 수 있는) 객체를 의미한다.</li>
<li>웹 페이지를 이루는 태그들을 자바스크립트가 이용할 수 있게끔 브라우저가 트리구조로 만든 객체 모델을 의미한다.</li>
</ul>
<p><img src="https://images.velog.io/images/lee_geon_woo4336/post/319534ae-686d-4c85-bc96-c55f6f1f08a7/image.png" alt=""></p>
<p>Dom 은 Html과 script 언어 (javascript)를 서로 이어주는 역할을 해준다 .</p>
<blockquote>
<p>자바스크립트는 어떻게 HTML을 조정 할 수 있을까 ? </p>
</blockquote>
<ul>
<li>document라는 전역 객체를 통해 접근할 수 있다.
또한 window라는 객체는 document객체의 상위에 위치한다.</li>
</ul>
<blockquote>
<p>가상돔(Virtual DOM)이란 ?</p>
</blockquote>
<p><img src="https://images.velog.io/images/lee_geon_woo4336/post/072a0bfb-9d38-4d3e-b572-eead49dcce2b/image.png" alt=""></p>
<ul>
<li>실제 돔에 접근하여 조작하는 대신, 이것을 추상화시킨 자바스크립트 객체를 이용해 사용한다.</li>
<li>실제 (무거운)돔의 가벼운 사본 같은 개념</li>
</ul>
<p><em><strong>그렇다면 가상돔(Virtual DOM)이 나오게 된 이유는 무엇 일까 ?</strong></em></p>
<ul>
<li>Virtual Dom은 실제 DOM보다 가볍고, 빠른 Rendering이 가능하기 때문에 압도적으로 DOM의 부담을 줄여줍니다. </li>
<li>몇가지의 특수 키워드(ref, key, htmlFor)등 조금씩 다른부분이 존재하지만 실제 DOM과 Virtual Dom은 구조상 큰 차이가 없어 이해하기 편하다는 장점이 있습니다. </li>
</ul>
<p><strong>리액트가 가상돔을 반영하는 절차</strong>
특정 페이지에서 데이터가 변했다고 가정했을 때, 리액트를 이용해 돔을 업데이트시키는 절차는 다음과 같다.</p>
<ol>
<li>변화가 일어났다. 변화된 버전을 가상돔으로 바꾸자.</li>
</ol>
<ul>
<li>데이터가 업데이트 되면 전체 UI를 가상돔에 리렌더링한다.</li>
</ul>
<ol start="2">
<li>가상돔끼리 비교하자.</li>
</ol>
<ul>
<li>변화 전의 가상돔과 변화된 가상돔을 비교한다.</li>
</ul>
<ol start="3">
<li>바뀐 부분만 적용하자.</li>
</ol>
<ul>
<li>바뀐 부분만 실제 돔에 적용을 함으로서 레이아웃 계산은 한 번만 이행된다.
(ex. 네비게이션(컴포넌트)을 열었을 때 특정 영역(컴포넌트)이 빨갛게 변하면서 위치가 변경되는 경우의 레이아웃 계산이 일괄로 단 한 번만 이행)</li>
</ul>
<p><img src="https://images.velog.io/images/lee_geon_woo4336/post/18167d2d-0516-428d-abd8-a62cd42ef1fd/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[함수형 프로그래밍]]></title>
            <link>https://velog.io/@lee_geon_woo4336/%ED%95%A8%EC%88%98%ED%98%95-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D</link>
            <guid>https://velog.io/@lee_geon_woo4336/%ED%95%A8%EC%88%98%ED%98%95-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D</guid>
            <pubDate>Mon, 29 Nov 2021 12:17:55 GMT</pubDate>
            <description><![CDATA[<p>** 함수형 프로그래밍을 알아보는데에 있어 먼저 알아야 할 것이 프로그래밍의 패러다임에 대해서 알아 보아야 한다** </p>
<p>_그 이유는 ? 전에 알아보았던  객체지향 프로그래밍과 이번에 알아볼 함수형 프로그래밍 모두 프로그래밍 패러다임의 한 종류 이기 때문이다  _</p>
<blockquote>
<p>프로그래밍 패러다임(Programming Paradigm)</p>
</blockquote>
<ul>
<li>프로그래밍 패러다임(Programming Paradigm)은 프로그래머에게 프로그래밍의 관점을 갖게 하고 코드를 어떻게 작성할 지 결정하는 역할을 한다. 새로운 프로그래밍 패러다임을 통해서는 새로운 방식으로 생각하는 법을 배우게 되고, 이를 바탕으로 코드를 작성하게 된다.</li>
</ul>
<ul>
<li><p>명령형 프로그래밍: 무엇(What)을 할 것인지 나타내기보다 어떻게(How) 할 건지를 설명하는 방식</p>
<ul>
<li>절차지향 프로그래밍: 수행되어야 할 순차적인 처리 과정을 포함하는 방식 (C, C++)</li>
<li>객체지향 프로그래밍: 객체들의 집합으로 프로그램의 상호작용을 표현 (C++, Java, C#)</li>
</ul>
</li>
<li><p>선언형 프로그래밍: 어떻게 할건지(How)를 나타내기보다 무엇(What)을 할 건지를 설명하는 방식</p>
<ul>
<li>함수형 프로그래밍: 순수 함수를 조합하고 소프트웨어를 만드는 방식 (클로저, 하스켈, 리스프)</li>
</ul>
<ul>
<li>선언형 프로그래밍 예제 </li>
</ul>
</li>
</ul>
<pre><code class="language-js"> const newArr = [];
for (let i = 0; i &lt; arr.length; i++) {
  if (arr[i].length !== 0) {
    newArr.push(
      arr[i].charAt(0).toUpperCase() + arr[i].substring(1)
    );
  }
}</code></pre>
<ul>
<li><p>함수형 프로그래밍 예제</p>
<pre><code class="language-js">function convert (s) {
return s.charAt(0).toUpperCase() + s.substring(1);
}
const newArr2 = arr
.filter(v =&gt; v.length !== 0)
.map(v =&gt; convert(v));</code></pre>
</li>
</ul>
<blockquote>
<p>함수형 프로그래밍</p>
</blockquote>
<p><img src="https://images.velog.io/images/lee_geon_woo4336/post/38c4ffa6-2a7d-4e5d-a8c0-54645ee58468/simson.png" alt=""></p>
<ul>
<li><p>명령형 프로그래밍은 어떻게 할 것인가(How)를 표현하고, 선언형 프로그래밍은 무엇을 할 것인가(What) 표현합니다.</p>
</li>
<li><p>함수형 프로그래밍은 프로그래밍 언어나 방식을 배우는것이 아니라 함수로 프로그래밍하는 사고를 배우는것이라고 할 수 있습니다.
즉, 새로운 계산방법을 배우는 것처럼 사고의 전환을 필요로 합니다. 다양한 사고방식으로 프로그래밍을 바라보면 더욱 유연한 문제해결이 가능해집니다.</p>
</li>
<li><p>명령형 프로그래밍과의 비교</p>
</li>
</ul>
<p><img src="https://images.velog.io/images/lee_geon_woo4336/post/d2501f0b-8bc9-409d-93c6-0ccfdaa66dec/image.png" alt=""></p>
<p>함수형 프로그래밍은 계산을 수학적 함수의 조합으로 생각하는 방식을 말합니다. 이것은 일반적인 프로그래밍 언어에서 함수가 특정 동작을 수행하는 역할을 담당하는 것과는 반대되는 개념으로, 함수를 수행해도 함수 외부의 값이 변경될 수 없습니다.</p>
<blockquote>
<p>함수형 프로그래밍에 필요한 개념</p>
</blockquote>
<ul>
<li>1급 객체</li>
<li>고차함수</li>
<li>불변성</li>
<li>순수 함수</li>
<li>데이터 변환 방법</li>
<li>합성함수</li>
</ul>
<p><strong>1급객체</strong></p>
<ul>
<li>1급 객체(First class object)란 다음과 같은 조건을 만족하는 객체<ul>
<li>변수나 데이터 구조안에 담을 수 있다.</li>
<li>파라미터로 전달 할 수 있다.</li>
<li>반환값(return value)으로 사용할 수 있다.</li>
<li>할당에 사용된 이름과 관계없이 고유한 구별이 가능하다.</li>
<li>동적으로 프로퍼티 할당이 가능하다.</li>
</ul>
</li>
</ul>
<pre><code>  자바스크립트에서 함수(Function)은 객체(Object)이므로 1급 함수로 불린다.</code></pre><p><strong>고차 함수 (High-Order Function)</strong></p>
<ul>
<li>람다 계산법에서 만들어진 용어로 아래 조건을 만족하는 함수<ul>
<li>함수에 함수를 파라미터로 전달할 수 있다.</li>
<li>함수의 반환값으로 함수를 사용할 수 있다.
고차 함수는 1급 함수의 부분 집합(Subset)이다.</li>
</ul>
</li>
</ul>
<pre><code>리액트의 고차 컴포넌트(HOC)는 컴포넌트를 사용하여 위의 조건을 만족하는 컴포넌트를 말한다.</code></pre><p><strong>불변성</strong></p>
<ul>
<li>함수형 프로그래밍에서는 데이터가 변할 수 없는데, 이를 불변성 데이터라고 한다. (자바스크립트는 가능하지만 불가능한 언어들이 있다)</li>
<li>데이터 변경이 필요한 경우, 원본 데이터 구조를 변경하지 않고 그 데이터를 복사본을 만들어 그 일부를 변경하고, 변경한 복사본을 사용해 작업을 진행한다.</li>
</ul>
<pre><code>const 키워드와 불변은 구분해야 한다. const는 Object로 사용되는 경우 변경 가능하다.</code></pre><p><strong>순수함수</strong></p>
<ul>
<li>순수 함수란 함수형 프로그래밍에 필요한 개념으로 아래 조건을 만족하는 함수를 뜻한다.<ul>
<li>동일한 입력에는 항상 같은 값을 반환해야 한다.</li>
<li>함수의 실행은 프로그램의 실행에 영향을 미치지 않아야 한다. (Side effect 가 없어야 한다
_  예를 들어, 함수 내부에서 인자의 값을 변경하거나 프로그램 상태를 변경하는 것_</li>
</ul>
</li>
</ul>
<pre><code>순수 함수를 호출하면 프로그램의 어떠한 변화도 없고, 입력 값에 대한 결과를 예상할수 있어서 테스트하기가 쉽다.</code></pre><p><strong>데이터 변환방법</strong></p>
<ul>
<li>함수형 프로그래밍은 데이터 변경이 불가능하기 때문에 기존 데이터의 복사본을 만들어 주는 도구들이 필요하다.</li>
<li>자바스크립트에는 이미 Array.map, Array.reduce등 데이터 복사본을 만들기 위한 함수들을 제공하고 있다.</li>
</ul>
<p><strong>합성함수</strong></p>
<ul>
<li>합성 함수란 새로운 함수를 만들어거나 계산하기 위해 둘 이상의 함수를 조합하는 과정을 말한다. 함수형 프로그램은 여러 작은 순수 함수들로 이루어져있기 때문에 이 함수들을 연쇄적으로 또는 병렬로 호출해서 더 큰 함수를 만드는 과정으로 전체 프로그램을 구축해야 한다.</li>
<li>메서드 체이닝 방식의 합성함수</li>
</ul>
<p>출처 
<a href="https://velog.io/@kyusung/%ED%95%A8%EC%88%98%ED%98%95-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D-%EC%9A%94%EC%95%BD">https://velog.io/@kyusung/%ED%95%A8%EC%88%98%ED%98%95-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D-%EC%9A%94%EC%95%BD</a></p>
<blockquote>
<p>함수형 프로그래밍을 왜 쓰는가 ?</p>
</blockquote>
<ul>
<li>장점 <ul>
<li>높은 수준의 추상화를 제공한다</li>
<li>함수 단위의 코드 재사용이 수월하다</li>
<li>불변성을 지향하기 때문에 프로그램의 동작을 예측하기 쉬워진다</li>
</ul>
</li>
</ul>
<p><em>John Hughes 는 1990년에 쓴 &quot;Why Functional Programming Matters&quot; 에서 다음과 같이 설명하였다.</em></p>
<p><em>함수형 프로그램은 대입문이 없어 변수에 값이 할당되면 그 이후 절대 변하지 않는다.
좀 더 일반적으로 말하자면, 함수형 프로그램은 부수 효과(side effect)가 전혀 없다. 함수 호출은 그 함수의 결과를 계산하는 것 외에 다른 효과는 없기 때문에, 버그의 주요 원인을 제거할 수 있고, 함수의 실행 순서는 중요하지 않게 된다.
표현식(expression: 이는 함수들의 조합이라 생각할 수 있다.)의 결과를 바꿀 수 있는 부수 효과가 없기 때문에 그 표현식은 아무때나 실행될 수 있다. 이것은 흐름의 제어를 지정해야 하는 프로그래머의 짐을 덜어준다.
표현식은 아무때나 실행될 수 있기 때문에 변수를 그 표현식의 값으로 대체할 수 있고, 반대로 값을 그 표현식으로도 대체할 수도 있다. 이러한 프로그램을 두고 &quot;참조 투명성을 가졌다&quot;라고 한다. 이러한 특성은 함수형 프로그램이 기존의 다른 프로그램보다 더 수학적으로 다루기 쉽게 한다.</em></p>
<p>출처 <a href="http://ruaa.me/why-functional-matters/">http://ruaa.me/why-functional-matters/</a></p>
<blockquote>
<p>함수형 프로그래밍 Method</p>
</blockquote>
<ul>
<li><p>arr.forEach(callback)
전달인자 : 반복실행 할 함수
배열의 길이만큼 반복 실행한다.
return 값 없음
callback함수의 파라미터 순서:순서대로 현재 엘리먼트(value),인덱스(index), 원본 배열(array)</p>
</li>
<li><p>arr.map(callback)
전달인자 : 반복 실행할 함수
callback 함수에는 리턴값이 필요하며, 해당 내용이 새로운 배열의 element가 됨
callback함수의 파라미터 순서:순서대로 현재 엘리먼트(value),인덱스(index), 원본 배열(array)</p>
<ul>
<li>arr.filter(callback)
전달인자 : 반복 실행할 함수
callback 함수에는 리턴값이 필요하며,true일 경우 필터 조건에 통과하며 그 element들은 새로운 배열의 element들이 된다.
callback함수의 파라미터 순서:순서대로 현재 엘리먼트(value),인덱스(index), 원본 배열(array)</li>
</ul>
</li>
<li><p>arr.reduce(reducer,[initialValue])
reduce의 작동원리에는 배열 축소에 있다.즉 여러개의 값이 담긴 배열이 줄어서 최종적으로 하나의 값으로 만드는 과정이다. 이때 배열을 하나의 값으로 만드는 함수를 reducer라고 한다.
전달인자: 리듀서, 초기값
reducer함수에는 리턴값이 필요하며, 다음번 리듀서 호출 시, 첫 번째 파라미터로 전달된다.
reducer함수의 파라미터 순서: 순서대로 누적값(accumulator), 현재 엘리먼트(value), 인덱스(index), 원본 배열(array)</p>
</li>
<li></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[객체지향 프로그래밍이란 ?]]></title>
            <link>https://velog.io/@lee_geon_woo4336/%EA%B0%9D%EC%B2%B4%EC%A7%80%ED%96%A5-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D%EC%9D%B4%EB%9E%80</link>
            <guid>https://velog.io/@lee_geon_woo4336/%EA%B0%9D%EC%B2%B4%EC%A7%80%ED%96%A5-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D%EC%9D%B4%EB%9E%80</guid>
            <pubDate>Mon, 29 Nov 2021 09:16:18 GMT</pubDate>
            <description><![CDATA[<p>객체지향 프로그래밍에 대해서 알아보겠습니다 </p>
<blockquote>
<p>프로그래밍 패러다임(Programming Paradigm)</p>
</blockquote>
<ul>
<li>프로그래밍 패러다임(Programming Paradigm)은 프로그래머에게 프로그래밍의 관점을 갖게 하고 코드를 어떻게 작성할 지 결정하는 역할을 한다. 새로운 프로그래밍 패러다임을 통해서는 새로운 방식으로 생각하는 법을 배우게 되고, 이를 바탕으로 코드를 작성하게 된다.</li>
</ul>
<ul>
<li><p>명령형 프로그래밍: 무엇(What)을 할 것인지 나타내기보다 어떻게(How) 할 건지를 설명하는 방식</p>
<ul>
<li>절차지향 프로그래밍: 수행되어야 할 순차적인 처리 과정을 포함하는 방식 (C, C++)</li>
<li>객체지향 프로그래밍: 객체들의 집합으로 프로그램의 상호작용을 표현 (C++, Java, C#)</li>
</ul>
</li>
<li><p>선언형 프로그래밍: 어떻게 할건지(How)를 나타내기보다 무엇(What)을 할 건지를 설명하는 방식</p>
<ul>
<li>함수형 프로그래밍: 순수 함수를 조합하고 소프트웨어를 만드는 방식 (클로저, 하스켈, 리스프)</li>
</ul>
</li>
</ul>
<blockquote>
<p>_ 객체지향 프로그래밍이란 무엇일까요 ?_</p>
</blockquote>
<ul>
<li>객체 지향 프로그래밍은 컴퓨터 프로그래밍의 패러다임 중 하나로 프로그래밍에서 필요한 데이터를 <strong>추상화</strong> 시켜 상태와 행위를 가진 <strong>객체</strong>를 만들고 그 객체들 간의 유기적인 상호 작용을 통해 로직을 구성하는 프로그래밍 방법 입니다</li>
</ul>
<blockquote>
<p><em>객체지향 프로그래밍과 절차지향 프로그래밍 ?</em></p>
</blockquote>
<ul>
<li>객체 지향 프로그래밍과 절차지향 프로그래밍의 차이는 아래의 예시를 보면 쉽습니다 </li>
</ul>
<p><img src="https://images.velog.io/images/lee_geon_woo4336/post/a5a5961d-4a6a-4196-b400-9ee267eedc94/%E1%84%80%E1%85%A2%E1%86%A8%E1%84%8E%E1%85%A6%E1%84%8C%E1%85%B5%E1%84%92%E1%85%A3%E1%86%BC%E1%84%8C%E1%85%A5%E1%86%A8.png" alt=""></p>
<p><img src="https://images.velog.io/images/lee_geon_woo4336/post/6ae84027-bd16-44b6-8de3-966ba92406b5/%E1%84%8E%E1%85%A1%E1%84%8B%E1%85%B5.png" alt=""></p>
<p>언뜻 보면 둘은 같아 보일 수 있습니다 하지만 둘의 큰차이점은 저런식으로 진행된다가 아니라</p>
<p>객체지향 프로그래밍은 객체의 디자인을 한 뒤에 이들의 데이터플로우를 짜고 진행시나리오를 설계해나가는 방식의 개발방법론일 뿐입니다. 플로우차트 먼저 짜느냐, 데이터모델링을 먼저 하느냐의 차이일 뿐이지 그 이후로는 절차지향 프로그램이나 객체지향 프로그램이나 다들 정해진 알고리즘을 따라 순서대로 실행되는건 마찬가지입니다.</p>
<h4 id="그렇다면-객체-지향-프로그래밍의-장단점은-어떤게-있을까요-">그렇다면 객체 지향 프로그래밍의 장단점은 어떤게 있을까요 ?</h4>
<ul>
<li>장점</li>
</ul>
<ol>
<li>코드 재사용이 용이<ul>
<li>남이 만든 클래스를 가져와서 이용 할 수 있고 상속을 통해 확장해서 사용 할 수 있다</li>
</ul>
</li>
<li>유지보수가 쉬움<ul>
<li>절차 지향 프로그래밍에서는 코드를 수정해야 할 때에 일일이 찾아 수정 해야하는 반면 객체 지향 프로그래밍에서는 수정해야 할 부분이 클래스 내부에 멤버 변수 혹은 메서드로 존재하기 때문에 해당 부분만 수정하면 된다 </li>
</ul>
</li>
<li>대형 프로젝트에 적합 <ul>
<li>클래스 단위로 모듈화시켜서 개발 할 수 있으므로 대형 프로젝트 처럼 여러명, 여러 회사에서 프로젝트를 개발 할 때 업무 분담하기가 쉽다 .</li>
</ul>
</li>
</ol>
<ul>
<li>단점</li>
</ul>
<ol>
<li>처리속도가 상대적으로 느림</li>
<li>객체가 많으면 용량이 커질 수 있음</li>
<li>설계시 많은 시간과 노력이 필요</li>
</ol>
<blockquote>
<p><em>객체지향 프로그래밍의 키워드 5개</em></p>
</blockquote>
<ul>
<li>클래스 + 인스턴스(객체)</li>
<li>추상화</li>
<li>캡슐화 </li>
<li>상속</li>
<li>다형성</li>
</ul>
<h4 id="클래스와-인스턴스에-대해-알아보자">클래스와 인스턴스에 대해 알아보자</h4>
<ul>
<li><p>클래스란 ? </p>
<ul>
<li>어떤 문제를 해결하기 위한 데이터를 만들기 위해 추상화를 거쳐** 집단에 속하는 속성(attribute)과 행위(behavior)를 변수와 메서드로 정의 한 것** 으로 객체를 만들기 위한 메타정보 라고 볼 수 있습니다 </li>
</ul>
</li>
<li><p>인스턴스란 ? </p>
<ul>
<li><p>클래스에서 정의한 것을 토대로 실제 메모리에 할당된 것으로 실제 프로그램에서 사용되는 데이터 
<img src="https://images.velog.io/images/lee_geon_woo4336/post/486f7e8b-df72-4b60-b47f-9e5d504006bf/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-11-29%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%204.46.02.png" alt="">
<img src="https://images.velog.io/images/lee_geon_woo4336/post/76149f40-4f80-4ccb-8e5a-f67a034a0bc5/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-11-29%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%204.46.18.png" alt=""></p>
<p>위의 예시와 같이 클래스와 인스턴스는 서로 상속 관계 이다 
또한 클래스를 더 디테일 하게 나눌 수도 있다
<img src="https://images.velog.io/images/lee_geon_woo4336/post/1b40089f-ec65-4c89-9ca5-5b1c6da36e79/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-11-29%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%204.45.48.png" alt=""></p>
<p>위의 예시처럼 서로 상속 상속 상속을 하게 된다</p>
</li>
</ul>
</li>
</ul>
<h4 id="객체지향-프로그래밍에서-추상화란-">객체지향 프로그래밍에서 추상화란 ?</h4>
<ul>
<li>객체지향 프로그래밍에서는 <strong>추상화</strong> 라는 단어를 여러군데 붙일 수 있다 .
여기서 말하는 추상화는 추상 클래스나 추상 메서드를 의미 하기 보다는 클래스를 설계 하는 것 자체를 의밓란다 즉, *<em>추상화란 공통의 속성이나 기능을 묶어 이름을 붙이는 것이다 *</em></li>
</ul>
<h4 id="캡슐화란-무엇일까-">캡슐화란 무엇일까 ?</h4>
<ul>
<li>캡슐화의 목적 2가지</li>
</ul>
<ol>
<li><p>코드를 재수정 없이 재활용 하는것 .</p>
</li>
<li><p>접근 제어자를 통한 정보 은닉</p>
<p>절차 지향 프로그래밍에서도 라이브러리를 통해서 변수와 함수를 재활용 할 수는 있었지만, 코드의 수정이 일어났을 때 영향 범위를 예상하기 어려운 문제가 있었다 .</p>
<p>그러나 객체지향 프로그래밍에서는 캡슐화를 통해 <strong>객체가 외부에 노출하지 않아야 할 정보 또는 기능을 접근 제어자를 통해 적절히 제어 권한이 있는 객체에서만 접근이 가능하도록 할 수 있기에</strong> 코드의 수정이 일어났을 때 책임이 있는 객체만 수정 하면 되기에 영향 범위를 예측하는데 수월해졌다.</p>
<p>뿐만 아니라 관련된 기능과 특성을 한곳에 모으로 분류하기 때문에 *<em>기능과 특성의 모음을 클래스 라는 캡슐에 분류해서 넣는것이 캡슐화다 *</em></p>
</li>
</ol>
<h4 id="상속이란-무엇일까-">상속이란 무엇일까 ?</h4>
<ul>
<li><p>절차지향 프로그래밍에서도 라이브러리를 통해서 남이 짜놓은 소스코드를 가져와 사용 할 수 있었습니다 하지만 내의도에 맞게 수정하게 되면 다른 라이브러리가 되어 버전에 따라 동작 하지 않을 수도 있고 불필요한 코드의 수정 작업을 해야 합니다 </p>
<p> 이런 문제를 해결하기 위해 상속 이라는 것을 도입 하였습니다
 <strong>상속은</strong> 부모클래스의 속성과 기능을 그대로 이어받아 사용 할 수 있게 하고 기능의 일부분을 변경해야 할 경우 상속 받은 자식 클래스에서 해당 기능만 다시 수정하여 사용 할 수있게 하는 것 입니다 </p>
</li>
</ul>
<p>_   다중상속은 불가합니다 클래스의 상속 관계에서 혼란을 줄 수 있기 때문에 상속은 반드시 하나만 가능하고 필요에 따라 인터페이스를 사용 할 수 있게 했습니다 _</p>
<h4 id="다향성-이란것은-무엇일까-">다향성 이란것은 무엇일까 ?</h4>
<ul>
<li>하나의 변수명, 함수명 등이 상황에 따라 다른 의미로 해석 될 수 있다는 뜻입니다 
즉 오버라이딩, 오버로딩이 가능하다는 이야기 입니다 <ul>
<li>오버라이딩: 부모 클래스의 메서드와 같은 이름 , 매개변수를 재정의 하는것</li>
<li>오버로딩: 같은 이름의 함수를 여러개 정의하고 , 매개변수의 타입과 개수를 다르게 하여 매개변수에 따라 다르게 호출 할 수 있게 하는것 입니다 .</li>
</ul>
</li>
</ul>
<p><strong>이렇게 객체 지향 프로그래밍에 대한 것과 키워드 5개를 알아보았습니다 .</strong></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[React 생명주기 및 Class형과 함수형 생명주기의 차이점]]></title>
            <link>https://velog.io/@lee_geon_woo4336/React-%EC%83%9D%EB%AA%85%EC%A3%BC%EA%B8%B0-%EB%B0%8F-Class%ED%98%95%EA%B3%BC-%ED%95%A8%EC%88%98%ED%98%95-%EC%83%9D%EB%AA%85%EC%A3%BC%EA%B8%B0%EC%9D%98-%EC%B0%A8%EC%9D%B4%EC%A0%90</link>
            <guid>https://velog.io/@lee_geon_woo4336/React-%EC%83%9D%EB%AA%85%EC%A3%BC%EA%B8%B0-%EB%B0%8F-Class%ED%98%95%EA%B3%BC-%ED%95%A8%EC%88%98%ED%98%95-%EC%83%9D%EB%AA%85%EC%A3%BC%EA%B8%B0%EC%9D%98-%EC%B0%A8%EC%9D%B4%EC%A0%90</guid>
            <pubDate>Tue, 23 Nov 2021 13:18:12 GMT</pubDate>
            <description><![CDATA[<h1 id="react-생명주기란-">React 생명주기란 ?</h1>
<p><em>React의 모든 컴포넌트는 아래의 세가지 단계를 거칩니다 .</em></p>
<ul>
<li>초기화 단계</li>
<li>업데이트 단계</li>
<li>소멸단계 </li>
</ul>
<p><em>각 단계에서 몇개의 메서드들이 정해진 순서대로 작동하며 각 단계 속에서 호출되는 메서드들을 생명주기 메서드 라고 합니다</em></p>
<p>리액트는 웹에서 UI데이터가 변경되면 자동으로 컴포넌트가 업데이트되며 동적으로 화면을 그려줍니다.
제대로 된 기능을 수행하려면 이런 자동으로 업데이트되는 과정에 끼어들어 API를 호출하기도 하고 데이터를 가공하기도 해야 합니다.
따라서 생명주기의 각 단계별로 필요한 순간에 필요한 작업들을 끼워넣을 수 있는 메서드들이 존재합니다.</p>
<p><img src="https://images.velog.io/images/lee_geon_woo4336/post/a8748542-49ef-413a-a14c-11f294534b11/image.png" alt=""></p>
<p>리액트에서의 생명주기 과정입니다 .</p>
<blockquote>
<p><strong>초기화 단계</strong></p>
</blockquote>
<ul>
<li><p>초기화 단계는 최초에 컴포넌트 객체가 생성 될 때 한번 수행되는 과정입니다</p>
</li>
<li><p>초기와 단계에서 실행되는 함수</p>
<ul>
<li><p>Constructor() : </p>
<ul>
<li><p>메소드를 바인딩하거나 state(상태)를 초기화 하는 작업이 없다면 constructor(생성자)가 없어도 됩니다 .</p>
</li>
<li><p>react 컴포넌트의 constructor(생성자)는 해당 컴포넌트가 마운트 되기 전에 호출됩니다</p>
</li>
<li><p>생성자를 구현하면 this.props가 생성자 내에서 정의 되도록 super(props)를 호출해야 합니다.</p>
<ul>
<li>state의 값을 변경하고자 한다면 , constructor() 외부에서 this.setState()를 통해 수정해야 합니다 </li>
</ul>
</li>
<li><p>render() </p>
<ul>
<li>Class 컴포넌트에서 반드시 구현되어야 하는 유일한 메소드 입니다 </li>
<li>이메소드가 호출되면 this.props와 this.state의 값을 활영하여 값을 변환합니다 .</li>
<li>render()함수는 컴포넌트의 state를 변경하지 않고 호출 될 때마다 동일한 결과를 반환하며 브라우저와 직접적인 상호작용을 하지 않습니다</li>
</ul>
</li>
<li><p>componentDidMount() </p>
<ul>
<li>컴포넌트가 마운트 된 직후에 호출됩니다 </li>
<li>DOM 노드가 있어야 하는 초기화 작업이 이루어지면 좋습니다 .</li>
<li>외부에서 데이터를 불러와야 한다면 네트워크 요청을 보내기 좋은 위치입니다 </li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<blockquote>
<p> <strong>업데이트 단계</strong></p>
</blockquote>
<ul>
<li>업데이트 단계는 컴포넌트가 마운트 된 이후 컴포넌트의 속성값(props) , 상태값 (state)이 변경되면 업데이트 단계가 실행 됩니다 .</li>
<li>업데이트 단계에서 실행되는 함수 <ul>
<li>componentDidUpdate()<ul>
<li>render가 일어난 직후에 호출되며 최초 랜더링에서는 호출 되지 않습니다</li>
</ul>
</li>
</ul>
</li>
</ul>
<blockquote>
<p><strong>소멸단계</strong></p>
</blockquote>
<ul>
<li>소멸단계에서는 컴포넌트가 소멸 할 때의 과정입니다 </li>
<li>소멸단계에서의 함수 <ul>
<li>componentWillUnmount() <ul>
<li>컴포넌트가 마운트 해제되어 제거되기 직전에 호출 됩니다</li>
<li>타이머 제거, 네트워크 요청 취소, componentDidMount()에서 생성된 작업 등을 정리할때 사용됩니다 .</li>
<li>실행직후 컴포넌트는 랜더링 되지 않으므로 setState() 호출을 하면 안됩니다 .</li>
</ul>
</li>
</ul>
</li>
</ul>
<blockquote>
<p><strong>Class형과 함수형의 생명주기 차이점</strong></p>
</blockquote>
<ul>
<li>React에서는 클래스형과 함수형으로 컴포넌트를 생성 할 수 있는데, 요새는 주로 함수형 컴포넌트가 많이 사용됩니다</li>
</ul>
<p>_왜 ? _
함수형 컴포넌트의 가장 큰 장점으로는 간단하게 함축적인 프로그래밍이 가능 하기 때문입니다 .</p>
<table>
<thead>
<tr>
<th align="left"></th>
<th>클래스형 컴포넌트</th>
<th align="center">함수형 컴포넌트</th>
</tr>
</thead>
<tbody><tr>
<td align="left">특징</td>
<td>render() 메소드와 Component 상속 필수</td>
<td align="center">간편한 컴포넌트 선언 및 프로그래밍 가능 <br/> React Hook사용</td>
</tr>
<tr>
<td align="left">단점</td>
<td>state, props 사용 불편 <br/> 많은 메모리 사용</td>
<td align="center">state와 생명주기 메소드를 별도로 구현해야함 ex) useStatem useEffect 사용</td>
</tr>
</tbody></table>
<blockquote>
<p>useEffect</p>
</blockquote>
<p>: React Hook에서 라이프사이클 구현에 사용되는 함수</p>
<p><em>useEffect 쓰는법</em></p>
<pre><code class="language-js">useEffect(() =&gt; {
    //코드 적는곳
})</code></pre>
<p><em>=&gt; 2번째 파라미터를 주지 않으면 모든 컴포넌트가 리렌더링될 때마다 실행(메모리 과다 사용)</em></p>
<ul>
<li>componentDidMount() 대신 쓸 때에 
: 렌더링이 완료된 후 호출되는 메소드</li>
</ul>
<pre><code class="language-js">useEffect(() =&gt; {
      // 코드 적는곳
}, []) //빈배열을 줌으로써 마운트 이후 1회만 실행</code></pre>
<p>_=&gt; 마운트 이후 1회만 실행 _</p>
<ul>
<li>componentDidUpdate() &amp; getDerivedStateFromProps()
: 컴포넌트 업데이트 작업 완료 후 실행되는 메소드</li>
</ul>
<p>위 함수 대신에 쓸 때에 </p>
<pre><code class="language-js">
useEffect(() =&gt; {
    // 코드 적는곳
}, [props명, state명, ...])
</code></pre>
<p><em>=&gt; 2번째 파라미터 배열에 명시한 변수가 변경될 때만 실행</em></p>
<ul>
<li>componentWillUnmount() : 컴포넌트가 DOM에서 제거될 때 호출되는 메소드
대신에 쓸 때에 </li>
</ul>
<pre><code class="language-js">
useEffect(() =&gt; {
    // 코드 적는 곳

    return () =&gt; {
        //  unmount나 unsubscribe 코드
    }
}, [props명, state명, ...])
</code></pre>
<p>_=&gt; effect(함수 혹은 변수 등)가 필요없어지면 return 함수 실행하여 메모리 반환 (언마운트 혹은 구독 취소 시에 사용)
_</p>
<p>이렇게 오늘은 react의 생명 주기와
class형과 함수형의 생명주기의 차이점을 작성해 보았습니다</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[CSS 방법론에 대하여]]></title>
            <link>https://velog.io/@lee_geon_woo4336/CSS-%EB%B0%A9%EB%B2%95%EB%A1%A0%EC%97%90-%EB%8C%80%ED%95%98%EC%97%AC</link>
            <guid>https://velog.io/@lee_geon_woo4336/CSS-%EB%B0%A9%EB%B2%95%EB%A1%A0%EC%97%90-%EB%8C%80%ED%95%98%EC%97%AC</guid>
            <pubDate>Tue, 23 Nov 2021 07:31:38 GMT</pubDate>
            <description><![CDATA[<h1 id="css-방법론이란-">CSS 방법론이란 ?</h1>
<blockquote>
<p><em>CSS의 활용도가 높아지고 대규모 프로젝트가 많아짐에 따라,
복잡한 설계의 필요성을 느끼지 못했던 CSS에도 다양한 방법론들이 생기기 시작했습니다. 따라서 CSS를 어떤 방법으로 짜면 더 효율 적으로 짤 수있는지에 대한 방법론 입니다 .</em></p>
</blockquote>
<p><em>CSS 방법론의 공통적인 특징은 ?</em></p>
<ol>
<li>코드의 재사용성을 높이기</li>
<li>쉬웁 유지보수를 위해</li>
<li>확장이 가능하게 하기</li>
<li>Class명 으로만으로도 무슨 의미인지 알 수 있게 하기</li>
</ol>
<h1 id="방법론의-종류">방법론의 종류</h1>
<ul>
<li>SMACSS (Scalable and Modular Archietechure for CSS)</li>
<li>BEM (Block , Element, Module)</li>
<li>OOCSS (Object Oriented CSS)</li>
</ul>
<h4 id="다양한-방법론들이-있지만-오늘은-대표적인-3가지의-방법론에-대해-알아-보겠습니다">다양한 방법론들이 있지만 오늘은 대표적인 3가지의 방법론에 대해 알아 보겠습니다</h4>
<h3 id="smacss-란-">SMACSS 란 ?</h3>
<ul>
<li>CSS에대한 확장형 모듈식 구조 , 범주화로 패턴화 하고자 하는 방법론</li>
<li>CSS의 프레임워크가 아닌 하나의 스타일 가이드 .</li>
<li>base, layout, module, state, them 다섯가지 범주를 제시</li>
</ul>
<p><em>사용하는 목적은 ?</em></p>
<ol>
<li>class 명을 통한 예측</li>
<li>재사용성</li>
<li>확장가능</li>
<li>유지보수</li>
</ol>
<p>** Base**</p>
<ul>
<li><code>body,p,h1,h2,h3,h4,h5,h6,ul,ol,li,dl,dt,dd,table,th,td,form,fieldset,legend,input,
textarea,button,select</code> 와 같은 기본 스타일 및 스타일을 초기화 제시</li>
</ul>
<p><strong>Layout</strong> </p>
<ul>
<li>주요 요소 (id) 와 하위 요소(class)로 구분하여 접두사를 사용 </li>
</ul>
<p>index.html</p>
<pre><code class="language-js">      &lt;div id = &#39;header&#39;&gt;
          &lt;div class = &#39;l-width&#39;&gt;

          &lt;/div&gt;
      &lt;/div&gt;

      &lt;div id = &#39;aside&#39;&gt;
        &lt;div class = &#39;l-width&#39;&gt;
</code></pre>
<p> css</p>
<pre><code class="language-css"> /* 상위요소 */
#header {
    width: 400px;
}
#aside {
    width: 30px;
}

/* 하위요소  */
.l-width #header {
    width: 600px;
    padding: 10px;
}
.l-width #aside {
    width: 100px
}</code></pre>
<p>위와같이 Layout을 사용 할 수 있다</p>
<p>Module</p>
<ul>
<li>재사용이 가능한 구성 요소 
ex) <pre><code class="language-css">.stick { ... }
.stick-name { ... }
.stick-number { ... }</code></pre>
</li>
</ul>
<p>State </p>
<ul>
<li>요소의 상태 변화를 사용 하고 접두사를 사용
ex) <pre><code class="language-css">.is-error { ... }
.is-hidden { ... }
.is-disabled { ... }</code></pre>
</li>
</ul>
<p>Theme </p>
<ul>
<li>사용자가 선택 가능하도록 스타일을 재선언 하여 사용
ex)<pre><code class="language-css">// base.css
.header {
  background-color: green;
}
// theme.css
.header {
  background-color: red;
}</code></pre>
</li>
</ul>
<h2 id="bem-이란-">BEM 이란 ?</h2>
<ul>
<li>Block(블록), Element(요소), Modifier(상태)로 구분하여 class를 작성하여 엄격한 네이밍 규칙을 가지고 id가 아닌 class만 사용한다 </li>
</ul>
<p><img src="https://images.velog.io/images/lee_geon_woo4336/post/725fe97a-1bdc-45e4-a66d-7c213637a36a/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-11-23%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%204.26.27.png" alt=""></p>
<p>** Block **</p>
<ul>
<li>재사용이 가능한 영역 (header, navigation, footer) 등등 </li>
<li>class명을 하나의 단어를 사용하되 길어 질 경우 하이폰 (-) 으로 나눔
ex)<pre><code>class=&quot;header&quot;</code></pre></li>
</ul>
<p>** Element(요소) **</p>
<ul>
<li>블록의 내부 구성을 표현 </li>
<li>두개의 undercross(__) 로 표현 
ex)<pre><code>class=&quot;header__tap&quot;</code></pre></li>
</ul>
<p>** Modifier **</p>
<ul>
<li>요소의 상태를 표현 </li>
<li>두개의 하이폰(--)으로 표시
ex)<pre><code>class=&quot;header__tap--hide&quot;</code></pre></li>
</ul>
<p>예시 코드 </p>
<pre><code class="language-js">
      &lt;div class=&quot;header&quot;&gt; //block

                &lt;div class=&quot;header__tap&quot;&gt; //element
                    &lt;div class=&quot;header__tap--hide&quot;&gt; //Modifier

                    &lt;/div&gt;
                    &lt;div class=&quot;header__tap--on&quot;&gt;

                    &lt;/div&gt;
                &lt;/div&gt;
            &lt;/div&gt;

            &lt;div class= &quot;header__nav&quot;&gt; //element

            &lt;/div&gt;
          &lt;/div&gt;
    &lt;/div&gt;</code></pre>
<p>CSS</p>
<pre><code class="language-css">/* BEM */

.header{
    width: 600px;
    padding: 10px;
}

.header__tap{
    width: 600px;
    padding: 10px;
}

.header__tap--hide{
    opacity: 0;
}</code></pre>
<h2 id="oocss란-">OOCSS란 ?</h2>
<ul>
<li>모듈방식으로 코딩하여 중복을 최소화 하는 기법</li>
</ul>
<p>OOCSS 적용전 예시 코드</p>
<pre><code class="language-js"> &lt;div class= &quot;btn-wrap&quot;&gt;

        &lt;button class=&quot;twitterbtn&quot;&gt; &lt;/button&gt;

        &lt;button class= &quot;googlebtn&quot;&gt; &lt;/button&gt;

    &lt;/div&gt;
</code></pre>
<p>CSS</p>
<pre><code class="language-css">.twitterbtn {
    border:3px solid #000;
    padding:10px 20px;
    color:#fff;
    border-radius:10px;
    background:red;
  }
  .googlebtn {
    border:3px solid #000;
    padding:10px 20px;
    color:#fff;
    border-radius:10px;
    background:gray;
  }</code></pre>
<p>OOCSS 적용 후</p>
<pre><code class="language-js">    &lt;div class= &quot;btn-wrap&quot;&gt;

        &lt;button class=&quot;twitter btnbase&quot;&gt; &lt;/button&gt;

        &lt;button class= &quot;google btnbase&quot;&gt; &lt;/button&gt;

    &lt;/div&gt;
</code></pre>
<p>CSS</p>
<pre><code class="language-css">  .btnbase {
    border:3px solid #000;
    padding:10px 20px;
    color:#fff;
    border-radius:10px;
  }
  .twitter {
    background:red;
  }
  .google {
    background:gray;
  }</code></pre>
<p>위와 같은 예시 코드로 OOCSS 방법론을 적용하면 googlebtn과 twitterbtn 중복적으로 있는 코드를 밖으로 빼내어서 공통 클래스로 넣는 방식 
이렇게 하면 코드의 재사용도가 높아짐</p>
<p>이렇게 3가지의 방법론에 대해서 알아 보았는데 제가 주로 쓰는 방법은 BEM을 쓰고 있습니다 . 코드가 길어진다는 문제점이 있지만 직관적으로 코드를 알아볼 수 있고 class의 네이밍을 짤 때에 시간을 덜 들이는 것 같습니다 </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[z인덱스에 대해 알아보자 ]]></title>
            <link>https://velog.io/@lee_geon_woo4336/z%EC%9D%B8%EB%8D%B1%EC%8A%A4%EC%97%90-%EB%8C%80%ED%95%B4-%EC%95%8C%EC%95%84%EB%B3%B4%EC%9E%90</link>
            <guid>https://velog.io/@lee_geon_woo4336/z%EC%9D%B8%EB%8D%B1%EC%8A%A4%EC%97%90-%EB%8C%80%ED%95%B4-%EC%95%8C%EC%95%84%EB%B3%B4%EC%9E%90</guid>
            <pubDate>Sat, 31 Jul 2021 09:45:48 GMT</pubDate>
            <description><![CDATA[<p>이번에는 CSS z-index속성에 대해 알아보려 합니다 !</p>
<p>z-index를 사용하는 이유 ? css를 작성하면서 내가 원하는 컨텐츠가 다른 컨텐츠 뒤에 가려져서 난감한 경우가 종종 있습니다 그런 경우를 해결하기 위해 사용하는 속성이 바로 z-index라는 속성입니다 z-index의 기본값은 auto 이고 보통 1, 9, 100, -1, -100등의 숫자로 그 속성의 값을 지정합니다 z-index의 가장 중요한 특징 중 하나는 아무 요소나 다 z-index를 넣는다고 해서 우선순위를 넣을 수 는 없다는 점이다. z-index 속성이 적용되기 위해서는 z-index를 적용한 영역이 position:static 값이 아니어야 합니다 예를 들면</p>
<pre><code class="language-js">&lt;body&gt;
    &lt;div class=&quot;wrap&quot;&gt;
       &lt;div class=&quot;box1&quot;&gt;BOX1&lt;/div&gt;
       &lt;div class=&quot;box2&quot;&gt;BOX2&lt;/div&gt;
    &lt;/div&gt;
 &lt;/body&gt;

 .wrap{
    position:relative;
}
.box1{
    background:skyblue; width:100px; height:100px; z-index:10;
}
.box2{
    position:absolute; 
    top:0; left:0; 
    background:pink; 
    width:50px; 
    height:50px; 
    z-index:1;
}</code></pre>
<p><img src="https://images.velog.io/images/lee_geon_woo4336/post/cb8bd3b4-2d2d-4dad-a3dd-d88239a3872d/box.png" alt="">
이렇게 되어 있는 경우에 z-index가 더 큰 box 1 이 우선으로 나와야 하지만 아래의 이미지 처럼 box2가 위쪽에 있는걸 볼 수 있습니다</p>
<p>그 이유가 바로 .box1에 position 값이 지정되어있지 않기 때문에 z-index 속성이 먹히지 않아서 입니다</p>
<p>이때 box1에 position relative를 주게되면</p>
<pre><code class="language-js">.box1{
    background:skyblue; 
    width:100px; 
    height:100px; 
    z-index:10;
    position: relative;
}</code></pre>
<p><img src="https://images.velog.io/images/lee_geon_woo4336/post/9743e4a6-d189-4d22-949f-a8aa7e48b425/box2.png" alt="">
이와같이 box1이 위로 온것을 확인 할 수 있습니다 !</p>
<p>z-index의 가장 중요하면서 헷갈리기 쉬운 특징 중에 하나는 z-index의 비교 대상을 확인하는 것입니다</p>
<p>z-index는 같은 형제 요소에 선언된 z-index끼리 비교를 합니다. 만약 같은 형제 요소끼리에서 z-index가 선언된 내용이 없으면 자식 요소의 z-index값을 가지고 확인합니다.</p>
<p>위 내용을 예를 들면</p>
<pre><code class="language-js">    &lt;div class=&quot;wrap&quot;&gt;
        &lt;div class=&quot;box1&quot;&gt;
           BOX1
        &lt;/div&gt;
        &lt;div class=&quot;box2&quot;&gt;
           BOX2
           &lt;div class=&quot;box2-1&quot;&gt;BOX2-1&lt;/div&gt;
        &lt;/div&gt;
     &lt;/div&gt;
     .wrap{position:relative;}
.box1{position:absolute;
     top:0; left:0; 
     background:skyblue; 
     width:40px; 
     height:40px; 
     z-index:10;
    }
.box2{
    position:absolute; 
    top:0; 
    left:0; 
    background:pink;
     width:80px; 
     height:80px; 
     z-index:1;
    }
.box2-1{
    position:absolute; 
    top:0; 
    left:0; 
    background:red; 
    width:60px; 
    height:60px; 
    z-index:999;
}</code></pre>
<p><img src="https://images.velog.io/images/lee_geon_woo4336/post/8101e5df-75e5-40d5-9025-29825b35a9a3/box3.png" alt="">
이와같이 z-index가 999인 box2-1이 제일 앞에 있어야 할 것 같지만</p>
<p>아래와 같이 box1 이 위에 있는걸 확인 할 수 있습니다</p>
<p>이는 .box1과 .box2 두 형제 요소끼리의 z-index 비교에서 이미 .box2영역이 z-index:1로 .box1의 z-index:10에서 밀리기 때문에 .box2 자식 요소로 있는 영역에 아무리 z-index를 많이 줘봤자 밀리게 됩니다. 원래 원하던대로 .box2-1를 가장 위쪽으로 위치하게 하기 위해선</p>
<p>.box2에 설정된 z-index:1; 을 제거하면 됩니다.</p>
<pre><code class="language-js">.wrap{position:relative;}
.box1{position:absolute;
     top:0; left:0; 
     background:skyblue; 
     width:40px; 
     height:40px; 
     z-index:10;
    }
.box2{
    position:absolute; 
    top:0; 
    left:0; 
    background:pink;
     width:80px; 
     height:80px; 
    }
.box2-1{
    position:absolute; 
    top:0; 
    left:0; 
    background:red; 
    width:60px; 
    height:60px; 
    z-index:999;
}</code></pre>
<p>아래와 같이 변한걸 볼 수 있습니다 !
<img src="https://images.velog.io/images/lee_geon_woo4336/post/c7e950db-b2b5-4dd7-970c-4673e4b9fa66/box4.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[React 라이브러리 Slick을 사용한 slider구현 ]]></title>
            <link>https://velog.io/@lee_geon_woo4336/React-%EB%9D%BC%EC%9D%B4%EB%B8%8C%EB%9F%AC%EB%A6%AC-Slick%EC%9D%84-%EC%82%AC%EC%9A%A9%ED%95%9C-slider%EA%B5%AC%ED%98%84</link>
            <guid>https://velog.io/@lee_geon_woo4336/React-%EB%9D%BC%EC%9D%B4%EB%B8%8C%EB%9F%AC%EB%A6%AC-Slick%EC%9D%84-%EC%82%AC%EC%9A%A9%ED%95%9C-slider%EA%B5%AC%ED%98%84</guid>
            <pubDate>Fri, 16 Jul 2021 13:25:49 GMT</pubDate>
            <description><![CDATA[<h1 id="til-2021---07---16-📖-">TIL 2021 - 07 - 16 📖 !</h1>
<p>이번에는 라이브러리를 이용한 슬라이더를 구현해 보았다 확실히 hooks만 사용한 것 보단 훨씬 쉽게 구현을했다 .
라이브러리는 Slick을 사용했고 강의를 보면서 배워 보았다 </p>
<p><img src="https://images.velog.io/images/lee_geon_woo4336/post/272fe481-c326-4c65-adc4-2bdfad68bbff/slickSlide.gif" alt="">
 가운데가 맞지 않는건 내가 동영상 캡쳐를 할때 가운대를 맞추지 않아서 이다 Slick을 사용하는 방법은 </p>
<p> <a href="https://github.com/Geonwoo-Lee/TIL-/blob/main/TIL/TIL20210715.MD">slick사용법</a></p>
<p>이곳에 자세히 적어 놓았다 slick 라이브러리와 css를 연결해야 하는데 </p>
<pre><code class="language-js">@import &#39;~slick-carousel/slick/slick.css&#39;;
@import &#39;~slick-carousel/slick/slick-theme.css&#39;;</code></pre>
<p>많은곳에서 이렇게 나와 있지만 애러가 너무 많이 발생한다 따라서 ~ 를 없애고 </p>
<pre><code class="language-js">@import &#39;slick-carousel/slick/slick.css&#39;;
@import &#39;slick-carousel/slick/slick-theme.css&#39;;</code></pre>
<p>이렇게 쓰는걸 추천한다 </p>
<pre><code class="language-js">
@import &#39;slick-carousel/slick/slick.css&#39;;
@import &#39;slick-carousel/slick/slick-theme.css&#39;;

.App {
  width: 50%;
  margin: 10rem auto;
  height: 570px;
}

.slide img {
  width: 20rem;
  margin: 0 auto;

}

.slide{
  transform: scale(0.2);
  transition: transform 300ms;
  opacity: 0.5;
}

.activeSlide {
  transform: scale(1.1);
  opacity: 1;
}

.arrow{
  background-color: white;
  position: absolute;
  cursor: pointer;
  z-index: 10;
}

.arrow svg {
  transition: color 300ms;
}

.arrow svg:hover{
  color: #68edff;
}

.next {
  right: 0%;
  top: 50%;
}

.prev {
  left: 0%;
  top: 50%;
}</code></pre>
<p>css 코드이다 </p>
<pre><code class="language-js">import &#39;./App.css&#39;;
import {useState} from &#39;react&#39;
import Slider from &#39;react-slick&#39;
import astronaut from &#39;./assets/astronaut.png&#39;
import celebrating from &#39;./assets/celebrating.png&#39;
import education from &#39;./assets/education.png&#39;
import taken from &#39;./assets/taken.png&#39;
import { FaArrowRight, FaArrowLeft } from &#39;react-icons/fa&#39;


const images = [astronaut, celebrating, education, taken]

function App() {

  const NextArrow = ({onClick}) =&gt; {
    return (
      &lt;div className = &#39;arrow next&#39; onClick = {onClick}&gt; 
      &lt;FaArrowRight/&gt;
      &lt;/div&gt;
    )
  }

  const PrevArrow = ({onClick}) =&gt; {
    return (
      &lt;div className = &#39;arrow prev&#39; onClick = {onClick}&gt; 
      &lt;FaArrowLeft/&gt;
      &lt;/div&gt;
    )
  }

  const [imageIndex, setImageIndex] = useState(0)



  const settings = {
    infinite: true,
    lazyLoad: true,
    speed: 300, 
    slidesToShow: 3,
    centerMode: true,
    centerPadding: 0,
    nextArrow: &lt;NextArrow/&gt;,
    prevArrow: &lt;PrevArrow/&gt;,
    beforeChange: (crruent, next) =&gt; setImageIndex(next)
  };

  return (
    &lt;div className = &#39;App&#39;&gt;
      &lt;Slider {...settings}&gt;
      {images.map((img, idx) =&gt; (
        &lt;div className = {idx === imageIndex ? &quot;slide activeSlide&quot; : &quot;slide&quot;}&gt;
          &lt;img src={img} alt = {img}/&gt;
        &lt;/div&gt;
      ))}
      &lt;/Slider&gt; 
    &lt;/div&gt;
  );
}

export default App;
</code></pre>
<p>app.js 의 코드이다 </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[React hooks로 slider 구현 ]]></title>
            <link>https://velog.io/@lee_geon_woo4336/React-hooks%EB%A1%9C-slider-%EA%B5%AC%ED%98%84</link>
            <guid>https://velog.io/@lee_geon_woo4336/React-hooks%EB%A1%9C-slider-%EA%B5%AC%ED%98%84</guid>
            <pubDate>Fri, 16 Jul 2021 13:24:50 GMT</pubDate>
            <description><![CDATA[<h1 id="til-2021---07---16-📖--">TIL 2021 - 07 - 16 📖  !</h1>
<ul>
<li>오늘은 사진 슬라이드 기능에 대해 공부하고 기능을 구현해 보았다 우선 react Hooks 로 구현을 해보았는데 생각보다 쉽지 않았다 상태관리와 jpeg 파일로 전부 하나하나 만들어 주어야 해서 힘들었다 우선 </li>
</ul>
<p><img src="https://images.velog.io/images/lee_geon_woo4336/post/4bfe076c-a004-4754-9783-109b1124b5dc/slide.gif" alt=""></p>
<p>이런식으로 구현을 해보았는데 치명적인 단점이 있다 .
사진의 범위를 넘어가면 사진이 나오지 않는데 이부분을 조금만 더 보안하면 될 것 같다
그리고 사진들의 파일 이름을 전부 같게 해주고 뒤에 숫자로 count를 하는식으로 구현을 해서 숫자 범위를 다시 정해주어야 겠다 </p>
<p>코드는 </p>
<pre><code class="language-js">function Thumbnail({source, alt}) {
    const [count, setCount] = useState(2)
    const handleClick = () =&gt; {
        setCount(count +1)
    }
   const disHandleClick = () =&gt; {
       setCount(count -1)
   }
    return (
   &lt;&gt;
    &lt;Image src = {`${source}${count}.jpeg`} alt= {alt} className = &#39;thumbnail&#39;/&gt;
    &lt;PrevBtn onClick = {disHandleClick}&gt;Prev&lt;/PrevBtn&gt;
    &lt;NextBtn onClick = {handleClick}&gt;Next&lt;/NextBtn&gt;
    &lt;/&gt;
    )
}
export default Thumbnail</code></pre>
<p>```js</p>
<p>export const Slide = ({theme}) =&gt; {
    const [basicImages, setBasicImages] = useState(images[0])
    return ( 
     <Thumbnail source = {basicImages.src} alt = {basicImages.alt} key ={basicImages.id} theme= {theme}  />
    )
}</p>
<p>이렇게 구현을 해보았따 </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Styled component 를 이용한 웹사이트 , Dark mode와 light mode 구현 ]]></title>
            <link>https://velog.io/@lee_geon_woo4336/Styled-component-%EB%A5%BC-%EC%9D%B4%EC%9A%A9%ED%95%9C-%EC%9B%B9%EC%82%AC%EC%9D%B4%ED%8A%B8-Dark-mode%EC%99%80-light-mode-%EA%B5%AC%ED%98%84</link>
            <guid>https://velog.io/@lee_geon_woo4336/Styled-component-%EB%A5%BC-%EC%9D%B4%EC%9A%A9%ED%95%9C-%EC%9B%B9%EC%82%AC%EC%9D%B4%ED%8A%B8-Dark-mode%EC%99%80-light-mode-%EA%B5%AC%ED%98%84</guid>
            <pubDate>Wed, 07 Jul 2021 12:48:40 GMT</pubDate>
            <description><![CDATA[<p>react로 웹사이트를 구현해 보았습니다 . HTML로 할 때에는 여러 코드가 복잡하게 얽혀 있었지만 react로 하니 코드가 복잡하지 않아 좋았습니다 .</p>
<p><img src="https://images.velog.io/images/lee_geon_woo4336/post/b398fd29-aa45-4ff8-b2cd-5c92b0585fe2/realDarkmode.gif" alt=""></p>
<p><img src="https://images.velog.io/images/lee_geon_woo4336/post/61d7af4a-4196-4d9e-86eb-e43825f76c42/realDarkmode2.gif" alt=""></p>
<p>코드는 너무 길어 따로 써놓지 않고 
<a href="https://github.com/Geonwoo-Lee/Darkmode">https://github.com/Geonwoo-Lee/Darkmode</a>
이 주소로 들어가면 코드를 보실 수 있습니다 </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Styled Component]]></title>
            <link>https://velog.io/@lee_geon_woo4336/Styled-Component</link>
            <guid>https://velog.io/@lee_geon_woo4336/Styled-Component</guid>
            <pubDate>Mon, 05 Jul 2021 12:55:25 GMT</pubDate>
            <description><![CDATA[<p>오늘은 Styled Component에 대해 배워보았습니다 다소 헷갈리는게 있지만 정리해보겠습니다 .</p>
<ul>
<li><p>Styled Component 란 무엇인가 </p>
<br/>
styles 지정과 React component를 생성을 동시에 할 수 있는 유용한 녀석이다 
</li>
<li><p>어떻게 사용하는가 </p>
<br/>
해당 레포 프로젝트 안에서 ```npm install --save styled-components```로 install 해준뒤에 ```import styled from "styled-components";``` 를 해주면 사용 할 수 있다 
</li>
<li><p>프로젝트 내에서 어떻게 Styled Component로 Component 를 만들까 ? 
간단한 예로 우리가 버튼을 만든다고 하자 그러면 </p>
</li>
</ul>
<pre><code class="language-js">const Button = styled.button`
 background-color: blue;
 &amp;:hover {
    background-color: red;
  }
  font-size: 1em;
  margin: 1em;
  padding: 0.25em 1em;
  border: 2px solid palevioletred;
  border-radius: 3px;
`;

export default function App() {
  return (
    &lt;div className=&quot;App&quot;&gt;
      &lt;Button&gt;Normal&lt;/Button&gt;
      &lt;Button primary&gt;Primary&lt;/Button&gt;
    &lt;/div&gt;
  );
}</code></pre>
<p><img src="https://images.velog.io/images/lee_geon_woo4336/post/76655c35-72f6-4a50-9159-ba5873909042/button1.png" alt="">
<br/>
<br/>
<br/>
이런식으로 버튼을 만들어줄 수 있다 이렇게 const 로 외부에서 선언해준 만들어준 녀석을 App함수 내에서 컴포넌트로 사용 할 수 있다 만약 저녀석이 컴포넌트 라면 props나 useState로 상태를 줄 수도 있지 않을까 ? 당연히 된다 </p>
<pre><code class="language-js">const Button = styled.button`

  background: ${(props) =&gt; (props.primary ? &quot;palevioletred&quot; : &quot;white&quot;)};
  color: ${(props) =&gt; (props.primary ? &quot;white&quot; : &quot;palevioletred&quot;)};
  &amp;:hover {
    background-color: red;
  }
  font-size: 1em;
  margin: 1em;
  padding: 0.25em 1em;
  border: 2px solid palevioletred;
  border-radius: 3px;
`;

export default function App() {
  return (
    &lt;div className=&quot;App&quot;&gt;
      &lt;Button&gt;Normal&lt;/Button&gt;
      &lt;Button primary&gt;Primary&lt;/Button&gt;
    &lt;/div&gt;
  );
}</code></pre>
<p><img src="https://images.velog.io/images/lee_geon_woo4336/post/22f88c6b-00e7-48b5-8aad-e5ab6986fe07/button2.png" alt="">
보다시피 두 버튼의 색깔이 다르다 Button 컴포넌트 안에 primary라는 값을 프롭스로 받아와서 primary 라는 값이 있다면 색깔과 글자색을 바꿔준것이다 . 이런식으로 useState도 사용이 가능하다. 또한 Nesting이 가능해서 hover를 넣을 때에도 &amp;로 네스팅 할 수 있다 </p>
<p>네스팅이란 ? 
네스팅이란 Scss에서 사용되는 문법인데 예를들어 </p>
<pre><code class="language-js">&lt;div class = &#39;boxWrap-&#39;&gt;
  &lt;div class = &#39;boxwrap-box1&#39;&gt; 
   box
  &lt;/div&gt;
  &lt;div class = &#39;boxwrap-box2&#39;&gt; 
   box
  &lt;/div&gt;
  &lt;div class = &#39;boxwrap-box3&#39;&gt; 
   box
  &lt;/div&gt;
&lt;/div&gt;</code></pre>
<p>이러한 박스 wrap 안에 감싸진 box1, 2, 3 의 자식들이 있다고 가정해보자 
그러면 Css 스타일을 넣어주기 위해선 
.boxWrap {
    //스타일
}</p>
<p>.boxwrap-box1{
    //스타일
}</p>
<p>이런식으러 스타일을 주었지만 nesting을 사용하면</p>
<p>.boxwrap{
    //스타일</p>
<pre><code>&amp;-box1{
    //스타일 
}</code></pre><p>}
이런식으로 자식으로 바로 스타일이 가능하다  &amp;는 자식의 부모 이름 그 자체이다 따라서 지금 &amp;의 값은 boxwrap- 이 된것이다 이게 Nesting인데 Styled component에서도 네스팅이 가능합니다 .</p>
<p>다음은 atts를 사용한 다이나믹한 컴포넌트를 만들어봅시다 </p>
<pre><code class="language-js">const Input = styled.input.attrs(
  props =&gt; ({ type: &quot;password&quot;,   size: props.size || &quot;100px&quot;,
 }))` 
 width: ${props =&gt; props.size}; `; 


export default function App() {
  return (
    &lt;div className=&quot;App&quot;&gt;
      &lt;Input placeholder=&quot;default size input!&quot;/&gt;
      &lt;br/&gt; 
      &lt;Input placeholder=&quot;bigger size input!&quot; size={&quot;200px&quot;} /&gt;
      &lt;br/&gt;
      &lt;Input/&gt;
    &lt;/div&gt;
  );
}</code></pre>
<p><img src="https://images.velog.io/images/lee_geon_woo4336/post/c7c9b480-7e11-4464-9951-7685cb10ca3a/input.png" alt="">
<br/>
<br/>
이렇게 Input 의 타입을 지정해줄 수 있고 props 로 size의 값이 있다면 그 값으로 지정해주고 그렇지 않을때에는 100px로 지정해 줄 수 있습니다.</p>
<p>다음으로는 애니메이션에 대해서 알아봅시다 .</p>
<pre><code class="language-js">import styled, {keyframes,} from &quot;styled-components&quot;;

const bounce = keyframes`
  0% {
    transform: scale(1)
  }
  50% {
    transform: scale(0)
  }
  100% {
    transform: scale(1)
  }
`;


const Circle = styled.div`
  width: 300px;
  height: 300px;
  border-radius: 50%;
  background-color: #ff7979;
  animation: ${bounce} 2s infinite;
`;

export default function App() {
  return (
    &lt;div className=&quot;App&quot;&gt;
      &lt;br/&gt;
     &lt;Circle/&gt;
    &lt;/div&gt;
  );
}</code></pre>
<p><img src="https://images.velog.io/images/lee_geon_woo4336/post/f12dbcdd-f305-4945-91c1-75d4938d6305/circle.gif" alt="">
애니메이션을 구현 할 때에는 keyframe이라는걸 이용해서 만드는데 keyframe은 쉽게 말해 이건 애니메이션이야 ~ 라고 넣어주는겁니다 우선 Circle이라는 공을 만들어 주고 거기에 animation을 사용해서 우리가 만들어준 애니메이션을 ${}안에 넣어주기만 하면 됩니다 쉽져 ? 
그리고 ketframe을 사용하기 때문에 <code>import styled, {keyframes,} from &quot;styled-components&quot;;</code> import 도 꼭 해줍시다 ! </p>
<p>이렇게 Styled Component로 다이나믹하고 스타일리쉬한 Component들을 만들어 줄 수 있었습니다. </p>
<p>구현해보았던것 
<br/>
<br/>
<br/>
<img src="https://images.velog.io/images/lee_geon_woo4336/post/e02dd84f-4d16-431e-9ef2-26d4a8797d72/whole.gif" alt=""></p>
<pre><code class="language-js">import styled, {keyframes,} from &quot;styled-components&quot;;

const Button = styled.button`
  /* Adapt the colors based on primary prop */
  background: ${(props) =&gt; (props.primary ? &quot;palevioletred&quot; : &quot;white&quot;)};
  color: ${(props) =&gt; (props.primary ? &quot;white&quot; : &quot;palevioletred&quot;)};
  &amp;:hover {
    background-color: red;
  }
  font-size: 1em;
  margin: 1em;
  padding: 0.25em 1em;
  border: 2px solid palevioletred;
  border-radius: 3px;
`;

const Tomato = styled(Button)`
  color: tomato;
  border-color: tomato;
`;

const Input = styled.input.attrs(
  props =&gt; ({ type: &quot;password&quot;,   size: props.size || &quot;100px&quot;,
 }))` 
 width: ${props =&gt; props.size}; `; 

const bounce = keyframes`
  0% {
    transform: scale(1)
  }
  50% {
    transform: scale(0)
  }
  100% {
    transform: scale(1)
  }
`;

const Circle = styled.div`
  width: 300px;
  height: 300px;
  border-radius: 50%;
  background-color: #ff7979;
  animation: ${bounce} 2s infinite;
`;







export default function App() {
  return (
    &lt;div className=&quot;App&quot;&gt;
      &lt;Button&gt;Normal&lt;/Button&gt;
      &lt;Button primary&gt;Primary&lt;/Button&gt;
      &lt;Tomato&gt;Tomato&lt;/Tomato&gt;
      &lt;br/&gt;
      &lt;Input placeholder=&quot;default size input!&quot;/&gt;
      &lt;br/&gt; 
      &lt;Input placeholder=&quot;bigger size input!&quot; size={&quot;200px&quot;} /&gt;
      &lt;br/&gt;
      &lt;Input/&gt;
      &lt;br/&gt;
      &lt;br/&gt;
      &lt;br/&gt;
      &lt;br/&gt;
      &lt;br/&gt;
     &lt;Circle/&gt;
    &lt;/div&gt;
  );
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[Express 2]]></title>
            <link>https://velog.io/@lee_geon_woo4336/Express-2</link>
            <guid>https://velog.io/@lee_geon_woo4336/Express-2</guid>
            <pubDate>Sat, 03 Jul 2021 15:05:32 GMT</pubDate>
            <description><![CDATA[<ul>
<li><p>Express의 사용법에 대해서 정리를 해보려고 합니다 </p>
</li>
<li><p>express의 기본적인틀을 먼저 보게되면 </p>
<pre><code class="language-js">// 외부에서 가져온 모듈
// 예를 들면 express와 cors 가 있습니다 
</code></pre>
</li>
</ul>
<p>// 내부 모듈
// 이미 있는 모듈들을 사용 할때에 </p>
<p>// 전역 변수
//예를 들면 
const app = express 와 같이 기본적인 틀을 정해줄때 쓰는 변수 </p>
<p>// 라우트 모듈
app.get(&#39;/&#39;,fuction(req, res){ </p>
<p>})
이것과 같이 라우팅 해주는 모듈</p>
<p>// 실행로직
app.use(cors()) 와 같이 실행할때 필요한 모듈 </p>
<p>// listen 꼭 정의
app.listen(port, ()=&gt;{
    console.log(&quot;Start Server!!&quot;)
})
}</p>
<pre><code>
- 다음으로 알아볼 건 use 메서드를 사용해서 내가 이 서버를 실행하기 전에 미리 설정해놓는 설정값이라고 생각 하면 됩니다 

```js
// 외부 모듈
const express = require(&#39;express&#39;)
const cors = require(&#39;cors&#39;)

//전역 변수
const app = express();
const port = 5000;
const ip = &#39;localhost&#39;;

//실행 로직
app.use(express.json()); //espress는 json형식으로 할거라고 설정
app.use(cors()); // 이 서버의 cors는 이렇게 설정할거라고 설정 </code></pre><p>위와같이 외부 모듈과 전역변수를 적용해주고 실행로직을 작성 해놓습니다 </p>
<ul>
<li><p>express의 장점 </p>
</li>
<li><p>express에서는 http 메서드들이이미 구현이 되어 있어서 app.메서드 를 통해서 요청을 받아 올 수 있고 cors를 설치하면 따로 corsHeader를 작성 할 필요가 없어서 저 cors 한줄로 cors요청을 다 해결 할 수 있습니다 . </p>
</li>
<li><p>상태 처리를 따로 해주지 않아도 서버의 상태에 따라서 상태처리를 해줍니다 ! </p>
</li>
<li><p>express 에서는 data 값을 req.body 로 받아와서 훨씬 더 간편하게 사용 할 수 있습니다 ! </p>
</li>
<li><p>정리 </p>
</li>
<li><p>express의 기본적인 구조를 분류해서 작성하기</p>
</li>
<li><p>서버를 실행할 때에 미리 설정 해놓고 싶은 설정 값이  use메서드를 사용하여 설정해놓기 </p>
</li>
<li><p>POST요청에서 req.body를 활용해서 응답 로직을 더 깔끔하게 보낼 수 있다 </p>
</li>
<li><p>cors를 사용해서 불필요한 CorsHeader 작성을 하지 않아도 된다 </p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Express ]]></title>
            <link>https://velog.io/@lee_geon_woo4336/Express</link>
            <guid>https://velog.io/@lee_geon_woo4336/Express</guid>
            <pubDate>Sat, 03 Jul 2021 15:05:02 GMT</pubDate>
            <description><![CDATA[<ul>
<li><p>Express
이번에는 노드 서버를 빠르고 간결하게 사용하기 위해 만들어진 웹 프레임워크 Express 를 사용해 보랴고 합니다 </p>
</li>
<li><p>express를 사용하기 위해서는 먼저 터미널에서 express를 설치해야 합니다 
<code>$ npm install express</code></p>
</li>
</ul>
<p>설치를 했다면 express가 어떻게 구성이 되어있고 어떻게 사용이 가능한지 알아보겠습니다 .</p>
<ul>
<li>express 의 기본 구성</li>
</ul>
<pre><code class="language-js">const express = require(&#39;express&#39;) // http를 불러온것 처럼 require를 통해 express를 불러옵니다.
const app = express() // require를 통해 불러온 express를 app이라는 변수에 담아 사용합니다
const PORT = 3000 //사용하고자 하는 포트를 선언 해줍니다 


app.listen(port, () =&gt; {  
  console.log(`Example app listening at http://localhost:${port}`)
})
//listen 서버의 요청 처리를 대기하는 중입니다 </code></pre>
<ul>
<li>다음으로 express의 예제를 통해 express를 어떻게 사용하고 작동되는지 알아보겠습니다 </li>
</ul>
<pre><code class="language-js">const express = require(&#39;express&#39;)
const app = express()
const port = 3000

app.get(&#39;/&#39;, (req, res) =&gt; {
  res.send(&#39;Hi&#39;)
})

app.listen(port, () =&gt; {
  console.log(&#39;Bye&#39;)
})
</code></pre>
<p>이렇게 get요청 메서드를 사용하고 &#39;/&#39; 경로로 인자로 req, res를 받습니다(req 는 request 요청 res 는 response 응답 의 약자 )
res.send로 요청에 응답할 내용을 입력해 주었습니다 
그럼 이 코드를 실행하면 터미널에서는 Bye 가 찍히고 브라우저에서는 Hi가 출력되게 됩니다 </p>
<ul>
<li>express에서의 라우팅 
<code>app.메서드(PAHT,HANDLER) // 기본적인 라우터 형식</code>
PATH에서는 경로가 들어가고 HANDLER부분에서는 라우터가 일치 할 때 실행되는 콜백 함수입니다 .
사용 예제<pre><code class="language-js">// get요청이 &#39;/&#39;의 경로로 들어왔을 경우 
// 홈 페이지에서 Hello World!로 응답:
app.get(&#39;/&#39;, function (req, res) {
res.send(&#39;Hello World!&#39;);
});
</code></pre>
</li>
</ul>
<p>// post 요청이 &#39;/&#39;의 경로로 들어온 경우
// 애플리케이션의 홈 페이지인 루트 라우트(/)에서 POST 요청에 응답:
app.post(&#39;/&#39;, function (req, res) {
  res.send(&#39;Got a POST request&#39;);
});</p>
<p>// put요청이 &#39;/user&#39;의 경로로 들어온 경우
// /user 라우트에 대한 PUT 요청에 응답:
app.put(&#39;/user&#39;, function (req, res) {
  res.send(&#39;Got a PUT request at /user&#39;);
});</p>
<p>// delete요창이 &#39;/user&#39;로 들어온 경우 
// /user 라우트에 대한 DELETE 요청에 응답:
app.delete(&#39;/user&#39;, function (req, res) {
  res.send(&#39;Got a DELETE request at /user&#39;);
});</p>
<pre><code>
- express로 /upper 와 /lower 구현했던것 구현해보기 

```js 

// 외부 모듈
const express = require(&#39;express&#39;)  //express모듈 불러오기 
const cors = require(&#39;cors&#39;) // cors 미들웨어를 불러오기

//전역 변수
const app = express(); // 모듈을 app이라는 변수에 담아 서버 만들기 
const port = 5000; //포트 5000 사용
const ip = &#39;localhost&#39;; //아이피 localhost사용 

//실행 로직
app.use(express.static(&#39;client&#39;)) //사용할 파일을 폴더에서 불러와 주는 것입니다 
app.use(express.json({strict: false})); //json형태가 아닌 string파일로 주고받을 거기 때문에 이렇게 해주어야 json이 아닌 원시자료형 을 받아올 수 있습니다 
app.use(cors()); // 모든 요청에 대해 CORS 를 허용한다.

 //use는 등록해주다라는 개념으로 이해하기!!! express에 ~를 사용할것을 알려줄꺼야~

//POST 
//upper 구현하기
app.post(&#39;/upper&#39;, function(req,res){
    console.log(req.body) // 터미널 콘솔 확인해보기 
    let buffer = req.body 
    buffer = buffer.toUpperCase()
    console.log(buffer) // 대문자로 변환되었는지 확인
    res.json(buffer) // 바디데이터 Json parsing해서 내보내기
})

//loewr 구현하기
app.post(&#39;/lower&#39;, function(req,res){
    res.json(req.body.toLowerCase())
})

app.listen(port, ()=&gt;{
  console.log(`http server listen on ${ip}:${port}`);
})</code></pre><p>이렇게 express로 구현을 해주면 nodeserver로 전부 구현하고 헤더를 넣어 주는 것 보다 훨씬 더 간단하게 만들어 줄 수 있습니다 .</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Node Server]]></title>
            <link>https://velog.io/@lee_geon_woo4336/Node-Server-uvdu86eh</link>
            <guid>https://velog.io/@lee_geon_woo4336/Node-Server-uvdu86eh</guid>
            <pubDate>Sat, 03 Jul 2021 15:03:14 GMT</pubDate>
            <description><![CDATA[<p>노드 서버에서 요청 메서드 처리하는 방법을 알아보겠습니다 </p>
<p>이번 스프린트 에서는 upper와 lower server를 구현해보았고 그 구현 과정을 설명 해보겠습니다</p>
<pre><code class="language-js">let http = require(&#39;http&#39;)
const PORT = 3000;
const IP = &#39;localhost&#39;


const server = http.createServer((request, response) =&gt; {
    if(request.method === &#39;POST&#39;){

    }
   if(request.method === &#39;OPTION&#39;){

    }

})</code></pre>
<p>이런식으로 메소드의 구간을 나누어서 요청되는 메소드가 어떤 메소드인지에 따라 알맞은 값을 줄 수 있습니다 </p>
<p>그 다음으로 POST 메소드로 요청이 들어온 경우에는 우리가 구현하고자 했던 /upper 와 /lower로 라우터를 정의 해줄 수 있습니다 
러우터란 ?
URI(경로) 및 특정한 HTTP(Hyper Text Transfet Protocol) 요청 메소드(GET,POST)의 클라이언트 요청에 응답하는 방법을 결정하고  각 라우트는 하나 이상의 핸들러 함수를 가질 수 있고, 라우트가 일치할 때 실행됩니다.</p>
<pre><code class="language-js">//GET 방식의 METHOD
app.get(&#39;/&#39;, function (req, res) {
    res.send(&quot;hello getMethod&quot;)
})

//POST 방식의 MEHTOD
app.post(&#39;/&#39;, function (req, res) {
    res.send(&quot;Hello postMethod&quot;)
})</code></pre>
<p>라우터의 사용 예시 </p>
<pre><code class="language-js">const server = http.createServer((request, response) =&gt; {
if(request.method === &quot;POST&quot;){
    if(request.url === &#39;/lower&#39;){


    }else
    if(request.url === &#39;/upper&#39;){


    }
}

if(request.method === &quot;OPTION&quot;){

}
});</code></pre>
<p>이렇게 라우터로 POST 요청으로 lower 요청이 왔을때와 upper 요청이 들어왔을때를 만들어 줄 수 있습니다 
if POST요청이 들어왔을때 =&gt; 그안에서의 lower 나 upper가 들어왔을 때 를 구현 해준 것입니다 </p>
<pre><code class="language-js">const server = http.createServer((request, response) =&gt; {
if(request.method === &quot;POST&quot;){
    if(request.url === &#39;/lower&#39;){
    let data = &#39;&#39;

    request.on(&#39;data&#39;,(chunk)=&gt;{ 
    data = data + chunk      
    })

    request.on(&#39;end&#39;,()=&gt;{ 
    data
    })

    }else
    if(request.url === &#39;/upper&#39;){


    }


if(request.method === &quot;OPTION&quot;){

}
});</code></pre>
<p>그 다음에는 request on 을 이용하여 데이터를 받아옵니다 .
on(&#39;data&#39;, 콜백), on(&#39;end&#39;, 콜백) 으로 각각 request에 data가 있을 경우 처리를 해주는 부분과 data처리가 끝났음을 알려주는 부분으로 작성해줍니다  on 이라는 데이터 키워드를 넣어 주면 chunk 를 통해 바디의 값을 받아 올 수 있습니다 .
여기 까지 해주면 데이터를 어떯게 바꾸어 줄건지와 상태에 응답을 해주는 것 과 애러 처리를 해주면 됩니다 </p>
<p>지금까지의 내용을 총 정리해서 부분부분 분리 해서 보자면 
이렇게 네가지의 형태로 볼 수 있습니다 </p>
<pre><code class="language-js">//-------------------------------------------------------------------------------------------
// 첫번째로 서버의 기본 구성과 서버를 만들어준 부분 
let http = require(&#39;http&#39;)
const PORT = 3000;
const IP = &#39;localhost&#39;

const server = http.createServer((request, response) =&gt; {
//-------------------------------------------------------------------------------------------
//if문을 통해 서버에 요청된 메소드를 확인하여 그 메소드가 요청하는 값을 전달 해주는 부분 

if(request.method === &quot;POST&quot;){
  if(request.url === &#39;/lower&#39;){//post 요청으로 lower이 들어왔을때 데이터를 처리해주는 부분 
    let data = &quot;&quot;;
    request.on(&#39;data&#39;,(chunk)=&gt;{  //요청으로 들어온데이터를 chunk로 바디값을 받아와준 부분 
      data = data + chunk       
    })

    request.on(&#39;end&#39;,()=&gt;{ //이 요청이 끝날때 callback으로 요청을 처리해준부분 
      data = data.toLowerCase() //lower가 들어왔으니 데이터를 lower 해준 부분 
      response.writeHead(201, defaultCorsHeader);//데이터의 상태코드와 cors응답 , 헤더를 넣어주고
      response.end(data)//마지막에 응답을 하기위한 메서드 end를 써주며 데이터를 전달 해줍니다 
    })
//-------------------------------------------------------------------------------------------

  }else 
  if(request.url === &#39;/upper&#39;){ //이번에는 uppet가 들어온 경우에는 똑같은 동작을 하지만 
    let data = &quot;&quot;;

    request.on(&#39;data&#39;,(chunk)=&gt;{ 
      data = data + chunk       

    request.on(&#39;end&#39;,()=&gt;{ 
      data = data.toUpperCase() //데이터를 upperCase로 만들어주기만하면 됩니다 
      response.writeHead(201, defaultCorsHeader);
      response.end(data)
    })
//-------------------------------------------------------------------------------------------
  }else{
    response.writeHead(404, defaultCorsHeader);//그리고 그외에 다른 post요청이 들어왔을 때에는 애러를 처리해줍니다 404의 상태 코드로 애러라는것을 명시해주고 
    response.end(&quot;Not found 404&quot;);
    //데이터를 전달 해주는 부분에서는 애러메세지를 띄워줍니다 
  }
}</code></pre>
]]></description>
        </item>
    </channel>
</rss>