KR_Set - somaz94/python-study GitHub Wiki

Python ์ง‘ํ•ฉ(Set) ๊ฐœ๋… ์ •๋ฆฌ


1๏ธโƒฃ ์ง‘ํ•ฉ(Set)์ด๋ž€?

์ง‘ํ•ฉ์€ ์ค‘๋ณต์„ ํ—ˆ์šฉํ•˜์ง€ ์•Š๊ณ  ์ˆœ์„œ๊ฐ€ ์—†๋Š” ์ž๋ฃŒํ˜•์ด๋‹ค. ์ˆ˜ํ•™์˜ ์ง‘ํ•ฉ๊ณผ ๋™์ผํ•œ ๊ฐœ๋…์œผ๋กœ, ๊ต์ง‘ํ•ฉ, ํ•ฉ์ง‘ํ•ฉ, ์ฐจ์ง‘ํ•ฉ ๋“ฑ์˜ ์ง‘ํ•ฉ ์—ฐ์‚ฐ์ด ๊ฐ€๋Šฅํ•˜๋‹ค.

# ์ง‘ํ•ฉ ์ƒ์„ฑ ๋ฐฉ๋ฒ•
empty = set()                         # ๋นˆ ์ง‘ํ•ฉ
numbers = {1, 2, 3}                   # ์ค‘๊ด„ํ˜ธ๋กœ ์ƒ์„ฑ
string_set = set("Hello")             # ๋ฌธ์ž์—ด๋กœ ์ƒ์„ฑ -> {'H', 'e', 'l', 'o'}
list_set = set([1, 2, 2, 3, 3])      # ๋ฆฌ์ŠคํŠธ๋กœ ์ƒ์„ฑ -> {1, 2, 3}

โœ… ํŠน์ง•:

  • ์ค‘๋ณต์„ ํ—ˆ์šฉํ•˜์ง€ ์•Š์Œ
  • ์ˆœ์„œ๊ฐ€ ์—†์Œ (์ธ๋ฑ์‹ฑ ๋ถˆ๊ฐ€)
  • ๋ณ€๊ฒฝ ๊ฐ€๋Šฅ(mutable)ํ•œ ์ž๋ฃŒํ˜•


2๏ธโƒฃ ์ง‘ํ•ฉ ์—ฐ์‚ฐ

s1 = {1, 2, 3, 4, 5}
s2 = {4, 5, 6, 7, 8}

# ๊ต์ง‘ํ•ฉ
print(s1 & s2)                        # {4, 5}
print(s1.intersection(s2))            # {4, 5}

# ํ•ฉ์ง‘ํ•ฉ
print(s1 | s2)                        # {1, 2, 3, 4, 5, 6, 7, 8}
print(s1.union(s2))                   # {1, 2, 3, 4, 5, 6, 7, 8}

# ์ฐจ์ง‘ํ•ฉ
print(s1 - s2)                        # {1, 2, 3}
print(s1.difference(s2))              # {1, 2, 3}

# ๋Œ€์นญ์ฐจ์ง‘ํ•ฉ (ํ•ฉ์ง‘ํ•ฉ - ๊ต์ง‘ํ•ฉ)
print(s1 ^ s2)                        # {1, 2, 3, 6, 7, 8}
print(s1.symmetric_difference(s2))     # {1, 2, 3, 6, 7, 8}

โœ… ์—ฐ์‚ฐ์ž์™€ ๋ฉ”์„œ๋“œ:

  • &, intersection(): ๊ต์ง‘ํ•ฉ
  • |, union(): ํ•ฉ์ง‘ํ•ฉ
  • -, difference(): ์ฐจ์ง‘ํ•ฉ
  • ^, symmetric_difference(): ๋Œ€์นญ์ฐจ์ง‘ํ•ฉ


3๏ธโƒฃ ์ง‘ํ•ฉ ๋ฉ”์„œ๋“œ

# ์š”์†Œ ์ถ”๊ฐ€
s = {1, 2, 3}
s.add(4)                              # ๋‹จ์ผ ์š”์†Œ ์ถ”๊ฐ€
s.update([5, 6, 7])                   # ์—ฌ๋Ÿฌ ์š”์†Œ ์ถ”๊ฐ€

