Kata ์ปจํ…Œ์ด๋„ˆ์˜ ๊ฐ„๋žตํ•œ ๊ฐœ์š” ๋ฐ ์„ค์ •

Kata ์ปจํ…Œ์ด๋„ˆ์˜ ๊ฐ„๋žตํ•œ ๊ฐœ์š” ๋ฐ ์„ค์ •
์ด ๊ธฐ์‚ฌ์—์„œ๋Š” ์ž‘๋™ ๋ฐฉ์‹์— ๋Œ€ํ•ด ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค. ์นดํƒ€ ์ปจํ…Œ์ด๋„ˆ, Docker์™€์˜ ์—ฐ๊ฒฐ๊ณผ ๊ด€๋ จ๋œ ์‹ค์šฉ์ ์ธ ๋ถ€๋ถ„๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

Docker ๋ฐ ํ•ด๋‹น ์†”๋ฃจ์…˜์˜ ์ผ๋ฐ˜์ ์ธ ๋ฌธ์ œ์— ๋Œ€ํ•ด ์ด๋ฏธ ์ผ๋‹ค, ์˜ค๋Š˜์€ Kata Containers์˜ ๊ตฌํ˜„์— ๋Œ€ํ•ด ๊ฐ„๋žตํ•˜๊ฒŒ ์„ค๋ช…ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. Kata Containers๋Š” ๊ฒฝ๋Ÿ‰ ๊ฐ€์ƒ ๋จธ์‹ ์„ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•˜๋Š” ์•ˆ์ „ํ•œ ์ปจํ…Œ์ด๋„ˆ ๋Ÿฐํƒ€์ž„์ž…๋‹ˆ๋‹ค. ๊ทธ๋“ค๊ณผ ํ•จ๊ป˜ ์ž‘์—…ํ•˜๋Š” ๊ฒƒ์€ ๋‹ค๋ฅธ ์ปจํ…Œ์ด๋„ˆ์™€ ๋™์ผํ•˜์ง€๋งŒ ํ•˜๋“œ์›จ์–ด ๊ฐ€์ƒํ™” ๊ธฐ์ˆ ์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ณด๋‹ค ์•ˆ์ •์ ์ธ ๊ฒฉ๋ฆฌ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ํ”„๋กœ์ ํŠธ๋Š” ๊ฐ™์€ ์ด๋ฆ„์˜ ์ปค๋ฎค๋‹ˆํ‹ฐ๊ฐ€ Intel Clear Containers์™€ Hyper.sh RunV์˜ ์ตœ๊ณ ์˜ ์•„์ด๋””์–ด๋ฅผ ํ†ตํ•ฉํ•œ 2017๋…„์— ์‹œ์ž‘๋˜์—ˆ์œผ๋ฉฐ, ๊ทธ ํ›„ AMD64, ARM, IBM p- ๋ฐ z๋ฅผ ํฌํ•จํ•œ ๋‹ค์–‘ํ•œ ์•„ํ‚คํ…์ฒ˜์— ๋Œ€ํ•œ ์ง€์› ์ž‘์—…์ด ๊ณ„์†๋˜์—ˆ์Šต๋‹ˆ๋‹ค. -์‹œ๋ฆฌ์ฆˆ. ๋˜ํ•œ ํ•˜์ดํผ๋ฐ”์ด์ € QEMU ๋‚ด์—์„œ ์ž‘์—…ํ•˜๊ณ  Firecracker๊ฐ€ ์ง€์›๋˜๋ฉฐ containerd์™€์˜ ํ†ตํ•ฉ๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ์ฝ”๋“œ๋Š” ๋‹ค์Œ์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. GitHub์˜ MIT ๋ผ์ด์„ผ์Šค์— ๋”ฐ๋ผ.

