-
음식 주문 관리 플랫폼 프로젝트 회고그 외/기타 2024. 11. 20. 10:36
깃헙 주소
https://github.com/peopleofF4/peopleofF
[주요 기능]
더보기- 주문 관리
- 주문 취소: 주문 생성 후 5분 이내에만 취소 가능하도록 제한
- 주문 유형: 온라인 주문과 대면 주문(가게에서 직접 주문) 모두 지원
- 대면 주문 처리: 가게 사장님이 직접 대면 주문을 접수
- 사용자 페이지: 고객이 카테고리를 탐색하고, 매장을 선택하고, 메뉴를 확인하며, 온라인으로 주문
- 관리자 페이지: 매장 소유자와 관리자가 주문을 효율적으로 조회, 수정 및 관리할 수 있는 제어 기능 제공
- 데이터 보존 및 삭제 처리
- 데이터 보존: 모든 데이터는 완전 삭제되지 않고 숨김 처리로 관리
- 상품 숨김: 개별 상품도 숨김 처리 가능하도록 구현
- 데이터 감사 로그: 모든 정보에 생성일, 생성 아이디, 수정일, 수정 아이디, 삭제일, 삭제 아이디를 포함
- 접근 권한 관리
- 고객: 자신의 주문 내역만 조회 가능
- 가게 주인: 자신의 가게 주문 내역, 가게 정보, 주문 처리 및 메뉴 수정 가능
- 관리자: 모든 가게 및 주문에 대한 전체 권한 보유
- AI API 연동
- 상품 설명 자동 생성: AI API 연동으로 메뉴 등록 시 설명 추천
- AI 요청 기록: AI API 요청 질문과 대답은 모두 데이터베이스에 저장
- 보안
- JWT 인증: Spring Security와 JWT(Json Web Token)를 이용한 인증 및 권한 관리
- 권한 확인 : CUSTOMER 이상의 권한은 요청마다 저장되어 있는 권한 값과 동일한지 체크
- 비밀번호 암호화: BCrypt 해시 알고리즘을 사용한 비밀번호 암호화
- 데이터 유효성 검사: 서버 측 데이터 유효성 검사를 위해 Spring Validator 사용
- 검색조건 및 정렬기능
- 정렬기능은 기본적으로 생성일순, 수정일순을 기준
- 서치 기능에는 10건, 30건, 50건 기준으로 페이지에 노출
이번 팀 프로젝트를 하면서 제일 좋았던 점은 팀원들 간의 소통이다.
매일 오전 시간은 데일리 스크럼 시간으로 서로 진행사항이라던가 고민되는 점 등 여러 주제로 활발하게 소통을 했는데 이로 인해서 발생할 수도 있던 오류를 사전에 막는다던가 몰랐던 부분을 서로에게 배울 수 있어서 좋았다.
특히 팀장님이 현업에 조금 계시다 오신 분이라 많은 도움을 주셨는데 질문 폭탄을 던져도 친절하게 대답해주셔서 정말 감사했다.
우리 팀원 모두 MBTI가 F여서 팀명은 F킬라, 프로젝트명은 people of F 였는데... 그래서였나... 결이 비슷해서 안 부딪힌 것 같기도...
팀원 4명이서 골고루 분배될 수 있도록 도매인을 크게 4개로 묶어서 사다리 타기를 했는데 나는 menu, store, review 기능을 맡게 되었다. menu나 store의 기능은 거의 비슷해서 menu 도매인 완성하고 나서 store는 금방 구현할 수 있었다.
기능 구현에 대한 어려움 보다는 처음에 프로그램은 실행되는데 실행 후 바로 종료되는 문제를 해결하고 (알고보니 처음에 프로젝트 구성할 때 spring boot starter web을 안 넣어서 tomcat이 실행 안돼서 그랬더라...) 연결된 엔티티들 때문에 더미데이터를 미리 만들고 하면서 더 진을 뺐던 것 같다.
리뷰의 경우 가게별 평균평점을 구하는 부분에 대한 고민이 많았는데 팀원들과 상의 끝에, store 엔티티에 총 리뷰 개수와 총 리뷰 합계를 추가해 review가 등록, 생성, 삭제 될 때 바로 업데이트 될 수 있도록 구현하였다.
PR의 개념은 알았지만 이번 팀프로젝트를 통해 처음 써보는거라 조금 걱정이되었는데 다행히도 다른 팀원들의 도움으로 어려움 없이 진행되었다. 팀원들에게 속성으로 배운 Git-Flow를 튜터님의 특강으로 한 번 더 정리할 수 있어서 좋았다.
PR을 올리니까 코드가 푸시되기 전에 다른 팀원들의 리뷰를 받을 수 있다는게 좋더라.
덕분에 미처 발견 못한 오류를 사전에 수정할 수 있었고, 더 좋은 코드에 대한 방향성을 잡을 수 있었다.
또, 다른 팀원들의 코드를 리뷰하는게 처음엔 눈에 잘 보이지 않다가 점점 읽히는게 신기하기도 했고, '이렇게도 구현할 수 있구나!'하고 많이 배운 것 같다.
배운 점 :
좋은 튜터님들과 팀원분들을 만난 덕에 배운 점은 정말 많지만 일단 기억에 남는 것만 몇 개 적어보자면,
1. API URI 설계
이번 API 설계를 하면서 RESTful API URI 설계 규칙을 좀 더 자세히 보는 기회가 되었다. 튜터님 조언으로 version 정보와 admin 정보도 추가하여, 개발자용은 /admin/v1/users, 일반 api는 /api/v1/users 이런식으로 구성하였다. 이렇게 구분하면 개발자용 서버를 따로 둘 수 있고 소스코드를 찾아가기 쉽다고 한다.
[RESTful API URI 설계 대표적 규칙]
더보기- 리소스는 명사로 작성: /users, /products
- HTTP 메서드로 동작 구분: GET, POST, PUT, DELETE
- 기본적인 CRUD는 URI로 구분하지 않음: /users에서 POST → 생성, GET → 조회.
- 리소스의 계층 구조 반영: /users/{userId}/orders/{orderId}
- 소문자 사용: /users, /orders
- 복수형 사용: /users (단수형이 아닌 복수형)
- 쿼리 파라미터는 필터링이나 정렬에 사용: /products?category=electronics&sort=price
- 리소스 식별자는 경로에 포함: /users/{userId}
- 파일 확장자 포함 금지: /users/{userId} (O), /users/{userId}.json (X)
- 액션은 서브 리소스 또는 HTTP 메서드로 처리: /orders/{orderId}/cancel (O), /cancelOrder/{orderId} (X)
- 버전 정보는 URI에 포함: /api/v1/users
- 대문자 사용 금지: /users (O), /Users (X)
- 하이픈(-)으로 단어 구분: /user-profiles (O), /user_profiles (X)
- 컨트롤러 이름 포함 금지: /users (O), /userController (X)
- 복합 리소스는 계층적으로 설계: /users/{userId}/posts/{postId}
- HTTP 상태 코드를 적절히 사용: 성공, 실패, 오류 상황을 명확히 전달.
- 최소한의 URI Depth 유지: /users/{userId}/orders (O), /app/api/v1/users/{userId}/orders (X).
- REST API는 무상태(Stateless) 설계: 모든 요청은 자체적으로 완전해야 함.
- 관련성이 높은 리소스는 링크로 연결: 응답에 관련 리소스 URI 포함.
- API 버전 관리는 명시적이거나 무상태적 방식 사용: /v1/, 또는 헤더 기반 버전 관리.
2. 같은 레이어를 주입 받으면 위험
Service는 transaction을 관리하기때문에 Service가 Service를 D/I하는 것은 좋지 않다고 튜터님께서 말씀해주셨다.
같은 레이어를 주입받아서 쓰는 것 자체는 문제가 안되지만,
Service가 점점 커지면 유지, 보수하면서 바뀌거나 미처 신경쓰지 못한 부분에서 Transaction이 꼬이면서 문제가 발생할 수 있다고 한다.
여기에 팀원분 중 한 분이 만약 PostService가 CommentService를 주입받는 것이 아닌 직접 CommentRepository를 호출하면, DDD를 위반하는 것이 아니냐는 의견이 있었다.
그래서 추가로 튜터님이 말씀해주신 방법이 김영한님은 Controller / ServiceComplex / ServiceSimple / Repository 이렇게 구분하신다는데, 같은 레이어가 아닌 ServiceSimple -> ServiceComplex를 주입 받는 것은 괜찮다고 하셨다.
3. google java style format 적용
팀원분의 권유로 적용하게됐는데 공통 스타일을 적용하니 푸시, 풀 받을 때마다 들여쓰기 같은 스타일 변경으로 쓸데없는 기록이 안남아서 좋았다. 설정하는 것도 간편해서 앞으로도 애용할 것 같다.
[사용법]
더보기1. https://github.com/google/styleguide : 여기서 intellij-java-google-style.xml 파일 복사해서 새 파일로 저장
2. IntelliJ IDEA - > Settings 접속
3. Editor -> Code Style -> Scheme -> 톱니바퀴모양 -> Import Scheme -> xml파일 적용
4. Tools - Actions on save - Reformat code, Optimize imports 체크
5. Editor -> Live Templates -> git commit (Commit changes) -> Options -> Reformat according to style 체크
4. 데이터 베이스 null 값
찬반여론이 둘 다 강해서 사실 아직도 뭐가 맞는지 모르겠다. 개인적으로는 null 값 넣는 것에 거부감은 없었는데, 팀원분 중 한 분이 null을 발명한 사람도 자신의 발명 중 null참조가 역사상 가장 큰 실수라고 언급한 적이 있다고하셔서 찾아봤는데 진짜더라. 토니 호어가 발명했는데 null 참조 도입 이후 수십 년 동안 소프트웨어 버그, 충돌, 보안 문제를 유발했고, 이로 인해 엄청난 시간과 비용이 낭비되었다고 인정했다고... 그래도 null 값의 장점도 분명 있으니 (값이 비어있다는 표현을 null 말고 어떤 것이 더 명확하게 표현해줄 수 있을까) null을 아예 안쓰는 것보다는 null 사용을 최소화하고 optional 같은 대안을 적극적으로 사용하는 방향으로 가야겠다.
5. git issue
깃 이슈도 처음 써봤는데 도메인이나 이슈사항에 따라 이슈를 발행하고 해당 이슈에 관한 커밋들을 모아볼 수 있어서 좋았다.
이슈 템플릿과 라벨도 커스텀하여 적용하였다. 커밋 메세지 뒤에나 footer에 #이슈번호 를 붙이면 자동 매핑되어 편했다.
다만, 푸시한 커밋 내역이 삭제되더라도 이슈번호를 제거하거나 변경하지 않으면 이슈 커밋내역에서 삭제되지 않는다는 점이 아쉬웠다.
더 공부해볼 점 :
1. Spring Security와 JWT / Refresh Token
Spring Security와 JWT / Refresh Token 쪽은 팀프로젝트 진행때마다 다른 팀원분이 해당 파트를 담당하셔서
내일배움캠프 첫번째 개인과제 제출때문에 클론 코딩식으로 구현해본게 다인게 아쉽다.
개인적으로 직접 구현해보는 시간을 가져봐야겠다.
2. 테스트코드
테스트코드를 작성하기로 했지만 시간 부족으로 생략되었다.
통합 테스트 코드를 작성하는게 꽤나 까다롭고 오래걸리지 않을까 싶은데.. 시간이 나면 도전해봐야겠다.
3. swagger
swagger를 팀장님이 구현해주셨지만 아직 사용해보지는 못했다.
swagger는 아직 공부해본적이 없어서 조만간 공부하면서 정리해보아야겠다.
4. QueryDSL
검색 기능을 나는 JPA 쿼리 메서드로 구현했는데 다른 팀원분은 QueryDSL을 사용해서 구현하셨더라.
유지보수나 확장성을 고려하면 QueryDSL을 쓰는게 더 좋다해서 다음엔 QueryDSL을 써봐야겠다.
'그 외 > 기타' 카테고리의 다른 글
AWS EC2 배포 + PostgreSQL (0) 2024.11.18 맥북 포맷 + 개발 환경설정 (Home Brew) (0) 2024.10.30