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 다운로드
$ wget <https://download.redis.io/releases/redis-6.0.10.tar.gz>
다운 받은 Redis 파일의 압축 해제
$ tar -xzf redis-6.0.10.tar.gz
압축을 해제한 Redis 디렉토리로 이동
$ cd redis-6.0.10
Redis를 컴파일
( make - 소스 코드에서 실행 파일을 만드는 명령어 )
$ make
Redis 서버 시작
$ src/redis-server
src/redis-server
에 생성된 바이너리의 이름을 변경하여 아래 프로젝트 경로에 추가
src/main/resources/binary/redis/{redis mac arm 바이너리 파일}
아키텍처에 따라 다르게 실행될 수 있도록 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
클래스에 대한 자세한 내용들은 아래 포스팅을 참고해주세요.