RestAPI(Representational State Transfer API)

JOY๐ŸŒฑยท2023๋…„ 4์›” 27์ผ
0

๐ŸŒŠ RESTful API

๋ชฉ๋ก ๋ณด๊ธฐ
1/3
post-thumbnail

๐Ÿ’โ€โ™€๏ธ RestAPI๋ž€,
ํด๋ผ์ด์–ธํŠธ์™€ ์„œ๋ฒ„ ๊ฐ„์— ๋ฐ์ดํ„ฐ๋ฅผ ์ฃผ๊ณ ๋ฐ›๊ธฐ ์œ„ํ•œ ์ธํ„ฐํŽ˜์ด์Šค๋กœ, ์›น ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ์„œ๋ฒ„ ๋ฐ์ดํ„ฐ๋ฅผ ์š”์ฒญํ•˜๊ณ  ๋ฐ›์„ ์ˆ˜ ์žˆ๋„๋ก ๋•๋Š” ๊ธฐ์ˆ 

  • REST API๋Š” ๋ฐ์ดํ„ฐ ํ˜•ํƒœ๋ฅผ ์ฃผ๋กœ JSON ํ˜น์€ XML ํ˜•์‹์œผ๋กœ ๋ฐ˜ํ™˜
  • ํด๋ผ์ด์–ธํŠธ๋Š” HTTP ์š”์ฒญ(GET, POST, PUT, DELETE ๋“ฑ)์„ ๋ณด๋‚ด๋Š” ๊ฒƒ์œผ๋กœ ์„œ๋ฒ„์—์„œ ์ œ๊ณตํ•˜๋Š” ๊ธฐ๋Šฅ ์ด์šฉ ๊ฐ€๋Šฅ

๐Ÿ‘€ ํƒ€์ž…๋ณ„ ์‘๋‹ต (Response)

๐Ÿ‘‰ Message

public class Message {

	private int httpStatusCode;
	private String message;
    
    /* ๊ธฐ๋ณธ ์…‹ํŒ… */
}

๐Ÿ‘‰ ResponseRestController

@RestController

/* @Controller + @ResponseBody์˜ ์˜๋ฏธ
 * ํด๋ž˜์Šค ๋ ˆ๋ฒจ์— ์ž‘์„ฑํ•˜๋ฉฐ ํ•ด๋‹น ํด๋ž˜์Šค ๋‚ด์˜ ๋ชจ๋“  ํ•ธ๋“ค๋Ÿฌ ๋ฉ”์†Œ๋“œ์— @ResponseBody ์–ด๋…ธํ…Œ์ด์…˜์„ ๋ฌต์‹œ์ ์œผ๋กœ ์ ์šฉํ•œ๋‹ค๋Š” ์˜๋ฏธ (๋ฆฌํ„ด๊ฐ’์ด ๊ณง ์‘๋‹ต๊ฐ’) */
@RestController
@RequestMapping("/response")
public class ResponseRestController {

[1] ๋ฌธ์ž์—ด ์‘๋‹ต

	/* 1. ๋ฌธ์ž์—ด ์‘๋‹ต */
	@GetMapping("/hello")
	public String helloworld() {
		
		return "Hello World๐Ÿฅณ";
	}

[2] ๊ธฐ๋ณธ ์ž๋ฃŒํ˜• ์‘๋‹ต

	/* 2. ๊ธฐ๋ณธ ์ž๋ฃŒํ˜• ์‘๋‹ต */
	@GetMapping("/random")
	public int getRandomNumber() {
		
		return (int) (Math.random() * 10) + 1;
	}

[3] Object ์‘๋‹ต

	/* 3. Object ์‘๋‹ต */
	@GetMapping("/message")
	public Message getMessage() {
		
		return new Message(200, "๋ฉ”์„ธ์ง€ ์‘๋‹ต ์„ฑ๊ณต!๐Ÿคฉ");
	}

[4] List ์‘๋‹ต

	/* 4. List ์‘๋‹ต */
	@GetMapping("/list")
	public List<String> getList() {
		
		return List.of(new String[] {"ํ–„์„œํ„ฐ๐Ÿน", "ํ˜ธ๋žญ์ด๐Ÿฏ", "์‚ฐ๋…๊ธฐ๐Ÿฐ"});
	}

[5] Map ์‘๋‹ต

