Ably JWT를 활용한 코드 활용 예시
Ably JWT Auth 방식
서비스에 로그인 할 때, 백엔드에서 ABLY_KEY를 통해 Ably.io에 requestToken을 하게됩니다. (위의 그림에서 1, 2의 단계에 해당)
리턴된 ably token을 payload에 {"x-ably-token" : 리턴된 ably 토큰 값}의 형식으로 담아 JWT 토큰을 발급하여 유저에게 리턴합니다. 유저는 이때 리턴된 토큰 값을 바탕으로 ably platform과 통신합니다.(위의 그림에 순서대로 3, 4, 5 단계에 해당)
Code 예시
백엔드
- auth.service.ts
import { ConflictException, Injectable } from '@nestjs/common';
import { JwtService } from '@nestjs/jwt';
import { hash } from 'bcryptjs';
import { User } from 'src/users/user.entity';
import { UsersService } from 'src/users/users.service';
@Injectable()
export class AuthService {
constructor(
private readonly usersService: UsersService,
private readonly jwtService: JwtService,
) {}
...... 중략 ......
async login(userId: number) {
const user = await this.usersService.findById(userId);
const Ably = require('ably');
var ably = new Ably.Rest.Promise({ key: process.env.ABLY_SECRET_KEY });
const token = await ably.auth.requestToken({
clientId: user.email,
});
const payload = { sub: userId, 'x-ably-token': token.token };
return { token: this.jwtService.sign(payload) };
}
async reAbly() {
const Ably = require('ably');
var ably = new Ably.Rest.Promise({ key: process.env.ABLY_SECRET_KEY });
const token = await ably.auth.requestToken();
return token;
}
}
- auth.controller.ts
@Public()
@Get('/re-create')
async reCreate() {
return this.service.reAbly();
} /// 해당 코드를 Auth Controller안에 추가
- messages.service.ts( 이 부분은 앞전의 포스트와 동일합니다.)
import { Injectable } from '@nestjs/common';
import { TypeOrmService } from '../common/typeorm.service';
import { Message } from './message.entity';
@Injectable()
export class MessagesService extends TypeOrmService(Message) {
..... 중략 ......
async createMessage(userId: number, roomId: string, message: string) {
this.publishMessage(userId, roomId, message);
return this.repository.save({ roomId, userId, message });
}
publishMessage(userId: number, roomId: string, chat: string) {
const Ably = require('ably');
const ably = new Ably.Rest(process.env.ABLY_SECRET_KEY);
const channel = ably.channels.get(roomId);
channel.publish(userId.toString(), chat);
}
}
프론트엔드
- ChatPage.tsx 혹은 채팅창 컴포넌트 or 페이지
import Ably from 'ably/promises';
import { Types } from 'ably';
export const ChatPage = () => {
const { id } = useParams<{ id: string }>();
const [client, setClient] = useState<Ably.Realtime>();
const [channel, setChannel] = useState<Types.RealtimeChannelPromise>();
const [chat, setChat] = useState('');
...... 중략 ......
useEffect(() => {
if (client) return;
const _client = new Ably.Realtime({
token: localStorage.getItem('token') ?? '',
authUrl: `${process.env.REACT_APP_API_URL}auth/re-create`,
transports: ['web_socket'],
});
setClient(_client);
}, [client]);
useEffect(() => {
if (!client || channel || !room) return;
const _channel = client.channels.get(room.id);
_channel.subscribe(() => refetchMessage());
setChannel(_channel);
return () => _channel.unsubscribe();
}, [client, channel, room]);
const createMessage = async (message: string) => {
return await api.post(`/rooms/${room?.id}/message`, { message });
};
...... 중략 ......
};
Realtime()의 옵션에 대해서 간략하게 설명해보면
token: localStorage.getItem('token') ?? ' '
부분은 발급받은 토큰을 불러오고 없을시 ' '로 처리하는 옵션
authUrl: ${process.env.REACT_APP_API_URL}auth/re-create
은 ably 토큰이 만료될 시, 재발급 받는 옵션
transports: ['web_socket']
은 ably-transport-preference을 web_socket으로 고정시키는 옵션이다.
위와 같이 코드를 넣으면 Ably token 방식으로 ably 채팅 서비스가 작동하는 것을 확인할 수 있다.
마치면서
Ably.io 라는 리얼타임 서비스를 이번에 PCUP 서비스를 만들면서 처음 써보았는데 한국어로 된 기술 블로그도 없고, 공식 문서가 생략해버린 부분이 꽤 있었지만, 이러한 새로운 서비스를 활용해보는 경험 또한 값진 것 같다. 추후 채팅을 제외한 iot, 혹은 GPS, Live-Update 등을 활용할 기회가 있다면 이번 시리즈에 추가할 예정이다.
Author And Source
이 문제에 관하여(Ably JWT를 활용한 코드 활용 예시), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@oustin/Ably-JWT저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)