<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>자몽 DevLog</title>
    <link>https://jamong.tistory.com/</link>
    <description></description>
    <language>ko</language>
    <pubDate>Fri, 17 Jul 2026 01:46:49 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>_자몽</managingEditor>
    <item>
      <title>프론트엔드 단위 테스트와 에러 모니터링</title>
      <link>https://jamong.tistory.com/112</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;단위 테스트란 (Unit Test)? &lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 모듈별로 하나의 가장 작은 단위로 독립적으로 실행되는 테스트로, 각 함수나 메서드가 올바르게 작동하는지 검사하는데 초점을 맞춤&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt; 단위 테스트, 왜 필요할까?&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 프로젝트 전체 규모의 테스트 코드를 작성하게 되면 서버와 연결하고 서로 상호작용 하는 컴포넌트들이 모두 문제 없이 작동해야 테스트 할 환경이 만들어지며, 이는 비용과 시간이 많이 들어가는 작업임. 반면 단위 테스트는 작은 모듈별로 독립적으로 테스팅 하기에 비용이 적게 들고, 테스팅을 원하는 곳만 부분적으로 실행할 수 있다는 장점이 있음.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&amp;nbsp;그럼 어떤 효과가 있는데?&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;1. 빠른 피드백과 에러 초기 발견 가능&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;- 개발자가 한 모듈을 개발한 이후 테스트 코드만 작성하여 실행하면 되기 때문에, 작업이 간편하며 이를 통해 모듈의 이상 유무와 예기치 못한 버그를 사전에 알아챌 수 있음&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;2. 리팩토링 안정성 향상&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;- 개발 과정 중 리팩토링을 하다 보면 초기 예상과는 다른 동작 결과가 나올 때가 있는데, 이를 사전에 방지하는 역할 수행&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;어떤 라이브러리가 있는데?&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;1. Jest&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- Facebook에서 개발한 테스트 프레임워크로, &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;node.js 기반 프로젝트에서 잘 실행되기에 &lt;/span&gt;React와 같은 프론트엔드 라이브러리/프레임워크에 최적화 되어 있음.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 테스트에 필요한 모든 기능이 내장되어 있어 별도 라이브러리 설치가 필요 없음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- API 요청이나 비동기 함수 호출을 mocking 하여 테스트할 수 있는 기능 내장&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 스냅샷 테스트 기능을 제공하여 컴포넌트 렌더링 결과를 비교 및 추적하여 테스트 가능&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 단, 프로젝트 규모가 커질수록 초기 설정에 성능 문제가 있을 수 있음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;2. Mocha&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- node.js 기반의 테스트 프레임워크로, 주로 백엔드 애플리케이션에서 많이 사용됨.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 다양한 테스트 어설션 라이브러리와의 조합으로 테스팅 환경에 맞게 커스터마이징 가능&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 단, Mocha는 테스트 실행만 담당하기에 다른 라이브러리의 추가 설치가 필요함.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;360&quot; data-origin-height=&quot;247&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bYaqQb/btsJwryFrbl/eVR92ZUobpHqoNjam2uPM1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bYaqQb/btsJwryFrbl/eVR92ZUobpHqoNjam2uPM1/img.png&quot; data-alt=&quot;모니터링중...&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bYaqQb/btsJwryFrbl/eVR92ZUobpHqoNjam2uPM1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbYaqQb%2FbtsJwryFrbl%2FeVR92ZUobpHqoNjam2uPM1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;360&quot; height=&quot;247&quot; data-origin-width=&quot;360&quot; data-origin-height=&quot;247&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;모니터링중...&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;모니터링?&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 서비스가 배포된 이후, 사용자들이 사용하는 환경에서 어떤 에러가 발생할지 모르기에 에러를 모니터링 하는 것은 굉장히 중요한 작업이며, 이는 실제 매출이나 서비스 만족도 등 여러 방면에 영향을 미칠 수 있는 issue가 된다. 혹은 사용자가 미처 발견하지 못한 에러의 경우 또한 모니터링 라이브러리를 사용하여 해결한다면 사용자의 경험을 높일 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;모니터링 라이브러리 종류&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;1. Sentry&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[장점] 서비스에서 발생하는 에러를 실시간으로 보고하며 다른 협업 툴과 연동하여 알람기능 제공, 오류 발생시 이슈를 자동 생성하며 이를 통해 오류의 우선순위를 결정할 수 있음, 특정 사용자 세션에서 발생한 문제를 추적할 수 있음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[단점] 에러 모니터링에는 강점이 있지만, 성능 문제를 추적하는데는 한계가 있음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. DataDog&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[장점] 프론트엔드뿐만 아니라 백엔드와 클라우드 인프라까지 한 번에 모니터링 가능, 에러-성능-로그 등을 종합한 대시보드 제공하여 한 눈에 서비스 현황을 보기 편함&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[단점] 규모가 큰 대신 초기 러닝커브가 있음.&lt;/p&gt;</description>
      <category>frontend</category>
      <category>Unit Test</category>
      <category>단위 테스트</category>
      <category>모니터링</category>
      <author>_자몽</author>
      <guid isPermaLink="true">https://jamong.tistory.com/112</guid>
      <comments>https://jamong.tistory.com/112#entry112comment</comments>
      <pubDate>Sun, 8 Sep 2024 14:25:32 +0900</pubDate>
    </item>
    <item>
      <title>JWT 로그인 분석_access token과 refresh token은 어디에 저장할까?</title>
      <link>https://jamong.tistory.com/111</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;910&quot; data-origin-height=&quot;289&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/v4yjM/btsJuCO7UPK/EJ0mN1abOUKn83bC6nckp0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/v4yjM/btsJuCO7UPK/EJ0mN1abOUKn83bC6nckp0/img.png&quot; data-alt=&quot;jwt의 구성요소&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/v4yjM/btsJuCO7UPK/EJ0mN1abOUKn83bC6nckp0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fv4yjM%2FbtsJuCO7UPK%2FEJ0mN1abOUKn83bC6nckp0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;702&quot; height=&quot;223&quot; data-origin-width=&quot;910&quot; data-origin-height=&quot;289&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;jwt의 구성요소&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;JWT 이란?&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- JWT(JSON Web Token): URL로 이용할 수 있는 문자로만 구성된 JSON형식의 토큰 형태로 주로 클라이언트-서버간 인증 및 정보 교환에 사용됨&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JWT의 구성요소&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. header(헤더): 토큰의 유형과 서명 생성에 어떤 알고리즘이 사용되었는지 정의&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. payload(내용): 사용자의 인증 정보를 담고 있으며, 정보의 한 조각을 '클레임'이라고 부름. 클레임은 name-vlaue의 쌍으로 이루어져 있으며, 토큰에 여러개의 클레임들을 넣을 수 있음(사용자 ID, 권한 등)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. signature(서명): header와 payload를 비밀키로 서명한 값으로, 토큰이 변조되지 않았음을 검증하고 인증해주는 부분&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;Access Token과 Refresh Token의 관리방식&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- JWT 방식은 결국 유저의 정보와 권한을 담고 있는 토큰을 주고 받는 형태기에, 탈취되었을 때 보안 문제가 생길 수 있음. 게다가Access Token과 Refresh Token은 각각의 취약점이 있어 저장소의 위치와 관리 방법이 중요함&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;1. Access Token&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;/b&gt;&amp;nbsp;- 서버와 인증, 인가 요청을 주고 받는 주요한 토큰. acess token의 주요 저장소로 아래 3가지가 있음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;1-1. local storage&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;- 페이지 새로고침 및 브라우저를 여닫아도 인증 상태가 유지되지만, XSS 공격에 취약함&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;1-2. session storage&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;-&amp;nbsp; 페이지 종료시 토큰이 사라져 사용하지 않는 동안의 보안의 위협은 감소하지만, 사용 중에 있어서 여전히 XSS 공격에 취약하며 새로고침시 로그인이 해제되는 불편함이 있을 수 있음&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;1-3. 메모리&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;- zustand, tanstack query, context api 등의 전역 상태로 관리하는 방법. 메모리를 사용하기에 XSS 공격에 비교적 안전하지만, 새로고침 시 데이터를 유지하기 어려움&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;=&amp;gt; 가장 안전한 장소로 꼽을 만한 곳이 존재하지 않으며, 새로고침 시 데이터 유지를 시킬 수 있는 local storage에 저장하는 편이다. 그 보완책으로&lt;u&gt;&lt;b&gt; Access Token의 유효시간을 짧게 설정&lt;/b&gt;&lt;/u&gt;하여 토큰 탈취에 대비함&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;2. Refresh Token&lt;/b&gt;&lt;/h3&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;/b&gt;-&amp;nbsp; Access Token의 수명이 짧기 때문에 토큰이 만료될 경우 다시 발급 받을 수 있도록 Refresh Token을 함께 사용한다. Accces Token이 만료될 경우 Refresh Token으로 서버에서 다시 Access Token을 발급받는데 사용되며, 유효기간이 짧은 Access Token과 비교해 &lt;b&gt;&lt;u&gt;긴 수명&lt;/u&gt;&lt;/b&gt;을 가지고 있다. Refresh Token은 서버에서 발급받고, 서버에서 관리되기에 탈취될 위협이 있다면 토큰을 강제로 사용하지 못하게 하는 방법을 사용한다.&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;2-1. local/session storage&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;- Refresh Token은 Access Token을 무한정 발급시킬 수 있는 토큰으로 더 보완에 신경써야 함. 때문에 XSS 취약점을 가지는 로컬/세션 스토리지에 저장하기는 위험성이 큼&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;2-2. Cookie&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;- Cookie는 HttpOnly와 Seure 플래그를 설정하여 javascript 상에서 토큰에 접근할 수 없도록 막을 수 있어 비교적 안전함. 단 &amp;nbsp;&lt;span style=&quot;color: #555555; text-align: start;&quot;&gt;CSRF 취약점이 있어 이를 대비하기 위한 추가적인 조치들을 해주어야 함.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #555555; text-align: start;&quot;&gt;2-3. 서버에서 관리&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #555555; text-align: start;&quot;&gt;&amp;nbsp;- 서버에서 관리되면 브라우저 상에서 발생하는 보안 취약점을 해결할 수 있지만, 서버상의 보안 위험은 따로 관리 해주어야 함.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #555555; text-align: start;&quot;&gt;* XSS &lt;span style=&quot;color: #555555; text-align: start;&quot;&gt;(Cross-site Scripting) : 유저의 브라우저에서 특정 스크립트를 실행시켜 원하는 정보를 탈취하는 방식&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #555555; text-align: start;&quot;&gt;&lt;span style=&quot;color: #555555; text-align: start;&quot;&gt;* CSRF&lt;/span&gt;&lt;span style=&quot;color: #555555; text-align: start;&quot;&gt; &lt;/span&gt;(&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #292929; text-align: start;&quot;&gt;Cross-Site Request Forgery): 인증된 사용자로 하여금 서버에 접근해 의도치 않은 행동을 하게 하는 방식&lt;/span&gt;&lt;/p&gt;</description>
      <category>access token</category>
      <category>frontend</category>
      <category>JWT</category>
      <category>login</category>
      <category>React</category>
      <author>_자몽</author>
      <guid isPermaLink="true">https://jamong.tistory.com/111</guid>
      <comments>https://jamong.tistory.com/111#entry111comment</comments>
      <pubDate>Fri, 6 Sep 2024 02:07:04 +0900</pubDate>
    </item>
    <item>
      <title>[2024.08.13] [검색] 꾹 눌러 단어 삭제하기</title>
      <link>https://jamong.tistory.com/109</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;검색 필터로 나라 이름을 보여주는 UI를 추가한 이후 만든 꾹 눌러 단어 삭제하는 기능.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;디자이너님이 요청해주셔서 만들어봤는데 완성되니 예쁘고, 디테일도 올라간 느낌이다~&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;꾹 눌러 삭제.gif&quot; data-origin-width=&quot;941&quot; data-origin-height=&quot;548&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/pXCp0/btsI24SUBZY/Ts0uTBlIUnCXJVK3EJtdek/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/pXCp0/btsI24SUBZY/Ts0uTBlIUnCXJVK3EJtdek/img.gif&quot; data-alt=&quot;꾹~ 누르면 삭제&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/pXCp0/btsI24SUBZY/Ts0uTBlIUnCXJVK3EJtdek/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/pXCp0/btsI24SUBZY/Ts0uTBlIUnCXJVK3EJtdek/img.gif&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;740&quot; height=&quot;431&quot; data-filename=&quot;꾹 눌러 삭제.gif&quot; data-origin-width=&quot;941&quot; data-origin-height=&quot;548&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;꾹~ 누르면 삭제&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;※ 구현 로직&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;Q. 꾹 누르는 것?&amp;nbsp;&lt;br /&gt;&amp;nbsp; A. mousedown(커서 누르기)이 일어나고 몇 초뒤 뒤에 mouseup(커서 떼기)이 일어남&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 필터 단어를 누르면 n초 뒤에 삭제되도록 setTimeout을 걸어두고, mouseup이 지정된 시간 전에 일어나면 꾹 누르는게 취소되었으니 clearTimeout으로&amp;nbsp; setTimeout을 삭제시킴&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;b&gt;once:true&lt;/b&gt; =&amp;gt; 이벤트 핸들러가 한 번만 실행되고 바로 삭제되게 함&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1253&quot; data-origin-height=&quot;605&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/PDU8p/btsI3SK40LP/NCIRUkVfSA22RgCxViuNO1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/PDU8p/btsI3SK40LP/NCIRUkVfSA22RgCxViuNO1/img.png&quot; data-alt=&quot;적용한 함수&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/PDU8p/btsI3SK40LP/NCIRUkVfSA22RgCxViuNO1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FPDU8p%2FbtsI3SK40LP%2FNCIRUkVfSA22RgCxViuNO1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;661&quot; height=&quot;319&quot; data-origin-width=&quot;1253&quot; data-origin-height=&quot;605&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;적용한 함수&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2375&quot; data-origin-height=&quot;494&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bG9r1r/btsI4qHhLpn/6mGrWrwuLf0ipY4ahjkqS0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bG9r1r/btsI4qHhLpn/6mGrWrwuLf0ipY4ahjkqS0/img.png&quot; data-alt=&quot;적용한 곳&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bG9r1r/btsI4qHhLpn/6mGrWrwuLf0ipY4ahjkqS0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbG9r1r%2FbtsI4qHhLpn%2F6mGrWrwuLf0ipY4ahjkqS0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;759&quot; height=&quot;158&quot; data-origin-width=&quot;2375&quot; data-origin-height=&quot;494&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;적용한 곳&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;2. 모바일 지원(+ 추가 기능)&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- window 객체에 touchstart 이벤트가 있으면 모바일 환경&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- touchcancel, mouseleaver까지 추가하여 클릭 도중 이탈하였을 때도 대응&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1444&quot; data-origin-height=&quot;1049&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cSvjAI/btsI4vIxiSh/O0DdYNtyo8OS1SKwgPRwFK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cSvjAI/btsI4vIxiSh/O0DdYNtyo8OS1SKwgPRwFK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cSvjAI/btsI4vIxiSh/O0DdYNtyo8OS1SKwgPRwFK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcSvjAI%2FbtsI4vIxiSh%2FO0DdYNtyo8OS1SKwgPRwFK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;582&quot; height=&quot;423&quot; data-origin-width=&quot;1444&quot; data-origin-height=&quot;1049&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>next.js</category>
      <category>React</category>
      <category>til</category>
      <author>_자몽</author>
      <guid isPermaLink="true">https://jamong.tistory.com/109</guid>
      <comments>https://jamong.tistory.com/109#entry109comment</comments>
      <pubDate>Wed, 14 Aug 2024 02:10:54 +0900</pubDate>
    </item>
    <item>
      <title>[2024.07.23] storybook + cva 공통 컴포넌트 개발</title>
      <link>https://jamong.tistory.com/94</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;다 잘 동작하는데 색상에 관련된 css만 안되는 이유를 모르겠다...&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1105&quot; data-origin-height=&quot;578&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bxVb86/btsIKSdvJwH/qM8HkzlInXRpc68Qymlt6k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bxVb86/btsIKSdvJwH/qM8HkzlInXRpc68Qymlt6k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bxVb86/btsIKSdvJwH/qM8HkzlInXRpc68Qymlt6k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbxVb86%2FbtsIKSdvJwH%2FqM8HkzlInXRpc68Qymlt6k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1105&quot; height=&quot;578&quot; data-origin-width=&quot;1105&quot; data-origin-height=&quot;578&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>TIL</category>
      <category>til</category>
      <author>_자몽</author>
      <guid isPermaLink="true">https://jamong.tistory.com/94</guid>
      <comments>https://jamong.tistory.com/94#entry94comment</comments>
      <pubDate>Wed, 24 Jul 2024 04:19:46 +0900</pubDate>
    </item>
    <item>
      <title>[2024.07.19] 최종프로젝트_코드 컨벤션, github rules, 모델 체크</title>
      <link>https://jamong.tistory.com/91</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;다음주부터 시작하는 본격적인 개발에 앞서 마지막으로 주어지는 최후의 주말을 하루 앞둔 금요일~ 부족한 부분이 많은데 주말에 좀 많이 채워넣어야겠다&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;210&quot; data-origin-height=&quot;210&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ze8wY/btsIIoiSZZL/aPpEo5SpTMyyaXlpsBWNgK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ze8wY/btsIIoiSZZL/aPpEo5SpTMyyaXlpsBWNgK/img.png&quot; data-alt=&quot;이제 곧 주말이라니~&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ze8wY/btsIIoiSZZL/aPpEo5SpTMyyaXlpsBWNgK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fze8wY%2FbtsIIoiSZZL%2FaPpEo5SpTMyyaXlpsBWNgK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;210&quot; height=&quot;210&quot; data-origin-width=&quot;210&quot; data-origin-height=&quot;210&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;이제 곧 주말이라니~&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;오늘 한 일&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;1. 코드 컨벤션, github rules 정하기&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;2. 프로젝트 세팅 논의 조금&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;3. 모델 체크&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;249&quot; data-origin-height=&quot;835&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/THqXR/btsIIGXUyCv/Rbh53gOrSoSb6KcZkBmdEK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/THqXR/btsIIGXUyCv/Rbh53gOrSoSb6KcZkBmdEK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/THqXR/btsIIGXUyCv/Rbh53gOrSoSb6KcZkBmdEK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FTHqXR%2FbtsIIGXUyCv%2FRbh53gOrSoSb6KcZkBmdEK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;249&quot; height=&quot;835&quot; data-origin-width=&quot;249&quot; data-origin-height=&quot;835&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>TIL</category>
      <category>til</category>
      <author>_자몽</author>
      <guid isPermaLink="true">https://jamong.tistory.com/91</guid>
      <comments>https://jamong.tistory.com/91#entry91comment</comments>
      <pubDate>Mon, 22 Jul 2024 01:08:42 +0900</pubDate>
    </item>
    <item>
      <title>[2024.07.18] 최종프로젝트_기능 논의</title>
      <link>https://jamong.tistory.com/90</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;튜터님과의 아침 회의&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Light'; color: #333333; text-align: start;&quot;&gt;@ 튜터님:&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;1. 모바일 first로 작업 했으면&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;2. 모바일 뷰로 한 페이지가 나오면, 그 데스크톱 뷰가 와이어프레임 수준으로는 나왔으면&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;뒤늦게 모바일 버전이 데스크톱 버전으로 할 때 호환이 안되는 경우가 있을 수 있음&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;span style=&quot;&quot;&gt;=&amp;gt; 이번 프로젝트는 보통 데스크톱을 우선시 하여 개발하던 이전과 다르게 모바일을 우선시 하여 개발하게 되었다. 처음 해보는 방식이라 익숙치 않아도 이 방법의 장점이 부각될 수 있었으면 좋겠다!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Light'; color: #333333; text-align: start;&quot;&gt;오후 회의&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;564&quot; data-origin-height=&quot;748&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bhYtNn/btsIGVIZ1PJ/Pke3n19nXxwWbiPUruBKK0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bhYtNn/btsIGVIZ1PJ/Pke3n19nXxwWbiPUruBKK0/img.png&quot; data-alt=&quot;IA&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bhYtNn/btsIGVIZ1PJ/Pke3n19nXxwWbiPUruBKK0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbhYtNn%2FbtsIGVIZ1PJ%2FPke3n19nXxwWbiPUruBKK0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;378&quot; height=&quot;501&quot; data-origin-width=&quot;564&quot; data-origin-height=&quot;748&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;IA&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light'; color: #333333; text-align: start;&quot;&gt;디자이너님이 가져오신 IA와 레퍼런스 보면서 기능 논의하는 시간을 가졌다. 확실히 추상적으로 머릿속에 있는 아이디어만으로 서로의 의견을 나누는 것 보다, 무언가 시각적으로 볼 게 있으니 좀 더 명확한 의사결정을 내릴 수 있었다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;708&quot; data-origin-height=&quot;527&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/beBgiT/btsIHAYtNAF/9cK8HThjbfDxocYcdPgkH1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/beBgiT/btsIHAYtNAF/9cK8HThjbfDxocYcdPgkH1/img.png&quot; data-alt=&quot;하루만에 이만큼 준비해오시다니 대단한 디자이너님...&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/beBgiT/btsIHAYtNAF/9cK8HThjbfDxocYcdPgkH1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbeBgiT%2FbtsIHAYtNAF%2F9cK8HThjbfDxocYcdPgkH1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;605&quot; height=&quot;450&quot; data-origin-width=&quot;708&quot; data-origin-height=&quot;527&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;하루만에 이만큼 준비해오시다니 대단한 디자이너님...&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>TIL</category>
      <category>til</category>
      <author>_자몽</author>
      <guid isPermaLink="true">https://jamong.tistory.com/90</guid>
      <comments>https://jamong.tistory.com/90#entry90comment</comments>
      <pubDate>Fri, 19 Jul 2024 00:00:40 +0900</pubDate>
    </item>
    <item>
      <title>[2024.07.17] 최종프로젝트_기획 2일차</title>
      <link>https://jamong.tistory.com/89</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;좌충우돌 최종프로젝트 하루의 시작은 튜터님과의 회의로 시작!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;전날에 작성된 기획안, 타임라인 등을 보시고 전체적인 일정 조정과 디자이너님과의 협업 방법을 추가로 조언해 주셨다. 확실히 튜터님이 명료하게 길을 제시해주시니 좀 더 수월해지는 느낌&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;튜터님 피드백&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 개발일정: 무리가 아닐까 싶을정도로 빡빡하게 하기(우리의 한계까지?)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 로그인, 모달, 버튼 컴포넌트 등 사전 준비작업 &amp;rArr; ui가 나오면 최대한 빠르게 할 수 있도록&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 다른 서비스들을 탐색해보고 편리한 점, 불편한 점을 직접 느껴보기&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후 팀 노션을 작성하며 팀 이름, 그라운드 룰, 목표 들을 정하고 가볍게 코드 컨벤션을 나누었다. 그리고 다른 여행 관련 애플리케이션을 직접 사용해보았는데 정말 실제 사용자들이 있고 유명한 서비스들은 그만한 이유가 있구나라고 생각했다. UI도 깔끔하고 몇 번 사용해보지 않아도 금세 쉽게 익힐 수 있으며 정보도 다양한 걸 사용자가 아닌 개발자의 시각으로 보니 정말 대단했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;물론 기획하는 과정이 순탄치만은 않고 의견 충돌도 있지만, 이게 기획하는 맛..?이 아닐까 싶다. 다들 힘내서 좋은 결과가 있기를~!!&lt;/p&gt;</description>
      <category>til</category>
      <author>_자몽</author>
      <guid isPermaLink="true">https://jamong.tistory.com/89</guid>
      <comments>https://jamong.tistory.com/89#entry89comment</comments>
      <pubDate>Thu, 18 Jul 2024 01:32:10 +0900</pubDate>
    </item>
    <item>
      <title>[2024.07.11] 팀 프로젝트_재배치 기능</title>
      <link>https://jamong.tistory.com/84</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;오늘의 기능 개선: 재배치 버튼 추가&lt;/b&gt;&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스티커1.gif&quot; data-origin-width=&quot;690&quot; data-origin-height=&quot;1544&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dN5Khy/btsIvwJuSbu/UG1k2JFFqgbSfYYd186Ga1/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dN5Khy/btsIvwJuSbu/UG1k2JFFqgbSfYYd186Ga1/img.gif&quot; data-alt=&quot;기존의 재배치 기능&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dN5Khy/btsIvwJuSbu/UG1k2JFFqgbSfYYd186Ga1/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/dN5Khy/btsIvwJuSbu/UG1k2JFFqgbSfYYd186Ga1/img.gif&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;464&quot; height=&quot;1038&quot; data-filename=&quot;스티커1.gif&quot; data-origin-width=&quot;690&quot; data-origin-height=&quot;1544&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;기존의 재배치 기능&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기존의 재배치 기능은 리스트에서 드래그를 통해 이루어졌는데, 자칫 클릭하다가도 의도치 않게 위치가 수정될 수 있어 '재배치' 버튼을 만들어 해당 버튼 활성화 상태에서만 위치를 수정할 수 있게 변경하였다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;460&quot; data-origin-height=&quot;918&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cj7l95/btsIv5YXHYR/8FxUrGskgPdS4kqpH0B8b0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cj7l95/btsIv5YXHYR/8FxUrGskgPdS4kqpH0B8b0/img.png&quot; data-alt=&quot;재배치 버튼 추가&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cj7l95/btsIv5YXHYR/8FxUrGskgPdS4kqpH0B8b0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcj7l95%2FbtsIv5YXHYR%2F8FxUrGskgPdS4kqpH0B8b0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;460&quot; height=&quot;918&quot; data-origin-width=&quot;460&quot; data-origin-height=&quot;918&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;재배치 버튼 추가&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>TIL</category>
      <category>til</category>
      <author>_자몽</author>
      <guid isPermaLink="true">https://jamong.tistory.com/84</guid>
      <comments>https://jamong.tistory.com/84#entry84comment</comments>
      <pubDate>Fri, 12 Jul 2024 07:07:10 +0900</pubDate>
    </item>
    <item>
      <title>[2024.07.08] 심화 프로젝트 시작</title>
      <link>https://jamong.tistory.com/81</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;오늘 한 일&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;알고리즘 코드카타 풀이 수업&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;심화프로젝트 발제&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;기획 및 디자인&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;챌린지반 수업&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;SSR을 활용한 SUPABASE 로그인/회원가입 기능&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;360&quot; data-origin-height=&quot;765&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b8aqE1/btsIrhFAVR1/S6CYbTqbi8yzoxGq9MkGmk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b8aqE1/btsIrhFAVR1/S6CYbTqbi8yzoxGq9MkGmk/img.png&quot; data-alt=&quot;귀염뽀짝&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b8aqE1/btsIrhFAVR1/S6CYbTqbi8yzoxGq9MkGmk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb8aqE1%2FbtsIrhFAVR1%2FS6CYbTqbi8yzoxGq9MkGmk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;250&quot; height=&quot;531&quot; data-origin-width=&quot;360&quot; data-origin-height=&quot;765&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;귀염뽀짝&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;벌써 최종 프로젝트 이전 마지막 프로젝트!&amp;nbsp; 준비한 기획이 우연찮게 선정되어 진행되었는데, 내배캠 참여 이전에 조금 생각만 해본 구성이 이제는 간단해보여서 뭔가 뿌듯하다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;한 줄 정리 : 모임이 끝나고 후기를 전할 수 있는 롤링페이퍼 프로젝트&lt;/li&gt;
