[패스트캠퍼스 X 야놀자: 백엔드 개발 부트캠프] Security&JWT 토이 프로젝트 후기

정의정·2023년 11월 23일
1

FC

목록 보기
5/6
post-thumbnail

나는 2023. 07. 10 ~ 2024. 01. 30 기간동안 내일배움카드로 수강하는 국비지원교육 중 K-digital training(패스트캠퍼스 X 야놀자: 백엔드 개발 부트캠프 4기)에 참여하고 있다.

💡 토이 프로젝트 3

토이 프로젝트는 총 세 단계로 진행된다.
1 단계 : 09. 04 ~ 09. 10
2 단계 : 10. 23 ~ 10. 29
3 단계 : 11. 10 ~ 11. 16

지난 주 11. 10 ~ 11. 16 토이 프로젝트 3단계를 진행했다.
이번 토이 프로젝트를 어떻게 진행했고, 어떤 어려움이 있었는지 후기를 남겨보려고 한다.

🌟 Security & JWT 토이 프로젝트

이번 토이 프로젝트는 Security와 JWT를 사용하여 인증 인가 기능을 추가하여 여행 여정을 기록하고 관리하는 SNS 서비스를 개발하는 프로젝트였다.
지난 2단계 토이 프로젝트와 같은 팀원들과 진행하였고, 이번에도 조장으로 활동하여 프로젝트를 총괄하며 회의 및 개발을 수행했다.

요구사항 분석🧐

  • Spring Security를 기반으로 회원(사용자)가 추가됩니다.
  • 회원은 인증/인가에 따라 기능을 사용할 수 있어야 합니다.
  • 여행 정보에는 ‘좋아요’ 갯수와 ‘댓글’ 기능이 추가로 포함되어야 합니다.
  • 각 회원들은 본인이 ‘좋아요’를 누른 여행 리스트를 조회할 수 있습니다.
  • 레이어별 (Controller, Service, Repository) 테스트 케이스를 각각 작성해야 합니다.
  • 네이버맵, 카카오맵, 구글맵 API를 활용하여 여정 정보를 표현해야 합니다.

기능 명세서 작성✏️

RFP와 지난 프로젝트 기능 명세서를 참고하며 작성했다.

API 설계와 역할 분담👥

기능명세서에서 확인할 수 있듯 각 기능을 누가 구현할 것인지는 회의를 통해 정했다.

프로젝트 일정📅

프로젝트 일정은 아래 이미지와 같이 수행되었다.

DB 설계 (ERD + Class Diagram)💾

지난 번과 마찬가지로 JPA 상속 관계 매핑에 SINGLE TABLE 전략을 사용했다.
여기에서 확인 가능하다.

ERD

패키지 구조 설계📁

DDD(Domain Drivn Design)과 MVC구조를 살려 패키지를 설계했다.

