์ปจ์Šˆ๋จธ ๊ทธ๋ฃน์ด ๋ฐ์ดํ„ฐ๋ฅผ ์ž˜ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋„๋ก ์กฐ์œจํ•˜๊ณ  ๊ด€๋ฆฌํ•˜๋Š” ์ฝ”๋””๋„ค์ดํ„ฐ์— ๋Œ€ํ•ด. ์ž‘์€ ํด๋Ÿฌ์Šคํ„ฐ์ฒ˜๋Ÿผ ๋™์ž‘ํ•˜๋Š” ์ปจ์Šˆ๋จธ ๊ทธ๋ฃน์„ ์–ด๋–ป๊ฒŒ ์ œ์–ดํ•  ์ˆ˜ ์žˆ์„๊นŒ?

6 minute read

ํšŒ์‚ฌ์—์„œ Confluent๋ฅผ ํ†ตํ•ด Kafka ํด๋Ÿฌ์Šคํ„ฐ๋ฅผ ์ž˜ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ๋ฐ, ์ด ์นดํ”„์นด์— ๋Œ€ํ•ด์„œ ์ข€๋” ์ž์„ธํžˆ ์•Œ๊ณ , ์ „๋ฌธ์„ฑ์„ ๊ฐ–์ถ”๊ณ  ์‹ถ๋‹ค๋Š” ์ƒ๊ฐ์ด ๋“ค์–ด์„œ 2025๋…„ ์ฒซ ๋ชฉํ‘œ๋กœ Confluent์˜ Kafka ์ž๊ฒฉ์ฆ์ธ Confluent Certified Developer for Apache Kafkaยฎ ์ž๊ฒฉ์ฆ์„ ์ค€๋น„ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค โœŒ๏ธ

๋“ค์–ด๊ฐ€๋ฉฐ

์ปจ์Šˆ๋จธ ๊ทธ๋ฃน์€ ์—ฌ๋Ÿฌ ์ปจ์Šˆ๋จธ๊ฐ€ ๋ชจ์—ฌ์„œ ์นดํ”„์นด ํ† ํ”ฝ์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณ‘๋ ฌ๋กœ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด ๊ตฌ์„ฑ๋œ ์ปดํฌ๋„ŒํŠธ ์ž…๋‹ˆ๋‹ค. โ€œ์ปจ์Šˆ๋จธ๊ฐ€ N๊ฐœ๋‹ˆ๊นŒ, ์ฒ˜๋ฆฌ๋Ÿ‰๋„ N๊ฐœ? ํžˆํžˆโ€์ฒ˜๋Ÿผ ๋‹จ์ˆœํ•˜๊ฒŒ ์ƒ๊ฐํ•  ์ˆ˜ ์žˆ๊ฒ ์ง€๋งŒ, ๋ณธ์งˆ์€ ์ปจ์Šˆ๋จธ ๊ทธ๋ฃน์ด ํ•˜๋‚˜์˜ โ€œ์ž‘์€ ํด๋Ÿฌ์Šคํ„ฐโ€๊ฐ€ ๋˜์–ด ์นดํ”„์นด ๋ธŒ๋กœ์ปค์™€ ํ†ต์‹ ํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ํด๋Ÿฌ์Šคํ„ฐ ์ฒ˜๋Ÿผ ๋™์ž‘ํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ์ด๋‹ˆ ์ด๋“ค์„ ์ œ์–ดํ•˜๊ณ  ๊ด€๋ฆฌํ•˜๋Š” ์ปจํŠธ๋กค ํ”Œ๋ ˆ์ธ ์—ญํ• ์ด ํ•„์š” ํ•ฉ๋‹ˆ๋‹ค! ๊ทธ ์—ญํ• ์„ ํ•ด์ฃผ๋Š” ๊ฒƒ์ด ์ฝ”๋””๋„ค์ดํ„ฐ(Coordinator)์ด๊ณ , ์ด๋ฒˆ ํฌ์ŠคํŠธ์—์„œ ์‚ดํŽด๋ณผ ๋…€์„ ์ž…๋‹ˆ๋‹ค.

