- 고객이 책을 검색하고 주문할 수 있는 인터넷 서점입니다.
- 관리자는 판매하고 싶은 책을 등록할 수 있습니다.
- 검색을 통해 원하시는 제목 또는 내용의 책을 확인할 수 있습니다.
- 개발 기간 : 2024.03.11 ~ 05.17
- URL : https://www.t3t.shop/
구건모 | 이주현 | 김유진 | 박종경 | 박수화 |
---|---|---|---|---|
@woody35545 | @JooH | @Yujin_nKim | @parkjonggyeong18 | @hydrationn |
-
FRONTEND : 클라이언트의 요청은 NginX 통해서 들어오고, 로드밸런서에서 Round Robin 방식으로 순서대로 Front Application 에 보내지게 됩니다. Front Application 은 필요한 요청을 API Gateway 를 통해 처리합니다. 프론트엔드는 Thymeleaf, HTML, CSS, Javascript로 구현되어 있으며, 사용자 인증 및 권한 관리를 위해 Spring Security와 JWT를 사용합니다.
-
API - GATEWAY : API 게이트웨이는 Spring Cloud Gateway를 이용하여 구현되었으며, 클라이언트의 요청을 받아 해당 요청을 처리할 서비스로 라우팅합니다. 또한 Spring Cloud Netflix Eureka Client를 사용하여 유레카 서버로부터 서비스 인스턴스 정보를 검색하고, JWT를 활용하여 인증된 요청만을 허용합니다. Access 토큰이 만료된 경우, Refresh 토큰과 비교를 통해 요청을 Auth 서버로 보내 토큰 재발급을 받고, 원래 요청을 수행하도록 구현하였습니다.
-
EUREKA : 유레카 서버는 Spring Cloud Netflix Eureka를 통해 서비스들의 인스턴스 정보를 등록하고 관리합니다. 이를 통해 서비스 디스커버리 및 로드 밸런싱이 가능하며, gateway는 유레카 서버를 통해 서비스의 위치를 동적으로 찾을 수 있습니다.
-
AUTH API : auth API 서버는 Spring Security를 이용하여 구현되었으며, JWT를 활용하여 사용자의 인증 및 권한 부여를 담당합니다. 보안을 위해, Access 토큰 과 Refresh 토큰을 활용하여 보안을 강화하였습니다. 또한 로그아웃시 사용된 Access 토큰을 Blacklist로 등록하여 로그아웃된 토큰의 재사용을 방지하였습니다. Access 토큰의 자동 재발급을 구현하여, Client가 매번 다시 로그인 해야하는 불편함을 해소하였습니다.
-
BOOKSTORE API : bookstore API 서버는 gateway로부터 요청을 받아 필요한 데이터를 응답합니다. Spring Data JPA와 QueryDSL을 활용하여 데이터를 관리합니다.Junit5, AssertJ, Mockito를 이용하여 테스트 코드를 작성하고, SonarQube를 통해 코드 품질을 유지합니다.
-
COUPON API : coupon API 서버는 Spring Boot와 Spring Data JPA를 이용하여 구현되었으며, QueryDSL을 활용하여 데이터베이스 조회를 효율적으로 처리합니다.Junit5, AssertJ, Mockito를 이용하여 테스트 코드를 작성하고, SonarQube를 통해 코드 품질을 유지합니다.
- Github를 통해 코드베이스를 관리하며 변경 사항을 병합하기 위해 Pull Request를 생성하고 팀원들을 이를 검토하고 코드 리뷰를 진행합니다. PR가 merge되면 Github Action을 통한 CI/CD가 시작됩니다. 이 파이프라인은 빌드를 자동으로 시작하고 빌드된 코드에 대해 SonarQube로 테스트가 진행되어 코드의 품질을 평가합니다. 모든 테스트가 성공하면 자동으로 배포가 진행됩니다.
- 또한, NHN Cloud의 Secure Key Manager를 사용하여 DB 정보를 비롯한 암호화가 필요한 중요한 데이터들을 안전하게 관리하고 환경변수를 통해 접근합니다.
- 개발도구: Intellij IDEA - Ultimate
- 언어: Java 11 LTS Temurin
- 빌드도구: Maven
- 개발
- Spring Framework: 5.3
- Spring Boot: 2.7.18
- Spring Cloud
- Spring Cloud Gateway
- Spring Cloud Netflex(Eureka)
- Spring Cloud OpenFeign
- Spring Data
- Spring Data JPA
- Spring Data Elasticsearch
- Spring Data Redis
- Spring Security
- JPA
- QueryDSL
- 테스트
- Junit5
- AssertJ
- Mockito
- SonarQube
- 데이터베이스
- MySQL: 8.0.25
- Redis
- 검색엔진
- Elastic Search: 7.11.1
- Kibana: 7.11.1
- Logstash: 7.11.1
- ERD
- ERDCloud
- 프론트 개발 환경 및 언어
- 언어:
- HTML
- CSS
- JavaScript
- 라이브러리 및 프레임워크:
- Bootstrap 5
- Thymeleaf
- TOAST UI
- 언어:
- NHN Cloud
- Instance
- Secure Key Manager
- Object Storage
- 형상관리 및 이슈관리
- GitHub
- 기타
- Dooray Hook Sender
Github Roadmap
- Github에서 제공하는 Project를 활용해 프로젝트의 작업 현황과 진행도를 체계적으로 관리했습니다.
- 이를 통해 작업 항목들을 시각적으로 구성하고, 각 항목과 관련된 PR, 이슈 등을 연결하여 프로젝트의 전반적인 진행 상황을 투명하게 공유할 수 있었습니다.
Github Kanban
- Github의 Project 기능 중 Kanban 보드를 활용하여 프로젝트를 관리했습니다.
- Todo, InProgress, Done 의 열로 작업을 구분해 현재 작업 상황을 실시간으로 확인할 수 있도록 했습니다. 또한, Delay 탭을 별도로 만들어 프로젝트 내에서 지연되는 부분을 확인해 적절한 조치를 취할 수 있도록 했습니다.
일주일 간격으로 스크럼 마스터를 선정해 매일 아침 10:00에 스크럼을 진행했습니다. 개발 기간 동안 총 40번이 넘는 스크럼이 진행되었고, 스크럼에서는 팀원들이 각자의 진행 상황을 공유하고 발생한 이슈들을 함께 논의하여 프로젝트를 원활하게 진행할 수 있었습니다.
-
Nginx 설정
- Nginx 에 SSL를 적용하여 클라이언트와 프론트 서버 사이의 요청 및 응답 암호화
- Nginx 를 L7 로드밸런서로 활용하여 클라이언트의 요청이 여러 프론트엔드 서버로 로드밸런싱 되도록 설정
-
CI/CD 및 배포 관련
-
기본적인 CI/CD 환경 구축
- Github Actions 와 Jenkins 를 통한 CI/CD 환경 구축
-
빌드 시 민감 정보 처리 과정
- 프로젝트 내의 인증서 또는 키파일 등이 공개 레포지토리에 올라가지 않도록 제외하고,
프로젝트 빌드 과정에 필요한 인증서 또는 키파일 등이 CI/CD 과정상에서 동적으로 생성되어 빌드시 포함되도록 설정
- 프로젝트 내의 인증서 또는 키파일 등이 공개 레포지토리에 올라가지 않도록 제외하고,
-
서버 상태 확인 및 간편한 배포하기 위한 배포 툴 개발
- Shell Script 를 이용하여 배포 및 서버 관리를 위한 커스텀 쉘 개발
- 현재 CI/CD 대상으로 설정해둔 master, develop 브랜치뿐만 아니라 모든 브랜치에 대해 단순한 커맨드 기반으로 직접 배포할 수 있도록 기능 제공
- 배포 기능 이외에도 서버 상태 확인, 서버 종료, 서버 접속, 로그 제공 등 다양한 편의 기능 구현
-
-
Eureka 및 Gateway 설정
- 분산된 서비스 관리를 위한 Service Discovery 기능을 수행하기 위한 Eureka 와 서비스간 로드밸런싱을 위한 Gateway 설정
- Eureka의 Service Registry 에 등록된 각 서비스 정보들을 기반으로 Gateway 에서 라운드 로빈 방식의 로드밸런싱이 이루어지도록 설정
- RewritePath Filter 를 이용하여 Gateway 로 들어온 요청에서 서비스 구분을 위해 추가된 prefix 가 자동으로 제거되어 실제 서비스로 전달되도록 설정
-
프로젝트 민감 정보 관리
-
프로젝트 내에 데이터베이스 접속 정보 등의 민감 정보들이 깃허브 공개 레포지토리 상에 반영되지 않도록 클라우드에서 제공하는 Secure Key Manager 기능을 활용
-
Secure Key Manager 를 사용하기 위한 설정 및 서비스 개발
- Secure Key Manager API 사용을 위해 RestTemplate 에 인증서가 포함되도록 설정
- Secure Key Manager 에 등록된 기밀데이터 식별자를 통해 특정 기밀 데이터 값 조회 기능 구현
-
Secure Key Manager 관련 Bean 들이 필요시에만 로드되도록 설정
-
-
프로젝트 환경 구성
-
각 프로젝트의 prod, dev, test 환경 설정
- 특정 환경에 필요한 Bean 들만 컨텍스트에 로드되도록 설정
- 선택한 환경에 따라 적절한 Datasource Bean 이 설정되도록 구성
-
-
회원 정보 조회 기능
-
회원 정보 수정 기능
- 비밀번호 변경
- 기본 배송지 변경 기능
-
회원 가입 기능
- 회원 가입 시 회원 비밀번호 해싱
-
회원 탈퇴 기능
- 탈퇴한 회원에 대한 정보들을 논리 삭제를 적용하여 기록 유지
- 탈퇴한 회원 계정으로 재가입 불가능 하도록 구현
-
휴면 회원 처리 및 활성화 기능
- 스케줄러를 활용하여 주기적으로 마지막 로그인 시간 기준으로 3개월 이상 로그인하지 않은 회원을 휴면 처리
- 휴면 회원 활성화를 위한 인증 코드 발급 및 검증 과정 구현
- 휴면 회원 활성화 인증 코드 관리를 위한 저장소로 Redis 사용
-
회원 등급 및 혜택 기능
- 현재 회원 등급 및 혜택 조회
- 다음 등급까지 남은 조건 조회
- 등급별 혜택 조회
-
회원 주소 관리 기능
-
등록된 주소 조회 기능
-
주소 등록 기능
-
Open API를 활용한 회원 주소 등록 기능
- 우편주소, 도로명 주소 등 검색 기능을 통해 편리한 주소 등록 기능 제공
-
10개까지 주소 등록 가능하도록 구현
-
-
주소 별칭 기능
- 주소 등록 시 별칭 설정 기능
- 등록된 주소의 별칭 변경 기능
-
등록된 주소 삭제 기능
-
등록된 주소 중 기본 배송지로 사용할 주소 설정 기능
-
-
기본적인 장바구니 항목 추가 및 삭제 기능 제공
-
회원/ 비회원 장바구니 항목을 Redis 에 저장하여 조회 성능 개선
-
쿠키를 통해 장바구니 식별자 정보 저장
- 쿠키에 사용자의 장바구니 식별자를 저장 후 해당 식별자를 통해 Redis 에서 장바구니 항목 조회
-
비회원 장바구니
- 비회원의 경우 임의의 장바구니 식별자 발급
- 비회원 장바구니는 영속되지 않도록 설계
-
회원 장바구니
- 회원의 경우 회원 식별자를 장바구니 식별에 사용
- 회원의 장바구니는 영속화 되도록하여 항목들이 영구적으로 유지되도록 구현
- 장바구니에 항목에 변경 사항이 발생할 때에만 영속화를 위해 데이터베이스 반영 후 Redis 갱신
- 조회 성능을 위해서 회원의 단순한 장바구니 조회는 Redis 를 통해서 조회하도록 설계
-
-
회원 / 비회원에 대한 바로 주문 기능 및 장바구니 주문 구현
-
주문 관련 설계
-
주문 처리를 위한 Facade 클래스
- Facade 클래스를 통해 Bean 사이의 순환참조 없이 여러 서비스들을 호출할 수 있도록 하여, 코드 중복 감소 및 재사용성이 증가하도록 설계
- Facade 클래스를 통해 하위 여러 서비스들의 기능들이 하나의 트랜잭션으로 처리될 수 있도록 구현
-
회원의 바로 주문, 장바구니 주문 또는 비회원의 바로 주문, 장바구니 주문 등의 여러가지 주문 상황에서 동일한 주문 페이지를 사용할 수 있도록 구현
-
-
주문에 대한 결제 검증
- 주문에 대한 결제 금액 검증을 위해 주문 요청 시점의 상품 가격등을 기반으로 결제 대기 상태의 임시 주문 정보 생성
- 주문 승인 요청시 사용자의 결제 기록을 결제 제공처에 요청하여 임시 주문에 기록된 금액과 동일한 금액이 결제가 이루어졌는지 검증 후 주문 승인
- 임시 주문이 생성되고 일정 시간 이상 결제 또는 주문 승인 요청이 이루어지지 않으면 임시 주문 폐기
-
동시에 발생한 주문 요청 처리
- 주문된 상품의 재고 차감 시 동시성 문제를 고려하여, 일관성을 유지하고 정합성을 보장하기 위해 비관적 락을 적용
- 같은 상품에 대해 동시에 주문을 요청한 경우 먼저 결제 단계에 먼저 진입한 사용자에게 구매의 우선권을 주도록 설계
- 임시 주문 생성 시 재고도 실제로 차감시켜서 선점하도록 설계
- 결제를 진행하지 않고 오랜시간 재고를 선점하는 것을 방지하기 위하여 임시 주문의 유효시간 설정
- 배송에 대한 기본적인 조회, 생성, 갱신, 삭제 API 구현
-
결제 정보 저장 및 결제 검증 기능 구현
-
결제 제공자의 확장성을 고려한 설계
-
서비스의 결제 기능이 전적으로 토스 결제 의존하고 있던 기존 설계에서, 확장성을 고려하여 여러 결제 제공자가 유연하게 추가될 수 있도록 재설계
-
확장성을 위해 테이블 및 엔티티 재설계
-
확장성을 위해 결제 제공자 서비스들에 대한 인터페이스 설계 및 Factory 도입
-
네이밍 컨벤션을 지키면 자동으로 결제 서비스들이 팩토리를 통해 관리되도록하여, 결제 서비스의 추가나 변경에 대해 별도의 코드 변경없이 사용할 수 있도록 설정
-
결제 서비스를 사용하는 측에서 팩토리 클래스를 통해 결제 서비스들에 접근하도록 변경하여 의존도를 낮추고, 추후 결제 제공자의 추가나 변경에 영향을 받지 않도록 설계
-
- Spring Security 사용 (Front, Auth)
- 로그인
- Client가 입력한 ID, PW가 DB에 저장되어 있는 암호화된 정보와 일치하는지 확인
- 로그인 실패시 로그인 페이지로 Redirect
- 로그아웃
- 로그아웃시 사용된 Access Token을 Redis에 BlackList Token으로 저장하여 해당 토큰은 재사용 불가능하게 처리
- JWT 토큰 발급
- JWT 토큰은 Access, Refresh 2개의 토큰을 사용, 각 토큰은 1대1 맵핑이 되도록 동일한 임의의 UUID값을 지님
- 토큰은 UserId, UserRole, UUID를 payload로 가짐
- JWT 토큰 재발급
- Refresh 토큰이 살아있는 경우
- Access Token이 만료 5분 전이거나, 만료된 경우 Refresh 토큰을 통한 재발급
- Refresh 토큰이 만료된 경우
- Access Token이 살아있는 경우는 요청 진행, 만료된 경우는 로그인 페이지로 Redirect
- Refresh 토큰이 살아있는 경우
- 인가
- Gateway에서 인가처리를 진행하여 권한이 없는 사용자는 메인페이지로 Redirect
-
Front Server에서 요청이 수행될 때, Cookie가 존재하면 Header에 추가
-
Feign Client로 요청 전송시 Header값 자동으로 추가
-
BookServer에서 Authorization Header Decode Filter 구현
-
시퀀스 다이어그램
- 쿠폰 발급 CRUD 개발 및 뷰 구현
- 도서 조회, 등록, 수정, 삭제 구현
- 도서 등록, 수정 시에 editor 적용(toast ui)
- 입력한 마크다운 대로 저장 및 불러오기 가능
- 메인 페이지에서 도서 추천 목록 조회 기능 구현
- 신간 도서, 평점 순, 베스트 셀러 순으로 정렬된 도서 조회
- Object Storage를 연동해 썸네일 및 다중 미리보기 이미지 등록 및 수정 가능
- 리뷰 등록, 수정, 삭제, 회원별 리뷰 목록 조회, 도서별 리뷰 목록 조회 구현
- Object Storage를 연동해 다중 이미지 등록 및 수정 가능
- 카테고리의 부모-자식 관계를 통해 계층 구조로 구성해 효과적으로 구조화하고 관리
- 카테고리 등록, 수정, 삭제 구현
- 카테고리 조회 구현
- 조회하고자 하는 카테고리의 depth 지정해 계층 구조로 조회 가능
- 카테고리 관리자 view
- 태그 등록, 수정, 조회, 삭제 구현
- 태그 관리자 view
- 저자 조회, 등록, 수정, 삭제 구현
- 저자 관리자 view
- NHN Object Storage 연동
- storage에 접근하기 위해 필요한 token을 Redis에 등록하여 사용
- 개발 및 실제 배포 환경에서 다양한 도서 데이터를 확보하기 위해, 데이터 insert를 위한 파이썬 스크립트 구현
- 알라딘 OpenAPI의 상품 검색 API와 상세 조회 API를 활용해 각 카테고리 별로 도서와 관련된 정보들(출판사, 작가, 이미지 등)을 중복없이 자동으로 데이터베이스에 삽입하는 작업을 수행
- 결제 인증
- 주문 / 환불 기능 수행을 위해 결제 정보 및 유저 검증
- 결제를 통해 주문/ 환불에 대한 기능을 수행하기 위해 toss api를 통해 결제 진행
- 결제 및 취소 데이터를 toss와의 연동을 통해 toss 데이터와 주문정보를 주고 받음
- toss 결제 view 구현 및 연동
- ELK
- Elasticsearch
- 데이터 저장, 수정된 데이터 업데이트 및 인덱싱
- Logstash
- database의 데이터를 elastic에 전달
- Kibana
- elasticsearch 시각화 및 데이터 탐색
- Elasticsearch
- Ngram, Nori, jaso 분석기를 사용해 다양한 조건의 검색 수행
- full text search를 수행하는 과정에서 카테고리 영역의 도서 검색 구현
- 실사간으로 elasticsearch의 정보를 받아와 자동완성 기능 구현
- full text search 수행
- 정확도순, 출판일순, 낮은 가격순, 평점순, 좋아요 순으로 정렬
- 검색 view 구현
- Ngram, Nori, jaso 분석기를 이용한 상품 검색
- 포인트 CRUD 및 view 구현
- 회원 포인트 사용 및 적립
- 회원 포인트 사용/적립 내역 조회
- 출판사 등록, 조회, 수정, 삭제(CRUD) 구현
- 회원 등급 정책 등록, 조회, 수정, 삭제(CRUD) 구현