<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>시골청년의 1인 개발 블로그</title>
    <link>https://ghkdtprhf5.tistory.com/</link>
    <description>시골에서 1인 개발자를 꿈꾸며 하루동안 배운 내용을 정리합니다!!</description>
    <language>ko</language>
    <pubDate>Sat, 13 Jun 2026 12:44:12 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>ghkdtprhf5</managingEditor>
    <item>
      <title>Next.js: 리액트 개발자를 위한 필수 프레임워크</title>
      <link>https://ghkdtprhf5.tistory.com/14</link>
      <description>&lt;h2&gt;Next.js: 리액트 개발자를 위한 필수 프레임워크&lt;/h2&gt;

&lt;p&gt;Next.js는 React 기반의 프레임워크로, 서버 사이드 렌더링(SSR)과 정적 사이트 생성(SSG)을 지원하여 성능과 SEO를 강화하는 데 최적화된 도구입니다. Next.js는 다양한 기능을 내장하고 있어 현대적인 웹 애플리케이션을 구축하는 데 매우 유용합니다. 이번 글에서는 Next.js의 주요 기능과 장점, 그리고 기본적인 사용 방법을 살펴보겠습니다.&lt;/p&gt;

&lt;h3&gt;1. Next.js의 주요 기능&lt;/h3&gt;

&lt;p&gt;Next.js는 개발자가 빠르게 웹 애플리케이션을 만들 수 있도록 다양한 기능을 제공합니다. 대표적인 기능으로는 &lt;strong&gt;서버 사이드 렌더링(SSR)&lt;/strong&gt;, &lt;strong&gt;정적 사이트 생성(SSG)&lt;/strong&gt;, &lt;strong&gt;자동 코드 분할&lt;/strong&gt;, &lt;strong&gt;라우팅&lt;/strong&gt;, 그리고 &lt;strong&gt;API 라우트&lt;/strong&gt;가 있습니다.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;SSR (서버 사이드 렌더링)&lt;/strong&gt;: 페이지가 서버에서 렌더링되어 브라우저로 전송되므로, 초기 로딩 속도가 빠르고 SEO에 유리합니다.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;SSG (정적 사이트 생성)&lt;/strong&gt;: 빌드 시점에 HTML 파일을 생성하여 성능을 극대화하고, CDN을 통한 빠른 배포가 가능합니다.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;자동 코드 분할&lt;/strong&gt;: 페이지별로 필요한 코드만 로딩하므로, 로딩 속도를 최적화할 수 있습니다.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;라우팅&lt;/strong&gt;: 폴더 구조에 따라 자동으로 라우팅이 설정되므로 별도의 설정이 필요 없습니다.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;API 라우트&lt;/strong&gt;: 백엔드 기능을 위한 간단한 API 엔드포인트를 쉽게 만들 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;2. Next.js 설치 및 기본 설정&lt;/h3&gt;

&lt;p&gt;Next.js 프로젝트를 시작하려면 &lt;code&gt;create-next-app&lt;/code&gt; 패키지를 사용하면 됩니다. 이 패키지는 Next.js 프로젝트의 기본 구조와 설정을 자동으로 생성해 줍니다.&lt;/p&gt;

&lt;pre&gt;
&lt;code&gt;
npx create-next-app@latest my-next-app
cd my-next-app
npm run dev
&lt;/code&gt;
&lt;/pre&gt;

&lt;p&gt;위 명령어를 실행하면 Next.js 개발 서버가 &lt;code&gt;http://localhost:3000&lt;/code&gt;에서 실행됩니다. 기본 설정을 통해 Next.js 프로젝트가 바로 실행 가능하며, &lt;code&gt;pages&lt;/code&gt; 폴더 안에 파일을 생성하면 자동으로 라우트가 설정됩니다.&lt;/p&gt;

&lt;h3&gt;3. 페이지 라우팅&lt;/h3&gt;

&lt;p&gt;Next.js에서는 &lt;code&gt;pages&lt;/code&gt; 폴더 내에 파일을 추가하면 자동으로 라우트가 설정됩니다. 예를 들어, &lt;code&gt;pages/about.js&lt;/code&gt; 파일을 만들면 &lt;code&gt;/about&lt;/code&gt; URL로 접근할 수 있습니다. 또한, &lt;code&gt;pages&lt;/code&gt; 폴더 내의 파일 이름을 통해 동적 라우팅도 구현할 수 있습니다.&lt;/p&gt;

&lt;pre&gt;
&lt;code&gt;
// pages/[id].js
import { useRouter } from 'next/router';

function Post() {
  const router = useRouter();
  const { id } = router.query;

  return &amp;lt;div&amp;gt;Post ID: {id}&amp;lt;/div&amp;gt;;
}

export default Post;
&lt;/code&gt;
&lt;/pre&gt;

&lt;p&gt;위 코드에서 &lt;code&gt;[id].js&lt;/code&gt; 파일을 만들면 &lt;code&gt;/post/1&lt;/code&gt;, &lt;code&gt;/post/2&lt;/code&gt;와 같은 동적 라우트를 설정할 수 있습니다.&lt;/p&gt;

&lt;h3&gt;4. 서버 사이드 렌더링과 정적 사이트 생성&lt;/h3&gt;

&lt;p&gt;Next.js는 서버 사이드 렌더링과 정적 사이트 생성을 지원합니다. &lt;code&gt;getServerSideProps&lt;/code&gt; 함수를 사용하여 서버에서 데이터를 받아올 수 있고, &lt;code&gt;getStaticProps&lt;/code&gt;를 사용해 빌드 시점에 데이터를 미리 가져올 수 있습니다.&lt;/p&gt;

&lt;pre&gt;
&lt;code&gt;
// getServerSideProps 예시
export async function getServerSideProps() {
  const res = await fetch('https://jsonplaceholder.typicode.com/posts');
  const posts = await res.json();

  return { props: { posts } };
}

function Blog({ posts }) {
  return (
    &amp;lt;div&amp;gt;
      &amp;lt;h1&amp;gt;블로그 글 목록&amp;lt;/h1&amp;gt;
      {posts.map(post =&gt; (
        &amp;lt;p key={post.id}&amp;gt;{post.title}&amp;lt;/p&amp;gt;
      ))}
    &amp;lt;/div&amp;gt;
  );
}

export default Blog;
&lt;/code&gt;
&lt;/pre&gt;

&lt;p&gt;위 코드에서 &lt;code&gt;getServerSideProps&lt;/code&gt;는 페이지 요청 시마다 서버에서 데이터를 가져오고, 컴포넌트에 props로 전달합니다. 이를 통해 동적 데이터를 페이지에 렌더링할 수 있습니다.&lt;/p&gt;

&lt;h3&gt;5. API 라우트&lt;/h3&gt;

&lt;p&gt;Next.js에서는 API 엔드포인트를 쉽게 만들 수 있습니다. &lt;code&gt;pages/api&lt;/code&gt; 폴더에 파일을 추가하면 서버리스 함수로 작동하는 API 엔드포인트가 생성됩니다.&lt;/p&gt;

&lt;pre&gt;
&lt;code&gt;
// pages/api/hello.js
export default function handler(req, res) {
  res.status(200).json({ message: 'Hello, Next.js API!' });
}
&lt;/code&gt;
&lt;/pre&gt;

&lt;p&gt;위 예제는 &lt;code&gt;/api/hello&lt;/code&gt; 엔드포인트에서 &quot;Hello, Next.js API!&quot;라는 메시지를 반환하는 간단한 API입니다. Next.js API 라우트를 사용하면 클라이언트와 서버 간의 데이터 통신이 간편해집니다.&lt;/p&gt;

&lt;h3&gt;6. 이미지 최적화&lt;/h3&gt;

&lt;p&gt;Next.js는 &lt;code&gt;next/image&lt;/code&gt; 컴포넌트를 통해 이미지 최적화를 지원합니다. 이 컴포넌트를 사용하면 자동으로 이미지 크기를 조정하고, 웹에서 최적화된 형식으로 제공합니다.&lt;/p&gt;

&lt;pre&gt;
&lt;code&gt;
import Image from 'next/image';

