๐Ÿ‘จ‍๐Ÿ’ป kimtongting
article thumbnail

 

๊ฐœ์š”

API ๋ฅผ ๊ฐœ๋ฐœํ•˜๊ฑฐ๋‚˜, ํŠน์ • ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์ œ์–ดํ•˜๊ธฐ ์œ„ํ•ด ํ•„์ˆ˜ ๊ฐ’์„ ์ง€์ •ํ•ด์•ผํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ์žˆ๋‹ค. (ํŒŒ๋ผ๋ฏธํ„ฐ์— ๋Œ€ํ•œ ์œ ํšจ์„ฑ)

๋”ฐ๋กœ Rule ์ด ์—†๋‹ค๋ฉด ๋ฐฉ๋ฒ•์€ ๋ฌด๊ถ๋ฌด์ง„ํ•˜๋‹ค. ๋ชจ๋“  ์š”์ฒญ์— if๋ฅผ ๊ฑธ์–ด ๊ฒ€์‚ฌํ•˜๊ฑฐ๋‚˜.. ๊ณตํ†ต์œผ๋กœ ํ•˜๋‚˜์˜ Class ๋ฅผ ๋งŒ๋“ค์–ด์„œ ๊ฒฝ์œ ํ•˜๊ฒŒ ํ•˜๊ฑฐ๋‚˜..

 

์ด ๊ธ€์—์„œ๋Š” ๊น”๋”ํ•œ ์ฝ”๋“œ๋ฅผ ์œ„ํ•ด ํ”„๋กœ์ ํŠธ ๋‚ด์—์„œ ๊ณตํ†ต์ ์œผ๋กœ ์‚ฌ์šฉํ•  Exception ์ฒ˜๋ฆฌ๋ฅผ ํ•˜๊ณ ์ž ํ•œ๋‹ค. ๊ทธ๋ž˜์•ผ ๊น”๋”ํ•˜๋‹ค.

 

๊ธฐ์กด Spring ์ด๋‚˜ Spring Boot์—์„œ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด ์•„๋ž˜์™€ ๊ฐ™์€ ๋‚ด์šฉ์œผ๋กœ ๋ฐœ์ƒํ–ˆ๋‹ค.

 

์šฐ๋ฆฌ๋Š” Spring Boot์—์„œ ์ œ๊ณตํ•˜๋Š” ๊ธฐ๋ณธ ์—๋Ÿฌ ๋ฉ”์‹œ์ง€๋ฅผ ์šฐ๋ฆฌ๊ฐ€ ์›ํ•˜๋Š” ๋ฉ”์‹œ์ง€๋กœ ์ œ์–ดํ•  ์˜ˆ์ •์ด๋‹ค.

 

*์•„๋ž˜ ๊ธ€์—์„œ๋Š” ์ฟ ํฐ์„ ๋ฐœํ–‰ํ•˜๊ธฐ ์œ„ํ•œ ๋‚ด์šฉ์„ ์‹œ๋‚˜๋ฆฌ์˜ค๋กœ @Valid ๋ฅผ ๋„ฃ์–ด ๊ตฌํ˜„ํ•˜์˜€๋‹ค.

1. ์‚ฌ์ „์ค€๋น„

๐Ÿ“Maven ์„ ๊ธฐ์ค€์œผ๋กœ Validator ๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•œ Lib ๋ฅผ ๋ฏธ๋ฆฌ ๋ฐ›์•„๋‘๋„๋ก ํ•œ๋‹ค.

์•„๋ž˜๋Š” pom.xml ์˜ dependency ๋‚ด์šฉ์ด๋‹ค.

<!-- pom.xml -->
<dependency>
	<groupId>org.hibernate.validator</groupId>
	<artifactId>hibernate-validator</artifactId>
	<version>6.2.0.Final</version>
</dependency>

2. ๊ณตํ†ต Exception Contoller ์ƒ์„ฑ

๐Ÿ“Exception Controller

@Slf4j
@ControllerAdvice
public class ExceptionController {

    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity<ErrorModule> methodValidException(MethodArgumentNotValidException e, HttpServletRequest request){
        log.error("MethodArgumentNotValidException url:{}, trace:{}",request.getRequestURI(), e.getStackTrace());
        return new ResponseEntity<>(errorResponse(e.getBindingResult()), HttpStatus.BAD_REQUEST);
    }

    private ErrorModule errorResponse(BindingResult bindingResult){
        //bindingResult.getFieldError().getCode(); : model ์—์„œ ์„ค์ •ํ•œ annotation
        //bindingResult.getFieldError().getField()); : model ์—์„œ ๋ฐœ์ƒํ•œ Error ์œ„์น˜
        //bindingResult.getFieldError().getDefaultMessage(); : model ์—์„œ ์„ค์ •ํ•œ message
        return new ErrorModule(
                bindingResult.getFieldError().getField(),
                bindingResult.getFieldError().getDefaultMessage());
    }

}

3. ๊ณตํ†ต ErrorModule ์ƒ์„ฑ

๐Ÿ“ErrorModule

import lombok.Data;