main
	├── java
	│   │   
	│   ├── docs/asciidoc
	│   │   
	│   ├── domain
	│   │   ├── trip
	│   │   │   ├── controller
	│   │   │   │   ├── TripRestController
	│   │   │   │   └── TripRestControllerAdvice
	│   │   │   ├── dto
	│   │   │   │   └── request
	│   │   │   │   │   └── GetTripRequestDTO
	│   │   │   │   │   └── PostTripRequestDTO
 	│   │   │   │   │   └── TripPageRequestDTO
	│   │   │   │   │   └── UpdateRequestDTO
	│   │   │   │   └── response
	│   │   │   │       ├── GetTripResponseDTO
	│   │   │   │       ├── GetTripsResponseDTO
	│   │   │   │       ├── TripResponseDTO
	│   │   │   │       └── TripsResponseDTO
	│   │   │   ├── entity
	│   │   │   │   └── Trip
	│   │   │   ├── Repository
	│   │   │   │   └── TripCustomRepository
	│   │   │   │   └── TripCustomRepositoryImpl
	│   │   │   │   └── TripRepository
	│   │   │   ├── exception
	│   │   │   │   ├── InvalidPagingRequestException
	│   │   │   │   └── InvalidTripDateRangeException
	│   │   │   │   └── NotTripAuthorException
	│   │   │   │   └── TripNotFoundException
	│   │   │   │   └── WrongTripEndDateException
	│   │   │   │   └── WrongTripStartDateException
	│   │   │   └── service
	│   │   │       └── TripService
	│   │   │ 
	│   │   └── itinerary
	│   │   │   ├── controller
	│   │   │   │   ├── ItineraryRestController
  	│   │   │   │   └── ItineraryRestControllerAdvice
	│   │   │   ├── dto
	│   │   │   │   └── request
	│   │   │   │   │   └── create
	│   │   │   │   │   │   ├── AccomodationCreateRequestDTO  
	│   │   │   │   │   │   ├── TransportationCreateRequestDTO
	│   │   │   │   │   │   └── VisitCreateRequestDTO
	│   │   │   │   │   └── update
	│   │   │   │   │       ├── AccomodationUpdateRequestDTO  
	│   │   │   │   │       ├── TransportationUpdateRequestDTO
	│   │   │   │   │       └── VisitUpdateRequestDTO 
	│   │   │   │   └── response
	│   │   │   │       └── get
	│   │   │   │       │   ├── GetAccomodationResponseDTO  
	│   │   │   │       │   ├── GetTransportationResponseDTO
	│   │   │   │       │   └── GetVisitResponseDTO  
	│   │   │   │       ├── AccomodationResponseDTO  
	│   │   │   │       ├── ItineraryDeleteResponseDTO
	│   │   │   │       ├── ItinerarySearchResponseDTO
	│   │   │   │       ├── TransportationResponseDTO
	│   │   │   │       └── VisitResponseDTO  
	│   │   │   ├── entity
	│   │   │   │   └── Itinerary
	│   │   │   │   └── Accommodation
	│   │   │   │   └── Transportation
	│   │   │   │   └── Visit
	│   │   │   ├── exception
	│   │   │   │   ├── InvalidItineraryException
	│   │   │   │   └── ItineraryNotFoundException
	│   │   │   │   └── NotItineraryAuthorException
	│   │   │   ├── Repository
	│   │   │   │   └── ItineraryRepository
	│   │   │   │   └── AccommodationRepository
	│   │   │   │   └── TransportationRepository
	│   │   │   │   └── VisitRepository
	│   │   │   └── service
	│   │   │       └── ItineraryService 
	│   │   │ 
	│   │   └── member
	│   │   │   ├── controller
	│   │   │   │   ├── MemberRestController
  	│   │   │   │   └── MemberRestControllerAdvice
	│   │   │   ├── dto
	│   │   │   │   └── SignInRequestDTO
	│   │   │   │   └── SingUpRequestDTO
	│   │   │   │   └── SignUpResponseDTO
	│   │   │   │   └── jWtResponseDTO
	│   │   │   ├── entity
	│   │   │   │   └── Member
	│   │   │   ├── exception
	│   │   │   │   ├── ExistingMemberException
	│   │   │   │   └── InvalidJwtException
	│   │   │   │   └── InvalidMemberException
	│   │   │   ├── Repository
	│   │   │   │   └── MemberRepository
	│   │   │   └── service
	│   │   │       └── MemberService 
	│   │   │ 
	│   │   └── comment
	│   │   │   ├── controller
	│   │   │   │   ├── CommentRestController
    │   │   │   │   └── CommetRestControllerAdvice
	│   │   │   ├── dto
	│   │   │   │   └── request
	│   │   │   │   │   └── CommmentCreateRequestDTO
	│   │   │   │   │   └── CommentUpdateRequestDTO
	│   │   │   │   └── response
	│   │   │   │       ├── CommentDeleteResponseDTO
	│   │   │   │       └── CommentResponseDTO
	│   │   │   ├── entity
	│   │   │   │   └── Comment
	│   │   │   ├── exception
	│   │   │   │   ├── CommentDeletedException
	│   │   │   │   └── CommentMemberNotFoundException
	│   │   │   │   └── CommentNotFoundException
	│   │   │   ├── Repository
	│   │   │   │   └── CommentRepository
	│   │   │   └── service
	│   │   │       └── CommentService 
	│   │   │ 
	│   │   └── like
	│   │   │   ├── controller
	│   │   │   │   ├── LikeRestController
    │   │   │   │   └── LikeRestControllerAdvice
	│   │   │   ├── dto
	│   │   │   │   └── request
	│   │   │   │   │   └── LikeRequestDTO
	│   │   │   │   └── response
	│   │   │   │       └── LikeResponseDTO
	│   │   │   ├── entity
	│   │   │   │   └── Like
	│   │   │   ├── exception
	│   │   │   │   └── LikeNotFoundException
	│   │   │   │   └── LikeUnauthorizedException
	│   │   │   ├── Repository
	│   │   │   │   └── LikeCustomRepository
	│   │   │   │   └── LikeCustomRepositoryImpl
	│   │   │   │   └── LikeRepository
	│   │   │   └── service
	│   │   │       └── LikeService 
	│   │   │ 
	│   ├── global
	│   │    ├── common
	│   │    │   └── BaseTimeEntity
	│   │    │   └── ResponseDTO
	│   │    ├── config
	│   │    │   │   └── jwt
	│   │    │   │       └── CustomUserDetails
	│   │    │   │       └── CustomUserDetailsService
	│   │    │   │       └── JwtAuthenticationFilter
	│   │    │   │       └── JwtTokenProvider
	│   │    │   └── JpaAuditConfiguration
	│   │    │   └── PasswordEncoderConfig
	│   │    │   └── WebSecurityConfig
	│   │    ├── exception
	│   │    │   └── GlobalControllerAdvice 
	│   │    │   └── InvalidDateFormatException 
	│   │    └── util
	│   │        └── DateTypeFormatterUtil
	│   │        └── QueryDslUtil
	│   │ 
    │   └── ToyProject3Appplication 
	│
	└── resources
	    └── applicion.yaml
			└── applicion-secret.yaml

