서비스별 시퀀스 다이어그램 - Kim-Gyuri/SanrioShop GitHub Wiki

구현한 서비스를 시퀀스 다이어그램으로 표현하고, 로직 수행 과정을 정리하였습니다.

✅ 회원가입

signup drawio (2)

  1. 클라이언트가 회원가입 정보(닉네임, 이메일, 비밀번호)를 서버로 전송합니다.

클라이언트는 회원가입 요청을 POST 메서드를 통해 서버로 보냅니다.

  1. 서버에서 JWT 필터 권한 허용 설정합니다.

회원가입은 인증이 필요 없는 요청이므로, JWT 필터에서 해당 요청을 예외로 설정합니다. 그래서 컨트롤러에서 회원가입 API가 정상적으로 수행됩니다.

  1. 컨트롤러에서 회원가입 처리 로직을 서비스에 위임합니다.

컨트롤러는 전달받은 데이터를 기반으로 signup() 메서드를 호출하여 서비스 단에서 실제 회원가입 처리를 진행합니다.

  1. 서비스에서 중복 확인 및 예외 처리합니다.

서비스 단에서는 회원 저장 전에, repository를 통해 닉네임이나 이메일이 중복되었는지 확인합니다.
중복된 정보가 있으면 409 Conflict 상태 코드와 함께 오류를 응답합니다.

  1. 정상 처리 시 암호화 및 회원가입 처리합니다.

중복되지 않은 경우 비밀번호를 BCrypt 등의 암호화 알고리즘으로 인코딩한 후, 회원 정보를 데이터베이스에 저장합니다.

  1. 응답으로 201 Created 반환합니다.

회원가입이 성공적으로 완료되면 서버는 HTTP 201 Created 응답을 클라이언트로 보냅니다.

✅ 로그인

로그인 성공하면 Access, Refresh 토큰을 받도록 구현했습니다.
각각의 토큰은 생명주기와 사용처가 다르게 설정했습니다.

  • Access : 헤더에 발급 후 프론트에서 로컬 스토리지에 저장하여 사용합니다.
  • Refresh : 쿠키에 발급 받습니다.

로그인 구현코드에 대해 따로 정리할 예정.

login jwt drawio

  1. 클라이언트가 로그인 정보(이메일, 비밀번호)를 서버로 전송합니다.

클라이언트는 로그인 요청을 POST 메서드를 통해 서버로 보냅니다.

  1. 서버에서 JWT 필터 권한 허용 설정합니다.

로그인은 인증이 필요 없는 요청이므로, JWT 필터에서 해당 요청을 예외로 설정합니다.

  1. 컨트롤러에서 로그인 처리 로직을 서비스에 위임합니다.

컨트롤러는 전달받은 데이터를 기반으로 login() 메서드를 호출하여 서비스 단에서 실제 로그인 처리를 진행합니다.


  1. 서비스에서 사용자 인증, JWT 생성, 응답 설정을 처리합니다. 단계별로 설명하면 다음과 같습니다.
  • 사용자 인증 검증
    • 클라이언트로부터 loginRequest 객체를 통해 이메일과 비밀번호가 전달됩니다.
    • 메서드 내부에서 authenticate() 메서드를 호출하여, 입력된 이메일과 비밀번호가 유효한지를 먼저 검증합니다.
      이 과정에서 Spring Security의 AuthenticationManager를 사용해 인증을 처리합니다.
    • 인증이 실패하면 UserNotFoundException을 발생시켜, 잘못된 사용자 정보에 대해 예외를 처리합니다.
  • 사용자 정보를 확인
    • CustomUserDetailsService를 통해 해당 이메일로 등록된 사용자의 세부 정보를 꺼냅니다. 이 정보는 UserDetails 객체에 저장됩니다.
  • 비밀번호 검증
    • checkEncodePassword() 메서드를 통해 클라이언트가 입력한 비밀번호와 DB에 저장된 인코딩된 비밀번호가 일치하는지 확인합니다.
    • 비밀번호가 일치하지 않으면, 예외를 발생시킵니다.
  • 역할(Role)
    • getRole() 메서드를 사용해 사용자가 가지고 있는 권한(역할, Role)을 가져옵니다. 이 권한은 JWT 토큰 생성에 사용됩니다.
  • JWT 토큰 생성
    • JwtProperties 클래스를 통해 JWT(Access Token, Refresh Token)를 생성합니다.
    • access 토큰은 인증을 위한 JWT로, 이메일, 역할 등의 정보를 담고 있습니다.
    • refresh 토큰은 Access Token이 만료되었을 때 재발급을 요청할 수 있는 토큰으로, 마찬가지로 이메일과 역할 등의 정보를 포함합니다.
  • Refresh Token 저장 및 Cookie 설정
    • Refresh 토큰을 RefreshTokenRepository에 저장합니다.
    • Refresh 토큰은 쿠키로 생성하여 클라이언트에게 전송합니다.
  • 응답 설정
    • Access Token을 JWT_AUTH라는 이름의 헤더로 클라이언트에 전송합니다.
    • Refresh Token은 쿠키로 전송됩니다.
    • 응답 상태 코드는 성공적인 인증을 나타내는 HTTP 200 OK로 설정됩니다.

