본문 바로가기
기록해보기

유저 생성 API 개발

by titlejjk 2023. 6. 1.

이번에는 도서관리 애플리케이션의 API를 개발할 것인데 이것을 만들려고 하는 애플리케이션의 요구사항을 먼저 살펴보겠다.

 

도서관리 애플리케이션의 요구사항👉

사용자

  • 도서관의 사용자를 등록할 수 있다.(이름 필수, 나이 선택)
  • 도서관 사용자의 목록을 볼 수 있다.
  • 도서관 사용자 이름을 업데이트 할 수 있다.
  • 도서관 사용자를 삭제할 수 있다.

  • 도서관에 책을 등록 및 삭제할 수 있다.
  • 사용자가 책을 빌릴 수 있다.
    다른 사람이 그 책을 진작 빌렸다면 빌릴 수 없다.
  • 사용자가 책을 반납할 수 있다.

사용자와 책 부분을 나누어서 작업을 할 것이다.

 

우선 강의에 따라 먼저 미리만들어진 셋팅했던 서버에 넣어져 있다. 먼저 그 화면에 접근해 보겠다.

먼저 서버를 동작시켜주고 서버가 동작하고 있는 상태에서 

http://localhost:8080/v1/index.html 로 입력해보겠다.

오류발생..

당황하지말고..

해결했다. 주소입력이 잘못되었었다. 오타주의!!

이제 준비된 웹 UI도있으니

도서관 사용자를 등록할 수 있다.(이름 필수, 나이 선택)

가장 먼저 API를 설계해야 한다.

지금 까지는 마음대로 API를 만들었지만 보통의 API는 일종의 약속이기 때문에 약속에 맞춰서 API를 같이 의논하고 설계하고 확정하는 과정을 거쳐야 한다.

이번 경우에는 도서관리 웹 UI가 만들어져있기에 여기서 사용할 기능들을 채워 넣어야 한다.

 

먼저 사용자를 등록하기 위한 API 명세는 다음과 같다.

  • HTTP Method : POST
  • HTTP Path : /user
  • HTTP Body (JSON)
{
	"name" : String (null 불가능)
    "age" : Integer
}
  • 결과 반환 X (HTTP상태 200 OK 이면 충분하다)

등록하는 거이기에 POST 사용자관련이기에 Path는 /user, POST이기에 Body 는 JSON으로 받으며 name 는 필수이기에 null은 불가능하게 결과는 성공하는 것으로만 하기로 API명세를 정했다.

이렇게 정해놓고 API를 만들어 보겠다.

먼저 아래와 같이 user package를 먼저 만들어주고

그 안에 UserController Class를 만들어주었다.

전에 만들었던 calculator 에다가 같이 만들 수도 있지만 사용자 관련 API는 사용자 Controller에서 책 관련 API는 책 Controller에서 이렇게 역할별로 모아두는 것이 조금 더 깔끔하기에 새로만들어서 사용하는 것이 좋다.

UserController를 새로 만들었기에 여기를 API 처음 진입지점으로 삼기위해 먼저 @RestController를 어노테이션해준다.

그 다음 POST API로 작성할 것이기에 @PostMapping 에 + ("/user")로 작성해준다.

이렇게 되면 Post /user를 했을 때 이 어노테이션 아래에 있는 함수가 호출이 된다.

함수 생성은 아무것도 반환 안하기로 했기에 public void 로 해주고 함수이름은 saveUser로 작성해주겠다.

package com.group.libraryapp.user;

import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class UserController {

    @PostMapping("/user") //POST /user
    public void saveUser(){
        
    }
}

이렇게 작성한 후에는 위에 작성한 Body를 객체로 표현할 DTO가 필요하기에 dto package 안에 request package를 만들어 주겠다.

이제  이 안에 UserCreateRequest 라는 Class를 만들어 dto를 만든다.

UserCreateRequest 같은 경우에는 문자열 name, 숫자 age의 두가 필드가 필요하다.

package com.group.dto.user.request;

public class UserCreateRequest {

    private String name;
    private Integer age; //여기가 Integer인 경우는 null을 표현하게 할 수 있다.
}

여기서 age 앞에 데이터타입이 Integer인 경우 그냥 int 같은 경우에는 null을 표현할 수 없어 Integer로 만들어주었다.