function HomePage() {
  return (
    &amp;lt;div&amp;gt;
      &amp;lt;h1&amp;gt;Next.js 이미지 최적화&amp;lt;/h1&amp;gt;
      &amp;lt;Image src=&quot;/example.jpg&quot; width={500} height={300} alt=&quot;Example image&quot; /&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}

export default HomePage;
&lt;/code&gt;
&lt;/pre&gt;

&lt;p&gt;위 코드에서 &lt;code&gt;next/image&lt;/code&gt; 컴포넌트를 사용하여 이미지를 로드하고 최적화된 형식으로 표시합니다. 이는 페이지 로딩 속도를 높이고, 사용자의 데이터를 절약하는 데 도움이 됩니다.&lt;/p&gt;

&lt;h3&gt;마치며&lt;/h3&gt;

&lt;p&gt;Next.js는 서버 사이드 렌더링, 정적 사이트 생성, 자동 라우팅, API 라우트 등 다양한 기능을 제공하여 React 개발자에게 매우 유용한 프레임워크입니다. 이러한 기능들을 활용하면 성능과 SEO에 최적화된 웹 애플리케이션을 쉽게 만들 수 있습니다. Next.js를 통해 빠르고 효율적인 웹 개발을 경험해 보세요.&lt;/p&gt;</description>
      <author>ghkdtprhf5</author>
      <guid isPermaLink="true">https://ghkdtprhf5.tistory.com/14</guid>
      <comments>https://ghkdtprhf5.tistory.com/14#entry14comment</comments>
      <pubDate>Fri, 8 Nov 2024 21:30:18 +0900</pubDate>
    </item>
    <item>
      <title>웹 접근성 향상하기: 시각적 장애인을 위한 필수 고려사항</title>
      <link>https://ghkdtprhf5.tistory.com/13</link>
      <description>&lt;h2&gt;웹 접근성 향상하기: 시각적 장애인을 위한 필수 고려사항&lt;/h2&gt;

&lt;p&gt;모든 사용자가 불편함 없이 웹 사이트를 이용할 수 있도록 만드는 것은 현대 웹 개발에서 중요한 과제입니다. 특히 시각적 장애인을 위해 접근성을 고려한 웹 사이트는 더 나은 사용자 경험을 제공할 수 있습니다. 이번 글에서는 시각적 장애인을 위한 웹 접근성을 높이는 &lt;strong&gt;5가지 필수 고려사항&lt;/strong&gt;을 소개합니다.&lt;/p&gt;

&lt;h3&gt;1. 대체 텍스트(Alt Text) 제공&lt;/h3&gt;

&lt;p&gt;이미지에 대체 텍스트(alt)를 제공하는 것은 시각적 장애인이 화면 낭독기를 통해 이미지의 내용을 이해할 수 있도록 돕습니다. &lt;code&gt;alt&lt;/code&gt; 속성에 이미지의 내용을 간략하고 명확하게 설명하면 좋습니다.&lt;/p&gt;

&lt;pre&gt;
&lt;code&gt;
&amp;lt;img src=&quot;flower.jpg&quot; alt=&quot;밝은 노란색과 흰색의 꽃이 핀 봄의 정원&quot; /&amp;gt;
&lt;/code&gt;
&lt;/pre&gt;

&lt;p&gt;위 예시에서 &lt;code&gt;alt&lt;/code&gt; 속성은 꽃 이미지의 내용을 설명하여 시각적 장애인이 이미지의 의미를 파악할 수 있도록 돕습니다. 대체 텍스트는 단순히 &quot;꽃&quot;이라고만 적지 말고, 가능하면 이미지의 구체적인 의미를 전달하는 것이 좋습니다.&lt;/p&gt;

&lt;h3&gt;2. 명확한 헤딩 구조 사용&lt;/h3&gt;

&lt;p&gt;화면 낭독기는 페이지의 구조를 파악하기 위해 헤딩 태그(&lt;code&gt;h1&lt;/code&gt;, &lt;code&gt;h2&lt;/code&gt;, &lt;code&gt;h3&lt;/code&gt; 등)를 사용합니다. 논리적인 헤딩 구조는 시각적 장애인이 페이지의 흐름을 이해하는 데 도움을 줍니다.&lt;/p&gt;

&lt;pre&gt;
&lt;code&gt;
&amp;lt;h1&amp;gt;웹 접근성의 중요성&amp;lt;/h1&amp;gt;
&amp;lt;h2&amp;gt;1. 시각적 장애인을 위한 접근성 고려사항&amp;lt;/h2&amp;gt;
&amp;lt;h2&amp;gt;2. 청각적 장애인을 위한 접근성 고려사항&amp;lt;/h2&amp;gt;
&lt;/code&gt;
&lt;/pre&gt;

&lt;p&gt;헤딩 태그를 순서에 맞게 사용하면 화면 낭독기를 사용하는 사용자가 웹 페이지의 흐름을 쉽게 파악할 수 있습니다. &lt;code&gt;h1&lt;/code&gt; 태그는 페이지의 주요 제목에만 사용하고, &lt;code&gt;h2&lt;/code&gt;, &lt;code&gt;h3&lt;/code&gt;는 하위 제목에 사용합니다.&lt;/p&gt;

&lt;h3&gt;3. 색상 대비&lt;/h3&gt;

&lt;p&gt;시각적 장애가 있는 사용자는 저시력이나 색맹일 수 있으므로, 텍스트와 배경의 색상 대비가 충분히 크도록 설정하는 것이 중요합니다. 일반적으로 텍스트와 배경 색상 간의 대비 비율이 최소 &lt;strong&gt;4.5:1&lt;/strong&gt; 이상이 되도록 합니다.&lt;/p&gt;

&lt;pre&gt;
&lt;code&gt;
body {
  color: #333;
  background-color: #f4f4f4;
}
&lt;/code&gt;
&lt;/pre&gt;

&lt;p&gt;위 스타일에서는 텍스트 색상과 배경 색상이 잘 구분되도록 설정했습니다. 웹 접근성을 확인할 때는 &lt;a href=&quot;https://webaim.org/resources/contrastchecker/&quot;&gt;WebAIM의 색상 대비 검사기&lt;/a&gt;와 같은 도구를 활용할 수 있습니다.&lt;/p&gt;

&lt;h3&gt;4. 키보드 네비게이션 지원&lt;/h3&gt;

&lt;p&gt;시각적 장애인은 마우스를 사용하지 않고 키보드만으로 사이트를 탐색할 수 있어야 합니다. &lt;code&gt;Tab&lt;/code&gt; 키를 사용해 주요 요소로 이동할 수 있도록 설정하고, 포커스 스타일을 지정하여 사용자가 현재 선택한 위치를 쉽게 파악할 수 있도록 돕습니다.&lt;/p&gt;

&lt;pre&gt;
&lt;code&gt;
button:focus, a:focus {
  outline: 2px solid #005fcc;
}
&lt;/code&gt;
&lt;/pre&gt;

&lt;p&gt;위 코드에서는 포커스된 버튼이나 링크에 파란색 윤곽선을 추가하여 키보드 네비게이션을 하는 사용자가 쉽게 현재 위치를 인식할 수 있도록 했습니다.&lt;/p&gt;

&lt;h3&gt;5. 의미 있는 링크 텍스트 사용&lt;/h3&gt;

&lt;p&gt;화면 낭독기는 링크 텍스트를 읽어 사용자에게 링크의 목적을 설명합니다. &quot;여기를 클릭&quot;과 같은 일반적인 표현보다는 링크의 목적을 명확하게 나타내는 텍스트를 사용하는 것이 좋습니다.&lt;/p&gt;

&lt;pre&gt;
&lt;code&gt;
&amp;lt;a href=&quot;https://example.com/accessibility&quot; &amp;gt;웹 접근성 향상 방법에 대해 자세히 알아보기&amp;lt;/a&amp;gt;
&lt;/code&gt;
&lt;/pre&gt;

&lt;p&gt;위 예제에서는 &quot;웹 접근성 향상 방법에 대해 자세히 알아보기&quot;라는 구체적인 링크 텍스트를 사용하여 사용자가 링크를 통해 어떤 정보를 얻을 수 있는지 명확하게 알 수 있도록 했습니다.&lt;/p&gt;

&lt;h3&gt;추가 팁: 웹 접근성 검사 도구 사용&lt;/h3&gt;

&lt;p&gt;웹 접근성을 쉽게 검사할 수 있는 도구들이 많이 있습니다. 아래 도구를 사용하면 웹 페이지의 접근성을 빠르게 분석하고 개선할 수 있습니다.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://wave.webaim.org/&quot;&gt;WAVE 웹 접근성 평가 도구&lt;/a&gt;: 웹 페이지의 접근성을 분석하고 문제점을 시각적으로 표시해줍니다.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://chrome.google.com/webstore/detail/axe/lhdoppojpmngadmnindnejefpokejbdd&quot;&gt;Axe DevTools&lt;/a&gt;: Chrome 확장 프로그램으로, 웹 페이지의 접근성 문제를 검사합니다.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://web.dev/measure/&quot;&gt;Lighthouse&lt;/a&gt;: Google에서 제공하는 웹 성능과 접근성 분석 도구로, 웹사이트의 성능과 접근성을 함께 평가할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;마치며&lt;/h3&gt;

&lt;p&gt;웹 접근성을 고려한 사이트는 모든 사용자가 편리하게 이용할 수 있으며, 특히 시각적 장애인을 위한 배려는 더 나은 사용자 경험을 제공합니다. 웹 접근성을 개선하려면 대체 텍스트 제공, 명확한 헤딩 구조, 색상 대비, 키보드 네비게이션, 의미 있는 링크 텍스트와 같은 요소를 적절히 활용해야 합니다. 이러한 접근성 고려 사항을 반영하여 더 많은 사용자가 웹 사이트를 편리하게 사용할 수 있도록 해보세요.&lt;/p&gt;</description>
      <author>ghkdtprhf5</author>
      <guid isPermaLink="true">https://ghkdtprhf5.tistory.com/13</guid>
      <comments>https://ghkdtprhf5.tistory.com/13#entry13comment</comments>
      <pubDate>Fri, 8 Nov 2024 21:28:24 +0900</pubDate>
    </item>
    <item>
      <title>React 컴포넌트 최적화: 메모이제이션과 성능 향상 기법</title>
      <link>https://ghkdtprhf5.tistory.com/12</link>
      <description>&lt;h2&gt;React 컴포넌트 최적화: 메모이제이션과 성능 향상 기법&lt;/h2&gt;

&lt;p&gt;React로 웹 애플리케이션을 개발할 때, 컴포넌트의 성능을 최적화하는 것은 매우 중요합니다. 특히 대규모 애플리케이션에서는 불필요한 렌더링을 줄이고, 필요한 부분만 다시 렌더링하도록 최적화하는 것이 필수적입니다. 이번 글에서는 &lt;strong&gt;React 컴포넌트 최적화&lt;/strong&gt;를 위해 사용할 수 있는 대표적인 기법인 &lt;strong&gt;메모이제이션&lt;/strong&gt;과 성능 향상 도구들을 소개합니다.&lt;/p&gt;

&lt;h3&gt;1. React.memo&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;React.memo&lt;/code&gt;는 함수형 컴포넌트의 불필요한 렌더링을 방지하기 위해 사용하는 고차 컴포넌트(HOC)입니다. 부모 컴포넌트가 렌더링될 때 자식 컴포넌트가 변경된 props를 받지 않는다면, &lt;code&gt;React.memo&lt;/code&gt;는 이전의 렌더링 결과를 재사용하여 성능을 최적화합니다.&lt;/p&gt;

&lt;pre&gt;
&lt;code&gt;
// React.memo 사용 예시
import React from 'react';

const ChildComponent = React.memo(({ count }) =&gt; {
  console.log('ChildComponent 렌더링');
  return &lt;p&gt;Count: {count}&lt;/p&gt;;
});

function ParentComponent() {
  const [count, setCount] = React.useState(0);

  return (
    &lt;div&gt;
      &lt;button onClick={() =&gt; setCount(count + 1)}&gt;증가&lt;/button&gt;
      &lt;ChildComponent count={count} /&gt;
    &lt;/div&gt;
  );
}

export default ParentComponent;
&lt;/code&gt;
&lt;/pre&gt;

&lt;p&gt;위 코드에서 &lt;code&gt;React.memo&lt;/code&gt;를 사용하여 &lt;code&gt;ChildComponent&lt;/code&gt;가 props가 변경되지 않으면 다시 렌더링되지 않도록 설정했습니다. 이를 통해 불필요한 렌더링을 방지할 수 있습니다.&lt;/p&gt;

&lt;h3&gt;2. useCallback&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;useCallback&lt;/code&gt;은 컴포넌트가 다시 렌더링될 때마다 동일한 콜백 함수를 재생성하지 않도록 하는 메모이제이션 훅입니다. 함수가 자주 재생성되면 성능 저하가 발생할 수 있는데, &lt;code&gt;useCallback&lt;/code&gt;을 사용하면 이를 방지할 수 있습니다.&lt;/p&gt;

&lt;pre&gt;
&lt;code&gt;
// useCallback 사용 예시
import React, { useState, useCallback } from 'react';

function ParentComponent() {
  const [count, setCount] = useState(0);
  const handleIncrement = useCallback(() =&gt; {
    setCount(prevCount =&gt; prevCount + 1);
  }, []);

  return (
    &lt;div&gt;
      &lt;p&gt;Count: {count}&lt;/p&gt;
      &lt;button onClick={handleIncrement}&gt;증가&lt;/button&gt;
    &lt;/div&gt;
  );
}

export default ParentComponent;
&lt;/code&gt;
&lt;/pre&gt;

&lt;p&gt;위 코드에서 &lt;code&gt;handleIncrement&lt;/code&gt; 함수는 &lt;code&gt;useCallback&lt;/code&gt;을 사용해 메모이제이션되었습니다. 이렇게 하면 &lt;code&gt;ParentComponent&lt;/code&gt;가 다시 렌더링되어도 같은 함수가 재사용되어 성능이 향상됩니다.&lt;/p&gt;

&lt;h3&gt;3. useMemo&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;useMemo&lt;/code&gt;는 특정 계산 결과를 메모이제이션하여 성능을 최적화하는 훅입니다. 복잡한 계산 로직이 있는 경우, 해당 로직을 &lt;code&gt;useMemo&lt;/code&gt;로 감싸서 컴포넌트가 다시 렌더링될 때 불필요한 계산을 방지할 수 있습니다.&lt;/p&gt;

&lt;pre&gt;
&lt;code&gt;
// useMemo 사용 예시
import React, { useState, useMemo } from 'react';

function ExpensiveComponent({ number }) {
  const expensiveCalculation = useMemo(() =&gt; {
    console.log('복잡한 계산 수행 중...');
    return number ** 2;
  }, [number]);

  return &lt;p&gt;Result: {expensiveCalculation}&lt;/p&gt;;
}

export default ExpensiveComponent;
&lt;/code&gt;
&lt;/pre&gt;

&lt;p&gt;위 코드에서 &lt;code&gt;expensiveCalculation&lt;/code&gt;은 &lt;code&gt;useMemo&lt;/code&gt;를 통해 &lt;code&gt;number&lt;/code&gt;가 변경될 때만 계산됩니다. 이를 통해 불필요한 계산을 방지하여 성능을 최적화할 수 있습니다.&lt;/p&gt;

&lt;h3&gt;4. React의 key 속성&lt;/h3&gt;

&lt;p&gt;React에서는 리스트를 렌더링할 때 &lt;code&gt;key&lt;/code&gt; 속성을 사용하는 것이 중요합니다. &lt;code&gt;key&lt;/code&gt; 속성은 각 요소를 고유하게 식별하며, React가 요소의 추가, 삭제, 변경을 효율적으로 관리할 수 있게 합니다.&lt;/p&gt;

&lt;pre&gt;
&lt;code&gt;
// key 속성 예시
function ListComponent() {
  const items = ['Apple', 'Banana', 'Cherry'];

  return (
    &lt;ul&gt;
      {items.map((item, index) =&gt; (
        &lt;li key={index}&gt;{item}&lt;/li&gt;
      ))}
    &lt;/ul&gt;
  );
}
&lt;/code&gt;
&lt;/pre&gt;

&lt;p&gt;위 코드에서 &lt;code&gt;index&lt;/code&gt;를 &lt;code&gt;key&lt;/code&gt;로 설정해 리스트의 각 요소를 고유하게 식별하도록 했습니다. React는 &lt;code&gt;key&lt;/code&gt; 속성을 통해 요소 변화를 추적하고, 효율적으로 리스트를 관리할 수 있습니다.&lt;/p&gt;

&lt;h3&gt;5. Lazy Loading과 Suspense&lt;/h3&gt;

&lt;p&gt;React의 &lt;code&gt;React.lazy&lt;/code&gt;와 &lt;code&gt;Suspense&lt;/code&gt;를 사용하면, 필요한 컴포넌트를 지연 로딩하여 초기 로딩 속도를 최적화할 수 있습니다. 대규모 애플리케이션에서는 초기 로딩 시간을 줄이고, 필요한 컴포넌트만 로딩하여 성능을 높이는 것이 중요합니다.&lt;/p&gt;

&lt;pre&gt;
&lt;code&gt;
// Lazy Loading과 Suspense 사용 예시
import React, { Suspense } from 'react';

const LazyComponent = React.lazy(() =&gt; import('./LazyComponent'));

function App() {
  return (
    &lt;div&gt;
      &lt;Suspense fallback={&lt;div&gt;Loading...&lt;/div&gt;}&gt;
        &lt;LazyComponent /&gt;
      &lt;/Suspense&gt;
    &lt;/div&gt;
  );
}

export default App;
&lt;/code&gt;
&lt;/pre&gt;

&lt;p&gt;위 코드에서 &lt;code&gt;LazyComponent&lt;/code&gt;는 &lt;code&gt;React.lazy&lt;/code&gt;로 로드되고, 로딩 중에는 &lt;code&gt;Suspense&lt;/code&gt;의 &lt;code&gt;fallback&lt;/code&gt;을 통해 대체 콘텐츠가 표시됩니다. 이를 통해 초기 로딩 시간을 단축할 수 있습니다.&lt;/p&gt;

&lt;h3&gt;마치며&lt;/h3&gt;

&lt;p&gt;React에서 성능을 최적화하는 다양한 기법을 통해 컴포넌트의 렌더링을 효율적으로 관리할 수 있습니다. &lt;code&gt;React.memo&lt;/code&gt;, &lt;code&gt;useCallback&lt;/code&gt;, &lt;code&gt;useMemo&lt;/code&gt;, &lt;code&gt;key&lt;/code&gt; 속성, 그리고 &lt;code&gt;Lazy Loading&lt;/code&gt;과 &lt;code&gt;Suspense&lt;/code&gt;를 적절히 활용하여 최적화된 애플리케이션을 개발해 보세요. 이번 글이 React 성능 최적화에 대한 이해를 돕는 데 도움이 되었기를 바랍니다.&lt;/p&gt;</description>
      <author>ghkdtprhf5</author>
      <guid isPermaLink="true">https://ghkdtprhf5.tistory.com/12</guid>
      <comments>https://ghkdtprhf5.tistory.com/12#entry12comment</comments>
      <pubDate>Fri, 8 Nov 2024 21:25:47 +0900</pubDate>
    </item>
    <item>
      <title>JavaScript 함수형 프로그래밍의 이해: 순수 함수, 고차 함수, 그리고 불변성</title>
      <link>https://ghkdtprhf5.tistory.com/11</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;JavaScript는 객체 지향 프로그래밍과 함수형 프로그래밍을 모두 지원하는 언어로, 다양한 스타일의 코딩이 가능합니다. 특히 함수형 프로그래밍은 코드의 가독성을 높이고, 예측 가능한 동작을 만들어 내는 데 유용합니다. 이번 글에서는 함수형 프로그래밍의 기본 개념인 &lt;b&gt;순수 함수(Pure Function)&lt;/b&gt;, &lt;b&gt;고차 함수(Higher-Order Function)&lt;/b&gt;, 그리고 **불변성(Immutability)**에 대해 알아보겠습니다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;1. 함수형 프로그래밍이란?&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;함수형 프로그래밍은 상태와 부수 효과를 줄이고, 데이터 처리 과정을 함수로만 이루어지게 하여 코드를 작성하는 스타일입니다. 함수형 프로그래밍을 통해 코드의 예측 가능성을 높이고, 모듈화를 쉽게 할 수 있습니다. 이 방식은 특히 복잡한 애플리케이션이나 대규모 데이터 처리가 필요한 환경에서 유용합니다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;2. 순수 함수(Pure Function)&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;순수 함수는 함수형 프로그래밍의 핵심 개념 중 하나로, 같은 입력이 주어지면 항상 같은 출력을 반환하는 함수를 의미합니다. 순수 함수는 외부 상태를 변경하지 않으며, 부수 효과가 없습니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1731068510276&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 순수 함수의 예시
function add(a, b) {
  return a + b;
}

console.log(add(2, 3)); // 항상 5를 반환&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 add 함수는 주어진 두 숫자를 더한 결과를 반환하며, 외부 상태나 전역 변수를 변경하지 않습니다. 이러한 순수 함수는 예측 가능성이 높고, 테스트가 용이합니다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;순수 함수가 아닌 예시&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1731068534517&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;let count = 0;

function increment() {
  count++;
  return count;
}

console.log(increment()); // 호출할 때마다 다른 결과 반환&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 예제의 increment 함수는 외부 변수 count를 변경하므로 순수 함수가 아닙니다. 이처럼 외부 상태를 변경하는 함수는 부수 효과가 발생할 가능성이 있어 예측 가능성이 떨어집니다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;3. 고차 함수(Higher-Order Function)&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;고차 함수는 다른 함수를 인자로 받거나, 함수를 반환하는 함수를 의미합니다. 고차 함수는 JavaScript에서 자주 사용되는 중요한 개념으로, 특히 배열과 같은 데이터 구조를 다룰 때 유용합니다.&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;map()&lt;/b&gt;: 배열의 각 요소에 함수를 적용하여 새로운 배열을 반환합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;filter()&lt;/b&gt;: 배열의 각 요소에 함수를 적용하여 조건에 맞는 요소만을 추출합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;reduce()&lt;/b&gt;: 배열을 순회하며 누적된 결과를 하나의 값으로 반환합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1731068551865&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// map()을 사용한 예시
const numbers = [1, 2, 3, 4, 5];
const doubled = numbers.map(num =&amp;gt; num * 2);

console.log(doubled); // [2, 4, 6, 8, 10]

// filter()를 사용한 예시
const evenNumbers = numbers.filter(num =&amp;gt; num % 2 === 0);

console.log(evenNumbers); // [2, 4]

// reduce()를 사용한 예시
const sum = numbers.reduce((total, num) =&amp;gt; total + num, 0);

console.log(sum); // 15&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;고차 함수를 사용하면 데이터를 간결하고 직관적으로 처리할 수 있습니다. 특히 배열이나 리스트와 같은 반복적인 데이터 처리 작업을 고차 함수를 통해 쉽게 구현할 수 있습니다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;4. 불변성(Immutability)&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;불변성은 객체나 배열과 같은 데이터 구조를 변경하지 않고, 항상 새로운 값을 생성하는 것을 의미합니다. JavaScript에서는 기본 데이터 타입(String, Number 등)은 불변성을 가지지만, 배열이나 객체는 기본적으로 가변적입니다. 함수형 프로그래밍에서는 불변성을 유지하기 위해 새로운 값을 반환하고, 기존 값을 변경하지 않도록 합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1731068562832&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const numbers = [1, 2, 3, 4];

// 새로운 배열을 생성하여 변경
const newNumbers = [...numbers, 5];

console.log(numbers); // [1, 2, 3, 4] - 원본 배열은 그대로 유지
console.log(newNumbers); // [1, 2, 3, 4, 5]&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 예제에서 newNumbers는 원본 배열 numbers를 변경하지 않고 새로운 배열을 생성합니다. 이처럼 불변성을 유지하면 데이터가 예상치 못하게 변경되는 문제를 방지할 수 있어, 코드의 안정성과 유지보수성이 높아집니다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;5. 함수형 프로그래밍의 장점과 단점&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;장점단점&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;예측 가능성과 테스트 용이성 증가&lt;/td&gt;
&lt;td&gt;복잡한 로직에서는 가독성 저하 가능&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;코드 재사용성과 모듈화 용이&lt;/td&gt;
&lt;td&gt;JavaScript에서 함수형 패러다임에 익숙해지기 어려움&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;부수 효과 감소로 인한 안정성 증가&lt;/td&gt;
&lt;td&gt;불변성을 유지하기 위한 메모리 사용 증가&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;함수형 프로그래밍을 통해 코드를 간결하게 유지하고 예측 가능성을 높일 수 있지만, 모든 상황에 적합한 것은 아닙니다. 함수형 프로그래밍의 장점과 단점을 이해하고, 프로젝트의 요구 사항에 따라 적절히 활용하는 것이 중요합니다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;6. 함수형 프로그래밍의 실제 사용 예&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;div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1731068572868&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const products = [
  { name: &quot;Laptop&quot;, price: 1000 },
  { name: &quot;Phone&quot;, price: 500 },
  { name: &quot;Tablet&quot;, price: 700 },
];

const affordableProducts = products
  .filter(product =&amp;gt; product.price &amp;lt; 800)
  .map(product =&amp;gt; product.name);

console.log(affordableProducts); // ['Phone', 'Tablet']&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 예제에서는 filter와 map을 조합하여 가격이 800 이하인 제품들의 이름만 추출했습니다. 고차 함수의 활용으로 간결하고 직관적인 코드를 작성할 수 있습니다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;마치며&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;함수형 프로그래밍은 JavaScript 개발에서 가독성과 유지보수성을 높이는 데 매우 유용한 패러다임입니다. 순수 함수, 고차 함수, 불변성을 이해하고 적용하면 더 효율적이고 예측 가능한 코드를 작성할 수 있습니다. 함수형 프로그래밍은 처음에는 다소 생소할 수 있지만, 반복적으로 사용하다 보면 큰 장점을 느낄 수 있을 것입니다. 이번 글이 함수형 프로그래밍에 대한 이해를 높이는 데 도움이 되었기를 바랍니다.&lt;/p&gt;</description>
      <author>ghkdtprhf5</author>
      <guid isPermaLink="true">https://ghkdtprhf5.tistory.com/11</guid>
      <comments>https://ghkdtprhf5.tistory.com/11#entry11comment</comments>
      <pubDate>Fri, 8 Nov 2024 21:22:57 +0900</pubDate>
    </item>
    <item>
      <title>CSS Flexbox와 Grid 완벽 가이드: 레이아웃을 쉽게 구성하는 방법</title>
      <link>https://ghkdtprhf5.tistory.com/10</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;웹 페이지를 만들 때 레이아웃은 가장 중요한 요소 중 하나입니다. CSS에서는 레이아웃을 쉽게 구성할 수 있도록 Flexbox와 Grid라는 강력한 도구를 제공합니다. 이 두 가지 도구는 각각의 특징을 가지고 있으며, 적절히 활용하면 효율적으로 페이지 레이아웃을 구성할 수 있습니다. 이번 글에서는 &lt;b&gt;Flexbox와 Grid의 기본 개념과 차이점&lt;/b&gt;을 소개하고, 사용 예제와 함께 실전에서 어떻게 활용할 수 있는지 설명하겠습니다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;1. Flexbox의 기본 개념&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Flexbox는 &lt;b&gt;1차원 레이아웃&lt;/b&gt;을 다루는 데 유용한 CSS 레이아웃 도구입니다. 즉, 한 줄의 수평 또는 수직 방향으로 요소를 배치할 때 매우 효과적입니다. Flexbox는 부모 요소에 display: flex 속성을 적용하여 자식 요소가 유연하게 공간을 차지할 수 있도록 합니다.&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;: Flexbox에서는 flex-direction 속성을 사용하여 요소가 배치되는 방향을 설정합니다. 기본적으로 주축은 수평이며, 교차축은 수직입니다. row, row-reverse, column, column-reverse와 같은 값을 통해 주축을 설정할 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;정렬 속성&lt;/b&gt;: justify-content와 align-items를 사용하여 요소를 주축과 교차축에 따라 정렬할 수 있습니다. 예를 들어, justify-content: center를 사용하면 요소가 주축의 중앙에 배치됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1730977916508&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;.container {
  display: flex;
  flex-direction: row;
  justify-content: center;
  align-items: center;
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;2. Flexbox를 활용한 레이아웃 예제&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음 예제는 3개의 박스를 Flexbox를 사용하여 가로로 배치하고, 중앙에 정렬하는 방법을 보여줍니다.&lt;/p&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1730977930531&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;div class=&quot;container&quot;&amp;gt;
  &amp;lt;div class=&quot;box&quot;&amp;gt;Box 1&amp;lt;/div&amp;gt;
  &amp;lt;div class=&quot;box&quot;&amp;gt;Box 2&amp;lt;/div&amp;gt;
  &amp;lt;div class=&quot;box&quot;&amp;gt;Box 3&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;pre id=&quot;code_1730977938560&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;.container {
  display: flex;
  justify-content: center;
  align-items: center;
}

.box {
  width: 100px;
  height: 100px;
  background-color: #f0f0f0;
  margin: 10px;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 코드에서는 display: flex와 justify-content: center를 사용하여 박스들이 가로로 중앙에 배치되도록 했습니다. Flexbox는 주로 수평 또는 수직 정렬에 최적화되어 있어, 상단 내비게이션 바나 카드 레이아웃 같은 단순한 레이아웃에 적합합니다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;3. Grid의 기본 개념&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CSS Grid는 &lt;b&gt;2차원 레이아웃&lt;/b&gt;을 위한 도구로, 행과 열을 동시에 관리할 수 있습니다. Grid는 Flexbox보다 복잡하지만, 그만큼 다양한 레이아웃을 유연하게 구성할 수 있습니다. display: grid 속성을 사용해 Grid 컨테이너를 정의한 다음, grid-template-columns와 grid-template-rows를 통해 행과 열의 크기를 지정합니다.&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;: grid-template-columns와 grid-template-rows를 사용하여 Grid의 행과 열 크기를 설정할 수 있습니다. repeat 함수와 fr 단위를 사용하면 요소의 크기를 쉽게 조정할 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;그리드 아이템 배치&lt;/b&gt;: Grid에서는 각 아이템의 위치를 grid-column과 grid-row 속성을 사용해 지정할 수 있습니다. 이를 통해 특정 아이템을 원하는 위치에 배치할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1730977952395&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;.container {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 10px;
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;4. Grid를 활용한 레이아웃 예제&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음 예제는 3x3 그리드 레이아웃을 만드는 코드입니다.&lt;/p&gt;
&lt;pre id=&quot;code_1730977965501&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;div class=&quot;container&quot;&amp;gt;
  &amp;lt;div class=&quot;box&quot;&amp;gt;Box 1&amp;lt;/div&amp;gt;
  &amp;lt;div class=&quot;box&quot;&amp;gt;Box 2&amp;lt;/div&amp;gt;
  &amp;lt;div class=&quot;box&quot;&amp;gt;Box 3&amp;lt;/div&amp;gt;
  &amp;lt;div class=&quot;box&quot;&amp;gt;Box 4&amp;lt;/div&amp;gt;
  &amp;lt;div class=&quot;box&quot;&amp;gt;Box 5&amp;lt;/div&amp;gt;
  &amp;lt;div class=&quot;box&quot;&amp;gt;Box 6&amp;lt;/div&amp;gt;
  &amp;lt;div class=&quot;box&quot;&amp;gt;Box 7&amp;lt;/div&amp;gt;
  &amp;lt;div class=&quot;box&quot;&amp;gt;Box 8&amp;lt;/div&amp;gt;
  &amp;lt;div class=&quot;box&quot;&amp;gt;Box 9&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;pre id=&quot;code_1730977974467&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;.container {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 10px;
}

.box {
  background-color: #e0e0e0;
  height: 100px;
  display: flex;
  justify-content: center;
  align-items: center;
}&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;5. Flexbox와 Grid의 차이점&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;속성FlexboxGrid&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;레이아웃&lt;/td&gt;
&lt;td&gt;1차원 레이아웃 (수평/수직)&lt;/td&gt;
&lt;td&gt;2차원 레이아웃 (행과 열)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;주된 목적&lt;/td&gt;
&lt;td&gt;요소 정렬 및 단순 레이아웃&lt;/td&gt;
&lt;td&gt;복잡한 레이아웃 구성&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;사용 용도&lt;/td&gt;
&lt;td&gt;네비게이션, 버튼 그룹, 카드&lt;/td&gt;
&lt;td&gt;페이지 레이아웃, 대시보드&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Flexbox는 주로 &lt;b&gt;단순한 1차원 레이아웃&lt;/b&gt;에 유리하며, Grid는 &lt;b&gt;2차원 레이아웃&lt;/b&gt;을 구성하는 데 유리합니다. 프로젝트의 요구 사항에 따라 이 두 가지를 적절히 혼합하여 사용할 수 있습니다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;6. Flexbox와 Grid를 함께 사용하기&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Flexbox와 Grid는 동시에 사용할 수 있으며, 각 도구의 장점을 살려 혼합하여 사용하는 것이 좋습니다. 예를 들어, 페이지의 전체 레이아웃은 Grid를 사용하고, 세부 구성 요소에는 Flexbox를 사용하면 효율적인 레이아웃을 구성할 수 있습니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;html&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&lt;span data-state=&quot;closed&quot;&gt;코드 복사&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&lt;span&gt;&amp;lt;&lt;span&gt;div&lt;/span&gt; &lt;span&gt;class&lt;/span&gt;=&lt;span&gt;&quot;container&quot;&lt;/span&gt;&amp;gt;&lt;/span&gt; &lt;span&gt;&amp;lt;&lt;span&gt;header&lt;/span&gt;&amp;gt;&lt;/span&gt;헤더&lt;span&gt;&amp;lt;/&lt;span&gt;header&lt;/span&gt;&amp;gt;&lt;/span&gt; &lt;span&gt;&amp;lt;&lt;span&gt;main&lt;/span&gt;&amp;gt;&lt;/span&gt; &lt;span&gt;&amp;lt;&lt;span&gt;section&lt;/span&gt; &lt;span&gt;class&lt;/span&gt;=&lt;span&gt;&quot;flex-container&quot;&lt;/span&gt;&amp;gt;&lt;/span&gt; &lt;span&gt;&amp;lt;&lt;span&gt;div&lt;/span&gt; &lt;span&gt;class&lt;/span&gt;=&lt;span&gt;&quot;item&quot;&lt;/span&gt;&amp;gt;&lt;/span&gt;아이템 1&lt;span&gt;&amp;lt;/&lt;span&gt;div&lt;/span&gt;&amp;gt;&lt;/span&gt; &lt;span&gt;&amp;lt;&lt;span&gt;div&lt;/span&gt; &lt;span&gt;class&lt;/span&gt;=&lt;span&gt;&quot;item&quot;&lt;/span&gt;&amp;gt;&lt;/span&gt;아이템 2&lt;span&gt;&amp;lt;/&lt;span&gt;div&lt;/span&gt;&amp;gt;&lt;/span&gt; &lt;span&gt;&amp;lt;&lt;span&gt;div&lt;/span&gt; &lt;span&gt;class&lt;/span&gt;=&lt;span&gt;&quot;item&quot;&lt;/span&gt;&amp;gt;&lt;/span&gt;아이템 3&lt;span&gt;&amp;lt;/&lt;span&gt;div&lt;/span&gt;&amp;gt;&lt;/span&gt; &lt;span&gt;&amp;lt;/&lt;span&gt;section&lt;/span&gt;&amp;gt;&lt;/span&gt; &lt;span&gt;&amp;lt;/&lt;span&gt;main&lt;/span&gt;&amp;gt;&lt;/span&gt; &lt;span&gt;&amp;lt;&lt;span&gt;footer&lt;/span&gt;&amp;gt;&lt;/span&gt;푸터&lt;span&gt;&amp;lt;/&lt;span&gt;footer&lt;/span&gt;&amp;gt;&lt;/span&gt; &lt;span&gt;&amp;lt;/&lt;span&gt;div&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;css&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&lt;span data-state=&quot;closed&quot;&gt;코드 복사&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&lt;span&gt;.container&lt;/span&gt; { &lt;span&gt;display&lt;/span&gt;: grid; &lt;span&gt;grid-template-rows&lt;/span&gt;: auto &lt;span&gt;1&lt;/span&gt;fr auto; &lt;span&gt;height&lt;/span&gt;: &lt;span&gt;100vh&lt;/span&gt;; } &lt;span&gt;.flex-container&lt;/span&gt; { &lt;span&gt;display&lt;/span&gt;: flex; &lt;span&gt;justify-content&lt;/span&gt;: space-between; } &lt;span&gt;.item&lt;/span&gt; { &lt;span&gt;width&lt;/span&gt;: &lt;span&gt;100px&lt;/span&gt;; &lt;span&gt;height&lt;/span&gt;: &lt;span&gt;100px&lt;/span&gt;; &lt;span&gt;background-color&lt;/span&gt;: &lt;span&gt;#ccc&lt;/span&gt;; }&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 코드에서는 container를 Grid로 전체 페이지 레이아웃을 구성하고, 내부의 flex-container는 Flexbox로 세부 아이템을 정렬했습니다. 이런 방식으로 두 레이아웃 방식을 혼합하면, 디자인 요구에 맞는 유연한 레이아웃 구성이 가능합니다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;마치며&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CSS Flexbox와 Grid는 강력하고 유연한 레이아웃 도구입니다. Flexbox는 수평 또는 수직 정렬에 최적화되어 있고, Grid는 행과 열을 활용한 복잡한 레이아웃에 적합합니다. 이 두 가지 도구를 적절히 사용하여 효율적이고 깔끔한 웹 레이아웃을 구성해 보세요. Flexbox와 Grid에 대한 이해가 높아지면 더욱 창의적이고 직관적인 웹 디자인이 가능해질 것입니다.&lt;/p&gt;</description>
      <author>ghkdtprhf5</author>
      <guid isPermaLink="true">https://ghkdtprhf5.tistory.com/10</guid>
      <comments>https://ghkdtprhf5.tistory.com/10#entry10comment</comments>
      <pubDate>Thu, 7 Nov 2024 20:12:59 +0900</pubDate>
    </item>
    <item>
      <title>웹 사이트 최적화 기본 원리: 성능을 향상시키는 5가지 방법</title>
      <link>https://ghkdtprhf5.tistory.com/9</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;웹 사이트 최적화 기본 원리: 성능을 향상시키는 5가지 방법&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자들은 빠르게 로딩되는 웹 사이트를 선호합니다. 로딩 속도가 느리면 이탈률이 높아지고, 사용자 경험이 나빠지며, 검색 엔진의 평가에도 부정적인 영향을 미칠 수 있습니다. 웹 사이트 최적화는 이런 문제를 해결하고, 사이트 성능을 개선하는 데 매우 중요합니다. 이번 글에서는 웹 사이트 성능을 향상시키기 위한 &lt;b&gt;5가지 최적화 방법&lt;/b&gt;을 소개하겠습니다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;1. 이미지 최적화&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;b&gt;이미지 포맷&lt;/b&gt;: WebP와 같은 최신 포맷은 JPEG나 PNG보다 더 작은 파일 크기를 유지하면서도 고품질 이미지를 제공할 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;이미지 크기 조절&lt;/b&gt;: 사용자가 보는 화면에 맞게 이미지 크기를 조절하고, CSS를 통해 이미지를 불필요하게 확대하지 않도록 합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;지연 로딩 (Lazy Loading)&lt;/b&gt;: 사용자가 스크롤을 내릴 때만 이미지를 로딩하도록 설정하여 초기 로딩 속도를 줄일 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;2. 코드 압축 및 최소화&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;웹 페이지의 HTML, CSS, JavaScript 파일은 필수적이지만, 파일 크기가 클수록 페이지 로딩 속도가 느려질 수 있습니다. 불필요한 공백, 주석, 줄 바꿈을 제거하고, 코드의 크기를 줄이면 성능이 향상됩니다.&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;HTML 최소화&lt;/b&gt;: 불필요한 공백과 주석을 제거해 HTML 파일 크기를 줄입니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;CSS 및 JavaScript 압축&lt;/b&gt;: cssnano, uglify-js와 같은 도구를 사용하여 CSS와 JavaScript 파일을 최소화할 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;코드 분할 (Code Splitting)&lt;/b&gt;: 페이지마다 필요한 코드만 로딩되도록 React.lazy, import()와 같은 모듈 분할 방법을 적용하면 초기 로딩 시간을 단축할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;3. 캐싱 활용&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;b&gt;브라우저 캐시 설정&lt;/b&gt;: Cache-Control과 Expires 헤더를 통해 브라우저가 정적 파일을 저장하도록 설정합니다. 이를 통해 동일한 리소스를 여러 번 로딩하지 않고 캐시에서 불러오게 할 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;콘텐츠 전송 네트워크 (CDN) 사용&lt;/b&gt;: CDN은 전 세계의 여러 서버에 데이터를 분산하여 저장해 사용자와 가장 가까운 서버에서 리소스를 제공하도록 합니다. 이를 통해 로딩 시간을 단축할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;4. 서버 최적화 및 GZIP 압축&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;b&gt;GZIP 압축&lt;/b&gt;: 웹 서버에서 GZIP 압축을 활성화하면 HTML, CSS, JavaScript 파일 크기를 크게 줄일 수 있습니다. 이를 통해 전송 속도가 빨라지고 로딩 시간이 단축됩니다.&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;h4 data-ke-size=&quot;size20&quot;&gt;5. JavaScript 비동기 로딩 및 불필요한 플러그인 제거&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JavaScript 파일은 페이지가 로딩되는 동안 서버에서 가져와 실행되는데, 이 과정에서 다른 리소스가 로딩되지 않도록 차단할 수 있습니다. 불필요한 JavaScript를 제거하고, 필요한 파일은 비동기적으로 로딩하여 로딩 속도를 최적화할 수 있습니다.&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;: &amp;lt;script&amp;gt; 태그에 async 또는 defer 속성을 추가하면 JavaScript 파일이 로딩되는 동안 다른 리소스를 동시에 로딩할 수 있어 로딩 속도가 개선됩니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;불필요한 플러그인 제거&lt;/b&gt;: 많은 JavaScript 라이브러리와 플러그인이 사이트에 사용될 수 있지만, 모든 플러그인이 필요한 것은 아닙니다. 필요한 기능을 가진 플러그인만 선택적으로 사용하여 성능을 향상시키세요.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&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;b&gt;Google PageSpeed Insights&lt;/b&gt;: 웹 사이트의 성능 점수를 확인하고, 개선할 부분에 대한 구체적인 가이드를 제공합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;GTmetrix&lt;/b&gt;: 로딩 속도, 코드 최적화 상태, 이미지 최적화 상태 등을 확인할 수 있는 도구입니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Chrome DevTools&lt;/b&gt;: 브라우저 내장 개발 도구로, 네트워크 탭을 통해 웹 페이지 로딩 시 어떤 리소스가 얼마나 오래 걸리는지 확인할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;마치며&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;웹 사이트 최적화는 사용자 경험을 높이고, 검색 엔진 순위에도 긍정적인 영향을 줄 수 있는 중요한 작업입니다. 이미지 최적화, 코드 압축, 캐싱 설정, 서버 최적화, JavaScript 비동기 로딩과 같은 방법을 활용하여 사이트의 성능을 개선할 수 있습니다. 이 글에서 소개한 최적화 방법들을 하나씩 적용해 보고, 더 나은 사용자 경험을 제공하는 웹 사이트를 만들어 보세요.&lt;/p&gt;</description>
      <author>ghkdtprhf5</author>
      <guid isPermaLink="true">https://ghkdtprhf5.tistory.com/9</guid>
      <comments>https://ghkdtprhf5.tistory.com/9#entry9comment</comments>
      <pubDate>Thu, 7 Nov 2024 20:10:00 +0900</pubDate>
    </item>
    <item>
      <title>React 상태 관리의 이해: useState, useReducer, 그리고 Context API</title>
      <link>https://ghkdtprhf5.tistory.com/8</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;React는 UI를 컴포넌트 단위로 관리하고, 각 컴포넌트의 상태를 통해 동적인 웹 애플리케이션을 쉽게 개발할 수 있게 해줍니다. 그러나 애플리케이션이 복잡해지면 상태를 관리하는 것이 쉽지 않습니다. React에는 &lt;b&gt;useState, useReducer, 그리고 Context API&lt;/b&gt;와 같은 다양한 상태 관리 방법이 있습니다. 이번 글에서는 이 방법들을 비교하고 언제 어떤 상태 관리 방식을 선택하면 좋을지 알아보겠습니다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;1. useState&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;useState는 React의 가장 기본적인 상태 관리 훅입니다. 이 훅을 사용하면 컴포넌트 내에서 상태를 선언하고 업데이트할 수 있습니다. 간단한 상태 관리에는 useState가 가장 적합합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1730977636223&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 'react';

function Counter() {
  const [count, setCount] = useState(0);

  return (
    &amp;lt;div&amp;gt;
      &amp;lt;p&amp;gt;현재 카운트: {count}&amp;lt;/p&amp;gt;
      &amp;lt;button onClick={() =&amp;gt; setCount(count + 1)}&amp;gt;증가&amp;lt;/button&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}

export default Counter;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 예제에서 useState를 사용하여 count라는 상태를 선언하고, setCount를 통해 상태를 업데이트합니다. useState는 간단한 컴포넌트에서 상태를 관리하기 매우 용이합니다. 그러나 여러 상태가 복잡하게 얽히면 가독성이 떨어질 수 있습니다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;2. useReducer&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;useReducer는 useState보다 복잡한 상태를 관리할 때 유용합니다. useReducer는 리듀서 함수를 사용해 상태를 업데이트하며, 상태와 액션을 기반으로 새로운 상태를 반환합니다. 상태가 여러 개의 값으로 이루어져 있고, 특정한 액션에 따라 상태를 변환해야 할 때 useReducer를 사용하면 좋습니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1730977666978&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import React, { useReducer } from 'react';

const initialState = { count: 0 };

function reducer(state, action) {
  switch (action.type) {
    case 'increment':
      return { count: state.count + 1 };
    case 'decrement':
      return { count: state.count - 1 };
    default:
      return state;
  }
}

function Counter() {
  const [state, dispatch] = useReducer(reducer, initialState);

  return (
    &amp;lt;div&amp;gt;
      &amp;lt;p&amp;gt;현재 카운트: {state.count}&amp;lt;/p&amp;gt;
      &amp;lt;button onClick={() =&amp;gt; dispatch({ type: 'increment' })}&amp;gt;증가&amp;lt;/button&amp;gt;
      &amp;lt;button onClick={() =&amp;gt; dispatch({ type: 'decrement' })}&amp;gt;감소&amp;lt;/button&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}

export default Counter;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 예제에서 useReducer는 상태와 액션에 따라 count 값을 증가하거나 감소시키는 역할을 합니다. 여러 상태를 복잡한 로직에 따라 관리해야 할 경우, useReducer는 상태 업데이트를 보다 명확하고 체계적으로 할 수 있게 도와줍니다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;3. Context API&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Context API는 전역 상태를 관리할 때 사용됩니다. useState나 useReducer는 기본적으로 컴포넌트 내에서만 상태를 공유할 수 있지만, Context API를 사용하면 특정 상태를 컴포넌트 트리 전반에 걸쳐 공유할 수 있습니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1730977679840&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import React, { useState, createContext, useContext } from 'react';

const CountContext = createContext();

function CountProvider({ children }) {
  const [count, setCount] = useState(0);

  return (
    &amp;lt;CountContext.Provider value={{ count, setCount }}&amp;gt;
      {children}
    &amp;lt;/CountContext.Provider&amp;gt;
  );
}

function Counter() {
  const { count, setCount } = useContext(CountContext);

  return (
    &amp;lt;div&amp;gt;
      &amp;lt;p&amp;gt;현재 카운트: {count}&amp;lt;/p&amp;gt;
      &amp;lt;button onClick={() =&amp;gt; setCount(count + 1)}&amp;gt;증가&amp;lt;/button&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}

function App() {
  return (
    &amp;lt;CountProvider&amp;gt;
      &amp;lt;Counter /&amp;gt;
    &amp;lt;/CountProvider&amp;gt;
  );
}

export default App;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 예제에서 Context API를 통해 count 상태를 Counter 컴포넌트에서 쉽게 가져올 수 있습니다. Context API는 상태를 전역으로 사용할 수 있게 해주어, 상위 컴포넌트에서 하위 컴포넌트로 상태를 일일이 전달하지 않아도 되기 때문에 코드가 깔끔해집니다. 단, 너무 많은 상태를 전역으로 관리하면 성능이 저하될 수 있습니다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;상태 관리 방식 선택하기&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;방식장점단점사용 예시&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;useState&lt;/td&gt;
&lt;td&gt;간단하고 빠르게 구현 가능&lt;/td&gt;
&lt;td&gt;복잡한 상태 관리에 어려움&lt;/td&gt;
&lt;td&gt;단일 컴포넌트의 상태 관리&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;useReducer&lt;/td&gt;
&lt;td&gt;복잡한 상태 로직을 체계적으로 관리 가능&lt;/td&gt;
&lt;td&gt;코드가 길어질 수 있음&lt;/td&gt;
&lt;td&gt;여러 상태를 가진 컴포넌트&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Context API&lt;/td&gt;
&lt;td&gt;전역 상태를 쉽게 관리 가능&lt;/td&gt;
&lt;td&gt;성능 저하 가능성&lt;/td&gt;
&lt;td&gt;로그인 정보, 설정 등 전역 상태&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;상황에 따라 적절한 상태 관리 방법을 선택하는 것이 중요합니다. 일반적으로 작은 프로젝트나 단일 컴포넌트에서는 useState를 사용하고, 복잡한 상태 로직이 필요할 때는 useReducer를 고려합니다. 애플리케이션 전반에 걸쳐 공유되어야 하는 상태는 Context API를 활용하는 것이 좋습니다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;마치며&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;React 상태 관리는 프로젝트의 복잡성에 따라 달라질 수 있습니다. 적절한 상태 관리 방법을 선택하여 가독성과 유지보수성을 높이면, 개발 과정에서의 효율성도 크게 향상됩니다. 상태 관리에 대해 고민 중이시라면 이번 글이 도움이 되셨기를 바랍니다. 앞으로도 효과적인 상태 관리를 통해 더욱 견고한 React 애플리케이션을 만드시길 응원합니다!&lt;/p&gt;</description>
      <author>ghkdtprhf5</author>
      <guid isPermaLink="true">https://ghkdtprhf5.tistory.com/8</guid>
      <comments>https://ghkdtprhf5.tistory.com/8#entry8comment</comments>
      <pubDate>Thu, 7 Nov 2024 20:08:09 +0900</pubDate>
    </item>
    <item>
      <title>JavaScript의 비동기 처리 이해하기: 콜백, 프로미스, 그리고 async/await</title>
      <link>https://ghkdtprhf5.tistory.com/7</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;웹 개발에서 자주 사용하는 JavaScript는 &lt;b&gt;싱글 스레드 기반의 언어&lt;/b&gt;로, 코드가 순차적으로 실행됩니다. 이로 인해 시간이 오래 걸리는 작업이 있을 경우, 전체 코드의 흐름을 방해할 수 있습니다. 이러한 문제를 해결하기 위해 JavaScript는 &lt;b&gt;비동기 처리&lt;/b&gt;를 지원하며, 이를 통해 오래 걸리는 작업도 효율적으로 처리할 수 있습니다. 오늘은 비동기 처리의 핵심인 &lt;b&gt;콜백, 프로미스, 그리고 async/await&lt;/b&gt;에 대해 알아보겠습니다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;1. 콜백 함수&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;콜백 함수는 가장 기초적인 비동기 처리 방식입니다. 특정 함수가 실행된 후에 호출되도록 설계된 함수로, 많은 코드에서 콜백을 사용하여 비동기적인 작업을 처리합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1730977481612&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function fetchData(callback) {
  setTimeout(() =&amp;gt; {
    console.log(&quot;데이터를 가져왔습니다!&quot;);
    callback();
  }, 1000);
}

fetchData(() =&amp;gt; {
  console.log(&quot;콜백 함수가 호출되었습니다!&quot;);
});&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 코드에서 fetchData 함수는 1초 후 데이터를 가져온 다음 콜백 함수를 호출합니다. 콜백은 간단하고 사용하기 쉬운 방식이지만, 복잡한 비동기 처리를 할 때는 코드가 깊어지는 &lt;b&gt;콜백 지옥&lt;/b&gt;에 빠질 수 있습니다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;2. 프로미스(Promise)&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;콜백 지옥을 해결하기 위해 ES6부터 &lt;b&gt;프로미스&lt;/b&gt;가 도입되었습니다. 프로미스는 작업이 성공했는지, 실패했는지 상태를 반환하여 비동기 작업의 흐름을 관리하기 쉽게 해줍니다. 프로미스는 resolve와 reject라는 두 가지 결과를 가지고 있으며, 이를 통해 성공 또는 실패 상태를 반환합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1730977493351&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function fetchData() {
  return new Promise((resolve, reject) =&amp;gt; {
    setTimeout(() =&amp;gt; {
      const success = true;
      if (success) {
        resolve(&quot;데이터를 가져왔습니다!&quot;);
      } else {
        reject(&quot;데이터 가져오기 실패!&quot;);
      }
    }, 1000);
  });
}

fetchData()
  .then(result =&amp;gt; console.log(result))
  .catch(error =&amp;gt; console.error(error));&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 코드에서 fetchData는 프로미스를 반환합니다. then 메서드를 통해 성공 시의 결과를, catch를 통해 실패 시의 결과를 처리할 수 있어 코드가 더욱 가독성이 좋고 관리하기 쉬워졌습니다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;3. async/await&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;async/await는 프로미스를 더욱 간편하게 사용할 수 있는 방법으로, ES8부터 도입되었습니다. 이를 통해 코드가 마치 동기식으로 작동하는 것처럼 보이지만, 실제로는 비동기적으로 처리됩니다. await 키워드를 통해 비동기 작업이 완료될 때까지 기다린 후, 다음 코드가 실행됩니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1730977503127&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;async function fetchData() {
  return new Promise((resolve, reject) =&amp;gt; {
    setTimeout(() =&amp;gt; {
      const success = true;
      if (success) {
        resolve(&quot;데이터를 가져왔습니다!&quot;);
      } else {
        reject(&quot;데이터 가져오기 실패!&quot;);
      }
    }, 1000);
  });
}

async function displayData() {
  try {
    const result = await fetchData();
    console.log(result);
  } catch (error) {
    console.error(error);
  }
}

displayData();&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 예제에서 displayData 함수는 await를 통해 fetchData 함수가 성공하거나 실패할 때까지 기다립니다. try...catch 문을 사용하여 오류를 처리할 수 있으므로, 에러 핸들링도 간편하게 할 수 있습니다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;콜백, 프로미스, 그리고 async/await의 비교&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;방식장점단점&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;콜백&lt;/td&gt;
&lt;td&gt;간단한 구조, 빠른 구현 가능&lt;/td&gt;
&lt;td&gt;콜백 지옥 발생 가능&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;프로미스&lt;/td&gt;
&lt;td&gt;에러 처리와 흐름 제어가 쉬움&lt;/td&gt;
&lt;td&gt;코드가 길어질 수 있음&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;async/await&lt;/td&gt;
&lt;td&gt;동기식 코딩 스타일, 가독성 향상&lt;/td&gt;
&lt;td&gt;모든 환경에서 지원되지 않음&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;콜백, 프로미스, async/await 각각의 비동기 처리 방식에는 저마다의 장점과 단점이 있습니다. 초보자에게는 콜백이 간단하고 이해하기 쉬울 수 있지만, 코드의 가독성과 유지보수를 고려할 때는 async/await가 권장됩니다. 프로미스와 async/await는 ES6와 ES8 이후의 버전에서 지원하므로, 최신 JavaScript 환경에서 사용하기 좋습니다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;마치며&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JavaScript의 비동기 처리는 웹 애플리케이션 개발에서 매우 중요한 부분입니다. 특히 서버와 데이터를 주고받거나 대규모 파일을 처리할 때 필수적으로 사용됩니다. 이번 글을 통해 콜백, 프로미스, async/await에 대한 이해가 더욱 깊어지셨기를 바랍니다. 여러분의 코드가 더욱 효율적이고 깔끔해지기를 응원합니다!&lt;/p&gt;</description>
      <author>ghkdtprhf5</author>
      <guid isPermaLink="true">https://ghkdtprhf5.tistory.com/7</guid>
      <comments>https://ghkdtprhf5.tistory.com/7#entry7comment</comments>
      <pubDate>Thu, 7 Nov 2024 20:05:16 +0900</pubDate>
    </item>
    <item>
      <title>[Recat] useEffect 이해하기</title>
      <link>https://ghkdtprhf5.tistory.com/6</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;useEffect는 React 컴포넌트에서 주로 사용하는 함수로, 두 개의 매개변수를 가집니다. 첫 번째는 콜백 함수이며, 두 번째는 &lt;b&gt;dependencies array&lt;/b&gt;입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음 코드를 통해 useEffect의 기본 사용 방법을 알아보겠습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1730725807351&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import React, { useEffect, useState } from 'react';
import './App.css';

function App() {
  const [count, setCount] = useState(1);
  const [name, setName] = useState('');

  const handleCountUpdate = () =&amp;gt; {
    setCount(count + 1);
  }

  const handleInputChange = (e) =&amp;gt; {
    setName(e.target.value);
  }

  // 렌더링 될 때마다 매번 콜백 함수 실행
  useEffect(() =&amp;gt; {
    console.log('렌더링');
  });

  // 마운트 + count 변경 시에만 실행
  useEffect(() =&amp;gt; {
    console.log('Count 변경');
  }, [count]);

  // 처음 마운트 될 때만 실행
  useEffect(() =&amp;gt; {
    console.log('첫 마운트');
  }, []);

  return (
    &amp;lt;div className=&quot;App&quot;&amp;gt;
      &amp;lt;button onClick={handleCountUpdate}&amp;gt;Update&amp;lt;/button&amp;gt;
      &amp;lt;span&amp;gt;count: {count}&amp;lt;/span&amp;gt;
      &amp;lt;input type='text' value={name} onChange={handleInputChange}/&amp;gt;
      &amp;lt;span&amp;gt;name: {name}&amp;lt;/span&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}

export default App;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  useEffect의 동작 결과&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;컴포넌트 실행 시&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;페이지가 로드되면 세 가지 useEffect 함수 안의 콜백 함수가 실행됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Update 버튼 클릭 시&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;count 값이 업데이트되어서, 렌더링과 Count 변경이 실행됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;input에 텍스트 입력 시&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;name 상태가 변경되므로 렌더링만 실행됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;정리&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;빈 dependencies array []&lt;/b&gt;: 처음 마운트될 때 한 번만 실행됩니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;특정 값 포함된 dependencies array [value]&lt;/b&gt;: 지정된 값이 변경될 때마다 실행됩니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;dependencies array 없음&lt;/b&gt;: 매번 렌더링 시마다 실행됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;Clean&amp;nbsp;Up&lt;/h2&gt;
&lt;pre id=&quot;code_1730725908068&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, { useState } from 'react';
import Timer from './components/Timer';

function App() {
  const [showTimer, setShowTimer] = useState(false);

  return (
    &amp;lt;div className=&quot;App&quot;&amp;gt;
      {showTimer &amp;amp;&amp;amp; &amp;lt;Timer /&amp;gt;}
      &amp;lt;button onClick={() =&amp;gt; setShowTimer(!showTimer)}&amp;gt;Toggle Timer&amp;lt;/button&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}

export default App;

// ./components/Timer.js
import React, { useEffect } from 'react';

const Timer = () =&amp;gt; {
  useEffect(() =&amp;gt; {
    const timer = setInterval(() =&amp;gt; {
      console.log('타이머 돌아가는 중...');
    }, 1000);

    // 컴포넌트 언마운트 시 클린업 함수 실행
    return () =&amp;gt; {
      clearInterval(timer);
      console.log('타이머가 종료되었습니다.');
    };
  }, []);

  return &amp;lt;div&amp;gt;&amp;lt;span&amp;gt;타이머를 시작합니다. 콘솔을 확인하세요!&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;;
}

export default Timer;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&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;Timer 컴포넌트 마운트 시&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;버튼 클릭으로 showTimer가 true가 되면 Timer 컴포넌트가 마운트되며 useEffect 내부 콜백 함수가 실행됩니다.&lt;/li&gt;
&lt;li&gt;타이머 돌아가는 중... 메시지가 1초마다 출력됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Timer 컴포넌트 언마운트 시&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;다시 버튼을 클릭하면 showTimer가 false가 되어 Timer 컴포넌트가 언마운트됩니다.&lt;/li&gt;
&lt;li&gt;언마운트 시 클린업 함수가 실행되어 타이머가 종료되었습니다.가 출력됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;클린업 함수의 필요성&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;useEffect의 클린업 함수가 없다면&lt;/b&gt;, 컴포넌트가 언마운트되더라도 타이머가 계속 실행됩니다. 이런 상황을 방지하려면 필요한 경우 useEffect의 return을 통해 클린업 함수를 지정해야 합니다.&lt;/p&gt;</description>
      <author>ghkdtprhf5</author>
      <guid isPermaLink="true">https://ghkdtprhf5.tistory.com/6</guid>
      <comments>https://ghkdtprhf5.tistory.com/6#entry6comment</comments>
      <pubDate>Mon, 4 Nov 2024 22:11:52 +0900</pubDate>
    </item>
    <item>
      <title>[NextJs] MongoDB(mongoose) 사용하기</title>
      <link>https://ghkdtprhf5.tistory.com/5</link>
      <description>&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;✅ 1. 데이터베이스 연결&lt;/h2&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;MongoDB 클러스터와 Mongoose를 연결하는 코드를 작성합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1729515491722&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import mongoose from 'mongoose';

const connectDB = async () =&amp;gt; {
    try {
        await mongoose.connect(process.env.MONGO_URI); // 데이터베이스 연결 주소
        console.log('MongoDB 연결 성공');
    } catch (err) {
        console.error('MongoDB 연결 실패', err);
        process.exit(1);
    }
};

export default connectDB;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  connectDB 함수를 비동기 처리한 이유&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;MongoDB에 연결하는 과정이 네트워크 요청이기 때문입니다.&lt;br /&gt;DB에 연결하려면 &lt;b&gt;MongoDB 서버와 네트워크 통신&lt;/b&gt;을 해야 하고, 이 작업은 시간이 걸릴 수 있기 때문에 비동기 작업으로 처리합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div data-message-model-slug=&quot;gpt-4o&quot; data-message-id=&quot;b0ec9f76-60bd-4a11-be4e-ee09b5ee4736&quot; data-message-author-role=&quot;assistant&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;벨로그에서 사용한 글을 티스토리에서 활용할 수 있도록 조금 더 포맷을 깔끔하게 조정해보겠습니다. 티스토리의 에디터가 다소 제한적일 수 있으니, 기본적인 문단 구조와 마크다운을 활용한 형태로 재구성하겠습니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-size: 1.62em;&quot;&gt;✅ 2. 스키마 및 모델 정의&lt;/span&gt;&lt;/h2&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1729515594691&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import mongoose from 'mongoose';

const TopiceSchema = new mongoose.Schema({
    id: {
        type: Number,  // 순차적인 ID 필드
        required: true,
        unique: true  // 각 id는 고유해야 함
    },
    title: {
        type: String,
        required: true
    },
    questions: {
        type: Number,
        required: true
    }
});

// 이미 모델이 존재하면 해당 모델을 사용하고, 없으면 새로 정의
export default mongoose.models.Topice || mongoose.model('Topice', TopiceSchema);​&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  required: true&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;의미&lt;/b&gt;: 이 필드는 &lt;b&gt;반드시 값이 있어야 한다&lt;/b&gt;는 제약 조건을 설정합니다.&lt;br /&gt;즉, 문서를 생성하거나 업데이트할 때 이 필드가 &lt;b&gt;빈 값이거나 누락되면 ValidationError&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;br /&gt;예를 들어, 아래 코드와 같이 title 필드가 빠지거나 빈 값이면 데이터 저장이 실패합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;pre id=&quot;code_1729515647853&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const newTopice = new Topice({ id: 1, questions: 5 }); // title이 없으므로 에러 발생&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  unique: true&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;의미&lt;/b&gt;: 이 필드는 &lt;b&gt;고유한 값&lt;/b&gt;이어야 한다는 제약 조건을 설정합니다.&lt;br /&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;br /&gt;아래 코드와 같이 id 필드에 같은 값이 두 번 입력되면 &lt;b&gt;중복 에러&lt;/b&gt;가 발생합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1729515659321&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const newTopice1 = new Topice({ id: 1, title: &quot;Test1&quot;, questions: 5 });
const newTopice2 = new Topice({ id: 1, title: &quot;Test2&quot;, questions: 5 }); // id 중복 에러 발생&lt;/code&gt;&lt;/pre&gt;</description>
      <category>mongodb #mongoose #몽고디비 #nextjs</category>
      <author>ghkdtprhf5</author>
      <guid isPermaLink="true">https://ghkdtprhf5.tistory.com/5</guid>
      <comments>https://ghkdtprhf5.tistory.com/5#entry5comment</comments>
      <pubDate>Mon, 21 Oct 2024 22:01:32 +0900</pubDate>
    </item>
  </channel>
</rss>