From 674777626ed20ccac89a797da1b8d4f97be18626 Mon Sep 17 00:00:00 2001 From: umsangdon Date: Sun, 6 Sep 2026 21:52:38 +0900 Subject: [PATCH] =?UTF-8?q?perf(auth):=20=EC=84=B8=EC=85=98=20=ED=99=95?= =?UTF-8?q?=EC=9D=B8=EC=9D=98=20=ED=99=9C=EB=8F=99=EC=8B=9C=EA=B0=81=20?= =?UTF-8?q?=EC=93=B0=EA=B8=B0=EB=A5=BC=201=EB=B6=84=EC=97=90=20=ED=95=9C?= =?UTF-8?q?=20=EB=B2=88=EC=9C=BC=EB=A1=9C=20=E2=80=94=2034.4=E2=86=9213.6m?= =?UTF-8?q?s?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 인증이 걸린 모든 요청이 지나는 자리인데 요청마다 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) --- common_util/common_util_auth.py | 17 ++++++++++++----- config/config_system.py | 6 ++++++ 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/common_util/common_util_auth.py b/common_util/common_util_auth.py index e04d7d7c..0129110b 100644 --- a/common_util/common_util_auth.py +++ b/common_util/common_util_auth.py @@ -15,6 +15,7 @@ from config.config_system import ( DEVICE_TOKEN_COOKIE_NAME, EMAIL_REVERIFY_DAYS, PASSWORD_BCRYPT_ROUNDS, + SESSION_ACTIVITY_WRITE_INTERVAL_SECONDS, SESSION_COOKIE_NAME, SESSION_COOKIE_SECURE, SESSION_IDLE_TIMEOUT_SECONDS, @@ -127,11 +128,17 @@ async def verify_session(request: Request) -> dict[str, Any]: await connection.commit() raise HTTPException(status_code=401, detail="세션이 만료되었습니다.") - await cursor.execute( - "UPDATE sessions SET last_activity_at = CURRENT_TIMESTAMP WHERE id = %s", - (session_id,), - ) - await connection.commit() + # `last_activity_at` 은 유휴 판정(기본 4시간)에만 쓰는 값이라 초 단위로 정확할 이유가 + # 없다. 그런데 **요청마다** 쓰고 있어 원격 DB 왕복이 UPDATE + commit 으로 붙었다 + # (2026-09-06 실측: verify_session 34.4ms = SELECT 10.8 + UPDATE 10.4 + commit 9.5). + # 인증이 걸린 모든 요청이 지나는 자리라, 화면 한 번 여는 데 API 가 180번 나가면 + # 그만큼 곱해진다. 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 { "session_id": row[0], "user_id": row[1], diff --git a/config/config_system.py b/config/config_system.py index be4eaef8..4a60494d 100644 --- a/config/config_system.py +++ b/config/config_system.py @@ -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") SESSION_MAX_AGE_SECONDS = int(os.getenv("SESSION_MAX_AGE_SECONDS", "43200")) 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" PASSWORD_BCRYPT_ROUNDS = int(os.getenv("PASSWORD_BCRYPT_ROUNDS", "12")) OTP_VALID_MINUTES = int(os.getenv("EMAIL_OTP_VALID_MINUTES", "5"))