[UMC Server] 7주차 - RESTful API

서요이·2022년 11월 19일
0

UMC Server

목록 보기
7/7
  1. 지난번 개발했던 API를 Framework에 맞춰서 Restful API로 개발, API 명세서도 포함
  2. open api를 활용해서 개발해보기 (Server to Server)

Spring Boot Template

  • 고객 - Client
    서버에 요청
  • 키오스크 - Route
    Restful API를 통해 요청 받음
    HTTP method, 주소
  • 점원 - Controller
    Path variable, query string, body 처리
    json 형식으로 response 반환
  • 요리사 - Provider / Service
    Provider - select / Service - insert, update
    값 가공, 트랜잭션
  • 냉장고 - DAO
    실질적 query 작성, 실행
    데이터 결과값

Validation

  • 형식적 validation: 빈 값 길이, 정규표현식 검사 (부적절한 타입 검사)
    Controller에 위치
  • 논리적 validation: 중복 검사
    Provider, Service에 위치

Template 코드 실습

어플리케이션 실행시 에러 발생

java.sql.SQLException: The server time zone value '���ѹα� ǥ�ؽ�' is unrecognized or represents more than one time zone. You must configure either the server or JDBC driver (via the 'serverTimezone' configuration property) to use a more specific time zone value if you want to utilize time zone support.

  • 트러블 슈팅
    [ 문제 원인 ]
    mysql-connector-java 버전 5.1 이후에 나온 버전부터 KST 타임존을 인식하지 못함
    [ 해결 방안 ]
    application.yml 에서 url에 serverTimezone을 UTC로 추가
    jdbc:mysql://ip주소 : port번호/DB스키마명?characterEncoding=UTF-8&serverTimezone=UTC
    [ 참고 자료 ]
    https://devuna.tistory.com/47

Run 성공