์ฃผ์š” ๊ธฐ๋Šฅ

  • ๋ณ„๋„์˜ ์ฝ”์–ด๋กœ ์ž‘์—…ํ•˜์—ฌ ๋„คํŠธ์›Œํฌ, ๋ฉ”๋ชจ๋ฆฌ ๋ฐ I/O ๊ฒฉ๋ฆฌ๋ฅผ ์ œ๊ณตํ•˜๋ฏ€๋กœ ๊ฐ€์ƒํ™” ํ™•์žฅ์„ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•˜๋“œ์›จ์–ด ๊ฒฉ๋ฆฌ๋ฅผ ๊ฐ•์ œ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • OCI(์ปจํ…Œ์ด๋„ˆ ํ˜•์‹), Kubernetes CRI๋ฅผ ํฌํ•จํ•œ ์‚ฐ์—… ํ‘œ์ค€ ์ง€์›
  • ์ผ๋ฐ˜ Linux ์ปจํ…Œ์ด๋„ˆ์˜ ์ผ๊ด€๋œ ์„ฑ๋Šฅ, ์ผ๋ฐ˜ VM์˜ ์„ฑ๋Šฅ ์˜ค๋ฒ„ํ—ค๋“œ ์—†์ด ํ–ฅ์ƒ๋œ ๊ฒฉ๋ฆฌ
  • ์™„์ „ํ•œ ๊ธฐ๋Šฅ์„ ๊ฐ–์ถ˜ ๊ฐ€์ƒ ๋จธ์‹  ๋‚ด์—์„œ ์ปจํ…Œ์ด๋„ˆ๋ฅผ ์‹คํ–‰ํ•  ํ•„์š”๊ฐ€ ์—†์œผ๋ฉฐ ์ผ๋ฐ˜ ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ํ†ตํ•ฉ ๋ฐ ์‹คํ–‰์„ ๋‹จ์ˆœํ™”ํ•ฉ๋‹ˆ๋‹ค.

์„ค์น˜

์ด ์„ธํŠธ ์„ค์น˜ ์˜ต์…˜, Centos 7 ์šด์˜ ์ฒด์ œ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ๋ฆฌํฌ์ง€ํ† ๋ฆฌ์—์„œ ์„ค์น˜ํ•˜๋Š” ๊ฒƒ์„ ๊ณ ๋ คํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.
์ค‘์š”ํ•œ ์ผ์ด์•ผ: Kata Containers ์ž‘์—…์€ ํ•˜๋“œ์›จ์–ด์—์„œ๋งŒ ์ง€์›๋˜๋ฉฐ, ๊ฐ€์ƒํ™” ํฌ์›Œ๋”ฉ์ด ํ•ญ์ƒ ์ž‘๋™ํ•˜๋Š” ๊ฒƒ์€ ์•„๋‹ˆ๋ฉฐ, sse4.1 ์ง€์› ํ•„์š” ํ”„๋กœ์„ธ์„œ์—์„œ.

Kata ์ปจํ…Œ์ด๋„ˆ ์„ค์น˜๋Š” ๋งค์šฐ ๊ฐ„๋‹จํ•ฉ๋‹ˆ๋‹ค.

๋ฆฌํฌ์ง€ํ† ๋ฆฌ ์ž‘์—…์„ ์œ„ํ•œ ์œ ํ‹ธ๋ฆฌํ‹ฐ๋ฅผ ์„ค์น˜ํ•ฉ๋‹ˆ๋‹ค.

# yum -y install yum-utils

Selinux๋ฅผ ๋น„ํ™œ์„ฑํ™”ํ•ฉ๋‹ˆ๋‹ค(๊ตฌ์„ฑํ•˜๋Š” ๊ฒƒ์ด ๋” ์ •ํ™•ํ•˜์ง€๋งŒ ๊ฐ„๋‹จํ•˜๊ฒŒ ํ•˜๊ธฐ ์œ„ํ•ด ๋น„ํ™œ์„ฑํ™”ํ•ฉ๋‹ˆ๋‹ค).

# setenforce 0
# sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config

์ €์žฅ์†Œ๋ฅผ ์—ฐ๊ฒฐํ•˜๊ณ  ์„ค์น˜๋ฅผ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