์ „์ฒด์ ์ธ ๊ตฌ์„ฑ

Confluent: Consumer Group Protocol

ํฐ๊ทธ๋ฆผ์„ ๋จผ์ € ๊ทธ๋ ค๋ด…์‹œ๋‹ค!

  • ๊ทธ๋ฃน ์ฝ”๋””๋„ค์ดํ„ฐ
    • ๋ธŒ๋กœ์ปค์— ์กด์žฌํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ ์ž…๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ โ€œserver-sideโ€๋ผ๊ณ  ๋ถ€๋ฅด๊ธฐ๋„ ํ•ฉ๋‹ˆ๋‹ค.
    • ๋ชจ๋“  ๋ธŒ๋กœ์ปค์—๋Š” ๊ทธ๋ฃน ์ฝ”๋””๋„คํ‹ฐ์–ด๊ฐ€ ์กด์žฌํ•ฉ๋‹ˆ๋‹ค๋งŒ, Consumer Group ๋ณ„๋กœ ๋‹ด๋‹นํ•˜๋Š” ๋ธŒ๋กœ์ปค๊ฐ€ ๋‹ค๋ฆ…๋‹ˆ๋‹ค. ์ž์„ธํ•œ ๋‚ด์šฉ์€ ๊ทธ๋ฃน ์ฝ”๋””๋„ค์ดํ„ฐ ๋ฌธ๋‹จ์— ๊ธฐ์ˆ ํ•˜์˜€์Šต๋‹ˆ๋‹ค.
    • ์ปจ์Šˆ๋จธ์˜ ์‹ ๊ทœ ๋“ฑ๋ก ๋˜๋Š” ํƒˆํ‡ด, ํ† ํ”ฝ ํŒŒํ‹ฐ์…˜์˜ ์ฆ๊ฐ€์™€ ๊ฐ™์€ ์ƒํ™ฉ์—์„œ โ€œ์ปจ์Šˆ๋จธ ๋ฆฌ๋ฐธ๋Ÿฐ์‹ฑโ€์„ ํŠธ๋ฆฌ๊ฑฐ ํ•ฉ๋‹ˆ๋‹ค.
  • ์ปจ์Šˆ๋จธ ์ฝ”๋””๋„ค์ดํ„ฐ
    • ๊ฐ ์ปจ์Šˆ๋จธ์— ์กด์žฌํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ ์ž…๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ โ€œclient-sideโ€๋ผ๊ณ  ๋ถ€๋ฅด๊ธฐ๋„ ํ•ฉ๋‹ˆ๋‹ค.
    • ๊ทธ๋ฃน ์ฝ”๋””๋„ค์ดํ„ฐ์—๊ฒŒ ์ง€์†์ ์œผ๋กœ โ€œํ•˜ํŠธ๋น„ํŠธ(heartbeat)โ€๋ฅผ ๋ณด๋‚ด๋ฉฐ, ์ปจ์Šˆ๋จธ๊ฐ€ ์ •์ƒ์ ์œผ๋กœ ๋™์ž‘ํ•˜๊ณ  ์žˆ์Œ์„ ์•Œ๋ฆฝ๋‹ˆ๋‹ค.
    • ์ปจ์Šˆ๋จธ ๊ทธ๋ฃน์— ๋“ฑ๋ก๋˜๊ธฐ ์œ„ํ•œ JoinGroupRequest์™€ LeaveGroupRequest๋ฅผ ๊ทธ๋ฃน ์ฝ”๋””๋„ค์ดํ„ฐ์—๊ฒŒ ๋ณด๋ƒ…๋‹ˆ๋‹ค.
    • ๊ทธ๋ฃน ์ฝ”๋””ํ…Œ์ด๋„ˆ๊ฐ€ ํ• ๋‹นํ•œ ํ† ํ”ฝ๊ณผ ํŒŒํ‹ฐ์…˜์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.
  • ์ปจ์Šˆ๋จธ ๊ทธ๋ฃน ๋ฆฌ๋”
    • ์ปจ์Šˆ๋จธ ์ค‘ ํ•˜๋‚˜๊ฐ€ ์ปจ์Šˆ๋จธ๋“ค์„ ์กฐ์œจํ•˜๋Š” ๊ทธ๋ฃน ๋ฆฌ๋”๊ฐ€ ๋ฉ๋‹ˆ๋‹ค.
    • ๋ณดํ†ต ๊ทธ๋ฃน ์ฝ”๋””๋„ค์ดํ„ฐ์™€ ๊ฐ€์žฅ ๋จผ์ € ์ ‘์ด‰ํ•œ ์ปจ์Šˆ๋จธ๊ฐ€ ๊ทธ๋ฃน ๋ฆฌ๋”๊ฐ€ ๋ฉ๋‹ˆ๋‹ค.
    • ๊ทธ๋ฃน ์ฝ”๋””๋„คํ‹ฐ์–ด๊ฐ€ ํŠธ๋ฆฌ๊ฑฐ ํ•œ ๋ฆฌ๋ฐธ๋Ÿฐ์‹ฑ์„ ๊ทธ๋ฃน ๋ฆฌ๋”๊ฐ€ ์ˆ˜ํ–‰ ํ•ฉ๋‹ˆ๋‹ค.

