Response
: μλ²μμ ν΄λΌμ΄μΈνΈλ‘ 보λ΄λ μλ΅ λ©μμ§λ‘, ν΄λΌμ΄μΈνΈμ μμ²μ λν μν λ° ν΄λΉ μμ²κ³Ό ν¨κ» μ λ¬λλ λ°μ΄ν°λ₯Ό μ μν©λλ€.
Overview
β’
μ€νλ§ λΆνΈλ‘ μλ²μμ μλ΅νκΈ°
β’
@RestController
β¦
μλ΅ νμ
βͺ
void
βͺ
String
βͺ
κ°μ²΄
βͺ
컬λ μ
βͺ
ResponseEntity<>
β’
@Controller
β¦
μλ΅ νμ
βͺ
void
βͺ
String
βͺ
@ResponseBody
β’
μλ΅ μν μ½λ
β’
리λ€μ΄λ νΈ
β’
μ΄λ―Έμ§ μλ΅ (μΈλ€μΌ)
β’
νμΌ μλ΅ (λ€μ΄λ‘λ)
β’
API κ°λ° λ¬Έμν λꡬ
β¦
Swagger
μ€νλ§ λΆνΈλ‘ μλ²μμ μλ΅νκΈ°
@RestController
: JSON λλ XMLκ³Ό κ°μ λ°μ΄ν°λ₯Ό λ°ννλ 컨νΈλ‘€λ¬λ₯Ό μ§μ νλ μ΄λ
Έν
μ΄μ
@RestController = @Controller + @ResponseBody
/**
* π’π‘π΄ @RestController
* : JSON λλ XMLκ³Ό κ°μ λ°μ΄ν°λ₯Ό λ°ννλ 컨νΈλ‘€λ¬λ₯Ό μ§μ νλ μ΄λ
Έν
μ΄μ
* π΅ RESTful μΉ μλΉμ€λ₯Ό μμ±νλ λ° μ¬μ©
* π΅ @Controller μ @ResponseBodyλ₯Ό ν©ν μν μ νλ μ΄λ
Έν
μ΄μ
* β @Controller β‘ Viewλ₯Ό λ°ν
* β @RestController β‘ μλ΅ λ°μ΄ν°(λ©μμ§[μνμ½λ,μλ΅ν€λ,μλ΅λ³Έλ¬Έ(body)])λ₯Ό λ°ν
*/
@Slf4j
@RestController
public class ResponseController {
}
Java
볡μ¬
μλ΅ νμ
void
voidλ₯Ό λ°ννλ κ²½μ°, μ€νλ§λΆνΈλ ν΄λΉ μλν¬μΈνΈμ λν΄ μ무κ²λ λ°ννμ§ μμ΅λλ€. μΌλ°μ μΌλ‘ μ΄λ 리λ€μ΄λ μ
, νμ΄μ§ μ΄λ λ±μ κΈ°λ₯μ μ¬μ©λ©λλ€.
/**
* π void
* - μ΄λ€ μμ
μ μννκ³ μλ΅μ΄ νμ μλ κ²½μ°
* β
μνμ½λ : 200 OK
* β
body : β
*/
@GetMapping("/void")
public void voidResponse() {
log.info("[GET] - /void");
}
Java
볡μ¬
String
Stringμ λ°ννλ κ²½μ°, ν΄λΉ String κ°μ HTTP μλ΅ λ³Έλ¬ΈμΌλ‘ λ°νλ©λλ€. μ€νΈλ§μ μΌλ°μ μΌλ‘ HTML, JSON, XML λ±κ³Ό κ°μ ν
μ€νΈ κΈ°λ°μ λ°μ΄ν°λ₯Ό μλ΅νλ λ° μ¬μ©λ©λλ€.
/**
* π String
* - λ°ννλ λ¬Έμμ΄λ‘, HTTP μλ΅μ λ³Έλ¬Έ(body)μ μ§μ νλ€.
* β
μνμ½λ : 200 OK
* β
body : "λ¬Έμμ΄ λ°μ΄ν°λ₯Ό μλ΅ν©λλ€."
*/
@GetMapping("/string")
public String stringResponse() {
log.info("[GET] - /string");
return "λ¬Έμμ΄ λ°μ΄ν°λ₯Ό μλ΅ν©λλ€.";
}
Java
볡μ¬
κ°μ²΄
κ°μ²΄λ₯Ό λ°ννλ κ²½μ°, μ€νλ§λΆνΈλ ν΄λΉ κ°μ²΄λ₯Ό JSON λλ XMLκ³Ό κ°μ νμμΌλ‘ μ§λ ¬ννμ¬ HTTP μλ΅ λ³Έλ¬ΈμΌλ‘ λ°νν©λλ€. μ£Όλ‘ JSON νμμΌλ‘ λ°νλλ©°, κ°μ²΄μ νλμ κ°μ΄ HTTP μλ΅μΌλ‘ μ μ‘λ©λλ€.
/**
* π κ°μ²΄
* - κ°μ²΄λ₯Ό JSON νμμΌλ‘ λ³ννκ³ , μ΄λ₯Ό HTTP μλ΅ λ³Έλ¬Έμ μ§μ νλ€.
* β
μνμ½λ : 200 OK
* β
body : {"boardNo":0,"title":"μ λͺ©1","writer":"μμ±μ1","content":"λ΄μ©1","regDate":null,"updDate":null,"views":0}
* @return
*/
@GetMapping("/object")
public Board objectResponse() {
log.info("[GET] - /object");
Board board = new Board("μ λͺ©1", "μμ±μ1", "λ΄μ©1");
return board;
}
Java
볡μ¬
컬λ μ
컬λ μ
μ λ°ννλ κ²½μ°, μ€νλ§λΆνΈλ ν΄λΉ 컬λ μ
μ JSON λλ XMLκ³Ό κ°μ νμμΌλ‘ μ§λ ¬ννμ¬ HTTP μλ΅ λ³Έλ¬ΈμΌλ‘ λ°νν©λλ€. κ° νλͺ©μ κ°μ²΄μ λ§μ°¬κ°μ§λ‘ μ§λ ¬νλμ΄ μ μ‘λ©λλ€.
List<>
/**
* π 컬λ μ
* - 컬λ μ
μ JSON λ°°μ΄ νμμΌλ‘ λ³ννκ³ , μ΄λ₯Ό HTTP μλ΅ λ³Έλ¬Έμ μ§μ νλ€.
* β
μνμ½λ : 200 OK
* β
body : [{"boardNo":0,"title":"μ λͺ©1","writer":"μμ±μ1","content":"λ΄μ©1","regDate":null,"updDate":null,"views":0},{"boardNo":0,"title":"μ λͺ©2","writer":"μμ±μ2","content":"λ΄μ©2","regDate":null,"updDate":null,"views":0},{"boardNo":0,"title":"μ λͺ©3","writer":"μμ±μ3","content":"λ΄μ©3","regDate":null,"updDate":null,"views":0}]
* @return
*/
@GetMapping("/collection")
public List<Board> collectionResponse() {
log.info("[GET] - /collection");
List<Board> boardList = new ArrayList<>();
boardList.add(new Board("μ λͺ©1", "μμ±μ1", "λ΄μ©1"));
boardList.add(new Board("μ λͺ©2", "μμ±μ2", "λ΄μ©2"));
boardList.add(new Board("μ λͺ©3", "μμ±μ3", "λ΄μ©3"));
return boardList;
}
Java
볡μ¬
Map<>
/**
* π Map<String, ?>
* - Map 컬λ μ
μ JSON νμμΌλ‘ λ³ννμ¬,
* key μ λν value λ‘ λ€μν κ°μ²΄λ€μ κ³μΈ΅μ μΈ κ΅¬μ‘°λ‘ HTTP μλ΅ λ³Έλ¬Έμ μ§μ νλ€.
* β
μνμ½λ : 200 OK
* β
body : {"student":{"name":"κΉμ‘°μ","age":20,"studentId":1001,"grade":"1"},"person":{"name":"κΉμ‘°μ","age":20},"board":{"boardNo":0,"title":"μ λͺ©","writer":"μμ±μ","content":"λ΄μ©","regDate":null,"updDate":null,"views":0}}
* @return
*/
@GetMapping("/map")
public Map<String, ?> mapResponse() {
log.info("[GET] - /map");
Map<String, Object> map = new HashMap<>();
map.put("board", new Board("μ λͺ©", "μμ±μ", "λ΄μ©"));
map.put("person", new Person());
map.put("student", new Student());
return map;
}
Java
볡μ¬
ResponseEntity<>
ResponseEntityλ HTTP μλ΅μ λ€μνκ² μ μ΄ν μ μλ ν΄λμ€μ
λλ€. κ°λ°μλ μν μ½λ, ν€λ, λ³Έλ¬Έμ μ§μ μ μνμ¬ ResponseEntity κ°μ²΄λ₯Ό λ°νν μ μμ΅λλ€.
ResponseEntity<>
/**
* π ResponseEntity<β‘>
* : ResponseEntity κ°μ²΄λ₯Ό μ¬μ©νλ©΄, "μνμ½λ/ν€λ/λ³Έλ¬Έ"μ μ§μ νμ¬ μλ΅ν μ μλ€.
* β
<β‘> νμ
맀κ°λ³μμ μλ΅ν λ°μ΄ν°μ νμ
μ μ§μ ν μ μλ€.
* - String, Object, Collection λ± μ§μ κ°λ₯
* - ? μμΌλ μΉ΄λλ‘ μ§μ νλ©΄, νΉμ νμ§ μκ³ μν©μ λ°λΌ λμ μΌλ‘ μ²λ¦¬ κ°λ₯
*
* 1οΈβ£ μνμ½λ : ok(), badRequest(), created(URI), status()
* β HttpStatus μλ΅ μν μ½λλ₯Ό κ°μ§κ³ μλ enum (μ΄κ±°νμ
)
*
* 2οΈβ£ ν€λ : ResponseEntity.1οΈβ£.header("ν€λ λͺ
", "ν€λ κ°")
*
* 3οΈβ£ λ³Έλ¬Έβ : ResponseEntity.1οΈβ£.body( data )
* ResponseEntity.1οΈβ£.2οΈβ£.body( data )
*
* 4οΈβ£ λ³Έλ¬Έβ : ResponseEntity.1οΈβ£.build( data )
* ResponseEntity.1οΈβ£.2οΈβ£.build( data )
* @return
*/
@GetMapping("/responseString")
public ResponseEntity<String> responseEntityResponse() {
log.info("[GET] - /responseString");
// π’ μμ² μ±κ³΅
// - μνμ½λ: 200
// - body :"200 OK - μμ² μ±κ³΅"
// return ResponseEntity.ok("200 OK - μμ² μ±κ³΅");
// π μλͺ»λ μμ² - μνμ½λ
// - μνμ½λ: 400
// - body :"400 Bad Request - μλͺ»λ μμ²"
// return ResponseEntity.badRequest().body("400 Bad Request - μλͺ»λ μμ²");
// π΄ μλ² μλ¬
// - μνμ½λ: 500
// - body :"500 Internal Server Error - μλ² λ΄λΆ μλ¬"
// return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("500 Internal Server Error - μλ² λ΄λΆ μλ¬");
return ResponseEntity.ok("200 OK - μμ² μ±κ³΅");
}
Java
볡μ¬
ResponseEntity<byte[]>
β’
Content-Type : image/* (μ΄λ―Έμ§)
/**
* π ResponseEntity<byte[]>
* @return
* @throws IOException
*/
@GetMapping("/img")
public ResponseEntity<byte[]> thumbnailImg() throws IOException {
log.info("[GET] - /img");
// μ΄λ―Έμ§ νμΌμ μ½μ΄μ΄
ClassPathResource imgFile = new ClassPathResource("sample.png");
byte[] bytes = Files.readAllBytes(imgFile.getFile().toPath());
// μ΄λ―Έμ§ νμΌμ μ½μ΄μ μλ΅
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.IMAGE_PNG);
return new ResponseEntity<>(bytes, headers, HttpStatus.OK);
}
Java
볡μ¬
ClassPathResource κ°μ²΄λ resources ν΄λμ νμΌλ₯Ό μ§μ νμ¬ κ°μ Έμ΅λλ€.
ResponseEntity<byte[]>
β’
Content-Type : application/octet-stream
β’
Content-Disposition : form-data; name="attachment"; filename="sample.pngβ
/**
* π ResponseEntity<byte[]>
* @return
* @throws IOException
*/
@GetMapping("/download")
public ResponseEntity<byte[]> download() throws IOException {
log.info("[GET] - /download");
// μ΄λ―Έμ§ νμΌμ μ½μ΄μ΄
ClassPathResource imgFile = new ClassPathResource("sample.png");
byte[] bytes = Files.readAllBytes(imgFile.getFile().toPath());
// νμΌμ λ€μ΄λ‘λ λ°λλ‘ μλ΅
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
headers.setContentDispositionFormData("attachment", "sample.png");
return new ResponseEntity<>(bytes, headers, HttpStatus.OK);
}
Java
볡μ¬
@Controller
: Spring MVC μ HTTP μμ²μ μλ΅νλ 컨νΈλ‘€λ¬ ν΄λμ€λ‘ μ§μ νλ μ΄λ
Έν
μ΄μ
Thymeleaf μμ‘΄μ±μ μΆκ°νλ©΄, μ€νλ§ λΆνΈλ νμ리νλ₯Ό λ·° ν
νλ¦ΏμΌλ‘ μλ μ€μ ν©λλ€.
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
SQL
볡μ¬
μλ΅ νμ
void
: URL κ³Ό λμΌν κ²½λ‘μ λ·°λ₯Ό μλ΅νλ€.
String
: λ¬Έμμ΄λ‘ μλ΅ν λ·°μ κ²½λ‘λ₯Ό μ§μ νλ€.
@ResponseBody
: 컨νΈλ‘€λ¬ λ©μλ μμ λΆμ¬, λ©μλκ° λ°ννλ κ°μ²΄λ₯Ό μλ΅ λ©μμ§ λ³Έλ¬Έμ ν¬ν¨μν€λ μ΄λ
Έν
μ΄μ
( λ·°λ₯Ό μλ΅νμ§ μλλ€. )
μλ΅ μν μ½λ
μλ΅ μν μ½λ
HTTP μλ΅ μν μ½λλ ν΄λΌμ΄μΈνΈμκ² μμ²μ΄ μ±κ³΅μ μΌλ‘ μ²λ¦¬λμλμ§λ₯Ό μλ €μ£Όλ μν μ ν©λλ€. λͺ κ°μ§ μΌλ°μ μΈ μν μ½λλ λ€μκ³Ό κ°μ΅λλ€:
β’
200 OK: μμ²μ΄ μ±κ³΅μ μΌλ‘ μ²λ¦¬λμμμ λνλ
λλ€.
β’
201 Created: μμ²μ΄ μ±κ³΅μ μΌλ‘ μ²λ¦¬λμκ³ , μλ‘μ΄ λ¦¬μμ€κ° μμ±λμμμ λνλ
λλ€.
β’
400 Bad Request: μλͺ»λ μμ²μΌλ‘ μΈν΄ μλ²κ° μμ²μ μ΄ν΄ν μ μμμ λνλ
λλ€.
β’
403 Forbidden : ν΄λΌμ΄μΈνΈκ° μμ²ν 리μμ€μ μ κ·Όν κΆνμ΄ μμμ λνλ
λλ€. μλ²λ μμ²μ μ΄ν΄νκ³ μμ§λ§, ν΄λΌμ΄μΈνΈμκ² ν΄λΉ 리μμ€μ μ κ·Όν κΆνμ΄ μλ€λ κ²μ μλ €μ€λλ€.
β’
404 Not Found: μμ²ν 리μμ€κ° μλ²μμ μ°Ύμ μ μμμ λνλ
λλ€. ν΄λΌμ΄μΈνΈκ° μλͺ»λ URLμ μμ²ν κ²½μ°λ μμ²ν 리μμ€κ° μμ λμκ±°λ μ΄λλμμ λ λ°μν©λλ€.
β’
500 Internal Server Error: μλ² λ΄λΆμμ μ€λ₯κ° λ°μνμ¬ μμ²μ μ²λ¦¬ν μ μμμ λνλ
λλ€.
κ° μν μ½λλ λ€λ₯Έ μλ―Έλ₯Ό κ°μ§κ³ μμΌλ©°, ν΄λΌμ΄μΈνΈλ μ΄λ¬ν μ½λλ₯Ό ν΅ν΄ μμ²μ λν μ μ ν μ‘°μΉλ₯Ό μ·¨ν μ μμ΅λλ€.
200 OK
: μμ²μ΄ μ±κ³΅μ μΌλ‘ μ²λ¦¬λμμμ λνλ
λλ€.
@GetMapping("/200")
public ResponseEntity<String> ok() {
log.info("[GET] - /200 - μλ²κ° ν΄λΌμ΄μΈνΈμ μμ²μ μ±κ³΅μ μΌλ‘ μ²λ¦¬νμ λ μλ΅νλ μνμ½λ μ
λλ€.");
return ResponseEntity.ok("μλ²κ° ν΄λΌμ΄μΈνΈμ μμ²μ μ±κ³΅μ μΌλ‘ μ²λ¦¬νμ λ μλ΅νλ μνμ½λ μ
λλ€.");
}
Java
볡μ¬
201 Created
: μμ²μ΄ μ±κ³΅μ μΌλ‘ μ²λ¦¬λμκ³ , μλ‘μ΄ λ¦¬μμ€κ° μμ±λμμμ λνλ
λλ€.
@GetMapping("/201")
public ResponseEntity<String> created() {
log.info("[GET] - /200 - μλ²κ° μλ‘μ΄ λ¦¬μμ€λ₯Ό μ±κ³΅μ μΌλ‘ μμ± νμ λ μλ΅νλ μνμ½λμ
λλ€.");
return ResponseEntity.status(HttpStatus.CREATED).body("μλ²κ° μλ‘μ΄ λ¦¬μμ€λ₯Ό μ±κ³΅μ μΌλ‘ μμ± νμ λ μλ΅νλ μνμ½λμ
λλ€.");
}
Java
볡μ¬
400 Bad Request
: μλͺ»λ μμ²μΌλ‘ μΈν΄ μλ²κ° μμ²μ μ΄ν΄ν μ μμμ λνλ
λλ€.
@GetMapping("/400")
public ResponseEntity<String> badRequest() {
log.info("[GET] - /400 - ν΄λΌμ΄μΈνΈ μμ²μ΄ μλͺ»λ¨μ μλ €μ£Όλ μνμ½λμ
λλ€.");
return ResponseEntity.badRequest().body("ν΄λΌμ΄μΈνΈ μμ²μ΄ μλͺ»λ¨μ μλ €μ£Όλ μνμ½λμ
λλ€.");
}
Java
볡μ¬
403 Forbidden
: ν΄λΌμ΄μΈνΈκ° μμ²ν 리μμ€μ μ κ·Όν κΆνμ΄ μμμ λνλ
λλ€. μλ²λ μμ²μ μ΄ν΄νκ³ μμ§λ§, ν΄λΌμ΄μΈνΈμκ² ν΄λΉ 리μμ€μ μ κ·Όν κΆνμ΄ μλ€λ κ²μ μλ €μ€λλ€.
@GetMapping("/403")
public ResponseEntity<String> forbidden() {
log.info("[GET] - /403 - ν΄λΌμ΄μΈνΈκ° μμ μ κ·Όμ κ±°λΆλμμμ μλ €μ£Όλ μνμ½λμ
λλ€. (μ£Όλ‘ κΆνμ΄ μμ λ, μλ΅νλ μνμ½λμ
λλ€.)");
return ResponseEntity.status(HttpStatus.FORBIDDEN).body("ν΄λΌμ΄μΈνΈκ° μμ μ κ·Όμ κ±°λΆλμμμ μλ €μ£Όλ μνμ½λμ
λλ€. (μ£Όλ‘ κΆνμ΄ μμ λ, μλ΅νλ μνμ½λμ
λλ€.)");
}
Java
볡μ¬
404 Not Found
: μμ²ν 리μμ€κ° μλ²μμ μ°Ύμ μ μμμ λνλ
λλ€. ν΄λΌμ΄μΈνΈκ° μλͺ»λ URLμ μμ²ν κ²½μ°λ μμ²ν 리μμ€κ° μμ λμκ±°λ μ΄λλμμ λ λ°μν©λλ€.
@GetMapping("/404")
public ResponseEntity<String> notFound() {
log.info("[GET] - /404 - ν΄λΌμ΄μΈνΈκ° μμ²ν 리μμ€κ° μλ²μ μκ±°λ, μμ²ν κ²½λ‘κ° μ‘΄μ¬νμ§ μμ λ μλ΅νλ μνμ½λ μ
λλ€.");
return ResponseEntity.status(HttpStatus.NOT_FOUND).body("ν΄λΌμ΄μΈνΈκ° μμ²ν 리μμ€κ° μλ²μ μκ±°λ, μμ²ν κ²½λ‘κ° μ‘΄μ¬νμ§ μμ λ μλ΅νλ μνμ½λ μ
λλ€.");
}
Java
볡μ¬
500 Internal Server Error
: μλ² λ΄λΆμμ μ€λ₯κ° λ°μνμ¬ μμ²μ μ²λ¦¬ν μ μμμ λνλ
λλ€.
@GetMapping("/500")
public ResponseEntity<String> internalServerError() {
log.info("[GET] - /500 - μλ² μΈ‘μμ μλ¬λ μμΈκ° λ°μνμ λ μλ΅νλ μνμ½λ μ
λλ€.");
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("μλ² μΈ‘μμ μλ¬λ μμΈκ° λ°μνμ λ μλ΅νλ μνμ½λ μ
λλ€.");
}
Java
볡μ¬
μΌλ°μ μΌλ‘, 400 λ²λ, 500 λ²λ μνμ½λλ μ§μ μλ΅νμ§ μκ³ μμΈ μ²λ¦¬λ₯Ό ν΅ν΄ μΌκ΄μ μΈ λ°©λ²μΌλ‘ μ²λ¦¬ν©λλ€.
리λ€μ΄λ νΈ
리λ€μ΄λ νΈλ ν΄λΌμ΄μΈνΈμ μμ²μ λ€λ₯Έ URLλ‘ μ μ‘νλ κΈ°λ₯μ λ§ν©λλ€. μ΄λ μλ²κ° ν΄λΌμ΄μΈνΈμ μμ²μ λ°μμ§λ§, ν΄λΉ 리μμ€κ° λ€λ₯Έ μμΉμ μκ±°λ μ΄λλμμ λ μ¬μ©λ©λλ€. 리λ€μ΄λ νΈλ ν΄λΌμ΄μΈνΈκ° μλ μμ²ν URL λμ μ μλ‘μ΄ URLλ‘ μ΄λνμ¬ λ¦¬μμ€λ₯Ό μ»μ μ μλλ‘ λμμ€λλ€. μ΄λ₯Ό ν΅ν΄ μΉ νμ΄μ§μ κ²½λ‘λ₯Ό λ³κ²½νκ±°λ, νΉμ νμ΄μ§λ‘μ 리λ€μ΄λ μ
μ μ€μ ν μ μμ΅λλ€.
νμ΄μ§ μ΄λ λ°©μ
β’
forward
β’
redirect
μΉ νμ΄μ§λ₯Ό μ΄λνλ λ°©μμ 2κ°μ§λ‘ λλμ΄ λ³Ό μ μλ€.
forward λ°©μ
forward : βμ λ¬νλ€β
β’
μλ² λ΄λΆμμ μμ² κ²½λ‘ A κ° B λ‘ μμ²μ μ λ¬νλ©° νμ΄μ§λ‘ μ΄λνλ λ°©μ
β’
νΉμ§
β¦
μλμ μμ² μ 보(request) λ° μλ΅ μ 보(response)λ₯Ό κ·Έλλ‘ μ¬μ©
β¦
ν΄λΌμ΄μΈνΈλ μ΄λν νμ΄μ§ B λ₯Ό μλ΅ λ°μ§λ§, μ£Όμ νμμ€μ μμ² URL μ κ·Έλλ‘μ
β¦
μ‘°ν(μ½κΈ°) μμ²μ νλ κ²½μ°μ μ£Όλ‘ μ¬μ©
redirect λ°©μ
redirect : βλ€μ μ§μνλ€β
β’
μλ²κ° μμ² κ²½λ‘ A λ‘ μμ²μ λ°μ ν, ν΄λΌμ΄μΈνΈμκ² B λ‘ λ€μ μμ²νλΌκ³ μ§μνλ©° νμ΄μ§λ₯Ό μ΄λνλ λ°©μ
β’
νΉμ§
β¦
ν΄λΌμ΄μΈνΈκ° μλμ μμ²κ³Ό λ¬λ¦¬ μμ ν λ€λ₯Έ μλ‘μ΄ μμ²μ νμ¬, κΈ°μ‘΄μ μμ² μ 보λ μ΄νμ μμ²μμλ μ¬μ©ν μ μμ
β¦
μ΄λν νλ©΄μμ μ£Όμ νμμ€μ URL μ΄ A μμ B λ‘ λ³νλ¨
β¦
λ±λ‘, μμ , μμ μμ² μμ μ£Όλ‘ μ¬μ©
μΌλ°μ μΌλ‘ κ²μκΈ λ±λ‘, μμ , μμ μ²λ¦¬ ν, κ²μκΈ λͺ©λ‘μΌλ‘ νμ΄μ§λ₯Ό μ΄λμν€κΈ° μν΄μ 리λ€μ΄λ μ
μ νλ€.
κ²μκΈ μ°κΈ° μ²λ¦¬ κ²μκΈ λͺ©λ‘ (redierct)
/**
* κ²μκΈ μ°κΈ° μ²λ¦¬
* [POST]
* /board/insert
* model : β
* @param board
* @return
* @throws Exception
*/
@PostMapping(value="/insert")
public String insertPro(@ModelAttribute Board board) throws Exception {
// @ModelAttribute : λͺ¨λΈμ μλμΌλ‘ λ±λ‘ν΄μ£Όλ μ΄λ
Έν
μ΄μ
// λ°μ΄ν° μ²λ¦¬
int result = new Random().nextInt(2);
// κ²μκΈ μ°κΈ° μ€ν¨ β‘ κ²μκΈ μ°κΈ° νλ©΄
if( result == 0 ) return "redirect:/board/insert";
// λ·° νμ΄μ§ μ§μ
return "redirect:/board/list";
}
Java
볡μ¬
κ²μκΈ μμ μ²λ¦¬ κ²μκΈ λͺ©λ‘ (redierct)
/**
* κ²μκΈ μμ μ²λ¦¬
* [POST]
* /board/update
* model : board
* @param board
* @return
* @throws Exception
*/
@PostMapping(value="/update")
public String updatePro(Board board) throws Exception {
// λ°μ΄ν° μ²λ¦¬
int result = new Random().nextInt(2);
int boardNo = board.getBoardNo();
// κ²μκΈ μμ μ€ν¨ β‘ κ²μκΈ μμ νλ©΄
if( result == 0 ) return "redirect:/board/update?boardNo=" + boardNo;
// λ·° νμ΄μ§ μ§μ
return "redirect:/board/list";
}
Java
볡μ¬
κ²μκΈ μμ μ²λ¦¬ κ²μκΈ λͺ©λ‘ (redierct)
/**
* κ²μκΈ μμ μ²λ¦¬
* [POST]
* /board/delete
* model : β
* @param boardNo
* @return
* @throws Exception
*/
@PostMapping(value="/delete")
public String deletePro(int boardNo) throws Exception {
// λ°μ΄ν° μ²λ¦¬
int result = new Random().nextInt(2);
// κ²μκΈ μμ μ€ν¨ β‘ κ²μκΈ μμ νλ©΄
if( result == 0 ) return "redirect:/board/update?boardNo=" + boardNo;
// λ·° νμ΄μ§ μ§μ
return "redirect:/board/list";
}
Java
볡μ¬
μ΄λ―Έμ§ μλ΅ (μΈλ€μΌ)
μ΄λ―Έμ§ μλ΅ ν€λ
β’
ContentType : image/*
λ°μ΄ν°κ° μ΄λ―Έμ§λ‘ μλ΅λλ €λ©΄ Content-Type μλ΅ ν€λμ κ°μ image/*μ νν μ§μ ν΄μΌν©λλ€.
μΌλ°μ μΌλ‘ μ΄λ―Έμ§λ₯Ό HTTP μλ΅μΌλ‘ λ°νν λ Content-Type ν€λλ image/*μ ννλ₯Ό μ·¨νκ² λ©λλ€. νμ§λ§ μ νν Content-Type ν€λλ ν΄λΉ μ΄λ―Έμ§ μ νμ λ°λΌ λ¬λΌμ§λλ€. μ΄λ―Έμ§ ν¬λ§·μ λ°λΌ μ μ ν Content-Typeμ μ€μ ν΄μΌ ν©λλ€.
β’
JPEG μ΄λ―Έμ§μ Content-Type: image/jpeg
β’
PNG μ΄λ―Έμ§μ Content-Type: image/png
β’
GIF μ΄λ―Έμ§μ Content-Type: image/gif
β’
WEBP μ΄λ―Έμ§μ Content-Type: image/webp
μ΄λ―Έμ§ μλ΅ λ°©λ²
β’
ResponseEntity<byte[]> μλ΅ νμ
μΌλ‘ μλ΅νκΈ°
β’
HttpServletResponse, FileCopyUtils κ°μ²΄λ₯Ό μ΄μ©νμ¬ μλ΅νκΈ°
ResponseEntity<byte[]> μλ΅ νμ μΌλ‘ μλ΅νκΈ°
ResponseEntity<byte[]>
/**
* π ResponseEntity<byte[]>
* @return
* @throws IOException
*/
@GetMapping("/img")
public ResponseEntity<byte[]> thumbnailImg() throws IOException {
log.info("[GET] - /img");
// μ΄λ―Έμ§ νμΌμ μ½μ΄μ΄
ClassPathResource imgFile = new ClassPathResource("sample.png");
byte[] bytes = Files.readAllBytes(imgFile.getFile().toPath());
// μ΄λ―Έμ§ νμΌμ μ½μ΄μ μλ΅
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.IMAGE_PNG);
return new ResponseEntity<>(bytes, headers, HttpStatus.OK);
}
Java
볡μ¬
HttpServletResponse, FileCopyUtils κ°μ²΄λ₯Ό μ΄μ©νμ¬ μλ΅νκΈ°
HttpServletResponse, FileCopyUtils
β’
Controller - showImg()
/**
* μ΄λ―Έμ§ μΈλ€μΌ
* @param filePath
* @param response
* @throws Exception
*/
@GetMapping("/img")
public void showImg(String filePath
,HttpServletResponse response ) throws Exception {
log.info("filePath : " + filePath);
File file = new File(filePath);
FileInputStream fis = new FileInputStream(file);
ServletOutputStream sos = response.getOutputStream();
FileCopyUtils.copy(fis, sos);
// filePath : C:/KHM/upload/[UID]_κ°μμ§.png
// μ΄λ―Έμ§ 컨ν
νΈ νμ
νμΈ ( .jpg, .png, .gif, ... )
String ext = filePath.substring( filePath.lastIndexOf(".") + 1 ); // νμ₯μ
MediaType mType = MediaUtil.getMediaType(ext);
// μ΄λ―Έμ§ νμ
μ΄ μλ κ²½μ°
if( mType == null ) {
return;
}
log.info("mType : " + mType);
response.setContentType( mType.toString() );
}
Java
볡μ¬
β’
MediaUtil.java
/**
* νμ₯μλ‘ μ»¨ν
νΈνμ
맀ν
* @author h
*
*/
public class MediaUtil {
private static Map<String, MediaType> mediaType;
static {
mediaType = new HashMap<String, MediaType>();
mediaType.put("JPG", MediaType.IMAGE_JPEG);
mediaType.put("JPEG", MediaType.IMAGE_JPEG);
mediaType.put("GIF", MediaType.IMAGE_GIF);
mediaType.put("PNG", MediaType.IMAGE_PNG);
mediaType.put("WEBP", MediaType.parseMediaType("img/webp") ); // MediaType.IMAGE_WEBP μμλ μ‘΄μ¬νμ§ μμ
}
// νμ₯μλ‘ μ»¨ν
νΈνμ
μ νμΈνλ λ©μλ
public static MediaType getMediaType(String ext) {
return mediaType.get(ext.toUpperCase());
}
}
Java
볡μ¬
HttpServletResponse
HTTP μλ΅μ ν΄λΌμ΄μΈνΈμκ² λ³΄λ΄κΈ° μν HTTP μλΈλ¦Ώ μλ΅μ λνλ
λλ€. μ΄ κ°μ²΄λ μλΈλ¦Ώμμ ν΄λΌμ΄μΈνΈλ‘ μ μ‘λλ μλ΅μ μ μ΄νλ λ° μ¬μ©λ©λλ€.
1.
HTTP μλ΅ μ€μ : HTTP μλ΅μ μμ± μ€μ . μλ₯Ό λ€μ΄, μ½ν
μΈ μ ν(Content-Type), μΊμ μ μ΄, μλ΅ μ½λ λ° λ©μμ§ λ±μ μ€μ ν μ μμ΅λλ€.
2.
μλ΅ ν€λ μ€μ : HTTP μλ΅μ ν€λ μ€μ . setHeader() λ©μλλ₯Ό μ¬μ©νμ¬ νΉμ ν€λ κ°μ μ€μ ν μ μμ΅λλ€.
3.
μΏ ν€ μ€μ : ν΄λΌμ΄μΈνΈλ‘ μΏ ν€λ₯Ό μ μ‘νκΈ° μν΄ addCookie() λ©μλλ₯Ό μ¬μ©ν μ μμ΅λλ€.
β’
μ£Όμ λ©μλ
λ©μλ | μ€λͺ
|
setContentType(String type) | μλ΅μ μ½ν
μΈ μ νμ μ€μ ν©λλ€. |
setStatus(int sc) | μλ΅ μ½λλ₯Ό μ€μ ν©λλ€. |
setHeader(String name, String value) | μ§μ λ ν€λ κ°μ μ€μ ν©λλ€. |
addCookie(Cookie cookie) | μΏ ν€λ₯Ό μλ΅μ μΆκ°ν©λλ€. |
FileCopyUtils
Spring νλ μμν¬μμ νμΌ λ³΅μ¬μ μ¬μ©λλ μ νΈλ¦¬ν° ν΄λμ€μ
λλ€. μ΄ ν΄λμ€λ μ€νΈλ¦Ό λλ 리μμ€μμ νμΌμ μ½κ³ μ°λ λ° μ¬μ©λ©λλ€.
β’
μ£Όμ λ©μλ
λ©μλ | μ€λͺ
|
copy() | νμΌ, μ€νΈλ¦Ό, λ°μ΄νΈ λ°°μ΄ λ± κ°μ λ³΅μ¬ μμ
μ μνν©λλ€. |
copy(byte[] in, byte[] out) | μ
λ ₯ byte[]μμ μΆλ ₯ byte[]λ‘ λ°μ΄ν°λ₯Ό 볡μ¬ν©λλ€. |
copy(InputStream in, OutputStream out) | InputStreamμμ OutputStreamμΌλ‘ λ°μ΄ν°λ₯Ό 볡μ¬ν©λλ€. |
copy(Resource in, File out) | Resourceμμ Fileλ‘ λ°μ΄ν°λ₯Ό 볡μ¬ν©λλ€. |
νμΌ μλ΅ (λ€μ΄λ‘λ)
νμΌ λ€μ΄λ‘λ μλ΅ ν€λ
β’
Content-Type : application/octet-stream
β’
Content-Disposition : form-data; name="attachment"; filename="sample.pngβ
νμΌ λ€μ΄λ‘λλ₯Ό μν΄, Content-Type μλ΅ ν€λμ κ°μ application/octet-stream μ νν μ§μ ν΄μΌν©λλ€. Content-Disposition μλ΅ ν€λμ κ°μ name="attachment"; filename="sample.pngβ ννλ‘ μ§μ ν΄μΌν©λλ€.
νμΌ λ€μ΄λ‘λ ꡬν λ°©λ²
β’
ResponseEntity<byte[]> μλ΅ νμ
μΌλ‘ μλ΅νκΈ°
β’
HttpServletResponse, FileCopyUtils κ°μ²΄λ₯Ό μ΄μ©νμ¬ μλ΅νκΈ°
ResponseEntity<byte[]>
β’
Content-Type : application/octet-stream
β’
Content-Disposition : form-data; name="attachment"; filename="sample.pngβ
/**
* π ResponseEntity<byte[]>
* @return
* @throws IOException
*/
@GetMapping("/img")
public ResponseEntity<byte[]> thumbnailImg() throws IOException {
log.info("[GET] - /img");
// μ΄λ―Έμ§ νμΌμ μ½μ΄μ΄
ClassPathResource imgFile = new ClassPathResource("sample.png");
byte[] bytes = Files.readAllBytes(imgFile.getFile().toPath());
// μ΄λ―Έμ§ νμΌμ μ½μ΄μ μλ΅
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.IMAGE_PNG);
return new ResponseEntity<>(bytes, headers, HttpStatus.OK);
}
Java
볡μ¬
HttpServletResponse, FileCopyUtils
/**
* νμΌ λ€μ΄λ‘λ
* @param fileNo
* @param response
* @throws Exception
*/
@GetMapping("/{fileNo}")
public void fileDownload(@PathVariable("fileNo") int fileNo
,HttpServletResponse response) throws Exception {
// νμΌ μ‘°ν
Files file = fileService.read(fileNo);
// νμΌμ΄ μ‘΄μ¬νμ§ μμΌλ©΄,
if( file == null ) {
// μλ΅ μνμ½λ : 400, ν΄λΌμ΄μΈνΈμ μμ²μ΄ μλͺ»λμμμ λνλ΄λ μνμ½λ
response.setStatus(response.SC_BAD_REQUEST);
return;
}
String fileName = file.getFileName(); // νμΌ λͺ
String filePath = file.getFilePath(); // νμΌ κ²½λ‘
// νμΌ λ€μ΄λ‘λλ₯Ό μν ν€λ μΈν
// - ContentType : application/octet-straem
// - Content-Disposition : attachment; fileanme="νμΌλͺ
.νμ₯μ"
response.setContentType("application/octet-stream");
response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\"");
// νμΌ μ
λ ₯
File downloadFile = new File(filePath);
FileInputStream fis = new FileInputStream(downloadFile);
ServletOutputStream sos = response.getOutputStream();
// λ€μ΄λ‘λ
FileCopyUtils.copy(fis, sos);
}
Java
볡μ¬
API κ°λ° λ¬Έμν λꡬ
: API κ°λ° λ¬Έμν λꡬλ API μλν¬μΈνΈ, μμ², μλ΅ λ° κ΄λ ¨ μ 보λ₯Ό λ¬Έμννμ¬ κ°λ°μλ€μκ² API μ¬μ© λ°©λ²μ μ 곡νλ μννΈμ¨μ΄ λꡬμ
λλ€.
μ’ λ₯
β’
Swagger
Swagger (OpenAPI)
REST APIλ₯Ό μ€κ³, ꡬμΆ, λ¬Έμν λ° μ¬μ©νλ λ° λμμ΄ λ μ μλ OpenAPI μ¬μμ κΈ°λ°μΌλ‘ ꡬμΆλ μ€ν μμ€ λꡬ μΈνΈμ
λλ€.
https://swagger.io/docs/specification/about/
β’
API μ€κ³, λΉλ, λ¬Έμν λ° ν
μ€νΈλ₯Ό μν ν΅ν© ν΄.
β’
OpenAPI νμ€μ μ€μνλ©°, RESTful APIλ₯Ό μ½κ² λμμΈνκ³ κ΄λ¦¬ν μ μμ.