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 (μ†ŒμŠ€μ½”λ“œ)