	/* 5. Map ์‘๋‹ต */
	@GetMapping("/map")
	public Map<Integer, String> getMap() {
		
		List<Message> messageList = new ArrayList<>();
		messageList.add(new Message(200, "์‘๋‹ต ์„ฑ๊ณต!๐Ÿฅ"));
		messageList.add(new Message(404, "ํŽ˜์ด์ง€๋ฅผ ์ฐพ์ง€ ๋ชป ํ–ˆ์–ด์š”๐Ÿ’ฉ"));
		messageList.add(new Message(500, "๋‹˜์˜ ์ž˜๋ชป!๐Ÿท"));
		
		return messageList.stream().collect(Collectors.toMap(Message::getHttpStatusCode, Message::getMessage));
	}

[6] ImageFile ์‘๋‹ต

	/* 6. ImageFile ์‘๋‹ต 
	 * produces ์„ค์ •์€ response header์˜ content-type ์„ค์ •
	 * ์„ค์ •์„ ๋”ฐ๋กœ ํ•˜์ง€ ์•Š์œผ๋ฉด text/html๋กœ ์‘๋‹ตํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ด๋ฏธ์ง€๊ฐ€ ํ…์ŠคํŠธ ํ˜•ํƒœ๋กœ ์ „์†ก ๋จ*/
	@GetMapping(value="/image", produces=MediaType.IMAGE_PNG_VALUE)
	public byte[] getImage() throws IOException {
		
		return getClass().getResourceAsStream("/com/greedy/api/section01/response/sample.png").readAllBytes();
	}

[7] ResponseEntity๋ฅผ ์ด์šฉํ•œ ์‘๋‹ต

	/* 7. ResponseEntity๋ฅผ ์ด์šฉํ•œ ์‘๋‹ต (๋Œ€๋ถ€๋ถ„ ์ด ๋ฐฉ์‹์„ ์‚ฌ์šฉ) */
	@GetMapping("/entity")
	public ResponseEntity<Message> getEntity() {
		
		return ResponseEntity.ok(new Message(123, "Baby Cheese"));
	}
	
}


๐Ÿ‘€ Response Entity

ResponseEntity

๐Ÿ’โ€โ™€๏ธ Response Entity๋ž€,
๊ฒฐ๊ณผ ๋ฐ์ดํ„ฐ์™€ HTTP ์ƒํƒœ ์ฝ”๋“œ, ์‘๋‹ต ํ—ค๋”๋ฅผ ์ง์ ‘ ์ œ์–ดํ•  ์ˆ˜ ์žˆ๋Š” ํด๋ž˜์Šค

๐Ÿ‘‰ UserDTO

public class UserDTO {
	
	private int no;
	private String id;
	private String pwd;
	private String name;
	private Date enrollDate;
    
    /* ๊ธฐ๋ณธ ์…‹ํŒ… */
    
}

๐Ÿ‘‰ ResponseMessage

public class  ResponseMessage {

	private int httpStatus;
	private String message;
	private Map<String, Object> results;
    
    /* ๊ธฐ๋ณธ ์…‹ํŒ… */
    
}

๐Ÿ‘‰ ResponseEntityTestController

@RestController
@RequestMapping("/entity")
public class ResponseEntityTestController {
	
	private List<UserDTO> users;
	
	public ResponseEntityTestController() {
		users = new ArrayList<>();
		users.add(new UserDTO(1, "user01", "pass01", "ํ—ˆ์น˜์น˜", new Date()));
		users.add(new UserDTO(2, "user02", "pass02", "ํ—ˆ๊ผฌ์ˆœ", new Date()));
		users.add(new UserDTO(3, "user03", "pass03", "ํ—ˆ๋ถ€์™", new Date()));
	}

[1] ๋ชจ๋“  User ์กฐํšŒ

@GetMapping HttpHeaders setContentType() MediaType Charset.forName()

