본문 바로가기
개발/Spring

Springboot + Mysql + JPA 로 간단한 프로젝트 2

by ujin2021 2021. 7. 16.

* 첫 스프링부트 프로젝트라서 일단은 실행되게끔 만들고 있기때문에 좋은 로직이 아닐 수 있습니당!

* 차차 공부하면서 발전시켜나갈 예정입니다

* 예외처리, security 적용 x

 

[환경설정]

2021.07.15 - [개발/Spring] - Springboot + Mysql + JPA 로 간단한 프로젝트 1

 

Springboot + Mysql + JPA 로 간단한 프로젝트 1

인프런에서 김영한님의 스프링 입문, 핵심원리, MVC1 강의까지 듣고 약간의 자신감이 생겨 API Server를 만들어보기로 했다. 강의에서는 H2 DB를 한번 사용해봤고, JPA와 DB연결에 대해서는 자세히 배

ujin-dev.tistory.com

 

회원가입 구현하기

  1. UserRepository 
// UserRepository.java

package com.youjin.domain.user;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import java.util.Optional;

@Repository
public interface UserRepository extends JpaRepository<User, Long> {
    Optional<User> findByUserId(String userId);
}
  • JpaRepository<User, Long> => User은 저장할 객체가 User이고 (이전에 만들어 놓은 User.java), pk가 Long type이므로 Long으로 해준다
  • JpaRepository를 extends 하면 JpaRepository에 있는 findById, findAll 등을 사용할 수 있다
  • 나머지 커스텀 해야하는 것은 저렇게 interface안에 넣어주면 된다. 현재 User 테이블의 속성은 (seq, user_id, password, user_name)이고, seq이 pk이다. 회원가입 후 로그인할 때 user_id, password를 받아 회원을 체크해야 하므로 findByUserId를 만들어 주었다
  • findBy ~ 형식으로 만들어주면 파라미터로 넣어주는 값으로 User객체를 찾을 수 있다

2. UserRequest

// UserRequest.java

package com.youjin.payload.request;

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

@NoArgsConstructor
@AllArgsConstructor
@Getter
public final class UserRequest {
    private String userId;
    private String password;
    private String userName;
}
  • 이전에 만든 User.java 에는 db가 자동으로 생성해주는 seq 값까지 들어있다. 우리가 회원가입시에 필요한 attribute만 뽑아서 UserRequest 객체로 만든다

3. UserController - signup 추가

// UserController.java

package com.youjin.controller;

import com.youjin.payload.request.UserRequest;
import com.youjin.service.UserService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@Slf4j
@RestController
@RequestMapping("user")
@RequiredArgsConstructor
public class UserController {

    private final UserService userService;

    @PostMapping("/signup")
    public ResponseEntity signup(@RequestBody UserRequest request) {
        log.info("userId = {}, password = {}, userName = {}", request.getUserId(), request.getPassword(), request.getUserName());
        if(userService.signup(request).equals("Success")) {
            return new ResponseEntity(HttpStatus.CREATED);
        }
        return new ResponseEntity(HttpStatus.BAD_REQUEST);
    }
}
  • class level에 붙여준 @RequestMapping("user") 는 중복되는 url 이다
  • signup method에 @PostMapping("/signup")으로 적어놨는데 그러면 class의 RequestMapping에 적어놓은 url과 method에 적어놓은 url을 합하게 된다 => 결국 localhost:8080/user/signup 으로 post를 보내면 signup 메서드가 실행되는 것이다
  • 회원가입시에 userId, password, userName 을 json 형식으로 받게 된다
  • {
        "userId" : "ujin", 
        "password" : "1234", 
        "userName" : "lee"
    }
  • @RequestBody는 json 객체로 넘어오는 것을 받아준다
  • 아까 만들어준 UserRequest 객체에 post로 받은 값이 저장된다
  • 값을 꺼낼때는 request.getUserId(), .. 로 해주면 된다! (UserRequest에 @Getter을 붙여줬으니까!)
  • DB에 값을 저장하는 것은 UserService에게 넘긴다

4. UserService

// UserService.java

package com.youjin.service;

import com.youjin.domain.user.User;
import com.youjin.domain.user.UserRepository;
import com.youjin.payload.request.UserRequest;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.Optional;


@Service
@RequiredArgsConstructor
@Slf4j
public class UserService{

    private final UserRepository userRepository;

    public String signup(UserRequest request){
        userRepository.save(User.builder()
                .userId(request.getUserId())
                .password(request.getPassword())
                .userName(request.getUserName())
                .build());
        return "Success";
    }
}
  • UserRequest 객체를 받는다
  • userRepository.save도 아까 extends한 JpaRepository에서 제공해준다
  • 아직 예외처리를 넣지 않았다. 그냥 항상 성공한다 치고 "Success"를 반환해주었다
  • 그러면 UserController에서 "Success"를 받고, HttpStatus.Create(201)을 반환해준다 

 

로그인

  • 로직
    • userId, password를 post로 받는다
    • User table에서 userId가 일치하는 회원의 password를 가져온다
    • db에서 가져온 password와 post로 받은 password를 비교한다
    • 같으면 200 반환

1. UserController에 login method 추가 (회원가입때 만들었던 UserController class안에 method 추가한 것 입니다)

@PostMapping("/login")
public ResponseEntity login(@RequestBody UserRequest request) {
	log.info("userId = {}, password = {}", request.getUserId(), request.getPassword());
	if(userService.login(request.getUserId(), request.getPassword()).equals("Success")) {
		return new ResponseEntity(HttpStatus.OK);
	}
	return new ResponseEntity(HttpStatus.BAD_REQUEST);
}
  • 회원가입때와 마찬가지로 UserRequest객체에 body 정보를 저장한다 (이때 UserRequest 객체의 userName은 그냥 null이 됨)
  • login처리는 userService에게 넘긴다

2. UserService (회원가입때 만들었던 UserService class안에 method 추가)

public String login(String userId, String password) {
	Optional<User> user = userRepository.findByUserId(userId);
	log.info("db password = {}, input password = {}", user.get().getPassword(), password);
	if(user.get().getPassword().equals(password)) {
		return "Success";
	}
	return "Failed";
}
  • 아까 UserRepository에서 선언해두었던 findByUserId를 사용한다
  • userId로 찾는 user가 존재할 수도 있고 존재하지 않을 수도 있기때문에 Optional을 사용한다
  • 만약 존재하면 user.get()으로 데이터를 꺼낸다
  • password를 .equals를 사용해 비교한다
  • 같으면 "Success" 반환
  • UserController에서 "Success"를 받으면 200을 반환한다

DB에도 확인해보면 데이터가 잘 들어간다!