์ปดํฌ๋„ŒํŠธ๋“ค์˜ ์ƒํ˜ธ์ž‘์šฉ

๊ฐ ๊ณผ์ •์„ ๋”ฐ๋ผ๊ฐ€๋ฉฐ ์ปจ์Šˆ๋จธ ๊ทธ๋ฃน์ด ์–ด๋–ป๊ฒŒ ์ฝ”๋””๋„ค์ด์…˜ ๋˜๋Š”์ง€ ์‚ดํŽด๋ด…์‹œ๋‹ค. Confluent์˜ โ€œConsumer Group Protocolโ€๋ผ๋Š” ์˜์ƒ์—์„œ ์ด๋ฅผ ์ž์„ธํžˆ ์„ค๋ช…ํ•ด์ฃผ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

Find Group Coordinator

Confluent: Consumer Group Protocol

์ปจ์Šˆ๋จธ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์€ ์‹คํ–‰ ๋  ๋•Œ, ์นดํ”„์นด ํด๋Ÿฌ์Šคํ„ฐ์— FindCoordinator ์š”์ฒญ์„ ๋ณด๋ƒ…๋‹ˆ๋‹ค. ์ด๋•Œ, group.id๊ฐ€ ์‹ค๋ ค ์š”์ฒญ์ด ์ „์†ก๋˜๋Š”๋ฐ, ์ด ๊ฐ’์€ ํ•ด์‹ฑ๋˜์–ด __consumer_offsets์„ ์ด๋ฃจ๋Š” ๋Œ€์‘๋˜๋Š” ํŒŒํ‹ฐ์…˜๊ณผ ๋งค์นญ ๋ฉ๋‹ˆ๋‹ค.

__consumer_offsets ํ† ํ”ฝ์€ ์นดํ”„์นด ํด๋Ÿฌ์Šคํ„ฐ์— ์—ฐ๊ฒฐ๋œ ์ปจ์Šˆ๋จธ ๊ทธ๋ฃน์˜ ์ •๋ณด๋ฅผ ์ €์žฅํ•˜๋Š” ์‹œ์Šคํ…œ ํ† ํ”ฝ ์ž…๋‹ˆ๋‹ค. ์ปจ์Šˆ๋จธ ๊ทธ๋ฃน์ด ์นดํ”„์นด ํด๋Ÿฌ์Šคํ„ฐ์— FindCoordinator๋ฅผ ์š”์ฒญํ•˜๋ฉด, ํด๋Ÿฌ์Šคํ„ฐ๋ฅผ ๊ตฌ์„ฑํ•˜๋Š” ๋ธŒ๋กœ์ปค ์ค‘ ํ•˜๋‚˜๊ฐ€ ๊ทธ ์ปจ์Šˆ๋จธ ๊ทธ๋ฃน์˜ ์ฝ”๋””๋„ค์ด์…˜์„ ์ „๋‹ด ํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