✅ 토큰 재발급

보안적 차원에서 Access 토큰의 생명주기를 짧게 설정하고, 만료된 Access 토큰은 Refresh 토큰을 사용해 재발급하는 방식으로 관리하도록 구현했습니다.

Refresh 토큰 관리는 아래와 같이 처리했습니다.

  • 로그인 시, 생명주기가 긴 Refresh 토큰을 서버측에 저장했었습니다.
  • 토큰 재발급 요청이 들어오면 기존 Reresh 토큰을 삭제하고 새롭게 발급한 Refresh 토큰을 저장합니다.

번외 현재 구현으로는, Refresh 토큰 재발급 요청이 있을 때만 기존 토큰을 삭제할 수 있다.
최악의 경우, 토큰 저장소 Mysql에 만료된 Refresh 토큰들이 계속 쌓여 용량 문제로 이어질 수 있다.
만료된 Refresh 토큰들을 주기적으로 삭제하는 방식을 도입하여 개선할 예정이다.


토큰 재발급 서비스에 대한 시퀀스 다이어그램은 다음과 같습니다.
renewJwt drawio

  1. Access 토큰과 함께 요청을 전송합니다.
  1. HttpServletRequest에서 쿠키 배열을 가져와, JWT_REFRESH라는 이름의 Refresh 토큰을 꺼냅니다.
  2. 토큰과 함께 /reissue POST 요청을 보냅니다.
  3. Refresh 토큰이 존재하지 않으면 RefreshTokenNotFoundException 예외를 발생시킵니다.
  1. Refresh 토큰에 대한 유효성 검사를 합니다.

JWT 유틸리티 클래스인 JwtProperties를 사용하여 리프레시 토큰이 만료되었는지 확인합니다.

  1. 만료된 토큰이면 InvalidRefreshTokenException 예외를 발생시킵니다.
  2. 데이터베이스에 저장된 Refresh 토큰인지 확인하여 유효하지 않은 토큰인 경우 예외를 발생시킵니다.
  1. 새로운 JWT를 발급합니다.

유효한 Refresh 토큰이면, 사용자 이름과 역할을 추출하여 새로운 Access 토큰과 Refresh 토큰을 생성합니다.

  1. 저장소에 Refresh 토큰을 갱신합니다.
  1. 기존에 저장된 Refresh 토큰을 삭제합니다.
  2. 새로 발급한 Refresh 토큰을 DB에 저장합니다.
  1. 응답 반환합니다.
  1. 새로 발급한 Access 토큰은 HTTP 헤더에, 그리고 Refresh 토큰은 쿠키에 담아 응답합니다.
  2. 성공적으로 처리되면 HTTP 200 응답을 반환합니다.

✅ 로그아웃

로그아웃을 수행하는 클래스의 위치는 필터로, 커스텀 필터 CustomLogoutFilter에 구현했습니다.
로그아웃 버튼을 클릭했을 때 JWT 토큰을 다음과 같이 처리했습니다.

  • 프론트엔드측
    • 로컬 스토리지에 존재하는 Access 토큰 삭제한다.
    • 서버측에 로그아웃 경로로 Refresh 토큰 전송한다.
  • 백엔드측
    • 로그아웃 로직을 추가하여 Refresh 토큰을 받아 쿠키를 초기화한다.
    • DB에 있는 Refresh 토큰을 삭제한다.

