$ sudo apt-get update
$ sudo apt-get install redis-server
위 명령어로 설치
$ redis-server --version
레디스 버전이 잘 뜨면 설치가 된 것
redis.conf 파일을 수정하면 최대 사용 메모리양을 정하고 최대 사용 메모리를 초과하게 될때 데이터를 어떻게 삭제할지를 정의할 수 있음
$ sudo vi /etc/redis/redis.conf
# 생략 ..
maxmemory 1g // 최대 사용 메모리
maxmemory-policy allkeys-lru // 초과시 가장 오래된 데이터 삭제
# 생략 ..
설정 후 서버 재시작
$ sudo systemctl restart redis-server.service
$ netstat -nlpt | grep 6379
6379는 redis 기본 포트. 잘 동작 되는지 확인 가능
아래 명령어로 redis 서버에 접속 가능
$ redis-cli
set으로 키에 값을 저장할 수 있고 get으로 키에 해당하는 값을 불러올 수 있음
keys로 저장된 key를 불러올 수 있음 → 검색어가 포함된 key들을 조회
keys *로 전체 키 조회
del로 key 삭제
> set [key] [value]
> get [key]
> keys *검색어*
> keys *
> del [key]
+) password 설정
다시 설정 파일을 수정해준다.
$ sudo vi /etc/redis/redis.conf
그 후 다음과 같은 설정을 추가한다
requirepass PASSWORD
PASSWORD 부분을 본인의 패스워드로 바꿔서 입력해주면 된다.
:wq! 로 저장하고 빠져나온 후 서비스 재시작
systemctl restart redis-server.service
그럼 이제 갑자기 재시작부터 비밀번호를 물어본다.
그리고 redis-cli로 들어가서 명령어를 실행하려고 해도 안됨
redis-cli 내에서 다음 명령어로 권한을 얻을 수 있다.
AUTH 비밀번호
그러면 권한을 얻고 명령어 실행 가능
redis-cli로 접속을 할 때마다 AUTH 입력을 해줘야 한다.
it('POST, GET /auth/redis', async () => {
const randomeBytes = Math.random().toString(36).slice(2, 10);
const key = randomeBytes;
const value = randomeBytes;
await request(app.getHttpServer())
.post('/auth/redis')
.send({ key, value })
.expect(201);
const response = await request(app.getHttpServer())
.get(`/auth/redis?key=${key}`)
.expect(200);
expect(response).toHaveProperty('body');
const redisValue = response.body;
expect(redisValue).toBe(value);
});
임의의 key와 value를 정하고 그것을 post로 redis에 저장한 후, get으로 찾아와서 맞는지 검증하는 테스트
$ yarn workspace server add ioredis
// config/redis.config.ts
import { configDotenv } from 'dotenv';
configDotenv();
export const redisConfig = {
host: process.env.REDIS_HOST,
port: parseInt(process.env.REDIS_PORT),
password: process.env.REDIS_PASSWORD,
};
// auth/redis.repository.ts
import Redis from 'ioredis';
import { Injectable } from '@nestjs/common';
import { redisConfig } from 'src/config/redis.config';
@Injectable()
export class RedisRepository {
private readonly redisClient: Redis;
constructor() {
this.redisClient = new Redis(redisConfig);
}
async get(key: string) {
return this.redisClient.get(key);
}
async set(key: string, value: string) {
return this.redisClient.set(key, value);
}
}
// auth/auth.service.ts
import ...
@Injectable()
export class AuthService {
constructor(
@InjectRepository(User)
private readonly authRepository: Repository<User>,
private readonly jwtService: JwtService,
private readonly redisRepository: RedisRepository, // RedisRepository 연결
) {}
// 생략 ..
async getValueFromRedis(key: string) {
return this.redisRepository.get(key);
}
async setValueToRedis(key: string, value: string) {
return this.redisRepository.set(key, value);
}
}
// auth/auth.controller.ts
import ...
@Controller('auth')
@ApiTags('인증/인가 API')
export class AuthController {
constructor(private readonly authService: AuthService) {}
// 생략 ..
@Get('redis')
getValueFromRedis(@Query('key') key: string) {
return this.authService.getValueFromRedis(key);
}
@Post('redis')
setValueToRedis(@Body() { key, value }: { key: string; value: string }) {
return this.authService.setValueToRedis(key, value);
}
}
이렇게 까지 하고 서버 실행을 했더니 다음과 같은 오류가 발생
[ioredis] Unhandled error event: Error: connect ECONNREFUSED 172.16.147.132:6379
at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1595:16)
Redis 연결이 실패해서 생긴 오류이다.
예전에 MySQL 연결할 때에도 비슷한 오류를 겪었던 기억이 있어서 바로 해결책이 생각이 났다.
설정 파일에서 bind를 수정해주면 아마 해결될 것으로 예상이 되었다.
다시 Redis 설정을 수정해주자.
$ sudo vi /etc/redis/redis.conf
여기에 bind 옵션을 다음과 같이 수정해 주었다.
그러니 드디어 실행이 잘 되었다!!
Good~~
근데 테스트 코드가 통과가 안됨
ㅜㅜ???
api가 잘 뚫렸는데 테스트 코드가 잘 통과하지 않는 이유가 뭐지
● Test suite failed to run
Cannot find module 'src/config/redis.config' from '/Users/songjs/projects/boostcamp/membership/web16-B1G1/packages/server/src/auth'
Require stack:
src/auth/redis.repository.ts
src/auth/auth.service.ts
src/auth/auth.module.ts
src/app.module.ts
test/auth/auth.e2e-spec.ts
1 | import Redis from 'ioredis';
2 | import { Injectable } from '@nestjs/common';
> 3 | import { redisConfig } from 'src/config/redis.config';
| ^
4 |
5 | @Injectable()
6 | export class RedisRepository {
at resolveSync (../../.yarn/cache/resolve-patch-4254c24959-0446f02443.zip/node_modules/resolve/lib/sync.js:111:15)
at Object.require (src/auth/redis.repository.ts:3:1)
at Object.require (src/auth/auth.service.ts:15:1)
at Object.require (src/auth/auth.module.ts:2:1)
at Object.require (src/app.module.ts:4:1)
at Object.<anonymous> (test/auth/auth.e2e-spec.ts:4:1)
redis와 관련 없는 다른 테스트들까지 위와 같은 오류가 발생한다.
redis.config를 찾지 못한다?
// redis.repository.ts
import Redis from 'ioredis';
import { Injectable } from '@nestjs/common';
import { redisConfig } from '../config/redis.config'; // 이 부분 문제였음
@Injectable()
export class RedisRepository {
private readonly redisClient: Redis;
constructor() {
this.redisClient = new Redis(redisConfig);
}
async get(key: string) {
return this.redisClient.get(key);
}
async set(key: string, value: string) {
return this.redisClient.set(key, value);
}
}
저기 Import redisConfig 한 부분의 경로가 위에처럼 되어야 하는데 ‘src/config/redis.config’로 되어있었음
WebStorm 자동완성이 이런 실수를 하다니..
어쨌든 저렇게 고치니 해결됨!
근데 정작 중요한 테스트 코드가 통과가 되지 않음..
expect(received).toBe(expected) // Object.is equality
Expected: "duc3lccr"
Received: {}
response의 body에 키에 대한 값이 담겨오지 않았다는 것.
뭐지?
분명 postman으로 조회를 하면 body에 값이 담겨온다.
그래서 일단 테스트 코드 내의 response를 console.log로 찍어보았다.
너무 길어서 보기 힘들었다..
근데 postman을 보던 중 /board에 대한 GET 요청의 응답은 다음과 같이 body 타입이 JSON이었다.
근데 Redis의 GET 요청의 응답은 저 위에 사진에서 보이듯 HTML이었다.
그래서 다음과 같이 RedisService의 리턴 값을 조금 바꿔보았다.
async getValueFromRedis(key: string) {
const value = await this.redisRepository.get(key);
return {
value,
};
}
그러니 Redis GET요청 응답의 body 또한 JSON 타입으로 변했다.
it('POST, GET /auth/redis', async () => {
const randomeBytes = Math.random().toString(36).slice(2, 10);
const key = randomeBytes;
const value = randomeBytes;
await request(app.getHttpServer())
.post('/auth/redis')
.send({ key, value })
.expect(201);
const response = await request(app.getHttpServer())
.get(`/auth/redis?key=${key}`)
.expect(200);
expect(response).toHaveProperty('body');
const responseValue = response.body.value; // value를 가져오게 수정
expect(responseValue).toBe(value);
});
그러고 테스트 코드를 살짝 수정하고 비교하니 통과하였다. ㅎㅎ
후,, 해결법을 찾기 어려웠을 것 같은데 찾아서 다행이다.
이렇게 대충 Redis 연결은 된 것 같다!
마지막에 값을 수정한건 컴퓨터와 회선마다 값이 달라지나요 아니면 저 값이 디폴트인데 아무것도 주어지지 않았다는 가정하에 찾아가는건가요?