# ์š”์†Œ ์ œ๊ฑฐ
s.remove(4)                           # ์š”์†Œ ์ œ๊ฑฐ (์—†์œผ๋ฉด KeyError)
s.discard(4)                          # ์š”์†Œ ์ œ๊ฑฐ (์—†์–ด๋„ ์—๋Ÿฌ ์—†์Œ)
s.pop()                               # ์ž„์˜์˜ ์š”์†Œ ์ œ๊ฑฐ ํ›„ ๋ฐ˜ํ™˜
s.clear()                             # ๋ชจ๋“  ์š”์†Œ ์ œ๊ฑฐ

โœ… ์ฃผ์š” ๋ฉ”์„œ๋“œ:

  • add(): ์š”์†Œ 1๊ฐœ ์ถ”๊ฐ€
  • update(): ์—ฌ๋Ÿฌ ์š”์†Œ ์ถ”๊ฐ€
  • remove(): ์š”์†Œ ์ œ๊ฑฐ (์—†์œผ๋ฉด ์—๋Ÿฌ)
  • discard(): ์š”์†Œ ์ œ๊ฑฐ (์—†์–ด๋„ ์—๋Ÿฌ ์—†์Œ)
  • pop(): ์ž„์˜์˜ ์š”์†Œ ์ œ๊ฑฐ ํ›„ ๋ฐ˜ํ™˜
  • clear(): ๋ชจ๋“  ์š”์†Œ ์ œ๊ฑฐ


4๏ธโƒฃ ์ง‘ํ•ฉ์˜ ํ™œ์šฉ

# ๋ฆฌ์ŠคํŠธ์˜ ์ค‘๋ณต ์ œ๊ฑฐ
numbers = [1, 2, 2, 3, 3, 3]
unique_numbers = list(set(numbers))    # [1, 2, 3]

# ํฌํ•จ ๊ด€๊ณ„ ํ™•์ธ
s1 = {1, 2, 3}
s2 = {1, 2}
print(s2.issubset(s1))                # True (๋ถ€๋ถ„์ง‘ํ•ฉ)
print(s1.issuperset(s2))              # True (์ƒ์œ„์ง‘ํ•ฉ)

# ๊ต์ง‘ํ•ฉ ์—ฌ๋ถ€ ํ™•์ธ
s3 = {4, 5}
print(s1.isdisjoint(s3))              # True (๊ต์ง‘ํ•ฉ ์—†์Œ)

โœ… ํ™œ์šฉ Tip:

  • ์ค‘๋ณต ์ œ๊ฑฐ๊ฐ€ ํ•„์š”ํ•  ๋•Œ
  • ์ง‘ํ•ฉ ์—ฐ์‚ฐ์ด ํ•„์š”ํ•  ๋•Œ
  • ๋ฉค๋ฒ„์‹ญ ํ…Œ์ŠคํŠธ๊ฐ€ ๋นˆ๋ฒˆํ•  ๋•Œ
  • ๋ฐ์ดํ„ฐ์˜ ์œ ์ผ์„ฑ์ด ์ค‘์š”ํ•  ๋•Œ


5๏ธโƒฃ ์ง‘ํ•ฉ ์ปดํ”„๋ฆฌํ—จ์…˜

์ง‘ํ•ฉ ์ปดํ”„๋ฆฌํ—จ์…˜(Set Comprehension)์€ ๋ฆฌ์ŠคํŠธ ์ปดํ”„๋ฆฌํ—จ์…˜๊ณผ ์œ ์‚ฌํ•˜๊ฒŒ ๊ฐ„๊ฒฐํ•œ ๋ฐฉ๋ฒ•์œผ๋กœ ์ง‘ํ•ฉ์„ ์ƒ์„ฑํ•˜๋Š” ๊ธฐ๋Šฅ์ด๋‹ค.

# ๊ธฐ๋ณธ ํ˜•์‹
squares = {x**2 for x in range(10)}
# {0, 1, 4, 9, 16, 25, 36, 49, 64, 81}

# ์กฐ๊ฑด์‹ ์ถ”๊ฐ€
even_squares = {x**2 for x in range(10) if x % 2 == 0}
# {0, 4, 16, 36, 64}

# ๋‹ค์ค‘ ์กฐ๊ฑด
mixed = {x for x in range(20) if x % 2 == 0 if x % 3 == 0}
# {0, 6, 12, 18} (2์™€ 3์˜ ๊ณต๋ฐฐ์ˆ˜)