로그아웃 시퀀스 다이어그램은 다음과 같습니다.
logout jwt drawio

  1. 클라이언트가 로그아웃 버튼을 누릅니다.
  1. doFilter() 메서드에서 클라이언트가 /api/user/logout 경로와 POST 요청을 보냈는지 확인합니다.
  2. 유효하지 않는 경로와 요청인 경우 HTTP 400 상태 코드를 응답합니다.
  1. Refresh 토큰 가져옵니다.
  1. getRefreshTokenFromCookies() 메서드를 통해 JWT_REFRESH라는 이름의 쿠키를 찾아 Refresh 토큰을 꺼냅니다.
  2. Refresh 토큰이 없을 경우 HTTP 상태 코드 400 (SC_BAD_REQUEST)을 응답하고 종료합니다.
  1. Refresh 토큰이 만료되었는지 확인합니다.

Refresh 토큰이 만료되었는지 검사합니다. 만약 만료된 경우, 역시 HTTP 401 상태 코드를 응답하고 종료합니다.

  1. 토큰 타입을 확인합니다.
  1. isRefreshToken() 메서드를 통해 토큰이 실제 Refresh 토큰인지 확인합니다.
  2. 만약 Refresh 토큰이 아니라면 HTTP 400 상태 코드를 반환하고 종료합니다.
  1. DB에 토큰이 있는지 확인합니다.
  1. validateTokenExistenceInDb() 메서드를 사용해 Refresh 토큰이 데이터베이스에 존재하는지 확인합니다.
  2. 만약 존재하지 않으면 HTTP 400 상태 코드를 반환합니다.
  1. 로그아웃 처리합니다.
  1. Refresh 토큰이 유효하고 모든 검사를 통과하면, 데이터베이스에서 해당 Refresh 토큰을 삭제하고 클라이언트의 쿠키에서도 토큰을 무효화합니다.
  2. invalidateRefreshTokenCookie() 메서드를 통해 쿠키의 만료 시간을 0으로 설정하여 삭제하고, HTTP 200 상태 코드를 반환합니다.

✅ 주문

주문요청

상품 거래 요청 로직을 구현할 때, 동시 거래 상황을 고려해 필요한 검증과 예외 처리를 추가했습니다.

주문 요청 서비스에 대한 시퀀스 다이어그램은 다음과 같습니다.
order drawio (1)

  1. 클라이언트가 주문 버튼을 누릅니다.

주문 요청이 POST 메서드를 통해 서버로 전송됩니다. 이때 로컬 스토리지에 저장된 Access 토큰과 상품 ID가 함께 전달됩니다.

  1. Access 토큰이 만료된 경우, Spring Security는 401 Unauthorized 상태 코드를 반환합니다.
  2. 컨트롤러는 주문 처리를 서비스에 위임하며, 전달받은 데이터를 바탕으로 contactTrade() 메서드를 호출하여 실제 주문 처리를 수행합니다.

  1. 서비스는 아래의 과정을 통해 상품 확인, 구매자 확인, 동시 거래 방지, 주문 요청 생성, 알림 생성을 처리합니다.
  • 상품 확인
    • itemRepository.findById(itemId)를 호출하여 해당 상품을 DB에서 조회합니다.
    • 상품이 존재하지 않으면 ItemNotFoundException으로 HTTP 404 상태 코드를 응답합니다.
  • 구매자 확인
    • userRepository.findByEmail(buyerEmail)을 사용해 구매자 정보를 조회합니다.
    • 해당 이메일의 사용자가 없을 경우 UserNotFoundException으로 HTTP 400 상태 코드를 응답합니다.
  • 동시 거래 방지
    • saleItemRepository.findByItemWithLock(item)을 통해 현재 상품이 이미 판매 중인지 확인합니다.
      이 과정에서 DB Lock을 사용하여 동시성을 처리합니다.
    • 상품이 이미 거래 중이면 SaleItemAlreadyExistsException을 발생시켜 중복 거래를 방지합니다.
  • 주문 요청 생성
    • createSaleItem(buyer, item) 메서드를 호출하여 구매자와 상품 정보를 기반으로 주문처리합니다.
  • 알림 생성
    • createOrderNotification(buyerEmail, item, buyer) 메서드를 통해 주문 관련 알림을 생성합니다.

  1. 주문 요청이 성공적으로 완료되면, 서버는 클라이언트에게 HTTP 200 OK 응답을 반환합니다.

✅ 찜하기

찜 등록

addWish drawio

  1. 클라이언트가 찜등록 버튼을 누릅니다.