# source /etc/os-release
# ARCH=$(arch)
# BRANCH="${BRANCH:-stable-1.10}"
# yum-config-manager --add-repo "http://download.opensuse.org/repositories/home:/katacontainers:/releases:/${ARCH}:/${BRANCH}/CentOS_${VERSION_ID}/home:katacontainers:releases:${ARCH}:${BRANCH}.repo"
# yum -y install kata-runtime kata-proxy kata-shim

์กฐ์ •

docker์™€ ํ•จ๊ป˜ ์ž‘๋™ํ•˜๋„๋ก ๊ตฌ์„ฑํ•˜๊ณ  ์„ค์น˜๊ฐ€ ์ผ๋ฐ˜์ ์ด๋ฏ€๋กœ ๋” ์ž์„ธํžˆ ์„ค๋ช…ํ•˜์ง€ ์•Š๊ฒ ์Šต๋‹ˆ๋‹ค.

# rpm -qa | grep docker
docker-ce-cli-19.03.6-3.el7.x86_64
docker-ce-19.03.6-3.el7.x86_64
# docker -v
Docker version 19.03.6, build 369ce74a3c

daemon.json์„ ๋ณ€๊ฒฝํ•ฉ๋‹ˆ๋‹ค.

# cat <<EOF > /etc/docker/daemon.json
{
  "default-runtime": "kata-runtime",
  "runtimes": {
    "kata-runtime": {
      "path": "/usr/bin/kata-runtime"
    }
  }
}
EOF

๋„์ปค๋ฅผ ๋‹ค์‹œ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค.

# service docker restart

๊ธฐ๋Šฅ ์ ๊ฒ€

Docker๋ฅผ ๋‹ค์‹œ ์‹œ์ž‘ํ•˜๊ธฐ ์ „์— ์ปจํ…Œ์ด๋„ˆ๋ฅผ ์‹œ์ž‘ํ•˜๋ฉด uname์ด ๊ธฐ๋ณธ ์‹œ์Šคํ…œ์—์„œ ์‹คํ–‰ ์ค‘์ธ ์ปค๋„ ๋ฒ„์ „์„ ์ œ๊ณตํ•˜๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

# docker run busybox uname -a
Linux 19efd7188d06 3.10.0-1062.12.1.el7.x86_64 #1 SMP Tue Feb 4 23:02:59 UTC 2020 x86_64 GNU/Linux

๋‹ค์‹œ ์‹œ์ž‘ํ•œ ํ›„ ์ปค๋„ ๋ฒ„์ „์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

# docker run busybox uname -a
Linux 9dd1f30fe9d4 4.19.86-5.container #1 SMP Sat Feb 22 01:53:14 UTC 2020 x86_64 GNU/Linux

๋” ๋งŽ์€ ํŒ€!

