<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>wynter_kim.log</title>
        <link>https://velog.io/</link>
        <description>Always Develop</description>
        <lastBuildDate>Sun, 04 Sep 2022 06:44:05 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>wynter_kim.log</title>
            <url>https://images.velog.io/images/wynter_kim/profile/648f7bd1-7515-4af3-a72d-55b393a200cd/KakaoTalk_20211122_225812404.jpg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. wynter_kim.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/wynter_kim" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[Next.js 파헤치기(1)]]></title>
            <link>https://velog.io/@wynter_kim/Next.js-%ED%8C%8C%ED%97%A4%EC%B9%98%EA%B8%B01</link>
            <guid>https://velog.io/@wynter_kim/Next.js-%ED%8C%8C%ED%97%A4%EC%B9%98%EA%B8%B01</guid>
            <pubDate>Sun, 04 Sep 2022 06:44:05 GMT</pubDate>
            <description><![CDATA[<h1 id="nextjs">Next.js</h1>
<p>리액트 프레임워크</p>
<p><strong>SEO(Search Engine Optimization)을 위한 SSR(Server-Side Rendering)</strong> 때문에 많이 쓴다고 알고 있다.</p>
<p><a href="https://nextjs.org/learn/basics/create-nextjs-app">넥스트에서 제공하는 튜토리얼</a>을 해석하면서 왜 쓰는지 알아봐야겠다</p>
<h3 id="create-a-nextjs-app">Create a Next.js App</h3>
<p>완전한 리액트 웹 어플리케이션을 빌드하라면 고려해야할 중요한 사항들이 있음</p>
<ul>
<li>코드는 웹팩같은 번들러에 의해 번들링되어야하고, 바벨같은 컴파일러에 의해 변환(transform)되어야함.</li>
<li>코드스플리팅같은 프로덕션 최적화를 해야함.</li>
<li>SEO와 성능을 위해 어떤 페이지를 정적으로 프리렌더를 원하고 싶을 수 있음. SSR, CSR을 사용하고 싶을 수도 있음</li>
<li>리액트 앱을 데이터 저장소에 연결하기 위해 서버쪽 코드를 작성해야할 수도 있음</li>
</ul>
<p>💡 참고 )</p>
<ul>
<li>번들링?
모듈화했던 파일들을 하나로 묶어주는 작업
<a href="https://kangdanne.tistory.com/190">https://kangdanne.tistory.com/190</a></li>
<li>바벨?
구식 브라우저 환경에서 호환가능한 코드로 변환하는 데에 사용되는 트랜스파일러</li>
<li>컴파일 vs 트랜스파일
컴파일은 다른 언어로 변환, 트랜스파일은 비슷한 수준의 추상화를가진 다른 언어로 변환(ex. es6 → es5)
<a href="https://ideveloper2.tistory.com/166">https://ideveloper2.tistory.com/166</a></li>
<li>코드스플리팅?
당장 필요없는 코드는 나중에 필요할 때 불러오는 방식
<a href="https://velog.io/@velopert/react-code-splitting">https://velog.io/@velopert/react-code-splitting</a></li>
</ul>
<p><em>프레임워크</em>는 이런 문제들을 해결할 수 있다. 사용하기 좋게 올바른 수준의 추상화를 가지고 있어야하고, DX도 좋아야 함.</p>
<h3 id="nextjs-the-react-framework">Next.js: The React Framework</h3>
<p>넥스트가 개발자 경험을 위해 겨냥하고 있는 것들</p>
<ul>
<li>직관적인 페이지 기반 라우팅 시스템 (동적 라우트 지원)</li>
<li>페이지단위로 지원 하는 프리렌더링, SSG, SSR</li>
<li>빠른 페이지 로딩을 위한 자동 코드 스플리팅</li>
<li>최적화된 prefetch를 통한 클라이언트 사이드 라우팅</li>
<li>Fast Refresh 개발 환경</li>
<li>확장 어쩌고..</li>
</ul>
<p>자세한 예시</p>
<p><strong>동적 라우트</strong></p>
<ul>
<li><code>pages/blog/[slug].js</code> → <code>/blog/:slug</code> (<code>/blog/hello-world</code>)</li>
<li><code>pages/[username]/settings.js</code> → <code>/:username/settings</code> (<code>/foo/settings</code>)</li>
<li><code>pages/post/[...all].js</code> → <code>/post/*</code> (<code>/post/2020/id/title</code>)</li>
</ul>
<p><strong>클라이언트 사이드 라우팅(Client-side routing)</strong></p>
<p><code>&lt;Link /&gt;</code> 컴포넌트 제공</p>
<p>뷰포트 안의 링크 컴포넌트는 SSG를 사용하는 페이지에 대해 기본적으로 프리페치(prefetch)됨. 서버에서 렌더된 라우트에 의한 데이터는 프리페치 되지 않음.</p>
<p>→ 이게 뭔 소리냐면 링크 컴포넌트가 화면에 보이면 링크 클릭 안해도 넥스트에서 <strong>링크랑 연결된 페이지 코드를 미리 로드</strong>함. 그래서 페이지 전환이 부드러움</p>
<p>새로고침도 안함. 이전에 받아온 데이터는 서버에 요청도 다시 안함.</p>
<p>참고로 Link 컴포넌트를 쓸 때, 칠드런으로 <code>&lt;a&gt;</code> 를 왜 넣어야할까?
<a href="https://github.com/vercel/next.js/blob/canary/packages/next/client/link.tsx#L226">안 넣어주면 next에서 if문으로 알아서 넣어주는 부분이 있긴함</a></p>
<p>공식 문서 설명을 좀 더 찾아보니,  <code>&lt;a&gt;</code> 태그로 href 어트리뷰트를 넣어서 SEO에 손상이 가지 않게 하려고.</p>
<h3 id="프리렌더링"><strong>프리렌더링</strong></h3>
<p>기본적으로 넥스트는 모든 페이지에 프리렌더가 적용됨. 이게 무슨말이냐면 넥스트가 매 페이지를 미리 html로 생성(generate)한다는 거임. </p>
<p>생성된 html은 그 페이지에 필요한 최소한의 자스 코드랑 연결됨. 브라우저에 의해 페이지가 로드되면, 자스 코드가 실행되고 페이지를 완전 interactive하게 만들어줌. (이 과정을 hydration이라고 부름)</p>
<p>프리렌더링에는 두 가지 형태가 있음. HTML을 생성하는 방식에 차이가 있음.</p>
<ul>
<li><strong>Static Generation(추천됨): HTML을 빌드 타임에 각 페이지별로 생성하고 해당 페이지로 요청이 올 경우 이미 생성된 HTML 문서를 반환</strong></li>
<li><strong>Sever-side Rendering: HTML은 매 요청마다 생성될 것임.</strong></li>
</ul>
<p>넥스트에서는 위 방식을 매 페이지마다 고를 수 있긴함. </p>
<p>넥스트에서는 성능상의 이유로 SSR 보다는 SSG를 사용하길 추천함. 정적으로 생성된 페이지는 성능 향상을 위한 추가 구성 없이 CDN에서 캐싱될 수 있음.</p>
<p>클라이언트 측 데이터 페칭으로, 페이지의 일부는 클라이언트 측 자스로 완전히 로딩될 수도 있음.</p>
<aside>
💡 CDN?
Content Delievery Network
콘첸츠 전송 기술. 서버와 사용자 사이의 물리적인 거리를 줄여 로딩 시간을 줄임. 각 지역의 캐시 서버를 분산 배치해서 원본 서버가 아닌 캐시 서버가 콘텐츠를 전달함.

</aside>

<p>다음 편에는 SSG, SSR, Hydration에 대해 알아보겠음.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[REACT] 에러바운더리에서 에러가 잡히지 않는 경우]]></title>
            <link>https://velog.io/@wynter_kim/%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C-%EC%97%90%EB%9F%AC%EB%B0%94%EC%9A%B4%EB%8D%94%EB%A6%AC%EC%97%90%EC%84%9C-%EC%97%90%EB%9F%AC%EA%B0%80-%EC%9E%A1%ED%9E%88%EC%A7%80-%EC%95%8A%EB%8A%94-%EA%B2%BD%EC%9A%B0</link>
            <guid>https://velog.io/@wynter_kim/%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C-%EC%97%90%EB%9F%AC%EB%B0%94%EC%9A%B4%EB%8D%94%EB%A6%AC%EC%97%90%EC%84%9C-%EC%97%90%EB%9F%AC%EA%B0%80-%EC%9E%A1%ED%9E%88%EC%A7%80-%EC%95%8A%EB%8A%94-%EA%B2%BD%EC%9A%B0</guid>
            <pubDate>Thu, 24 Mar 2022 13:19:17 GMT</pubDate>
            <description><![CDATA[<p>최종 수정일 : 2022-08-20</p>
<h2 id="에러바운더리란">에러바운더리란?</h2>
<p><a href="https://ko.reactjs.org/docs/error-boundaries.html#gatsby-focus-wrapper">https://ko.reactjs.org/docs/error-boundaries.html#gatsby-focus-wrapper</a>
명령형 대신 선언형으로 에러를 처리하기 위해 회사에서 쓰고 있다.</p>
<h2 id="에러바운더리에서-에러를-캐치하지-못하는-경우">에러바운더리에서 에러를 캐치하지 못하는 경우</h2>
<p>에러바운더리로 컴포넌트를 감쌌으나, 이 에러바운더리도 캐치하지 못하는 에러들이 있다.
<a href="https://ko.reactjs.org/docs/error-boundaries.html#introducing-error-boundaries">공식문서</a>에서도 알려준다.</p>
<pre><code>Note

에러 경계는 다음과 같은 에러는 포착하지 않습니다.

이벤트 핸들러 (더 알아보기)
비동기적 코드 (예: setTimeout 혹은 requestAnimationFrame 콜백)
서버 사이드 렌더링
자식에서가 아닌 에러 경계 자체에서 발생하는 에러</code></pre><h2 id="그래서-내가-겪은-문제">그래서 내가 겪은 문제</h2>
<p>비동기 처리를 할 때, 에러가 나니까 에러바운더리에서 걸러내지 못하고 Uncaught Error가 떴다.
찾아보니 에러바운더리도 캐치하지 못하는 에러가 있었다.
<a href="https://www.smashingmagazine.com/2020/06/react-error-handling-reporting-error-boundary-sentry/">https://www.smashingmagazine.com/2020/06/react-error-handling-reporting-error-boundary-sentry/</a>
그럼 이것을 어떻게 에러바운더리나 선언형으로 걸러내지?
명령적 해결 - <a href="https://wani.kr/posts/2015/03/09/js-something-2-catchable-settimeout-exception/">https://wani.kr/posts/2015/03/09/js-something-2-catchable-settimeout-exception/</a></p>
<p>선언적 해결 - <a href="https://jbee.io/react/error-declarative-handling-3/">https://jbee.io/react/error-declarative-handling-3/</a>
unhandledrejection event를 사용한다.
참고로 catch하고 버블링되는 걸 막지 않았더니 uncaught에러가 났다. 멍청이..</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[우아한 테크 세미나, React Query 후기]]></title>
            <link>https://velog.io/@wynter_kim/%EC%9A%B0%EC%95%84%ED%95%9C-%ED%85%8C%ED%81%AC-%EC%84%B8%EB%AF%B8%EB%82%98-React-Query-%ED%9B%84%EA%B8%B0</link>
            <guid>https://velog.io/@wynter_kim/%EC%9A%B0%EC%95%84%ED%95%9C-%ED%85%8C%ED%81%AC-%EC%84%B8%EB%AF%B8%EB%82%98-React-Query-%ED%9B%84%EA%B8%B0</guid>
            <pubDate>Tue, 22 Feb 2022 12:32:41 GMT</pubDate>
            <description><![CDATA[<h2 id="intro">Intro</h2>
<p>상태란?</p>
<p>주어진 시간에 대해 시스템을 나타내는 것으로 언제든지 변경될 수 있음.</p>
<p>문자열, 배열, 객체 등의 형태로 응용 프로그램에 저장된 데이터!</p>
<p>→ 개발자 입장에선 관리해야하는 데이터들</p>
<p>모던 웹 프론트엔드는 프로덕트가 커져서 관리해야할 상태도 많아졌음.</p>
<h2 id="react-query와-상태관리-주제를-가지고-온-이유">React Query와 상태관리 주제를 가지고 온 이유</h2>
<h3 id="주문-fe-프로덕트를-보며-가진-고민">주문 FE 프로덕트를 보며 가진 고민</h3>
<p>너무 많은 레포.</p>
<p>반복되는 컴포넌트, 로직..</p>
<p>Redux로 구성한 Store 코드인데, 상태관리보단 <strong>API 통신 코드</strong>같다.</p>
<ul>
<li>API 관련 코드가 Store에?</li>
<li>반복되는 isFetching, isError 등 API 관련 상태</li>
<li>반복되는 비슷한 구조의 API 통신 코드</li>
</ul>
<p>(이때는 rtk 같은 게 없었다고 함)</p>
<p>소유주가 Client냐 Server냐에 따라 상태를 두 가지로 나누어 보자.</p>
<p>Client State. Server State.</p>
<p>소유주가 Client냐 Server냐에 따라.</p>
<p>배민 주문팀에서는 React Query 기술을 채택했다.</p>
<h2 id="react-query">React Query</h2>
<p>fetching, caching, synchronizing and updating server state.</p>
<p>zero-config, can be customized.</p>
<p><QueryClientProvider client={queryClient}>로 감싸고 있음.</p>
<p>컨텍스트와 비슷한데?</p>
<p>사용은 useQuery</p>
<p>세가지 core 컨셉</p>
<p>Queries. Mutations. Query Invalidation.</p>
<h3 id="queries">Queries</h3>
<p>데이터 Fetching 용!</p>
<p>userQuery(’todos’, fetchTodoList, option) // query key, query function, option</p>
<p>qeury keyDP 따라 query caching을 관리.</p>
<p>string과 array형태로 사용할 수 있음.</p>
<p>queries 파일 분리 추천!</p>
<p>redux에서 언제 server state를 받을까? → onSuccess단계가 좋다고 생각한다.</p>
<h3 id="mutations">Mutations</h3>
<p>데이터 생성/수정/삭제용!</p>
<p>useMutation(mutationFn, </p>
<p>onMutate는 Optimistic update를 적용할 때 유용</p>
<p>api 요청을 성공할 것이라고 보고 UI 업데이트. 롤백 가능.</p>
<h3 id="query-invalidation">Query Invalidation</h3>
<p>queryClient.invaldateQueries()</p>
<p>query가 stale 취급 된다.</p>
<h3 id="caching하고-synchronization은-리액트-쿼리가-어떻게-알아서-하나">Caching하고 Synchronization은 리액트 쿼리가 어떻게 알아서 하나?</h3>
<p>RFC 5861</p>
<p>stale-while-revalidate</p>
<p>→ 백그라운드에서 stale response를 revalidate 하는 동안 캐시가 가진 stale response를 반환</p>
<p>Cache-Control: max-age=600, stale-while-revalidate=30</p>
<p>600초 동안은 유효한 값이라고 생각한다.</p>
<p>latency가 숨겨짐.</p>
<p>새 물건이 올 때까지 옛날 물건을 보여준다.</p>
<p>( 이 부분은 조금 더 공부 후에 채워 놔야겠다. )</p>
<p>이 컨셉을 메모리 캐시에도 적용해보자!</p>
<p>cacheTime: 메모리에 얼마만큼 있을건지</p>
<p>staleTime: 얼마의 시간이 흐른 후에 데이터를 stale 취급할 건지.</p>
<p>Query 상태흐름</p>
<p>fetching → fresh → stale → inactive → deleted</p>
<p>스크린에서 빠져나갈때 stale→inactive</p>
<p>다시 mount되어도 fresh한 값이면 refetch가 일어나지 않음.</p>
<h3 id="그럼-react-query는-어디에서-값을-관리할까요">그럼 React Query는 어디에서 값을 관리할까요?</h3>
<p>전역으로 관리될까?</p>
<p>중복호출 될까?</p>
<p>답은 Context API에 있다.</p>
<p>내부적으로 컨텍스트를 이용함!</p>
<h2 id="주문-팀에서는-어떻게-바뀌었나">주문 팀에서는 어떻게 바뀌었나?</h2>
<p>Store는 Client State만 남았다!</p>
<p>Server State는 React Query와 함꼐 좋아졌다!</p>
<p>Component는 쬐끔 길어졌지만 수용가능한 범위.</p>
<h3 id="사용하면서">사용하면서...</h3>
<p> 다른 상태관리라이브러리들보다 직관적이다!</p>
<h3 id="고민해야할-문제">고민해야할 문제</h3>
<p>Component가 상대적으로 비대해지는 문제</p>
<p>좀 더 난이도가 높아진 프로젝트 설계</p>
<p>단순 API 통신 이상으로 장점을 잘 활용할 방법</p>
<h2 id="나도-써야하나">나도 써야하나?</h2>
<p>역시 중요한건 트렌드보단 Why!</p>
<p>추가 질문</p>
<p>swr과 다른점?</p>
<p>리액트 쿼리가 더 많은 인터페이스를 제공함.</p>
<p>Client 스토어?</p>
<p>Mobx</p>
<p>query 키?</p>
<p>함수명으로 자주 씀</p>
<p>디폴트 옵션?</p>
<p>안씀</p>
<p>에러바운더리?</p>
<p>안씀! Suspense는 실험단계라서 안씀!</p>
<p>시간 날 때 내용 수정 및 추가 해야겠다...</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Redux] CreateAsyncThunk에서 getState로 Store 접근하기]]></title>
            <link>https://velog.io/@wynter_kim/Redux-CreateAsyncThunk%EC%97%90%EC%84%9C-getState%EB%A1%9C-Store-%EC%A0%91%EA%B7%BC%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@wynter_kim/Redux-CreateAsyncThunk%EC%97%90%EC%84%9C-getState%EB%A1%9C-Store-%EC%A0%91%EA%B7%BC%ED%95%98%EA%B8%B0</guid>
            <pubDate>Mon, 21 Feb 2022 14:13:34 GMT</pubDate>
            <description><![CDATA[<p>Store -&gt; Container -&gt; Component -&gt; AsyncThunk
스토어에 있는 값을 Props와 Parameter로 넘겨받는 게 너무 불편했다.
같은 Slice 파일에 있는데 어째서!
Component가 깊어지면 깊어질수록, 공통으로 받아야할 인자가 많으면 많을수록 예쁘지 않은 코드가 나타난다.</p>
<blockquote>
<p>찾아보니 CreateAsyncThunk에서 getState 옵션으로 바로 store에 접근할 수 있었다!
<a href="https://redux-toolkit.js.org/api/createAsyncThunk">https://redux-toolkit.js.org/api/createAsyncThunk</a></p>
</blockquote>
<p><code>async (_, { getState }) =&gt; {}</code> 이런 식으로 처리하면 된다.</p>
<p><strong>근데 이렇게 처리해도 괜찮을까?</strong> redux의 데이터 흐름을 막 쓰게 되는 거 아닐까?</p>
<p>이것에 대한 답변을 <a href="https://blog.isquaredsoftware.com/2017/01/idiomatic-redux-thoughts-on-thunks-sagas-abstraction-and-reusability/">이 글</a>에서 찾아보려고 한다.</p>
<hr>
<p><strong>2022-03-05 추가 글</strong></p>
<p>TL;DR
redux제작자 Dan Abramov 는 주의해서 사용해야한다고 했음.
현재 Redux 유지 관리자 Mark Erikson은 괜찮다고함.</p>
<hr>
<p>Dan Abramov - &quot;thunks에서 <code>getState</code> 쓰지 마세요!
Dan Abramov가 2월 <a href="https://stackoverflow.com/questions/35667249/accessing-redux-state-in-an-action-creator">스택오버플로</a>에 답했는데, 아래처럼 쓰여있었습니다.</p>
<blockquote>
<p>액션 크리에이터에서 상태에 접근하는 것은 anti-pattern이고, 가능하다면 피해야합니다. 접근해도 괜찮다고 생각되는 몇가지 사례는 요청을 보내기 전에 캐시된 데이터를 확인할 때, 권한이 있는지 체크할 때입니다.<code>state.something.items</code>와 같은 데이터를 액션 크리에이터에서 전달하는 것은 명백한 anti-pattern이고 이해하기 힘든 변경 이력을 가지기 때문에 장려되지 않습니다. 만약 버그가 있고 items가 부정확하다면, 이미 액션의 일부이기 때문에 어디서 잘못된 값이 왔는지 추적하기 힘듭니다. 그러니까 주의를 가지고 사용해야합니다.</p>
</blockquote>
<p>그 후로 저 코멘트에 몇몇 사람이 혼란스러워 하는 걸 봤습니다. &quot;thunk에서 getState는 가능하지만 사실상 못쓴다면, 어떻게 해야하나요?&quot;. 지금은 &quot;가능하다면 피해라&quot;를 사람들이 &quot;절대 쓰지마&quot;로 해석하고 있지만, Dan이 스택오버플로에서 말한 사실은 사람들이 그것을 복음처럼 받아들이도록 만든다.</p>
<hr>
<p>MarkEricson의 후반부 글.</p>
<p>물론, 정말 복잡한 응답 처리 로직을 가지고 있다면 중앙집중화되어야할지도 모릅니다. 하지만, 대다수의 어플리케이션은 요청하고, 액션을 디스패치하고, 완료하는 것이 간단할 것이라고 생각합니다. 중앙집중화할 것이 별로 없죠.</p>
<p>&quot;단방향 데이터 흐름을 깨는 상태에 액세스&quot;에 저는 전혀 동의하지 않습니다. 단방향 데이터 흐름의 개념은 데이터 업데이트가 한 곳에서 적용되어 시스템을 통해 전파된다는 것입니다. 일반 React 애플리케이션에서 이는 컴포넌트 트리에서 조상으로 전달하고, <code>setState()</code>를 부르고 새로운 데이터를 props로 내려주는 콜백을 의미합니다. Redux 앱에서 이는 모든 &quot;쓰기&quot; 로직이 루트 리듀서 함수에 캡슐화 되어있고 리듀서가 디스패치된 액션에 대한 응답하고 연결된 모든 컴포넌트는 이후에 저장소에서 업데이트된 상태를 읽는다는 것을 의미합니다. 이것은 모델을 직접 수정하기 위해 양방향 입력 바인딩을 사용하는 전형적인 앵귤러 앱이나 모든 뷰가 언제든지 <code>this.model.set(&quot;someField&quot;, someValue&quot;)</code>를 호출할 수 있는 Backbone 앱과 대조됩니다.</p>
<p>이는 양방향 입력 바인딩을 사용하여 모델을 직접 수정하는 일반적인 Angular 앱 또는 모든 보기가 this.model.set(&quot;someField&quot;, someValue)언제든지 호출할 수 있는 Backbone 앱과 대조됩니다.</p>
<p>내가 알기로, 썽크나 사가에서 상태를 읽어도 단방향 데이터 흐름이 중단되지 않습니다 . 액션은 여전히 디스패치되고 리듀서는 여전히 실행되며 컴포넌트는 여전히 업데이트된 상태를 읽습니다. 썽크가 상태 자체를 직접 수정하는 것과는 다릅니다. 모든 데이터 조각이 뷰에서 뷰로 명시적으로 전달되는 Elm만큼 엄격하지 않다는 점을 인정하지만 여기서는 문제가 발생하지 않습니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[드래그드롭의 이벤트 위임, 이벤트 버블링과 캡쳐링]]></title>
            <link>https://velog.io/@wynter_kim/%EB%93%9C%EB%9E%98%EA%B7%B8%EB%93%9C%EB%A1%AD%EC%9D%98-%EC%9D%B4%EB%B2%A4%ED%8A%B8-%EC%9C%84%EC%9E%84-%EC%9D%B4%EB%B2%A4%ED%8A%B8-%EB%B2%84%EB%B8%94%EB%A7%81%EA%B3%BC-%EC%BA%A1%EC%B3%90%EB%A7%81</link>
            <guid>https://velog.io/@wynter_kim/%EB%93%9C%EB%9E%98%EA%B7%B8%EB%93%9C%EB%A1%AD%EC%9D%98-%EC%9D%B4%EB%B2%A4%ED%8A%B8-%EC%9C%84%EC%9E%84-%EC%9D%B4%EB%B2%A4%ED%8A%B8-%EB%B2%84%EB%B8%94%EB%A7%81%EA%B3%BC-%EC%BA%A1%EC%B3%90%EB%A7%81</guid>
            <pubDate>Sat, 11 Dec 2021 08:13:08 GMT</pubDate>
            <description><![CDATA[<p>첫 게시글로 무엇을 할까 고민을 많이 했는데, 최근에 겪었던 문제와 해결했던 과정에 대해서 적어볼까 한다.</p>
<hr>
<h3 id="내가-겪은-문제">내가 겪은 문제</h3>
<ul>
<li>이벤트가 일어난 후에 이벤트를 걸어준 타겟이 바뀌어서 이벤트가 사라졌던 문제</li>
<li>드래그드롭 이벤트를 위임했으나, drop 이벤트가 먹지 않았던 문제</li>
</ul>
<p><strong>문제설명</strong>
드롭 이벤트에 DOM이 바뀌는 이벤트를 걸어주어서, DOM이 바뀌니까 내가 걸어줬던 이벤트가 없어졌다.
바뀔때마다 새로 걸어주는 것 보다 좋은 방법이 없을까?</p>
<h3 id="해결방안">해결방안</h3>
<p><strong>이벤트 위임</strong>으로 해결 하면 된다!
이벤트 위임을 알기 전에, 버블링과 캡쳐링 개념에 대해 알아보자.
이벤트 흐름은 3단계가 있는데, 캡쳐링 -&gt; 타깃 -&gt; 버블링 단계로 이루어진다.</p>
<p><strong><em>이벤트 캡쳐링이란?</em></strong>
최상위 요소에서 가장 안쪽에 있는 타깃까지 이벤트가 내려가는 단계!
<code>addEventListener</code>하고 인자로 <code>capture:true</code>를 해야 캡쳐링때 이벤트 핸들러가 동작함.</p>
<p><strong><em>이벤트 버블링이란?</em></strong>
한 요소의 이벤트 핸들러가 동작하고 부모 요소의 핸들러가 동작하고, 또 그 부모 요소의 해들러가 동작하는 것. 그렇게 최상단 요소까지 진행된다.
(버블링과 캡쳐링을 막는 것이 그 유명한 <code>event.stopPropagation()</code>)</p>
<p>나는 이 중에서 버블링을 이용할 것임.
DOM이 바뀌지 않는 곳에 이벤트를 걸어주고, 하위에서 버블링으로 이벤트핸들러가 올라오면 내가 걸어준 이벤트가 실행이 됨.
회사에서 작성한 코드는 공개가 힘들고, 예시를 만들어보자면!</p>
<pre><code class="language-html">&lt;!DOCTYPE HTML&gt;
&lt;html&gt;
  &lt;head&gt;
    &lt;style&gt;
      .up {
      width: 300px;
      height: 300px;
      background-color: black;
      color: white;
      }

      .middle {
      width: 200px;
      height: 200px;
      background-color: blue;
      color: white;
      }

      .down {
      width: 100px;
      height: 100px;
      background-color: green;
      color: white;
      }
    &lt;/style&gt;
  &lt;/head&gt;
  &lt;body&gt;
    &lt;div class=&quot;up&quot;&gt;
      내가 바로 상단의 이벤트를 받을곳!
      &lt;div class=&quot;middle&quot;&gt;난 아무것도 아님!
        &lt;div class=&quot;down&quot;&gt;난 이곳에 이벤트를 걸고 싶어!&lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/body&gt;
  &lt;script&gt;
    const upSelector = document.querySelector(&#39;.up&#39;);
    const downSelector = document.querySelector(&#39;.down&#39;);

    upSelector.addEventListener(&#39;click&#39;, (e) =&gt; {
    if(e.target === downSelector) alert(&#39;event!&#39;);
    } )
  &lt;/script&gt;
&lt;/html&gt;</code></pre>
<hr>
<p>다음으로 드롭이벤트가 먹지 않던 문제는 간단했다.
dragover 중에 <code>e.preventdefault()</code>를 넣으니까 해결.
어플리케이션의 대부분은 drop 속성이 허용되지 않아서 그것을 막고 drop을 허용시키는 것임! <a href="https://developer.mozilla.org/ko/docs/Web/API/HTML_Drag_and_Drop_API/Drag_operations#droptargets">(참고자료)</a></p>
<h3 id="참고자료-모음">참고자료 모음</h3>
<p><a href="https://stackoverflow.com/questions/21339924/drop-event-not-firing-in-chrome">https://stackoverflow.com/questions/21339924/drop-event-not-firing-in-chrome</a>
<a href="https://joshua1988.github.io/web-development/javascript/javascript-interview-3questions/">https://joshua1988.github.io/web-development/javascript/javascript-interview-3questions/</a>
<a href="https://ko.javascript.info/bubbling-and-capturing">https://ko.javascript.info/bubbling-and-capturing</a></p>
]]></description>
        </item>
    </channel>
</rss>