찜등록 요청이 POST 메서드를 통해 서버로 전송됩니다. 이때 로컬 스토리지에 저장된 Access 토큰과 상품 ID가 함께 전달됩니다.

  1. Access 토큰이 만료된 경우, Spring Security는 401 Unauthorized 상태 코드를 반환합니다.
  2. 컨트롤러는 찜등록 처리를 서비스에 위임하며, 전달받은 데이터를 바탕으로 markAsWished() 메서드를 호출하여 실제 찜 등록 처리를 수행합# 니다.

  1. 서비스는 아래의 과정을 통해 회원정보 확인, 상품 확인, 찜등록 요청을 처리합니다.
  • 회원정보 확인
    • userRepository.findByEmail(user.getEmail())를 호출해 회원 정보를 조회합니다.
    • 해당 이메일의 사용자가 없을 경우 UserNotFoundException으로 HTTP 404 상태 코드를 응답합니다.
  • 상품 확인
    • itemRepository.findById(itemId)를 호출하여 해당 상품을 DB에서 조회합니다.
    • 상품이 존재하지 않으면 ItemNotFoundException으로 HTTP 404 상태 코드를 응답합니다.
  • 찜등록
    • wishItemRepository.save()를 호출하여 찜등록을 처리합니다.
    • 회원이 이미 찜등록을 했을 경우, 중복 요청이므로 DuplicateWishItemException으로 HTTP 409 상태 코드를 응답합니다.

  1. 찜 등록요청이 성공적으로 완료되면, 서버는 클라이언트에게 HTTP 201 상태 코드를 반환합니다.



찜 취소

deleteWish drawio

  1. 클라이언트가 찜취소 버튼을 누릅니다.

찜취소 요청이 DELETE 메서드를 통해 서버로 전송됩니다. 이때 로컬 스토리지에 저장된 Access 토큰과 함께 전달됩니다.

  1. Access 토큰이 만료된 경우, Spring Security는 401 Unauthorized 상태 코드를 반환합니다.
  2. 컨트롤러는 찜취소 처리를 서비스에 위임하며, 전달받은 데이터를 바탕으로 unmarkAsWished() 메서드를 호출하여 찜 취소 처리를 수행합니다.

  1. 서비스는 아래의 과정을 통해 회원정보 확인, 상품 확인, 찜취소 요청을 처리합니다.
  • 회원정보 확인
    • userRepository.findByEmail(user.getEmail())를 호출해 회원 정보를 조회합니다.
    • 해당 이메일의 사용자가 없을 경우 UserNotFoundException으로 HTTP 404 상태 코드를 응답합니다.
  • 상품 확인
    • itemRepository.findById(itemId)를 호출하여 해당 상품을 DB에서 조회합니다.
    • 상품이 존재하지 않으면 ItemNotFoundException으로 HTTP 404 상태 코드를 응답합니다.
  • 찜취소
    • wishItemRepository.findByWishListAndItem()을 호출해 찜등록된 상태인지 확인합니다.
      찜등록된 상태가 아닌 경우 NotOnWishListException으로 HTTP 409 상태 코드를 응답합니다.
    • wishItemRepository.delete(wishItem)을 호출하여 찜취소를 처리합니다.

  1. 찜 취소요청이 성공적으로 완료되면, 서버는 클라이언트에게 HTTP 200 상태 코드를 반환합니다.



✅ 검색

메인 페이지 검색

웹사이트 메인 페이지에서 해시태그상품명으로 검색할 수 있는 기능을 구현했습니다.
사용자는 해시태그 또는 상품명을 입력하여 원하는 상품을 조회하거나, 상품에 표시된 해시태그를 클릭해 검색할 수 있습니다.

또한, 산리오 캐릭터별로 검색할 수 있는 기능도 추가했습니다. 사용자는 특정 산리오 캐릭터를 선택해 조건에 맞는 상품을 검색할 수 있습니다.

검색 서비스에 대한 시퀀스 다이어그램은 다음과 같습니다.
mainsearch drawio

  1. 클라이언트가 검색을 요청할 때 Access 토큰과 함께 전달됩니다.

조회된 상품에서 찜 요청이나 구매 요청을 처리할 수 있도록 현재 로그인된 회원정보를 받도록 구현했습니다.

번외 다음에 기획을 수정한다면, 비회원도 검색할 수 있도록 개발할 예정이다,
프론트 작업을 혼자서 구현하다보니, 비회원과 회원 요청을 구별하면서 구현하는 작업이 복잡할 것 같았다.
현재 가입된 회원만 서비스를 이용할 수 있도록 구현되어 있다.


  1. 컨트롤러는 검색 처리를 서비스에 위임하며, 전달받은 데이터를 바탕으로 search_fetch_mainPage() 메서드를 호출하여 검색 처리를 수행합니다.
  2. 서비스에서 '산리오 캐릭터' '해시태그' ' 상품명' 조건으로 상품을 검색합니다.
  • 산리오 캐릭터별로 찾는다.
  • 상품명으로 찾는다.
  • 해시태그로 찾는다.

