<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ Yerim Kang - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/korean/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ Yerim Kang - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/korean/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Fri, 22 May 2026 15:16:07 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/korean/news/author/yerim/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ 자바스크립의 콜백 함수 – 자바스크립트에서 콜백 함수가 무엇이고 어떻게 사용하는지 알아봅시다 ]]>
                </title>
                <description>
                    <![CDATA[ 여러분이 프로그래밍과 익숙하시다면, 함수가 무엇이고 어떻게 사용하는지 알고 계실 겁니다. 그러나 콜백 함수가 뭔지 정확히 알고 있나요? 콜백 함수는 자바스크립트에서 중요한 파트 중 하나이고 콜백 함수가 어떻게 작동하는지 알고 계신다면 자바스크립트를 훨씬 더 잘 다룰 수 있게 될 것입니다. 그래서 이번 글에서는 콜백 함수가 무엇인지 그리고 몇 가지 예제를 통해 ]]>
                </description>
                <link>https://www.freecodecamp.org/korean/news/https-www-freecodecamp-org-news-javascript-callback-functions-what-are-callbacks-in-js-and-how-to-use-them/</link>
                <guid isPermaLink="false">63c2d20fa06cec064ac5d46c</guid>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Yerim Kang ]]>
                </dc:creator>
                <pubDate>Thu, 19 Jan 2023 06:48:29 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/korean/news/content/images/2023/01/caspar-camille-rubin-7SDoly3FV_0-unsplash-1.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p data-test-label="translation-intro">
        <strong>기사 원문:</strong> <a href="https://www.freecodecamp.org/news/javascript-callback-functions-what-are-callbacks-in-js-and-how-to-use-them/" target="_blank" rel="noopener noreferrer" data-test-label="original-article-link">JavaScript Callback Functions – What are Callbacks in JS and How to Use&nbsp;Them</a>
      </p><p>여러분이 프로그래밍과 익숙하시다면, 함수가 무엇이고 어떻게 사용하는지 알고 계실 겁니다. 그러나 콜백 함수가 뭔지 정확히 알고 있나요? 콜백 함수는 자바스크립트에서 중요한 파트 중 하나이고 콜백 함수가 어떻게 작동하는지 알고 계신다면 자바스크립트를 훨씬 더 잘 다룰 수 있게 될 것입니다.</p><p>그래서 이번 글에서는 콜백 함수가 무엇인지 그리고 몇 가지 예제를 통해 자바스크립트에서 어떻게 동작하는지를 알려드리려고 합니다.</p><h2 id="-"><strong>콜백 함수가 무엇인가요?</strong></h2><p>자바스크립트에서는 함수는 객체입니다. 함수의 파라미터로서 객체를 전달할 수 있을까요? 네, 할 수 있습니다.</p><p>그래서 우리는 함수의 파라미터로서 다른 함수에 전달하고 감싼 함수의 내부에서 그 함수를 호출합니다. 헷갈리신다고요? 아래에 예시를 보여드리겠습니다.</p><pre><code>function print(callback) {
    callback();
}
</code></pre><p>print() 함수는 다른 함수를 파라미터로 받아서 내부에서 그것을 호출하고 있습니다. 자바스크립트에서는 가능합니다. 그리고 이걸 우리는 “콜백”이라고 하기로 했어요. 다른 함수의 파라미터로써 전달되는 함수를 콜백 함수라고 합니다. 그러나 그게 다는 아니에요.</p><p>아래 비디오에서 콜백 함수의 종류를 시청하실 수 있습니다.</p><h3 id="--1"><strong>콜백 함수가 왜 필요한가요?</strong></h3><p>자바스크립트는 코드를 위에서 아래로 순차적으로 실행합니다. 그러나, 코드가 다른 행위가 일어난 뒤에 실행되는 경우도 있고 순차적으로 실행되지 않을 때도 있습니다. 이런 걸 비동기 프로그래밍이라고 합니다.</p><p>콜백은 태스크가 끝나기 전에 함수가 실행되지 않는 것을 보장합니다. 다르게 말하자면 콜백은 그 태스크가 끝난 직후에 실행될 것입니다. 콜백은 비동기 자바스크립트 코드를 작성할 수 있도록 해주고 여러 문제와 에러들로부터 안전하게 지켜줍니다.</p><p>자바스크립트에서 콜백 함수를 만드는 방법은 어떤 함수의 파라미터로써 함수를 넘기고 어떤 행위나 태스크가 완료된 직후에 콜백 함수를 호출하는 것입니다.</p><h2 id="--2"><strong>콜백을 만드는 방법</strong></h2><p>위에 설명한 내용들을 이해하기 위해, 간단한 예제로 시작해 보겠습니다. 콘솔에 로그를 찍어보려고 하는데, 이것은 꼭 3초 뒤에 출력되어야 합니다.</p><pre><code>const message = function() {
    console.log("This message is shown after 3 seconds");
}