@Data
public class ErrorModule {
    String code;		//enum ์œผ๋กœ ์ œ์–ดํ•  ๋ชฉ์ 
    String requestType; //ํ™•์žฅ์„ฑ์„ ๊ณ ๋ ค, ์š”์ฒญํ•œ ๊ธฐ๋Šฅ์ด ์–ด๋–ค ๊ฒƒ์ธ์ง€ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•จ
    String field;		//๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•œ field ํ™•์ธ
    String description;	//์„ค๋ช…
    String message;		//์ถœ๋ ฅํ•˜๋Š” ๋ฉ”์‹œ์ง€

//TODO: ์ง€๊ธˆ์€ ์ด๊ฑธ๋กœ..
    public ErrorModule(String field, String message) {
        this.field = field;
        this.message = message;
    }
    public ErrorModule(String requestType, String description, String message) {
        this.requestType = requestType;
        this.description = description;
        this.message = message;
    }

    public ErrorModule(String code, String requestType, String field, String description, String message) {
        this.code = code;
        this.requestType = requestType;
        this.field = field;
        this.description = description;
        this.message = message;
    }

 

 

 

4. @Valid ์„ ์–ธ

๐Ÿ“์ œ์–ด๋ฅผ ํ•˜๊ณ  ์‹ถ์€ Parameter์— @Valid๋ฅผ ๋ถ™์—ฌ์ค€๋‹ค.

 

Controller

๐Ÿ‘จ‍๐Ÿ’ป๐Ÿ’ปโŒจ

	@ApiOperation(value = "์ฟ ํฐ ๋ฐœํ–‰ API", notes = "์ฟ ํฐ ๋ฐœํ–‰ API ๊ธฐ๋Šฅ (๊ฑด๋ณ„)")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "token", value = "API ํ† ํฐ๊ฐ’", dataType = "string", paramType = "header", required = true),
            @ApiImplicitParam(name = "company", value = "API ์†Œ์†๊ฐ’", dataType = "string", paramType = "header", required = true),
            @ApiImplicitParam(name = "group", value = "API ๊ทธ๋ฃน๊ฐ’", dataType = "string", paramType = "header", required = true),
            @ApiImplicitParam(name = "type", value = "GIFT: 1ํšŒ๊ถŒ / RUSE: ๋‹คํšŒ๊ถŒ", dataType = "string", paramType = "query", required = true),
            @ApiImplicitParam(name = "amount", value = "type.equals('GIFT') ? ์ฟ ํฐ๊ธˆ์•ก : 0", dataType = "long", paramType = "query", required = true),
            @ApiImplicitParam(name = "phone", value = "์—ฐ๋ฝ์ฒ˜ (-) ํฌํ•จํ•˜์—ฌ ์ „์†ก", dataType = "string", paramType = "query", required = true),
    })
    @PostMapping(value = "/issuance")
    @Transactional(timeout = 5)
    public ResponseEntity<JSONObject> couponIssuance(
            @RequestHeader("token") String token,
            @RequestHeader("company") String company,
            @RequestHeader("group") String group,
            //ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ Model ๋กœ ๋ฐ›๊ณ , Model ์•ˆ์—์„œ ์ œ์–ดํ•˜๊ณ ์ž ํ•œ๋‹ค.
            @RequestBody @Valid CouponModel couponModel            
            ) {
        try {
            
        } catch (Exception e) {            
            e.printStackTrace();            
        }

        if (true) {
            return new ResponseEntity<>(new JSONObject(), HttpStatus.OK);
        } else {
            return new ResponseEntity<>(new JSONObject(), HttpStatus.NOT_FOUND);
        }
    }

5. ์‹คํ–‰๊ฒฐ๊ณผ

๐Ÿ“์ผ๋ถ€๋Ÿฌ ํŒŒ๋ผ๋ฏธํ„ฐ์ธ phone ์„ ๋น„์šฐ๊ณ  ์š”์ฒญ์„ ์ „์†กํ•œ ๊ฒฐ๊ณผ์ด๋‹ค.

์›ํ•˜๋Š” ์‘๋‹ต ๊ฐ’์œผ๋กœ ์ž˜ ๋ฟŒ๋ ค์ฃผ๊ณ  ์žˆ๋‹ค.

 

 

๋งˆ์ง€๋ง‰์— ํ™•์žฅ์„ฑ์„ ์ƒ๊ฐํ•˜์—ฌ enum ์œผ๋กœ ๊ด€๋ฆฌํ•  ์ƒ๊ฐ์œผ๋กœ ๋ณ€์ˆ˜๋ฅผ ์ถ”๊ฐ€ํ•˜์˜€๋‹ค.

'์˜ค๋ฅ˜ ์ฝ”๋“œ'์™€ '์ฝ”๋“œ์— ๋”ฐ๋ฅธ ๋ฌธ๊ตฌ' ์ถ”๊ฐ€ํ•œ๋‹ค๋ฉด ๋”์šฑ ๊น”๋”ํ•œ ๊ตฌ์กฐ๋ฅผ ํ™•๋ฆฝํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ ๊ฐ™๊ธฐ์—..

 


 

 

๋ฐ˜์‘ํ˜•
profile

๐Ÿ‘จ‍๐Ÿ’ป kimtongting

@kimtongting ์ž…๋‹ˆ๋‹ค

ํฌ์ŠคํŒ…์ด ์ข‹์•˜๋‹ค๋ฉด "์ข‹์•„์š”โค๏ธ" ๋˜๋Š” "๊ตฌ๋…๐Ÿ‘๐Ÿป" ํ•ด์ฃผ์„ธ์š”!