perf(auth): 세션 확인의 활동시각 쓰기를 1분에 한 번으로 — 34.4→13.6ms
인증이 걸린 모든 요청이 지나는 자리인데 요청마다 UPDATE + commit 이 나갔음. DB 가 원격이라 그 둘이 곧 왕복 20ms 임. 실측 — verify_session 34.4ms = SELECT 10.8 + UPDATE 10.4 + commit 9.5. 쓰기를 1분 간격으로 낮춘 뒤 13.6ms(최소 9.4). last_activity_at 은 유휴 판정에만 쓰는 값이고 그 판정이 4시간 단위라 초 단위 정확도가 필요 없음. 간격은 SESSION_ACTIVITY_WRITE_INTERVAL_SECONDS (기본 60, .env 로 조정). 화면 한 번 여는 데 API 가 약 180번 나가므로 그만큼 곱해짐. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -15,6 +15,7 @@ from config.config_system import (
|
|||||||
DEVICE_TOKEN_COOKIE_NAME,
|
DEVICE_TOKEN_COOKIE_NAME,
|
||||||
EMAIL_REVERIFY_DAYS,
|
EMAIL_REVERIFY_DAYS,
|
||||||
PASSWORD_BCRYPT_ROUNDS,
|
PASSWORD_BCRYPT_ROUNDS,
|
||||||
|
SESSION_ACTIVITY_WRITE_INTERVAL_SECONDS,
|
||||||
SESSION_COOKIE_NAME,
|
SESSION_COOKIE_NAME,
|
||||||
SESSION_COOKIE_SECURE,
|
SESSION_COOKIE_SECURE,
|
||||||
SESSION_IDLE_TIMEOUT_SECONDS,
|
SESSION_IDLE_TIMEOUT_SECONDS,
|
||||||
@@ -127,11 +128,17 @@ async def verify_session(request: Request) -> dict[str, Any]:
|
|||||||
await connection.commit()
|
await connection.commit()
|
||||||
raise HTTPException(status_code=401, detail="세션이 만료되었습니다.")
|
raise HTTPException(status_code=401, detail="세션이 만료되었습니다.")
|
||||||
|
|
||||||
await cursor.execute(
|
# `last_activity_at` 은 유휴 판정(기본 4시간)에만 쓰는 값이라 초 단위로 정확할 이유가
|
||||||
"UPDATE sessions SET last_activity_at = CURRENT_TIMESTAMP WHERE id = %s",
|
# 없다. 그런데 **요청마다** 쓰고 있어 원격 DB 왕복이 UPDATE + commit 으로 붙었다
|
||||||
(session_id,),
|
# (2026-09-06 실측: verify_session 34.4ms = SELECT 10.8 + UPDATE 10.4 + commit 9.5).
|
||||||
)
|
# 인증이 걸린 모든 요청이 지나는 자리라, 화면 한 번 여는 데 API 가 180번 나가면
|
||||||
await connection.commit()
|
# 그만큼 곱해진다. 1분에 한 번만 쓴다 — 4시간 판정에는 영향이 없다.
|
||||||
|
if (now - row[4]).total_seconds() >= SESSION_ACTIVITY_WRITE_INTERVAL_SECONDS:
|
||||||
|
await cursor.execute(
|
||||||
|
"UPDATE sessions SET last_activity_at = CURRENT_TIMESTAMP WHERE id = %s",
|
||||||
|
(session_id,),
|
||||||
|
)
|
||||||
|
await connection.commit()
|
||||||
return {
|
return {
|
||||||
"session_id": row[0],
|
"session_id": row[0],
|
||||||
"user_id": row[1],
|
"user_id": row[1],
|
||||||
|
|||||||
@@ -238,6 +238,12 @@ SESSION_COOKIE_NAME = os.getenv("SESSION_COOKIE_NAME", "session_id")
|
|||||||
DEVICE_TOKEN_COOKIE_NAME = os.getenv("DEVICE_TOKEN_COOKIE_NAME", "device_token")
|
DEVICE_TOKEN_COOKIE_NAME = os.getenv("DEVICE_TOKEN_COOKIE_NAME", "device_token")
|
||||||
SESSION_MAX_AGE_SECONDS = int(os.getenv("SESSION_MAX_AGE_SECONDS", "43200"))
|
SESSION_MAX_AGE_SECONDS = int(os.getenv("SESSION_MAX_AGE_SECONDS", "43200"))
|
||||||
SESSION_IDLE_TIMEOUT_SECONDS = int(os.getenv("SESSION_IDLE_TIMEOUT_SECONDS", "14400"))
|
SESSION_IDLE_TIMEOUT_SECONDS = int(os.getenv("SESSION_IDLE_TIMEOUT_SECONDS", "14400"))
|
||||||
|
|
||||||
|
# `sessions.last_activity_at` 을 다시 쓰는 최소 간격(초). 유휴 판정이 4시간 단위라 초 단위로
|
||||||
|
# 정확할 이유가 없고, 요청마다 쓰면 원격 DB 왕복이 약 20ms 씩 붙는다(2026-09-06 실측).
|
||||||
|
SESSION_ACTIVITY_WRITE_INTERVAL_SECONDS = int(
|
||||||
|
os.getenv("SESSION_ACTIVITY_WRITE_INTERVAL_SECONDS", "60")
|
||||||
|
)
|
||||||
SESSION_COOKIE_SECURE = os.getenv("SESSION_COOKIE_SECURE", "True").lower() == "true"
|
SESSION_COOKIE_SECURE = os.getenv("SESSION_COOKIE_SECURE", "True").lower() == "true"
|
||||||
PASSWORD_BCRYPT_ROUNDS = int(os.getenv("PASSWORD_BCRYPT_ROUNDS", "12"))
|
PASSWORD_BCRYPT_ROUNDS = int(os.getenv("PASSWORD_BCRYPT_ROUNDS", "12"))
|
||||||
OTP_VALID_MINUTES = int(os.getenv("EMAIL_OTP_VALID_MINUTES", "5"))
|
OTP_VALID_MINUTES = int(os.getenv("EMAIL_OTP_VALID_MINUTES", "5"))
|
||||||
|
|||||||
Reference in New Issue
Block a user