setTimeout(message, 3000);
</code></pre><p>setTimeout 함수는 자바스크립트에 내장된 함수입니다. 이 함수는 주어진 시간(밀리세컨드 단위) 이후에 함수를 호출하거나 표현식을 평가합니다. 그래서 여기 message 함수는 3초가 지난 후에 호출됩니다. (1초 = 1000 밀리세컨드)</p><p>다르게 이야기하자면, message 함수는 어떤 일이 일어나기 전이 아니라 뒤에(여기서는 3초가 지난 후에) 호출됩니다. 그래서 이 message 함수는 콜백 함수의 예시라고 할 수 있죠.</p><h3 id="--3"><strong>비동기 함수가 무엇인가요?</strong></h3><p>다르게는 비동기 함수를 다른 함수에 호출하는 방법 말고 함수 내부에 직접적으로 정의하는 방법도 있습니다. 이런 방법은 아래와 같습니다.</p><pre><code>setTimeout(function() {
    console.log("This message is shown after 3 seconds");
}, 3000);
</code></pre><p>보시다시피 여기서 콜백 함수는 이름이 없고 자바스크립트에서 이름이 없는 함수 정의를 "익명 함수"라고 합니다. 이것은 위의 샘플과 정확하게 똑같이 작동합니다.</p><h3 id="--4"><strong>화살표 함수 모양의 콜백</strong></h3><p>사용자의 선호에 따라 똑같은 콜백 함수를 ES6 화살표 함수로 사용할 수 있습니다. 화살표 함수는 자바스크립트 내에서 새로운 타입의 함수 표현입니다.</p><pre><code>setTimeout(() =&gt; {
    console.log("This message is shown after 3 seconds");
}, 3000);
</code></pre><h2 id="--5"><strong>이벤트 처리는요?</strong></h2><p>자바스크립트는 이벤트 기반 프로그래밍 언어입니다. 콜백 함수를 이벤트 선언을 위해 사용하기도 합니다. 예를 들어 사용자가 버튼을 클릭하기를 바란다고 해봅시다.</p><pre><code>&lt;button id="callback-btn"&gt;Click here&lt;/button&gt;
</code></pre><p>이번에는 사용자가 버튼을 클릭했을 때 콘솔에 메시지를 남겨 보도록 하겠습니다.</p><pre><code>document.queryselector("#callback-btn")
    .addEventListener("click", function() {
      console.log("User has clicked on the button!");
});
</code></pre><p>첫 번째로 버튼의 id 값을 사용하여 버튼을 선택하고 addEventListener 메소드를 사용하여 이벤트 리스너를 추가했습니다. 이벤트 리스너 함수는 두 개의 파라미터를 필요로 합니다. 첫 번째 파라미터로는 이벤트의 타입인 “클릭”이고 두 번째 파라미터는 버튼이 클릭되었을 때 메시지를 남기는 콜백 함수입니다.</p><p>보기와 같이, 콜백 함수는 자바스크립트에서 이벤트 정의를 위해 사용되기도 합니다.</p><h2 id="--6"><strong>마무리</strong></h2><p>콜백 함수는 자바스크립트에서 종종 사용됩니다. 이 포스트가 콜백 함수가 정확히 어떤 방식으로 작동하고 더 쉽게 사용하는 방법들을 이해하는 데 도움이 되었으면 합니다. 다음에는 비슷한 주제인 자바스크립트 프로미스에 대해서 새로운 포스트로 배워보실 수 있도록 하겠습니다.</p><p>웹 개발에 대해 더 알고 싶으시다면, 제 유튜브를 팔로우 해주셔도 좋습니다!</p><p>글 읽어주셔서 감사합니다!</p> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ 리액트에서 컴포넌트를 검색하고 필터하는 방법 ]]>
                </title>
                <description>
                    <![CDATA[ 리액트 앱을 만들다보면, 당신의 사용자가 검색을 해서 정확한 결과를 얻기를 원할겁니다. 그런데 만약 API에서 엄청난 양의 아이템을 받게 된다면 사용자들이 많은 아이템들을 쉽게 찾을 수 있는 방법을 찾아야할 거에요. 이번 튜토리얼에서는 예제로 Frontend Mentor’s free advanced API project를 사용할 것입니다. 목차 1. 시작하기 2. 리액트 셋팅하기 3. 데이터 받아오기 4. ]]>
                </description>
                <link>https://www.freecodecamp.org/korean/news/search-and-filter-component-in-reactjs/</link>
                <guid isPermaLink="false">638f196137582306394d7cc1</guid>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Yerim Kang ]]>
                </dc:creator>
                <pubDate>Wed, 07 Dec 2022 07:43:49 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/korean/news/content/images/2022/12/wirxeocmd6tpnn9c5oqc.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p data-test-label="translation-intro">
        <strong>기사 원문:</strong> <a href="https://www.freecodecamp.org/news/search-and-filter-component-in-reactjs/" target="_blank" rel="noopener noreferrer" data-test-label="original-article-link">How to Search and Filter Components in React</a>
      </p><h2 id="-api-">리액트 앱을 만들다보면, 당신의 사용자가 검색을 해서 정확한 결과를 얻기를 원할겁니다. 그런데 만약 API에서 엄청난 양의 아이템을 받게 된다면 사용자들이 많은 아이템들을 쉽게 찾을 수 있는 방법을 찾아야할 거에요.</h2><p>이번 튜토리얼에서는 예제로 Frontend Mentor’s free advanced API project를 사용할 것입니다.</p><h2 id="-">목차</h2><h3 id="1-">1. 시작하기</h3><h3 id="2-">2. 리액트 셋팅하기</h3><h3 id="3-">3. 데이터 받아오기</h3><h3 id="4-api-">4. API에서 아이템 찾기</h3><h3 id="5-">5. 지역에서 아이템 필터링하기</h3><p></p><h1 id="--1">시작하기</h1><p>이번 튜토리얼을 위해서 우리는 <a href="https://apilayer.com/">Apilayer</a>가 제공하는 무료 API인 <a href="https://restcountries.eu/">REST COUNTRIES API</a>을 사용할 겁니다.</p><p>기본적으로 우리의 API의 엔드포인트인 <a href="https://restcountries.eu/rest/v2/all">https://restcountries.eu/rest/v2/all</a> 에서 데이터를 가져올 겁니다. 그리고 사용자가 읽을 수 있는 형식으로 데이터를 표기할 겁니다.</p><p>그러고 나면 우리는 특정 나라를 이름과 수도로 사용자가 쉽게 사용할 수 있는 방법을 제공해보도록 합시다. 여기 어느 나라의 응답 예시를 드릴게요.</p><pre><code class="language-json">"name": "Colombia",