산리오 캐릭터를 선택하고, 동시에 상품명 또는 해시태그 조건으로 검색할 수 있습니다.


  1. 서버는 클라이언트에게 HTTP 200 상태 코드와 함께 상품 데이터를 반환합니다.



카테고리 페이지 검색

테마 검색 기능을 추가했습니다. 테마는 '인기검색어', '포카 꾸미기', '책상 꾸미기', '다꾸/문구', '필기류', '소품'으로 구성되어 있습니다.
회원은 이러한 테마를 통해 원하는 상품을 쉽게 찾을 수 있으며, 상품에 표시된 해시태그를 클릭하여 선택한 테마에 맞는 해시태그로 검색 조건을 설정해 검색할 수 있습니다.
또한 선택한 테마 조건에서 산리오캐릭터별로 검색할 수 있습니다.

검색 서비스에 대한 시퀀스 다이어그램은 다음과 같습니다.
searchbyCategory drawio

  1. 클라이언트가 검색을 요청할 때 Access 토큰과 함께 전달됩니다.

조회된 상품에서 찜 요청이나 구매 요청을 처리할 수 있도록 현재 로그인된 회원정보를 받도록 구현했습니다.


  1. 컨트롤러는 검색 처리를 서비스에 위임하며, 전달받은 데이터를 바탕으로 search_fetch_category() 메서드를 호출하여 검색 처리를 수행합니다.
  2. 서비스에서 '산리오 캐릭터' '해시태그' '테마' 조건으로 상품을 검색합니다.
  • 테마검색으로 찾는다.
  • 해시태그로 찾는다.

선택한 테마에서 원하는 산리오 캐릭터를 클릭하여 상품을 검색할 수 있습니다.


  1. 서버는 클라이언트에게 HTTP 200 상태 코드와 함께 상품 데이터를 반환합니다.



✅ 판매자 기능

상품 등록

uploadItem drawio

  1. 회원은 상품 정보를 입력하여 등록버튼을 누릅니다.

회원은 상품을 직접 판매할 수 있으며, 상품 등록 시 해시태그, 상품 이미지, 테마 등 다양한 정보를 입력할 수 있습니다.
상품 정보와 이미지를 함께 전송해야 하기 때문에 formData를 사용하여 데이터를 처리합니다.
상품 등록 요청은 POST 메서드를 통해 서버로 전송되며, 이때 로컬 스토리지에 저장된 Access 토큰이 함께 전달됩니다.


  1. Access 토큰이 만료된 경우, Spring Security는 401 Unauthorized 상태 코드를 반환합니다.
  2. 컨트롤러는 상품등록 처리를 서비스에 위임하며, 전달받은 데이터를 바탕으로 createItem() 메서드를 호출하여 실제 상품등록 처리를 수행합니다.
  3. 서비스는 아래의 과정을 통해 회원정보 확인, 상품 생성요청, 상품 이미지 생성요청을 처리합니다.
  • 회원정보 확인
    • userRepository.findByEmail(user.getEmail())를 호출해 회원 정보를 조회합니다.
    • 해당 이메일의 사용자가 없을 경우 UserNotFoundException으로 HTTP 400 상태 코드를 응답합니다.
  • 상품 생성요청
    • itemRepository.save()을 호출해 DB에 상품 데이터를 입력합니다.
    • 만약 해시태그 입력이 있다면, createItemTag()를 호출해 태그 데이터를 DB에 입력합니다.
  • 상품 이미지 생성요청
    • 상품 이미지가 최소 1개라도 업로드하지 않는 경우는 MinimumImageRequiredException()으로 HTTP 409 상태 코드를 응답합니다.
    • 클라이언트가 업로드한 이미지 파일은 GCS에 업로드합니다.
    • imgService.saveImg()를 호출해 DB에 상품 이미지 데이터를 입력합니다.

  1. 상품 등록요청이 성공적으로 완료되면, 서버는 클라이언트에게 HTTP 201 상태 코드를 반환합니다.



상품 수정

