๐ python ๊ธฐ๋ณธ ๊ฐ๋
1. ํ์ด์ฌ ์๋ฃ๊ตฌ์กฐ (Data Structures)โ
์๋ฃ๊ตฌ์กฐ๋ ์ฌ๋ฌ ๋ฐ์ดํฐ๋ฅผ ํจ์จ์ ์ผ๋ก ์ ์ฅํ๊ณ ๊ด๋ฆฌํ๊ธฐ ์ํ ๋ฐฉ๋ฒ์ ๋๋ค. ํ์ด์ฌ์ ๋ค์ํ ๋ด์ฅ ์๋ฃ๊ตฌ์กฐ๋ฅผ ์ ๊ณตํฉ๋๋ค.
- ๋ฆฌ์คํธ (List -
list)- ํน์ง: ์์๊ฐ ์๊ณ , ๋ณ๊ฒฝ ๊ฐ๋ฅํ(mutable) ์ํ์ค. ์ค๋ณต๋ ๊ฐ์ ๊ฐ์ง ์ ์์ต๋๋ค. ์ธ๋ฑ์ค๋ฅผ ํตํด ์์์ ์ ๊ทผํฉ๋๋ค.
- ๋์: ์์ ์ถ๊ฐ(
append,insert), ์ญ์ (remove,pop), ๋ณ๊ฒฝ์ด ์์ ๋กญ์ต๋๋ค. ๋ด๋ถ์ ์ผ๋ก ๋์ ๋ฐฐ์ด๋ก ๊ตฌํ๋์ด ํฌ๊ธฐ๊ฐ ๋ณํ ์ ์์ต๋๋ค. - ์ฉ๋: ์์๊ฐ ์ค์ํ๊ณ ๋ฐ์ดํฐ๊ฐ ๋ณ๊ฒฝ๋ ์ ์๋ ๊ฒฝ์ฐ์ ์ฃผ๋ก ์ฌ์ฉ๋ฉ๋๋ค.
- ํํ (Tuple -
tuple)- ํน์ง: ์์๊ฐ ์์ง๋ง, ๋ณ๊ฒฝ ๋ถ๊ฐ๋ฅํ(immutable) ์ํ์ค. ์ค๋ณต๋ ๊ฐ์ ๊ฐ์ง ์ ์์ต๋๋ค. ์ธ๋ฑ์ค๋ฅผ ํตํด ์์์ ์ ๊ทผํฉ๋๋ค.
- ๋์: ์์ฑ ํ์๋ ์์๋ฅผ ์ถ๊ฐ, ์ญ์ , ๋ณ๊ฒฝํ ์ ์์ต๋๋ค. ๋ฆฌ์คํธ๋ณด๋ค ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์ ๊ฒ ์ฌ์ฉํ๊ณ ๋ฐ๋ณต ์๋๊ฐ ์ฝ๊ฐ ๋ ๋น ๋ฅผ ์ ์์ต๋๋ค.
- ์ฉ๋: ๋ณ๊ฒฝ๋์ง ์์์ผ ํ๋ ๋ฐ์ดํฐ ๋ฌถ์ (์: ํจ์์ ๋ฐํ ๊ฐ, ๋์ ๋๋ฆฌ ํค์ ์ผ๋ถ)์ ์ฌ์ฉ๋ฉ๋๋ค.
- ๋์
๋๋ฆฌ (Dictionary -
dict)- ํน์ง: ํค(Key)์ ๊ฐ(Value)์ ์์ผ๋ก ์ด๋ฃจ์ด์ง ์ปฌ๋ ์ . ํค๋ ๊ณ ์ ํ๊ณ ๋ณ๊ฒฝ ๋ถ๊ฐ๋ฅํ(hashable) ๊ฐ์ด์ด์ผ ํฉ๋๋ค (์ฃผ๋ก ๋ฌธ์์ด, ์ซ์, ํํ ์ฌ์ฉ). ๊ฐ์ ์ด๋ค ํ์ ์ด๋ ๊ฐ๋ฅํฉ๋๋ค. Python 3.7+ ๋ถํฐ๋ ์ ๋ ฅ ์์๊ฐ ์ ์ง๋ฉ๋๋ค.
- ๋์: ํค๋ฅผ ํตํด ๊ฐ์ ๋งค์ฐ ๋น ๋ฅด๊ฒ ์ ๊ทผ, ์ถ๊ฐ, ์์ , ์ญ์ ํ ์ ์์ต๋๋ค (ํด์ ํ ์ด๋ธ ๊ธฐ๋ฐ).
- ์ฉ๋: ํค๋ฅผ ํตํด ๋ฐ์ดํฐ๋ฅผ ๋น ๋ฅด๊ฒ ์ฐพ์์ผ ํ๋ ๊ฒฝ์ฐ, ๋ฐ์ดํฐ ๊ฐ์ ์ฐ๊ด ๊ด๊ณ๋ฅผ ํํํ ๋ ์ ์ฉํฉ๋๋ค.
- ์ธํธ (Set -
set)- ํน์ง: ์์๊ฐ ์๊ณ , ์ค๋ณต๋ ๊ฐ์ ํ์ฉํ์ง ์๋ ์ปฌ๋ ์ . ๋ณ๊ฒฝ ๊ฐ๋ฅํ(mutable) ์๋ฃ๊ตฌ์กฐ์ ๋๋ค.
- ๋์: ์์์ ์กด์ฌ ์ฌ๋ถ๋ฅผ ๋งค์ฐ ๋น ๋ฅด๊ฒ ํ์ธํ ์ ์์ต๋๋ค. ํฉ์งํฉ(
|), ๊ต์งํฉ(&), ์ฐจ์งํฉ(-) ๋ฑ ์งํฉ ์ฐ์ฐ์ ์ง์ํฉ๋๋ค. - ์ฉ๋: ์ค๋ณต ์ ๊ฑฐ, ๋ฉค๋ฒ์ญ ํ ์คํธ, ์งํฉ ์ฐ์ฐ์ ์ฃผ๋ก ์ฌ์ฉ๋ฉ๋๋ค.
- ํ๋ก์ฆ์
(Frozenset -
frozenset)- ํน์ง: ์ธํธ์ ์ ์ฌํ์ง๋ง ๋ณ๊ฒฝ ๋ถ๊ฐ๋ฅํ(immutable) ๋ฒ์ ์ ๋๋ค.
- ๋์: ์์ฑ ํ์ ๋ ์์๋ฅผ ์ถ๊ฐํ๊ฑฐ๋ ์ญ์ ํ ์ ์์ต๋๋ค. ๋ณ๊ฒฝ ๋ถ๊ฐ๋ฅํ๋ฏ๋ก ๋์ ๋๋ฆฌ์ ํค๋ ๋ค๋ฅธ ์ธํธ์ ์์๋ก ์ฌ์ฉ๋ ์ ์์ต๋๋ค.
- ์ฉ๋: ๋ณ๊ฒฝ๋์ง ์๋ ์งํฉ์ด ํ์ํ๊ฑฐ๋, ๋์ ๋๋ฆฌ ํค ๋ฑ์ผ๋ก ์ฌ์ฉํด์ผ ํ ๋ ์ฐ์ ๋๋ค.
์ด ์ธ์๋ collections ๋ชจ๋์์ deque, Counter, defaultdict ๋ฑ ๋ ์ ๋ฌธ์ ์ธ ์๋ฃ๊ตฌ์กฐ๋ฅผ ์ ๊ณตํฉ๋๋ค.
2. ์ ๋๋ ์ดํฐ (Generators)โ
์ ๋๋ ์ดํฐ๋ ์ดํฐ๋ ์ดํฐ(iterator)๋ฅผ ์์ฑํ๋ ๊ฐ๋จํ๊ณ ๊ฐ๋ ฅํ ๋ฐฉ๋ฒ์ ๋๋ค. ๋ชจ๋ ๊ฐ์ ๋ฉ๋ชจ๋ฆฌ์ ์ ์ฅํ๋ ๋์ , ํ์ํ ๋๋ง๋ค ๊ฐ์ ํ๋์ฉ ์์ฑ(yield)ํฉ๋๋ค.
- ๋์ ๋ฐฉ์:
- ํจ์ ๋ด์์
yieldํค์๋๋ฅผ ์ฌ์ฉํ๋ฉด ํด๋น ํจ์๋ ์ ๋๋ ์ดํฐ ํจ์๊ฐ ๋ฉ๋๋ค. - ์ ๋๋ ์ดํฐ ํจ์๋ฅผ ํธ์ถํ๋ฉด ์ฆ์ ์คํ๋์ง ์๊ณ ์ ๋๋ ์ดํฐ ๊ฐ์ฒด(์ดํฐ๋ ์ดํฐ)๋ฅผ ๋ฐํํฉ๋๋ค.
next()ํจ์๋ฅผ ํธ์ถํ๊ฑฐ๋for๋ฃจํ ๋ฑ์์ ์ ๋๋ ์ดํฐ ๊ฐ์ฒด๋ฅผ ์ฌ์ฉํ๋ฉด ํจ์ ๋ด๋ถ ์ฝ๋๊ฐ ์คํ๋๋ค๊ฐyield๋ฌธ์ ๋ง๋ฉ๋๋ค.yield๋ ๊ฐ์ ๋ฐํํ๊ณ ํจ์์ ์คํ์ ์ผ์ ์ค์งํฉ๋๋ค. ํจ์์ ๋ชจ๋ ์ํ(์ง์ญ ๋ณ์ ๋ฑ)๋ ์ ์ง๋ฉ๋๋ค.- ๋ค์
next()๊ฐ ํธ์ถ๋๋ฉด ์ค์ง๋ ์ง์ ๋ค์๋ถํฐ ์คํ์ ์ฌ๊ฐํฉ๋๋ค. - ํจ์ ์คํ์ด ๋๋๊ฑฐ๋
return๋ฌธ์ ๋ง๋๋ฉดStopIteration์์ธ๊ฐ ๋ฐ์ํฉ๋๋ค.
- ํจ์ ๋ด์์
- ํน์ง ๋ฐ ์ฅ์ :
- ๋ฉ๋ชจ๋ฆฌ ํจ์จ์ฑ: ๋๋์ ๋ฐ์ดํฐ๋ฅผ ์ฒ๋ฆฌํ ๋ ๋ชจ๋ ๊ฐ์ ๋ฏธ๋ฆฌ ์์ฑํ์ฌ ๋ฉ๋ชจ๋ฆฌ์ ์ ์ฅํ ํ์๊ฐ ์์ต๋๋ค. ํ์ํ ์์ ์ ํ๋์ฉ ์์ฑํ๋ฏ๋ก ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋์ด ๋งค์ฐ ์ ์ต๋๋ค.
- ์ง์ฐ ํ๊ฐ (Lazy Evaluation): ์ค์ ๊ฐ์ด ํ์ํ ์์ ๊น์ง ๊ณ์ฐ์ ๋ฏธ๋ฃน๋๋ค.
- ๊ฐ๊ฒฐํ ์ฝ๋: ๋ณต์กํ ์ดํฐ๋ ์ดํฐ ํด๋์ค(
__iter__,__next__๊ตฌํ)๋ฅผ ์์ฑํ๋ ๊ฒ๋ณด๋ค ํจ์ฌ ๊ฐ๊ฒฐํ๊ฒ ์ดํฐ๋ ์ดํฐ๋ฅผ ๋ง๋ค ์ ์์ต๋๋ค. - ๋ฌดํ ์ํ์ค ์์ฑ ๊ฐ๋ฅ: ๋ฉ๋ชจ๋ฆฌ ์ ์ฝ ์์ด ๋ฌดํํ ๊ฐ์ ์์ฑํ๋ ์ํ์ค๋ฅผ ๋ง๋ค ์ ์์ต๋๋ค.
def count_up_to(n):
i = 1
while i <= n:
yield i # ๊ฐ์ ๋ฐํํ๊ณ ์ฌ๊ธฐ์ ์ ์ ๋ฉ์ถค
i += 1
# ์ ๋๋ ์ดํฐ ๊ฐ์ฒด ์์ฑ
counter = count_up_to(3)
print(next(counter)) # ์ถ๋ ฅ: 1 // ์ฌ๊ธฐ์ ์ ์ ๋ฉ์ถค
# ์ฌ๊ธฐ์ ์๋ฌด๋ฐ ์ง์ ํด๋ 2,3์ด ์ถ๋ ฅ๋์ง ์์
print(next(counter)) # ์ถ๋ ฅ: 2
# ์ฌ๊ธฐ์ ์๋ฌด๋ฐ ์ง์ ํด๋ 3์ด ์ถ๋ ฅ๋์ง ์์
print(next(counter)) # ์ถ๋ ฅ: 3 ์ด๋ ๊ฒ ์ง์ ํธ์ถ์ ํด์ผ 3์ด ์ถ๋ ฅ๋จ
# ๊ทธ๋ฌ๋๊น ๋๋์ ๋ฐ์ดํฐ๋ฅผ ์ฒ๋ฆฌํ ๋ ์ฌ์ฉํ๋ ๊ฑฐ๊ณ , ๋ฉ๋ชจ๋ฆฌ ํจ์จ์ ์ผ๋ก ์ฌ์ฉํ ์ ์์,
# ๋น์ฐํ ์ค์ ๊ฐ์ด ํ์ํ ์์ ๊น์ง ๊ณ์ฐ์ ๋ฏธ๋ฃจ๋ ๊ฑฐ๊ณ , ๋ฌดํ ์ํ์ค ์์ฑ๋ ๊ฐ๋ฅํจ(์ถ๋ ฅํ์ง ์์ผ๋๊น)
# ์ฌ์ฉ๋ ๋งค์ฐ ๊ฐ๋จํ๊ณ ์ฌ์
# print(next(counter)) # ์ฌ๊ธฐ์ StopIteration ์์ธ ๋ฐ์
์ค๋ฌด์์ ์ ๋๋ ์ดํฐ ์ฌ์ฉ ์์โ
from typing import AsyncGenerator
from sqlalchemy.ext.asyncio import AsyncSession, async_sessionmaker, create_async_engine
from .config import settings
engine = create_async_engine(settings.DATABASE_URL, echo=True, future=True)
AsyncSessionLocal = async_sessionmaker(engine, class_=AsyncSession, expire_on_commit=False)
async def get_session() -> AsyncGenerator[AsyncSession, None]:
async with AsyncSessionLocal() as session:
try:
yield session
except Exception:
await session.rollback()
raise
์ธ์ ์ ๊ณต (Yield):
yield session: get_session ํจ์์ ์คํ์ด ์ฌ๊ธฐ์ ์ผ์ ์ค์ง๋ฉ๋๋ค. ๊ทธ๋ฆฌ๊ณ async with๋ฅผ ํตํด ์ป์ session ๊ฐ์ฒด๊ฐ get_session ํจ์๋ฅผ ํธ์ถํ ์ชฝ(์: ์น ์์ฒญ ํธ๋ค๋ฌ)์ผ๋ก **๋ฐํ(์ ๊ณต)**๋ฉ๋๋ค. ํธ์ถํ ์ชฝ์์๋ ์ด session ๊ฐ์ฒด๋ฅผ ์ฌ์ฉํ์ฌ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฟผ๋ฆฌ, ์ถ๊ฐ, ์์ , ์ญ์ ๋ฑ์ ์์ ์ ์ํํฉ๋๋ค.
3. ๋ฐ์ฝ๋ ์ดํฐ (Decorators)โ
๋ฐ์ฝ๋ ์ดํฐ๋ ๊ธฐ์กด ํจ์๋ ๋ฉ์๋์ ์ฝ๋๋ฅผ ์ง์ ์์ ํ์ง ์์ผ๋ฉด์, ์ถ๊ฐ ๊ธฐ๋ฅ์ ๋ง๋ถ์ด๊ฑฐ๋ ์์ ํ ์ ์๊ฒ ํด์ฃผ๋ ๊ฐ๋ ฅํ ๊ธฐ๋ฅ์
๋๋ค. @ ๊ธฐํธ๋ฅผ ์ฌ์ฉํ์ฌ ์ ์ฉํฉ๋๋ค.
- ๋์ ๋ฐฉ์:
- ๋ฐ์ฝ๋ ์ดํฐ๋ ํจ์๋ฅผ ์ธ์๋ก ๋ฐ์์, ์์ ๋ ๋๋ ์๋ก์ด ํจ์๋ฅผ ๋ฐํํ๋ ํจ ์ (๊ณ ์ฐจ ํจ์)์ ๋๋ค.
@my_decorator๋ฅผ ํจ์func์์ ์ฐ๋ฉด, ํ์ด์ฌ์ ๋ด๋ถ์ ์ผ๋กfunc = my_decorator(func)์ ๊ฐ์ด ์ฒ๋ฆฌํฉ๋๋ค.- ์ฆ, ์๋ ํจ์
func๊ฐ ๋ฐ์ฝ๋ ์ดํฐ ํจ์my_decorator์ ์ ๋ฌ๋๊ณ , - ๊ทธ ๋ฐํ๊ฐ(์ฃผ๋ก ๋ด๋ถ wrapper ํจ์)์ด ๋ค์
func๋ผ๋ ์ด๋ฆ์ ํ ๋น๋ฉ๋๋ค.
- ์ฆ, ์๋ ํจ์
- ์ดํ
func()๋ฅผ ํธ์ถํ๋ฉด ์ค์ ๋ก๋ ๋ฐ์ฝ๋ ์ดํฐ๊ฐ ๋ฐํํ ํจ์๊ฐ ์คํ๋ฉ๋๋ค.- ์ด ๋ฐํ๋ ํจ์๋ ๋ณดํต ๋ด๋ถ์์ ์๋ณธ ํจ์๋ฅผ ํธ์ถํ๋ฉด์ ์ถ๊ฐ์ ์ธ ๋ก์ง(์ ์ฒ๋ฆฌ, ํ์ฒ๋ฆฌ)์ ์ํํฉ๋๋ค.
- ํน์ง ๋ฐ ์ฉ๋:
- ์ฝ๋ ์ค๋ณต ๊ฐ์: ๋ก๊น , ์ ๊ทผ ์ ์ด, ์ฑ๋ฅ ์ธก์ , ํธ๋์ญ์ ์ฒ๋ฆฌ ๋ฑ ์ฌ๋ฌ ํจ์์ ๊ณตํต์ ์ผ๋ก ์ ์ฉ๋ ๋ก์ง์ ๋ฐ์ฝ๋ ์ดํฐ๋ก ๋ง๋ค์ด ์ฌ์ฌ์ฉํ ์ ์์ต๋๋ค.
- ๊ฐ๋ ์ฑ ํฅ์: ํจ์์ ํต์ฌ ๋ก์ง๊ณผ ๋ถ๊ฐ ๊ธฐ๋ฅ์ ๋ถ๋ฆฌํ์ฌ ์ฝ๋๋ฅผ ๋ ๊น๋ํ๊ณ ์ดํดํ๊ธฐ ์ฝ๊ฒ ๋ง๋ญ๋๋ค.
- ์ ์ง๋ณด์ ์ฉ์ด์ฑ: ๊ณตํต ๋ก์ง ๋ณ๊ฒฝ ์ ๋ฐ์ฝ๋ ์ดํฐ ํจ์๋ง ์์ ํ๋ฉด ๋ฉ๋๋ค.
import time
def measure_time(func):
def wrapper(*args, **kwargs):
start_time = time.time()
result = func(*args, **kwargs) # ์๋ณธ ํจ์ ํธ์ถ
end_time = time.time()
print(f"Function {func.__name__} took {end_time - start_time:.4f} seconds")
return result
return wrapper # ๋ด๋ถ ํจ์(wrapper)๋ฅผ ๋ฐํ
@measure_time # ๋ฐ์ฝ๋ ์ดํฐ ์ ์ฉ
def slow_function(n):
time.sleep(n)
return "Done"
slow_function(1) # ์ถ๋ ฅ: Function slow_function took 1.xxxx seconds
# ๋ด๋ถ์์๋ ์๋ ์ฒ๋ผ ๋์ํจ
slow_function = measure_time(slow_function)
4. ๋น๋๊ธฐ ํ๋ก๊ทธ๋๋ฐ (Asyncio)โ
asyncio๋ ํ์ด์ฌ ํ์ค ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ก, async/await ๋ฌธ๋ฒ์ ์ฌ์ฉํ์ฌ ๋น๋๊ธฐ ์ฝ๋๋ฅผ ์์ฑํ๊ธฐ ์ํ ํ๋ ์์ํฌ์
๋๋ค. ์ฃผ๋ก I/O ๋ฐ์ด๋(๋คํธ์ํฌ ํต์ , ํ์ผ ์ฝ๊ธฐ/์ฐ๊ธฐ ๋ฑ ๋๊ธฐ ์๊ฐ์ด ๋ง์ ์์
) ์์
์์ ๋์ ์ฑ๋ฅ์ ๋ฐํํฉ๋๋ค.
- ๋์ ๋ฐฉ์ (์ด๋ฒคํธ ๋ฃจํ ๊ธฐ๋ฐ):
async def๋ก ์ ์๋ ํจ์๋ ์ฝ๋ฃจํด(coroutine) ๊ฐ์ฒด๋ฅผ ๋ฐํํฉ๋๋ค. ์ฝ๋ฃจํด์ ์คํ์ ์ค๊ฐ์ ๋ฉ์ถ๊ณ ๋ค๋ฅธ ์ฝ๋ฃจํด์๊ฒ ์ ์ด๊ถ์ ๋๊ฒจ์ค ์ ์๋ ํน๋ณํ ํจ์์ ๋๋ค.awaitํค์๋๋ ์ฝ๋ฃจํด ๋ด์์ ๋ค๋ฅธ ์ฝ๋ฃจํด์ด๋awaitable๊ฐ์ฒด(์:asyncio.sleep, I/O ์์ )์ ์๋ฃ๋ฅผ ๊ธฐ๋ค๋ฆด ๋ ์ฌ์ฉ๋ฉ๋๋ค.await๋ฅผ ๋ง๋๋ฉด ํ์ฌ ์ฝ๋ฃจํด์ ์คํ์ ์ผ์ ์ค์ง๋๊ณ , ํ๋ก๊ทธ๋จ์ ์ ์ด๊ถ์ **์ด๋ฒคํธ ๋ฃจํ(event loop)**๋ก ๋์ด๊ฐ๋๋ค.- ์ด๋ฒคํธ ๋ฃจํ๋ ํ์ฌ ๋๊ธฐ ์ค์ธ ๋ค๋ฅธ ์์ (๋ค๋ฅธ ์ฝ๋ฃจํด)์ ์คํํฉ๋๋ค.
awaitํ๋ ์์ ์ด ์๋ฃ๋๋ฉด (์: ๋คํธ์ํฌ ์๋ต ๋์ฐฉ), ์ด๋ฒคํธ ๋ฃจํ๋ ํด๋น ์ง์ ์์ ์ค์ง๋์๋ ์ฝ๋ฃจํด์ ์คํ์ ๋ค์ ์ฌ๊ฐํฉ๋๋ค.
- ํน์ง ๋ฐ ์ฅ์ :
- ์ฑ๊ธ ์ค๋ ๋ ๋์์ฑ: ์ฌ๋ฌ ์ค๋ ๋๋ ํ๋ก์ธ์ค๋ฅผ ์ฌ์ฉํ์ง ์๊ณ ๋ ๋จ์ผ ์ค๋ ๋ ๋ด์์ ์ฌ๋ฌ ์์ ์ ๋์์ ์ฒ๋ฆฌํ๋ ๊ฒ์ฒ๋ผ ๋ณด์ด๊ฒ ํฉ๋๋ค (์ฃผ๋ก I/O ๋๊ธฐ ์๊ฐ์ ํ์ฉ). GIL์ ์ ์ฝ์ ๋ฐ์ง ์๊ณ I/O ์์ ์ ํจ์จ์ ์ผ๋ก ์ฒ๋ฆฌํ ์ ์์ต๋๋ค.
- ๋์ I/O ์ฒ๋ฆฌ๋: ๋คํธ์ํฌ ์๋ฒ, ์น ํด๋ผ์ด์ธํธ ๋ฑ ๋์์ ๋ง์ I/O ์ฐ๊ฒฐ์ ์ฒ๋ฆฌํด์ผ ํ๋ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ ํฉํฉ๋๋ค.
- ๋ช
์์ ๋น๋๊ธฐ:
async/awaitํค์๋๋ฅผ ํตํด ์ฝ๋์ ์ด๋ค ๋ถ๋ถ์ด ๋น๋๊ธฐ์ ์ผ๋ก ๋์ํ๊ณ ๋๊ธฐํ๋์ง ๋ช ํํ๊ฒ ์ ์ ์์ต๋๋ค.
import asyncio
async def say_after(delay, what):
await asyncio.sleep(delay) # delay ์ด ๋์ ๋๊ธฐ
print(what)
async def main():
print("Started")
task1 = asyncio.create_task(say_after(1, 'hello')) # ์์
์ ์ด๋ฒคํธ ๋ฃจํ์ ๋ฑ๋ก
task2 = asyncio.create_task(say_after(2, 'world'))
await task1 # task1 ์๋ฃ๋ ๋๊น์ง ๋๊ธฐ
await task2 # task2 ์๋ฃ๋ ๋๊น์ง ๋๊ธฐ
print("Finished")
# Python 3.7+
asyncio.run(main())
# ์ถ๋ ฅ ์์:
# Started
# (1์ด ํ) hello
# (1์ด ๋ ํ) world
# Finished
5. GIL (Global Interpreter Lock)โ
GIL์ ์ ์ญ ์ธํฐํ๋ฆฌํฐ ์ ๊ธ(Global Interpreter Lock)์ ์ฝ์๋ก, CPython(ํ์ด์ฌ ํ์ค ๊ตฌํ์ฒด)์์ ์ฌ์ฉ๋๋ ๋ฉ์ปค๋์ฆ์ ๋๋ค. ์ด๊ฒ์ ํ๋์ ํ๋ก์ธ์ค ๋ด์์ ์ฌ๋ฌ ์ค๋ ๋๊ฐ ๋์์ ํ์ด์ฌ ๋ฐ์ดํธ์ฝ๋๋ฅผ ์คํํ์ง ๋ชปํ๋๋ก ๋ง๋ ๋ฎคํ ์ค(mutex, ์ํธ ๋ฐฐ์ ์ ๊ธ)์ ๋๋ค.
- ๋์ ๋ฐฉ์:
- CPython ์ธํฐํ๋ฆฌํฐ๋ ์คํ๋ ๋ GIL์ ํ๋ํด์ผ ํฉ๋๋ค.
- ํ ๋ฒ์ ์ค์ง ํ๋์ ์ค๋ ๋๋ง์ด GIL์ ๋ณด์ ํ๊ณ ํ์ด์ฌ ๋ฐ์ดํธ์ฝ๋๋ฅผ ์คํํ ์ ์์ต๋๋ค.
- ์ผ์ ์๊ฐ ์คํํ๊ฑฐ๋, ํนํ I/O ์์ (ํ์ผ ์ฝ๊ธฐ/์ฐ๊ธฐ, ๋คํธ์ํฌ ํต์ ๋ฑ)์ ๋ง๋๋ฉด ํด๋น ์ค๋ ๋๋ GIL์ ๋ฐฉ์ถ(release)ํ์ฌ ๋ค๋ฅธ ์ค๋ ๋๊ฐ ์คํ๋ ๊ธฐํ๋ฅผ ์ค๋๋ค.
- ์ํฅ:
- CPU ๋ฐ์ด๋ ์์ : ๊ณ์ฐ ์ง์ฝ์ ์ธ ์์ ์ ๊ฒฝ์ฐ, ๋ฉํฐ์ฝ์ด ํ๋ก์ธ์๊ฐ ์๋๋ผ๋ ์ฌ๋ฌ ์ค๋ ๋๋ฅผ ์ฌ์ฉํด๋ ์ง์ ํ ๋ณ๋ ฌ ์คํ์ด ๋ถ๊ฐ๋ฅํฉ๋๋ค. ์คํ๋ ค ์ค๋ ๋ ๊ฐ GIL ํ๋ ๊ฒฝ์ ๋๋ฌธ์ ์ฑ๋ฅ์ด ์ ํ๋ ์๋ ์์ต๋๋ค.
- I/O ๋ฐ์ด๋ ์์ : ์ค๋ ๋๊ฐ I/O ๋๊ธฐ ์ค์ GIL์ ๋์์ฃผ๊ธฐ ๋๋ฌธ์, ๋ค๋ฅธ ์ค๋ ๋๊ฐ ๊ทธ ์๊ฐ์ ์คํ๋ ์ ์์ต๋๋ค. ๋ฐ๋ผ์ ์ค๋ ๋ฉ์ I/O ๋ฐ์ด๋ ์์ ์ ๋์์ฑ ์ฒ๋ฆฌ์๋ ์ฌ์ ํ ํจ๊ณผ์ ์ ๋๋ค.
- ์ ์กด์ฌํ๋๊ฐ?
- CPython์ ๋ฉ๋ชจ๋ฆฌ ๊ด๋ฆฌ(ํนํ ์ฐธ์กฐ ์นด์ดํ )๋ฅผ ๋จ์ํํ๊ณ ์ค๋ ๋ ์์ ํ๊ฒ ๋ง๋ค๊ธฐ ์ํด ๋์ ๋์์ต๋๋ค.
- C ํ์ฅ ๋ชจ๋ ๊ฐ๋ฐ์ ์ฉ์ดํ๊ฒ ํฉ๋๋ค (GIL์ด ์ค๋ ๋ ๊ด๋ จ ๋ณต์ก์ฑ์ ์ผ๋ถ ํด๊ฒฐ).
- ๊ทน๋ณต ๋ฐฉ๋ฒ:
- ๋ฉํฐํ๋ก์ธ์ฑ (
multiprocessing๋ชจ๋): ๊ฐ ํ๋ก์ธ์ค๋ ์์ ๋ง์ ํ์ด์ฌ ์ธํฐํ๋ฆฌํฐ์ ๋ฉ๋ชจ๋ฆฌ ๊ณต๊ฐ, ๊ทธ๋ฆฌ๊ณ ์์ ๋ง์ GIL์ ๊ฐ์ง๋ฏ๋ก, ์ฌ๋ฌ CPU ์ฝ์ด๋ฅผ ํ์ฉํ ์ง์ ํ ๋ณ๋ ฌ ์ฒ๋ฆฌ๊ฐ ๊ฐ๋ฅํฉ๋๋ค. CPU ๋ฐ์ด๋ ์์ ์ ์ ํฉํฉ๋๋ค. - Asyncio: ์์ ์ค๋ช ํ๋ฏ์ด ์ฑ๊ธ ์ค๋ ๋ ๋ด์์ ์ด๋ฒคํธ ๋ฃจํ๋ฅผ ํตํด I/O ๋ฐ์ด๋ ์์ ์ ๋์์ฑ์ ํจ์จ์ ์ผ๋ก ๊ด๋ฆฌํฉ๋๋ค. GIL ๊ฒฝ์์ ํผํ ์ ์์ต๋๋ค.
- ๋ค๋ฅธ ํ์ด์ฌ ๊ตฌํ์ฒด: Jython(JVM ๊ธฐ๋ฐ), IronPython(.NET ๊ธฐ๋ฐ) ๋ฑ GIL์ด ์๋ ๊ตฌํ์ฒด๋ ์์ง๋ง, CPython๊ณผ์ ํธํ์ฑ์ด๋ ์ํ๊ณ ํฌ๊ธฐ์์ ์ฐจ์ด๊ฐ ์์ ์ ์์ต๋๋ค.
- ๋ฉํฐํ๋ก์ธ์ฑ (