모든 케이스 스터디
정부광고통합지원시스템한국언론진흥재단2020.08 - 2025.12 (5년 4개월)

INFRA / SESSION

Redis 기반 세션 클러스터링

JEUS Standard Edition에서는 세션 클러스터링 기능을 쓸 수 없어서, Redis를 외부 세션 저장소로 두고 우회했습니다. 그 결과 레거시 환경에서도 WAS 순차 재기동이 가능해졌습니다.

핵심 효과
무중단 배포

WAS 순차 재기동 가능

세션 지연
밀리초

UX 영향 없음

프레임워크
전자정부 3.x

Spring Session 네이티브

인프라
Redis 7.4

Docker 컨테이너

Redis 7.4Spring SessionSpring Data RedisLettuceJEUS (Standard)Docker전자정부 프레임워크

Problem

WAS 하나만 재기동해도 로그인·입력이 날아감

WAS가 여러 대 있는데 세션은 서버마다 제각각 들고 있는 구조였습니다. 그래서 서버 한 대만 재기동해도 거기 붙어 있던 사용자는 로그아웃됐고, 뭔가 작성 중이었다면 그 내용도 그대로 날아갔습니다. JEUS가 세션 클러스터링 기능을 지원하긴 하지만 Enterprise 라이선스에만 들어 있었고, 우리 쪽 환경은 Standard라 공식 경로로는 해결할 방법이 없었습니다.

  • 재기동하면 로그인·입력 데이터가 날아감

    새로고침 한 번에 작성하던 내용이 통째로 사라지는 경험을 사용자가 자주 겪음

  • 무중단 배포가 불가능

    세션을 지키려고 배포를 미루거나, 반대로 세션 단절을 감수하고 배포해야 하는 상황 반복

  • 라이선스로는 풀 수 없음

    세션 클러스터링은 JEUS Enterprise에만 포함된 기능, Standard에서는 사용 불가

Approach

Redis 외부 세션 저장소로 우회

라이선스 업그레이드는 비용이 크니까, 대신 애플리케이션 쪽에서 세션을 외부 저장소로 빼내는 방향을 골랐습니다. Spring Session이 Redis와 바로 붙어 있어 코드는 건드리지 않고 설정만 추가하면 됐고, Redis는 응답이 밀리초 단위라 사용자 경험에도 영향이 거의 없을 거라고 봤습니다.

BEFORE

세션 격리 · 재기동 시 유실

WAS 1

session

WAS 2

session

WAS 3

session

✕ WAS 간 세션 공유 없음

AFTER

세션 공유 · 무중단 재기동

WAS 1

WAS 2

WAS 3

Redis

SHARED SESSION STORE

빠른 응답

세션 조회/저장이 밀리초 단위라 UX에 영향 없음

기존 코드 유지

Spring Session이 Redis와 기본 통합 — 설정만 추가

가벼운 운영

Docker로 설치, TTL 자동 관리, 구조가 단순함

Process

구현 단계

  1. 01

    Redis 띄우기

    공용 Docker 호스트에 Redis 7.4 컨테이너를 올렸습니다. 비밀번호, 영속 볼륨, 자동 재시작 정책을 같이 설정했고, 애플리케이션에서 쓸 호스트·포트·패스워드는 프로퍼티 파일로 분리했습니다.

    install-redis.sh
    bash
    # Redis 설치 (7.4.2)
    docker pull redis:7.4.2
     
    # 컨테이너 실행
    docker run -d \
    --name redis \
    --restart unless-stopped \
    -p 6379:6379 \
    -v /data/redis:/data \
    redis:7.4.2 redis-server --requirepass "your-password"
    redis.properties
    properties
    # redis.properties
    redis.host = your.redis.host
    redis.port = 6379
    redis.password = your-password
    redis.database = 0
  2. 02

    Spring Session 의존성 추가

    전자정부 프레임워크 프로젝트의 pom.xml에 Spring Session / Spring Data Redis / Lettuce를 추가했습니다. 서블릿 세션을 외부 저장소로 위임하기 위한 준비 단계입니다.

    pom.xml
    xml
    <!-- pom.xml - Spring Session + Redis 의존성 -->
    <dependency>
    <groupId>org.springframework.session</groupId>
    <artifactId>spring-session-data-redis</artifactId>
    <version>2.7.0</version>
    </dependency>
    <dependency>
    <groupId>org.springframework.data</groupId>
    <artifactId>spring-data-redis</artifactId>
    <version>2.7.0</version>
    </dependency>
    <dependency>
    <groupId>io.lettuce</groupId>
    <artifactId>lettuce-core</artifactId>
    <version>6.2.0.RELEASE</version>
    </dependency>
  3. 03

    Redis 연결·세션 매핑 설정

    context-redis.xml에 LettuceConnectionFactory와 RedisHttpSessionConfiguration을 선언했습니다. HTTP 세션이 자동으로 Redis에 저장되도록 매핑한 거라, 애플리케이션 코드 수정은 없습니다.

    context-redis.xml
    xml
    <!-- context-redis.xml - Redis 연결/직렬화/세션 구성 -->
    <bean id="redisConnectionFactory"
    class="org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory">
    <property name="hostName" value="${redis.host}"/>
    <property name="port" value="${redis.port}"/>
    <property name="password" value="${redis.password}"/>
    <property name="database" value="${redis.database}"/>
    </bean>
     
    <bean class="org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration">
    <property name="maxInactiveIntervalInSeconds" value="1800"/>
    </bean>

