SSR + Thymeleaf 이중화 환경에서 RedirectAttributes 메시지 유실 문제 해결하기

이경헌·2025년 5월 18일
0

Redirect 시 사용자에게 피드백 메시지를 전달하고 싶은데, 서버 이중화 환경에서는 메시지가 유실된다면?


💡 문제 상황

Spring Boot + Thymeleaf 기반의 SSR 웹 애플리케이션에서 RedirectAttributes를 사용해 리다이렉트 이후 사용자에게 알림 메시지를 출력하는 상황

예:

@PutMapping("/{postId}/isFixed")
public String updatePostIsFixed(@PathVariable Long postId, @RequestParam Boolean isFixed,
	RedirectAttributes redirectAttributes) {
	redirectAttributes.addFlashAttribute("message", "게시글이 고정되었습니다.");
	return "redirect:/posts/" + postId;
}

이 방식은 단일 서버에서는 잘 동작하지만, 이중화된 서버 구조(Blue/Green 배포 등) 에서는 문제가 생깁니다.

리다이렉트 이후 연결된 서버가 다르면 세션이 공유되지 않아 메시지가 유실됩니다.


🔧 해결 방법

✅ 방법 1. 쿠키를 이용한 메시지 전달 방식

메시지를 쿠키에 담아 브라우저에 전달하고, 클라이언트에서 꺼내 사용하는 방식입니다.

💻 컨트롤러에서 메시지를 쿠키로 전달

@PutMapping("/{postId}/isFixed")
public String updatePostIsFixed(@PathVariable Long postId, @RequestParam Boolean isFixed,
	HttpServletResponse response) {
	String message = "게시글이 고정되었습니다.";
	Cookie cookie = new Cookie("alertMessage", URLEncoder.encode(message, StandardCharsets.UTF_8));
	cookie.setPath("/");
	cookie.setMaxAge(10); // 메시지 노출 후 짧게 유지
	response.addCookie(cookie);
	return "redirect:/posts/" + postId;
}

🖥️ 클라이언트 (Thymeleaf 페이지)에서 메시지 출력

<div id="alertBox" class="alert-box">
    <span id="alertMessage"></span>
    <span class="closeBtn" onclick="closeAlert()">&times;</span>
</div>
<script>
function getCookie(name) {
    const cookies = document.cookie.split(';').map(c => c.trim());
    for (let cookie of cookies) {
        if (cookie.startsWith(name + '=')) {
            let value = cookie.substring(name.length + 1);
            value = value.replace(/\+/g, ' ');  // + → 공백
            return decodeURIComponent(value);
        }
    }
    return null;
}

function deleteCookie(name) {
    document.cookie = name + '=; Max-Age=0; path=/;';
}

function showAlert(message) {
    const alertBox = document.getElementById('alertBox');
    const alertMessage = document.getElementById('alertMessage');
    alertMessage.textContent = message;
    alertBox.classList.add("show");

    setTimeout(() => {
        alertBox.classList.remove('show');
        deleteCookie('alertMessage');
    }, 5000);
}

document.addEventListener("DOMContentLoaded", function () {
    const message = getCookie('alertMessage');
    if (message) {
        showAlert(message);
    }
});
</script>

✅ 방법 2. Redis를 활용한 세션 공유 방식

이중화 서버 환경에서도 RedirectAttributes를 그대로 유지하고 싶다면, Redis 기반의 세션 공유 설정이 필요합니다.

1. 의존성 추가

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

<dependency>
    <groupId>org.springframework.session</groupId>
    <artifactId>spring-session-data-redis</artifactId>
</dependency>

2. Redis 세션 설정 (application.yml)

spring:
  session:
    store-type: redis
  data:
    redis:
      host: localhost
      port: 6379
      password: yourpassword

3. Redis 세션 전용 설정 클래스

@Configuration
@EnableRedisHttpSession
public class SessionConfig {
}

4. Redis 연결 설정 (세션은 5번 DB에 저장)

@Configuration
@RequiredArgsConstructor
public class RedisConfig {

	@Value("${spring.data.redis.host}")
	private String hostname;

	@Value("${spring.data.redis.password}")
	private String password;

	@Bean("sessionRedisConnectionFactory")
	public RedisConnectionFactory sessionRedisConnectionFactory() {
		RedisStandaloneConfiguration config = new RedisStandaloneConfiguration();
		config.setHostName(hostname);
		config.setPort(6379);
		config.setPassword(password);
		config.setDatabase(5); // 세션용 DB
		return new LettuceConnectionFactory(config);
	}
}

이렇게 하면 RedirectAttributes.addFlashAttribute()로 추가한 메시지가 Redis를 통해 서버 간 공유되며, 다른 서버로 리다이렉트 되어도 메시지가 유지됩니다.


📌 어떤 방법이 더 좋을까?

상황추천 방법
간단한 메시지, 빠른 구현👉 쿠키 방식
보안, 다중 페이지 유지, 이중화 대응👉 Redis 세션 방식
메시지 유지를 위해 Redis 도입 고려 가능👉 세션 방식 적극 추천

0개의 댓글