Skip to content

Commit

Permalink
충남대 BE_윤정훈 6주차 과제 (1단계) (#146)
Browse files Browse the repository at this point in the history
* add: 주문하기 코드를 옮겨온다.

옮겨온다.

* refactor: gitignore 변경

* remove: 동시성 테스트 진행으로 인해 발생하는 build 과부하 방지를 위해 동시성테스트 제거

동시성 테스트 제거

* add: 기존 동시성테스트 추가

동시성 테스트 추가

* add: ci-cd 파일 추가

ci-cd 파일 추가

* rename: workflows -> workflow

* rename: ci-cd to gradle

* Create gradle.yml

* remove: workflow remove

* add: CI with java

* refactor: 자동으로 application.yml 파일 생성하도록 추가

* add: make application.yml 설정파일 생성

* rename: application 설정파일 이름 재설정

* remove: 동시성 테스트 삭제

* change: setup jdk

* remove: deploy 코드 제거

* add: make application.yml 방식 추가

* refactor: application.yml 만드는 코드 수정

* add: deploy gradle 추가

* rename: secret deploy server로 ip 보호

* add: EC2 서버에 키를 알려줌

* add: 호스트키 신뢰하도록 설정

* rename: 호스트키 이름 변경

* add: HOST 추가

* add: 호스트키 검증 무시

* add: redirect-token-uri를 따로 관리해서 배포환경과 다른값 설정할 수 있도록 함

* refactor: 이름 명시

* refactor: 배포 코드 수정

* refactor: 절대 경로 설정

* add: 배포시 중간에 sleep 10 추가

* remove: 그냥 실행되는 부분 제거

* add: 기존 실행중인 8080포트 죽이기

* refactor: 절대경로로 설정

* refactor: application.yml이 아닌 application.properties에 추가작성함으로써 하나로 통일관리

* refactor: 설정값 변경

* add: 동시성테스트의 크기를 줄여 부하를 적게하여 업로드하기 쉽도록 변경

테스트코드 사이즈 변경

* refactor: test부하 일부 증가

test부하 일부 증가

* refactor: API 명세 팀원들과 통일

API 명세-URL을 팀원들과 통일

* test: 수정된 API 명세에 알맞게 controller URL 변경

* docs: Swagger 문서 작성을 위한 ApiResponse(Auth, Category) 작성 완료

AuthApi, CategoryApi ApiResponse 정의 완료

* docs: API 명세 통일에 따른 응답 반환

응답 반환하기

* remove: 중복되는 @hidden 삭제

* infra: 스프링 배포 환경시 nohup 스프링 실행부분을 세션과 분리하여 종료

* infra: 백그라운드에서 실행 및 exit 으로 자동으로 배포까지하도록 설정

* infra: 백그라운드에서 스프링이 정상적으로 돌아가도록 gradle.yml 수정

* add: 스프링실행시 세션을 정상적으로 종료할 수 있도록 한다

* remove: Member-Role을 삭제

* add: 예외 Response를 한번 더 감싸서 status와 함께 반환

예외 Response 를 status, message 함께 반환

* add: API 명세서 중 응답이 포함되지 않는 부분은 응답에서 제외한다.

Schema-hidden=true 설정을 통해 응답에서 제외했다.

* refactor: 팀원들간 API 명세 통일 작업 수행

API 명세 통일 작업 수행

* docs: README.md 진행한 부분 체크

진행한 부분 체크작업 수행

* add: ADD 요청시 created 에 URL 을 담고, body를 반환하도록 함

body를 반환하도록 함

* remove: 사용하지 않는 예외 코드 삭제

사용하지 않는 예외코드 삭제

* refactor: List로 반환한 정보를 Page로 반환하도록 변경

List to Page 변경

* refactor: Page -> PageResponse 라는 DTO를 만들어 반환하도록 변경

DTO로 응답 타입 변환 과정 거침

* docs: API 명세서 PageResponse 로 변경

API 명세서 변경

* refactor: API 수정사항 반영

API 수정 사항 반영
  • Loading branch information
yunjunghun0116 authored Aug 1, 2024
1 parent 531a67c commit b72cae4
Show file tree
Hide file tree
Showing 78 changed files with 1,161 additions and 893 deletions.
11 changes: 6 additions & 5 deletions .github/workflows/gradle.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,8 @@ jobs:

- name: 설정파일 생성
run: |
touch ./src/main/resources/application.yml
echo "${{ secrets.APPLICATION }}" > ./src/main/resources/application.yml
cat ./src/main/resources/application.yml
echo "${{ secrets.APPLICATION_PROPERTIES }}" >> ./src/main/resources/application.properties
cat ./src/main/resources/application.properties
- name: gradlew 권한 추가
run: chmod +x gradlew
Expand All @@ -49,10 +48,12 @@ jobs:
echo "$SSH_KEY" > key.pem
chmod 400 key.pem
scp -o StrictHostKeyChecking=no -i key.pem build/libs/*.jar $DEPLOY_USER@$DEPLOY_SERVER:~/spring-gift-point/build/libs/
scp -o StrictHostKeyChecking=no -i key.pem ./src/main/resources/application.yml $DEPLOY_USER@$DEPLOY_SERVER:~/spring-gift-point/src/main/resources/application.yml
scp -o StrictHostKeyChecking=no -i key.pem ./src/main/resources/application.properties $DEPLOY_USER@$DEPLOY_SERVER:~/spring-gift-point/src/main/resources/application.properties
ssh -o StrictHostKeyChecking=no -i key.pem $DEPLOY_USER@$DEPLOY_SERVER "
sudo lsof -t -i:8080 | xargs -r sudo kill -9
nohup java -jar ~/spring-gift-point/build/libs/spring-gift-0.0.1-SNAPSHOT.jar &"
nohup java -jar ~/spring-gift-point/build/libs/spring-gift-0.0.1-SNAPSHOT.jar > /dev/null 2>&1 &
exit
" && echo "스프링 프로젝트가 서버에서 정상적으로 돌아가고 있습니다."
dependency-submission:

Expand Down
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,13 @@

- [X] 주문하기 코드를 옮겨온다.

#### 1단계

- [X] URL 주소를 일치시킨다.
- [X] DTO 를 일치시킨다.
- [X] 반환하는 응답을 일정하게 상태코드를 통일시킨다.
- [X] 예외에 해당하는 응답을 Exception Handler 에서는 ExceptionResponse 으로 감싸서 반환하도록 한다.

### 나만의 HTTP RULE

| HTTP Method | 사용상황 | 반환(상태코드) |
Expand Down
11 changes: 4 additions & 7 deletions src/main/java/gift/client/KakaoApiClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
import gift.dto.kakao.template.KakaoTemplateContent;
import gift.dto.kakao.template.KakaoTemplateLink;
import gift.exception.BadRequestException;
import gift.exception.InvalidKakaoTokenException;
import gift.exception.UnauthorizedAccessException;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
Expand Down Expand Up @@ -63,10 +63,7 @@ public KakaoTokenResponse getRefreshedTokenResponse(String refreshToken) {
.body(body)
.retrieve()
.onStatus(statusCode -> statusCode.equals(HttpStatus.UNAUTHORIZED), (req, res) -> {
throw new InvalidKakaoTokenException(INVALID_TOKEN_MESSAGE);
})
.onStatus(statusCode -> statusCode.equals(HttpStatus.BAD_REQUEST), (req, res) -> {
throw new InvalidKakaoTokenException(INVALID_TOKEN_MESSAGE);
throw new UnauthorizedAccessException("유효하지 않은 카카오 리프레시 토큰입니다.");
})
.body(String.class);

Expand Down Expand Up @@ -102,7 +99,7 @@ public void sendSelfMessageOrder(String accessToken, GiftOrderResponse giftOrder
.body(body)
.retrieve()
.onStatus(statusCode -> statusCode.equals(HttpStatus.UNAUTHORIZED), (req, res) -> {
throw new InvalidKakaoTokenException(INVALID_TOKEN_MESSAGE);
throw new UnauthorizedAccessException(INVALID_TOKEN_MESSAGE);
})
.body(String.class);
} catch (JsonProcessingException exception) {
Expand All @@ -122,7 +119,7 @@ private KakaoTemplate getCommerceTemplate(GiftOrderResponse giftOrderResponse) {
var objectType = "commerce";
var link = new KakaoTemplateLink("https://gift.kakao.com/product/2370524");
var content = new KakaoTemplateContent(giftOrderResponse.message(), "https://img1.kakaocdn.net/thumb/[email protected]/?fname=https%3A%2F%2Fst.kakaocdn.net%2Fproduct%2Fgift%2Fproduct%2F20240417111629_616eccb9d4cd464fa06d3430947dce15.jpg", giftOrderResponse.message(), link);
var commerce = new KakaoTemplateCommerce(giftOrderResponse.optionInformation().productName() + "[" + giftOrderResponse.optionInformation().name() + "]", giftOrderResponse.optionInformation().price() * giftOrderResponse.quantity());
var commerce = new KakaoTemplateCommerce(giftOrderResponse.productBasicInformation().name() + "[" + giftOrderResponse.optionResponse().name() + "]", giftOrderResponse.productBasicInformation().price() * giftOrderResponse.quantity());
return new KakaoTemplate(objectType, content, commerce);
}
}
65 changes: 0 additions & 65 deletions src/main/java/gift/config/SwaggerConfig.java
Original file line number Diff line number Diff line change
@@ -1,17 +1,10 @@
package gift.config;

import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.Operation;
import io.swagger.v3.oas.models.PathItem;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.parameters.HeaderParameter;
import io.swagger.v3.oas.models.responses.ApiResponse;
import org.springdoc.core.customizers.OpenApiCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.Set;

@Configuration
public class SwaggerConfig {

Expand All @@ -23,62 +16,4 @@ public OpenAPI openAPI() {
.description("프론트엔드와 협업을 위한 API 문서");
return new OpenAPI().info(info);
}

@Bean
public OpenApiCustomizer openApiCustomizer() {
return openApi -> {
openApi.getPaths()
.forEach((path, pathItem) -> {
setBaseOperationResponse(path, pathItem);
setOperationResponse(pathItem.getPut(), path, "PUT");
setOperationResponse(pathItem.getPost(), path, "POST");
setOperationResponse(pathItem.getDelete(), path, "DELETE");
});
};
}

private void setBaseOperationResponse(String path, PathItem pathItem) {
var excludePaths = Set.of("/api/members/oauth/kakao", "/api/members/login", "/api/members/register", "/api/kakao/get-oauth");

for (var operation : pathItem.readOperations()) {
var successResponse = new ApiResponse().description("성공");
operation.getResponses()
.addApiResponse("200", successResponse);

if (!excludePaths.contains(path)) {
var header = new HeaderParameter()
.name("Authorization")
.required(Boolean.TRUE);
operation.addParametersItem(header);

var unauthorizedResponse = new ApiResponse().description("잘못된 인증정보");
operation.getResponses().addApiResponse("401", unauthorizedResponse);
}
}
}

private void setOperationResponse(Operation operation, String path, String method) {
if (operation == null) return;
if (method.equals("POST") && path.contains("/add")) {
var createdResponse = new ApiResponse().description("생성 성공");
operation.getResponses()
.addApiResponse("201", createdResponse);
operation.getResponses()
.remove("200");
}
if (method.equals("PUT")) {
var updatedResponse = new ApiResponse().description("업데이트 성공");
operation.getResponses()
.addApiResponse("204", updatedResponse);
operation.getResponses()
.remove("200");
}
if (method.equals("DELETE")) {
var updatedResponse = new ApiResponse().description("삭제 성공");
operation.getResponses()
.addApiResponse("204", updatedResponse);
operation.getResponses()
.remove("200");
}
}
}
6 changes: 2 additions & 4 deletions src/main/java/gift/config/WebConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,7 @@ public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(authInterceptor)
.addPathPatterns("/**")
.excludePathPatterns("/swagger-resources/**", "/swagger-ui/**", "/v3/api-docs/**")
.excludePathPatterns("/api/members/oauth/kakao")
.excludePathPatterns("/api/members/login")
.excludePathPatterns("/api/members/register")
.excludePathPatterns("/api/kakao/get-oauth");
.excludePathPatterns("/api/members/login/**")
.excludePathPatterns("/api/members/register");
}
}
2 changes: 1 addition & 1 deletion src/main/java/gift/config/properties/KakaoProperties.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@
import org.springframework.boot.context.properties.ConfigurationProperties;

@ConfigurationProperties(prefix = "kakao")
public record KakaoProperties(String restApiKey, String redirectUri, String tokenUri) {
public record KakaoProperties(String restApiKey, String redirectUri, String tokenUri, String oauthBaseUri) {
}
21 changes: 8 additions & 13 deletions src/main/java/gift/controller/CategoryController.java
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
package gift.controller;

import gift.controller.api.CategoryApi;
import gift.dto.category.CategoryRequest;
import gift.dto.category.CategoryResponse;
import gift.service.CategoryService;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.web.PageableDefault;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
Expand All @@ -23,22 +20,21 @@

@RestController
@RequestMapping("/api/categories")
@Tag(name = "CATEGORY")
public class CategoryController {
public class CategoryController implements CategoryApi {

private final CategoryService categoryService;

public CategoryController(CategoryService categoryService) {
this.categoryService = categoryService;
}

@PostMapping("/add")
public ResponseEntity<Void> addCategory(@Valid @RequestBody CategoryRequest categoryRequest) {
@PostMapping
public ResponseEntity<CategoryResponse> addCategory(@Valid @RequestBody CategoryRequest categoryRequest) {
var category = categoryService.addCategory(categoryRequest);
return ResponseEntity.created(URI.create("/api/categories/" + category.id())).build();
return ResponseEntity.created(URI.create("/api/categories/" + category.id())).body(category);
}

@PutMapping("/update/{id}")
@PutMapping("/{id}")
public ResponseEntity<Void> updateCategory(@PathVariable Long id, @Valid @RequestBody CategoryRequest categoryRequest) {
categoryService.updateCategory(id, categoryRequest);
return ResponseEntity.noContent().build();
Expand All @@ -51,9 +47,8 @@ public ResponseEntity<CategoryResponse> getCategory(@PathVariable Long id) {
}

@GetMapping
public ResponseEntity<List<CategoryResponse>> getCategories(
@PageableDefault(sort = "id", direction = Sort.Direction.DESC) Pageable pageable) {
var categories = categoryService.getCategories(pageable);
public ResponseEntity<List<CategoryResponse>> getCategories() {
var categories = categoryService.getCategories();
return ResponseEntity.ok(categories);
}

Expand Down
31 changes: 24 additions & 7 deletions src/main/java/gift/controller/GiftOrderController.java
Original file line number Diff line number Diff line change
@@ -1,30 +1,47 @@
package gift.controller;

import gift.controller.api.GiftOrderApi;
import gift.dto.giftorder.GiftOrderPageResponse;
import gift.dto.giftorder.GiftOrderRequest;
import gift.dto.giftorder.GiftOrderResponse;
import gift.service.GiftOrderService;
import io.swagger.v3.oas.annotations.tags.Tag;
import gift.service.KakaoService;
import gift.service.OptionService;
import jakarta.validation.Valid;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.web.PageableDefault;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestAttribute;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;
import java.net.URI;

@RestController
@RequestMapping("/api/giftOrders")
@Tag(name = "GIFT_ORDER")
public class GiftOrderController {
@RequestMapping("/api/orders")
public class GiftOrderController implements GiftOrderApi {

private final GiftOrderService giftOrderService;
private final OptionService optionService;
private final KakaoService kakaoService;

public GiftOrderController(GiftOrderService giftOrderService) {
public GiftOrderController(GiftOrderService giftOrderService, OptionService optionService, KakaoService kakaoService) {
this.giftOrderService = giftOrderService;
this.optionService = optionService;
this.kakaoService = kakaoService;
}

@PostMapping
public ResponseEntity<GiftOrderResponse> orderOption(@RequestAttribute("memberId") Long memberId, @Valid @RequestBody GiftOrderRequest giftOrderRequest) {
var order = optionService.orderOption(memberId, giftOrderRequest);
kakaoService.sendOrderResponseWithKakaoMessage(memberId, order);
return ResponseEntity.created(URI.create("/api/orders/" + order.id())).body(order);
}

@GetMapping("/{id}")
Expand All @@ -34,7 +51,7 @@ public ResponseEntity<GiftOrderResponse> getOrder(@PathVariable Long id) {
}

@GetMapping
public ResponseEntity<List<GiftOrderResponse>> getOrders(@RequestAttribute("memberId") Long memberId, @PageableDefault(sort = "id", direction = Sort.Direction.DESC) Pageable pageable) {
public ResponseEntity<GiftOrderPageResponse> getOrders(@RequestAttribute("memberId") Long memberId, @PageableDefault(sort = "id", direction = Sort.Direction.DESC) Pageable pageable) {
var orders = giftOrderService.getGiftOrders(memberId, pageable);
return ResponseEntity.ok(orders);
}
Expand Down
23 changes: 3 additions & 20 deletions src/main/java/gift/controller/KakaoController.java
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
package gift.controller;

import gift.config.properties.KakaoProperties;
import gift.controller.api.KakaoApi;
import gift.service.KakaoService;
import io.swagger.v3.oas.annotations.Hidden;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
Expand All @@ -17,12 +16,10 @@

@RestController
@RequestMapping("/api/kakao")
@Tag(name = "KAKAO")
public class KakaoController {
public class KakaoController implements KakaoApi {

private final KakaoService kakaoService;
private final KakaoProperties kakaoProperties;
private static final String OAUTH_BASE_URL = "https://kauth.kakao.com/oauth/authorize?response_type=code&scope=account_email,talk_message";

public KakaoController(KakaoService kakaoService, KakaoProperties kakaoProperties) {
this.kakaoService = kakaoService;
Expand All @@ -35,30 +32,16 @@ public ResponseEntity<Void> redirectSetToken(@RequestAttribute("memberId") Long
return new ResponseEntity<>(headers, HttpStatus.MOVED_PERMANENTLY);
}

@Hidden
@GetMapping("/token")
public ResponseEntity<Void> setToken(@RequestParam String code, @RequestParam String state) {
var memberId = Long.valueOf(state);
kakaoService.saveKakaoToken(memberId, code);
return ResponseEntity.noContent().build();
}

@GetMapping("/get-oauth")
public ResponseEntity<Void> redirectOAuth() {
var headers = getRedirectHeader(kakaoProperties.redirectUri());
return new ResponseEntity<>(headers, HttpStatus.MOVED_PERMANENTLY);
}

private HttpHeaders getRedirectHeader(String redirectUri) {
var headers = new HttpHeaders();
String redirectLocation = OAUTH_BASE_URL + "&client_id=" + kakaoProperties.restApiKey() + "&redirect_uri=" + redirectUri;
headers.setLocation(URI.create(redirectLocation));
return headers;
}

private HttpHeaders getRedirectHeader(String redirectUri, Long memberId) {
var headers = new HttpHeaders();
String redirectLocation = OAUTH_BASE_URL + "&client_id=" + kakaoProperties.restApiKey() + "&redirect_uri=" + redirectUri + "&state=" + memberId;
String redirectLocation = kakaoProperties.oauthBaseUri() + "&client_id=" + kakaoProperties.restApiKey() + "&redirect_uri=" + redirectUri + "&state=" + memberId;
headers.setLocation(URI.create(redirectLocation));
return headers;
}
Expand Down
5 changes: 2 additions & 3 deletions src/main/java/gift/controller/MemberController.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package gift.controller;

import gift.controller.api.MemberApi;
import gift.service.MemberService;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.RequestAttribute;
Expand All @@ -10,8 +10,7 @@

@RestController
@RequestMapping("/api/members")
@Tag(name = "MEMBER")
public class MemberController {
public class MemberController implements MemberApi {

private final MemberService memberService;

Expand Down
Loading

0 comments on commit b72cae4

Please sign in to comment.