# if-else ์‚ฌ์šฉ
categorized = {x if x % 2 == 0 else -x for x in range(10)}
# {0, -1, 2, -3, 4, -5, 6, -7, 8, -9}

# ๋ฌธ์ž์—ด ์ฒ˜๋ฆฌ
words = ['hello', 'world', 'python', 'programming']
lengths = {len(word) for word in words}
# {5, 6, 11} (์ค‘๋ณต ์ œ๊ฑฐ๋œ ๋ฌธ์ž์—ด ๊ธธ์ด)

โœ… ์ง‘ํ•ฉ ์ปดํ”„๋ฆฌํ—จ์…˜ Tip:

  • ์ค‘๋ณต์ด ์ž๋™์œผ๋กœ ์ œ๊ฑฐ๋˜๋ฏ€๋กœ ์œ ์ผํ•œ ๊ฐ’๋งŒ ์ถ”์ถœํ•  ๋•Œ ์œ ์šฉํ•˜๋‹ค
  • ์ง‘ํ•ฉ์€ ์ˆœ์„œ๊ฐ€ ์—†๊ธฐ ๋•Œ๋ฌธ์— ๊ฒฐ๊ณผ์˜ ์ˆœ์„œ๋Š” ๋ณด์žฅ๋˜์ง€ ์•Š๋Š”๋‹ค
  • ๋ฆฌ์ŠคํŠธ ์ปดํ”„๋ฆฌํ—จ์…˜๋ณด๋‹ค ๋ฉ”๋ชจ๋ฆฌ ํšจ์œจ์ด ์ข‹์„ ์ˆ˜ ์žˆ๋‹ค (์ค‘๋ณต ์ œ๊ฑฐ ์‹œ)
  • ๋ณต์žกํ•œ ์—ฐ์‚ฐ์˜ ๊ฒฝ์šฐ ๊ฐ€๋…์„ฑ์„ ์œ„ํ•ด ์ผ๋ฐ˜ ๋ฐ˜๋ณต๋ฌธ ์‚ฌ์šฉ์„ ๊ณ ๋ คํ•œ๋‹ค


6๏ธโƒฃ ๋ถˆ๋ณ€ ์ง‘ํ•ฉ(Frozen Set)

ํŒŒ์ด์ฌ์€ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์—†๋Š”(immutable) ์ง‘ํ•ฉ์ธ frozenset์„ ์ œ๊ณตํ•œ๋‹ค.

# frozenset ์ƒ์„ฑ
immutable = frozenset([1, 2, 3, 4])
print(immutable)  # frozenset({1, 2, 3, 4})

# ์ง‘ํ•ฉ ์—ฐ์‚ฐ์€ ๊ฐ€๋Šฅ
normal_set = {3, 4, 5, 6}
print(immutable & normal_set)  # frozenset({3, 4})
print(immutable | normal_set)  # frozenset({1, 2, 3, 4, 5, 6})

# ๋ณ€๊ฒฝ ์‹œ๋„๋Š” ์˜ค๋ฅ˜ ๋ฐœ์ƒ
try:
    immutable.add(5)  # ์˜ค๋ฅ˜: 'frozenset' object has no attribute 'add'
except AttributeError as e:
    print(e)

# ๋”•์…”๋„ˆ๋ฆฌ ํ‚ค๋‚˜ ์ง‘ํ•ฉ ์š”์†Œ๋กœ ์‚ฌ์šฉ ๊ฐ€๋Šฅ
set_of_sets = {frozenset({1, 2}), frozenset({3, 4})}
dict_with_sets = {frozenset({1, 2}): 'set1', frozenset({3, 4}): 'set2'}

โœ… frozenset ํŠน์ง•:

  • ํ•œ๋ฒˆ ์ƒ์„ฑ๋˜๋ฉด ๋ณ€๊ฒฝ ๋ถˆ๊ฐ€๋Šฅ(immutable)ํ•˜๋‹ค
  • ์ง‘ํ•ฉ ์—ฐ์‚ฐ(ํ•ฉ์ง‘ํ•ฉ, ๊ต์ง‘ํ•ฉ ๋“ฑ)์€ ๊ฐ€๋Šฅํ•˜๋‹ค
  • ํ•ด์‹œ ๊ฐ€๋Šฅ(hashable)ํ•˜์—ฌ ๋‹ค๋ฅธ ์ง‘ํ•ฉ์˜ ์š”์†Œ๋‚˜ ๋”•์…”๋„ˆ๋ฆฌ์˜ ํ‚ค๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค
  • ์ฐธ์กฐ์˜ ์•ˆ์ •์„ฑ์ด ํ•„์š”ํ•  ๋•Œ ์‚ฌ์šฉํ•œ๋‹ค


