[Redis] Can't start redis server. Check logs for details 에러

현주·2023년 6월 29일
0

Trouble Shooting

목록 보기
24/29

🔥 문제

JWT를 활용한 Spring Security를 작업하면서 로그아웃 기능을 구현하기 위해 Redis를 Spring에 적용한 후,

로컬 환경과 테스트에서 사용할 Embedded Redis까지 적용하였다.

테스트까지 잘 통과해서 홀가분한 마음으로 풀 리퀘스트를 날리고 머지를 했는데,

윈도우를 사용하는 팀원들은 괜찮았지만, Mac(M1)을 사용하는 팀원은 아래와 같은 에러를 만났다.

Caused by: java.lang.RuntimeException: Can't start redis server. Check logs for details.

💡 원인

Redis는 M1의 ARM 프로세서 아키텍처에서 실행되는 것을 지원하지 않는 것이 원인이었다.

Embedded Redis는 애플리이션이 실행될 때 자동으로 시작되고, 애플리케이션이 종료될 때 Redis도 종료되는데,
Redis가 ARM 프로세서 아키텍처에서 실행되지 않기 때문에 M1에서 Embedded Redis를 실행할 수 없었던 것이었다.


☘️ 해결

Embedded Redis 라이브러리를 봐도 mac_arm64 바이너리가 없으므로,
문서에서는 직접 바이너리를 지정해 사용하는 방법을 권장한다.

✔️ Redis 소스 코드 컴파일

  1. Redis 다운로드

    $ wget <https://download.redis.io/releases/redis-6.0.10.tar.gz>
  2. 다운 받은 Redis 파일의 압축 해제

    $ tar -xzf redis-6.0.10.tar.gz
  3. 압축을 해제한 Redis 디렉토리로 이동

    $ cd redis-6.0.10
  4. Redis를 컴파일
    ( make - 소스 코드에서 실행 파일을 만드는 명령어 )

    $ make
  5. Redis 서버 시작

    $ src/redis-server
  6. src/redis-server에 생성된 바이너리의 이름을 변경하여 아래 프로젝트 경로에 추가
    src/main/resources/binary/redis/{redis mac arm 바이너리 파일}

  7. 아키텍처에 따라 다르게 실행될 수 있도록 EmbeddedRedisConfig 클래스에 설정 추가
    ( 우리 프로젝트의 경우 LocalRedisConfig 클래스임 )

@Slf4j
@Profile("!prod")
@Configuration
public class LocalRedisConfig {
    @Value("${spring.redis.port}")
    private int redisPort;

    private RedisServer redisServer;

    @PostConstruct
    public void redisServer() throws IOException {
        int port = isRedisRunning() ? findAvailablePort() : redisPort;
        
        // 현재 시스템이 ARM 아키텍처인지 확인 
        if (isArmArchitecture()) {
            // ARM 아키텍처가 맞다면, RedisServer 클래스를 사용하여 Redis 서버를 생성
            System.out.println("ARM Architecture");
            redisServer = new RedisServer(Objects.requireNonNull(getRedisServerExecutable()), port);
            // getRedisServerExecutable() - ARM 아키텍처에서 Redis Server를 실행할 때 사용할 Redis Server 실행 파일을 가져오는 메서드
            // ( 가져올 파일이 없는 경우 예외를 던짐 )
        } else {
            // ARM 아키텍처가 아니라면, RedisServer.builder()를 사용하여 Redis 서버를 생성
            redisServer = RedisServer.builder()
                    .port(port)
                    .setting("maxmemory 128M")
                    .build();
        }
        
        redisServer.start();
    }

    .
    .
    
    // Arm 아키텍처가 맞는지 확인하는 메서드
    private boolean isArmArchitecture() {
        return System.getProperty("os.arch").contains("aarch64");
    }
    
    .
    .
    .
}

위의 if문에서 Arm 아키텍처인지 확인하고
맞다면 Redis 실행파일과 port 번호를 넣은 RedisServer를 생성함으로써 문제를 해결
하였고,

이렇게 설정 후에 M1을 사용하는 팀원분이 실행해보았는데 에러없이 잘 작동하는 것을 알 수 있었다 !

📌 Redis를 이용한 로그아웃 구현과 LocalRedisConfig 클래스에 대한 자세한 내용들은 아래 포스팅을 참고해주세요.

0개의 댓글