Outcome

결과와 배운 것

  • 무중단 배포가 가능해짐

    WAS를 순차 재기동해도 세션이 유지됩니다. 긴급 패치나 테스트 적용도 서비스 중단 없이 돌릴 수 있게 됐습니다.

  • 로그인 끊김 문제 해결

    장애, 재배포, 장시간 운영 상황에서도 로그인이 끊기거나 입력 데이터가 날아가는 일이 없어졌습니다.

  • 라이선스 한계를 외부 저장소로 우회

    상위 라이선스를 구매하지 않고도 세션 클러스터링을 구현했습니다. 플랫폼 제약이 있어도 아키텍처로 돌아갈 길이 있다는 걸 직접 경험했습니다.

  • 다음부터는 호환성부터 확인

    전자정부 프레임워크 버전이 낮아서 Spring Session·Redis 호환성 확인에 시간이 생각보다 많이 들었습니다. 앞으로는 호환성부터 먼저 검증하고 진행할 계획입니다.

MORE

다른 케이스 살펴보기

바다봄

AUTH / SSO

외부 사이트용 SSO Provider 구축

OTT 등 외부 기관 사이트에서 바다봄 계정으로 로그인하도록 Provider를 직접 구현했습니다. 일회용 UUID 토큰을 DB에 저장해 다중 WAS를 지원하고, CI(개인 공통 식별자) 기반으로 양쪽 계정을 자동 매핑합니다.

자세히 보기

바다봄

DEVOPS / OBSERVABILITY

SSE + Cross-WAS 실시간 로그 뷰어

WAS는 대전 IDC에 있는데, 망분리 정책상 그 서버에 붙을 수 있는 PC가 부산 사무실에만 있었습니다. 그래서 로그 한 번 보려면 사실상 부산으로 가야 하는 구조였어요. 관리자 웹 안에 SSE 기반 뷰어를 만들고, 두 개 WAS 노드 로그까지 Cross-WAS 릴레이로 한 화면에서 보이도록 구성했습니다.

자세히 보기

바다봄

LEGACY MIGRATION

OTT 기술거래 시스템을 바다봄으로 이관

Oracle + MyBatis 기반의 OTT 기술거래 플랫폼을 PostgreSQL + iBATIS 환경으로 옮겼습니다. 87개 URL, 34개 JSP, 80여 개 SQL과 14개 테이블을 재작성했습니다.

자세히 보기

정부광고통합지원시스템

CI/CD

빌드·배포 프로세스 자동화

전부 수동으로 하던 빌드·배포를 Jenkins + GitLab Webhook 기반으로 자동화해서, 배포 시간을 15~20분에서 4분대로 줄였습니다.

자세히 보기

정부광고통합지원시스템

SECURITY / NETWORK

Nginx 리버스 프록시로 TLS 1.3 적용

WebtoB 공용 SSL을 건드리기 부담스러워서, 앞단에 Nginx를 세우고 거기서 TLS를 종단하도록 바꿨습니다. 기존 서비스는 영향 없이 TLS 1.3으로 올렸습니다.

자세히 보기

프리랜서 · 사이드 프로젝트

CLIENT WORK / WEB

산후조리원 홈페이지 리뉴얼 제안 → 제작

아내가 입소한 조리원의 홈페이지가 오래돼 보여서 직접 UI 샘플을 만들어 제안했습니다. 192프레임 스크롤 애니메이션, 카카오맵, SEO까지 갖춘 Astro 정적 사이트를 제작해서 실제 운영 도메인으로 배포했습니다.

자세히 보기

프리랜서 · 사이드 프로젝트

SIDE PROJECT / AI

AI 작명 + 이상형 월드컵으로 가족이 함께 고르는 아기 이름

기존 작명 서비스가 혼자 쓰는 구조여서, 가족이 같이 참여할 수 있는 방식을 만들었습니다. GPT-4o가 사주·오행 맞춰 이름을 추천하면, 이상형 월드컵으로 가족이 투표해서 최종 이름을 고릅니다.

자세히 보기