[해결하기] Zuul / Redis 적용

이호인·2022년 6월 15일
0

문제해결

목록 보기
1/2

📌 무엇을 해결하려했나요

  • 현재 모놀리스 아키텍처로 작업하던 것을 마이크로서비스 아키텍처로 점진적 변경 중
  • Board -> Board, Account, Alarm 등 분리 작업을 진행하고 있다.
  • 필요한 작업마다 각 해당 서버를 호출하기 때문에, 세션 공유 작업이 필요했다.
  • 저번에 서버를 scale-out 했다고 가정하고 Redis를 적용해봤기 때문에 이번에도 Redis를 활용해서 해결하고자 했다.

📌 어떻게 해결했나요

  • Redis 설치
  • pom.xml에 의존성을 추가해준다. (버전은 spring boot 가 알아서 해준다.)
<!-- spring에서 redis에 대한 의존성 -->
<dependency>
	<groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- spring에서 redis를 session storage로 사용하기 위한 의존성 -->
<dependency>
	<groupId>org.springframework.session</groupId>
    <artifactId>spring-session-data-redis</artifactId>
</dependency>
  • yml 파일 설정
spring
	session:
      storage-type: redis
    redis:
      host: localhost
      port: 6379
  • @ConfigurationProperties 사용 (오타 방지, 코드 깔끔하게 사용하기 위함)
@Component
@ConfigurationProperties(prefix = "spring.redis")
@Getter
@Setter
public class RedisProperties {
    private String host;
    private int port;
}
  • RedisConfig 코드 작성해서 커넥션, 템플릿 설정
@Configuration
@RequiredArgsConstructor
public class RedisConfigure {

    private final RedisProperties redisProperties;

    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
        redisTemplate.setConnectionFactory(connectionFactory);
        return redisTemplate;
    }

    @Bean
    public RedisConnectionFactory redisConnectionFactory() {
        RedisStandaloneConfiguration configuration = new RedisStandaloneConfiguration();
        configuration.setHostName(redisProperties.getHost());
        configuration.setPort(redisProperties.getPort());
        return new LettuceConnectionFactory(configuration);
    }
}
  • application 클래스에 @EnableRedisHttpSession 추가

❗ 주의할 점 : redis는 hash를 사용하기 때문에 사용할 객체(dto)를 직렬화 해줄 필요가 있다. implements Serializable을 추가해준다.


여기까지가 기본적인 Redis 설정이고 저번에 멘토가 서버를 두 대로 scale-out 했다고 가정하고 진행해보자 했을 때 적용해봤던 내용들이다. 똑같은 어플리케이션 8080, 8081, 8082로 돌려 확인했을 때도 잘 작동했고, 배포 중에도 로그인이 풀리지 않는 것도 확인하여 잘 동작하고 있다는 것을 알 수 있었다.

하지만 이번에 무엇을 잘못했는지 생각처럼 잘 진행되지 않았지만 😂
저번에 API 나눌 떄도 막막했지만 해결하고 나서 많이 배운 것처럼 이번에도 그러리라 믿고 해결하면서 얻은 내용들을 정리해보고자 한다.

📌 현재 상황 정리

  • 현재 8080 BoardStudy 어플리케이션에서 모든 것이 다 있던 모놀리스 구조에서
  1. 8081 alarm
  2. 8082 account
  3. 8083 zuul 서버

이렇게 작업 순 포트 번호를 임시 지정해서 사용하고 있다.
(어차피 dev 환경과 real 환경에 도메인 설정해서 배포하기 때문에 사실 포트 번호는 내 편한대로 설정해도 상관없음)
8083 zuul 서버로 요청을 받고 각 서버스 별로 호출하는 것은 완료를 했지만, 로그인을 성공하고 넘어가도 로그인이 되지않는 상황이 발생했다. (세션 정보가 공유가 안되는 듯) ---> 문제점

  • 간단히 생각했을 때
    - 세션 정보를 Redis에 저장 --> session.setAttribute("키",값)
    - 각 서버가 같은 Redis 저장소로 세션 처리하게끔 설정

이렇게 하면 당연히 될 줄 알았으나.. 실패.

📌 확인하기

1. Redis는 제대로 설정이 됐을까.

session 확인하는 코드를 작성해서 호출해보니 정상적으로 설정은 된 것 같다.
(개발자 도구에서 확인하는 방법도 있는 듯)

원래 배포하는 서버에 redis 설치하고 사용 중이었는데 답답해서 확인해보려고 local에 설치해서 확인.
user -> 제대로 저장은 되는 것을 확인할 수 있었다.

2. 쿠키 문제가 아닌가?

진짜 안 본 것 없이 다 찾아봐도 그냥 다들 스무스하게 해결한 글 밖에 없어서.. 며칠을 고민하다가 멘토에게 도움을 요청했다. 여기까지 지금 동작하고 어디가 문제인 것 같다 설명해주니 개발자 도구부터 확인해서 쿠키 문제인 것 같다고 조언을 해줬고
https://stackoverflow.com/questions/43625298/spring-session-sharing-between-zuul-and-resource-servers
스택오버플로우에 비슷한 글이 있어 적용해보아도 해결이 안되어서 일단 패스.

3. zuul 서버 사용 안하면?

그냥 8080에서 로그인해도 8082에서도 세션 정보가 남아있어야 한다고 생각해서 시도해봤는데 계속 classNotFoundException과 직렬화에 관련된 에러가 자꾸 발생했다. 계속 에러도 내보고 잘 읽다보니 8080에서 set해준 User와 8002에 있는 User는 다른 클래스기 때문에 자꾸 에러가 발생하는 것 같았다. 사실 로그인되면 아이디만 필요하기 때문에 간단하게 User 객체를 set하지 않고 String인 Id만 set해주는 것으로 코드를 교체했고, 해결했다.

--> zuul 서버 이용하지 않으면 세션 공유에 문제가 없다는 것을 확인함.

4. 해결 ㅠㅠ

3번까지 해결하고 나서 이제 쿠키 문제인 것 같다고 해준 조언이 생각나서 다시 한번 들어가서 읽어보니

Redis에 세션을 저장해도, session Id는 쿠키에 저장되며 리소스 서버에 전달되어야 한다고 한다. 그때 멘토와 개발자 도구를 확인했을 때 어쩐지 쿠키가 제대로 전달되지 않는 모습이었는데..
zuul의 디폴트 설정은 헤더와 관련된 모든 쿠키들을 필터링한다고 되어있었다. 👉 여기가 문제였음 !

그래서 마지막 문단에 리소스 서버에 쿠키 관련 헤더를 전달하려면 쿠키 관련 헤더 없이 재정의 해야 한다고 한다.

zuul:
  sensitiveHeaders: Authorization
  routes:

이런 식으로 재정의 해주었고 문제가 해결되었다. ⭐⭐⭐

📌 해결 후기

  • 며칠 내내 붙잡고 있었는데.. (잔디 빵꾸남)
  • 앞으로는 이렇게 해결이 좀 어려운 것이 있으면 정리해가면서 진행해야겠다.
  • 행복하다. 맛있는 거 먹어야지😉

📌 reference !

https://stackoverflow.com/questions/43625298/spring-session-sharing-between-zuul-and-resource-servers
https://velog.io/@albaneo0724/Spring-Redis%EB%A5%BC-session-storage%EB%A1%9C-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0

profile
공부 기록

0개의 댓글