[Project_] TD Trouble Shooting - 1
WebSocket을 사용한 Tower Defense 게임 만들기 트러블 슈팅
● 로그인/회원가입 웹 소켓으로 구현하는 과정에서...
○ 시도한 방법 : Redis에 모든 데이터를 담아서 관리
- Redis의 특징 중에 '빠르다'라는 것과 websocket = 실시간이라는 공식에 빠져서
무조건적인 Redis사용과 websocket 통신 방식으로 로그인/회원가입을 구현하려고 했다.
- 'Redis는 디스크가 아닌 메모리 기반의 데이터 저장소이다'
간과한 것이 있었는데, Redis는 디스크 기반에 SSD, HDD 같은 저장소에 저장하는 것이 아닌
RAM과 같은 용량이 적지만 속도가 빠른 저장소에 데이터가 저장되는 noSQL DBMS였던 것이다.
- 너무 webSocket 통신 방식으로만 구현하려고 해서 생각의 폭이 짧아졌다. 심지어 Redis로만 데이터베이스를
채택했다면 사용자의 회원가입 데이터가 일정 시간마다 사라져야할 것이다.
어떻게 해결했는가?
● 로그인/회원가입은 웹 서버 통신 방식으로 구현
○ 로그인/회원가입 하는 과정은 API로 구현하여 MySQL 및 Redis에 저장
- 민감한 데이터에 대해서는 영속적으로 데이터를 저장하고 Redis에 장애가 생겼을 때, 대처할 수 있다
○ MySQL DB에 회원가입할 때 입력한 데이터 저장하는 방법 채택
Redis는 사용자의 접속 기록 및 세션 정보를 저장하는데 사용
- MySQL을 사용함으로써 사용자의 데이터가 일정 시간마다 사라지는 것을 방지
- 사용자가 삭제 요청하지 않는 한 계속해서 영구적으로 데이터가 존재할 수 있도록 MySQL 사용
- Redis에는 사용자가 로그인할 때 MySQL에 있는 데이터를 가져와 사용하고 로그인했을 때 Redis에 접속 기록 저장
- Redis에 저장할 때는 Hash type으로 저장해서 noSQL에서도 표 형식으로 볼 수 있도록 구현


- ip를 기록함으로써 중복 로그인을 방지할 수 있다.
클라이언트에서 인증에 대한 부분은?
● Client에서 input에 값을 입력했을 때 그에 대한 정보를 Server에 전송
○ 회원가입
1) Server는 해당 데이터를 받아서 account-router에서 처리
2) 받아온 데이터를 prisma를 사용하여 mysql에 저장!

○ 로그인
1) Client에서 input 필드에 회원가입할 때 사용했던 이메일과 비밀번호 입력
2) Server에 input 값을 보내고 DB에 저장된 데이터와 비교
3) 성공 시 토큰을 반환하고 로그인해서 필요한 권한 부여

// routes/account-router.js
// router.post('/login'...)
// JWT 생성
const token = jwt.sign(
{ userId: user.id, email: user.email },
process.env.JWT_SECRET || 'default_secret_key',
{ expiresIn: '1h' },
);
- Redis에 저장되는 데이터들은?
// routes/account-router.js
// router.post('/login'...)
// Redis에 세션 데이터 저장 (Hash 형식)
await redisClient.hSet(sessionKey, {
userId: user.id,
email: user.email,
ip: clientIp,
loginTime: new Date().toISOString(),
token,
});

- TTL 설정으로 데이터는 설정한 시간이 지나면 사라진다.

- Hash key:value 값은 session:'email'

이번에 확실하게 배운 것
● '실시간'이라고 해서 무조건적으로 socket 통신을 사용하는 것은 좋지 않다.
● 적절하게 사용하는 것이 가장 중요하며 로그인/회원가입의 경우에는 데이터 저장에는
굳이 Redis를 고집할 이유가 없었다.
● 빠르다고 좋은 것은 아니며, 반영구적으로 저장해야하는 데이터는 mySQL를 적절히 사용해야 할 거 같다.