그간 팀프로젝트를 하느라 바빠 오랜만에 글을 써봅니다.
이번 주제는 팀프로젝트를 하는동안 만났던 문제점과 그 문제를 해결한 방법에대해 써볼까 합니다.
제가 네이버클라우드 캠프에서 팀원들과 했던 프로젝트는 SpringBoot와 Thymeleaf를 사용하는 Server Side Rendering 방식의 웹 어플리케이션이였습니다.
서버사이드렌더링 방식은 Front-end와 Back-end가 구분되어 있는 구조가 아닌
1. 서버측에서 필요한 데이터를 준비하고
2. 해당 데이터를 Model 객체에 담아 템플릿 엔진을 사용해 HTML 파일에 데이터를 그려낸후,
3. 클라이언트의 요청에 대한 응답으로 정적 파일(HTML, CSS, JAVASCRIPT)을 내려주는 방식을 말합니다.
그림으로 나타내면 다음과 같죠
이때, 문제가 있었습니다.
Json Web Token을 활용한 SpringSecurity를 적용하려면 클라이언트의 매 요청의 헤더에 AccessToken을 담아야 하는데
클라이언트측에서 페이지를 이동하거나, 어떤 데이터를 삽입, 변경하는 등의 요청을 보내는 것을 JavaScript의 Ajax요청을 통해서 하는 것이 아닌 HTML파일에 쓰여진 <a>태그나 <form> 태그를 통해서 한다는 것이죠.
만약, 모든 요청을 Ajax를 사용해 처리한다면, Ajax 요청은 페이지를 이동하지 않고 새로운 요청을 보내고 응답의 결과로 객체나 json을 받기 위해 사용하다 보니
이러지도 저러지도 못하는 상황에 직면하게 되었습니다.
그래서 고민을 한참 하던중 SpringBoot의 본래 사용 목적이 RestfulAPI를 구현한 백엔드 구축이라는 것을 알게 되었습니다.
즉, 백엔드와 프론트엔드가 구분되어있는 형태의 앱이 SpringBoot의 본래 목적과 가장 잘 부합한다는 것을 알게 되었습니다.
또한 프론트엔드와 백엔드를 분리하게 된다면 서버에 보내는 모든 요청을 Ajax로 처리하고 헤더에도 AccessToken을 담을 수 있으므로 좀더 자유롭고 유연하게 요청과 응답을 처리할 수 있다는 장점을 알 수 있었습니다.
따라서 프론트엔드와 백엔드를 분리하는것을 피할 수 없게 되었습니다.
(문제를 직면했을때 부터 프론트와 백을 분리하면 문제를 해결할 수 있다는 걸 알았지만 기존의 방식에서 토큰을 헤더에 담을 수 없을까 고민을 많이 했었습니다...
나중에 쿠키에 token을 담을 수 있다는 것을 알게 되었습니다..
또한 SSR 방식에서는 JWT보다 코드의 복잡성과 생산성의 문제로 세션 방식이 더 선호된다고 합니다.)
그래서 프론트와 백을 분리한 후 이렇게 되었습니다.
어플리케이션 아키텍처로는 다음과 같죠
AccessToken을 매요청의 헤더에 담는 방법도 Axios의 Inteceptor기능을 활용하니 손쉽게 해결할 수 있었습니다.
const axiosInstance = axios.create();
// 요청 인터셉터 설정: 매 요청마다 sessionStorage에서 accessToken을 가져와서 헤더에 설정
axiosInstance.interceptors.request.use(
(config) => {
const token = sessionStorage.getItem('accessToken');
if (token) {
config.headers['Authorization'] = `Bearer ${token}`;
}
return config;
},
(error) => {
return Promise.reject(error);
}
);
요렇게 특정 상태코드에 대해서는 일괄적으로 에러 처리도 가능했습니다.
// 전역 에러 핸들러 추가
axiosInstance.interceptors.response.use(
(response) => {
return response;
},
(error) => {
if (error.response.status === 403) {
Swal.fire({
icon: "error",
title: "등록되지 않은 사용자입니다.",
showConfirmButton: false,
timer: 1500
});
// 특정 작업 수행
} else if (error.response.status === 401) {
Swal.fire({
icon: "error",
title: "권한이 없습니다.",
showConfirmButton: false,
timer: 1500
});
}
return Promise.reject(error);
}
);
다만 한가지 아쉬웠던 점은 토큰을 SessionStorage가 아닌 HttpOnly 쿠키에 담고 싶었는데 https를 사용하지 않으면 사용할 수 없다고 하더라구요..
HttpOnly 쿠키는 자바스크립트 코드에서 절대 접근하지 못한다고 합니다 따라서 보안에 훨씬 좋다고..
다음에 기회가 되면 한번 다뤄봐야겠습니다
긴글 읽어주셔서 감사합니다~
'Java' 카테고리의 다른 글
사용자가 여러번 클릭할 수 있는 버튼에 대한 요청을 보내는 시점 문제 (0) | 2024.05.29 |
---|---|
[Java] 간단한 ConnectionPool 구현 해보기(JDBC Driver, Connection) (0) | 2024.02.21 |