<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>darren, dev blog</title>
    <link>https://darrengwon.tistory.com/</link>
    <description>블로그 관리하지 않습니다.
-  글을 올리는 주기가 일정하지 않습니다.
- 댓글에 답변을 달지 않습니다. 죄송합니다.</description>
    <language>ko</language>
    <pubDate>Wed, 15 Apr 2026 06:11:50 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>DarrenKwonDev</managingEditor>
    <image>
      <title>darren, dev blog</title>
      <url>https://tistory1.daumcdn.net/tistory/3597497/attach/b27282101ad24d0cb8a4116c8c6e46e4</url>
      <link>https://darrengwon.tistory.com</link>
    </image>
    <item>
      <title>kernel study 03: Understanding the Calculation of Load Average in Linux Kernel</title>
      <link>https://darrengwon.tistory.com/1584</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;아래 블로그에서 좀 더 깔끔하고 제대로 읽을 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://darrenkwondev.github.io/posts/2023-12-28_kernel_study_03.md/&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://darrenkwondev.github.io/posts/2023-12-28_kernel_study_03.md/&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1703793055063&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;kernel study 03: Understanding the Calculation of Load Average in Linux Kernel | darrenkwon.dev blog&quot; data-og-description=&quot;/proc/loadavg The first three fields in this file are load average figures giving the number of jobs in the run queue (state R) or waiting for disk I/O (state D) averaged over 1, 5, and 15 minutes. They are the same as the load average numbers given by upt&quot; data-og-host=&quot;darrenkwondev.github.io&quot; data-og-source-url=&quot;https://darrenkwondev.github.io/posts/2023-12-28_kernel_study_03.md/&quot; data-og-url=&quot;https://darrenkwondev.github.io/posts/2023-12-28_kernel_study_03.md/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bQtsQJ/hyUTJoRZLj/kNinZqSa48PT8phq7MvMf1/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630&quot;&gt;&lt;a href=&quot;https://darrenkwondev.github.io/posts/2023-12-28_kernel_study_03.md/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://darrenkwondev.github.io/posts/2023-12-28_kernel_study_03.md/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bQtsQJ/hyUTJoRZLj/kNinZqSa48PT8phq7MvMf1/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;kernel study 03: Understanding the Calculation of Load Average in Linux Kernel | darrenkwon.dev blog&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;/proc/loadavg The first three fields in this file are load average figures giving the number of jobs in the run queue (state R) or waiting for disk I/O (state D) averaged over 1, 5, and 15 minutes. They are the same as the load average numbers given by upt&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;darrenkwondev.github.io&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Linux kernel v6.7-rc7 기준으로 작성되었습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Load average&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;definition&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;/proc/loadavg
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;The first three fields in this file are load average figures giving the number of jobs in the run queue (state R) or waiting for disk I/O (state D) averaged over 1, 5, and 15 minutes.&lt;/u&gt; They are the same as the load average numbers given by uptime(1) and other programs. The fourth field consists of two numbers separated by a slash (/). The first of these is the number of currently runnable kernel scheduling entities (processes, threads). The value after the slash is the number of kernel scheduling entities that currently exist on the system. The fifth field is the PID of the process that was most recently created on the system.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, load average는 1분, 5분, 15분 동안 process status가 R(run queue에 적재) 또는 D(waiting for disk I/O)인 job(task)의 수이다.[^1] 그러나 단순히 task의 수 만으로는 시스템 부하를 판단하기는 어렵다. 현재 가동 중인 cpu 코어의 갯수와 고려하여 다른 측면까지도 고려해야 한다. 본 포스트에서는 시스템 부하를 판단하는 방법에 대해서는 다루지 않고, load average가 어떻게 계산되는지에 대해서만 알아보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[^1]: process status에 대해서는 &lt;a href=&quot;https://darrenkwondev.github.io/posts/2023-12-27_kernel_study_02.md/#process-status&quot;&gt;이전 포스트&lt;/a&gt;를 참고하자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;load average는 다음과 같이 다양한 방법으로 조회할 수 있다.&lt;/p&gt;
&lt;pre class=&quot;tcl&quot;&gt;&lt;code&gt;cat /proc/loadavg
uptime
top -b | head -1&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;tracking how load average is calculated&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;strace&lt;/h3&gt;
&lt;pre class=&quot;armasm&quot;&gt;&lt;code&gt;strace uptime&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;출력된 덤프 하단을 보면 다음과 같은 점들을 확인할 수 있습니다.&lt;/p&gt;
&lt;pre class=&quot;lsl&quot;&gt;&lt;code&gt;# uptime 실행
execve(&quot;/usr/bin/uptime&quot;, [&quot;uptime&quot;], 0xfffff2486300 /* 24 vars */) = 0

# 메모리 할당 및 매핑
brk(NULL)                               = 0xaaaaf84c2000
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xffffaf954000

... 생략

# /proc/loadavg를 RDONLY로 open하여 fd 4에 할당
openat(AT_FDCWD, &quot;/proc/loadavg&quot;, O_RDONLY) = 4

# fd 4의 시작으로 SEEK_SET. 처음부터 파일을 읽을 것을 위함.
lseek(4, 0, SEEK_SET)                   = 0
read(4, &quot;0.00 0.00 0.00 3/190 26203\n&quot;, 8191) = 27

... 생략
+++ exited with 0 +++&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결국 uptime은 /proc/loadavg를 읽어오는 것에 불과합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;top에 출력되는 load average도 마찬가지입니다.&lt;br /&gt;&lt;code&gt;strace -e openat top -b -n 1&lt;/code&gt;를 실행하여 덤프 하단을 살펴보면 /proc/loadavg를 읽어오는 것을 확인할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇다면 구체적으로 /proc/loadavg이 어떻게 계산되는지 kernel을 살펴보겠습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;loadavg_proc_show&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://elixir.bootlin.com/linux/v6.7-rc7/source/fs/proc/loadavg.c&quot;&gt;/fs/proc/loadavg.c&lt;/a&gt; 파일의 코드에는 다음과 같은 내용이 존재합니다. 짧은 코드니 header를 제외한 전부를 첨부해보겠습니다.&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;// /fs/proc/loadavg.c

static int loadavg_proc_show(struct seq_file *m, void *v)
{
    unsigned long avnrun[3];

    get_avenrun(avnrun, FIXED_1/200, 0);

    seq_printf(m, &quot;%lu.%02lu %lu.%02lu %lu.%02lu %u/%d %d\n&quot;,
        LOAD_INT(avnrun[0]), LOAD_FRAC(avnrun[0]),
        LOAD_INT(avnrun[1]), LOAD_FRAC(avnrun[1]),
        LOAD_INT(avnrun[2]), LOAD_FRAC(avnrun[2]),
        nr_running(), nr_threads,
        idr_get_cursor(&amp;amp;task_active_pid_ns(current)-&amp;gt;idr) - 1);
    return 0;
}

static int __init proc_loadavg_init(void)
{
    struct proc_dir_entry *pde;

    pde = proc_create_single(&quot;loadavg&quot;, 0, NULL, loadavg_proc_show);
    pde_make_permanent(pde);
    return 0;
}
fs_initcall(proc_loadavg_init);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;cat /proc/loadavg&lt;/code&gt;의 결과를 고려해보면 0.01 0.01 0.00 1/188 26290 와 같은 꼴로 출력되었는데 loadavg_proc_show 함수의 seq_printf 호출에서 이 형식을 확인해볼 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러나 이는 수식이 아니고 출력 형식입니다. 실제 계산하는 과정을 확인하기 위해 get_avenrun 함수를 살펴보겠습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;exponentially decaying average of (R + D)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;구체적인 계산식은 kernel/sched/loadavg.c의 &lt;a href=&quot;https://elixir.bootlin.com/linux/v6.7-rc7/source/kernel/sched/loadavg.c#L71&quot;&gt;get_avenrun&lt;/a&gt; 함수에서 확인할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 파일에 접근하면, 상단의 주석에서 load average의 계산 결과에 대한 설명을 참고할 수 있습니다.&lt;/p&gt;
&lt;pre class=&quot;livescript&quot;&gt;&lt;code&gt;The global load average is an exponentially decaying average of nr_running +
nr_uninterruptible.

Once every LOAD_FREQ:
    nr_active = 0;
    for_each_possible_cpu(cpu)
    nr_active += cpu_of(cpu)-&amp;gt;nr_running + cpu_of(cpu)-&amp;gt;nr_uninterruptible;
    avenrun[n] = avenrun[0] * exp_n + nr_active * (1 - exp_n)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 psuedo code를 보면 load average가 우리가 알고 있는 R, D 상태의 task 수를 적당히 가공한 수치임을 확인할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;새로운 avenrun(avenrun[n])을 계산하기 위해 이전 시점의 avenrun(avenrun[0])을 활용하며, 이전 시점 avenrun[0]는 exp_n에 의해 지수적으로 감소하며[^2], 새로운 R, D 상태의 프로세스의 수를 의미하는 nr_active는 (1 - exp_n)에 의해 지수적으로 증가합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[^2]: decay는 일반적으로 최근에 더욱 가중치를 주고 싶어 과거의 데이터의 가중치를 감소시키는 일종의 수학적 trick입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$$&lt;br /&gt;active \space process = R + D \&lt;br /&gt;\space \&lt;br /&gt;avenrun[n] = avenrun[0] \times exp + (R + D) \times (1 - exp)&lt;br /&gt;$$&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결국 단순히 R, D 상태의 task 수만으로 load average를 계산하는 것이 아니라&lt;br /&gt;&lt;u&gt;load average is an exponentially decaying average of nr_running + nr_uninterruptible.&lt;/u&gt; 라는 사실을 확인할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;구체적으로 계산되는 코드를 찾기 위해 get_avenrun 함수를 살펴보겠습니다.&lt;/p&gt;
&lt;pre class=&quot;smali&quot;&gt;&lt;code&gt;/**
 * get_avenrun - get the load average array
 * @loads:    pointer to dest load array
 * @offset:    offset to add
 * @shift:    shift count to shift the result left
 *
 * These values are estimates at best, so no need for locking.
 */