# time docker run busybox mount
kataShared on / type 9p (rw,dirsync,nodev,relatime,mmap,access=client,trans=virtio)
proc on /proc type proc (rw,nosuid,nodev,noexec,relatime)
tmpfs on /dev type tmpfs (rw,nosuid,size=65536k,mode=755)
devpts on /dev/pts type devpts (rw,nosuid,noexec,relatime,gid=5,mode=620,ptmxmode=666)
sysfs on /sys type sysfs (ro,nosuid,nodev,noexec,relatime)
tmpfs on /sys/fs/cgroup type tmpfs (ro,nosuid,nodev,noexec,relatime,mode=755)
cgroup on /sys/fs/cgroup/systemd type cgroup (ro,nosuid,nodev,noexec,relatime,xattr,name=systemd)
cgroup on /sys/fs/cgroup/cpu,cpuacct type cgroup (ro,nosuid,nodev,noexec,relatime,cpu,cpuacct)
cgroup on /sys/fs/cgroup/blkio type cgroup (ro,nosuid,nodev,noexec,relatime,blkio)
cgroup on /sys/fs/cgroup/memory type cgroup (ro,nosuid,nodev,noexec,relatime,memory)
cgroup on /sys/fs/cgroup/devices type cgroup (ro,nosuid,nodev,noexec,relatime,devices)
cgroup on /sys/fs/cgroup/perf_event type cgroup (ro,nosuid,nodev,noexec,relatime,perf_event)
cgroup on /sys/fs/cgroup/net_cls,net_prio type cgroup (ro,nosuid,nodev,noexec,relatime,net_cls,net_prio)
cgroup on /sys/fs/cgroup/freezer type cgroup (ro,nosuid,nodev,noexec,relatime,freezer)
cgroup on /sys/fs/cgroup/pids type cgroup (ro,nosuid,nodev,noexec,relatime,pids)
cgroup on /sys/fs/cgroup/cpuset type cgroup (ro,nosuid,nodev,noexec,relatime,cpuset)
mqueue on /dev/mqueue type mqueue (rw,nosuid,nodev,noexec,relatime)
shm on /dev/shm type tmpfs (rw,nosuid,nodev,noexec,relatime,size=65536k)
kataShared on /etc/resolv.conf type 9p (rw,dirsync,nodev,relatime,mmap,access=client,trans=virtio)
kataShared on /etc/hostname type 9p (rw,dirsync,nodev,relatime,mmap,access=client,trans=virtio)
kataShared on /etc/hosts type 9p (rw,dirsync,nodev,relatime,mmap,access=client,trans=virtio)
proc on /proc/bus type proc (ro,relatime)
proc on /proc/fs type proc (ro,relatime)
proc on /proc/irq type proc (ro,relatime)
proc on /proc/sys type proc (ro,relatime)
tmpfs on /proc/acpi type tmpfs (ro,relatime)
tmpfs on /proc/timer_list type tmpfs (rw,nosuid,size=65536k,mode=755)
tmpfs on /sys/firmware type tmpfs (ro,relatime)

real    0m2.381s
user    0m0.066s
sys 0m0.039s

# time docker run busybox free -m
              total        used        free      shared  buff/cache   available
Mem:           1993          30        1962           0           1        1946
Swap:             0           0           0

real    0m3.297s
user    0m0.086s
sys 0m0.050s

๋น ๋ฅธ ๋ถ€ํ•˜ ํ…Œ์ŠคํŠธ

๊ฐ€์ƒํ™”๋กœ ์ธํ•œ ์†์‹ค์„ ํ‰๊ฐ€ํ•˜๊ธฐ ์œ„ํ•ด - ์ฃผ์š” ์˜ˆ๋กœ sysbench๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค. ์ด ์˜ต์…˜์„ ์„ ํƒ.

Docker+containerd๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ sysbench ์‹คํ–‰

ํ”„๋กœ์„ธ์„œ ํ…Œ์ŠคํŠธ

sysbench 1.0:  multi-threaded system evaluation benchmark

Running the test with following options:
Number of threads: 1
Initializing random number generator from current time

Prime numbers limit: 20000

Initializing worker threads...

Threads started!

General statistics:
    total time:                          36.7335s
    total number of events:              10000
    total time taken by event execution: 36.7173s
    response time:
         min:                                  3.43ms
         avg:                                  3.67ms
         max:                                  8.34ms
         approx.  95 percentile:               3.79ms

Threads fairness:
    events (avg/stddev):           10000.0000/0.00
    execution time (avg/stddev):   36.7173/0.00

๋žจ ํ…Œ์ŠคํŠธ

sysbench 1.0:  multi-threaded system evaluation benchmark

Running the test with following options:
Number of threads: 1
Initializing random number generator from current time

Initializing worker threads...

Threads started!

Operations performed: 104857600 (2172673.64 ops/sec)

102400.00 MiB transferred (2121.75 MiB/sec)

General statistics:
    total time:                          48.2620s
    total number of events:              104857600
    total time taken by event execution: 17.4161s
    response time:
         min:                                  0.00ms
         avg:                                  0.00ms
         max:                                  0.17ms
         approx.  95 percentile:               0.00ms