"topLevelDomain": [".co"],
"alpha2Code": "CO",
"alpha3Code": "COL",
"callingCodes": ["57"],
"capital": "Bogotá",
"altSpellings": ["CO", "Republic of Colombia", "República de Colombia"],
"region": "Americas",
"subregion": "South America",
"population": 48759958,
"latlng": [4.0, -72.0],
"demonym": "Colombian",
"area": 1141748.0,
"gini": 55.9,
"timezones": ["UTC-05:00"],
"borders": ["BRA", "ECU", "PAN", "PER", "VEN"],
"nativeName": "Colombia",
"numericCode": "170",
"currencies": [{
    "code": "COP",
    "name": "Colombian peso",
    "symbol": "$"
}],
"languages": [{
    "iso639_1": "es",
    "iso639_2": "spa",
    "name": "Spanish",
    "nativeName": "Español"
}],
"translations": {
    "de": "Kolumbien",
    "es": "Colombia",
    "fr": "Colombie",
    "ja": "コロンビア",
    "it": "Colombia",
    "br": "Colômbia",
    "pt": "Colômbia"
},
"flag": "&lt;https://restcountries.eu/data/col.svg&gt;",
"regionalBlocs": [{
    "acronym": "PA",
    "name": "Pacific Alliance",
    "otherAcronyms": [],
    "otherNames": ["Alianza del Pacífico"]
}, {
    "acronym": "USAN",
    "name": "Union of South American Nations",
    "otherAcronyms": ["UNASUR", "UNASUL", "UZAN"],
    "otherNames": ["Unión de Naciones Suramericanas", "União de Nações Sul-Americanas", "Unie van Zuid-Amerikaanse Naties", "South American Union"]
}],
"cioc": "COL"
}]
</code></pre><p>이 튜토리얼이 끝날 때 쯤이면 당신은 API를 통해 검색하는 법을 배우고 리액트를 통해 요청한 결과만을 반환하는 법을 배울 수 있으면 좋겠습니다!</p><h2 id="--2">리액트 셋팅하기</h2><p>어떠한 설정 없이도 모던 빌드 환경을 제공하는 <code>create-react-app</code> 으로 우리 프로젝트를 셋팅 할 겁니다.</p><p>리액트를 셋팅하기 위해서 터미널을 실행(아니면 당신이 사용하는 시스템에서 제공하거나 VS Code와 같은 에디터에서 제공하는 터미널)하고 아래의 커맨드를 실행시키세요.</p><pre><code class="language-json">npx create-react-app my-app 
cd my-app 
npm start
</code></pre><p>만약 <code>create-react-app</code> 으로 프로젝트를 제대로 구성하는 것이 확신이 없다면 <a href="https://create-react-app.dev/docs/getting-started/">create-react-app-dev</a> 이곳에서 공식 가디으 문서를 참조해보세요.</p><p>이번 튜토리얼에선 실시간 결과를 보여드리기 위해, 우리는 코드펜을 우리의 프로젝트에도 사용할 겁니다. <a href="https://codepen.io/MrMaster">Lathryx</a>가 만든 코드펜 템플릿을 이용해보세요. 그렇게 했다면 우리는 코드펜에서 리액트 셋팅을 할 수 있습니다.</p><figure class="kg-card kg-embed-card"><iframe id="cp_embed_oNYWNjr" src="https://codepen.io/MrMaster/embed/preview/oNYWNjr?default-tabs=css%2Cresult&amp;height=300&amp;host=https%3A%2F%2Fcodepen.io&amp;slug-hash=oNYWNjr" title="Embedded content" scrolling="no" frameborder="0" height="300" allowtransparency="true" class="cp_embed_iframe" loading="lazy" style="box-sizing: inherit; margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; font-family: inherit; font-size: 22px; vertical-align: middle; width: 720px; overflow: hidden;"></iframe></figure><p></p><h2 id="api-">API 엔드포인트에서 데이터를 가져오기</h2><p>지금 우리는 리액트 프로젝트 셋팅을 성공적으로 완료했고 이제 API에서 데이터를 가져와볼 시간입니다. 리액트에서 데이터를 가져오는 다양한 방법이 있는데 가장 유명한 두개는 Axios(프로미스 기반 HTTP 클라이언트)와 Fetch API(브라우저에 내장된 웹 API) 입니다.</p><p>우리는 브라우저에서 제공하는 Fetch API를 사용할 것이고 API 엔드포인트에서 데이터를 가져오는 것은 Ajax를 사용할 것입니다. 여기 React에서 Ajax와 API을 훅으로 사용하는 예시가 있습니다.</p><pre><code class="language-jsx">function MyComponent() {
      const [error, setError] = useState(null);
      const [isLoaded, setIsLoaded] = useState(false);
      const [items, setItems] = useState([]);

      // Note: the empty deps array [] means
      // this useEffect will run once
      // similar to componentDidMount()
      useEffect(() =&gt; {
        fetch("&lt;https://api.example.com/items&gt;")
          .then(res =&gt; res.json())
          .then(
            (result) =&gt; {
              setIsLoaded(true);
              setItems(result);
            },
            // Note: it's important to handle errors here
            // instead of a catch() block so that we don't swallow
            // exceptions from actual bugs in components.
            (error) =&gt; {
              setIsLoaded(true);
              setError(error);
            }
          )
      }, [])

      if (error) {
        return &lt;div&gt;Error: {error.message}&lt;/div&gt;;
      } else if (!isLoaded) {
        return &lt;div&gt;Loading...&lt;/div&gt;;
      } else {
        return (
          &lt;ul&gt;
            {items.map(item =&gt; (
              &lt;li key={item.id}&gt;
                {item.name} {item.price}
              &lt;/li&gt;
            ))}
          &lt;/ul&gt;
        );
      }
    }
