1. 개념

    1. 함수나 클래스 정의 위에 @데코레이터이름을 붙이면, 해당 함수 / 클래스의 동작을 감싸서 새로운 기능을 추가할 수 있습니다.
  2. 장점

    1. 코드 중복 없이 공통 기능 (로깅, 인증, 트랜잭션 등) 추가
    2. 함수 / 클래스 선언부에 한 줄로 부가 기능 명시
  3. 단점

    1. 내부 동장이 감춰져 있어 초보자에서는 직관적이지 않을 수 있음
    2. 데코레이터가 많아지면 코드 추적이 어려울 수 있음
  4. 예시

    from fastapi import FastAPI
    
    app = FastAPI()
    //app은 FastAPI 호출
    @app.get("/hello") //@GetMapping 어노테이션과 같음
    def hello();
    	return {"msg": "hello"}
    	
    	//장점 라우팅이 한눈에 보임
    	//코드가 간결해짐	
    
    from contextlib import asynccontectmanager
    
    @asynccontextmanager
    async def lifespan(app);
    	log.debug("서버 시작")
    	yield  // 값 하나를 반환하고 나중에 반환을 하거나 멈추는 함수
    	log.debug("서버 종료")
    	
    	// 동기: 한 작업이 끝날 때까지 다음 작업이 "기다렸다가" 순차적으로 실행됨
    	// 비동기 : 작업이 "기다리지 않고" 동시에 (혹은 예약해두고) 실행됨 -> 다른 작업이 끝날 날까지 멈추지 않고, 다른 일도 처리할 수 있음
    	// 비동기 파이썬 예시	
    	// 비동기는 여러 작업이 "시작"될 수 있고, 각 작업의 "끝"은 순서와 상관없이 도착
    
    	@asynccontextmanager
    async def lifespan(app):
        await log.debug("시작")      # 1
        await log.debug("중간")     # 2
        log.debug("한참전 시작")    # 3
    
        yield
    
        log.debug("123")           # 4
        log.debug("234")           # 5
        await log.debug("567")     # 6