์–ด๋–ค ๋ธŒ๋กœ์ปค๊ฐ€ ์ปจ์Šˆ๋จธ ๊ทธ๋ฃน์„ ์ „๋‹ดํ• ์ง€๋Š” ์ปจ์Šˆ๋จธ ๊ทธ๋ฃน์˜ group.id์˜ ํ•ด์‹œ๊ฐ’๊ณผ ๊ด€๋ จ ์žˆ์Šต๋‹ˆ๋‹ค. group.id๋Š” ํ•ด์‹ฑ ๋˜์–ด์„œ __consumer_offsets ํ† ํ”ฝ์˜ ํŒŒํ‹ฐ์…˜ ์ค‘ ํ•˜๋‚˜์— ํ• ๋‹น ๋˜์–ด ์ •๋ณด๊ฐ€ ๊ด€๋ฆฌ ๋ฉ๋‹ˆ๋‹ค. ์ด๋•Œ, group.id์— ๋Œ€์‘ ๋˜๋Š” ํŒŒํ‹ฐ์…˜์˜ ๋ฆฌ๋” ํŒŒํ‹ฐ์…˜์„ ๊ด€๋ฆฌํ•˜๋Š” ๋ธŒ๋กœ์ปค๊ฐ€ ํ•ด๋‹น Consumer Group์˜ ์ฝ”๋””๋„ค์ด์…˜์„ ์ „๋‹ด ํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

์ฐธ๊ณ ๋กœ __consumer_offsets ํ† ํ”ฝ์€ ๊ธฐ๋ณธ๊ฐ’์œผ๋กœ 50๊ฐœ์˜ ํŒŒํ‹ฐ์…˜์— Replication 3์œผ๋กœ ๊ตฌ์„ฑ ๋ฉ๋‹ˆ๋‹ค.

๊ฐ ์ปจ์Šˆ๋จธ๋Š” FindCoordinator ์š”์ฒญ์˜ ์‘๋‹ต์œผ๋กœ ์ปจ์Šˆ๋จธ ๊ทธ๋ฃน์„ ๊ด€๋ฆฌํ•  ์ฝ”๋””๋„ค์ดํ„ฐ๊ฐ€ ์žˆ๋Š” ๋ธŒ๋กœ์ปค์˜ endpoint๋ฅผ ์‘๋‹ต์œผ๋กœ ๋Œ๋ ค ๋ฐ›๊ณ , ์•ž์œผ๋กœ ํ•ด๋‹น ๋ธŒ๋กœ์ปค์—๋งŒ ์š”์ฒญ์„ ๋ณด๋ƒ…๋‹ˆ๋‹ค.

Members Join

Confluent: Consumer Group Protocol

๊ฐ ์ปจ์Šˆ๋จธ๋Š” ์ „๋‹ฌ๋ฐ›์€ endpoint๋กœ JoinGroup ์š”์ฒญ์„ ๋ณด๋ƒ…๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์—๋Š” Topic subscription๊ณผ ๊ด€๋ จ๋œ ์ •๋ณด๊ฐ€ ์ „๋‹ฌ๋ฉ๋‹ˆ๋‹ค.

๊ทธ๋ฃน ์ฝ”๋””๋„ค์ดํ„ฐ๋Š” JoinGroup ์š”์ฒญ์„ ๋ณด๋‚ธ ์ปจ์Šˆ๋จธ ์ค‘ ํ•˜๋‚˜๋ฅผ ๊ทธ๋ฃน ๋ฆฌ๋”๋กœ ์„ ์ •ํ•˜์—ฌ ์‘๋‹ต์„ ๋ณด๋ƒ…๋‹ˆ๋‹ค. ๋ณดํ†ต์€ ์ œ์ผ ๋จผ์ € ์š”์ฒญ์„ ๋ณด๋‚ธ ์ปจ์Šˆ๋จธ๊ฐ€ ๊ทธ๋ฃน ๋ฆฌ๋”๊ฐ€ ๋ฉ๋‹ˆ๋‹ค

