앵귤러에서 리프레시 토큰으로 사용자 세션 관리하기
2024-12-31 04:11:16사용자 세션 관리를 위한 토큰 리프레시 워크플로우 이해하기
웹 애플리케이션에서 사용자 경험을 매끄럽게 유지하는 주요 요소 중 하나는 빈번한 로그인을 피하고, 사용자 세션을 관리하는 것입니다. 이러한 목표를 달성하는 한 가지 방법으로 토큰 리프레시(Refresh Token) 워크플로우가 사용됩니다. 이 항목에서는 Angular에서 이를 구현하는 방법과 401 오류를 처리하는 방법에 대해 알아보겠습니다.
토큰 리프레시의 정의와 필요성
토큰이란?
액세스 토큰은 사용자가 인증된 상태임을 서버에 증명하는 방식으로 이용됩니다. 하지만 보안상의 이유로 액세스 토큰은 만료 기간이 짧습니다. 만료된 후에는 서버에 다시 로그인하지 않고도 새로운 액세스 토큰을 요청할 수 있도록 리프레시 토큰이 사용됩니다.
리프레시 토큰과 Angular의 역할
Angular에서는 리프레시 토큰을 사용하여 만료된 액세스 토큰을 교체하고, 사용자에게 부드러운 경험을 제공합니다. 이 프로세스는 주로 Angular의 HttpInterceptor를 사용하여 구현됩니다.
Angular에서의 리프레시 토큰 구현
Angular의 HttpInterceptor를 사용하여 리프레시 토큰 워크플로우를 구현할 수 있습니다. 주요 목표는 401 Unauthorized 응답을 가로채어 새로운 토큰으로 요청을 재시도하는 것입니다.
구현 단계
- 요청 감지 및 가로채기: 인터셉터가 401 응답을 감지합니다.
- 토큰 리프레시: 리프레시 토큰을 사용하여 새 액세스 토큰을 서버에서 받아옵니다.
- 요청 재시도: 새로운 토큰으로 원래의 요청을 다시 시도합니다.
- 큐 관리: 토큰이 갱신되면 대기 중인 요청을 순차적으로 처리합니다.
토큰 리프레시 로직
Angular에서 리프레시 토큰 기능은 HttpInterceptor를 통해 'handleUnauthorized' 메소드를 사용하여 관리됩니다.
코드를 통한 예시
handleUnauthorized(
req: HttpRequest<any>,
next: HttpHandlerFn
): Observable<any> {
if (!this.isRefreshingToken) {
this.isRefreshingToken = true;
// 모든 대기 요청들에 갱신중임을 알립니다.
this.tokenSubject.next(null);
return this.refreshToken().pipe(
switchMap((newToken: string) => {
if (newToken) {
this.tokenSubject.next(newToken);
// 새 토큰으로 원래의 요청을 재시도합니다.
return next(this.addToken(req, newToken));
}
// 토큰 갱신 실패 시, 사용자 로그아웃 처리
this.logout();
return throwError(() => 'Token expired');
}),
catchError((error) => {
this.logout(); // 오류 발생 시 로그아웃
return throwError(() => error);
}),
finalize(() => {
this.isRefreshingToken = false; // 리프레시 플래그 초기화
}),
);
} else {
// 토큰 갱신 중에는 요청을 큐에 대기시킵니다.
return this.tokenSubject.pipe(
filter((token) => token != null),
take(1),
switchMap((token) => next(this.addToken(req, token))),
);
}
}
이 코드 구조의 핵심 요소
-
단일 갱신 요청 유지:
isRefreshingToken플래그를 사용하여 한 번에 하나의 갱신 요청만 발생하도록 합니다. 만약 토큰이 이미 갱신 중이라면, 후속 요청을 큐에 모으게 됩니다. -
토큰 갱신 요청 시작: 갱신 요청이 진행되지 않고 있을 경우,
refreshToken메소드를 호출하여 새로운 토큰을 가져옵니다. -
대기 중인 요청 처리: 새로운 토큰이 수신되어 발행되면, 원래의 요청을 새 토큰으로 재시도하고 대기 중인 요청들을 처리합니다.
오류 처리 전략
토큰 갱신 실패 혹은 예외 상황 발생 시:
- 사용자를 로그아웃 처리하여 보안을 유지합니다.
- 관련 오류 정보를 호출자에게 반환합니다.
후속 작업 및 정리
finalize 연산자를 사용하여 갱신 플래그를 해제하고, 향후 새 갱신 요청이 이루어질 수 있도록 합니다.
요청에 토큰 추가
새롭게 발급받은 토큰은 요청 헤더에 첨부됩니다. addToken 메소드를 사용하여 이를 구현할 수 있습니다.
addToken(request: HttpRequest<any>, token: string): HttpRequest<any> {
return request.clone({
setHeaders: {
'X-Token': token,
},
});
}
이러한 전반적인 프로세스는 모든 HTTP 요청을 안전하고 일관성 있게 관리하도록 보장합니다.
결론: 안전하고 매끄러운 사용자 경험
앵귤러에서의 강력한 토큰 리프레시 워크플로우는 보안과 사용자 경험을 동시에 높일 수 있습니다. 401 오류 처리 및 동시 요청 관리에 대한 효과적인 솔루션을 제공하여 애플리케이션의 신뢰성과 사용자 만족도를 높여줍니다.