<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>bear-frog.log</title>
        <link>https://velog.io/</link>
        <description>개굴개굴 곰개굴</description>
        <lastBuildDate>Fri, 13 Jun 2025 00:26:11 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>bear-frog.log</title>
            <url>https://velog.velcdn.com/images/bear-frog/profile/f1e394e8-6bfd-42c1-992e-9a4b440e76a5/social_profile.jpeg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. bear-frog.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/bear-frog" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[kernel multiplier benchmark]]></title>
            <link>https://velog.io/@bear-frog/kernel-multiplier-benchmark</link>
            <guid>https://velog.io/@bear-frog/kernel-multiplier-benchmark</guid>
            <pubDate>Fri, 13 Jun 2025 00:26:11 GMT</pubDate>
            <description><![CDATA[<p>schoolbook, lut, koa에 대한 bentchmark code
AES-GCM시 사용되는 GHASH-GF(2^128)-에서의 적용
kernel module로 build하여 runtime상에서 benchmark  확인 가능하도록 하였다.</p>
<p><a href="https://github.com/bear-frog/gf128mul_koa">https://github.com/bear-frog/gf128mul_koa</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Docker를 이용한 cross compile]]></title>
            <link>https://velog.io/@bear-frog/Docker%EB%A5%BC-%EC%9D%B4%EC%9A%A9%ED%95%9C-cross-compile</link>
            <guid>https://velog.io/@bear-frog/Docker%EB%A5%BC-%EC%9D%B4%EC%9A%A9%ED%95%9C-cross-compile</guid>
            <pubDate>Sun, 18 Aug 2024 09:07:26 GMT</pubDate>
            <description><![CDATA[<h3 id="개요">개요</h3>
<ul>
<li>clamav를 개발 환경에 맞춰 빌드하고 가져오는 것이 필요했다</li>
<li>환경은 기본적으로 openwrt buildroot를 이용한 크로스 컴파일이 지원되었다</li>
<li>그러나 clamav는 공유 라이브러리(so) 형식으로 종속 모듈들과 관리되어야 한다</li>
<li>clamav는 1.x 이상 버전을 사용해야 한다</li>
</ul>
<h3 id="환경구성">환경구성</h3>
<ul>
<li>glibc 2.31</li>
<li>openssl 3.0.13</li>
</ul>
<h3 id="방안">방안</h3>
<ul>
<li>docker를 사용해 cross compile을 시도했다</li>
<li>glibc 2.31을 기본으로 사용하는 ubuntu 20.04 환경에서 clamav를 빌드했다</li>
<li>현재 clamav lts (1.0.6) 이 openssl 3.x를 지원하지 않아 최근 릴리즈 버전인 1.3.1을 사용했다</li>
</ul>
<h3 id="플로우">플로우</h3>
<ul>
<li>ubuntu 20.04 docker 환경에서 clamav와 그 종속 모듈들을 빌드한다</li>
<li>빌드된 clamav와 종속 모듈들의 공유 라이브러리, clamav의 종속 헤더 파일을 각각 docker에서 압축하여 가져온다</li>
</ul>
<h3 id="사용-도커파일">사용 도커파일</h3>
<pre><code class="language-yml"># Base image 설정 (Ubuntu 20.04)
FROM ubuntu:20.04

# tzdata 설치 시 대화형 프롬프트를 피하기 위한 환경 변수 설정
ENV DEBIAN_FRONTEND=noninteractive

# 필수 패키지 설치 및 시간대 설정
RUN apt-get update &amp;&amp; \
    apt-get install -y build-essential wget libssl-dev libmspack-dev libbz2-dev zlib1g-dev \
                       libcurl4-openssl-dev libncurses5-dev cmake curl git check python3 \
                       python3-pip libxml2-dev libpcre2-dev libjson-c-dev libmilter-dev \
                       libclamav-dev ca-certificates tzdata

# Rust 및 Cargo 설치
RUN curl https://sh.rustup.rs -sSf | sh -s -- -y
ENV PATH=&quot;/root/.cargo/bin:${PATH}&quot;

# 시간대 설정 (서울 기준)
ENV TZ=Asia/Seoul
RUN ln -fs /usr/share/zoneinfo/$TZ /etc/localtime &amp;&amp; dpkg-reconfigure --frontend noninteractive tzdata

# OpenSSL 3.x 설치
RUN wget https://www.openssl.org/source/openssl-3.0.13.tar.gz &amp;&amp; \
    tar -xzf openssl-3.0.13.tar.gz &amp;&amp; \
    cd openssl-3.0.13 &amp;&amp; \
    ./config --prefix=/usr/local --openssldir=/usr/local/openssl &amp;&amp; \
    make -j$(nproc) &amp;&amp; \
    make install &amp;&amp; \
    cd .. &amp;&amp; rm -rf openssl-3.0.13*

# 환경 변수 설정
ENV LD_LIBRARY_PATH=/usr/local/lib64:/usr/local/lib:/usr/local/libcurl/lib:$LD_LIBRARY_PATH
ENV PKG_CONFIG_PATH=/usr/local/libcurl/lib/pkgconfig:$PKG_CONFIG_PATH

# libcurl 설치 (OpenSSL 3.x와 함께)
RUN wget https://curl.se/download/curl-8.0.1.tar.gz &amp;&amp; \
    tar -xzf curl-8.0.1.tar.gz &amp;&amp; \
    cd curl-8.0.1 &amp;&amp; \
    LDFLAGS=&quot;-L/usr/local/lib64&quot; CPPFLAGS=&quot;-I/usr/local/include&quot; ./configure --with-ssl=/usr/local --prefix=/usr/local/libcurl --enable-shared --disable-static &amp;&amp; \
    make -j$(nproc) &amp;&amp; \
    make install &amp;&amp; \
    cd .. &amp;&amp; rm -rf curl-8.0.1*

# ClamAV 1.3.1 설치 (OpenSSL 3.x 및 최신 libcurl 사용)
RUN wget https://www.clamav.net/downloads/production/clamav-1.3.1.tar.gz &amp;&amp; \
    tar -xzf clamav-1.3.1.tar.gz &amp;&amp; \
    cd clamav-1.3.1 &amp;&amp; \
    mkdir build &amp;&amp; cd build &amp;&amp; \
    cmake .. -DOPENSSL_ROOT_DIR=/usr/local -DOPENSSL_INCLUDE_DIR=/usr/local/include -DOPENSSL_CRYPTO_LIBRARY=/usr/local/lib64/libcrypto.so -DOPENSSL_SSL_LIBRARY=/usr/local/lib64/libssl.so -DCURL_LIBRARY=/usr/local/libcurl/lib/libcurl.so -DCURL_INCLUDE_DIR=/usr/local/libcurl/include &amp;&amp; \
    make -j$(nproc) &amp;&amp; \
    make install &amp;&amp; \
    cd ../.. &amp;&amp; rm -rf clamav-1.3.1*

# 라이브러리 및 헤더 파일 복사 및 압축
RUN mkdir -p /tmp/clamav-libs/lib /tmp/clamav-libs/include /tmp/clamav-libs/include/openssl &amp;&amp; \
    cp /usr/local/lib/libclamav.so* /tmp/clamav-libs/lib/ &amp;&amp; \
    cp /usr/local/lib/libclammspack.so* /tmp/clamav-libs/lib/ &amp;&amp; \
    cp /usr/local/include/clamav.h /tmp/clamav-libs/include/ &amp;&amp; \
    cp /usr/local/include/clamav-types.h /tmp/clamav-libs/include/ &amp;&amp; \
    cp /usr/local/include/clamav-version.h /tmp/clamav-libs/include/ &amp;&amp; \
    cp /usr/local/include/openssl/* /tmp/clamav-libs/include/openssl/ &amp;&amp; \
    cp /usr/lib/x86_64-linux-gnu/libpcre2-8.so* /tmp/clamav-libs/lib/ &amp;&amp; \
    cp /usr/local/lib64/libcrypto.so* /tmp/clamav-libs/lib/ &amp;&amp; \
    cp /usr/lib/x86_64-linux-gnu/libbz2.so* /tmp/clamav-libs/lib/ &amp;&amp; \
    cp /usr/local/lib64/libssl.so* /tmp/clamav-libs/lib/ &amp;&amp; \
    cp /usr/lib/x86_64-linux-gnu/libz.so* /tmp/clamav-libs/lib/ &amp;&amp; \
    cp /usr/lib/x86_64-linux-gnu/libjson-c.so* /tmp/clamav-libs/lib/ &amp;&amp; \
    cp /usr/lib/x86_64-linux-gnu/libxml2.so* /tmp/clamav-libs/lib/ &amp;&amp; \
    cp /usr/lib/x86_64-linux-gnu/libicuuc.so* /tmp/clamav-libs/lib/ &amp;&amp; \
    cp /usr/lib/x86_64-linux-gnu/libicudata.so* /tmp/clamav-libs/lib/ &amp;&amp; \
    tar -czvf /tmp/clamav-libs.tar.gz -C /tmp clamav-libs

# 기본 명령어 설정
CMD [&quot;clamscan&quot;, &quot;--version&quot;]
</code></pre>
<h3 id="테스트-코드c">테스트 코드(c)</h3>
<pre><code class="language-c">#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;clamav.h&gt;

int main(int argc, char **argv) {
    if (argc != 2) {
        fprintf(stderr, &quot;Usage: %s &lt;file_to_scan&gt;\n&quot;, argv[0]);
        return 1;
    }

    const char *filename = argv[1];
    const char *dbdir = &quot;./clamav-db&quot;;  // 데이터베이스 디렉터리 경로
    int ret;
    unsigned long int scanned = 0;
    const char *virname = NULL;

    // Initialize ClamAV
    if ((ret = cl_init(CL_INIT_DEFAULT)) != CL_SUCCESS) {
        fprintf(stderr, &quot;cl_init() error: %s\n&quot;, cl_strerror(ret));
        return 1;
    }

    // Create a new scan engine
    struct cl_engine *engine = cl_engine_new();
    if (!engine) {
        fprintf(stderr, &quot;cl_engine_new() error: %s\n&quot;, cl_strerror(CL_EMEM));
        return 1;
    }

    // Load the virus signature database from the specified directory
    unsigned int sigs = 0;
    if ((ret = cl_load(dbdir, engine, &amp;sigs, CL_DB_STDOPT)) != CL_SUCCESS) {
        fprintf(stderr, &quot;cl_load() error: %s\n&quot;, cl_strerror(ret));
        cl_engine_free(engine);
        return 1;
    }

    printf(&quot;Loaded %u virus signatures from %s.\n&quot;, sigs, dbdir);

    // Compile the engine
    if ((ret = cl_engine_compile(engine)) != CL_SUCCESS) {
        fprintf(stderr, &quot;cl_engine_compile() error: %s\n&quot;, cl_strerror(ret));
        cl_engine_free(engine);
        return 1;
    }

    // Define scan options
    struct cl_scan_options scan_options = {
        .general = CL_SCAN_GENERAL_ALLMATCHES | CL_SCAN_GENERAL_HEURISTICS | CL_SCAN_GENERAL_UNPRIVILEGED, // 표준 스캔 옵션
        .parse = CL_SCAN_PARSE_ARCHIVE | CL_SCAN_PARSE_ELF | CL_SCAN_PARSE_PDF | CL_SCAN_PARSE_MAIL,      // 추가 파싱 옵션
        .heuristic = CL_SCAN_HEURISTIC_BROKEN | CL_SCAN_HEURISTIC_MACROS,                                 // 휴리스틱 옵션
        .mail = CL_SCAN_MAIL_PARTIAL_MESSAGE,                                                            // 메일 스캔 옵션
        .dev = 0                                                                                         // 개발 옵션 (사용하지 않음)
    };

    // Scan the file
    ret = cl_scanfile(filename, &amp;virname, &amp;scanned, engine, &amp;scan_options);
    if (ret == CL_VIRUS) {
        printf(&quot;Virus found: %s\n&quot;, virname);
    } else if (ret == CL_CLEAN) {
        printf(&quot;No virus found in %s\n&quot;, filename);
    } else {
        fprintf(stderr, &quot;cl_scanfile() error: %s\n&quot;, cl_strerror(ret));
    }

    // Clean up
    cl_engine_free(engine);
    return 0;
}
</code></pre>
<h3 id="빌드">빌드</h3>
<ul>
<li><code>gcc -o clamscan_example clamscan_example.c -I./include -L./lib -lclamav -Wl,-rpath=./lib</code></li>
</ul>
<h3 id="테스트">테스트</h3>
<ul>
<li>eicar에서 테스트 악성코드를 가져와서 테스트했다<ul>
<li><code>wget -O eicar_com.zip &quot;https://www.eicar.org/download/eicar_com-zip/?wpdmdl=8847&amp;refresh=66c1ae90c82bb1723969168&quot;</code></li>
</ul>
</li>
<li><code>LD_LIBRARY_PATH=/tmp/workplace/clamav-libs/lib ./clamscan_example eicar_com.zip</code></li>
<li>결과<pre><code class="language-shell">root@4dd1c9322fad:/tmp/workplace/clamav-libs# LD_LIBRARY_PATH=/tmp/workplace/clamav-libs/lib ./clamscan_example eicar_com.zip
Loaded 8697521 virus signatures from ./clamav-db.
Virus found: Win.Test.EICAR_HDB-1</code></pre>
</li>
</ul>
<h3 id="참조-바이러스-데이터베이스">참조: 바이러스 데이터베이스</h3>
<ul>
<li>main.cvd: <a href="https://database.clamav.net/main.cvd">https://database.clamav.net/main.cvd</a></li>
<li>daily.cvd: <a href="https://database.clamav.net/daily.cvd">https://database.clamav.net/daily.cvd</a></li>
<li>bytecode.cvd: <a href="https://database.clamav.net/bytecode.cvd">https://database.clamav.net/bytecode.cvd</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Vue.js: reactive? ref?]]></title>
            <link>https://velog.io/@bear-frog/Vue.js-reactive-ref</link>
            <guid>https://velog.io/@bear-frog/Vue.js-reactive-ref</guid>
            <pubDate>Sat, 23 Mar 2024 10:56:52 GMT</pubDate>
            <description><![CDATA[<h3 id="vuejs에서의-반응형">Vue.js에서의 반응형</h3>
<p><img src="https://velog.velcdn.com/images/bear-frog/post/8135a616-4ce1-48e1-b242-fca3ecf51fcd/image.png" alt=""></p>
<blockquote>
<p>Vue 마을에서는 View와 ViewModel 사이 통신할 방법이 필요하다.
하지만 일반 JS값들의 변화는 감지할 방법이 없다</p>
</blockquote>
<h3 id="객체의-경우">객체의 경우</h3>
<p><img src="https://velog.velcdn.com/images/bear-frog/post/4294de4d-0c42-4f46-8308-6ca172c96afb/image.png" alt=""></p>
<blockquote>
<p>객체의 경우 JS의 Proxy 객체를 사용하면 된다.
이를 통해 객체의 변화를 감지하고, View와 ViewModel 사이의 반응형을 구현할 수 있다.</p>
</blockquote>
<p><strong>이것이 reactive</strong></p>
<h3 id="하지만-원시-데이터에서는">하지만 원시 데이터에서는</h3>
<p><img src="https://velog.velcdn.com/images/bear-frog/post/ecc3a47c-8687-4cd1-bcde-586190dfa286/image.png" alt=""></p>
<blockquote>
<p>원시 데이터 형태의 경우 Proxy객체에 등록이 불가하다
이런!</p>
</blockquote>
<h3 id="방법은-있다">방법은 있다</h3>
<p><img src="https://velog.velcdn.com/images/bear-frog/post/99d310d3-fe36-4927-9e14-5c6cb2ef5850/image.png" alt=""></p>
<blockquote>
<p>원시 데이터를 래핑하여 객체로 만들고, 래핑된 객체를 Proxy에 등록한다.
이를 통해 원시 데이터에 대한 변화가 감지되고, View와 ViewModel 사이의 반응형을 구현할 수 있다.</p>
</blockquote>
<p><strong>이것이 ref</strong></p>
<blockquote>
<p>이 때문에 ref에서는 .value를 통한 값 참조가 필요하다</p>
</blockquote>
<h3 id="잘-됐네-잘-됐어">잘 됐네 잘 됐어</h3>
<p><img src="https://velog.velcdn.com/images/bear-frog/post/6db4e1b6-1e04-4d1d-9952-9cdb6c5137ed/image.png" alt=""></p>
<blockquote>
<p>이렇게 Vue 마을은 평화로워졌다</p>
</blockquote>
<h3 id="참조">참조</h3>
<ul>
<li>vue core<ul>
<li>링크: <a href="https://github.com/vuejs/core">https://github.com/vuejs/core</a></li>
</ul>
</li>
<li>reactive, ref의 구현 방식을 확인해보면 더 명확하다</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Vue.js 공식문서 5. Reactivity Fundamentals]]></title>
            <link>https://velog.io/@bear-frog/Vue.js-%EA%B3%B5%EC%8B%9D%EB%AC%B8%EC%84%9C-5.-Reactivity-Fundamentals</link>
            <guid>https://velog.io/@bear-frog/Vue.js-%EA%B3%B5%EC%8B%9D%EB%AC%B8%EC%84%9C-5.-Reactivity-Fundamentals</guid>
            <pubDate>Fri, 15 Mar 2024 12:11:45 GMT</pubDate>
            <description><![CDATA[<h3 id="1-why-ref-why-reactive">1. Why, ref? Why, reactive?</h3>
<ul>
<li>View와 ViewModal 사이의 반응형 바인딩 구현</li>
<li>Vue는 반응형 프로그래밍 모델을 기반</li>
</ul>
<p><strong>상태의 변화가 자동으로 UI를 업데이트하도록 하는 것</strong>
<strong>애플리케이션의 상태와 UI 사이의 동기화를 자동으로 관리</strong>
<strong>ref와 reactive는 뷰(View)와 뷰모델(ViewModel) 사이의 연결고리 역할</strong></p>
<h4 id="vuejs-반응형-프로그래밍-모델">Vue.js: 반응형 프로그래밍 모델</h4>
<blockquote>
<p>반응형 프로그래밍 모델은 애플리케이션의 상태 변화를 자동으로 감지하고, 이러한 변화에 의존하는 다른 부분(주로 UI 컴포넌트)을 자동으로 업데이트하는 프로그래밍 패러다임</p>
</blockquote>
<h3 id="2-ref">2. ref</h3>
<h4 id="ref의-작동-원리">ref의 작동 원리</h4>
<ul>
<li>ref는 Vue.js에서 제공하는 함수로, 주어진 값을 반응형 참조 객체로 래핑합니다. </li>
<li>이 객체는 .value 속성을 통해 실제 값을 보유합니다. </li>
<li>ref로 생성된 참조 객체는 Vue의 반응형 시스템에 의해 관리됩니다.<ul>
<li>이 시스템은 .value 속성에 접근하거나 수정할 때마다 이를 감지합니다.</li>
</ul>
</li>
</ul>
<p><strong>접근 시:</strong> Vue의 반응형 시스템은 해당 참조가 읽힐 때(즉, .value가 접근될 때) 그 접근을 추적합니다. 이는 나중에 의존성이 있는 컴포넌트를 업데이트할 수 있는 기반을 마련합니다.
<strong>수정 시:</strong> .value 속성의 값이 변경될 때, Vue는 이전에 추적한 의존성을 기반으로 하여 변경 사항을 감지하고, 관련된 컴포넌트의 재렌더링을 트리거합니다.</p>
<blockquote>
<p>이 메커니즘을 통해, ref는 Vue 애플리케이션 내에서 데이터의 변화를 실시간으로 감지하고 반응할 수 있게 합니다.</p>
</blockquote>
<h4 id="ref의-본질적-목적">ref의 본질적 목적</h4>
<ul>
<li>ref의 본질적 목적은 원시 값 또는 복잡한 객체를 반응형 데이터로 관리하여, Vue 컴포넌트의 상태와 UI 사이의 자동 동기화를 달성하는 것입니다. </li>
<li>원시 값들(문자열, 숫자, 불리언 등)은 직접적으로 반응형으로 만들 수 없기 때문에, ref는 이러한 값들을 .value 속성을 사용하여 래핑하고 관리함으로써 반응형 시스템의 일부로 통합합니다.</li>
</ul>
<p><strong>원시 값 관리:</strong> ref는 원시 값에 대한 반응형 래퍼를 제공함으로써, 값의 변경을 자동으로 감지하고, 이에 따라 UI를 업데이트할 수 있도록 합니다.
<strong>UI와 상태의 동기화:</strong> 데이터 상태의 변화가 Vue 컴포넌트의 UI 업데이트를 자동으로 촉발함으로써, 개발자는 데이터 관리와 UI 업데이트 사이의 동기화 로직에 대해 걱정할 필요가 없습니다.</p>
<blockquote>
<p>결론적으로, ref의 본질적 목적은 Vue 애플리케이션 개발에서 선언적 UI 프로그래밍을 가능하게 하는 것입니다.</p>
</blockquote>
<pre><code class="language-vue">&lt;script setup&gt;
import { ref, reactive } from &#39;vue&#39;

const data = {a: 1, b: 2, c: 3};
const refData = ref(data);
console.log(&#39;origin data&#39;, data)
console.log(&#39;reactiveData&#39;, refData)
console.log(&#39;============change original data============&#39;)
data.a = 10
console.log(&#39;origin data&#39;, data)
console.log(&#39;reactiveData&#39;, refData)
console.log(&#39;============change reactive data============&#39;)
refData.value.a = 100
console.log(&#39;origin data&#39;, data)
console.log(&#39;reactiveData&#39;, refData)
// 원본 객체의 변환
// 반응형 값, 원본 객체 모두 변화(프록시 객체도 원본 값 참조) 하지만 반응형 미동작
const handleOriginalData = () =&gt; {
  console.log(&#39;============change original data============&#39;)
  data.a += 1
  console.log(&#39;origin data&#39;, data)
  console.log(&#39;reactiveData&#39;, refData)
}
// 반응형 객체의 변환
// 반응형 값, 원본 객체 모두 변화하고 반응형 동작
// template과 script에 대한 양방향 바인딩이 반응형을 통해 동작
const handleReactiveData = () =&gt; {
  console.log(&#39;============change reactive data============&#39;)
  refData.value.a += 1
  console.log(&#39;origin data&#39;, data)
  console.log(&#39;reactiveData&#39;, refData)
}
&lt;/script&gt;

&lt;template&gt;
  &lt;h4&gt;{{`original data: ${JSON.stringify(data)}`}}&lt;/h4&gt;
  &lt;h4&gt;{{ `reactive data: ${JSON.stringify(refData)}` }}&lt;/h4&gt;
  &lt;input value=&quot;original data&quot; type=&quot;button&quot; @click=&quot;handleOriginalData&quot;/&gt;
  &lt;input value=&quot;reactive data&quot; type=&quot;button&quot; @click=&quot;handleReactiveData&quot;/&gt;
&lt;/template&gt;</code></pre>
<h3 id="3-reactive">3. reactive</h3>
<h3 id="reactive의-작동-원리">reactive의 작동 원리</h3>
<ul>
<li>reactive는 객체를 받아 이를 반응형으로 만드는 Vue.js의 Composition API 기능입니다.</li>
<li>이는 JavaScript의 Proxy 객체를 사용하여 작동합니다.</li>
<li>Proxy를 통해 객체의 모든 속성 접근, 수정 및 삭제 등의 작업을 감지하고, 이러한 작업이 발생할 때 Vue의 반응형 시스템에 알려 UI가 적절히 업데이트되도록 합니다.</li>
</ul>
<p><strong>객체 감지:</strong> reactive로 만들어진 객체에 접근하거나 수정할 때, 내부적으로 Proxy의 get, set 트랩이 활성화됩니다. 이는 Vue가 해당 객체의 읽기 및 쓰기 작업을 추적할 수 있게 해줍니다.
<strong>자동 업데이트:</strong> 객체의 속성이 변경되면, reactive는 Vue의 반응형 시스템을 통해 이 변경사항을 감지하고, 해당 변경사항에 의존하는 컴포넌트를 자동으로 재렌더링합니다.</p>
<h3 id="reactive의-본질적-목적">reactive의 본질적 목적</h3>
<ul>
<li>reactive의 본질적 목적은 객체나 배열과 같은 복잡한 데이터 구조를 전체적으로 반응형으로 만들어, 애플리케이션 상태의 변화가 자동으로 UI에 반영되도록 하는 것입니다.</li>
<li>이를 통해 데이터와 UI 사이의 동기화를 쉽고 효율적으로 관리할 수 있습니다.</li>
</ul>
<p><strong>복잡한 데이터 구조 관리:</strong> reactive는 깊은 반응형 변환을 제공하여, 객체 내부의 중첩된 데이터까지 반응형으로 만들 수 있습니다. 이를 통해 개발자는 복잡한 데이터 구조를 쉽게 관리하고, 상태 변화에 따른 UI 업데이트를 자동으로 처리할 수 있습니다.
<strong>효율적인 상태 관리:</strong> reactive를 사용하면, 애플리케이션의 상태 로직을 더 선언적이고 직관적으로 작성할 수 있습니다. 개발자는 상태 변경에 따른 UI 업데이트 로직을 별도로 구현할 필요 없이, 데이터 상태에 집중할 수 있습니다.</p>
<pre><code class="language-vue">#### &lt;script setup&gt;
import { ref, reactive } from &#39;vue&#39;

const data = {a: 1, b: 2, c: 3};
const reactiveData = reactive(data);
console.log(&#39;origin data&#39;, data)
console.log(&#39;reactiveData&#39;, reactiveData)
console.log(&#39;============change original data============&#39;)
data.a = 10
console.log(&#39;origin data&#39;, data)
console.log(&#39;reactiveData&#39;, reactiveData)
console.log(&#39;============change reactive data============&#39;)
reactiveData.a = 100
console.log(&#39;origin data&#39;, data)
console.log(&#39;reactiveData&#39;, reactiveData)
// 원본 객체의 변환
// 반응형 값, 원본 객체 모두 변화(프록시 객체도 원본 값 참조) 하지만 반응형 미동작
const handleOriginalData = () =&gt; {
  console.log(&#39;============change original data============&#39;)
  data.a += 1
  console.log(&#39;origin data&#39;, data)
  console.log(&#39;reactiveData&#39;, reactiveData)
}
// 반응형 객체의 변환
// 반응형 값, 원본 객체 모두 변화하고 반응형 동작
// template과 script에 대한 양방향 바인딩이 반응형을 통해 동작
const handleReactiveData = () =&gt; {
  console.log(&#39;============change reactive data============&#39;)
  reactiveData.a += 1
  console.log(&#39;origin data&#39;, data)
  console.log(&#39;reactiveData&#39;, reactiveData)
}
&lt;/script&gt;

&lt;template&gt;
  &lt;h4&gt;{{`original data: ${JSON.stringify(data)}`}}&lt;/h4&gt;
  &lt;h4&gt;{{ `reactive data: ${JSON.stringify(reactiveData)}` }}&lt;/h4&gt;
  &lt;input value=&quot;original data&quot; type=&quot;button&quot; @click=&quot;handleOriginalData&quot;/&gt;
  &lt;input value=&quot;reactive data&quot; type=&quot;button&quot; @click=&quot;handleReactiveData&quot;/&gt;
&lt;/template&gt;
</code></pre>
<h3 id="4-ref-vs-reactive">4. ref vs. reactive</h3>
<h4 id="ref-vs-reactive-in-array">ref vs. reactive in array</h4>
<h4 id="왜-ref에는-value가-존재하는가">왜 ref에는 .value가 존재하는가?</h4>
]]></description>
        </item>
        <item>
            <title><![CDATA[CSR? SSR? SSG?]]></title>
            <link>https://velog.io/@bear-frog/SPA-SSR-SSG</link>
            <guid>https://velog.io/@bear-frog/SPA-SSR-SSG</guid>
            <pubDate>Wed, 13 Mar 2024 07:26:58 GMT</pubDate>
            <description><![CDATA[<p>검색을 해 봐도 어려운 얘기들만 있는 것 같아서,
내가 이해한 내용 바탕으로 적어본다.</p>
<h3 id="csrclient-side-rendering">CSR(Client Side Rendering)</h3>
<p><img src="https://velog.velcdn.com/images/bear-frog/post/bc5dfc34-f2f5-4718-accc-c13383f4f821/image.png" alt=""></p>
<ul>
<li>페이지 렌더링의 주체가 클라이언트에 있다<ul>
<li>빌드 시 클라이언트 배포 파일만이 생성된다</li>
</ul>
</li>
<li>.js파일이 페이지를 렌더링한다</li>
<li>클라이언트 코드는 페이지를 렌더링하는 .js 파일을 가지고 있다</li>
<li>사용자가 특정 페이지를 요청하면 클라이언트가 가진 .js 파일이 해석되어 해당 페이지를 렌더링하게 된다</li>
</ul>
<h3 id="ssrserver-side-rendering">SSR(Server Side Rendering)</h3>
<p><img src="https://velog.velcdn.com/images/bear-frog/post/4445bf6c-e00a-4f40-8a78-d36338348113/image.png" alt=""></p>
<ul>
<li>페이지 렌더링의 주체가 서버에 있다<ul>
<li>빌드 시 클라이언트, 서버 배포 파일이 생성된다</li>
<li>SSR에서 풀 스택 개발이 가능한 이유</li>
</ul>
</li>
<li>.js 파일이 페이지를 렌더링한다</li>
<li>서버 코드는 페이지를 렌더링하는 .js파일을 가지고 있다</li>
<li>사용자가 특정 페이지 요청 시 서버가 가진 .js파일이 해석되어 해당 페이지를 렌더링하게 된다.</li>
</ul>
<h3 id="ssgstatic-site-generation">SSG(Static Site Generation)</h3>
<p><img src="https://velog.velcdn.com/images/bear-frog/post/d8d99995-b830-4549-be71-27f30da3cc00/image.png" alt=""></p>
<ul>
<li>빌드 시 모든 파일을 정적으로 생성한다</li>
<li>Web 1.0과 비슷한 개념<ul>
<li>사용자의 상호작용을 배제한, View에 집중한 웹 제작</li>
</ul>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Vue.js 공식문서 1. Introduction]]></title>
            <link>https://velog.io/@bear-frog/Vue.js-%EA%B3%B5%EC%8B%9D%EB%AC%B8%EC%84%9C-1.-Introduction</link>
            <guid>https://velog.io/@bear-frog/Vue.js-%EA%B3%B5%EC%8B%9D%EB%AC%B8%EC%84%9C-1.-Introduction</guid>
            <pubDate>Mon, 11 Mar 2024 04:57:46 GMT</pubDate>
            <description><![CDATA[<p>Vue.js 공식문서를 공부하면서 이해가 안 되는 부분만 작성해보려 한다.</p>
<h3 id="1-introduction">1. Introduction</h3>
<ul>
<li>링크: <a href="https://v3-docs.vuejs-korea.org/guide/introduction.html">https://v3-docs.vuejs-korea.org/guide/introduction.html</a></li>
</ul>
<h3 id="2-선언적-명령적">2. 선언적? 명령적?</h3>
<ul>
<li><p>원문</p>
<pre><code>선언적 렌더링(Declarative Rendering): 
Vue는 표준 HTML을 템플릿 문법으로 확장하여 
JavaScript 상태(State)를 기반으로 화면에 출력될 HTML을 
선언적(declaratively)으로 작성할 수 있습니다.</code></pre><h4 id="21-명령적-프로그래밍">2.1 명령적 프로그래밍</h4>
</li>
<li><p>명령적 프로그래밍은 어떻게(How) 작업을 수행할 것인지를 구체적으로 지시하는 방식</p>
</li>
<li><p>알고리즘의 각 단계와 절차를 명확하게 명시</p>
</li>
<li><p>컴퓨터가 수행해야 할 명령을 순서대로 나열</p>
</li>
<li><p>특징</p>
<ul>
<li>작업을 수행하기 위한 단계적인 절차와 명령을 개발자가 직접 작성</li>
<li>명시적인 상태 관리<ul>
<li>프로그램의 상태는 변수에 의해 추적되고, 상태 변경을 위해 변수에 명시적으로 값을 할당<blockquote>
<p>예: 전통적인 for 루프를 사용하여 배열의 모든 요소에 대해 특정 작업을 수행하는 경우, 각 단계(초기화, 조건 검사, 카운터 증가)를 명시적으로 지정</p>
</blockquote>
</li>
</ul>
</li>
</ul>
</li>
<li><p>코드 예시</p>
<pre><code class="language-js">let sum = 0;
const numbers = [1, 2, 3, 4, 5];
for (let i = 0; i &lt; numbers.length; i++) {
sum += numbers[i]; // 명령을 통해 sum의 상태를 직접 변경
}</code></pre>
<h4 id="22-선언적-프로그래밍">2.2 선언적 프로그래밍</h4>
</li>
<li><p>선언적 프로그래밍은 <strong><em>무엇(What)</em></strong> 을 할 것인지에 초점을 맞춤</p>
</li>
<li><p>개발자는 결과를 얻기 위한 목표만을 선언</p>
</li>
<li><p>그 과정(어떻게 도달할 것인지)에 대해서는 신경 쓰지 않음</p>
</li>
<li><p>프로그램이 최종적으로 달성하고자 하는 결과를 기술하는 데 집중</p>
</li>
<li><p>함수형 프로그래밍이 좋은 예시인 듯...</p>
</li>
<li><p>특징:</p>
<ul>
<li>프로그램의 로직보다는 원하는 결과에 더 집중</li>
<li>고수준 추상화  <ul>
<li>내부적으로 복잡한 로직이나 상태 관리를 프레임워크나 라이브러리가 처리<blockquote>
<p>예: SQL 쿼리는 선언적 프로그래밍의 좋은 예입니다. 데이터를 어떻게 가져올지 구체적인 절차를 쓰지 않고, 무엇을 가져오고 싶은지를 &quot;선언&quot;합니다.</p>
</blockquote>
</li>
</ul>
</li>
</ul>
</li>
<li><p>코드 예시</p>
<pre><code class="language-js">// reduce 메서드로 배열의 값을 순회하며 축적하는 연산을 수행한다는 &quot;선언&quot;
// reduce 함수를 통해 &quot;무엇을&quot; 하고 싶은지를 선언
// &quot;어떻게&quot; 그 연산이 내부적으로 수행되는지는 중요하지 않음
const sum = numbers.reduce((acc, curr) =&gt; acc + curr, 0);</code></pre>
<h4 id="23-명령적-렌더링">2.3 명령적 렌더링</h4>
</li>
<li><p>명령적 렌더링은 개발자가 단계별로 어떻게(UI를 어떻게 변경할 것인지)와 같은 과정을 자세히 지정해야 하는 방식</p>
</li>
<li><p>특정 조건이나 이벤트 발생 시 DOM을 직접 조작하여 UI를 업데이트하는 과정을 개발자가 모두 명시해야 함</p>
</li>
<li><p>예시</p>
<pre><code class="language-js">let count = 0; // 상태 초기화
</code></pre>
</li>
</ul>
<p>document.getElementById(&#39;button&#39;).addEventListener(&#39;click&#39;, function() {
  count++; // 상태 업데이트
  document.getElementById(&#39;counter&#39;).innerText = count; // UI 업데이트
});</p>
<pre><code>#### 2.4 선언적 렌더링
* 선언적 렌더링은 &quot;무엇(What)&quot;을 할 것인지에 초점
* UI의 최종 상태를 선언하고, 데이터 상태의 변화에 따라 프레임워크가 자동으로 UI를 해당 상태로 만듦
* 개발자는 UI가 어떤 조건에서 어떻게 보여져야 하는지를 선언
* 상태 변화 시 UI 업데이트 과정은 Vue.js 같은 프레임워크가 알아서 처리
* 예시
  * 개발자는 &quot;버튼을 클릭했을 때 화면에 표시되는 숫자를 증가시킨다&quot;는 최종 상태만 선언
```js
import { createApp } from &#39;vue&#39;

createApp({
  data() {
    return {
      count: 0
    }
  }
}).mount(&#39;#app&#39;)</code></pre><pre><code class="language-html">&lt;div id=&quot;app&quot;&gt;
  &lt;button @click=&quot;count++&quot;&gt;
    숫자 세기: {{ count }}
  &lt;/button&gt;
&lt;/div&gt;</code></pre>
<h3 id="3-vue의-사용처">3. Vue의 사용처</h3>
<ul>
<li>원문
```
Vue를 다양한 방식으로 사용</li>
<li>빌드 과정 없이 정적 HTML에 적용</li>
<li>모든 페이지에 웹 컴포넌트로 추가</li>
<li>싱글 페이지 어플리케이션 (SPA: Single-Page Application)</li>
<li>Fullstack / 서버 사이드 렌더링 (SSR: Server-Side-Rendering)</li>
<li>Jamstack / 정적 사이트 생성 (SSG: Static-Site-Generation)</li>
<li>데스크톱, 모바일, WebGL 또는 터미널을 대상으로 하는 경우<pre><code></code></pre></li>
</ul>
<h4 id="31-spasingle-page-application">3.1 SPA(Single-Page Application)</h4>
<ol>
<li>SPA의 핵심 특징<ul>
<li>단일 웹 페이지로 구성됨.</li>
<li>사용자 상호작용에 따라 콘텐츠를 동적으로 업데이트함.</li>
<li>전체 페이지 리로드 없이 필요한 데이터만 서버로부터 불러옴.</li>
<li>프론트엔드 라우팅을 통해 다중 페이지 탐색 효과 제공.</li>
</ul>
</li>
<li>SPA의 장점<ul>
<li>부드럽고 빠른 사용자 경험 제공.</li>
<li>초기 로딩 이후 향상된 애플리케이션 성능.</li>
<li>프론트엔드와 백엔드 분리로 개발 용이성 증가.</li>
<li>현대 프론트엔드 프레임워크(Vue.js, React, Angular 등)로 구현 가능.</li>
</ul>
</li>
<li>SPA의 단점<ul>
<li>SEO 최적화에 어려움이 있을 수 있음.</li>
<li>애플리케이션의 JavaScript 파일 전체를 처음에 로드해야 하므로 초기 로딩 시간이 길어질 수 있음.</li>
</ul>
</li>
<li>결론<ul>
<li>현대 웹 개발에서 사용자 경험을 중시하는 애플리케이션에 적합함.</li>
<li>데스크탑 애플리케이션과 유사한 경험 제공을 목표로 함.</li>
<li>SEO 최적화와 초기 로딩 속도는 프로젝트 요구 사항과 목표에 따라 고려해야 함.<h4 id="32-ssrserver-side-rendering">3.2 SSR(Server-Side-Rendering)</h4>
</li>
</ul>
</li>
<li>SSR의 핵심 특징<ul>
<li>서버에서 초기 페이지 렌더링을 수행함.</li>
<li>클라이언트에 전송되기 전에 HTML이 완성됨.</li>
<li>사용자 요청에 따라 각 페이지를 서버에서 실시간으로 생성함.</li>
<li>초기 페이지 로드 시 필요한 HTML, CSS, JavaScript를 함께 전송함.</li>
</ul>
</li>
<li>SSR의 장점<ul>
<li>향상된 SEO: 검색 엔진이 콘텐츠를 더 쉽게 인덱싱할 수 있음.</li>
<li>빠른 초기 페이지 로딩: 사용자에게 초기 콘텐츠를 빠르게 제공함.</li>
<li>사용자 체감 성능 개선: 사용자가 첫 화면을 빠르게 볼 수 있음.</li>
</ul>
</li>
<li>SSR의 단점<ul>
<li>서버 부하 증가: 모든 페이지 요청에 대해 서버에서 렌더링 수행 필요.</li>
<li>개발 복잡성 증가: 클라이언트와 서버 코드를 동기화해야 함.</li>
<li>캐싱 전략 필요: 효율적인 리소스 관리를 위해 캐싱 전략이 필요함.</li>
</ul>
</li>
<li>결론<ul>
<li>SSR은 SEO와 초기 로딩 성능을 중시하는 애플리케이션에 적합함.</li>
<li>사용자에게 빠른 콘텐츠 제공을 목표로 함.</li>
<li>서버 부하와 개발 복잡성을 고려하여 적절한 사용 사례에 적용해야 함.<h4 id="33-ssgstatic-site-generation">3.3 SSG(Static-Site-Generation)</h4>
</li>
</ul>
</li>
<li>SSG의 핵심 특징<ul>
<li>빌드 타임에 사이트의 모든 페이지를 HTML로 미리 생성함.</li>
<li>서버는 사전에 생성된 정적 파일을 직접 제공함.</li>
<li>동적 서버 사이드 프로세스 없이 정적 파일만으로 구성됨.</li>
<li>데이터 변경 시 새로운 빌드를 통해 사이트를 재생성해야 함.</li>
</ul>
</li>
<li>SSG의 장점<ul>
<li>빠른 로딩 속도: 서버에서 처리할 동적 콘텐츠가 없어 빠르게 로드됨.</li>
<li>보안 강화: 서버 사이드 코드 실행 없이 정적 파일만 제공되므로 보안성이 높음.</li>
<li>호스팅 용이성: 정적 파일을 제공하므로 간단한 서버 구성 또는 CDN 사용 가능.</li>
<li>SEO 최적화: 검색 엔진이 정적 HTML 페이지를 쉽게 크롤링하고 인덱싱함.</li>
</ul>
</li>
<li>SSG의 단점<ul>
<li>동적 기능 제한: 사전에 생성된 정적 페이지로 동적 인터랙션이 제한됨.</li>
<li>빌드 시간: 사이트가 커질수록 빌드 시간이 길어질 수 있음.
콘텐츠 업데이트 지연: 콘텐츠 변경 시 전체 사이트 재빌드 필요.</li>
</ul>
</li>
<li>결론<ul>
<li>SSG는 보안성이 높고, 로딩 속도가 빠른 정적 웹사이트에 적합함.</li>
<li>블로그, 마케팅 사이트, 문서화 프로젝트 등 변하지 않는 콘텐츠를 다루는 사이트에 이상적임.</li>
<li>동적 기능이 필요한 경우, 클라이언트 사이드 JavaScript 또는 서버리스 함수와 결합하여 사용해야 함.</li>
</ul>
</li>
</ol>
<h3 id="4-참조">4. 참조</h3>
<ul>
<li>명령형 프로그래밍<ul>
<li><a href="https://ko.wikipedia.org/wiki/%EB%AA%85%EB%A0%B9%ED%98%95_%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D">https://ko.wikipedia.org/wiki/%EB%AA%85%EB%A0%B9%ED%98%95_%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D</a></li>
</ul>
</li>
<li>선언형 프로그래밍<ul>
<li><a href="https://ko.wikipedia.org/wiki/%EC%84%A0%EC%96%B8%ED%98%95_%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D">https://ko.wikipedia.org/wiki/%EC%84%A0%EC%96%B8%ED%98%95_%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D</a></li>
</ul>
</li>
<li>선언형 프로그래밍으로 이해하기 쉬운 코드 작성하기<ul>
<li><a href="https://yozm.wishket.com/magazine/detail/2083/">https://yozm.wishket.com/magazine/detail/2083/</a></li>
</ul>
</li>
<li><code>[프로그래밍 언어론]</code> 명령형(Imperative)프로그래밍과 선언형(Declarative)프로그래밍<ul>
<li><a href="https://code-lab1.tistory.com/244">https://code-lab1.tistory.com/244</a></li>
</ul>
</li>
</ul>
<ul>
<li>Naver D2: 어서 와, SSR은 처음이지?<ul>
<li><a href="https://d2.naver.com/helloworld/7804182">https://d2.naver.com/helloworld/7804182</a></li>
</ul>
</li>
<li>SSR 시작하기 전 알아야 할 것들 (feat. CSR)<ul>
<li><a href="https://yozm.wishket.com/magazine/detail/2330/">https://yozm.wishket.com/magazine/detail/2330/</a></li>
</ul>
</li>
<li>(번역)도대체 SSG가 뭘까요? Next.js로 설명하는 정적 사이트 생성<ul>
<li><a href="https://velog.io/@lky5697/what-the-heck-is-ssg-static-site-generation-explained-with-nextjs">https://velog.io/@lky5697/what-the-heck-is-ssg-static-site-generation-explained-with-nextjs</a></li>
</ul>
</li>
<li>정적 사이트 생성자란?<ul>
<li><a href="https://www.cloudflare.com/ko-kr/learning/performance/static-site-generator/">https://www.cloudflare.com/ko-kr/learning/performance/static-site-generator/</a></li>
</ul>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[프로그래머스 가장 많이 받은 선물 javascript]]></title>
            <link>https://velog.io/@bear-frog/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EA%B0%80%EC%9E%A5-%EB%A7%8E%EC%9D%B4-%EB%B0%9B%EC%9D%80-%EC%84%A0%EB%AC%BC-javascript</link>
            <guid>https://velog.io/@bear-frog/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EA%B0%80%EC%9E%A5-%EB%A7%8E%EC%9D%B4-%EB%B0%9B%EC%9D%80-%EC%84%A0%EB%AC%BC-javascript</guid>
            <pubDate>Sun, 07 Jan 2024 07:26:39 GMT</pubDate>
            <description><![CDATA[<p><a href="https://school.programmers.co.kr/learn/courses/30/lessons/258712">문제 링크</a></p>
<h4 id="문제-해석">문제 해석</h4>
<ol>
<li>개인이 주고받은 선물 지수를 계산해야 한다<ul>
<li><code>선물 지수 = total(받은 선물) + -1 * total(준 선물)</code></li>
<li>위 계산식을 통해 선물 지수를 계산한다</li>
</ul>
</li>
<li>서로 주고받은 선물 개수를 파악해야 한다</li>
</ol>
<p>위 계산을 바탕으로 <code>pseudo code</code>는 아래와 같다</p>
<pre><code class="language-py">for friend in friends:
  for relation in relations:
    tempAnswer is 0
    if(relation.from 이 준 선물 수 &gt; relation.to 이 준 선물 수) {
      tempAnswer is tempAnswer + 1
    }
    else if(relation.from 이 준 선물 수 &gt; relation.to 이 준 선물 수) {
      if(선물 지수.relation.from &gt; 선물 지수.relation.to) {
        tempAnswer += 1
      }
    }
  answer = max(
    answer, tempAnswer
  )
return answer</code></pre>
<h4 id="문제-풀이">문제 풀이</h4>
<ul>
<li>친구 정보, 선물 정보를 기반으로 dstData라는 데이터를 파싱하여 사용하였다.</li>
<li>파싱된 dstData의 기반 타입은 아래와 같다.<pre><code class="language-ts">interface friendGift {</code></pre>
</li>
</ul>
<pre><code>[key: string]: number | number[]; // 이름이 같을 경우 number, 다를 경우 number[]</code></pre><p>  };
}</p>
<pre><code>* 작성 코드는 아래와 같다.
```js
function solution(friends, gifts) {
    let answer = 0; // 정답
    let dstData = {}; // 파싱될 데이터 초기화
    // dstData 초기화
    friends.forEach(outerName =&gt; {
        dstData[outerName] = {}
        friends.forEach(innerName =&gt; {
            if(outerName !== innerName) { // 이름이 같지 않을 경우 [준 개수 = 0, 받은 개수 = 0] 으로 초기화
                dstData[outerName][innerName] = [
                  0, // 준 개수 
                  0 // 받은 개수
                ]
            }
            // 이름이 같은 경우 선물 지수 0으로 초기화
            else {
                dstData[outerName][innerName] = 0
            }
        })
    })
    // dstData 파싱
    gifts.forEach(gift =&gt; {
        [
          from, // 선물을 준 사람
          to // 선물을 받은 사람
        ] = gift.split(&#39; &#39;)
        dstData[from][from] += 1 // 선물을 준 사람의 선물 지수 증감
        dstData[to][to] -= 1 // 선물을 받은 사람의 선물 지수 감소
        // 선물 계수 계산
        dstData[from][to][0] += 1
        dstData[to][from][1] += 1
    })
    Object.entries(dstData).forEach(([name, giftDatas], index) =&gt; {
        tempAnswer = 0; // 임시 정답 데이터
        Object.entries(giftDatas).forEach(([toName, giftData], index) =&gt; {
            // 받은 사람과 준 사람의 이름이 다른 경우
            if(name !== toName) {
                const [
                  give, // 선물 준 사람 
                  receive // 선물 받은 사람
                ] = [...giftData]
                // 선물 준 사람의 갯수가 더 많을 경우
                if(give &gt; receive) {
                    // 정답 증가
                    tempAnswer += 1
                }
                // 선물 준 사람과 받은 사람의 갯수가 같을 경우
                else if(give === receive) {
                    // 선물 지수 비교
                    // 준 사람의 선물 지수가 큰 경우에만 정답 증가
                    if(dstData[name][name] &gt; dstData[toName][toName]) {
                        tempAnswer += 1
                    }
                }
            }
        })
        // 정답 갱신
        answer = Math.max(answer, tempAnswer)
    })
    return answer;
}</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[[Type Challenge][easy] Tuple to Object]]></title>
            <link>https://velog.io/@bear-frog/Type-Challenge-11-Tuple-to-Object</link>
            <guid>https://velog.io/@bear-frog/Type-Challenge-11-Tuple-to-Object</guid>
            <pubDate>Thu, 28 Dec 2023 07:43:27 GMT</pubDate>
            <description><![CDATA[<h3 id="개요">개요</h3>
<pre><code class="language-ts">배열(튜플)을 받아, 각 원소의 값을 key/value로 갖는 오브젝트 타입을 반환하는 타입을 구현하세요.

예시:

const tuple = [&#39;tesla&#39;, &#39;model 3&#39;, &#39;model X&#39;, &#39;model Y&#39;] as const

type result = TupleToObject&lt;typeof tuple&gt; // expected { tesla: &#39;tesla&#39;, &#39;model 3&#39;: &#39;model 3&#39;, &#39;model X&#39;: &#39;model X&#39;, &#39;model Y&#39;: &#39;model Y&#39;}

/* _____________ 여기에 코드 입력 _____________ */

type TupleToObject&lt;T extends readonly any[]&gt; = any

/* _____________ 테스트 케이스 _____________ */
import type { Equal, Expect } from &#39;@type-challenges/utils&#39;

const tuple = [&#39;tesla&#39;, &#39;model 3&#39;, &#39;model X&#39;, &#39;model Y&#39;] as const
const tupleNumber = [1, 2, 3, 4] as const
const sym1 = Symbol(1)
const sym2 = Symbol(2)
const tupleSymbol = [sym1, sym2] as const
const tupleMix = [1, &#39;2&#39;, 3, &#39;4&#39;, sym1] as const

type cases = [
  Expect&lt;Equal&lt;TupleToObject&lt;typeof tuple&gt;, { tesla: &#39;tesla&#39;, &#39;model 3&#39;: &#39;model 3&#39;, &#39;model X&#39;: &#39;model X&#39;, &#39;model Y&#39;: &#39;model Y&#39; }&gt;&gt;,
  Expect&lt;Equal&lt;TupleToObject&lt;typeof tupleNumber&gt;, { 1: 1, 2: 2, 3: 3, 4: 4 }&gt;&gt;,
  Expect&lt;Equal&lt;TupleToObject&lt;typeof tupleSymbol&gt;, { [sym1]: typeof sym1, [sym2]: typeof sym2 }&gt;&gt;,
  Expect&lt;Equal&lt;TupleToObject&lt;typeof tupleMix&gt;, { 1: 1, &#39;2&#39;: &#39;2&#39;, 3: 3, &#39;4&#39;: &#39;4&#39;, [sym1]: typeof sym1 }&gt;&gt;,
]

// @ts-expect-error
type error = TupleToObject&lt;[[1, 2], {}]&gt;</code></pre>
<h3 id="해석">해석</h3>
<ul>
<li>두 가지 조건에서 모두 에러가 나지 않아야 한다</li>
</ul>
<ol>
<li><p>아래 조건에서 타입이 일치해야 함</p>
<pre><code class="language-ts">type cases = [
Expect&lt;Equal&lt;TupleToObject&lt;typeof tuple&gt;, { tesla: &#39;tesla&#39;, &#39;model 3&#39;: &#39;model 3&#39;, &#39;model X&#39;: &#39;model X&#39;, &#39;model Y&#39;: &#39;model Y&#39; }&gt;&gt;,
Expect&lt;Equal&lt;TupleToObject&lt;typeof tupleNumber&gt;, { 1: 1, 2: 2, 3: 3, 4: 4 }&gt;&gt;,
Expect&lt;Equal&lt;TupleToObject&lt;typeof tupleSymbol&gt;, { [sym1]: typeof sym1, [sym2]: typeof sym2 }&gt;&gt;,
Expect&lt;Equal&lt;TupleToObject&lt;typeof tupleMix&gt;, { 1: 1, &#39;2&#39;: &#39;2&#39;, 3: 3, &#39;4&#39;: &#39;4&#39;, [sym1]: typeof sym1 }&gt;&gt;,
]</code></pre>
</li>
<li><p>아래 조건에서 타입이 일치하지 않아야 함</p>
<pre><code class="language-ts">// @ts-expect-error
type error = TupleToObject&lt;[[1, 2], {}]&gt;</code></pre>
</li>
</ol>
<h3 id="아이디어">아이디어</h3>
<blockquote>
<ol>
<li>즉, 타입은 동일한 key / value쌍으로 이루어진 타입이다.</li>
</ol>
</blockquote>
<blockquote>
<ol start="2">
<li>즉, 타입의 key는 string, number, symbol만으로만 이루어져 있어야 한다.</li>
</ol>
</blockquote>
<h3 id="풀이">풀이</h3>
<h4 id="1-타입은-동일한-key--value쌍으로-이루어진-타입이다">1. 타입은 동일한 key / value쌍으로 이루어진 타입이다.</h4>
<pre><code class="language-ts">type TupleToObject&lt;T extends readonly any[]&gt; = {
  [P in T[number]]: p
}</code></pre>
<p>위 풀이를 사용할 경우 하단의 </p>
<pre><code class="language-ts">// @ts-expect-error
type error = TupleToObject&lt;[[1, 2], {}]&gt;</code></pre>
<p>에서 error가 발생하지 않는다</p>
<ul>
<li><code>any[]</code> 으로 이루어져 있어 <code>[[1, 2], {}]</code> 와 같은 값이 들어올 때 에러를 발생시키지 않는 것</li>
</ul>
<h4 id="2-타입의-key는-string-number-symbol만으로만-이루어져-있어야-한다">2. 타입의 key는 string, number, symbol만으로만 이루어져 있어야 한다.</h4>
<pre><code class="language-ts">type TupleToObject&lt;T extends readonly (string | number | symbol)[]&gt; = {
  [P in T[number]]: p
}</code></pre>
<ul>
<li>key 값의 type을 <code>string | number | symbol</code> 로 제한한다<ul>
<li>위 방법을 통해<pre><code class="language-ts">// @ts-expect-error
type error = TupleToObject&lt;[[1, 2], {}]&gt;</code></pre>
에서 에러를 발생시킨다</li>
</ul>
</li>
</ul>
<h3 id="결과-코드">결과 코드</h3>
<pre><code class="language-ts">/* _____________ 여기에 코드 입력 _____________ */

type TupleToObject&lt;T extends readonly (string | number | symbol)[]&gt; = {
  [P in T[number]] : P
}

/* _____________ 테스트 케이스 _____________ */
import type { Equal, Expect } from &#39;@type-challenges/utils&#39;

const tuple = [&#39;tesla&#39;, &#39;model 3&#39;, &#39;model X&#39;, &#39;model Y&#39;] as const
const tupleNumber = [1, 2, 3, 4] as const
const sym1 = Symbol(1)
const sym2 = Symbol(2)
const tupleSymbol = [sym1, sym2] as const
const tupleMix = [1, &#39;2&#39;, 3, &#39;4&#39;, sym1] as const

type cases = [
  Expect&lt;Equal&lt;TupleToObject&lt;typeof tuple&gt;, { tesla: &#39;tesla&#39;, &#39;model 3&#39;: &#39;model 3&#39;, &#39;model X&#39;: &#39;model X&#39;, &#39;model Y&#39;: &#39;model Y&#39; }&gt;&gt;,
  Expect&lt;Equal&lt;TupleToObject&lt;typeof tupleNumber&gt;, { 1: 1, 2: 2, 3: 3, 4: 4 }&gt;&gt;,
  Expect&lt;Equal&lt;TupleToObject&lt;typeof tupleSymbol&gt;, { [sym1]: typeof sym1, [sym2]: typeof sym2 }&gt;&gt;,
  Expect&lt;Equal&lt;TupleToObject&lt;typeof tupleMix&gt;, { 1: 1, &#39;2&#39;: &#39;2&#39;, 3: 3, &#39;4&#39;: &#39;4&#39;, [sym1]: typeof sym1 }&gt;&gt;,
]

// @ts-expect-error
type error = TupleToObject&lt;[[1, 2], {}]&gt;</code></pre>
<h3 id="알게-된-것">알게 된 것</h3>
<pre><code class="language-ts">type TupleToObject&lt;T extends readonly (string | number | symbol)[]&gt; = {
  [P in T[number]] : P
}</code></pre>
<p>위 코드에서 <code>T[number]</code> 와 같이 사용 할 경우 T의 각 인덱스의 요소를 순회하면서 type으로 사용 가능하다.</p>
<blockquote>
<p>예를 들어...</p>
</blockquote>
<pre><code class="language-ts">const students = [&#39;hana&#39;, &#39;maple&#39;, &#39;jordan&#39;, &#39;rily&#39;] </code></pre>
<p>일 때</p>
<pre><code class="language-ts">type MyType&lt;T extends (string | number | symbol)[]&gt; = {
  [P in T[number]]: P
}

const data: MyType&lt;string[]&gt; = {&#39;a&#39;: &#39;a&#39;, &#39;b&#39;: &#39;b&#39;}</code></pre>
<p>위와 같이 사용 가능한 것!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[프로그래머스 181950 문자열 반복해서 출력하기 javascript]]></title>
            <link>https://velog.io/@bear-frog/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-181950-%EB%AC%B8%EC%9E%90%EC%97%B4-%EB%B0%98%EB%B3%B5%ED%95%B4%EC%84%9C-%EC%B6%9C%EB%A0%A5%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@bear-frog/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-181950-%EB%AC%B8%EC%9E%90%EC%97%B4-%EB%B0%98%EB%B3%B5%ED%95%B4%EC%84%9C-%EC%B6%9C%EB%A0%A5%ED%95%98%EA%B8%B0</guid>
            <pubDate>Thu, 28 Dec 2023 00:20:57 GMT</pubDate>
            <description><![CDATA[<h3 id="곰개구리-알고리즘-매니패스토">곰개구리 알고리즘 매니패스토</h3>
<pre><code>1. 하나의 문제에 대해 최소 2가지 이상의 풀이를 생각한다.
2. null, undefined등을 고려하는 방어적이고 안전한 코드를 작성한다.
3. 알기 쉬운 변수명을 지정한다.
4. 읽기 쉬운 주석을 작성한다.
...
코딩하다 생각나면 맘대로 추가</code></pre><h3 id="문제-설명">문제 설명</h3>
<pre><code>문자열 str과 정수 n이 주어집니다.
str이 n번 반복된 문자열을 만들어 출력하는 코드를 작성해 보세요.</code></pre><h3 id="아이디어">아이디어</h3>
<pre><code>결과 문자열을 얻기 위해서는 주어지는 문자열을 주어지는 숫자만큼 축적한 결과를 반환해야 한다.</code></pre><h3 id="설계">설계</h3>
<pre><code>1. 반복문
2. Array.prototype.reduce()
3. String.prototype.repeat()</code></pre><h3 id="구현">구현</h3>
<h4 id="1-반복문">1. 반복문</h4>
<pre><code class="language-js">const readline = require(&#39;readline&#39;);
const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout
});

let input = [];

rl.on(&#39;line&#39;, function (line) {
    typeof line === &#39;string&#39; ? input = line.split(&#39; &#39;) : null;
}).on(&#39;close&#39;, function () {
    // 결과 문자열
    let answer = &#39;&#39;
    const [
        inputStr, // 반복될 문자열 
        n // 반복될 수
    ] = [String(input[0]), Number(input[1])]

    // 반복될 수 만큼 반복문 시행
    for(let i = 0; i &lt; n ; i += 1) {
        answer += inputStr
        // concat을 이용한 풀이
        // answer = answer.concat(inputStr)
    }
    console.log(answer)
});</code></pre>
<h4 id="2-arrayprototypereduce">2. Array.prototype.reduce()</h4>
<ul>
<li>목표 문자열 <code>inputStr</code> 요소를 <code>n</code> 개 가지는 배열을 만들고, reduce를 통한 축적으로 해결하였다.</li>
<li>어거지라는 느낌이 없잖아 들지만...</li>
</ul>
<h5 id="21-arrayfrom">2.1 Array.from()</h5>
<pre><code class="language-js">const readline = require(&#39;readline&#39;);
const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout
});

let input = [];

rl.on(&#39;line&#39;, function (line) {
    typeof line === &#39;string&#39; ? input = line.split(&#39; &#39;) : null;
}).on(&#39;close&#39;, function () {
    // 결과 문자열
    let answer = &#39;&#39;
    const [
        inputStr, // 반복될 문자열 
        n // 반복될 수
    ] = [String(input[0]), Number(input[1])]

    // inputStr 요소를 n개 가지는 배열 생성
    const inputArray = Array.from({ length: n }, () =&gt; inputStr);

    answer = inputArray.reduce((accumulator, currentValue) =&gt; {
        return accumulator.concat(currentValue)
    }, answer)

    console.log(answer)
});</code></pre>
<h5 id="22-arrayfill">2.2 Array.fill()</h5>
<pre><code class="language-js">const readline = require(&#39;readline&#39;);
const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout
});

let input = [];

rl.on(&#39;line&#39;, function (line) {
    typeof line === &#39;string&#39; ? input = line.split(&#39; &#39;) : null;
}).on(&#39;close&#39;, function () {
    // 결과 문자열
    let answer = &#39;&#39;
    const [
        inputStr, // 반복될 문자열 
        n // 반복될 수
    ] = [String(input[0]), Number(input[1])]

    // inputStr 요소를 n개 가지는 배열 생성
    const inputArray = Array(n).fill(inputStr)

    answer = inputArray.reduce((accumulator, currentValue) =&gt; {
        return accumulator.concat(currentValue)
    }, answer)

    console.log(answer)
});</code></pre>
<h4 id="3-stringprototyperepeat">3. String.prototype.repeat()</h4>
<ul>
<li>현재로서는 가장 idle한 방법이 아닐까</li>
</ul>
<pre><code class="language-js">const readline = require(&#39;readline&#39;);
const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout
});

let input = [];

rl.on(&#39;line&#39;, function (line) {
    typeof line === &#39;string&#39; ? input = line.split(&#39; &#39;) : null;
}).on(&#39;close&#39;, function () {
    // 결과 문자열
    let answer = &#39;&#39;
    const [
        inputStr, // 반복될 문자열 
        n // 반복될 수
    ] = [String(input[0]), Number(input[1])]

    // input을 n번 반복한 문자열 생성
    answer = inputStr.repeat(n)

    console.log(answer)
});</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[type challenge][easy] readonly]]></title>
            <link>https://velog.io/@bear-frog/type-challengeeasy-readonly</link>
            <guid>https://velog.io/@bear-frog/type-challengeeasy-readonly</guid>
            <pubDate>Mon, 20 Nov 2023 12:39:24 GMT</pubDate>
            <description><![CDATA[<h3 id="질문">질문</h3>
<p>  <code>T</code>의 모든 프로퍼티를 읽기 전용(재할당 불가)으로 바꾸는 내장 제네릭 <code>Readonly&lt;T&gt;</code>를 이를 사용하지 않고 구현하세요.</p>
<p>  예시:</p>
<pre><code class="language-ts">  interface Todo {
    title: string
    description: string
  }

  const todo: MyReadonly&lt;Todo&gt; = {
    title: &quot;Hey&quot;,
    description: &quot;foobar&quot;
  }

  todo.title = &quot;Hello&quot; // Error: cannot reassign a readonly property
  todo.description = &quot;barFoo&quot; // Error: cannot reassign a readonly property</code></pre>
<pre><code class="language-ts">type MyReadonly&lt;T&gt; = any</code></pre>
<h3 id="생각해보기">생각해보기</h3>
<p>T라는 타입이 주어졌을 때 해당 타입을 재활용하는 프로퍼티는 다음과 같다</p>
<pre><code class="language-ts">type MyReadonly&lt;T&gt; = {
  [t in keyof T]: T[t]
}</code></pre>
<h5 id="빠밤-빨간줄">빠밤! 빨간줄!</h5>
<p>이제 여기에 readonly를 한 스푼 얹어주자</p>
<pre><code class="language-ts">type MyReadonly&lt;T&gt; = {
  readonly [t in keyof T]: T[t]
}</code></pre>
<h4 id="짠-풀렸다">짠! 풀렸다!</h4>
]]></description>
        </item>
        <item>
            <title><![CDATA[[type challenge][easy] pick]]></title>
            <link>https://velog.io/@bear-frog/type-challengeeasy-pick</link>
            <guid>https://velog.io/@bear-frog/type-challengeeasy-pick</guid>
            <pubDate>Mon, 20 Nov 2023 12:24:50 GMT</pubDate>
            <description><![CDATA[<h3 id="문제">문제</h3>
<p>T에서 K 프로퍼티만 선택해 새로운 오브젝트 타입을 만드는 내장 제네릭 Pick&lt;T, K&gt;을 이를 사용하지 않고 구현하세요.</p>
<pre><code class="language-ts">interface Todo {
  title: string
  description: string
  completed: boolean
}

type TodoPreview = MyPick&lt;Todo, &#39;title&#39; | &#39;completed&#39;&gt;

const todo: TodoPreview = {
    title: &#39;Clean room&#39;,
    completed: false,
}</code></pre>
<pre><code class="language-ts">/* _____________ 여기에 코드 입력 _____________ */

type MyPick&lt;T, K&gt; = any

/* _____________ 테스트 케이스 _____________ */</code></pre>
<h3 id="생각해보기">생각해보기</h3>
<p>말이 참 어렵다 T니 K니 내장 제네릭이니. 이놈의 공대생들은 조금 쉬운 단어를 쓰면 병이라도 걸리나보다.</p>
<p>쉽게 생각해보자</p>
<ul>
<li>주어진 타입은 두 개이다 T, K 이들을 어떻게든 써도 된다</li>
<li>T에서 K만을 고른다... 말이 어렵다... 가만... 이거?<ul>
<li>교집합 아니야?</li>
</ul>
</li>
</ul>
<p><strong><em>그렇다! 교집합이다!</em></strong></p>
<p>생각해보자</p>
<p><code>T</code>니 <code>K</code> 니 어려운 제네릭 약어 말고</p>
<p><code>type A: &#39;a&#39; | &#39;b&#39; | &#39;c&#39; | &#39;d&#39; | &#39;e&#39;</code> 이고
<code>type B:  &#39;c&#39; | &#39;d&#39; | &#39;e&#39; | &#39;f&#39; | &#39;h&#39;</code> 라고 생각하자</p>
<p><code>A</code>에서 <code>B</code> 프로퍼티만을 선택한다는건, 맞다! 교집합이다. 즉 두 타입의 공통적 부분인 <code>&#39;c&#39; | &#39;d&#39; | &#39;e&#39;</code> 를 뽑아내면 된다.</p>
<p>이렇게 생각하니 조금 풀어낼 만 한 것 같다.</p>
<p>그렇다면</p>
<pre><code class="language-ts">type MyPick&lt;T, K&gt; = any</code></pre>
<p>이 코드는</p>
<pre><code class="language-ts">type MyPick&lt;T, K extends keyof T&gt; = {
  [k in K]: T[k]
}</code></pre>
<p>이렇게 풀렸다</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Type challenge 13・Hello World]]></title>
            <link>https://velog.io/@bear-frog/Type-challenge-13%E3%83%BBHello-World</link>
            <guid>https://velog.io/@bear-frog/Type-challenge-13%E3%83%BBHello-World</guid>
            <pubDate>Sun, 01 Oct 2023 08:53:45 GMT</pubDate>
            <description><![CDATA[<pre><code class="language-javascript">/* _____________ 여기에 코드 입력 _____________ */
type HelloWorld = string // expected to be a string

/* _____________ 테스트 케이스 _____________ */
import type { Equal, Expect, NotAny } from &#39;@type-challenges/utils&#39;

type cases = [
  Expect&lt;NotAny&lt;HelloWorld&gt;&gt;,
  Expect&lt;Equal&lt;HelloWorld, string&gt;&gt;,
]

/* _____________ 다음 단계 _____________ */
/*
  &gt; 정답 공유하기: https://tsch.js.org/13/answer/ko
  &gt; 정답 보기: https://tsch.js.org/13/solutions
  &gt; 다른 문제들: https://tsch.js.org/ko
*/
</code></pre>
<p>NotAny는 any type이 아니어야 하고,
Expect는 내부 타입이 true? 여야 하고
Equal은 두 type이 같아야 하나 보다</p>
<p>워밍업이라 그냥 답을 알려주는 문제</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[백준 1213 팰린드롬 만들기 python]]></title>
            <link>https://velog.io/@bear-frog/%EB%B0%B1%EC%A4%80-1213-%ED%8C%B0%EB%A6%B0%EB%93%9C%EB%A1%AC-%EB%A7%8C%EB%93%A4%EA%B8%B0-python</link>
            <guid>https://velog.io/@bear-frog/%EB%B0%B1%EC%A4%80-1213-%ED%8C%B0%EB%A6%B0%EB%93%9C%EB%A1%AC-%EB%A7%8C%EB%93%A4%EA%B8%B0-python</guid>
            <pubDate>Wed, 21 Jun 2023 08:03:01 GMT</pubDate>
            <description><![CDATA[<h3 id="concept">Concept</h3>
<p>Map, Sort를 이용해 해결했다
각 문자별 나타나는 횟수를 기록하고 사전 순으로 정렬하여 정답 문자열을 생성하였다</p>
<p><strong><em>핵심 예외처리!</em></strong></p>
<p>갯수가 <strong><em>홀수</em></strong> 인 문자가 존재하는 경우</p>
<ol>
<li><p>해당 문자가 하나인 경우</p>
<ul>
<li>가능하다!<ul>
<li><strong><em>해당 문자의 갯수에서 하나를 빼 중간에 고정한다</em></strong>
이 방법으로 모든 문자가 짝수 갯수로 나타나도록 할 수 있다</li>
</ul>
</li>
</ul>
</li>
<li><p>해당 문자가 하나를 초과하는 경우</p>
<ul>
<li>불가능하다!</li>
</ul>
</li>
</ol>
<h3 id="code">Code</h3>
<pre><code class="language-py">from collections import Counter
from functools import cmp_to_key


# 짝수 개수만을 가진 딕셔너리(튜플)을 정렬합니다
def dict_sort(x1, x2):
    # 첫 인덱스의 값은 문자이므로 해당 값을 기준으로 정렬합니다
    if x1[0] &gt; x2[0]:
        return 1
    else:
        return -1


src = Counter(list(input()))
middle = &#39;&#39;
middle_key = 0
possible_counter = 0
for key, value in src.items():
    # 홀수 개수 출현 문자를 검사합니다
    if value % 2 != 0:
        middle = key
        middle_key = value
        src[key] -= 1
        possible_counter += 1
# 홀수 개수 출현 문자의 개수가 하나를 초과한다면 팰린드롬이 불가합니다
if possible_counter &gt; 1:
    print(&#39;I\&#39;m Sorry Hansoo&#39;)
else:
    src = sorted(src.items(), key=cmp_to_key(dict_sort))
    answer = &#39;&#39;
    for key, value in src:
        if value % 2 == 0:
            answer += key * (value // 2)
    answer = answer + middle + answer[::-1]
    print(answer)</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[백준 1916 최소비용 구하기 python]]></title>
            <link>https://velog.io/@bear-frog/%EB%B0%B1%EC%A4%80-1916-%EC%B5%9C%EC%86%8C%EB%B9%84%EC%9A%A9-%EA%B5%AC%ED%95%98%EA%B8%B0-python</link>
            <guid>https://velog.io/@bear-frog/%EB%B0%B1%EC%A4%80-1916-%EC%B5%9C%EC%86%8C%EB%B9%84%EC%9A%A9-%EA%B5%AC%ED%95%98%EA%B8%B0-python</guid>
            <pubDate>Tue, 20 Jun 2023 12:55:49 GMT</pubDate>
            <description><![CDATA[<h3 id="concept">Concept</h3>
<p>heap을 이용한 다익스트라 구현
교과서대로의, 구현이다
사실 올해 초 까지만 해도 다익스트라 구현이 익숙하지 않았는데 지금은 할 만한 걸 보니
성장했?나? 싶긴 하다</p>
<p>다들 알겠지만 뭐... Greedy를 이용한 그래프 문제... 그것이 다익스트라...
해당 정점에서 인접 정점을 탐색하고 거리를 갱신하고... 그렇게 푸는... 문제...</p>
<h3 id="code">Code</h3>
<pre><code class="language-py">import heapq

def dijkstra(start_v):
    q = []
    distance[start_v] = 0
    heapq.heappush(q, (0, start_v))
    while q:
        dist, now = heapq.heappop(q)
        if distance[now] &lt; dist:
            continue
        for next_node in graph[now]:
            cost = dist + next_node[1]
            if cost &lt; distance[next_node[0]]:
                distance[next_node[0]] = cost
                heapq.heappush(q, (cost, next_node[0]))

n = int(input())
m = int(input())
graph = [[] for _ in range(n + 1)]
distance = [int(1e9) for _ in range(n + 1)]
for _ in range(m):
    s, e, w = map(int, input().split())
    graph[s].append((e, w))
st, en = map(int, input().split())

dijkstra(st)
print(distance[en])</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[백준 17626 Four Squares python]]></title>
            <link>https://velog.io/@bear-frog/%EB%B0%B1%EC%A4%80-17626-Four-Squares-python</link>
            <guid>https://velog.io/@bear-frog/%EB%B0%B1%EC%A4%80-17626-Four-Squares-python</guid>
            <pubDate>Tue, 20 Jun 2023 05:39:44 GMT</pubDate>
            <description><![CDATA[<h3 id="concept">Concept</h3>
<p>특정 수를 최소한의 제곱수로 표현한다</p>
<h3 id="trial-1">Trial. 1</h3>
<p>임의의 수 n을 해당 수의 제곱근의 정수값을 제곱한 값의 테이블 값 + 1로 풀 수 있을거라 생각했다</p>
<h4 id="점화식">점화식</h4>
<pre><code>dp[n] = dp[n - int(√n) ^ 2] + 1 </code></pre><h4 id="error-trial-1">Error Trial. 1</h4>
<p>n의 값이 43라고 가정하자
&#39;시도 1&#39; 의 점화식대로라면 43 = 6^2 + dp[7]이다
여기서 dp[7]의 값은 2^2 + 1 + 1 + 1로 4이다
즉 &#39;시도 1&#39;대로라면 dp[43] = 1 + 4 = 5가 나오게 된다</p>
<p><strong><em>그러나!</em></strong></p>
<p>만약 43에서 5^2를 먼저 뺀다면
43 = 5^2 + 4^2 + 1^2 + 1^2로 나타낼 수 있다
<strong><em>즉 Trial 1은 오류가 있다</em></strong></p>
<h3 id="trial-2">Trial. 2</h3>
<p>시도 1이 dp만을 사용했다면 시도 2는 여기서 brute force를 추가한다</p>
<h4 id="점화식-1">점화식</h4>
<pre><code>(1 &lt;= i &lt;= n)
dp[n] = min(dp[n - int(√i) ^ 2)) + 1</code></pre><h4 id="코드">코드</h4>
<pre><code class="language-py">import math

n = int(input())

dp = [int(1e9) for _ in range(50001)]
dp[0] = 0
dp[1] = 1
dp[2] = 2
dp[3] = 3
for _ in range(4, n + 1):
    d = int(math.sqrt(_))
    for _n in range(1, d + 1):
        dp[_] = min(dp[_], 1 + dp[_ - _n ** 2])

print(dp[n])</code></pre>
<h3 id="여담">여담</h3>
<p>시간초과 걸릴 줄 알았다. 하지만 생각해보니 O(n) = n * √n이고 n이 50000이라 0.5초 안에 충분히 풀 수 있는 문제였다</p>
]]></description>
        </item>
    </channel>
</rss>