	@GetMapping("/users")
	public ResponseEntity<ResponseMessage> findAllUsers() {
		
		HttpHeaders headers = new HttpHeaders();
		headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
		
		Map<String, Object> responseMap = new HashMap<>();
		responseMap.put("users", users);
		
		ResponseMessage responseMessage = new ResponseMessage(200, "์กฐํšŒ ์„ฑ๊ณต!๐Ÿถ", responseMap);
		
		return new ResponseEntity<>(responseMessage, headers, HttpStatus.OK); // new ResponseEntity<>(๋ฉ”์„ธ์ง€, ์ปจํ…์ธ ํƒ€์ž…, ์ƒํƒœ์ฝ”๋“œ)
		
		// users๋ผ๋Š” key๊ฐ’์— addํ•œ user๋“ค์„ Map์— ๋„ฃ๊ณ , responseMessage์— ๊ทธ Map์„ ํ•จ๊ป˜ ๋‹ด์•„ ๋ณด๋ƒ„ 
		// ๊ฒฐ๊ตญ ์‘๋‹ต ๊ฐ’์€ responseMessage๊ฐ€ JSON ํ˜•ํƒœ๋กœ ์˜ด !!
	}

[2] User ์กฐํšŒ

@GetMapping stream() filter() toList() ok() headers() body()

	@GetMapping("/users/{userNo}")
	public ResponseEntity<ResponseMessage> findUserByNo(@PathVariable int userNo) {
		
		HttpHeaders headers = new HttpHeaders();
		headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
		
		UserDTO foundUser = users.stream().filter(user -> user.getNo() == userNo).toList().get(0); // no๊ฐ€ ์ผ์น˜ํ•˜๋Š” user๋ฅผ ์ฐพ๊ณ  List๋กœ ๋ฐ˜ํ™˜
	
		Map<String, Object> responseMap = new HashMap<>();
		responseMap.put("user", foundUser);
		
		/* ๋นŒ๋” ํŒจํ„ด์œผ๋กœ๋„ ์ž‘์„ฑ ๊ฐ€๋Šฅ (๋ฐฉ์‹์˜ ์ฐจ์ด์ผ๋ฟ, ๊ฒฐ๊ณผ๋Š” ์œ„์™€ ๊ฐ™์Œ) */
		return ResponseEntity
				.ok()
				.headers(headers)
				.body(new ResponseMessage(200, "์กฐํšŒ ์„ฑ๊ณต!๐Ÿถ", responseMap));
	}

[3] User ๋“ฑ๋ก

@PostMapping @RequestBody created(URI.create()) build()

	// body ์ชฝ์— ์‘๋‹ตํ•  ๊ฒƒ์ด ๋”ฐ๋กœ ์—†์„ ๋–„ ResponseEntity<?>
	@PostMapping("/users")
	public ResponseEntity<?> registUser(@RequestBody UserDTO newUser) { 
		// @ModelAttribute : url encoded ๋ฐฉ์‹์œผ๋กœ ๋ฐ์ดํ„ฐ๊ฐ€ ๋„˜์–ด์˜ด์„ ์˜๋ฏธ(๊ธฐ๋ณธ๊ฐ’, ์ƒ๋žต๊ฐ€๋Šฅ) => key=value&key=value
		// @RequestBody : JSON ๋ฐฉ์‹์˜ ๋ฌธ์ž์—ด๋กœ ๋„˜์–ด์˜ด์„ ์˜๋ฏธ(JSON ๋ฐฉ์‹์œผ๋กœ ๋ฐ›๊ธฐ ์œ„ํ•ด ๋ช…์‹œ ํ•„์š”) => "key" : value, "key" : value
		
		int lastUserNo = users.get(users.size()- 1).getNo();
		newUser.setNo(lastUserNo + 1);
		newUser.setEnrollDate(new Date());
		
		users.add(newUser);
		
		/* ์กฐํšŒ ์‹œ์—๋Š” 200๋ฒˆ ์ฝ”๋“œ๋ฅผ ์‘๋‹ตํ•˜์ง€๋งŒ ์‚ฝ์ž… ์‹œ์—๋Š” 201๋ฒˆ ์ฝ”๋“œ๋ฅผ ์‘๋‹ต
		 * 201 : ์š”์ฒญ์ด ์„ฑ๊ณต์ ์œผ๋กœ ์ฒ˜๋ฆฌ ๋˜์—ˆ์œผ๋ฉฐ, ์ž์›์ด ์ƒ์„ฑ๋˜์—ˆ์Œ์„ ๋‚˜ํƒ€๋‚ด๋Š” ์„ฑ๊ณต ์ƒํƒœ ์‘๋‹ต ์ฝ”๋“œ
		 * ํ•ด๋‹น ์ž์›์— ๋Œ€ํ•œ ์š”์ฒญ url์„ location์œผ๋กœ ์„ค์ •ํ•˜์—ฌ ์‘๋‹ต */
		return ResponseEntity
				.created(URI.create("/entity/users/" + users.get(users.size() - 1).getNo())) 
				.build();
		// ์œ„์—์„œ newUser๊ฐ€ ์ถ”๊ฐ€ ๋˜์—ˆ์œผ๋ฏ€๋กœ ์ด users์˜ ์‚ฌ์ด์ฆˆ์—์„œ -1์„ ํ•œ ๊ฒƒ์˜ no๊ฐ€ ์ถ”๊ฐ€ํ•ด์•ผํ•  user
	}

[4] User ์ˆ˜์ •

@PutMapping