7๏ธโƒฃ ์ง‘ํ•ฉ์˜ ์„ฑ๋Šฅ ํŠน์„ฑ

์ง‘ํ•ฉ์€ ํ•ด์‹œ ํ…Œ์ด๋ธ”์„ ๊ธฐ๋ฐ˜์œผ๋กœ ๊ตฌํ˜„๋˜์–ด ์žˆ์–ด, ๋ฉค๋ฒ„์‹ญ ๊ฒ€์‚ฌ์™€ ์ค‘๋ณต ์ œ๊ฑฐ์— ๋งค์šฐ ํšจ์œจ์ ์ด๋‹ค.

import timeit
import random

# ๋ฐ์ดํ„ฐ ์ค€๋น„
size = 10000
data = list(range(size))
random.shuffle(data)
lookup_value = size - 1

# ๋ฆฌ์ŠคํŠธ vs ์ง‘ํ•ฉ ๋ฉค๋ฒ„์‹ญ ๊ฒ€์‚ฌ ์„ฑ๋Šฅ ๋น„๊ต
list_time = timeit.timeit(
    lambda: lookup_value in data,
    number=1000
)

set_data = set(data)
set_time = timeit.timeit(
    lambda: lookup_value in set_data,
    number=1000
)

print(f"๋ฆฌ์ŠคํŠธ ๊ฒ€์ƒ‰ ์‹œ๊ฐ„: {list_time:.6f}์ดˆ")
print(f"์ง‘ํ•ฉ ๊ฒ€์ƒ‰ ์‹œ๊ฐ„: {set_time:.6f}์ดˆ")
print(f"์ง‘ํ•ฉ์ด ์•ฝ {list_time/set_time:.1f}๋ฐฐ ๋น ๋ฆ„")

# ๊ต์ง‘ํ•ฉ ๊ณ„์‚ฐ ์„ฑ๋Šฅ (naive vs set)
def naive_intersection(list1, list2):
    return [item for item in list1 if item in list2]