회원은 업로드했던 상품을 수정할 수 있는데, 상품에 대한 상세 설명, 해시태그, 이미지를 수정할 수 있습니다.

  • 기존에 입력했던 상품명, 가격, 상세 설명, 테마를 수정할 수 있습니다.
  • 등록된 해시태그를 삭제하거나 새로운 해시태그를 추가할 수 있습니다.
  • 업로드했던 이미지를 삭제하거나 새 이미지를 업로드할 수 있습니다.

상품 수정 서비스에 대한 시퀀스 다이어그램은 다음과 같습니다.
editItem drawio

  1. 클라이언트가 상품에 대한 입력을 수정하여 수정버튼을 클릭합니다.

상품수정 요청이 PATCH 메서드를 통해 서버로 전송됩니다. 이때 로컬 스토리지에 저장된 Access 토큰과 입력 데이터가 전달됩니다.

  1. Access 토큰이 만료된 경우, Spring Security는 401 Unauthorized 상태 코드를 반환합니다.
  2. 컨트롤러는 상품수정 처리를 서비스에 위임하며, 전달받은 데이터를 바탕으로 updateItem() 메서드를 호출하여 실제 상품수정 처리를 수행합니다.

  1. 서비스는 아래의 과정을 통해 '상품정보 수정', '상품이미지 수정' 처리합니다.
  • 상품정보 수정
    • itemRepository.findById(itemId)를 호출하여 해당 상품을 DB에서 조회합니다.
      상품이 존재하지 않으면 ItemNotFoundException으로 HTTP 404 상태 코드를 응답합니다.
    • 추가로 넣고 싶은 태그가 있다면, createItemTag()를 호출해 태그 데이터를 DB에 입력합니다.
    • 삭제하고 싶은 태그가 있다면, /api/items/userTag/{id}으로 DELETE 요청으로 처리합니다.
      만약 존재하지 않는 태그인 경우, TagNotFoundException으로 HTTP 404 상태 코드를 응답합니다.
  • 상품이미지 수정
    • 클라이언트가 추가로 업로드한 이미지 파일이 있다면, GCS에 업로드합니다.
    • uploadImg_extra()을 호출해 상품이미지를 생성하여 DB에 입력합니다.
    • 만약 삭제하고 싶은 이미지가 있다면, /api/items/img으로 DELETE 요청으로 처리합니다.
      만약 존재하지 않는 이미지인 경우 ItemImgNotFoundException으로 HTTP 404 상태 코드를 응답합니다.

  1. 상품 수정요청이 성공적으로 완료되면, 서버는 클라이언트에게 HTTP 200 상태 코드를 반환합니다.



상품 삭제

deleteItem drawio

  1. 클라이언트가 상품 삭제 버튼을 누릅니다.

상품삭제 요청이 DELETE 메서드를 통해 서버로 전송됩니다. 이때 로컬 스토리지에 저장된 Access 토큰과 상품 ID가 함께 전달됩니다.

  1. Access 토큰이 만료된 경우, Spring Security는 401 Unauthorized 상태 코드를 반환합니다.
  2. 컨트롤러는 상품삭제 처리를 서비스에 위임하며, 전달받은 데이터를 바탕으로 deleteItem() 메서드를 호출하여 실제 상품삭제 처리를 수행합니다.

  1. 서비스는 아래의 과정을 통해 '상품 확인', '상품삭제 절차' 처리합니다.
  • 상품 확인
    • itemRepository.findById(itemId)를 호출하여 해당 상품을 DB에서 조회합니다.
    • 상품이 존재하지 않으면 ItemNotFoundException으로 HTTP 404 상태 코드를 응답합니다.
    • 주문요청을 받은 상품인 경우, 상품을 삭제할 수 없으므로 ItemDeletionNotAllowedException으로 HTTP 409 상태 코드를 응답합니다.
  • 상품삭제 절차
    • itemRepository.findUsersByItemId()를 호출해 해당 상품을 찜등록한 회원들을 조회합니다.
    • notificationRepository.save(request.toEntity())를 호출해 품절 메시지를 생성하여 DB에 입력합니다.
    • wishItemRepository.findAllByItem()를 호출해 찜항목에서 삭제합니다.
    • 마지막으로 itemRepository.delete()를 호출해 상품을 삭제합니다.
      이때 연관 데이터(상품에 대한 이미지, 해시태그)도 삭제됩니다.

  1. 상품 삭제요청이 성공적으로 완료되면, 서버는 클라이언트에게 HTTP 200 상태 코드를 반환합니다.



판매상품 조회