API 문서(Spring REST Docs)📜

API는 이번에도 지난 Toy Project 2 때와 마찬가지로 Spring REST Docs를 도입하여 문서화 했다.
관련 포스팅에서 Spring REST Docs를 어떻게 설정하고 도입했는지 자세히 살펴볼 수 있다.
테스트 후 빌드 및 실행하면 http://localhost:8080/docs/index.html 를 통해 API 문서 인덱스를 확인할 수 있고, 여행을 선택하면 아래처럼 API 문서를 성공적으로 확인할 수 있다.

다른 API들도 궁금하다면 여기에서 전체 API 문서를 확인할 수 있다.

잘한 점👍

프로젝트를 진행하며 잘했고, 앞으로도 적용할 부분을 정리해봤다.

  1. Git Flow 브랜치 전략을 사용하여, 효과적으로 브랜치를 운용할 수 있었다.
  2. GitHub Action을 통한 CI 도입으로, develop 브랜치를 안정적으로 유지할 수 있었다.
  3. Spring REST Docs를 도입하여, API를 문서화했다. 테스트 코드 기반이기 때문에 실제 API 설계에 맞게 구현되었는지, 잘 작동하는지 확인할 수 있어 좋았던 것 같다.
  4. 회의 시간과 회의 안건, 개발 일정을 미리 계획하여, 효과적으로 회의를 진행할 수 있었다.
    오후 2시, 오후 5시에 매일 회의를 진행하였고, 이후 더 회의가 필요한 경우에만 추가적인 회의를 진행했다. 이를 통해 개발할 시간을 좀 더 확보할 수 있었다.

🎀 느낀 점

이번 프로젝트에서는 Security, JWT 을 적용한 인증/인가 구현과 함께 개발을 해봤다.

드디어 1, 2, 3단계까지 모든 토이 프로젝트가 마무리 되었다. 토이 프로젝트는 끝났지만 앞으로 더 중요한 미니 프로젝트, 파이널 프로젝트가 남아있으니 끝까지 힘내 봐야겠다!

profile
배움 기록

0개의 댓글