공부/Spring

RESTful Web Service 개발 - User Service API 구현_1

데부한 2023. 1. 16. 00:06
반응형

 

 

Spring Boot를 이용한 RESTful Web Services 개발

User Service API 구현

User 도메인 클래스 생성

  • User.java 생성 (com.example.restfulwebservice)

@Data
@AllArgsConstructor
public class User {
    private Integer id;
    private String name;
    //private Date joinDate; Date 클래스 미사용
    private LocalDateTime joinDate;
}

강의에선 joinDate의 타입을 Date로 지정하였지만 나는 LocalDateTime으로 지정했다.

 

  • UserDaoService.java 생성
    • Dao는 DB와 관련된 코드, Service는 비즈니스 로직을 작성하는데 이 예제에선 딱히 구분이 필요 없으므로 합침.

 

먼저 클래스 맨 위에 @Service 어노테이션을 붙이고, 클래스에 static 변수 두 개를 생성한다.

@Service
public class UserDaoService {
    private static List<User> users = new ArrayList<>();
    private static int userCount = 0;
}

users는 말 그대로 user 정보를 담는 List이다. userCount는 user의 정보를 구별할 수 있는 id 값이다.

DB에 연동 안하고 간단하게 사용하기 위해 user를 생성해 static 블록으로 메모리에 올린다.

이러면 클래스가 로딩 된 후 static 블록 안에 있는 코드들이 실행되어 users에 3개의 user 정보가 담기게 된다.

static {
    users.add(new User( ++userCount, "길동", LocalDateTime.now()));
    users.add(new User(++userCount, "영미", LocalDateTime.now()));
    users.add(new User(++userCount, "철수", LocalDateTime.now()));
}

 

그 외 전체 사용자 조회, 사용자 추가, 사용자 조회 비즈니스 로직을 작성한다.

// 전체 사용자 조회
public List<User> findAll() {
    return users;
}

// 사용자 추가
public User save(User user) {
    // user에 id 값이 없으면
    if(user.getId() == null) {
        user.setId(++userCount);
    }

    users.add(user);
    return user;
}

// 사용자 조회
public User findOne(int id) {
    for( User user : users ) {
        if(user.getId() == id) return user;
    }
    // 없으면 null 반환
    return null;
}

 

 

사용자 목록 조회를 위한 API 구현 - GET HTTP Method

  • UserController.java 생성

REST를 이용하기 때문에 클래스 이름 위에 @RestController 어노테이션을 붙여준다.

@RestController
public class UserController {}

그리고 위에서 생성한 UserDaoService를 Controller에서 사용할 수 있도록 가져와야하는데 'new' 연산자를 사용해서 직접적으로 가져오는 것이 아니라, 스프링이 관리할 수 있는 인스턴스(Bean) 형태로 가져와야한다. 이를 의존성 주입이라고 하는데 왜 service 인스턴스를 스프링에서 관리하도록 해야할까? 이유는 스프링 컨테이너에 등록되어 있는 Bean은 프로그램 실행 도중 사용자나 개발자가 함부로 변경할 수 없기 때문에 일관성 있는 인스턴스를 사용할 수 있기 때문이다.

스프링 컨테이너에 등록되어 있는 Bean(인스턴스)을 사용하기 위해서는 컨테이너에 등록된 Bean의 참조값을 가져와서 사용하면 된다. 여러가지 방법이 있는데 이번에는 생성자를 통한 의존성 주입 방법을 사용한다.

private UserDaoService service;

// 생성자를 통한 의존성 주입
public UserController(UserDaoService service) {
    this.service = service;
}

 

마지막으로 전체 사용자 조회, 사용자 조회를 위한 메서드를 생성한다.

사용자 조회의 경우 @PathVariable을 사용하였다. 원래 주소 창에 입력되는 id의 타입은 String이나 똑똑한 스프링이 매개변수 타입을 int라고 지정하면 알아서 형변환하여 들어온다.

 // 사용자 전체 조회
@GetMapping("/users")
public List<User> retrieveAllUsers() {
    return service.findAll();
}

// 주소에 입력된 id는 서버에 넘어올 때 String 타입으로 넘어오지만 PathVariable에 int로 선언 시 형변환 되어서 넘어온다.
@GetMapping("/users/{id}")
public User retrieveUser(@PathVariable int id) {
    return service.findOne(id);
}

 

  • 서버 실행 후 크롬에서 확인

전체 사용자 조회 및 사용자(id) 조회

전체 사용자 조회, 사용자 조회, 사용자 조회(id가 없는 경우)

 

  • 추가

위 retrieveUser() 메서드에서 String으로 타입으로 입력된 값을 int로 자동 형변환 시켜준다고 말했다. 그럼 만약 주소 창에 숫자가 아닌 다른 값이 들어가면 어떻게 될까? 숫자 말고 한글을 넣어보자.

뭘 어떻게 돼. 에러가 발생한다!

400 에러가 발생했다. 개발자가 아니더라도 이런 페이지를 반기는 사람은 없다. Exception 처리를 해보자.

위에 에러 내용을 보면 'NumberFormatException' 이라는 에러가 발생한 걸 확인할 수 있다.

컨트롤러에서 해당 에러를 처리해보자.

@ExceptionHandler(NumberFormatException.class)
public String castIdException() {
    return "잘못된 id 값을 입력하였습니다. 숫자로만 입력해주세요.";
}

@ExceptionHandler 어노테이션이 붙은 컨트롤러 클래스가 존재하면 해당 에러 발생 시 이 메서드가 처리한다. @ExceptionHandler의 괄호 안에는 처리하고 싶은 Exception 클래스를 기재해주면 된다.

서버 재실행 후 잘못된 값을 입력해보자.

허접하지만 그래도 에러 메시지가 보이는 화면보단 100배 낫다!

 

 

사용자 등록을 위한 API 구현 - POST HTTP Method

  • UserController.java 메서드 추가
// 사용자 추가
@PostMapping("/users")
public void createUser(@RequestBody User user) {
    User savedUser = service.save(user);
}

@RequestBody 어노테이션을 사용하면 http에 담긴 데이터를 자바 객체로 전달받을 수 있다.

  • 서버 재실행 후 포스트맨 실행

포스트맨에서 HTTP Method를 POST로 설정 후 Body에 JSON 데이터를 추가하고 send한다.

해당 메서드의 리턴 값이 void라 아무것도 표시되지 않지만 HTTP Status 코드는 200 OK가 떴다.

만약 이 과정에서 500 에러가 발생한다면 User 클래스에 @NoArgsConstructor를 추가해주면 된다.

 

더 확실하게 확인하기 위해 GET Method로 전체 사용자 조회를 해보자. (나는 여러 번 해보느라 New User가 많다.)

 

 

 


- 출처 : 인프런 Spring Boot를 이용한 RESTful Web Services 개발 강의

반응형