'판매상품 리스트' 메뉴버튼을 누르면, 회원이 등록한 판매상품 리스트를 조회할 수 있습니다.
판매상품 조회 서비스에 대한 시퀀스 다이어그램은 다음과 같습니다.
salelist drawio

  1. 클라이언트가 '판매상품 리스트' 버튼을 누릅니다.

판매상품 조회요청이 GET 메서드를 통해 서버로 전송됩니다. 이때 로컬 스토리지에 저장된 Access 토큰이 헤더에 포함됩니다.


  1. Access 토큰이 만료된 경우, Spring Security는 401 Unauthorized 상태 코드를 반환합니다.
  2. 컨트롤러는 판매상품 조회를 서비스에 위임하며, findSale() 메서드를 호출하여 실제 판매상품 조회를 수행합니다.
  3. 서버는 클라이언트에게 HTTP 200 상태 코드와 함께 판매상품 데이터를 응답합니다.



주문요청 조회

회원은 등록한 상품에 대한 주문요청 정보를 확인할 수 있습니다.
주문조회 서비스 시퀀스 다이어그램은 다음과 같습니다.
orderDetail drawio

  1. 클라이언트가 주문조회 버튼을 누른다.

주문조회 요청이 GET 메서드를 통해 서버로 전송됩니다. 이때 로컬 스토리지에 저장된 Access 토큰과 상품 ID가 함께 전달됩니다.


  1. Access 토큰이 만료된 경우, Spring Security는 401 Unauthorized 상태 코드를 반환합니다.
  2. 컨트롤러는 주문조회 요청을 서비스에 위임하며, findOrderDetail() 메서드를 호출하여 실제 주문조회를 수행합니다.
  3. 서버는 클라이언트에게 HTTP 200 상태 코드와 함께 주문정보 데이터를 응답합니다.



✅ 회원기능

프로필 수정

회원은 프로필 이미지를 바꿀 수 있습니다.
프로필 수정 서비스 시퀀스 다이어그램은 다음과 같습니다.
editProfile drawio

  1. 클라이언트가 프로필 수정 버튼을 눌러 이미지를 업로드합니다.

프로필수정 요청이 PATCH 메서드를 통해 서버로 전송됩니다. 이때 로컬 스토리지에 저장된 Access 토큰과 이미지 파일이 함께 전달됩니다.
이미지 파일을 업로드하기 때문에 formdata를 사용하여 데이터를 처리합니다.


  1. Access 토큰이 만료된 경우, Spring Security는 401 Unauthorized 상태 코드를 반환합니다.
  2. 컨트롤러는 프로필 수정요청을 서비스에 위임하며, updateProfileImg() 메서드를 호출하여 실제 프로필 수정요청을 수행합니다.
  3. 서비스는 아래의 과정을 통해 '회원정보 확인', '회원 프로필 업데이트'를 처리합니다.
  • 회원정보 확인
    • userRepository.findByEmail(user.getEmail())를 호출해 회원 정보를 조회합니다.
    • 해당 이메일의 사용자가 없을 경우 UserNotFoundException으로 HTTP 404 상태 코드를 응답합니다.
  • 회원 프로필 업데이트
    • 클라이언트가 업로드한 이미지 파일은 GCS에 업로드합니다.
    • loginUser.updateProfileImg()으로 회원 프로필에 대한 업데이트 쿼리를 실행합니다.

  1. 성공적으로 완료되면, 서버는 클라이언트에게 HTTP 200 상태 코드를 반환합니다.



닉네임 수정

회원은 닉네임을 바꿀 수 있습니다.
닉네임 수정 서비스 시퀀스 다이어그램은 다음과 같습니다.
editNick drawio

  1. 클라이언트가 닉네임 수정 버튼을 누릅니다.

닉네임수정 요청이 PATCH 메서드를 통해 서버로 전송됩니다. 이때 로컬 스토리지에 저장된 Access 토큰과 함께 입력한 닉네임 데이터를 바디에 담아 전달합니다.

  1. Access 토큰이 만료된 경우, Spring Security는 401 Unauthorized 상태 코드를 반환합니다.
  2. 컨트롤러는 닉네임 수정요청을 서비스에 위임하며, updateNickname() 메서드를 호출하여 실제 닉네임 수정요청을 수행합니다.
  3. 서비스는 아래의 과정을 통해 '회원정보 확인', '회원 닉네임 업데이트'를 처리합니다.
  • 회원정보 확인
    • userRepository.findByEmail(user.getEmail())를 호출해 회원 정보를 조회합니다.
    • 해당 이메일의 사용자가 없을 경우 UserNotFoundException으로 HTTP 404 상태 코드를 응답합니다.
  • 회원 닉네임 업데이트
    • loginUser.updateNickname()를 호출해 회원 닉네임에 대한 업데이트 쿼리를 실행합니다.
    • 클라이언트가 입력한 닉네임이 이미 존재하는 닉네임인 경우에는 DuplicateNicknameException으로 HTTP 409 상태 코드를 응답합니다.

  1. 성공적으로 완료되면, 서버는 클라이언트에게 HTTP 200 상태 코드를 반환합니다.