1. API를 Framework에 맞춰서 Restful API로 개발

  • Model
    @Getter
    @Setter
    @AllArgsConstructor
    // 회원 정보 조회 요청의 결과
    public class GetUserRes {
        private int userIdx;
        private String name;
        private String email;
        private String password;
    }
    
    @Getter
    @Setter
    @AllArgsConstructor
    @NoArgsConstructor(access = AccessLevel.PROTECTED)
    // 회원 가입을 위해 전달할 데이터 형태
    public class PostUserReq {
        private String email;
        private String password;
        private String name;
    }
    
    @Getter
    @Setter
    @AllArgsConstructor
    // 회원 가입의 결과
    public class PostUserRes {
        private int userIdx;
    }
    
    @Getter
    @Setter
    @AllArgsConstructor
    @NoArgsConstructor(access = AccessLevel.PROTECTED)
    // 로그인을 위해 전달할 데이터 형태
    public class PostLoginReq {
        private String email;
        private String password;
    }
    
    @Getter
    @Setter
    @AllArgsConstructor
    // 로그인의 결과
    public class PostLoginRes {
        private int userIdx;
    }
    
    @Getter
    @Setter
    @AllArgsConstructor
    @NoArgsConstructor(access = AccessLevel.PROTECTED)
    // 회원 정보 수정을 위해 전달할 데이터
    public class PatchUserReq {
        private int userId;
        private String name;
    }
  • User
    package com.umc.board.model;
    
    import lombok.AllArgsConstructor;
    import lombok.Getter;
    import lombok.Setter;
    
    @Getter
    @Setter
    @AllArgsConstructor
    public class User {
        private int userIdx;
        private String email;
        private String password;
        private String name;
    }
  • UserController
    package com.umc.board;
    
    import com.umc.board.model.*;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.*;
    
    import java.util.List;
    
    @RestController
    @RequestMapping("/users")
    public class UserController {
    
        @Autowired
        private final UserService userService;
    
        public UserController(UserService userService) {
            this.userService = userService;
        }
    
        // 회원 가입 API
        @ResponseBody
        @PostMapping("/sign-up")
        public PostUserRes createUser(@RequestBody PostUserReq postUserReq) {
            try {
                return userService.createUser(postUserReq);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    
        // 로그인 API
        @ResponseBody
        @PostMapping("/log-in")
        public PostLoginRes logIn(@RequestBody PostLoginReq postLoginReq) {
            try {
                return userService.logIn(postLoginReq);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    
        // 전체 유저 정보 조회 API
        @ResponseBody
        @GetMapping("")
        public List<GetUserRes> getUsers() {
            try {
                return userService.getUsers();
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    
        // 유저 아이디로 정보 조회 API
        @ResponseBody
        @GetMapping("/{userIdx}")
        public GetUserRes getUser(@PathVariable("userIdx") int userIdx) {
            try {
                return userService.getUser(userIdx);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    
        // 회원 정보 수정 API
        @ResponseBody
        @PatchMapping("/{userIdx}")
        public String modifyUser(@PathVariable("userIdx") int userIdx, @RequestBody User user) {
            try {
                userService.modifyUser(new PatchUserReq(userIdx, user.getName()));
                return "회원 정보가 수정되었습니다.";
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    }
  • UserService
    package com.umc.board;
    
    import lombok.RequiredArgsConstructor;
    import com.umc.board.model.*;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    import javax.transaction.Transactional;
    import java.util.List;
    
    @RequiredArgsConstructor
    @Service
    public class UserService {
        private final UserDao userDao;
    
        public final UserRepository userRepository;
        @Autowired
        public UserService(UserDao userDao) {
            this.userDao = userDao;
        }
    
        // 이메일 중복 확인
        public int checkEmail(String email) throws Exception{
            try {
                return userDao.checkEmail(email);
            } catch (Exception e) {
                throw new Exception("데이터베이스 오류");
            }
        }
    
        // 회원 가입
        public PostUserRes createUser(PostUserReq postUserReq) throws Exception{
            if (checkEmail(postUserReq.getEmail()) == 1) {
                throw new Exception("이미 존재하는 이메일");
            }
            try {
                int userIdx = userDao.createUser(postUserReq);
                return new PostUserRes(userIdx);
            } catch (Exception e) {
                throw new Exception("회원 가입 실패");
            }
        }
    
        public User findById(Long id) {
            return userRepository.findById(id)
                    .orElseThrow(() -> new IllegalArgumentException("존재하지 않는 유저입니다."));
        // 회원 정보 수정
        public void modifyUser(PatchUserReq patchUserReq) throws Exception{
            try {
                int result = userDao.modifyUser(patchUserReq);
                if (result == 0) {
                    throw new Exception("회원정보 수정 실패");
                }
            } catch (Exception e) {
                throw new Exception("데이터베이스 오류");
            }
        }
    
        @Transactional
        public Long save(User user) {
            return userRepository.save(user).getId();
        // 로그인
        public PostLoginRes logIn(PostLoginReq postLoginReq) throws Exception {
            User user = userDao.getPassword(postLoginReq);
            if (postLoginReq.getPassword().equals(user.getPassword())) {
                int userIdx = userDao.getPassword(postLoginReq).getUserIdx();
                return new PostLoginRes(userIdx);
            } else {
                throw new Exception("로그인 실패");
            }
        }
    
        @Transactional
        public Long update(Long id, User user) {
            User currentUser = findById(id);
            currentUser.update(user.getName(), user.getAge(), user.getAddress());
            return id;
        // 전체 유저 정보 조회
        public List<GetUserRes> getUsers() throws Exception{
            try {
                return userDao.getUsers();
            } catch (Exception e) {
                throw new Exception("유저 정보 조회 실패");
            }
        }
    
        @Transactional
        public void delete(Long id) {
            User user = findById(id);
            userRepository.delete(user);
        // 유저 아이디로 정보 조회
        public GetUserRes getUser(int userIdx) throws Exception {
            try {
                return userDao.getUser(userIdx);
            } catch (Exception e) {
                throw new Exception("유저 정보 조회 실패");
            }
        }
    }
  • UserDao
    package com.umc.board;
    
    import com.umc.board.model.*;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.jdbc.core.JdbcTemplate;
    import org.springframework.stereotype.Repository;
    
    import javax.sql.DataSource;
    import java.util.List;
    
    @Repository
    public class UserDao {
    
        private JdbcTemplate jdbcTemplate;
    
        @Autowired
        public void SetDataSource(DataSource dataSource) {
            this.jdbcTemplate = new JdbcTemplate(dataSource);
        }
    
        // 회원 가입
        public int createUser(PostUserReq postUserReq) {
            String createUserQuery = "insert into User (email, password, name) values (?,?,?)";
            Object[] createUserParams = new Object[]{postUserReq.getEmail(), postUserReq.getPassword(), postUserReq.getName()};
            this.jdbcTemplate.update(createUserQuery, createUserParams);
            String lastInsertIdQuery = "select last_insert_id()";
    
            return this.jdbcTemplate.queryForObject(lastInsertIdQuery, int.class);
        }
    
        // 로그인 (비밀번호 값 가져오기)
        public User getPassword(PostLoginReq postLoginReq) {
            String getPasswordQuery = "select userIdx, password, email, name from User where email = ?";
            String getPasswordParams = postLoginReq.getEmail();
    
            return this.jdbcTemplate.queryForObject(getPasswordQuery,
                    (rs, rowNum) -> new User(
                            rs.getInt("userIdx"),
                            rs.getString("email"),
                            rs.getString("password"),
                            rs.getString("name")),
                    getPasswordParams
            );
        }
    
        // 전체 유저 정보 조회
        public List<GetUserRes> getUsers() {
            String getUsersQuery = "select * from User";
    
            return this.jdbcTemplate.query(getUsersQuery,
                    (rs, rowNum) -> new GetUserRes(
                            rs.getInt("userIdx"),
                            rs.getString("name"),
                            rs.getString("email"),
                            rs.getString("password"))
            );
        }
    
        // 유저 아이디로 정보 조회
        public GetUserRes getUser(int userIdx) {
            String getUserQuery = "select * from User where userIdx = ?";
            int getUserParams = userIdx;
    
            return this.jdbcTemplate.queryForObject(getUserQuery,
                    (rs, rowNum) -> new GetUserRes(
                            rs.getInt("userIdx"),
                            rs.getString("name"),
                            rs.getString("email"),
                            rs.getString("password")),
                    getUserParams
            );
        }
    
        // 회원 정보 수정
        public int modifyUser(PatchUserReq patchUserReq) {
            String modifyUserQuery = "update User set name = ? where userIdx = ?";
            Object[] modifyUserParams = new Object[]{patchUserReq.getName(), patchUserReq.getUserIdx()};
    
            return this.jdbcTemplate.update(modifyUserQuery, modifyUserParams);
        }
    
        // 이메일 중복 확인
        public int checkEmail(String email) {
            String checkEmailQuery = "select exist(select email from User where email = ?)";
            String checkEmailParams = email;
    
            return this.jdbcTemplate.queryForObject(checkEmailQuery,
                    int.class,
                    checkEmailParams);
        }
    }
  • API 명세서

0개의 댓글