최근에 스프링 부트가 아닌 Spring으로 RESTFul API를 제작하는 와중에 Spring session을 적용하다가 한글로 된 관련 문서가 잘 보이지 않아 적게 되었습니다.
본 게시글은 spring-session-jdbc를 적용하는 것을 기준으로 합니다.
제 프로젝트 기준으로 버전은 아래와 같습니다.
1. Spring framework 5.3.18
2. Tomcat 9.x
3. MySQL 8.x
<!-- https://mvnrepository.com/artifact/org.springframework.session/spring-session-jdbc -->
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-jdbc</artifactId>
<version>2.6.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.3.18</version>
</dependency>
spring-session-jdbc와 spring-jdbc가 필요합니다. spring-jdbc의 경우 프로젝트에 적용된 spring framework와 버전을 통일하면 되고, spring-session-jdbc의 경우 최신 버전을 사용해도 될 것이라고 생각됩니다.
<filter>
<filter-name>springSessionRepositoryFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSessionRepositoryFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
web.xml 가장 위에 필터를 명시해줍니다. 여기서 filter-name에 들어가는 필터는 application context.xml에서 정의된 필터 Bean입니다. bean id를 어떻게 설정하는지에 따라 달라질 수 있습니다.
<bean id="myDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.cj.jdbc.Driver" />
<property name="url" value="${db.url}" />
<property name="username" value="${db.username}"/>
<property name="password" value="${db.password}"/>
</bean>
먼저 jdbc로 연결될 데이터 소스를 정의합니다. 저같은 경우 MySQL을 사용했습니다.
Hibernate와 같은 JPA를 사용하고 계실 경우에는 SessionFactory 혹은 EntityManager 그리고 트랜잭션 수행을 위한 TransactionManager가 등록되어 있을 것입니다.
이제 이러한 설정을 기반으로 SpringSession을 위한 SessionRepository 빈을 생성하겠습니다.
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="myDataSource"/>
</bean>
<bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
<constructor-arg name="transactionManager" ref="myTransactionManager" />
</bean>
<bean id="mySpringSessionRepository" class="org.springframework.session.jdbc.JdbcIndexedSessionRepository">
<constructor-arg name="jdbcOperations" ref="jdbcTemplate" />
<constructor-arg name="transactionOperations" ref="transactionTemplate"/>
<property name="defaultMaxInactiveInterval" value="1800"/>
</bean>
SessionRespository 빈은 생성 인자로 JdbcTemplate와 TransactionTemplate가 필요합니다.
따라서, 먼저 JdbcTemplate를 내 데이터 소스를 넘겨줘서 만들고 트랜잭션 매니저를 넘겨줘서 TransactionTemplate를 생성합니다.
이후에 생성된 빈들을 이용해서 SessionRepository까지도 생성할 수 있습니다.
<bean id="springSessionRepositoryFilter" class="org.springframework.session.web.http.SessionRepositoryFilter">
<constructor-arg ref="mySpringSessionRepository"/>
</bean>
마지막으로 생성된 SessionRepository 빈을 RespositoryFilter 빈에 넘겨주어 빈 설정을 마무리합니다.
안타깝게도 스프링 부트에서는 자동으로 잘 설정되지만 일반 Spring에서는 스키마마저 설정해줘야 했습니다.
이렇게 하지 않더라도 hibernate의 ddl-auto 옵션에 따라서 자동으로 생성할 수도 있습니다.
저는 오류가 뜨는게 보고싶지 않아서 그냥 설정을 마저 했습니다.
CREATE TABLE SPRING_SESSION (
PRIMARY_ID CHAR(36) NOT NULL,
SESSION_ID CHAR(36) NOT NULL,
CREATION_TIME BIGINT NOT NULL,
LAST_ACCESS_TIME BIGINT NOT NULL,
MAX_INACTIVE_INTERVAL INT NOT NULL,
EXPIRY_TIME BIGINT NOT NULL,
PRINCIPAL_NAME VARCHAR(100),
CONSTRAINT SPRING_SESSION_PK PRIMARY KEY (PRIMARY_ID)
);
CREATE UNIQUE INDEX SPRING_SESSION_IX1 ON SPRING_SESSION (SESSION_ID);
CREATE INDEX SPRING_SESSION_IX2 ON SPRING_SESSION (EXPIRY_TIME);
CREATE INDEX SPRING_SESSION_IX3 ON SPRING_SESSION (PRINCIPAL_NAME);
CREATE TABLE SPRING_SESSION_ATTRIBUTES (
SESSION_PRIMARY_ID CHAR(36) NOT NULL,
ATTRIBUTE_NAME VARCHAR(200) NOT NULL,
ATTRIBUTE_BYTES BLOB NOT NULL,
CONSTRAINT SPRING_SESSION_ATTRIBUTES_PK PRIMARY KEY (SESSION_PRIMARY_ID, ATTRIBUTE_NAME),
CONSTRAINT SPRING_SESSION_ATTRIBUTES_FK FOREIGN KEY (SESSION_PRIMARY_ID) REFERENCES SPRING_SESSION(PRIMARY_ID) ON DELETE CASCADE
);
해당 스키마를 사용하여 datasource로 사용한 데이터베이스에 테이블들을 생성해줍시다.
Spring boot에 익숙해지다보면 의존성 관리부터 빈 관리까지 너무나 많은 것을 프레임워크에 의존하게 된다는 것을 최근 프로젝트를 진행하면서 느끼고 있습니다.
제가 생각할 때에 굳이 스프링 부트를 사용하기보다는 표준 Spring 프레임워크로 API를 개발을 시도해보는 것을 추천드립니다.
현재 API 자동 명세를 위한 Swagger를 Spring에 올리는 것을 시도하고 있습니다.
정말로 참고할만한 문서가 없기에 성공한다면 게시글로 올려보도록 하겠습니다.