์‘๋‹ต์—๋Š” ๊ฐ ์ปจ์Šˆ๋จธ์— ํ• ๋‹น๋œ memberId ๊ฐ’์ด ๋‹ด๊ฒจ์„œ ์ „๋‹ฌ๋ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฃน ๋ฆฌ๋”์—๊ฒŒ๋Š” ์ „์ฒด ๋ฉค๋ฒ„ ๋ฆฌ์ŠคํŠธ์™€ subscription๊ณผ ๊ด€๋ จ๋œ ์ •๋ณด๊ฐ€ ์ „๋‹ฌ๋ฉ๋‹ˆ๋‹ค. ์ด๋Š” ๊ทธ๋ฃน ๋ฆฌ๋”๊ฐ€ ์‹ค์ œ ํŒŒํ‹ฐ์…˜ ํ• ๋‹น๊ณผ ๋ฆฌ๋ฐธ๋Ÿฐ์‹ฑ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

Partitions Assigned

Confluent: Consumer Group Protocol

๊ทธ๋ฃน ๋ฆฌ๋”๋Š” JoinGroup ์š”์ฒญ์—์„œ ๋ฉค๋ฒ„ ๋ฆฌ์ŠคํŠธ์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ๋ฐ›์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฃน ๋ฆฌ๋”๋Š” โ€œํŒŒํ‹ฐ์…˜ ํ• ๋‹น(Partition Assign)โ€ ๊ณ„ํš์„ ์ˆ˜๋ฆฝ ํ•ฉ๋‹ˆ๋‹ค. ํ• ๋‹น ์ •์ฑ…์€ ์ปจ์Šˆ๋จธ ๊ทธ๋ฃน์˜ partition.assignment.strategy์— ์ •์˜๋˜์–ด ์žˆ๊ณ , ์•„๋ž˜์™€ ๊ฐ™์€ ์˜ต์…˜๋“ค์ด ์žˆ์Šต๋‹ˆ๋‹ค.

  • RoundRobinAssignor
  • RangeAssignor
  • StickyAssignor

ํŒŒํ‹ฐ์…˜ ์–ด์‹ธ์ธ์— ๋Œ€ํ•œ ๋ถ€๋ถ„์€ ๋ณ„๋„ ํฌ์ŠคํŠธ์—์„œ ์ข€๋” ๋‹ค๋ค„๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

๊ทธ๋ฃน ๋ฆฌ๋”๊ฐ€ ํŒŒํ‹ฐ์…˜ ํ• ๋‹น์„ ๊ณ„ํš์„ ์ˆ˜๋ฆฝํ•˜๋ฉด, ๋ธŒ๋กœ์ปค์—๊ฒŒ SyncGroup ์š”์ฒญ์„ ๋ณด๋‚ด์–ด ํ•ด๋‹น ์ •๋ณด๋ฅผ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค. ์ด ์ •๋ณด๋Š” ๊ฐ ์ปจ์Šˆ๋จธ๊ฐ€ SyncGroup ์š”์ฒญ์„ ํ•  ๋•Œ, ์‘๋‹ต์œผ๋กœ ์ „๋‹ฌ ๋ฉ๋‹ˆ๋‹ค.

Commit Consumption

Confluent: Consumer Group Protocol

์ปจ์Šˆ๋จธ ๊ทธ๋ฃน์€ ํ• ๋‹น ๋ฐ›์€ ํŒŒํ‹ฐ์…˜์˜ ๋ฐ์ดํ„ฐ๋ฅผ Subscription ํ•˜์—ฌ ์ฒ˜๋ฆฌ ํ•œ ํ›„, ์ฒ˜๋ฆฌ ์ •๋ณด๋ฅผ ๊ธฐ๋กํ•˜๊ธฐ ์œ„ํ•ด ๋ธŒ๋กœ์ปค์— CommitOffset ์š”์ฒญ์„ ๋ณด๋ƒ…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋ฉด, ๋ธŒ๋กœ์ปค๋Š” __consumer_offsets ํ† ํ”ฝ์— ์ด ์ •๋ณด๋ฅผ ๋ฐ˜์˜ํ•ฉ๋‹ˆ๋‹ค.