주문 리스트 조회

회원은 장바구니에 담아 주문했던 주문상품을 조회할 수 있습니다.
주문 리스트 조회 서비스 시퀀스 다이어그램은 다음과 같습니다.
orderlist drawio

  1. 클라이언트가 장바구니 버튼을 누릅니다.

주문조회 요청이 GET 메서드를 통해 서버로 전송됩니다. 이때 로컬 스토리지에 저장된 Access 토큰이 헤더에 포함됩니다.


  1. Access 토큰이 만료된 경우, Spring Security는 401 Unauthorized 상태 코드를 반환합니다.
  2. 컨트롤러는 주문조회 요청을 서비스에 위임하며, findOrderList() 메서드를 호출하여 실제 주문조회 요청을 수행합니다.
  3. 서버는 클라이언트에게 HTTP 200 상태 코드와 함께 주문 리스트 데이터를 응답합니다.



찜 리스트 조회

회원은 찜등록 했던 상품을 조회할 수 있습니다.
찜 리스트 조회 서비스 시퀀스 다이어그램은 다음과 같습니다.
wishlist drawio

  1. 클라이언트가 장바구니 버튼을 누릅니다.

찜 리스트 조회요청이 GET 메서드를 통해 서버로 전송됩니다. 이때 로컬 스토리지에 저장된 Access 토큰이 헤더에 포함됩니다.


  1. Access 토큰이 만료된 경우, Spring Security는 401 Unauthorized 상태 코드를 반환합니다.
  2. 컨트롤러는 찜 리스트 조회요청을 서비스에 위임하며, findWishList() 메서드를 호출하여 실제 찜 리스트 조회요청을 수행합니다.
  3. 서버는 클라이언트에게 HTTP 200 상태 코드와 함께 찜 리스트 데이터를 응답합니다.



메시지 조회

회원은 주문과 품절 안내에 대한 알림 메시지를 받을 수 있습니다.

  • 상품 판매자는 자신이 등록한 상품에 주문 요청이 들어오면, "A님이 상품 B를 주문하였습니다." 라는 메시지를 받습니다.
  • 구매자는 주문 요청이 완료되면, "A님, 상품 B 주문이 완료되었습니다. 감사합니다!"라는 메시지를 받습니다.
  • 판매자가 등록한 상품을 삭제했을 경우, 해당 상품을 찜 목록에 추가한 회원은 "상품 B가 품절되어 찜 목록에서 삭제되었습니다."라는 메시지를 받습니다.

메시지 조회 서비스 시퀀스 다이어그램은 다음과 같습니다.
getMsg drawio

  1. 회원은 알림 메뉴 아이콘을 클릭합니다.

메시지 조회요청이 GET 메서드를 통해 서버로 전송됩니다. 이때 로컬 스토리지에 저장된 Access 토큰이 헤더에 포함됩니다.


  1. Access 토큰이 만료된 경우, Spring Security는 401 Unauthorized 상태 코드를 반환합니다.
  2. 컨트롤러는 메시지 조회요청을 서비스에 위임하며, findMessage() 메서드를 호출하여 실제 메시지 조회요청을 수행합니다.
  3. 서비스는 아래의 과정을 통해 '회원정보 확인', '메시지 조회'를 처리합니다.
  • 회원정보 확인
    • userRepository.findByEmail(user.getEmail())를 호출해 회원 정보를 조회합니다.
    • 해당 이메일의 사용자가 없을 경우 UserNotFoundException으로 HTTP 404 상태 코드를 응답합니다.
  • 메시지 조회
    • notificationRepository.findByUserEmail()를 호출해 메시지를 조회합니다.

  1. 서버는 클라이언트에게 HTTP 200 상태 코드와 함께 메시지 데이터를 응답합니다.
⚠️ **GitHub.com Fallback** ⚠️