① 배운 것
socket.io를 이용해 소켓 연결을 했는데 연결이 안되는 이슈 발생!
연결이 안되는 코드
final chatSocket = IO.io(
Config.instance.socketBaseUrl+'/socket/io/somepath',
IO.OptionBuilder()
.setTransports(['websocket'])
.disableAutoConnect()
.build());
연결이 성공한 코드
final chatSocket = IO.io(
Config.instance.socketBaseUrl,
IO.OptionBuilder()
.setPath('/socket/io/somepath')
.setTransports(['websocket'])
.disableAutoConnect()
.build());
문제원인 :
baseurl과 path를 구분하지 않아서 경로를 찾지못함
socket.io에서 path는 서버의 소켓 연결 경로를 정의. path는 기본적으로 socket/io이고 이건 서버단과 일치해야한다.
추가적인 정보 :
처음에는 'socket/io/somepath'를 namespace에 넣어야 하는 줄 알았으나 그건 아니였다. namespace는 하나의 소켓 내에서도 여러 노드를 구분짓는 기능이다.
자세한 설명
문제 상황 : access token이 만료되면 refresh api로 토큰 리프래시 요청을 보내고 토큰 리프래시가 성공하면 이전 요청에 토큰을 갈아끼워서 다시 요청함 -> 이 로직을 try-catch로 잡고 있고 catch에 잡혔다는 것은 토큰 리프래시가 제대로 안되었다는 의미이므로 로그아웃 시킴 -> 그런데 토큰 리프래시가 잘 되어서 새로운 토큰을 넣고 다시 요청한 api에서 에러가 발생하면 로그아웃이 됨
문제 해결 : catch에 잡혔다는것은
1. 토큰 리프래시 api 실패
2. 토큰 리프래시가 잘 되어서 새로운 토큰으로 갈아끼워서 이전 api를 재요청 했는데 그 api에서 에러가남
이 두가지 경우가 있음
1번의 경우 토큰 리프래시가 잘 안되었다면 로그아웃 시킴
2번의 경우 정상적인 에러 반환일것이기 때문에 로그아웃 시키지 않음
void onError(DioException err, ErrorInterceptorHandler handler) async {
if (err.response?.statusCode == 401) {
//토큰 리프래시 및 이전 요청에 토큰 새로 갈아끼워서 요청 재시도
try {
/// 요청 재시도
final options = err.requestOptions;
options.headers.addAll({
'Authorization': 'Bearer $accessToken'
});
final response = await dio.fetch(options);
return handler.resolve(response);
}
on DioException
catch (e) {
//재시도한 api에 정상적인 에러(하루에 한번만 할 수 있는 행위를 여러번 요청 등)가 발생해도 여기도 떨어짐 -> 이때는 로그아웃 되면 안됨
//토큰 리프래시 api가 아닐경우에만 로그아웃 처리
//e-> catch한 에러(/refresh api에서 에러가 나면 /refresh 이고, 재요청 api에서 에러가 나면 재요청 api 주소임)
//err -> onError에서 받은 에러(토큰이 만료되어서 요청이 제대로 안된 api 즉, 재요청해야하는 api 주소)
if (!e.requestOptions.path.contains('/refresh')) {
return handler.reject(e);
}
/// 토큰 갱신 실패시 로그아웃 처리
return handler.reject(e);
}
}
return super.onError(err, handler);
}
② 회고 (restropective)
③ 개선을 위한 방법