	@PutMapping("/users/{userNo}")
	public ResponseEntity<?> modifyUser(@PathVariable int userNo, @RequestBody UserDTO modifyInfo) {
		
		UserDTO foundUser = users.stream().filter(user -> user.getNo() == userNo).toList().get(0);
		foundUser.setId(modifyInfo.getId());
		foundUser.setPwd(modifyInfo.getPwd());
		foundUser.setName(modifyInfo.getName());
		
		/* ์ˆ˜์ • ์š”์ฒญ์œผ๋กœ ์ž์›์ด ๋ณ€๊ฒฝ ๋œ๋‹ค๋ฉด 201๋ฒˆ ์ฝ”๋“œ๋กœ ์‘๋‹ต
		 * ๋งŒ์•ฝ ์ž์› ์ˆ˜์ • ์š”์ฒญ์˜ ๊ฒฐ๊ณผ๊ฐ€ ๊ธฐ์กด์˜ ์ž์› ๋‚ด์šฉ๊ณผ ๋™์ผํ•˜์—ฌ ๋ณ€๊ฒฝ๋œ ๋‚ด์šฉ์ด ์—†์„ ๋•Œ๋Š” 204๋กœ ์‘๋‹ตํ•  ์ˆ˜๋„ ์žˆ์Œ
		 * 204 : ์š”์ฒญ์ด ์„ฑ๊ณตํ–ˆ์œผ๋‚˜ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ํ˜„์žฌ ํŽ˜์ด์ง€์—์„œ ๋ฒ—์–ด๋‚˜์ง€ ์•Š์•„๋„ ๋œ๋‹ค๋Š” ๊ฒƒ์„ ๋‚˜ํƒ€๋‚ด๋Š” ์ƒํƒœ ์ฝ”๋“œ */
		return ResponseEntity
				.created(URI.create("/entity/users/" + userNo))
				.build();
		
	}

[5] User ์‚ญ์ œ

@DeleteMapping noContent()

	@DeleteMapping("/users/{userNo}")
	public ResponseEntity<?> removeUser(@PathVariable int userNo) {
		
		UserDTO foundUser = users.stream().filter(user -> user.getNo() == userNo).toList().get(0);
		users.remove(foundUser);
		
		/* ์‚ญ์ œ ์š”์ฒญ์„ ํ•˜์—ฌ ๋”์ด์ƒ ์ฐธ์กฐํ•  ์ˆ˜ ์—†์„ ๊ฒฝ์šฐ 204๋ฒˆ์œผ๋กœ ์‘๋‹ตํ•˜๋Š” ๊ฒƒ์ด ๊ทœ์น™ */
		return ResponseEntity
				.noContent()
				.build();
		
	}

}


๐Ÿ‘€ Valid

๐Ÿ’โ€โ™€๏ธ ๋ฐ์ดํ„ฐ ๊ฒ€์ฆ(validation)์ด๋ž€,
ํด๋ผ์ด์–ธํŠธ์˜ ๋ฐ์ดํ„ฐ๋Š” ์กฐ์ž‘์ด ์‰ฝ๊ณ , ๋ชจ๋“  ๋ฐ์ดํ„ฐ๊ฐ€ ์ •์ƒ์ ์ธ ๋ฐฉ์‹์œผ๋กœ ๋“ค์–ด์˜ค์ง€ ์•Š์„ ๊ฐ€๋Šฅ์„ฑ๋„ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— Client side ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ Server side์—์„œ๋„ ๋ฐ์ดํ„ฐ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ ํ•  ํ•„์š”์„ฑ ์กด์žฌ !
๐Ÿ‘‰ Spring boot starter validation ํ™œ์šฉ


