Search

Response

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๋ฅผ ์‰ฝ๊ฒŒ ๋””์ž์ธํ•˜๊ณ  ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ์Œ.

Github (์†Œ์Šค์ฝ”๋“œ)