2022년 7월 작성, 2026년 10월 보완. 세션 문자열의 형식과 파싱 예제 코드, 주의점을 추가했다.
목차
배경
- Node.js 서버와 PHP(Apache) 서버가 로그인 세션을 공유해야 했다.
- 처음에는 Redis에 세션을 저장해 공유하려고 했지만, 레거시 PHP 버전과 Redis 확장이 호환되지 않아 설정에 실패했다.
- 대안으로 PHP 세션을 MySQL(MariaDB)에 저장하도록 구현했다.
문제 상황
Node.js에서 MySQL에 저장된 PHP 세션을 읽을 수는 있었다. 그런데 세션 데이터가 아래처럼 PHP 고유 형식의 문자열이라, JavaScript 객체로 바꿔야 쓸 수 있었다.
user_id|i:42;user_name|s:6:"kabkee";cart|a:2:{i:0;s:5:"apple";i:1;s:6:"banana";}
PHP의 기본 세션 형식(session.serialize_handler = php)은 키|직렬화된 값 이 이어 붙은 구조다. i: 는 정수, s:6: 는 6바이트 문자열, a:2: 는 원소 2개짜리 배열을 뜻한다.
해결 방법
검색해 보면 여러 방법이 나오는데, 이미 같은 고민을 한 사람들이 파서를 만들어 공개해 두었다. 당시에는 PHP 함수를 JavaScript로 옮긴 프로젝트의 session_decode.js를 가져다 썼다.
npm 패키지로는 php-unserialize가 세션 형식 파싱 함수(unserializeSession)를 제공한다.
const { unserializeSession } = require("php-unserialize");
// MySQL 세션 테이블에서 읽은 data 값 (테이블 구조는 구현마다 다르다)
const raw =
'user_id|i:42;user_name|s:6:"kabkee";cart|a:2:{i:0;s:5:"apple";i:1;s:6:"banana";}';
const session = unserializeSession(raw);
console.log(session);
// { user_id: 42, user_name: 'kabkee', cart: { '0': 'apple', '1': 'banana' } }
PHP 배열은 숫자 키를 가진 객체로 바뀐다. 배열로 쓰려면 Object.values() 로 바꾼다. 이 패키지는 2022년 이후 업데이트가 없는 작은 패키지라, 쓰기 전에 코드를 한 번 확인하는 것이 좋다.
주의할 점
읽기 전용으로만 쓴다. 이 방법은 Node.js에서 PHP 세션을 확인하는 용도다. Node.js에서 세션을 수정해서 다시 저장하면 PHP와 형식이 어긋나기 쉬우니, 세션 변경은 PHP 쪽에서만 한다.
- PHP 설정
session.serialize_handler가php_serialize라면 세션 전체가 일반serialize()형식이라, 세션용 파서가 아니라 일반unserialize함수로 파싱해야 한다. 먼저 서버 설정을 확인한다. - 세션에는 로그인 정보가 들어 있다. Node.js에서 세션 테이블에 접근하는 DB 계정은 읽기 권한만 주고, 세션의 만료 시간도 함께 확인한다.
정리
- PHP 세션 문자열은
키|직렬화된 값형식이고, 공개된 파서로 JavaScript 객체로 바꿀 수 있다. - 파싱하기 전에
session.serialize_handler설정을 확인한다. - Node.js에서는 세션을 읽기만 하고, 수정은 PHP에서 한다.