이름 같은 경우에는 필수지만 나이는 선택이기에 이렇게 설정했다.

그 다음에 getter 를 만들어준다.

package com.group.dto.user.request;

public class UserCreateRequest {

    private String name;
    private Integer age; //여기가 Integer인 경우는 null을 표현하게 할 수 있다.

    public String getName() {
        return name;
    }

    public Integer getAge() {
        return age;
    }
}

이렇게 생성한 후에 POST API에서 들어온 HTTP Body를 위에 만들었던 Class로 변환하기 위해서는 @RequestBody라는 어노테이션이 필요하기에 @RequestBody UserCreatRequest를 입력해준다.

package com.group.libraryapp.user;

import com.group.dto.user.request.UserCreateRequest;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class UserController {

    @PostMapping("/user") //POST /user
    public void saveUser(@RequestBody UserCreateRequest request){

    }
}

여기까지가 전체적으로 API의 구조를 잡았다.

이제 실제로 유저가 저장되도록 구현해 보겠다.

User라는 정보를 저장하기위해 user라는 객체를 만들어 저장할 건데 이 객체를 com.group.libraryapp에 dto package와 같은 위치에 domain이라는 package를 그리고 그 아래 User라는 Class를 하나 더 만들어 준다.

위에 미리 만들었던 saveUser 사용되서 user가 만들어지면 실제 list에 저장을 할 것이다.

이 User 같은 경우에는 이름과 나이를 가지고 있고 생성자도 같이 만들어 준다. 이 때 name같은 경우는 null이 들어올수 없기에

name이 null이거나 name이 비어있다면 IllegalArgumentException을 throw해줘서 String.fomat을 이용해

"잘못된 name(%s)이 들어왔습니다" 라는 예외처리까지 작성해보겠다.

package com.group.libraryapp.domain;

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("잘못된 name(%s)이 들어왔습니다", name));
        }
        this.name = name;
        this.age = age;
    }
}

이렇게 입력해주면 API를 통해 들어온 name 값이 null이거나 비어있으면 생성 및 저장이 안된다.

그리고 예외를 던지는 과정에서 어떤 잘못된 값이 들어왔는지 알려주면 좋기에 자바에 있는 String.format을 사용해서 예외에 메세지로 담을 수 있게끔 처리했다.

 

이제 실제 방금 작성한 User Class에 저장되게 해보겠다.

UserController Class 안에서 코드를 작성한다.

package com.group.libraryapp.controller.user;

import com.group.libraryapp.dto.user.request.UserCreateRequest;
import com.group.libraryapp.domain.user.User;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.List;

@RestController
public class UserController {

    private final List<User> users = new ArrayList<>();
    
    @PostMapping("/user") //POST /user
    public void saveUser(@RequestBody UserCreateRequest request){

    }
}

이렇게 만들면 saveUser 라는 함수가 호출 되면 즉 POST/user가 호출되면 이 user에 새로운 user를 추가할 건데, 이 때 user를 만들 때는 API를 통해 들어온 이름과 나이를 집어 넣어주도록한다.

package com.group.libraryapp.controller.user;

import com.group.libraryapp.dto.user.request.UserCreateRequest;
import com.group.libraryapp.domain.user.User;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.List;

@RestController
public class UserController {

    private final List<User> users = new ArrayList<>();

    @PostMapping("/user") //POST /user
    public void saveUser(@RequestBody UserCreateRequest request){
        users.add(new User(request.getName(), request.getAge()));
        //user에 새로운 user를 추가할 건데, 이 때 user를 만들 때는 
        //API를 통해 들어온 이름(request.getName())과 
        //나이(request.getAge())를 집어 넣어주도록한다.
    }
}

전체적으로 보았을 때 POST/user가 호출되면 아래 함수가 실행되고 이 때 JSON형식으로 HTTP Body

UserCreateRequest에 name과 age 에 전체적인 값이 mapping되고  새로만들어진 객체는 List<User> users에 저장되고 예외없이 정상적으로 함수가 마무리 된다면 200ok를 반납하게 될 것이다.(말이 어렵네;)

다음에 user를 반환하는 user정보가 잘 저장되었는지 확인하는 GET API를 WEB UI로 통해 확인하는 것을 공부해 보겠다.

댓글