유저 생성, 조회 API

goose_bumps·2024년 5월 19일

만들어보려하는 웹 페이지는 도서 관리 웹으로 사용자와 책에 관련된 API를 생성해야 한다.

사용자

  • 사용자 등록(이름, 나이)
  • 사용자 목록
  • 사용자 이름 업데이트
  • 사용자 삭제

  • 책 등록 및 삭제
  • 사용자가 책 빌릴 수 있음(다른 사람이 빌렸을 경우에는 불가능)
  • 책 반납

여기서 사용자를 등록하고 조회하는 API를 생성해보자.

1. 유저 생성 API

우선 API 설계 먼저 해보자
데이터를 저장해야 하기 때문에 Post method를 사용하고 path는 /user로 설정한다.
Post 방식이기 때문에 Body를 사용하며 이름은 필수이기 때문에 null값을 허용하지 않는다. 데이터를 반환할 필요는 없고 200 ok 상태 출력만 되면 된다.

1) UserController 생성

controller 패키지에 user 패키지를 생성하고 UserController 클래스를 만들자.

@RestController
public class UserController{}

@RestController 에너테이션을 사용하여 API 진입로를 만들었다. API를 통해 유저가 저장되면 유저 객체를 리스트에 저장해야 한다. 그럴려면 유저 객체를 만들어야 하기 때문에 User class를 만들어줘야 한다.

2) User 생성

domain 패키지에 user 패키지를 생성하고 User 클래스를 만들어보자. User 클래스는 이름과 나이를 저장하며 나이는 null값이 가능하기 때문에 int형이 아닌 Integer형으로 선언한다.
constructor와 getter을 생성하여 다음과 같이 클래스를 구성한다.

package com.group.libraryapp.domain.user;

public class User {
    private String name;
    private Integer age;

    public User(String name, Integer age) {
        if(name == null || name.isBlank())
            throw new IllegalArgumentException(String.format("잘못된 입력(%s)입니다",name));
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public Integer getAge() {
        return age;
    }
}

생성자로 변수 초기화를 실행할 시 이름값이 null이면 if문이 실행되어 예외를 던진다. 따라서, 이름에는 null이 들어갈 수 없게 된다.

이제 UserController로 돌아와서 API를 만들어보자. 유저 객체를 리스트에 저장해야 하기 때문에 클래스 첫 줄에 User타입의 리스트를 만든다.

@RestController
public class UserController {

    private final List<User> users = new ArrayList<>();
    @PostMapping("/user") //사용자 등록
    public void saveUser(){}
}

이렇게 하면 User 타입의 리스트가 생성되고 saveUser를 통해 이 리스트에 유저 객체를 저장하면 된다.

3) 데이터 전달을 위한 Body인 UserCreateRequest 생성

post 방식에서 데이터 전달은 JSON 즉, Body를 통해 전달한다고 하였다. 그러기 위해서는 Body 객체가 필요하다. 즉, 클래스를 만들어야 한다는 것이다. Post API 설계를 공부하면서 dto 패키지에 데이터 전달 객체를 만들었었다.
이번에도 마찬가지로 dto 패키지 user 패키지를 생성하여 데이터 전달을 위한 클래스 UserCreateRequest를 생성하겠다.

package com.group.libraryapp.dto.user;

public class UserCreateRequest {
    private String name;
    private Integer age;

    public String getName() {
        return name;
    }
    public Integer getAge() {
        return age;
    }
}

이 UserCreateRequest 클래스가 Body 객체를 만들기 위한 클래스가 되는 것이다. 자, 그럼 Body 객체는 어디에 들어가야 할까?
바로 saveUser의 매개변수로 들어가야 한다. 하지만, 그냥 들어가는 것이 아니다. 객체 형식으로 전달되기 때문에 post 방식에서는 객체 매개변수 앞에 @RequestBody가 추가되어야 한다.

@RequestBody : Post Method에서 Body 객체라는 의미를 가진 에너테이션

그러면 saveUser 메서드는 다음과 같이 작성하면 된다.

    @PostMapping("/user") //사용자 등록
    public void saveUser(@RequestBody UserCreateRequest request){
        users.add(new User(request.getName(), request.getAge()));
    }

매개변수로 Body 객체를 받고 그 객체의 getter 메서드를 사용하여 name과 age를 반환하고 그 값을 User 클래스의 매개변수 생성자에 대입한다.
그러면 User 인스턴스에 name,age 초기화 되고 그 인스턴스를 User 타입의 리스트 users에 추가(add)하는 것이다.

여기까지 완성했으면 postman을 사용하여 잘 작동하나 확인해보자.

post 방식으로 할 경우에는 Params이 아닌 Body를 선택하고 raw -> JSON을 선택하여

{
"Key1":Value1,
"Key2":Value2
}

형식으로 데이터를 전달해야 한다.
200 OK가 출력된 것을 보니 잘 작동하는 것을 알 수 있다. void 메서드이기 때문에 반환값을 별도로 출력되지 않는다.

2. 유저 조회 API

