[Spring Framework] - 예제

김수빈·2022년 6월 28일
0

Spring

목록 보기
8/8

Spring Framework 이용한 실습

User 라는 클래스를 이용한 간단한 실습 진행하였다.

1. Spring Boot 프로젝트 생성

https://start.spring.io 에서 프로젝트를 Generate 하였다.

내장 WAS를 사용하기 위해 Spring Web, Lombok 어노테이션 사용을 위해 Lombok Dependency를 추가했다.


2. 파일 디렉토리

기능 별로 디렉토리를 생성했다. 후에 주문 같은 새로운 패키지가 필요하면 추가하면 된다.

디렉토리 생성은 dto, controller 등으로 나누어 만들어도 된다.

3. Entity

package com.example.demo.user.entity;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class User {
    private long userId;

    private long id;

    private String password;

    private String name;

    private String email;
}

데이터베이스의 PK 로 사용할 userId, 그 외 데이터 들을 필드로 추가했다.
Lombok의 getter, setter 를 사용하여 직접 작성할 필요가 없다.
파라미터가 없는 생성자, 파라미터가 있는 생성자를 자동으로 만들어준다.

4. Service

package com.example.demo.user.service;

import com.example.demo.user.entity.User;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class UserService {
    public User createUser(User user) {
        // TODO business logic
        User createdUser = user;
        return createdUser;
    }

    public User updateUser(User user) {
        // TODO business logic
        User updatedUser = user;
        return updatedUser;
    }

    public User findUser(long userId) {
        // TODO business logic

        User user =
                new User(userId, "sampleId1", "samplePassword1", "유저1","sample@naver.com");
        return user;
    }

    public List<User> findUsers() {
        // TODO business logic
        List<User> users = List.of(
                new User(1, "sampleId1", "samplePassword1", "유저1","sample1@naver.com"),
                new User(2, "sampleId2", "samplePassword2", "유저2","sample2@naver.com")
        );
        return users;
    }

    public void deleteUser(long userId) {
        // TODO business logic
    }
}

데이터베이스에 연결하지 않았기 때문에, Service 의 비즈니스 로직은 아직 없다. 간단한 CRUD 정도의 기능을 수행할 메소드들을 만들어 두었다.

5. DTO

DTO(Data Transfer Object)
DTO를 사용하는 이유는 계층 간 데이터 교환을 하기 위함이다. HashMap 같은 key-value 자료구조를 이용하여도 되지만, 그렇게 되면 필드가 조금만 많아져도 과도한 put 메소드가 사용된다.

또한 DTO를 사용하면 유효성 검사를 Controller 의 비즈니스 로직에서 하지 않아도 된다.

따라서 DTO를 사용하면 유지 보수가 좀더 수월해진다.

DTO도 프로젝트 규모가 커지면 RequestDTO, ResponseDTO 등 기능 별로 추가되어야 할 DTO가 너무 많아진다. 이 때 사용하는 방법이 DTO 안에 inner static class를 생성하는 것이다.

package com.example.demo.user.dto;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

public class UserDTO {

    @Getter
    @Setter
    @NoArgsConstructor
    @AllArgsConstructor
    public static class UserPostDTO{
        private String id;

        private String password;

        private String name;

        private String phone;
    }

    @Getter
    @Setter
    @NoArgsConstructor
    @AllArgsConstructor
    public static class UserPatchDTO{
        private long userId;

        private String id;

        private String password;

        private String name;

        private String phone;
    }

    @Getter
    @Setter
    @NoArgsConstructor
    @AllArgsConstructor
    public static class UserResponseDTO{
        private long userId;

        private String id;

        private String password;

        private String name;

        private String phone;
    }
}

유저 생성에 사용될 UserPostDTO, 유저 업데이트에 사용될 UserPatchDTO, Web에 데이터를 전송할 때 사용할 UserReponseDTO 를 만들었다.

UserReponseDTO를 사용하는 이유는, DTO를 웹 상으로 전송할 때 필요한 데이터들만 보내기 위함이다. 불필요한 데이터를 보내는 상황이 없어진다.

6. Controller

위에서 구현한 Service와 DTO를 이용할 Controller 를 구현해야 한다

package com.example.demo.user.controller;

import com.example.demo.user.dto.UserDto;
import com.example.demo.user.dto.UserDto.UserResponseDto;
import com.example.demo.user.dto.UserDto.UserPatchDto;
import com.example.demo.user.entity.User;
import com.example.demo.user.mapper.UserMapper;
import com.example.demo.user.service.UserService;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import javax.validation.constraints.Positive;
import java.util.List;
import java.util.stream.Collectors;

@RestController
@RequestMapping("v1/users")
@Validated
public class UserController {
    private final UserService usersService;
    private final UserMapper mapper;

    public UserController2(UserService usersService, UserMapper mapper) {
        this.usersService = usersService;
        this.mapper = mapper;
    }

    @PostMapping
    public ResponseEntity postUser(@RequestBody UserDto.UserPostDto userDto) {
        User user = mapper.userPostDtoToUser1(userDto);

        User response = usersService.createUser(user);

        return new ResponseEntity<>(mapper.userToUserResponseDto1(response),
                HttpStatus.CREATED);
    }

    @PatchMapping("/{user-id}")
    public ResponseEntity patchUser(
            @PathVariable("user-id") @Positive long usersId,
            @Valid @RequestBody UserPatchDto usersPatchDto) {
        usersPatchDto.setUserId(usersId);

        User response =
                usersService.updateUser(mapper.userPatchDtoToUser1(usersPatchDto));

        return new ResponseEntity<>(mapper.userToUserResponseDto1(response),
                HttpStatus.OK);
    }

    @GetMapping("/{user-id}")
    public ResponseEntity getUser(
            @PathVariable("user-id") @Positive long usersId) {
        User response = usersService.findUser(usersId);
        return new ResponseEntity<>(mapper.userToUserResponseDto(response), HttpStatus.OK);
    }

    @GetMapping
    public ResponseEntity getUsers() {
        List<User> users = usersService.findUsers();
        List<UserResponseDto> response =
                users.stream()
                        .map(user -> mapper.userToUserResponseDto1(user))
                        .collect(Collectors.toList());
        return new ResponseEntity<>(response, HttpStatus.OK);
    }

    @DeleteMapping("/{user-id}")
    public ResponseEntity deleteUser(
            @PathVariable("user-id") @Positive long usersId) {
        System.out.println("# delete user");
        usersService.deleteUser(usersId);

        return new ResponseEntity<>(HttpStatus.NO_CONTENT);
    }
}

7. Mapper

package com.example.demo.user.mapper;

import com.example.demo.user.dto.UserPatchDto;
import com.example.demo.user.dto.UserPostDto;
import com.example.demo.user.dto.UserResponseDto;
import com.example.demo.user.entity.User;
import org.mapstruct.Mapper;

@Mapper(componentModel = "spring")
public interface UserMapper {
    User userPostDtoToUser(UserPostDto userPostDto);
    User userPatchDtoToUser(UserPatchDto userPatchDto);
    UserResponseDto userToUserResponseDto(User user);
}

0개의 댓글