<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>코딩 공부 일지</title>
    <link>https://cocoon1787.tistory.com/</link>
    <description>개발 블로그</description>
    <language>ko</language>
    <pubDate>Thu, 6 Aug 2026 16:45:49 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>Cocoon_</managingEditor>
    <image>
      <title>코딩 공부 일지</title>
      <url>https://tistory1.daumcdn.net/tistory/3697807/attach/2e5e3b8dd104408baf1d5952db94a60c</url>
      <link>https://cocoon1787.tistory.com</link>
    </image>
    <item>
      <title>Goodbye 2024, Hello 2025</title>
      <link>https://cocoon1787.tistory.com/883</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;626&quot; data-origin-height=&quot;373&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mD5Xm/btsLBhbJG8l/L3jPxXynwnM9iRXDZf0Nvk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mD5Xm/btsLBhbJG8l/L3jPxXynwnM9iRXDZf0Nvk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mD5Xm/btsLBhbJG8l/L3jPxXynwnM9iRXDZf0Nvk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmD5Xm%2FbtsLBhbJG8l%2FL3jPxXynwnM9iRXDZf0Nvk%2Fimg.jpg&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;626&quot; height=&quot;373&quot; data-origin-width=&quot;626&quot; data-origin-height=&quot;373&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;2024년에 세웠었던 목표&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;(1) 받는 만큼 일하는 게 아닌 받고 싶은 만큼 일하기&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;2년간 열심히 일해온 덕분에 올해 성공적으로 이직을 하게 되었다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt; &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;(2) &lt;/span&gt;5000 commit 달성하기&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;전 회사에서는 개인 git 계정으로 개발을 했었기 때문에 2024년에는 이게 가능했었을 수도 있었을 테지만 이직 후 회사일에 집중하게 되면서 집에 와서 따로 개발을 하지 않다 보니 이루기 쉽지 않은 목표가 되었다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; font-size: 16px; letter-spacing: 0px; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt; &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;(3) &lt;/span&gt;Modern Javascript Deep Dive 책 완독&lt;/b&gt;&lt;br /&gt;이 부분도 회사일에 집중하다 보니 개인 공부 시간이 많지 않아 쉽지 않았다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt; &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;(4) &lt;/span&gt;건강을 위한 주 3회 운동&lt;/b&gt;&lt;br /&gt;야근을 많이 하다 보니 가장 근간이 되는 기초 체력이 중요하다고 크게 느끼게 되었었다. 요즘은 일이 좀 바빠서 주 2회로 30~40분씩 꾸준히 유산소 운동을 하고 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt; &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;(5) &lt;/span&gt;사이드 프로젝트 미니 거래소 앱 만들기&lt;/b&gt;&lt;br /&gt;어쩌다 보니 거래소 도메인으로 다시 돌아오게 되었고(CEX -&amp;gt; WEB3 -&amp;gt; CEX), 회사일에 집중하다 보니 따로 사이드 프로젝트를 할 시간이 없었다.&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: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;2024년 회고&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2024년&amp;nbsp;한&amp;nbsp;해를&amp;nbsp;한&amp;nbsp;문장으로&amp;nbsp;정의하자면&amp;nbsp;&quot;야근으로&amp;nbsp;시작해서&amp;nbsp;야근으로&amp;nbsp;끝난&amp;nbsp;한&amp;nbsp;해&quot;라고&amp;nbsp;정리할&amp;nbsp;수&amp;nbsp;있을&amp;nbsp;것&amp;nbsp;같다.&amp;nbsp;2024년&amp;nbsp;12월&amp;nbsp;31일&amp;nbsp;~&amp;nbsp;2025년&amp;nbsp;1월&amp;nbsp;1일&amp;nbsp;새벽&amp;nbsp;서비스&amp;nbsp;점검으로&amp;nbsp;새해를&amp;nbsp;회사에서&amp;nbsp;보냈다.&amp;nbsp;주변에서는&amp;nbsp;그러다가&amp;nbsp;번아웃이&amp;nbsp;올&amp;nbsp;것이라고&amp;nbsp;걱정하는&amp;nbsp;시선이&amp;nbsp;많지만&amp;nbsp;만&amp;nbsp;3년&amp;nbsp;차가&amp;nbsp;다되어&amp;nbsp;가는&amp;nbsp;현시점에&amp;nbsp;아직까지는&amp;nbsp;일하게는&amp;nbsp;재밌고&amp;nbsp;시간도&amp;nbsp;정말&amp;nbsp;빨리&amp;nbsp;가는&amp;nbsp;것&amp;nbsp;같다.&amp;nbsp;아무래도&amp;nbsp;자기가&amp;nbsp;하고&amp;nbsp;싶은&amp;nbsp;일을&amp;nbsp;하다&amp;nbsp;보니&amp;nbsp;가능한&amp;nbsp;게&amp;nbsp;아닌가&amp;nbsp;싶다.&amp;nbsp;이&amp;nbsp;직종이&amp;nbsp;나와&amp;nbsp;잘&amp;nbsp;맞는&amp;nbsp;직종&amp;nbsp;같으나&amp;nbsp;5년&amp;nbsp;뒤에도&amp;nbsp;Frontend를&amp;nbsp;할까&amp;nbsp;라는&amp;nbsp;질문에는&amp;nbsp;잘&amp;nbsp;모르겠다는&amp;nbsp;생각이&amp;nbsp;든다.&amp;nbsp;지금은&amp;nbsp;Frontend&amp;nbsp;가&amp;nbsp;재밌지만&amp;nbsp;AI,&amp;nbsp;ML,&amp;nbsp;DL&amp;nbsp;데이터&amp;nbsp;분석&amp;nbsp;업무도&amp;nbsp;재밌어&amp;nbsp;보이고&amp;nbsp;BE도&amp;nbsp;재밌어&amp;nbsp;보인다.&amp;nbsp;그냥&amp;nbsp;개발&amp;nbsp;자체가&amp;nbsp;재밌는&amp;nbsp;게&amp;nbsp;아닐까&amp;nbsp;싶다. &lt;br /&gt;&lt;br /&gt;2024년&amp;nbsp;5월까지&amp;nbsp;블록체인&amp;nbsp;스타트업에서&amp;nbsp;근무를&amp;nbsp;하면서&amp;nbsp;&amp;nbsp;WEB3&amp;nbsp;적인&amp;nbsp;지식과&amp;nbsp;스킬들을&amp;nbsp;배웠고&amp;nbsp;좋은&amp;nbsp;동료들과&amp;nbsp;재밌는&amp;nbsp;회사&amp;nbsp;생활을&amp;nbsp;보냈었다.&amp;nbsp;특히&amp;nbsp;자율&amp;nbsp;출퇴근과&amp;nbsp;재택이&amp;nbsp;가능했던&amp;nbsp;점이&amp;nbsp;너무나도&amp;nbsp;좋았다.(실제로는&amp;nbsp;출근을&amp;nbsp;선호해서&amp;nbsp;재택을&amp;nbsp;많이&amp;nbsp;하지는&amp;nbsp;않았다)&amp;nbsp;그러나&amp;nbsp;블록체인&amp;nbsp;업계에서&amp;nbsp;근무를&amp;nbsp;하면서&amp;nbsp;하면서&amp;nbsp;한국에서의&amp;nbsp;WEB3&amp;nbsp;입지나&amp;nbsp;회사&amp;nbsp;방향성을&amp;nbsp;생각했었을&amp;nbsp;때&amp;nbsp;내가&amp;nbsp;생각했던&amp;nbsp;것과는&amp;nbsp;좀&amp;nbsp;다른&amp;nbsp;부분이&amp;nbsp;있었고&amp;nbsp;나의&amp;nbsp;방향성과는&amp;nbsp;맞지&amp;nbsp;않다고&amp;nbsp;생각되어&amp;nbsp;이직하는&amp;nbsp;것을&amp;nbsp;결심하게&amp;nbsp;되었다. &lt;br /&gt;&lt;br /&gt;채용&amp;nbsp;공고가&amp;nbsp;올라온&amp;nbsp;강남,&amp;nbsp;성수,&amp;nbsp;판교에&amp;nbsp;있는&amp;nbsp;유니콘&amp;nbsp;회사들,&amp;nbsp;시리즈&amp;nbsp;C&amp;nbsp;이상&amp;nbsp;투자를&amp;nbsp;받은&amp;nbsp;회사들에&amp;nbsp;지원을&amp;nbsp;했었느냐&amp;nbsp;채용&amp;nbsp;한파를&amp;nbsp;직접적으로&amp;nbsp;겪어보니&amp;nbsp;정말&amp;nbsp;쉽지&amp;nbsp;않았고&amp;nbsp;좌절도&amp;nbsp;많이&amp;nbsp;했었다.&amp;nbsp;신입,&amp;nbsp;주니어급&amp;nbsp;PO가&amp;nbsp;확실히&amp;nbsp;줄어들고&amp;nbsp;서류&amp;nbsp;탈락&amp;nbsp;커트라인이&amp;nbsp;꽤나&amp;nbsp;높아졌다는&amp;nbsp;생각이&amp;nbsp;들었다.&amp;nbsp;또한&amp;nbsp;이력서상으로&amp;nbsp;블록체인&amp;nbsp;쪽으로&amp;nbsp;많이&amp;nbsp;기술되어&amp;nbsp;있고&amp;nbsp;지원하는&amp;nbsp;회사의&amp;nbsp;도메인에&amp;nbsp;플러스가&amp;nbsp;될만한&amp;nbsp;요소가&amp;nbsp;없었기&amp;nbsp;때문은&amp;nbsp;아닐까&amp;nbsp;생각을&amp;nbsp;하였다.&amp;nbsp;&amp;nbsp; &lt;br /&gt;&lt;br /&gt;그러나 여러 개의 지원중에 딱 한 군데를 붙게 되었고 그 회사가 현재 재직 중인 CEX이다. 아무래도 커리어가 블록체인 쪽으로 일관성이 있어 합격에 플러스 요소가 되지 않았나 싶다. (여담이지만 사실 블록체인에는 별 관심이 없다... 첫 회사는 붙어서 바로 갔고, 두 번째 회사는 잘 모르고 갔기 때문...) &lt;br /&gt;회사는 이때까지 다녔던 회사 중에서 가장 큰 편이었고, 무엇보다도 같은 포지션 직군이 많고 잘하시는 개발자분들도 많아서 배울 점이 많다는 점이 장점인 것 같다. 작년 4분기에는 Bull market이다 보니 일이 꽤 많이 들어왔고 야근도 많이 했던 것 같다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;연차가 쌓일수록 느끼는 점은 기술적 능력치도 중요하지만 사람과 함께 생활하고 일을 하다 보니 원활한 커뮤니케이션 방식과 협업 스킬이 정말 중요하다는 점이었다. 이전까지는 거의 혼자 또는 두 명이서 일을 같이 하다 보니 크게 못 느낀 부분이었는데 좀 큰 회사에 들어가 보니 이러한 생각을 많이 느끼게 되었다. 아무리 뛰어난 개인의 능력도 팀의 시너지를 따라갈 수 없다는 것을 깨달았고 대규모 프로젝트에서 여러 팀과의 협업, 다양한 이해관계자들과의 소통에 대한 중요성을 새롭게 인식하게 되었다. 신입 때 매번 생각했었던 &lt;b&gt;&quot;팀에 기여할 수 있는 개발자&quot;&lt;/b&gt;에 대한 정의가 바뀌게 된 계기가 된 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2024년 말에는 4년 동안 살았던 6평 원룸에서 10평 오피스텔로 이사를 가게 되었다. 원하는 지역에 매물이 없어 네이버 부동산을 거의 한 달간 매일 봤었고 동시에 회사 업무하느라 정신없고 집주인은 보증금을 안 주려고 해서 육체적 + 정신적으로 힘들었던 연말이었다. 다행히도 잘 해결되었고 집도 이전보다 넓어져서 행복한 나날을 보내고 있다. 직전 집은 바닥이 장판이어서 바퀴 달린 의자로 오래 앉아있으면 장판이 울고 밀리고 했었는데, 이번에는 마루 바닥인 집으로 이사 와서 그 부분이 정말 마음에 드는 것 같다.&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;2025년 다짐, 목표&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;매년 새해 목표를 포스팅하다 보니 역시 사람은 쉽게 변하지 않고 같은 실수를 반복한다는 것을 깨달았다.&lt;br /&gt;목표는 거창하지 않고 소소하면서 매우 현실적인 것들이 좋을 것 같다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;(1) 팀에 기여할 수 있는 개발자 되기&lt;/b&gt;&lt;br /&gt;새로운 회사에서 적응하고 신뢰가 쌓이고 업무 효율이 나오는 시기가 입사 후 1년 차로 생각한다. 2024년 5월 27일에 입사를 하여 7개월 정도가 지났지만 아직 업무적으로 배우고 좀 더 알아가야 할 부분이 많이 있는 것 같다. &lt;br /&gt;나의 장점은 업무를 대하는 태도와 책임감이다. 그러한 점을 바탕으로 6개월 뒤에는 더 큰 가치를 창출하는 팀원으로 발전하기 위해 노력할 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;(2) 주 2~3회 꾸준한 유산소 운동&lt;/b&gt;&lt;br /&gt;운동 1시간이 결론적으로 1시간 반 이상의 효율성을 더 벌어다 준다고 생각을 한다. &lt;br /&gt;좀 더 많은 시간 안정적으로 야근을 하기 위해서 꾸준하게 운동을 하자. (나처럼 생각하는 사람이 또 있으려나...)&lt;br /&gt;2024년에 했던 그대로 하면 될 것 같다. (주말에 종종 등산 가는 것도 도움이 될 것 같다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;(3) 사이드 프로젝트 개발하기&lt;/b&gt;&lt;br /&gt;개발적으로 성장하기 위해서는 회사일도 중요하지만 외부적으로 새로운 기술도 써보고 다른 환경에서 개발을 하는 것이 회사에서는 채울 수 없는 부분을 채우는데 도움이 된다고 생각한다. 작년에 개발했었던 React UI library인&amp;nbsp; &lt;a href=&quot;https://liteui-web.vercel.app/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Lite UI&lt;/a&gt;의 주간 다운로드 수 1000회 달성하기를 목표로 할 것이다.&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 data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;[2024년 회고록]&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1735748397920&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;Goodbye 2023, Hello 2024&quot; data-og-description=&quot;2023년도 회고록 Work 2023년 3월 20일에는 역삼역과 강남역 사이에 위치한 새로운 회사로 이직을 하게 되었다. 첫 회사였던 이전 회사는 딱 1년을 채우고 퇴사를 했었고 현재 회사에서 근무한 지는 1&quot; data-og-host=&quot;cocoon1787.tistory.com&quot; data-og-source-url=&quot;https://cocoon1787.tistory.com/880&quot; data-og-url=&quot;https://cocoon1787.tistory.com/880&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bChRA8/hyXSrlNH63/d0KpO7eAlKr72sq3FXFkBk/img.jpg?width=800&amp;amp;height=533&amp;amp;face=0_0_800_533,https://scrap.kakaocdn.net/dn/NL2SH/hyXSpIhTWj/NtKGlTuJSVJKmsG2hw6fB0/img.jpg?width=800&amp;amp;height=533&amp;amp;face=0_0_800_533,https://scrap.kakaocdn.net/dn/tZr8l/hyXSupjik5/dioVwQQrcLyldFF07ufPd0/img.png?width=940&amp;amp;height=237&amp;amp;face=0_0_940_237&quot;&gt;&lt;a href=&quot;https://cocoon1787.tistory.com/880&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://cocoon1787.tistory.com/880&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bChRA8/hyXSrlNH63/d0KpO7eAlKr72sq3FXFkBk/img.jpg?width=800&amp;amp;height=533&amp;amp;face=0_0_800_533,https://scrap.kakaocdn.net/dn/NL2SH/hyXSpIhTWj/NtKGlTuJSVJKmsG2hw6fB0/img.jpg?width=800&amp;amp;height=533&amp;amp;face=0_0_800_533,https://scrap.kakaocdn.net/dn/tZr8l/hyXSupjik5/dioVwQQrcLyldFF07ufPd0/img.png?width=940&amp;amp;height=237&amp;amp;face=0_0_940_237');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Goodbye 2023, Hello 2024&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;2023년도 회고록 Work 2023년 3월 20일에는 역삼역과 강남역 사이에 위치한 새로운 회사로 이직을 하게 되었다. 첫 회사였던 이전 회사는 딱 1년을 채우고 퇴사를 했었고 현재 회사에서 근무한 지는 1&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;cocoon1787.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category> 일상</category>
      <author>Cocoon_</author>
      <guid isPermaLink="true">https://cocoon1787.tistory.com/883</guid>
      <comments>https://cocoon1787.tistory.com/883#entry883comment</comments>
      <pubDate>Thu, 2 Jan 2025 03:18:57 +0900</pubDate>
    </item>
    <item>
      <title>저의 첫 오픈소스를 소개합니다.</title>
      <link>https://cocoon1787.tistory.com/882</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1200&quot; data-origin-height=&quot;630&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c2URxW/btsHoJpAqKI/K5vvxjk1i49ETfo9mVGIE0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c2URxW/btsHoJpAqKI/K5vvxjk1i49ETfo9mVGIE0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c2URxW/btsHoJpAqKI/K5vvxjk1i49ETfo9mVGIE0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc2URxW%2FbtsHoJpAqKI%2FK5vvxjk1i49ETfo9mVGIE0%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;1200&quot; height=&quot;630&quot; data-origin-width=&quot;1200&quot; data-origin-height=&quot;630&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;안녕하세요.&amp;nbsp;3년차&amp;nbsp;프론트엔드&amp;nbsp;개발자&amp;nbsp;김준영이라고&amp;nbsp;합니다.&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;고객들의 돈이 오가는 서비스를&amp;nbsp;개발하다 보면&amp;nbsp;서버에서 값을 받아&amp;nbsp;aggregation 하여&amp;nbsp;화면에 금액이나 수량을&amp;nbsp;표시해 주는&amp;nbsp;상황이 많이 생기게 됩니다. 자바스크립트에서는&amp;nbsp;0.1+0.2 !==&amp;nbsp;0.3인 문제가 있기 때문에 이와 같은 정확도 문제를 해결하기 위해서 bignumber.js, big.js, decimal.js와 같은 정밀 계산 라이브러리를 많이 사용하게 됩니다. 하지만 실무에서 해당 라이브러리들을&amp;nbsp;사용해 보면서&amp;nbsp;조금 아쉬운 포인트들이 있었고, 아래와 문제들을 좀 더 개선한 오픈소스를 만들어보자는 생각이 들었습니다..!&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;-&amp;nbsp;계산할 때마다&amp;nbsp;new 생성자를&amp;nbsp;사용해야 하는&amp;nbsp;점을 어떻게 개선할 수 있을까?&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;- 0.000001보다 작은 수는 왜 string type의 지수표현식으로 반환될까? (ex : new&amp;nbsp;Big(0.0000001).valueOf()&amp;nbsp;=&amp;gt; &quot;1e-7&quot;)&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;-&amp;nbsp;add, sub, mul, div와&amp;nbsp;같은 메서드들에서 single parameter가 아닌 rest parameter 방식으로 값을 받게 할&amp;nbsp;수는&amp;nbsp;없을까?&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;이러한 포인트들을 개선하기 위해서 big.js를 활용하여 @ma9pie/math라는 계산 유틸 라이브러리를 개발하였습니다. 내부적으로 계산은 big.js로 처리하고 DX(Developer Experience)에 좀 더 중점을 두었습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;background-color: #ffffff; color: #111111; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;  Install&lt;/b&gt;&lt;/h2&gt;
&lt;pre id=&quot;code_1715665032465&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;npm i @ma9pie/math&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;background-color: #ffffff; color: #111111; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;  Use&lt;/b&gt;&lt;/h2&gt;
&lt;pre class=&quot;javascript&quot; style=&quot;background-color: #f7f7f7; color: #333333; text-align: start;&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;import { math } from '@ma9pie/math';

math(1).add(2).sub(3).value(); // 0
math(10).add(5).sub(7).mul(2).div(4).value(); // 4&lt;/code&gt;&lt;/pre&gt;
&lt;div style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot;&gt;
&lt;p style=&quot;color: #111111;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;value&lt;br /&gt;&lt;/b&gt;value() =&amp;gt; string &lt;br /&gt;returns calculated value as string.&lt;/p&gt;
&lt;/div&gt;
&lt;pre class=&quot;less&quot; style=&quot;background-color: #f7f7f7; color: #333333; text-align: start;&quot;&gt;&lt;code&gt;math(1000).value(); // '1000'
math('1e7').value(); // '10000000'
math(1e-7).value(); // '0.0000001'
&lt;/code&gt;&lt;/pre&gt;
&lt;div style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot;&gt;
&lt;p style=&quot;color: #111111;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;toNumber&lt;br /&gt;&lt;/b&gt;toNumber() =&amp;gt; number &lt;br /&gt;returns calculated value as number.&lt;/p&gt;
&lt;/div&gt;
&lt;pre class=&quot;less&quot; style=&quot;background-color: #f7f7f7; color: #333333; text-align: start;&quot;&gt;&lt;code&gt;math(1000).toNumber(); // 1000
math('1e7').toNumber(); // 10000000
math(1e-7).toNumber(); // 1e-7
&lt;/code&gt;&lt;/pre&gt;
&lt;div style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot;&gt;
&lt;p style=&quot;color: #111111;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;add&lt;br /&gt;&lt;/b&gt;.add(n) =&amp;gt; Big n : number | string | BigInt &lt;br /&gt;returns the current value added by n.&lt;span style=&quot;color: #333333; font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; font-size: 16px; letter-spacing: 0px;&quot;&gt;&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;i&gt;if the n is invalid, it is treated as 0.&lt;/i&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;pre class=&quot;angelscript&quot; style=&quot;background-color: #f7f7f7; color: #333333; text-align: start;&quot;&gt;&lt;code&gt;0.1 + 0.2, // 0.30000000000000004
math(0.1).add(0.2).value(); // '0.3'
math(1).add(2).add(3).value(); // '6'
math(1).add(2, 3, 4).value(); // '10'
&lt;/code&gt;&lt;/pre&gt;
&lt;div style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot;&gt;
&lt;p style=&quot;color: #111111;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;sub&lt;br /&gt;&lt;/b&gt;.sub(n) =&amp;gt; Big n : number | string | BigInt &lt;br /&gt;returns the current value subtracted by n.&lt;span style=&quot;color: #333333; font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; font-size: 16px; letter-spacing: 0px;&quot;&gt;&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;i&gt;if the n is invalid, it is treated as 0.&lt;/i&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;pre class=&quot;perl&quot; style=&quot;background-color: #f7f7f7; color: #333333; text-align: start;&quot;&gt;&lt;code&gt;0.3 - 0.1, // 0.19999999999999998
math(0.3).sub(0.1).value(); // '0.2'
math(1).sub(2).sub(3).value(); // '-4'
math(1).sub(2, 3, 4).value(); // '-8'
&lt;/code&gt;&lt;/pre&gt;
&lt;div style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot;&gt;
&lt;p style=&quot;color: #111111;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;mul&lt;br /&gt;&lt;/b&gt;.mul(n) =&amp;gt; Big n : number | string | BigInt &lt;br /&gt;returns the current value multiplied by n.&lt;span style=&quot;color: #333333; font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; font-size: 16px; letter-spacing: 0px;&quot;&gt;&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;i&gt;if the n is invalid, it is treated as 0.&lt;/i&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;pre class=&quot;angelscript&quot; style=&quot;background-color: #f7f7f7; color: #333333; text-align: start;&quot;&gt;&lt;code&gt;0.6 * 3, // 1.7999999999999998
math(0.6).mul(3).value(); // '1.8'
math(2).mul(2).mul(2).value(); // '8'
math(2).mul(2, 2, 2).value(); // '16'
&lt;/code&gt;&lt;/pre&gt;
&lt;div style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot;&gt;
&lt;p style=&quot;color: #111111;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;div&lt;br /&gt;&lt;/b&gt;.div(n) =&amp;gt; Big n : number | string | BigInt &lt;br /&gt;returns the current value divided by n.&lt;span style=&quot;color: #333333; font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; font-size: 16px; letter-spacing: 0px;&quot;&gt;&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;i&gt;if the n is invalid, it is treated as 0.&lt;/i&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;pre class=&quot;angelscript&quot; style=&quot;background-color: #f7f7f7; color: #333333; text-align: start;&quot;&gt;&lt;code&gt;355 / 113, // 3.1415929203539825
math(355).div(113).value(); // '3.141592920353982300'
math(10).div(3).value(); // '3.333333333333333333'
math(1000).div(10, 10, 10).value(); // '1'
&lt;/code&gt;&lt;/pre&gt;
&lt;div style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot;&gt;
&lt;p style=&quot;color: #111111;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;abs&lt;br /&gt;&lt;/b&gt;.abs() =&amp;gt; Big returns the absolute current value.&lt;/p&gt;
&lt;/div&gt;
&lt;pre class=&quot;gcode&quot; style=&quot;background-color: #f7f7f7; color: #333333; text-align: start;&quot;&gt;&lt;code&gt;math(-0.8).abs().value(); // '0.8'
&lt;/code&gt;&lt;/pre&gt;
&lt;div style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot;&gt;
&lt;p style=&quot;color: #111111;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;pow&lt;br /&gt;&lt;/b&gt;.pow(n) =&amp;gt; Big n : number | string | BigInt &lt;br /&gt;returns the current value nth power.&lt;span style=&quot;color: #333333; font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; font-size: 16px; letter-spacing: 0px;&quot;&gt;&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;i&gt;if the n is invalid, it is treated as 0.&lt;/i&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;pre class=&quot;angelscript&quot; style=&quot;background-color: #f7f7f7; color: #333333; text-align: start;&quot;&gt;&lt;code&gt;0.7 ** 2, // 0.48999999999999994
Math.pow(0.7, 2); // 0.48999999999999994
math(0.7).pow(2).value(); // '0.49'
&lt;/code&gt;&lt;/pre&gt;
&lt;div style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot;&gt;
&lt;p style=&quot;color: #111111;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;eq&lt;br /&gt;&lt;/b&gt;.eq(n) =&amp;gt; boolean n : number | string | BigInt &lt;br /&gt;returns whether the current value and n are the same.&lt;/p&gt;
&lt;/div&gt;
&lt;pre class=&quot;perl&quot; style=&quot;background-color: #f7f7f7; color: #333333; text-align: start;&quot;&gt;&lt;code&gt;0.1 + 0.2 === 0.3, // false
math(0.1).add(0.2).eq(0.3); // true
math('0.0000001').eq(1e-7); // true
math(1e7).eq(10000000); // true
&lt;/code&gt;&lt;/pre&gt;
&lt;div style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot;&gt;
&lt;p style=&quot;color: #111111;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;gt&lt;br /&gt;&lt;/b&gt;.gt(n) =&amp;gt; boolean n : number | string | BigInt &lt;br /&gt;returns whether the current value is greater than n.&lt;/p&gt;
&lt;/div&gt;
&lt;pre class=&quot;angelscript&quot; style=&quot;background-color: #f7f7f7; color: #333333; text-align: start;&quot;&gt;&lt;code&gt;0.1 + 0.2 &amp;gt; 0.3, // true
math(0.1).add(0.2).gt(0.3); // false
&lt;/code&gt;&lt;/pre&gt;
&lt;div style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot;&gt;
&lt;p style=&quot;color: #111111;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;gte&lt;br /&gt;&lt;/b&gt;.gte(n) =&amp;gt; boolean n : number | string | BigInt &lt;br /&gt;returns whether the current value is greater than or equal to n.&lt;/p&gt;
&lt;/div&gt;
&lt;pre class=&quot;angelscript&quot; style=&quot;background-color: #f7f7f7; color: #333333; text-align: start;&quot;&gt;&lt;code&gt;0.1 + 0.2 &amp;lt;= 0.3, // false
math(0.1).add(0.2).gte(0.3); // true
&lt;/code&gt;&lt;/pre&gt;
&lt;div style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot;&gt;
&lt;p style=&quot;color: #111111;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;lt&lt;br /&gt;&lt;/b&gt;.lt(n) =&amp;gt; boolean n : number | string | BigInt &lt;br /&gt;returns whether the current value is less than n.&lt;/p&gt;
&lt;/div&gt;
&lt;pre class=&quot;angelscript&quot; style=&quot;background-color: #f7f7f7; color: #333333; text-align: start;&quot;&gt;&lt;code&gt;0.1 + 0.2 &amp;gt; 0.3, // true
math(0.1).add(0.2).lt(0.3); // false
&lt;/code&gt;&lt;/pre&gt;
&lt;div style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot;&gt;
&lt;p style=&quot;color: #111111;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;lte&lt;br /&gt;&lt;/b&gt;.lte(n) =&amp;gt; boolean n : number | string | BigInt &lt;br /&gt;returns whether the current value is less than or equal to n.&lt;/p&gt;
&lt;/div&gt;
&lt;pre class=&quot;angelscript&quot; style=&quot;background-color: #f7f7f7; color: #333333; text-align: start;&quot;&gt;&lt;code&gt;0.1 + 0.2 &amp;lt;= 0.3, // false
math(0.1).add(0.2).lte(0.3); // true
&lt;/code&gt;&lt;/pre&gt;
&lt;div style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot;&gt;
&lt;p style=&quot;color: #111111;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;isZero&lt;br /&gt;&lt;/b&gt;.isZero() =&amp;gt; boolean &lt;br /&gt;returns whether the current value is 0.&lt;/p&gt;
&lt;/div&gt;
&lt;pre class=&quot;less&quot; style=&quot;background-color: #f7f7f7; color: #333333; text-align: start;&quot;&gt;&lt;code&gt;math(0).isZero(); // true
math(-0).isZero(); // true
math(0.0).isZero(); // true
math('0').isZero(); // true
math('-0').isZero(); // true
math(Number.MIN_SAFE_INTEGER).isZero(); // false
math(Number.MAX_SAFE_INTEGER).isZero(); // false
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot;&gt;
&lt;h2 style=&quot;color: #111111;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;  Test&lt;/b&gt;&lt;/h2&gt;
&lt;/div&gt;
&lt;pre class=&quot;dockerfile&quot; style=&quot;background-color: #f7f7f7; color: #333333; text-align: start;&quot;&gt;&lt;code&gt;npm run test&lt;/code&gt;&lt;/pre&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 data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;git : &lt;a href=&quot;https://github.com/ma9pie/math&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://github.com/ma9pie/math&lt;/a&gt;&lt;br /&gt;npm : &lt;a href=&quot;https://www.npmjs.com/package/@ma9pie/math&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.npmjs.com/package/@ma9pie/math&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;감사합니다!&lt;/span&gt;&lt;/p&gt;</description>
      <category> &amp;zwj; Project</category>
      <author>Cocoon_</author>
      <guid isPermaLink="true">https://cocoon1787.tistory.com/882</guid>
      <comments>https://cocoon1787.tistory.com/882#entry882comment</comments>
      <pubDate>Wed, 15 May 2024 15:47:10 +0900</pubDate>
    </item>
    <item>
      <title>Jest 메서드 정리</title>
      <link>https://cocoon1787.tistory.com/881</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;jest는 프론트엔드에서 자주 사용되는 테스팅 라이브러리 입니다. 간단한 유닛 테스트부터 통합 테스트, E2E 테스트까지 가능합니다.&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;Common Matchers&lt;/b&gt;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;toBe&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;같은 메모리 주소를 가리키고 있는지 확인&lt;/p&gt;
&lt;pre class=&quot;lisp&quot;&gt;&lt;code&gt;test('two plus two is four', () =&amp;gt; {
  expect(2 + 2).toBe(4);
});
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;toEqual&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;값 자체가 같은지 비교&lt;/p&gt;
&lt;pre class=&quot;haskell&quot;&gt;&lt;code&gt;test('object assignment', () =&amp;gt; {
  const data = {one: 1};
  data['two'] = 2;
  expect(data).toEqual({one: 1, two: 2});
});
&lt;/code&gt;&lt;/pre&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;Truthiness&lt;/b&gt;&lt;/h3&gt;
&lt;pre class=&quot;lisp&quot;&gt;&lt;code&gt;test('null', () =&amp;gt; {
  const n = null;
  expect(n).toBeNull();
  expect(n).toBeDefined();
  expect(n).not.toBeUndefined();
  expect(n).not.toBeTruthy();
  expect(n).toBeFalsy();
});

test('zero', () =&amp;gt; {
  const z = 0;
  expect(z).not.toBeNull();
  expect(z).toBeDefined();
  expect(z).not.toBeUndefined();
  expect(z).not.toBeTruthy();
  expect(z).toBeFalsy();
});
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;toBeNull&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;null 인지&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;toBeUndefined&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;undefined 인지&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;toBeDefined&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;toBeDefined의 반대&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;toBeTruthy&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;true 인지&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;toBeFalsy&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;false 인지&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;Numbers&lt;/b&gt;&lt;/h3&gt;
&lt;pre class=&quot;lisp&quot;&gt;&lt;code&gt;test('two plus two', () =&amp;gt; {
  const value = 2 + 2;
  expect(value).toBeGreaterThan(3);
  expect(value).toBeGreaterThanOrEqual(3.5);
  expect(value).toBeLessThan(5);
  expect(value).toBeLessThanOrEqual(4.5);
})
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;toBeGreaterThan&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;초과&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;toBeGreaterThanOrEqual&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이상&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;toBeLessThan&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;미만&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;toBeLessThanOrEqual&lt;/b&gt;&lt;/h4&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;Strings&lt;/b&gt;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;toMatch&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정규표현식으로 검사&lt;/p&gt;
&lt;pre class=&quot;lisp&quot;&gt;&lt;code&gt;test('there is no I in team', () =&amp;gt; {
  expect('team').not.toMatch(/I/);
});

test('but there is a &quot;stop&quot; in Christoph', () =&amp;gt; {
  expect('Christoph').toMatch(/stop/);
});
&lt;/code&gt;&lt;/pre&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;Arrays and iterables&lt;/b&gt;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;toContain&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;배열이나 반복 가능 항목에 해당 값을 포함하는지 체크&lt;/p&gt;
&lt;pre class=&quot;sml&quot;&gt;&lt;code&gt;const shoppingList = [
  'diapers',
  'kleenex',
  'trash bags',
  'paper towels',
  'milk',
];

test('the shopping list has milk on it', () =&amp;gt; {
  expect(shoppingList).toContain('milk');
  expect(new Set(shoppingList)).toContain('milk');
});
&lt;/code&gt;&lt;/pre&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;Exceptions&lt;/b&gt;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;toThrow&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특정 함수가 호출될 때 오류가 발생하는지 테스트&lt;/p&gt;</description>
      <category> JavaScript</category>
      <author>Cocoon_</author>
      <guid isPermaLink="true">https://cocoon1787.tistory.com/881</guid>
      <comments>https://cocoon1787.tistory.com/881#entry881comment</comments>
      <pubDate>Tue, 14 May 2024 12:17:52 +0900</pubDate>
    </item>
    <item>
      <title>Goodbye 2023, Hello 2024</title>
      <link>https://cocoon1787.tistory.com/880</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;vecteezy_happy-new-year-2024-text-design-for-brochure-design_20411321.jpg&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1280&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cm1hXS/btsCTUVktZg/eOwjfpuGzz6TkLzWuThkV0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cm1hXS/btsCTUVktZg/eOwjfpuGzz6TkLzWuThkV0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cm1hXS/btsCTUVktZg/eOwjfpuGzz6TkLzWuThkV0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcm1hXS%2FbtsCTUVktZg%2FeOwjfpuGzz6TkLzWuThkV0%2Fimg.jpg&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;1920&quot; height=&quot;1280&quot; data-filename=&quot;vecteezy_happy-new-year-2024-text-design-for-brochure-design_20411321.jpg&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1280&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;2023년도 회고록&lt;/b&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Work&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2023년 3월 20일에는 역삼역과 강남역 사이에 위치한 새로운 회사로 이직을 하게 되었다. 첫 회사였던 이전 회사는 딱 1년을 채우고 퇴사를 했었고 현재 회사에서 근무한 지는 10개월 정도 지났다. 지금 회사는 친구의 지인분이 근무 중이셔서 친구의 소개로 별생각 없이 FE 포지션 커피챗을 보러 갔었었는데, 커피챗 경험이 좋았었고 어쩌다 보니 사전과제, 실무핏, 컬처핏, CEO 면접에 모두 pass 하게 되었으며, 근무 조건도 이전보다 더 나은 조건이어서 일주일 정도 고민하다가 이전 회사에 퇴사하기 한 달 전 이직 의사를 밝혔었다. 시니어분들, 동료들 모두 좋은 사람들이었고, 최대한 좋은 모습으로 떠나고 싶어서 마지막 한 달간은 인수인계도 철저히 하면서 정말 열심히 했었던 것 같다.(3월 17일 마지막 근무일에도 지라에 등록된 이슈 20여 개를 수정 후 자리 정리한 뒤 모든 직원분들에게 인사드리고 퇴근을 했었다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 한 달간 쉰다거나 그런 것 없이 바로 다음 주에 새 회사로 출근을 하였다. 첫날에 출근하니 자리에 맥북과 모니터 2개가 있었는데 책상은 모션데스크에 의자는 시디즈 T80이어서 너무 좋았다. 그리고 필요 장비 구매 복지도 있어 회사에서 사용할 키보드를 주문했었고, 식사 또한 정기 배달 서비스를 이용 중이어서 식사 시간 때마다 밖에 나가 근처 식당 앞에 줄 서거나 하지 않아도 돼서 그런 부분들이 참 마음에 들었다. 사내 직원수는 30명 정도에 대부분 젊은 편이었고 회사 소속 카페도 있어 커피는 무료로 마시고 싶을 때 마실 수 있다. 그리고 출퇴근 시간이 따로 정해져 있지 않아 근무시간은 전적으로 자율에 맡기며, 재택 또한 가능해서 좋았다.(물론 회사 출근하는 게 좋아서 실제로 재택 한 날은 손에 꼽힌다...) 업무 자체는 FE가 적성에 맞아 재밌지만 블록체인 회사다 보니 Front를 구현하기 위해 해당 지식을 필요로 하는 부분이 존재해 어려움이 있었지만 주변의 좋은 동료들의 친절한 설명 덕분에 쉽게 이해할 수 있었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;11월 달 즈음에는 이전 회사에서 자금 사정으로 인해 거래소 서비스를 종료한다는 소식을 듣게 되었다. 첫 회사에서 처음으로 만든 프로젝트 였었는데 너무나도 아쉬운 소식이었고, 서비스를 만들기 위해서 갈아 넣었던 시간과 야근 및 주말 출근이 주마등처럼 스쳐 지나가면서 남은 건 개발 실력뿐이라는 생각이 들었다. 요즘 고금리 시대에 투자 위축으로 스타트업들이 죽어나가고 있고, 개발자 채용 한파로 인해 경기가 많이 힘든 상황인 것 같다. 그래도 내가 지금 회사를 다니고 있다는 사실에 항상 감사하고 있다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Skills&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이전 회사에서는 기술스택이 Next.js, React, Javascript, Emotion, Redux였고, 현재 회사는 Next.js, React, &lt;b&gt;Typescript&lt;/b&gt;, &lt;b&gt;TailwindCSS&lt;/b&gt;, Jotai이다. 입사 후 typescript와 tailwind에 익숙하지 않아 어려움이 많았었다. 특히 Styling의 경우 Styled component 방식을 선호해서 가독성이 좋지 않고 속성을 외워야 하는 tailwind 사용에 불편함이 많았지만 이제는 어느 정도 익숙해졌고, 현재는 &lt;a href=&quot;https://fe-developers.kakaoent.com/2022/221013-tailwind-and-design-system/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;카카오페이에서 사용하는 방식&lt;/a&gt;처럼 tw.macro를 통해서 emotion과 tailwind를 결합하여 사용 중이다. 2023년도 커리어적으로 가장 잘한 일은 아마 typescript와 tailwind를 배운 게 아닐까 싶다. 그리고 Sentry error logging을 통한 버그 수정, GA event tracking을 통한 유저 행동 분석 및 UX 증대, Jest test code 작성 및 git action 연동과 같은 경험들을 하게 되었다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Health&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;새로운 서비스 런칭으로 인해 높은 업무강도와 반복되는 야근으로 체력적으로 힘들다고 느꼈으며, 체력을 키워야겠다고 생각이 먼저 들어 무작정 회사 주변 헬스장을 등록했다. 5월부터 헬스장에서 주 3회(월, 수, 금) 운동을 시작하였고, 작심삼일이 되지 않기 위해서 초반부터 너무 무리하지 않고 재미를 붙여서 퇴근 후 운동가는 습관을 만들고자 했다. 덕분에 7개월째 주 3회 퇴근 후 운동을 하고 있고, 살이 빠지면서 근육이 늘어 몸이 좀 좋아진 것 같다. 처음에는 유산소 1시간에 근력 10분 정도만 했었는데, 살을 5kg 정도 빼고 나서 근력 30분에 유산소 30분으로 비중을 바꿔서 운동 중이다. 식단까지 하게 될 경우 못 버티고 폭식을 하게 될 것 같아서 따로 식단은 안 하고 새벽 야식을 안 먹기 위해서 배고픔 달램용으로 닭가슴살 단백질 핫바를 구매해서 먹고 있는데 꽤나 도움이 되는 것 같다. 그리고 운동을 시작하니 주말에 치킨, 피자를 먹어도 월요일에 오히려 살이 빠져있는 경우도 있어 신기했었다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Side Project&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;작년에 목표 삼았었던 4개의 사이드 프로젝트들 중에서 하나인 ToDo List App을 완성하였다. 사실 직장 다니면서 회사 업무가 1순위 이기 때문에 퇴근 후 피곤한 상태로 프로젝트 하나를 만드는 게 쉬운 일은 아닌 것 같다.&lt;/p&gt;
&lt;figure id=&quot;og_1703949708266&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[Project] Todo List App 개발&quot; data-og-description=&quot;Site URL https://check-todo.vercel.app/ Todo List App This is a Todo List App that allows users to add tasks to a list and mark completion with a checkbox. Users can manage their to-do tasks more systematically, and the intuitive and simple design makes it&quot; data-og-host=&quot;cocoon1787.tistory.com&quot; data-og-source-url=&quot;https://cocoon1787.tistory.com/879&quot; data-og-url=&quot;https://cocoon1787.tistory.com/879&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/czxZJj/hyUXWNZegZ/Jd5psYwLJvqG6iaQejCbck/img.png?width=800&amp;amp;height=528&amp;amp;face=0_0_800_528,https://scrap.kakaocdn.net/dn/bupkSU/hyUTDigLsV/nLqndNt5Km8eVfKAId6G0k/img.png?width=800&amp;amp;height=528&amp;amp;face=0_0_800_528,https://scrap.kakaocdn.net/dn/0gi5P/hyUXXsAASL/mXhTkBYff5RNMZim2hKyk0/img.png?width=3265&amp;amp;height=2158&amp;amp;face=0_0_3265_2158&quot;&gt;&lt;a href=&quot;https://cocoon1787.tistory.com/879&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://cocoon1787.tistory.com/879&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/czxZJj/hyUXWNZegZ/Jd5psYwLJvqG6iaQejCbck/img.png?width=800&amp;amp;height=528&amp;amp;face=0_0_800_528,https://scrap.kakaocdn.net/dn/bupkSU/hyUTDigLsV/nLqndNt5Km8eVfKAId6G0k/img.png?width=800&amp;amp;height=528&amp;amp;face=0_0_800_528,https://scrap.kakaocdn.net/dn/0gi5P/hyUXXsAASL/mXhTkBYff5RNMZim2hKyk0/img.png?width=3265&amp;amp;height=2158&amp;amp;face=0_0_3265_2158');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[Project] Todo List App 개발&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Site URL https://check-todo.vercel.app/ Todo List App This is a Todo List App that allows users to add tasks to a list and mark completion with a checkbox. Users can manage their to-do tasks more systematically, and the intuitive and simple design makes it&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;cocoon1787.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내가 원하는 디자인에 심플하면서 필요한 기능은 다 있는 그런 Todo List App을 만들고 싶었는데, 프로젝트를 완성하여 휴대폰에 설치하여 잘 사용 중이다. 시간 날 때 List drag and drop 기능도 추가할 예정이다.&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;2024년도 목표&lt;/b&gt;&lt;/h2&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Career&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;&lt;b&gt;받는 만큼&lt;span&gt;&amp;nbsp;&lt;/span&gt;일하는 게&lt;span&gt;&amp;nbsp;&lt;/span&gt;아닌&lt;span&gt;&amp;nbsp;&lt;/span&gt;받고 싶은&lt;span&gt;&amp;nbsp;&lt;/span&gt;만큼 일하자&lt;/b&gt;&lt;/i&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;라는 모토를 가지고 있다.&lt;br /&gt;2023년도 열심히 달려왔고 2024년에도 받는 것의 2배 이상으로 열심히 일하며 알차게 보낼 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Commit&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;940&quot; data-origin-height=&quot;237&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b0CUzs/btsCODAxRAi/hVyLOL8pSNskOATrb8wZnk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b0CUzs/btsCODAxRAi/hVyLOL8pSNskOATrb8wZnk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b0CUzs/btsCODAxRAi/hVyLOL8pSNskOATrb8wZnk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb0CUzs%2FbtsCODAxRAi%2FhVyLOL8pSNskOATrb8wZnk%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;940&quot; height=&quot;237&quot; data-origin-width=&quot;940&quot; data-origin-height=&quot;237&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2023년도에는 3700개 이상의 commit을 하였다. 2024년도에는 5000 commit에 도전해보려고 한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Study&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;웹 개발을 하면서 곧 3년 차가 다돼 가는데 아직도 자바스크립트에 모르는 부분이 많고 Chat GPT의 도움을 받을 때가 많은 것 같다. 3년 차가 되기 전에 Modern Javascript Deep Dive 책을 완독 할 것이다.&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Health&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2024년도에도 현재 주 3회 운동하는 것을 계속 유지할 계획이다. 운동이 생활에 긍정적인 영향을 준다는 것은 확실한 것 같다.&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Side Project&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;작년에 목표했었지만 시도하지 못했던 미니 거래소 앱을 만들어 볼 계획이다. Upbit API를 사용할지, Binance API를 사용할지 정하지는 못했지만, 아무래도 초당 socket message수가 많은 Binance API를 사용하여 렉 없이 Rendering 최적화가 된 앱을 만들어 보고 싶다.&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 data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;2023년도 다들 고생 많으셨고 새해 복 많이 받으세요..! &lt;/b&gt;&lt;/p&gt;</description>
      <category> 일상</category>
      <author>Cocoon_</author>
      <guid isPermaLink="true">https://cocoon1787.tistory.com/880</guid>
      <comments>https://cocoon1787.tistory.com/880#entry880comment</comments>
      <pubDate>Mon, 1 Jan 2024 00:00:10 +0900</pubDate>
    </item>
    <item>
      <title>[Project] Todo List App 개발</title>
      <link>https://cocoon1787.tistory.com/879</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;3265&quot; data-origin-height=&quot;2158&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bfkRjl/btssZcZY79l/pamKlqaHDPLu51rDFtr0Vk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bfkRjl/btssZcZY79l/pamKlqaHDPLu51rDFtr0Vk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bfkRjl/btssZcZY79l/pamKlqaHDPLu51rDFtr0Vk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbfkRjl%2FbtssZcZY79l%2FpamKlqaHDPLu51rDFtr0Vk%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;3265&quot; height=&quot;2158&quot; data-origin-width=&quot;3265&quot; data-origin-height=&quot;2158&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;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;Site URL&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://check-todo.vercel.app/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://check-todo.vercel.app/&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1693766817232&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Todo List App&quot; data-og-description=&quot;This is a Todo List App that allows users to add tasks to a list and mark completion with a checkbox. Users can manage their to-do tasks more systematically, and the intuitive and simple design makes it easy to use.&quot; data-og-host=&quot;check-todo.vercel.app&quot; data-og-source-url=&quot;https://check-todo.vercel.app/&quot; data-og-url=&quot;https://check-todo.vercel.app&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://check-todo.vercel.app/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://check-todo.vercel.app/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Todo List App&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;This is a Todo List App that allows users to add tasks to a list and mark completion with a checkbox. Users can manage their to-do tasks more systematically, and the intuitive and simple design makes it easy to use.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;check-todo.vercel.app&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;안녕하세요. Google Tasks나 Microsoft Todo 앱을 사용해 보면서 나만의 todo app을 만들어보면 어떨까 하는 생각을 계속 가지고 있었는데, 바쁘고 피곤해서 미루다가 드디어 Todo list app을 완성하게 되었습니다. 어떻게 보면 2023-09-04 오늘이 Todo list app 런칭일이자, v1.0.0이라고 할 수 있을 듯하네요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;LocalStorage만 사용하는 버전을 선 런칭 후에 로그인 연동 + 데이터 서버 연동 기능을 개발하여 배포를 하려고 했었는데, 다행히도 &lt;a href=&quot;https://www.npmjs.com/package/next-auth&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;next-auth&lt;/a&gt;라는 좋은 라이브러리가 있어 쉽게 로그인 기능을 연동할 수 있었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;웹서버 같은 경우에는 vercel로 호스팅을 하고 서버 데이터의 경우 firestore로 관리하여 서버 비용 zero로 운영하고 있습니다. 원래는 mongoDB의 shared cluster(무료)를 사용하여 데이터를 관리할까 고민하였었는데, 개인 프로젝트를 할 때 firestore도 많이 쓰인다는 얘기를 들어서 이번에 한번 써봤습니다. 아직은 데이터가 많지 않아 응답속도도 괜찮게 나오는 듯합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로젝트 기술 스택은 Next.js, React, Typescript이고 styling은 emotion을 사용하였습니다. 그리고 개인 프로젝트에는 한 번도 도입해보지 못했던 &lt;a href=&quot;https://sentry.io/welcome/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Sentry&lt;/a&gt;를 처음으로 넣어봤습니다. Sentry는 실시간 로그 취합 및 분석 도구이자 모니터링 플랫폼인데, 무료로도 사용이 가능하고 좀 더 정밀한 에러 분석을 위해서 플랜을 업그레이드할 수 있습니다. 런칭하기 전에 PC, Android, ios에서 기능 및 디자인 QA를 스스로 많이 했었는데, 아무래도 QA에서 발견하지 못한 에러들이 실사용자에게 발생할 가능성은 항상 있기 때문에 Sentry로 에러를 분석하고 Bug fix를 할 수 있다는 점에서 굉장히 좋은 툴이라고 생각됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;Service screenshot&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/by6BD6/btssTg2HiRw/KKzNY1dJrqbW9NTjk62QA1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/by6BD6/btssTg2HiRw/KKzNY1dJrqbW9NTjk62QA1/img.png&quot; data-origin-width=&quot;1170&quot; data-origin-height=&quot;2532&quot; data-is-animation=&quot;false&quot; style=&quot;width: 32.5581%; margin-right: 10px;&quot; data-widthpercent=&quot;33.33&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/by6BD6/btssTg2HiRw/KKzNY1dJrqbW9NTjk62QA1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fby6BD6%2FbtssTg2HiRw%2FKKzNY1dJrqbW9NTjk62QA1%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;1170&quot; height=&quot;2532&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/TD2g1/btssUaASVB7/P2r9Gqwow2vfogJ0peIsTK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/TD2g1/btssUaASVB7/P2r9Gqwow2vfogJ0peIsTK/img.png&quot; data-origin-width=&quot;1170&quot; data-origin-height=&quot;2532&quot; data-is-animation=&quot;false&quot; style=&quot;width: 32.5581%; margin-right: 10px;&quot; data-widthpercent=&quot;33.33&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/TD2g1/btssUaASVB7/P2r9Gqwow2vfogJ0peIsTK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FTD2g1%2FbtssUaASVB7%2FP2r9Gqwow2vfogJ0peIsTK%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;1170&quot; height=&quot;2532&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cFNOd9/btssSoGCLXp/yVHTJtV9Rz7GfEBjLCJQJk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cFNOd9/btssSoGCLXp/yVHTJtV9Rz7GfEBjLCJQJk/img.png&quot; data-origin-width=&quot;1170&quot; data-origin-height=&quot;2532&quot; data-is-animation=&quot;false&quot; style=&quot;width: 32.5581%;&quot; data-widthpercent=&quot;33.34&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cFNOd9/btssSoGCLXp/yVHTJtV9Rz7GfEBjLCJQJk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcFNOd9%2FbtssSoGCLXp%2FyVHTJtV9Rz7GfEBjLCJQJk%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;1170&quot; height=&quot;2532&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/csC7eV/btssS4HXKH1/bU2faMKwBTCBoken7qQ1qK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/csC7eV/btssS4HXKH1/bU2faMKwBTCBoken7qQ1qK/img.png&quot; data-origin-width=&quot;1170&quot; data-origin-height=&quot;2532&quot; data-is-animation=&quot;false&quot; style=&quot;width: 32.5581%; margin-right: 10px;&quot; data-widthpercent=&quot;33.33&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/csC7eV/btssS4HXKH1/bU2faMKwBTCBoken7qQ1qK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcsC7eV%2FbtssS4HXKH1%2FbU2faMKwBTCBoken7qQ1qK%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;1170&quot; height=&quot;2532&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bQrA83/btss3ZdXssR/KiMMut4gkaOmeQY09jwCnk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bQrA83/btss3ZdXssR/KiMMut4gkaOmeQY09jwCnk/img.png&quot; data-origin-width=&quot;1170&quot; data-origin-height=&quot;2532&quot; data-is-animation=&quot;false&quot; style=&quot;width: 32.5581%; margin-right: 10px;&quot; data-widthpercent=&quot;33.33&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bQrA83/btss3ZdXssR/KiMMut4gkaOmeQY09jwCnk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbQrA83%2Fbtss3ZdXssR%2FKiMMut4gkaOmeQY09jwCnk%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;1170&quot; height=&quot;2532&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bVaECp/btssN2RDvPV/KcTLLrj06my3gpl5FUjkRK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bVaECp/btssN2RDvPV/KcTLLrj06my3gpl5FUjkRK/img.png&quot; data-origin-width=&quot;1170&quot; data-origin-height=&quot;2532&quot; data-is-animation=&quot;false&quot; style=&quot;width: 32.5581%;&quot; data-widthpercent=&quot;33.34&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bVaECp/btssN2RDvPV/KcTLLrj06my3gpl5FUjkRK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbVaECp%2FbtssN2RDvPV%2FKcTLLrj06my3gpl5FUjkRK%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;1170&quot; height=&quot;2532&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;남은 여정&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;s&gt;LocalStorage를 사용한 데이터 관리 및 기능 구현&lt;/s&gt;&lt;/li&gt;
&lt;li&gt;&lt;s&gt;소셜 로그인 서비스 연동&lt;/s&gt;&lt;/li&gt;
&lt;li&gt;&lt;s&gt;Firestore 연동 및 서버 데이터 관리&lt;/s&gt;&lt;/li&gt;
&lt;li&gt;&lt;s&gt;Sentry 도입&lt;/s&gt;&lt;/li&gt;
&lt;li&gt;&lt;s&gt;v1.0.0 런칭&lt;/s&gt;&lt;/li&gt;
&lt;li&gt;Jest를 통한 테스트 코드 작성&lt;/li&gt;
&lt;li&gt;Storybook을 통한 컴포넌트 테스트&lt;/li&gt;
&lt;li&gt;&lt;s&gt;List edit 기능 추가&lt;/s&gt;&lt;/li&gt;
&lt;li&gt;List drag and drop 기능 추가&lt;/li&gt;
&lt;li&gt;다국어 지원&lt;/li&gt;
&lt;li&gt;...&lt;/li&gt;
&lt;/ul&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;&lt;a href=&quot;https://docs.google.com/forms/d/1eE3KBOtAmtNh5cLHlGyrZC7q5I_rvG0TxwaJ16UiuvI/edit&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Todo&amp;nbsp;List&amp;nbsp;App 문의하기&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;Github Link&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;a href=&quot;https://github.com/ma9pie/todo-list-app&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://github.com/ma9pie/todo-list-app&lt;/a&gt;&lt;/b&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1693852022595&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;GitHub - ma9pie/todo-list-app&quot; data-og-description=&quot;Contribute to ma9pie/todo-list-app development by creating an account on GitHub.&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/ma9pie/todo-list-app&quot; data-og-url=&quot;https://github.com/ma9pie/todo-list-app&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/Uwokj/hyTPx3UMBd/QucFK3GLtBY5AA9aGqdkCK/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/ma9pie/todo-list-app&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/ma9pie/todo-list-app&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/Uwokj/hyTPx3UMBd/QucFK3GLtBY5AA9aGqdkCK/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;GitHub - ma9pie/todo-list-app&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Contribute to ma9pie/todo-list-app development by creating an account on GitHub.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category> &amp;zwj; Project</category>
      <author>Cocoon_</author>
      <guid isPermaLink="true">https://cocoon1787.tistory.com/879</guid>
      <comments>https://cocoon1787.tistory.com/879#entry879comment</comments>
      <pubDate>Mon, 4 Sep 2023 04:23:21 +0900</pubDate>
    </item>
    <item>
      <title>[Next.js] Next.js에서 styled-components 사용 시 발생하는 &amp;quot;Warning: Prop `className` did not match.&amp;quot; 에러</title>
      <link>https://cocoon1787.tistory.com/878</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1081&quot; data-origin-height=&quot;721&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/AQSjS/btsiPPmiY96/3Q5K6MKVrz5Gf8tREp66RK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/AQSjS/btsiPPmiY96/3Q5K6MKVrz5Gf8tREp66RK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/AQSjS/btsiPPmiY96/3Q5K6MKVrz5Gf8tREp66RK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FAQSjS%2FbtsiPPmiY96%2F3Q5K6MKVrz5Gf8tREp66RK%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;1081&quot; height=&quot;721&quot; data-origin-width=&quot;1081&quot; data-origin-height=&quot;721&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;Warning: Prop `className` did not match. Server: &quot;sc-hmdomO rgEEX&quot; Client: &quot;sc-jlZhew bwbgGd&quot; at button at P (webpack-internal:///./node_modules/styled-components/dist/styled-components.browser.esm.js:31:19658) at Button (webpack-internal:///./components/Button.tsx:19:23) at div at P (webpack-internal:///./node_modules/styled-components/dist/styled-components.browser.esm.js:31:19658) at Page (webpack-internal:///./pages/recoil.tsx:30:78) at Provider (webpack-internal:///./node_modules/react-redux/es/components/Provider.js:13:3) at App (webpack-internal:///./pages/_app.tsx:27:24) at _PathnameContextProviderAdapter (webpack-internal:///./node_modules/next/dist/shared/lib/router/adapters.js:118:24) at ErrorBoundary (webpack-internal:///./node_modules/next/dist/compiled/@next/react-dev-overlay/dist/client.js:305:63) at ReactDevOverlay (webpack-internal:///./node_modules/next/dist/compiled/@next/react-dev-overlay/dist/client.js:854:919) at Container (webpack-internal:///./node_modules/next/dist/client/index.js:149:5) at AppContainer (webpack-internal:///./node_modules/next/dist/client/index.js:314:24) at Root (webpack-internal:///./node_modules/next/dist/client/index.js:533:25) See more info here: https://nextjs.org/docs/messages/react-hydration-error&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Next.js에서 Emotion을 사용할 때는 해당 에러를 마주한 적이 없었는데, styled-components 라이브러리를 사용하고 해당 에러를 만나게 되었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 에러의 경우 Next.js에서 styled-components를 사용할 경우 className이 달라서 생기는 에러입니다.&lt;br /&gt;npm run dev를 통해서 첫 화면 로딩 시에는 해당 에러가 발생하지 않지만, 개발을 하면서 코드가 변경될 시 해당 에러가 발생하는 것을 확인하였습니다. 원인은 첫 로딩 시 서버사이드 렌더링(SSR)으로 화면을 그리게 되고, 그 이후부터 클라이언트사이드 렌더링(CSR)으로 화면을 그리기 때문에 서버와 클라이언트의 클래스명이 동일하지 않기 때문에 발생하는 에러입니다.&amp;nbsp;&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;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(1) babel-plugin-styled-components 설치&lt;/p&gt;
&lt;pre id=&quot;code_1686065448295&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;npm i -D babel-plugin-styled-components&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;설치 후 루트 디렉토리의 .babelrc 파일에 설정을 해줍니다.(없을 시 .babelrc 파일 생성!)&lt;/p&gt;
&lt;pre id=&quot;code_1686065482972&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;{
  &quot;presets&quot;: [&quot;next/babel&quot;],
  &quot;plugins&quot;: [&quot;babel-plugin-styled-components&quot;]
}&lt;/code&gt;&lt;/pre&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) Next.js 12 버전부터는 (1) 번 방식으로 해결되지 않을 수 도 있습니다. 12 버전부터는 babel 대신 swc를 사용하여 컴파일하도록 업데이트되었기 때문에 아래와 같이 next.config.js 파일에서 styledComponents 관련 설정을 하여 해결해 줍니다.&lt;/p&gt;
&lt;pre id=&quot;code_1686065611778&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/** @type {import('next').NextConfig} */
const nextConfig = {
  reactStrictMode: false,
  compiler: {
    styledComponents: true,
  },
};

module.exports = nextConfig;&lt;/code&gt;&lt;/pre&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;</description>
      <category> ERROR</category>
      <author>Cocoon_</author>
      <guid isPermaLink="true">https://cocoon1787.tistory.com/878</guid>
      <comments>https://cocoon1787.tistory.com/878#entry878comment</comments>
      <pubDate>Wed, 7 Jun 2023 00:35:38 +0900</pubDate>
    </item>
    <item>
      <title>[Web3] ethers.js BigNumber 사용법</title>
      <link>https://cocoon1787.tistory.com/876</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1127&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b3YlO0/btsibcJlH9g/39inRG3NEQ6Pju73nTA5iK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b3YlO0/btsibcJlH9g/39inRG3NEQ6Pju73nTA5iK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b3YlO0/btsibcJlH9g/39inRG3NEQ6Pju73nTA5iK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb3YlO0%2FbtsibcJlH9g%2F39inRG3NEQ6Pju73nTA5iK%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;2000&quot; height=&quot;1127&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1127&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;
&lt;h1&gt;  &lt;b&gt;BigNumber&lt;/b&gt;&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;BigNumber은 일반 JavaScript 숫자로 표현하기에는 너무 큰 큰 숫자로 작업할 수 있는 방법을 제공하는 ethers.js 라이브러리의 모듈입니다. BigNumber은 최대 256비트의 정밀도로 임의로 큰 정수를 나타내는 불변 개체입니다. 자바스크립트의 기본 자료형의 연산은 정확하지 않은 경우가 많기 때문에 높은 수준의 정밀도가 필요한 Ether와 같은 암호화폐를 다룰 때는 BigNumber을 통해 정확한 연산이 가능하게 됩니다.&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 data-token-index=&quot;0&quot;&gt;&lt;span&gt; &lt;/span&gt; 사용 방법&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;pre id=&quot;code_1685565988778&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const { BigNumber } = require('ethers');

const bigNumber = BigNumber.from('12345678901234567890');
console.log(bigNumber.toString()); // '12345678901234567890&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;BigNumber.from(BigNumberish) &amp;rarr; BigNumber&lt;br /&gt;&lt;/b&gt;BigNumber.from은 BigNumberish에 대한 BigNumber 인스턴스를 반환하는 메서드입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;BigNumberish&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ethers.js에는 BigNumberish라는 타입이 있으며 아래와 같이 지정될 수 있습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;string : hexString 또는 10진수 문자열&lt;/li&gt;
&lt;li&gt;ByteLike : 배열 또는 Uint8Array와 같은 BytesLike 객체&lt;/li&gt;
&lt;li&gt;BigNumber : BigNumber 인스턴스&lt;/li&gt;
&lt;li&gt;number : safe range에 있는 자바스크립트 숫자 (Number.MAX_SAFE_INTEGER === 9007199254740991 === 2^53-1)&lt;/li&gt;
&lt;li&gt;BigInt : 자바스크립트의 BigInt 객체&lt;/li&gt;
&lt;/ul&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;pre id=&quot;code_1685566008396&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;console.log(BigNumber.from('42').toString());
// Output: 42
console.log(BigNumber.from('0x2a').toString());
// Output: 42
console.log(BigNumber.from('-0x2a').toString());
// Output: -42
console.log(BigNumber.from([42]).toString());
// Output: 42
console.log(BigNumber.from(42).toString());
// Output: 42
console.log(BigNumber.from(BigInt(42)).toString());
// Output: 42
console.log(BigNumber.from(Number.MAX_SAFE_INTEGER - 1).toString());
// Output: 9007199254740990&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;BigNumber 사칙연산 예제&lt;/p&gt;
&lt;pre id=&quot;code_1685566016710&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 10^18 ==&amp;gt; &quot;1000000000000000000&quot;
const bigNumber = BigNumber.from('1000000000000000000');

console.log(bigNumber.add(100).toString());
// Output: &quot;1000000000000000100&quot;
console.log(bigNumber.sub(50).toString());
// Output: &quot;999999999999999950&quot;
console.log(bigNumber.mul(2).toString());
// Output: &quot;2000000000000000000&quot;
console.log(bigNumber.div(3).toString());
// Output: &quot;333333333333333333&quot;
console.log(bigNumber.mul(2).div(2).add(2).sub(2).toString());
// Output: &quot;1000000000000000000&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비교 메서드&lt;/p&gt;
&lt;pre id=&quot;code_1685566028884&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;BigNumber.eq( otherValue ) &amp;rArr; boolean
Returns true if and only if the value of BigNumber is equal to otherValue.

BigNumber.lt( otherValue ) &amp;rArr; boolean
Returns true if and only if the value of BigNumber &amp;lt; otherValue.

BigNumber.lte( otherValue ) &amp;rArr; boolean
Returns true if and only if the value of BigNumber &amp;le; otherValue.

BigNumber.gt( otherValue ) &amp;rArr; boolean
Returns true if and only if the value of BigNumber &amp;gt; otherValue.

BigNumber.gte( otherValue ) &amp;rArr; boolean
Returns true if and only if the value of BigNumber &amp;ge; otherValue.

BigNumber.isZero( ) &amp;rArr; boolean
Returns true if and only if the value of BigNumber is zero.&lt;/code&gt;&lt;/pre&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 data-token-index=&quot;0&quot;&gt;&lt;span&gt; &lt;/span&gt; 가장 흔한 NUMERIC_FAULT&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;1. overflow&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자바스크립트의 숫자는 IEEE754로 규정된 64비트 부동소수점 숫자를 사용하여 값을 나타내는데 결과적으로 9,007,199,254,740,991 이상의 값부터는 오차가 있으며, 안전 범위를 벗어난 숫자를 사용하는 것을 방지하기 위해 overflow 오류를 발생시킵니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;801&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/VRzER/btsiaAYhCgC/0A9hqkwmjNlGQWYwJcD4yK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/VRzER/btsiaAYhCgC/0A9hqkwmjNlGQWYwJcD4yK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/VRzER/btsiaAYhCgC/0A9hqkwmjNlGQWYwJcD4yK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FVRzER%2FbtsiaAYhCgC%2F0A9hqkwmjNlGQWYwJcD4yK%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;2000&quot; height=&quot;801&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;801&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;2. underflow&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;underflow오류는 값의 정밀도를 현재 데이터 유형으로 안전하게 표현할 수 없을 때 발생하는 오류입니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;BigNumber은 소수점이 있는 숫자를 생성할 수 없습니다.&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;2000&quot; data-origin-height=&quot;819&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/br7Zwj/btsicNWztrx/Gqq7uVrkreuNfva4f2zF4K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/br7Zwj/btsicNWztrx/Gqq7uVrkreuNfva4f2zF4K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/br7Zwj/btsicNWztrx/Gqq7uVrkreuNfva4f2zF4K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbr7Zwj%2FbtsicNWztrx%2FGqq7uVrkreuNfva4f2zF4K%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;2000&quot; height=&quot;819&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;819&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;utils.parseUnits(value, decimal)에서 decimal보다 긴 소수점 자릿수를 가진 value를 생성할 수 없습니다.&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;2000&quot; data-origin-height=&quot;806&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/5vrdt/btsidVGCS8W/9cGY0SSl7cpVKqYGGq8kq1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/5vrdt/btsidVGCS8W/9cGY0SSl7cpVKqYGGq8kq1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/5vrdt/btsidVGCS8W/9cGY0SSl7cpVKqYGGq8kq1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F5vrdt%2FbtsidVGCS8W%2F9cGY0SSl7cpVKqYGGq8kq1%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;2000&quot; height=&quot;806&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;806&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;3. Division by zero&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;0으로 나누려고 할 때 에러가 발생합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;810&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/9cjnw/btsib0u765f/fTVwa9Z0i3jOjnqvBci6ak/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/9cjnw/btsib0u765f/fTVwa9Z0i3jOjnqvBci6ak/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/9cjnw/btsib0u765f/fTVwa9Z0i3jOjnqvBci6ak/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F9cjnw%2Fbtsib0u765f%2FfTVwa9Z0i3jOjnqvBci6ak%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;2000&quot; height=&quot;810&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;810&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;
&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 data-token-index=&quot;0&quot;&gt;&lt;span&gt; &lt;/span&gt; 추가로 알아두면 좋은 정보&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;단위&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1685566147055&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;1이더 = 1000000000000000000 Wei (0이 18개)
1이더 = 1000000000000000 Kwei (0이 15개)
1이더 = 1000000000000 Mwei (0이 12개)
1이더 = 1000000000 Gwei (0이 9개)
1이더 = 1000000 Szabo
1이더 = 1000 Finney
1이더 = 0.001 Kether
1이더 = 0.000001 Mether
1이더 = 0.000000001 Gether
1이더 = 0.000000000001 Tether&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;ethers.utils 라이브러리 내에 구현되어 있는 메서드 캡처&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1418&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/tQNN2/btsibbReJ28/vJUcKJ8k72PSq1CPxyfn9K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/tQNN2/btsibbReJ28/vJUcKJ8k72PSq1CPxyfn9K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/tQNN2/btsibbReJ28/vJUcKJ8k72PSq1CPxyfn9K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FtQNN2%2FbtsibbReJ28%2FvJUcKJ8k72PSq1CPxyfn9K%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;2000&quot; height=&quot;1418&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1418&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1.parseUnits(value: string, decimals) &amp;rarr; BigNumber&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;parseUnits 함수는 &lt;b&gt;value 문자열&lt;/b&gt;과 숫자를 인수로 사용하고 소수 자릿수를 기준으로 토큰의 최소 단위로 입력 값을 나타내는 BigNumber 객체를 반환합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1685566179659&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;console.log(utils.parseUnits('1.5', 18).toString());
// Output: &quot;1500000000000000000&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;parseUnits('1.5', 18)은 1500000000000000000(Wei의 1.5 ETH)인 BigNumber 객체를 반환합니다.&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;b&gt;2. parseEther(value: string) &amp;rarr; BigNumber&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;parseUnits(value, 18)의 줄임말입니다. &lt;b&gt;value 문자열&lt;/b&gt;을 받고 Ether의 최소 단위인 Wei로 나타내는 BigNumber 객체를 반환합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1685566199750&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;console.log(utils.parseEther('1.5').toString());
// Output: &quot;1500000000000000000&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. &lt;b&gt;formatUnits(value: BigNumberish, decimals) &amp;rarr; string&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;formatUnits 함수는 &lt;b&gt;BigNumberish인 value&lt;/b&gt;와 decimals 숫자를 인수로 사용하고 소수 자릿수를 기준으로 토큰의 최대 단위로 입력 값의 문자열 표현을 반환합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1685566216096&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;console.log(utils.formatUnits('1500000000000000000', 18));
// Output: &quot;1.5&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;formatUnits(&quot;1500000000000000000&quot;, 18)은 값이 &quot;1.5&quot;(1.5 ETH)인 문자열을 반환합니다.&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;b&gt;4. formatEther(value: BigNumberish) &amp;rarr; string&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;formatEther 함수는 formatUnits(value, 18)의 줄임말입니다. &lt;b&gt;BigNumberish인 value&lt;/b&gt;를 인수로 받아 ETH값을 문자열로 표현해 반환합니다&lt;/p&gt;
&lt;pre id=&quot;code_1685566233475&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;console.log(utils.formatUnits(BigNumber.from('1500000000000000000')));
// Output: &quot;1.5&quot;&lt;/code&gt;&lt;/pre&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 data-token-index=&quot;0&quot;&gt;&lt;span&gt; &lt;/span&gt; &lt;/span&gt;참고 문헌&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://docs.ethers.org/v5/api/utils/bignumber/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://docs.ethers.org/v5/api/utils/bignumber/&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1685566260679&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;BigNumber&quot; data-og-description=&quot;Documentation for ethers, a complete, tiny and simple Ethereum library.&quot; data-og-host=&quot;docs.ethers.org&quot; data-og-source-url=&quot;https://docs.ethers.org/v5/api/utils/bignumber/&quot; data-og-url=&quot;https://docs.ethers.org/v5/api/utils/bignumber/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/fsQ2D/hySPqkMKMv/DRGeY9YhfjlRIUOoIFzTKK/img.jpg?width=1280&amp;amp;height=640&amp;amp;face=0_0_1280_640&quot;&gt;&lt;a href=&quot;https://docs.ethers.org/v5/api/utils/bignumber/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://docs.ethers.org/v5/api/utils/bignumber/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/fsQ2D/hySPqkMKMv/DRGeY9YhfjlRIUOoIFzTKK/img.jpg?width=1280&amp;amp;height=640&amp;amp;face=0_0_1280_640');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;BigNumber&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Documentation for ethers, a complete, tiny and simple Ethereum library.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;docs.ethers.org&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://docs.ethers.org/v5/troubleshooting/errors/#help-NUMERIC_FAULT-overflow&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://docs.ethers.org/v5/troubleshooting/errors/#help-NUMERIC_FAULT-overflow&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1685566262630&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Error Codes&quot; data-og-description=&quot;Documentation for ethers, a complete, tiny and simple Ethereum library.&quot; data-og-host=&quot;docs.ethers.org&quot; data-og-source-url=&quot;https://docs.ethers.org/v5/troubleshooting/errors/#help-NUMERIC_FAULT-overflow&quot; data-og-url=&quot;https://docs.ethers.org/v5/troubleshooting/errors/#help-NUMERIC_FAULT-overflow&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bJ36C1/hySPrcUYcu/qH2s7iUG7M2LMP3QVPYJvk/img.jpg?width=1280&amp;amp;height=640&amp;amp;face=0_0_1280_640&quot;&gt;&lt;a href=&quot;https://docs.ethers.org/v5/troubleshooting/errors/#help-NUMERIC_FAULT-overflow&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://docs.ethers.org/v5/troubleshooting/errors/#help-NUMERIC_FAULT-overflow&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bJ36C1/hySPrcUYcu/qH2s7iUG7M2LMP3QVPYJvk/img.jpg?width=1280&amp;amp;height=640&amp;amp;face=0_0_1280_640');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Error Codes&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Documentation for ethers, a complete, tiny and simple Ethereum library.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;docs.ethers.org&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://docs.ethers.org/v5/api/utils/display-logic/#utils-parseUnits&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://docs.ethers.org/v5/api/utils/display-logic/#utils-parseUnits&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1685566268808&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Display Logic and Input&quot; data-og-description=&quot;Documentation for ethers, a complete, tiny and simple Ethereum library.&quot; data-og-host=&quot;docs.ethers.org&quot; data-og-source-url=&quot;https://docs.ethers.org/v5/api/utils/display-logic/#utils-parseUnits&quot; data-og-url=&quot;https://docs.ethers.org/v5/api/utils/display-logic/#utils-parseUnits&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/b5c6z1/hySPpsDO3Y/m7gD2gAGCkIdApTcZaBlXk/img.jpg?width=1280&amp;amp;height=640&amp;amp;face=0_0_1280_640&quot;&gt;&lt;a href=&quot;https://docs.ethers.org/v5/api/utils/display-logic/#utils-parseUnits&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://docs.ethers.org/v5/api/utils/display-logic/#utils-parseUnits&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/b5c6z1/hySPpsDO3Y/m7gD2gAGCkIdApTcZaBlXk/img.jpg?width=1280&amp;amp;height=640&amp;amp;face=0_0_1280_640');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Display Logic and Input&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Documentation for ethers, a complete, tiny and simple Ethereum library.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;docs.ethers.org&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/MAX_SAFE_INTEGER#description&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/MAX_SAFE_INTEGER#description&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1685566277718&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Number.MAX_SAFE_INTEGER - JavaScript | MDN&quot; data-og-description=&quot;The Number.MAX_SAFE_INTEGER static data property represents the maximum safe integer in JavaScript (253 &amp;ndash; 1).&quot; data-og-host=&quot;developer.mozilla.org&quot; data-og-source-url=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/MAX_SAFE_INTEGER#description&quot; data-og-url=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/MAX_SAFE_INTEGER&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/trf0F/hySQIjOLH9/Zq5cfUJxn2cKKK4FpIRAN0/img.png?width=1920&amp;amp;height=1080&amp;amp;face=0_0_1920_1080&quot;&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/MAX_SAFE_INTEGER#description&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/MAX_SAFE_INTEGER#description&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/trf0F/hySQIjOLH9/Zq5cfUJxn2cKKK4FpIRAN0/img.png?width=1920&amp;amp;height=1080&amp;amp;face=0_0_1920_1080');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Number.MAX_SAFE_INTEGER - JavaScript | MDN&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;The Number.MAX_SAFE_INTEGER static data property represents the maximum safe integer in JavaScript (253 &amp;ndash; 1).&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;developer.mozilla.org&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&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 data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category> WEB</category>
      <author>Cocoon_</author>
      <guid isPermaLink="true">https://cocoon1787.tistory.com/876</guid>
      <comments>https://cocoon1787.tistory.com/876#entry876comment</comments>
      <pubDate>Fri, 2 Jun 2023 12:00:45 +0900</pubDate>
    </item>
    <item>
      <title>[React] 모달 깊게 파헤치기 : 효율적인 모달 관리에 대하여 (useModal custom hooks)</title>
      <link>https://cocoon1787.tistory.com/875</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;450&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cwwok3/btshE0CUKoO/W6Ruxqy0mHHknPo63x2WPk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cwwok3/btshE0CUKoO/W6Ruxqy0mHHknPo63x2WPk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cwwok3/btshE0CUKoO/W6Ruxqy0mHHknPo63x2WPk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcwwok3%2FbtshE0CUKoO%2FW6Ruxqy0mHHknPo63x2WPk%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;800&quot; height=&quot;450&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;450&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;안녕하세요.&lt;br /&gt;이번 포스팅은 제가 1년간 모달 관련해서 깊게 고민하고 생각했던 부분에 대한 내용입니다.&lt;br /&gt;개인 프로젝트에서는 모달 관련해서 구글링을 하여 나오는 내용으로 쉽게 관리가 가능했지만,&lt;br /&gt;실무를 하다 보니 프로젝트 크기가 커지고,&amp;nbsp; 모달 위에 또 다른 모달이 띄워져야 하는 상황들이 많아 관리 포인트가 많아지는 문제가 발생했었습니다. 관리 포인트가 많아지면 오류가 발생했을 때의 이슈 대응이나 유지보수가 힘들어질 수 도 있겠다고 생각하였고, 이를 해결하기 위해 제가 연구하고 테스트했었던 가장 쉬운 방법부터 제가 현재 사용하고 있는 방법까지 공유를 해드리려 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a style=&quot;color: #0070d1; text-align: start;&quot; href=&quot;https://www.npmjs.com/package/react-modal&quot;&gt;react-modal&lt;/a&gt;과 같은 npm 라이브러리를 사용해서 모달을 구현할 수도 있지만, 프로젝트 내부의 라이브러리 의존성을 최소화해야겠다는 생각이 들어 간단하게 직접 구현을 하였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt; ️ 점진적으로 코드를 개선하려 했던 이유&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;페이지마다 모달을 &lt;b&gt;조건부 렌더링&lt;/b&gt;으로 관리해야 함&lt;/li&gt;
&lt;li&gt;하나의 컴포넌트에 모달이 여러 개면, &lt;b&gt;관리해야 하는 state도 여러 개&lt;/b&gt;인 부분&lt;/li&gt;
&lt;li&gt;&lt;b&gt;컴포넌트 내부가 아닌 외부&lt;/b&gt;(일반 자바스크립트 util 파일 등등)에서 모달을 열어야 하는 경우가 생김&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;  &lt;b&gt;Index&lt;/b&gt;&lt;/h2&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;useState로 구현하기&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;createPortal 적용&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;useModal로 리팩토링&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;createRoot 방식&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;with redux&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;with recoil&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;with context&lt;/b&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; 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;&lt;b&gt;포스팅 내 코드 참고 Repository&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;a href=&quot;https://github.com/ma9pie/modal&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://github.com/ma9pie/modal&lt;/a&gt;&lt;/b&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1686059713258&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;GitHub - ma9pie/modal&quot; data-og-description=&quot;Contribute to ma9pie/modal development by creating an account on GitHub.&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/ma9pie/modal&quot; data-og-url=&quot;https://github.com/ma9pie/modal&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bFPDhi/hySTWXQp7c/BjbNjeTKQ1NjKH1diNBInk/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/ma9pie/modal&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/ma9pie/modal&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bFPDhi/hySTWXQp7c/BjbNjeTKQ1NjKH1diNBInk/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;GitHub - ma9pie/modal&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Contribute to ma9pie/modal development by creating an account on GitHub.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&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;b&gt;package.json&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1685390220952&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;{
  &quot;name&quot;: &quot;modal&quot;,
  &quot;version&quot;: &quot;0.1.0&quot;,
  &quot;private&quot;: true,
  &quot;scripts&quot;: {
    &quot;dev&quot;: &quot;next dev&quot;,
    &quot;build&quot;: &quot;next build&quot;,
    &quot;start&quot;: &quot;next start&quot;,
    &quot;lint&quot;: &quot;next lint&quot;
  },
  &quot;dependencies&quot;: {
    &quot;@next/font&quot;: &quot;13.4.4&quot;,
    &quot;@reduxjs/toolkit&quot;: &quot;^1.9.5&quot;,
    &quot;@types/node&quot;: &quot;20.2.5&quot;,
    &quot;@types/react&quot;: &quot;18.2.7&quot;,
    &quot;@types/react-dom&quot;: &quot;18.2.4&quot;,
    &quot;axios&quot;: &quot;^1.4.0&quot;,
    &quot;eslint&quot;: &quot;8.41.0&quot;,
    &quot;eslint-config-next&quot;: &quot;13.4.4&quot;,
    &quot;next&quot;: &quot;13.4.4&quot;,
    &quot;react&quot;: &quot;18.2.0&quot;,
    &quot;react-dom&quot;: &quot;18.2.0&quot;,
    &quot;react-redux&quot;: &quot;^8.0.5&quot;,
    &quot;recoil&quot;: &quot;^0.7.7&quot;,
    &quot;sass&quot;: &quot;^1.62.1&quot;,
    &quot;styled-components&quot;: &quot;^5.3.11&quot;,
    &quot;typescript&quot;: &quot;5.0.4&quot;
  },
  &quot;devDependencies&quot;: {
    &quot;@types/styled-components&quot;: &quot;^5.1.26&quot;,
    &quot;babel-plugin-styled-components&quot;: &quot;^2.1.3&quot;
  }
}&lt;/code&gt;&lt;/pre&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;b&gt;Confirm 컴포넌트&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1685489404098&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/* @/components/Confirm.tsx */

import React from &quot;react&quot;;
import styled from &quot;styled-components&quot;;

type Props = {
  title?: string;
  message?: string;
  close?: () =&amp;gt; void;
  confirm?: () =&amp;gt; void;
};

const Confirm = ({ title, message, close, confirm }: Props) =&amp;gt; {
  return (
    &amp;lt;Wrapper&amp;gt;
      &amp;lt;Overlay onClick={close}&amp;gt;&amp;lt;/Overlay&amp;gt;
      &amp;lt;Content&amp;gt;
        &amp;lt;Top&amp;gt;
          &amp;lt;Title&amp;gt;{title}&amp;lt;/Title&amp;gt;
          &amp;lt;CloseBtn onClick={close}&amp;gt;&amp;amp;#x2716;&amp;lt;/CloseBtn&amp;gt;
        &amp;lt;/Top&amp;gt;
        &amp;lt;Message&amp;gt;{message}&amp;lt;/Message&amp;gt;
        &amp;lt;BtnContainer&amp;gt;
          &amp;lt;CancelBtn onClick={close}&amp;gt;cancel&amp;lt;/CancelBtn&amp;gt;
          &amp;lt;ConfirmBtn
            onClick={() =&amp;gt; {
              confirm &amp;amp;&amp;amp; confirm();
              close &amp;amp;&amp;amp; close();
            }}
          &amp;gt;
            confirm
          &amp;lt;/ConfirmBtn&amp;gt;
        &amp;lt;/BtnContainer&amp;gt;
      &amp;lt;/Content&amp;gt;
    &amp;lt;/Wrapper&amp;gt;
  );
};

export default Confirm;

const Wrapper = styled.div``;
const Overlay = styled.div`
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 999;
  background-color: rgba(0, 0, 0, 0.4);
`;
const Content = styled.div`
  position: fixed;
  display: grid;
  gap: 16px;
  top: 50%;
  left: 50%;
  padding: 16px;
  min-width: 200px;
  max-width: 400px;
  border-radius: 12px;
  overflow: hidden;
  background-color: white;
  transform: translate(-50%, -50%);
  z-index: 999;
`;
const Top = styled.div`
  display: flex;
  justify-content: space-between;
`;
const Title = styled.h3``;
const CloseBtn = styled.div`
  width: 24px;
  height: 24px;
  line-height: 24px;
  font-size: 20px;
  text-align: center;
  cursor: pointer;
`;
const Message = styled.p``;
const BtnContainer = styled.div`
  display: flex;
  gap: 8px;
`;
const CancelBtn = styled.div`
  flex: 1;
  height: 24px;
  text-align: center;
  border: 1px solid lightgrey;
  border-radius: 4px;
  cursor: pointer;
`;
const ConfirmBtn = styled.div`
  flex: 1;
  height: 24px;
  text-align: center;
  color: white;
  background-color: royalblue;
  border-radius: 4px;
  cursor: pointer;
`;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;475&quot; data-origin-height=&quot;307&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Hx5WO/btsh1UpgalU/EmXSmfQxdl8LatapHtHZ51/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Hx5WO/btsh1UpgalU/EmXSmfQxdl8LatapHtHZ51/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Hx5WO/btsh1UpgalU/EmXSmfQxdl8LatapHtHZ51/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FHx5WO%2Fbtsh1UpgalU%2FEmXSmfQxdl8LatapHtHZ51%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;475&quot; height=&quot;307&quot; data-origin-width=&quot;475&quot; data-origin-height=&quot;307&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모달은 Alert, Confirm, BottmSheet, Toast, ModalForm, ModalDialog 등등 여러 가지가 있지만, 그중에서도 가장 일반적인 Confirm 형식으로 모달을 디자인해 봤습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;props로는 title, message, confirm 함수를 내려줄 수 있고, 필요에 따라 message대신 children을 받아서 컴포넌트를 모달 props로 전달하도록 구성할 수 도 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 닫기버튼, cancel버튼, overlay부분을 클릭 시 모달이 닫히도록 props로 받은 close 함수를&amp;nbsp; onClick이벤트로 등록을 해주었습니다.&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;1. useState&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 기본적인 방법입니다. &lt;b&gt;DOM 내부에 Modal을 삽입하고 useState값으로 조건부 렌더링하는 방식&lt;/b&gt;입니다.&lt;/p&gt;
&lt;pre id=&quot;code_1685490225870&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import React, { useState } from &quot;react&quot;;
import Confirm from &quot;@/components/Confirm&quot;;
import Button from &quot;@/components/Button&quot;;
import styled from &quot;styled-components&quot;;

const UseState = () =&amp;gt; {
  const [isOpen, setIsOpen] = useState&amp;lt;boolean&amp;gt;(false);
  const open = () =&amp;gt; {
    setIsOpen(true);
  };
  const close = () =&amp;gt; {
    setIsOpen(false);
  };
  const confirm = () =&amp;gt; {
    console.log(&quot;confirm clicked&quot;);
    setIsOpen(false);
  };
  return (
    &amp;lt;Wrapper&amp;gt;
      &amp;lt;Button onClick={open}&amp;gt;Open Confirm&amp;lt;/Button&amp;gt;
      {isOpen &amp;amp;&amp;amp; (
        &amp;lt;Confirm
          title=&quot;알림&quot;
          message=&quot;상품을 주문하시겠습니까?&quot;
          close={close}
          confirm={confirm}
        &amp;gt;&amp;lt;/Confirm&amp;gt;
      )}
    &amp;lt;/Wrapper&amp;gt;
  );
};

export default UseState;

const Wrapper = styled.div`
  width: 100vw;
  height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
`;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;버튼을 클릭하면 isOpen의 상태값이 true로 바뀌게 되고 모달이 렌더링 됩니다. confirm을 클릭 시 실행시킬 함수도 정의가 가능합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bm4zGm/btsh2trabgJ/KZmKjW2VOknkhElp88iReK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bm4zGm/btsh2trabgJ/KZmKjW2VOknkhElp88iReK/img.png&quot; data-origin-width=&quot;427&quot; data-origin-height=&quot;268&quot; data-is-animation=&quot;false&quot; style=&quot;width: 48.7483%; margin-right: 10px;&quot; data-widthpercent=&quot;49.32&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bm4zGm/btsh2trabgJ/KZmKjW2VOknkhElp88iReK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbm4zGm%2Fbtsh2trabgJ%2FKZmKjW2VOknkhElp88iReK%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;427&quot; height=&quot;268&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bGMvMy/btsh03T2iPE/UOQgPwkc1rdjHVzcM63lA0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bGMvMy/btsh03T2iPE/UOQgPwkc1rdjHVzcM63lA0/img.png&quot; data-origin-width=&quot;406&quot; data-origin-height=&quot;248&quot; data-is-animation=&quot;false&quot; data-widthpercent=&quot;50.68&quot; style=&quot;width: 50.0889%;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bGMvMy/btsh03T2iPE/UOQgPwkc1rdjHVzcM63lA0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbGMvMy%2Fbtsh03T2iPE%2FUOQgPwkc1rdjHVzcM63lA0%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;406&quot; height=&quot;248&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;2. createPortal 적용&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1번 방법의 경우 해당 페이지 또는 컴포넌트 내부에서 modal이 렌더링 되므로, &lt;b&gt;modal사용 시 다른 컴포넌트와 겹치거나 z-index를 지정하여 관리를 해야 한다는 문제점&lt;/b&gt;이 있습니다. 이러한 문제를 해결하기 위해 &lt;b&gt;createPortal&lt;/b&gt;을 사용합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1029&quot; data-origin-height=&quot;590&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/n1NvJ/btsh6aDPaFh/8d0f3HdrtH3NI0aI5IagB1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/n1NvJ/btsh6aDPaFh/8d0f3HdrtH3NI0aI5IagB1/img.png&quot; data-alt=&quot;모달이 페이지 내부에 렌더링 되어있는 상태&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/n1NvJ/btsh6aDPaFh/8d0f3HdrtH3NI0aI5IagB1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fn1NvJ%2Fbtsh6aDPaFh%2F8d0f3HdrtH3NI0aI5IagB1%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;1029&quot; height=&quot;590&quot; data-origin-width=&quot;1029&quot; data-origin-height=&quot;590&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;(1) 먼저 next.js를 사용하신다면 _document.tsx, react만 사용하신다면 public 폴더의 index.html에 &lt;b&gt;&amp;lt;div id='modal'&amp;gt;&amp;lt;/div&amp;gt;&lt;/b&gt;을 삽입해 줍니다.&lt;/p&gt;
&lt;pre id=&quot;code_1685491467830&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/* @/pages/_document.tsx */

import { Html, Head, Main, NextScript } from &quot;next/document&quot;;

export default function Document() {
  return (
    &amp;lt;Html lang=&quot;ko&quot;&amp;gt;
      &amp;lt;Head /&amp;gt;
      &amp;lt;body&amp;gt;
        &amp;lt;div id=&quot;modal&quot;&amp;gt;&amp;lt;/div&amp;gt;
        &amp;lt;Main /&amp;gt;
        &amp;lt;NextScript /&amp;gt;
      &amp;lt;/body&amp;gt;
    &amp;lt;/Html&amp;gt;
  );
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(2) 그리고 Portal 컴포넌트를 생성해 줍니다.&lt;/p&gt;
&lt;pre id=&quot;code_1685491983201&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/* @/components/Portal.tsx */

import { ReactNode } from &quot;react&quot;;
import { createPortal } from &quot;react-dom&quot;;

type Props = {
  children: ReactNode;
};

const Portal = ({ children }: Props) =&amp;gt; {
  const node = document.getElementById(&quot;modal&quot;) as HTMLElement;

  return createPortal(children, node);
};

export default Portal;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ReactDOM에서 제공하는 &lt;b&gt;createPortal은 부모 컴포넌트 DOM 외부에 존재하는 DOM 노드에 해당 컴포넌트를 렌더링 할 수 있게 해주는 함수&lt;/b&gt;입니다. 쉽게 말해서 portal을 사용해서 모달 렌더링 시 부모 컴포넌트의 내부가 아닌, 위에서 삽입해 준 &lt;b&gt;&amp;lt;div id='modal'&amp;gt;&amp;lt;/div&amp;gt;&lt;/b&gt;에 모달을 렌더링 시킬 수 있는 것입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(3) 모달에 Portal 컴포넌트를 감싸줍니다.&lt;/p&gt;
&lt;pre id=&quot;code_1685492417963&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import React, { useState } from &quot;react&quot;;
import Confirm from &quot;@/components/Confirm&quot;;
import Button from &quot;@/components/Button&quot;;
import Portal from &quot;@/components/Portal&quot;;
import styled from &quot;styled-components&quot;;

const UseState = () =&amp;gt; {
  const [isOpen, setIsOpen] = useState&amp;lt;boolean&amp;gt;(false);
  const open = () =&amp;gt; {
    setIsOpen(true);
  };
  const close = () =&amp;gt; {
    setIsOpen(false);
  };
  const confirm = () =&amp;gt; {
    console.log(&quot;confirm clicked&quot;);
    setIsOpen(false);
  };
  return (
    &amp;lt;Wrapper&amp;gt;
      &amp;lt;Button onClick={open}&amp;gt;Open Confirm&amp;lt;/Button&amp;gt;
      {isOpen &amp;amp;&amp;amp; (
        &amp;lt;Portal&amp;gt;
          &amp;lt;Confirm
            title=&quot;알림&quot;
            message=&quot;상품을 주문하시겠습니까?&quot;
            close={close}
            confirm={confirm}
          &amp;gt;&amp;lt;/Confirm&amp;gt;
        &amp;lt;/Portal&amp;gt;
      )}
    &amp;lt;/Wrapper&amp;gt;
  );
};

export default UseState;

const Wrapper = styled.div`
  width: 100vw;
  height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
`;&lt;/code&gt;&lt;/pre&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;1035&quot; data-origin-height=&quot;970&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/S45QF/btsh2meKkmJ/HTji5CsyJajA5yiyPaTzkk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/S45QF/btsh2meKkmJ/HTji5CsyJajA5yiyPaTzkk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/S45QF/btsh2meKkmJ/HTji5CsyJajA5yiyPaTzkk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FS45QF%2Fbtsh2meKkmJ%2FHTji5CsyJajA5yiyPaTzkk%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;1035&quot; height=&quot;970&quot; data-origin-width=&quot;1035&quot; data-origin-height=&quot;970&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;페이지 요소 확인 시 모달이 컴포넌트 내부가 아닌&amp;nbsp;&lt;b&gt;&amp;lt;div id='modal'&amp;gt;&amp;lt;/div&amp;gt; &lt;/b&gt;내부에 생성된 것을 확인할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저의 경우 예시를 위해서 Portal이라는 컴포넌트를 생성해서 모달에 감싸줬지만, &lt;b&gt;실사용시에는 Portal 컴포넌트를 생성할 필요 없이 모달 컴포넌트 내부에서 createPortal을 사용하여 적용&lt;/b&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;3. useModal로 리팩토링&lt;/b&gt;&lt;/h2&gt;
&lt;pre id=&quot;code_1685566647561&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import React, { useState } from &quot;react&quot;;
import Confirm from &quot;@/components/Confirm&quot;;
import Button from &quot;@/components/Button&quot;;
import Portal from &quot;@/components/Portal&quot;;
import styled from &quot;styled-components&quot;;

const Page = () =&amp;gt; {
  const [isOpen, setIsOpen] = useState&amp;lt;boolean&amp;gt;(false);
  const open = () =&amp;gt; {
    setIsOpen(true);
  };
  const close = () =&amp;gt; {
    setIsOpen(false);
  };
  const confirm = () =&amp;gt; {
    console.log(&quot;confirm clicked&quot;);
    setIsOpen(false);
  };
  return (
    &amp;lt;Wrapper&amp;gt;
      &amp;lt;Button onClick={open}&amp;gt;Open Confirm&amp;lt;/Button&amp;gt;
      {isOpen &amp;amp;&amp;amp; (
        &amp;lt;Portal&amp;gt;
          &amp;lt;Confirm
            title=&quot;알림&quot;
            message=&quot;상품을 주문하시겠습니까?&quot;
            close={close}
            confirm={confirm}
          &amp;gt;&amp;lt;/Confirm&amp;gt;
        &amp;lt;/Portal&amp;gt;
      )}
    &amp;lt;/Wrapper&amp;gt;
  );
};

export default Page;

const Wrapper = styled.div`
  width: 100vw;
  height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
`;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;useState를 통해 모달을 관리할 시&lt;b&gt; 컴포넌트마다 useState로 모달을 렌더링 할지 말지에 대한 state를 정의하고 open과 close 함수를 생성해줘야 하는 문제점&lt;/b&gt;이 있습니다. 해당 부분을 리팩토링 해봅시다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 모달 state를 아래와 같이 useModal이라는 custom hook으로 만들어 줍니다.&lt;/p&gt;
&lt;pre id=&quot;code_1685566735823&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/* @/hooks/useModal.tsx */
import { useState } from &quot;react&quot;;

const useModal = () =&amp;gt; {
  const [isOpen, setIsOpen] = useState&amp;lt;boolean&amp;gt;(false);
  const open = () =&amp;gt; {
    setIsOpen(true);
  };
  const close = () =&amp;gt; {
    setIsOpen(false);
  };
  return { isOpen, open, close };
};

export default useModal;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;useModal custom hook을 생성했으니 이제 모달 렌더링이 필요한 컴포넌트에서 사용해 봅시다.&lt;/p&gt;
&lt;pre id=&quot;code_1685567008052&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import React from &quot;react&quot;;
import Confirm from &quot;@/components/Confirm&quot;;
import Button from &quot;@/components/Button&quot;;
import Portal from &quot;@/components/Portal&quot;;
import styled from &quot;styled-components&quot;;
import useModal from &quot;@/hooks/useModal&quot;;

const Page = () =&amp;gt; {
  const { isOpen, open, close } = useModal();

  const confirm = () =&amp;gt; {
    console.log(&quot;confirm clicked&quot;);
    close();
  };
  return (
    &amp;lt;Wrapper&amp;gt;
      &amp;lt;Button onClick={open}&amp;gt;Open Confirm&amp;lt;/Button&amp;gt;
      {isOpen &amp;amp;&amp;amp; (
        &amp;lt;Portal&amp;gt;
          &amp;lt;Confirm
            title=&quot;알림&quot;
            message=&quot;상품을 주문하시겠습니까?&quot;
            close={close}
            confirm={confirm}
          &amp;gt;&amp;lt;/Confirm&amp;gt;
        &amp;lt;/Portal&amp;gt;
      )}
    &amp;lt;/Wrapper&amp;gt;
  );
};

export default Page;

const Wrapper = styled.div`
  width: 100vw;
  height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
`;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리팩토링 시 위와 같이 state관리를 custom hook에 위임하고 open, close함수를 정의할 필요도 사라지게 됩니다.&lt;br /&gt;코드가 좀 더 깔끔해진 듯합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;(1) 페이지에 모달을 삽입하고 모달 관련 state관리 및 open &amp;amp; close 함수를 useModal이라는 custom hook으로 split&amp;nbsp;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;(2) createPortal을 사용해서 부모 컴포넌트 DOM 외부에서 모달을 렌더링&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;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;4. createRoot 방식&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 방식을 설명드리기 전에 먼저 빌드업부터 하겠습니다.&lt;br /&gt;Front에서는 서버와 통신하기 위해서는 아래와 같이 axios라는 라이브러리를 많이 사용합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1685568681994&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import React, { useEffect } from &quot;react&quot;;
import axios from &quot;axios&quot;;

const Page = () =&amp;gt; {
  useEffect(() =&amp;gt; {
    axios.get(&quot;/api/hello&quot;).then((res) =&amp;gt; {
      // business logic
    }).catch((err) =&amp;gt; {
      // error handling
    });
  }, []);
  return &amp;lt;div&amp;gt;index&amp;lt;/div&amp;gt;;
};

export default Page;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 해당 api가 오류를 발생시킬 때를 대비하여 catch 함수로 에러 핸들링을 하게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지금 여러분들은 Frontend 개발자이고 회사에서 프로젝트를 하나 담당하고 있다고 가정하겠습니다. &lt;br /&gt;회사 프로젝트에 페이지마다 2~3개씩 api를 호출하고, 프로젝트 전체에서 사용하는 총 api 수는 100개가 넘습니다.&lt;br /&gt;그래서 매일 아침 출근하자마자 해야 할 일은 상용 서비스에서 api응답에 오류가 없는지 확인하기 위해 콘솔창 네트워크 탭을 켜서 500 error 발생하는 api가 있는지 일일이 확인을 합니다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1685569172052&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import React, { useEffect } from &quot;react&quot;;
import axios from &quot;axios&quot;;

const Page = () =&amp;gt; {
  useEffect(() =&amp;gt; {
    axios
      .get(&quot;/api/user&quot;)
      .then((res) =&amp;gt; {
        // business logic
      })
      .catch((err) =&amp;gt; {
        if (err.response.status === 500) {
          // 서버 오류 알림 관련 모달
        }
      });
  }, []);
  useEffect(() =&amp;gt; {
    axios
      .get(&quot;/api/login&quot;)
      .then((res) =&amp;gt; {
        // business logic
      })
      .catch((err) =&amp;gt; {
        if (err.response.status === 500) {
          // 서버 오류 알림 관련 모달
        }
      });
  }, []);

  // ... 중략

  useEffect(() =&amp;gt; {
    axios
      .get(&quot;/api/signup&quot;)
      .then((res) =&amp;gt; {
        // business logic
      })
      .catch((err) =&amp;gt; {
        if (err.response.status === 500) {
          // 서버 오류 알림 관련 모달
        }
      });
  }, []);

  return &amp;lt;div&amp;gt;index&amp;lt;/div&amp;gt;;
};

export default Page;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 위와 같이 사용하는 api마다 catch로 500 error를 처리하게 된다면 100개가 넘는 api를 관리하고 유지보수하기 어려울 것입니다. 따라서 api 공통 에러 처리를 위해 axios라는 util을 만들어서 모든 api 통신의 톨게이트로 사용합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1685569796724&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/* @/utils/axios.tsx */
import Axios from &quot;axios&quot;;

const headers = {
  &quot;Content-Type&quot;: &quot;application/json&quot;,
};

const axios = Axios.create({
  baseURL: process.env.NEXT_PUBLIC_SERVER_URL,
  timeout: 15000,
  headers: headers,
});

axios.interceptors.request.use(
  (req) =&amp;gt; {
    return req;
  },
  (err) =&amp;gt; {
    return Promise.reject(err);
  }
);

axios.interceptors.response.use(
  (res) =&amp;gt; {
    return Promise.resolve(res);
  },
  (err) =&amp;gt; {
    if (err.response.status === 500) {
      // 서버 오류 알림 관련 모달
    }
    return Promise.reject(err);
  }
);

export default axios;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;axios를 사용하기 위해서 &lt;b&gt;import axios from &quot;axios&quot;&lt;/b&gt;&amp;nbsp; 대신 &lt;b&gt;import axios from &quot;@/utils/axios&quot;&lt;/b&gt;를 사용합니다&lt;/p&gt;
&lt;pre id=&quot;code_1685569916819&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import axios from &quot;@/utils/axios&quot;;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 일반 타입스크립트(자바스크립트) utils 파일에서 서버 오류 관련 모달을 렌더링 하여 서버 오류에 대한 &lt;b&gt;공통 처리&lt;/b&gt;가 가능하게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;axios util file은 컴포넌트가 아니라서 useState도 사용 못하는데...&lt;br /&gt;어떻게 모달을 렌더링 할 수가 있죠?&lt;/span&gt;&lt;/blockquote&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;b&gt;ReactDOM.createRoot&lt;/b&gt; 함수를 사용해서 구현할 수 있습니다. &lt;br /&gt;getElementById를 통해서 모달을 띄울 node를 찾고 &lt;b&gt;ReactDOM.createRoot를 통해서 root를 생성&lt;/b&gt;하여 해당 node에 &lt;b&gt;root.render, root.unmount 함수를 통해서 모달을 rendering 하고 unmount&lt;/b&gt; 할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 서버 오류를 띄울 Alert 모달을 하나 만들어 보겠습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1685572398669&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/* @/components/Alert.tsx */

import React from &quot;react&quot;;
import styled from &quot;styled-components&quot;;

type Props = {
  title?: string;
  message?: string;
  btnText?: string;
  close?: () =&amp;gt; void;
};

const Alert = ({ title, message, btnText, close }: Props) =&amp;gt; {
  return (
    &amp;lt;Wrapper&amp;gt;
      &amp;lt;Overlay onClick={close}&amp;gt;&amp;lt;/Overlay&amp;gt;
      &amp;lt;Content&amp;gt;
        &amp;lt;Title&amp;gt;{title}&amp;lt;/Title&amp;gt;
        &amp;lt;Message&amp;gt;{message}&amp;lt;/Message&amp;gt;
        &amp;lt;ConfirmBtn onClick={close}&amp;gt;{btnText}&amp;lt;/ConfirmBtn&amp;gt;
      &amp;lt;/Content&amp;gt;
    &amp;lt;/Wrapper&amp;gt;
  );
};

export default Alert;

const Wrapper = styled.div``;
const Overlay = styled.div`
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 999;
  background-color: rgba(0, 0, 0, 0.4);
`;
const Content = styled.div`
  position: fixed;
  display: grid;
  gap: 16px;
  top: 50%;
  left: 50%;
  padding: 16px;
  min-width: 200px;
  max-width: 400px;
  border-radius: 12px;
  overflow: hidden;
  background-color: white;
  transform: translate(-50%, -50%);
  z-index: 999;
`;
const Title = styled.h3`
  text-align: center;
`;
const Message = styled.p``;
const ConfirmBtn = styled.div`
  flex: 1;
  height: 24px;
  text-align: center;
  color: white;
  background-color: royalblue;
  border-radius: 4px;
  cursor: pointer;
`;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 modal util을 하나 만들어 줍니다.&lt;/p&gt;
&lt;pre id=&quot;code_1685572427091&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/* @/utils/modal.tsx */
import ReactDOM from &quot;react-dom/client&quot;;

import Alert from &quot;@/components/Alert&quot;;

type Props = {
  isOpen?: boolean;
  title?: string;
  message?: string;
  btnText?: string;
  component?: () =&amp;gt; JSX.Element;
};

const modal = {
  open: (Component: (props: Props) =&amp;gt; JSX.Element, props: Props) =&amp;gt; {
    const defaultProps = {
      isOpen: true,
      close: () =&amp;gt; {},
    };
    const container = document.getElementById(&quot;modal&quot;);
    if (!container) return;
    const root = ReactDOM.createRoot(container);

    defaultProps.close = () =&amp;gt; {
      defaultProps.isOpen = false;
      root.unmount();
    };

    defaultProps.isOpen = true;
    root.render(&amp;lt;Component {...defaultProps} {...props}&amp;gt;&amp;lt;/Component&amp;gt;);
  },

  // alert
  openAlert: (props: Props) =&amp;gt; {
    modal.open(Alert, props);
  },
};

export default modal;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 axios uitl에서 아래와 같이 modal을 open 시킬 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1685572564109&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/* @/utils/axios.tsx */
import Axios from &quot;axios&quot;;
import modal from &quot;@/utils/modal&quot;;

const headers = {
  &quot;Content-Type&quot;: &quot;application/json&quot;,
};

const axios = Axios.create({
  baseURL: process.env.NEXT_PUBLIC_SERVER_URL,
  timeout: 15000,
  headers: headers,
});

axios.interceptors.request.use(
  (req) =&amp;gt; {
    return req;
  },
  (err) =&amp;gt; {
    return Promise.reject(err);
  }
);

axios.interceptors.response.use(
  (res) =&amp;gt; {
    return Promise.resolve(res);
  },
  (err) =&amp;gt; {
    if (err.response.status === 500) {
      // 서버 오류 알림 관련 모달
      modal.openAlert({
        title: &quot;알림&quot;,
        message: &quot;서버 오류가 발생하였습니다.&quot;,
        btnText: &quot;확인&quot;,
      });
    }
    return Promise.reject(err);
  }
);

export default axios;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;api에서 일부러 500 error를 발생시키면 아래와 같은 모달이 뜨는 것을 확인할 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;527&quot; data-origin-height=&quot;264&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bIHpqe/btsicO81niu/swURA7XocY4ssGEoXI2YTK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bIHpqe/btsicO81niu/swURA7XocY4ssGEoXI2YTK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bIHpqe/btsicO81niu/swURA7XocY4ssGEoXI2YTK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbIHpqe%2FbtsicO81niu%2FswURA7XocY4ssGEoXI2YTK%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;527&quot; height=&quot;264&quot; data-origin-width=&quot;527&quot; data-origin-height=&quot;264&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;컴포넌트 내부에서도 모달을 띄울 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1685572713050&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import React, { useEffect } from &quot;react&quot;;
import modal from &quot;@/utils/modal&quot;;

const Page = () =&amp;gt; {
  useEffect(() =&amp;gt; {
    modal.openAlert({
      title: &quot;Notice&quot;,
      message: &quot;Message&quot;,
      btnText: &quot;Ok&quot;,
    });
  }, []);

  return &amp;lt;div&amp;gt;index&amp;lt;/div&amp;gt;;
};

export default Page;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;516&quot; data-origin-height=&quot;315&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qVBsa/btsiaZcseUm/qGkwKqINke3BAYMXyN45F0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qVBsa/btsiaZcseUm/qGkwKqINke3BAYMXyN45F0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qVBsa/btsiaZcseUm/qGkwKqINke3BAYMXyN45F0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqVBsa%2FbtsiaZcseUm%2FqGkwKqINke3BAYMXyN45F0%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;516&quot; height=&quot;315&quot; data-origin-width=&quot;516&quot; data-origin-height=&quot;315&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러나 createRoot 방식 같은 경우에는 next/router의 useRouter나 recoilState 같은 일부 기능사용 시 에러가 발생하는 문제점이 있습니다.(React DOM의 계층구조에서 렌더링 된 것이 아닌 node에 컴포넌트를 create 하는 방식이기 때문인 것으로 생각됩니다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇기 때문에 &lt;b&gt;createRoot 방식의 경우는 util파일에서 데이터 변경이 없는 정적이고 간단한 알림 모달이 필요할 경우에만 사용하는 것을 추천&lt;/b&gt;드립니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;5. with Redux&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;useState로 모달을 사용하면서 모달 관련 상태관리 코드가 많아지게 되었고&amp;nbsp; &quot;&lt;b&gt;모달을 전역상태로 관리를 하면 어떨까?&quot;라는&lt;/b&gt; 아이디어가 떠올라서 그 당시 프로젝트에서 사용 중인 전역상태관리 라이브러리인 redux로 모달을 구현하여 썼었던 경험이 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컴포넌트를 props로 받는 모달 컴포넌트 생성&lt;/p&gt;
&lt;pre id=&quot;code_1686063193036&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/* @/components/Modal.tsx */

import React from &quot;react&quot;;
import styled from &quot;styled-components&quot;;

type Props = {
  close?: () =&amp;gt; void;
  component?: () =&amp;gt; JSX.Element;
};

const Alert = ({ component, close }: Props) =&amp;gt; {
  return (
    &amp;lt;Wrapper&amp;gt;
      &amp;lt;Overlay onClick={close}&amp;gt;&amp;lt;/Overlay&amp;gt;
      &amp;lt;Content&amp;gt; {component &amp;amp;&amp;amp; component()}&amp;lt;/Content&amp;gt;
    &amp;lt;/Wrapper&amp;gt;
  );
};

export default Alert;

const Wrapper = styled.div``;
const Overlay = styled.div`
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 999;
  background-color: rgba(0, 0, 0, 0.4);
`;
const Content = styled.div`
  position: fixed;
  display: grid;
  gap: 16px;
  top: 50%;
  left: 50%;
  padding: 16px;
  min-width: 200px;
  max-width: 400px;
  border-radius: 12px;
  overflow: hidden;
  background-color: white;
  transform: translate(-50%, -50%);
  z-index: 999;
`;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(1) 프로젝트 redux 폴더 내 store, reducer, hooks 구현&lt;/p&gt;
&lt;pre id=&quot;code_1686059884581&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/* @/redux/store.ts */

import { configureStore } from &quot;@reduxjs/toolkit&quot;;
import modalReducer from &quot;@/redux/modal&quot;;

export const store = configureStore({
  reducer: { modal: modalReducer },
  middleware: (getDefaultMiddleware) =&amp;gt;
    getDefaultMiddleware({ serializableCheck: false }),
});

// @ts-ignore
export type RootState = ReturnType&amp;lt;typeof store.getState&amp;gt;;
export type AppDispatch = typeof store.dispatch;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Store 설정입니다. 가장 간단하게 설정하였고 state로 컴포넌트를 저장하기 때문에 미들웨어 serializableCheck를 false로 설정해 줍시다.(컴포넌트 children의 순환구조 때문에 직렬화 이슈가 있어 콘솔 에러가 발생하는 것으로 기억)&lt;/p&gt;
&lt;pre id=&quot;code_1686059892088&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/* @/redux/hooks.ts */

import { TypedUseSelectorHook, useDispatch, useSelector } from &quot;react-redux&quot;;
import type { RootState, AppDispatch } from &quot;@/redux/store&quot;;

export const useAppDispatch = () =&amp;gt; useDispatch&amp;lt;AppDispatch&amp;gt;();
export const useAppSelector: TypedUseSelectorHook&amp;lt;RootState&amp;gt; = useSelector;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;타입스크립트에서 useSelector, useDispatch를 좀 더 쉽게 사용하기 위해 만들어 줍니다.&lt;/p&gt;
&lt;pre id=&quot;code_1686059937246&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/* @/redux/modal.ts */

import { createSlice } from &quot;@reduxjs/toolkit&quot;;
import type { RootState } from &quot;@/redux/store&quot;;

export type ModalProps = {
  key?: string;
  component?: () =&amp;gt; JSX.Element;
};

const initialState: ModalProps[] = [];

const modalReducer = createSlice({
  name: &quot;modal&quot;,
  initialState,
  reducers: {
    setState(state, action) {
      return action.payload;
    },
  },
});

export const modalActions = { ...modalReducer.actions };
export const selecModal = (state: RootState) =&amp;gt; state.modal;
export default modalReducer.reducer;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;reducer부분입니다. 상태 관리를 위한 setState함수만 추가해 줍니다.&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) _app.tsx에 redux Provider를 감싸주고, 모달을 띄워줄 root 컴포넌트를 생성하여 _app.tsx에 넣어줍니다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1686060362708&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/* @/components/ReduxModalRoot.tsx */

import React from &quot;react&quot;;
import { useAppSelector } from &quot;@/redux/hooks&quot;;
import Modal from &quot;@/components/Modal&quot;;

const ReduxModalRoot = () =&amp;gt; {
  const modals = useAppSelector((state) =&amp;gt; state.modal);

  return (
    &amp;lt;div id=&quot;redux-modal&quot;&amp;gt;
      {modals.map((modal) =&amp;gt; (
        &amp;lt;Modal key={modal.key} {...modal}&amp;gt;&amp;lt;/Modal&amp;gt;
      ))}
    &amp;lt;/div&amp;gt;
  );
};

export default ReduxModalRoot;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모달을 띄워줄 root입니다. 배열을 map으로 돌려서 modal들을 띄워주는 역할을 합니다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1686060482531&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/* @/pages/_app.tsx */

import &quot;@/styles/globals.scss&quot;;
import type { AppProps } from &quot;next/app&quot;;
import { store } from &quot;@/redux/store&quot;;
import { Provider } from &quot;react-redux&quot;;
import ReduxModalRoot from &quot;@/components/ReduxModalRoot&quot;;

export default function App({ Component, pageProps }: AppProps) {
  return (
    &amp;lt;Provider store={store}&amp;gt;
      &amp;lt;ReduxModalRoot&amp;gt;&amp;lt;/ReduxModalRoot&amp;gt;
      &amp;lt;Component {...pageProps} /&amp;gt;
    &amp;lt;/Provider&amp;gt;
  );
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(3) 모달 사용을 위한 custom hooks를 만들어 줍니다.&lt;/p&gt;
&lt;pre id=&quot;code_1686060638149&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/* @/hooks/useReduxModal.tsx */

import { modalActions, ModalProps } from &quot;@/redux/modal&quot;;
import { useAppSelector, useAppDispatch } from &quot;@/redux/hooks&quot;;

const useReduxModal = () =&amp;gt; {
  const dispatch = useAppDispatch();
  const modals = useAppSelector((state) =&amp;gt; state.modal);

  const openModal = (props: ModalProps) =&amp;gt; {
    const key = Math.random().toString(36).substring(2);
    const nextProps = {
      key,
      close: () =&amp;gt; dispatch(modalActions.setState([...modals])),
      ...props,
    };
    dispatch(modalActions.setState([...modals].concat(nextProps)));
  };

  return { openModal };
};

export default useReduxModal;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;openModal 함수에서는 unique 한 key와 close 함수를 만들어 modals state 배열에 모달을 추가해 주는 역할을 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;사용 예시&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1686063058715&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import React from &quot;react&quot;;
import useReduxModal from &quot;@/hooks/useReduxModal&quot;;
import styled from &quot;styled-components&quot;;
import Button from &quot;@/components/Button&quot;;

const Page = () =&amp;gt; {
  const modal = useReduxModal();

  const open = () =&amp;gt; {
    modal.openModal({ component: () =&amp;gt; &amp;lt;Content&amp;gt;modal content&amp;lt;/Content&amp;gt; });
  };

  return (
    &amp;lt;Wrapper&amp;gt;
      &amp;lt;Button onClick={open}&amp;gt;Open Modal&amp;lt;/Button&amp;gt;
    &amp;lt;/Wrapper&amp;gt;
  );
};

export default Page;

const Wrapper = styled.div`
  width: 100vw;
  height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
`;
const Content = styled.div`
  width: 200px;
  height: 300px;
`;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/n8LrF/btsiO6aJLGV/Uz4ZWb0JTNw4gc67dL2Bxk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/n8LrF/btsiO6aJLGV/Uz4ZWb0JTNw4gc67dL2Bxk/img.png&quot; data-origin-width=&quot;651&quot; data-origin-height=&quot;382&quot; data-is-animation=&quot;false&quot; style=&quot;width: 50.2787%; margin-right: 10px;&quot; data-widthpercent=&quot;50.87&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/n8LrF/btsiO6aJLGV/Uz4ZWb0JTNw4gc67dL2Bxk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fn8LrF%2FbtsiO6aJLGV%2FUz4ZWb0JTNw4gc67dL2Bxk%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;651&quot; height=&quot;382&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/M6kud/btsiOivQxcr/eWsjUetH32TH7GjMSgBpm0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/M6kud/btsiOivQxcr/eWsjUetH32TH7GjMSgBpm0/img.png&quot; data-origin-width=&quot;660&quot; data-origin-height=&quot;401&quot; data-is-animation=&quot;false&quot; data-widthpercent=&quot;49.13&quot; style=&quot;width: 48.5585%;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/M6kud/btsiOivQxcr/eWsjUetH32TH7GjMSgBpm0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FM6kud%2FbtsiOivQxcr%2FeWsjUetH32TH7GjMSgBpm0%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;660&quot; height=&quot;401&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;useReduxModal hooks를 사용하여 modal.openModal로 모달을 띄워줄 수 있습니다. 전역 상태로 모달을 관리할 경우 장점은 &lt;b&gt;모달의 props로 전달하는 component 내부에서도 next/router나 redux state값들을 사용할 수 있다&lt;/b&gt;는 점, 모달에 type이라는 property를 추가하여 openAlert, openConfirm, openBottomSheet 같은 함수들을 생성하고 &lt;b&gt;root에서 type별로(Alert, Confirm, BottomSheet,...) 필터링하여 렌더링 할 수 있다&lt;/b&gt;는 장점이 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;5. with Recoil&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;recoil을 사용하는 방법은 redux를 사용하여 구현한 방법과 흡사하며, &lt;b&gt;redux보다 boilerplate 코드가 적다는 장점&lt;/b&gt;이 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(1) 상태 atoms 생성&lt;/p&gt;
&lt;pre id=&quot;code_1686066695895&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/* @/recoil/atoms.ts */

import { atom } from &quot;recoil&quot;;

export type ModalProps = {
  key?: string;
  component?: () =&amp;gt; JSX.Element;
};

export const modalState = atom&amp;lt;ModalProps[]&amp;gt;({
  key: &quot;modalState&quot;,
  default: [],
});&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(2) ModalRoot 생성 및 _app.tsx 설정&lt;/p&gt;
&lt;pre id=&quot;code_1686066757021&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/* @/components/RecoilModalRoot.tsx */

import React from &quot;react&quot;;
import Modal from &quot;@/components/Modal&quot;;
import { useRecoilValue } from &quot;recoil&quot;;
import { modalState } from &quot;@/recoil/atoms&quot;;

const RecoilModalRoot = () =&amp;gt; {
  const modals = useRecoilValue(modalState);
  return (
    &amp;lt;div id=&quot;recoil-modal&quot;&amp;gt;
      {modals.map((modal) =&amp;gt; (
        &amp;lt;Modal key={modal.key} {...modal}&amp;gt;&amp;lt;/Modal&amp;gt;
      ))}
    &amp;lt;/div&amp;gt;
  );
};

export default RecoilModalRoot;&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1686066763662&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/* @/pages/_app.tsx */

import &quot;@/styles/globals.scss&quot;;
import type { AppProps } from &quot;next/app&quot;;
import { RecoilRoot } from &quot;recoil&quot;;
import RecoilModalRoot from &quot;@/components/RecoilModalRoot&quot;;

export default function App({ Component, pageProps }: AppProps) {
  return (
    &amp;lt;RecoilRoot&amp;gt;
      &amp;lt;RecoilModalRoot&amp;gt;&amp;lt;/RecoilModalRoot&amp;gt;
      &amp;lt;Component {...pageProps} /&amp;gt;
    &amp;lt;/RecoilRoot&amp;gt;
  );
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;_app.tsx에서는 전체를 RecoilRoot로 감싸주고 ModalRoot를 삽입해 줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(3) useRecoilModal custom hooks 생성&lt;/p&gt;
&lt;pre id=&quot;code_1686066925745&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/* @/hooks/useRecoilModal.tsx */

import { useRecoilState } from &quot;recoil&quot;;
import { modalState, ModalProps } from &quot;@/recoil/atoms&quot;;

const useRecoilModal = () =&amp;gt; {
  const [modals, setModals] = useRecoilState(modalState);

  const openModal = (props: ModalProps) =&amp;gt; {
    const key = Math.random().toString(36).substring(2);
    const nextProps = {
      key,
      close: () =&amp;gt; setModals([...modals]),
      ...props,
    };
    setModals([...modals].concat(nextProps));
  };

  return { openModal };
};

export default useRecoilModal;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;redux를 이용한 방식에서와 같이 openModal이라는 함수를 통해 모달 상태 관리를 해줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;사용 예제&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1686066974424&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import React from &quot;react&quot;;
import useRecoilModal from &quot;@/hooks/useRecoilModal&quot;;
import styled from &quot;styled-components&quot;;
import Button from &quot;@/components/Button&quot;;

const Page = () =&amp;gt; {
  const modal = useRecoilModal();

  const open = () =&amp;gt; {
    modal.openModal({ component: () =&amp;gt; &amp;lt;Content&amp;gt;component&amp;lt;/Content&amp;gt; });
  };

  return (
    &amp;lt;Wrapper&amp;gt;
      &amp;lt;Button onClick={open}&amp;gt;Open Modal&amp;lt;/Button&amp;gt;
    &amp;lt;/Wrapper&amp;gt;
  );
};

export default Page;

const Wrapper = styled.div`
  width: 100vw;
  height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
`;
const Content = styled.div`
  width: 200px;
  height: 300px;
  background-color: #eeeeee;
  border-radius: 12px;
`;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/9bHk4/btsiM97cHRA/TdFLv97g2kQhn85DT8NeiK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/9bHk4/btsiM97cHRA/TdFLv97g2kQhn85DT8NeiK/img.png&quot; data-origin-width=&quot;669&quot; data-origin-height=&quot;499&quot; data-is-animation=&quot;false&quot; style=&quot;width: 47.5017%; margin-right: 10px;&quot; data-widthpercent=&quot;48.06&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/9bHk4/btsiM97cHRA/TdFLv97g2kQhn85DT8NeiK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F9bHk4%2FbtsiM97cHRA%2FTdFLv97g2kQhn85DT8NeiK%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;669&quot; height=&quot;499&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Fx6hN/btsiOi3Iymn/0IjhjAidFOhc7pDsY2zykk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Fx6hN/btsiOi3Iymn/0IjhjAidFOhc7pDsY2zykk/img.png&quot; data-origin-width=&quot;652&quot; data-origin-height=&quot;450&quot; data-is-animation=&quot;false&quot; data-widthpercent=&quot;51.94&quot; style=&quot;width: 51.3356%;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Fx6hN/btsiOi3Iymn/0IjhjAidFOhc7pDsY2zykk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FFx6hN%2FbtsiOi3Iymn%2F0IjhjAidFOhc7pDsY2zykk%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;652&quot; height=&quot;450&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;useReduxModal hooks와 마찬가지로 openModal을 통해서 모달에 렌더링 할 컴포넌트를 props로 전달하여 모달을 렌더링 시킬 수 도 있고, openAlert, openConfirm 함수 생성 후 title, message, onClickConfirm을 props로 전달하여 Alert나 Confirm을 띄울 수 도 있습니다. 아무래도 redux보다는 recoil이 보일러플레이트 코드가 적고 사용이 쉬워서 사용하기에 간편하다는 생각이 듭니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;6. with Context&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;redux, recoil을 통해서 모달 관리를 할 시 &lt;b&gt;redux나 recoil을 무조건 사용해야 한다는 의존성&lt;/b&gt;이 생기게 됩니다. 그러한 의존성을 제거하기 위해서 React 내장 API인 &lt;b&gt;useContext&lt;/b&gt;를 통해서 구현을 해봤습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(1) useContextModal를 만들어주고 ModalProvider 생성 후 _app.tsx에 설정&lt;/p&gt;
&lt;pre id=&quot;code_1698412057666&quot; class=&quot;javascript&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;/* @/hooks/useContextModal.tsx */

import { useContext } from &quot;react&quot;;
import { ModalContext } from &quot;@/components/ModalProvider&quot;;
import { ModalProps, Modals } from &quot;@/types&quot;;

let tmpModals: Modals;

const useContextModal = () =&amp;gt; {
  const { modals, setModals } = useContext(ModalContext);
  tmpModals = modals;

  const openModal = (props: ModalProps) =&amp;gt; {
    const hashMapA: Map&amp;lt;string, ModalProps&amp;gt; = new Map(tmpModals);
    const key = Math.random().toString(36).substring(2);
    props.key = props.key || key;
    props.close = async () =&amp;gt; {
      const hashMapB = new Map(hashMapA);
      if (props.key) {
        hashMapB.delete(props.key!);
        setModals(new Map(hashMapB));
      }
    };
    hashMapA.set(props.key, props);
    setModals(hashMapA);
  };

  const closeModal = (key?: string) =&amp;gt; {
    const hashMap: Map&amp;lt;string, ModalProps&amp;gt; = new Map(tmpModals);
    if (key) {
      const props = hashMap.get(key);
      if (props) {
        hashMap.delete(key);
        setModals(new Map(hashMap));
      }
      return;
    }
  };

  const openAlert = (props: ModalProps) =&amp;gt; {
    openModal({ ...props, type: &quot;ALERT&quot; });
  };

  const openConfirm = (props: ModalProps) =&amp;gt; {
    openModal({ ...props, type: &quot;CONFIRM&quot; });
  };

  return {
    openModal,
    closeModal,
    openAlert,
    openConfirm,
  };
};

export default useContextModal;&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1686069282587&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/* @/components/ModalProvider.tsx */

import React, { createContext, ReactNode, useState } from &quot;react&quot;;

import Alert from &quot;@/components/Alert&quot;;
import Confirm from &quot;@/components/Confirm&quot;;
import Modal from &quot;@/components/Modal&quot;;
import { ModalProps, Modals } from &quot;@/hooks/useContextModal&quot;;

type Props = {
  children: ReactNode;
};

export const ModalContext = createContext({
  modals: new Map(),
  setModals: (state: Modals) =&amp;gt; {},
});

const ModalProvider = ({ children }: Props) =&amp;gt; {
  const [modals, setModals] = useState&amp;lt;Modals&amp;gt;(new Map());

  const alertList: ModalProps[] = [];
  const confirmList: ModalProps[] = [];
  const modalList: ModalProps[] = [];

  modals.forEach((value, key) =&amp;gt; {
    switch (value.type) {
      case &quot;ALERT&quot;:
        alertList.push(value);
        break;
      case &quot;CONFIRM&quot;:
        confirmList.push(value);
        break;
      default:
        modalList.push(value);
        break;
    }
  });

  return (
    &amp;lt;ModalContext.Provider value={{ modals, setModals }}&amp;gt;
      &amp;lt;div id=&quot;alert&quot;&amp;gt;
        {alertList.map((modal) =&amp;gt; (
          &amp;lt;Alert key={modal.key} {...modal}&amp;gt;&amp;lt;/Alert&amp;gt;
        ))}
      &amp;lt;/div&amp;gt;
      &amp;lt;div id=&quot;confirm&quot;&amp;gt;
        {confirmList.map((modal) =&amp;gt; (
          &amp;lt;Confirm key={modal.key} {...modal}&amp;gt;&amp;lt;/Confirm&amp;gt;
        ))}
      &amp;lt;/div&amp;gt;
      &amp;lt;div id=&quot;modal&quot;&amp;gt;
        {modalList.map((modal) =&amp;gt; (
          &amp;lt;Modal key={modal.key} {...modal}&amp;gt;&amp;lt;/Modal&amp;gt;
        ))}
      &amp;lt;/div&amp;gt;
      {children}
    &amp;lt;/ModalContext.Provider&amp;gt;
  );
};

export default ModalProvider;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;redux와 recoil에서 구현했던 방식과는 조금 다르게 &lt;b&gt;Hash Map&lt;/b&gt;을 사용하여 state를 관리합니다. 그리고 &lt;b&gt;Map 순회를 통해 각 타입별(Alert, Confirm, Modal)로 배열에 담아 DOM에 모달을 렌더링&lt;/b&gt;을 합니다. 그리고 해당 컴포넌트를 &lt;b&gt;ModalContext.Provider&lt;/b&gt;로 감싸주어 state를 공급합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1686069289802&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/* @/pages/_app.tsx */

import &quot;@/styles/globals.scss&quot;;
import type { AppProps } from &quot;next/app&quot;;
import ModalProvider from &quot;@/components/ModalProvider&quot;;

export default function App({ Component, pageProps }: AppProps) {
  return (
    &amp;lt;ModalProvider&amp;gt;
      &amp;lt;Component {...pageProps} /&amp;gt;
    &amp;lt;/ModalProvider&amp;gt;
  );
}&lt;/code&gt;&lt;/pre&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;사용 예제&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1686069739192&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import React from &quot;react&quot;;
import useContextModal from &quot;@/hooks/useContextModal&quot;;
import styled from &quot;styled-components&quot;;
import Button from &quot;@/components/Button&quot;;

const Page = () =&amp;gt; {
  const modal = useContextModal();

  const openAlert = () =&amp;gt; {
    modal.openAlert({
      title: &quot;알림&quot;,
      message: &quot;할인 특가 이벤트 중&quot;,
      btnText: &quot;바로가기&quot;,
    });
  };
  const openConfirm = () =&amp;gt; {
    modal.openConfirm({
      title: &quot;주문&quot;,
      message: &quot;상품을 주문하시겠습니까?&quot;,
      confirm: () =&amp;gt; {
        console.log(&quot;주문 완료&quot;);
      },
    });
  };
  const openModal = () =&amp;gt; {
    modal.openModal({ component: () =&amp;gt; &amp;lt;Content&amp;gt;Modal component&amp;lt;/Content&amp;gt; });
  };

  return (
    &amp;lt;Wrapper&amp;gt;
      &amp;lt;Button onClick={openAlert}&amp;gt;Open Alert&amp;lt;/Button&amp;gt;
      &amp;lt;Button onClick={openConfirm}&amp;gt;Open Confirm&amp;lt;/Button&amp;gt;
      &amp;lt;Button onClick={openModal}&amp;gt;Open Modal&amp;lt;/Button&amp;gt;
    &amp;lt;/Wrapper&amp;gt;
  );
};

export default Page;

const Wrapper = styled.div`
  width: 100vw;
  height: 100vh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  gap: 8px;
`;
const Content = styled.div`
  width: 400px;
  height: 200px;
`;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cQdjmp/btsiU5WcEH5/eBIHAz03fEIt8IbisEmXL1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cQdjmp/btsiU5WcEH5/eBIHAz03fEIt8IbisEmXL1/img.png&quot; data-origin-width=&quot;664&quot; data-origin-height=&quot;409&quot; data-is-animation=&quot;false&quot; style=&quot;width: 48.6578%; margin-right: 10px;&quot; data-widthpercent=&quot;49.23&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cQdjmp/btsiU5WcEH5/eBIHAz03fEIt8IbisEmXL1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcQdjmp%2FbtsiU5WcEH5%2FeBIHAz03fEIt8IbisEmXL1%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;664&quot; height=&quot;409&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mKSBv/btsiOKTdSfi/kKvkIHhOVgKkbwzGaX7fVK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mKSBv/btsiOKTdSfi/kKvkIHhOVgKkbwzGaX7fVK/img.png&quot; data-origin-width=&quot;663&quot; data-origin-height=&quot;396&quot; data-is-animation=&quot;false&quot; style=&quot;width: 50.1794%;&quot; data-widthpercent=&quot;50.77&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mKSBv/btsiOKTdSfi/kKvkIHhOVgKkbwzGaX7fVK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmKSBv%2FbtsiOKTdSfi%2FkKvkIHhOVgKkbwzGaX7fVK%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;663&quot; height=&quot;396&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bPeQXg/btsiJ7BHP3u/FU0Oliy3VqAEXrVuF0dPuK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bPeQXg/btsiJ7BHP3u/FU0Oliy3VqAEXrVuF0dPuK/img.png&quot; data-origin-width=&quot;659&quot; data-origin-height=&quot;409&quot; data-is-animation=&quot;false&quot; style=&quot;width: 53.0112%; margin-right: 10px;&quot; data-widthpercent=&quot;53.63&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bPeQXg/btsiJ7BHP3u/FU0Oliy3VqAEXrVuF0dPuK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbPeQXg%2FbtsiJ7BHP3u%2FFU0Oliy3VqAEXrVuF0dPuK%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;659&quot; height=&quot;409&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/boXDy8/btsiO4Rz63A/jt99gfNtztVlB4S8Dl2Ir0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/boXDy8/btsiO4Rz63A/jt99gfNtztVlB4S8Dl2Ir0/img.png&quot; data-origin-width=&quot;663&quot; data-origin-height=&quot;476&quot; data-is-animation=&quot;false&quot; style=&quot;width: 45.826%;&quot; data-widthpercent=&quot;46.37&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/boXDy8/btsiO4Rz63A/jt99gfNtztVlB4S8Dl2Ir0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FboXDy8%2FbtsiO4Rz63A%2Fjt99gfNtztVlB4S8Dl2Ir0%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;663&quot; height=&quot;476&quot;/&gt;&lt;/span&gt;&lt;/div&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;이 방식의 경우 제가 현재 사용하고 있는 방식이며 &lt;b&gt;라이브러리 의존성 없이 내장 함수만을 사용하여 구현&lt;/b&gt;할 수 있는 방법입니다. &lt;b&gt;&lt;u&gt;본 포스팅에서는 아이디어를 공유한다는 느낌으로 최대한 간단하게 구현을 하였고 실제로 사용을 하신다면 해당 아이디어를 통해서 커스터마이징하고 프로젝트의 특성에 맞게 변환시켜줘야 합니다.&lt;/u&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 modal의 width, height, padding, top, left, cancelBtnText, confirmBtnText, onAfterOpen, onAfterClose 등등을 props로 받아서 처리를 할 수 도 있고, isOpen이라는 변수를 props로 넘겨줘서 모달이 만들어지고 사라지는 애니메이션을 보여주고 200ms 뒤 모달을 state에서 제거하는 방식으로도 구현이 가능합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 컴포넌트가 아닌 파일에서 모달이 띄울 필요가 생길 때는 해당 방식을 사용할 수 없어 (&lt;b&gt;4) createRoo&lt;/b&gt;t 방식을 혼용해서 사용하고 있습니다. 좀 더 좋은 아이디어를 아시는 분은 댓글로 알려주시면 감사드리겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래의 링크는 제가 시간 날 때마다 만들고 있는 todo list app에서 사용할 모달들을 테스트하는 페이지입니다. context를 통해서 모달을 관리하는 프로젝트이며 실제 사용 코드는 해당 레포에서 확인이 가능합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://todo-list-ma9pie.vercel.app/test/modals&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://todo-list-ma9pie.vercel.app/test/modals&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1686071151557&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Todo List App&quot; data-og-description=&quot;사용자가 할 일을 리스트에 추가하고, 체크박스로 완료 여부를 표시할 수 있도록 해주는 Todo List App입니다. 사용자들은 할 일을 보다 체계적으로 관리할 수 있으며, 직관적이고 간단한 디자인으&quot; data-og-host=&quot;todo-list-ma9pie.vercel.app&quot; data-og-source-url=&quot;https://todo-list-ma9pie.vercel.app/test/modals&quot; data-og-url=&quot;https://todo-list-ma9pie.vercel.app&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://todo-list-ma9pie.vercel.app/test/modals&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://todo-list-ma9pie.vercel.app/test/modals&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Todo List App&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;사용자가 할 일을 리스트에 추가하고, 체크박스로 완료 여부를 표시할 수 있도록 해주는 Todo List App입니다. 사용자들은 할 일을 보다 체계적으로 관리할 수 있으며, 직관적이고 간단한 디자인으&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;todo-list-ma9pie.vercel.app&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/ma9pie/todo-list&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://github.com/ma9pie/todo-list&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1686071154295&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;GitHub - ma9pie/todo-list&quot; data-og-description=&quot;Contribute to ma9pie/todo-list development by creating an account on GitHub.&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/ma9pie/todo-list&quot; data-og-url=&quot;https://github.com/ma9pie/todo-list&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bzuJBo/hySTPYPMy6/dNUz4KgVaygoF5F2TqLNAk/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/ma9pie/todo-list&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/ma9pie/todo-list&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bzuJBo/hySTPYPMy6/dNUz4KgVaygoF5F2TqLNAk/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;GitHub - ma9pie/todo-list&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Contribute to ma9pie/todo-list development by creating an account on GitHub.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&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 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>⚛️React</category>
      <author>Cocoon_</author>
      <guid isPermaLink="true">https://cocoon1787.tistory.com/875</guid>
      <comments>https://cocoon1787.tistory.com/875#entry875comment</comments>
      <pubDate>Tue, 30 May 2023 23:48:59 +0900</pubDate>
    </item>
    <item>
      <title>[React] &amp;quot;Manifest: Line: 1, column: 1, Syntax error.&amp;quot; 에러</title>
      <link>https://cocoon1787.tistory.com/874</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1293&quot; data-origin-height=&quot;714&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/WYcYD/btscQQx0VYb/IK2yBuTvs2yzyUK0lCCQ8k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/WYcYD/btscQQx0VYb/IK2yBuTvs2yzyUK0lCCQ8k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/WYcYD/btscQQx0VYb/IK2yBuTvs2yzyUK0lCCQ8k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FWYcYD%2FbtscQQx0VYb%2FIK2yBuTvs2yzyUK0lCCQ8k%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;1293&quot; height=&quot;714&quot; data-origin-width=&quot;1293&quot; data-origin-height=&quot;714&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;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;243&quot; data-origin-height=&quot;109&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/O05lu/btscPcIFWUM/60snt1brNeDTuoX6eJzptk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/O05lu/btscPcIFWUM/60snt1brNeDTuoX6eJzptk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/O05lu/btscPcIFWUM/60snt1brNeDTuoX6eJzptk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FO05lu%2FbtscPcIFWUM%2F60snt1brNeDTuoX6eJzptk%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;243&quot; height=&quot;109&quot; data-origin-width=&quot;243&quot; data-origin-height=&quot;109&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CRA를 통해서 리액트 프로젝트를 생성하면 manifest.json이 생기는데, 저의 경우에는 next.js 프로젝트에서 manifest.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;해결 방법은 간단하게도 경로의 문제였습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;418&quot; data-origin-height=&quot;27&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/zm5nI/btscQniz1ye/9F71bkJ2PKdndfn9uq9IYk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/zm5nI/btscQniz1ye/9F71bkJ2PKdndfn9uq9IYk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/zm5nI/btscQniz1ye/9F71bkJ2PKdndfn9uq9IYk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fzm5nI%2FbtscQniz1ye%2F9F71bkJ2PKdndfn9uq9IYk%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;418&quot; height=&quot;27&quot; data-origin-width=&quot;418&quot; data-origin-height=&quot;27&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;메타태그를 설정해 주는 부분에 경로가 상대경로로 되어있어 루트(&quot;/&quot;)가 아닌 경로에서 해당 에러가 발생하고 있어 절대경로로 수정해 주었습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;431&quot; data-origin-height=&quot;26&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bFHXk7/btscSnIG81J/7ZcHRC9T7rbdyCfq9WoKbk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bFHXk7/btscSnIG81J/7ZcHRC9T7rbdyCfq9WoKbk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bFHXk7/btscSnIG81J/7ZcHRC9T7rbdyCfq9WoKbk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbFHXk7%2FbtscSnIG81J%2F7ZcHRC9T7rbdyCfq9WoKbk%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;431&quot; height=&quot;26&quot; data-origin-width=&quot;431&quot; data-origin-height=&quot;26&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;  &lt;b&gt;추가 포스팅&lt;/b&gt;&lt;/p&gt;
&lt;h4 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;a href=&quot;https://cocoon1787.tistory.com/873&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;b&gt;  manifest.json은 무슨 역할을 하는 파일일까?&lt;/b&gt;&lt;/a&gt;&lt;b&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;figure id=&quot;og_1682522300757&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[WEB] manifest.json은 무슨 역할을 할까?&quot; data-og-description=&quot;manifest.json은 웹 애플리케이션에 대한 메타데이터를 제공하여 웹 애플리케이션을 다운로드할 수 있도록 하는 파일입니다. 파일 내에는 아래와 같이 애플리케이션 이름, 버전 번호, 사용될 아이&quot; data-og-host=&quot;cocoon1787.tistory.com&quot; data-og-source-url=&quot;https://cocoon1787.tistory.com/873&quot; data-og-url=&quot;https://cocoon1787.tistory.com/873&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/1DJno/hySpJj8FQ6/t7K0Xf6dArXYXguslI0WPK/img.png?width=800&amp;amp;height=448&amp;amp;face=0_0_800_448,https://scrap.kakaocdn.net/dn/1UztD/hySpwrzQiK/3XhukkwHcoMUksI8UETHJ1/img.png?width=800&amp;amp;height=448&amp;amp;face=0_0_800_448,https://scrap.kakaocdn.net/dn/29YlL/hySpzV7giv/bmM2t9tAPFWQZiIoiyZDTK/img.png?width=1957&amp;amp;height=1096&amp;amp;face=0_0_1957_1096&quot;&gt;&lt;a href=&quot;https://cocoon1787.tistory.com/873&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://cocoon1787.tistory.com/873&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/1DJno/hySpJj8FQ6/t7K0Xf6dArXYXguslI0WPK/img.png?width=800&amp;amp;height=448&amp;amp;face=0_0_800_448,https://scrap.kakaocdn.net/dn/1UztD/hySpwrzQiK/3XhukkwHcoMUksI8UETHJ1/img.png?width=800&amp;amp;height=448&amp;amp;face=0_0_800_448,https://scrap.kakaocdn.net/dn/29YlL/hySpzV7giv/bmM2t9tAPFWQZiIoiyZDTK/img.png?width=1957&amp;amp;height=1096&amp;amp;face=0_0_1957_1096');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[WEB] manifest.json은 무슨 역할을 할까?&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;manifest.json은 웹 애플리케이션에 대한 메타데이터를 제공하여 웹 애플리케이션을 다운로드할 수 있도록 하는 파일입니다. 파일 내에는 아래와 같이 애플리케이션 이름, 버전 번호, 사용될 아이&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;cocoon1787.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&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 data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category> ERROR</category>
      <author>알 수 없는 사용자</author>
      <guid isPermaLink="true">https://cocoon1787.tistory.com/874</guid>
      <comments>https://cocoon1787.tistory.com/874#entry874comment</comments>
      <pubDate>Thu, 27 Apr 2023 13:00:37 +0900</pubDate>
    </item>
    <item>
      <title>[WEB] manifest.json은 무슨 역할을 할까?</title>
      <link>https://cocoon1787.tistory.com/873</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1957&quot; data-origin-height=&quot;1096&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cI38EL/btscRqMDfvI/9WBL3OozareV0Or6x7ruL1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cI38EL/btscRqMDfvI/9WBL3OozareV0Or6x7ruL1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cI38EL/btscRqMDfvI/9WBL3OozareV0Or6x7ruL1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcI38EL%2FbtscRqMDfvI%2F9WBL3OozareV0Or6x7ruL1%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;1957&quot; height=&quot;1096&quot; data-origin-width=&quot;1957&quot; data-origin-height=&quot;1096&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;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;243&quot; data-origin-height=&quot;109&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/1uhLN/btscRqTntdR/5aMN3Mks15MYx4V9VDs8N1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/1uhLN/btscRqTntdR/5aMN3Mks15MYx4V9VDs8N1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/1uhLN/btscRqTntdR/5aMN3Mks15MYx4V9VDs8N1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F1uhLN%2FbtscRqTntdR%2F5aMN3Mks15MYx4V9VDs8N1%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;243&quot; height=&quot;109&quot; data-origin-width=&quot;243&quot; data-origin-height=&quot;109&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;manifest.json은 웹&lt;span&gt;&amp;nbsp;애플리케이션에&lt;/span&gt; 대한 메타데이터를 제공하여 웹 애플리케이션을 다운로드할 수 있도록 하는 파일입니다. 파일 내에는 아래와 같이 애플리케이션 이름, 버전 번호, 사용될 아이콘 및 애플리케이션에 대한 다른 세부 정보와 같은 정보를 포함합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;manifest.json를 통해서 웹 앱도 PWA(Progressive Web App)의 기술 중 하나인 &quot;설치&quot; 기능을 제공하여 웹을 데스크톱 또는 모바일에 설치를 가능하게 하고, 모바일 앱과 유사한 경험을 지원할 수 있습니다.&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;short_name : 화면에 설치된 아이콘의 이름&lt;/li&gt;
&lt;li&gt;name : 애플리케이션의 이름&lt;/li&gt;
&lt;li&gt;strat_url : 해당 애플리케이션을 실행하면 이동하는 주소&lt;/li&gt;
&lt;li&gt;display : 표시 방법에 관련된 속성입니다.&amp;nbsp;&lt;br /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;fullscreen : 전체 화면&lt;/li&gt;
&lt;li&gt;standalone : 상단 URL bar 제거&lt;/li&gt;
&lt;li&gt;minimal-ui : &lt;span style=&quot;color: #333333; text-align: left;&quot;&gt;standalone에서 일부 UI를 추가적으로 표시&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #333333; text-align: left;&quot;&gt;browser : 일반적인 브라우저 창으로 보임(URL bar 표시)&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;orientation : 기기의 방향&lt;br /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;portrait : 세로 모드&lt;/li&gt;
&lt;li&gt;landscape : 가로 모드&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;theme_color : 애플리케이션의 시스템 UI 색을 지정&lt;/li&gt;
&lt;li&gt;background_color : 애플리케이션의 배경색&lt;/li&gt;
&lt;li&gt;icons : 애플리케이션이 사용할 아이콘 배열&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1682520835338&quot; class=&quot;json&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;{
  &quot;short_name&quot;: &quot;Todo List App&quot;,
  &quot;name&quot;: &quot;Todo List App&quot;,
  &quot;start_url&quot;: &quot;.&quot;,
  &quot;display&quot;: &quot;standalone&quot;,
  &quot;orientation&quot;: &quot;portrait&quot;,
  &quot;theme_color&quot;: &quot;#ffffff&quot;,
  &quot;background_color&quot;: &quot;#ffffff&quot;,
  &quot;icons&quot;: [
    {
      &quot;src&quot;: &quot;icons/apple-touch-icon-57x57.png&quot;,
      &quot;sizes&quot;: &quot;57x57&quot;,
      &quot;type&quot;: &quot;/image/png&quot;
    },
    {
      &quot;src&quot;: &quot;icons/apple-touch-icon-60x60.png&quot;,
      &quot;sizes&quot;: &quot;60x60&quot;,
      &quot;type&quot;: &quot;/image/png&quot;
    },
    {
      &quot;src&quot;: &quot;icons/apple-touch-icon-72x72.png&quot;,
      &quot;sizes&quot;: &quot;72x72&quot;,
      &quot;type&quot;: &quot;/image/png&quot;
    },
    {
      &quot;src&quot;: &quot;icons/apple-touch-icon-76x76.png&quot;,
      &quot;sizes&quot;: &quot;76x76&quot;,
      &quot;type&quot;: &quot;/image/png&quot;
    },
    {
      &quot;src&quot;: &quot;icons/apple-touch-icon-114x114.png&quot;,
      &quot;sizes&quot;: &quot;114x114&quot;,
      &quot;type&quot;: &quot;/image/png&quot;
    },
    {
      &quot;src&quot;: &quot;icons/apple-touch-icon-120x120.png&quot;,
      &quot;sizes&quot;: &quot;120x120&quot;,
      &quot;type&quot;: &quot;/image/png&quot;
    },
    {
      &quot;src&quot;: &quot;icons/apple-touch-icon-144x144.png&quot;,
      &quot;sizes&quot;: &quot;144x144&quot;,
      &quot;type&quot;: &quot;/image/png&quot;
    },
    {
      &quot;src&quot;: &quot;icons/apple-touch-icon-152x152.png&quot;,
      &quot;sizes&quot;: &quot;152x152&quot;,
      &quot;type&quot;: &quot;/image/png&quot;
    },
    {
      &quot;src&quot;: &quot;icons/favicon-512x512.png&quot;,
      &quot;sizes&quot;: &quot;512x512&quot;,
      &quot;type&quot;: &quot;/image/png&quot;
    },
    {
      &quot;src&quot;: &quot;icons/favicon.ico&quot;,
      &quot;sizes&quot;: &quot;64x64&quot;,
      &quot;type&quot;: &quot;/image/icon&quot;,
      &quot;purpose&quot;: &quot;any maskable&quot;
    }
  ]
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;manifest.json 파일을 추가한 웹 서비스 예시 (안드로이드)&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1485&quot; data-origin-height=&quot;855&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bB9rix/btscQWdNEwh/flrqNNMKMmkqhInctxx88k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bB9rix/btscQWdNEwh/flrqNNMKMmkqhInctxx88k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bB9rix/btscQWdNEwh/flrqNNMKMmkqhInctxx88k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbB9rix%2FbtscQWdNEwh%2FflrqNNMKMmkqhInctxx88k%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;1485&quot; height=&quot;855&quot; data-origin-width=&quot;1485&quot; data-origin-height=&quot;855&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;아이폰의 경우 사파리 앱 중앙 하단에 공유 버튼을 탭 하여 &quot;홈 화면에 추가&quot;로 아이콘 생성이 가능합니다.&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 data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category> WEB</category>
      <author>알 수 없는 사용자</author>
      <guid isPermaLink="true">https://cocoon1787.tistory.com/873</guid>
      <comments>https://cocoon1787.tistory.com/873#entry873comment</comments>
      <pubDate>Thu, 27 Apr 2023 00:17:57 +0900</pubDate>
    </item>
    <item>
      <title>[IT] 출퇴근 시간 지하철에서 틈틈이 보는 개발자 커뮤니티 '커리어리'</title>
      <link>https://cocoon1787.tistory.com/872</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1200&quot; data-origin-height=&quot;630&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/F6gwL/btr7iM1zxTV/xqOISnTQqe1VU76OH4WIAk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/F6gwL/btr7iM1zxTV/xqOISnTQqe1VU76OH4WIAk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/F6gwL/btr7iM1zxTV/xqOISnTQqe1VU76OH4WIAk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FF6gwL%2Fbtr7iM1zxTV%2FxqOISnTQqe1VU76OH4WIAk%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;1200&quot; height=&quot;630&quot; data-origin-width=&quot;1200&quot; data-origin-height=&quot;630&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;2023년 개발자 채용 혹한기 속에서도 여전히 개발자를 꿈꾸는 사람들의 수는 지속되고 있으며, 빠르게 변화하는 개발 트렌드나 Q&amp;amp;A, 채용, 사이드프로젝트, 네트워크 등등의 수요를 충족시켜 줄 커뮤니티가 많이 생겨나고 있는 것 같습니다. 그중에서도 제가 시간 날 때마다 짬짬이 보는 &lt;a href=&quot;https://careerly.co.kr/?utm_source=social&amp;amp;utm_medium=21&amp;amp;utm_campaign=49&amp;amp;utm_content=ma9pie&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;careerly&lt;/a&gt;에 관해 소개를 시켜드릴까 합니다.&lt;/p&gt;
&lt;figure id=&quot;og_1680771149245&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;커리어리 | 요즘 개발자 커뮤니티 커리어리&quot; data-og-description=&quot;개발 트렌드, Q&amp;amp;A, 탑 개발자들과의 네트워킹까지. 누구나 쉽고 간편하게 성장할 수 있도록. 요즘 개발자들의 필수 커뮤니티&quot; data-og-host=&quot;careerly.co.kr&quot; data-og-source-url=&quot;https://careerly.co.kr/?utm_source=social&amp;amp;utm_medium=21&amp;amp;utm_campaign=49&amp;amp;utm_content=ma9pie&quot; data-og-url=&quot;https://careerly.co.kr/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/79gL3/hySa4bJFWv/S2ZYkijjn7NLRn0L2qZHBK/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/cGCuh8/hyScs27Eh6/QknLEibjwxbGvd4gt0DBU0/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/dem4Cz/hySa34XfGZ/ODZuua0okdSdq8wytrNDlk/img.png?width=2061&amp;amp;height=1917&amp;amp;face=0_0_2061_1917&quot;&gt;&lt;a href=&quot;https://careerly.co.kr/?utm_source=social&amp;amp;utm_medium=21&amp;amp;utm_campaign=49&amp;amp;utm_content=ma9pie&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://careerly.co.kr/?utm_source=social&amp;amp;utm_medium=21&amp;amp;utm_campaign=49&amp;amp;utm_content=ma9pie&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/79gL3/hySa4bJFWv/S2ZYkijjn7NLRn0L2qZHBK/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/cGCuh8/hyScs27Eh6/QknLEibjwxbGvd4gt0DBU0/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/dem4Cz/hySa34XfGZ/ODZuua0okdSdq8wytrNDlk/img.png?width=2061&amp;amp;height=1917&amp;amp;face=0_0_2061_1917');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;커리어리 | 요즘 개발자 커뮤니티 커리어리&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;개발 트렌드, Q&amp;amp;A, 탑 개발자들과의 네트워킹까지. 누구나 쉽고 간편하게 성장할 수 있도록. 요즘 개발자들의 필수 커뮤니티&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;careerly.co.kr&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&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;color: #333333; text-align: start;&quot;&gt;프로그래밍 질문이나 개발자 트렌드,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;자기 계발,&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;시니어 개발자들의 피드 등등 출퇴근길이나&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;심심할 때&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;커리어리 눈팅만 해도 생각보다 많은 것을&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;알게 되었던&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;것 같습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; 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;커리어리는 개발자 커뮤니티 사이트로, &lt;span style=&quot;color: #000000;&quot;&gt;개발 트렌드부터 Q&amp;amp;A, 네트워킹까지, 누구나 쉽게 성장할 수 있도록 &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;국내외 다양한 분야의 IT기업 현직 개발자들이&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;직접 자신의 커리어 경험과 지식을 공유해 주는 서비스를 제공해 주는 사이트입니다.&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;1177&quot; data-origin-height=&quot;632&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mGOz6/btr7hTz5IM8/Fp0YPFKb3jfNqTF6u8Kiq1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mGOz6/btr7hTz5IM8/Fp0YPFKb3jfNqTF6u8Kiq1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mGOz6/btr7hTz5IM8/Fp0YPFKb3jfNqTF6u8Kiq1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmGOz6%2Fbtr7hTz5IM8%2FFp0YPFKb3jfNqTF6u8Kiq1%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;1177&quot; height=&quot;632&quot; data-origin-width=&quot;1177&quot; data-origin-height=&quot;632&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;스택오버플로우는 여전히 개발자에게서 떼려야 뗄 수 없는 개발자 필수 커뮤니티이지만, 네카라쿠배당토처럼 현재 유명한 IT 기업에 재직 중이신 개발자분들도 활동 중이시며, 시니어 개발자들의 콘텐츠 피드, 프로그래밍 Q&amp;amp;A를 할 수 있는 커리어리도 정말 유용한 서비스라고 생각이 됩니다.&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;1151&quot; data-origin-height=&quot;829&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/HlASG/btr7hQQP1Vs/ESqQAcLh8B7MfHNBSU03a0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/HlASG/btr7hQQP1Vs/ESqQAcLh8B7MfHNBSU03a0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/HlASG/btr7hQQP1Vs/ESqQAcLh8B7MfHNBSU03a0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FHlASG%2Fbtr7hQQP1Vs%2FESqQAcLh8B7MfHNBSU03a0%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;1151&quot; height=&quot;829&quot; data-origin-width=&quot;1151&quot; data-origin-height=&quot;829&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;IT업계는 5년만 지나도 기술 스택이나 트렌드가 빠르게 바뀌는 생태계이기 때문에 이러한 시장 상황에서 살아남기 위해서는 개발자들이 현재 어떠한 기술을 많이 사용하고 있고, 개발자 채용 시장 트렌드가 어떠한지 빠르게 파악할 필요가 있다고 생각합니다. 저의 경우는 &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;Frontend&lt;span&gt; &lt;/span&gt;&lt;/span&gt;개발자이기 때문에 2021년도부터 React로 개발을 시작하였지만 리액트 이전의 웹 개발은 jQuery로 했었다는 것만 알고 있고, 또 3년 혹은 5년 뒤에도 React를 대체할 언어가 올 것이라 예상하고 있습니다.&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;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/4Ubhg/btr7gjsmESs/bb0wldd0XLFfklhDVHzBE0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/4Ubhg/btr7gjsmESs/bb0wldd0XLFfklhDVHzBE0/img.png&quot; data-origin-width=&quot;1051&quot; data-origin-height=&quot;675&quot; data-is-animation=&quot;false&quot; style=&quot;width: 51.1296%; margin-right: 10px;&quot; data-widthpercent=&quot;51.73&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/4Ubhg/btr7gjsmESs/bb0wldd0XLFfklhDVHzBE0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F4Ubhg%2Fbtr7gjsmESs%2Fbb0wldd0XLFfklhDVHzBE0%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;1051&quot; height=&quot;675&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bi9QiG/btr7pUx7Xdg/BvO1Bp6bKRakWVlm8zmX61/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bi9QiG/btr7pUx7Xdg/BvO1Bp6bKRakWVlm8zmX61/img.png&quot; data-origin-width=&quot;1078&quot; data-origin-height=&quot;742&quot; data-is-animation=&quot;false&quot; data-widthpercent=&quot;48.27&quot; style=&quot;width: 47.7076%;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bi9QiG/btr7pUx7Xdg/BvO1Bp6bKRakWVlm8zmX61/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbi9QiG%2Fbtr7pUx7Xdg%2FBvO1Bp6bKRakWVlm8zmX61%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;1078&quot; height=&quot;742&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&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;특히나 제가 커리어리를 사용해 보면서 가장 좋다고 느꼈던 서비스는 대기업에서 Frontend 개발자로 재직 중이신 분들을 팔로우하고 TOP 개발자들의 실무 이야기를 읽어볼 수 있었던 점인데요..!&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1191&quot; data-origin-height=&quot;621&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bKrlgw/btr7f0NuZni/hkf7utvtq7YoyTtkKSu1kk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bKrlgw/btr7f0NuZni/hkf7utvtq7YoyTtkKSu1kk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bKrlgw/btr7f0NuZni/hkf7utvtq7YoyTtkKSu1kk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbKrlgw%2Fbtr7f0NuZni%2Fhkf7utvtq7YoyTtkKSu1kk%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;1191&quot; height=&quot;621&quot; data-origin-width=&quot;1191&quot; data-origin-height=&quot;621&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bWB9uR/btr7fnPNtA3/KfUCtshh6uWzfBJc58oQYk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bWB9uR/btr7fnPNtA3/KfUCtshh6uWzfBJc58oQYk/img.png&quot; data-origin-width=&quot;642&quot; data-origin-height=&quot;437&quot; data-is-animation=&quot;false&quot; style=&quot;width: 49.3235%; margin-right: 10px;&quot; data-widthpercent=&quot;49.9&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bWB9uR/btr7fnPNtA3/KfUCtshh6uWzfBJc58oQYk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbWB9uR%2Fbtr7fnPNtA3%2FKfUCtshh6uWzfBJc58oQYk%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;437&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eA4Rde/btr7e01dLiP/KibEow6pBdfVTdJMUnc8x1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eA4Rde/btr7e01dLiP/KibEow6pBdfVTdJMUnc8x1/img.png&quot; data-origin-width=&quot;643&quot; data-origin-height=&quot;436&quot; data-is-animation=&quot;false&quot; style=&quot;width: 49.5137%;&quot; data-widthpercent=&quot;50.1&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eA4Rde/btr7e01dLiP/KibEow6pBdfVTdJMUnc8x1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FeA4Rde%2Fbtr7e01dLiP%2FKibEow6pBdfVTdJMUnc8x1%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;643&quot; height=&quot;436&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/wcBEH/btr7fnI1ZZ8/IBvnYhSqk68k1f6CMvErP0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/wcBEH/btr7fnI1ZZ8/IBvnYhSqk68k1f6CMvErP0/img.png&quot; data-origin-width=&quot;637&quot; data-origin-height=&quot;433&quot; data-is-animation=&quot;false&quot; style=&quot;width: 49.5862%; margin-right: 10px; margin-top: 10px;&quot; data-widthpercent=&quot;50.17&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/wcBEH/btr7fnI1ZZ8/IBvnYhSqk68k1f6CMvErP0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FwcBEH%2Fbtr7fnI1ZZ8%2FIBvnYhSqk68k1f6CMvErP0%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;637&quot; height=&quot;433&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/yhG0z/btr7gh2rJrN/ulPKqmKHEgoip5HFbK3s40/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/yhG0z/btr7gh2rJrN/ulPKqmKHEgoip5HFbK3s40/img.png&quot; data-origin-width=&quot;640&quot; data-origin-height=&quot;438&quot; data-is-animation=&quot;false&quot; style=&quot;width: 49.251%; margin-top: 10px;&quot; data-widthpercent=&quot;49.83&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/yhG0z/btr7gh2rJrN/ulPKqmKHEgoip5HFbK3s40/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FyhG0z%2Fbtr7gh2rJrN%2FulPKqmKHEgoip5HFbK3s40%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;640&quot; height=&quot;438&quot;/&gt;&lt;/span&gt;&lt;/div&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;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1054&quot; data-origin-height=&quot;593&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/GljC8/btr7hSnFzLM/xzzcuNAQ5QsaLoaoeKXZ5K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/GljC8/btr7hSnFzLM/xzzcuNAQ5QsaLoaoeKXZ5K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/GljC8/btr7hSnFzLM/xzzcuNAQ5QsaLoaoeKXZ5K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FGljC8%2Fbtr7hSnFzLM%2FxzzcuNAQ5QsaLoaoeKXZ5K%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;1054&quot; height=&quot;593&quot; data-origin-width=&quot;1054&quot; data-origin-height=&quot;593&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1053&quot; data-origin-height=&quot;718&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cGkB6b/btr7mtVbrYU/5MNCQYJf2JpX1782mUCjHK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cGkB6b/btr7mtVbrYU/5MNCQYJf2JpX1782mUCjHK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cGkB6b/btr7mtVbrYU/5MNCQYJf2JpX1782mUCjHK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcGkB6b%2Fbtr7mtVbrYU%2F5MNCQYJf2JpX1782mUCjHK%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;1053&quot; height=&quot;718&quot; data-origin-width=&quot;1053&quot; data-origin-height=&quot;718&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 개발자 Q&amp;amp;A나 사이드프로젝트 탭을 둘러보고 커리어리가 개발자들의 네트워크를 구축하고 커뮤니티 역할을 잘할 수 있는 서비스라고 생각이 들었습니다. 개발을 하다가 막힐 때, 스택오버플로우나 ChatGPT로 해결이 안 되는 부분이 생길 때, 커리어에 대한 고민이 있을 때 편하게 질문을 올리고 국내 개발자들과 언어적 제약을 느끼지 않고 최적화된 네트워킹이 가능하다는 점이 장점인 것 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div style=&quot;background-color: #ffffff; color: #222222; text-align: start;&quot;&gt;- 웹 : &lt;span style=&quot;background-color: #ffffff; color: #222222; text-align: start;&quot;&gt;&lt;a href=&quot;https://careerly.co.kr/?utm_source=social&amp;amp;utm_medium=21&amp;amp;utm_campaign=49&amp;amp;utm_content=ma9pie&quot;&gt;https://careerly.co.kr/?utm_source=social&amp;amp;utm_medium=21&amp;amp;utm_campaign=49&amp;amp;utm_content=ma9pie&lt;/a&gt;&lt;/span&gt;
&lt;figure id=&quot;og_1680771444432&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;커리어리 | 요즘 개발자 커뮤니티 커리어리&quot; data-og-description=&quot;개발 트렌드, Q&amp;amp;A, 탑 개발자들과의 네트워킹까지. 누구나 쉽고 간편하게 성장할 수 있도록. 요즘 개발자들의 필수 커뮤니티&quot; data-og-host=&quot;careerly.co.kr&quot; data-og-source-url=&quot;https://careerly.co.kr/?utm_source=social&amp;amp;utm_medium=21&amp;amp;utm_campaign=49&amp;amp;utm_content=ma9pie&quot; data-og-url=&quot;https://careerly.co.kr/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/79gL3/hySa4bJFWv/S2ZYkijjn7NLRn0L2qZHBK/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/cGCuh8/hyScs27Eh6/QknLEibjwxbGvd4gt0DBU0/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/dem4Cz/hySa34XfGZ/ODZuua0okdSdq8wytrNDlk/img.png?width=2061&amp;amp;height=1917&amp;amp;face=0_0_2061_1917&quot;&gt;&lt;a href=&quot;https://careerly.co.kr/?utm_source=social&amp;amp;utm_medium=21&amp;amp;utm_campaign=49&amp;amp;utm_content=ma9pie&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://careerly.co.kr/?utm_source=social&amp;amp;utm_medium=21&amp;amp;utm_campaign=49&amp;amp;utm_content=ma9pie&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/79gL3/hySa4bJFWv/S2ZYkijjn7NLRn0L2qZHBK/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/cGCuh8/hyScs27Eh6/QknLEibjwxbGvd4gt0DBU0/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/dem4Cz/hySa34XfGZ/ODZuua0okdSdq8wytrNDlk/img.png?width=2061&amp;amp;height=1917&amp;amp;face=0_0_2061_1917');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;커리어리 | 요즘 개발자 커뮤니티 커리어리&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;개발 트렌드, Q&amp;amp;A, 탑 개발자들과의 네트워킹까지. 누구나 쉽고 간편하게 성장할 수 있도록. 요즘 개발자들의 필수 커뮤니티&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;careerly.co.kr&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div style=&quot;background-color: #ffffff; color: #222222; text-align: start;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;background-color: #ffffff; color: #222222; text-align: start;&quot;&gt;- 앱 :&lt;span style=&quot;background-color: #f5f6f8; color: #000000;&quot;&gt;&lt;/span&gt;&lt;a href=&quot;https://careerly.onelink.me/Gbs9/ma9pie&quot;&gt;https://careerly.onelink.me/Gbs9/ma9pie&lt;/a&gt;
&lt;figure id=&quot;og_1680771337255&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;커리어리 | 요즘 개발자 커뮤니티 커리어리&quot; data-og-description=&quot;개발 트렌드, Q&amp;amp;A, 탑 개발자들과의 네트워킹까지. 누구나 쉽고 간편하게 성장할 수 있도록. 요즘 개발자들의 필수 커뮤니티&quot; data-og-host=&quot;careerly.onelink.me&quot; data-og-source-url=&quot;https://careerly.onelink.me/Gbs9/ma9pie&quot; data-og-url=&quot;https://careerly.onelink.me/af-preview/facebook?url=https%3A%2F%2Fcareerly.co.kr%2F%3Futm_source%3Dsocial%26utm_medium%3Dpost%26utm_campaign%3DBlog_UA_AppInstall_Engineer_All_Web%26utm_content%3DAll_Blog_ma9pie&amp;amp;ios_dp=careerly%3A%2F%2Fcareerly.co.kr%3Faf_deeplink%3Dtrue%26af_dp%3Dcareerly%253A%252F%252Fcareerly.co.kr%26af_generate_clk%3Dtrue%26af_original_url%3Dhttps%253A%252F%252Fcareerly.onelink.me%252FGbs9%252Fma9pie%26af_xp%3Dsocial%26c%3Dma9pie%26campaign%3Dma9pie%26media_source%3DBlog%26pid%3DBlog%26shortlink%3Dma9pie%26source_caller%3Dui&amp;amp;android_dp=careerly%3A%2F%2Fcareerly.co.kr%3Faf_deeplink%3Dtrue%26af_dp%3Dcareerly%253A%252F%252Fcareerly.co.kr%26af_generate_clk%3Dtrue%26af_original_url%3Dhttps%253A%252F%252Fcareerly.onelink.me%252FGbs9%252Fma9pie%26af_xp%3Dsocial%26c%3Dma9pie%26campaign%3Dma9pie%26media_source%3DBlog%26pid%3DBlog%26shortlink%3Dma9pie%26source_caller%3Dui&amp;amp;ios_store_id=1474321863&amp;amp;android_store_id=com.publy.news&amp;amp;af_robot_sig=4fc18e5cfa62f0bf8e4fd5fd27240adeed9202cd4aea37de068fcd2d38e605df&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bOQhi5/hyScx4qqA7/WKt9eCk4ldjE1UskFmdYKk/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630&quot;&gt;&lt;a href=&quot;https://careerly.onelink.me/Gbs9/ma9pie&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://careerly.onelink.me/Gbs9/ma9pie&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bOQhi5/hyScx4qqA7/WKt9eCk4ldjE1UskFmdYKk/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;커리어리 | 요즘 개발자 커뮤니티 커리어리&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;개발 트렌드, Q&amp;amp;A, 탑 개발자들과의 네트워킹까지. 누구나 쉽고 간편하게 성장할 수 있도록. 요즘 개발자들의 필수 커뮤니티&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;careerly.onelink.me&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;div style=&quot;background-color: #ffffff; color: #222222; text-align: start;&quot;&gt;&amp;nbsp;&lt;/div&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 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 data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category> IT</category>
      <author>알 수 없는 사용자</author>
      <guid isPermaLink="true">https://cocoon1787.tistory.com/872</guid>
      <comments>https://cocoon1787.tistory.com/872#entry872comment</comments>
      <pubDate>Sat, 1 Apr 2023 22:03:36 +0900</pubDate>
    </item>
    <item>
      <title>[VSCODE] typescript 파일에서 빨간줄 에러가 도배되는 현상</title>
      <link>https://cocoon1787.tistory.com/871</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;597&quot; data-origin-height=&quot;432&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b95hXY/btr5dSiVMTo/FX9aweBA3YN9kx365NEVR0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b95hXY/btr5dSiVMTo/FX9aweBA3YN9kx365NEVR0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b95hXY/btr5dSiVMTo/FX9aweBA3YN9kx365NEVR0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb95hXY%2Fbtr5dSiVMTo%2FFX9aweBA3YN9kx365NEVR0%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;597&quot; height=&quot;432&quot; data-origin-width=&quot;597&quot; data-origin-height=&quot;432&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;요즘 typescript를 공부 중인데 다른 레포를 클론 후 분석하려고 할 때 typescript파일을 열면 바로 빨간 줄 에러가 도배되는 현상이 있었습니다. 해당 문제로 해결 방법이 없나 마음속으로 불편했었는데 오늘 드디어 해결법을 찾게 되었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 문제의 원인은 오류라기보다는 typescript 버전에 따른 문제였습니다.&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;F1을 누른 후 typescript 검색&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;655&quot; data-origin-height=&quot;177&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/1y7vX/btr45knljha/ECxBWWkvmdjaoEjBlAgwQ0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/1y7vX/btr45knljha/ECxBWWkvmdjaoEjBlAgwQ0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/1y7vX/btr45knljha/ECxBWWkvmdjaoEjBlAgwQ0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F1y7vX%2Fbtr45knljha%2FECxBWWkvmdjaoEjBlAgwQ0%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;655&quot; height=&quot;177&quot; data-origin-width=&quot;655&quot; data-origin-height=&quot;177&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Typescript 버전 선택 클릭&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 alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;632&quot; data-origin-height=&quot;235&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/csdSOl/btr5defEHZh/OHHYsLNIAoUQ6Vh2krBxR1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/csdSOl/btr5defEHZh/OHHYsLNIAoUQ6Vh2krBxR1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/csdSOl/btr5defEHZh/OHHYsLNIAoUQ6Vh2krBxR1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcsdSOl%2Fbtr5defEHZh%2FOHHYsLNIAoUQ6Vh2krBxR1%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;632&quot; height=&quot;235&quot; data-origin-width=&quot;632&quot; data-origin-height=&quot;235&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;확인해보면 VS Code 버전 사용이 선택되어 있습니다.&lt;br /&gt;이 부분에서 작업 영역 버전 사용을 클릭하여 해당 작업 영역의 node_modules typescript 버전과 맞춰줍니다.&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> IT</category>
      <author>알 수 없는 사용자</author>
      <guid isPermaLink="true">https://cocoon1787.tistory.com/871</guid>
      <comments>https://cocoon1787.tistory.com/871#entry871comment</comments>
      <pubDate>Wed, 22 Mar 2023 00:09:00 +0900</pubDate>
    </item>
    <item>
      <title>요즘 핫한 ChatGPT 사용후기 (feat. Todo App 만들기)</title>
      <link>https://cocoon1787.tistory.com/870</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1080&quot; data-origin-height=&quot;675&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c8uiQI/btr0eT19YQA/j3MYCwbNj2X4PA5awuq9yk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c8uiQI/btr0eT19YQA/j3MYCwbNj2X4PA5awuq9yk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c8uiQI/btr0eT19YQA/j3MYCwbNj2X4PA5awuq9yk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc8uiQI%2Fbtr0eT19YQA%2Fj3MYCwbNj2X4PA5awuq9yk%2Fimg.jpg&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;1080&quot; height=&quot;675&quot; data-origin-width=&quot;1080&quot; data-origin-height=&quot;675&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;요즘 가장 핫한 기술인 대화형 인공지능(AI) 서비스 ChatGPT를 소개해드리려고 합니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;  What is ChatGPT?&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ChatGPT는 GPT(Generative Pre-trained Transformer)라는 대화에 최적화되어 훈련된 언어 모델을 기반으로, 인공지능 회사인 Open AI에서 출시한 AI기반의 챗봇 서비스입니다. ChatGPT의 경우 질문에 대한 이해력과, 문장력이 뛰어나며 마치 사람과 대화를 나누듯 원하는 정보를 얻을 수 있습니다.&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; &amp;zwj;  &lt;b&gt;How to use&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://chat.openai.com/auth/login&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://chat.openai.com/auth/login&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;733&quot; data-origin-height=&quot;296&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cjHV2d/btr0fsQCKpT/UBzKkAEsExk1r150b7QbnK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cjHV2d/btr0fsQCKpT/UBzKkAEsExk1r150b7QbnK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cjHV2d/btr0fsQCKpT/UBzKkAEsExk1r150b7QbnK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcjHV2d%2Fbtr0fsQCKpT%2FUBzKkAEsExk1r150b7QbnK%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;733&quot; height=&quot;296&quot; data-origin-width=&quot;733&quot; data-origin-height=&quot;296&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재는 ChatGPT 베타버전이 무료로 공개되어 있기 때문에 무료로 사용이 가능하지만 곧 유료 서비스로 전환될 예정이기 때문에 유료로 전환되기 전에 한번 체험해 보시는 것을 추천드립니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용방법은 위의 URL로 접속하셔서 회원가입을 하시면 바로 사용할 수 있습니다.&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-origin-width=&quot;1199&quot; data-origin-height=&quot;655&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bjCh2s/btr0e9jtAaX/gBlqbJIRI6MeliQKMNzr90/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bjCh2s/btr0e9jtAaX/gBlqbJIRI6MeliQKMNzr90/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bjCh2s/btr0e9jtAaX/gBlqbJIRI6MeliQKMNzr90/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbjCh2s%2Fbtr0e9jtAaX%2FgBlqbJIRI6MeliQKMNzr90%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;1199&quot; height=&quot;655&quot; data-origin-width=&quot;1199&quot; data-origin-height=&quot;655&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;회원가입 후 ChatGPT 홈으로 이동하시면 ChatGPT의 질문 예제, 할 수 있는 일, 제한사항, 질문 검색창이 있습니다.&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;910&quot; data-origin-height=&quot;500&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/GFJ4G/btr0jiTvCEw/Ee8U4vfzkffVVdIhd4ODCk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/GFJ4G/btr0jiTvCEw/Ee8U4vfzkffVVdIhd4ODCk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/GFJ4G/btr0jiTvCEw/Ee8U4vfzkffVVdIhd4ODCk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FGFJ4G%2Fbtr0jiTvCEw%2FEe8U4vfzkffVVdIhd4ODCk%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;910&quot; height=&quot;500&quot; data-origin-width=&quot;910&quot; data-origin-height=&quot;500&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;질문을 검색하시면 위와 같이 ChatGPT가 딥러닝 기술을 통해 답변을 해줍니다.&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;  Make&amp;nbsp;a&amp;nbsp;TodoList&amp;nbsp;App&amp;nbsp;with&amp;nbsp;React&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실 이 글을 포스팅하는 이유는 ChatGPT로도 코딩이 가능하다는 점을 보여드리기 위해서 작성하게 되었습니다. 프론트엔드 개발자로서 &quot;과연 인공지능 챗봇에서 만들어진 코드가 실제로 동작할까?&quot;라는 의구심이 들었고 ChatGPT로 TodoList 만드는 법에 대해 질문을 하였고 나온 답변을 토대로 코드를 실행해 보았습니다.&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;828&quot; data-origin-height=&quot;1531&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bKZbsZ/btr0imaGDIu/6ZdoM519eihDTJvzKHqpg1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bKZbsZ/btr0imaGDIu/6ZdoM519eihDTJvzKHqpg1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bKZbsZ/btr0imaGDIu/6ZdoM519eihDTJvzKHqpg1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbKZbsZ%2Fbtr0imaGDIu%2F6ZdoM519eihDTJvzKHqpg1%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;828&quot; height=&quot;1531&quot; data-origin-width=&quot;828&quot; data-origin-height=&quot;1531&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;821&quot; data-origin-height=&quot;1519&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/DWZxP/btr0glcqtW1/GCNil6ce0oo6Fv0tgEkgeK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/DWZxP/btr0glcqtW1/GCNil6ce0oo6Fv0tgEkgeK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/DWZxP/btr0glcqtW1/GCNil6ce0oo6Fv0tgEkgeK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FDWZxP%2Fbtr0glcqtW1%2FGCNil6ce0oo6Fv0tgEkgeK%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;821&quot; height=&quot;1519&quot; data-origin-width=&quot;821&quot; data-origin-height=&quot;1519&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;823&quot; data-origin-height=&quot;620&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/EGlzv/btr0il3TvZX/NlzANCLHy9saGCnKjOATTk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/EGlzv/btr0il3TvZX/NlzANCLHy9saGCnKjOATTk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/EGlzv/btr0il3TvZX/NlzANCLHy9saGCnKjOATTk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FEGlzv%2Fbtr0il3TvZX%2FNlzANCLHy9saGCnKjOATTk%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;823&quot; height=&quot;620&quot; data-origin-width=&quot;823&quot; data-origin-height=&quot;620&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;실제로 프로젝트를 생성 후 ChatGPT에서 나온 답변대로 src 폴더에 TodoList.js, TodoList.css를 추가하고 App.js를 수정하였습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;231&quot; data-origin-height=&quot;479&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bAkZ5f/btr0aRju5TJ/6ecGCb1SVr71Xl5KRGhYiK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bAkZ5f/btr0aRju5TJ/6ecGCb1SVr71Xl5KRGhYiK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bAkZ5f/btr0aRju5TJ/6ecGCb1SVr71Xl5KRGhYiK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbAkZ5f%2Fbtr0aRju5TJ%2F6ecGCb1SVr71Xl5KRGhYiK%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;231&quot; height=&quot;479&quot; data-origin-width=&quot;231&quot; data-origin-height=&quot;479&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre id=&quot;code_1677017882673&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// App.js
import React from 'react';
import TodoList from './TodoList';

function App() {
  return (
    &amp;lt;div&amp;gt;
      &amp;lt;TodoList /&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}

export default App;&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1677017852965&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// TodoList.js
import React, { useState } from 'react';
import './TodoList.css';

function TodoList() {
  const [tasks, setTasks] = useState([]);
  const [newTask, setNewTask] = useState('');

  const handleNewTaskChange = (event) =&amp;gt; {
    setNewTask(event.target.value);
  };

  const handleAddTask = (event) =&amp;gt; {
    event.preventDefault();
    if (newTask.trim() !== '') {
      setTasks([...tasks, { text: newTask, completed: false }]);
      setNewTask('');
    }
  };

  const handleToggleCompleted = (index) =&amp;gt; {
    const newTasks = [...tasks];
    newTasks[index].completed = !newTasks[index].completed;
    setTasks(newTasks);
  };

  return (
    &amp;lt;div className=&quot;TodoList&quot;&amp;gt;
      &amp;lt;h1&amp;gt;Todo List&amp;lt;/h1&amp;gt;
      &amp;lt;form onSubmit={handleAddTask}&amp;gt;
        &amp;lt;input
          type=&quot;text&quot;
          placeholder=&quot;New task...&quot;
          value={newTask}
          onChange={handleNewTaskChange}
        /&amp;gt;
        &amp;lt;button type=&quot;submit&quot;&amp;gt;Add&amp;lt;/button&amp;gt;
      &amp;lt;/form&amp;gt;
      &amp;lt;ul&amp;gt;
        {tasks.map((task, index) =&amp;gt; (
          &amp;lt;li key={index}&amp;gt;
            &amp;lt;label className={task.completed ? 'completed' : ''}&amp;gt;
              &amp;lt;input
                type=&quot;checkbox&quot;
                checked={task.completed}
                onChange={() =&amp;gt; handleToggleCompleted(index)}
              /&amp;gt;
              {task.text}
            &amp;lt;/label&amp;gt;
          &amp;lt;/li&amp;gt;
        ))}
      &amp;lt;/ul&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}

export default TodoList;&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1677017863392&quot; class=&quot;css&quot; data-ke-language=&quot;css&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// TodoList.css
.TodoList {
  max-width: 600px;
  margin: 0 auto;
  padding: 20px;
  border: 1px solid #ddd;
  border-radius: 5px;
}

h1 {
  margin-top: 0;
}

form {
  display: flex;
  margin-bottom: 10px;
}

input[type=&quot;text&quot;] {
  flex: 1;
  padding: 5px;
  font-size: 16px;
  border: 1px solid #ddd;
  border-radius: 3px;
}

button {
  padding: 5px 10px;
  font-size: 16px;
  background-color: #007bff;
  color: #fff;
  border: none;
  border-radius: 3px;
  cursor: pointer;
}

ul {
  list-style: none;
  padding: 0;
  margin: 0;
}

li {
  display: flex;
  align-items: center;
  margin-bottom: 10px;
}

label {
  display: flex;
  align-items: center;
  flex: 1;
  font-size: 16px;
  cursor: pointer;
}

label.completed {
  text-decoration: line-through;
}

input[type=&quot;checkbox&quot;] {
  margin-right: 10px;
}&lt;/code&gt;&lt;/pre&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;  npm start&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;786&quot; data-origin-height=&quot;479&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/NTC2q/btr0gk5BiDW/QKVyC5Rhm884cBRgHI1Cp1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/NTC2q/btr0gk5BiDW/QKVyC5Rhm884cBRgHI1Cp1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/NTC2q/btr0gk5BiDW/QKVyC5Rhm884cBRgHI1Cp1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FNTC2q%2Fbtr0gk5BiDW%2FQKVyC5Rhm884cBRgHI1Cp1%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;786&quot; height=&quot;479&quot; data-origin-width=&quot;786&quot; data-origin-height=&quot;479&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;786&quot; data-origin-height=&quot;479&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/UZipp/btr0dkTkwJX/15gjJn473RkvzXeEopH8OK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/UZipp/btr0dkTkwJX/15gjJn473RkvzXeEopH8OK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/UZipp/btr0dkTkwJX/15gjJn473RkvzXeEopH8OK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FUZipp%2Fbtr0dkTkwJX%2F15gjJn473RkvzXeEopH8OK%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;786&quot; height=&quot;479&quot; data-origin-width=&quot;786&quot; data-origin-height=&quot;479&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;786&quot; data-origin-height=&quot;479&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bkp9A5/btr0frKYd4n/1dsiSf9XlhdtE4l7eewYWk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bkp9A5/btr0frKYd4n/1dsiSf9XlhdtE4l7eewYWk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bkp9A5/btr0frKYd4n/1dsiSf9XlhdtE4l7eewYWk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbkp9A5%2Fbtr0frKYd4n%2F1dsiSf9XlhdtE4l7eewYWk%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;786&quot; height=&quot;479&quot; data-origin-width=&quot;786&quot; data-origin-height=&quot;479&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;ChatGPT로 간단한 Todo List App이 완성되었습니다. 진짜로 코드가 돌아가서 많이 신기했고, 질문에 따라 Todo List App 개발방법에 대해 조금씩 다른 답변을 해주는 것 같습니다.&amp;nbsp; 실사용은 무리가 있겠지만 React를 시작한 지 얼마 안 되었거나 Todo List 작동 원리에 대해 공부를 하신다면 꽤나 도움이 될만한 코드인 것 같습니다.&amp;nbsp;&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;</description>
      <category> IT</category>
      <author>알 수 없는 사용자</author>
      <guid isPermaLink="true">https://cocoon1787.tistory.com/870</guid>
      <comments>https://cocoon1787.tistory.com/870#entry870comment</comments>
      <pubDate>Wed, 22 Feb 2023 12:00:21 +0900</pubDate>
    </item>
    <item>
      <title>프론트엔드 기술 면접 질문 리스트 모음</title>
      <link>https://cocoon1787.tistory.com/869</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1912&quot; data-origin-height=&quot;930&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c1mmCT/btrXn5YBJX7/edfKnDJ90cmWgZhiIFlw8K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c1mmCT/btrXn5YBJX7/edfKnDJ90cmWgZhiIFlw8K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c1mmCT/btrXn5YBJX7/edfKnDJ90cmWgZhiIFlw8K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc1mmCT%2FbtrXn5YBJX7%2FedfKnDJ90cmWgZhiIFlw8K%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;1912&quot; height=&quot;930&quot; data-origin-width=&quot;1912&quot; data-origin-height=&quot;930&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;구글, 티스토리, 깃헙 등등 프론트엔드 면접에서 자주 물어보는 질문 자료들을 직접 정리하여 만든 사이트입니다. &lt;/b&gt;&lt;br /&gt;&lt;b&gt;PWA(Progressive&amp;nbsp;Web&amp;nbsp;App)를&amp;nbsp;적용하여&amp;nbsp;반응형&amp;nbsp;모바일&amp;nbsp;웹앱으로&amp;nbsp;개발을&amp;nbsp;하였고,&amp;nbsp;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;모바일에서&amp;nbsp;앱을&amp;nbsp;설치하여&amp;nbsp;사용할&amp;nbsp;수&amp;nbsp;있습니다.&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;프레임워크는 Next.js, React 최신버전 18.2.0, 스타일링은 Styled component 라이브러리인 Emotion을 사용하여 프로젝트를 개발하였고, Vercel로 배포하고 있습니다.&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;  사이트 링크&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://frontend-interview-question.vercel.app/&quot;&gt;https://frontend-interview-question.vercel.app/&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1675003353491&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;프론트엔드 면접질문&quot; data-og-description=&quot;기존 클래스형 컴포넌트의 Lifecycle method(componentDidMount, componentDidUpdate, componentWillUnmount)을 대체하는 hook으로, 컴포넌트가 마운트, 업데이트, 언마운트될 때 특정 작업을 실행할 수 있습니다. useEffec&quot; data-og-host=&quot;frontend-interview-question.vercel.app&quot; data-og-source-url=&quot;https://frontend-interview-question.vercel.app/&quot; data-og-url=&quot;https://frontend-interview-question.vercel.app/&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://frontend-interview-question.vercel.app/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://frontend-interview-question.vercel.app/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;프론트엔드 면접질문&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;기존 클래스형 컴포넌트의 Lifecycle method(componentDidMount, componentDidUpdate, componentWillUnmount)을 대체하는 hook으로, 컴포넌트가 마운트, 업데이트, 언마운트될 때 특정 작업을 실행할 수 있습니다. useEffec&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;frontend-interview-question.vercel.app&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;  깃헙 링크&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/ma9pie/frontend-interview&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://github.com/ma9pie/frontend-interview&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1675003529739&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;GitHub - ma9pie/frontend-interview&quot; data-og-description=&quot;Contribute to ma9pie/frontend-interview development by creating an account on GitHub.&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/ma9pie/frontend-interview&quot; data-og-url=&quot;https://github.com/ma9pie/frontend-interview&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/orThL/hyRq10D34B/kKrqrnvRkI6M4l90EOA2K0/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/ma9pie/frontend-interview&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/ma9pie/frontend-interview&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/orThL/hyRq10D34B/kKrqrnvRkI6M4l90EOA2K0/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;GitHub - ma9pie/frontend-interview&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Contribute to ma9pie/frontend-interview development by creating an account on GitHub.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;  모바일 Install (Android)&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cqn13I/btrXqsZNAFJ/IA95pHab7eXmrMu1kcFzxK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cqn13I/btrXqsZNAFJ/IA95pHab7eXmrMu1kcFzxK/img.jpg&quot; width=&quot;30%&quot; height=&quot;30%/&quot; data-origin-width=&quot;540&quot; data-origin-height=&quot;1320&quot; data-is-animation=&quot;false&quot; style=&quot;width: 32.5581%; margin-right: 10px;&quot; data-widthpercent=&quot;33.33&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cqn13I/btrXqsZNAFJ/IA95pHab7eXmrMu1kcFzxK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcqn13I%2FbtrXqsZNAFJ%2FIA95pHab7eXmrMu1kcFzxK%2Fimg.jpg&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;540&quot; height=&quot;1320&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cU7a2D/btrXnjpuN8l/CKn7pin3yLWnvUkWkzf5g1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cU7a2D/btrXnjpuN8l/CKn7pin3yLWnvUkWkzf5g1/img.jpg&quot; width=&quot;30%&quot; height=&quot;30%/&quot; data-origin-width=&quot;540&quot; data-origin-height=&quot;1320&quot; data-is-animation=&quot;false&quot; style=&quot;width: 32.5581%; margin-right: 10px;&quot; data-widthpercent=&quot;33.33&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cU7a2D/btrXnjpuN8l/CKn7pin3yLWnvUkWkzf5g1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcU7a2D%2FbtrXnjpuN8l%2FCKn7pin3yLWnvUkWkzf5g1%2Fimg.jpg&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;540&quot; height=&quot;1320&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/WvvTS/btrXwihNPtM/Rwe5qMBObKOQQ9FvFyqSRk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/WvvTS/btrXwihNPtM/Rwe5qMBObKOQQ9FvFyqSRk/img.jpg&quot; width=&quot;30%&quot; height=&quot;30%/&quot; data-origin-width=&quot;540&quot; data-origin-height=&quot;1320&quot; data-is-animation=&quot;false&quot; style=&quot;width: 32.5581%;&quot; data-widthpercent=&quot;33.34&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/WvvTS/btrXwihNPtM/Rwe5qMBObKOQQ9FvFyqSRk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FWvvTS%2FbtrXwihNPtM%2FRwe5qMBObKOQQ9FvFyqSRk%2Fimg.jpg&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;540&quot; height=&quot;1320&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;우측 상단 설정(점 3개) 클릭 후 홈 화면에 추가 터치&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&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/WNaFH/btrXo4x7XUd/OAR18oYYt4IKbYJq6EIKUK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/WNaFH/btrXo4x7XUd/OAR18oYYt4IKbYJq6EIKUK/img.jpg&quot; width=&quot;30%&quot; height=&quot;30%/&quot; data-origin-width=&quot;540&quot; data-origin-height=&quot;1320&quot; data-is-animation=&quot;false&quot; style=&quot;width: 31.2442%; margin-right: 10px;&quot; data-widthpercent=&quot;31.99&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/WNaFH/btrXo4x7XUd/OAR18oYYt4IKbYJq6EIKUK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FWNaFH%2FbtrXo4x7XUd%2FOAR18oYYt4IKbYJq6EIKUK%2Fimg.jpg&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;540&quot; height=&quot;1320&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/wD4OC/btrXnIJln3c/ddaxk5R33DmsAZwzulkzjK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/wD4OC/btrXnIJln3c/ddaxk5R33DmsAZwzulkzjK/img.jpg&quot; width=&quot;30%&quot; height=&quot;30%/&quot; data-origin-width=&quot;540&quot; data-origin-height=&quot;1320&quot; data-is-animation=&quot;false&quot; style=&quot;width: 31.2442%; margin-right: 10px;&quot; data-widthpercent=&quot;31.99&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/wD4OC/btrXnIJln3c/ddaxk5R33DmsAZwzulkzjK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FwD4OC%2FbtrXnIJln3c%2Fddaxk5R33DmsAZwzulkzjK%2Fimg.jpg&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;540&quot; height=&quot;1320&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/czAtGu/btrXoDOi8SG/MfZtQ0SBrsPKPeAWDX94Ok/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/czAtGu/btrXoDOi8SG/MfZtQ0SBrsPKPeAWDX94Ok/img.png&quot; data-origin-width=&quot;381&quot; data-origin-height=&quot;827&quot; data-is-animation=&quot;false&quot; style=&quot;width: 35.186%;&quot; data-widthpercent=&quot;36.02&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/czAtGu/btrXoDOi8SG/MfZtQ0SBrsPKPeAWDX94Ok/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FczAtGu%2FbtrXoDOi8SG%2FMfZtQ0SBrsPKPeAWDX94Ok%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;381&quot; height=&quot;827&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;홈 화면에 추가 후 서비스 이용&lt;/figcaption&gt;
&lt;/figure&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;b&gt;안드로이드의 경우 크롬에서 우측 상단 점 3개 표시를 클릭하여 &quot;홈 화면에 추가&quot; 클릭&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;사파리의 경우 사파리 앱 중앙 하단에 공유 버튼을 탭 하여 &quot;홈 화면에 추가&quot; 클릭&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;✨업데이트 내역&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;2023-02-18
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;코드 리팩토링 및 검색 기능 추가&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/49Uxk/btrZKx5SKFc/LGzH9FRZ2NiZKyu3wnhky1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/49Uxk/btrZKx5SKFc/LGzH9FRZ2NiZKyu3wnhky1/img.png&quot; width=&quot;30%&quot; height=&quot;30%/&quot; data-origin-width=&quot;566&quot; data-origin-height=&quot;1269&quot; data-is-animation=&quot;false&quot; style=&quot;width: 32.6199%; margin-right: 10px;&quot; data-widthpercent=&quot;33.43&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/49Uxk/btrZKx5SKFc/LGzH9FRZ2NiZKyu3wnhky1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F49Uxk%2FbtrZKx5SKFc%2FLGzH9FRZ2NiZKyu3wnhky1%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;566&quot; height=&quot;1269&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bj1kPs/btrZKxSmM39/Sf7RS4NrIYJkgE1TG8CJSk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bj1kPs/btrZKxSmM39/Sf7RS4NrIYJkgE1TG8CJSk/img.png&quot; width=&quot;30%&quot; height=&quot;30%/&quot; data-origin-width=&quot;566&quot; data-origin-height=&quot;1274&quot; data-is-animation=&quot;false&quot; style=&quot;width: 32.4919%; margin-right: 10px;&quot; data-widthpercent=&quot;33.3&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bj1kPs/btrZKxSmM39/Sf7RS4NrIYJkgE1TG8CJSk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbj1kPs%2FbtrZKxSmM39%2FSf7RS4NrIYJkgE1TG8CJSk%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;566&quot; height=&quot;1274&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bzNhzP/btrZNvsIong/JvFAmX7xVJo2J2K8eeWGA1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bzNhzP/btrZNvsIong/JvFAmX7xVJo2J2K8eeWGA1/img.png&quot; width=&quot;30%&quot; height=&quot;30%/&quot; data-origin-width=&quot;567&quot; data-origin-height=&quot;1277&quot; data-is-animation=&quot;false&quot; style=&quot;width: 32.4728%;&quot; data-widthpercent=&quot;33.27&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bzNhzP/btrZNvsIong/JvFAmX7xVJo2J2K8eeWGA1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbzNhzP%2FbtrZNvsIong%2FJvFAmX7xVJo2J2K8eeWGA1%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;567&quot; height=&quot;1277&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt; &amp;nbsp;목록 리스트&lt;/b&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;CS&lt;/b&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;객체 지향 프로그래밍에 대해 설명해주세요.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;프로세스와 스레드의 차이에 대해 설명해주세요.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;멀티 프로세스와 멀티 스레드의 차이에 대해 설명해주세요.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Stack과 Queue의 차이에 대해 설명해주세요.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;List, Map, Set의 차이점을 설명해주세요.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;라이브러리와 프레임워크의 차이점을 설명해주세요.&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;JavaScript&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Sync와 Async의 차이점을 설명해주세요.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Blocking과 Non-Blocking의 차이를 설명해주세요.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;콜백함수에 대해 설명해주세요.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;콜백지옥의 의미와 콜백지옥을 해결하는 방법을 설명해주세요.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Promise와 Async, Await의 차이를 설명해주세요.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;map과 forEach의 차이를 설명해주세요.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;var, let, const의 차이를 설명해주세요.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;메서드 체이닝에 대해 설명해주세요.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;일반 함수와 화살표 함수의 차이&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;this의 의미를 설명해주세요.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;함수 선언형과 함수 표현식의 차이를 설명해주세요.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;호이스팅에 대해 설명해주세요.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;이벤트 버블링과 이벤트 캡처링에 대해 설명해주세요.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;이벤트 전파와 이벤트 위임에 대해 설명해주세요.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;클로져에 대해 설명해주세요.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;렉시컬 스코프에 대해 설명해주세요.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;스코프와 스코프 체인에 대해 설명해주세요.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;실행 컨텍스트에 대해 설명해주세요.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;프로토타입과 프로토타입 체인에 대해 설명해주세요.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;깊은복사와 얕은복사의 차이점을 설명해주세요.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;구조 분해 할당(destructuring) 대해 설명해주세요.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;spread 문법과 rest 문법의 차이에 대해 설명해주세요.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;ES6에서 생긴 큰 변화들에 대해 설명해주세요.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Ajax에 대해 설명해주세요.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;import와 require의 차이점에 대해 설명해주세요.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;npm에 대해 설명해주세요.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;package.json과 package-lock.json의 역할에 대해 설명해주세요.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;typescript를 쓰는 이유에 대해 설명해주세요.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;null, undefined, undeclared, NaN에 대해 설명해주세요.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;자바스크립트 데이터 타입에 대해 설명해주세요.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;mutable과 immutable에 대해 설명해주세요.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;throttle과 debounce에 대해 설명해주세요.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;iterable, iterator, generator에 대해 설명해주세요.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;자바스크립트 동작 원리에 대해 설명해주세요.&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;React&lt;/b&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;DOM에 대해 설명해주세요.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Virtual DOM에 대해 설명해주세요.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;클래스형 컴포넌트와 함수형 컴포넌트의 차이를 설명해주세요.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;React의 장점과 단점을 설명해주세요.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;JSX에 대해 설명해주세요.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;브라우저는 JSX 파일을 읽을 수 있나요?&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;재조정(Reconciliation) 개념에 대해서 설명해주세요.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;state와 props의 차이를 설명해주세요.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;자식 컴포넌트에서 props를 변경할 수 있나요?&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;React Hooks에 대해 설명해주세요.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;React Lifecycle에 대해 설명해주세요.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;useState에 대해 설명해주세요.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;useEffect에 대해 설명해주세요.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;useEffect와 useLayoutEffect의 차이 대해 설명해주세요.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;state를 직접변경하지 않고 setState를 사용하는 이유를 설명해주세요.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;React rendering 성능을 향상시키기 위한 방법들을 설명해주세요.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Props drilling의 개념과 Props drilling을 피하는 방법에 대해 설명해주세요.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;전역 상태 관리 방법에 대해 설명해주세요.&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;Frontend&lt;/b&gt;&lt;/p&gt;
&lt;div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;브라우저 주소창에 google을 입력하면 발생하는 일을 설명해주세요.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;브라우저 렌더링 과정을 설명해주세요.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;DNS에 대해 설명해주세요.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;REST API에 대해 설명해주세요.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Webpack, Babel, Polyfill에 대해 설명해주세요.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;SPA, CSR, SSR의 차이를 설명해주세요.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;CORS가 무엇인지, 해결해 본 경험이 있으신지 말씀해주세요.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;b&gt;Sementic Markup에 대해 설명해주세요.&lt;/b&gt;&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;HTML에서의 attributes와 properties의 차이점을 설명해주세요.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;로컬 스토리지, 세션 스토리지, 쿠키에 대해 설명해주세요.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Event loop와 Task queue에 대해 설명해주세요.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;MVC, MVVM 패턴에 대해 설명해주세요.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;HTTP와 HTTPS의 차이점을 설명해주세요.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;페이지 로드 시간을 줄이는 방법들에 대해서 설명해주세요.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;테스트 코드를 작성하신 경험이 있으신가요?&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;웹 서비스 배포 시스템 구축 경험이 있으신가요?&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;CI/CD에&amp;nbsp;대해&amp;nbsp;설명해&amp;nbsp;주세요.&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;기타&lt;/b&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;자기소개 부탁드립니다.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;회사 지원 동기가 어떻게 되시나요.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;프론트엔드 포지션을 선택한 이유가 어떻게 되시나요?&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;최근에 경험했던 기억에 남는 에러에 대해 말씀해주세요.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;요즘 공부중이시는 것에대해 설명해주세요.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;새로운 기술을 습득하기 위해 어떠한 방식으로 연구하시나요?&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;협업을 하면서 갈등이 생겼던 경험이 있으신가요?&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;개발 도중에 발생하는 에러에 대해 보통 어떻게 대처하시나요?&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;</description>
      <category> IT</category>
      <author>알 수 없는 사용자</author>
      <guid isPermaLink="true">https://cocoon1787.tistory.com/869</guid>
      <comments>https://cocoon1787.tistory.com/869#entry869comment</comments>
      <pubDate>Mon, 30 Jan 2023 11:00:49 +0900</pubDate>
    </item>
    <item>
      <title>[JavaScript] navigator.vibrate로 모바일 웹뷰 진동 기능 추가하기</title>
      <link>https://cocoon1787.tistory.com/868</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1200&quot; data-origin-height=&quot;780&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cF8EOc/btrXn6353rK/g7Iks23UDJQJHqXCZXLbAK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cF8EOc/btrXn6353rK/g7Iks23UDJQJHqXCZXLbAK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cF8EOc/btrXn6353rK/g7Iks23UDJQJHqXCZXLbAK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcF8EOc%2FbtrXn6353rK%2Fg7Iks23UDJQJHqXCZXLbAK%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;1200&quot; height=&quot;780&quot; data-origin-width=&quot;1200&quot; data-origin-height=&quot;780&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;요즘 대부분의 모바일 기기는 vibration 하드웨어를 포함하고 있습니다.&lt;br /&gt;Android, IOS로 만든 서비스들을 보면 진동 기능이 거의 필수이지만 일반적인 웹 같은 경우에는 데스크톱을 사용하기 때문에 진동 기능을 잘 사용하지 않습니다. 하지만 모바일 웹뷰의 경우에는 진동 기능이 필요한 경우가 많으며 해당 기술을 vibration API를 통해 구현이 가능합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;&lt;i&gt;참고로 IOS 모바일 기기(또는 사파리 등등)에서는 해당 API를 지원하지 않기 때문에 진동 기능이 동작하지 않습니다.&lt;/i&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1674983625280&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/**
 * 진동 함수
 * @param {Number} ms millisecond
 */
const vibration = (ms = 10) =&amp;gt; {
  navigator.vibrate =
    navigator.vibrate ||
    navigator.webkitVibrate ||
    navigator.mozVibrate ||
    navigator.msVibrate;
  if (navigator.vibrate) navigator.vibrate(ms);
};&lt;/code&gt;&lt;/pre&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;  참고&lt;/b&gt;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;a href=&quot;https://shapeshed.com/html5-vibrate-api/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://shapeshed.com/html5-vibrate-api/&lt;/a&gt;&lt;br /&gt;&lt;a href=&quot;https://developer.mozilla.org/ko/docs/Web/API/Vibration_API&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://developer.mozilla.org/ko/docs/Web/API/Vibration_API&lt;/a&gt;&lt;/h4&gt;</description>
      <category> JavaScript</category>
      <author>Cocoon_</author>
      <guid isPermaLink="true">https://cocoon1787.tistory.com/868</guid>
      <comments>https://cocoon1787.tistory.com/868#entry868comment</comments>
      <pubDate>Sun, 29 Jan 2023 18:17:39 +0900</pubDate>
    </item>
    <item>
      <title>Algorithm Skills</title>
      <link>https://cocoon1787.tistory.com/pages/Algorithm-Skill</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;[BOJ RANK]&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;1028&quot; data-origin-height=&quot;145&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/yDIeT/btrVT7wlDQk/HnkNqkyOwVJCy4k5hNT7F0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/yDIeT/btrVT7wlDQk/HnkNqkyOwVJCy4k5hNT7F0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/yDIeT/btrVT7wlDQk/HnkNqkyOwVJCy4k5hNT7F0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FyDIeT%2FbtrVT7wlDQk%2FHnkNqkyOwVJCy4k5hNT7F0%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;1028&quot; height=&quot;145&quot; data-origin-width=&quot;1028&quot; data-origin-height=&quot;145&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;37&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b3YSeT/btrVT5FfiOB/bvUoQOHUkrYnsTI1F5qtAk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b3YSeT/btrVT5FfiOB/bvUoQOHUkrYnsTI1F5qtAk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b3YSeT/btrVT5FfiOB/bvUoQOHUkrYnsTI1F5qtAk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb3YSeT%2FbtrVT5FfiOB%2FbvUoQOHUkrYnsTI1F5qtAk%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;1280&quot; height=&quot;37&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;37&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cv2q6c/btqPlb0lrrl/3nk7D5dtWd7XAel2uei2IK/img.png&quot; data-lightbox=&quot;lightbox&quot; data-alt=&quot;2020.04.12&quot;&gt;&lt;/span&gt;2020.04.12&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/OQzRC/btqPuTK94Jq/rtSXZtviYTPsf6CKpWEuak/img.png&quot; data-lightbox=&quot;lightbox&quot; data-alt=&quot;2020.12.07&quot;&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;1034&quot; data-origin-height=&quot;39&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cT1e0z/btrVUi5nX3h/ubmO90zK7XTHV5oDr1hA01/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cT1e0z/btrVUi5nX3h/ubmO90zK7XTHV5oDr1hA01/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cT1e0z/btrVUi5nX3h/ubmO90zK7XTHV5oDr1hA01/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcT1e0z%2FbtrVUi5nX3h%2FubmO90zK7XTHV5oDr1hA01%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;1034&quot; height=&quot;39&quot; data-origin-width=&quot;1034&quot; data-origin-height=&quot;39&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/OQzRC/btqPuTK94Jq/rtSXZtviYTPsf6CKpWEuak/img.png&quot; data-lightbox=&quot;lightbox&quot; data-alt=&quot;2020.12.07&quot;&gt;&lt;/span&gt;2020.12.07&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cw7YRr/btqReRdEEt5/EZPzZKUUdK9qaSypEV6jR1/img.png&quot; data-lightbox=&quot;lightbox&quot; data-alt=&quot;2020.12.23&quot;&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;1033&quot; data-origin-height=&quot;35&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/btjQd0/btrVWfmnXaJ/dFRAW3z2CPAA1QirkZdvOK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/btjQd0/btrVWfmnXaJ/dFRAW3z2CPAA1QirkZdvOK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/btjQd0/btrVWfmnXaJ/dFRAW3z2CPAA1QirkZdvOK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbtjQd0%2FbtrVWfmnXaJ%2FdFRAW3z2CPAA1QirkZdvOK%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;1033&quot; height=&quot;35&quot; data-origin-width=&quot;1033&quot; data-origin-height=&quot;35&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cw7YRr/btqReRdEEt5/EZPzZKUUdK9qaSypEV6jR1/img.png&quot; data-lightbox=&quot;lightbox&quot; data-alt=&quot;2020.12.23&quot;&gt;&lt;/span&gt;2020.12.23&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lOy6V/btqVe8pf9HZ/uCDAgKWGLHERMgCES5IEu1/img.png&quot; data-lightbox=&quot;lightbox&quot; data-alt=&quot;2021.02.01&quot;&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;1030&quot; data-origin-height=&quot;35&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kxRxn/btrVUrH685n/birM3ZTEa5PFCuXU3GXdG0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kxRxn/btrVUrH685n/birM3ZTEa5PFCuXU3GXdG0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kxRxn/btrVUrH685n/birM3ZTEa5PFCuXU3GXdG0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkxRxn%2FbtrVUrH685n%2FbirM3ZTEa5PFCuXU3GXdG0%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;1030&quot; height=&quot;35&quot; data-origin-width=&quot;1030&quot; data-origin-height=&quot;35&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lOy6V/btqVe8pf9HZ/uCDAgKWGLHERMgCES5IEu1/img.png&quot; data-lightbox=&quot;lightbox&quot; data-alt=&quot;2021.02.01&quot;&gt;&lt;/span&gt;2021.02.01&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dz1BRr/btqZefxpOxC/x2zSbAp5h0LACcXFyaxrY0/img.png&quot; data-lightbox=&quot;lightbox&quot; data-alt=&quot;2021.03.01&quot;&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;1029&quot; data-origin-height=&quot;36&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/UYgnv/btrVUyfWTvv/vktKdxBF8qpZj3KVk3l0A1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/UYgnv/btrVUyfWTvv/vktKdxBF8qpZj3KVk3l0A1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/UYgnv/btrVUyfWTvv/vktKdxBF8qpZj3KVk3l0A1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FUYgnv%2FbtrVUyfWTvv%2FvktKdxBF8qpZj3KVk3l0A1%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;1029&quot; height=&quot;36&quot; data-origin-width=&quot;1029&quot; data-origin-height=&quot;36&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dz1BRr/btqZefxpOxC/x2zSbAp5h0LACcXFyaxrY0/img.png&quot; data-lightbox=&quot;lightbox&quot; data-alt=&quot;2021.03.01&quot;&gt;&lt;/span&gt;2021.03.01&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bpcHpJ/btq0zu9DKKY/3mkCbOycvpkqoGR6dAVrhK/img.png&quot; data-lightbox=&quot;lightbox&quot; data-alt=&quot;2021.03.22&quot;&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;1028&quot; data-origin-height=&quot;35&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/RCO3p/btrVWfmnXa1/LYThYZDCmYmjo77xsaXcc1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/RCO3p/btrVWfmnXa1/LYThYZDCmYmjo77xsaXcc1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/RCO3p/btrVWfmnXa1/LYThYZDCmYmjo77xsaXcc1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FRCO3p%2FbtrVWfmnXa1%2FLYThYZDCmYmjo77xsaXcc1%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;1028&quot; height=&quot;35&quot; data-origin-width=&quot;1028&quot; data-origin-height=&quot;35&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bpcHpJ/btq0zu9DKKY/3mkCbOycvpkqoGR6dAVrhK/img.png&quot; data-lightbox=&quot;lightbox&quot; data-alt=&quot;2021.03.22&quot;&gt;&lt;/span&gt;2021.03.22&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cdXApU/btq1uuy33XM/ICh7qPlZR7J2DR16LTD1A1/img.png&quot; data-lightbox=&quot;lightbox&quot; data-alt=&quot;2021.03.31&quot;&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;1029&quot; data-origin-height=&quot;34&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bkuut7/btrVQoMl6zz/ykkkwHMSH7Yl5567j2Cqek/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bkuut7/btrVQoMl6zz/ykkkwHMSH7Yl5567j2Cqek/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bkuut7/btrVQoMl6zz/ykkkwHMSH7Yl5567j2Cqek/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbkuut7%2FbtrVQoMl6zz%2FykkkwHMSH7Yl5567j2Cqek%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;1029&quot; height=&quot;34&quot; data-origin-width=&quot;1029&quot; data-origin-height=&quot;34&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cdXApU/btq1uuy33XM/ICh7qPlZR7J2DR16LTD1A1/img.png&quot; data-lightbox=&quot;lightbox&quot; data-alt=&quot;2021.03.31&quot;&gt;&lt;/span&gt;2021.03.31&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음 정답비율이 23%정도였는데 35%까지 올라온것을 보면 점점 실력이 느는것 같다.&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;[Solved.ac RANK]&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;1050&quot; data-origin-height=&quot;96&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/r4fBg/btrVSs15IRQ/6s0psGevP23aL1S0CZOvw1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/r4fBg/btrVSs15IRQ/6s0psGevP23aL1S0CZOvw1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/r4fBg/btrVSs15IRQ/6s0psGevP23aL1S0CZOvw1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fr4fBg%2FbtrVSs15IRQ%2F6s0psGevP23aL1S0CZOvw1%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;1050&quot; height=&quot;96&quot; data-origin-width=&quot;1050&quot; data-origin-height=&quot;96&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1059&quot; data-origin-height=&quot;35&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cu43WL/btrVWeHLREn/uRq83JroOIDkJ4xvYOnLb1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cu43WL/btrVWeHLREn/uRq83JroOIDkJ4xvYOnLb1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cu43WL/btrVWeHLREn/uRq83JroOIDkJ4xvYOnLb1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcu43WL%2FbtrVWeHLREn%2FuRq83JroOIDkJ4xvYOnLb1%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;1059&quot; height=&quot;35&quot; data-origin-width=&quot;1059&quot; data-origin-height=&quot;35&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b5UCNJ/btqPensVAms/JsAWaZyHBDfJ6MFYZ2AhYK/img.png&quot; data-lightbox=&quot;lightbox&quot; data-alt=&quot;2020.12.06 골드 V 달성&quot;&gt;&lt;/span&gt;2020.12.06 골드 V 달성&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/WPgjg/btqRcHo0ZRk/isjSKSnDKe3ruCPO80cpsk/img.png&quot; data-lightbox=&quot;lightbox&quot; data-alt=&quot;2020.12.23 골드 IV 달성&quot;&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;1050&quot; data-origin-height=&quot;33&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ptBgA/btrVU8OOr2s/hkZARpHp4AwV7p35JLg80K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ptBgA/btrVU8OOr2s/hkZARpHp4AwV7p35JLg80K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ptBgA/btrVU8OOr2s/hkZARpHp4AwV7p35JLg80K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FptBgA%2FbtrVU8OOr2s%2FhkZARpHp4AwV7p35JLg80K%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;1050&quot; height=&quot;33&quot; data-origin-width=&quot;1050&quot; data-origin-height=&quot;33&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/WPgjg/btqRcHo0ZRk/isjSKSnDKe3ruCPO80cpsk/img.png&quot; data-lightbox=&quot;lightbox&quot; data-alt=&quot;2020.12.23 골드 IV 달성&quot;&gt;&lt;/span&gt;2020.12.23 골드 IV 달성&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c4B4nt/btqRCWTyU32/weir7Ni1WZGuYevfIckyq1/img.png&quot; data-lightbox=&quot;lightbox&quot; data-alt=&quot;2020.12.28 골드 III 달성&quot;&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;1280&quot; data-origin-height=&quot;40&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/OpfOm/btrVTl9pwzA/L6pfdY4ielkpXed8KUsU4K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/OpfOm/btrVTl9pwzA/L6pfdY4ielkpXed8KUsU4K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/OpfOm/btrVTl9pwzA/L6pfdY4ielkpXed8KUsU4K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FOpfOm%2FbtrVTl9pwzA%2FL6pfdY4ielkpXed8KUsU4K%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;1280&quot; height=&quot;40&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;40&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c4B4nt/btqRCWTyU32/weir7Ni1WZGuYevfIckyq1/img.png&quot; data-lightbox=&quot;lightbox&quot; data-alt=&quot;2020.12.28 골드 III 달성&quot;&gt;&lt;/span&gt;2020.12.28 골드 III 달성&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cLBN1F/btqVcrQz821/zojpNQyHiYYyacL9sj8290/img.png&quot; data-lightbox=&quot;lightbox&quot; data-alt=&quot;2021.02.01 골드 II 달성&quot;&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;1058&quot; data-origin-height=&quot;34&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bejOIJ/btrVWe8PUDP/sNklvgbZkKkEm1ZB1wqpLk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bejOIJ/btrVWe8PUDP/sNklvgbZkKkEm1ZB1wqpLk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bejOIJ/btrVWe8PUDP/sNklvgbZkKkEm1ZB1wqpLk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbejOIJ%2FbtrVWe8PUDP%2FsNklvgbZkKkEm1ZB1wqpLk%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;1058&quot; height=&quot;34&quot; data-origin-width=&quot;1058&quot; data-origin-height=&quot;34&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cLBN1F/btqVcrQz821/zojpNQyHiYYyacL9sj8290/img.png&quot; data-lightbox=&quot;lightbox&quot; data-alt=&quot;2021.02.01 골드 II 달성&quot;&gt;&lt;/span&gt;2021.02.01 골드 II 달성&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1049&quot; data-origin-height=&quot;37&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bbeFeH/btrVSsA14Fx/G7KRRrU3ibbSo4EqTCw61K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bbeFeH/btrVSsA14Fx/G7KRRrU3ibbSo4EqTCw61K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bbeFeH/btrVSsA14Fx/G7KRRrU3ibbSo4EqTCw61K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbbeFeH%2FbtrVSsA14Fx%2FG7KRRrU3ibbSo4EqTCw61K%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;1049&quot; height=&quot;37&quot; data-origin-width=&quot;1049&quot; data-origin-height=&quot;37&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1054&quot; data-origin-height=&quot;37&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b0M7y4/btrVUA5MM4e/k7JHqcwJ7PniwaebmdE7f0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b0M7y4/btrVUA5MM4e/k7JHqcwJ7PniwaebmdE7f0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b0M7y4/btrVUA5MM4e/k7JHqcwJ7PniwaebmdE7f0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb0M7y4%2FbtrVUA5MM4e%2Fk7JHqcwJ7PniwaebmdE7f0%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;1054&quot; height=&quot;37&quot; data-origin-width=&quot;1054&quot; data-origin-height=&quot;37&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/oNc9I/btqZehoq8WW/4TpUT7OoO9ZO0PiVllz9x0/img.png&quot; data-lightbox=&quot;lightbox&quot; data-alt=&quot;2021.03.01 골드 l 달성 (레이팅 시스템 업데이트로 인한 승급)&quot;&gt;&lt;/span&gt;2021.03.01 골드 l 달성 (레이팅 시스템 업데이트로 인한 승급)&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dCSsR1/btq0BDRReAx/OKGfA6xq0x3xSNnBdbf58K/img.png&quot; data-lightbox=&quot;lightbox&quot; data-alt=&quot;2021.03.22 플레 V 달성&quot;&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;1048&quot; data-origin-height=&quot;37&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dnnYS5/btrVVQmKY3I/eKWojh80ok6nEdcHdkueXK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dnnYS5/btrVVQmKY3I/eKWojh80ok6nEdcHdkueXK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dnnYS5/btrVVQmKY3I/eKWojh80ok6nEdcHdkueXK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdnnYS5%2FbtrVVQmKY3I%2FeKWojh80ok6nEdcHdkueXK%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;1048&quot; height=&quot;37&quot; data-origin-width=&quot;1048&quot; data-origin-height=&quot;37&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dCSsR1/btq0BDRReAx/OKGfA6xq0x3xSNnBdbf58K/img.png&quot; data-lightbox=&quot;lightbox&quot; data-alt=&quot;2021.03.22 플레 V 달성&quot;&gt;&lt;/span&gt;2021.03.22 플레 V 달성&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;롤 실력은 만년 브론즈이지만, 백준 랭크만큼은 플래티넘 가보자. (2020.12.28)&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1249&quot; data-origin-height=&quot;936&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/IuC2x/btrVQn0Wo2i/loH1dN8OB0cuQAOG1lgxh0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/IuC2x/btrVQn0Wo2i/loH1dN8OB0cuQAOG1lgxh0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/IuC2x/btrVQn0Wo2i/loH1dN8OB0cuQAOG1lgxh0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FIuC2x%2FbtrVQn0Wo2i%2FloH1dN8OB0cuQAOG1lgxh0%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;472&quot; height=&quot;936&quot; data-origin-width=&quot;1249&quot; data-origin-height=&quot;936&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(경축) 드디어 플래티넘 달성!! ㅜ.ㅜ 플래티넘 달성하니 다이아도 가보고싶은 생각이 드네요... (2021.03.22)&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-origin-width=&quot;1032&quot; data-origin-height=&quot;701&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cl9agh/btrVP8QzkTv/PMkXl1Gu2bfGo7c7FmkNTK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cl9agh/btrVP8QzkTv/PMkXl1Gu2bfGo7c7FmkNTK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cl9agh/btrVP8QzkTv/PMkXl1Gu2bfGo7c7FmkNTK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcl9agh%2FbtrVP8QzkTv%2FPMkXl1Gu2bfGo7c7FmkNTK%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;869&quot; height=&quot;701&quot; data-origin-width=&quot;1032&quot; data-origin-height=&quot;701&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/k2omr/btq1nH1cvLO/2C7xxNOuTy0VkWshqkKk3k/img.png&quot; data-lightbox=&quot;lightbox&quot; data-alt=&quot;2021.03.31 백준 500 solve.&quot;&gt;&lt;/span&gt;2021.03.31 백준 500 solve.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;백준 500문제 풀이 달성 (2021.03.31)&lt;/p&gt;</description>
      <author>알 수 없는 사용자</author>
      <guid isPermaLink="true">https://cocoon1787.tistory.com/pages/Algorithm-Skill</guid>
      <pubDate>Tue, 10 Jan 2023 20:43:21 +0900</pubDate>
    </item>
    <item>
      <title>[React] Next.js - Parsing error: Cannot find module 'next/babel' 에러</title>
      <link>https://cocoon1787.tistory.com/866</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1550&quot; data-origin-height=&quot;793&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ceugK5/btrVOdKfU57/Ioy1Kf35kj86rQGXAV7DL1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ceugK5/btrVOdKfU57/Ioy1Kf35kj86rQGXAV7DL1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ceugK5/btrVOdKfU57/Ioy1Kf35kj86rQGXAV7DL1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FceugK5%2FbtrVOdKfU57%2FIoy1Kf35kj86rQGXAV7DL1%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;1550&quot; height=&quot;793&quot; data-origin-width=&quot;1550&quot; data-origin-height=&quot;793&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;Parsing&amp;nbsp;error:&amp;nbsp;Cannot&amp;nbsp;find&amp;nbsp;module&amp;nbsp;'next/babel'&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;Next.js로 프로젝트를 구성하던 도중 해당 에러가 발생하여 해결 방법을 공유드립니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&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;프로젝트 루트에 .babelrc 파일을 생성하고 프로젝트 루트에 있는 .eslintrc.json 파일을 수정합니다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;  &lt;b&gt;.babelrc&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1673277043076&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;{
  &quot;presets&quot;: [&quot;next/babel&quot;],
  &quot;plugins&quot;: []
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;  &lt;b&gt;.eslintrc.json&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1673277055369&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;{
  &quot;extends&quot;: [&quot;next/babel&quot;,&quot;next/core-web-vitals&quot;]
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;위와 같이 파일을 생성하고 수정하면 babel parsing error가 사라지게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category> ERROR</category>
      <author>알 수 없는 사용자</author>
      <guid isPermaLink="true">https://cocoon1787.tistory.com/866</guid>
      <comments>https://cocoon1787.tistory.com/866#entry866comment</comments>
      <pubDate>Tue, 10 Jan 2023 00:17:19 +0900</pubDate>
    </item>
    <item>
      <title>Goodbye 2022, Hello 2023</title>
      <link>https://cocoon1787.tistory.com/865</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;3565.jpg&quot; data-origin-width=&quot;8641&quot; data-origin-height=&quot;8641&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/FQJnl/btrUYpSDIlC/2yLsPImNqpYEorOUaNKpg0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/FQJnl/btrUYpSDIlC/2yLsPImNqpYEorOUaNKpg0/img.jpg&quot; data-alt=&quot;작가 Harryarts 출처 Freepik&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/FQJnl/btrUYpSDIlC/2yLsPImNqpYEorOUaNKpg0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FFQJnl%2FbtrUYpSDIlC%2F2yLsPImNqpYEorOUaNKpg0%2Fimg.jpg&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;8641&quot; height=&quot;8641&quot; data-filename=&quot;3565.jpg&quot; data-origin-width=&quot;8641&quot; data-origin-height=&quot;8641&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;작가 Harryarts 출처 Freepik&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;2022년도 회고록&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1, 2월에 사이드 프로젝트를 진행하면서 취업준비를 했었고 2월 말에는 어디라도 들어가서 경력을 쌓자는 생각으로 jumpit에서 5곳을 지원했었다. 그중에서 4곳은 서류탈락을 하게 되었지만, 운 좋게 한 곳의 연락을 받아 3월 10일 면접을 보러 갔었고 바로 면접 후 바로 다음날 합격 통보를 받아 설레는 마음으로 3월 16일에 첫 출근을 하게 되었다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;회사는 강남에 위치한 암호화폐 거래소였고 개발팀 인원은 20명이 안 되는 작은 회사였다. 업무는 기존의 웹 서비스를 갈아엎고 9월에 새로운 2.0 웹 서비스를 오픈하는 Frontend&amp;nbsp;업무였다. 하지만 인원이 적다 보니 대부분 신입인 젊은 조직이었고 5월까지&amp;nbsp;Frontend 인원이&amp;nbsp;나 혼자여서 삽질하는 시간이 꽤나 길었었다. 특히나 트레이딩뷰로 거래소 차트를 구현하는 과정에서 관련 레퍼런스도 적었으며 도저히 해결이 안 될 때는 본사에 이메일로 문의를 하거나 디스코드로 트레이딩뷰 개발자에게 직접 영어로 질문도 하고 그랬었다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 가장 힘들었었던 부분이 소켓으로 많은 데이터를 받을 때 사이트가 버벅거린다는 것이었는데, 해당 문제를 해결하기 위해 관련 부분을 하나씩 분리하면서 렌더링 비용이 큰 부분을 찾아내어 계속해서 코드를 최적화하고 속도를 개선하기 위해 많은 노력을 했었었다. 또한 일이 많다 보니 오전 9시에 출근하여 오후 11시에 퇴근을 하거나 주말에도 출근하여 업무를 하는 날이 잦았었다. 물론 몸이 힘들고 많이 피곤하긴 했었어도 워낙 React를 좋아하고 Frontend 업무가 적성에 너무나도 맞아 일하는 게 재미있었다. 그리고 사내에 좋은 사람들, 좋은 환경 덕분에 회사생활도 즐거웠었다. 다른 회사를 거쳐온 신입 동료들도 이렇게 자유롭고 즐겁고 재미있게 회사생활 할 수 있는 곳이 흔치 않다는 말을 했었었다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다들 열심히 한 끝에 9월 27일에 2.0 서비스를 오픈하였고 오픈 전후로 1개월간 굉장히 바쁜 나날을 보냈었다. 현재는 어느 정도 서비스가 안정화되어 그렇게 급하게 일하지 않아도 되었고 야근과 주말 출근으로 다져진(..?) 개발 노하우와 지식으로 빠르게 일처리를 할 수 있게 되었다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2022년도는 업무에 몰두하면서 이뤄낸 성과에 대해 만족스러운 한 해였고, 고생한 나 자신에게 정말 고맙고, 고생 많았다고 말해주고 싶다.&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;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;2023년도 도전과 다짐&lt;/b&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;사이드 프로젝트&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사이드 프로젝트에 대한 나의 생각은 &quot;회사에서 시도해보지 못했었던 새로운 기회&quot;라고 표현을 하고 싶다. 물론 사이드 프로젝트를 한다는 것 때문에 회사 업무에 지장이 가면 안 되며, 항상 1순위는 회사 업무여야 한다. 퇴근 후 집에 오면 아무것도 하기 싫고, 주말에 남들 쉴 때 사이드 프로젝트 한다는 것이 정말 힘든 일이라는 것을 대부분의 직장인들은 공감할 것이다. 그렇기 때문에 나의 개발에 대한 열정을 보여줄 수 있는 부분이 바로 사이드 프로젝트이고, 새로운 라이브러리, 새로운 기술과 패턴을 사용해보면서 회사에서는 채울 수 없었던 부분을 채울 수 있는 장점이 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;매번 사이드 프로젝트 하는 것에 대해 미루고 미루시는 분들에게 &quot;시작이 반이고 허술해도 괜찮으니 일단 시작하는 게 좋습니다.&quot;라는 말을 전해드리고 싶다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;타입 스크립트 기반 TodoList&lt;/li&gt;
&lt;li&gt;Upbit OPEN API Websocket을 이용한 미니 거래소 앱&lt;/li&gt;
&lt;li&gt;요기요 음식점 API를 이용한 배달 앱&lt;/li&gt;
&lt;li&gt;토스 앱 클론코딩&lt;/li&gt;
&lt;/ul&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;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2020년도, 2021년도에는 취업을 준비한다고 백준에서 알고리즘 문제를 많이 풀곤 했었는데, 취직을 하게 되면서 알고리즘 문제를 풀지 않은지 꽤나 오래되었었다. 그 당시에는 &quot;알고리즘 공부가 회사 업무에 큰 도움을 줄까?&quot;라고 의구심이 들었었는데, 회사 업무를 하면서 느낀 것은 예전 알고리즘 문제를 풀려고 고민하고 또 고민했었던 과정이 실직적인 문제 해결력에 큰 영향을 준다는 점이었다. 자바스크립트로 서버 데이터를 다루면서 &quot;어떻게 하면 깔끔하게 로직을 짜고 시간복잡도를 줄일 수 있을까?&quot;라는 생각을 항상 하면서 개발을 했었다. 그만큼 알고리즘이 중요하다고 생각되며 2023년도에는 많이는 아니더라도 꾸준하게 알고리즘 문제를 풀 것이다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;프로그래머스 LEVEL 4 달성하기&lt;/li&gt;
&lt;li&gt;프로그래머스 문제 풀기 &lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;(주당 최소 4개)&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;CS 지식 및 자격증&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;cs지식이 당장 업무에는 관련 없을지라도 기본적인 소양으로 가져야 할 중요한 지식으로 생각이 된다. 인터넷으로 검색을 하다가 포스팅할만한 cs 주제를 찾게 되면 google task에 쌓아두는 편인데 현재 80개나 쌓이게 되었다. 꾸준하게 배운 지식을 공부하면서 블로그에 포스팅을 할 것이다. 또한 2023년도는 그동안 해보지 못했던 자격등 취득도 해볼 예정이다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;cs지식 관련 포스팅 하기&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;(주당 최소 2개)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;정보처리기능사 자격증 취득&lt;/li&gt;
&lt;li&gt;정보처리기사 자격증 취득&lt;/li&gt;
&lt;/ul&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;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예전에는 등산도 많이 가고 했었는데 요즘은 운동도 잘 안 하게 되고 맨날 앉아서 일하다 보니 살이 많이 찌게 되었다. 앞으로는 야식은 물론, 먹는 양을 좀 줄일 수 있도록 노력하고 좀 덜 바빠지면 헬스장도 등록해서 다이어트를 해야겠다는 생각이 들었다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;2월에 헬스장 등록하기&lt;/li&gt;
&lt;li&gt;야식 자제하기&lt;/li&gt;
&lt;/ul&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;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음에 React를 배울 때 나의 선생님과도 같은 분이신&amp;nbsp;&lt;a href=&quot;https://react.vlpt.us/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;벨로퍼트(vlpt)&lt;/a&gt;님의 글들을 보면서 공부를 많이 했었다. 회사 일을 하면서 정보도 많이 찾아보고 공부도 많이 했었는데, 그동안 배운 지식들을 정리할 시간이 없었던 것 같다. 2023년도에는 벨로퍼트님처럼 react 관련 글을 많이 작성하고 자바스크립트에 대해 심도 깊은 공부 및 관련 포스팅을 많이 작성하는 것을 목표로 할 것이다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;React 관련 포스팅 하기 (주당 최소 3개)&lt;/li&gt;
&lt;li&gt;Javascript 관련 포스팅&lt;span&gt;&lt;span&gt; 하기&amp;nbsp;&lt;/span&gt;(주당 최소 3개)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;일 조회수 1만명 달성하기&lt;/li&gt;
&lt;/ul&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 data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2022년도 어느 때와 같이 정말 순식간에 지나가버렸지만 다들 고생 많으셨으며,&lt;/b&gt;&lt;br /&gt;&lt;b&gt;2023년도에도 알차게 보내시길 바랍니다..! 감사합니다. &lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category> 일상</category>
      <author>알 수 없는 사용자</author>
      <guid isPermaLink="true">https://cocoon1787.tistory.com/865</guid>
      <comments>https://cocoon1787.tistory.com/865#entry865comment</comments>
      <pubDate>Sun, 1 Jan 2023 00:00:12 +0900</pubDate>
    </item>
    <item>
      <title>[HTML/CSS] Footer 하단 고정</title>
      <link>https://cocoon1787.tistory.com/864</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1893&quot; data-origin-height=&quot;1226&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bmsNIj/btrS3GINMUg/UkCcuFOhFOPjP1wYsKhK91/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bmsNIj/btrS3GINMUg/UkCcuFOhFOPjP1wYsKhK91/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bmsNIj/btrS3GINMUg/UkCcuFOhFOPjP1wYsKhK91/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbmsNIj%2FbtrS3GINMUg%2FUkCcuFOhFOPjP1wYsKhK91%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;1893&quot; height=&quot;1226&quot; data-origin-width=&quot;1893&quot; data-origin-height=&quot;1226&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;모바일 웹의 경우에는 하단에 footer 대신 navigationBar를 position: fixed; 하기도 하는데,&lt;br /&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;h4 data-ke-size=&quot;size20&quot;&gt; &lt;span&gt;&lt;b&gt;&lt;span&gt; HTML 구조&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1670411410601&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;  &amp;lt;body&amp;gt;
    &amp;lt;header&amp;gt;header&amp;lt;/header&amp;gt;
    &amp;lt;div id=&quot;wrap&quot;&amp;gt;
      &amp;lt;div id=&quot;content-wrap&quot;&amp;gt;
        &amp;lt;div&amp;gt;content-wrap&amp;lt;/div&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
    &amp;lt;footer&amp;gt;footer&amp;lt;/footer&amp;gt;
  &amp;lt;/body&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대략적인 HTML 구조는 위와 같습니다.&amp;nbsp;&lt;br /&gt;일반적으로 header와 footer에 height를 60px씩 주고 wrap에 height로 200px정도를 주면 &lt;br /&gt;다음과 같은 결과가 나오게 됩니다.&lt;/p&gt;
&lt;pre id=&quot;code_1670411586056&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;    &amp;lt;style&amp;gt;
      html,
      body {
        height: 100%;
        padding: 0px;
        margin: 0px;
      }

      header {
        height: 60px;
        background-color: #e9eaed;
      }

      #wrap {
        height: 200px;
      }

      footer {
        height: 60px;
        background-color: #e9eaed;
      }
    &amp;lt;/style&amp;gt;&lt;/code&gt;&lt;/pre&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;1450&quot; data-origin-height=&quot;747&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mMx37/btrS1RjuK4H/ebtVN9HoU9fKs39EYHi7P1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mMx37/btrS1RjuK4H/ebtVN9HoU9fKs39EYHi7P1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mMx37/btrS1RjuK4H/ebtVN9HoU9fKs39EYHi7P1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmMx37%2FbtrS1RjuK4H%2FebtVN9HoU9fKs39EYHi7P1%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;1450&quot; height=&quot;747&quot; data-origin-width=&quot;1450&quot; data-origin-height=&quot;747&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;footer영역 아래로 공간이 남게 되어 좋지 않은 레이아웃을 보여주게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 CSS 코드를 수정해봅시다.&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;h4 data-ke-size=&quot;size20&quot;&gt; &lt;span&gt;&lt;b&gt;&lt;span&gt; CSS 코드 수정&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1670411940865&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;    &amp;lt;style&amp;gt;
      html,
      body {
        height: 100%;
        padding: 0px;
        margin: 0px;
      }

      header {
        height: 60px;
        background-color: #e9eaed;
      }

      #wrap {
        min-height: calc(100% - 120px);
      }

      footer {
        height: 60px;
        background-color: #e9eaed;
      }
    &amp;lt;/style&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;#wrap부분만 바뀌었습니다.&lt;br /&gt;전체 화면 영역에서 header와 footer부분이 각각 60px씩 총 120px을 차지하고 있으므로&amp;nbsp;&lt;br /&gt;#wrap 영역의 min-height를 calc(100% - 120px)로 설정하면 footer을 하단에 고정시킬 수 있습니다.&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;h4 data-ke-size=&quot;size20&quot;&gt; &lt;span&gt;&lt;b&gt; 전체&lt;/b&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;코드&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1670410832035&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html lang=&quot;en&quot;&amp;gt;
  &amp;lt;head&amp;gt;
    &amp;lt;meta charset=&quot;UTF-8&quot; /&amp;gt;
    &amp;lt;meta http-equiv=&quot;X-UA-Compatible&quot; content=&quot;IE=edge&quot; /&amp;gt;
    &amp;lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot; /&amp;gt;
    &amp;lt;title&amp;gt;Document&amp;lt;/title&amp;gt;
    &amp;lt;style&amp;gt;
      html,
      body {
        height: 100%;
        padding: 0px;
        margin: 0px;
      }

      header {
        height: 60px;
        background-color: #e9eaed;
      }

      #wrap {
        min-height: calc(100% - 120px);
      }

      footer {
        height: 60px;
        background-color: #e9eaed;
      }
    &amp;lt;/style&amp;gt;
  &amp;lt;/head&amp;gt;
  &amp;lt;body&amp;gt;
    &amp;lt;header&amp;gt;header&amp;lt;/header&amp;gt;
    &amp;lt;div id=&quot;wrap&quot;&amp;gt;
      &amp;lt;div id=&quot;content-wrap&quot;&amp;gt;
        &amp;lt;div&amp;gt;content-wrap&amp;lt;/div&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
    &amp;lt;footer&amp;gt;footer&amp;lt;/footer&amp;gt;
  &amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/OB9TG/btrS3oOYIwi/JLwobFlbQ6Cup3NxPMfnh0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/OB9TG/btrS3oOYIwi/JLwobFlbQ6Cup3NxPMfnh0/img.png&quot; data-origin-width=&quot;997&quot; data-origin-height=&quot;739&quot; data-is-animation=&quot;false&quot; style=&quot;width: 73.1365%; margin-right: 10px;&quot; data-widthpercent=&quot;74&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/OB9TG/btrS3oOYIwi/JLwobFlbQ6Cup3NxPMfnh0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FOB9TG%2FbtrS3oOYIwi%2FJLwobFlbQ6Cup3NxPMfnh0%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;997&quot; height=&quot;739&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Jfr0n/btrS7JwZe1E/nEnhuQPUq5q7BrAx20W3iK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Jfr0n/btrS7JwZe1E/nEnhuQPUq5q7BrAx20W3iK/img.png&quot; data-origin-width=&quot;613&quot; data-origin-height=&quot;1293&quot; data-is-animation=&quot;false&quot; style=&quot;width: 25.7007%;&quot; data-widthpercent=&quot;26&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Jfr0n/btrS7JwZe1E/nEnhuQPUq5q7BrAx20W3iK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FJfr0n%2FbtrS7JwZe1E%2FnEnhuQPUq5q7BrAx20W3iK%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;613&quot; height=&quot;1293&quot;/&gt;&lt;/span&gt;&lt;/div&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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category> WEB</category>
      <author>Cocoon_</author>
      <guid isPermaLink="true">https://cocoon1787.tistory.com/864</guid>
      <comments>https://cocoon1787.tistory.com/864#entry864comment</comments>
      <pubDate>Wed, 7 Dec 2022 20:24:16 +0900</pubDate>
    </item>
    <item>
      <title>[React] safari/iOS 에서 정규식 Invalid regular expression 에러 해결</title>
      <link>https://cocoon1787.tistory.com/863</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;734&quot; data-origin-height=&quot;1609&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bfTGOK/btrH2oq6gC4/PEz39PnbR2khtR3NmP0tN0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bfTGOK/btrH2oq6gC4/PEz39PnbR2khtR3NmP0tN0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bfTGOK/btrH2oq6gC4/PEz39PnbR2khtR3NmP0tN0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbfTGOK%2FbtrH2oq6gC4%2FPEz39PnbR2khtR3NmP0tN0%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;337&quot; height=&quot;739&quot; data-origin-width=&quot;734&quot; data-origin-height=&quot;1609&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;SyntaxError: Invalid regular expression: invalid group specifier name&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Next.js, React로 구성된 웹페이지에서 크롬이나 안드로이드에서는 오류가 발생하지 않지만 사파리나 아이폰에서 웹사이트 접속 시 위와 같은 에러가 발생하였습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;  에러 원인&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;구글링하여 찾아본 결과 크롬에서는 작동하지만 파이어폭스 또는 사파리에서는 작동하지 않는 x(?&amp;lt;=y)&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;x(?&amp;lt;!y)와 같은&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt; 정규표현식&amp;nbsp;&lt;/span&gt;lookbehind 문법을 사용한 것이 문제의 원인이었습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;  기존 코드&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1658660141763&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;let number = 1000000.123;
     return number.toString().replace(/\B(?&amp;lt;!\.\d*)(?=(\d{3})+(?!\d))/g, &quot;,&quot;);

//returns 1,000,000.123&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위와 같은 정규식에서 ?&amp;lt;! 과 같은 표기법은 최신 기법으로 익스, IOS, Safari에서 통하지 않는 스크립트입니다.&amp;nbsp;&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;  수정 코드&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1658660270945&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;let number = 1000000.123;
     return number.toString().replace(/\B(?=(\d{3})+(?!\d))/g, &quot;,&quot;);

//returns 1,000,000.123&lt;/code&gt;&lt;/pre&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;</description>
      <category> ERROR</category>
      <author>Cocoon_</author>
      <guid isPermaLink="true">https://cocoon1787.tistory.com/863</guid>
      <comments>https://cocoon1787.tistory.com/863#entry863comment</comments>
      <pubDate>Sun, 24 Jul 2022 20:02:46 +0900</pubDate>
    </item>
    <item>
      <title>[CSS] Transition 성능 최적화 (애니메이션 버벅거림 해결)</title>
      <link>https://cocoon1787.tistory.com/862</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1391&quot; data-origin-height=&quot;412&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/8ani1/btrGQ6Zj1gf/atAxT7PA7o2pcNPU17Wt3k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/8ani1/btrGQ6Zj1gf/atAxT7PA7o2pcNPU17Wt3k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/8ani1/btrGQ6Zj1gf/atAxT7PA7o2pcNPU17Wt3k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F8ani1%2FbtrGQ6Zj1gf%2FatAxT7PA7o2pcNPU17Wt3k%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;1391&quot; height=&quot;412&quot; data-origin-width=&quot;1391&quot; data-origin-height=&quot;412&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Next.js로 만든 홈페이지의 배너를 제작하면서 슬라이더를 구현하고 테스트 중 버벅거리는 현상을 발견하였습니다. 사실 이미지의 크기가 작으면 애니메이션이 버벅거림 문제는 발생하지 않지만 큰 사이즈의 이미지를 사용하자마자 이러한 문제가 발생해서 &lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;UX적으로 굉장히 좋지 않다고 판단하였고 이를 해결하기 위해 이미지를 최적화할 수 있는 방법에 대해서 알아보았습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;배너 이미지 크기&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1338&quot; data-origin-height=&quot;388&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/q8Ebr/btrGSx3AmkO/FuLlP2s8Ga58FWamf1x2n0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/q8Ebr/btrGSx3AmkO/FuLlP2s8Ga58FWamf1x2n0/img.png&quot; data-alt=&quot;배너 이미지 크기가 꽤 큰편&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/q8Ebr/btrGSx3AmkO/FuLlP2s8Ga58FWamf1x2n0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fq8Ebr%2FbtrGSx3AmkO%2FFuLlP2s8Ga58FWamf1x2n0%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;1338&quot; height=&quot;388&quot; data-origin-width=&quot;1338&quot; data-origin-height=&quot;388&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-filename=&quot;left.gif&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;158&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eePzD5/btrGP51MgX6/sfLaNXXSKz9NVoRCGsq6g1/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eePzD5/btrGP51MgX6/sfLaNXXSKz9NVoRCGsq6g1/img.gif&quot; data-alt=&quot;슬라이더 버튼 클릭 시 버벅거림 발생&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eePzD5/btrGP51MgX6/sfLaNXXSKz9NVoRCGsq6g1/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/eePzD5/btrGP51MgX6/sfLaNXXSKz9NVoRCGsq6g1/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;600&quot; height=&quot;158&quot; data-filename=&quot;left.gif&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;158&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;슬라이더 버튼 클릭 시 버벅거림 발생&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;작은 사이즈의 이미지(24KB)의 경우&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;small-size.gif&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;158&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Yl5Uz/btrGPDKSkVx/et0RWJnXaxxOXnt84vcaE1/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Yl5Uz/btrGPDKSkVx/et0RWJnXaxxOXnt84vcaE1/img.gif&quot; data-alt=&quot;큰 사이즈의 이미지 애니메이션보다 부드러움&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Yl5Uz/btrGPDKSkVx/et0RWJnXaxxOXnt84vcaE1/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/Yl5Uz/btrGPDKSkVx/et0RWJnXaxxOXnt84vcaE1/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;600&quot; height=&quot;158&quot; data-filename=&quot;small-size.gif&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;158&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;사실 사용할 이미지를 미리 최대한 압축해서 사용하여 성능을 끌어올릴 수 있지만 저는 개발자이기 때문에(?) 최악의 케이스를 염두에 두고 코드로서 최적화할 수 있는 방법이 있는지 찾아봤습니다.&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;pre id=&quot;code_1657353181760&quot; data-ke-language=&quot;css&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;  left: ${(props) =&amp;gt; `${props.left}px`};
  transition: left 0.2s ease;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 배너&amp;nbsp; 슬라이더 애니메이션을 구현하면서 transtion 속성을 사용하였는데 먼저 웹브라우저에 스타일이 어떤 순서로 적용되는지 알아보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;1. Style&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;2. Layout&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;&amp;lt;적용되는 속성&amp;gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 111px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style4&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;position&lt;/td&gt;
&lt;td&gt;display&lt;/td&gt;
&lt;td&gt;overflow&lt;/td&gt;
&lt;td&gt;overflow-y&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;width&lt;/td&gt;
&lt;td&gt;height&lt;/td&gt;
&lt;td&gt;min-width&lt;/td&gt;
&lt;td&gt;min-height&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;padding&lt;/td&gt;
&lt;td&gt;margin&lt;/td&gt;
&lt;td&gt;border&lt;/td&gt;
&lt;td&gt;border-width&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;top&lt;/td&gt;
&lt;td&gt;bottom&lt;/td&gt;
&lt;td&gt;left&lt;/td&gt;
&lt;td&gt;right&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;font&lt;/td&gt;
&lt;td&gt;font-family&lt;/td&gt;
&lt;td&gt;font-size&lt;/td&gt;
&lt;td&gt;font-weight&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;white-space&lt;/td&gt;
&lt;td&gt;line-height&lt;/td&gt;
&lt;td&gt;vertical-align&lt;/td&gt;
&lt;td&gt;float&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;clear&lt;/td&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;3. Paint&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;&amp;lt;적용되는 속성&amp;gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style4&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;color&lt;/td&gt;
&lt;td style=&quot;width: 24.3023%;&quot;&gt;background&lt;/td&gt;
&lt;td style=&quot;width: 25.9303%;&quot;&gt;visibility&lt;/td&gt;
&lt;td style=&quot;width: 24.6511%;&quot;&gt;text-deocration&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;background-image&lt;/td&gt;
&lt;td style=&quot;width: 24.3023%;&quot;&gt;background-position&lt;/td&gt;
&lt;td style=&quot;width: 25.9303%;&quot;&gt;background-repeat&lt;/td&gt;
&lt;td style=&quot;width: 24.6511%;&quot;&gt;background-size&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;outline&lt;/td&gt;
&lt;td style=&quot;width: 24.3023%;&quot;&gt;outline-color&lt;/td&gt;
&lt;td style=&quot;width: 25.9303%;&quot;&gt;outline-style&lt;/td&gt;
&lt;td style=&quot;width: 24.6511%;&quot;&gt;outline-width&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;border-radius&lt;/td&gt;
&lt;td style=&quot;width: 24.3023%;&quot;&gt;border-style&lt;/td&gt;
&lt;td style=&quot;width: 25.9303%;&quot;&gt;box-shadow&lt;/td&gt;
&lt;td style=&quot;width: 24.6511%;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&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;4. Composite&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;브라우저가 레이어(z-index) 순으로 객체를 화면에 그림&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 17px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50.2325%;&quot;&gt;transform&lt;/td&gt;
&lt;td style=&quot;width: 49.6512%;&quot;&gt;opacity&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&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;스타일&amp;nbsp;성능&amp;nbsp;최적화&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 순서에 따라 Layout 속성을 바꾸면 Paint, Composite 순서를 거치기 때문에 성능 저하가 발생하고 이를 &lt;b&gt;Reflow&lt;/b&gt;라 합니다. 또한 Paint 속성을 바꾸면 Composite 순서를 거치기 때문에 성능 저하가 발생하고 이를 &lt;b&gt;Repaint&lt;/b&gt;라 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서 최대 성능을 위해 최대한 적은 순서를 거치도록 Composite 속성만 바꿔야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1657353261606&quot; class=&quot;css&quot; data-ke-language=&quot;css&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;.banner{
    left: -100px;
    transition: left 0.2s ease;
}

.banner-move .banner{
    left: 0px;
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1657353294507&quot; class=&quot;css&quot; data-ke-language=&quot;css&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;.banner{
    transform: translateX(-100px);
    transition: transform 0.2s ease;
}

.banner-move .banner{
    transition: none;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;첫 번째 코드에서는 left가 변할 시 Layout-&amp;gt;Paint-&amp;gt;Composite 순서를 거치게 되고&lt;br /&gt;두 번째 코드에서는 transform이 변할 시 Composite 순서만 거치게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1657353228899&quot; data-ke-language=&quot;css&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;  left: ${(props) =&amp;gt; `${props.left}px`};
  transition: left 0.2s ease;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 저의 경우 Next.js에서 Styled-components를 사용 중이고 배너의 개수가 고정된 것이 아닌 가변적인 여러 개의 배너를 띄울 수 도 있고 적용되는 스타일의 값이 변하므로 항상 Style-&amp;gt;Layout-&amp;gt;Patin-&amp;gt;Composite의 모든 순서를 거치게 됩니다. 즉, 다른 방법을 모색해야 합니다.&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;will-change 속성&lt;/b&gt;&lt;/h2&gt;
&lt;pre id=&quot;code_1657354400404&quot; class=&quot;css&quot; data-ke-language=&quot;css&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;will-change: 속성명;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;will-change 속성은 브라우저에게 값이 변경될 속성에 대한 힌트를 미리 지정해주어 앞으로 동적으로 변화할 값을 알고 부드러운 이벤트를 구사할 수 있게 해주는 속성입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;GPU 가속을 이용하여 애니메이션의 프레임을 최대로 끌어올릴 수 있습니다.&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;a href=&quot;https://developer.mozilla.org/ko/docs/Web/CSS/will-change&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;MDN web docs&lt;/a&gt;에 있는 글에 따르면 이 속성을 너무 남발해서는 안된다고 합니다. 이미 페이지가 잘 돌아간다면 사용하지 말고 당장의 성능 문제를 빠르게 해결하기 위한 마지막 수단으로 사용되기 위해 만들어진 속성이며, 너무나도 많은 will-change의 사용은 과도한 메모리 사용과 복잡한 렌더링을 초래할 수 있다고 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한 will-change 속성은 애니메이션이 종료되었을 때 속성을 제거해주는 것을 권장하고 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1657354658508&quot; class=&quot;css&quot; data-ke-language=&quot;css&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;will-change: auto;&lt;/code&gt;&lt;/pre&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;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(아래의 코드에서 props는 리액트 컴포넌트에 전달하기 위한 값으로 해당 styled-component에 left값을 변수로 내려주는 역할을 한다고 보시면 될 것 같습니다.)&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;407&quot; data-origin-height=&quot;67&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/wcj70/btrGQZs2AsR/a1BW5Q6hkqtdXOsFZ4W7l0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/wcj70/btrGQZs2AsR/a1BW5Q6hkqtdXOsFZ4W7l0/img.png&quot; data-alt=&quot;bannerNum에 따라 다른 left값을 props로 전달&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/wcj70/btrGQZs2AsR/a1BW5Q6hkqtdXOsFZ4W7l0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fwcj70%2FbtrGQZs2AsR%2Fa1BW5Q6hkqtdXOsFZ4W7l0%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;407&quot; height=&quot;67&quot; data-origin-width=&quot;407&quot; data-origin-height=&quot;67&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;bannerNum에 따라 다른 left값을 props로 전달&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;transition : left&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;left.gif&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;158&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/blpo4f/btrGRG7yXp5/lMdVujPUKX64Fry7KX4uw0/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/blpo4f/btrGRG7yXp5/lMdVujPUKX64Fry7KX4uw0/img.gif&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/blpo4f/btrGRG7yXp5/lMdVujPUKX64Fry7KX4uw0/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/blpo4f/btrGRG7yXp5/lMdVujPUKX64Fry7KX4uw0/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;600&quot; height=&quot;158&quot; data-filename=&quot;left.gif&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;158&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre id=&quot;code_1657352059892&quot; class=&quot;css&quot; data-ke-language=&quot;css&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt; left: ${(props) =&amp;gt; `${props.left}px`};
 transition: left 0.2s ease;&lt;/code&gt;&lt;/pre&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;transition : transform&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;transform.gif&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;158&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xJuct/btrGUsUPpS5/kBlQ7WXyfby1vnMwSa6SJ1/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xJuct/btrGUsUPpS5/kBlQ7WXyfby1vnMwSa6SJ1/img.gif&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xJuct/btrGUsUPpS5/kBlQ7WXyfby1vnMwSa6SJ1/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/xJuct/btrGUsUPpS5/kBlQ7WXyfby1vnMwSa6SJ1/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;600&quot; height=&quot;158&quot; data-filename=&quot;transform.gif&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;158&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre id=&quot;code_1657352085705&quot; class=&quot;css&quot; data-ke-language=&quot;css&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt; transform: ${(props) =&amp;gt; `translateX(${props.left}px)`};
 transition: transform 0.2s ease;&lt;/code&gt;&lt;/pre&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;transition : left + whill-change&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;left-will.gif&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;158&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eMaJsO/btrGTxWoo70/Rb70hgpZsplxS1Tg7dzey0/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eMaJsO/btrGTxWoo70/Rb70hgpZsplxS1Tg7dzey0/img.gif&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eMaJsO/btrGTxWoo70/Rb70hgpZsplxS1Tg7dzey0/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/eMaJsO/btrGTxWoo70/Rb70hgpZsplxS1Tg7dzey0/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;600&quot; height=&quot;158&quot; data-filename=&quot;left-will.gif&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;158&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre id=&quot;code_1657352104700&quot; class=&quot;css&quot; data-ke-language=&quot;css&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;left: ${(props) =&amp;gt; `${props.left}px`};
transition: left 0.2s ease;
will-change: transform;&lt;/code&gt;&lt;/pre&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;transition : transform + whill-change&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;transform-will.gif&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;158&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bFYZce/btrGS47X392/S4U4ZKZtDKshUcXPdFfa10/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bFYZce/btrGS47X392/S4U4ZKZtDKshUcXPdFfa10/img.gif&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bFYZce/btrGS47X392/S4U4ZKZtDKshUcXPdFfa10/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/bFYZce/btrGS47X392/S4U4ZKZtDKshUcXPdFfa10/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;600&quot; height=&quot;158&quot; data-filename=&quot;transform-will.gif&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;158&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre id=&quot;code_1657352140949&quot; class=&quot;css&quot; data-ke-language=&quot;css&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;transform: ${(props) =&amp;gt; `translateX(${props.left}px)`};
transition: transform 0.2s ease;
will-change: transform;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;will-change를 사용 후 애니메이션 속도가 확실히 빨라진 것을 체감하였습니다. 그러나 너무 남발하면 안 될 것 같은 속성이고 급한 불을 끄기 위한 속성 같아 보입니다. 따라서 사이트의 속도를 최대로 끌어올리기 위해서는 근본적인 문제(이미지의 크기, 압축, 최적화)를 해결해야 하지 않을까 싶습니다.&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 data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;  참고&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://aproid.github.io/2019/03/21/transition-optimize/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://aproid.github.io/2019/03/21/transition-optimize/&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://developer.mozilla.org/ko/docs/Web/CSS/will-change&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://developer.mozilla.org/ko/docs/Web/CSS/will-change&lt;/a&gt;&lt;/p&gt;</description>
      <category> WEB</category>
      <category>바</category>
      <author>Cocoon_</author>
      <guid isPermaLink="true">https://cocoon1787.tistory.com/862</guid>
      <comments>https://cocoon1787.tistory.com/862#entry862comment</comments>
      <pubDate>Sat, 9 Jul 2022 17:24:36 +0900</pubDate>
    </item>
    <item>
      <title>[React] Warning: validateDOMNesting(...): &amp;lt;p&amp;gt; cannot appear as a descendant of &amp;lt;p&amp;gt;. 오류 해결</title>
      <link>https://cocoon1787.tistory.com/861</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1550&quot; data-origin-height=&quot;760&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bNFOdP/btrFvsvAb7y/kbIH97QbEFuxWCaCvE62dK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bNFOdP/btrFvsvAb7y/kbIH97QbEFuxWCaCvE62dK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bNFOdP/btrFvsvAb7y/kbIH97QbEFuxWCaCvE62dK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbNFOdP%2FbtrFvsvAb7y%2FkbIH97QbEFuxWCaCvE62dK%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;1550&quot; height=&quot;760&quot; data-origin-width=&quot;1550&quot; data-origin-height=&quot;760&quot;/&gt;&lt;/span&gt;&lt;/figure&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;무슨 문제인가 구글링하여 찾아보니 p태그 내부에 p태그를 넣으면 생기는 오류라고합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;329&quot; data-origin-height=&quot;196&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/blqBIS/btrFt8x7lT7/o8nC4uL5EVCG1ccJ86AXK0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/blqBIS/btrFt8x7lT7/o8nC4uL5EVCG1ccJ86AXK0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/blqBIS/btrFt8x7lT7/o8nC4uL5EVCG1ccJ86AXK0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FblqBIS%2FbtrFt8x7lT7%2Fo8nC4uL5EVCG1ccJ86AXK0%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;329&quot; height=&quot;196&quot; data-origin-width=&quot;329&quot; data-origin-height=&quot;196&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;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;948&quot; data-origin-height=&quot;32&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bUfF4m/btrFsYCLyeW/2QnSkaWOvrTQcqSgBwvjrK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bUfF4m/btrFsYCLyeW/2QnSkaWOvrTQcqSgBwvjrK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bUfF4m/btrFsYCLyeW/2QnSkaWOvrTQcqSgBwvjrK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbUfF4m%2FbtrFsYCLyeW%2F2QnSkaWOvrTQcqSgBwvjrK%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;948&quot; height=&quot;32&quot; data-origin-width=&quot;948&quot; data-origin-height=&quot;32&quot;/&gt;&lt;/span&gt;&lt;/figure&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;오류 메시지 제대로 읽지도않고 자동반사로 ctrl+c, ctrl+v로 구글링해서 찾아봤네요  &lt;/p&gt;</description>
      <category>⚛️React</category>
      <author>Cocoon_</author>
      <guid isPermaLink="true">https://cocoon1787.tistory.com/861</guid>
      <comments>https://cocoon1787.tistory.com/861#entry861comment</comments>
      <pubDate>Wed, 22 Jun 2022 19:48:44 +0900</pubDate>
    </item>
    <item>
      <title>[OS] 페이징(Paging)과 세그멘테이션(Segmentation)</title>
      <link>https://cocoon1787.tistory.com/860</link>
      <description>&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;810&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ctAORr/btrEeYoUkIg/jac0da0lpV3SoA0XDN6AL1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ctAORr/btrEeYoUkIg/jac0da0lpV3SoA0XDN6AL1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ctAORr/btrEeYoUkIg/jac0da0lpV3SoA0XDN6AL1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FctAORr%2FbtrEeYoUkIg%2Fjac0da0lpV3SoA0XDN6AL1%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;1444&quot; height=&quot;810&quot; data-origin-width=&quot;1444&quot; data-origin-height=&quot;810&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;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt; &lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;어떠한 프로그램을 실행할 때, 컴퓨터에서는 프로그램들을 메모리 공간에 연속적으로 할당하게 됩니다. 만약 여러 프로그램들이 메모리에 할당되고 해제되는 것이 반복되다 보면 메모리 공간이 조각조각 나뉘게 되어 총메모리가 충분함에도 불구하고 프로그램에 메모리를 할당하는 것이 불가능한 상태가 발생하게 됩니다. 이러한 현상을 바로 메모리 단편화라고 하며, 이번 포스팅은 메모리 단편화 해결방법인 페이징과 세그멘테이션에 대해 알아보도록 하겠습니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;  &lt;b&gt;추천 링크&lt;/b&gt;&lt;span&gt; - &lt;/span&gt;&lt;b&gt;[메모리 단편화란?]&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://cocoon1787.tistory.com/859&quot;&gt;https://cocoon1787.tistory.com/859&lt;/a&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;/b&gt;&lt;/h2&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;메모리 관리 기법&lt;/b&gt;&lt;/h4&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;연속 메모리 기법&lt;/b&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;b&gt;내부 단편화 발생&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;동적 분할 기법 : 파티션들이 동적으로 생성되고 자신의 크기와 같은 파티션에 메모리 할당. &lt;b&gt;외부 단편화 발생&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;불연속 메모리 기법&lt;/b&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;Page : 프로세스를 고정된 크기로 나눈 블록&lt;/li&gt;
&lt;li&gt;Frame : 메모리를 고정된 크기로 나는 블록&lt;/li&gt;
&lt;li&gt;Segment : 서로 다른 크기의 논리적 블록&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;가상 메모리&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;884&quot; data-origin-height=&quot;570&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/B8mdX/btrEc3rcdi7/YWqKXJZotCTpzXTM4kCeu1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/B8mdX/btrEc3rcdi7/YWqKXJZotCTpzXTM4kCeu1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/B8mdX/btrEc3rcdi7/YWqKXJZotCTpzXTM4kCeu1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FB8mdX%2FbtrEc3rcdi7%2FYWqKXJZotCTpzXTM4kCeu1%2Fimg.jpg&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;508&quot; height=&quot;570&quot; data-origin-width=&quot;884&quot; data-origin-height=&quot;570&quot;/&gt;&lt;/span&gt;&lt;/figure&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;/li&gt;
&lt;li&gt;프로세스의 일부분만 메모리에 로드하고 나머지는 보조 기억 장치(가상 메모리 공간)에 할당&lt;/li&gt;
&lt;li&gt;MMU(Memory&amp;nbsp;Management&amp;nbsp;Unit)를 통해 논리 주소, 물리 주소를 나누어서 사용&lt;/li&gt;
&lt;li&gt;가상 주소를 주기억장치의 실제적인 주소로 매핑(Mapping)하는 방법을 통해 구현&lt;/li&gt;
&lt;/ul&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;페이징(Paging)&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;950&quot; data-origin-height=&quot;479&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/yaaix/btrEdsK3PPJ/0U6gkxhlTGah6p0kg4mrL1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/yaaix/btrEdsK3PPJ/0U6gkxhlTGah6p0kg4mrL1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/yaaix/btrEdsK3PPJ/0U6gkxhlTGah6p0kg4mrL1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fyaaix%2FbtrEdsK3PPJ%2F0U6gkxhlTGah6p0kg4mrL1%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;950&quot; height=&quot;479&quot; data-origin-width=&quot;950&quot; data-origin-height=&quot;479&quot;/&gt;&lt;/span&gt;&lt;/figure&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;/li&gt;
&lt;li&gt;메모리는 Frame이라는 고정크기로 분할되고, 프로세스는 Page라는 고정크기로 분할됨&lt;/li&gt;
&lt;li&gt;페이지와 프레임은 크기가 같음&lt;/li&gt;
&lt;li&gt;페이지와 프레임을 대응시키는 page mapping 과정이 필요하여 paging table을 생성해야 함&lt;/li&gt;
&lt;li&gt;연속적이지 않은 공간도 활용할 수 있기 때문에 외부 단편화 문제 해결&lt;/li&gt;
&lt;li&gt;페이지 테이블에는 각 페이지 번호와 해당 페이지가 할당된 프레임의 시작 물리 주소를 저장&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;b&gt;But, 프로세스의 크기가 페이지 크기의 배수가 아닐 경우 마지막 페이지에 내부 단편화가 발생하고 페이지의 크기가 클수록 내부 단편화가 커짐&lt;br /&gt;&lt;/b&gt;=&amp;gt; 페이지 단위를 작게 하면 내부 단편화 문제도 해결할 수 있겠지만 page mapping 과정이 많아지므로 효율이 떨어짐&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;세그멘테이션(Segmentation)&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;950&quot; data-origin-height=&quot;507&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/22MDs/btrEcQMrq7W/FoKKXCHIBOvfcsu9YvU18k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/22MDs/btrEcQMrq7W/FoKKXCHIBOvfcsu9YvU18k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/22MDs/btrEcQMrq7W/FoKKXCHIBOvfcsu9YvU18k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F22MDs%2FbtrEcQMrq7W%2FFoKKXCHIBOvfcsu9YvU18k%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;950&quot; height=&quot;507&quot; data-origin-width=&quot;950&quot; data-origin-height=&quot;507&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;프로세스를 서로 크기가 다른 논리적인 블록 단위인 세그먼트(Segment)로 분할하여 메모리에 할당&lt;/li&gt;
&lt;li&gt;각 세그먼트는 연속적인 공간에 저장&lt;/li&gt;
&lt;li&gt;세그먼트들의 크기가 서로 다르기 때문에 프로세스가 메모리에 적재될 때 빈 공간을 찾아 할당하는 기법&lt;/li&gt;
&lt;li&gt;페이징과 마찬가지로 mapping을 위한 segment table 필요&lt;/li&gt;
&lt;/ul&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;b&gt;But, 프로세스가 필요한 메모리 공간만큼 메모리를 할당해주기 때문에 내부 단편화 문제는 발생하지 않지만, 중간에 메모리를 해제하면 생기는 외부 단편화 문제가 발생&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;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;⚖️ Paging vs Segmentation&lt;/b&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Paging은 고정 크기를 가짐&lt;/li&gt;
&lt;li&gt;Segmentation은 가변 크기를 가짐&lt;/li&gt;
&lt;li&gt;Paging은 내부 단편화 발생 가능, Segmentation은 외부 단편화 발생 가능&lt;/li&gt;
&lt;/ul&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 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;</description>
      <category>⚙️OS</category>
      <author>Cocoon_</author>
      <guid isPermaLink="true">https://cocoon1787.tistory.com/860</guid>
      <comments>https://cocoon1787.tistory.com/860#entry860comment</comments>
      <pubDate>Thu, 9 Jun 2022 05:49:06 +0900</pubDate>
    </item>
    <item>
      <title>[OS] 메모리 단편화(Memory Fragmentation)란?</title>
      <link>https://cocoon1787.tistory.com/859</link>
      <description>&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;810&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qmNDV/btrEdrL58Mz/soWKgyCmYlr3eORthYxRM0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qmNDV/btrEdrL58Mz/soWKgyCmYlr3eORthYxRM0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qmNDV/btrEdrL58Mz/soWKgyCmYlr3eORthYxRM0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqmNDV%2FbtrEdrL58Mz%2FsoWKgyCmYlr3eORthYxRM0%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;1444&quot; height=&quot;810&quot; data-origin-width=&quot;1444&quot; data-origin-height=&quot;810&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;
&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;  메모리 단편화(Memory Fragmentation)의 정의&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컴퓨터에서 프로그램을 실행하거나 작업을 할 때 컴퓨터는 메모리에 해당 프로그램을 올리고 실행을 하게 됩니다. &lt;br /&gt;이때 주기억장치 상에서 빈번하게 기억 장소가 할당되고 반납됨에 따라 &lt;b&gt;메모리 공간이 작은 조각 공간&lt;/b&gt;으로 나뉘게 될 경우, 사용 가능한 메모리가 충분함에도 불구하고 메모리 할당이 불가능한 상태가 발생하게 되는데, 이를 &lt;b&gt;메모리 단편화&lt;/b&gt;라고 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;메모리 단편화의 종류로는 &lt;b&gt;내부 단편화&lt;/b&gt;와 &lt;b&gt;외부&amp;nbsp;단편화&lt;/b&gt;가 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;  내부 단편화&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;506&quot; data-origin-height=&quot;445&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/WwRcT/btrEeJyk5pT/eLhvmks2WVeO1pveamkkbk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/WwRcT/btrEeJyk5pT/eLhvmks2WVeO1pveamkkbk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/WwRcT/btrEeJyk5pT/eLhvmks2WVeO1pveamkkbk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FWwRcT%2FbtrEeJyk5pT%2FeLhvmks2WVeO1pveamkkbk%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;355&quot; height=&quot;312&quot; data-origin-width=&quot;506&quot; data-origin-height=&quot;445&quot;/&gt;&lt;/span&gt;&lt;/figure&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;b&gt;주기억장치 내의 실행 프로그램보다 사용자 영역이 커서 메모리 할당 후 사용되지 않고 남아있는 공간을 의미&lt;/b&gt;&lt;/li&gt;
&lt;/ul&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;b&gt;&amp;lt;예시&amp;gt;&lt;/b&gt;&lt;br /&gt;메모장을 실행시키고 OS가 4KB만큼의 메모리를 할당해주었지만 사실상 1KB만큼만 사용하고 있을 때 필요 이상으로 프로세스가 메모리를 할당받았기 때문에 내부 단편화가 3KB만큼 생김&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;  외부 단편화&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1132&quot; data-origin-height=&quot;454&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cNKIJs/btrEcOObp2A/OxWKBlVD8DGkZkJkcpF98k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cNKIJs/btrEcOObp2A/OxWKBlVD8DGkZkJkcpF98k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cNKIJs/btrEcOObp2A/OxWKBlVD8DGkZkJkcpF98k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcNKIJs%2FbtrEcOObp2A%2FOxWKBlVD8DGkZkJkcpF98k%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;1132&quot; height=&quot;454&quot; data-origin-width=&quot;1132&quot; data-origin-height=&quot;454&quot;/&gt;&lt;/span&gt;&lt;/figure&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;b&gt;주기억장치 내의 사용자 영역보다 실행 프로그램이 커서 프로그램이 메모리가 할당되지 않고 남아있는 공간을 의미&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;메모리가 할당되고 해제되는 작업이 반복적으로 일어날 때 발생&lt;/b&gt;&lt;/li&gt;
&lt;/ul&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;b&gt;&amp;lt;예시&amp;gt;&lt;/b&gt;&lt;br /&gt;메모리 처음 주소에 프로세스를 4KB만큼 할당하고 바로 이어서 8KB만큼의 메모리를 또 다른 프로세스에게 할당했다고 가정할 때, 4KB만큼의 메모리를 할당하고 있던 프로세스를 종료시키면 메모리의 처음 주소부터 4KB만큼의 공간이 생기게 되고 이런 식으로 계속해서 빈 메모리 공간 생기게 되면 전체적으로 메모리 여유는 있지만 메모리를 많이 잡아먹는 프로세스를 실행시킬 수 없는 현상&amp;nbsp;&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 data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>⚙️OS</category>
      <author>Cocoon_</author>
      <guid isPermaLink="true">https://cocoon1787.tistory.com/859</guid>
      <comments>https://cocoon1787.tistory.com/859#entry859comment</comments>
      <pubDate>Wed, 8 Jun 2022 10:57:10 +0900</pubDate>
    </item>
    <item>
      <title>[OS] 교착상태(Deadlock, 데드락)의 정의, 발생 조건, 해결 방법</title>
      <link>https://cocoon1787.tistory.com/858</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1446&quot; data-origin-height=&quot;810&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nNqIu/btrEd5BC9YG/k7bL10OoHS2kbUMRuCaZj0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nNqIu/btrEd5BC9YG/k7bL10OoHS2kbUMRuCaZj0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nNqIu/btrEd5BC9YG/k7bL10OoHS2kbUMRuCaZj0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FnNqIu%2FbtrEd5BC9YG%2Fk7bL10OoHS2kbUMRuCaZj0%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;1446&quot; height=&quot;810&quot; data-origin-width=&quot;1446&quot; data-origin-height=&quot;810&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt; &lt;/h2&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;안녕하세요. 이번 포스팅은 NSC 전공시험이나 신입 기술면접에서도 자주 등장하는 주제인 &lt;/b&gt;&lt;br /&gt;&lt;b&gt;교착상태(Deadlock)에 대해 한번 알아보고자 합니다.&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;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 alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;946&quot; data-origin-height=&quot;813&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xVu3c/btrEc3xU5u8/4zLX6it423piByeKW3SJLk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xVu3c/btrEc3xU5u8/4zLX6it423piByeKW3SJLk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xVu3c/btrEc3xU5u8/4zLX6it423piByeKW3SJLk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxVu3c%2FbtrEc3xU5u8%2F4zLX6it423piByeKW3SJLk%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;449&quot; height=&quot;813&quot; data-origin-width=&quot;946&quot; data-origin-height=&quot;813&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;교착상태란 두 개 이상의 프로세스가 자원을 점유한 상태에서 서로 다른 프로세스가 점유하고 있는 자원을 요구하며, 서로의 작업을 끝나기만을 기다리며 둘 다 영원히 끝나지 않는 상황을 뜻합니다.&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;&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;  교착상태의 발생 조건 4가지&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;교착상태는 아래의 4가지 조건이 모두 만족되는 경우(필요충분조건)에 발생할 가능성이 있으며,&lt;br /&gt;하나라도 만족하지 않으면 교착상태가 발생하지 않습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;1. 상호 배제(Mutual Exclusion)&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한 번에 한 개의 프로세스만이 공유자원을 사용할 수 있음&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;2. 점유 대기(Hold and Wait)&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로세스가 할당된 자원을 가진 상태에서 다른 자원을 기다림&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;3. 비선점(No Preemption)&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로세스가 작업을 마친 후 자원을 자발적으로 반환할 때까지 기다림&lt;br /&gt;(이미 할당된 자원을 강제적으로 빼앗을 수 없음)&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;4. 순환 대기(Circular Wait)&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로세스의 자원 점유 및 점유된 자원의 요구 관계가 원형을 이루면서 대기하는 조건.&lt;br /&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;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;-&amp;nbsp; 예방(Prevention)&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;교착상태 예방 방법은 교착상태가 애초에 일어나지 않도록 방지하는 방법으로 교착상태의 발생조건 4가지 중 하나를 부정함으로써 교착상태를 예방하는 방법입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;1. 상호 배제 부정&lt;br /&gt;&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;여러 개의 프로세스가 동시에 공유자원을 사용할 수 있음&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;2. 점유 대기 부정&lt;br /&gt;&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;프로세스가 실행되기 전에 필요한 모든 자원을 할당하여 프로세스 대기를 없애거나, 자원이 점유되지 않은 상태에서만 자원 요청을 받도록 함&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;3. 비선점 부정&lt;br /&gt;&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;모든 자원에 대한 선점을 허용&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;4. 순환 대기 부정&lt;br /&gt;&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;자원을 선형으로 분류하여 고유 번호를 할당하고, 각 프로세스는 현재 점유한 자원의 고유번호보다 앞이나 뒤 한쪽 방향으로만 자원을 요구하도록 함&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러나 이렇게 교착상태 발생조건을 방지해서 데드락을 예방하는 방법은 &lt;u&gt;시스템 처리량이나 자원 사용의 효율성을 떨어트리는 단점&lt;/u&gt;이 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;-&amp;nbsp; 회피(Avoidance)&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;교착상태가 발생할 가능성이 있는 자원 할당(Unsafe allocation)을 하지 않고 안전한 상태(Safe state)에서만 자원 요청을 허용하는 방법입니다. 하지만 교착상태 회피를 하기 위해서는 아래와 같은 가정이 필요합니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;프로세스 수 고정&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;자원의 종류와 수 고정&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;프로세스가 요구하는 최대 자원의 수를 알아야 함&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;프로세스는 자원 사용 후 반드시 반납&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;Safe state&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;safe sequence(교착상태를 발생시키지 않고 자원을 할당하는 순서)가 존재하며 모든 프로세스가 정상적으로 종료될 수 있는 상태를 의미&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;Unsafe state&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;교착상태를 회피하기 위한 알고리즘으로 크게 두 가지가 있습니다.&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p id=&quot;-은행원-알고리즘bankers-algorithm&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;  은행원 알고리즘&lt;b&gt;(Banker's Algorithm)&lt;/b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다익스트라가 제안한 기법으로, 은행에서 모든 고객의 요구를 충족할 수 있도록 현금을 대출해주는 것에서 유래하였습니다. 은행원 알고리즘은 자원 할당 결정전에 예상되는 모든 자원의 최대 할당량을 가지고 시뮬레이션을 하여 safe state에 들 수 있는지 여부를 검사하여 교착상태의 가능성을 미리 조사하는 알고리즘입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본 개념 자체는 &lt;i&gt;&lt;b&gt;&quot;CPU는 최소한 하나의 프로세스에게 할당해줄 만큼의 자원을 항상 보유하고 있어야 한다&quot; &lt;/b&gt;&lt;/i&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;b&gt;&amp;lt;예시&amp;gt;&lt;/b&gt; 시스템은 총 12개의 자원을 가지고 있다고 가정&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 62px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;height: 17px; width: 10.2326%; text-align: center;&quot;&gt;&lt;b&gt;(t=t0)&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;height: 17px; width: 23.8372%; text-align: center;&quot;&gt;&lt;b&gt;최대 자원 요청량&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;height: 17px; width: 25.465%; text-align: center;&quot;&gt;&lt;b&gt;할당중인 자원량&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;height: 17px; width: 20.6977%; text-align: center;&quot;&gt;&lt;b&gt;남은 필요한 자원의 양&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 11px;&quot;&gt;
&lt;td style=&quot;height: 11px; width: 10.2326%; text-align: center;&quot;&gt;&lt;b&gt;P0&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;height: 11px; width: 23.8372%; text-align: center;&quot;&gt;&lt;b&gt;10&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;height: 11px; width: 25.465%; text-align: center;&quot;&gt;&lt;b&gt;5&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;height: 11px; width: 20.6977%; text-align: center;&quot;&gt;&lt;b&gt;5&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;height: 17px; width: 10.2326%; text-align: center;&quot;&gt;&lt;b&gt;P1&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;height: 17px; width: 23.8372%; text-align: center;&quot;&gt;&lt;b&gt;4&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;height: 17px; width: 25.465%; text-align: center;&quot;&gt;&lt;b&gt;2&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;height: 17px; width: 20.6977%; text-align: center;&quot;&gt;&lt;b&gt;2&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;height: 17px; width: 10.2326%; text-align: center;&quot;&gt;&lt;b&gt;P2&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;height: 17px; width: 23.8372%; text-align: center;&quot;&gt;&lt;b&gt;9&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;height: 17px; width: 25.465%; text-align: center;&quot;&gt;&lt;b&gt;2&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;height: 17px; width: 20.6977%; text-align: center;&quot;&gt;&lt;b&gt;7&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재 할당 중인 자원량의 합 은 &lt;b&gt;5+2+2 = 9&lt;/b&gt; 입니다. 시스템은 총 12개의 자원을 가지고 있으므로 현재 상태에서 가용 자원량은 &lt;b&gt;12 - 9 = 3&lt;/b&gt; 이 됩니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 가용자원을 어느 프로세스에게 할당해주느냐에 따라서 자원을 효율적으로 이용할 수 있게 됩니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;남은 가용자원 3개를 P1에게 할당 =&amp;gt; &lt;b&gt;가용자원은 3 - 2 = 1&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;P1의 작업이 끝나고 할당되어 있던 자원&amp;nbsp; 4개 반납 =&amp;gt; &lt;b&gt;가용자원은 1 + 4 = 5&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;남은 가용자원 5개를 P0에게 할당 =&amp;gt; &lt;b&gt;가용자원은 5 - 5 = 0&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;P0의 작업이 끝나고 할당되어 있던 자원 10개 반납 =&amp;gt; &lt;b&gt;가용자원은 0 + 10 = 10&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;남은 가용자원 10개 중 7개를 P2에게 할당 =&amp;gt; &lt;b&gt;가용자원은 10 - 7 = 3&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;P2의 작업이 끝나고 할당되어 있던 자원 9개 반납 =&amp;gt;&amp;nbsp;&lt;b&gt;가용자원은 3 + 9 = 12&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 P1 - P0 - P2 순서로 자원 할당 시 Safe sequence를 만족하게 됩니다.&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;이처럼 교착상태 회피 방법의 가장 큰 문제는 &lt;u&gt;문제 발생에 대한 일관성과 가정이 완벽할 것이라는 것을 보장하기가 현실적으로 어렵다는 점&lt;/u&gt;입니다. 시스템의 규모가 작은 운영체제라면 고려해볼 만한 방법이지만, 멀티 리소스, 멀티 프로세스의 복잡한 운영체제 환경에서는 자원 할당 그래프를 분석하면서 Safe state를 파악하기가 상당히 어렵습니다.&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;  자원 할당 그래프 알고리즘&lt;b&gt;(&lt;b&gt;Resource-Allocation Graph Algorithm&lt;/b&gt;)&lt;/b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;/b&gt;자원 할당 그래프에 예약 간선을 추가하여 예약 간선으로 설정한 자원에 대해서만 자원 할당을 요청할 수 있고 사이클이 형성되지 않을 때만 자원을 할당받는 방법입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #666666;&quot;&gt;&lt;i&gt;자원 할당 그래프 : 프로세스가 어떤 자원을 사용 중이고, 어떤 자원을 기다리는지 방향성 있는 그래프로 표시한 것&lt;br /&gt;&lt;i&gt;예약 간선 : 향후 요청할 수 있는 자원을 가리키는 점선으로 표시된 간선&lt;/i&gt;&lt;br /&gt;&lt;/i&gt;&lt;/span&gt;&lt;span style=&quot;color: #666666;&quot;&gt;&lt;i&gt;&lt;/i&gt;&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;color: #666666;&quot;&gt;&lt;/span&gt;&lt;b&gt;&amp;lt;예시&amp;gt; &lt;/b&gt;그래프에서 사이클 발생 시 교착상태일 가능성이 있음&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;450&quot; data-origin-height=&quot;666&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/5KP6r/btrEbDmsXru/ynb8xo1e4hgckSbKlZ6QfK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/5KP6r/btrEbDmsXru/ynb8xo1e4hgckSbKlZ6QfK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/5KP6r/btrEbDmsXru/ynb8xo1e4hgckSbKlZ6QfK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F5KP6r%2FbtrEbDmsXru%2Fynb8xo1e4hgckSbKlZ6QfK%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;450&quot; height=&quot;666&quot; data-origin-width=&quot;450&quot; data-origin-height=&quot;666&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;상호 배제 : R1, R2, R3, R4&lt;br /&gt;점유 대기 : P1, P2&lt;br /&gt;비선점 : O&lt;br /&gt;순환 대기 : X&lt;br /&gt;=&amp;gt; 교착상태 X&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 alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;456&quot; data-origin-height=&quot;673&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/pfGF7/btrEc3dC9VO/BUKAmPkpAC5OjlOJnMpSJ0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/pfGF7/btrEc3dC9VO/BUKAmPkpAC5OjlOJnMpSJ0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/pfGF7/btrEc3dC9VO/BUKAmPkpAC5OjlOJnMpSJ0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FpfGF7%2FbtrEc3dC9VO%2FBUKAmPkpAC5OjlOJnMpSJ0%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;456&quot; height=&quot;673&quot; data-origin-width=&quot;456&quot; data-origin-height=&quot;673&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;상호 배제 : R1, R2, R3, R4&lt;br /&gt;점유 대기 : P1, P2, P3&lt;br /&gt;비선점 : O&lt;br /&gt;순환 대기 : O&lt;br /&gt;=&amp;gt; 교착상태 O&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;533&quot; data-origin-height=&quot;682&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nEh30/btrEejmxqx4/iq5IFSCmFAkdxzxfk3goLK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nEh30/btrEejmxqx4/iq5IFSCmFAkdxzxfk3goLK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nEh30/btrEejmxqx4/iq5IFSCmFAkdxzxfk3goLK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FnEh30%2FbtrEejmxqx4%2Fiq5IFSCmFAkdxzxfk3goLK%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;533&quot; height=&quot;682&quot; data-origin-width=&quot;533&quot; data-origin-height=&quot;682&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;상호 배제 : R1, R2&lt;br /&gt;점유 대기 : P1, P3&lt;br /&gt;비선점 : O&lt;br /&gt;순환 대기 : O&lt;br /&gt;=&amp;gt; 교착상태 X (P4가 R2를 해제하면 해결)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;-&amp;nbsp; 탐지(Detection)&lt;/b&gt;&lt;/h4&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;-&amp;nbsp; 회복(Recovery)&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;교착상태 회복 기법은 교착상태가 발생했을 때 해결하는 기법을 의미합니다.&lt;/p&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;교착상태에 있는 프로세스 중 하나의 프로세스를 사용자가 강제 종료&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;2. 시스템 처리&lt;/b&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;프로세스 중지&amp;nbsp;&lt;/b&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;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;자원 선점&lt;/b&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;/ul&gt;
&lt;/li&gt;
&lt;/ol&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;</description>
      <category>⚙️OS</category>
      <author>Cocoon_</author>
      <guid isPermaLink="true">https://cocoon1787.tistory.com/858</guid>
      <comments>https://cocoon1787.tistory.com/858#entry858comment</comments>
      <pubDate>Wed, 8 Jun 2022 03:14:51 +0900</pubDate>
    </item>
    <item>
      <title>[AWS] EC2 원격 인스턴스에서 열린 포트 확인 방법</title>
      <link>https://cocoon1787.tistory.com/857</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;706&quot; data-origin-height=&quot;374&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/t0wJe/btrDQFRawra/cp0QZTrR8XgP14mb8pzcB1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/t0wJe/btrDQFRawra/cp0QZTrR8XgP14mb8pzcB1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/t0wJe/btrDQFRawra/cp0QZTrR8XgP14mb8pzcB1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Ft0wJe%2FbtrDQFRawra%2Fcp0QZTrR8XgP14mb8pzcB1%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;706&quot; height=&quot;374&quot; data-origin-width=&quot;706&quot; data-origin-height=&quot;374&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;
&lt;pre id=&quot;code_1654185801239&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;sudo netstat -tlnp&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>☁️AWS</category>
      <author>Cocoon_</author>
      <guid isPermaLink="true">https://cocoon1787.tistory.com/857</guid>
      <comments>https://cocoon1787.tistory.com/857#entry857comment</comments>
      <pubDate>Fri, 3 Jun 2022 01:03:30 +0900</pubDate>
    </item>
    <item>
      <title>[Next.js] 리액트 다크모드 새로고침 시 화면 깜빡임 이슈 해결</title>
      <link>https://cocoon1787.tistory.com/855</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;898&quot; data-origin-height=&quot;455&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b9ko1q/btrDd1ABBdy/b7kGkvK8TwRwaAy5t0eU6k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b9ko1q/btrDd1ABBdy/b7kGkvK8TwRwaAy5t0eU6k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b9ko1q/btrDd1ABBdy/b7kGkvK8TwRwaAy5t0eU6k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb9ko1q%2FbtrDd1ABBdy%2Fb7kGkvK8TwRwaAy5t0eU6k%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;898&quot; height=&quot;455&quot; data-origin-width=&quot;898&quot; data-origin-height=&quot;455&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;
&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;Next.js 프로젝트를 진행하면서 다크 모드를 개발하게 되었는데 다크 모드 상태에서 새로고침 시 흰 화면이 보였다가 어두운 화면으로 바뀌어서 깜빡이는 현상을 발견하였고 이는 UX(사용자 경험)적으로 마이너스가 될 수 도 있을 것 같아서 해결방법을 알아봤습니다.&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;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;ToggleTheme.jsx&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1653587995647&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import React, { useEffect, useCallback } from &quot;react&quot;;

const ToggleTheme = ({ changeTheme }) =&amp;gt; {
  const setDark = useCallback(() =&amp;gt; {
    localStorage.setItem(&quot;theme&quot;, &quot;Dark&quot;);
    document.documentElement.setAttribute(&quot;data-theme&quot;, &quot;Dark&quot;);
    if (changeTheme !== undefined) changeTheme();
  }, [changeTheme]);

  const setLight = () =&amp;gt; {
    localStorage.setItem(&quot;theme&quot;, &quot;Light&quot;);
    document.documentElement.setAttribute(&quot;data-theme&quot;, &quot;Light&quot;);
    if (changeTheme !== undefined) changeTheme();
  };

  const toggleTheme = (e) =&amp;gt; {
    if (e.target.checked) {
      setDark();
    } else {
      setLight();
    }
  };
  const storedTheme = localStorage.getItem(&quot;theme&quot;);

  const prefersDark =
    window.matchMedia &amp;amp;&amp;amp;
    window.matchMedia(&quot;(prefers-color-scheme: Dark)&quot;).matches;

  const defaultDark =
    storedTheme === &quot;Dark&quot; || (storedTheme === null &amp;amp;&amp;amp; prefersDark);

  useEffect(() =&amp;gt; {
    if (defaultDark) {
      setDark();
    }
  }, [defaultDark, setDark]);

  return (
    &amp;lt;input
      type=&quot;checkbox&quot;
      id=&quot;checkbox&quot;
      onChange={toggleTheme}
      defaultChecked={defaultDark}
    /&amp;gt;
  );
};

export default ToggleTheme;&lt;/code&gt;&lt;/pre&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;b&gt;Test.jsx&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1653588007047&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import React from &quot;react&quot;;
import styled from &quot;@emotion/styled&quot;;
import dynamic from &quot;next/dynamic&quot;;

const ToggleTheme = dynamic(() =&amp;gt; import(&quot;@/components/common/ToggleTheme&quot;), {
  ssr: false,
});

function Test() {
  return (
    &amp;lt;Container&amp;gt;
      &amp;lt;Title&amp;gt;다크 모드&amp;lt;/Title&amp;gt;
      &amp;lt;ToggleTheme&amp;gt;&amp;lt;/ToggleTheme&amp;gt;
    &amp;lt;/Container&amp;gt;
  );
}

export default Test;

const Container = styled.div`
  width: 300px;
  height: 100px;
  margin: 100px auto;
  text-align: center;
`;

const Title = styled.h1`
  font-size: 50px;
`;&lt;/code&gt;&lt;/pre&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;b&gt;global.scss&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1653588257568&quot; class=&quot;css&quot; data-ke-language=&quot;css&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;* {
  color: var(--font-color);
  background-color: var(--background-color);
  box-sizing: border-box;
}

:root {
  --font-color: #1d212c;
  --background-color: #ffffff;
}

[data-theme=&quot;Dark&quot;] {
  --font-color: #ffffff;
  --background-color: #1d212c;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;338&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Ot714/btrDeCHEY7A/neziwa5VJ4Cbt1iOhWX3Z0/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Ot714/btrDeCHEY7A/neziwa5VJ4Cbt1iOhWX3Z0/img.gif&quot; data-alt=&quot;새로고침 시 흰색 화면이 나타나 깜빡임&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Ot714/btrDeCHEY7A/neziwa5VJ4Cbt1iOhWX3Z0/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/Ot714/btrDeCHEY7A/neziwa5VJ4Cbt1iOhWX3Z0/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;600&quot; height=&quot;338&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;338&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;위의 gif처럼 새로고침 시 화면이 번쩍이는 현상을 확인할 수 있습니다.&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;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;테마를 변경하는 과정이 DOM 트리가 구성된 후 자바스크립트 파일을 파싱 한 후에 이루어졌기 때문에 처음 흰 화면이 렌더링 되고 그다음 어두운 화면이 렌더링 되어 깜빡임 현상이 발생했던 것입니다. 따라서 테마를 설정하는 시점이 스타일시트를 불러오고, DOM트리가 구성되기 전에 결정되어야 하므로 html 파일의 head에 script 태그로 dangerouslySetInnerHTML를 아래와 같이 설정해주면 화면 깜빡임 현상을 해결할 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1653268676485&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;script
  dangerouslySetInnerHTML={{
    __html: `
              const theme = localStorage.getItem(&quot;theme&quot;);
              document.documentElement.setAttribute(&quot;data-theme&quot;, theme);
              console.log(theme);
            `,
  }}
&amp;gt;&amp;lt;/script&amp;gt;;&lt;/code&gt;&lt;/pre&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;b&gt;pages/_document.js&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1653587691342&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import { Html, Head, Main, NextScript } from &quot;next/document&quot;;

function Document() {
  return (
    &amp;lt;Html&amp;gt;
      &amp;lt;Head&amp;gt;
        &amp;lt;script
          dangerouslySetInnerHTML={{
            __html: `
              const theme = localStorage.getItem(&quot;theme&quot;);
              document.documentElement.setAttribute(&quot;data-theme&quot;, theme);
              console.log(theme);
            `,
          }}
        &amp;gt;&amp;lt;/script&amp;gt;
      &amp;lt;/Head&amp;gt;
      &amp;lt;body&amp;gt;
        &amp;lt;Main /&amp;gt;
        &amp;lt;NextScript /&amp;gt;
      &amp;lt;/body&amp;gt;
    &amp;lt;/Html&amp;gt;
  );
}

export default Document;&lt;/code&gt;&lt;/pre&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;b&gt;public/index.html&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;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;338&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cj3viF/btrDeDNksc7/rhwXTWI9iuE9kVBG2JTCb1/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cj3viF/btrDeDNksc7/rhwXTWI9iuE9kVBG2JTCb1/img.gif&quot; data-alt=&quot;새로고침 시 기존 모드 유지&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cj3viF/btrDeDNksc7/rhwXTWI9iuE9kVBG2JTCb1/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/cj3viF/btrDeDNksc7/rhwXTWI9iuE9kVBG2JTCb1/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;600&quot; height=&quot;338&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;338&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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>◀️Next.js</category>
      <author>Cocoon_</author>
      <guid isPermaLink="true">https://cocoon1787.tistory.com/855</guid>
      <comments>https://cocoon1787.tistory.com/855#entry855comment</comments>
      <pubDate>Fri, 27 May 2022 03:13:21 +0900</pubDate>
    </item>
    <item>
      <title>[React] 리액트 다음 주소 검색 (react-daum-postcode)</title>
      <link>https://cocoon1787.tistory.com/856</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;736&quot; data-origin-height=&quot;471&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/3P8wh/btrC75KKYaZ/vkUIWHKU72vxHDvrju9kmk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/3P8wh/btrC75KKYaZ/vkUIWHKU72vxHDvrju9kmk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/3P8wh/btrC75KKYaZ/vkUIWHKU72vxHDvrju9kmk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F3P8wh%2FbtrC75KKYaZ%2FvkUIWHKU72vxHDvrju9kmk%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;736&quot; height=&quot;471&quot; data-origin-width=&quot;736&quot; data-origin-height=&quot;471&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;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;  &lt;b&gt;react-daum-postcode install&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1653524883644&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;npm install react-daum-postcode&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;✔️ 다음 주소 검색을 사용할 컴포넌트에 import&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1653524995026&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import DaumPostcode from 'react-daum-postcode';&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;  &lt;b&gt;코드&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1653524812218&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/**
 * [Title] Daum 우편번호 검색
 * [Description] 리액트 컴포넌트로 만든 Daum 우편번호 검색 서비스
 * [Usage]
 * @props onComplete {Function} : 우편번호 검색 시 선택한 정보 받아올 콜백함수
 * @props onSearch {Function} : 주소를 검색할 경우 실행되는 콜백함수
 * @props onClose {Function} : 검색 결과선택 후 우편번호 검색이 닫힐때 실행되는 콜백함수
 * @props onResize {Function} : 검색결과로 우편번호 화면 크기가 변경될때 실행되는 콜백함수
 * @props className {String} : 우편번호 검색창을 감싸는 최상위 엘리먼트 ClassName
 * @props style : 우편번호 검색창 최상위 엘리먼트 스타일
 *  @default {width:100%,height:400px}
 * @props scriptUrl {String} : Daum 우편번호 스크립트 주소
 *  @default &quot;https://t1.daumcdn.net/mapjsapi/bundle/postcode/prod/postcode.v2.js&quot;
 * @props defaultQuery {String} : 우편번호 검색창에 기본으로 입력할 검색어
 *  @default undefined
 * @props autoClose {Boolean} : 우편번호 검색 완료시, 자동닫힘 여부
 *  @default true
 * @props errorMessage {React element} : 로드되지 않을때 보이는 에러 메시지
 *  @default &quot;&amp;lt;p&amp;gt;현재 Daum 우편번호 서비스를 이용할 수 없습니다. 잠시 후 다시 시도해주세요.&amp;lt;/p&amp;gt;&quot;
 */

import React from &quot;react&quot;;
import DaumPostcode from &quot;react-daum-postcode&quot;;
import styled from &quot;@emotion/styled&quot;;

function SearchAddress(props) {
  const handleComplete = (data) =&amp;gt; {
    let fullAddress = data.address;
    let extraAddress = &quot;&quot;;
    // console.log(data);
    if (data.addressType === &quot;R&quot;) {
      if (data.bname !== &quot;&quot;) {
        extraAddress += data.bname;
      }
      if (data.buildingName !== &quot;&quot;) {
        extraAddress +=
          extraAddress !== &quot;&quot; ? `, ${data.buildingName}` : data.buildingName;
      }
      fullAddress += extraAddress !== &quot;&quot; ? ` (${extraAddress})` : &quot;&quot;;
    }

    console.log(fullAddress); // e.g. '서울 성동구 왕십리로2길 20 (성수동1가)'
  };

  const handleSearch = (data) =&amp;gt; {
    // console.log(data);
  };

  return (
    &amp;lt;DaumPostcode
      onComplete={handleComplete}
      onSearch={handleSearch}
      {...props}
    /&amp;gt;
  );
}

export default SearchAddress;

SearchAddress.defaultProps = {
  style: {
    width: &quot;700px&quot;,
    height: &quot;450px&quot;,
  },
};

/**
 * &quot;학동로 31길 12&quot; 입력 시
onComplete {Function}
@return
{
  &quot;q&quot;: &quot;학동로 31길 12&quot;,
  &quot;count&quot;: 1
}

handleSearch {Function}
@return
{
  &quot;postcode&quot;: &quot;&quot;,
  &quot;postcode1&quot;: &quot;&quot;,
  &quot;postcode2&quot;: &quot;&quot;,
  &quot;postcodeSeq&quot;: &quot;&quot;,
  &quot;zonecode&quot;: &quot;06052&quot;,
  &quot;address&quot;: &quot;서울 강남구 학동로31길 12&quot;,
  &quot;addressEnglish&quot;: &quot;12, Hakdong-ro 31-gil, Gangnam-gu, Seoul, Korea&quot;,
  &quot;addressType&quot;: &quot;R&quot;,
  &quot;bcode&quot;: &quot;1168010800&quot;,
  &quot;bname&quot;: &quot;논현동&quot;,
  &quot;bnameEnglish&quot;: &quot;Nonhyeon-dong&quot;,
  &quot;bname1&quot;: &quot;&quot;,
  &quot;bname1English&quot;: &quot;&quot;,
  &quot;bname2&quot;: &quot;논현동&quot;,
  &quot;bname2English&quot;: &quot;Nonhyeon-dong&quot;,
  &quot;sido&quot;: &quot;서울&quot;,
  &quot;sidoEnglish&quot;: &quot;Seoul&quot;,
  &quot;sigungu&quot;: &quot;강남구&quot;,
  &quot;sigunguEnglish&quot;: &quot;Gangnam-gu&quot;,
  &quot;sigunguCode&quot;: &quot;11680&quot;,
  &quot;userLanguageType&quot;: &quot;K&quot;,
  &quot;query&quot;: &quot;학동로 31길 12&quot;,
  &quot;buildingName&quot;: &quot;벤쳐캐슬빌딩&quot;,
  &quot;buildingCode&quot;: &quot;1168010800100820018000001&quot;,
  &quot;apartment&quot;: &quot;N&quot;,
  &quot;jibunAddress&quot;: &quot;&quot;,
  &quot;jibunAddressEnglish&quot;: &quot;&quot;,
  &quot;roadAddress&quot;: &quot;서울 강남구 학동로31길 12&quot;,
  &quot;roadAddressEnglish&quot;: &quot;12, Hakdong-ro 31-gil, Gangnam-gu, Seoul, Korea&quot;,
  &quot;autoRoadAddress&quot;: &quot;&quot;,
  &quot;autoRoadAddressEnglish&quot;: &quot;&quot;,
  &quot;autoJibunAddress&quot;: &quot;서울 강남구 논현동 82-17&quot;,
  &quot;autoJibunAddressEnglish&quot;: &quot;82-17, Nonhyeon-dong, Gangnam-gu, Seoul, Korea&quot;,
  &quot;userSelectedType&quot;: &quot;R&quot;,
  &quot;noSelected&quot;: &quot;N&quot;,
  &quot;hname&quot;: &quot;&quot;,
  &quot;roadnameCode&quot;: &quot;4166791&quot;,
  &quot;roadname&quot;: &quot;학동로31길&quot;,
  &quot;roadnameEnglish&quot;: &quot;Hakdong-ro 31-gil&quot;
}
 */&lt;/code&gt;&lt;/pre&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 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 data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.npmjs.com/package/react-daum-postcode&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://www.npmjs.com/package/react-daum-postcode&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1653524922205&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;react-daum-postcode&quot; data-og-description=&quot;React daum-postcode component. Latest version: 3.0.3, last published: 11 days ago. Start using react-daum-postcode in your project by running &amp;#96;npm i react-daum-postcode&amp;#96;. There are 16 other projects in the npm registry using react-daum-postcode.&quot; data-og-host=&quot;www.npmjs.com&quot; data-og-source-url=&quot;https://www.npmjs.com/package/react-daum-postcode&quot; data-og-url=&quot;https://www.npmjs.com/package/react-daum-postcode&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/cJKGOH/hyOxoxDUsG/KxX6PNHhAWERyqHZDCFaNk/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630&quot;&gt;&lt;a href=&quot;https://www.npmjs.com/package/react-daum-postcode&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.npmjs.com/package/react-daum-postcode&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/cJKGOH/hyOxoxDUsG/KxX6PNHhAWERyqHZDCFaNk/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;react-daum-postcode&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;React daum-postcode component. Latest version: 3.0.3, last published: 11 days ago. Start using react-daum-postcode in your project by running `npm i react-daum-postcode`. There are 16 other projects in the npm registry using react-daum-postcode.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.npmjs.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>⚛️React</category>
      <author>Cocoon_</author>
      <guid isPermaLink="true">https://cocoon1787.tistory.com/856</guid>
      <comments>https://cocoon1787.tistory.com/856#entry856comment</comments>
      <pubDate>Thu, 26 May 2022 09:30:28 +0900</pubDate>
    </item>
    <item>
      <title>[React] &amp;quot;Warning: Unknown event handler property `onToggleBackground`. It will be ignored.&amp;quot; 오류 해결</title>
      <link>https://cocoon1787.tistory.com/854</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1584&quot; data-origin-height=&quot;609&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ciN4Lo/btrCNM5ssGW/A6h0Rg85GHzvn5sfI1qtP0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ciN4Lo/btrCNM5ssGW/A6h0Rg85GHzvn5sfI1qtP0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ciN4Lo/btrCNM5ssGW/A6h0Rg85GHzvn5sfI1qtP0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FciN4Lo%2FbtrCNM5ssGW%2FA6h0Rg85GHzvn5sfI1qtP0%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;1584&quot; height=&quot;609&quot; data-origin-width=&quot;1584&quot; data-origin-height=&quot;609&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;
&lt;h4 data-ke-size=&quot;size20&quot;&gt; &lt;b&gt; 오류 발생&lt;/b&gt;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;재사용 가능한 토글 컴포넌트를 제작하다가 발견한 오류&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;633&quot; data-origin-height=&quot;312&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Xeowj/btrCOKGjSsj/ETjumpvRbFhknIRfqVKS80/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Xeowj/btrCOKGjSsj/ETjumpvRbFhknIRfqVKS80/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Xeowj/btrCOKGjSsj/ETjumpvRbFhknIRfqVKS80/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FXeowj%2FbtrCOKGjSsj%2FETjumpvRbFhknIRfqVKS80%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;633&quot; height=&quot;312&quot; data-origin-width=&quot;633&quot; data-origin-height=&quot;312&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 속성을 props로 보내는 컴포넌트나 페이지가 있는지 살펴보다가 도저히 해결되지 않아서 구글링 해본 결과....&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;&lt;a href=&quot;https://stackoverflow.com/questions/53945281/warning-unknown-event-handler-property-onheaderclick-it-will-be-ignored&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://stackoverflow.com/questions/53945281/warning-unknown-event-handler-property-onheaderclick-it-will-be-ignored&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1653225759910&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Warning: Unknown event handler property &amp;#96;onHeaderClick&amp;#96;. It will be ignored&quot; data-og-description=&quot;I am creating Higher order components for passing some props with another component. But getting the warning for Unknown event handler property. export class TableHeaderRow extends React.PureComp...&quot; data-og-host=&quot;stackoverflow.com&quot; data-og-source-url=&quot;https://stackoverflow.com/questions/53945281/warning-unknown-event-handler-property-onheaderclick-it-will-be-ignored&quot; data-og-url=&quot;https://stackoverflow.com/questions/53945281/warning-unknown-event-handler-property-onheaderclick-it-will-be-ignored&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/dYLr3M/hyOuft7Jmu/5mKMLjCbmxuPkXInvrThv1/img.png?width=316&amp;amp;height=316&amp;amp;face=0_0_316_316&quot;&gt;&lt;a href=&quot;https://stackoverflow.com/questions/53945281/warning-unknown-event-handler-property-onheaderclick-it-will-be-ignored&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://stackoverflow.com/questions/53945281/warning-unknown-event-handler-property-onheaderclick-it-will-be-ignored&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/dYLr3M/hyOuft7Jmu/5mKMLjCbmxuPkXInvrThv1/img.png?width=316&amp;amp;height=316&amp;amp;face=0_0_316_316');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Warning: Unknown event handler property `onHeaderClick`. It will be ignored&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;I am creating Higher order components for passing some props with another component. But getting the warning for Unknown event handler property. export class TableHeaderRow extends React.PureComp...&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;stackoverflow.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;✔️ &lt;b&gt;해결&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코드에서 onToggleBackground를 사용하였는데 리액트에서 props를 전달할 때 &quot;on&quot;으로 시작하는 단어들을 onClick. onChange와 같이 자바스크립트 이벤트로 가정하고 바인딩을 시도하려고 하기 때문에 발생하는 에러라고 합니다.&amp;nbsp;&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;</description>
      <category> ERROR</category>
      <author>Cocoon_</author>
      <guid isPermaLink="true">https://cocoon1787.tistory.com/854</guid>
      <comments>https://cocoon1787.tistory.com/854#entry854comment</comments>
      <pubDate>Sun, 22 May 2022 22:24:59 +0900</pubDate>
    </item>
    <item>
      <title>[CSS] 클래스 네이밍 시 container와 wrapper의 차이</title>
      <link>https://cocoon1787.tistory.com/853</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1449&quot; data-origin-height=&quot;814&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bsEYET/btrCJbKStCZ/kCWGEVSwKpgKOyVGo2mnHk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bsEYET/btrCJbKStCZ/kCWGEVSwKpgKOyVGo2mnHk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bsEYET/btrCJbKStCZ/kCWGEVSwKpgKOyVGo2mnHk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbsEYET%2FbtrCJbKStCZ%2FkCWGEVSwKpgKOyVGo2mnHk%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;1449&quot; height=&quot;814&quot; data-origin-width=&quot;1449&quot; data-origin-height=&quot;814&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;
&lt;h4 style=&quot;text-align: center;&quot; data-ke-size=&quot;size20&quot;&gt; &lt;/h4&gt;
&lt;pre id=&quot;code_1653104159771&quot; class=&quot;applescript&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;div class=&quot;container&quot;&amp;gt;
    ...
&amp;lt;/div&amp;gt;

&amp;lt;div class=&quot;wrapper&quot;&amp;gt;
    ...
&amp;lt;/div&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;페이지를 제작하다 보면 공통 요소들이나 단일 요소를 담거나 감쌀 때 container나 wrapper를 많이 사용하게 됩니다. container와 wrapper 모두 일반적으로 어떠한 요소들을 포괄하는 의미를 지니고 있고 클래스 네임으로 많이 사용되는 단어들입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;퍼블리싱 업무를 하면서 코드를 보니 문득 제가 container와 wrapper를 혼용해서 사용하고 있다는 사실을 알게 되었고, 해당 단어에 대해 규칙이나 관례가 있는지 한번 찾아보았습니다.&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;2010년 스택오버플로우에 container vs wrapper 관련 토론 게시글이 있어서 공유드립니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://stackoverflow.com/questions/4059163/css-language-speak-container-vs-wrapper&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://stackoverflow.com/questions/4059163/css-language-speak-container-vs-wrapper&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1653104228131&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;CSS Language Speak: Container vs Wrapper?&quot; data-og-description=&quot;What's the difference between container and wrapper? And what is meant by each?&quot; data-og-host=&quot;stackoverflow.com&quot; data-og-source-url=&quot;https://stackoverflow.com/questions/4059163/css-language-speak-container-vs-wrapper&quot; data-og-url=&quot;https://stackoverflow.com/questions/4059163/css-language-speak-container-vs-wrapper&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/cPO9ni/hyOs22YstA/5KpMvjt6ATaukqKZNA4sSK/img.png?width=316&amp;amp;height=316&amp;amp;face=0_0_316_316&quot;&gt;&lt;a href=&quot;https://stackoverflow.com/questions/4059163/css-language-speak-container-vs-wrapper&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://stackoverflow.com/questions/4059163/css-language-speak-container-vs-wrapper&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/cPO9ni/hyOs22YstA/5KpMvjt6ATaukqKZNA4sSK/img.png?width=316&amp;amp;height=316&amp;amp;face=0_0_316_316');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;CSS Language Speak: Container vs Wrapper?&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;What's the difference between container and wrapper? And what is meant by each?&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;stackoverflow.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;  container(컨테이너)&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하나 이상의 요소를 포함할 수 있는 구조&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;✉️ wrapper(래퍼)&lt;/b&gt;&lt;/h4&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;&lt;b&gt;사탕을 상자에 담는다고 가정했을 때 개별 사탕들을 포장지(wrapper)에 포장한 후 상자(container)에 넣습니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로그래밍적 관점으로 봤을 때도 일반적으로 container는 하나 이상의 요소를 포괄하는 개체를 지칭하고 wrapper는 하나의 개체만을 포함하는 것을 뜻합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1653104635911&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;ul class=&quot;items-container&quot;&amp;gt;
    &amp;lt;li class=&quot;item-wrapper&quot;&amp;gt;
        &amp;lt;div class=&quot;item&quot;&amp;gt;...&amp;lt;/div&amp;gt;
    &amp;lt;/li&amp;gt;
    &amp;lt;li class=&quot;item-wrapper&quot;&amp;gt;
        &amp;lt;div class=&quot;item&quot;&amp;gt;...&amp;lt;/div&amp;gt;
    &amp;lt;/li&amp;gt;
    &amp;lt;li class=&quot;item-wrapper&quot;&amp;gt;
        &amp;lt;div class=&quot;item&quot;&amp;gt;...&amp;lt;/div&amp;gt;
    &amp;lt;/li&amp;gt;
    &amp;lt;li class=&quot;item-wrapper&quot;&amp;gt;
        &amp;lt;div class=&quot;item&quot;&amp;gt;...&amp;lt;/div&amp;gt;
    &amp;lt;/li&amp;gt;
    &amp;lt;li class=&quot;item-wrapper&quot;&amp;gt;
        &amp;lt;div class=&quot;item&quot;&amp;gt;...&amp;lt;/div&amp;gt;
    &amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt; &amp;zwj; &amp;zwj;  &lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;하지만 사람들마다 wrapper나 container를 사용하는 방법과 보는 관점, 취향이 다르므로 어느 것이 맞고 어느 것이 틀리다고 단정 지을 수는 없습니다. 저 또한 다른 웹페이지들을 분석했을 때 페이지 html 최상단에 전체를 감싸는 것을 wrapper로 되어 있는 것을 많이 봐왔으며 사람에 따라서 &quot;하나의 페이지를 감싸는 wrapper가 맞다&quot;, &quot;아니다 페이지 내의 구성요소들을 담고 있으므로 container가 맞다&quot; 등등 의견의 서로 다를 수 도 있기 때문입니다. 따라서 협업을 할 때 위의 내용을 토대로 팀원 간의 충분한 논의, 협의를 통해서 클래스 네이밍을 하시면 좋을 것 같습니다.&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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category> WEB</category>
      <author>Cocoon_</author>
      <guid isPermaLink="true">https://cocoon1787.tistory.com/853</guid>
      <comments>https://cocoon1787.tistory.com/853#entry853comment</comments>
      <pubDate>Sat, 21 May 2022 12:59:17 +0900</pubDate>
    </item>
    <item>
      <title>[React] &amp;quot;Error: error:0308010C:digital envelope routines::unsupported&amp;quot; 에러 해결</title>
      <link>https://cocoon1787.tistory.com/852</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1252&quot; data-origin-height=&quot;726&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cQb7vV/btrCboQ9AP9/6q5KAIdNjfiekVqXhD0X21/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cQb7vV/btrCboQ9AP9/6q5KAIdNjfiekVqXhD0X21/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cQb7vV/btrCboQ9AP9/6q5KAIdNjfiekVqXhD0X21/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcQb7vV%2FbtrCboQ9AP9%2F6q5KAIdNjfiekVqXhD0X21%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;1252&quot; height=&quot;726&quot; data-origin-width=&quot;1252&quot; data-origin-height=&quot;726&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;
&lt;h4 style=&quot;text-align: center;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;  Error log&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Error:&amp;nbsp;error:0308010C:digital&amp;nbsp;envelope&amp;nbsp;routines::unsupported&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;...&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;{&lt;br /&gt;&lt;/b&gt;&lt;b&gt;opensslErrorStack: [ '&lt;span style=&quot;color: #409d00;&quot;&gt;error:03000086:digital&amp;nbsp;envelope&amp;nbsp;routines::initialization&amp;nbsp;error&lt;/span&gt;'&amp;nbsp;], &lt;/b&gt;&lt;br /&gt;&lt;b&gt;library: '&lt;span style=&quot;color: #409d00;&quot;&gt;digital&amp;nbsp;envelope&amp;nbsp;routines&lt;/span&gt;', &lt;/b&gt;&lt;br /&gt;&lt;b&gt;reason: '&lt;span style=&quot;color: #409d00;&quot;&gt;unsupported&lt;/span&gt;', &lt;/b&gt;&lt;br /&gt;&lt;b&gt;code: '&lt;span style=&quot;color: #409d00;&quot;&gt;ERR_OSSL_EVP_UNSUPPORTED&lt;/span&gt;'&lt;br /&gt;}&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Node.js&amp;nbsp;v17.0.1&lt;/b&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&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;443&quot; data-origin-height=&quot;134&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/biiAdk/btrB7MMfBGc/OhvYci2SO2ZAK55XCJLnQk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/biiAdk/btrB7MMfBGc/OhvYci2SO2ZAK55XCJLnQk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/biiAdk/btrB7MMfBGc/OhvYci2SO2ZAK55XCJLnQk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbiiAdk%2FbtrB7MMfBGc%2FOhvYci2SO2ZAK55XCJLnQk%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;443&quot; height=&quot;134&quot; data-origin-width=&quot;443&quot; data-origin-height=&quot;134&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;102&quot; data-origin-height=&quot;41&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/6KrtO/btrB9tMcbFz/pwriVoKLekKuc4b2hzTJFK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/6KrtO/btrB9tMcbFz/pwriVoKLekKuc4b2hzTJFK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/6KrtO/btrB9tMcbFz/pwriVoKLekKuc4b2hzTJFK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F6KrtO%2FbtrB9tMcbFz%2FpwriVoKLekKuc4b2hzTJFK%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;102&quot; height=&quot;41&quot; data-origin-width=&quot;102&quot; data-origin-height=&quot;41&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;package.json&lt;/b&gt;&lt;/h4&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; &amp;zwj; &lt;span&gt;&amp;nbsp;&lt;/span&gt;해결 과정&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어느 날부터 갑자기 위와 같은 오류가 발생하기 시작하였는데 스택오버플로우나 구글링으로 검색 결과 Node.js 버전 17 이상을 제거하고 버전 16을 설치, 명령 프롬프트 창에서 노드 옵션으로 아래와 같이 붙여 넣기 등등을 해봤으나 해결되지 않았습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Linux 및 Mac OS(Windows git bash)-&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;export NODE_OPTIONS=--openssl-legacy-provider
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Windows 명령 프롬프트-&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;set NODE_OPTIONS=--openssl-legacy-provider&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;좀 더 찾아본 뒤 package.json의 scripts에서 start 명령어에 옵션을 주어 임시방편으로 해결하는 방법을 알아냈습니다.&lt;/p&gt;
&lt;pre data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;&quot;start&quot;: &quot;react-scripts start&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;에서&lt;/p&gt;
&lt;pre id=&quot;code_1652610405572&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&quot;start&quot;: &quot;set NODE_OPTIONS=--openssl-legacy-provider &amp;amp;&amp;amp; react-scripts start&quot;&lt;/code&gt;&lt;/pre&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;954&quot; data-origin-height=&quot;421&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/wQmjk/btrB7MS0ItR/YYopKZ9w42y21vK1xtiio0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/wQmjk/btrB7MS0ItR/YYopKZ9w42y21vK1xtiio0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/wQmjk/btrB7MS0ItR/YYopKZ9w42y21vK1xtiio0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FwQmjk%2FbtrB7MS0ItR%2FYYopKZ9w42y21vK1xtiio0%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;954&quot; height=&quot;421&quot; data-origin-width=&quot;954&quot; data-origin-height=&quot;421&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러나 근본적인 문제를 해결하지는 못하였으므로 npx create-react-app으로 생성한 프로젝트로 실행해보니 잘 실행되어 두 프로젝트의 package.json 파일의 차이점을 분석하였고 react, react-dom, react-scripts 패키지를 하나하나씩 업그레이드해보면서 react-scripts의 버전 문제였다는 것을 알게 되었습니다.&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;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;react-scripts 버전 업그레이드&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;415&quot; data-origin-height=&quot;523&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/up2ss/btrCcEM10DV/mykJ9ZC7i7vroWdUWCAhtk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/up2ss/btrCcEM10DV/mykJ9ZC7i7vroWdUWCAhtk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/up2ss/btrCcEM10DV/mykJ9ZC7i7vroWdUWCAhtk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fup2ss%2FbtrCcEM10DV%2FmykJ9ZC7i7vroWdUWCAhtk%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;415&quot; height=&quot;523&quot; data-origin-width=&quot;415&quot; data-origin-height=&quot;523&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre id=&quot;code_1652609419692&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ npm install --save react-scripts@5.0.1&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;413&quot; data-origin-height=&quot;523&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/E0gC8/btrB6QVSMDl/dkCkXBsEzSsrdzbtuVds0K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/E0gC8/btrB6QVSMDl/dkCkXBsEzSsrdzbtuVds0K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/E0gC8/btrB6QVSMDl/dkCkXBsEzSsrdzbtuVds0K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FE0gC8%2FbtrB6QVSMDl%2FdkCkXBsEzSsrdzbtuVds0K%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;413&quot; height=&quot;523&quot; data-origin-width=&quot;413&quot; data-origin-height=&quot;523&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;
&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 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 data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category> ERROR</category>
      <author>Cocoon_</author>
      <guid isPermaLink="true">https://cocoon1787.tistory.com/852</guid>
      <comments>https://cocoon1787.tistory.com/852#entry852comment</comments>
      <pubDate>Sun, 15 May 2022 22:44:03 +0900</pubDate>
    </item>
    <item>
      <title>[Next.js] Module not found: Can't resolve 'fs' 오류 해결</title>
      <link>https://cocoon1787.tistory.com/851</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;971&quot; data-origin-height=&quot;497&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Di809/btrCatK9PlD/sK352kb0W1GbYnxPNSO2k0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Di809/btrCatK9PlD/sK352kb0W1GbYnxPNSO2k0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Di809/btrCatK9PlD/sK352kb0W1GbYnxPNSO2k0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FDi809%2FbtrCatK9PlD%2FsK352kb0W1GbYnxPNSO2k0%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;971&quot; height=&quot;497&quot; data-origin-width=&quot;971&quot; data-origin-height=&quot;497&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 style=&quot;text-align: center;&quot; data-ke-size=&quot;size20&quot;&gt;  Error log&lt;/h4&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;Module&amp;nbsp;not&amp;nbsp;found&lt;/span&gt;:&amp;nbsp;Can't&amp;nbsp;resolve&amp;nbsp;'&lt;span style=&quot;color: #409d00;&quot;&gt;fs&lt;/span&gt;'&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;&lt;b&gt;fs 모듈&lt;/b&gt;은 nodejs의 기본 파일 시스템 모듈입니다. 해당 오류는 일반적으로 &lt;b&gt;클라이언트 측에서 nodejs 라이브러리를 사용&lt;/b&gt;하려고 할 때 발생하는 오류입니다. 즉, fs모듈은 컴퓨터의 파일 시스템에 접근하여 읽고 쓰기 위한 것인데 &lt;b&gt;클라이언트(브라우저)에서는 사용이 불가능한 패키지&lt;/b&gt; 이므로 오류가 발생하게 된 것입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Next.js로 만든 프로젝트에서 해당 모듈을 찾을 수 없다는 에러를 만나게 되었고 구글링 해본 결과 &lt;b&gt;웹팩을 설정&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;&quot;Next.js v12.1.6&quot;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;package.json&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1652602381168&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;{
  &quot;name&quot;: &quot;coin.gg&quot;,
  &quot;version&quot;: &quot;0.1.0&quot;,
  &quot;private&quot;: true,
  &quot;scripts&quot;: {
    &quot;dev&quot;: &quot;next dev&quot;,
    &quot;build&quot;: &quot;next build&quot;,
    &quot;start&quot;: &quot;next start&quot;,
    &quot;lint&quot;: &quot;next lint&quot;
  },
  &quot;dependencies&quot;: {
    &quot;@emotion/css&quot;: &quot;^11.9.0&quot;,
    &quot;@emotion/react&quot;: &quot;^11.9.0&quot;,
    &quot;@emotion/styled&quot;: &quot;^11.8.1&quot;,
    &quot;axios&quot;: &quot;^0.27.2&quot;,
    &quot;bootstrap-icons&quot;: &quot;^1.8.2&quot;,
    &quot;fs&quot;: &quot;^0.0.1-security&quot;,
    &quot;js-cookie&quot;: &quot;^3.0.1&quot;,
    &quot;lodash&quot;: &quot;^4.17.21&quot;,
    &quot;lodash.clonedeep&quot;: &quot;^4.5.0&quot;,
    &quot;moment&quot;: &quot;^2.29.3&quot;,
    &quot;net&quot;: &quot;^1.0.2&quot;,
    &quot;next&quot;: &quot;12.1.6&quot;,
    &quot;next-i18next&quot;: &quot;^11.0.0&quot;,
    &quot;react&quot;: &quot;18.1.0&quot;,
    &quot;react-dom&quot;: &quot;18.1.0&quot;,
    &quot;request-promise&quot;: &quot;^4.2.6&quot;,
    &quot;sass&quot;: &quot;^1.51.0&quot;,
    &quot;socket.io-client&quot;: &quot;^4.5.0&quot;,
    &quot;styled-components&quot;: &quot;^5.3.5&quot;,
    &quot;tls&quot;: &quot;^0.0.1&quot;
  },
  &quot;devDependencies&quot;: {
    &quot;@babel/plugin-transform-runtime&quot;: &quot;^7.17.10&quot;,
    &quot;eslint&quot;: &quot;8.15.0&quot;,
    &quot;eslint-config-next&quot;: &quot;12.1.6&quot;
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;기존 next.config.js 파일&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1652602566280&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/** @type {import('next').NextConfig} */

const nextConfig = {
  reactStrictMode: true,
};

module.exports = nextConfig;&lt;/code&gt;&lt;/pre&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;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Next,js v12에서 webpack4에 대한 지원 제거&lt;br /&gt;&lt;/b&gt;&lt;b&gt;(&lt;a href=&quot;https://nextjs.org/docs/messages/webpack5&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://nextjs.org/docs/messages/webpack5&lt;/a&gt;)&lt;/b&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;for webpack4&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1652602600522&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/** @type {import('next').NextConfig} */

const nextConfig = {
  reactStrictMode: true,
  webpack: (config, { isServer }) =&amp;gt; {
    // Fixes npm packages that depend on `fs` module
    if (!isServer) {
      config.node = {
        fs: 'empty'
      }
    }

    return config
  }
};

module.exports = nextConfig;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;for webpack5&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1652602616713&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/** @type {import('next').NextConfig} */

const nextConfig = {
  reactStrictMode: true,
  webpack5: true,
  webpack: (config) =&amp;gt; {
    config.resolve.fallback = { fs: false };

    return config;
  },
};

module.exports = nextConfig;&lt;/code&gt;&lt;/pre&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 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 data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;  참고&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://stackoverflow.com/questions/64926174/module-not-found-cant-resolve-fs-in-next-js-application&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://stackoverflow.com/questions/64926174/module-not-found-cant-resolve-fs-in-next-js-application&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1652602465865&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Module not found: Can't resolve 'fs' in Next.js application&quot; data-og-description=&quot;Unable to identify what's happening in my next.js app. As fs is a default file system module of nodejs. It is giving the error of module not found.&quot; data-og-host=&quot;stackoverflow.com&quot; data-og-source-url=&quot;https://stackoverflow.com/questions/64926174/module-not-found-cant-resolve-fs-in-next-js-application&quot; data-og-url=&quot;https://stackoverflow.com/questions/64926174/module-not-found-cant-resolve-fs-in-next-js-application&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/8bSNc/hyOoLtydty/dss59B83qUSQmguCKb9Cq1/img.png?width=316&amp;amp;height=316&amp;amp;face=0_0_316_316,https://scrap.kakaocdn.net/dn/bay6xC/hyOpJnjei8/xlcvbdhkvuNMIjvWWo8u80/img.png?width=488&amp;amp;height=773&amp;amp;face=0_0_488_773,https://scrap.kakaocdn.net/dn/bOGyBQ/hyOpDm6dxa/EpGg8DKjJkRAM70M19MJWk/img.png?width=969&amp;amp;height=241&amp;amp;face=0_0_969_241&quot;&gt;&lt;a href=&quot;https://stackoverflow.com/questions/64926174/module-not-found-cant-resolve-fs-in-next-js-application&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://stackoverflow.com/questions/64926174/module-not-found-cant-resolve-fs-in-next-js-application&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/8bSNc/hyOoLtydty/dss59B83qUSQmguCKb9Cq1/img.png?width=316&amp;amp;height=316&amp;amp;face=0_0_316_316,https://scrap.kakaocdn.net/dn/bay6xC/hyOpJnjei8/xlcvbdhkvuNMIjvWWo8u80/img.png?width=488&amp;amp;height=773&amp;amp;face=0_0_488_773,https://scrap.kakaocdn.net/dn/bOGyBQ/hyOpDm6dxa/EpGg8DKjJkRAM70M19MJWk/img.png?width=969&amp;amp;height=241&amp;amp;face=0_0_969_241');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Module not found: Can't resolve 'fs' in Next.js application&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Unable to identify what's happening in my next.js app. As fs is a default file system module of nodejs. It is giving the error of module not found.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;stackoverflow.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&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;</description>
      <category> ERROR</category>
      <author>Cocoon_</author>
      <guid isPermaLink="true">https://cocoon1787.tistory.com/851</guid>
      <comments>https://cocoon1787.tistory.com/851#entry851comment</comments>
      <pubDate>Sun, 15 May 2022 17:44:46 +0900</pubDate>
    </item>
    <item>
      <title>[AWS] MobaXterm으로 EC2 접속하기</title>
      <link>https://cocoon1787.tistory.com/850</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1680&quot; data-origin-height=&quot;1053&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Rx99l/btrBr7W7D5F/wxa9Edk2wEAWJY5yNQJr31/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Rx99l/btrBr7W7D5F/wxa9Edk2wEAWJY5yNQJr31/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Rx99l/btrBr7W7D5F/wxa9Edk2wEAWJY5yNQJr31/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FRx99l%2FbtrBr7W7D5F%2Fwxa9Edk2wEAWJY5yNQJr31%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;1680&quot; height=&quot;1053&quot; data-origin-width=&quot;1680&quot; data-origin-height=&quot;1053&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt; &lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;안녕하세요. 서버를 관리하면서 git bash로 리눅스 명령어를 써가며 폴더를 찾고 해당 파일의 내용을 확인하고 수정하는 작업을 했었었는데 회사에서 환경세팅을 하면서 모바엑스텀(MobaXterm)이라는 프로그램을 알게 되었고 굉장히 유용하게 사용중입니다. 이번 포스팅으로 MobaXterm으로 EC2에 접속하는 방법에 대해 알아보도록 하겠습니다.&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; ️ MobaXterm이 무엇인가요??&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PUTTY와 같이 SSH, RDP, SFTP 등등 다양한 네트워크 클라이언트와 터미널을 제공하는 툴입니다. 다른 클라이언트 프로그램들에 비해 훨씬 편리한 세션 연결과 작업들을 지원하기 때문에 꼭 사용하시길 바랍니다!&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;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://mobaxterm.mobatek.net/download-home-edition.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://mobaxterm.mobatek.net/download-home-edition.html&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1651922553128&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;MobaXterm free Xserver and tabbed SSH client for Windows&quot; data-og-description=&quot;The ultimate toolbox for remote computing - includes X server, enhanced SSH client and much more!&quot; data-og-host=&quot;mobaxterm.mobatek.net&quot; data-og-source-url=&quot;https://mobaxterm.mobatek.net/download-home-edition.html&quot; data-og-url=&quot;https://mobaxterm.mobatek.net/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/kt4aE/hyOhEBoDEU/LHXVXy9KMhAYoi625up0r0/img.png?width=764&amp;amp;height=489&amp;amp;face=0_0_764_489,https://scrap.kakaocdn.net/dn/3uNn5/hyOhCXQPOd/um2XoVWwzeDyKjuEUzutDK/img.png?width=768&amp;amp;height=443&amp;amp;face=0_0_768_443,https://scrap.kakaocdn.net/dn/bSGpLe/hyOi9T2WXv/aDSD0OWqbiuRnQrbO7IRqk/img.png?width=768&amp;amp;height=443&amp;amp;face=0_0_768_443&quot;&gt;&lt;a href=&quot;https://mobaxterm.mobatek.net/download-home-edition.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://mobaxterm.mobatek.net/download-home-edition.html&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/kt4aE/hyOhEBoDEU/LHXVXy9KMhAYoi625up0r0/img.png?width=764&amp;amp;height=489&amp;amp;face=0_0_764_489,https://scrap.kakaocdn.net/dn/3uNn5/hyOhCXQPOd/um2XoVWwzeDyKjuEUzutDK/img.png?width=768&amp;amp;height=443&amp;amp;face=0_0_768_443,https://scrap.kakaocdn.net/dn/bSGpLe/hyOi9T2WXv/aDSD0OWqbiuRnQrbO7IRqk/img.png?width=768&amp;amp;height=443&amp;amp;face=0_0_768_443');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;MobaXterm free Xserver and tabbed SSH client for Windows&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;The ultimate toolbox for remote computing - includes X server, enhanced SSH client and much more!&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;mobaxterm.mobatek.net&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&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;/b&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;b&gt;OS :&amp;nbsp; Windows&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;MobaXterm 설치&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;EC2 인스턴스 생성 후 키페어 다운받음&lt;/b&gt;&lt;/li&gt;
&lt;/ul&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;/b&gt;&lt;/h2&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;1. MobaXterm 실행 후 상단 탭 Session 클릭&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1680&quot; data-origin-height=&quot;1053&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dsJOXl/btrBtDhnl0H/gI11UD2q9qF1UBGTRO08k1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dsJOXl/btrBtDhnl0H/gI11UD2q9qF1UBGTRO08k1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dsJOXl/btrBtDhnl0H/gI11UD2q9qF1UBGTRO08k1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdsJOXl%2FbtrBtDhnl0H%2FgI11UD2q9qF1UBGTRO08k1%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;1680&quot; height=&quot;1053&quot; data-origin-width=&quot;1680&quot; data-origin-height=&quot;1053&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;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;2. Session setting에서 SSH, Advanced SSH settings 클릭&amp;nbsp;&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1396&quot; data-origin-height=&quot;931&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/E2fn5/btrBsukVtYF/JUHVrYLM3sxbkmXpuvbj00/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/E2fn5/btrBsukVtYF/JUHVrYLM3sxbkmXpuvbj00/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/E2fn5/btrBsukVtYF/JUHVrYLM3sxbkmXpuvbj00/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FE2fn5%2FbtrBsukVtYF%2FJUHVrYLM3sxbkmXpuvbj00%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;1396&quot; height=&quot;931&quot; data-origin-width=&quot;1396&quot; data-origin-height=&quot;931&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;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;3. EC2 정보들을 기입합니다.&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;&lt;span style=&quot;background-color: #dddddd;&quot;&gt;Remote host&lt;/span&gt; : EC2 세부정보의 퍼블릭 IP4주소 혹은 탄력적 IP 주소&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;span style=&quot;background-color: #dddddd;&quot;&gt;user private key&lt;/span&gt; : 다운받은 .pem 키의 경로 선택&lt;/b&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;1668&quot; data-origin-height=&quot;931&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/vlgWc/btrBuytmqtN/vliIMZC8clkNmqwFzmYxH1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/vlgWc/btrBuytmqtN/vliIMZC8clkNmqwFzmYxH1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/vlgWc/btrBuytmqtN/vliIMZC8clkNmqwFzmYxH1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FvlgWc%2FbtrBuytmqtN%2FvliIMZC8clkNmqwFzmYxH1%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;1668&quot; height=&quot;931&quot; data-origin-width=&quot;1668&quot; data-origin-height=&quot;931&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1398&quot; data-origin-height=&quot;937&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dswUTI/btrBxbxs0kW/2VNP7wv6Hs1GFSgHq0POZ1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dswUTI/btrBxbxs0kW/2VNP7wv6Hs1GFSgHq0POZ1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dswUTI/btrBxbxs0kW/2VNP7wv6Hs1GFSgHq0POZ1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdswUTI%2FbtrBxbxs0kW%2F2VNP7wv6Hs1GFSgHq0POZ1%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;1398&quot; height=&quot;937&quot; data-origin-width=&quot;1398&quot; data-origin-height=&quot;937&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;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;4. 세션 접속 후 username 입력&amp;nbsp;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;lt;defalut username&amp;gt;&amp;nbsp;&lt;/b&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;background-color: #dddddd;&quot;&gt;ubuntu&lt;/span&gt; : &lt;span&gt;ubuntu&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #dddddd;&quot;&gt;linux&lt;/span&gt; : ec2-user&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;1680&quot; data-origin-height=&quot;1053&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/btK64L/btrBsY695Br/Z6dJiRBKEH2X2UEUdp1ozK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/btK64L/btrBsY695Br/Z6dJiRBKEH2X2UEUdp1ozK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/btK64L/btrBsY695Br/Z6dJiRBKEH2X2UEUdp1ozK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbtK64L%2FbtrBsY695Br%2FZ6dJiRBKEH2X2UEUdp1ozK%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;1680&quot; height=&quot;1053&quot; data-origin-width=&quot;1680&quot; data-origin-height=&quot;1053&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;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;5. 접속 완료&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1680&quot; data-origin-height=&quot;1053&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bibl9p/btrBq1pLIIy/jgJ2R0suUBtJkosXgu4wgk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bibl9p/btrBq1pLIIy/jgJ2R0suUBtJkosXgu4wgk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bibl9p/btrBq1pLIIy/jgJ2R0suUBtJkosXgu4wgk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbibl9p%2FbtrBq1pLIIy%2FjgJ2R0suUBtJkosXgu4wgk%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;1680&quot; height=&quot;1053&quot; data-origin-width=&quot;1680&quot; data-origin-height=&quot;1053&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>☁️AWS</category>
      <author>Cocoon_</author>
      <guid isPermaLink="true">https://cocoon1787.tistory.com/850</guid>
      <comments>https://cocoon1787.tistory.com/850#entry850comment</comments>
      <pubDate>Sat, 7 May 2022 20:51:49 +0900</pubDate>
    </item>
    <item>
      <title>[OS] 스레드(Thread)란?</title>
      <link>https://cocoon1787.tistory.com/849</link>
      <description>&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;812&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dotguH/btrASCQZEGH/mAssEyFkmr2y3rcdqT6CM1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dotguH/btrASCQZEGH/mAssEyFkmr2y3rcdqT6CM1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dotguH/btrASCQZEGH/mAssEyFkmr2y3rcdqT6CM1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdotguH%2FbtrASCQZEGH%2FmAssEyFkmr2y3rcdqT6CM1%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;1444&quot; height=&quot;812&quot; data-origin-width=&quot;1444&quot; data-origin-height=&quot;812&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;
&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;스레드(Thread)란 프로세스 내에서 실행되는 흐름의 단위를 의미합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;695&quot; data-origin-height=&quot;428&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bEmrOF/btrATR2H1hj/xSCNljS70k2qYoKzWBlIlK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bEmrOF/btrATR2H1hj/xSCNljS70k2qYoKzWBlIlK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bEmrOF/btrATR2H1hj/xSCNljS70k2qYoKzWBlIlK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbEmrOF%2FbtrATR2H1hj%2FxSCNljS70k2qYoKzWBlIlK%2Fimg.jpg&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;695&quot; height=&quot;428&quot; data-origin-width=&quot;695&quot; data-origin-height=&quot;428&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일반적으로 하나의 프로그램은 하나의 스레드를 가지고 있지만, 프로그램의 환경에 따라 다수의 스레드를 동시에 실행할 수 있으며 이러한 실행 방식을 멀티스레드(Multi Thread)라고 합니다.&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;⚖️ 프로세스 vs 스레드&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로세스 : 별도의 메모리 공간에서 실행&lt;br /&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;/b&gt;&lt;/h2&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;장점&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;스레드는 하나의 프로세스 내의 자원(코드, 데이터, 힙)을 공유하기 때문에 프로세스에 비해 자원 할당 비용이 적게 들고 문맥 교환(Context Swtich) 비용도 적게 듦&lt;/li&gt;
&lt;li&gt;다중 스레드의 경우 일부 스레드의 처리가 지연되더라도 다른 스레드에서 작업을 계속 처리할 수 있음&lt;/li&gt;
&lt;li&gt;프로세스 간의 통신은 IPC가 필요한 반면, 스레드는 공유(데이터, 힙) 주소 공간을 사용하여 데이터를 교환할 수 있음&lt;/li&gt;
&lt;li&gt;프로세스를 생성하여 자원을 할당하는 시스템 콜이 줄어들어 자원을 효율적으로 관리&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;단점&lt;/b&gt;&lt;/h4&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;
&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;/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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;1. 커널 수준 스레드(1 : 1 매핑 방식)&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스레드를 OS(커널)이 직접 관리(스레드 생성, 스케줄링 등등)합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;594&quot; data-origin-height=&quot;287&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Sc4OP/btrAVtAl4C2/DQVavAV6XEIi368VhfzEzk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Sc4OP/btrAVtAl4C2/DQVavAV6XEIi368VhfzEzk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Sc4OP/btrAVtAl4C2/DQVavAV6XEIi368VhfzEzk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FSc4OP%2FbtrAVtAl4C2%2FDQVavAV6XEIi368VhfzEzk%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;594&quot; height=&quot;287&quot; data-origin-width=&quot;594&quot; data-origin-height=&quot;287&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;장점&lt;/b&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;/li&gt;
&lt;li&gt;프로세스 내 스레드들이 병행 수행 가능&lt;/li&gt;
&lt;li&gt;하나의 스레드가 block 되어도 다른 스레드는 계속 작업 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;단점&lt;/b&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;/li&gt;
&lt;li&gt;문맥 교환으로 인한 오버헤드가 큼&lt;/li&gt;
&lt;li&gt;사용자 스레드보다 생성 및 관리 속도가 느림&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;2. 사용자 수준 스레드(N : 1&amp;nbsp; 매핑)&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자 영역의 스레드 라이브러리로 구현하며, 라이브러리는 스레드의 생성, 스케줄링 담당합니다. 또한 커널은 스레드의 존재를 인식하지 못하기 때문에 커널의 개입을 받지 않습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;513&quot; data-origin-height=&quot;289&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/5f3OL/btrAYudzA4x/WGtSVkdwKeTRyoVEGWZ2Sk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/5f3OL/btrAYudzA4x/WGtSVkdwKeTRyoVEGWZ2Sk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/5f3OL/btrAYudzA4x/WGtSVkdwKeTRyoVEGWZ2Sk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F5f3OL%2FbtrAYudzA4x%2FWGtSVkdwKeTRyoVEGWZ2Sk%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;513&quot; height=&quot;289&quot; data-origin-width=&quot;513&quot; data-origin-height=&quot;289&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;장점&lt;/b&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;/li&gt;
&lt;li&gt;동일한 메모리 영역에서 스레드가 생성 및 관리되므로 속도가 빠름&lt;/li&gt;
&lt;li&gt;라이브러리를 통한 이식성이 높음&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;단점&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;커널은 프로세스 단위로 자원을 할당하기 때문에 하나의 스레드가 block 될 시 모든 스레드가 대기해야 함&lt;br /&gt;(커널이 프로세스의 내부 스레드를 인식하지 못하여 해당 프로세스를 대기상태로 전환시키기 때문)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;3. 혼합 스레드(N : M 매핑 방식)&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자 수준 스레드와 커널 수준 스레드를 혼합한 구조입니다. 일-대-일 방식과 다-대-일 방식의 문제점을 해결하기 위해 고안되었습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;509&quot; data-origin-height=&quot;273&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b20vhF/btrAR8ihyMI/H0pIdFlMu98kktYcGxkQ6K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b20vhF/btrAR8ihyMI/H0pIdFlMu98kktYcGxkQ6K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b20vhF/btrAR8ihyMI/H0pIdFlMu98kktYcGxkQ6K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb20vhF%2FbtrAR8ihyMI%2FH0pIdFlMu98kktYcGxkQ6K%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;509&quot; height=&quot;273&quot; data-origin-width=&quot;509&quot; data-origin-height=&quot;273&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;장점&lt;/b&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;/li&gt;
&lt;li&gt;사용자는 원하는 수만큼 스레드 사용&lt;/li&gt;
&lt;li&gt;효율적이면서도 유연함&lt;/li&gt;
&lt;li&gt;스레드 풀링 기법을 통해 일대일 스레드 매핑에서의 오버헤드를 줄여줌&lt;/li&gt;
&lt;/ul&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;  스레드 풀링?&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;  참고 사이트&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://yoongrammer.tistory.com/55&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://yoongrammer.tistory.com/55&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>⚙️OS</category>
      <author>Cocoon_</author>
      <guid isPermaLink="true">https://cocoon1787.tistory.com/849</guid>
      <comments>https://cocoon1787.tistory.com/849#entry849comment</comments>
      <pubDate>Mon, 2 May 2022 12:34:35 +0900</pubDate>
    </item>
    <item>
      <title>[ OS] 프로세스의 개념, 상태, 제어</title>
      <link>https://cocoon1787.tistory.com/848</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1445&quot; data-origin-height=&quot;806&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lYJFy/btrATStJy77/V3woXw67irhFfhWIA3PhzK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lYJFy/btrATStJy77/V3woXw67irhFfhWIA3PhzK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lYJFy/btrATStJy77/V3woXw67irhFfhWIA3PhzK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlYJFy%2FbtrATStJy77%2FV3woXw67irhFfhWIA3PhzK%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;1445&quot; height=&quot;806&quot; data-origin-width=&quot;1445&quot; data-origin-height=&quot;806&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;
&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;&lt;b&gt;운영체제에서 프로세스는 일련의 작업 단위입니다. 프로그램은 파일이 저장장치에 저장되어 있지만 메모리에는 올라가 있지 않은 정적인 상태이며, 이러한 프로그램을 실행시켜 운영 체제로부터 CPU를 할당받고 실행되고 있는 상태를 바로 프로세스라고 합니다.&lt;/b&gt;&lt;b&gt;&lt;/b&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;/li&gt;
&lt;li&gt;실행 중인 프로시저&lt;/li&gt;
&lt;li&gt;운영 체제로부터 시스템 자원을 할당받는 작업의 단위&lt;/li&gt;
&lt;li&gt;운영체제에 들어있는 프로세스 제어 블록&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, &lt;b&gt;프로세스&lt;/b&gt;는 &lt;b&gt;실행 중인 프로그램&lt;/b&gt;을 의미하며, 프로그램이 실행 중이라는 것은 디스크에 저장되어있던 프로그램을 메모리에 저장한 뒤 &lt;b&gt;운영체제의 CPU 제어권을 받을 수 있는 상태&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;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;프로세스는 아래와 같이 스택, 힙, BSS, 데이터, 코드로 구성되어 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;500&quot; data-origin-height=&quot;475&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/CKXfJ/btrAZe9VdPu/wSez5Zyc2YETxpS5bOoZR0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/CKXfJ/btrAZe9VdPu/wSez5Zyc2YETxpS5bOoZR0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/CKXfJ/btrAZe9VdPu/wSez5Zyc2YETxpS5bOoZR0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FCKXfJ%2FbtrAZe9VdPu%2FwSez5Zyc2YETxpS5bOoZR0%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;500&quot; height=&quot;475&quot; data-origin-width=&quot;500&quot; data-origin-height=&quot;475&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;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li id=&quot;SE-37e69951-03d1-4a55-8d9b-ab934689ed78&quot;&gt;&lt;b&gt;OS Kerner Space : 드라이버 설치&lt;/b&gt;&lt;/li&gt;
&lt;li id=&quot;SE-52df397f-f9f2-4a14-b4b1-90186da33f14&quot;&gt;&lt;b&gt;Stack : 지역변수, 매개변수, 후입 선출(LIFO) 방식, 높은 주소에서 낮은 주소의 방향으로 할당됨&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/li&gt;
&lt;li id=&quot;SE-cb03f452-2c96-45b9-9aa2-52fc8180d6af&quot;&gt;&lt;b&gt;Heap : 동적 메모리(new), 선입선출(FIFO) 방식, 낮은 주소에서&lt;b&gt; 높은 주소의 방향으로 할당됨&lt;/b&gt;&lt;/b&gt;&lt;/li&gt;
&lt;li id=&quot;SE-ca2556e3-45be-4db3-9338-0754e9fce55d&quot;&gt;&lt;b&gt;BSS : Block Started by Symbol, 초기화되지 않은 변수를 위한 영역&lt;/b&gt;&lt;/li&gt;
&lt;li id=&quot;SE-e56fd859-9a8f-40b9-970e-1f07fc6574cd&quot;&gt;&lt;b&gt;Data : 전역 변수, 정적(static) 변수&lt;/b&gt;&lt;/li&gt;
&lt;li id=&quot;SE-92a07266-d2e7-46b8-9748-96d527dbea66&quot;&gt;&lt;b&gt;Text : 상수, 실행할 프로그램의 코드가 저장되는 부분&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p id=&quot;SE-32ca411d-679d-4a38-ba55-986dc3f99dc1&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;오버플로우(Overflow)&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;807&quot; data-origin-height=&quot;401&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cu8QTv/btrA0X7AqPL/k9el4TkKtzs2PVx7lZLcd0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cu8QTv/btrA0X7AqPL/k9el4TkKtzs2PVx7lZLcd0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cu8QTv/btrA0X7AqPL/k9el4TkKtzs2PVx7lZLcd0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcu8QTv%2FbtrA0X7AqPL%2Fk9el4TkKtzs2PVx7lZLcd0%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;807&quot; height=&quot;401&quot; data-origin-width=&quot;807&quot; data-origin-height=&quot;401&quot;/&gt;&lt;/span&gt;&lt;/figure&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;b&gt;한정된 메모리 공간이 부족하여 데이터가 넘친다는 의미&lt;/b&gt;로, 힙의 경우에는 낮은 주소에서 높은 주소로 할당되고, 스택의 경우에는 높은 주소에서 낮은 주소로 할당되어 서로의 영역을 침범할 수 있습니다. 이때 힙이 스택 영역을 침범하는 경우를 &lt;b&gt;힙 오버플로우&lt;/b&gt;, 스택이 힙 영역을 침범하는 경우를 &lt;b&gt;스택 오버플로우&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;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt; &amp;zwj;  프로세스의 상태&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로세스의 상태는 크게 실행(Running), 준비(Ready), 봉쇄(Blocked || Waiting || Sleep) 세 가지로 분류됩니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;690&quot; data-origin-height=&quot;279&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bNNz9y/btrASB5AEN3/5nwzfO0g8MGMjGMZsv3J40/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bNNz9y/btrASB5AEN3/5nwzfO0g8MGMjGMZsv3J40/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bNNz9y/btrASB5AEN3/5nwzfO0g8MGMjGMZsv3J40/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbNNz9y%2FbtrASB5AEN3%2F5nwzfO0g8MGMjGMZsv3J40%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;690&quot; height=&quot;279&quot; data-origin-width=&quot;690&quot; data-origin-height=&quot;279&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;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;new : 프로세스 생성 상태&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;ready : 프로세스 할당 대기 상태&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;running : 프로세스의 명령어를 실행 중인 상태&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;waiting : 프로세스가 어떠한 이벤트가 일어나는 것을 기다리는 상태&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;terminated : 프로세스가 종료된 상태&lt;/b&gt;&lt;/li&gt;
&lt;/ul&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;b&gt;Admitted [생성 -&amp;gt; 준비] : 준비 큐가 비어있을 때 작업 스케줄러에 의해 실행&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Dispatch [준비 -&amp;gt; 실행] : 스케줄러에 의해 준비 큐 맨 앞에 있는 프로세스에게 CPU를 할당&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Blocked [실행 -&amp;gt; 대기] : CPU를 할당받은 프로세스가 입출력 작업등으로 인해 명령을 실행할 수 없는 상태&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Wake up [대기 -&amp;gt; 준비] : block상태의 프로세스가 입출력 작업이 끝나면 대기 상태에서 준비 상태가 됨&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Interrupt [실행 -&amp;gt; 준비] : Timer run out, CPU를 점유 중인 프로세스가 할당된 시간을 모두 사용하여 타임 아웃되거나, CPU 스케줄링 정책에 따라 우선순위가 높은 프로세스로 CPU 디스 패치된 상태&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Exit [실행 -&amp;gt; 종료] : 프로세스가 CPU를 할당받아 작업을 모두 수행한 상태&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;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;&lt;b&gt;문맥 교환(Context Switch)&lt;/b&gt;란 &lt;b&gt;하나의 프로세스로부터 다른 프로세스로 CPU 제어권이 이양되는 과정&lt;/b&gt;을 뜻하는데, 이러한 과정을 CPU 디스패치(Dispatch)라고 합니다. 어떠한 프로세스가 CPU를 할당받고 실행되는 도중 인터럽트가 발생하면 CPU의 제어권은 운영체제로 넘어가게 되고 타이머 인터럽트 처리 루틴으로 가서 수행 중이던 프로세스의 문맥을 저장하고 새롭게 실행시킬 프로세스에게 CPU를 이양합니다. 하지만 프로세스 간 문맥 교환이 빈번하게 발생 시에는 &lt;b&gt;오버헤드&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;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;프로세스 제어블록(PCB, Process Control Block)이란 운영체제가 시스템 내의 프로세스들을 관리하기 위해 프로세스마다 유지하는 정보를 담는 커널 내의 자료구조를 뜻합니다. 프로세스의 상태 관리와 문맥 교환 때문에 필요합니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;프로세스 생성 시 PCB 생성&lt;/li&gt;
&lt;li&gt;프로세스 종료 시 PCB 제거&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;334&quot; data-origin-height=&quot;474&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/SG0MD/btrAUxv8Ow9/Nvta8ns7UZkxoiheWyzvp0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/SG0MD/btrAUxv8Ow9/Nvta8ns7UZkxoiheWyzvp0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/SG0MD/btrAUxv8Ow9/Nvta8ns7UZkxoiheWyzvp0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FSG0MD%2FbtrAUxv8Ow9%2FNvta8ns7UZkxoiheWyzvp0%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;334&quot; height=&quot;474&quot; data-origin-width=&quot;334&quot; data-origin-height=&quot;474&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;PCB 모듈&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;프로세스 식별자 : PID&lt;/li&gt;
&lt;li&gt;프로세스 상태 : CPU 할당 가능 여부&lt;/li&gt;
&lt;li&gt;프로그램 카운터 : 다음에 수행할 명령의 위치&lt;/li&gt;
&lt;li&gt;레지스터 저장 영역 : 레지스터 관련 정보&lt;/li&gt;
&lt;li&gt;프로세서 스케줄링 정보 : 우선순위, 스케줄 큐에 대한 포인터, 다른 스케줄 매개변수 포함&lt;/li&gt;
&lt;li&gt;계정 정보 : CPU 사용시간, 계정 번호 등등&lt;/li&gt;
&lt;li&gt;입출력 상태 관련 정보 : 프로세스에 할당된 입출력 장치들과 열린 파일 목록 등등&lt;/li&gt;
&lt;/ul&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 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;</description>
      <category>⚙️OS</category>
      <author>Cocoon_</author>
      <guid isPermaLink="true">https://cocoon1787.tistory.com/848</guid>
      <comments>https://cocoon1787.tistory.com/848#entry848comment</comments>
      <pubDate>Mon, 2 May 2022 02:28:51 +0900</pubDate>
    </item>
    <item>
      <title>[OS] 컴퓨터 시스템의 기본 구성 요소</title>
      <link>https://cocoon1787.tistory.com/847</link>
      <description>&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;806&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c6pFh8/btrAUxpjFbK/K8DsQmekRRwS9sXhGUWxi1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c6pFh8/btrAUxpjFbK/K8DsQmekRRwS9sXhGUWxi1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c6pFh8/btrAUxpjFbK/K8DsQmekRRwS9sXhGUWxi1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc6pFh8%2FbtrAUxpjFbK%2FK8DsQmekRRwS9sXhGUWxi1%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;1444&quot; height=&quot;806&quot; data-origin-width=&quot;1444&quot; data-origin-height=&quot;806&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;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1066&quot; data-origin-height=&quot;728&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bNIVIJ/btrAnF0Uncw/iIrw8b2dboyUVg3p9xzCNK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bNIVIJ/btrAnF0Uncw/iIrw8b2dboyUVg3p9xzCNK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bNIVIJ/btrAnF0Uncw/iIrw8b2dboyUVg3p9xzCNK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbNIVIJ%2FbtrAnF0Uncw%2FiIrw8b2dboyUVg3p9xzCNK%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;1066&quot; height=&quot;728&quot; data-origin-width=&quot;1066&quot; data-origin-height=&quot;728&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;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;1. 중앙처리장치(CPU, Centeral Processing Unit)&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컴퓨터 동작 제어 및 데이터 처리를 담당하며 중앙처리장치(CPU)라고 부름&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;산술 논리 장치(ALU, Arithmetic and Logic Unit)&lt;br /&gt;데이터 처리&lt;br /&gt;산술/논리 연산을 수행&lt;/li&gt;
&lt;li&gt;제어 장치(CU, Control Unit)&lt;br /&gt;명령어 레지스터에 저장된 명령어 해석&lt;br /&gt;각 컴퓨터의 구성요소를 제어할 제어신호 생성&lt;/li&gt;
&lt;li&gt;레지스터(Register)&lt;br /&gt;명령어를 실행하기 위해 필요한 데이터와 상태, 명령어 저장&lt;/li&gt;
&lt;li&gt;내부 버스(Internal bus)&lt;br /&gt;CPU 내부의 구성요소 간의 데이터 전달과 연결을 위한 통로&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;2. 주기억장치(Main memory)&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데이터와 프로그램을 저장. 휘발성(volatile) 메모리. &lt;br /&gt;보조 저장장치보다 저장 용량이 적지만 속도가 빠르기 때문에 실행되는 프로그램을 적재하고 있음&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;ROM&lt;/li&gt;
&lt;li&gt;RAM&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;3. 입출력 장치(I/O Unit)&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&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;/li&gt;
&lt;li&gt;랜선&lt;/li&gt;
&lt;li&gt;하드디스크&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;4. 시스템 버스(System bus)&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&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;br /&gt;기억장치의 주소 또는 입출력 장치의 포트번호를 지정하고 전달&lt;/li&gt;
&lt;li&gt;데이터 버스&lt;br /&gt;컴퓨터 구성 요소들 간에 데이터 전달&lt;/li&gt;
&lt;li&gt;제어 신호&lt;br /&gt;각 구성 요소 간 제어신호 전달&lt;/li&gt;
&lt;/ul&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 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 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;</description>
      <category>⚙️OS</category>
      <author>Cocoon_</author>
      <guid isPermaLink="true">https://cocoon1787.tistory.com/847</guid>
      <comments>https://cocoon1787.tistory.com/847#entry847comment</comments>
      <pubDate>Mon, 25 Apr 2022 06:57:18 +0900</pubDate>
    </item>
    <item>
      <title>[OS] 운영체제의 구성요소</title>
      <link>https://cocoon1787.tistory.com/846</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1445&quot; data-origin-height=&quot;809&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cMVZTy/btrAh8DduEw/xoKk4OvWYdlohEoLZvct41/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cMVZTy/btrAh8DduEw/xoKk4OvWYdlohEoLZvct41/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cMVZTy/btrAh8DduEw/xoKk4OvWYdlohEoLZvct41/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcMVZTy%2FbtrAh8DduEw%2FxoKk4OvWYdlohEoLZvct41%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;1445&quot; height=&quot;809&quot; data-origin-width=&quot;1445&quot; data-origin-height=&quot;809&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;
&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;&lt;b&gt;운영체제는 커널과 인터페이스로 이루어져 있습니다.&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;726&quot; data-origin-height=&quot;554&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/daVUZF/btrAjoTkGTd/rXqws4nyxtXbCEW6nKKEQ0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/daVUZF/btrAjoTkGTd/rXqws4nyxtXbCEW6nKKEQ0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/daVUZF/btrAjoTkGTd/rXqws4nyxtXbCEW6nKKEQ0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdaVUZF%2FbtrAjoTkGTd%2FrXqws4nyxtXbCEW6nKKEQ0%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;726&quot; height=&quot;554&quot; data-origin-width=&quot;726&quot; data-origin-height=&quot;554&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;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;커널(Kernel)&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로세스 관리, 메모리 관리, 저장장치 관리와 같은 운영체제의 핵심적인 기능을 모아놓은 부분입니다. 커널의 주요 기능은 컴퓨터에 속한 자원들에 대한 접근을 중재하는 것인데, 구체적으로는 입출력 관리, 자원이 필요한 프로세스에 메모리 할당, 프로세스, 메모리 제어, 프로세스 간의 통신, 파일 시스템 관리, 시스템 콜과 같은 역할을 운영체제 맨 하부에서 수행합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;커널 종류&amp;nbsp;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;단일형 구조(MS-DOS, VMS)&lt;/li&gt;
&lt;li&gt;계층형 구조(Windows 등 오늘날의 대부분의 운영체제)&lt;/li&gt;
&lt;li&gt;마이크로 구조(애플의 OS X, IOS)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;인터페이스(Interface)&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자의 명령을 컴퓨터에 전달하고 결과를 사용자에게 알려주는 소통의 역할을 합니다. 운영체제가 제공하는 대표적인 인터페이스로는 GUI, CLI가 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;시스템 콜(System call)&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자나 프로그램이 직접적으로 컴퓨터 자원에 대한 접근하는 것을 막고 커널을 보호하기 위해 만든 인터페이스입니다. prinf(), write(), read()와 같이 사용자나 응용 프로그램이 컴퓨터 자원을 사용하기 위해서는 시스템 호출을 사용해야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;드라이버(Driver)&lt;/b&gt;&lt;/h4&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 data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>⚙️OS</category>
      <author>Cocoon_</author>
      <guid isPermaLink="true">https://cocoon1787.tistory.com/846</guid>
      <comments>https://cocoon1787.tistory.com/846#entry846comment</comments>
      <pubDate>Mon, 25 Apr 2022 02:46:51 +0900</pubDate>
    </item>
    <item>
      <title>[Node.js] 무신사 상품 재입고 알림 만들기 (ver 1.1)</title>
      <link>https://cocoon1787.tistory.com/845</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1200&quot; data-origin-height=&quot;734&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qNeJV/btrxmAWQRxR/IHXFOJgktmVTXbYhx52b1K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qNeJV/btrxmAWQRxR/IHXFOJgktmVTXbYhx52b1K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qNeJV/btrxmAWQRxR/IHXFOJgktmVTXbYhx52b1K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqNeJV%2FbtrxmAWQRxR%2FIHXFOJgktmVTXbYhx52b1K%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;1200&quot; height=&quot;734&quot; data-origin-width=&quot;1200&quot; data-origin-height=&quot;734&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;lt;이전 ver 1.0 개발 포스팅&amp;gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://cocoon1787.tistory.com/741&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://cocoon1787.tistory.com/741&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1648298433537&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[Node.js] Node + Kakao API로 상품 재입고 알림 만들기 (ver 1.0)&quot; data-og-description=&quot;  이제 날이 슬슬 추워지기 시작하는 것 같고 패딩도 좀 필요해서 무신사에서 숏 패딩 하나 구매나 할까 하고 좀 둘러봤습니다. 괜찮은 상품이 있어서 살려했는데 아쉽게도 L, XL 사이즈 모두 &quot; data-og-host=&quot;cocoon1787.tistory.com&quot; data-og-source-url=&quot;https://cocoon1787.tistory.com/741&quot; data-og-url=&quot;https://cocoon1787.tistory.com/741&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/cwfPcG/hyNOr3Ik2k/3QAdlfggz5cNtaWTp5ZSS0/img.png?width=800&amp;amp;height=489&amp;amp;face=0_0_800_489,https://scrap.kakaocdn.net/dn/yDgq0/hyNPKghZv8/hJsP0XcktDJ70ujoAKLosk/img.png?width=800&amp;amp;height=489&amp;amp;face=0_0_800_489,https://scrap.kakaocdn.net/dn/AzbQL/hyNOwDXV31/tWhd2x0PFlV46HbDuwqNc0/img.png?width=1200&amp;amp;height=734&amp;amp;face=0_0_1200_734&quot;&gt;&lt;a href=&quot;https://cocoon1787.tistory.com/741&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://cocoon1787.tistory.com/741&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/cwfPcG/hyNOr3Ik2k/3QAdlfggz5cNtaWTp5ZSS0/img.png?width=800&amp;amp;height=489&amp;amp;face=0_0_800_489,https://scrap.kakaocdn.net/dn/yDgq0/hyNPKghZv8/hJsP0XcktDJ70ujoAKLosk/img.png?width=800&amp;amp;height=489&amp;amp;face=0_0_800_489,https://scrap.kakaocdn.net/dn/AzbQL/hyNOwDXV31/tWhd2x0PFlV46HbDuwqNc0/img.png?width=1200&amp;amp;height=734&amp;amp;face=0_0_1200_734');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[Node.js] Node + Kakao API로 상품 재입고 알림 만들기 (ver 1.0)&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;  이제 날이 슬슬 추워지기 시작하는 것 같고 패딩도 좀 필요해서 무신사에서 숏 패딩 하나 구매나 할까 하고 좀 둘러봤습니다. 괜찮은 상품이 있어서 살려했는데 아쉽게도 L, XL 사이즈 모두&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;cocoon1787.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;메서드 모듈화&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;여러 상품 크롤링&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;코드 리팩터링&lt;/b&gt;&lt;/li&gt;
&lt;/ul&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;/b&gt;&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;249&quot; data-origin-height=&quot;162&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Q8LAq/btrxlpVwrRG/X2awWbwy5UKbJcZPjP99U1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Q8LAq/btrxlpVwrRG/X2awWbwy5UKbJcZPjP99U1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Q8LAq/btrxlpVwrRG/X2awWbwy5UKbJcZPjP99U1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FQ8LAq%2FbtrxlpVwrRG%2FX2awWbwy5UKbJcZPjP99U1%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;162&quot; data-origin-width=&quot;249&quot; data-origin-height=&quot;162&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;
&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;  Run Code&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;server.js&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1648299014477&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const crawl = require(&quot;./crawl.js&quot;);

crawl.restock(1145380, &quot;L&quot;);
crawl.restock(1520534, &quot;XL&quot;);
...&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;restock 함수의 첫 번째 파라미터는 itemNum, 두 번째 파라미터는 size&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;289&quot; data-origin-height=&quot;22&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bReHLM/btrxkN3ucI2/HOY367ZrbxlEoEssk2W9V1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bReHLM/btrxkN3ucI2/HOY367ZrbxlEoEssk2W9V1/img.png&quot; data-alt=&quot;상품의 주소 goods/ 다음 값이 itemNum&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bReHLM/btrxkN3ucI2/HOY367ZrbxlEoEssk2W9V1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbReHLM%2FbtrxkN3ucI2%2FHOY367ZrbxlEoEssk2W9V1%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;289&quot; height=&quot;22&quot; data-origin-width=&quot;289&quot; data-origin-height=&quot;22&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;상품의 주소 goods/ 다음 값이 itemNum&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;308&quot; data-origin-height=&quot;96&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/u3l8a/btrxmzXVHNw/mt8iOsV5uK7toYWm7F5VBk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/u3l8a/btrxmzXVHNw/mt8iOsV5uK7toYWm7F5VBk/img.png&quot; data-alt=&quot;사이즈는 해당 상품의 사이즈들&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/u3l8a/btrxmzXVHNw/mt8iOsV5uK7toYWm7F5VBk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fu3l8a%2FbtrxmzXVHNw%2Fmt8iOsV5uK7toYWm7F5VBk%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;308&quot; height=&quot;96&quot; data-origin-width=&quot;308&quot; data-origin-height=&quot;96&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;&lt;b&gt;터미널에서 다음을 입력.&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1648299001491&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;node server.js&lt;/code&gt;&lt;/pre&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;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;crawl.js&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1648298820778&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const scheduler = require(&quot;node-schedule&quot;);
const cheerio = require(&quot;cheerio&quot;);
const request = require(&quot;request&quot;);
const kakaoTalk = require(&quot;./kakaoTalk.js&quot;);

function restock(itemNum, size) {
  const schedule = scheduler.scheduleJob(&quot;*/2 * * * * *&quot;, function () {
    let url = &quot;https://store.musinsa.com/app/goods/&quot; + itemNum;
    request(url, function (error, response, html) {
      if (error) {
        throw error;
      }
      const $ = cheerio.load(html);
      const productTitle = $(&quot;.product_title em&quot;).text();
      const option = $(&quot;.option1 option&quot;);
      let map = new Map();
      console.log(productTitle);
      for (let i = 1; i &amp;lt; option.length; i++) {
        // console.log(option[i].attribs.value + &quot; &quot; + option[i].attribs.jaego_yn);
        map.set(option[i].attribs.value, option[i].attribs.jaego_yn);
      }

      console.log(&quot;사이즈: &quot; + size);
      console.log(&quot;재고: &quot; + map.get(size));

      if (map.get(size) === &quot;Y&quot;) {
        const msg = productTitle + &quot; &quot; + size + &quot; 재고있음&quot;;
        console.log(msg);
        kakaoTalk.sendMessage(msg);
        schedule.cancel();
      }
    });
  });
}

module.exports = {
  restock: restock,
};&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;kakaoTalk.js&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1648298855168&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const request = require(&quot;request&quot;);
const accessToken = &quot;tFcr8OIN47i4J6dgN9JL9FrHHx_6a52OaY4jfAo9dJkAAAF_xjVFJg&quot;;
const headers = {
  &quot;Content-Type&quot;: &quot;application/x-www-form-urlencoded&quot;,
  Authorization: &quot;Bearer &quot; + accessToken,
};

function sendMessage(msg) {
  const dataString = `template_object={
    &quot;object_type&quot;: &quot;text&quot;,
    &quot;text&quot;: &quot;${msg}&quot;,
    &quot;link&quot;: {
        &quot;web_url&quot;: &quot;https://developers.kakao.com&quot;,
        &quot;mobile_web_url&quot;: &quot;https://developers.kakao.com&quot;
    },
    &quot;button_title&quot;: &quot;바로 확인&quot;
}`;
  const options = {
    url: &quot;https://kapi.kakao.com/v2/api/talk/memo/default/send&quot;,
    method: &quot;POST&quot;,
    headers: headers,
    body: dataString,
  };
  request(options, (error, response, body) =&amp;gt; {
    console.log(response.statusCode);
    if (!error &amp;amp;&amp;amp; response.statusCode == 200) {
      console.log(&quot;메시지 전송 완료.&quot;);
    } else {
      console.log(error);
    }
  });
}

module.exports = {
  sendMessage: sendMessage,
};&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;server.js&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1648298860793&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const crawl = require(&quot;./crawl.js&quot;);

crawl.restock(1145380, &quot;L&quot;);
crawl.restock(1520534, &quot;LL&quot;);&lt;/code&gt;&lt;/pre&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;Node.js 크롤링&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;crawl.js&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1648298938773&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const scheduler = require(&quot;node-schedule&quot;);
const cheerio = require(&quot;cheerio&quot;);
const request = require(&quot;request&quot;);
const kakaoTalk = require(&quot;./kakaoTalk.js&quot;);

function restock(itemNum, size) {
  const schedule = scheduler.scheduleJob(&quot;*/2 * * * * *&quot;, function () {
    let url = &quot;https://store.musinsa.com/app/goods/&quot; + itemNum;
    request(url, function (error, response, html) {
      if (error) {
        throw error;
      }
      const $ = cheerio.load(html);
      const productTitle = $(&quot;.product_title em&quot;).text();
      const option = $(&quot;.option1 option&quot;);
      let map = new Map();
      console.log(productTitle);
      for (let i = 1; i &amp;lt; option.length; i++) {
        // console.log(option[i].attribs.value + &quot; &quot; + option[i].attribs.jaego_yn);
        map.set(option[i].attribs.value, option[i].attribs.jaego_yn);
      }

      console.log(&quot;사이즈: &quot; + size);
      console.log(&quot;재고: &quot; + map.get(size));

      if (map.get(size) === &quot;Y&quot;) {
        const msg = productTitle + &quot; &quot; + size + &quot; 재고있음&quot;;
        console.log(msg);
        kakaoTalk.sendMessage(msg);
        schedule.cancel();
      }
    });
  });
}

module.exports = {
  restock: restock,
};&lt;/code&gt;&lt;/pre&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;b&gt;상품명 출력&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;733&quot; data-origin-height=&quot;120&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cIzMNx/btrxr4PV4w1/kYpfBOMylP3ZHvfCY6yNK1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cIzMNx/btrxr4PV4w1/kYpfBOMylP3ZHvfCY6yNK1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cIzMNx/btrxr4PV4w1/kYpfBOMylP3ZHvfCY6yNK1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcIzMNx%2Fbtrxr4PV4w1%2FkYpfBOMylP3ZHvfCY6yNK1%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;733&quot; height=&quot;120&quot; data-origin-width=&quot;733&quot; data-origin-height=&quot;120&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre id=&quot;code_1648299287291&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const $ = cheerio.load(html);  
const productTitle = $(&quot;.product_title em&quot;).text();&lt;/code&gt;&lt;/pre&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;b&gt;옵션 값들 map으로 저장(key : 사이즈, value : 재고 존재 여부)&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;871&quot; data-origin-height=&quot;264&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cD7ZdZ/btrxkhqbdAG/3WJWxTPFW7o1kejFvcKM80/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cD7ZdZ/btrxkhqbdAG/3WJWxTPFW7o1kejFvcKM80/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cD7ZdZ/btrxkhqbdAG/3WJWxTPFW7o1kejFvcKM80/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcD7ZdZ%2FbtrxkhqbdAG%2F3WJWxTPFW7o1kejFvcKM80%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;871&quot; height=&quot;264&quot; data-origin-width=&quot;871&quot; data-origin-height=&quot;264&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre id=&quot;code_1648299336854&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const $ = cheerio.load(html);
const productTitle = $(&quot;.product_title em&quot;).text();
const option = $(&quot;.option1 option&quot;);
let map = new Map();
console.log(productTitle);
for (let i = 1; i &amp;lt; option.length; i++) {
	// console.log(option[i].attribs.value + &quot; &quot; + option[i].attribs.jaego_yn);
	map.set(option[i].attribs.value, option[i].attribs.jaego_yn);
}&lt;/code&gt;&lt;/pre&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;b&gt;해당 사이즈의 재고가 있을 경우 카카오톡 메시지 보내기&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1648299508759&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;if (map.get(size) === &quot;Y&quot;) {
  const msg = productTitle + &quot; &quot; + size + &quot; 재고있음&quot;;
  console.log(msg);
  kakaoTalk.sendMessage(msg);
  schedule.cancel();
}&lt;/code&gt;&lt;/pre&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;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;kakaoTalk.js&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1648299642710&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const request = require(&quot;request&quot;);
const accessToken = &quot;tFcr8OIN47i4J6dgN9JL9FrHHx_6a52OaY4jfAo9dJkAAAF_xjVFJg&quot;;
const headers = {
  &quot;Content-Type&quot;: &quot;application/x-www-form-urlencoded&quot;,
  Authorization: &quot;Bearer &quot; + accessToken,
};

function sendMessage(msg) {
  const dataString = `template_object={
    &quot;object_type&quot;: &quot;text&quot;,
    &quot;text&quot;: &quot;${msg}&quot;,
    &quot;link&quot;: {
        &quot;web_url&quot;: &quot;https://developers.kakao.com&quot;,
        &quot;mobile_web_url&quot;: &quot;https://developers.kakao.com&quot;
    },
    &quot;button_title&quot;: &quot;바로 확인&quot;
}`;
  const options = {
    url: &quot;https://kapi.kakao.com/v2/api/talk/memo/default/send&quot;,
    method: &quot;POST&quot;,
    headers: headers,
    body: dataString,
  };
  request(options, (error, response, body) =&amp;gt; {
    console.log(response.statusCode);
    if (!error &amp;amp;&amp;amp; response.statusCode == 200) {
      console.log(&quot;메시지 전송 완료.&quot;);
    } else {
      console.log(error);
    }
  });
}

module.exports = {
  sendMessage: sendMessage,
};&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;429&quot; data-origin-height=&quot;458&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bpneZP/btrxqacg5mf/ylZLRYwP8N5ErK0AM7yelK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bpneZP/btrxqacg5mf/ylZLRYwP8N5ErK0AM7yelK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bpneZP/btrxqacg5mf/ylZLRYwP8N5ErK0AM7yelK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbpneZP%2Fbtrxqacg5mf%2FylZLRYwP8N5ErK0AM7yelK%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;429&quot; height=&quot;458&quot; data-origin-width=&quot;429&quot; data-origin-height=&quot;458&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;
&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;⭐️ 카카오 API 액세스 토큰 발급&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;kakao developers에서 애플리케이션 생성&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://developers.kakao.com/console/app&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://developers.kakao.com/console/app&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1648301062925&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;카카오계정 로그인&quot; data-og-description=&quot;여기를 눌러 링크를 확인하세요.&quot; data-og-host=&quot;accounts.kakao.com&quot; data-og-source-url=&quot;https://developers.kakao.com/console/app&quot; data-og-url=&quot;https://accounts.kakao.com/login?continue=https%3A%2F%2Fdevelopers.kakao.com%2Flogin%3Fcontinue%3D%252Fconsole%252Fapp&amp;amp;lang=en&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/ilDNW/hyNOsuNSXx/5KydR4d0bXxKdeCZymFk9k/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/sXHEs/hyNOvSEutF/TVrbYk0RZCzWFcpY0Ok1jK/img.png?width=1080&amp;amp;height=632&amp;amp;face=0_0_1080_632&quot;&gt;&lt;a href=&quot;https://developers.kakao.com/console/app&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://developers.kakao.com/console/app&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/ilDNW/hyNOsuNSXx/5KydR4d0bXxKdeCZymFk9k/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/sXHEs/hyNOvSEutF/TVrbYk0RZCzWFcpY0Ok1jK/img.png?width=1080&amp;amp;height=632&amp;amp;face=0_0_1080_632');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;카카오계정 로그인&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;여기를 눌러 링크를 확인하세요.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;accounts.kakao.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;935&quot; data-origin-height=&quot;439&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/pqw6n/btrxqbbb5y7/lknxcE9MtkK27CkDmkGUT0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/pqw6n/btrxqbbb5y7/lknxcE9MtkK27CkDmkGUT0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/pqw6n/btrxqbbb5y7/lknxcE9MtkK27CkDmkGUT0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fpqw6n%2Fbtrxqbbb5y7%2FlknxcE9MtkK27CkDmkGUT0%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;935&quot; height=&quot;439&quot; data-origin-width=&quot;935&quot; data-origin-height=&quot;439&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;934&quot; data-origin-height=&quot;565&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c640JU/btrxmzp6WYy/vaKUd2uKZz4Q7OcfoKC0pk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c640JU/btrxmzp6WYy/vaKUd2uKZz4Q7OcfoKC0pk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c640JU/btrxmzp6WYy/vaKUd2uKZz4Q7OcfoKC0pk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc640JU%2Fbtrxmzp6WYy%2FvaKUd2uKZz4Q7OcfoKC0pk%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;934&quot; height=&quot;565&quot; data-origin-width=&quot;934&quot; data-origin-height=&quot;565&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;애플리케이션을 추가하고 추가한 애플리케이션을 클릭합니다.&lt;/b&gt;&lt;b&gt;&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;&lt;b&gt;애플리케이션을 생성했으니 이제 아래의 URL로 들어가 봅시다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://developers.kakao.com/tool/rest-api/open/post/v2-api-talk-memo-default-send&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://developers.kakao.com/tool/rest-api/open/post/v2-api-talk-memo-default-send&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1648301562066&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;카카오계정 로그인&quot; data-og-description=&quot;여기를 눌러 링크를 확인하세요.&quot; data-og-host=&quot;accounts.kakao.com&quot; data-og-source-url=&quot;https://developers.kakao.com/tool/rest-api/open/post/v2-api-talk-memo-default-send&quot; data-og-url=&quot;https://accounts.kakao.com/login?continue=https%3A%2F%2Fdevelopers.kakao.com%2Flogin%3Fcontinue%3D%252Ftool%252Frest-api%252Fopen%252Fpost%252Fv2-api-talk-memo-default-send&amp;amp;lang=en&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/eAw91/hyNOpEQdch/cVNkv1sQjT1VrHkSEcKZ91/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/cm4pPb/hyNOkXQYot/CRXgStFxELLQBuMMvtuRc0/img.png?width=1080&amp;amp;height=632&amp;amp;face=0_0_1080_632&quot;&gt;&lt;a href=&quot;https://developers.kakao.com/tool/rest-api/open/post/v2-api-talk-memo-default-send&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://developers.kakao.com/tool/rest-api/open/post/v2-api-talk-memo-default-send&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/eAw91/hyNOpEQdch/cVNkv1sQjT1VrHkSEcKZ91/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/cm4pPb/hyNOkXQYot/CRXgStFxELLQBuMMvtuRc0/img.png?width=1080&amp;amp;height=632&amp;amp;face=0_0_1080_632');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;카카오계정 로그인&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;여기를 눌러 링크를 확인하세요.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;accounts.kakao.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&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;1895&quot; data-origin-height=&quot;929&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ZXbxc/btrxkhcC3rM/knC0ag6ctXtViEWWf46fi1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ZXbxc/btrxkhcC3rM/knC0ag6ctXtViEWWf46fi1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ZXbxc/btrxkhcC3rM/knC0ag6ctXtViEWWf46fi1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FZXbxc%2FbtrxkhcC3rM%2FknC0ag6ctXtViEWWf46fi1%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;1895&quot; height=&quot;929&quot; data-origin-width=&quot;1895&quot; data-origin-height=&quot;929&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;요청 - 인증 앱 부분이 developers-sample로 되어있습니다. 오른쪽에 목록 아이콘을 클릭하여 아까 만들어준 애플리케이션으로 변경시켜 줍니다.&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;954&quot; data-origin-height=&quot;374&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Of8dk/btrxj8lAShO/qIphO0MnepAx7vDOxKUEBK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Of8dk/btrxj8lAShO/qIphO0MnepAx7vDOxKUEBK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Of8dk/btrxj8lAShO/qIphO0MnepAx7vDOxKUEBK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FOf8dk%2Fbtrxj8lAShO%2FqIphO0MnepAx7vDOxKUEBK%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;954&quot; height=&quot;374&quot; data-origin-width=&quot;954&quot; data-origin-height=&quot;374&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;그리고 토큰 발급을 받아보려고 하니....&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;990&quot; data-origin-height=&quot;621&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ciqrXE/btrxqb9755l/3zT8GYsf0FX5LGR5cU9WiK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ciqrXE/btrxqb9755l/3zT8GYsf0FX5LGR5cU9WiK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ciqrXE/btrxqb9755l/3zT8GYsf0FX5LGR5cU9WiK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FciqrXE%2Fbtrxqb9755l%2F3zT8GYsf0FX5LGR5cU9WiK%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;990&quot; height=&quot;621&quot; data-origin-width=&quot;990&quot; data-origin-height=&quot;621&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;지금 사용해야 할 기능은 talk_message이지만 활성화할 수 없는 상태입니다. talk_message기능을 활성화해주러 가봅시다.&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;&lt;b&gt;최상단의 &quot;내 애플리케이션&quot;으로 들어가 생성한 애플리케이션을 클릭해주시고&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1340&quot; data-origin-height=&quot;545&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bjFy2u/btrxtZ19L9G/LshegpuNdiFKr69w43FY91/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bjFy2u/btrxtZ19L9G/LshegpuNdiFKr69w43FY91/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bjFy2u/btrxtZ19L9G/LshegpuNdiFKr69w43FY91/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbjFy2u%2FbtrxtZ19L9G%2FLshegpuNdiFKr69w43FY91%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;1340&quot; height=&quot;545&quot; data-origin-width=&quot;1340&quot; data-origin-height=&quot;545&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;제품 설정 - 카카오 로그인으로 들어가 주세요.&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1325&quot; data-origin-height=&quot;647&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bnqUvr/btrxoXxuJJb/jyGkQ4KHFbU7MisRWLoMpK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bnqUvr/btrxoXxuJJb/jyGkQ4KHFbU7MisRWLoMpK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bnqUvr/btrxoXxuJJb/jyGkQ4KHFbU7MisRWLoMpK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbnqUvr%2FbtrxoXxuJJb%2FjyGkQ4KHFbU7MisRWLoMpK%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;1325&quot; height=&quot;647&quot; data-origin-width=&quot;1325&quot; data-origin-height=&quot;647&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;카카오 로그인을 활성화시켜줍니다.&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1317&quot; data-origin-height=&quot;666&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/oDgIe/btrxoXjYzj1/CLe6JOXk51U4q5yZTE93F0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/oDgIe/btrxoXjYzj1/CLe6JOXk51U4q5yZTE93F0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/oDgIe/btrxoXjYzj1/CLe6JOXk51U4q5yZTE93F0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FoDgIe%2FbtrxoXjYzj1%2FCLe6JOXk51U4q5yZTE93F0%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;1317&quot; height=&quot;666&quot; data-origin-width=&quot;1317&quot; data-origin-height=&quot;666&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;그리고 이번엔 제품 설정 - 카카오 로그인 - 동의 항목으로 들어가 주세요.&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1323&quot; data-origin-height=&quot;678&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bW2Mfi/btrxqbPO986/U6gccuiXN3lz9LwNDuYTB0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bW2Mfi/btrxqbPO986/U6gccuiXN3lz9LwNDuYTB0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bW2Mfi/btrxqbPO986/U6gccuiXN3lz9LwNDuYTB0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbW2Mfi%2FbtrxqbPO986%2FU6gccuiXN3lz9LwNDuYTB0%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;1323&quot; height=&quot;678&quot; data-origin-width=&quot;1323&quot; data-origin-height=&quot;678&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;b&gt;맨 아래쪽 접근권한 - 카카오톡 메시지 전송 - 설정&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;907&quot; data-origin-height=&quot;378&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/pEanL/btrxoW6q3wR/NVCyEJsZ2m9Iv8ZhFTM4pK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/pEanL/btrxoW6q3wR/NVCyEJsZ2m9Iv8ZhFTM4pK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/pEanL/btrxoW6q3wR/NVCyEJsZ2m9Iv8ZhFTM4pK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FpEanL%2FbtrxoW6q3wR%2FNVCyEJsZ2m9Iv8ZhFTM4pK%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;907&quot; height=&quot;378&quot; data-origin-width=&quot;907&quot; data-origin-height=&quot;378&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;선택 동의로 체크해줍니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://devtalk.kakao.com/t/topic/60237&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://devtalk.kakao.com/t/topic/60237&lt;/a&gt; (선택 동의, 이용 중 동의 차이점)&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1322&quot; data-origin-height=&quot;902&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/subxQ/btrxoHndq34/NryDYlyarw93EPNpGwxSO0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/subxQ/btrxoHndq34/NryDYlyarw93EPNpGwxSO0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/subxQ/btrxoHndq34/NryDYlyarw93EPNpGwxSO0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FsubxQ%2FbtrxoHndq34%2FNryDYlyarw93EPNpGwxSO0%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;1322&quot; height=&quot;902&quot; data-origin-width=&quot;1322&quot; data-origin-height=&quot;902&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;동의를 하였으니 이제 아까 페이지로 돌아가서 토큰을 발급받아 봅시다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://developers.kakao.com/tool/rest-api/open/post/v2-api-talk-memo-default-send&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://developers.kakao.com/tool/rest-api/open/post/v2-api-talk-memo-default-send&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1648302290415&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;카카오계정 로그인&quot; data-og-description=&quot;여기를 눌러 링크를 확인하세요.&quot; data-og-host=&quot;accounts.kakao.com&quot; data-og-source-url=&quot;https://developers.kakao.com/tool/rest-api/open/post/v2-api-talk-memo-default-send&quot; data-og-url=&quot;https://accounts.kakao.com/login?continue=https%3A%2F%2Fdevelopers.kakao.com%2Flogin%3Fcontinue%3D%252Ftool%252Frest-api%252Fopen%252Fpost%252Fv2-api-talk-memo-default-send&amp;amp;lang=en&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/eAw91/hyNOpEQdch/cVNkv1sQjT1VrHkSEcKZ91/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/cm4pPb/hyNOkXQYot/CRXgStFxELLQBuMMvtuRc0/img.png?width=1080&amp;amp;height=632&amp;amp;face=0_0_1080_632&quot;&gt;&lt;a href=&quot;https://developers.kakao.com/tool/rest-api/open/post/v2-api-talk-memo-default-send&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://developers.kakao.com/tool/rest-api/open/post/v2-api-talk-memo-default-send&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/eAw91/hyNOpEQdch/cVNkv1sQjT1VrHkSEcKZ91/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/cm4pPb/hyNOkXQYot/CRXgStFxELLQBuMMvtuRc0/img.png?width=1080&amp;amp;height=632&amp;amp;face=0_0_1080_632');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;카카오계정 로그인&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;여기를 눌러 링크를 확인하세요.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;accounts.kakao.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;991&quot; data-origin-height=&quot;627&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ekJwC1/btrxqbvwLTh/IrzFjWSwbutw3qO8yvb8C1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ekJwC1/btrxqbvwLTh/IrzFjWSwbutw3qO8yvb8C1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ekJwC1/btrxqbvwLTh/IrzFjWSwbutw3qO8yvb8C1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FekJwC1%2FbtrxqbvwLTh%2FIrzFjWSwbutw3qO8yvb8C1%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;991&quot; height=&quot;627&quot; data-origin-width=&quot;991&quot; data-origin-height=&quot;627&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;talk_message 항목이 활성화되었습니다.&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1306&quot; data-origin-height=&quot;814&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c7FlSp/btrxkf0lsFL/Vy8LHnyo14PIMLloyvSXQ0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c7FlSp/btrxkf0lsFL/Vy8LHnyo14PIMLloyvSXQ0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c7FlSp/btrxkf0lsFL/Vy8LHnyo14PIMLloyvSXQ0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc7FlSp%2Fbtrxkf0lsFL%2FVy8LHnyo14PIMLloyvSXQ0%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;1306&quot; height=&quot;814&quot; data-origin-width=&quot;1306&quot; data-origin-height=&quot;814&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;선택항목을 체크하고 &quot;동의하고 계속하기&quot;를 눌러주면 토큰 발급됩니다.&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;974&quot; data-origin-height=&quot;528&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Grzeb/btrxmBaqNqA/hhC402J1JOJQzOTQU5iJ3k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Grzeb/btrxmBaqNqA/hhC402J1JOJQzOTQU5iJ3k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Grzeb/btrxmBaqNqA/hhC402J1JOJQzOTQU5iJ3k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FGrzeb%2FbtrxmBaqNqA%2FhhC402J1JOJQzOTQU5iJ3k%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;974&quot; height=&quot;528&quot; data-origin-width=&quot;974&quot; data-origin-height=&quot;528&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;발급받으신 토큰을 kakaoTalk.js의 accessToken이라는 변수에 붙여 넣어 주세요.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;608&quot; data-origin-height=&quot;196&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/uGooq/btrxqbh0zYa/xKRIoopCzcglfzxjN18gcK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/uGooq/btrxqbh0zYa/xKRIoopCzcglfzxjN18gcK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/uGooq/btrxqbh0zYa/xKRIoopCzcglfzxjN18gcK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FuGooq%2Fbtrxqbh0zYa%2FxKRIoopCzcglfzxjN18gcK%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;608&quot; height=&quot;196&quot; data-origin-width=&quot;608&quot; data-origin-height=&quot;196&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;
&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;&lt;b&gt;server.js&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1648299862796&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const crawl = require(&quot;./crawl.js&quot;);

crawl.restock(1145380, &quot;L&quot;);
crawl.restock(1520534, &quot;LL&quot;);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;lt;상황&amp;gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;itemNum : 1145380 -&amp;gt; &lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;플리스 집업 자켓 블랙 / L 사이즈 / &lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;재고 있음&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;itemNum : 1520534 - &amp;gt; 304-ALT 드라이 무지 긴팔티 블랙 / LL 사이즈 / &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;재고 없음&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;699&quot; data-origin-height=&quot;325&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/FCPdd/btrxt0zWX5f/gkCeqS7wMy9fc3QXeIg31k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/FCPdd/btrxt0zWX5f/gkCeqS7wMy9fc3QXeIg31k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/FCPdd/btrxt0zWX5f/gkCeqS7wMy9fc3QXeIg31k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FFCPdd%2Fbtrxt0zWX5f%2FgkCeqS7wMy9fc3QXeIg31k%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;699&quot; height=&quot;325&quot; data-origin-width=&quot;699&quot; data-origin-height=&quot;325&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;scheduler 모듈을 통해 2초마다 크롤링하도록 하였고 크롤링 후 재고가 있을 시에 카카오톡으로 메시지를 보내고 scheduler를 종료하도록 하였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 콘솔 창에서 &lt;span&gt;1145380번 상품의 L사이즈 재고를 확인하고 스케쥴러를 종료하여 &lt;span&gt;1520534번 상품만 크롤링되고 있는 것을 확인할 수 있습니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;429&quot; data-origin-height=&quot;119&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/csrpce/btrxkgSjC6v/DUmB7GKslsfkWZX5tDnb90/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/csrpce/btrxkgSjC6v/DUmB7GKslsfkWZX5tDnb90/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/csrpce/btrxkgSjC6v/DUmB7GKslsfkWZX5tDnb90/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcsrpce%2FbtrxkgSjC6v%2FDUmB7GKslsfkWZX5tDnb90%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;429&quot; height=&quot;119&quot; data-origin-width=&quot;429&quot; data-origin-height=&quot;119&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;물론 카카오톡 나와의 채팅에서는 &quot;플리스 집업 자켓 블랙 L 재고 있음&quot;이라고 메시지가 하나만 와있게 됩니다.&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;  Bug&lt;/b&gt;&lt;/h2&gt;
&lt;pre id=&quot;code_1648300243386&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const crawl = require(&quot;./crawl.js&quot;);

crawl.restock(9999999, &quot;L&quot;);
crawl.restock(1520534, &quot;asdasd&quot;);&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;737&quot; data-origin-height=&quot;146&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kVh8C/btrxsDZjinC/wRjVp7No6aHLU9SehGGeEK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kVh8C/btrxsDZjinC/wRjVp7No6aHLU9SehGGeEK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kVh8C/btrxsDZjinC/wRjVp7No6aHLU9SehGGeEK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkVh8C%2FbtrxsDZjinC%2FwRjVp7No6aHLU9SehGGeEK%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;737&quot; height=&quot;146&quot; data-origin-width=&quot;737&quot; data-origin-height=&quot;146&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;존재하지 않는 itemNum이거나 사이즈 명이 이상할 경우 위와 같이 출력될 수 있으니 꼭 해당 상품의 itemNum과 사이즈명을 확인하시고 크롤링하시길 바랍니다.&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 data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/K-Junyyy/MUSINSA-CRWALING&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://github.com/K-Junyyy/MUSINSA-CRWALING&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1648300450144&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;GitHub - K-Junyyy/MUSINSA-CRWALING&quot; data-og-description=&quot;Contribute to K-Junyyy/MUSINSA-CRWALING development by creating an account on GitHub.&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/K-Junyyy/MUSINSA-CRWALING&quot; data-og-url=&quot;https://github.com/K-Junyyy/MUSINSA-CRWALING&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bCTAdt/hyNPLzvQvr/VcCcdgL7kTyknz3xHZZeL1/img.png?width=1200&amp;amp;height=600&amp;amp;face=984_161_1064_249&quot;&gt;&lt;a href=&quot;https://github.com/K-Junyyy/MUSINSA-CRWALING&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/K-Junyyy/MUSINSA-CRWALING&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bCTAdt/hyNPLzvQvr/VcCcdgL7kTyknz3xHZZeL1/img.png?width=1200&amp;amp;height=600&amp;amp;face=984_161_1064_249');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;GitHub - K-Junyyy/MUSINSA-CRWALING&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Contribute to K-Junyyy/MUSINSA-CRWALING development by creating an account on GitHub.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&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;</description>
      <category> Node.js</category>
      <author>Cocoon_</author>
      <guid isPermaLink="true">https://cocoon1787.tistory.com/845</guid>
      <comments>https://cocoon1787.tistory.com/845#entry845comment</comments>
      <pubDate>Sat, 26 Mar 2022 22:15:25 +0900</pubDate>
    </item>
    <item>
      <title>[React] 리액트 .js vs .jsx 차이점</title>
      <link>https://cocoon1787.tistory.com/844</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;450&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xBeEO/btrwey0Cc7I/yXpelfJKlWkhrIr4eQT4a1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xBeEO/btrwey0Cc7I/yXpelfJKlWkhrIr4eQT4a1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xBeEO/btrwey0Cc7I/yXpelfJKlWkhrIr4eQT4a1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxBeEO%2Fbtrwey0Cc7I%2FyXpelfJKlWkhrIr4eQT4a1%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;800&quot; height=&quot;450&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;450&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;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;⏲&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;TL;DR&lt;/b&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;jsx는 JavaScript 확장 문법&lt;/li&gt;
&lt;li&gt;JavaScript안에서 HTML 사용 가능&lt;/li&gt;
&lt;li&gt;jsx 사용이 필수는 아니지만 추천 (리액트 공식 홈페이지 - 문서 - JSX 소개 탭)&lt;/li&gt;
&lt;li&gt;기능적인 차이는 없으나 팀 내 협의의 문제&lt;/li&gt;
&lt;/ul&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;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;리액트를 공부할 때 js보다 jsx를 쓰는 이유가 &quot;자바스크립트 내에 HTML을 사용할 수 있어서&quot;라고 얼핏 본거 같은데 구체적으로 뭐가 더 왜 좋은지, 대체적으로 뭘 더 많이 쓰는지 몰라서 한번 제대로 알아봤습니다.&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;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;  JSX란?&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JSX는 JavaScript XML의 약자로 자바스크립트에서 XML을 추가한 확장형 문법입니다. 큰 특징은 자바스크립트에서 HTML 문법을 사용할 수 있다는 점이고 주로 리액트나 다른 프론트엔드 프레임워크에서도 사용이 가능합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1647537942680&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// jsx
const element = &amp;lt;h1&amp;gt;Hello, world!&amp;lt;/h1&amp;gt;;&lt;/code&gt;&lt;/pre&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;  .js vs .jsx 논쟁&lt;/b&gt;&lt;/h2&gt;
&lt;pre id=&quot;code_1647538213691&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// JS
class Hello extends React.Component {
  render() {
    return React.createElement(&quot;div&quot;, null, &quot;Hello &quot;, this.props.name);
  }
}

ReactDOM.render(
  React.createElement(Hello, {name: &quot;World&quot;}),
  document.getElementById('container')
);&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1647538198710&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// JSX
class Hello extends React.Component {
  render() {
    return &amp;lt;div&amp;gt;Hello {this.props.name}&amp;lt;/div&amp;gt;;
  }
}

ReactDOM.render(
  &amp;lt;Hello name=&quot;World&quot; /&amp;gt;,
  document.getElementById('container')
);&lt;/code&gt;&lt;/pre&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 data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://stackoverflow.com/questions/46169472/reactjs-js-vs-jsx&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://stackoverflow.com/questions/46169472/reactjs-js-vs-jsx&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1647536646125&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;ReactJS - .JS vs .JSX&quot; data-og-description=&quot;There is something I find very confusing when working in React.js. There are plenty of examples available on internet which use .js files with React but many others use .jsx files. I have read abou...&quot; data-og-host=&quot;stackoverflow.com&quot; data-og-source-url=&quot;https://stackoverflow.com/questions/46169472/reactjs-js-vs-jsx&quot; data-og-url=&quot;https://stackoverflow.com/questions/46169472/reactjs-js-vs-jsx&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/j1pfX/hyNKhSojVR/9nOmt7c7j5zGoAWOjwLG51/img.png?width=316&amp;amp;height=316&amp;amp;face=0_0_316_316&quot;&gt;&lt;a href=&quot;https://stackoverflow.com/questions/46169472/reactjs-js-vs-jsx&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://stackoverflow.com/questions/46169472/reactjs-js-vs-jsx&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/j1pfX/hyNKhSojVR/9nOmt7c7j5zGoAWOjwLG51/img.png?width=316&amp;amp;height=316&amp;amp;face=0_0_316_316');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;ReactJS - .JS vs .JSX&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;There is something I find very confusing when working in React.js. There are plenty of examples available on internet which use .js files with React but many others use .jsx files. I have read abou...&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;stackoverflow.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;js vs jsx&quot;라고 구글링 시 가장 먼저 나오는 스택오버플로우 게시물입니다.&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 alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;767&quot; data-origin-height=&quot;212&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bgWfQ5/btrwgQ6Ra4L/qO5dOWTT4ssK2pfvy7MKc1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bgWfQ5/btrwgQ6Ra4L/qO5dOWTT4ssK2pfvy7MKc1/img.png&quot; data-alt=&quot;질문&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bgWfQ5/btrwgQ6Ra4L/qO5dOWTT4ssK2pfvy7MKc1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbgWfQ5%2FbtrwgQ6Ra4L%2FqO5dOWTT4ssK2pfvy7MKc1%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;767&quot; height=&quot;212&quot; data-origin-width=&quot;767&quot; data-origin-height=&quot;212&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;질문&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;768&quot; data-origin-height=&quot;148&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/BH0xz/btrwhd2ggAD/ddndqCtGMWTps54SEhC761/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/BH0xz/btrwhd2ggAD/ddndqCtGMWTps54SEhC761/img.png&quot; data-alt=&quot;답변&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/BH0xz/btrwhd2ggAD/ddndqCtGMWTps54SEhC761/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FBH0xz%2Fbtrwhd2ggAD%2FddndqCtGMWTps54SEhC761%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;768&quot; height=&quot;148&quot; data-origin-width=&quot;768&quot; data-origin-height=&quot;148&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;답변&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&amp;lt;질문&amp;gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;.js를 사용하는 많은 예시가 있지만 .jsx 또한 많이 사용되는 것 같습니다. 저는 jsx관련 문서를 읽었고 JavaScript안에 HTML을 사용할 수 있다는 점을 알게 되었습니다. 그렇다면 실질적으로 .js와 .jsx의 차이점은 어떻게 되나요?&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&amp;lt;답변&amp;gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;.js와 .jsx의 확장자로서의 차이점은 없으나 jsx가 표준 자바스크립트 문법이 아닌 만큼, Plain하지 않은 자바스크립트가 js파일에 들어가는 것에 대한 논쟁이 있을 수도 있습니다.&amp;nbsp;&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;b&gt;요약하자면 기능에는 차이가 없으나 팀 내 convention에 관련하여 js를 쓸 것인지, jsx를 쓸 것인지 협의를 해야 하는 부분이 존재하는 것 같습니다.&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;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 alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;737&quot; data-origin-height=&quot;129&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/FxoUT/btrwdlN1r08/bKsqYKG0akkC7luwPLDws0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/FxoUT/btrwdlN1r08/bKsqYKG0akkC7luwPLDws0/img.png&quot; data-alt=&quot;리액트 공식 홈페이지 JSX 소개 페이지&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/FxoUT/btrwdlN1r08/bKsqYKG0akkC7luwPLDws0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FFxoUT%2FbtrwdlN1r08%2FbKsqYKG0akkC7luwPLDws0%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;737&quot; height=&quot;129&quot; data-origin-width=&quot;737&quot; data-origin-height=&quot;129&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;리액트 공식 홈페이지 JSX 소개 페이지&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리액트 공식 홈페이지에서 JSX 관련해서는 자바스크립트 내에서 직관적으로 UI 관련 작업이 가능하고, 개발에 도움을 주는 에러 및 경고 메시지를 표시할 수 있게 해 준다고 하고 있습니다. 뉘앙스 자체는 선호 or 추천하는 듯한 느낌입니다.&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;⚙️ JSX의 특징&lt;/b&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;b&gt;JSX에 표현식 포함&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1647537496310&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const name = 'Josh Perez';
const element = &amp;lt;h1&amp;gt;Hello, {name}&amp;lt;/h1&amp;gt;;

ReactDOM.render(
  element,
  document.getElementById('root')
);&lt;/code&gt;&lt;/pre&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;b&gt;JSX 속성 정의&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1647537740377&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const element = &amp;lt;a href=&quot;https://www.reactjs.org&quot;&amp;gt; link &amp;lt;/a&amp;gt;;&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1647537747149&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const element = &amp;lt;img src={user.avatarUrl}&amp;gt;&amp;lt;/img&amp;gt;;&lt;/code&gt;&lt;/pre&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;b&gt;JSX 태그 자식 포함&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1647537690384&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const element = (
  &amp;lt;div&amp;gt;
    &amp;lt;h1&amp;gt;Hello!&amp;lt;/h1&amp;gt;
    &amp;lt;h2&amp;gt;Good to see you here.&amp;lt;/h2&amp;gt;
  &amp;lt;/div&amp;gt;
);&lt;/code&gt;&lt;/pre&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;b&gt;XSS(cross-site-scripting) 공격 방지&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1647537671993&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const title = response.potentiallyMaliciousInput;
// 이것은 안전합니다.
const element = &amp;lt;h1&amp;gt;{title}&amp;lt;/h1&amp;gt;;&lt;/code&gt;&lt;/pre&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;b&gt;JSX 객체 표현&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1647537604177&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const element = (
  &amp;lt;h1 className=&quot;greeting&quot;&amp;gt;
    Hello, world!
  &amp;lt;/h1&amp;gt;
);&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1647537623953&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const element = React.createElement(
  'h1',
  {className: 'greeting'},
  'Hello, world!'
);&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1647537649782&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 단순화된 구조
const element = {
  type: 'h1',
  props: {
    className: 'greeting',
    children: 'Hello, world!'
  }
};&lt;/code&gt;&lt;/pre&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 data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;  참고&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://ko.reactjs.org/docs/introducing-jsx.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://ko.reactjs.org/docs/introducing-jsx.html&lt;/a&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 data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>⚛️React</category>
      <author>Cocoon_</author>
      <guid isPermaLink="true">https://cocoon1787.tistory.com/844</guid>
      <comments>https://cocoon1787.tistory.com/844#entry844comment</comments>
      <pubDate>Fri, 18 Mar 2022 06:37:35 +0900</pubDate>
    </item>
    <item>
      <title>[CSS] CSS, SASS, SCSS 차이점, 사용방법</title>
      <link>https://cocoon1787.tistory.com/843</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1447&quot; data-origin-height=&quot;811&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bpNaaf/btrwgElkK0R/3xwB1hPVCvlOxV3sQ7jKl0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bpNaaf/btrwgElkK0R/3xwB1hPVCvlOxV3sQ7jKl0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bpNaaf/btrwgElkK0R/3xwB1hPVCvlOxV3sQ7jKl0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbpNaaf%2FbtrwgElkK0R%2F3xwB1hPVCvlOxV3sQ7jKl0%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;1447&quot; height=&quot;811&quot; data-origin-width=&quot;1447&quot; data-origin-height=&quot;811&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;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;⏲ &lt;b&gt;TL;DR&lt;/b&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;b&gt;SASS와 SCSS는 CSS를 편리하게 사용할 수 있도록 하며 추가 기능 또한 있는 확장판 스크립트 언어&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;SASS, SCSS에서 기존의 CSS의 기능 부재 단점을 보완한 다양한 기능 추가&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;SASS는 들여 쓰기+줄 바꿈 형식, SCSS는 중괄호+세미콜론 형식&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;전 세계적으로 SCSS 사용자 수, SCSS를 활용한 라이브러리&amp;amp;프레임워크 수가 SASS 보다 더 많음&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;SASS보다 SCSS가 CSS와의 호환성이 더 좋음&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cFNgTE/btrwhc93pQX/mf6EgM9vMXT9gJRFXD3G80/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cFNgTE/btrwhc93pQX/mf6EgM9vMXT9gJRFXD3G80/img.png&quot; data-origin-width=&quot;469&quot; data-origin-height=&quot;164&quot; data-is-animation=&quot;false&quot; style=&quot;width: 49.7181%; margin-right: 10px;&quot; data-widthpercent=&quot;50.3&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cFNgTE/btrwhc93pQX/mf6EgM9vMXT9gJRFXD3G80/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcFNgTE%2Fbtrwhc93pQX%2Fmf6EgM9vMXT9gJRFXD3G80%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;469&quot; height=&quot;164&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bagTGW/btrwdlf9vuF/pdUHpC64DEcbKko3O1w3Pk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bagTGW/btrwdlf9vuF/pdUHpC64DEcbKko3O1w3Pk/img.png&quot; data-origin-width=&quot;469&quot; data-origin-height=&quot;166&quot; data-is-animation=&quot;false&quot; style=&quot;width: 49.1191%;&quot; data-widthpercent=&quot;49.7&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bagTGW/btrwdlf9vuF/pdUHpC64DEcbKko3O1w3Pk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbagTGW%2Fbtrwdlf9vuF%2FpdUHpC64DEcbKko3O1w3Pk%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;469&quot; height=&quot;166&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;SCSS&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; SASS&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;CSS는 잘 알지만 SASS? SCSS??&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;CSS : Cascading Style Sheets - 종속형 시트&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;SASS : &lt;span style=&quot;background-color: #ffffff; color: #212529;&quot;&gt;Syntactically Awesome Style Sheets - 문법적으로 어썸한 스타일시트&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;SCSS : &lt;span style=&quot;background-color: #ffffff; color: #212529;&quot;&gt;Sassy CSS - 문법적으로 짱 멋진(Sassy) CSS&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;full-name으로 봤을 때 SASS, SCSS 둘 다 문법적으로 어썸한 CSS라는 뜻을 가지고 있습니다. SCSS의 경우 SASS보다 뒤에 나왔고(SASS 3 버전에서 SCSS가 생겨남) 약간의 문법 차이가 있지만 SCSS가 좀 더 넓은 범용성과 CSS의 호환성의 장점을 가집니다. 큰 차이점은 SASS는 중첩으로 들여 쓰기를 사용하고 속성 구분은 줄 바꿈을 이용하지만 SCSS의 경우 중괄호로 중첩을 표현하고 세미콜론으로 속성을 구분합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한 공식 레퍼런스는 SASS보다 CSS와 더 비슷한 SCSS를 선호한다고 합니다. 그리고 다수의 라이브러리, 프레임워크가 SCSS 문법을 활용하며, 사용자 수는 SASS보다 SCSS가 더 많습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&amp;lt;2012년 css-tricks.com에서 12,712명의 사용자로부터 받은 응답&amp;gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1690&quot; data-origin-height=&quot;311&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/UYdhJ/btrwapJoDwn/Hmgw1xh4EZwHYqHEuYZsd0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/UYdhJ/btrwapJoDwn/Hmgw1xh4EZwHYqHEuYZsd0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/UYdhJ/btrwapJoDwn/Hmgw1xh4EZwHYqHEuYZsd0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FUYdhJ%2FbtrwapJoDwn%2FHmgw1xh4EZwHYqHEuYZsd0%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;1690&quot; height=&quot;311&quot; data-origin-width=&quot;1690&quot; data-origin-height=&quot;311&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1689&quot; data-origin-height=&quot;310&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lXTLr/btrwhc3iV03/aL7sshiGVLqrseJciVjEy0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lXTLr/btrwhc3iV03/aL7sshiGVLqrseJciVjEy0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lXTLr/btrwhc3iV03/aL7sshiGVLqrseJciVjEy0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlXTLr%2Fbtrwhc3iV03%2FaL7sshiGVLqrseJciVjEy0%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;1689&quot; height=&quot;310&quot; data-origin-width=&quot;1689&quot; data-origin-height=&quot;310&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1689&quot; data-origin-height=&quot;305&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/8KPA0/btrwiyENqCW/LKyCunsBNz93WkZkE89bc1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/8KPA0/btrwiyENqCW/LKyCunsBNz93WkZkE89bc1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/8KPA0/btrwiyENqCW/LKyCunsBNz93WkZkE89bc1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F8KPA0%2FbtrwiyENqCW%2FLKyCunsBNz93WkZkE89bc1%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;1689&quot; height=&quot;305&quot; data-origin-width=&quot;1689&quot; data-origin-height=&quot;305&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1691&quot; data-origin-height=&quot;300&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dcFeeG/btrwglsVpea/3Ydl9828TkRyrd01ARQkCK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dcFeeG/btrwglsVpea/3Ydl9828TkRyrd01ARQkCK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dcFeeG/btrwglsVpea/3Ydl9828TkRyrd01ARQkCK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdcFeeG%2FbtrwglsVpea%2F3Ydl9828TkRyrd01ARQkCK%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;1691&quot; height=&quot;300&quot; data-origin-width=&quot;1691&quot; data-origin-height=&quot;300&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1687&quot; data-origin-height=&quot;311&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/twnEN/btrwhUBiMnr/WbYpw4rpslWssHyMchaFkK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/twnEN/btrwhUBiMnr/WbYpw4rpslWssHyMchaFkK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/twnEN/btrwhUBiMnr/WbYpw4rpslWssHyMchaFkK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FtwnEN%2FbtrwhUBiMnr%2FWbYpw4rpslWssHyMchaFkK%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;1687&quot; height=&quot;311&quot; data-origin-width=&quot;1687&quot; data-origin-height=&quot;311&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;
&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;css가 그렇게 복잡한 언어는 아니지만 프로젝트의 크기가 커지고 고도화될수록 유지보수에 큰 어려움이 생기게 됩니다. 예를 들어 기존의 CSS는 불필요한 선택자(Selector), 연산 기능 한계, 구문(Statement)의 부재의 문제점이 있고 SASS와 SCSS는 이러한 이슈를 해소시켜줄 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;660&quot; data-origin-height=&quot;475&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/9Avfq/btrwfcppCgg/KG5COcCxOAMaDBlUbTV2sk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/9Avfq/btrwfcppCgg/KG5COcCxOAMaDBlUbTV2sk/img.png&quot; data-alt=&quot;팀 프로젝트로 진행한 CSS 파일 상태 (React 기반 Web)&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/9Avfq/btrwfcppCgg/KG5COcCxOAMaDBlUbTV2sk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F9Avfq%2FbtrwfcppCgg%2FKG5COcCxOAMaDBlUbTV2sk%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;660&quot; height=&quot;475&quot; data-origin-width=&quot;660&quot; data-origin-height=&quot;475&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;팀 프로젝트로 진행한 CSS 파일 상태 (React 기반 Web)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;통상적으로 SASS보다 SCSS를 사용을 많이 하는데 SCSS의 경우 CSS문법과 완벽하게 호환이 되는 장점 또한 가지고 있습니다. 또한 코드의 가속성과 재사용성을 높여주며 심플한 표기법으로 CSS 구조를 평준화할 수 있습니다.&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;/b&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;b&gt;변수(Variable) 할당&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;중첩(Nesting) 구문&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;모듈화(Modularity)&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;믹스인(Mixins)&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;확장&amp;amp;상속(Extend/Inheritance)&lt;/span&gt;&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;연산자(Operators)&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;1. 변수(Variable) 할당&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1647534946314&quot; class=&quot;css&quot; data-ke-language=&quot;css&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/* CSS */
body {
  font: 100% Helvetica, sans-serif;
  color: #333;
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1647534968467&quot; class=&quot;css&quot; data-ke-language=&quot;css&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/* SCSS */
$font-stack: Helvetica, sans-serif;
$primary-color: #333;

body {
  font: 100% $font-stack;
  color: $primary-color;
}&lt;/code&gt;&lt;/pre&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;2. 중첩(Nesting) 구문&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1647535054467&quot; class=&quot;css&quot; data-ke-language=&quot;css&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/* CSS */
nav ul {
  margin: 0;
  padding: 0;
  list-style: none;
}
nav li {
  display: inline-block;
}
nav a {
  display: block;
  padding: 6px 12px;
  text-decoration: none;
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1647535077995&quot; class=&quot;css&quot; data-ke-language=&quot;css&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/* SCSS */
nav {
  ul {
    margin: 0;
    padding: 0;
    list-style: none;
  }

  li { display: inline-block; }

  a {
    display: block;
    padding: 6px 12px;
    text-decoration: none;
  }
}&lt;/code&gt;&lt;/pre&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;3. 모듈화(Modularity)&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1647535057732&quot; class=&quot;css&quot; data-ke-language=&quot;css&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/* CSS */
body {
  font: 100% Helvetica, sans-serif;
  color: #333;
}

.inverse {
  background-color: #333;
  color: white;
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1647535081384&quot; class=&quot;css&quot; data-ke-language=&quot;css&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/* _base.scss */
$font-stack: Helvetica, sans-serif;
$primary-color: #333;

body {
  font: 100% $font-stack;
  color: $primary-color;
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1647535285293&quot; class=&quot;css&quot; data-ke-language=&quot;css&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/* styles.scss */
@use 'base';

.inverse {
  background-color: base.$primary-color;
  color: white;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;@use를 사용하여 파일을 분할하고 모듈화 할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;4. 믹스인(Mixins)&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1647535061980&quot; class=&quot;css&quot; data-ke-language=&quot;css&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/* CSS */
.info {
  background: DarkGray;
  box-shadow: 0 0 1px rgba(169, 169, 169, 0.25);
  color: #fff;
}

.alert {
  background: DarkRed;
  box-shadow: 0 0 1px rgba(139, 0, 0, 0.25);
  color: #fff;
}

.success {
  background: DarkGreen;
  box-shadow: 0 0 1px rgba(0, 100, 0, 0.25);
  color: #fff;
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1647535085027&quot; class=&quot;css&quot; data-ke-language=&quot;css&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/* SCSS */
@mixin theme($theme: DarkGray) {
  background: $theme;
  box-shadow: 0 0 1px rgba($theme, .25);
  color: #fff;
}

.info {
  @include theme;
}
.alert {
  @include theme($theme: DarkRed);
}
.success {
  @include theme($theme: DarkGreen);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;함수처럼 defalut parameter를 지정할 수 있고 parameter를 받아서 속성을 부여할 수 있습니다. (재사용성)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span&gt;5. 확장&amp;amp;상속(Extend/Inheritance)&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1647535064768&quot; class=&quot;css&quot; data-ke-language=&quot;css&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/* CSS */
/* This CSS will print because %message-shared is extended. */
.message, .success, .error, .warning {
  border: 1px solid #ccc;
  padding: 10px;
  color: #333;
}

.success {
  border-color: green;
}

.error {
  border-color: red;
}

.warning {
  border-color: yellow;
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1647535088220&quot; class=&quot;css&quot; data-ke-language=&quot;css&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/* SCSS */
/* This CSS will print because %message-shared is extended. */
%message-shared {
  border: 1px solid #ccc;
  padding: 10px;
  color: #333;
}

/* This CSS won't print because %equal-heights is never extended. */
%equal-heights {
  display: flex;
  flex-wrap: wrap;
}

.message {
  @extend %message-shared;
}

.success {
  @extend %message-shared;
  border-color: green;
}

.error {
  @extend %message-shared;
  border-color: red;
}

.warning {
  @extend %message-shared;
  border-color: yellow;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;@extend 사용 시 css 속성 집합을 상속받을 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;6. 연산자(Operators)&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1647535069462&quot; class=&quot;css&quot; data-ke-language=&quot;css&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/* CSS */
.container {
  display: flex;
}

article[role=&quot;main&quot;] {
  width: 62.5%;
}

aside[role=&quot;complementary&quot;] {
  width: 31.25%;
  margin-left: auto;
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1647535091534&quot; class=&quot;css&quot; data-ke-language=&quot;css&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/* SCSS */
@use &quot;sass:math&quot;;

.container {
  display: flex;
}

article[role=&quot;main&quot;] {
  width: math.div(600px, 960px) * 100%;
}

aside[role=&quot;complementary&quot;] {
  width: math.div(300px, 960px) * 100%;
  margin-left: auto;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;math.div(나누기) 외에도 sin, cos, tan, random, max, min 등등 여러 가지 수학적 기능을 사용할 수 있습니다.&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;SASS, SCSS가 적용되는 원리&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SASS, SCSS를 CSS pre-processor(전처리기)라고도 하는데 스크립팅 언어이기 때문에 SASS, SCSS로 작성된 파일들은 곧바로 웹에 적용될 수는 없습니다. 웹은 기본적으로 CSS파일로 동작하므로 별도의 컴파일 과정을 거친 다음 CSS파일로 변환하여 사용하게 됩니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;752&quot; data-origin-height=&quot;267&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bFDn1y/btrwdlAod30/zvbuwt5slllfuIt48911XK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bFDn1y/btrwdlAod30/zvbuwt5slllfuIt48911XK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bFDn1y/btrwdlAod30/zvbuwt5slllfuIt48911XK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbFDn1y%2FbtrwdlAod30%2Fzvbuwt5slllfuIt48911XK%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;752&quot; height=&quot;267&quot; data-origin-width=&quot;752&quot; data-origin-height=&quot;267&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;
&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;전처리기를 위한 도구 필요&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;컴파일 시간 소요&lt;/b&gt;&lt;/li&gt;
&lt;/ul&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;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저의 경우 기존의 프로젝트를 진행하면서 프로젝트 크기가 커질수록 CSS파일 수도 많아지고 Div Class명 짓는 것도 굉장히 난감했던 적이 많았습니다. 평소에 선택자를 사용해가면서 CSS를 작성했을 때 코드에 중복되는 부분이 많이 보였고 뭔가 리팩터링 하고 싶은 열망이 있었으나 당시에는 SCSS의 존재를 몰랐었습니다. 최근에 들어서야 SCSS를 알아보게 되면서 새로운 프로젝트에 적용해봤고, 코드 재사용성, 가독성, 유지보수성 등등 많은 차원에서의 이점을 몸소 체험할 수 있었습니다. 물론 간단한 프로젝트이고 코드량이 작다면 그냥 CSS를 쓰는 것이 좋지만 프로젝트의 크기가 커질수록 SCSS 사용의 장점이 두각 되므로 한번 사용해보시는 것을 추천드립니다.&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;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://sass-lang.com/guide&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://sass-lang.com/guide&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category> WEB</category>
      <author>Cocoon_</author>
      <guid isPermaLink="true">https://cocoon1787.tistory.com/843</guid>
      <comments>https://cocoon1787.tistory.com/843#entry843comment</comments>
      <pubDate>Fri, 18 Mar 2022 01:54:15 +0900</pubDate>
    </item>
    <item>
      <title>[리뷰] 쿠팡에서 에어팟 프로(AirPods Pro) 구매후기 &amp;amp; 개봉기</title>
      <link>https://cocoon1787.tistory.com/842</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;KakaoTalk_20220314_034833935_13.jpg&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;810&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cu1A8l/btrvUCntfFX/ZUeBZxsv7nqzCTL69PNpK1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cu1A8l/btrvUCntfFX/ZUeBZxsv7nqzCTL69PNpK1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cu1A8l/btrvUCntfFX/ZUeBZxsv7nqzCTL69PNpK1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcu1A8l%2FbtrvUCntfFX%2FZUeBZxsv7nqzCTL69PNpK1%2Fimg.jpg&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;1440&quot; height=&quot;810&quot; data-filename=&quot;KakaoTalk_20220314_034833935_13.jpg&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;810&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;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt; &lt;/h2&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;기존에 QCY-T5를 쓰다가 언젠가는 에어팟 프로를 사려고 했는데&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;마침 쿠팡에서 할인도 하고 여유가 돼서 큰맘 먹고 지르게 되었습니다.&lt;/b&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;1045&quot; data-origin-height=&quot;482&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/boQKQB/btrvVMb3LU3/0fMSEQToIJ7qVcduL2WuEK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/boQKQB/btrvVMb3LU3/0fMSEQToIJ7qVcduL2WuEK/img.png&quot; data-alt=&quot;2022.03.14&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/boQKQB/btrvVMb3LU3/0fMSEQToIJ7qVcduL2WuEK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FboQKQB%2FbtrvVMb3LU3%2F0fMSEQToIJ7qVcduL2WuEK%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;1045&quot; height=&quot;482&quot; data-origin-width=&quot;1045&quot; data-origin-height=&quot;482&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;2022.03.14&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.coupang.com/vp/products/6135671327?itemId=11731447886&amp;amp;vendorItemId=79005405788&amp;amp;pickType=COU_PICK&amp;amp;q=%EC%97%90%EC%96%B4%ED%8C%9F+%ED%94%84%EB%A1%9C&amp;amp;itemsCount=36&amp;amp;searchId=aebc8188e6754927b11b1c10069f9899&amp;amp;rank=1&amp;amp;isAddedCart=&quot;&gt;https://www.coupang.com/vp/products/6135671327?itemId=11731447886&amp;amp;vendorItemId=79005405788&amp;amp;pickType=COU_PICK&amp;amp;q=%EC%97%90%EC%96%B4%ED%8C%9F+%ED%94%84%EB%A1%9C&amp;amp;itemsCount=36&amp;amp;searchId=aebc8188e6754927b11b1c10069f9899&amp;amp;rank=1&amp;amp;isAddedCart=&lt;/a&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1647198075224&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Apple 2021 에어팟 프로 블루투스 이어폰 맥세이프 호환&quot; data-og-description=&quot;COUPANG&quot; data-og-host=&quot;www.coupang.com&quot; data-og-source-url=&quot;https://www.coupang.com/vp/products/6135671327?itemId=11731447886&amp;amp;vendorItemId=79005405788&amp;amp;pickType=COU_PICK&amp;amp;q=%EC%97%90%EC%96%B4%ED%8C%9F+%ED%94%84%EB%A1%9C&amp;amp;itemsCount=36&amp;amp;searchId=aebc8188e6754927b11b1c10069f9899&amp;amp;rank=1&amp;amp;isAddedCart=&quot; data-og-url=&quot;https://www.coupang.com/vp/products/6135671327&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/lUzvn/hyNGByejF9/rYVLyPEgshzG6bIsJX2fR0/img.jpg?width=230&amp;amp;height=230&amp;amp;face=0_0_230_230&quot;&gt;&lt;a href=&quot;https://www.coupang.com/vp/products/6135671327?itemId=11731447886&amp;amp;vendorItemId=79005405788&amp;amp;pickType=COU_PICK&amp;amp;q=%EC%97%90%EC%96%B4%ED%8C%9F+%ED%94%84%EB%A1%9C&amp;amp;itemsCount=36&amp;amp;searchId=aebc8188e6754927b11b1c10069f9899&amp;amp;rank=1&amp;amp;isAddedCart=&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.coupang.com/vp/products/6135671327?itemId=11731447886&amp;amp;vendorItemId=79005405788&amp;amp;pickType=COU_PICK&amp;amp;q=%EC%97%90%EC%96%B4%ED%8C%9F+%ED%94%84%EB%A1%9C&amp;amp;itemsCount=36&amp;amp;searchId=aebc8188e6754927b11b1c10069f9899&amp;amp;rank=1&amp;amp;isAddedCart=&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/lUzvn/hyNGByejF9/rYVLyPEgshzG6bIsJX2fR0/img.jpg?width=230&amp;amp;height=230&amp;amp;face=0_0_230_230');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Apple 2021 에어팟 프로 블루투스 이어폰 맥세이프 호환&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;COUPANG&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.coupang.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&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;에어팟 프로 언박싱 &amp;amp; 구성품&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;KakaoTalk_20220314_034833935_12.jpg&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;810&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kQG9I/btrvQfUk2TY/sTOq7NyLAn92IkKblgd6pk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kQG9I/btrvQfUk2TY/sTOq7NyLAn92IkKblgd6pk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kQG9I/btrvQfUk2TY/sTOq7NyLAn92IkKblgd6pk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkQG9I%2FbtrvQfUk2TY%2FsTOq7NyLAn92IkKblgd6pk%2Fimg.jpg&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;1440&quot; height=&quot;810&quot; data-filename=&quot;KakaoTalk_20220314_034833935_12.jpg&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;810&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;
&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;KakaoTalk_20220314_034833935_11.jpg&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;810&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dHORdL/btrvVKSP5JV/CIhbAONEJkLFkAaTldBJi1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dHORdL/btrvVKSP5JV/CIhbAONEJkLFkAaTldBJi1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dHORdL/btrvVKSP5JV/CIhbAONEJkLFkAaTldBJi1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdHORdL%2FbtrvVKSP5JV%2FCIhbAONEJkLFkAaTldBJi1%2Fimg.jpg&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;1440&quot; height=&quot;810&quot; data-filename=&quot;KakaoTalk_20220314_034833935_11.jpg&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;810&quot;/&gt;&lt;/span&gt;&lt;/figure&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;KakaoTalk_20220314_034833935_10.jpg&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;810&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bOvmPy/btrvUB29Mpy/z4vp2YkYpLklfKxvHRhEuk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bOvmPy/btrvUB29Mpy/z4vp2YkYpLklfKxvHRhEuk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bOvmPy/btrvUB29Mpy/z4vp2YkYpLklfKxvHRhEuk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbOvmPy%2FbtrvUB29Mpy%2Fz4vp2YkYpLklfKxvHRhEuk%2Fimg.jpg&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;1440&quot; height=&quot;810&quot; data-filename=&quot;KakaoTalk_20220314_034833935_10.jpg&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;810&quot;/&gt;&lt;/span&gt;&lt;/figure&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;KakaoTalk_20220314_034833935_09.jpg&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;810&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bNGlNU/btrvSA3147U/TOuFeKVg2xxDWw9hP6akZ1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bNGlNU/btrvSA3147U/TOuFeKVg2xxDWw9hP6akZ1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bNGlNU/btrvSA3147U/TOuFeKVg2xxDWw9hP6akZ1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbNGlNU%2FbtrvSA3147U%2FTOuFeKVg2xxDWw9hP6akZ1%2Fimg.jpg&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;1440&quot; height=&quot;810&quot; data-filename=&quot;KakaoTalk_20220314_034833935_09.jpg&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;810&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이어팁은 S, M, L 사이즈가 있으며 기본적으로 에어팟 프로에는 M사이즈가 장착되어있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 저기 라이트닝 to C타입 케이블은 저처럼 라이트닝 케이블을 사용하는 제품이 없다면 굳이 풀지 않는 것을 추천드립니다. 저걸 다시 박스에 넣으려면 딱 맞게 감아서 정리해야 하는데 좀 힘든 작업입니다...^^;;&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;KakaoTalk_20220314_034833935.jpg&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;810&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/y9lnw/btrvPgzbMo0/x55Kl9r3YJDF63T25H0oN0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/y9lnw/btrvPgzbMo0/x55Kl9r3YJDF63T25H0oN0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/y9lnw/btrvPgzbMo0/x55Kl9r3YJDF63T25H0oN0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fy9lnw%2FbtrvPgzbMo0%2Fx55Kl9r3YJDF63T25H0oN0%2Fimg.jpg&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;1440&quot; height=&quot;810&quot; data-filename=&quot;KakaoTalk_20220314_034833935.jpg&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;810&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;에어팟 프로 충전기 구멍은 보시다시피 라이트닝 8핀입니다.&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;KakaoTalk_20220314_034833935_06.jpg&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;810&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Jkps3/btrvKqBRBnx/9Cy61a6J4txYDG6AZV42jK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Jkps3/btrvKqBRBnx/9Cy61a6J4txYDG6AZV42jK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Jkps3/btrvKqBRBnx/9Cy61a6J4txYDG6AZV42jK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FJkps3%2FbtrvKqBRBnx%2F9Cy61a6J4txYDG6AZV42jK%2Fimg.jpg&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;1440&quot; height=&quot;810&quot; data-filename=&quot;KakaoTalk_20220314_034833935_06.jpg&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;810&quot;/&gt;&lt;/span&gt;&lt;/figure&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;KakaoTalk_20220314_034833935_05.jpg&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;810&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bCOoGe/btrvOglRmto/9EEzel4lfO1OaqstaL82k1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bCOoGe/btrvOglRmto/9EEzel4lfO1OaqstaL82k1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bCOoGe/btrvOglRmto/9EEzel4lfO1OaqstaL82k1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbCOoGe%2FbtrvOglRmto%2F9EEzel4lfO1OaqstaL82k1%2Fimg.jpg&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;1440&quot; height=&quot;810&quot; data-filename=&quot;KakaoTalk_20220314_034833935_05.jpg&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;810&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;KakaoTalk_20220314_034833935_01.jpg&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;810&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ro8Nh/btrvPfG5EDh/D0JegcF9wUSHKKb7djrsgk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ro8Nh/btrvPfG5EDh/D0JegcF9wUSHKKb7djrsgk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ro8Nh/btrvPfG5EDh/D0JegcF9wUSHKKb7djrsgk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fro8Nh%2FbtrvPfG5EDh%2FD0JegcF9wUSHKKb7djrsgk%2Fimg.jpg&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;1440&quot; height=&quot;810&quot; data-filename=&quot;KakaoTalk_20220314_034833935_01.jpg&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;810&quot;/&gt;&lt;/span&gt;&lt;/figure&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;810&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/McNOn/btrvNHRw9Ir/jxEIXlHK3X4mt4gGXQnL41/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/McNOn/btrvNHRw9Ir/jxEIXlHK3X4mt4gGXQnL41/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/McNOn/btrvNHRw9Ir/jxEIXlHK3X4mt4gGXQnL41/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FMcNOn%2FbtrvNHRw9Ir%2FjxEIXlHK3X4mt4gGXQnL41%2Fimg.jpg&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;1440&quot; height=&quot;810&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;810&quot;/&gt;&lt;/span&gt;&lt;/figure&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;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;⚙️ &lt;b&gt;조작법 &amp;amp; 기능&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;348&quot; data-origin-height=&quot;308&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/efWpSI/btrvRAqmX6B/VAPQ767xkdj3rFU3EvdjvK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/efWpSI/btrvRAqmX6B/VAPQ767xkdj3rFU3EvdjvK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/efWpSI/btrvRAqmX6B/VAPQ767xkdj3rFU3EvdjvK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FefWpSI%2FbtrvRAqmX6B%2FVAPQ767xkdj3rFU3EvdjvK%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;348&quot; height=&quot;308&quot; data-origin-width=&quot;348&quot; data-origin-height=&quot;308&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;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;센서 1번 누름 : 재생/정지(전화받기)&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;센서 2번 누름 : 다음 곡으로(전화 거절)&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;센서 3번 누름 : 이전 곡으로&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;센서 길게 누름 : 노이즈 캔슬링 &lt;span style=&quot;color: #ee2323;&quot;&gt;on/off&lt;/span&gt;&lt;/b&gt;&lt;/li&gt;
&lt;/ul&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;/b&gt;&lt;/h2&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;1. 노이즈 캔슬링&lt;/b&gt;&lt;/h4&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;2. 음질&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;갤럭시 버즈나 에어팟 1,2 세대를 사용해보지는 않았지만 기존에 QCY 제품을 이용하던 저로서는 음질이 너무 좋다고 느끼고 있습니다. 근데 다른 리뷰들을 살펴보니 329,000원이라는 가격에도 불구하고 음질이 밍밍하거나 뭔가 좀 2프로 부족한 음질이라는 평이 꽤나 있는 것으로 보입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;3. 디자인&lt;/b&gt;&lt;/h4&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;4. 배터리&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;케이스에 넣어 여러 번 충전 시 24시간 이상의 재생시간 또는 18시간 이상의 통화 가능&lt;/li&gt;
&lt;li&gt;한 번의 충전으로 최대 4.5시간의 재생시간 또는 최대 3.5시간의 통화 가능&lt;/li&gt;
&lt;li&gt;5분 동안 충전하면 약 1시간의 재생시간 또는 약 1시간의 통화 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;에어팟의 배터리 충전량이 20, 10, 5% 일 때 아이폰 또는 아이패드에 알림을 보내고 배터리 충전량이 10% 혹은 꺼질 때는 한쪽 또는 양쪽의 에어팟에서 신호음을 울립니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;5. 착용감&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;평소에 집에 있을 때 컴퓨터를 하면서 이어폰을 오래 착용하는 편입니다. 잠깐 낄 때는 별 문제가 없지만 시간이 지날수록 귀가 살짝 뜨겁고 아픈 느낌이 듭니다. 참지 못할 정도는 아니고 한두 시간 착용하고 10분 정도 쉬어주는 식으로 하면 괜찮을 것 같습니다.&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;KakaoTalk_20220314_034833935_08.jpg&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;810&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dxPQtR/btrvNIpsZjt/8I5sxNTEqh5qDvMKtVcip1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dxPQtR/btrvNIpsZjt/8I5sxNTEqh5qDvMKtVcip1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dxPQtR/btrvNIpsZjt/8I5sxNTEqh5qDvMKtVcip1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdxPQtR%2FbtrvNIpsZjt%2F8I5sxNTEqh5qDvMKtVcip1%2Fimg.jpg&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;1440&quot; height=&quot;810&quot; data-filename=&quot;KakaoTalk_20220314_034833935_08.jpg&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;810&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;
&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;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;귀에 맞는 이어팁을 찾으려고 교체하다가 이어팁이 잘 빠지지 않았고 &quot;이거 고무인데 이렇게 세게 당겨도 되나...?&quot;라는 생각이 들어 유튜브로 찾아봤습니다.&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;b&gt;1. 이어팁을 뒤집는다.&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;KakaoTalk_20220314_034833935_04.jpg&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;810&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bv1Blu/btrvVzxgHKs/suhYqJLaXcxmPziIjOf9cK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bv1Blu/btrvVzxgHKs/suhYqJLaXcxmPziIjOf9cK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bv1Blu/btrvVzxgHKs/suhYqJLaXcxmPziIjOf9cK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbv1Blu%2FbtrvVzxgHKs%2FsuhYqJLaXcxmPziIjOf9cK%2Fimg.jpg&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;1440&quot; height=&quot;810&quot; data-filename=&quot;KakaoTalk_20220314_034833935_04.jpg&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;810&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. 이어팁의 플라스틱 부분을 잡는다.&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;KakaoTalk_20220314_034833935_03.jpg&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;810&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/7Js2A/btrvNTb1iHw/KX3GvfVVJZLtdqwNdDjDi1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/7Js2A/btrvNTb1iHw/KX3GvfVVJZLtdqwNdDjDi1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/7Js2A/btrvNTb1iHw/KX3GvfVVJZLtdqwNdDjDi1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F7Js2A%2FbtrvNTb1iHw%2FKX3GvfVVJZLtdqwNdDjDi1%2Fimg.jpg&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;1440&quot; height=&quot;810&quot; data-filename=&quot;KakaoTalk_20220314_034833935_03.jpg&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;810&quot;/&gt;&lt;/span&gt;&lt;/figure&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;&lt;b&gt;3. 위아래로 당기면서 이어팁을 분리한다.&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;KakaoTalk_20220314_034833935_02.jpg&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;810&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cs1gVN/btrvS7uvhPJ/tCAj9alz4PHBZrMoMVDbo1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cs1gVN/btrvS7uvhPJ/tCAj9alz4PHBZrMoMVDbo1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cs1gVN/btrvS7uvhPJ/tCAj9alz4PHBZrMoMVDbo1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcs1gVN%2FbtrvS7uvhPJ%2FtCAj9alz4PHBZrMoMVDbo1%2Fimg.jpg&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;1440&quot; height=&quot;810&quot; data-filename=&quot;KakaoTalk_20220314_034833935_02.jpg&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;810&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;
&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 data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category> IT</category>
      <category>airpods</category>
      <category>Airpods Pro</category>
      <category>내돈내산</category>
      <category>노이즈캔슬링</category>
      <category>무선이어폰</category>
      <category>애플에어팟프로</category>
      <category>에어팟</category>
      <category>에어팟프로</category>
      <category>에어팟프로언박싱</category>
      <category>쿠팡</category>
      <author>Cocoon_</author>
      <guid isPermaLink="true">https://cocoon1787.tistory.com/842</guid>
      <comments>https://cocoon1787.tistory.com/842#entry842comment</comments>
      <pubDate>Mon, 14 Mar 2022 05:08:26 +0900</pubDate>
    </item>
    <item>
      <title>[React] 리액트 자식 컴포넌트에서 부모 컴포넌트로 데이터 전달하기</title>
      <link>https://cocoon1787.tistory.com/841</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;727&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bbDNR7/btrvNHB0fFV/FspE3jQElegffxm0e5kJt0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bbDNR7/btrvNHB0fFV/FspE3jQElegffxm0e5kJt0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bbDNR7/btrvNHB0fFV/FspE3jQElegffxm0e5kJt0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbbDNR7%2FbtrvNHB0fFV%2FFspE3jQElegffxm0e5kJt0%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;1280&quot; height=&quot;727&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;727&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt; &lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리액트에서 부모 컴포넌트의 데이터를 자식 컴포넌트에 전달할 때는 props를 사용하여 간단하게 전달할 수 있습니다.&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;1. 부모 컴포넌트 -&amp;gt; 자식 컴포넌트&lt;/b&gt;&lt;/h2&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;App.jsx&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1647037318474&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import React, { useState } from &quot;react&quot;;
import Child from &quot;./components/Child&quot;;

function App() {
  const [data, setData] = useState(1);

  return &amp;lt;Child data={data}&amp;gt;&amp;lt;/Child&amp;gt;;
}

export default App;&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;Child.jsx&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1647037310073&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import React from &quot;react&quot;;

function Child({ data }) {
  console.log(data);
  return &amp;lt;div&amp;gt;Child&amp;lt;/div&amp;gt;;
}

export default Child;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;498&quot; data-origin-height=&quot;145&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/8jQ0g/btrvLKfaxqk/SmSbAD01MultkKAvB2N2e0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/8jQ0g/btrvLKfaxqk/SmSbAD01MultkKAvB2N2e0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/8jQ0g/btrvLKfaxqk/SmSbAD01MultkKAvB2N2e0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F8jQ0g%2FbtrvLKfaxqk%2FSmSbAD01MultkKAvB2N2e0%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;498&quot; height=&quot;145&quot; data-origin-width=&quot;498&quot; data-origin-height=&quot;145&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러나 자식 컴포넌트의 데이터를 부모 컴포넌트로 끌어올려야 하는 상황이 종종 생기고 이러한 문제는 함수를 props로 전달하여 해결할 수 있습니다.&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. 자식 컴포넌트 -&amp;gt; 부모 컴포넌트&lt;/b&gt;&lt;/h2&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;App.jsx&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1647037726204&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import React, { useState } from &quot;react&quot;;
import Child from &quot;./components/Child&quot;;

function App() {
  const parentFunction = (x) =&amp;gt; {
    console.log(x);
  };

  return &amp;lt;Child parentFunction={parentFunction}&amp;gt;&amp;lt;/Child&amp;gt;;
}

export default App;&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;Child.jsx&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1647037734597&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import React, { useState } from &quot;react&quot;;

function Child({ parentFunction }) {
  const [data, setData] = useState(2);

  parentFunction(data);

  return &amp;lt;div&amp;gt;Child&amp;lt;/div&amp;gt;;
}

export default Child;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;498&quot; data-origin-height=&quot;150&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bkHZvD/btrvIytG9VJ/3KVzUyQ6UjMkBJcXqh772k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bkHZvD/btrvIytG9VJ/3KVzUyQ6UjMkBJcXqh772k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bkHZvD/btrvIytG9VJ/3KVzUyQ6UjMkBJcXqh772k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbkHZvD%2FbtrvIytG9VJ%2F3KVzUyQ6UjMkBJcXqh772k%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;498&quot; height=&quot;150&quot; data-origin-width=&quot;498&quot; data-origin-height=&quot;150&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 부모 컴포넌트에서 함수를 정의하고 이 함수를 자식 컴포넌트에 props로 내려줍니다.&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;</description>
      <category>⚛️React</category>
      <author>Cocoon_</author>
      <guid isPermaLink="true">https://cocoon1787.tistory.com/841</guid>
      <comments>https://cocoon1787.tistory.com/841#entry841comment</comments>
      <pubDate>Sat, 12 Mar 2022 12:31:58 +0900</pubDate>
    </item>
    <item>
      <title>[면접 후기] 프론트엔드 신입 개발자의 면접 후기 (합격)</title>
      <link>https://cocoon1787.tistory.com/840</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1447&quot; data-origin-height=&quot;810&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/IEJpO/btrvMc3aSOM/GI0qcTLzivlfeEtxmKflH1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/IEJpO/btrvMc3aSOM/GI0qcTLzivlfeEtxmKflH1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/IEJpO/btrvMc3aSOM/GI0qcTLzivlfeEtxmKflH1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FIEJpO%2FbtrvMc3aSOM%2FGI0qcTLzivlfeEtxmKflH1%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;1447&quot; height=&quot;810&quot; data-origin-width=&quot;1447&quot; data-origin-height=&quot;810&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;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt; &lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;작년 10월부터 5개월간 4인 팀 프로젝트 진행하면서 리액트에 대해 혼자 공부하고 많이 배웠는데 이제 슬슬 여러 곳 지원을 해보려고 &lt;a href=&quot;https://www.jumpit.co.kr/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;점핏&lt;/a&gt;에서 저의 기술 스택에 맞는 회사들 5곳을 지원하였습니다. 그중에서 한 곳에서 연락이 와서 어제(2022.03.10) 학동역 쪽에 면접을 보러 갔고 오늘(2022.03.16) 합격 문자 및 입사제의를 받아 면접에서 받은 질문들에 대해 포스팅하고자 합니다. 면접은 2대 1로 진행되었습니다.&lt;/b&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;1. Polypoli - 관심 있는 국회의원의 피드를 받아볼 수 있는 서비스&amp;nbsp;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt; &lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a href=&quot;http://polypoli.kr/&quot;&gt;http://polypoli.kr/&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1646979682629&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Polypoli&quot; data-og-description=&quot;&quot; data-og-host=&quot;polypoli.kr&quot; data-og-source-url=&quot;http://polypoli.kr/&quot; data-og-url=&quot;http://polypoli.kr/&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;http://polypoli.kr/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;http://polypoli.kr/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Polypoli&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;polypoli.kr&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1286&quot; data-origin-height=&quot;380&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/d69AOO/btrvH0CH9fe/hNgcBrRp3fLLyntfAlVqWk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/d69AOO/btrvH0CH9fe/hNgcBrRp3fLLyntfAlVqWk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/d69AOO/btrvH0CH9fe/hNgcBrRp3fLLyntfAlVqWk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fd69AOO%2FbtrvH0CH9fe%2FhNgcBrRp3fLLyntfAlVqWk%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;1286&quot; height=&quot;380&quot; data-origin-width=&quot;1286&quot; data-origin-height=&quot;380&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1287&quot; data-origin-height=&quot;376&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lYFKt/btrvJTQpSBc/8qNA58LXy8fDKwIMWBU4Z0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lYFKt/btrvJTQpSBc/8qNA58LXy8fDKwIMWBU4Z0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lYFKt/btrvJTQpSBc/8qNA58LXy8fDKwIMWBU4Z0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlYFKt%2FbtrvJTQpSBc%2F8qNA58LXy8fDKwIMWBU4Z0%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;1287&quot; height=&quot;376&quot; data-origin-width=&quot;1287&quot; data-origin-height=&quot;376&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;873&quot; data-origin-height=&quot;189&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/M1YH6/btrvJyZQoG8/QE2bOEmaskWEwUBXk2UG60/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/M1YH6/btrvJyZQoG8/QE2bOEmaskWEwUBXk2UG60/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/M1YH6/btrvJyZQoG8/QE2bOEmaskWEwUBXk2UG60/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FM1YH6%2FbtrvJyZQoG8%2FQE2bOEmaskWEwUBXk2UG60%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;873&quot; height=&quot;189&quot; data-origin-width=&quot;873&quot; data-origin-height=&quot;189&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;872&quot; data-origin-height=&quot;206&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bwd7T7/btrvE40nvlh/fU0T0QHMzA2Rjn5ig927ck/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bwd7T7/btrvE40nvlh/fU0T0QHMzA2Rjn5ig927ck/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bwd7T7/btrvE40nvlh/fU0T0QHMzA2Rjn5ig927ck/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbwd7T7%2FbtrvE40nvlh%2FfU0T0QHMzA2Rjn5ig927ck%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;872&quot; height=&quot;206&quot; data-origin-width=&quot;872&quot; data-origin-height=&quot;206&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프론트는 리액트로, 백엔드는 스프링 부트로 작업을 하였습니다. 리액트의 경우 클래스형 컴포넌트에 redux를 사용하였고 react-router-dom v5.3.0을 사용하였습니다. 포지션은 풀스택입니다. 아직 개발 중에 있으며 4월에 론칭을 할 예정입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;[Service]&lt;/b&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;b&gt;관심 있는 국회의원의 정보(국회 회의 출결, 법안 발의 내용 등등)를 인스타그램 피드 형식으로 제공&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;피드 별 좋아요 &amp;amp; 싫어요 버튼&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;좋아요 &amp;amp; 싫어요 수 기준 유저에게 가장 관심도가 높은 국회의원 월간 랭킹&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;이번 주 핫한 법안&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;현재 팔로잉 중인 국회의원 목록&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;국회의원 프로필 및 검색 기능&amp;nbsp;&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;2. Chatting-App&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1077&quot; data-origin-height=&quot;652&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bgrIf4/btrvJyr2n0d/U1bAhav9vJbRtZMKUNTYa1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bgrIf4/btrvJyr2n0d/U1bAhav9vJbRtZMKUNTYa1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bgrIf4/btrvJyr2n0d/U1bAhav9vJbRtZMKUNTYa1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbgrIf4%2FbtrvJyr2n0d%2FU1bAhav9vJbRtZMKUNTYa1%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;1077&quot; height=&quot;652&quot; data-origin-width=&quot;1077&quot; data-origin-height=&quot;652&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;socket.io와 express를 사용한 간단한 채팅 서비스&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;채팅 서버로 접속 시 Pug로 만든 페이지를 클라이언트로 전송하도록 하였고 사용자는 채팅 및 닉네임 변경이 가능합니다. 유저가 채팅방에 참여, 종료, 닉네임 변경 시 채팅 로그에 알림이 뜨도록 하였습니다.&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;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;  &lt;b&gt;안녕하세요~ 저는 ~ 직책을 맡고 있는 ~입니다. 반갑습니다.&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;span&gt;&lt;b&gt;&lt;span&gt;&amp;nbsp;혹시 뭐하다 오셨나요?&lt;/span&gt;&lt;/b&gt;&lt;/span&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;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt; &amp;nbsp;자기소개&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt; &lt;span&gt;&amp;nbsp; 자기소개 부탁드립니다.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저는 기계공학과를 졸업하였고 비전공자로 개발 공부를 하고 있습니다. 개발에 관심이 있음을 보이기 위해 2년 전부터 현재까지 개발 블로그를 운영 중이고, 주로 알고리즘 문제풀이, cs지식, 에러 해결법, 언어 문법(메서드 사용법 등등) 관련하여 포스팅하고 있습니다. 작년 10월부터 현재까지 팀 프로젝트를 진행하고 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt; &lt;span&gt;&amp;nbsp; 본인의 장단점을 설명해주세요.&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt; &amp;nbsp;Project 관련 질문&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;  폴리폴리 서비스에 대해 어떠한 서비스인지 설명해주세요.&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;그러한 서비스를 제공하고 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt; &lt;span&gt; 데이터들은 어디서 받아오시나요?&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;국회의원 300명에 대한 정보는 공공데이터 포털에서 제공하는 API에서 받아오고 있으며, 국회의원이 발의한 법안 내용의 경우에는 &lt;a href=&quot;https://opinion.lawmaking.go.kr/gcom/gcomMain&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;국민참여입법센터&lt;/a&gt;에서 node로 크롤링하여 받아오고 있습니다. 공공데이터 포털처럼 API로 제공해주었으면 정말 좋겠는데 아무리 찾아봐도 관련 API가 존재하지 않는 것 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;  &lt;span&gt;&lt;span&gt;아까 전에 오시기 전에 포트폴리오에 있는 polypoli URL로 접속해서 한번 봤는데 문자인증 부분이 적용 안된 것 같습니다.&lt;/span&gt;&lt;/span&gt;&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;b&gt; &lt;span&gt;&lt;span&gt;&lt;span&gt; 로그인을 하지 않고는 피드 탭, 랭킹 탭 등등을 볼 수 있나요?&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리덕스로 userKey라는 state를 default로 -1로 주고 로그인 시 store의 uerKey 값을 DB의 PK값으로 업데이트되도록 하였습니다. 그렇기 때문에 꼭 로그인을 하여야 메인 페이지를 볼 수 있도록 하였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt; &lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt; 그렇다면 모든 컴포넌트에서 userKey를 검사하여 라우팅 하나요?&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;최상단에 Router.js라는 파일을 만들어두고 여기에서 store의 userKey를 받아와서 라우팅 처리를 하였습니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt; &lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt; 만약에 사용자가 접속 중에 있다가 네트워크 불안정으로 접속이 끊어졌다고 가정할 때 다시 연결은 어떻게 할까요?&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;혹시 jwt 같은 웹 토큰 말씀하시는 건가요? 그 부분은 아직 잘 모르겠습니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;  리액트 함수형 컴포넌트가 아닌 클래스형 컴포넌트를 사용하셨는데 이유는?&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;함수형 컴포넌트에 Hook을 사용하고 싶었으나 팀원이 클래스형 컴포넌트로만 작성이 가능하고 백엔드 개발자 직장인이기도 해서 새롭게 배울 시간이 없어서 클래스형 컴포넌트로 작성하기로 협의를 했습니다. 저는 개인적으로 함수형 컴포넌트를 선호해서 현재 개인 토이 프로젝트로 진행 중인 ToDo List App에서는 함수형 컴포넌트를 사용하고 있습니다. 그러나 프론트엔드 업무 시 이미 작성된 코드(혹은 레거시 코드)들 중에서 클래스형으로 작성된 것도 많을 테니 클래스형 컴포넌트도 어차피 알아야하는 내용이라고 생각합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt; &lt;span&gt;&lt;span&gt; 작년 10월부터 지금까지 프로젝트 진행 중이신데 그럼 리액트 5개월 정도 하신 건가요?&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정확히 말씀드리자면 작년 10월부터 12월까지 디자이너가 피그마로 UI 디자인해주었고 그 기간 동안에는 필요한 데이터들을 크롤링하는 작업과 리액트 기초를 공부하였습니다. 리액트를 한 순수 기간으로 따지면 2개월 정도라고 생각합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;  &lt;span&gt;디자인할 때 부트스트랩을 사용하였나요?&lt;/span&gt;&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;b&gt; &lt;span&gt;&lt;span&gt; 앱 너비가 고정되어있는 것 같습니다. 폰마다 크기가 다를 텐데 옆에 마진으로 비어있는 부분은 왜 그런가요?&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음에 회의할 때 너비를 아이폰의 너비 기준으로 360px로 고정하기로 협의를 해서 폰마다 옆에 너비가 남는 현상이 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt; &lt;span&gt;&lt;span&gt; 채팅 앱 관련해서 어떻게 동작하는지 설명해주세요.&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;작업은 모두 로컬에서 작업하고 node express로 서버를 열어서 emit 되는 이벤트들을 처리하였습니다. 클라이언트는 Pug로 보여주었고 인스타그램 DM처럼 개인 메시지 가능하고 채팅룸 기능도 구현하였습니다. 이벤트 경우 클라이언트에서 특정 함수를 emit 하면 서버에서 해당 emit을 받아 처리를 하고 다시 클라이언트들에게 emit으로 수정된 내역을 뿌려주는 형식으로 처리하였습니다. 그리고 해당 채팅 내역은 MongoDB에 저장하였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt; &lt;span&gt;&lt;span&gt;&lt;span&gt; Pug가 뭔가요?&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저도 잘 모르겠습니다.... HTML이랑 비슷하면서도 조금 다른 것이라는 것 밖에 모릅니다... ㅜ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt; &lt;span&gt;&amp;nbsp;&lt;/span&gt;SCSS를 사용해보셨나요?&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;b&gt; &lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;B&lt;/span&gt;abel을&amp;nbsp;써보셨나요?&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;b&gt; &lt;span&gt;&amp;nbsp;&lt;/span&gt;마크업,&amp;nbsp;퍼블리싱 작업은&amp;nbsp;어떻게&amp;nbsp;하시나요?&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;디자이너에게 받은 UI를 피그마로 띄워놓고 리액트로 npm start 한 다음 코드 작성하고 새로고침하여 보고 다시 수정하는 식으로 작업합니다. 사실 프론트엔드 실무자분들이 어떻게 작업하는지 궁금하기도 합니다.&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;b&gt;⭐️&lt;/b&gt; React 관련 질문&amp;nbsp;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리액트 관련 질문의 경우 &lt;b&gt;이 글을 읽으러 들어오신 분들이 가장 궁금해할 사항&lt;/b&gt;이니 저의 답변이 아닌 구글링 하여 찾은 답을 적어놨습니다. 실제 면접에서 아래의 질문을 받았을 때는 70% 이상은 자신 있게 답변했던 걸로 기억합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt; &lt;span&gt;&amp;nbsp;&lt;/span&gt;state와 props의 차이는?&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;state는 현재 컴포넌트의 생명주기 동안에 변경될 수 있는 정보를 담고 있는 상태이고, props는 부모 컴포넌트에서 자식 컴포넌트로 전달되는 데이터입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;  &lt;b&gt;Props&amp;nbsp;Drilling이란?&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1108&quot; data-origin-height=&quot;76&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bBr3v4/btrvJTjpUli/TuevOkiuRmMSJLmQMD4mY1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bBr3v4/btrvJTjpUli/TuevOkiuRmMSJLmQMD4mY1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bBr3v4/btrvJTjpUli/TuevOkiuRmMSJLmQMD4mY1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbBr3v4%2FbtrvJTjpUli%2FTuevOkiuRmMSJLmQMD4mY1%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;1108&quot; height=&quot;76&quot; data-origin-width=&quot;1108&quot; data-origin-height=&quot;76&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Props 내리꽂기란 상위 컴포넌트에서 하위 컴포넌트로 props를 전달하는&amp;nbsp;과정을 말합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #666666;&quot;&gt;&lt;i&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;깊이가 깊을수록 그 과정이 귀찮고 힘들며 예기치 못한 오류를 발생시킬 수도 있고 이것에 대한 꼬리 질문으로 이러한 현상을 해결하는 방법(전역으로 state를 관리할 수 있는 redux, context API 사용 등등)에 대한 질문이 나올 가능성이 높습니다.&lt;/span&gt;&lt;/i&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt; &lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;Redux의 정의, 필요성, 구조에 대해 설명해주세요.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리덕스는 리액트에서 사용되는 상태 관리 라이브러리 중 하나입니다. 프로젝트의 규모가 커지면 state의 전달이 복잡하고 어려워지게 되고 오류가 발생할 가능성이 높아집니다. 리덕스 사용 시 순수 함수를 사용하기 때문에 상태가 예측 가능하고 유지보수 및 디버깅에 유리하다는 이점이 존재합니다.&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;b&gt;스토어(Stroe)&lt;/b&gt; : 상태가 관리되는 오직 하나의 공간&lt;/li&gt;
&lt;li&gt;&lt;b&gt;액션(Action)&lt;/b&gt; : 상태 변화를 발생시킬 때 참조하는 객체 (애플리케이션에서 저장소로 보내는 데이터 묶음)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;리듀서(Reducer)&lt;/b&gt; : 현재 state와 action을 이용해 다음 state를 만들어냄&lt;/li&gt;
&lt;li&gt;&lt;b&gt;디스패치(Dispatch)&lt;/b&gt; : 액션을 발생시키는 것&lt;/li&gt;
&lt;li&gt;&lt;b&gt;구독(Subscribe)&lt;/b&gt; : Subscribe 함수 안에 리스너 함수를 파리미터로 넣어주면 store의 state가 변경될 때마다 리스너 함수를 호출&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt; &lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;제어 컴포넌트와&amp;nbsp;비제어&amp;nbsp;컴포넌트의&amp;nbsp;차이점은?&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;제어 컴포넌트의 경우 리액트 state에 의해서 값이 관리 및 변경이 되고, 비제어 컴포넌트의 경우 ref를 통해 DOM 자체에서 form 데이터가 다뤄집니다. 가장 큰 차이점은 동기화인데, 제어 컴포넌트의 경우 사용자가 입력할 때마다 input의 state가 동기화되지만 state가 변경될 때마다 리렌더링이 발생하여 불필요한 자원의 낭비로 이어질 수 있습니다. 반면 비제어 컴포넌트의 경우 입력을 하고 버튼을 누르는 최종적인 상황에서만 input의 value에 접근을 하므로 리렌더링이 계속해서 발생하지는 않지만 입력의 최신 값에 접근하기 힘든 특성이 존재합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt; &lt;span&gt;&amp;nbsp;&lt;/span&gt;Virtual DOM에 대해 설명해주세요.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DOM과 유사한 객체를 메모리 상으로 구현하고 변경사항이 생기면 메모리에 올라간 Virtual DOM을 수정하고. DOM에 대한 비교를 수행하여 변경 사항에 대해서만 DOM에 반영합니다. 이로 인해 더 반응성이 빠른 웹을 구현할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt; &lt;span&gt;&amp;nbsp;&lt;/span&gt;리액트&amp;nbsp;라이프사이클에&amp;nbsp;대해서&amp;nbsp;설명해주세요.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;React LifeCycle은 컴포넌트가 DOM위에 생성되거나 사라질 때, 혹은 업데이트될 때 호출되는 API입니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1097&quot; data-origin-height=&quot;654&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cbs7nU/btrvL45oWDg/UhjSKwaKysjCtuX3uIEbnk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cbs7nU/btrvL45oWDg/UhjSKwaKysjCtuX3uIEbnk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cbs7nU/btrvL45oWDg/UhjSKwaKysjCtuX3uIEbnk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcbs7nU%2FbtrvL45oWDg%2FUhjSKwaKysjCtuX3uIEbnk%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;1097&quot; height=&quot;654&quot; data-origin-width=&quot;1097&quot; data-origin-height=&quot;654&quot;/&gt;&lt;/span&gt;&lt;/figure&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;b&gt;constructor&lt;/b&gt; : 컴포넌트의 생성자 메서드. 컴포넌트 생성 시 가장 먼저 실행되는 메서드. 초기 state를 설정&lt;/li&gt;
&lt;li&gt;&lt;b&gt;getDerivedStateFromProps&lt;/b&gt; : props로 받아온 것을 state에 넣어주고 싶을 때 사용&lt;/li&gt;
&lt;li&gt;&lt;b&gt;render&lt;/b&gt; : 컴포넌트를 렌더링 하는 메서드&lt;/li&gt;
&lt;li&gt;&lt;b&gt;componentDidMount&lt;/b&gt; : 컴포넌트의 첫 번째 렌더링을 마치고 호출되는 메서드. 주로 여기서 비동기 요청 작업 처리&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;&lt;b&gt;shouldComponentUpdate&lt;/b&gt; : 컴포넌트를 리렌더링 할지 말지를 결정하는 메서드&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;getSnapshotBeforeUpdate&lt;/b&gt; : Virtual DOM이 실제 DOM에 반영되기 직전에 실행. 이 메서드에서는 이전과 현재의 props와 state에 접근이 가능하고 return으로 넘겨진 값은 componentDidUpdate의 3번째 인자로 전달됨&lt;/li&gt;
&lt;li&gt;&lt;b&gt;componentDidUpdate&lt;/b&gt; : 리렌더링을 마치고 화면에 변화가 모두 반영되고 난 뒤 호출되는 메서드&lt;/li&gt;
&lt;li&gt;&lt;b&gt;componentWillUnmount&lt;/b&gt; : 컴포넌트가 화면에서 사라지기 직전에 호출되는 메서드&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt; &lt;span&gt;&amp;nbsp;&lt;/span&gt;함수형&amp;nbsp;컴포넌트의&amp;nbsp;장점은?&lt;/b&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;/li&gt;
&lt;li&gt;클래스형 컴포넌트보다 메모리 자원을 절약&lt;/li&gt;
&lt;li&gt;프로젝트 빌드 후 배포 시 빌드 파일의 크기가 작음(사실상 별 차이 없음)&lt;/li&gt;
&lt;li&gt;리액트 16.8 버전부터 Hook으로 라이프사이클 사용 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt; &lt;span&gt; 클래스형 컴포넌트와 &lt;/span&gt;함수형 컴포넌트 차이점은?&lt;/b&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;/li&gt;
&lt;li&gt;state 사용법&lt;/li&gt;
&lt;li&gt;함수형이 클래스형보다 사용하기 편함&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt; &lt;span&gt;&amp;nbsp;&lt;/span&gt;Context란 무엇인가요?&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Props drilling 과정 없이 컴포넌트 트리 전체에 데이터를 제공할 수 있는 방법입니다. 리덕스의 비교대상이 아니며 상태를 관리하는 것이 아닌 Props drilling을 피하기 위해 값을 전달해주는 파이프와 같은 존재입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt; &lt;span&gt;&amp;nbsp;&lt;/span&gt;JSX란 무엇인가요?&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JSX는 JavaScript XML의 약자로 자바스크립트에서 XML 유사 구문을 확장시킨 문법입니다. HTML과 같은 문법과 함께 JS를 표현할 수 있어 편리하고 가독성이 높고 작성하기 쉽습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt; &lt;span&gt;&amp;nbsp;&lt;/span&gt;리액트&amp;nbsp;훅이란?&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;React Hook은 함수형 컴포넌트에서도 클래스형 컴포넌트의 기능을 사용할 수 있게 하는 기능입니다. Hook을 통해서 함수형 컴포넌트에서도 컴포넌트의 상태 값을 관리할 수 있고 생명주기 메서드 또한 사용이 가능합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt; &lt;span&gt; Hook이 추가된 리액트 버전은?&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;version &lt;span&gt;16.8&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt; &lt;span&gt;&amp;nbsp;&lt;/span&gt;쿠키,&amp;nbsp;세션에&amp;nbsp;대해&amp;nbsp;아시나요?&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- 쿠키&lt;/b&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;/li&gt;
&lt;li&gt;데이터 형태는 Key와 Value로 구성되고 String 형태로 이루어져 있음&lt;/li&gt;
&lt;li&gt;서버가 아닌 사용자에게 저장되기 때문에 임의 수정이나 가로채기가 쉬워 보안에 취약&lt;/li&gt;
&lt;li&gt;사용자의 브라우저에 저장되기 때문에 클라이언트의 자원을 사용&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- 세션&lt;/b&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;/li&gt;
&lt;li&gt;클라이언트가 페이지를 이동하거나 재접속했을 때 구분할 수 있는 수단&lt;/li&gt;
&lt;li&gt;쿠키에 비해 보안성이 좋으며 주로 로그인 정보 유지에 사용됨&lt;/li&gt;
&lt;li&gt;서버에 데이터를 저장하기 때문에 서버의 자원을 사용&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt; &lt;span&gt; Props의 Type을 강제하는 방법에 대해 아시나요?&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;prop-types&quot;라는 라이브러리를 사용하여 props의 데이터 type을 지정해줄 수 있습니다. props에 유효하지 않은 값이 전달되면 콘솔 창에 경고문을 띄웁니다.&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;❔&amp;nbsp;궁금한 점 있으신가요?&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;  보통 처음 신입으로 들어가면 바로 실무에 투입되지 않고 과제를 받는다고 들었는데 어떠한 과제인지 여쭤봐도 될까요?&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;회사 By 회사인데 저희 같은 경우에는 따로 과제는 없고 실무에 필요한 트레이딩 뷰와 웹소켓에 대해 배우고 그것만 해도 50% 정도는 했다고 보시면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt; &lt;span&gt; 커피 머신이 있나요? 아니면 아이스티라도,,,,!&lt;/span&gt;&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;&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;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #8a3db6;&quot;&gt;&lt;b&gt;1. 자기소개도 중요하지만 경험이 가장 중요하다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 면접 과정을 거치면서 경험이 가장 중요하다는 생각이 들었습니다. 회사의 인사담당자분들마다 다르겠지만 채용하려는 지원자의 최소한의 커트라인(예를 들어 리액트로 이 페이지 정도는 3일 안에 완성이 가능한 실력인지 등등)이 있을 것입니다. 저의 경우 작년 10월부터 프로젝트를 하면서 리액트 모르는 게 있으면 구글링 하면서 배워가면서 작업을 해나갔고 그러한 경험 속에서 리액트 관련 지식이 쌓이게 되었습니다. 작년에 면접을 볼 때는 면접 가기 전에 외운 것을 답하느라 많이 횡설수설하고 힘들었으나 이번 면접은 별다른 준비를 하지 않았고 면접 가서 외운 내용이 아닌 머리에 들어있는 개념을 말하는 식으로 면접을 굉장히 편안하게 봤던 것 같습니다. 면접관분들도 아마 질문을 통해 이 지원자가 단순히 외운 내용인지 아니면 몸소 체험하면서 머리에 박힌 개념인지 아실 겁니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #8a3db6;&quot;&gt;&lt;b&gt;2. 생각보다 자세히 보신다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;면접관분들도 바쁘시고 자기 업무가 있으시니까 포트폴리오나 이력서에 있는 URL은 잘 안 눌러보신다고 알고 있습니다. 그런데 이번에 면접 본 곳은 이력서에서 깃헙, 블로그, 프로젝트 서비스 링크 모두 들어가 보시고 깃헙 저장소의 package.json의 내용까지도 물어보셨습니다. 정말 꼼꼼하게 이것저것 피드백과 질문을 받았고 가장 인상 깊었던 질문은 &quot;블로그에 광고가 달려있는데 광고수익은 얼마나 되나요? 하루에 스타벅스 커피 한잔...?&quot;이라는 질문을 받았던 게 생각이 납니다 &lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #8a3db6;&quot;&gt;&lt;b&gt;3. 모르는 것은 모른다고 답하자.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;친구가 한창 신입으로 일할 때의 경험담인데, 자기 사수가 어떤 것에 대해 아냐고 물었을 때 자기 자신이 자세히 모름에도 불구하고 안다고 대답해놓고 나중에 가서 일처리가 제대로 안되어 문제가 된 적이 있었습니다. 그러한 일을 겪고 저에게 &quot;&lt;b&gt;사수나 면접관이 질문을 할 때 확실하게 알고 있는 부분이면 확실하게 대답하고, 잘 모르는 부분이면 확실하게 잘 모른다고 대답하는 게 중요하다&quot;&lt;/b&gt;라고 조언을 해주었습니다. 어차피 추가 질문이 들어오게 되어있고 거기에서 잘 모르는 사실이 들통 하면 마이너스이니까 잘 모르는 부분은 걱정 마시고 확실하게 모르신다고 답하시면 됩니다. 저도 리액트 관련 질문 중에서 잘 모르는 내용은 확실하게 잘 모른다고 답하고 전체 질문 중에서 70% 정도만 답했던 것 같습니다.&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;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;진행 중인 프로젝트의 끝이 보이기 시작해서 한번 그냥 지원해봤는데 운 좋게도 면접을 보러 오라고 연락이 왔었고 가벼운 마음으로 면접을 갔었습니다. 면접 가서도 대답도 나쁘지 않게 하고 면접관님들도 저에 대해 궁금한 점이 많으신 것 같고 분위기도 괜찮았었습니다. 그리고 마지막에는 희망연봉도 물어보시던데 면접 끝나고 친구한테 말하니 그거 힌트일 수도 있다고 하더라구요 ㄷㄷ.... 합격 문자는 다음 주 중으로 갈 것이라 해서 오늘 무방비상태로 있었는데 아까 점심때 합격 연락 및 입사 제의가 와서 어안이 벙벙했습니다. 6개월간 준비해서 드디어 취업에 성공했고 이 글을 읽으시는 분들 모두 면접 파이팅 하시길 바라겠습니다! 궁금한 점 있으면 댓글 남겨주세요~ &lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category> IT</category>
      <author>Cocoon_</author>
      <guid isPermaLink="true">https://cocoon1787.tistory.com/840</guid>
      <comments>https://cocoon1787.tistory.com/840#entry840comment</comments>
      <pubDate>Sat, 12 Mar 2022 01:47:48 +0900</pubDate>
    </item>
    <item>
      <title>[React] 리액트 setState Callback 함수 사용법</title>
      <link>https://cocoon1787.tistory.com/839</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;727&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ccnJdC/btrvEG5uNkl/bged9NboVWT5ZrKUadcio0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ccnJdC/btrvEG5uNkl/bged9NboVWT5ZrKUadcio0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ccnJdC/btrvEG5uNkl/bged9NboVWT5ZrKUadcio0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FccnJdC%2FbtrvEG5uNkl%2Fbged9NboVWT5ZrKUadcio0%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;1280&quot; height=&quot;727&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;727&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt; &lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;리액트에서 setState 후 변경된 state값을 사용하는 경우가 종종 있으며, Callback 함수를 사용하여 해결할 수 있습니다.&lt;/b&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;  setState를 한 뒤 state를 사용하는 경우&lt;/b&gt;&lt;/h2&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;  코드&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1646934240934&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import React, { Component } from &quot;react&quot;;
import styled from &quot;styled-components&quot;;
import &quot;./App.css&quot;;

const Wrapper = styled.div`
  display: flex;
  margin: 20px;
`;

const Print = styled.div`
  border-radius: 5px;
  border: 1px solid #6c757d;
  width: 80px;
  height: 30px;
  font-size: 20px;
  text-align: center;
`;

const Button = styled.button`
  background-color: #6c757d;
  border-radius: 5px;
  border: 0px;
  color: white;
  width: 80px;
  height: 30px;
  margin-left: 10px;
  &amp;amp;:hover {
    background-color: #5a6268;
  }
`;

class App extends Component {
  constructor(props) {
    super(props);
    this.state = { counter: 0 };
  }

  onClick = () =&amp;gt; {
    this.setState({ counter: this.state.counter + 1 });
    console.log(this.state.counter);
  };

  render() {
    return (
      &amp;lt;Wrapper&amp;gt;
        &amp;lt;Print&amp;gt;{this.state.counter}&amp;lt;/Print&amp;gt;
        &amp;lt;Button onClick={this.onClick}&amp;gt;+1&amp;lt;/Button&amp;gt;
      &amp;lt;/Wrapper&amp;gt;
    );
  }
}

export default App;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;661&quot; data-origin-height=&quot;64&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/TA6wT/btrvFeNSJoT/yNNWkseHxEKLZvLHTKkQ3k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/TA6wT/btrvFeNSJoT/yNNWkseHxEKLZvLHTKkQ3k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/TA6wT/btrvFeNSJoT/yNNWkseHxEKLZvLHTKkQ3k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FTA6wT%2FbtrvFeNSJoT%2FyNNWkseHxEKLZvLHTKkQ3k%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;64&quot; data-origin-width=&quot;661&quot; data-origin-height=&quot;64&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;버튼을 누르면 state의 counter 값이 +1씩 증가하게 하는 예제입니다.&lt;/p&gt;
&lt;pre id=&quot;code_1646934349316&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;  onClick = () =&amp;gt; {
    this.setState({ counter: this.state.counter + 1 });
    console.log(this.state.counter);
  };&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;onClick 함수에서 setState로 state를 변경해주고 this.state.counter 출력 시 결과는 아래와 같습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;666&quot; data-origin-height=&quot;247&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ecSUgJ/btrvFChbs6h/FVeEtTqwTfE3Pg4Cj8Q280/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ecSUgJ/btrvFChbs6h/FVeEtTqwTfE3Pg4Cj8Q280/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ecSUgJ/btrvFChbs6h/FVeEtTqwTfE3Pg4Cj8Q280/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FecSUgJ%2FbtrvFChbs6h%2FFVeEtTqwTfE3Pg4Cj8Q280%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;666&quot; height=&quot;247&quot; data-origin-width=&quot;666&quot; data-origin-height=&quot;247&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1이 출력되기를 기대했지만 예상과는 다르게 바뀌기 이전 값이 '&lt;b&gt;0&lt;/b&gt;'이 출력되었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;  &lt;b&gt;Why?&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;setState 함수는 비동기 함수이기 때문에 이벤트 핸들러 함수에서 바로 값을 갱신하는 것이 아닌 이벤트 핸들러 함수 종료 후 state값이 갱신됩니다.&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;✔️ 클래스형 컴포넌트의 setState Callback 사용법&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&amp;lt;setState 함수의 정의&amp;gt;&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1646934782835&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;setState&amp;lt;K extends keyof S&amp;gt;(
  state: ((prevState: Readonly&amp;lt;S&amp;gt;, props: Readonly&amp;lt;P&amp;gt;) =&amp;gt; (Pick&amp;lt;S, K&amp;gt; | S | null)) | (Pick&amp;lt;S, K&amp;gt; | S | null),
  callback?: () =&amp;gt; void
): void;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;setState함수는 2개의 인자를 받는데 첫 번째 인자는 변경할 state를 전달하며, 두 번째 인자는 state가 변경된 후 실행되는 callback 함수를 전달합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;  코드&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1646934692640&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import React, { Component } from &quot;react&quot;;
import styled from &quot;styled-components&quot;;
import &quot;./App.css&quot;;

const Wrapper = styled.div`
  display: flex;
  margin: 20px;
`;

const Print = styled.div`
  border-radius: 5px;
  border: 1px solid #6c757d;
  width: 80px;
  height: 30px;
  font-size: 20px;
  text-align: center;
`;

const Button = styled.button`
  background-color: #6c757d;
  border-radius: 5px;
  border: 0px;
  color: white;
  width: 80px;
  height: 30px;
  margin-left: 10px;
  &amp;amp;:hover {
    background-color: #5a6268;
  }
`;

class App extends Component {
  constructor(props) {
    super(props);
    this.state = { counter: 0 };
  }

  onClick = () =&amp;gt; {
    this.setState({ counter: this.state.counter + 1 }, () =&amp;gt; {
      console.log(this.state.counter);
    });
  };

  render() {
    return (
      &amp;lt;Wrapper&amp;gt;
        &amp;lt;Print&amp;gt;{this.state.counter}&amp;lt;/Print&amp;gt;
        &amp;lt;Button onClick={this.onClick}&amp;gt;+1&amp;lt;/Button&amp;gt;
      &amp;lt;/Wrapper&amp;gt;
    );
  }
}

export default App;

// function App() {
//   return (
//     &amp;lt;Wrapper&amp;gt;
//       &amp;lt;Print&amp;gt;&amp;lt;/Print&amp;gt;
//       &amp;lt;Button&amp;gt;&amp;lt;/Button&amp;gt;
//     &amp;lt;/Wrapper&amp;gt;
//   );
// }&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;668&quot; data-origin-height=&quot;243&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/V7Zw7/btrvBlH0DrY/JaA2pJ128Mp4Is2fka7zG1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/V7Zw7/btrvBlH0DrY/JaA2pJ128Mp4Is2fka7zG1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/V7Zw7/btrvBlH0DrY/JaA2pJ128Mp4Is2fka7zG1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FV7Zw7%2FbtrvBlH0DrY%2FJaA2pJ128Mp4Is2fka7zG1%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;668&quot; height=&quot;243&quot; data-origin-width=&quot;668&quot; data-origin-height=&quot;243&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre id=&quot;code_1646934721915&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;  onClick = () =&amp;gt; {
    this.setState({ counter: this.state.counter + 1 }, () =&amp;gt; {
      console.log(this.state.counter);
    });
  };&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서 위와 같이 state를 변경하고 callback함수로 변경된 state를 사용할 수 있게 됩니다.&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&gt;&amp;nbsp;함수&lt;/span&gt;형 컴포넌트의 setState Callback 사용법&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리액트 16.8 이전 버전에서는 함수형 컴포넌트에서 상태를 관리할 수 없었는데, 리액트 16.8 버전에서 Hooks라는 기능이 도입되면서 useState라는 함수를 사용하여 함수형 컴포넌트에서도 상태를 관리할 수 있게 되었습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러나 useState 함수의 경우 두 번째 인수가 존재하지 않기 때문에 userEffect를 사용하여 변경된 state를 사용해보겠습니다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;  코드&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1646935569758&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import React, { Component, useState, useEffect } from &quot;react&quot;;
import styled from &quot;styled-components&quot;;
import &quot;./App.css&quot;;

const Wrapper = styled.div`
  display: flex;
  margin: 20px;
`;

const Print = styled.div`
  border-radius: 5px;
  border: 1px solid #6c757d;
  width: 80px;
  height: 30px;
  font-size: 20px;
  text-align: center;
`;

const Button = styled.button`
  background-color: #6c757d;
  border-radius: 5px;
  border: 0px;
  color: white;
  width: 80px;
  height: 30px;
  margin-left: 10px;
  &amp;amp;:hover {
    background-color: #5a6268;
  }
`;

function App() {
  const [counter, setCounter] = useState(0);

  const onClick = () =&amp;gt; {
    setCounter(counter + 1);
  };

  useEffect(() =&amp;gt; {
    console.log(counter);
  }, [counter]);

  return (
    &amp;lt;Wrapper&amp;gt;
      &amp;lt;Print&amp;gt;{counter}&amp;lt;/Print&amp;gt;
      &amp;lt;Button onClick={onClick}&amp;gt;+1&amp;lt;/Button&amp;gt;
    &amp;lt;/Wrapper&amp;gt;
  );
}

export default App;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;667&quot; data-origin-height=&quot;265&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dM6vE6/btrvH0hkFNR/3A6wySyGKpxRgyZ1lPoheK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dM6vE6/btrvH0hkFNR/3A6wySyGKpxRgyZ1lPoheK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dM6vE6/btrvH0hkFNR/3A6wySyGKpxRgyZ1lPoheK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdM6vE6%2FbtrvH0hkFNR%2F3A6wySyGKpxRgyZ1lPoheK%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;667&quot; height=&quot;265&quot; data-origin-width=&quot;667&quot; data-origin-height=&quot;265&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;useEffrct에서 두 번째 인자로 배열에 state를 넣어서 해당 state가 변경(업데이트)되면 useEffect 함수가 실행되도록 하였습니다.&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;  useEffect 추가 설명&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1646936016417&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;  useEffect(() =&amp;gt; {
    console.log(&quot;마운트 될 때만 실행&quot;);
  }, []);

  useEffect(() =&amp;gt; {
    console.log(&quot;렌더링 될 때마다 실행&quot;);
  });

  useEffect(() =&amp;gt; {
    console.log(&quot;counter가 업데이트 될 때마다 실행&quot;);
  }, [counter]);&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;648&quot; data-origin-height=&quot;208&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cAycPc/btrvFBvPo7E/LSwUsV3huDjkPWVPnrrE8K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cAycPc/btrvFBvPo7E/LSwUsV3huDjkPWVPnrrE8K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cAycPc/btrvFBvPo7E/LSwUsV3huDjkPWVPnrrE8K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcAycPc%2FbtrvFBvPo7E%2FLSwUsV3huDjkPWVPnrrE8K%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;648&quot; height=&quot;208&quot; data-origin-width=&quot;648&quot; data-origin-height=&quot;208&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;649&quot; data-origin-height=&quot;231&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b5vjHo/btrvDP9qY6q/JfOzJ0s8nnR7fGbwed0Kn0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b5vjHo/btrvDP9qY6q/JfOzJ0s8nnR7fGbwed0Kn0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b5vjHo/btrvDP9qY6q/JfOzJ0s8nnR7fGbwed0Kn0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb5vjHo%2FbtrvDP9qY6q%2FJfOzJ0s8nnR7fGbwed0Kn0%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;649&quot; height=&quot;231&quot; data-origin-width=&quot;649&quot; data-origin-height=&quot;231&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;
&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;</description>
      <category>⚛️React</category>
      <author>Cocoon_</author>
      <guid isPermaLink="true">https://cocoon1787.tistory.com/839</guid>
      <comments>https://cocoon1787.tistory.com/839#entry839comment</comments>
      <pubDate>Fri, 11 Mar 2022 12:15:43 +0900</pubDate>
    </item>
    <item>
      <title>[HTML/CSS] 텍스트가 넘칠 때 생략하는 방법 (... 말줄임 표시)</title>
      <link>https://cocoon1787.tistory.com/838</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1448&quot; data-origin-height=&quot;812&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/q07Vp/btrvCnrWND1/wwoNphmgeY07ta8VUrKzrk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/q07Vp/btrvCnrWND1/wwoNphmgeY07ta8VUrKzrk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/q07Vp/btrvCnrWND1/wwoNphmgeY07ta8VUrKzrk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fq07Vp%2FbtrvCnrWND1%2FwwoNphmgeY07ta8VUrKzrk%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;1448&quot; height=&quot;812&quot; data-origin-width=&quot;1448&quot; data-origin-height=&quot;812&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;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt; &lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;웹페이지에서 UI를 만들 때 박스 안의 텍스트의 길이가 길어서 해당 영역을 벗어나는 경우 &lt;b&gt;말줄임(...)&lt;/b&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;  &lt;b&gt;코드&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1646931672898&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html lang=&quot;ko&quot;&amp;gt;
  &amp;lt;head&amp;gt;
    &amp;lt;meta charset=&quot;UTF-8&quot; /&amp;gt;
    &amp;lt;title&amp;gt;Document&amp;lt;/title&amp;gt;
    &amp;lt;style&amp;gt;
      body {
        background: #ddd;
      }
      .area {
        margin: 20px 10px;
        width: 240px;
        background: white;
      }

      .white-space {
        white-space: nowrap;
      }

      .overflow {
        overflow: hidden;
      }
    &amp;lt;/style&amp;gt;
  &amp;lt;/head&amp;gt;
  &amp;lt;body&amp;gt;
    &amp;lt;div class=&quot;area&quot;&amp;gt;
      Lorem ipsum dolor sit amet, consectetur adipisicing elit.
    &amp;lt;/div&amp;gt;
    &amp;lt;div class=&quot;area white-space&quot;&amp;gt;
      Lorem ipsum dolor sit amet, consectetur adipisicing elit.
    &amp;lt;/div&amp;gt;
    &amp;lt;div class=&quot;area white-space overflow&quot;&amp;gt;
      Lorem ipsum dolor sit amet, consectetur adipisicing elit.
    &amp;lt;/div&amp;gt;
  &amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;665&quot; data-origin-height=&quot;277&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bj1d0w/btrvHZQd18C/hQMRea7Df8nmHxoQMRk1Ck/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bj1d0w/btrvHZQd18C/hQMRea7Df8nmHxoQMRk1Ck/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bj1d0w/btrvHZQd18C/hQMRea7Df8nmHxoQMRk1Ck/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbj1d0w%2FbtrvHZQd18C%2FhQMRea7Df8nmHxoQMRk1Ck%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;665&quot; height=&quot;277&quot; data-origin-width=&quot;665&quot; data-origin-height=&quot;277&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;white-space: no-wrap&lt;/b&gt; 속성은 해당 영역 내에 텍스트가 길 때 자동으로 줄 바꿈 하는 것을 방지합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;overflow: hidden&lt;/b&gt; 속성은 해당 영역을 벗어나는 텍스트를 숨깁니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 3번째 div에 대해 말줄임을 적용하기 위해 아래의 css 속성을 추가해줍니다.&lt;/p&gt;
&lt;pre id=&quot;code_1646932169188&quot; class=&quot;css&quot; data-ke-language=&quot;css&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;text-overflow: ellipsis;&lt;/code&gt;&lt;/pre&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;h4 data-ke-size=&quot;size20&quot;&gt; &lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;코드&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1646932178104&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html lang=&quot;ko&quot;&amp;gt;
  &amp;lt;head&amp;gt;
    &amp;lt;meta charset=&quot;UTF-8&quot; /&amp;gt;
    &amp;lt;title&amp;gt;Document&amp;lt;/title&amp;gt;
    &amp;lt;style&amp;gt;
      body {
        background: #ddd;
      }
      .area {
        margin: 40px 30px;
        width: 180px;
        height: 40px;
        background: white;
      }

      .ellipsis {
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
      }
    &amp;lt;/style&amp;gt;
  &amp;lt;/head&amp;gt;
  &amp;lt;body&amp;gt;
    &amp;lt;div class=&quot;area ellipsis&quot;&amp;gt;
      Lorem ipsum dolor sit amet, consectetur adipisicing elit.
    &amp;lt;/div&amp;gt;
  &amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;663&quot; data-origin-height=&quot;125&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/wEkdp/btrvF9lxKT3/vBQIvTME4lcopl01sBFm51/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/wEkdp/btrvF9lxKT3/vBQIvTME4lcopl01sBFm51/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/wEkdp/btrvF9lxKT3/vBQIvTME4lcopl01sBFm51/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FwEkdp%2FbtrvF9lxKT3%2FvBQIvTME4lcopl01sBFm51%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;663&quot; height=&quot;125&quot; data-origin-width=&quot;663&quot; data-origin-height=&quot;125&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt; &lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;코드&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1646932557933&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html lang=&quot;ko&quot;&amp;gt;
  &amp;lt;head&amp;gt;
    &amp;lt;meta charset=&quot;UTF-8&quot; /&amp;gt;
    &amp;lt;title&amp;gt;Document&amp;lt;/title&amp;gt;
    &amp;lt;style&amp;gt;
      body {
        background: #ddd;
      }
      .area {
        margin: 40px 30px;
        width: 300px;
        background: white;
      }

      .ellipsis {
        overflow: hidden;
        text-overflow: ellipsis;
        display: -webkit-box;
        -webkit-line-clamp: 3;
        -webkit-box-orient: vertical;
      }
    &amp;lt;/style&amp;gt;
  &amp;lt;/head&amp;gt;
  &amp;lt;body&amp;gt;
    &amp;lt;div class=&quot;area&quot;&amp;gt;
      Lorem ipsum dolor sit amet consectetur adipisicing elit. Non, quo nesciunt
      aliquid nulla eveniet cupiditate odit nemo dolor nobis vel dicta, aliquam
      suscipit id assumenda eius consectetur blanditiis deleniti dolorum?
    &amp;lt;/div&amp;gt;
    &amp;lt;div class=&quot;area ellipsis&quot;&amp;gt;
      Lorem ipsum dolor sit amet consectetur adipisicing elit. Non, quo nesciunt
      aliquid nulla eveniet cupiditate odit nemo dolor nobis vel dicta, aliquam
      suscipit id assumenda eius consectetur blanditiis deleniti dolorum?
    &amp;lt;/div&amp;gt;
  &amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;666&quot; data-origin-height=&quot;324&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/70rrA/btrvvuSgbIE/NxlPCJuJYkMrxuhLb18KBk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/70rrA/btrvvuSgbIE/NxlPCJuJYkMrxuhLb18KBk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/70rrA/btrvvuSgbIE/NxlPCJuJYkMrxuhLb18KBk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F70rrA%2FbtrvvuSgbIE%2FNxlPCJuJYkMrxuhLb18KBk%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;666&quot; height=&quot;324&quot; data-origin-width=&quot;666&quot; data-origin-height=&quot;324&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;display:&amp;nbsp;-webkit-box&lt;/b&gt;&amp;nbsp;속성은&amp;nbsp;해당&amp;nbsp;영역을&amp;nbsp;box&amp;nbsp;형태로&amp;nbsp;관리되도록&amp;nbsp;합니다. &lt;/li&gt;
&lt;li&gt;&lt;b&gt;-webkit-line-clamp&lt;/b&gt; 속성은 해당 영역 내의 텍스트의 최대 라인수를 결정합니다. &lt;/li&gt;
&lt;li&gt;&lt;b&gt;-webkit-box-orient: vertical&lt;/b&gt; 속성은 box의 흐름 방향을 수직으로 지정합니다.&lt;/li&gt;
&lt;/ol&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 data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category> WEB</category>
      <author>Cocoon_</author>
      <guid isPermaLink="true">https://cocoon1787.tistory.com/838</guid>
      <comments>https://cocoon1787.tistory.com/838#entry838comment</comments>
      <pubDate>Fri, 11 Mar 2022 07:21:00 +0900</pubDate>
    </item>
  </channel>
</rss>