๐Ÿค”โ“ ์‚ฌ์šฉ ๋ฐฉ๋ฒ•
[1] ์˜์กด์„ฑ ์ถ”๊ฐ€
[2] controller์˜ ํ•ธ๋“ค๋Ÿฌ ๋ฉ”์†Œ๋“œ์˜ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ๋ฅผ ์ ์šฉํ•  request ๊ฐ์ฒด ์•ž์— @Validated ์–ด๋…ธํ…Œ์ด์…˜ ์ž‘์„ฑ
[3] request๋ฅผ ํ•ธ๋“ค๋งํ•  ๊ฐ์ฒด ์ •์˜ ์‹œ @Validation ์–ด๋…ธํ…Œ์ด์…˜์„ ํ†ตํ•ด ํ•„์š”ํ•œ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ ์ ์šฉ

๐Ÿ‘‰ pom.xml

์˜์กด์„ฑ ์ถ”๊ฐ€

<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-validation -->
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-validation</artifactId>
</dependency>

๐Ÿ‘‰ UserDTO

@NotNull @NotBlank @Size @DateTimeFormat @Past

public class UserDTO {
	
	private int no;
	
//	@NotNull(message = "์•„์ด๋””๋Š” ํ•„์ˆ˜ ์ž…๋ ฅ ์‚ฌํ•ญ์ž„๋‹ค๐Ÿ˜ฌ") // null์€ ํ—ˆ์šฉํ•˜์ง€ ์•Š์œผ๋‚˜ "", " "๋“ฑ์€ ํ—ˆ์šฉ
	@NotBlank(message = "์•„์ด๋””๋Š” ๊ณต๋ฐฑ์ผ ์ˆ˜ ์—†์Šด๋‹ค๐Ÿ˜ฌ")	 // null, "", " " ๋ชจ๋‘ ํ—ˆ์šฉ X
	private String id;
	private String pwd;
	
	@Size(min=2, message="์ด๋ฆ„์€ ๋‘ ๊ธ€์ž ์ด์ƒ ์ž…๋ ฅํ•ด์•ผํ•จ๋‹ค๐Ÿ˜ฌ")
	private String name;
	
	@DateTimeFormat(pattern="yyyy-MM-dd")
	@Past						// @Past : ํ˜„์žฌ๋ณด๋‹ค ๊ณผ๊ฑฐ, @Future : ํ˜„์žฌ๋ณด๋‹ค ๋ฏธ๋ž˜
	private Date enrollDate;
    
    /* ๊ธฐ๋ณธ ์…‹ํŒ… */
    
}

๐Ÿ‘‰ UserNotFoundException

public class UserNotFoundException extends Exception {

	public UserNotFoundException(String msg) {
		super(msg);
	}
	
}

๐Ÿ‘‰ ValidTestController

@Validated

@RestController
@RequestMapping("/valid")
public class ValidTestController {

	@GetMapping("/users/{userNo}")
	public ResponseEntity<?> findUserByNo() throws UserNotFoundException {
		
		boolean check = true;
		
		if(check) {
			throw new UserNotFoundException("ํšŒ์› ์ •๋ณด๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์–ด์šฉ๐Ÿฅบ");
			
		}
		
		return ResponseEntity.ok().build();
	}
	@PostMapping("/users")
	public ResponseEntity<?> registUser(@Validated @RequestBody UserDTO user) {
		
		/* null์„ ๋ฐ˜ํ™˜ํ•ด๋„ ์ƒ๊ด€์—†์œผ๋‚˜, ๋ฏธ์™„์„ฑ ๊ฐ™์œผ๋ฏ€๋กœ ์ฝ”๋“œ ์ถ”๊ฐ€ */
		return ResponseEntity
				.created(URI.create("/valid/users/4"))
				.build();
	}
}

๐Ÿ‘‰ ErrorResponse

public class ErrorResponse {
	
	private String code;
	private String description;
	private String detail;
    
    /* ๊ธฐ๋ณธ ์…‹ํŒ… */
    
}

๐Ÿ‘‰ ExceptionController

