HTTP 헤더란?
HTTP 메시지(Messages)의 구성 요소 중 하나로써 클라이언트의 요청이나 서버의 응답에 포함되어 부가적인 정보를 HTTP 메시지에 포함할 수 있도록 해준다.
Content-Type
Content-Type 헤더 정보는 클라이언트와 서버가 주고받는 HTTP 메시지 바디의 데이터 형식이 무엇인지를 알려주는 역할을 한다.
클라이언트와 서버는 이 Content-Type이 명시된 데이터 형식에 맞는 데이터들을 주고받는 것이다.
ex) 샘플 애플리케이션의 ‘Content-Type’은 ‘application/json’이다.
Authorization(인가)
‘Authorization’ 헤더 정보는 클라이언트가 적절한 자격 증명을 가지고 있는지를 확인하기 위한 정보이다.
일반적으로 REST API 기반 애플리케이션의 경우 클라이언트와 서버 간의 로그인(사용자 ID/비밀번호) 인증에 통과한 클라이언트들은 ‘Authorization’ 헤더 정보를 기준으로 인증에 통과한 클라이언트가 맞는지 확인하는 절차를 거친다.
User-Agent
데스크 탑에서 들어오는 요청과 모바일에서 들어오는 요청을 구분해서 응답 데이터를 다르게 보내줘야 되는 경우가 있을 수 있다.
예를 들면, 모바일 화면과 데스크톱 또는 노트북의 화면 크기의 차이가 많이 나기 때문에 더 큰 화면에서 더 많은 정보를 보여주기 위해 각각 데이터의 종류와 크기가 다를 수 있다.
이 경우, ‘User-Agent’ 정보를 이용해서 모바일 에이전트에서 들어오는 요청인지 모바일 이외에 다른 에이전트에서 들어오는 요청인지를 구분해서 처리할 수 있다.
1. @RequestHeader로 개별 헤더 정보 받기
@RestController
@RequestMapping(path = "/v1/coffees")
public class CoffeeController {
@PostMapping
public ResponseEntity postCoffee(@RequestHeader("user-agent") String userAgent,
@RequestParam("korName") String korName,
.
.
.
@RequestHeader를 사용해서 특정 헤더 정보만 읽는 예제이다. @RequestParam과 사용법이 거의 동일
2. @RequestHeader로 전체 헤더 정보 받기
@PostMapping
public ResponseEntity postMember(@RequestHeader Map<String, String> headers,
@RequestParam("email") String email) {
for (Map.Entry<String, String> entry : headers.entrySet()) {
System.out.println("key: " + entry.getKey() +
", value: " + entry.getValue());
}
.
.
.
@RequestHeader를 사용해서 Request의 모든 헤더 정보를 Map으로 전달받는 예제이다.
3. HttpServletRequest 객체로 헤더 정보 얻기
@PostMapping
public ResponseEntity postOrder(HttpServletRequest httpServletRequest,
@RequestParam("memberId") long memberId,
@RequestParam("coffeeId") long coffeeId) {
System.out.println("user-agent: " + httpServletRequest.getHeader("user-agent"));
.
.
.
HttpServletRequest 객체를 통해서 Request 헤더 정보를 얻을 수 있다.
HttpServletRequest 객체를 이용하면 Request 헤더 정보에 다양한 방법으로 접근이 가능하다.
그런데 HttpServletRequest는 다양한 API를 지원하지만 단순히 특정 헤더 정보에 접근하고자 한다면 HttpServletRequest 대신에 앞에서 설명한 @RequestHeader를 이용하는 편이 낫다.
4. HttpEntity 객체로 헤더 정보 얻기
Spring MVC에서는 HttpEntity 객체를 통해서도 헤더 정보를 읽을 수 있다. HttpEntity는 Request 헤더와 바디 정보를 래핑하고 있으며, 조금 더 쉽게 헤더와 바디에 접근할 수 있는 다양한 API를 지원한다.
@GetMapping
public ResponseEntity getCoffees(HttpEntity httpEntity) {
for(Map.Entry<String, List<String>> entry : httpEntity.getHeaders().entrySet()){
System.out.println("key: " + entry.getKey()
+ ", " + "value: " + entry.getValue());
}
System.out.println("host: " + httpEntity.getHeaders().getHost());
.
.
.
HttpEntity 객체를 통해서 Request 헤더 정보를 읽어 왔다.
HttpServletRequest 객체를 사용할 때와 마찬가지로 Entry를 통해서 각각의 헤더 정보에 접근할 수 있는데, 특이한 것은 자주 사용될 만한 헤더 정보들을 getXXX()로 얻을 수 있다.
getXXX() 메서드는 자주 사용되는 헤더 정보만 얻어올 수 있으므로 getXXX() 메서드로 원하는 헤더 정보를 읽어올 수 없다면 get() 메서드를 사용해서 get(”host”)와 같이 해당 헤더 정보를 얻을 수 있다.
1. ResponseEntity와 HttpHeaders를 이용해 헤더 정보 추가하기
@RestController
@RequestMapping(path = "/v1/members")
public class MemberController{
@PostMapping
public ResponseEntity postMember(@RequestParam("email") String email,
@RequestParam("name") String name,
@RequestParam("phone") String phone) {
// 위치 정보를 헤더에 추가
HttpHeaders headers = new HttpHeaders();
headers.set("Client-Geo-Location", "Korea,Seoul");
return new ResponseEntity<>(new Member(email, name, phone), headers,
HttpStatus.CREATED);
}
}
ResponseEntity와 HttpHeaders를 이용해서 위치 정보를 커스텀 헤더로 추가하고 있다.
Map이나 Set 같은 Java의 컬렉션(Collections) API처럼 HttpHeaders의 set() 메서드를 이용해서 헤더 정보를 추가할 수 있다.
2. HttpServletResponse 객체로 헤더 정보 추가하기
@RestController
@RequestMapping(path = "/v1/members")
public class MemberController{
@GetMapping
public ResponseEntity getMembers(HttpServletResponse response) {
response.addHeader("Client-Geo-Location", "Korea,Seoul");
.
.
.
HttpServletResponse를 이용해서 위치 정보를 커스텀 헤더로 추가하고 있다.
HttpServletResponse의 addHeader() 메서드 역시 HttpHeaders의 set() 메서드와 메서드 이름만 다를 뿐 헤더 정보를 추가하는 방법은 같다.
한 가지 차이점은 HttpHeaders 객체는 ResponseEntity에 포함을 시키는 처리가 필요하지만 HttpServletResponse 객체는 헤더 정보만 추가할 뿐 별도의 처리가 필요 없다.
HttpServletRequest와 HttpServletResponse는 저수준(Low Level)의 서블릿 API를 사용할 수 있기 때문에 복잡한 HTTP Request/Response를 처리하는 데 사용할 수 있다.
반면에 ResponseEntity나 HttpHeaders는 Spring에서 지원하는 고수준(High Level) API로써 간단한 HTTP Request/Response 처리를 빠르게 진행할 수 있다.
복잡한 처리가 아니라면 코드의 간결성이나 생산성 면에서 가급적 Spring에서 지원하는 고수준 API를 사용하길 권장한다.