HTTP 헤더

Backend kwon·2023년 8월 16일

HTTP 헤더란?

HTTP 메시지(Messages)의 구성 요소 중 하나로써 클라이언트의 요청이나 서버의 응답에 포함되어 부가적인 정보를 HTTP 메시지에 포함할 수 있도록 해준다.

HTTP 헤더(Header)의 사용 목적

  • Content-Type
    Content-Type 헤더 정보는 클라이언트와 서버가 주고받는 HTTP 메시지 바디의 데이터 형식이 무엇인지를 알려주는 역할을 한다.
    클라이언트와 서버는 이 Content-Type이 명시된 데이터 형식에 맞는 데이터들을 주고받는 것이다.
    ex) 샘플 애플리케이션의 ‘Content-Type’은 ‘application/json’이다.

  • Authorization(인가)
    ‘Authorization’ 헤더 정보는 클라이언트가 적절한 자격 증명을 가지고 있는지를 확인하기 위한 정보이다.
    일반적으로 REST API 기반 애플리케이션의 경우 클라이언트와 서버 간의 로그인(사용자 ID/비밀번호) 인증에 통과한 클라이언트들은 ‘Authorization’ 헤더 정보를 기준으로 인증에 통과한 클라이언트가 맞는지 확인하는 절차를 거친다.

  • User-Agent
    데스크 탑에서 들어오는 요청과 모바일에서 들어오는 요청을 구분해서 응답 데이터를 다르게 보내줘야 되는 경우가 있을 수 있다.
    예를 들면, 모바일 화면과 데스크톱 또는 노트북의 화면 크기의 차이가 많이 나기 때문에 더 큰 화면에서 더 많은 정보를 보여주기 위해 각각 데이터의 종류와 크기가 다를 수 있다.
    이 경우, ‘User-Agent’ 정보를 이용해서 모바일 에이전트에서 들어오는 요청인지 모바일 이외에 다른 에이전트에서 들어오는 요청인지를 구분해서 처리할 수 있다.

 

HTTP Request 헤더 정보 얻기

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”)와 같이 해당 헤더 정보를 얻을 수 있다.

 

HTTP Response 헤더 정보 추가

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를 사용하길 권장한다.

profile
백엔드개발자를 향해서

0개의 댓글