&lt;li&gt;기획 의도 : 어떤 모임을 마치고 소감은 듣고 싶은데, 막상 부탁하기 어려울 때! 어땠어?를 사용해보는건 어떨까요?(팀플을 마치고, 회의를 마치고, 어떤 모임을 마치고)&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>TIL</category>
      <category>til</category>
      <author>_자몽</author>
      <guid isPermaLink="true">https://jamong.tistory.com/81</guid>
      <comments>https://jamong.tistory.com/81#entry81comment</comments>
      <pubDate>Tue, 9 Jul 2024 10:00:08 +0900</pubDate>
    </item>
    <item>
      <title>[2024.07.05] Next.js 14의 loading.tsx와 suspense</title>
      <link>https://jamong.tistory.com/79</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;Next.js에서 데이터 로딩 상태를 표현하기 위한 방법으로 loading.tsx와 suspense를 적용해 보기로 했다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2469&quot; data-origin-height=&quot;1368&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/E2jjC/btsIpNLtwBg/zqcae7AibsEsUABkGAKdQk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/E2jjC/btsIpNLtwBg/zqcae7AibsEsUABkGAKdQk/img.png&quot; data-alt=&quot;로딩화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/E2jjC/btsIpNLtwBg/zqcae7AibsEsUABkGAKdQk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FE2jjC%2FbtsIpNLtwBg%2Fzqcae7AibsEsUABkGAKdQk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;642&quot; height=&quot;356&quot; data-origin-width=&quot;2469&quot; data-origin-height=&quot;1368&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;로딩화면&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1731&quot; data-origin-height=&quot;549&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/deue9W/btsIraZHmNa/GM1UBiehN5aI2wK48GNtwK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/deue9W/btsIraZHmNa/GM1UBiehN5aI2wK48GNtwK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/deue9W/btsIraZHmNa/GM1UBiehN5aI2wK48GNtwK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdeue9W%2FbtsIraZHmNa%2FGM1UBiehN5aI2wK48GNtwK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;624&quot; height=&quot;198&quot; data-origin-width=&quot;1731&quot; data-origin-height=&quot;549&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt; &amp;nbsp;도입배경&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;Toss의 SLASH21의 '프론트엔드 웹 서비스에서 우아하기 비동기 처리하기'라는 세션을 보고 인상 깊은 내용이 있어 적용해보고자 했다. 로딩과&amp;nbsp;에러 상태를 매 페이지마다 useState나 useQuery문 등으로 관리하기에는 비효율적인 것 같아 부분적으로 Suspense와 ErrorBoundary를 사용하면 코드의 중복도 줄이고 로직도 이해하기 편해지지 않을까?라는 생각으로 개인 프로젝트 때 도입해 보았다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2525&quot; data-origin-height=&quot;604&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/caqQ8r/btsIqTcMSqc/X4Pu0Bv8V5xeAYOTK3BXO0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/caqQ8r/btsIqTcMSqc/X4Pu0Bv8V5xeAYOTK3BXO0/img.png&quot; data-alt=&quot;시간 날 때마다 듣는 컨퍼런스&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/caqQ8r/btsIqTcMSqc/X4Pu0Bv8V5xeAYOTK3BXO0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcaqQ8r%2FbtsIqTcMSqc%2FX4Pu0Bv8V5xeAYOTK3BXO0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;747&quot; height=&quot;179&quot; data-origin-width=&quot;2525&quot; data-origin-height=&quot;604&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;시간 날 때마다 듣는 컨퍼런스&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1791&quot; data-origin-height=&quot;1174&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/FgMnG/btsIpwXtvoq/Xmk7kdsOKLHhL4f4hLQ7F0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/FgMnG/btsIpwXtvoq/Xmk7kdsOKLHhL4f4hLQ7F0/img.png&quot; data-alt=&quot;토스ㅣSLASH 21 - 프론트엔드 웹 서비스에서 우아하게 비동기 처리하기&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/FgMnG/btsIpwXtvoq/Xmk7kdsOKLHhL4f4hLQ7F0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FFgMnG%2FbtsIpwXtvoq%2FXmk7kdsOKLHhL4f4hLQ7F0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;590&quot; height=&quot;387&quot; data-origin-width=&quot;1791&quot; data-origin-height=&quot;1174&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;토스ㅣSLASH 21 - 프론트엔드 웹 서비스에서 우아하게 비동기 처리하기&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;  하지만 실패와 실패...&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;Next.js 14에는 클라이언트 사이드일 경우 로딩 상태를 감지하여 &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;loading.tsx의 내용을 보여주는 내부 기능이 탑재되어 있다. 이를 통하여 클라이언트 사이드에서는 수월하게 로딩상태 구현이 가능했으나, 문제는 서버 사이드 렌더링을 할 때는 이미 서버에서 만들어서 보내기 때문에 감지하지 못한다는 것이다.&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;353&quot; data-origin-height=&quot;212&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bdL9Yh/btsIqazo0Tr/F5aGMeCXLDLRWfNqr2ozX0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bdL9Yh/btsIqazo0Tr/F5aGMeCXLDLRWfNqr2ozX0/img.png&quot; data-alt=&quot;실패 기록지와 성공&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bdL9Yh/btsIqazo0Tr/F5aGMeCXLDLRWfNqr2ozX0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbdL9Yh%2FbtsIqazo0Tr%2FF5aGMeCXLDLRWfNqr2ozX0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;353&quot; height=&quot;212&quot; data-origin-width=&quot;353&quot; data-origin-height=&quot;212&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;실패 기록지와 성공&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;Next.js가 익숙하지 않았기에 일명 삽질(?)을 많이 했다. 특히 loading.tsx가 서버 컴포넌트인데, lottie 애니메이션을 사용하는 컴포넌트는 클라이언트 컴포넌트여서, 글씨는 잘 출력되는데 lottie 애니메이션이 출력되지 않는 현상이 참 많았다...&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1731&quot; data-origin-height=&quot;549&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ccPjx5/btsIqQmRdPZ/3gUbk6KkWMkNFXMvEZoVrK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ccPjx5/btsIqQmRdPZ/3gUbk6KkWMkNFXMvEZoVrK/img.png&quot; data-alt=&quot;LoadingAnimation은 클라이언트 컴포넌트&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ccPjx5/btsIqQmRdPZ/3gUbk6KkWMkNFXMvEZoVrK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FccPjx5%2FbtsIqQmRdPZ%2F3gUbk6KkWMkNFXMvEZoVrK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;630&quot; height=&quot;200&quot; data-origin-width=&quot;1731&quot; data-origin-height=&quot;549&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;LoadingAnimation은 클라이언트 컴포넌트&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;  해결방법&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;이 문제로 거의 3일 동안 해결방법을 찾아 헤맸고, 최종적으로는 useSuspenseQuery와 dynamic의 조합으로 페이지 내부가 아닌, 외부에서 로딩상태를 처리할 수 있게 되었다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;7. suspense Homepage.png&quot; data-origin-width=&quot;1480&quot; data-origin-height=&quot;798&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/sTwtf/btsIrgZUaNl/xDwT7OkYcUhRo4kle0RgOK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/sTwtf/btsIrgZUaNl/xDwT7OkYcUhRo4kle0RgOK/img.png&quot; data-alt=&quot;dynamic 기능&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/sTwtf/btsIrgZUaNl/xDwT7OkYcUhRo4kle0RgOK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FsTwtf%2FbtsIrgZUaNl%2FxDwT7OkYcUhRo4kle0RgOK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;619&quot; height=&quot;334&quot; data-filename=&quot;7. suspense Homepage.png&quot; data-origin-width=&quot;1480&quot; data-origin-height=&quot;798&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;dynamic 기능&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;7. suspense PokemonList.png&quot; data-origin-width=&quot;1188&quot; data-origin-height=&quot;292&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nyZZp/btsIqVaFhFB/wUuFXzDzQwGBiVq78BtNx1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nyZZp/btsIqVaFhFB/wUuFXzDzQwGBiVq78BtNx1/img.png&quot; data-alt=&quot;공식문서를 통해 알게된 useSuspenseQuery&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nyZZp/btsIqVaFhFB/wUuFXzDzQwGBiVq78BtNx1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FnyZZp%2FbtsIqVaFhFB%2FwUuFXzDzQwGBiVq78BtNx1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;620&quot; height=&quot;152&quot; data-filename=&quot;7. suspense PokemonList.png&quot; data-origin-width=&quot;1188&quot; data-origin-height=&quot;292&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;공식문서를 통해 알게된 useSuspenseQuery&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;dynamic은 자체적으로 React.lazy()와 Suspense가 내장되어 있으며, useSuspenseQuery를 통해, Suspense 상태를 감지할 수 있게 해 주었다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt; 하지만 절반의 성공?&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;결국 외부에서 페이지나 컴포넌트들의 로딩상태를 관리할 수 있게 되었으나, 결과적으로 나중엔 하나하나 dynamic으로 컴포넌트들을 import 해야 한다는 번거로움도 있을 수 있으며 &amp;lt;Suspense&amp;gt;&amp;lt;/Suspense&amp;gt; 안에 넣어 직관적으로 '이 컴포넌트들은 Suspense가 적용되어 있구나'라는 인상은 주지 못했다. 좀 더 연구해서 꼭 가능하게끔 해보고 싶다. Suspense는 SSR에서 사용하지 못한다고 많은 블로그에서 본 것 같지만, 무언가 방법이 있지 않을까?&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;오랜만에 말끔하게 해결하지 못한 트러블슈팅이라 찜찜하지만, 나중에 보았을 땐 '그땐 왜 이것도 해결 못했나?'라는 생각이 들겠지 싶다.&lt;/span&gt;&lt;/p&gt;</description>
      <category>TIL</category>
      <category>til</category>
      <category>toss</category>
      <category>toss slash21</category>
      <author>_자몽</author>
      <guid isPermaLink="true">https://jamong.tistory.com/79</guid>
      <comments>https://jamong.tistory.com/79#entry79comment</comments>
      <pubDate>Mon, 8 Jul 2024 06:06:46 +0900</pubDate>
    </item>
  </channel>
</rss>