Fetching Offset

Confluent: Consumer Group Protocol

์ปจ์Šˆ๋จธ ๊ทธ๋ฃน์ด ์žฌ์‹œ์ž‘ํ•˜๊ฑฐ๋‚˜ ๋งจ์ฒ˜์Œ์— ์‹คํ–‰๋˜๋Š” ๊ฒฝ์šฐ, ๋ธŒ๋กœ์ปค์—๊ฒŒ์„œ ์ฒ˜๋ฆฌํ•  Offset ์ •๋ณด๋ฅผ ๋ฐ›์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๊ฐ ์ปจ์Šˆ๋จธ๋Š” OffsetFetch ์š”์ฒญ์„ ๋ธŒ๋กœ์ปค์— ๋ณด๋‚ด๊ณ , ๊ธฐ์กด์— ์ฒ˜๋ฆฌํ•˜๋˜ ์ •๋ณด๊ฐ€ ์žˆ๋‹ค๋ฉด ๊ทธ ์ •๋ณด๋ฅผ, ์ฒ˜๋ฆฌํ•˜๋˜ ์ •๋ณด๊ฐ€ ์—†๋‹ค๋ฉด, ์ปจ์Šˆ๋จธ์˜ auto.offset.reset ๊ฐ’์— ๋”ฐ๋ผ Offset ๊ฐ’์„ ๊ฒฐ์ •ํ•ด ์‘๋‹ต์œผ๋กœ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

๋งบ์Œ๋ง

๊ทธ๋™์•ˆ ์นดํ”„์นด๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด์„œ, โ€œ๊ณ ์„ฑ๋Šฅ์ด๊ณ  ๊ณ ๊ฐ€์šฉ์„ฑ์„ ๊ฐ–์ถ”๋Š” ๋ถ„์‚ฐ MQโ€ ์ •๋„๋ผ๊ณ  ์ƒ๊ฐํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ๋ฐ ๋งˆ์Œ๋จน๊ณ  ์นดํ”„์นด๋ฅผ ๊นŠ๊ฒŒ ๊ณต๋ถ€ํ•ด๋ณด๋‹ˆ, ์œ„์˜ ํŠน์„ฑ๋“ค์„ ๊ฐ–์ถ”๊ธฐ ์œ„ํ•ด ํ•„์š”ํ•œ ๊ตฌํ˜„๊ณผ ์ปจ์…‰์ด ํ•œ ๋‘˜์ด ์•„๋‹Œ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค ใ…Žใ„ทใ„ท

๋” ๋งŽ์ด ์•Œ๋ฉด, ๋” ์žฌ๋ฐŒ๋Š” ๊ฒƒ๋“ค์„ ๋งŽ์ด ํ•ด๋ณผ ์ˆ˜ ์žˆ๋Š”๋ฒ•!! ใ…Žใ…Ž ์˜ˆ์ „๋ณด๋‹ค๋Š” ํ˜„์ƒ์—์„œ ์‹ ๊ฒฝ ์“ธ ๊ฒƒ๋“ค์ด ๋งŽ์•„์„œ ์ƒˆ๋กœ์šด ๊ฑธ ๋ฐ”๋‹ฅ๊นŒ์ง€ ์ตํ˜€๋ณผ ์‹œ๊ฐ„์ด ๋ถ€์กฑํ–ˆ๋Š”๋ฐ, ์˜ค๋žœ๋งŒ์— ์ฆ๊ฒ๊ฒŒ ๊ณต๋ถ€ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค ๐Ÿ™‚

References

Categories:

Updated: