API를 작성하는 다양한 방법(CH05-2 GET API 만들기)

이도훈·2025년 4월 2일

스프링부트 핵심 가이드 책을 통한 글 입니다.

5.2 GET API 만들기

GET API웹 애플리케이션 서버에서 값을 가져올 때 사용하는 API이다. GET을 쉽게 말하자면, 서버에게 리소스(데이터)를 가져와라(GET)라는 의미이다. GET API를 작성하는 방법은 다양하며, 이번 장에서는 애플리케이션으로 들어오는 여러 요청에 대한 처리 방법의 하나로서 소개한다. 추가로 프론트엔드에서 백엔드로 데이터를 요청할 때 쓰인다.

아래의 예제 코드를 통해 여러 GET 방식을 알아보자.

전체 코드

Controller 클래스 코드

@RestController
@RequestMapping("/api/v1/get-api")
public class GetController {
	//5.2.1 @RequestMapping으로 구현하기
    @RequestMapping(value="/hello",method = RequestMethod.GET)
    public String getHello(){
        return "Hello World";
    }
    //5.2.2 매개변수가 없는 GET 메서드 구현
    @GetMapping(value="/name")
    public String getName(){
        return "Flature";
    }
    //5.2.3 @PathVariable을 활용한 GET 요청(매개변수 있는 GET요청)
    @GetMapping(value="/variable1/{variable}")
    public String getVariable1(@PathVariable String variable){
        return variable;
    }
    @GetMapping(value="/variable2/{variable}")
    public String getVariable2(@PathVariable("variable") String var){
        return var;
    }
    //5.2.4 @RequestParam을 활용한 GET 메서드 구현+Map 함수
    @GetMapping(value="/request1")
    public String getRequestParam1(
            @RequestParam String name,
            @RequestParam String email,
            @RequestParam String organization){
        return name+" "+email+" "+organization;
    }
    @GetMapping(value="/request2")
    	public String getRequestParam2(@RequestParam Map<String,String> param){
        StringBuilder sb = new StringBuilder();
        param.entrySet().forEach(map->{
            sb.append(map.getKey()+" : " + map.getValue()+"\n");
        });
        return sb.toString();
    }
    @GetMapping(value="/request3")// DTO를 활용한 GET 요청
    public String getRequestParam3(MemberDto memberDto){
        return memberDto.toString();
    }
}

DTO 클래스(5.2.5)

public class MemberDto {
    private String name;
    private String email;
    private String organization;

    public String getName(){
        return name;
    }

    public void setName(String name){
        this.name = name;
    }

    public String getEmail(){
        return email;
    }

    public void setEmail(String email){
        this.email=email;
    }

    public String getOrganization(){
        return organization;
    }

    public void setOrganization(String organization){
        this.organization = organization;
    }

    @Override
    public String toString(){//원래의 toString()함수를 오버라이딩하여 재정의하였다.
        return "MemberDto{"+"name=`"+name+'\''+", email='"+email+'\''+
                ",organization='"+organization+'\''+'}';
    }
    //결국 System.out.println(member);을 호출하면 오버라이딩한 toString()이 불린다.
}

  • @RestController은 내부적으로 @Controller + @ResponseBody의 기능을 합친 것이다. 이 클래스 안의 메서드들이 데이터(String, JSON 등)를 직접 반환하며, 뷰(view)를 사용하지 않는다.
  • 여기서 @ResponseBodyController에서 return 할 때 json형식으로 반환하는 역할을 한다.

5.2.1 @RequestMapping으로 구현하기

	@RequestMapping(value="/hello",method = RequestMethod.GET)
    public String getHello(){
        return "Hello World";
    }
  • 클래스에 붙어있는 @RequestMapping어노테이션은 이 클래스의 모든 요청 경로 앞에는 /api/v1/get-api가 붙게 매핑된다. 클래스 안에 있는 매서드(getHello)에 붙어있는 @RequestMapping/hello 요청을 보내려면 실제 요청 경로는 /api/v1/get-api/hello가 되어 Hello World를 출력한다.
  • @RequestMapping의 단점은 GET메서드를 매개변수로 받아야 하기 때문에 잘 쓰이지 않고 아래 내용인 @GetMapping을 더 많이 쓴다.

5.2.2 매개변수가 없는 GET 메서드 구현

	@GetMapping(value="/name")
    public String getName(){
        return "Flature";
    }
  • 매개변수가 없는 요청은 @GetMapping을 통해 응답을 반환한다. 즉, http://localhost:8080/api/v1/get-api/name을 입력하면 Flature가 반환된다.
  • @RequestMapping과의 차이점은 GET요청을 한다는 가독성과 @RequestMapping보다 편리하다는 점에서 더 많이 쓰인다.

5.2.3 @PathVariable을 활용한 GET 요청

	@GetMapping(value="/variable1/{variable}")//URL값과 매개변수 값 같은 경우
    public String getVariable1(@PathVariable String variable){
        return variable;
    }
    @GetMapping(value="/variable2/{variable}")//URL값과 매개변수값이 다른 경우
    public String getVariable2(@PathVariable("variable") String var){
        return var;
    }
  • @PathVariable은 URL 경로에 있는 값({variable})과 메서드 매개변수(variable)를 바인딩(연결)해 주는 어노테이션이고, @GetMapping("/변수포함경로")와 함께 쓰여 URL을 통해 매개변수를 받게 할 수 있는 어노테이션이다.
  • URL 경로에 있는 값과 메서드 매개변수에 있는 값을 바인딩하기 때문에 두 값은 같아야한다. 위의 코드에서는 variable로 같다.

5.2.4 @RequestParam을 활용한 GET 메서드 구현(1,2)

@RequestParam을 통한 GET 메서드 구현

	@GetMapping(value="request1")
    public String getRequestParam1(
            @RequestParam String name,
            @RequestParam String email,
            @RequestParam String organization){
        return name+" "+email+" "+organization;
    }
  • 앞서 살펴본 URL 경로에 값을 담아 요청을 보내는 방법 외에도 URL 우측부터 ?{key}:{value}&{key}:{value}... 이러한 식으로 요청을 전송할 수 있다. 위의 코드를 예시로 들면
    http://localhost:8080/api/v1/get-api/request1?name=value1 &email=value2&organization=value3 이렇게 요청을 전송한다.
  • GET결과는 value1 value2 value3가 된다.

@RequestParam + Map 을 통한 GET 메서드 구현

   @GetMapping(value="request2")
   public String getRequestParam2(@RequestParam Map<String,String> param){
        StringBuilder sb = new StringBuilder();
        param.entrySet().forEach(map->{
            sb.append(map.getKey()+" : " + map.getValue()+"\n");
        });
        return sb.toString();
    }
  • 이 형태로 코드를 작성하면 값에 상관없이 요청을 받을 수 있다. 예를들어, 회원 가입 관련 API에서 사용자는 회원가입을 하면서 ID 같은 필수 항목이 아닌 취미 같은 선택 항목에 대해서는 기입하지 않는 경우에 매개변수의 항목이 일정하지 않을 수 있어 Map 객체로 받는 것이 효율적이다.

1) @RequestParam Map<String, String> param
클라이언트가 보낸 쿼리 파라미터를 Map 형태로 전부 받아온다.
예를 들어 요청이 GET /request2?name=Tom&age=30 라면,

param = {
  "name" : "Tom",
  "age" : "30"
}

2) StringBuilder sb = new StringBuilder();
여러 문자열을 효율적으로 연결하기 위해 사용하는 클래스이다.
여기선 keyvalue"key : value" 형식으로 하나의 문자열로 합칠 때 사용된다.
3) param.entrySet().forEach(...)
Map의 모든 key-value 쌍을 하나씩 반복(.forEach)하면서,
각 쌍을 "key : value\n" 형식으로 만들어 StringBuilder에 추가한다.

// 반복 예시:
"Tom" -> sb.append("name : Tom\n")
"30"  -> sb.append("age : 30\n")

4) return sb.toString();
StringBuilder에 저장된 모든 문자열을 하나로 묶어 String으로 변환해서 반환한다.
이 값이 HTTP 응답 본문으로 클라이언트에게 전달된다.

5.2.5 DTO 개체를 활용한 GET 메서드 구현

DTO(Data Transfer Object)란?

다른 레이어 간의 데이터 교환에 활용
(예를 들어 Controller<->DTO<->Service)된다. 각 클래스 및 인터페이스를 호출하면서 전달하는 매개변수로 사용되는 데이터 객체이다. 즉, 별도의 로직이 필요없다.

DTO 클래스를 활용한 GET 매서드 구현

//DTO 클래스
public class MemberDto {
    private String name;
    private String email;
    private String organization;

    public String getName(){
        return name;
    }

    public void setName(String name){
        this.name = name;
    }

    public String getEmail(){
        return email;
    }

    public void setEmail(String email){
        this.email=email;
    }

    public String getOrganization(){
        return organization;
    }

    public void setOrganization(String organization){
        this.organization = organization;
    }

    @Override
    public String toString(){//원래의 toString()함수를 오버라이딩하여 재정의하였다.
        return "MemberDto{"+"name=`"+name+'\''+", email='"+email+'\''+
                ",organization='"+organization+'\''+'}';
    }
    //결국 System.out.println(member);을 호출하면 오버라이딩한 toString()이 불린다.
}
//Controller 클래스
@GetMapping(value="/request3")
public String getRequestParam3(MemberDto memberDto){
	return memberDto.toString();
}
  • DTO 패키지에 있는 MemberDto 클래스에서 toString()함수를 오버라이딩 했기 때문에 memberDto.toString()시 밑의 요청이 return되게 한다.
    "MemberDto{"+"name=`"+name+'\''+", email='"+email+'\''+ ",organization='"+organization+'\''+'}'
  • 또한 밑의 http요청이 어떻게 자동으로 set되는지 궁금했는데 DTO 클래스에는 setter가 있으면 자동으로 set된다고 한다 즉, 스프링이 자동으로 쿼리스트링 값(?기호 뒤에 붙는 키-값 쌍의 데이터)을 DTO의 `setter에 매핑한다.
  • http://localhost:8080/api/v1/get-api/request3?name=value1&email=value2&organization=value3

0개의 댓글