</code></pre><p>10번째 줄에서 보면 엔드포인트에서 데이터를 가져오고 있고 데이터를 받아왔을 때 컴포넌트를 업데이트하기 위해 setState를 사용하고 있습니다.</p><p>27번째 줄에서는 에러메세지를 표시하고 있는데 이것은 우리가 API에서 데이터를 가져오기 실패했을 때 사용하기 위해서 입니다. 데이터가져오기에 실패하지 않는다면 데이터를 리스트로 보여줄 것입니다.</p><p>만약 리액트로 리스트를 표현하는 것이 익숙하지 않다면 저는 <a href="https://reactjs.org/docs/lists-and-keys.html">React Lists And Keys</a>의 가이드를 보고 올 것을 추천드립니다.</p><p>이제 이 코드를 이용해서 REST COUNTRIES API에서 데이터를 가져오고 표시해보도록 합시다.</p><p>위의 예제 코드에서 React에서 useState를 가져오고 10번재 라인을 아래와 같이 바꿔보겠습니다.</p><p><code>fetch("&lt;https://restcountries.eu/rest/v2/all&gt;")</code>‌</p><p>이것들을 모두 합치면 우리는 아래와 같은 코드를 갖게 됩니다.</p><pre><code class="language-jsx">import { useState, useEffect } from "&lt;https://cdn.skypack.dev/react&gt;";

    // Note: the empty deps array [] means
    // this useEffect will run once
    function App() {
        const [error, setError] = useState(null);
        const [isLoaded, setIsLoaded] = useState(false);
        const [items, setItems] = useState([]);

        useEffect(() =&gt; {
            fetch("&lt;https://restcountries.eu/rest/v2/all&gt;")
                .then((res) =&gt; res.json())
                .then(
                    (result) =&gt; {
                        setIsLoaded(true);
                        setItems(result);
                    },
                    // Note: it's important to handle errors here
                    // instead of a catch() block so that we don't swallow
                    // exceptions from actual bugs in components.
                    (error) =&gt; {
                        setIsLoaded(true);
                        setError(error);
                    }
                );
        }, []);
</code></pre><p>참고: <code>"[&lt;https://cdn.skypack.dev/react&gt;](&lt;https://cdn.skypack.dev/react&gt;)";</code> 로부터 useState와 useEffect를 가져오고 있습니다. 이것은 우리가 Codepen에서 리액트를 CDN을 사용해서 가져오고 있기 때문입니다. 만약 당신이 리액트를 지역적으로 셋팅했다면 <code>import { useState, useEffect } from "react";</code> 를 사용해야 할것입니다.</p><p>그리고 나서 우리는 받아온 데이터를 나라들을 목록으로 표시하려고 합니다. 최종적으로 코드는 아래와 같이 되겠지요 :</p><pre><code class="language-jsx">// Note: the empty deps array [] means
    // this useEffect will run once
    function App() {
        const [error, setError] = useState(null);
        const [isLoaded, setIsLoaded] = useState(false);
        const [items, setItems] = useState([]);

        useEffect(() =&gt; {
            fetch("&lt;https://restcountries.eu/rest/v2/all&gt;")
                .then((res) =&gt; res.json())
                .then(
                    (result) =&gt; {
                        setIsLoaded(true);
                        setItems(result);
                    },
                    // Note: it's important to handle errors here
                    // instead of a catch() block so that we don't swallow
                    // exceptions from actual bugs in components.
                    (error) =&gt; {
                        setIsLoaded(true);
                        setError(error);
                    }
                );
        }, []);

        if (error) {
            return &lt;&gt;{error.message}&lt;/&gt;;
        } else if (!isLoaded) {
            return &lt;&gt;loading...&lt;/&gt;;
        } else {
            return (
                /* here we map over the element and display each item as a card  */
                &lt;div className="wrapper"&gt;
                    &lt;ul className="card-grid"&gt;
                        {items.map((item) =&gt; (
                            &lt;li&gt;
                                &lt;article className="card" key={item.callingCodes}&gt;
                                    &lt;div className="card-image"&gt;
                                        &lt;img src={item.flag} alt={item.name} /&gt;
                                    &lt;/div&gt;
                                    &lt;div className="card-content"&gt;
                                        &lt;h2 className="card-name"&gt;{item.name}&lt;/h2&gt;
                                        &lt;ol className="card-list"&gt;
                                            &lt;li&gt;
                                                population:{" "}
                                                &lt;span&gt;{item.population}&lt;/span&gt;
                                            &lt;/li&gt;
                                            &lt;li&gt;
                                                Region: &lt;span&gt;{item.region}&lt;/span&gt;
                                            &lt;/li&gt;
                                            &lt;li&gt;
                                                Capital: &lt;span&gt;{item.capital}&lt;/span&gt;
                                            &lt;/li&gt;
                                        &lt;/ol&gt;
                                    &lt;/div&gt;
                                &lt;/article&gt;
                            &lt;/li&gt;
                        ))}
                    &lt;/ul&gt;
                &lt;/div&gt;
            );
        }
    }

    ReactDOM.render(&lt;App /&gt;, document.getElementById("root"));
</code></pre><p>여기 코드펜에서 실시간 미리보기를 참고하세요</p><figure class="kg-card kg-embed-card"><iframe id="cp_embed_ZELeWoN" src="https://codepen.io/Spruce_khalifa/embed/preview/ZELeWoN?default-tabs=js%2Cresult&amp;height=300&amp;host=https%3A%2F%2Fcodepen.io&amp;slug-hash=ZELeWoN" title="Embedded content" scrolling="no" frameborder="0" height="300" allowtransparency="true" class="cp_embed_iframe" loading="lazy" style="box-sizing: inherit; margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; font-family: inherit; font-size: 22px; vertical-align: middle; width: 720px; overflow: hidden;"></iframe></figure><p></p><p>REST COUNTRIES API로부터 성공적으로 데이터를 받아오고 표시한 시점에서 우리는 표시되는 국가를 검색하는 데 집중할 수 있습니다.</p><p>그러나 시작하기 전에 위의 예제를 css로 스타일을 지정해보겠습니다. (왜냐면 이렇게 표시되면 이상하기 때문이죠)</p><p>위의 예제에 css를 더하게 되면 아래의 예시와 같은 것을 얻게 됩니다.</p><figure class="kg-card kg-embed-card"><iframe id="cp_embed_zYNZBBB" src="https://codepen.io/Spruce_khalifa/embed/preview/zYNZBBB?default-tabs=js%2Cresult&amp;height=300&amp;host=https%3A%2F%2Fcodepen.io&amp;slug-hash=zYNZBBB" title="Embedded content" scrolling="no" frameborder="0" height="300" allowtransparency="true" class="cp_embed_iframe" loading="lazy" style="box-sizing: inherit; margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; font-family: inherit; font-size: 22px; vertical-align: middle; width: 720px; overflow: hidden;"></iframe></figure><p>우리가 추가한 css가 완벽하진 않더라도 이전보다 깔끔한 방식으로 국가를 표시합니다. 그렇죠?</p><h2 id="--3">검색하는 컴포넌트를 생성하는 방법</h2><p>우리는 APP 함수 내에서 쿼리 q를 빈 스트링 값으로 셋팅하기 위해 <code>useState()</code> 를 사용했습니다. 또한 우리는 setQ를 가지고 있는데 이건 검색 폼의 값을 바인딩할 때 사용할 거에요.</p><p>13번째 줄에서 useState를 사용하여 API에서 검색할 수 있는 배열의 기본값을 정의했습니다. 이것은 국가의 <code>Capital(수도)</code> 와 <code>name(이름)</code> 으로 모든 국가를 검색할 수 있기를 원한다는 것을 의미합니다. 당신의 선호에 따라서 이 배열을 더 길게 만들수 있겠습니다.</p><pre><code class="language-jsx">const [error, setError] = useState(null);
        const [isLoaded, setIsLoaded] = useState(false);
        const [items, setItems] = useState([]);

        //     set search query to empty string
        const [q, setQ] = useState("");
        //     set search parameters
        //     we only what to search countries by capital and name
        //     this list can be longer if you want
        //     you can search countries even by their population
        // just add it to this array
        const [searchParam] = useState(["capital", "name"]);

        useEffect(() =&gt; {
            // our fetch codes
        }, []);

     }
