LogoSkills

serverpod-sessions

Serverpod session 종류, lifecycle, InternalSession, cleanup callback. 수동으로 session을 생성하거나, session-closed 오류를 디버깅하거나, session lifecycle을 이해해야 할 때 사용합니다.

Serverpod Sessions#

한마디로#

세션(Session)은 서버가 한 가지 일을 처리하는 동안 들고 다니는 "출입증 겸 작업 가방"이라고 보면 됩니다. 이 가방 안에는 데이터베이스, 캐시, 저장소, 로그 같은 도구가 들어 있어, 서버가 요청 하나를 끝낼 때까지 필요한 것들을 꺼내 씁니다. 보통은 서버가 알아서 가방을 챙겨주고 끝나면 반납하지만, 직접 만든 가방(InternalSession)은 사람이 손수 반납해야 합니다. 이 문서는 그 가방을 언제 만들고 어떻게 제대로 닫는지를 설명합니다.

무엇을·언제#

  • 무엇을 해주나: 세션의 종류, 생성·종료(생명주기), 직접 만드는 InternalSession, 닫히기 직전 처리(cleanup) 방법을 정리해 줍니다.
  • 언제 쓰나:
    • 직접(수동으로) 세션을 만들어야 할 때
    • "세션이 이미 닫혔다"는 오류를 만나 원인을 찾을 때
    • 세션이 언제 만들어지고 언제 닫히는지 흐름을 이해하고 싶을 때
  • 핵심 주의: 직접 만든 세션을 닫지 않으면 메모리가 새고 기록(로그)도 남지 않습니다. 그래서 "항상 닫기"가 중요합니다.

핵심 용어#

용어쉬운 설명
Session(세션)서버가 한 작업을 처리하는 동안 쓰는 도구 묶음(가방). 끝나면 반납(닫기)함
InternalSession사람이 직접 만들고 직접 닫아야 하는 세션
lifecycle(생명주기)세션이 생기고 살아 있다가 닫히는 전체 흐름
cleanup callback세션이 닫히기 직전에 자동으로 실행되는 마무리 처리
StateError이미 닫힌 세션을 다시 쓰려 할 때 나는 오류
future call나중에(지연 후) 실행하도록 예약하는 작업. 닫힌 세션을 붙잡는 대신 사용

A Session provides access to database, cache, storage, messages, passwords, and logging. The framework creates and closes sessions automatically; only InternalSession requires manual management. Do not store a request session for work that outlives the request/stream/future call.

Session types#

TypeCreated forLifetime
MethodCallSessionEndpoint methodsSingle request
WebCallSessionWeb server routesSingle request
MethodStreamSessionStream methodsStream duration
StreamingSessionWebSocket connectionsConnection duration
FutureCallSessionFuture callsTask execution
InternalSessionManual creationUntil closed

Manual sessions (InternalSession)#

Always close in a finally block:

var session = await Serverpod.instance.createSession();
try {
  await doWork(session);
} finally {
  await session.close();
}

Unclosed sessions leak memory and never persist logs. Using a closed session throws StateError.

Cleanup callbacks#

session.addWillCloseListener((session) async {
  // Runs just before session closes (all session types)
});

Common pitfall: using session after method returns#

Sessions close when the endpoint returns. Do not capture for later use:

// BAD — session already closed when callback runs
Timer(Duration(seconds: 5), () => user.updateLastSeen(session));

Fix: Use a future call (session.serverpod.futureCalls.callWithDelay(...)) or create a new InternalSession inside the callback and close it in finally.

Serverpod 4.0 (beta)#

Serverpod cut 4.0.0-beta.0 off the 3.5.0-beta.* line (previously referred to as "Serverpod 4 tech preview" — now versioned as beta, still not GA). Production services in this repo still target Serverpod 3.x, so everything above remains valid. New session-related changes across 3.5.0-beta.14.0.0-beta.0:

  • Serverpod.instance.withSession(...) helper (3.5.0-beta.11): wraps manual InternalSession creation with automatic teardown, so you no longer have to hand-write the try/finally pattern above:

    await Serverpod.instance.withSession((session) async {
      await doWork(session);
    });
    
  • Not-configured features throw StateError (3.5.0-beta.11): calling a session feature that isn't configured (e.g. cache/storage without the backing service set up) now consistently throws StateError instead of a generic Exception — the same exception type as the "already closed" case above.

Beta version pin: serverpod: 4.0.0-beta.0, Dart SDK ^3.10.3, Flutter ^3.38.4.