void get_avenrun(unsigned long *loads, unsigned long offset, int shift)
{
    loads[0] = (avenrun[0] + offset) &amp;lt;&amp;lt; shift;
    loads[1] = (avenrun[1] + offset) &amp;lt;&amp;lt; shift;
    loads[2] = (avenrun[2] + offset) &amp;lt;&amp;lt; shift;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;loads 배열에 avenrun 배열의 원소값을 조작해서 계산하는 것을 확인할 수 있습니다.&lt;br /&gt;이제는 avenrun 배열이 초기화 되거나 활용되는 부분을 찾아야 합니다.&lt;br /&gt;찾아보면, 동일 파일인 /kernel/sched/loadavg.c에서 avenrun 가 선언되었으며 calc_global_load 에서 계산되는 것을 확인할 수 있습니다.&lt;/p&gt;
&lt;pre class=&quot;cpp&quot;&gt;&lt;code&gt;// /kernel/sched/loadavg.c

/* Variables and functions for calc_load */
atomic_long_t calc_load_tasks;
unsigned long calc_load_update;
unsigned long avenrun[3]; // 여기에서 초기화 됩니다.&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;// /kernel/sched/loadavg.c

/*
 * calc_load - update the avenrun load estimates 10 ticks after the
 * CPUs have updated calc_load_tasks.
 *
 * Called from the global timer code.
 */
void calc_global_load(void)
{
    unsigned long sample_window;
    long active, delta;

    sample_window = READ_ONCE(calc_load_update);
    if (time_before(jiffies, sample_window + 10))
        return;

    /*
     * Fold the 'old' NO_HZ-delta to include all NO_HZ CPUs.
     */
    delta = calc_load_nohz_read();
    if (delta)
        atomic_long_add(delta, &amp;amp;calc_load_tasks);

    active = atomic_long_read(&amp;amp;calc_load_tasks);
    active = active &amp;gt; 0 ? active * FIXED_1 : 0;

    avenrun[0] = calc_load(avenrun[0], EXP_1, active);
    avenrun[1] = calc_load(avenrun[1], EXP_5, active);
    avenrun[2] = calc_load(avenrun[2], EXP_15, active);

    WRITE_ONCE(calc_load_update, sample_window + LOAD_FREQ);

    /*
     * In case we went to NO_HZ for multiple LOAD_FREQ intervals
     * catch up in bulk.
     */
    calc_global_nohz();
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 avenrun은 calc_load 함수에 의해 여러 값과 함께 계산이 되는 것으로 보입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;매크로 값은 아래와 같이 확인됩니다. 지수적 감소를 위한 exp_n 값으로 보입니다.&lt;/p&gt;
&lt;pre class=&quot;cpp&quot;&gt;&lt;code&gt;// /include/linux/sched/loadavg.h
#define EXP_1        1884        /* 1/exp(5sec/1min) as fixed-point */
#define EXP_5        2014        /* 1/exp(5sec/5min) */
#define EXP_15        2037        /* 1/exp(5sec/15min) */&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;active의 경우에는 앞서 살펴본 active process (R + D)의 갯수를 의미하는 것으로 보입니다.&lt;br /&gt;&lt;code&gt;active = atomic_long_read(&amp;amp;calc_load_tasks);&lt;/code&gt; 와 같은 함수의 형식으로 미루어보아, atomic_long_read는 atomic read를 지원하기 위한 함수로 보이며 calc_load_tasks가 핵심적인 값으로 보입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;conclusion : calc_load&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최종적으로는 다음과 같이 계산되는 것을 확인할 수 있습니다.&lt;br /&gt;주석에서 설명하던 exponential decay average를 계산하는 것을 확인할 수 있습니다.&lt;/p&gt;
&lt;pre class=&quot;cpp&quot;&gt;&lt;code&gt;// include/linux/sched/loadavg.h

calc_load(unsigned long load, unsigned long exp, unsigned long active)
{
    unsigned long newload;

    newload = load * exp + active * (FIXED_1 - exp);
    if (active &amp;gt;= load)
        newload += FIXED_1 - 1;

    return newload / FIXED_1;
}&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;load: 이전의 부하 평균 값입니다.&lt;/li&gt;
&lt;li&gt;exp: 지수적 감쇠를 위한 계수로, 과거 데이터의 현재 값에 대한 영향을 조절합니다. (EXP_1, EXP_5, EXP_15)&lt;/li&gt;
&lt;li&gt;active: 현재 활성화된 (실행 중 또는 실행 대기 중인) 프로세스의 수입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;newload = load * exp + active * (FIXED_1 - exp);&lt;/code&gt;&lt;br /&gt;과거 부하 평균(load)에 지수적 감쇠 계수(exp)를 곱하고, 현재 활성화된 프로세스 수(active)에 1 - exp를 곱하여 두 값을 합산합니다. 여기서 FIXED_1은 고정 소수점 연산을 위한 상수입니다.[^3]&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;if (active &amp;gt;= load) newload += FIXED_1 - 1;&lt;/code&gt;&lt;br /&gt;만약 현재 활성화된 프로세스 수가 이전 부하 평균보다 크거나 같은 경우, newload에 추가적인 값(FIXED_1-1)을 더합니다. 이는 부하가 증가하는 상황에서 부하 평균을 보다 빠르게 반응하도록 하는 조정입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;return newload / FIXED_1;&lt;/code&gt;&lt;br /&gt;마지막으로, 계산된 새로운 부하 평균(newload)을 FIXED_1로 나누어 반환합니다. 이는 고정 소수점 연산을 실제 부동 소수점 값으로 변환하는 단계입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[^3]: &lt;code&gt;FIXED_1이 왜 고정 소수점 연산을 위한 상수인가?&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;고정 소수점은 비트 중 일부를 소수 부분에 할당합니다. 그래서 얼마나 많은 비트를 소수 부분에 할당할 것인지를 결정해야 합니다. 이를 위해 FSHIFT라는 상수를 사용합니다.

구체적인 값은 다음과 같습니다.

```c
// include/linux/sched/loadavg.h
#define FSHIFT        11        /* nr of bits of precision */
#define FIXED_1        (1&amp;lt;&amp;lt;FSHIFT)    /* 1.0 as fixed-point */
```

FIXED_1는 1.0을 고정 소수점으로 표현한 것입니다. 전체 비트에서 소수에 할당된 부분을 제외하고 left shift를 하여 1.0을 표현합니다.

따라서, 우리가 부동 소수점으로 5.0을 표현했고 이것은 고정 소수점으로 변환하고 싶다면 5.0 \* FIXED_1을 하면 됩니다. 반대로 고정 소수점을 부동 소수점으로 변환하고 싶다면 5.0 / FIXED_1을 하면 됩니다.&lt;/code&gt;&lt;/pre&gt;</description>
      <category>  Linux, shell, web server</category>
      <author>DarrenKwonDev</author>
      <guid isPermaLink="true">https://darrengwon.tistory.com/1584</guid>
      <comments>https://darrengwon.tistory.com/1584#entry1584comment</comments>
      <pubDate>Fri, 29 Dec 2023 04:50:38 +0900</pubDate>
    </item>
    <item>
      <title>kernel study 02: top을 통해 확인할 수 있는 프로세스 정보들</title>
      <link>https://darrengwon.tistory.com/1583</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://darrenkwondev.github.io/posts/2023-12-27_kernel_study_02.md/&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://darrenkwondev.github.io/posts/2023-12-27_kernel_study_02.md/&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래에서 더 깔끔하게 읽을 수 있습니다.&lt;/p&gt;
&lt;figure id=&quot;og_1703705687253&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;kernel study 02: top을 통해 확인할 수 있는 프로세스 정보들 | darrenkwon.dev blog&quot; data-og-description=&quot;단순한 사용 방법은 리눅스 top 정리 및 설명 을 참고하는 것이 좋습니다. 또한, 표현된 각 column 외에도 다른 metric은 man 페이지를 통해 확인하실 수 있습니다. 여기서는 top을 통해 살펴볼 수 있는 &quot; data-og-host=&quot;darrenkwondev.github.io&quot; data-og-source-url=&quot;https://darrenkwondev.github.io/posts/2023-12-27_kernel_study_02.md/&quot; data-og-url=&quot;https://darrenkwondev.github.io/posts/2023-12-27_kernel_study_02.md/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/4JqgP/hyUTwW3k2h/s5o1a3j5Zof3Iwnp9tTGh0/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/dPUgUa/hyUTCQuRCc/CxTcZ0cwB2KSYRf44BQ84k/img.png?width=1980&amp;amp;height=552&amp;amp;face=0_0_1980_552&quot;&gt;&lt;a href=&quot;https://darrenkwondev.github.io/posts/2023-12-27_kernel_study_02.md/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://darrenkwondev.github.io/posts/2023-12-27_kernel_study_02.md/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/4JqgP/hyUTwW3k2h/s5o1a3j5Zof3Iwnp9tTGh0/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/dPUgUa/hyUTCQuRCc/CxTcZ0cwB2KSYRf44BQ84k/img.png?width=1980&amp;amp;height=552&amp;amp;face=0_0_1980_552');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;kernel study 02: top을 통해 확인할 수 있는 프로세스 정보들 | darrenkwon.dev blog&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;단순한 사용 방법은 리눅스 top 정리 및 설명 을 참고하는 것이 좋습니다. 또한, 표현된 각 column 외에도 다른 metric은 man 페이지를 통해 확인하실 수 있습니다. 여기서는 top을 통해 살펴볼 수 있는&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;darrenkwondev.github.io&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;top&lt;/h2&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;top -hv|-bcEeHiOSs1 -d secs -n max -u|U user -p pids -o field -w [cols]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단순한 사용 방법은 &lt;a href=&quot;https://zzsza.github.io/development/2018/07/18/linux-top/&quot;&gt;리눅스 top 정리 및 설명&lt;/a&gt;을 참고하는 것이 좋습니다.&lt;br /&gt;또한, 표현된 각 column 외에도 다른 metric은 man 페이지를 통해 확인하실 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서는 top을 통해 살펴볼 수 있는 세부적인 여러 process 관련 정보들을 살펴보도록 하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;{{&amp;lt; box info &amp;gt;}}&lt;br /&gt;task&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리눅스에서 프로세스와 스레드는 개념적으로 구분되지만, 내부적으로는 모두 '태스크'로 관리됩니다.&lt;br /&gt;리눅스 커널은 프로세스와 스레드를 동일한 기본 구조인 'task_struct'를 사용하여 표현합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://elixir.bootlin.com/linux/latest/source/include/linux/sched.h&quot;&gt;sched.h&lt;/a&gt;&lt;br /&gt;{{&amp;lt; /box &amp;gt;}}&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;top의 개선판들&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/hishamhm/htop&quot;&gt;htop&lt;/a&gt;, &lt;a href=&quot;https://github.com/MrRio/vtop&quot;&gt;vtop&lt;/a&gt;, &lt;a href=&quot;https://github.com/aksakalli/gtop&quot;&gt;gtop&lt;/a&gt;, &lt;a href=&quot;https://github.com/cjbassi/gotop&quot;&gt;gotop&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;memory&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;virtual memory (메모리 가상화)&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;A program selects a memory location using a virtual address. The processor translates this into a physical address and finally the memory controller selects the RAM chip corresponding to that address.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, 프로세스는 virtual address를 통해 메모리를 다루지만, 실제 physical address로의 변환은 processor가 수행하는 셈입니다.[^2]&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정리하자면,&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;virtual address(가상 주소): 프로세스가 참조하는 주소&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;physical address(물리 주소): 실제 메모리 주소&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이며, 특정 가상 주소가 어느 물리 주소에 매핑되어있는지 변환하는 과정을 수행하는 과정은 cpu(processor) 내의 MMU(Memory Management Unit)가 수행합니다. MMU의 역할을 다시 정리하자면, CPU에에서 컴파일된 코드 실행시 가상 주소 메모리 접근이 필요할 때 해당 주소를 물리 주소 값으로 변환해주는 하드웨어 장치입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가상 메모리 서브시스템의 실제 구현 세부 사항을 직접 확인해보고 싶다면 lwn의 관련 아티클&lt;a href=&quot;https://lwn.net/Articles/253361/&quot;&gt;^1&lt;/a&gt; 을 참고할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[^2]: 이러한 가상(logical, virtual)과 물리(physical)의 분리는 메모리 뿐만 아니라 스토리지, 네트워크 등의 분야에서 자주 접하게 되는 패턴입니다. 물리를 감싸는 하나의 추상화된 레이어를 제공하여 파편화 해결, 공유화 등의 이점을 제공할 수 있습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Linux Memory Types&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;man 페이지에 따르면 프로세스가 소유한 메모리는 다음 4가지로 분류될 수 있습니다. 지금 당장 top의 출력물을 이해하는데 필요한 내용은 아니지만, 이후에 프로세스의 메모리 사용량을 살펴볼 때 필요한 내용이므로 간단히 정리해보도록 하겠습니다.&lt;/p&gt;
&lt;pre class=&quot;coq&quot;&gt;&lt;code&gt;                             Private | Shared
                         1           |          2
    Anonymous  . stack               |
               . malloc()            |
               . brk()/sbrk()        | . POSIX shm*
               . mmap(PRIVATE, ANON) | . mmap(SHARED, ANON)
              -----------------------+----------------------
               . mmap(PRIVATE, fd)   | . mmap(SHARED, fd)
  File-backed  . pgms/shared libs    |
                         3           |          4&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 사분면에 근거하여, top의 각 세부 정보들을 대략적으로 설명하면 다음과 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우리가 흔히 메모리 영역을 heap, stack, data, code로 분류하곤 합니다. 이에 대해 관련 있는 내용은 다음과 같습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;stack : quadrant 1에 해당합니다. 컴파일 타임에 크기가 결정됩니다.&lt;/li&gt;
&lt;li&gt;heap : quadrant 1에 해당하되 mmap을 통해 할당된 경우에도 속합니다. 우리가 흔히 쓰는 malloc이 qudrant 1에 속함을 확인해볼 수 있습니다.&lt;/li&gt;
&lt;li&gt;CODE : the `pgms' portion of quadrant 3&lt;/li&gt;
&lt;li&gt;DATA : the entire quadrant 1 portion of VIRT plus all explicit mmap file-backed pages of quadrant 3&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;top의 출력물에서 관련있는 정보는 다음과 같습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;VIRT : everything in-use and/or reserved (all quadrants)&lt;/li&gt;
&lt;li&gt;SHR : subset of RES (excludes 1, includes all 2 &amp;amp; 4, some 3)&lt;/li&gt;
&lt;li&gt;RES : anything occupying physical memory which, beginning with Linux-4.5, is the sum of the following three fields:
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;RSan - quadrant 1 pages, which include any&lt;/li&gt;
&lt;li&gt;former quadrant 3 pages if modified&lt;/li&gt;
&lt;li&gt;RSfd - quadrant 3 and quadrant 4 pages&lt;/li&gt;
&lt;li&gt;RSsh - quadrant 2 pages&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;memory commit 과정과 VIRT, RES, SHR&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 종합적으로 프로세스가 처음 생성될 때 메모리를 할당 받는 과정인 memory commit을 살펴보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가상 메모리 할당 (&lt;u&gt;VIRT&lt;/u&gt;): 프로세스가 생성될 때, 커널은 해당 프로세스에 대해 가상 메모리 공간(VIRT)을 할당합니다. 이 공간은 프로세스가 사용할 수 있는 메모리의 최대 범위를 나타내지만, 처음에는 실제 물리 메모리에 할당되지 않습니다. 이것은 메모리를 효율적으로 관리하고, 실제로 필요할 때만 물리 메모리를 사용하도록 하는 것입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실제 메모리 할당과 페이지 폴트 (&lt;u&gt;RES&lt;/u&gt;): 프로세스가 운영되는 동안, 특히 쓰기 작업이 시작될 때, 가상 메모리의 일부가 실제로 필요하게 됩니다. 이때 '페이지 폴트(page fault)'가 발생합니다. 페이지 폴트는 매핑된 물리적 메모리가 페이지 테이블에 존재하지 않을 때 발생하는 것으로, 이를 통해 커널은 해당 가상 메모리 공간에 대응하는 물리 메모리(RES)를 할당하게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;공유 메모리 (&lt;u&gt;SHR&lt;/u&gt;): 공유 라이브러리와 같이 여러 프로세스에서 공유되는 메모리 영역은 SHR(공유 메모리)로 표시됩니다. 이러한 메모리는 다른 프로세스와 공유되는 물리적 메모리 주소를 가리키며, 각 프로세스의 가상 메모리 공간을 통해 동일한 물리적 메모리 주소를 참조하게 됩니다. 이는 메모리 사용의 효율성을 높이고, 중복을 방지하는 역할을 합니다.&lt;/p&gt;
&lt;details&gt;
&lt;summary&gt;VIRT, RES, SHR에 대한 man 페이지 설명&lt;/summary&gt;
&lt;pre class=&quot;mipsasm&quot;&gt;&lt;code&gt;1.  VIRT  --  Virtual Memory Size (KiB)
The total amount of virtual memory used by the task.  It includes all code, data and shared libraries plus  pages  that  have
been swapped out and pages that have been mapped but not used.

22. RES  --  Resident Memory Size (KiB)
A subset of the virtual address space (VIRT) representing the non-swapped physical memory a task is currently using.   It  is
also the sum of the RSan, RSfd and RSsh fields.
It  can  include  private anonymous pages, private pages mapped to files (including program images and shared libraries) plus
shared anonymous pages.  All such memory is backed by the swap file represented separately under SWAP.
Lastly, this field may also include shared file-backed pages which, when modified, act as a dedicated swap file and thus will
never impact SWAP.

30. SHR  --  Shared Memory Size (KiB)
A subset of resident memory (RES) that may be used by other processes.  It will include shared  anonymous  pages  and  shared
file-backed pages.  It also includes private pages mapped to files representing program images and shared libraries.&lt;/code&gt;&lt;/pre&gt;
&lt;/details&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;memory overcommit&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로세스가 요구하는 메모리의 양은 결국 물리 메모리 공간의 한계를 넘을 수 없다.&lt;br /&gt;넘게 된다면 커널 파라미터인 vm.overcommit_memory의 정의에 따라 커널이 처리한다.&lt;a href=&quot;https://mjmwired.net/kernel/Documentation/vm/overcommit-accounting&quot;&gt;^1346&lt;/a&gt;&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;sysctl vm.overcommit_memory # can be 0, 1, 2&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;process status&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;맨 페이지를 통해 좀 더 자세한 내용을 살펴보자.&lt;/p&gt;
&lt;pre class=&quot;properties&quot;&gt;&lt;code&gt;29. S  --  Process Status
    The status of the task which can be one of:
        D = uninterruptible sleep
        I = idle
        R = running
        S = sleeping
        T = stopped by job control signal
        t = stopped by debugger during trace
        Z = zombie&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;D (&lt;code&gt;un&lt;/code&gt;interruptible sleep)&lt;br /&gt;i/o를 대기하고 있는 프로세스를 의미합니다. 프로세스가 D 상태라는 것은, run queue에서 나와 wait queue에서 대기하게 됨을 말합니다.&lt;br /&gt;만약 i/o 작업이 완료되면 (예를 들어, read/write가 완료되면) 프로세스는 다시 R 상태가 됩니다.&lt;/li&gt;
&lt;li&gt;R&lt;br /&gt;실제로 cpu를 사용하고 있는 프로세스를 의미합니다.&lt;/li&gt;
&lt;li&gt;S (interruptible sleep)&lt;br /&gt;sleep 상태입니다. D와 다른 점은,&lt;br /&gt;i/o가 아닌 단순 sleep이나 콘솔의 입력을 기다리는 경우에는 S 상태가 됩니다.&lt;/li&gt;
&lt;li&gt;T, t&lt;br /&gt;프로세스를 디버거, strace 등으로 중단시킨 상태를 의미합니다.&lt;/li&gt;
&lt;li&gt;Z&lt;br /&gt;좀비 프로세스입니다. 종료되었지만, 부모 프로세스에 의해 아직 회수(리소스 해제)되지 않은 프로세스입니다. 부모 프로세스가 자식 프로세스의 exit code(exit(int) 혹은 main return(int))을 요청해야 합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;보통 좀비 프로세스를 제거하기 위해서 child process의 종료 시그널을 받아 처리하는 방식을 사용하곤 합니다. 아래는 간략한 예시입니다.&lt;/p&gt;
&lt;pre class=&quot;cpp&quot;&gt;&lt;code&gt;void handle_child(int sig) {
    if (sig == SIGCHLD) {
        int status;

        // 성공시 종료된 ps의 pid반환.
        // 특정 pid가 아닌 -1을 전달함으로써 임의의 자식 프로세스 종료를 처리함.
        pid_t id = waitpid(-1, &amp;amp;status, WNOHANG); // non blocking
        if (WIFEXITED(status)) {
            printf(&quot;remove ps id : %d\n&quot;, id);
            printf(&quot;child send : %d\n&quot;, WEXITSTATUS(status));
        }
    }
}

int main(int argc, char* argv[]) {
    pid_t pid = 0;

    // signal handling
    struct sigaction act;
    act.sa_handler = handle_child;
    sigemptyset(&amp;amp;act.sa_mask);
    act.sa_flags = 0;
    sigaction(SIGCHLD, &amp;amp;act, 0);

    ... 생략

    return 0;
}&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;PR, NI&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;run queue에 잡힌 task들은 PR(priority)와 NI(nice)에 따라 스케쥴러의 알고리즘에 의해 cpu를 할당받게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실제로 PR이 낮으면 먼저 dispatcher가 cpu에게 처리해줄 것을 요청한다.&lt;br /&gt;NI는 PR의 조정값으로, 우선순위는 PR + NI로 결정된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 process A의 PR: 10, NI: 0, process B의 PR: 10, NI: 5라면,&lt;br /&gt;process A가 10, process B가 15의 우선순위를 갖게 된다.&lt;br /&gt;따라서 process A가 먼저 cpu를 할당받게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;renice&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Alters the scheduling priority/niceness of one or more running processes.&lt;br /&gt;Niceness values range from -20 (most favorable to the process) to 19 (least favorable to the process).&lt;br /&gt;More information: &lt;a href=&quot;https://manned.org/renice&quot;&gt;https://manned.org/renice&lt;/a&gt;.&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;# Change priority of a running process:
renice -n niceness_value -p pid

# Change priority of all processes owned by a user:
renice -n niceness_value -u user

# Change priority of all processes that belong to a process group:
renice -n niceness_value --pgrp process_group&lt;/code&gt;&lt;/pre&gt;</description>
      <category>  Linux, shell, web server</category>
      <author>DarrenKwonDev</author>
      <guid isPermaLink="true">https://darrengwon.tistory.com/1583</guid>
      <comments>https://darrengwon.tistory.com/1583#entry1583comment</comments>
      <pubDate>Thu, 28 Dec 2023 04:34:04 +0900</pubDate>
    </item>
    <item>
      <title>kernel study 01: 시스템 구성 정보 확인하기</title>
      <link>https://darrengwon.tistory.com/1582</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://darrenkwondev.github.io/posts/2023-12-27_kernel_study_01.md/kernel_study_01/&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://darrenkwondev.github.io/posts/2023-12-27_kernel_study_01.md/kernel_study_01/&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1703612068194&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;kernel study 01: 시스템 구성 정보 확인하기 | darrenkwon.dev blog&quot; data-og-description=&quot;커널 이름, 호스트 이름, 커널 버전, 커널 릴리즈, 운영 체제, 하드웨어 이름(아키텍처) 등 시스템 정보를 출력하는 도구 5.15.0-91-generic 커널을 사용 중임을 확인할 수 있다. 커널의 메시지 버퍼의 &quot; data-og-host=&quot;darrenkwondev.github.io&quot; data-og-source-url=&quot;https://darrenkwondev.github.io/posts/2023-12-27_kernel_study_01.md/kernel_study_01/&quot; data-og-url=&quot;https://darrenkwondev.github.io/posts/2023-12-27_kernel_study_01.md/kernel_study_01/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/ZYGvU/hyUTCCzJzI/7AlwKPkameKuf5LXAgyh71/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630&quot;&gt;&lt;a href=&quot;https://darrenkwondev.github.io/posts/2023-12-27_kernel_study_01.md/kernel_study_01/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://darrenkwondev.github.io/posts/2023-12-27_kernel_study_01.md/kernel_study_01/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/ZYGvU/hyUTCCzJzI/7AlwKPkameKuf5LXAgyh71/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;kernel study 01: 시스템 구성 정보 확인하기 | darrenkwon.dev blog&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;커널 이름, 호스트 이름, 커널 버전, 커널 릴리즈, 운영 체제, 하드웨어 이름(아키텍처) 등 시스템 정보를 출력하는 도구 5.15.0-91-generic 커널을 사용 중임을 확인할 수 있다. 커널의 메시지 버퍼의&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;darrenkwondev.github.io&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위에서 더 깔끔하게 읽을 수 있겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;---&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div style=&quot;background-color: #282c34; color: #abb2bf;&quot;&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;+++&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;title = &lt;/span&gt;&lt;span style=&quot;color: #98c379;&quot;&gt;'kernel study 01: 시스템 구성 정보 확인하기'&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;date = &lt;/span&gt;&lt;span style=&quot;color: #d19a66;&quot;&gt;2023-12-27T00:02:35+09:00&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;math = &lt;/span&gt;&lt;span style=&quot;color: #d19a66;&quot;&gt;true&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;toc = &lt;/span&gt;&lt;span style=&quot;color: #d19a66;&quot;&gt;true&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;bold = &lt;/span&gt;&lt;span style=&quot;color: #d19a66;&quot;&gt;true&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;draft = &lt;/span&gt;&lt;span style=&quot;color: #d19a66;&quot;&gt;false&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;tags = [&lt;/span&gt;&lt;span style=&quot;color: #98c379;&quot;&gt;&quot;linux&quot;&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color: #98c379;&quot;&gt;&quot;system engineering&quot;&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color: #98c379;&quot;&gt;&quot;korean&quot;&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;]&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;+++&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;{{&amp;lt; box info &amp;gt;}}&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;based on Ubuntu 22.04.3 LTS (GNU/Linux 5.15.0-91-generic aarch64) VM&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;{{&amp;lt; /box &amp;gt;}}&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;## 커널 정보 확인&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;### uname (UNIX name)&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;커널 이름, 호스트 이름, 커널 버전, 커널 릴리즈, 운영 체제, 하드웨어 이름(아키텍처) 등 시스템 정보를 출력하는 도구&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;```&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;# uname -a&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;Linux drkup 5.15.0-91-generic #101-Ubuntu SMP Tue Nov 14 13:29:11 UTC 2023 aarch64 aarch64 aarch64 GNU/Linux&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;```&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;5.15.0-91-generic 커널을 사용 중임을 확인할 수 있다.&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;### dmesg (display message)&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;커널의 메시지 버퍼의 내용을 출력하는 도구.&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;kernel이 부팅되면서 출력했된 내용을 살펴보겠습니다.&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;```&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;# sudo dmesg | grep -i kernel | more&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;# kernel 문자열을 포함한 로그만 출력해보았다.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;# 좌측 괄호 [] 안은 시스템 부팅 이후 경과한 시간을 초 단위를 표현한 것이다.&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;# 커널 코드에 패치 적용 (시스템이 부팅되는 과정)&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;[ 0.000000] alternatives: patching kernel code&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;# 커널 파라미터. BOOT_IMAGE, root, ro 등이 보인다.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;[ 0.000000] Kernel command line: BOOT_IMAGE=/vmlinuz-5.15.0-91-generic root=/dev/mapper/ubuntu--vg-ubuntu--lv ro&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;# 주어진 커널 파라미터이지만 인식하지 못하는 파라미터는 user space로 전달된다.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;[ 0.000000] Unknown kernel command line parameters &quot;BOOT_IMAGE=/vmlinuz-5.15.0-91-generic&quot;, will be passed to user space.&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;# 커널이 인식하는 메모리 정보.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;# 시스템에 4194304K 메모리가 존재하며 3860508K가 사용 가능하다.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;[ 0.000000] Memory: 3860508K/4194304K available (17280K kernel code, 4576K rwdata, 13928K rodata, 9600K init, 1194K bss, 301028K reserved&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;, 32768K cma-reserved)&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;# 직접 메모리 액세스(DMA)에 사용되는 사전 할당된 메모리 풀 관련 로그&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;# CPU를 거치지 않고 메모리와 하드웨어 장치 간에 데이터를 직접 전송하기 위해 필요합니다.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;[ 0.084903] DMA: preallocated 512 KiB GFP_KERNEL pool for atomic allocations&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;[ 0.085653] DMA: preallocated 512 KiB GFP_KERNEL|GFP_DMA pool for atomic allocations&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;[ 0.086177] DMA: preallocated 512 KiB GFP_KERNEL|GFP_DMA32 pool for atomic allocations&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;# 커널이 로드한 X.509 인증서 관련 로그&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;[ 0.744737] Loaded X.509 cert 'Build time autogenerated kernel key: a3ee82ff8d989103803e60e521b19f3fabe02ee9'&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;[ 0.746343] Loaded X.509 cert 'Canonical Ltd. Kernel Module Signing: 88f752e560a1e0737e31163a466ad7b70a850c19'&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;[ 0.797094] Loaded X.509 cert 'Build time autogenerated kernel key: a3ee82ff8d989103803e60e521b19f3fabe02ee9'&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;# 시스템 부팅 하면서 사용했던 메모리를 반환&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;[ 0.802006] Freeing unused kernel memory: 9600K&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;# systemd 작업들.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;[ 3.234080] systemd[1]: Listening on udev Kernel Socket.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;[ 3.236727] systemd[1]: Mounting Kernel Debug File System...&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;[ 3.241096] systemd[1]: Mounting Kernel Trace File System...&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;[ 3.276186] systemd[1]: Starting Load Kernel Module chromeos_pstore...&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;[ 3.278110] systemd[1]: Starting Load Kernel Module configfs...&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;[ 3.283414] systemd[1]: Starting Load Kernel Module drm...&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;[ 3.285204] systemd[1]: Starting Load Kernel Module efi_pstore...&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;[ 3.290713] systemd[1]: Starting Load Kernel Module fuse...&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;[ 3.298218] systemd[1]: Starting Load Kernel Module pstore_blk...&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;[ 3.302885] systemd[1]: Starting Load Kernel Module pstore_zone...&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;[ 3.305147] systemd[1]: Starting Load Kernel Module ramoops...&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;[ 3.311579] systemd[1]: Starting Load Kernel Modules...&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;[ 3.313671] systemd[1]: Starting Remount Root and Kernel File Systems...&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;```&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;### /boot/config-$(uname -r)&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;커널의 컴파일 옵션을 확인해보겠습니다. 특정 옵션이 활성화 되어 있어야만 사용할 수 있는 기능이 존재합니다.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;예를 들어 ftrace를 사용하기 위해서는 CONFIG_FTRACE 옵션이 활성화 되어 있어야 합니다.&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;```&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;#cat /boot/config-$(uname -r) | head -n 10&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;# 너무 많은 옵션이 존재하니 앞의 10줄 정도만 출력해보았습니다.&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;#&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;# Automatically generated file; DO NOT EDIT.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;# Linux/arm64 5.15.0-91-generic Kernel Configuration&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;#&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;CONFIG_CC_VERSION_=&quot;gcc (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0&quot;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;CONFIG_CC_IS_GCC=y&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;CONFIG_GCC_VERSION=110400&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;CONFIG_CLANG_VERSION=0&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;CONFIG_AS_IS_GNU=y&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;CONFIG_AS_VERSION=23800&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;```&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;## dmidecode (dmi : Desktop Management Interface)&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;하드웨어 정보를 보여주는 명령어입니다. 이 명령어는 시스템의 BIOS, 시스템 보드, 프로세서, 메모리 등과 같은 다양한 컴포넌트에 대한 상세한 정보를 제공합니다.&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;가능한 타입을 나열하면 아래와 같습니다.&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;```&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;Valid type keywords are:&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; bios&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; system&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; baseboard&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; chassis&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; processor&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; memory&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; cache&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; connector&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; slot&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;```&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;### dmidecode -t bios&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;BIOS(Basic Input/Output System)를 확인해보겠습니다.&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;```&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;# dmidecode -t bios&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;# UTM VM에서 실행하여 흔히 보이는 vendor가 아닌 UEFI 환경임을 확인할 수 있습니다.&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;# dmidecode 3.3&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;Getting SMBIOS data from sysfs.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;SMBIOS 3.0.0 present.&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;Handle 0x0000, DMI type 0, 26 bytes&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;BIOS Information&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; #&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Vendor: EFI Development Kit II / OVMF&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Version: 0.0.0&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Release Date: 02/06/2015&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Address: 0xE8000 # bios가 메모리 상에서 위치한 시작 주소&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Runtime Size: 96 kB # bios run time의 크기입니다.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; ROM Size: 64 kB&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Characteristics:&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; BIOS characteristics not supported&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Targeted content distribution is supported&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; UEFI is supported&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; System is a virtual machine&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; BIOS Revision: 0.0&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;```&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;### dmidecode -t system&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;시스템 관련 정보를 출력해보겠습니다. 컴퓨터를 구성하는 다양한 하드웨어의 모델명 등을 확인할 수 있습니다.&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;```&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;# dmidecode -t system&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;# VM이라서 에뮬레이터인 QEMU를 사용하고 있음을 확인할 수 있습니다.&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;# dmidecode 3.3&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;Getting SMBIOS data from sysfs.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;SMBIOS 3.0.0 present.&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;Handle 0x0100, DMI type 1, 27 bytes&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;System Information&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Manufacturer: QEMU&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Product Name: QEMU Virtual Machine&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Version: virt-7.2&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Serial Number: Not Specified&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; UUID: &amp;lt;omit&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Wake-up Type: Power Switch&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; SKU Number: Not Specified&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Family: Not Specified&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;Handle 0x2000, DMI type 32, 11 bytes&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;System Boot Information&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Status: No errors detected&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;```&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;## cpu&lt;/span&gt;&lt;span style=&quot;color: #d19a66;&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color: #61afef;&quot;&gt;^1&lt;/span&gt;&lt;span style=&quot;color: #d19a66;&quot;&gt;]&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #d19a66;&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color: #61afef;&quot;&gt;^1&lt;/span&gt;&lt;span style=&quot;color: #d19a66;&quot;&gt;]&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;: cpu의 개략적인 내용은 &lt;/span&gt;&lt;span style=&quot;color: #d19a66;&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color: #61afef;&quot;&gt;cpu.land&lt;/span&gt;&lt;span style=&quot;color: #d19a66;&quot;&gt;]&lt;/span&gt;&lt;span style=&quot;color: #c678dd;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #c678dd;&quot;&gt;&lt;a href=&quot;https://cpu.land/&quot;&gt;https://cpu.land/&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color: #c678dd;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;의 문서를 확인해보는 것이 좋습니다.&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;### /proc/cpuinfo&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;```&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;# cat /proc/cpuinfo&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;processor : 0&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;BogoMIPS : 48.00&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm jscvt fcma lrcpc dcpop sha3 asimddp sha512 asimdfhm dit uscat ilrcpc flagm sb paca pacg dcpodp flagm2 frint&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;CPU implementer : 0x00&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;CPU architecture: 8&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;CPU variant : 0x0&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;CPU part : 0x000&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;CPU revision : 0&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;(omit)&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;```&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;### dmidecode -t processor&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;cpu(processor) 정보를 출력해보겠습니다. &lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;자주 출력해보는 내용이기 때문에 가상 머신이 아닌 타 기기에서 출력된 내용물을 가지고 설명해보겠습니다.&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;장착된 cpu가 1개라고 인식되기 때문에 하나의 cpu 정보만 출력되었습니다. 만약 motherboard의 소켓에 여러 cpu를 장착했다면, 해당 갯수만큼 출력될 것입니다.&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;흔히 물리적 cpu 코어의 갯수와 논리적 cpu 코어의 갯수를 헷갈리는데 해당 출력을 통해 명확히 구분할 수 있습니다. Socket Designation은 곧 cpu가 mother board에 장착된 소켓의 위치이며, Core Count는 장착된 하나의 cpu가 소유한 컴퓨팅 코어를 의미합니다. 아래 출력물을 기준으로 설명하자면, 물리적으로 cpu는 2개가 소켓에 장착되어 있으며 각각 8개의 코어를 가지고 있으며 하이퍼 쓰레딩이 적용되어 있어 하나의 코어당 2개 이상의 thread가 존재하는 것으로 확인됩니다.&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;```&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;# dmidecode -t processor&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;# dmidecode 3.3&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;Getting SMBIOS data from sysfs.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;SMBIOS 3.2.0 present.&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;Handle 0x0400, DMI type 4, 48 bytes&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;Processor Information&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Socket Designation: CPU 0 # cpu가 장착된 소켓의 이름입니다. MB에 cpu를 장착할 때 사용하는 소켓의 이름과 동일합니다.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Type: Central Processor # cpu임을 나타냅니다.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Family: Xeon&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Manufacturer: Intel&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; ID: C3 06 03 00 FF FB EB BF&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Version: Intel(R) Xeon(R) CPU E5-2600 v4&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Voltage: 1.2 V&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; External Clock: 100 MHz&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Max Speed: 3000 MHz&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Current Speed: 3000 MHz&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Status: Populated, Enabled&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Upgrade: Socket LGA 2011&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; L1 Cache Handle: 0x0700&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; L2 Cache Handle: 0x0701&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; L3 Cache Handle: 0x0702&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Serial Number: Not Specified&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Asset Tag: Not Specified&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Part Number: Not Specified&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Core Count: 8 # cpu가 소유한 물리적 core 갯수를 의미합니다.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Core Enabled: 8&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Thread Count: 16 # 일반적으로 하이퍼스레딩 또는 다중 스레딩 기술이 적용된 경우, 물리적 코어 수보다 스레드 수가 더 많습니다.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Characteristics:&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; 64-bit capable&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Multi-Core&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Hardware Thread&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;# 다른 소켓에 장착된 cpu의 정보를 출력합니다. 해당 컴퓨터가 2개의 cpu를 장착하고 있음을 의미합니다.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;Handle 0x0401, DMI type 4, 48 bytes&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;Processor Information&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Socket Designation: CPU 1&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Type: Central Processor&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Family: Xeon&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Manufacturer: Intel&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; ID: C3 06 03 00 FF FB EB BF&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Version: Intel(R) Xeon(R) CPU E5-2600 v4&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Voltage: 1.2 V&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; External Clock: 100 MHz&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Max Speed: 3000 MHz&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Current Speed: 3000 MHz&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Status: Populated, Enabled&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Upgrade: Socket LGA 2011&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; L1 Cache Handle: 0x0703&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; L2 Cache Handle: 0x0704&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; L3 Cache Handle: 0x0705&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Serial Number: Not Specified&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Asset Tag: Not Specified&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Part Number: Not Specified&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Core Count: 8&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Core Enabled: 8&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Thread Count: 16&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Characteristics:&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; 64-bit capable&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Multi-Core&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Hardware Thread&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;```&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;### lscpu&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;cpu와 관련된 정보를 출력하는 명령어입니다. dmidecode와 비슷한 역할을 하지만, 더 간단하게 출력해줍니다. &lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;특히, NUMA와 관련된 정보를 출력해주는 점이 차이점입니다.&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;```&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;# lscpu&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;Architecture: aarch64&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; CPU op-mode(s): 64-bit&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Byte Order: Little Endian&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;CPU(s): 8&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; On-line CPU(s) list: 0-7&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;Vendor ID: 0x00&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Model: 0&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Thread(s) per core: 1&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Core(s) per socket: 8&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Socket(s): 1&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Stepping: 0x0&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; BogoMIPS: 48.00&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Flags: fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm jscvt fcma lrcpc dcpop sha3 asimddp s&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; ha512 asimdfhm dit uscat ilrcpc flagm sb paca pacg dcpodp flagm2 frint&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;NUMA:&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; NUMA node(s): 1&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; NUMA node0 CPU(s): 0-7&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;Vulnerabilities:&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Gather data sampling: Not affected&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Itlb multihit: Not affected&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; L1tf: Not affected&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Mds: Not affected&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Meltdown: Not affected&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Mmio stale data: Not affected&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Retbleed: Not affected&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Spec rstack overflow: Not affected&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Spec store bypass: Vulnerable&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Spectre v1: Mitigation; __user pointer sanitization&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Spectre v2: Not affected&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Srbds: Not affected&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Tsx async abort: Not affected&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;```&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;## memory&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;### /proc/meminfo&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;메모리 정보를 출력하는 명령어입니다. 메모리의 총 용량, 사용량, 사용 가능한 용량 등을 확인할 수 있습니다.&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;```&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;# cat /proc/meminfo&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;MemTotal: 4004640 kB&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;MemFree: 1628216 kB&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;MemAvailable: 3582652 kB&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;Buffers: 62432 kB&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;Cached: 1957112 kB&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;SwapCached: 0 kB&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;Active: 623540 kB&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;Inactive: 1451744 kB&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;Active(anon): 1332 kB&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;```&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;### free&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;```&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;# free&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; total used free shared buff/cache available&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;Mem: 4004640 225444 1628468 5380 2150728 3582876&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;Swap: 3001340 0 3001340&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;```&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;total = used + free + buff/cached&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; total : Total installed memory (MemTotal and SwapTotal in /proc/meminfo)&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; used : Used memory (= total - free - buffers - cache)&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; 진짜로 사용되고 있는 영역이 아니라, buff/cache를 제외한 메모리를 말합니다.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; free : Unused memory (MemFree and SwapFree in /proc/meminfo)&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; buff/cache = 디스크에 있는 파일이 메모리에 올라와 유지된 것들. 사실상 쓰고 있지만 used로 잡히지가 않음&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; buffers : Memory used by kernel buffers (Buffers in /proc/meminfo)&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; 파일 정보, 파일의 메타 데이터를 의미합니다.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; cache : Memory used by the page cache and slabs (Cached and SReclaimable in /proc/meminfo)&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; 파일의 실제 내용을 저장되는데 사용됩니다.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; 예를 들면 동영상 파일이 메모리에 올라와 있다면 buffer는 작겠지만 cache는 클 것이라 예측할 수 있다.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; shared : Memory used (mostly) by tmpfs (Shmem in /proc/meminfo)&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; available : Estimation of how much memory is available for starting new applications, without swapping.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; 어떤 프로세스가 만들어진다면 메모리를 사용할 때 최대 어디까지 사용할 수 있음?&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; 보통 buff/cache + free 정도임.&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;### dmidecode -t memory&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;dmidecode의 메모리 정보 출력물을 통해서, 메모리를 Physical Memory Array와 Memory Device로 구분하여 출력합니다.&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;```&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;# dmidecode -t memory&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;# dmidecode 3.3&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;Getting SMBIOS data from sysfs.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;SMBIOS 3.0.0 present.&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;Handle 0x1000, DMI type 16, 23 bytes&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;Physical Memory Array&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Location: Other&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Use: System Memory&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Error Correction Type: Multi-bit ECC&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Maximum Capacity: 4 GB&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Error Information Handle: Not Provided&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Number Of Devices: 1&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;Handle 0x1100, DMI type 17, 40 bytes&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;Memory Device&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Array Handle: 0x1000&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Error Information Handle: Not Provided&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Total Width: Unknown&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Data Width: Unknown&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Size: 4 GB&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Form Factor: DIMM&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Set: None&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Locator: DIMM 0&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Bank Locator: Not Specified&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Type: RAM&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Type Detail: Other&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Speed: Unknown&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Manufacturer: QEMU&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Serial Number: Not Specified&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Asset Tag: Not Specified&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Part Number: Not Specified&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Rank: Unknown&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Configured Memory Speed: Unknown&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Minimum Voltage: Unknown&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Maximum Voltage: Unknown&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Configured Voltage: Unknown&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;```&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;## disk&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;### df (disk free)&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;각 파일 시스템이 마운트 된 곳과 용량을 출력합니다.&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;/dev/mapper/ubuntu--vg-ubuntu--lv, /dev/vda1, /dev/vda2 3개의 파일 시스템이 확인됩니다.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;마운트된 경로를 보니 vda1, vda2는 부트 파티션으로 사용되고 있고, ubuntu--vg-ubuntu--lv는 루트 파티션으로 사용되고 있음을 확인할 수 있습니다.&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;VM 위의 파일 시스템이기 때문에 vda로 시작하는 이름을 가지고 있습니다. 일반적으로는 hda나 sda로 시작하는 이름을 가지고 있습니다.&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;tmpfs 는 임시 파일 시스템을 의미합니다.&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;```&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;# df -h (human readable)&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;Filesystem Size Used Avail Use% Mounted on&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;tmpfs 392M 1.4M 390M 1% /run&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;/dev/mapper/ubuntu--vg-ubuntu--lv 15G 7.0G 6.5G 52% /&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;tmpfs 2.0G 0 2.0G 0% /dev/shm&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;tmpfs 5.0M 0 5.0M 0% /run/lock&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;/dev/vda2 2.0G 129M 1.7G 8% /boot&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;/dev/vda1 1.1G 6.4M 1.1G 1% /boot/efi&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;tmpfs 392M 4.0K 392M 1% /run/user/1000&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;```&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;### lsblk (list block devices)&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;블록 장치(디스크, 파티션, 논리 볼륨 등)에 대한 정보를 출력합니다.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;특히, RAID 구성 여부를 확인할 수 있습니다.&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;```&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;# lsblk&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;loop0 7:0 0 59.2M 1 loop /snap/core20/1977&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;loop1 7:1 0 109.6M 1 loop /snap/lxd/24326&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;loop2 7:2 0 46.4M 1 loop /snap/snapd/19459&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;loop3 7:3 0 35.5M 1 loop /snap/snapd/20298&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;sr0 11:0 1 1024M 0 rom&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;vda 252:0 0 32G 0 disk&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;├─vda1 252:1 0 1G 0 part /boot/efi&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;├─vda2 252:2 0 2G 0 part /boot&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;└─vda3 252:3 0 28.9G 0 part&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; └─ubuntu--vg-ubuntu--lv 253:0 0 14.5G 0 lvm /&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;```&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;MAJ:MIN: major, minor number. 커널이 해당 디스크를 식별하는 데 사용하는 고유 번호입니다.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;RM: 디스크의 제거 가능 여부&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;RO: 읽기 전용 여부&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;TYPE: 디스크의 타입. lvm(logical volume manager)를 사용하고 있음을 확인할 수 있습니다. RAID로 구성여부도 출력됩니다.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;MOUNTPOINTS: 마운트된 경로&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;```&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;sda 8:0 0 1TB 0 disk&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;├─sda1 8:1 0 512M 0 part /boot/efi&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;├─sda2 8:2 0 2GB 0 part [SWAP]&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;└─sda3 8:3 0 997.5G 0 part&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; └─md0 9:0 0 1.9T 0 raid1 /&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;sdb 8:16 0 1TB 0 disk&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;├─sdb1 8:17 0 512M 0 part&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;├─sdb2 8:18 0 2GB 0 part&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;└─sdb3 8:19 0 997.5G 0 part&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; └─md0 9:0 0 1.9T 0 raid1 /&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;```&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;위 예시에서 &quot;sda&quot;와 &quot;sdb&quot; 디스크는 RAID1으로 구성되었습니다. &quot;md0&quot;은 RAID 레이드 장치를 나타내며 &quot;/dev/md0&quot;는 RAID로 구성된 볼륨을 나타냅니다. RAID 구성은 여러 디스크의 복제 또는 데이터 분산을 허용하므로 &quot;md0&quot;의 하위 항목으로 &quot;sda3&quot;와 &quot;sdb3&quot;이 나타납니다.&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;## network (네트워크 카드)&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;### 네트워크 카드(NIC) 확인하기&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;lspci 명령어는 PCI 버스를 통해 연결된 장치들의 정보를 출력합니다.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;여기서는 네트워크와 관련된 정보만을 grep하기 위해 grep 명령어를 사용하였습니다.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;구체적으로, 서버가 사용하는 네트워크 카드(NIC)를 확인할 수 있습니다.&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;```&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;# lspci | grep -i ether&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;00:01.0 Ethernet controller: Red Hat, Inc. Virtio network device&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;```&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;### ip로 network interface 확인&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;{{&amp;lt; box tip &amp;gt;}}&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;ifconfig 보다 ip 사용을 권장함. ifconfig는 유지 보수가 끝났으나 ip는 리눅스 커널과 같이 개발되며 지속적으로 유지보수되고 있음.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;{{&amp;lt; /box &amp;gt;}}&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;```&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;ip address # ip a로만 입력 가능&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;ip link # 네트워크 인터페이스 확인&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;ip neigh # ARP 테이블 (mac 주소) 확인하기&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;```&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;해당 글에서는 하드웨어적인 측면에서 살펴봐야하므로 ip 명령어에 대한 설명은 네트워크 인터페이스의 목록을 확인하는 것 정도로 마치겠습니다.&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;```&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;ip a&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;1: lo: &amp;lt;LOOPBACK,UP,LOWER_UP&amp;gt; mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; inet 127.0.0.1/8 scope host lo&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; valid_lft forever preferred_lft forever&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; inet6 ::1/128 scope host&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; valid_lft forever preferred_lft forever&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;2: enp0s1: &amp;lt;BROADCAST,MULTICAST,UP,LOWER_UP&amp;gt; mtu 1500 qdisc fq_codel state UP group default qlen 1000&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; link/ether 1e:6f:22:b0:70:1e brd ff:ff:ff:ff:ff:ff&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; inet 192.168.64.4/24 metric 100 brd 192.168.64.255 scope global dynamic enp0s1&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; valid_lft 72571sec preferred_lft 72571sec&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; inet6 fd1d:e88a:d67e:2671:1c6f:22ff:feb0:701e/64 scope global dynamic mngtmpaddr noprefixroute&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; valid_lft 2591943sec preferred_lft 604743sec&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; inet6 fe80::1c6f:22ff:feb0:701e/64 scope link&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; valid_lft forever preferred_lft forever&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;```&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;루프팩 인터페이스를 제외하고, enp0s1 인터페이스, en(이더넷), po(포트), s1(슬롯1)을 의미합니다.&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;### ethtool&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;위에서 확인한 네트워크 인터페이스의 구체적인 정보를 확인해볼 수 있습니다.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;안타깝게도 가상 머신에서는 정상적인 값을 출력하지 않으므로 타 기기의 출력물을 살펴보겠습니다.&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;Supported link modes는 네트워크 카드가 지원하는 연결 모드를 의미합니다. &lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;Advertised link modes는 네크워크 상 다른 장치와 연결 할 때 사용할 수 있는 연결 모드를 의미합니다.&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;해당 네트워크 카드가 지원하는 연결 모드와 속도를 확인해보겠습니다.&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;{{&amp;lt; box tip &amp;gt;}}&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;Half Duplex and Full Duplex&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;Half Duplex는 데이터가 한 번에 한 방향으로만 전송될 수 있음을 의미합니다. &lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;Full Duplex는 데이터가 동시에 양방향으로 전송될 수 있음을 의미합니다. &lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;{{&amp;lt; /box &amp;gt;}}&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; 10baseT/Half 10baseT/Full: 10 Mbps 속도의 Half Duplex와 Full Duplex 연결을 지원합니다.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; 100baseT/Half와 100baseT/Full: 각각 100 Mbps의 Half Duplex와 Full Duplex 연결을 지원합니다.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; 1000baseT/Full: 1000 Mbps (1 Gbps) 속도의 Full Duplex 연결을 지원합니다.&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;```&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;Settings for enp0s1:&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Supported ports: [ TP ]&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Supported link modes: 10baseT/Half 10baseT/Full&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; 100baseT/Half 100baseT/Full&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; 1000baseT/Full&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Supported pause frame use: No&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Supports auto-negotiation: Yes&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Advertised link modes: 10baseT/Half 10baseT/Full&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; 100baseT/Half 100baseT/Full&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; 1000baseT/Full&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Advertised pause frame use: No&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Advertised auto-negotiation: Yes&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Link partner advertised link modes: Not reported&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Link partner advertised pause frame use: No&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Link partner advertised auto-negotiation: No&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Speed: 1000Mb/s # 현재 속도&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Duplex: Full # duplex 지원&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Port: Twisted Pair&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; PHYAD: 0&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Transceiver: internal&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Auto-negotiation: on&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; MDI-X: off (auto)&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Supports Wake-on: pumbg&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Wake-on: g&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Current message level: 0x00000007 (7)&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; drv probe link&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; Link detected: yes # 정상적으로 연결되었음을 의미합니다.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;```&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;### ethtool -g (ring buffer)&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;NIC의 버퍼 공간인 ring buffer의 크기를 확인해볼 수 있습니다. &lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;패킷이 전달되면 ring buffer에 우선 복사된 후 커널에 의해 처리됩니다. &lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;ring buffer가 너무 작다면 자주 커널에 의해 처리되어야 하므로 성능 저하가 발생할 수 있습니다.&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;관습적으로 pre-set maximums와 같게 hardware settings을 맞춰야 합니다.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;수정을 원한다면 -G 플래그를 통해 수정할 수 있습니다.&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;```&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;# ethtool -g enp0s1&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;Ring parameters for enp0s1:&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;Pre-set maximums:&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;RX: 256&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;RX Mini: n/a&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;RX Jumbo: n/a&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;TX: 256&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;Current hardware settings:&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;RX: 256&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;RX Mini: n/a&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;RX Jumbo: n/a&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;TX: 256&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;```&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;### ethtool -k&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;NIC 옵션을 확인할 수 있습니다. &lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;tcp-offload 기능을 통해 mtu 이상의 크기를 가진 패킷의 분할 작업을 cpu가 아닌 NIC가 처리하도록 할 수 있습니다. 그러나 네트워크 대역폭이 높은 서버와 같이 특정 환경에서는 불특정한 패킷 유실이 발생할 수 있어 off 시키곤 합니다.&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;```&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;# ethtool -k enp0s1 | head -n 10&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;Features for enp0s1:&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;rx-checksumming: off [fixed]&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;tx-checksumming: off&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; tx-checksum-ipv4: off [fixed]&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; tx-checksum-ip-generic: off [fixed]&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; tx-checksum-ipv6: off [fixed]&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; tx-checksum-fcoe-crc: off [fixed]&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; tx-checksum-sctp: off [fixed]&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;scatter-gather: off&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; tx-scatter-gather: off [fixed]&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;```&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;### ethtool -i&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;NIC의 커널 드라이버 정보를 확인할 수 있습니다.&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;```&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;ethtool -i enp0s1&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;driver: virtio_net&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;version: 1.0.0&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;firmware-version:&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;expansion-rom-version:&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;bus-info: 0000:00:01.0&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;supports-statistics: yes&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;supports-test: no&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;supports-eeprom-access: no&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;supports-register-dump: no&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;supports-priv-flags: no&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;```&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>  Linux, shell, web server</category>
      <author>DarrenKwonDev</author>
      <guid isPermaLink="true">https://darrengwon.tistory.com/1582</guid>
      <comments>https://darrengwon.tistory.com/1582#entry1582comment</comments>
      <pubDate>Wed, 27 Dec 2023 02:34:47 +0900</pubDate>
    </item>
    <item>
      <title>게임 엔진 제작하기</title>
      <link>https://darrengwon.tistory.com/1581</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/DarrenKwonDev/simple_2d_game_engine&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://github.com/DarrenKwonDev/simple_2d_game_engine&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1703617060214&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;GitHub - DarrenKwonDev/simple_2d_game_engine: SDL-based 2D game engine using event system and ECS pattern&quot; data-og-description=&quot;SDL-based 2D game engine using event system and ECS pattern - GitHub - DarrenKwonDev/simple_2d_game_engine: SDL-based 2D game engine using event system and ECS pattern&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/DarrenKwonDev/simple_2d_game_engine&quot; data-og-url=&quot;https://github.com/DarrenKwonDev/simple_2d_game_engine&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/csTlgO/hyUTGrtuWI/ehpPb5IKtQ6VqAOXwcl2Ek/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/DarrenKwonDev/simple_2d_game_engine&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/DarrenKwonDev/simple_2d_game_engine&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/csTlgO/hyUTGrtuWI/ehpPb5IKtQ6VqAOXwcl2Ek/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;GitHub - DarrenKwonDev/simple_2d_game_engine: SDL-based 2D game engine using event system and ECS pattern&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;SDL-based 2D game engine using event system and ECS pattern - GitHub - DarrenKwonDev/simple_2d_game_engine: SDL-based 2D game engine using event system and ECS pattern&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위에서 코드 전문과 깔끔한 글을 읽을 수 있습니다.&lt;/p&gt;
&lt;h1&gt;simple_2d_game_engine&lt;/h1&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;configure&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;deps&lt;/h3&gt;
&lt;pre class=&quot;mipsasm&quot;&gt;&lt;code&gt;brew install sdl2 sdl2_image sdl2_ttf sdl2_mixer lua&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;game things&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;VSync (vertical sync, 수직 동기화)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래와 같은 tearing은 게임이 매 프레임마다 렌더링을 하는 사이 모니터의 refresh rate(주사율, 재생률) 과 맞지 않아서 그리는 도중을 보여줘서 보이는 현상임.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./imgs/screen_tearing.webp&quot; /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이를 위해 게임 렌더러의 프레젠테이션(화면에 그리는 것)을 모니터의 refresh rate와 동기화하는 기술이 vsync이며 결과적으론 tearing을 방지 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;추가로, GPU가 모니터의 refresh rate보다 더 많은 프레임을 렌더링하지 않도록 제한함으로써, 불필요한 GPU 부하를 줄일 수도 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제는 모니터의 refresh rate가 60Hz라면, 게임의 fps는 60fps로 제한되며 (60fps 이상으로 렌더링해도 60fps 이상이라고 인식하지 못함. 애초에 주사율이 초당 60번 refresh되니까.) 만약 60fps를 못 맞춘다면 나누어 떨어지는 30fps로 렌더링됨. 결국 GPU가 힘들면 fps가 낮아짐.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Double-Buffered Renderer&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;back buffer와 front buffer의 이중 운용.&lt;br /&gt;draw를 back buffer에서 먼저하고 front buffer로 swap하는 방식.&lt;br /&gt;glitch를 방지하고, 렌더링이 완료되지 않은 프레임은 화면에 보여지지 않는 장점이 있음.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Fixed Time Step(Frame Rate Independence) game loop&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래 코드는 while loop를 도는데 구동되는 컴퓨터의 CPU 성능에 의존적이다.&lt;br /&gt;즉, 게임을 구동하는 클라이언트마다 동일한 게임 경험을 줄 수 없다는 것을 의미한다.&lt;/p&gt;
&lt;pre class=&quot;cpp&quot;&gt;&lt;code&gt;void Game::RunGameLoop() {
    Game::Setup();
    while (mIsRunning) {
        Game::ProcessInput();
        Game::Update();
        Game::Render();
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 문제에 대한 해결책으로&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;고정 프레임 레이트 업데이트&lt;/li&gt;
&lt;li&gt;시간 기반 업데이트&lt;/li&gt;
&lt;li&gt;등... 이 존재한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Variable Delta-Time (frame drop compensate with delta time)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;unity, love2d 등 웬만한 게임 엔진은 game loop를 메서드 형식으로 노출하고 있다. 그 중에서도 update는 frame마다 호출된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서, fps가 하락하면 update 호출 횟수도 줄어듦. frame이 바뀌어도 동일한 정도로 움직이게 만들어야 함.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, 다른 frame rate에서도 속도 등이 frame rate에 영향을 받지 않게 만들어야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해결 방법의 핵심 : if frame rate drop, should be compensate for it.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;case 1. 60fps -&amp;gt; 30fps&lt;br /&gt;update 호출이 덜 일어나지만 dt가 늘어났으므로 dt를 곱하여 compensate.&lt;/li&gt;
&lt;li&gt;case 2. 60fps -&amp;gt; 120fps&lt;br /&gt;update 호출이 더 자주 일어나지만 dt가 줄어들었으므로 dt를 곱하면 compensate됨.&lt;/li&gt;
&lt;li&gt;dt를 곱함으로써 frame rate에 영향을 받지 않고, '초' 단위로 속도를 조절할 수 있게 됨.&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-lua&quot;&gt;-- 17pixel per second
player.x = player.x + 17 * dt&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Determinism&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어떤 것이 Deterministic 하다는 것은, 동일한 입력을 제공할 때마다 정확히 동일한 출력이 되돌아오는 것을 의미한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대부분 컴퓨터에서는 결정적인 것이 많으므로 비결정적인 것을 살펴보는 것이 더 빠르다. 멀티 쓰레딩, 네트워크, 가변 delta time을 활용한 compensating 등이 비결정적이다. 멀티 쓰레딩을 해봤다면, 동일한 queue에 데이터를 각 쓰레드가 데이터를 던졌다면, 그 순서가 매 실행마다 달라지는 것을 체험해봤을 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서는 게임을 다루고 있으니 variable delta time에 대해서 이야기해보자. variable delta time을 활용했다면 비결정적이다. 왜냐하면, 동일한 입력을 제공했을 때마다 다른 delta time이 반환되기 때문이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결정적인 constant delta time을 이용하려면 단순히 &lt;code&gt;1 / fps&lt;/code&gt;를 활용하면 된다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;ECS(Entity Component System)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;box(entity)에 box collider(component)를 넣어 특성을 부여하는 식의 구현은 unity을 비롯한 게임 엔진에서 흔히 볼 수 있는 시스템.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;data-oriented design을 통해 cache-friendly하게 구현하느 것이 목표임. 따라서 OOP와는 다른 구조를 가짐.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;OOP와 ECS의 가장 큰 차이점은, OOP에서는 base class와 derived class간의 상속과 위계가 강조되지만 ECS에서는 Component가 데이터를 소유하고, 엔티티는 단순히 컴포넌트의 컨테이너 역할을 한다는 것입니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Entity(id)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;게임 내의 모든 객체나 아이템은 엔티티로 표현됩니다. 엔티티 자체는 단순히 고유 식별자(ID)를 가진 컨테이너에 불과하며, 실제로는 아무런 데이터나 행동을 직접 가지지 않습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Component(data)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;pure data&lt;/li&gt;
&lt;li&gt;pure data라는 관점에서 plain old data(POD)를 표현하기 위한 struct로 구현하는게 잘 어울린다. 그 과정에서 memory padding을 고려하는 것이 좋다. (#pragma pack을 활용하거나 수동으로 구조체 멤버의 순서를 조정하자.)&lt;/li&gt;
&lt;li&gt;그러나 여러 기능 때문에 class로 구현이 되곤 한다.&lt;/li&gt;
&lt;li&gt;컴포넌트는 엔티티의 데이터를 나타냅니다. 예를 들어, 위치, 속도, 건강 상태 등과 같은 속성들이 컴포넌트로 표현됩니다. 이들은 엔티티에 첨부되어 엔티티의 상태를 정의합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;System(transform data logic)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;entity는 id, component는 data, system은 behavior를 담당한다. 즉, component의 상태 데이터를 변경하는 것이 system의 역할이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;component의 memory contiguous한 배치와 Pool&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ECS에서는 컴포넌트를 사용하여 데이터를 저장합니다. 이 컴포넌트들은 종종 메모리 상에서 연속적으로 배치됩니다. 즉, memory contiguity (메모리 연속성)를 지키도록 배치됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;쉽게 말해서 [comp, comp, comp, comp, ...] 와 같은 꼴입니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;캐시 친화적 접근: 시스템이 특정 컴포넌트 유형을 작업할 때, 연속된 메모리 레이아웃 덕분에 캐시 효율성이 높아집니다. 예를 들어, 물리 시스템이 모든 위치 컴포넌트를 순차적으로 처리할 때, 연속된 메모리 레이아웃은 캐시 적중률을 높여 성능을 향상시킵니다.&lt;/li&gt;
&lt;li&gt;데이터 지향 설계: ECS는 데이터 지향 설계 원칙을 따릅니다. 이는 데이터를 중심으로 시스템을 구성하여, 메모리 접근 패턴을 최적화하는 것을 목표로 합니다. 이러한 접근 방식은 메모리 연속성을 중시합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;생각해보면, memory contiguous한 자료구조(vector, array, ...)에 객체를 넣기만 하면 이를 달성할 수 있을 것으로 보인다. 이의 구현체를 관습적으로 &lt;code&gt;Pool&lt;/code&gt;이라고 부른다. (DB connection 비용 아끼려고 만드는 pool과는 맥락이 다르니 이해에 주의)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ECS 시스템에서의 Pool이란 &lt;code&gt;컴포넌트를 저장, 관리하기 위한 메모리 저장 영역&lt;/code&gt;을 의미한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Pool 방식으로 관리함으로써 동일한 유형의 컴포넌트를 연속된 메모리 공간에 저장하여 memory contiguity를 달성함으로써, 메모리 할당 및 해제를 최적화하고, 캐시 효율성이 향상된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Pool의 구현은 단순히 memory contiguous한 자료구조(vector, array, ...)에 객체 혹은 식별자를 넣은 것에 불과하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 엔진에서의 Pool은 (entity의 갯수, component의 갯수)의 이차원 배열 꼴로 아래와 같이 구성된다.&lt;/p&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Entity / Component&lt;/th&gt;
&lt;th&gt;CompA&lt;/th&gt;
&lt;th&gt;CompB&lt;/th&gt;
&lt;th&gt;CompC&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Entity 0&lt;/td&gt;
&lt;td&gt;CompA&lt;/td&gt;
&lt;td&gt;CompB&lt;/td&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Entity 1&lt;/td&gt;
&lt;td&gt;CompA&lt;/td&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;td&gt;CompC&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Entity 2&lt;/td&gt;
&lt;td&gt;CompA&lt;/td&gt;
&lt;td&gt;CompB&lt;/td&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Entity 3&lt;/td&gt;
&lt;td&gt;CompA&lt;/td&gt;
&lt;td&gt;CompB&lt;/td&gt;
&lt;td&gt;CompC&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실, 이러한 구성은 entity가 가지고 있지 않은 component 부분에 대해서 data cap을 가진, 즉, 메모리를 낭비하는 부분이 있다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;pool의 data gap을 제거하는 방안 (개선안)&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, component pool을 packed하게 관리해야 한다.&lt;br /&gt;위 방식에 data gap이 발생하는 이유는, 단순히 entityId를 index로 사용하고 있기 때문이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 간단한 방식으로 해결하려면, entity-index 간 상호 변환 가능한 양방향 맵을 운영하는 것.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;DOP (data-oriented programming)&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;게임 관련 프로그램은 말 그대로 &lt;code&gt;squeeze performance out of hardware&lt;/code&gt;를 목표로 한다. 보통 CPU cache hit rate를 높이는 것이 목표이다. 따라서 data locality를 위해 memory contiguity한 처리를 중시한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;cache fail하면 memory hierarchy 하위인 매체로 접근해야 하는데 (CPU -&amp;gt; RAM -&amp;gt; Disk) 각 매체는 용량과 속도를 trade off한 것이므로 속도가 자연스레 느리다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=rX0ItVEVjHc&amp;amp;ab_channel=CppCon&quot;&gt;CppCon 2014: Mike Acton &quot;Data-Oriented Design and C++&quot;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://monday9pm.com/%EC%B4%88%EB%B3%B4%EA%B0%9C%EB%B0%9C%EC%9E%90-%EB%8D%B0%EC%9D%B4%ED%84%B0%EC%A7%80%ED%96%A5-%EC%84%A4%EA%B3%84-data-oriented-design-%EC%95%8C%EC%95%84%EB%B3%B4%EA%B8%B0-c0bbd36ea9da&quot;&gt;초보개발자 데이터지향 설계(Data Oriented Design) 알아보기&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://android-developers.googleblog.com/2015/07/game-performance-data-oriented.html&quot;&gt;Game Performance: Data-Oriented Programming&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;array of struct(AOS) vs struct of array(SOA)&lt;/h4&gt;
&lt;pre class=&quot;cpp&quot;&gt;&lt;code&gt;// AOS. 흔히 짜던 방식이고 직관적
struct ThreeDimensionalVector {
    double x, y, z;
};
std::array&amp;lt;ThreeDimensionalVector, 1024&amp;gt; arrayOfStruct;

// SOA. DOD에서의 방식
struct structOfArrays {
    std::array&amp;lt;double, 1024&amp;gt; x;
    std::array&amp;lt;double, 1024&amp;gt; y;
    std::array&amp;lt;double, 1024&amp;gt; z;
};&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AOS 방식은, x, y, z가 동시에 다 바뀌어야 할 때 유용한 편&lt;br /&gt;SOA 방식은, 어느 한 축의 값만 바뀌는 경우가 많을 때 유용한 편&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;특정 시스템, 로직은 보통 객체의 한 멤버 변수에만 관심이 있을 때가 많다. 아이템의 수량만 바꾸지, 수량과 이름을 동시에 바꿀만한 경우는 드물다. 그래서 DOD 관점에선 SOA가 더 자주 사용되는 편이라고 한다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;메모리 레이아웃으로 따지자면, AOS는 [(x, y, z), (x, y, z)] 꼴일 터이고, SOA는 [x, x, x, ...], [y, y, y, ...], [z, z, z, ...] 와 같은 꼴일 터이다. 특정 로직이 x, y, z가 다 필요하면 AOS 방식이 data locality 측면에서 유리할 것이고, 특정 필드에만 자주 접근하는 경우 SOA 방식이 유리할 것이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;해당 시스템에서는 직관적인 AOS 방식을 사용하였다. 어.. 사실 뭘 사용하는 지 확실하게 정하는 건 프로파일링을 통해서 성능 차이가 확연한 이점이 있을 때 하는게 좋다고 생각한다. don't premature optimization.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;event system&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;비동기 프로그래밍과 pub-sub&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;coroutine, generator
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;python 이야기를 하자면, coroutine(generator based), native coroutine(async/await)로 분리할 수 있겠다.&lt;/li&gt;
&lt;li&gt;javascript의 generator는 엄밀히 말하자면 coroutine은 아니다. sub routine간의 양방향 전환이 안되기 때문에 제한된 coroutine이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;promise(future)&lt;/li&gt;
&lt;li&gt;callback
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;그것이 event loop를 타는 것이든(node, python) 단순히 함수 포인터로 호출하는 방식이든(c/cpp)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;reactive programming(rx)&lt;/li&gt;
&lt;li&gt;observer pattern
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;엄밀히 이야기하면, pub-sub과는 조금 다르다. pubsub은 event channel(이벤트 버스)를 통해 이벤트를 전달하는 것이고, observer pattern은 subject가 observer에게 직접 이벤트를 전달하는 것이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;거칠게 요약하자면 비동기 프로그래밍은 pub-sub 패턴의 변형이다.&lt;br /&gt;본 엔진에서 구현되는 이벤트 시스템도 pub-sub 패턴의 변형이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어떠한 topic에 대해 subscribe하고 어떤 동작을 지정하면,&lt;br /&gt;eventBus가 각 이벤트의 리스너와 콜백의 목록을 관리하고, 이벤트를 전송하는 역할을 한다.&lt;br /&gt;그리고 이벤트 emit(publish) 되는 시점에 동작이 실행된다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;collision check&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 엔진에선 box collider로 감싼 entity의 충돌을 AABB collision check로 확인함.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;circle collision detection&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단순하게, 원의 중심점 사이의 거리가 반지름의 합보다 작으면 충돌이 발생한 것으로 간주한다.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./imgs/circle_collision.jpeg&quot; /&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;AABB collision detection&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AABB (Axis-Aligned Bounding Box) collision check는, 단순히 entity를 감싼 collider 가 겹치는 가를 확인하는 로직이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;박스 A, 박스 B가 존재한다고 가정할 때 두 영역이 충돌(영역 겹침) 확인 조건.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./imgs/AABB.jpeg&quot; /&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;A의 최대 X 좌표(A.x + A.width)가 B의 최소 X 좌표(B.x)보다 커야 함&lt;/li&gt;
&lt;li&gt;A의 최소 X 좌표(A.x)가 B의 최대 X 좌표(B.x + B.width)보다 작아야 함&lt;/li&gt;
&lt;li&gt;A의 최대 Y 좌표(A.y + A.height)가 B의 최소 Y 좌표(B.height)보다 커야 함&lt;/li&gt;
&lt;li&gt;A의 최소 Y 좌표(A.y)가 B의 최대 Y 좌표(B.y + B.height)보다 작아야 함&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;language interoperability(언어 간 상호 운용성)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다른 언어간의 바인딩 작업은, 개발 전략적으로 중요하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;core engine은 성능을 위해 저수준 언어로 개발하고, 상위 추상화 계층에선 script 언어를 사용하는 패턴은, 게임 엔진 뿐만 아니라 tensorflow, pytorch와 같은 cpu bound한 작업을 요구하는 소프트웨어에서 squeeze performance out of hardware를 위해 많이 사용되는 패턴이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이를 구현하는 방법을 생각해보자면 아래 정도가 있겠다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;FFI(Foreign Function Interface)가 지원되면 사용하거나 (deno 같은 경우에는 내장으로 FFI를 지원한다.)&lt;/li&gt;
&lt;li&gt;저수준 언어에서 스크립트 언어를 embedding하거나,&lt;/li&gt;
&lt;li&gt;고수준 언어에서 컴파일된 binary를 통으로 불러와서 아예 실행하던가,&lt;/li&gt;
&lt;li&gt;서로 다른 책임을 가진 두 언어로 만들어진 프로그램을 실행하여 프로세스 간에 통신하거나(이 방법은 언어 간 상호 운용이라는 측면에서는 좀 벗어난 측면이 있지만)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 엔진에서는 sol을 통해 간단하게 cpp과 lua 간의 바인딩을 구현하였다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;SLD2&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;paths&lt;/h3&gt;
&lt;pre class=&quot;crystal&quot;&gt;&lt;code&gt;# sd2 check
sdl2-config --version # 2.28.5

sdl2-config --libs
# 링커 플래그 제공
# 링커가 SDL2 라이브러리를 찾고 링크하는 데 필요한 설정을 제공합니다

sdl2-config --cflags
# 컴파일러 플래그 제공
# SDL2 헤더 파일의 경로를 출력.
# 컴파일러가 SDL2의 헤더 파일을 찾을 수 있도록 해줍니다.

sdl2-config --libs --cflags # 동시에 출력

# 현재 맥 환경에선 --cflags가 -I/opt/homebrew/include/SDL2 -D_THREAD_SAFE 를 출력함.
# 문제는 이렇나 방식이면 #include &amp;lt;SDL.h&amp;gt; 방식으로 include해야 함.
clang++ -Wall -std=c++17 Main.cpp $(sdl2-config --libs --cflags) -o Main

# 코딩 컨벤션에 맞게 &amp;lt;SDL2/SDL.h&amp;gt; 로 사용하기 위해 -I 옵션을 수정하여 아래처럼 적용함.
clang++ -Wall -std=c++17 Main.cpp -L/opt/homebrew/lib -lSDL2 -I/opt/homebrew/include -D_THREAD_SAFE -o Main
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;full screen, fake full screen&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;full screen은 다른 화면 전환이 번거로움. (전체 화면)&lt;br /&gt;Fake Fullscreen은 사실상 크기를 조정한 창 모드. (전체 창모드)&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;SDL_WINDOW_FULLSCREEN
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;전체 화면. SDL이 해상도를 변경하여 전체 화면으로 만듬.&lt;/li&gt;
&lt;li&gt;화면 전환 시 느림. (게임 하다가 ctrl + tab으로 전환하려고 하면 해상도 깨졌다가 다시 복구되는 그것.)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;SDL_WINDOW_FULLSCREEN_DESKTOP
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;fake full screen으로, 해상도 변경 없이 전체 화면처럼 보이게 함.&lt;/li&gt;
&lt;li&gt;전체 화면을 채우는 보더리스 창을 생성하는 것과 유사.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;SDL_WINDOW_BORDERLESS
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;전체 화면과 크게 관련 없으나 전체 화면을 꽉 채우는 borderless 창을 생성하는 것과 유사.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;rendererFlags and hardware acceleration&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SDL_CreateRenderer에서 GPU 사용이 가능&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://wiki.libsdl.org/SDL2/SDL_RendererFlags&quot;&gt;SDL_RendererFlags&lt;/a&gt; 참고.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;SDL_RENDERER_SOFTWARE : 하드웨어 가속 사용 안하고 CPU 사용&lt;/li&gt;
&lt;li&gt;SDL_RENDERER_ACCELERATED : dedicated graphics card (GPU) 사용&lt;/li&gt;
&lt;li&gt;SDL_RENDERER_PRESENTVSYNC : VSync 사용. tearing 방지&lt;/li&gt;
&lt;li&gt;SDL_RENDERER_TARGETTEXTURE&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;lisp&quot;&gt;&lt;code&gt;SDL_CreateRenderer(
    window,
    -1,
    SDL_RENDERER_ACCELERATED
);&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;surface vs texture&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SDL_Surface는 이미지 처리나 간단한 소프트웨어 렌더링에 적합하고, SDL_Texture는 GPU를 사용한 빠른 화면 렌더링에 적합합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일반적으로 이미지 파일을 로드하고 조작할 때는 SDL_Surface를 사용하고, 화면에 이미지를 렌더링할 때는 SDL_Texture로 변환하여 사용합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SDL_Surface는 시스템 메모리(RAM)에 저장되고, SDL_Texture는 GPU의 비디오 메모리(VRAM)에 저장됩니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;etc&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;UI paradigm (retain vs immediate)&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;retain mode(RMGUI)&lt;br /&gt;web에서 vanilla js로 DOM을 구성하는 것과 비슷하다.&lt;br /&gt;UI 요소를 객체로 보고, UI가 바인딩한 데이터의 변화에 따른 변화를 처리하도록 해당 객체를 구성해야 한다. 따라서 해당 UI가 state의 변화 로직과 변화에 따른 렌더링 로직을 모두 가지고 있어야 한다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;UI의 상태가 지속적으로 저장 및 관리되어야 하는 경우 사용&lt;/li&gt;
&lt;li&gt;UI와 데이터를 바인딩(sync)하여 사용하는 대부분의 SPA 프레임워크의 방식&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;immediate mode(IMGUI)&lt;br /&gt;게임 루프에 UI 렌더링을 태워서 UI를 새롭게 그려낸다. 그래서 UI가 데이터를 직접적으로 소유하지 않고 바인딩하는 것도 없다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/ocornut/imgui/wiki/About-the-IMGUI-paradigm&quot;&gt;About the IMGUI paradigm&lt;/a&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;OTF(OpenType Font), TTF(TrueType Font)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;둘 다 많이 쓰이는 폰트 포맷이다.&lt;br /&gt;OTF는 TTF보다 더 많은 기능을 제공하는 대신 더 큰 용량을 차지하곤 하며,&lt;br /&gt;오래된 브라우저에서는 지원하지 않는 경우도 있다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;lldb 두 번 쓰세요&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;code&gt;b [function-name]&lt;/code&gt; 나 &lt;code&gt;b [file]:[line]&lt;/code&gt;로 의심되는 지점을 건다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;r&lt;/code&gt;로 실행한다.&lt;/li&gt;
&lt;li&gt;다음과 같은 도구들을 이용해본다
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;뭔가 터지면 &lt;code&gt;bt&lt;/code&gt;로 스택 트레이스를 확인한다.&lt;/li&gt;
&lt;li&gt;문제가 되는 메모리 공간을 &lt;code&gt;memory read [주소]&lt;/code&gt;로 확인한다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;expr [변수명] = [새로운 값]&lt;/code&gt;으로 새로운 값으로 변경해본다&lt;/li&gt;
&lt;li&gt;&lt;code&gt;expr [변수명]&lt;/code&gt; 혹은 &lt;code&gt;p [변수명]&lt;/code&gt; 으로 변수를 확인해본다&lt;/li&gt;
&lt;li&gt;&lt;code&gt;frame variable [변수명]&lt;/code&gt;, &lt;code&gt;fr v [변수명]&lt;/code&gt;으로 현 프레임에서의 변수의 값을 확인한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;known issues&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;다중 모니터 문제
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;전체 화면 문제&lt;br /&gt;monitor 0, 1 두 개의 모니터가 존재할 때,&lt;br /&gt;monitor 0에서 전체 화면 게임을 실행하면 monitor 1은 어떻게 해야 하는가? (모니터에 따라 동작이 다른 것을 확인)&lt;/li&gt;
&lt;li&gt;화면 분할 문제&lt;/li&gt;
&lt;li&gt;내장 모니터가 3456 x 2234임에도 화면 분할 기능을 사용하면 1728 x 2234로 나눠지게 된다.&lt;br /&gt;전체 화면 게임을 실행할 경우 어떻게 대처할 것인가?&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;개인적인 coding convention이나 기타 개발 관습에 대해&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;여기서는 struct와 class를 혼용하였다. 그러나 struct는 POD만을 담도록 하는 것이 좋다고 생각한다.&lt;/li&gt;
&lt;li&gt;c lib는 smart pointer로 wrapping하지 않는다.&lt;/li&gt;
&lt;li&gt;여기서는 대입을 통해 멤버 변수를 초기화한 부분이 있으나 가급적 initializer list를 사용하는 것이 좋다고 생각한다.&lt;/li&gt;
&lt;li&gt;IDE로 vscode를 사용 중인데, c/c++ extension가 제공해주는 intellisense가 아주 느리다. &lt;a href=&quot;https://clangd.llvm.org/&quot;&gt;clangd&lt;/a&gt; 사용을 권장하며, 사용하는 빌드 시스템 툴에 따라 compile_commands.json을 생성하여 사용하자.&lt;/li&gt;
&lt;li&gt;enum 보다 enum class가 strongly typed기도 하고, enum의 class를 명시하는 효과가 있어서 더 자주 사용하는 편이다. 특히, 타 언어에서 그런 표기법을 사용하는 경우가 많아서 익숙하다.&lt;/li&gt;
&lt;li&gt;DO NOT USE EXCEPTION. just let engine crash.&lt;/li&gt;
&lt;li&gt;타 언어일 때는 inlay hints가 지저분해보였는데 c/cpp에서는 이게 없으면 코드 읽기가 더 힘들어지는 듯. 활성화 추천.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;resources&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://savas.ca/nomad&quot;&gt;Nomad Game Engine&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://austinmorlan.com/posts/entity_component_system/&quot;&gt;A SIMPLE ENTITY COMPONENT SYSTEM (ECS) [C++]&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/arvidsson/Mix&quot;&gt;MIX(C++ minimal ECS)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/isadorasophia/murder&quot;&gt;murder game engine&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/skypjack/entt&quot;&gt;EnTT (for C++ projects)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/SanderMertens/flecs&quot;&gt;Flecs (for C projects)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://wikidocs.net/book/6636&quot;&gt;SDL 프로그래밍 컴플리트 가이드&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://gafferongames.com/post/fix_your_timestep/&quot;&gt;https://gafferongames.com/post/fix_your_timestep/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://denyskryvytskyi.github.io/event-system&quot;&gt;https://denyskryvytskyi.github.io/event-system&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://gameprogrammingpatterns.com/contents.html&quot;&gt;https://gameprogrammingpatterns.com/contents.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>미분류/Tip</category>
      <author>DarrenKwonDev</author>
      <guid isPermaLink="true">https://darrengwon.tistory.com/1581</guid>
      <comments>https://darrengwon.tistory.com/1581#entry1581comment</comments>
      <pubDate>Tue, 26 Dec 2023 01:57:25 +0900</pubDate>
    </item>
    <item>
      <title>use vscode for Unity external editor + omnisharp intellisense setting in MAC!</title>
      <link>https://darrengwon.tistory.com/1580</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;text-align: start;&quot; data-darkreader-inline-color=&quot;&quot;&gt;you should know, C# does not well-&lt;/span&gt;&lt;span style=&quot;text-align: start;&quot; data-darkreader-inline-color=&quot;&quot;&gt;supported arm64. so using C# in mac is quite annoying.&lt;/span&gt;&lt;span style=&quot;text-align: start;&quot; data-darkreader-inline-color=&quot;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot; data-darkreader-inline-color=&quot;&quot;&gt;I'll omit to install process like dotnet, unity, and so on.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;0.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;downgrade C# extension to 1.24.0.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;(it's triggering my temper...)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;do not use the modern net. not support Unity&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-09-30 오전 10.04.56.png&quot; data-origin-width=&quot;728&quot; data-origin-height=&quot;146&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eJMpGV/btsv8S4TSTE/GYnDmf93oJk5Blxzk6glxk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eJMpGV/btsv8S4TSTE/GYnDmf93oJk5Blxzk6glxk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eJMpGV/btsv8S4TSTE/GYnDmf93oJk5Blxzk6glxk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FeJMpGV%2Fbtsv8S4TSTE%2FGYnDmf93oJk5Blxzk6glxk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;728&quot; height=&quot;146&quot; data-filename=&quot;스크린샷 2023-09-30 오전 10.04.56.png&quot; data-origin-width=&quot;728&quot; data-origin-height=&quot;146&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;instead, use &lt;a style=&quot;color: #000000;&quot; href=&quot;https://www.mono-project.com/download/stable/#download-mac&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;mono&lt;/a&gt; framework&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-09-30 오전 10.05.35.png&quot; data-origin-width=&quot;745&quot; data-origin-height=&quot;157&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/86FBA/btsv8hw9x82/uUTub5p1w3OaPrkeSdPK60/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/86FBA/btsv8hw9x82/uUTub5p1w3OaPrkeSdPK60/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/86FBA/btsv8hw9x82/uUTub5p1w3OaPrkeSdPK60/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F86FBA%2Fbtsv8hw9x82%2FuUTub5p1w3OaPrkeSdPK60%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;745&quot; height=&quot;157&quot; data-filename=&quot;스크린샷 2023-09-30 오전 10.05.35.png&quot; data-origin-width=&quot;745&quot; data-origin-height=&quot;157&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;after that, you can get 'omnisharp server running' in bottom of vscode.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;It takes about 3~5 sec to fully working. so be patient.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-09-30 오전 10.08.50.png&quot; data-origin-width=&quot;373&quot; data-origin-height=&quot;105&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/NtGpN/btsv7ucvxmX/qq5kKSgnv5L0i1EzYKqj81/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/NtGpN/btsv7ucvxmX/qq5kKSgnv5L0i1EzYKqj81/img.png&quot; data-alt=&quot;there's omnisharp logo in bottom right&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/NtGpN/btsv7ucvxmX/qq5kKSgnv5L0i1EzYKqj81/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FNtGpN%2Fbtsv7ucvxmX%2Fqq5kKSgnv5L0i1EzYKqj81%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;373&quot; height=&quot;105&quot; data-filename=&quot;스크린샷 2023-09-30 오전 10.08.50.png&quot; data-origin-width=&quot;373&quot; data-origin-height=&quot;105&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;there's omnisharp logo in bottom right&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>  Game/❒ Unity</category>
      <author>DarrenKwonDev</author>
      <guid isPermaLink="true">https://darrengwon.tistory.com/1580</guid>
      <comments>https://darrengwon.tistory.com/1580#entry1580comment</comments>
      <pubDate>Sat, 30 Sep 2023 10:11:42 +0900</pubDate>
    </item>
    <item>
      <title>네이버 부스트캠프 AI Tech 합격 후기</title>
      <link>https://darrengwon.tistory.com/1577</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-02-09 오후 8.49.02.png&quot; data-origin-width=&quot;935&quot; data-origin-height=&quot;304&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/BW5WS/btrYJaKb8vz/jcpKYaIu4L6NUEsi3PLzF0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/BW5WS/btrYJaKb8vz/jcpKYaIu4L6NUEsi3PLzF0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/BW5WS/btrYJaKb8vz/jcpKYaIu4L6NUEsi3PLzF0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FBW5WS%2FbtrYJaKb8vz%2FjcpKYaIu4L6NUEsi3PLzF0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;935&quot; height=&quot;304&quot; data-filename=&quot;스크린샷 2023-02-09 오후 8.49.02.png&quot; data-origin-width=&quot;935&quot; data-origin-height=&quot;304&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;퇴사 후 recsys를 공부하고 싶다는 생각이 들었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;통계 스터디를 진행하면서 수학과 통합된 기능 개발을 하고 싶었고(비록 첫 회사에서 개발한 추천 시스템은 무산되었지만) 무엇보다 일반 backend의 업무보다 보다 전문성 있을 것같다는 생각이 들었거든요. 더 나아가서 뭔가 수학적인 일을 하고 싶다는 모호한 욕망도 있었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지금까지 해왔던 것처럼 독학을 할 수도 있었겠지만 독학이 조금 지치기도하고 교육기관을 알아보았습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;교육 기관을 조사해보니 국내에서 AI나 ML을 말하면서 NLP나 CV를 (어영부영) 가르쳐주는 곳은 많았지만 AI, tech의 hype를 타고 급조되어 만들어진 것에 대부분으로 보였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실 위와 같은 분야에서 실제로 어떠한 성과를 이뤄내려면 부트캠프가 아닌 대학원에 가야 한다고 생각합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저는 연구가 목적이 아닌 엔지니어링을 기반으로 한 비즈니스에 관심이 있었기에 recsys에 좀 더 관심이 갔습니다. 그러나&amp;nbsp;recsys를 교육 과정에 포함한 곳은 드물었습니다. buzz word를 이미 좀 지나쳐온 것이라서 그런 것으로 추측됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여튼, Naver AI boostcamp가 가장 합리적인 선택이라고 생각하고 전형을 진행하였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;0. 진행과정 overall&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-12-08 오전 9.25.04.png&quot; data-origin-width=&quot;1956&quot; data-origin-height=&quot;550&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bjrIKt/btrYI4QKbhV/v6sSGKY7WETKIEvNdZ2hSK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bjrIKt/btrYI4QKbhV/v6sSGKY7WETKIEvNdZ2hSK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bjrIKt/btrYI4QKbhV/v6sSGKY7WETKIEvNdZ2hSK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbjrIKt%2FbtrYI4QKbhV%2Fv6sSGKY7WETKIEvNdZ2hSK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1956&quot; height=&quot;550&quot; data-filename=&quot;스크린샷 2022-12-08 오전 9.25.04.png&quot; data-origin-width=&quot;1956&quot; data-origin-height=&quot;550&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;pre-course는 선형대수, 머신러닝과 딥러닝의 기초에 대한 강의를 수강하고 인증하는 것입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이미 관련 지식이 있으신 분은 쉽게 이해하실 수 있습니다. 다만, 강의를 너무 빠른 배속으로 듣게 된다면 수업 완료가 되지 않기에 이를 유의하시는 것이 좋습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;1. 지원서 작성&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;차후 달라질 수 있으나 아래와 같은 질문에 답하면 되었습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 질문이 으레 그러하듯 가급적 limit까지 분량을 '내용있게' 채우는 것을 기본 전략으로 하였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이타적인 모습과 학습에 대한 열의를 앞에 배치하고, 이에 해당하는 증거나 스펙 등을 후에 첨부하였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 부스트캠프 AI Tech 교육은 어떤 이유로 지원하셨나요? 여러 교육과정 중에서 부스트캠프를 선택한 이유와 AI 엔지니어가 되기로 결심한 이유를 알려주세요 (500자&amp;nbsp;내외)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 지금까지&amp;nbsp;소프트웨어&amp;nbsp;개발&amp;nbsp;관련&amp;nbsp;경험&amp;nbsp;또는&amp;nbsp;인공지능을&amp;nbsp;배우기&amp;nbsp;위해&amp;nbsp;시도했거나&amp;nbsp;참여한&amp;nbsp;경험을&amp;nbsp;모두&amp;nbsp;적어주세요.&amp;nbsp;결과물보다&amp;nbsp;그&amp;nbsp;과정에서&amp;nbsp;무엇을&amp;nbsp;고민했고&amp;nbsp;어떤&amp;nbsp;점을&amp;nbsp;배웠는지를&amp;nbsp;자세히&amp;nbsp;작성해주세요.(500자&amp;nbsp;내외)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 부스트캠프는&amp;nbsp;5개월&amp;nbsp;정도를&amp;nbsp;온라인&amp;nbsp;환경에서&amp;nbsp;몰입하여&amp;nbsp;풀타임으로&amp;nbsp;학습해야&amp;nbsp;합니다.&amp;nbsp;이러한&amp;nbsp;몰입&amp;nbsp;과정이&amp;nbsp;끝나면&amp;nbsp;개인적으로&amp;nbsp;많은&amp;nbsp;성장이&amp;nbsp;있을&amp;nbsp;텐데요,&amp;nbsp;교육&amp;nbsp;수료&amp;nbsp;후&amp;nbsp;5년&amp;nbsp;뒤&amp;nbsp;본인은&amp;nbsp;어떤&amp;nbsp;개발자로&amp;nbsp;성장하여&amp;nbsp;어떤&amp;nbsp;꿈을&amp;nbsp;펼치고&amp;nbsp;있을지&amp;nbsp;최대한&amp;nbsp;자세히&amp;nbsp;작성해주세요.&amp;nbsp;(500자&amp;nbsp;내외)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 부스트캠프&amp;nbsp;교육은&amp;nbsp;자기주도적인&amp;nbsp;학습과&amp;nbsp;동료와&amp;nbsp;원활한&amp;nbsp;소통을&amp;nbsp;중시합니다.&amp;nbsp;원활한&amp;nbsp;교육진행을&amp;nbsp;위해&amp;nbsp;기존에&amp;nbsp;자기&amp;nbsp;스스로&amp;nbsp;학습한&amp;nbsp;기억&amp;nbsp;또는&amp;nbsp;성공적인&amp;nbsp;커뮤니티&amp;nbsp;활동&amp;nbsp;경험을&amp;nbsp;소개주세요.&amp;nbsp;(서술은&amp;nbsp;300자&amp;nbsp;내외)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자소서와 별개로, 포트폴리오나 github를 첨부할 수 있는데 이도 모두 제출하였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;2. 1차 시험: 머신러닝 기초 퀴즈 및 코테&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;수학 및 머신러닝의 기초에 대해서는, pre-course를 잘 수강한 후에 자가 진단을 한 번 다 풀어보고 유형을 정리하는 것을 추천드립니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코딩 테스트는 자세한 내용을 말할 수 없으나 백준 기준 브론즈~실버 수준이며 프로그래머스 0~1 단계의 문제들로 이루어져있었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다만 코딩 테스트의 난위도는 널뛰기할 수 있습니다. 전 기수는 2차 코딩 테스트보다 1차 코딩테스트가 너무나 어려웠기에 2솔이 컷이었다는 말이 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;3. 2차 시험: 코테&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1차보다 좀 더 심화적인 문제가 나옵니다. 백준 기준 실버 ~ 골드 수준이며 프로그래머스 2~3 단계로 느껴졌습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;8문제 중 5문제를 풀고 합격을 받았습니다. bfs, dfs, greedy, 구현과 같은 기본적인 유형에 집중하는 것으로 충분했었습니다.&lt;/p&gt;</description>
      <category>미분류/Tip</category>
      <author>DarrenKwonDev</author>
      <guid isPermaLink="true">https://darrengwon.tistory.com/1577</guid>
      <comments>https://darrengwon.tistory.com/1577#entry1577comment</comments>
      <pubDate>Thu, 9 Feb 2023 21:14:19 +0900</pubDate>
    </item>
    <item>
      <title>latex 기반의 이력서</title>
      <link>https://darrengwon.tistory.com/1574</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;1.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/James-Yu/LaTeX-Workshop/wiki/Install&quot;&gt;https://github.com/James-Yu/LaTeX-Workshop/wiki/Install&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1666286951216&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;GitHub - James-Yu/LaTeX-Workshop: Boost LaTeX typesetting efficiency with preview, compile, autocomplete, colorize, and more.&quot; data-og-description=&quot;Boost LaTeX typesetting efficiency with preview, compile, autocomplete, colorize, and more. - GitHub - James-Yu/LaTeX-Workshop: Boost LaTeX typesetting efficiency with preview, compile, autocomplet...&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/James-Yu/LaTeX-Workshop/wiki/Install&quot; data-og-url=&quot;https://github.com/James-Yu/LaTeX-Workshop&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/b4n3M9/hyQaySI4Cv/UY8ecZD4edun0tZduABKe1/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/James-Yu/LaTeX-Workshop/wiki/Install&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/James-Yu/LaTeX-Workshop/wiki/Install&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/b4n3M9/hyQaySI4Cv/UY8ecZD4edun0tZduABKe1/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;GitHub - James-Yu/LaTeX-Workshop: Boost LaTeX typesetting efficiency with preview, compile, autocomplete, colorize, and more.&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Boost LaTeX typesetting efficiency with preview, compile, autocomplete, colorize, and more. - GitHub - James-Yu/LaTeX-Workshop: Boost LaTeX typesetting efficiency with preview, compile, autocomplet...&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;설치된 texlive는 /usr/local/texlive 경로 하위에 bin 폴더 내부에 있으므로 PATH에 추가할 것.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;overleaf의 잘 구성된 cv 참고할 것&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.overleaf.com/gallery/tagged/cv&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://www.overleaf.com/gallery/tagged/cv&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;빌드하여 제출한다.&lt;/p&gt;</description>
      <category>미분류/Tip</category>
      <author>DarrenKwonDev</author>
      <guid isPermaLink="true">https://darrengwon.tistory.com/1574</guid>
      <comments>https://darrengwon.tistory.com/1574#entry1574comment</comments>
      <pubDate>Fri, 21 Oct 2022 02:32:05 +0900</pubDate>
    </item>
    <item>
      <title>VSCode 설치했으면 여기 오세요 : 내가 사용하는 VSCode</title>
      <link>https://darrengwon.tistory.com/1098</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;기본 Shell을 bash 혹은 zsh로 교체하기&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;F1을 누르고 Select Default Shell을 통해 설정해주자&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;윈도우 환경이라면 git bash를 선택해주자 &lt;span&gt;bash를 사용할 수 있게 된다!&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthContent&quot; data-origin-width=&quot;867&quot; data-origin-height=&quot;89&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/brgSZk/btqSDuOLQnv/Tx9xdPQjxvzEN5oHfn1gVK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/brgSZk/btqSDuOLQnv/Tx9xdPQjxvzEN5oHfn1gVK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/brgSZk/btqSDuOLQnv/Tx9xdPQjxvzEN5oHfn1gVK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbrgSZk%2FbtqSDuOLQnv%2FTx9xdPQjxvzEN5oHfn1gVK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;867&quot; height=&quot;89&quot; data-origin-width=&quot;867&quot; data-origin-height=&quot;89&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;'code' command PATH에 추가하기&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;723&quot; data-origin-height=&quot;156&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bwwa6U/btrslVqz7QQ/Qtbk5Aj8P9ppcatHybqFG0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bwwa6U/btrslVqz7QQ/Qtbk5Aj8P9ppcatHybqFG0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bwwa6U/btrslVqz7QQ/Qtbk5Aj8P9ppcatHybqFG0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbwwa6U%2FbtrslVqz7QQ%2FQtbk5Aj8P9ppcatHybqFG0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;723&quot; height=&quot;156&quot; data-origin-width=&quot;723&quot; data-origin-height=&quot;156&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;자동 포매팅 설정&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;세팅에서 그냥 format on save를 켜면 되는 일이지만,&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;json에서는 다음과 같이 언어별 설정이 가능하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고, eslint를 사용한다면 저장 시 포매팅 기능은 꺼두는 것이 좋다.&lt;/p&gt;
&lt;pre id=&quot;code_1609761658209&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&quot;[javascript]&quot;: {
  &quot;editor.defaultFormatter&quot;: &quot;esbenp.prettier-vscode&quot;
},
&quot;[javascriptreact]&quot;: {
  &quot;editor.defaultFormatter&quot;: &quot;esbenp.prettier-vscode&quot;
},
&quot;[typescript]&quot;: {
  &quot;editor.defaultFormatter&quot;: &quot;esbenp.prettier-vscode&quot;
},
&quot;[typescriptreact]&quot;: {
  &quot;editor.defaultFormatter&quot;: &quot;esbenp.prettier-vscode&quot;
},
{
 &quot;[dart]&quot;: {
      &quot;editor.defaultFormatter&quot;: &quot;Dart-Code.dart-code&quot;,
      &quot;editor.formatOnSave&quot;: true,
      &quot;editor.rulers&quot;: [120]
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;inlay hint&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1643771419127&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&quot;javascript.inlayHints.parameterNames.enabled&quot;: &quot;all&quot;
&quot;typescript.inlayHints.parameterNames.enabled&quot;: &quot;all&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;jsx에서 html 태그 완성이 잘 안될 때.&lt;/p&gt;
&lt;pre id=&quot;code_1643849664336&quot; class=&quot;1c&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&quot;emmet.includeLanguages&quot;: {
    &quot;javascript&quot;: &quot;javascriptreact&quot; // jsx에서 html 태그 자동완성이 안 됐었는데, 이 부분 추가해서 해결했다.
  },&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;deno 프로젝트에 세팅하기. globally enabled 시키면 일반 노드 프로젝트에서 deno 랭귀지 서버를&amp;nbsp; 쓰게 되어 이상한 곳에서 경고를 보냄.&lt;/p&gt;
&lt;pre id=&quot;code_1643849678450&quot; class=&quot;json&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;{ &quot;deno.enable&quot;: true }
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;VSCode 설정 싱크하기&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;extension이 많아졌을 때 + 다른 컴퓨터에서 작업을 해야만 하거나 새 컴퓨터를 샀을 때. 설치에 시간을 쏟고 싶지 않다면 VSCode를 sync하는 방법을 고려해보자&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;핵심은&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;발급받은 토큰을&lt;span&gt;&amp;nbsp;&lt;/span&gt;사용하여 github에 vscode 설정 upload&lt;br /&gt;&lt;span&gt;- shift + alt + u 단축키를 누르고 입력란에 발급받은 토큰을 입력합니다.&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;발급받은 토큰을 사용하여 기기에서 download&lt;br /&gt;- shift + alt + d 단축키를 눌러 동기화가 필요한 기기에서 다운받습니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://ithub.tistory.com/211&quot;&gt;https://ithub.tistory.com/211&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1609761412795&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-og-type=&quot;article&quot; data-og-title=&quot;VSCODE 유용한 플러그인 settings sync 사용하기&quot; data-og-description=&quot;안녕하세요. 오늘은 vscode를 집, 회사 등 여러 디바이스에서 동일한 환경을 사용할 수 있게 해주는 플러그인 Settings Sync 사용법에 대해서 를 알아보겠습니다. 직접 설정한 설정정보와 설치한 플러그인까지 여..&quot; data-og-host=&quot;ithub.tistory.com&quot; data-og-source-url=&quot;https://ithub.tistory.com/211&quot; data-og-url=&quot;https://ithub.tistory.com/211&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/opvfE/hyE9jS6Ske/Z53MVdBAEsPKkgrMApT3O1/img.png?width=800&amp;amp;height=470&amp;amp;face=0_0_800_470,https://scrap.kakaocdn.net/dn/bbjFpg/hyE9fb6xN4/oM36vt9OmqpGMDoTQeOKB1/img.png?width=800&amp;amp;height=470&amp;amp;face=0_0_800_470,https://scrap.kakaocdn.net/dn/zXOBX/hyE9c7wbT7/WCVQkiGp5FxNNekCKV2EHK/img.png?width=2048&amp;amp;height=2048&amp;amp;face=0_0_2048_2048&quot;&gt;&lt;a href=&quot;https://ithub.tistory.com/211&quot; data-source-url=&quot;https://ithub.tistory.com/211&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/opvfE/hyE9jS6Ske/Z53MVdBAEsPKkgrMApT3O1/img.png?width=800&amp;amp;height=470&amp;amp;face=0_0_800_470,https://scrap.kakaocdn.net/dn/bbjFpg/hyE9fb6xN4/oM36vt9OmqpGMDoTQeOKB1/img.png?width=800&amp;amp;height=470&amp;amp;face=0_0_800_470,https://scrap.kakaocdn.net/dn/zXOBX/hyE9c7wbT7/WCVQkiGp5FxNNekCKV2EHK/img.png?width=2048&amp;amp;height=2048&amp;amp;face=0_0_2048_2048');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;VSCODE 유용한 플러그인 settings sync 사용하기&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;안녕하세요. 오늘은 vscode를 집, 회사 등 여러 디바이스에서 동일한 환경을 사용할 수 있게 해주는 플러그인 Settings Sync 사용법에 대해서 를 알아보겠습니다. 직접 설정한 설정정보와 설치한 플러그인까지 여..&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;ithub.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;alt + shift + i + (home/end) 로 다중 선택, 이동, 수정&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본적인 VSCode 단축키는 직접&lt;span&gt;&amp;nbsp;&lt;/span&gt;찾아보면 되지만 여기서 소개하는 이 단축키는 워낙 유용해서 올려본다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;alt + shift + i + (home/end)이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단순 반복을 해야 하는데 매 줄마다 길이가 다르다면 곤란하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;alt + clcik으로 매번 클릭하기도 힘들다. 특히 다음과 같은 코드가 있다고 가정한다면... ( )&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1609761545856&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class Block {
  public index: number;
  public hash: string;
  public previousHash: string;
  public data: string;
  public timeStamp: number;

  constructor(
    index: number,
    hash: string,
    previousHash: string,
    data: string,
    timeStamp: number
  ) {
    this.index = index;
    this.hash = hash;
    this.previousHash = previousHash;
    this.data = data;
    this.timeStamp = timeStamp;
  }
}

export {};
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;드래그한 후 alt + shift + i를 누르면 다음과 같이 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 상태에서 home/end를 통해 해당 코드의 맨 앞/맨 뒤로 이동할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthContent&quot; data-filename=&quot;캡처.JPG&quot; data-origin-width=&quot;532&quot; data-origin-height=&quot;251&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lMIyH/btqSsRcXHVQ/iTB2IR2E8TZt27FS92TTe1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lMIyH/btqSsRcXHVQ/iTB2IR2E8TZt27FS92TTe1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lMIyH/btqSsRcXHVQ/iTB2IR2E8TZt27FS92TTe1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlMIyH%2FbtqSsRcXHVQ%2FiTB2IR2E8TZt27FS92TTe1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;450&quot; height=&quot;251&quot; data-filename=&quot;캡처.JPG&quot; data-origin-width=&quot;532&quot; data-origin-height=&quot;251&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;빈 폴더를 나열식으로 보는 방법&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;빈 폴더를 생성하면 VSCode에서는 다음과 같이 보여주는데 이게 여긴 귀찮고 불편한 게 아니다. preference에서 해당 기능을 꺼주자. 해당 기능 이름은 compactfolers이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bnMZ6u/btqSxBAVQbZ/BUkEhSTLvjkjblvFTKpclK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bnMZ6u/btqSxBAVQbZ/BUkEhSTLvjkjblvFTKpclK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbgPk78%2FbtqDDwNx1je%2Fk9RoxG1lwNIV7iK4yd77j1%2Fimg.png&quot; data-origin-width=&quot;243&quot; data-origin-height=&quot;304&quot; data-ke-mobilestyle=&quot;widthContent&quot; style=&quot;width: 52.4395%; margin-right: 10px;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bnMZ6u/btqSxBAVQbZ/BUkEhSTLvjkjblvFTKpclK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbnMZ6u%2FbtqSxBAVQbZ%2FBUkEhSTLvjkjblvFTKpclK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;243&quot; height=&quot;304&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/9NhMe/btqSpGW9dEt/2wsk3pcudb25vSkf9GMgE0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/9NhMe/btqSpGW9dEt/2wsk3pcudb25vSkf9GMgE0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FvKiu2%2FbtqDACuI6WE%2F2hhHCJGXxuw4vd7ebRFSeK%2Fimg.png&quot; data-origin-width=&quot;244&quot; data-origin-height=&quot;345&quot; data-ke-mobilestyle=&quot;widthContent&quot; style=&quot;width: 46.3977%;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/9NhMe/btqSpGW9dEt/2wsk3pcudb25vSkf9GMgE0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F9NhMe%2FbtqSpGW9dEt%2F2wsk3pcudb25vSkf9GMgE0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;244&quot; height=&quot;345&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthContent&quot; data-filename=&quot;캡처2.PNG&quot; data-origin-width=&quot;1074&quot; data-origin-height=&quot;252&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/m9SDb/btqSGj0dCyp/VKt15TxHuZ8xlKNHVNYegk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/m9SDb/btqSGj0dCyp/VKt15TxHuZ8xlKNHVNYegk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/m9SDb/btqSGj0dCyp/VKt15TxHuZ8xlKNHVNYegk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fm9SDb%2FbtqSGj0dCyp%2FVKt15TxHuZ8xlKNHVNYegk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1074&quot; height=&quot;252&quot; data-filename=&quot;캡처2.PNG&quot; data-origin-width=&quot;1074&quot; data-origin-height=&quot;252&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;vscode prettier formatter가 작동을 안한다면&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://stackoverflow.com/questions/52586965/why-prettier-does-not-format-code-in-vscode&quot;&gt;stackoverflow.com/questions/52586965/why-prettier-does-not-format-code-in-vscode&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;react-native나 뭔가 새로운 걸 할 때마다 작동을 안하는 경우가 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;default formatter를 esbenp.prettier.vscode로 설정하고, 저장 시 포매터를 켜야 한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthContent&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;448&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b8OQYU/btqYN01GEE7/KWrJm4KfKFd8h96KjsJEC0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b8OQYU/btqYN01GEE7/KWrJm4KfKFd8h96KjsJEC0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b8OQYU/btqYN01GEE7/KWrJm4KfKFd8h96KjsJEC0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb8OQYU%2FbtqYN01GEE7%2FKWrJm4KfKFd8h96KjsJEC0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1280&quot; height=&quot;448&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;448&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthContent&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;496&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cQqDsd/btqYAuwPglT/7Q8YnLSgDiwW5mF2pNMUK0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cQqDsd/btqYAuwPglT/7Q8YnLSgDiwW5mF2pNMUK0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cQqDsd/btqYAuwPglT/7Q8YnLSgDiwW5mF2pNMUK0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcQqDsd%2FbtqYAuwPglT%2F7Q8YnLSgDiwW5mF2pNMUK0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1280&quot; height=&quot;496&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;496&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;x가 x로 인식되지 않고 y로 인식된다면?(ex-&lt;/b&gt;&lt;b&gt;내 html이 django-html-template으로 인식된다면?&lt;span&gt;)&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 사항은 대표적인 사항이고, 이 뿐만 아니라, 특정 파일이 본 파일이 아닌 extension에 의해 다른 것으로 인식될 때가 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;괜히 익스텐션 깔았다 지웠다 하지 말고 &lt;b&gt;file: Associations&lt;/b&gt;를 이용하여 직접 잡아주면 된다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthContent&quot; data-origin-width=&quot;1103&quot; data-origin-height=&quot;263&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/4nOyr/btqYW2dTcqY/UsIXo8ypEYwi6KAlsuY1c1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/4nOyr/btqYW2dTcqY/UsIXo8ypEYwi6KAlsuY1c1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/4nOyr/btqYW2dTcqY/UsIXo8ypEYwi6KAlsuY1c1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F4nOyr%2FbtqYW2dTcqY%2FUsIXo8ypEYwi6KAlsuY1c1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1103&quot; height=&quot;263&quot; data-origin-width=&quot;1103&quot; data-origin-height=&quot;263&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;저는 프로젝트에 eslint + prettier를 쓸거라서 format on save를 끄고 싶은데요&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;eslint를 이용하려면&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로젝트 소스코드 내에 eslint 구성은 생략하고, vscode에서 이를 활용하기 위해 세팅 작업을 해줘,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;command + shift + p =&amp;gt; open setting (json) =&amp;gt; 아래 내용 붙여넣기.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약 저장시 포매팅 작업을 체크해놨다면 해제해야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단은 js, ts만 eslinting을 하기로 하자. 사실 이 두 언어 외에서 eslint를 쓸 일이...있나? 싶다.&lt;/p&gt;
&lt;pre id=&quot;code_1614612410204&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&quot;editor.codeActionsOnSave&quot;: {
      &quot;source.fixAll.eslint&quot;: true
  },
  &quot;eslint.alwaysShowStatus&quot;: true,
  &quot;eslint.workingDirectories&quot;: [
      {&quot;mode&quot;: &quot;auto&quot;}
  ],
  &quot;eslint.validate&quot;: [
      &quot;javascript&quot;,
      &quot;typescript&quot;
  ],&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저장시 eslint의 규칙에 맞게 자동으로 세팅해준다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;당연한 말이지만, .eslintrc를 설정한 프로젝트에서만 저장시 eslint에 의해 포매팅이 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;협업할 때 =&amp;gt; 오토 포매팅 꺼두고 eslint+prettier가 돌아가게 해두자&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;혼자할 때 =&amp;gt; 협업 세팅을 그대로 써도 되고, eslint가 거슬리면 저장시 포매팅을 켜서 사용하면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;C/C++ 등을 VScode에서 사용하고 싶다면&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;javascript, go, dart 등은 vscode에서 뚝딱이지만&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;c, cpp은 visual studio를 주로 사용한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼에도 용량이라던가, 컴퓨터 사양에 의해 vs를 사용할 수 없다면 vscode를 사용해보자.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;솔직히 연습할 때 vscode가 더 나은 것 같기도 하다...&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://darrengwon.tistory.com/1091&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;darrengwon.tistory.com/1091&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1609761733881&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-og-type=&quot;article&quot; data-og-title=&quot;C/C++ in VSCode / code runner! / formatting&quot; data-og-description=&quot;왜 VS안 쓰심? 무겁다. 게다가 visual studio 컴파일러보다 gcc 컴파일러를 사용하고 싶었기 때문이다. &amp;quot;visual studio에서는 되는데 왜 이 환경에서는 안되지?&amp;quot;와 같은 상황이 싫었다. 그래서 Clion을 쓸 것&quot; data-og-host=&quot;darrengwon.tistory.com&quot; data-og-source-url=&quot;https://darrengwon.tistory.com/1091&quot; data-og-url=&quot;https://darrengwon.tistory.com/1091&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/MQYLS/hyIOeA54ZZ/7IqqlksrbbKu9pUqwC1KOK/img.png?width=800&amp;amp;height=166&amp;amp;face=0_0_800_166,https://scrap.kakaocdn.net/dn/dF5ISj/hyIOdvq0Av/1sjtkeCzUpmtNDaEKSaE81/img.png?width=800&amp;amp;height=166&amp;amp;face=0_0_800_166,https://scrap.kakaocdn.net/dn/A0EJd/hyIPzcx6hj/IrXXmfWqqLfdmcpwEz5Smk/img.jpg?width=1110&amp;amp;height=740&amp;amp;face=0_0_1110_740&quot;&gt;&lt;a href=&quot;https://darrengwon.tistory.com/1091&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://darrengwon.tistory.com/1091&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/MQYLS/hyIOeA54ZZ/7IqqlksrbbKu9pUqwC1KOK/img.png?width=800&amp;amp;height=166&amp;amp;face=0_0_800_166,https://scrap.kakaocdn.net/dn/dF5ISj/hyIOdvq0Av/1sjtkeCzUpmtNDaEKSaE81/img.png?width=800&amp;amp;height=166&amp;amp;face=0_0_800_166,https://scrap.kakaocdn.net/dn/A0EJd/hyIPzcx6hj/IrXXmfWqqLfdmcpwEz5Smk/img.jpg?width=1110&amp;amp;height=740&amp;amp;face=0_0_1110_740');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;C/C++ in VSCode / code runner! / formatting&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;왜 VS안 쓰심? 무겁다. 게다가 visual studio 컴파일러보다 gcc 컴파일러를 사용하고 싶었기 때문이다. &quot;visual studio에서는 되는데 왜 이 환경에서는 안되지?&quot;와 같은 상황이 싫었다. 그래서 Clion을 쓸 것&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;darrengwon.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;rainbow extension deprecated -&amp;gt; using native vscode&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;966&quot; data-origin-height=&quot;122&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/2oo02/btrnQ3NAOSU/6aHkJYKtJtZWKgvd77Hf41/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/2oo02/btrnQ3NAOSU/6aHkJYKtJtZWKgvd77Hf41/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/2oo02/btrnQ3NAOSU/6aHkJYKtJtZWKgvd77Hf41/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F2oo02%2FbtrnQ3NAOSU%2F6aHkJYKtJtZWKgvd77Hf41%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;966&quot; height=&quot;122&quot; data-origin-width=&quot;966&quot; data-origin-height=&quot;122&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>미분류/Tip</category>
      <author>DarrenKwonDev</author>
      <guid isPermaLink="true">https://darrengwon.tistory.com/1098</guid>
      <comments>https://darrengwon.tistory.com/1098#entry1098comment</comments>
      <pubDate>Thu, 3 Feb 2022 09:57:43 +0900</pubDate>
    </item>
    <item>
      <title>flavor 분리에 따른 iOS info.plist 자동 변경을 위한 bash script</title>
      <link>https://darrengwon.tistory.com/1571</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;flavor 분리는 다른 팀원 분이 해주셨는데 문제가 iOS에서 빌드시 다음과 같은 꼴을 유지해야 했다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Untitled (1).png&quot; data-origin-width=&quot;536&quot; data-origin-height=&quot;412&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/uXNs5/btrrQzQFvu8/eEmt6OlK78tWkUhnZ000A1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/uXNs5/btrrQzQFvu8/eEmt6OlK78tWkUhnZ000A1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/uXNs5/btrrQzQFvu8/eEmt6OlK78tWkUhnZ000A1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FuXNs5%2FbtrrQzQFvu8%2FeEmt6OlK78tWkUhnZ000A1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;342&quot; height=&quot;263&quot; data-filename=&quot;Untitled (1).png&quot; data-origin-width=&quot;536&quot; data-origin-height=&quot;412&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. iOS 경로에 GoogleService-info.plist가 위치&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 그 다음 프로젝트 내의 Info.plist의 CFBundleURLSchemes 하단 부분에 flavor에 해당하는 REVERSED_CLIENT_ID를 주입&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해야 하는 지점이 있었다. XCode를 통해서 Add Files to &quot;Runner&quot;로 직접 넣어주면 되었지만 개발 중에 이들을 신경쓰기가 너무 불편하더라. 자동화하기 위해 Build Phases에서 빌드시 호출되는 로직 중 다음과 같이 bash shell을 끼워주었다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1734&quot; data-origin-height=&quot;892&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b7ZrVW/btrrU8Ylc0x/LAkwO6aIhQKK6Rw2cIwHp1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b7ZrVW/btrrU8Ylc0x/LAkwO6aIhQKK6Rw2cIwHp1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b7ZrVW/btrrU8Ylc0x/LAkwO6aIhQKK6Rw2cIwHp1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb7ZrVW%2FbtrrU8Ylc0x%2FLAkwO6aIhQKK6Rw2cIwHp1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1734&quot; height=&quot;892&quot; data-origin-width=&quot;1734&quot; data-origin-height=&quot;892&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;짜면서 얻은 교훈은&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. bash script가 생각보다 표기법이 불친절하다. 비교문의 [ ] 내부에 공백이 반드시 존재해야 한다던지 하는 룰이 익숙하지 않았다. bash를 계속 짜다보면 익숙해지긴 할 것이다. 시간이 많이 남았더라면 google이 만든 zx를 사용해보아도 좋을 듯하지만 여기서는 bash를 사용했다. &lt;a href=&quot;https://github.com/google/zx&quot;&gt;https://github.com/google/zx&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 크로스 플랫폼이라고는 하지만 native 언어와 플랫폼에 대한 지식은 반드시 필요하다. '덜' 필요할 뿐이지. 그리고 충분히 복잡한 어플리케이션을 제작해야 한다면 native 단을 건드리는 일이 훨씬 잦아질 것으로 예상한다. React 개발자 몇 명 있다고 React-native 앱 개발하라고 던져 놓으면 하긴 하겠지만 시행 착오에 드는 리소스 + 네이티브 학습 비용까지 고려한 일정을 잡아줘야 한다. 정말루... 아니면 native 개발자를 모셔오는 게 맞다. 그리고 일반 웹 개발자라가 모바일 앱에 발이라도 들여 놓으려면 최소한 kotlin이랑 android는 배워놔야 한다는 생각이 많이 든다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. iOS 개발에 있어서 XCode에 익숙해지는 것은 필수 불가결한 일 같다. 우리가 아는 일반적인 파일 시스템과는 다른. reference로 파일을 복사하는 것과 아닌 것을 구분한다던지, 특정한 방식으로 파일을 추가하면 부가적인 파일이 수정, 추가된다던지 하는 일이 잦다. 예를 들자면, 최초로 GoogleSerivce.plist를 일반적으로 추가하는 것과 XCode의 Add Files to &quot;Runner&quot;를 통해 추가하는 것은 Info.plist를 생성해주느냐 안해주느냐의 차이가 있다. iOS 개발을 전혀 모르면 나처럼 삽질을 장시간 할 수 밖에 없다...&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. 웬만히 다급하거나 답이 없는게 아니라면 plist를 하드 코딩으로 수정하지 말자. plistBuddy나 plutil을 통해서 코드로 조작하는게 좋다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대충 다음과 같이 생겼다. 실제로는 이것저것 더 있긴한데, 앞서 설명한 프로세스와는 관련이 없어서 지웠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;script를 읽고 프로젝트에 적합하게 알아서 가공해서 쓰면 되겠다...&lt;/p&gt;
&lt;pre id=&quot;code_1643272001371&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;environment=&quot;&quot;

# 환경을 얻기 위해서 정규식으로 발라내기
# CONFIGURATION=&quot;Debug-prod&quot; 꼴이면 &quot;prod&quot;를 반환
if [[ $CONFIGURATION =~ -([^-]*)$ ]]; then
environment=${BASH_REMATCH[1]}
fi

echo $environment

# GoogleService-Info.plist의 경로
GOOGLESERVICE_INFO_PLIST=GoogleService-Info.plist
GOOGLESERVICE_INFO_FILE=${PROJECT_DIR}/firebase/${environment}/${GOOGLESERVICE_INFO_PLIST}

# GoogleService-Info.plist가 경로에 존재하는지 체크
echo &quot;Looking for ${GOOGLESERVICE_INFO_PLIST} in ${GOOGLESERVICE_INFO_FILE}&quot;
if [ ! -f $GOOGLESERVICE_INFO_FILE ]
then
echo &quot;No GoogleService-Info.plist found. Please ensure it's in the proper directory.&quot;
exit 1
fi

# GoogleService-Info.plist를 복사할 경로
PLIST_DESTINATION=${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.app

# release 빌드와 debug 빌드를 위해 GoogleService-Info.plist를 필요한 곳에 복사
cp &quot;${GOOGLESERVICE_INFO_FILE}&quot; &quot;${PLIST_DESTINATION}&quot;
cp &quot;${GOOGLESERVICE_INFO_FILE}&quot; &quot;${PROJECT_DIR}&quot;

# Info-plist의 CFBundleURLSchemes를 교체하기 위한 로직
INFO_PLIST_FILE=${PROJECT_DIR}/Runner/Info.plist

# GoogleService-info.plist의 REVERSED_CLIENT_ID를 불러옵니다.
REVERSE_CLIENT_ID=&quot;&quot;

# 만약 googleService가 바뀔 경우 여기에 있는 값들도 변경되어야 합니다.
if [ &quot;$environment&quot; = &quot;dev&quot; ]; then
    REVERSE_CLIENT_ID=&quot;dev일 때의 REVERSE_CLIENT_ID&quot;
elif [ &quot;$environment&quot; = &quot;staging&quot; ]; then
    REVERSE_CLIENT_ID=&quot;staging일 때의 REVERSE_CLIENT_ID&quot;
elif [ &quot;$environment&quot; = &quot;prod&quot; ]; then
    REVERSE_CLIENT_ID=&quot;prod일 때의 REVERSE_CLIENT_ID&quot;
else
    echo &quot;environment is not correct, REVERSE_CLIENT_ID will be empty string&quot;
fi

# echo &quot;removing current url string&quot;
plutil -remove CFBundleURLTypes.0.CFBundleURLSchemes.0 $INFO_PLIST_FILE

# echo &quot;updating with new url string&quot;
plutil -replace CFBundleURLTypes.0.CFBundleURLSchemes.0 -string $REVERSE_CLIENT_ID $INFO_PLIST_FILE&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>  Mobile/  Flutter v 2.0</category>
      <author>DarrenKwonDev</author>
      <guid isPermaLink="true">https://darrengwon.tistory.com/1571</guid>
      <comments>https://darrengwon.tistory.com/1571#entry1571comment</comments>
      <pubDate>Thu, 27 Jan 2022 17:42:25 +0900</pubDate>
    </item>
    <item>
      <title>null safety</title>
      <link>https://darrengwon.tistory.com/1566</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;런타임 시점에 null이 들어오게 되어 발생하는 에러를 방지하고자 함.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이전과 다르게 모든 자료형은 nullable(?)이 붙지 않는 이상 non-nullable로 취급됨.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;dart의 타입 시스템이 바뀌었음&amp;nbsp;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #777777;&quot;&gt;&lt;a href=&quot;https://dart.dev/null-safety/understanding-null-safety&quot;&gt;https://dart.dev/null-safety/understanding-null-safety&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1641298993725&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Understanding null safety&quot; data-og-description=&quot;A deep dive into Dart language and library changes related to null safety.&quot; data-og-host=&quot;dart.dev&quot; data-og-source-url=&quot;https://dart.dev/null-safety/understanding-null-safety&quot; data-og-url=&quot;https://dart.dev/null-safety/understanding-null-safety/&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://dart.dev/null-safety/understanding-null-safety&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://dart.dev/null-safety/understanding-null-safety&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Understanding null safety&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;A deep dive into Dart language and library changes related to null safety.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;dart.dev&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;좌측이 null safety가 적용되기 전의 타입 시스템이라면 null safety가 적용되고난 후에는 우측처럼 되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Null이 별도의 타입 처리된 것이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nltgp/btrpJQfBn8F/754YdHV4s8ULqo7QBzwzk1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nltgp/btrpJQfBn8F/754YdHV4s8ULqo7QBzwzk1/img.png&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;1089&quot; style=&quot;width: 40.3724%; margin-right: 10px;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nltgp/btrpJQfBn8F/754YdHV4s8ULqo7QBzwzk1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fnltgp%2FbtrpJQfBn8F%2F754YdHV4s8ULqo7QBzwzk1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1280&quot; height=&quot;1089&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/zBUcl/btrpLuJZ571/Z6pIBnGJsKXL495EahtM50/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/zBUcl/btrpLuJZ571/Z6pIBnGJsKXL495EahtM50/img.png&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;752&quot; style=&quot;width: 58.4648%;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/zBUcl/btrpLuJZ571/Z6pIBnGJsKXL495EahtM50/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FzBUcl%2FbtrpLuJZ571%2FZ6pIBnGJsKXL495EahtM50%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1280&quot; height=&quot;752&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;https://dart.dev/null-safety/understanding-null-safety&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;더 나아가 String? 꼴과 같이 nullable 타입을 지정하게 되었다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;943&quot; data-origin-height=&quot;476&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/pMYJh/btrpPGpigyg/vkgHrfVnn2CVamzceL7KI0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/pMYJh/btrpPGpigyg/vkgHrfVnn2CVamzceL7KI0/img.png&quot; data-alt=&quot;https://dart.dev/null-safety/understanding-null-safety&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/pMYJh/btrpPGpigyg/vkgHrfVnn2CVamzceL7KI0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FpMYJh%2FbtrpPGpigyg%2FvkgHrfVnn2CVamzceL7KI0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;450&quot; height=&quot;227&quot; data-origin-width=&quot;943&quot; data-origin-height=&quot;476&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://dart.dev/null-safety/understanding-null-safety&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한 최하단에 Never라는 타입이 오게 되었는데 사실상 추상적인 개념이라고 보아야할 듯 싶다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;1308&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qSYKJ/btrpPE56gmr/fdOiynen1XkgkOP4HmdUgk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qSYKJ/btrpPE56gmr/fdOiynen1XkgkOP4HmdUgk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qSYKJ/btrpPE56gmr/fdOiynen1XkgkOP4HmdUgk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqSYKJ%2FbtrpPE56gmr%2FfdOiynen1XkgkOP4HmdUgk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;450&quot; height=&quot;460&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;1308&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;null이 별도 타입 처리되면서 강조되는 문법들&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코드랩 한 번 쫙 돌려주면 게임 끝&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://dart.dev/codelabs/null-safety&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://dart.dev/codelabs/null-safety&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1641298958918&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Null safety codelab&quot; data-og-description=&quot;Learn about and practice writing null-safe code in DartPad!&quot; data-og-host=&quot;dart.dev&quot; data-og-source-url=&quot;https://dart.dev/codelabs/null-safety&quot; data-og-url=&quot;https://dart.dev/codelabs/null-safety.html&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/dnRT7m/hyMXJqyC4m/jPjbsa158lodKiybh24JW0/img.png?width=2650&amp;amp;height=1488&amp;amp;face=0_0_2650_1488&quot;&gt;&lt;a href=&quot;https://dart.dev/codelabs/null-safety&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://dart.dev/codelabs/null-safety&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/dnRT7m/hyMXJqyC4m/jPjbsa158lodKiybh24JW0/img.png?width=2650&amp;amp;height=1488&amp;amp;face=0_0_2650_1488');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Null safety codelab&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Learn about and practice writing null-safe code in DartPad!&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;dart.dev&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;exception으로 처리&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일반적으로 그냥 null 잡아서 throw Exception해도 된다.&lt;/p&gt;
&lt;pre id=&quot;code_1641300349972&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;int getLength(String? str) {
  if (str == null) {
    throw Exception(&quot;str is null&quot;);
  }
  
  return str.length;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Nullish coalescing operator (??)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;??를 통해 null일 경우 할당할 값을 지정할 수 있음&lt;/p&gt;
&lt;pre id=&quot;code_1641297545410&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;int? nullableVar = null;
int a = nullableVar ?? 1;
print(a);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Optional chaining (?.)&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1641298213483&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;int? a = null;
print(a?.toString());&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;null assertion (!)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;!를 통해 non-null assertion을 할 수 있음. 당연히 런타임에 확실하게 null이 절대 들어올 일 없다고 확신해야만 사용해야 함.&lt;/p&gt;
&lt;pre id=&quot;code_1641298346602&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;  int? couldBeNullButIsnt = 1;
  List&amp;lt;int?&amp;gt; listThatCouldHoldNulls = [2, null, 4];

  int a = couldBeNullButIsnt;
  int b = listThatCouldHoldNulls.first!; // first item in the list
  int c = couldReturnNullButDoesnt().abs(); // absolute value&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Generic과 관련된 nullable 예시&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1641298541955&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;List&amp;lt;int&amp;gt; a = [3, 4, 1, 5];
List&amp;lt;int&amp;gt;? b = null; // List 자체가 null이 될 수 있다
List&amp;lt;int?&amp;gt; c = [1, 3, null, 4]; // 원소에 null이 들어올 수 있다
List&amp;lt;int?&amp;gt;? d = null; // List 자체가 null이 될 수도 있고, List가 있더라도 원소 중 null이 존재할 수 있다.&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;late 키워드&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;써보니 이 녀석은 &quot;&lt;b&gt;곧 할당 될거니까 nullable 처리 안해줘도 그냥 좀 넘어가라&lt;/b&gt;&quot;라는 의미다.&lt;/p&gt;
&lt;pre id=&quot;code_1641300628258&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class Meal {
  // late 처리가 없다면non-nullable 필드는 반드시 초기화 되어야 한다고 경고뜸
  late String _description; 

  set description(String desc) {
    _description = 'Meal description: $desc';
  }

  String get description =&amp;gt; _description;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;순환 참조에 있어서 late 활용&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러니까 Team은 Coach가 있어야하고 Coach는 Team이 있는, 순환 참조의 형태인데 이럴 경우 late 처리를 해줘야한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;안해주면 초기화하라고 경고 뜬다&lt;/p&gt;
&lt;pre id=&quot;code_1641300703072&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class Team {
  late final Coach coach;
}

class Coach {
  late final Team team;
}

void main() {
  final myTeam = Team();
  final myCoach = Coach();
  myTeam.coach = myCoach;
  myCoach.team = myTeam;

  print('All done!');
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;late를 활용한 lazy 초기화&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(&lt;a href=&quot;https://dart.dev/null-safety/understanding-null-safety#lazy-initialization&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://dart.dev/null-safety/understanding-null-safety#lazy-initialization&lt;/a&gt;)&lt;/p&gt;
&lt;pre id=&quot;code_1641300909845&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;int _computeValue() {
  print('In _computeValue...');
  return 3;
}

class CachedValueProvider {
  // 여기에 late 키워드를 붙이면, 요구하기 전까지 _computeValue 실행을 미룬다.
  final _cache = _computeValue(); 
  int get value =&amp;gt; _cache;
}

void main() {
  print('Calling constructor...');
  var provider = CachedValueProvider();
  print('Getting value...');
  print('The value is ${provider.value}!');
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;감이 오겠지만 late를 사용하면 _computeValue는 &amp;nbsp;print('The value is ${provider.value}!');에 의해 호출되어 필요해질 때 실행된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;추가적으로&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;typescript 처럼 flow analysis 분석해줘서 type narrowing이 된다. 너무 편함!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ref)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=tP9TcrUZoIs&quot;&gt;https://www.youtube.com/watch?v=tP9TcrUZoIs&lt;/a&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://dart.dev/null-safety&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://dart.dev/null-safety&lt;/a&gt;&lt;/p&gt;</description>
      <category>Programming Language/  Dart</category>
      <author>DarrenKwonDev</author>
      <guid isPermaLink="true">https://darrengwon.tistory.com/1566</guid>
      <comments>https://darrengwon.tistory.com/1566#entry1566comment</comments>
      <pubDate>Mon, 3 Jan 2022 21:57:22 +0900</pubDate>
    </item>
  </channel>
</rss>