list1 = random.sample(range(size), size//2)
list2 = random.sample(range(size), size//2)

naive_time = timeit.timeit(
    lambda: naive_intersection(list1, list2),
    number=10
)

set_intersection_time = timeit.timeit(
    lambda: set(list1) & set(list2),
    number=10
)

print(f"์ผ๋ฐ˜ ๊ต์ง‘ํ•ฉ ๊ตฌํ˜„: {naive_time:.6f}์ดˆ")
print(f"์ง‘ํ•ฉ ๊ต์ง‘ํ•ฉ ์—ฐ์‚ฐ: {set_intersection_time:.6f}์ดˆ")
print(f"์ง‘ํ•ฉ์ด ์•ฝ {naive_time/set_intersection_time:.1f}๋ฐฐ ๋น ๋ฆ„")

์ง‘ํ•ฉ ์—ฐ์‚ฐ์˜ ์‹œ๊ฐ„ ๋ณต์žก๋„๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค:


์—ฐ์‚ฐ ํ‰๊ท  ์‹œ๊ฐ„ ๋ณต์žก๋„ ์ตœ์•… ์‹œ๊ฐ„ ๋ณต์žก๋„
์š”์†Œ ์ถ”๊ฐ€ (add) O(1) O(n)
์š”์†Œ ์ œ๊ฑฐ (remove, discard) O(1) O(n)
์š”์†Œ ํฌํ•จ ํ™•์ธ (in) O(1) O(n)
ํ•ฉ์ง‘ํ•ฉ, ๊ต์ง‘ํ•ฉ, ์ฐจ์ง‘ํ•ฉ O(len(s1) + len(s2)) O(len(s1) * len(s2))
๋ณต์‚ฌ (copy) O(n) O(n)

โœ… ์„ฑ๋Šฅ ๊ด€๋ จ Tip:

  • ๋ฉค๋ฒ„์‹ญ ๊ฒ€์‚ฌ๊ฐ€ ๋นˆ๋ฒˆํ•  ๋•Œ๋Š” ๋ฆฌ์ŠคํŠธ๋ณด๋‹ค ์ง‘ํ•ฉ ์‚ฌ์šฉ์ด ํšจ์œจ์ ์ด๋‹ค
  • ์ง‘ํ•ฉ์˜ ์š”์†Œ๋Š” ํ•ด์‹œ ๊ฐ€๋Šฅ(hashable)ํ•ด์•ผ ํ•˜๋ฏ€๋กœ ๋ถˆ๋ณ€ ๊ฐ์ฒด๋งŒ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•˜๋‹ค
  • ๋Œ€์šฉ๋Ÿ‰ ๋ฐ์ดํ„ฐ์—์„œ ์ค‘๋ณต ์ œ๊ฑฐ ์‹œ ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰์ด ํฌ๊ฒŒ ์ค„์–ด๋“ค ์ˆ˜ ์žˆ๋‹ค
  • ์ง‘ํ•ฉ ์—ฐ์‚ฐ์€ ์ผ๋ฐ˜์ ์œผ๋กœ O(1)์ด์ง€๋งŒ, ํ•ด์‹œ ์ถฉ๋Œ์ด ๋งŽ์„ ๊ฒฝ์šฐ ์„ฑ๋Šฅ์ด ์ €ํ•˜๋  ์ˆ˜ ์žˆ๋‹ค


8๏ธโƒฃ ๊ณ ๊ธ‰ ์ง‘ํ•ฉ ํ™œ์šฉ ์˜ˆ์ œ

1. ์ค‘๋ณต ์ œ๊ฑฐ ๋ฐ ํ•„ํ„ฐ๋ง

# ๋‹จ์–ด ๋ชฉ๋ก์—์„œ ์ค‘๋ณต๊ณผ ํŠน์ • ์กฐ๊ฑด ํ•„ํ„ฐ๋ง
words = ['apple', 'banana', 'apple', 'cherry', 'date', 'banana', 'elderberry']

# ์ค‘๋ณต ์ œ๊ฑฐ ๋ฐ 5๊ธ€์ž ์ดˆ๊ณผ ๋‹จ์–ด ํ•„ํ„ฐ๋ง
filtered_words = {word for word in words if len(word) > 5}
print(filtered_words)  # {'banana', 'cherry', 'elderberry'}

# ๋‹ค์Œ๊ณผ ๊ฐ™์ด๋„ ํ™œ์šฉ ๊ฐ€๋Šฅ
unique_sorted_words = sorted(set(words))
print(unique_sorted_words)  # ['apple', 'banana', 'cherry', 'date', 'elderberry']

2. ๋ฐ์ดํ„ฐ ๋ถ„์„ ๋ฐ ์ง‘๊ณ„

# ํ•™์ƒ๋“ค์˜ ์ˆ˜๊ฐ• ๊ณผ๋ชฉ ๋ถ„์„
student_courses = {
    'Alice': {'math', 'physics', 'chemistry'},
    'Bob': {'math', 'physics', 'biology'},
    'Charlie': {'physics', 'biology', 'computer science'},
    'David': {'math', 'computer science'}
}

# ๋ชจ๋“  ๊ณผ๋ชฉ ๋ชฉ๋ก
all_courses = set()
for courses in student_courses.values():
    all_courses.update(courses)
print(f"๊ฐœ์„ค๋œ ๋ชจ๋“  ๊ณผ๋ชฉ: {all_courses}")

# ๊ฐ€์žฅ ์ธ๊ธฐ ์žˆ๋Š” ๊ณผ๋ชฉ ์ฐพ๊ธฐ
course_count = {}
for courses in student_courses.values():
    for course in courses:
        course_count[course] = course_count.get(course, 0) + 1

most_popular = max(course_count, key=course_count.get)
print(f"๊ฐ€์žฅ ์ธ๊ธฐ ์žˆ๋Š” ๊ณผ๋ชฉ: {most_popular} ({course_count[most_popular]}๋ช… ์ˆ˜๊ฐ•)")

# ๋ชจ๋“  ํ•™์ƒ์ด ๋“ฃ๋Š” ๊ณตํ†ต ๊ณผ๋ชฉ
common_courses = set.intersection(*student_courses.values())
print(f"๋ชจ๋“  ํ•™์ƒ์ด ์ˆ˜๊ฐ•ํ•˜๋Š” ๊ณผ๋ชฉ: {common_courses if common_courses else '์—†์Œ'}")

# ์ ์–ด๋„ ํ•œ ํ•™์ƒ์ด ๋“ฃ๋Š” ๊ณผ๋ชฉ
any_courses = set.union(*student_courses.values())
print(f"์ ์–ด๋„ ํ•œ ํ•™์ƒ์ด ์ˆ˜๊ฐ•ํ•˜๋Š” ๊ณผ๋ชฉ: {any_courses}")

3. ์•Œ๊ณ ๋ฆฌ์ฆ˜ ๋ฌธ์ œ ํ•ด๊ฒฐ

# Two Sum ๋ฌธ์ œ: ๋ฐฐ์—ด์—์„œ ํ•ฉ์ด target์ธ ๋‘ ์ˆ˜์˜ ์ธ๋ฑ์Šค ์ฐพ๊ธฐ
def two_sum(nums, target):
    seen = set()
    for num in nums:
        complement = target - num
        if complement in seen:
            return [num, complement]
        seen.add(num)
    return None

print(two_sum([2, 7, 11, 15], 9))  # [7, 2]

# ๋ฌธ์ž์—ด์—์„œ ์ค‘๋ณต ์—†๋Š” ๊ฐ€์žฅ ๊ธด ๋ถ€๋ถ„ ๋ฌธ์ž์—ด ์ฐพ๊ธฐ
def longest_substring_without_repeating(s):
    char_set = set()
    max_length = 0
    i = 0
    
    for j in range(len(s)):
        while s[j] in char_set:
            char_set.remove(s[i])
            i += 1
        char_set.add(s[j])
        max_length = max(max_length, j - i + 1)
    
    return max_length

print(longest_substring_without_repeating("abcabcbb"))  # 3 (abc)
print(longest_substring_without_repeating("bbbbb"))     # 1 (b)
print(longest_substring_without_repeating("pwwkew"))    # 3 (wke)

4. ์ง‘ํ•ฉ์„ ์ด์šฉํ•œ ๊ทธ๋ž˜ํ”„ ์•Œ๊ณ ๋ฆฌ์ฆ˜

# ๊ทธ๋ž˜ํ”„์—์„œ ์—ฐ๊ฒฐ ์š”์†Œ ์ฐพ๊ธฐ
def connected_components(graph):
    visited = set()
    components = []
    
    def dfs(node, component):
        visited.add(node)
        component.add(node)
        for neighbor in graph.get(node, []):
            if neighbor not in visited:
                dfs(neighbor, component)
    
    for node in graph:
        if node not in visited:
            component = set()
            dfs(node, component)
            components.append(component)
    
    return components

# ์ธ์ ‘ ๋ฆฌ์ŠคํŠธ๋กœ ํ‘œํ˜„๋œ ๊ทธ๋ž˜ํ”„
graph = {
    'A': ['B', 'C'],
    'B': ['A', 'D', 'E'],
    'C': ['A', 'F'],
    'D': ['B'],
    'E': ['B', 'F'],
    'F': ['C', 'E'],
    'G': ['H'],
    'H': ['G']
}

components = connected_components(graph)
print(f"์—ฐ๊ฒฐ ์š”์†Œ์˜ ๊ฐœ์ˆ˜: {len(components)}")
for i, component in enumerate(components, 1):
    print(f"์—ฐ๊ฒฐ ์š”์†Œ {i}: {component}")

โœ… ํ™œ์šฉ ์‚ฌ๋ก€:

  • ์ค‘๋ณต ์ œ๊ฑฐ ๋ฐ ๊ณ ์œ  ๊ฐ’ ์ถ”์ถœ
  • ์ง‘ํ•ฉ ์—ฐ์‚ฐ์„ ์ด์šฉํ•œ ๋ฐ์ดํ„ฐ ๋ถ„์„
  • ํšจ์œจ์ ์ธ ๊ฒ€์ƒ‰ ๋ฐ ์กฐํšŒ
  • ๊ทธ๋ž˜ํ”„ ์•Œ๊ณ ๋ฆฌ์ฆ˜ ๊ตฌํ˜„
  • ์บ์‹ฑ ๋ฐ ๋ฉ”๋ชจ๋ฆฌ ์ตœ์ ํ™”
  • ๋ฐ์ดํ„ฐ ๋ฌด๊ฒฐ์„ฑ ๊ฒ€์ฆ


โš ๏ธ **GitHub.com Fallback** โš ๏ธ