Threads fairness:
    events (avg/stddev):           104857600.0000/0.00
    execution time (avg/stddev):   17.4161/0.00

Docker+Kata ์ปจํ…Œ์ด๋„ˆ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ sysbench ์‹คํ–‰

ํ”„๋กœ์„ธ์„œ ํ…Œ์ŠคํŠธ

sysbench 1.0:  multi-threaded system evaluation benchmark

Running the test with following options:
Number of threads: 1
Initializing random number generator from current time

Prime numbers limit: 20000

Initializing worker threads...

Threads started!

General statistics:
    total time:                          36.5747s
    total number of events:              10000
    total time taken by event execution: 36.5594s
    response time:
         min:                                  3.43ms
         avg:                                  3.66ms
         max:                                  4.93ms
         approx.  95 percentile:               3.77ms

Threads fairness:
    events (avg/stddev):           10000.0000/0.00
    execution time (avg/stddev):   36.5594/0.00

๋žจ ํ…Œ์ŠคํŠธ

sysbench 1.0:  multi-threaded system evaluation benchmark

Running the test with following options:
Number of threads: 1
Initializing random number generator from current time

Initializing worker threads...

Threads started!

Operations performed: 104857600 (2450366.94 ops/sec)

102400.00 MiB transferred (2392.94 MiB/sec)

General statistics:
    total time:                          42.7926s
    total number of events:              104857600
    total time taken by event execution: 16.1512s
    response time:
         min:                                  0.00ms
         avg:                                  0.00ms
         max:                                  0.43ms
         approx.  95 percentile:               0.00ms

Threads fairness:
    events (avg/stddev):           104857600.0000/0.00
    execution time (avg/stddev):   16.1512/0.00

์›์น™์ ์œผ๋กœ ์ƒํ™ฉ์€ ์ด๋ฏธ ๋ช…ํ™•ํ•˜์ง€๋งŒ ํ…Œ์ŠคํŠธ๋ฅผ ์—ฌ๋Ÿฌ ๋ฒˆ ์‹คํ–‰ํ•˜์—ฌ ์ด์ƒ ์น˜๋ฅผ ์ œ๊ฑฐํ•˜๊ณ  ๊ฒฐ๊ณผ๋ฅผ ํ‰๊ท ํ™”ํ•˜๋Š” ๊ฒƒ์ด ๋” ์ตœ์ ์ด๋ฏ€๋กœ ์•„์ง ๋” ๋งŽ์€ ํ…Œ์ŠคํŠธ๋ฅผ ์ˆ˜ํ–‰ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์กฐ์‚ฌ ๊ฒฐ๊ณผ

์ด๋Ÿฌํ•œ ์ปจํ…Œ์ด๋„ˆ๋Š” ์‹œ์ž‘ํ•˜๋Š” ๋ฐ ์•ฝ XNUMX~XNUMX๋ฐฐ ๋” ์˜ค๋ž˜ ๊ฑธ๋ฆฐ๋‹ค๋Š” ์‚ฌ์‹ค์—๋„ ๋ถˆ๊ตฌํ•˜๊ณ (containerd๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ ์œ ์‚ฌํ•œ ๋ช…๋ น์˜ ์ผ๋ฐ˜์ ์ธ ์‹คํ–‰ ์‹œ๊ฐ„์€ XNUMX/XNUMX์ดˆ ๋ฏธ๋งŒ) ์ ˆ๋Œ€ ์‹œ์ž‘ ์‹œ๊ฐ„์„ ์ทจํ•˜๋ฉด ์—ฌ์ „ํžˆ ๋งค์šฐ ๋น ๋ฅด๊ฒŒ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค(๊ฑฐ๊ธฐ ์œ„์˜ ์˜ˆ, ํ‰๊ท  XNUMX์ดˆ ๋‚ด์— ์ˆ˜ํ–‰๋˜๋Š” ๋ช…๋ น). ์Œ, CPU์™€ RAM์— ๋Œ€ํ•œ ๋น ๋ฅธ ํ…Œ์ŠคํŠธ ๊ฒฐ๊ณผ๋Š” ๊ฑฐ์˜ ๋™์ผํ•œ ๊ฒฐ๊ณผ๋ฅผ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค. ํŠนํžˆ kvm๊ณผ ๊ฐ™์ด ์ž˜ ์‹คํ–‰๋˜๋Š” ๋ฉ”์ปค๋‹ˆ์ฆ˜์„ ์‚ฌ์šฉํ•˜์—ฌ ๊ฒฉ๋ฆฌ๊ฐ€ ์ œ๊ณต๋œ๋‹ค๋Š” ์ ์—์„œ ๊ธฐ๋ปํ•  ์ˆ˜๋ฐ–์— ์—†์Šต๋‹ˆ๋‹ค.