@ControllerAdvice : ์ปจํŠธ๋กค๋Ÿฌ๋ฅผ ๋ณด์กฐํ•ด์ฃผ๋Š” ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•œ๋‹ค๋Š” ๊ฒƒ์„ ๋ช…์‹œํ•˜๋Š” ์–ด๋…ธํ…Œ์ด์…˜์œผ๋กœ ํ•ด๋‹น ํด๋ž˜์Šค ๋‚ด์— ์ „์—ญ ์˜ˆ์™ธ์ฒ˜๋ฆฌ ๋“ฑ๋ก ๊ฐ€๋Šฅ
@ExceptionHandler MethodArgumentNotValidException
getBindingResult() hasErrors() getFieldError() getDefaultMessage() getCode()

@ControllerAdvice
public class ExceptionController {

	@ExceptionHandler(UserNotFoundException.class)
	public ResponseEntity<ErrorResponse> handleUserException(UserNotFoundException e) {
		
		String code = "ERROR_CODE_00000";
		String description = "ํšŒ์› ์ •๋ณด ์กฐํšŒ ์‹คํŒจ!";
		String detail = e.getMessage();
		
		return new ResponseEntity<>(new ErrorResponse(code, description, detail), HttpStatus.NOT_FOUND);
	}
	
	@ExceptionHandler(MethodArgumentNotValidException.class)
	public ResponseEntity<ErrorResponse> mothodVaildException(MethodArgumentNotValidException e) {
		
		String code = "";
		String description = "";
		String detail = "";
		
		/* ๊ธฑ๊ธฐ ๋‹ค๋ฅธ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ–ˆ์„ ๊ฒฝ์šฐ, ๊ฐ ๋ฉ”์„ธ์ง€๋“ค์ด ์ถœ๋ ฅ๋˜๋„๋ก ํ•จ */
		if(e.getBindingResult().hasErrors()) {
			detail = e.getBindingResult().getFieldError().getDefaultMessage(); /* UesrDTO์—์„œ ์–ด๋…ธํ…Œ์ด์…˜์˜ message์— ์ž…๋ ฅํ•œ ๋ฉ”์„ธ์ง€ ๊ฐ€์ ธ์˜ค๊ธฐ */
			
			String bindResultCode = e.getBindingResult().getFieldError().getCode();
			System.out.println("bindResultCode : " + bindResultCode);
			
			switch(bindResultCode) {
			case "NotNull" :
				code = "ERROR_CODE_00001";
				description = "ํ•„์ˆ˜ ๊ฐ’์ด ๋ˆ„๋ฝ๋˜์—ˆ์–ด์š”!";
				break;
			case "NotBlank" :
				code = "ERROR_CODE_00002";
				description = "ํ•„์ˆ˜ ๊ฐ’์ด ๊ณต๋ฐฑ์œผ๋กœ ์ฒ˜๋ฆฌ๋˜์—ˆ์–ด์š”!";
				break;
			case "Size" :
				code = "ERROR_CODE_00003";
				description = "์•Œ๋งž์€ ํฌ๊ธฐ์˜ ๊ฐ’์ด ์ž…๋ ฅ๋˜์ง€ ์•Š์•˜์–ด์š”!";
				break;
			case "Past" :
				code = "ERROR_CODE_00004";
				description = "์•Œ๋งž์€ ๊ธฐ๊ฐ„์˜ ๊ฐ’์ด ์ž…๋ ฅ๋˜์ง€ ์•Š์•˜์–ด์š”!";
				break;
			}
		}
		/* ์œ ํšจ์„ฑ ์กฐ๊ฑด์— ๋ถˆ์ผ์น˜ํ•˜๋ฉด code, description, detail๊ฐ€ ์ถœ๋ ฅ๋จ */
		return new ResponseEntity<>(new ErrorResponse(code, description, detail), HttpStatus.BAD_REQUEST);
	}
		
}


๐Ÿ‘€ Hateoas

๐Ÿ‘‰ pom.xml

์˜์กด์„ฑ ์ถ”๊ฐ€

<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-hateoas -->
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-hateoas</artifactId>
</dependency>

๐Ÿ‘‰


๐Ÿ‘€ ??

๐Ÿ‘‰

profile
Tiny little habits make me

0๊ฐœ์˜ ๋Œ“๊ธ€