웹 스택 계층
스택의 5계층 지도 위에 이 프로젝트를 얹어 본 것.
아직 만들지 않았습니다
이 페이지는 카드에 적힌 내용을 펼쳐 보여줄 뿐입니다 — 돌아가는 코드도, 열어볼 데모도 아직 없습니다. 무엇을 왜 만들려는지가 아래에 있습니다.
어떻게 보나
참조 — docs/knowledge/web-stack-layers.html.
기술 노트
각 항목이 실제로 무엇을 보여주고 어떻게 동작하는지 — 위 카드보다 자세한 기술 설명입니다.
웹 스택 계층준비 중
목적: 스터디라기보다 방향 지도입니다: 이 프로젝트의 각 조각이 실제로 어느 계층에 사는지, 그리고 빈 곳은 어디인지. 서로 다른 문제처럼 들리던 카드 여럿이 사실 같은 계층에 앉아 있다는 것, 그리고 어떤 계층은 아예 비어 있다는 것을 알아차리는 데 주로 쓸모가 있습니다.
동작 방식: 프로젝트의 라우트와 데모를 얹은 정적 5계층 다이어그램. 코드는 없습니다.
관련 코드:
"""Web stack layers PoC -- a request flowing through a chain of middleware layers.
Illustrates the core mechanism: each layer wraps the next, adding something on the way
in and/or the way out, and the order in which layers run is visible in the output.
"""
from typing import Callable
Handler = Callable[[dict], dict]
def logging_layer(next_layer: Handler) -> Handler:
def handle(request: dict) -> dict:
print(f" [logging] in: {request['path']}")
response = next_layer(request)
print(f" [logging] out: status={response['status']}")
return response
return handle
def auth_layer(next_layer: Handler) -> Handler:
def handle(request: dict) -> dict:
print(f" [auth] checking token for {request['path']}")
request["user"] = "jay"
return next_layer(request)
return handle
def cache_layer(cache: dict) -> Callable[[Handler], Handler]:
def wrap(next_layer: Handler) -> Handler:
def handle(request: dict) -> dict:
if request["path"] in cache:
print(f" [cache] hit for {request['path']}")
return cache[request["path"]]
print(f" [cache] miss for {request['path']}")
response = next_layer(request)
cache[request["path"]] = response
return response
return handle
return wrap
def app_layer(request: dict) -> dict:
print(f" [app] handling {request['path']} for user={request.get('user')}")
return {"status": 200, "body": f"hello, {request.get('user')}"}
if __name__ == "__main__":
cache: dict = {}
# Layers compose from the outside in: logging -> auth -> cache -> app.
stack = logging_layer(auth_layer(cache_layer(cache)(app_layer)))
print("request 1 (/profile):")
stack({"path": "/profile"})
print("\nrequest 2 (/profile again -- cache should hit):")
stack({"path": "/profile"})