๋ฐœํ‘œ

๊ธ€์€ ๋ฆฌ๋ทฐ์ง€๋งŒ ๋Œ€์ฒด๋Ÿฐํƒ€์ž„์„ ๋Š๋‚„ ์ˆ˜ ์žˆ๋Š” ๊ธฐํšŒ๋ฅผ ์ค๋‹ˆ๋‹ค. ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ๋งŽ์€ ์˜์—ญ์€ ๋‹ค๋ฃจ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ์ด ์‚ฌ์ดํŠธ์—์„œ๋Š” Kata ์ปจํ…Œ์ด๋„ˆ ์œ„์—์„œ Kubernetes๋ฅผ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋Š” ๊ฐ€๋Šฅ์„ฑ์— ๋Œ€ํ•ด ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ ๋ณด์•ˆ ๋ฌธ์ œ ์ฐพ๊ธฐ, ์ œํ•œ ์„ค์ • ๋ฐ ๊ธฐํƒ€ ํฅ๋ฏธ๋กœ์šด ์‚ฌํ•ญ์— ์ดˆ์ ์„ ๋งž์ถ˜ ์ผ๋ จ์˜ ํ…Œ์ŠคํŠธ๋ฅผ ์‹คํ–‰ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

๋‚˜๋Š” ์—ฌ๊ธฐ์—์„œ ์ฝ๊ณ  ๋˜๊ฐ์€ ๋ชจ๋“  ์‚ฌ๋žŒ๋“ค์—๊ฒŒ ์ด ์ฃผ์ œ์— ๋Œ€ํ•œ ํ–ฅํ›„ ์ถœํŒ๋ฌผ์ด ์˜์กดํ•  ์„ค๋ฌธ ์กฐ์‚ฌ์— ์ฐธ์—ฌํ•˜๋„๋ก ์š”์ฒญํ•ฉ๋‹ˆ๋‹ค.

๋“ฑ๋ก๋œ ์‚ฌ์šฉ์ž๋งŒ ์„ค๋ฌธ ์กฐ์‚ฌ์— ์ฐธ์—ฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋กœ๊ทธ์ธ์ œ๋ฐœ

Kata ์ปจํ…Œ์ด๋„ˆ์— ๋Œ€ํ•œ ๊ธฐ์‚ฌ๋ฅผ ๊ณ„์† ๊ฒŒ์‹œํ•ด์•ผ ํ•ฉ๋‹ˆ๊นŒ?

  • 80,0%๋„ค, ๋” ์จ์ฃผ์„ธ์š”!28

  • 20,0%์•„๋‹ˆ, ํ•˜์ง€๋งˆ...7

35๋ช…์˜ ์‚ฌ์šฉ์ž๊ฐ€ ํˆฌํ‘œํ–ˆ์Šต๋‹ˆ๋‹ค. 7๋ช…์˜ ์‚ฌ์šฉ์ž๊ฐ€ ๊ธฐ๊ถŒํ–ˆ์Šต๋‹ˆ๋‹ค.

์ถœ์ฒ˜ : habr.com

์ฝ”๋ฉ˜ํŠธ๋ฅผ ์ถ”๊ฐ€