</code></pre><p>반환 함수 안에서는 검색 폼을 만들것이고 우리의 코드는 아마 아래와 같을 것입니다.</p><pre><code class="language-jsx">return &lt;&gt;{error.message}&lt;/&gt;;
        } else if (!isLoaded) {
            return &lt;&gt;loading...&lt;/&gt;;
        } else {
            return (
                &lt;div className="wrapper"&gt;
                    &lt;div className="search-wrapper"&gt;
                        &lt;label htmlFor="search-form"&gt;
                            &lt;input
                                type="search"
                                name="search-form"
                                id="search-form"
                                className="search-input"
                                placeholder="Search for..."
                                value={q}
                                /*
                                // set the value of our useState q
                                //  anytime the user types in the search box
                                */
                                onChange={(e) =&gt; setQ(e.target.value)}
                            /&gt;
                            &lt;span className="sr-only"&gt;Search countries here&lt;/span&gt;
                        &lt;/label&gt;
                    &lt;/div&gt;
                    &lt;ul className="card-grid"&gt;
                        {items.map((item) =&gt; (
                            &lt;li&gt;
                                &lt;article className="card" key={item.callingCodes}&gt;
                                    &lt;div className="card-image"&gt;
                                        &lt;img src={item.flag} alt={item.name} /&gt;
                                    &lt;/div&gt;
                                    &lt;div className="card-content"&gt;
                                        &lt;h2 className="card-name"&gt;{item.name}&lt;/h2&gt;
                                        &lt;ol className="card-list"&gt;
                                            &lt;li&gt;
                                                population:{" "}
                                                &lt;span&gt;{item.population}&lt;/span&gt;
                                            &lt;/li&gt;
                                            &lt;li&gt;
                                                Region: &lt;span&gt;{item.region}&lt;/span&gt;
                                            &lt;/li&gt;
                                            &lt;li&gt;
                                                Capital: &lt;span&gt;{item.capital}&lt;/span&gt;
                                            &lt;/li&gt;
                                        &lt;/ol&gt;
                                    &lt;/div&gt;
                                &lt;/article&gt;
                            &lt;/li&gt;
                        ))}
                    &lt;/ul&gt;
                &lt;/div&gt;
            );
        }
    }

    ReactDOM.render(&lt;App /&gt;, document.getElementById("root"));
