🟢Plango프로젝트에서는 아래의 TourAPI API 5개를 호출할 예정이다.
🟢나는 아래와 같은 흐름으로 만들 예정이다.
🟢어떻게 개발 하면 좋을지 정리해 보았다!
contentid, contenttypeid가 나와야 나머지 4개를 호출 가능)따라서 나는 python 비동기에 대해서 공부할 필요성을 느끼게 되었다!
비동기(async) 란, 프로그램이 특정 작업을 기다리는 동안 다른 작업을 수행할 수 있도록 하는 것을 의미 합니다.
비동기 함수 선언:
async def를 사용하여 함수를 선언합니다. 이렇게 선언된 함수는코루틴(coroutine)을 반환합니다.
await 키워드:
await 키워드는 코루틴의 실행을 일시 중지하고, 완료될 때까지 기다립니다.await는async 함수내에서만 사용할 수 있습니다.
A:
await 키워드는 비동기 함수(async def로 정의된 함수) 안에서 다른 비동기 작업이 끝날 때까지 기다리기 위해 사용됩니다.
await는 "기다려!"라는 뜻입니다.
정확히 말하면, 비동기 작업이 완료될 때까지 다른 작업을 멈추고 기다리는 것입니다.
하지만 프로그램 전체가 멈추는 건 아니고, 현재 함수만 멈추고 나머지 작업은 계속 돌아갑니다.
await는 반드시 async로 정의된 함수 안에서만 쓸 수 있습니다.
async def my_func():
    result = await other_async_func()async def: 비동기 함수 정의await: 다른 비동기 함수(other_async_func())의 결과를 기다림import asyncio
async def say_hello():
    print("Hello...")
    await asyncio.sleep(2)  # 2초 기다림
    print("...World!")
async def main():
    await say_hello()
asyncio.run(main())Hello...
(2초 후)
...World!await asyncio.sleep(2)는 2초 동안 현재 함수를 멈춥니다.A:
 여러 비동기 함수가 동시에 실행되는 상황에서 await가 어떻게 동작하는지 살펴보자!
import asyncio
async def cook_rice():
    print("🍚 밥 짓기 시작!")
    await asyncio.sleep(3)  # 3초 걸림
    print("✅ 밥 완성!")
async def boil_soup():
    print("🍲 국 끓이기 시작!")
    await asyncio.sleep(2)  # 2초 걸림
    print("✅ 국 완성!")
async def main():
    task1 = asyncio.create_task(cook_rice())
    task2 = asyncio.create_task(boil_soup())
    print("👉 요리 시작!")
    await task1
    await task2
    print("🍽️ 모든 요리 완료!")
asyncio.run(main())👉 요리 시작!
🍚 밥 짓기 시작!
🍲 국 끓이기 시작!
✅ 국 완성!       <-- 2초 후
✅ 밥 완성!       <-- 3초 후
🍽️ 모든 요리 완료!cook_rice()와 boil_soup()는 각각 await asyncio.sleep()으로 시간이 걸리는 작업을 시뮬레이션합니다.asyncio.create_task()로 동시에 실행되며, await는 각각의 작업이 끝날 때까지 기다립니다.await는 자기 함수만 멈춘다.cook_rice()가 await asyncio.sleep(3)에서 멈추는 동안, boil_soup()는 자기 일정을 계속 진행할 수 있습니다.task1 = asyncio.create_task(cook_rice())
task2 = asyncio.create_task(boil_soup())아래는 위 두 줄의 코드를 지운 코드입니다!
async def main():
    await cook_rice()   # 먼저 밥 짓기 끝까지 기다림 (3초)
    await boil_soup()   # 그 다음 국 끓임 (2초)boil_soup()은 밥이 다 끝나야 호출된다!!
🍚 밥 짓기 시작!
✅ 밥 완성!     <-- 3초
🍲 국 끓이기 시작!
✅ 국 완성!     <-- +2초 (총 5초 소요)결과: 총 5초 걸림 (비효율적)
create_task()로 두함수 동시에 실행하면? (예시1코드)🍚 밥 짓기 시작!
🍲 국 끓이기 시작!
✅ 국 완성!     <-- 2초
✅ 밥 완성!     <-- 3초 (총 3초 소요)결과: 총 3초에 모든 작업 완료 (효율적)
await는 비동기 함수 안에서만 사용 가능하며, 해당 작업이 끝날 때까지 일시 중지합니다.create_task()를 쓰면 여러 비동기 작업을 병렬적으로 처리할 수 있습니다.A:
await task1, await task2는 단순히 task1과 task2를 기다리는 용도로 사용됩니다. 
task1 = asyncio.create_task(cook_rice())
task2 = asyncio.create_task(boil_soup())
await task1
await task2여기서 핵심 키워드는 두 가지입니다:
create_task() → 비동기 작업을 백그라운드에서 실행함await → 그 작업이 끝날 때까지 기다림await task1을 써야 하나요?task1 = asyncio.create_task(cook_rice())이 줄은 cook_rice()라는 비동기 작업을 예약해서 실행만 합니다.
즉시 실행은 되지만, 결과를 기다리지 않고 main 함수는 다음 줄로 넘어가 버립니다.
await task1으로 결과를 기다려야 함await task1이 줄이 없으면, main() 함수는 작업이 끝나기를 기다리지 않고 그냥 종료될 수 있습니다.
즉, 프로그램이 요리가 끝나기 전에 끝나버릴 수도 있어요.
await task1은:
라고 명령하는 것입니다.
async def main():
    task1 = asyncio.create_task(cook_rice())
    task2 = asyncio.create_task(boil_soup())
    print("요리를 맡겨두고 그냥 끝내버리기!")  # main은 끝났지만 task는 아직...실행하면, 아래처럼 완료 메시지가 안 뜰 수도 있어요:
🍚 밥 짓기 시작!
🍲 국 끓이기 시작!
요리를 맡겨두고 그냥 끝내버리기!main()이 끝났기 때문에 프로그램이 종료되고, task1과 task2가 완료되지 못함.
await task1을 쓰는 이유는, 해당 비동기 작업이 정상적으로 끝날 때까지 기다리기 위해서입니다.await를 생략하면 작업이 중간에 끊기거나, 예외가 누락될 수 있어 프로그램이 예상대로 작동하지 않습니다.create_task()로 실행한 후, await로 하나씩 기다려서 완전한 작업 종료를 보장해야 합니다.await task1 → await task2 이렇게 하면 형식적으로는 순차적으로 기다리는 것처럼 보입니다.
하지만 중요한 건, task1, task2를 이미 동시에 시작해두었다는 점입니다.
task1 = asyncio.create_task(cook_rice())
task2 = asyncio.create_task(boil_soup())
await task1
await task2❗ 여기서 중요한 포인트:
create_task()로 동시에 실행 시작await task1은 task1의 완료를 기다림task2는 그동안 뒤에서 계속 실행 중await task2는 남은 시간만 기다리면 됨 (이미 다 끝났다면 바로 넘어감)import asyncio
async def timer(name, delay):
    print(f"⏱️ {name} 시작")
    await asyncio.sleep(delay)
    print(f"✅ {name} 완료 ({delay}초)")
async def main():
    task1 = asyncio.create_task(timer("타이머1", 3))
    task2 = asyncio.create_task(timer("타이머2", 2))
    await task1  # ⏳ 타이머1 끝날 때까지 기다림 (task2도 이때 계속 실행 중!)
    await task2  # task2는 이미 끝났거나 거의 끝나서 바로 넘어감
asyncio.run(main())⏱️ 타이머1 시작
⏱️ 타이머2 시작
✅ 타이머2 완료 (2초)
✅ 타이머1 완료 (3초)create_task()로 두 작업을 동시에 시작함await task1: 타이머1이 3초 동안 실행됨 → 그 사이에 타이머2도 알아서 실행됨await task2 할 때는 이미 끝났기 때문에 즉시 통과await timer("타이머1", 3)
await timer("타이머2", 2)실행 결과:
⏱️ 타이머1 시작
✅ 타이머1 완료 (3초)
⏱️ 타이머2 시작
✅ 타이머2 완료 (2초)총 5초 걸림 (비효율적)
 await task1과 await task2는 순차 실행이 아니라 순차적으로 완료를 기다리는 것입니다.
이미 시작한 작업들이기 때문에, await는 그 작업의 남은 시간만 기다리는 역할이에요.
A:
asyncio.create_task() 방식과 asyncio.gather() 방식은 겉보기엔 비슷해 보이지만, 내부적으로 동작 방식과 용도에 차이가 있어요.
두 방식 모두 "비동기 함수 여러 개를 동시에 실행"할 수 있습니다.
즉, task(1), task(2), task(3)이 순서대로 실행되는 게 아니라, 거의 동시에 시작되고 각자의 sleep() 시간이 지난 뒤 종료됩니다.
asyncio.create_task() 방식 설명task1 = asyncio.create_task(say_hello())
task2 = asyncio.create_task(say_hi())
await task1
await task2이 방식은 두 단계로 나뉩니다:
create_task()는 "작업을 이벤트 루프에 등록해서 백그라운드에서 실행"하게 합니다.즉시 실행되도록 예약만 해두는 거예요.
이때 함수는 바로 실행되기 시작하지만, 그 결과는 아직 기다리지 않아요.
await task1, await task2는 그 작업이 끝나기를 기다리는 단계입니다.즉, 각각의 작업이 끝나야 다음 줄로 넘어갈 수 있어요.
이 방식의 특징은 각 작업을 개별적으로 추적할 수 있다는 점이에요.
예를 들어 중간에 취소하거나, 결과값을 따로 관리하거나, 순서를 바꾸는 게 가능합니다.
asyncio.gather() 방식 설명await asyncio.gather(
    task(1),
    task(2),
    task(3)
)gather()는 내부적으로 아래처럼 작동합니다:
task(1), task(2), task(3)를 동시에 실행합니다.즉, "하나의 묶음"처럼 동작해요. 이 묶음 전체가 끝나야 다음 코드로 넘어갈 수 있습니다.
이 방식은 단순히 동시에 여러 코루틴을 실행하고, 결과를 함께 기다릴 때 아주 간단하고 직관적이에요.
create_task()
await할지는 개발자가 정할 수 있다.gather()
create_task()는 여러 배달 주문을 따로 걸어두고, 각 배달이 도착하면 하나씩 확인하는 방식.gather()는 세 개를 한꺼번에 시키고, 전부 도착할 때까지 문 앞에서 기다리는 방식.create_task()gather()아래 블로그도 읽어보니 많은 도움이 되었다!