์๊ธ ์ ์ฑ
- ๋ก๊ทธ์ธ ์ฌ์ฉ์์ ๋น๋ก๊ทธ์ธ ์ฌ์ฉ์๋ฅผ ๊ตฌ๋ณํ์ฌ ์๊ธ ์ ์ฑ ์ ์ ์ฉ
- PathController์์๋ ํ ํฐ์ด ์์ด๋ ์์ธ๊ฐ ์๋์๊ณ
- MemberController์์๋ ํ ํฐ์ด ์์ผ๋ฉด ์์ธ์๊ธฐ์ Resolver์์๋ ๊ฐ๊ฐ์ ๋ง๋ ์ฒ๋ฆฌ๋ฅผ ํด์ฃผ์ด์ผ ํ์
- ๋งจ ์ฒ์ ํ์ด๋ ๊ธฐ๋ฅ๋ง ๋์๊ฐ๊ฒ ๊ตฌํํ์ ๋๋ ๊ธฐ์กด์ ์๋ ๋ก๊ทธ์ธ๋ ์ฌ์ฉ์์ ๋ํ ์ธ๊ฐ ๊ณผ์ ์ ๊ฑฐ์น๋ Resolver๋ฅผ ์ฌ์ฌ์ฉํ๋๋ก ๊ตฌํ
- ์ด๋ฌ๊ธฐ ์ํด์๋ ์ด ๊ฐ๊ฐ์ ๋ง๋ ์ฒ๋ฆฌ๋ฅผ ์ผ๊ฐ Controller๋ก ์ฎ๊ฒจ์ผ ํ์
AuthenticationPrincipalArgumentResolver
@Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) {
String credentials = AuthorizationExtractor.extract(webRequest.getNativeRequest(HttpServletRequest.class));
LoginMember member = authService.findMemberByToken(credentials);
if (member.getId() == null) {
throw new AuthorizationException();
}
return member;
}
MemberController์์ LoginMember์ ๋ํ ์ฒ๋ฆฌ
private void unAuthorizedThrowException(@AuthenticationPrincipal LoginMember loginMember) {
if (loginMember.getId() == null) {
throw new AuthorizationException();
}
}
- id๊ฐ ์์ผ๋ฉด (์กด์ฌํ์ง ์๋ ์ฌ์ฉ์์ด๋ฉด) ์์ธ
PathController์์ LoginMember์ ๋ํ ์ฒ๋ฆฌ
private LoginMember unLoginMemberWrapper(@AuthenticationPrincipal LoginMember loginMember) {
if (loginMember.getId() == null) {
return new LoginMember(null, null, -1);
}
return loginMember;
}
- id๊ฐ ์กด์ฌํ์ง ์์ผ๋ฉด age๋ฅผ
-1
๋ก wrap
๊ทธ๋ฐ๋ฐ ์ด๋ ๊ฒ ๊ตฌํํ๊ณ ์๊ฐํ ๋ฌธ์ ์ ์ดโฆ
- Controller์์ ์ด๋ฏธ ๋ฆฌ์กธ๋น๋ LoginMember์ ๋ํ ์ฒ๋ฆฌ๋ฅผ ๋ ๊ฑด๋๋ฆฌ๊ณ ์๋ค๋ ๋๋
- Controller์์ LoginMember์ ๋ํ ๋น์ฆ๋์ค ๋ก์ง์ ์๊ณ ์๋ ๋๋์ด๋ผ ๊ฐ์ ์ด ํ์ํ๋ค๊ณ ๋๋
- age๋ฅผ -1๋ก ๊ฐ์ธ์ ์ด ๊ฒฝ์ฐ ๋น๋ก๊ทธ์ธ์๋ก ๊ฐ์ ํ๋ ๋ก์ง์ด ๊ด์ฐฎ์์ง ์๋ฌธ์ ํ๊ณ ์์์
ํ์ด์ ๋ฆฌ๋ทฐ์ด์๊ฒ ์จ ํผ๋๋ฐฑ
- ์ผ๋จ
AuthenticationPrincipalArgumentResolver
์AgeAuthenticationPrincipalArgumentResolver
๋๊ฐ๋ก ๋ถ๋ฆฌํ์์ AgeAuthenticationPrincipalArgumentResolver
์์๋ ์๊ธ ์ ์ฑ ์ ํ์ํ ๊ฐ์ธage
๋ง ๋ฐํํ๋๋ก ๋ฆฌํฉํ ๋ง
AgeAuthenticationPrincipalArgumentResolver
public class AgeAuthenticationPrincipalArgumentResolver implements HandlerMethodArgumentResolver {
private AuthService authService;
public AgeAuthenticationPrincipalArgumentResolver(AuthService authService) {
this.authService = authService;
}
@Override
public boolean supportsParameter(MethodParameter parameter) {
return parameter.hasParameterAnnotation(AgeAuthenticationPrincipal.class);
}
@Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) {
String credentials = AuthorizationExtractor.extract(Objects.requireNonNull(webRequest.getNativeRequest(HttpServletRequest.class)));
LoginMember memberByToken = authService.findMemberByToken(credentials);
return memberByToken.getAge();
}
}
Integer
ํ์ธ age๋ฅผ ๋ฐํํ๋๋กโฆ.- ๋ฐํํ์ ์ ๋ช ์์ ์ผ๋ก ์ ์ด์ค๊ฑธ ๊ทธ๋ฌ๋ค
PathService์ findPath()
public PathResponse findPath(Integer age, Long source, Long target) {
try {
List<Line> lines = lineService.findLines();
Station sourceStation = stationService.findStationById(source);
Station targetStation = stationService.findStationById(target);
SubwayPath subwayPath = pathFinder.findPath(lines, sourceStation, targetStation);
int distance = subwayPath.calculateDistance();
int lineFare = subwayPath.getMaxLineFare();
SubwayPathFare subwayPathFare = new SubwayPathFare(age, distance, lineFare);
return PathResponseAssembler.assemble(subwayPath, subwayPathFare);
} catch (Exception e) {
throw new InvalidPathException();
}
}
SubwayPathFare
public class SubwayPathFare {
private final Integer age;
private final int distance;
private final int lineFare;
public SubwayPathFare(Integer age, int distance, int lineFare) {
this.age = wrapAge(age);
this.distance = distance;
this.lineFare = lineFare;
}
private int wrapAge(Integer age) {
if (age == null) {
return -1;
}
return age;
}
public int getFare() {
int fareByDistance = FareCalculatorByDistance.from(distance);
return FareAdjusterByAge.of(age, fareByDistance, lineFare);
}
}
- ์๊ธ ์ ์ฑ
์ ํด๋น ๋๋ฉ์ธ์์ Enum์ธ
FareCalculatorByDistance
์FareAdjusterByAge
๋ฅผ ํตํด ๊ณ์ฐํ๊ณ ์์์ wrapAge()
๋ฅผ ํตํด null ๊ฐ์ผ๋ก age๊ฐ ๋ค์ด์ค๋ฉดFareAdjusterByAge.of()
์์ ์คํธ๋ฆผ์ ๋๋ฆฌ๋๋ฐ, ์ด์ ์์ธ๊ฐ ๋ฐ์ํ์ง ์๋๋ก -1๋ก ํฌ์ฅ
์ฐธ๊ณ - FareAdjusterByAge.of()
public static int of(int age, int fare, int lineFare) {
return Arrays.stream(values())
.filter(ageRange -> ageRange.minInclusive <= age && age < ageRange.maxExclusive)
.map(calculator -> calculator.adjuster.apply(fare, lineFare))
.findAny()
.orElse(fare + lineFare);
}
FareCalculatorByDistance - ๊ฑฐ๋ฆฌ๋ณ ์๊ธ ์ ์ฑ
public enum FareCalculatorByDistance {
BASE(0, Constants.BASE_MAX_BOUNDARY, distance -> Constants.BASE_FARE),
FIRST_ADDITIONAL(Constants.BASE_MAX_BOUNDARY, Constants.FIRST_ADDITIONAL_MAX_BOUNDARY,
(distance) -> Constants.BASE_FARE + (int) ((Math.ceil((distance - Constants.BASE_MAX_BOUNDARY - 1) / 5)) + 1) * Constants.EXTRA_FARE),
SECOND_ADDITIONAL(Constants.FIRST_ADDITIONAL_MAX_BOUNDARY, Integer.MAX_VALUE,
(distance) -> Constants.BASE_FARE + 800 + (int) ((Math.ceil((distance - Constants.FIRST_ADDITIONAL_MAX_BOUNDARY - 1) / 8)) + 1) * Constants.EXTRA_FARE);
private final int minExclusive;
private final int maxInclusive;
private final UnaryOperator<Integer> calculator;
FareCalculatorByDistance(int minExclusive, int maxInclusive, UnaryOperator<Integer> calculator) {
this.minExclusive = minExclusive;
this.maxInclusive = maxInclusive;
this.calculator = calculator;
}
FareAdjusterByAge - ๋์ด๋ณ ์๊ธ ์ ์ฑ
public enum FareAdjusterByAge {
PRE_SCHOOLED(0, Constants.PRE_SCHOOL_MAX_BOUNDARY, getIntegerBinaryOperator(0)),
SCHOOL_AGED(Constants.PRE_SCHOOL_MAX_BOUNDARY, Constants.SCHOOL_AGED_MAX_BOUNDARY, getIntegerBinaryOperator(Constants.SCHOOL_AGED_RATE)),
ADOLESCENT(Constants.SCHOOL_AGED_MAX_BOUNDARY, Constants.ADOLESCENT_MAX_BOUNDARY, getIntegerBinaryOperator(Constants.ADOLESCENT_RATE));
private final int minInclusive;
private final int maxExclusive;
private final BinaryOperator<Integer> adjuster;
FareAdjusterByAge(int minInclusive, int maxExclusive, BinaryOperator<Integer> adjuster) {
this.minInclusive = minInclusive;
this.maxExclusive = maxExclusive;
this.adjuster = adjuster;
}
private static BinaryOperator<Integer> getIntegerBinaryOperator(double rate) {
return (fare, lineFare) -> (int) (((fare + lineFare) - 350) * rate);
}
๋ฆฌ๋ทฐ์ด์๊ฒ ๋ฐ์ ํผ๋๋ฐฑ
- ๋ฆฌ๋ทฐ์ด์ ์๋๋ Member๋ฅผ ๋ํ๋ด๋ ๋๋ฉ์ธ์์ age๋ฅผ nullableํ๊ฒ ๋๊ณ ์ด๋ฅผ ์ฒ๋ฆฌํ๋ ๊ฒ์ด ๋ ๋ช ํํ ๊ฒ ๊ฐ๋คํ์ฌ
์์ฌ์ด ์
๋์ด๋ณ ์๊ธ์ ์ฑ ์ ์ ์ฉํ ๋ Member ๋๋ฉ์ธ์ ์ฌ์ฉํด๋ณผ๊ฑธ!
ํ์ฌ ๊ฒฝ๋ก ์กฐํ๋ฅผ ํ ๋๋ member ๋๋ฉ์ธ์ด ๋์ด์ค์ง ์๊ณ age ๊ฐ๋ง ๋์ด์ค๋๋ก ๊ตฌํํ์๋ค.
๊ทธ๋ฐ๋ฐ Age๋ Member์ ์ข
์๋๋ ํ๋์ธ๋ฐ ์ด๋ฅผ ๋นผ์ ๋
๋ฆฝ์ ์ผ๋ก ์ฒ๋ฆฌํ๊ณ ์๋๊ฒ ์ง๊ธ๋ณด๋ ๋ง์์ ๋ค์ง ์๋๋ค.
๋ง์ฝ Member์ ๋ค๋ฅธ ํ๋๋ค๋ ์๊ธ์ ์ฑ
์ ์ํ์ ์ฃผ๊ฒ ๋๋ค๋ฉด ์ ์ง๋ณด์๊ฐ ์ด๋ ค์ด ์ฝ๋๊ฐ ๋๋ค.
ํฌ๋ฃจ๋ค์ด๋ ์ด์ผ๊ธฐ๋ฅผ ํด๋ณด๋ ํ ๋ฆฌ์กธ๋ฒ์์ Member๋ฅผ ๋ฐํํด์ฃผ๋๋ฐ, ์ด ๋ฐํ ๋๋ฉ์ธ์ ํ ์ธํฐํ์ด์ค(์๋ฅผ ๋ค๋ฉด Member)๋ฅผ ๋ง๋ค๊ณ ์ด๋ฅผ ๊ตฌํํ Guest
, LoginMember
๋ก ๋ก๊ทธ์ธ, ๋น๋ก๊ทธ์ธ ์ฌ์ฉ์๋ฅผ ๊ตฌ๋ณํ์ฌ ๋ก์ง์ ์ํํ๋ ๋ฐฉ๋ฒ๋ ์๋ค๊ณ ํ๋ค.
์ด๋ฌ๋ฉด ๋ฆฌ์กธ๋ฒ๋ฅผ ๋๋ ํ์๋ ์๊ณ Member๊ฐ age๋ฅผ ๊ฐ์ง๊ณ ๋์ด์ ๊ดํ ์๊ธ ์ ์ฑ ์ ์ํํ ๋ ํด๋น ๋๋ฉ์ธ์๊ฒ ๋ฌผ์ด์ ์ฒ๋ฆฌํ ์ ์์ ๊ฒ ๊ฐ๋ค.
Enum์ Predicate๋ฅผ ๊ฐ์ง ํ ๊ฑธ!
๋ํ ๊ฐ๊ฐ ์๊ธ ์ ์ฑ ์ Enum์ผ๋ก ๊ตฌํํ์๋๋ฐ, ์ฌ๊ธฐ์ ์์๋ฅผ ์ฐ๋ ๊ฐ๋ ์ฑ์ด ๋งค์ฐ ๋จ์ด์ง๋ ๋๋์ด๋ค.
์์๋ฅผ ์ด ์ด์ ๋ ์์ ํผ๋๋ฐฑ์ผ๋ก ๋งค์ง ๋๋ฒ์ ์๋ฏธ๋ฅผ ๋ถ์ฌํ๊ณ ์ถ์์ผ๋โฆ
์ด๋ ๊ฒ ํ๋ ์คํ๋ ค ๊ฐ๋
์ฑ์ ํค์น๋ ๋๋์ด์๊ณ ๋ง์ง๋ง ๋ฆฌ๋ทฐ๋๋ก Enum ์์ ๋ฒ์๋ฅผ ํ๋จํ๋ Predicate
๋ฅผ ๊ฐ์ง๋๋ก ํ ๊ฑธ ๊ทธ๋ฌ๋ค.
ํ๋ก ํธ์๋์์ ํ์
- ๋ฐฑ์๋ 4, ํ๋ก ํธ์๋ 2๋ช ์ ๋์ฉ ํ์ ์ด๋ฃจ์ด ํ์ ํ๋ ๋ฏธ์ ์ด์์
- ํด๋น ๋ฌธ์ ์ ์๋ ํ๋ก ํธ์๋ ์๊ตฌ์ฌํญ์ ๋ผ๋์ฝ๋์ ๋ฐ์ํด ๋๊ฐ
API ๋ฌธ์ํ
- Spring Rest Docs๋ฅผ ํตํด API ๋ฌธ์ํ ์์ ์ ์งํ
- ๊ธฐ์กด์ ์๋ RestAssured ํ ์คํธ๋ฅผ ์ด์ฉํด API๋ฅผ ๋ง๋ค์๋ ์๋๋ฐ, ํ์ด๋ ๊ฐ์ด ์๋ํ๋ค๊ฐ ๊ณ์ ์ค๋ฅ๋์โฆ.
- ๊ฒฐ๊ตญ MockMvc๋ก ํ ์คํธ ์ฝ๋ ๋ค์์ง์ API ๋ฌธ์๋ฅผ ๋ง๋ค์์
- ๋ค๋ฅธ ํฌ๋ฃจ๊ฐ RestAssured๋ก ๋ฌธ์๋ฅผ ๋ง๋ค์๋๋ฐ ๊ทธ๊ฑฐ ๋ณด๊ณ ์๋ํด๋ด์ผ์งโฆ
- ๋ ๋ฆฌ๋ทฐ์ด๊ฐ ์ ์ํ ๋ฐฉํฅ์ผ๋ก API ๋ฌธ์ ๋ง๋๋ ํ ์คํธ ์ฝ๋๋ฅผ ์กฐ๊ธ ์์ ํ๋๋ ๋ ์ข์ ๋ฌธ์๋ฅผ ๋ง๋ค ์ ์์์
ControllerTest
@ActiveProfiles("test")
@AutoConfigureRestDocs
public class ControllerTest {
@Autowired
public MockMvc mockMvc;
@Autowired
public ObjectMapper objectMapper;
protected static OperationRequestPreprocessor getDocumentRequest() {
return preprocessRequest(
modifyUris()
.scheme("https")
.host("newwisdom-subway.p-e.kr")
.removePort(),
prettyPrint());
}
protected static OperationResponsePreprocessor getDocumentResponse() {
return preprocessResponse(prettyPrint());
}
}
- API ๋ฌธ์ ๋ง๋๋๋ฐ ํ์ํ MockMvc ํ ์คํธ๋ค์ ์ ํด๋์ค๋ฅผ ์์๋ฐ๊ณ ์์
- ๋ฆฌ๋ทฐ์ด์ ์ ์์ ํตํด
getDocumentRequest()
์getDocumentResponse()
์ ์ถ๊ฐ
ํ ์คํธ ์ฝ๋์ ๊ฐ๋ ์ฑ
- ์ด๋ฒ ๋ฆฌ๋ทฐ์ด๊ฐ ํ ์คํธ ์ฝ๋์์ ๊ฐ๋ ์ฑ์ ์งํค์ง ๋ชปํ ๋ถ๋ถ๋ค์ ๋ง์ด ํผ๋๋ฐฑ ํด์ฃผ์์
- ํ ์คํธ ์ฝ๋๋ ํ๋์ ๋ฌธ์์ด๋ฉฐ ์ ์ง๋ณด์ ๋์์ด๊ธฐ ๋๋ฌธ์ ๊ฐ๋ ์ฑ์ ๊ณ ๋ คํด์ผ ํ๋ค๋ ๊ฒ์ ๋๊ผ์
- ์๋ก ๋ค๋ฅธ ํ ์คํธ์์ ๊ณตํต์ผ๋ก ์ฐ์ด๋ ๋ฉ์๋๋ค์ ์์ ํด๋์ค์ธ AcceptanceTest๋ก ๋์ด ์ฌ๋ฆผ
- ํ ์คํธ์ ์ฐ์ด๋ ๋ณ์๋ช ๋ค๋ ๋งฅ๋ฝ์ ํ์ ํ๊ธฐ ์ฝ๋๋ก ๋ณ๊ฒฝ
- ์์์ฒ๋ฆฌ๋ ์ ๊ฒฝ์
์์ธ ์ฒ๋ฆฌ
- โ์ผ๋จ ํ๋ก ํธ์ ์๊ตฌ์ฌํญ ๋ค ๋ฐ์ํ๋๋ก ๊ตฌํํด๋ณด์!โ๋ก ์ก๊ณ ํ๋๋ ๋ฌด์ํ ์ปค์คํ ์์ธ๊ฐ ๋ง๋ค์ด์ก๋คโฆ^ใ ^
- ์ด๋ฅผ ๊ฐ์ ํ ๋ฐฉ๋ฒ์ ์ฐพ๋ค๊ฐโฆ ํฌ๋ฃจ๋คํํ ๋ค์ Spring Guide - Exception ์ ๋ต ์ ์ ์ฉํด๋ณด๊ธฐ๋ก~
- RuntimeException์ ์์๋ฐ๋ BuisnessException์ ๋ง๋ค๊ณ ํ๋์ ์ํ์ฝ๋์ ErrorMessage(DTO)๋ฅผ ๊ฐ์ง๋๋ก ๊ตฌํ
- ์ด๋ฅผ ์์ํ๋ ์ํ์ฝ๋ 400์ธ BusinessException๊ณผ ์ํ์ฝ๋ 401์ธ AuthorizationException์ ๋ง๋ฆ
- ๋ ์ด๋ฅผ ์์๋ฐ๋ ๊ฐ๊ฐ์ ํด๋ผ์ด์ธํธ์ ์๊ตฌ์ฌํญ์ ๋ง๋ ์ปค์คํ ์์ธ ๋ง๋ฆ
-
ControllerAdvice์์๋ ๋ค์๊ณผ ๊ฐ์ด BuisnessException์ ์ก๊ณ ์ด ์์ธ์์ ์ํ์ฝ๋์ ์์ธ ๋ฉ์์ง๋ฅผ ๊บผ๋ด๋๋ก ๊ตฌํ
- ์ด๋ ๊ฒ ๋๋ฉด ์ด๋๋ฐ์ด์ค์์ ์๋ง์ ์ปค์คํ ์์ธ๋ค์ BuisnessException ํ๋๋ง ์ก๊ณ ์ฒ๋ฆฌํ ์ ์์
- ์ํ์ฝ๋์ ๋ฐ๋ฅธ ํด๋์ค๋ฅผ ๋์ด ์ด๊ฐ ๋ณ๊ฒฝ๋์ด๋ ์ ์ง๋ณด์๊ฐ ์ฌ์
@ExceptionHandler(BusinessException.class)
public ResponseEntity<ErrorMessage> handleRuntimeException(BusinessException e) {
return ResponseEntity.status(e.getHttpStatus()).body(e.getErrorMessage());
}
BusinessException
public class BusinessException extends RuntimeException {
private final HttpStatus httpStatus;
private final ErrorMessage errorMessage;
public BusinessException(HttpStatus httpStatus, String errorMessage) {
this(httpStatus, new ErrorMessage(errorMessage));
}
public BusinessException(HttpStatus httpStatus, ErrorMessage errorMessage) {
this.httpStatus = httpStatus;
this.errorMessage = errorMessage;
}
public HttpStatus getHttpStatus() {
return httpStatus;
}
public ErrorMessage getErrorMessage() {
return errorMessage;
}
}
AuthorizationException
public class AuthorizationException extends BusinessException {
public AuthorizationException(String message) {
super(HttpStatus.UNAUTHORIZED, message);
}
}
- BusinessException์ ์์
- 401 ์ํ์ฝ๋
BadRequestException
public class BadRequestException extends BusinessException {
public BadRequestException(String message) {
super(HttpStatus.BAD_REQUEST, message);
}
}
- BusinessException์ ์์
- 400 ์ํ์ฝ๋
๋ฐฐํฌ ์คํฌ๋ฆฝํธ
- ์ค์ API ์ฌ์ฉ์ด ๊ฐ๋ฅํ๋๋ก EC2์ ๋ฐฐํฌํ์ฌ์ผ ํ์
- ํ๋ก์ ํธ๊ฐ ์ ๋ฐ์ดํธ๋๋ฉด ํ๋ก์ธ์ค๋ฅผ ์ฌ์๋ํด์ผํ์
- ์ด๋ฌ๋ฉด ์ฌ๋ฌ๊ฐ์ง ๋ช ๋ น์ด๋ฅผ ์คํํด์ผ ํจโฆ.
- ์ด๋ฅผ ์คํฌ๋ฆฝํธ๋ก ๋ง๋ค์ด ํ๋ฒ์ ์ฒ๋ฆฌํ๋๋ก ๊ตฌํ!
deploy-prod.sh
#!/bin/bash
#!/bin/bash in the top of your scripts then you are telling your system to use bash as a default shell.
REPOSITORY=/home/ubuntu/ # ๊ฒฝ๋ก ์ค์
PROJECT_NAME=atdd-subway-fare
cd $REPOSITORY/$PROJECT_NAME/ # ๊ฒฝ๋ก๋ก ์ ๊ทผ
echo "> git reset --hard"
git reset --hard # ๊นํ๋ธ ์ด๊ธฐํ
echo "> git pull origin step1"
git pull origin step1 # pull ๋ก๊ฒจ์ค๊ธฐ
echo "> ํ๋ก์ ํธ Build ์์"
./gradlew clean build # ๋น๋
echo "> Build ํ์ผ ๊ฒฝ๋ก ๋ณต์ฌ"
JAR_LOCATION=$(find ./* -name "*jar" | grep atdd-subway-fare)
echo "> ํ์ฌ ๊ตฌ๋์ค์ธ ์ ํ๋ฆฌ์ผ์ด์
pid ํ์ธ"
CURRENT_PID=$(pgrep -f ${PROJECT_NAME}[-A-z0-9.]*.jar$) # ์คํ์์ผ์ ธ์๋ jar pid ๋ฐ๊ธฐ
if [ -z "$CURRENT_PID" ]; then # -z ํ๋๊ทธ๋ null์ธ๊ฒ์ ์ฒดํฌํจ, PID๊ฐ null์ธ ๊ฒฝ์ฐ if์ ์์ผ๋ก ๋ค์ด๊ฐ
echo "> ํ์ฌ ๊ตฌ๋ ์ค์ธ ์ ํ๋ฆฌ์ผ์ด์
์ด ์์ผ๋ฏ๋ก ์ข
๋ฃํ์ง ์์ต๋๋ค."
else
echo "> ํ์ฌ ๊ตฌ๋์ค์ธ ์ ํ๋ฆฌ์ผ์ด์
์ข
๋ฃ(pid : $CURRENT_PID)"
echo "> kill -15 $CURRENT_PID"
kill -15 $CURRENT_PID
sleep 5
fi
echo "> ์ ์ ํ๋ฆฌ์ผ์ด์
๋ฐฐํฌ"
echo "> JAR Location: $JAR_LOCATION" ํด๋น jarํ์ผ ์คํ
#nohup java -jar ์คํ
nohup java -jar -Dspring.profiles.active=prod ${JAR_LOCATION} 1> log-prod.md 2>&1 &