</code></pre><p>이제 우리는 검색을 담당할 함수를 만들고 우리의 반환 함수 위에 둘 겁니다.</p><pre><code class="language-jsx">return items.filter((item) =&gt; {
                return searchParam.some((newItem) =&gt; {
                    return (
                        item[newItem]
                            .toString()
                            .toLowerCase()
                            .indexOf(q.toLowerCase()) &gt; -1
                    );
                });
            });
        }
</code></pre><p>이 함수는 응답받은 아이템들을 가져와서 <code>searchParam</code> 배열에 존재하는 &nbsp;indexOF()의 값이 -1보다 큰 모든 아이템들을 반환합니다.</p><p>함수가 만들어졌으므로 이걸 사용하기 위해 반환된 데이터를 검색 함수로 감쌉니다.</p><pre><code class="language-jsx">{serach(items).map((item) =&gt; ( &lt;li&gt; // card goes here &lt;/li&gt; ))}
</code></pre><p>useState()에 저장된 데이터는 리스트 항목에 전달되기 전에 검색 함수에서 필터링 되어 작성한 쿼리와 일치하는 항목만 반환됩니다.</p><p>다음은 코드를 모두 합쳤을 때의 코드와 Codepen의 실시간 미리보기 입니다. 아래의 검색 폼으로 국가의 이름이나 수도로 어떠한 국가든지 검색해보세요.</p><figure class="kg-card kg-embed-card"><iframe id="cp_embed_wvgJWdO" src="https://codepen.io/Spruce_khalifa/embed/preview/wvgJWdO?default-tabs=js%2Cresult&amp;height=300&amp;host=https%3A%2F%2Fcodepen.io&amp;slug-hash=wvgJWdO" title="Embedded content" scrolling="no" frameborder="0" height="300" allowtransparency="true" class="cp_embed_iframe" loading="lazy" style="box-sizing: inherit; margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; font-family: inherit; font-size: 22px; vertical-align: middle; width: 720px; overflow: hidden;"></iframe></figure><p><br></p><h2 id="--4">지역으로 국가들을 필터링 하는 방법</h2><p>이제 지역별로 국가를 필터링 할 수 있도록 더 만들어 봅시다. 모든 국가를 표기하지 않고, 아프리카 또는 아시아에만 있는 국가들을 검색하고 노출하고 싶다고 가정해보세요. 리액트에서 useState()를 사용하여 구현해낼 수 있습니다.</p><h3 id="--5">지역:</h3><ol><li>아프리카</li><li>아메리카</li><li>아시아</li><li>유럽</li><li>오세아니아</li></ol><p>우리의 지역들을 알아보았으니 이제 필터 컴포넌트를 만듭시다. 첫번째로 필터의 useState를 아래와 같이 구성합니다.</p><pre><code class="language-jsx">const [filterParam, setFilterParam] = useState(["All"]);
</code></pre><p>지역이 지정되지 않은 경우 모든 국가를 표시하고 검색할 수 있기를 원하기 때문에 useState 기본값을 의도적으로 ALL로 설정했습니다.</p><pre><code class="language-jsx">&lt;select
    /*
    // here we create a basic select input
    // we set the value to the selected value
    // and update the setFilterParam() state every time onChange is called
    */
      onChange={(e) =&gt; {
      setFilterParam(e.target.value);
       }}
       className="custom-select"
       aria-label="Filter Countries By Region"&gt;
        &lt;option value="All"&gt;Filter By Region&lt;/option&gt;
        &lt;option value="Africa"&gt;Africa&lt;/option&gt;
        &lt;option value="Americas"&gt;America&lt;/option&gt;
        &lt;option value="Asia"&gt;Asia&lt;/option&gt;
        &lt;option value="Europe"&gt;Europe&lt;/option&gt;
        &lt;option value="Oceania"&gt;Oceania&lt;/option&gt;
        &lt;/select&gt;
        &lt;span className="focus"&gt;&lt;/span&gt;
        &lt;/div&gt;
</code></pre><p>이제 필터를 만들었으므로 남은 것은 검색 기능을 수정하는 것입니다. 기본적으로 입력한 지역을 확인하고 해당 지역이 있는 국가만 반환해야 합니다.</p><pre><code class="language-jsx">function search(items) {
       return items.filter((item) =&gt; {
    /*
    // in here we check if our region is equal to our c state
    // if it's equal to then only return the items that match
    // if not return All the countries
    */
       if (item.region == filterParam) {
           return searchParam.some((newItem) =&gt; {
             return (
               item[newItem]
                   .toString()
                   .toLowerCase()
                   .indexOf(q.toLowerCase()) &gt; -1
                        );
                    });
                } else if (filterParam == "All") {
                    return searchParam.some((newItem) =&gt; {
                        return (
                            item[newItem]
                                .toString()
                                .toLowerCase()
                                .indexOf(q.toLowerCase()) &gt; -1
                        );
                    });
                }
            });
        }
</code></pre><p>Codepen에서 전체 코드와 실시간 미리보기를 찾을 수 있습니다. 국가를 필터링하고 결과를 보십시오.</p><figure class="kg-card kg-embed-card"><iframe id="cp_embed_BapWzPe" src="https://codepen.io/Spruce_khalifa/embed/preview/BapWzPe?default-tabs=js%2Cresult&amp;height=300&amp;host=https%3A%2F%2Fcodepen.io&amp;slug-hash=BapWzPe" title="Embedded content" scrolling="no" frameborder="0" height="300" allowtransparency="true" class="cp_embed_iframe" loading="lazy" style="box-sizing: inherit; margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; font-family: inherit; font-size: 22px; vertical-align: middle; width: 720px; overflow: hidden;"></iframe></figure><p><br>CSS를 추가하면 이제 React 앱의 최종 미리보기를 볼 수 있습니다.</p><figure class="kg-card kg-embed-card"><iframe id="cp_embed_GRrWjmR" src="https://codepen.io/Spruce_khalifa/embed/preview/GRrWjmR?default-tabs=js%2Cresult&amp;height=300&amp;host=https%3A%2F%2Fcodepen.io&amp;slug-hash=GRrWjmR" title="Embedded content" scrolling="no" frameborder="0" height="300" allowtransparency="true" class="cp_embed_iframe" loading="lazy" style="box-sizing: inherit; margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; font-family: inherit; font-size: 22px; vertical-align: middle; width: 720px; overflow: hidden;"></iframe></figure><p><br></p><h1 id="--6">마무리</h1><p>사용자에게 표시해야 하는 많은 양의 데이터를 처리할 때 검색 및 필터 기능을 사용하면 사용자가 중요한 정보를 빠르게 탐색하고 찾을 수 있습니다. 질문이 있는 경우 저에게 연락해 주시면 기꺼이 답변해드리겠습니다. 이 프로젝트의 전체 미리보기는 여기 earthly vercel 앱에서 찾을 수 있습니다. 트위터 @sprucekhalifa에서 저를 팔로우할 수 있습니다.</p> ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
