약 두달간 진행한 프로젝트가 마무리 되었다!!!
오늘은 프로젝트 내에서 내가 맡은 부분 중 고민했던 부분들을 공유하는 포스팅을 해보려 한다.
간단히 프로젝트를 설명하자면, 가맹점주가 가맹점 관련 정보를 해당 서비스에 등록하면 일반 사용자는 네이버 지도 API 를 기반으로 한 가맹점 정보 조회 서비스를 이용할 수 있다. 또한 가맹점 정보는 OPEN API 를 통해서 외부에 제공된다.
프로젝트 이미지는 아래와 같다.
깃헙 링크는 아래에서~~
https://github.com/gugbab2/franchisee-management-program
이번 프로젝트에서는 크게 다음 2가지 역할을 수행했다.
- REST API 설계
- Spring Secutiry 를 사용한 권한 부여(JWT 토큰 사용)
- 나머지 자잘구리한 역할은 제외~~
고민점
DTO 구현 범위 설정
REST API 를 만들어 나가며 가장 많이 생각했던 부분이 아니었나 싶다.
처음에 채택했던 방식은, 모든 API return 에 따라 커스텀 하여 DTO 를 만들어 줬었다.
그런데 프로젝트를 진행하면 진행할수록 API 만 해도 수십개를 넘어가는데 하나하나 손수 DTO 를 만들어 주어야 한다는 것이 여간 성가신 일이 아니었다...
이를 해결하기 위해 두번째로 채택한 방식, 보안에 문제가 되지 않을 것 같은 필드값은 모두 노출시키는 DTO 를 만들어 범용적으로 사용하자는 것이었다. 하지만 이것도 만들고 보니,,, 뭐랄까 역할이 너무 중첩되는 느낌이랄까??
때문에 마지막으로 채택한 방식! 내부클래스로 다음 3가지 역할을 하는 DTO 를 만들어내자는 것이다!!
- POST Api에서 Request Payload를 매핑할 DTO
- GET Api에서 Return해줄 Response DTO
- 레이어를 옮겨다니거나 결과를 Return하기 위해 실제 User정보를 담은 DTO
구글링을 통해 발견한 방식으로 아주 깔끔하게 역할에 따라서 DTO 를 관리할 수 있게 되었다.
역시 구글링은 위대해~~
DTO를 관리할 수 있는 더 좋은 아이디어가 있다면 언제든지 이야기 해주시면 감사하겠다.. (한 수 부탁드립니다!!!)
자바를 사용하며 객체지향적이지 못한 설계
사실 가장 가슴아픈 부분이다.. 자바를 사용하면서 객체지향적이지 못한 설계라니..
이 부분을 알게 되었을 시점은 프로젝트 마무리를 앞 둔 시점이었다!
동료 조원의 피드백으로 API 를 수정하고 있었는데, 수정을 마무리한 뒤 실행을 시켜보니 다른 API 에서 또 다른 문제가 생겨나고 있었다..
보이는 그대로 코드가 독립적이지 못하고 종속적으로 설계되었다는 뜻이다.. 이 상황을 마주하고 얼마나 좌절했었는지 ,,
이 때 들었던 생각이 객체지향이 뭐지? 라는 생각이 처음으로 들었다.. 물론 그에 대한 시원한 대답을 하지 못하고 있던 상태였기에 부리나케 구글링을 통해 객체지향의 명서라 불리우는 조용호님의 "객체지향의 사실과 오해" 라는 책을 읽었다!
물론 초심자인 나의 입장으로 한번 읽고, 모든 내용을 이해하기란 쉽지 않았지만, 한가지 깨달은 지점이 있다. 그 깨달음은 다음과 같다.
- 객체지향을 제대로 설계하기 위해서는 각각의 객체의 자유도가 높아야 한다.
- 이를 위해 다형성을 기반으로 한 인터페이스를 통해 역할과 책임을 나누어야 한다.
(예를 들어, 연극에서 주인공의 역할은 인터페이스이고, 주의공의 책임을 가진 각각의 사람들은 클래스로 생각할 수 있다) - 인터페이스로 행동에 대한 가이드라인을 표시하고, 그를 상속받은 클래스를 통해 세부사항을 구현한다.
이를 기반으로 한 나의 API 설계 전략은 다음과 같다.
- 스프링에서 비지니스 로직을 처리하는 서비스단에서 공통되는 행동을 인터페이스로 묶는다.
- 서비스 클래스를 만들때에는 가장 먼저 해당 인터페이스를 상속받아 구현한다.
머랄까,, 그때 생각했을 때는 엄청난 깨달음은 얻은 듯 했지만, 막상 적어보니 상당히 별게 없다..
때문에! 이도 마찬가지로 좋은 아이디어가 있다면 언제든지 이야기 해주시면 감사하겠다.. (한 수 부탁드립니다!!!)
JWT 를 사용하며 선택했던 AccessToken / RefreshToken 전략
Spring Security 를 사용하며, 많이 사용 하는 JWT!
하지만 이 토큰 하나로 모든 인증이 통과 되버릴 수 있기 때문에 탈취되었을 때 전략은 필수적이다!
최근에 RefreshToken을 사용한다고 하지만 이 또한 단단한 전략이 없다면 별 의미가 없을 수 있다.
나는 기본적으로 유저 ID / AccessToken / RefreshToken 3가지 정보를 가진 토큰 테이블을 관리했고,
기본적으로 토큰 관리시간을 3분으로 짧게 설정했다. \
토큰을 탈취 당했을 때, 나의 전략은 다음 3가지 경우로 나뉠 수 있다.
- AccessToken 을 탈취 당했을 때 : AccessToken 과 매핑되는 RefreshToken을 가지고 있는지 확인한다.
- Refresh 토큰을 탈취 당했을 때 : RefreshToken과 매핑되는 AccessToken 을 가지고 있는지 확인한다.
- 두 개의 토큰 모두 탈취당했을 때 : AccessToken이 만료되지 않았는데, RefreshToken 을 사용해 AccessToken 을 재발급 받으려 한다면 부적절한 접근으로 판단, 모든 토큰을 초기화 시킨다.
물론 많은 전략들이 있지만 동일하게 볼 수 있는 것은, 100% 완벽한 보안 전략은 없다는 것이다.
개선할 부분이 있거나, 궁금한 사항들이 있다면 언제든지 이야기 부탁드린다.
프로젝트 총평
사실상 처음으로 해보는 프로젝트,, 그 안에서 다수의 조원들과 역할을 나누다 보니 많은 부분들을 담당할 수 없었다는 점을 매우 아쉽게 생각한다.
빨리 결과물을 만들어내야 한다는 부담감 때문에, 원리를 이해하려들지 않고 무작정 구글링의 결과를 복사했던 점, 그로인해 마주쳐야 했던 수많은 오류들, 무턱대고 코드부터 짜기 시작하는 않좋은 습관 등..
아쉬움 투성이지만, 실수를 통해 느끼고 반복하지 않으면 되다 생각하고, 수동적으로 수업을 듣는 과정보다, 실제로 익히는 과정 가운데 많은 성장을 했다고 느낀다.
부족함도 많이 느끼고, 아쉬움도 많으니 1달에 한번은 개인 프로젝트를 진행해 포스팅하며 생각을 정리하는 시간을 가져야겠다.
다음달에 새로운 포스팅으로 이야기 하겠다!
이상!