유저를 생성하였으니 조회를 하는 기능을 만들어야 한다.
유저 생성과 동일하게 유저 조회 API도 설계를 해보자.
우선 데이터를 얻어야 하기 때문에 Get Method를 사용하고 path는 /user, 쿼리의 경우 여기서는 전체 데이터를 조회할 목적이기 때문에 사용하지 않겠다.
결과는 반환해야 하며 id, name, age 3가지를 반환한다.

여기서 id란 유저에게 부여되는 고유 번호로, 만약 이름과 나이가 같아도 id가 다르면 다른 유저로 구별할 수 있다.

1) getUser 생성

UserController를 이미 만들어놓았기 때문에 메서드만 추가해주면 된다.

@GetMapping("/user")
public void getUser(){}

우선 고려해야 할 점은 id 값은 users 리스트에서 반환한 순서대로 부여해야 한다. name,user도 id값과 같이 반환되어야 하기 때문에 반환된 데이터를 받을 수 있는 객체가 필요하다.

2) UserResponse 생성

dto 패키지에 response 패키지를 생성한 후 UserResponse 클래스를 만든다.

package com.group.libraryapp.dto.response;

public class UserResponse {
    private long id;
    private String name;
    private Integer age;

    public UserResponse(long id, String name, Integer age) {
        this.id = id;
        this.name = user.getName();
        this.age = user.getAge();
    }

    public long getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public Integer getAge() {
        return age;
    }
}

UserResponse 클래스의 인스턴스가 id,name,age를 저장하여 UserResponse 타입의 리스트에 객체를 저장하고 그 리스트를 반환하는 기능을 getUser 메서드에 만들 것이다.

간단하게 다시 정리해보자면

  • 데이터 저장을 post 방식을 통해 User타입의 리스트에 한다
  • 데이터를 조회하려면 User 타입의 리스트에서 객체를 가지고 온다
  • 그 객체에서 name,age 값을 추출한다
  • 그리고 그 객체를 반환한 순서에 id를 부여한다
  • 부여한 id, 추출한 name,age 값을 UserResponse 타입의 리스트에 추가한다
  • 그 리스트를 반환하여 데이터를 조회한다

그럼, 코드를 다시 구성해보자.

    @GetMapping("/user")
    public List<UserResponse> getUser(){
        List<UserResponse> responses = new ArrayList<>();
        for(int i = 0; i < users.size(); i++){
            responses.add(new UserResponse(i + 1, users.get(i).getName(), users.get(i).getAge()));
        }
        return responses;
    }

코드를 하나하나 분석해보자.
우선, UserResponse 타입의 리스트를 반환해야 하기 때문에 return type으로 List을 설정하였다.
UserResponse 타입의 리스트 responses를 생성하고 반복문을 사용하여 id 값은 1부터 부여, name과 age는 users 리스트에서 인덱스 순서대로 추출한다.
id,name,age 값을 UserResponse 생성자의 매개변수로 입력하여 인스턴스 변수를 초기화하고 그 인스턴스를 UserResponse 타입의 리스트 responses에 추가(add)한다.
마지막으로 그 리스트인 responses를 반환한다.

이제 postman을 사용하여 잘 작동하는지 확인해보자.
post 방식으로 JSON 데이터를 3개를 저장해두었다.
전체 데이터 조회이기 때문에 쿼리 없이 http://localhost:8080/user 를 입력하고 send를 누르면 다음과 같이 id,name,age 값이 JSON 형태로 잘 출력되는 것을 알 수 있다.

getUser 메서드를 좀 더 간결한 코드로 정리해보자.
UserResponse 생성자에서 name,age 매개변수를 User 클래스의 객체로 받아보자.

package com.group.libraryapp.dto.response;

import com.group.libraryapp.domain.user.User;

public class UserResponse {
  private long id;
  private String name;
  private Integer age;

  public UserResponse(long id, User user) {
      this.id = id;
      this.name = user.getName();
      this.age = user.getAge();
  }

  public long getId() {
      return id;
  }
  public String getName() {
      return name;
  }
  public Integer getAge() {
      return age;
  }
}

User 클래스의 객체를 매개변수로 받고 get 메서드를 통해 인스턴스 변수에 대입한다.
그리고 getUser 메서드를 다음과 같이 바꿔준다.

  @GetMapping("/user")
  public List<UserResponse> getUser(){
      List<UserResponse> responses = new ArrayList<>();
      for(int i = 0; i < users.size(); i++){
          responses.add(new UserResponse(i + 1, users.get(i)));
      }
      return responses;
  }

기존의 users.get(i).getName/Age 대신 users 리스트에 있는 User 객체를 가져와 매개변수로 사용하면 된다.


여기까지 유저 생성 및 조회 API를 작성하는 방법이고 한 가지 큰 문제점이 있는데 서버를 다시 시작하면 데이터가 초기화 된다는 것이다. 유저 정보가 메모리에서만 유지되고 있어 서버를 재실행하면 저장한 사용자 정보가 사라지기 때문이다.

이 문제점을 해결하기 위해 데이터 베이스를 사용해야 한다

                                                               

0개의 댓글