2023.08.01

서수정·2023년 8월 1일
0

spring

목록 보기
6/7
post-thumbnail

연습

site2
로그인, 회원가입

페이지 화면을 만든다. html

- 회원가입페이지

id, password, 회원가입버튼

  • join.html
<!DOCTYPE html>
<html xmlns:th="http://thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <h1>회원가입</h1>
    <div>
        <span>아이디</span>
        <input type="id">
    </div>
    <div>
        <span>비밀번호</span>
        <input type="password">
    </div>
    <div>
        <button>회원가입</button>
    </div>
</body>
</html>

- 로그인 페이지

id, password, 로그인 버튼

  • login.html
<!DOCTYPE html>
<html xmlns:th="http://thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <h1>로그인</h1>
<div >
    <div>
        <span>아이디</span>
        <input type="id">
    </div>
    <div>
        <span>비밀번호</span>
        <input type="password">
    </div>
    <div>
        <button>로그인</button>
    </div>
</div>
</body>
</html>

Controller와 html 연결

domain / auth / AuthController.java만든다.

  • AuthController.java
@Controller
public class AuthController {
    
    @GetMapping("/login")
    public ModelAndView loginPage(){
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("login");
        return modelAndView;
    }

    @GetMapping("/join")
    public ModelAndView joinPage(){
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("join");
        return modelAndView;
    }


}

Controller와 ControllerApiV1

AuthController : 화면을 내보내고
AuthControllerApiV1 : HTTP 상태코드를 보낸다.
ResponseEntity에 담아서 보낸다.

  • AuthControllerApiV1.java

아이디랑 비밀번호를 받아야한다. -> 받을 dto만들기

entity는 컨트롤러까지 못 간다 서비스까지 밖에 못 감.
서비스에서 entity 와 dto가 교환된다.

-> dto 만들기

  • JoinUserDTO.java(치킨)
@AllArgsConstructor
@NoArgsConstructor
@Getter
public class JoinUserDTO {
    private String id;
    private String password;
}
  • ReqJoinDTO.java(봉지)

JoinUserDTO(치킨)를 담는다.

@AllArgsConstructor
@NoArgsConstructor
@Getter
public class ReqJoinDTO {
    private JoinUserDTO joinUserDTO;
}
  • AuthControllerApiV1.java

: 로그인도 서버에 데이터 주는거라서 postmapping이다.


  • postman으로 테스트

  • 콘솔창

- Service만들기

  • AuthServiceApiV1.java
@Service
@Transactional(readOnly = true)
public class AuthServiceApiV1 {
 
    @Autowired
    private UserRepository userRepository;
    
    public ResponseEntity<?> join(ReqJoinDTO reqJoinDTO){

        UserEntity userEntity = new UserEntity(null,reqJoinDTO.getJoinUserDTO().getId(),reqJoinDTO.getJoinUserDTO().getPassword());

        // insert into user values(...);
        userRepository.save(userEntity);

        return new ResponseEntity<>(
            "회원가입에 성공했습니다.",
            HttpStatus.OK
        );
    }
}

@Transactional(readOnly = true)을 메서드에 적용하면 해당 메서드에서는 데이터베이스의 읽기 작업만 수행하고, 데이터를 변경하는 쓰기 작업은 허용되지 않음. 이렇게 하면 성능을 향상시킬 수 있으며, 데이터베이스의 읽기 작업에 대한 잠금을 줄여 다른 트랜잭션이 동시에 읽기 작업을 수행할 수 있다.

@Transactional(readOnly = true)은 Java Spring 프레임워크에서 사용되는 어노테이션.
데이터베이스 트랜잭션을 지원하며, 메서드 또는 클래스에 적용하여 해당 메서드 또는 클래스에서 데이터베이스 작업을 수행할 때 읽기 전용(read-only) 트랜잭션을 설정하는 데 사용.

트랜잭션은 데이터베이스 작업의 단위를 나타내며, 하나 이상의 작업이 모두 성공적으로 완료되거나 실패하면 모든 작업이 롤백되도록 보장. 데이터베이스 작업에 대한 일관성과 무결성을 보장할 수 있다.


  • AuthControllerApiV1.java
@RestController // @RestController안에 @ResponseBody 있어서 생략가능 , Responsebody로 json으로 보내는 컨트롤러 
public class AuthControllerApiV1 {

    @Autowired
    private AuthServiceApiV1 authServiceApiV1;
    
    @PostMapping("/join") // @PostMapping 데이터를 삽입하거나 받는 역할
    public @ResponseBody ResponseEntity<?> join( @RequestBody ReqJoinDTO dto){ // 아이디랑 비밀번호를 받아야한다. -> 받을 dto만들기 /@RequestBody 객체받을때 
        // json데이터를 받을 때 @RequestBody , @RequestBody 사용자 요청을 받고 (원래는 파싱 해야하는데  스프링이 바꿔줌)
        //  @ResponseBody json데이터로 바꿔줌. 서버에 응답해주기위해
        // 서버가 유저에게 보내는게 응답이다.
        // System.out.println(dto.getJoinUserDTO().getId());
        // System.out.println(dto.getJoinUserDTO().getPassword());

        ResponseEntity<?> responseEntity = authServiceApiV1.join(dto);

        return responseEntity;
    }
}

  • test


똑같은 id와 password 보내면 오류 (id가 유니크 이기 때문)

db에 넣기 전에 해당id를 가진 유저가 있는지 찾고, 있으면 이미 사용중인 아이디 입니다. 라는 메세지 보내야한다.

  • AuthServiceApiV1.java


id를 안 넣었을때

  • AuthServiceApiV1.java
    추가해준다.


id 빈 값으로 보낼 때

id에 빈 값으로 보냈는데 회원가입이 가능하므로 막아야한다.

  • AuthServiceApiV1.java
    추가해준다.


화면

  • join.html


아이디를 지정해준다.

회원가입 함수 만들기


자바스크립트로 함수를 만든다.
documen.getElementById로 id가 "id"와 "password"인 요소들을 가져온다. 이걸로 사용자가 입력한 아이디와 패스워드를 가져옴.

if문으로 사용자가 아이디를 입력안하면 경고창 띄우기.

'dto'라는 자바스크립트 객체를 생성한다.
서버로 보낼 회원 가입 정보를 담고있다.

서버와 통신하기 위해 fetch 함수 사용한다.

"/api/v1/auth/join" 경로에 POST 요청을 보내고, headers에는 "Content-Type"을 "application/json"으로 설정하여 데이터가 JSON 형식임을 알려준다.
body에는 위에서 만든 dto 객체를 JSON 문자열로 변환하여 넣어준다.

그 후, 서버에서 받은 응답은 response.text()를 통해 텍스트 형식으로 읽어지며, 이를 다시 then을 통해 result 변수로 받아서 경고창(alert)으로 보여준다.


fetch 함수

fetch는 네트워크를 통해 데이터를 가져오는 작업.

이 용어는 주로 웹 개발에서 사용되며, 클라이언트 측에서 서버로 데이터를 요청하고, 서버는 해당 데이터를 응답하는 과정을 나타냄.

일반적으로 JavaScript에서는 fetch API가 이러한 목적으로 사용됨. fetch 함수는 Promise를 반환하며, 네트워크를 통해 데이터를 가져오기 위해 사용됨.


  • 실행



JoinUserDTO를 ReqJoinDTO에 넣고싶을때


파일로 있던 user를 안에 넣어줬다.

  • join.html


로그인

  • AuthController.java

  • AuthControllerApiV1.java
 @PostMapping("/login")
    public ResponseEntity<?> login (@RequestBody ReqLoginDTO dto, HttpSession session){ // 아이디랑 비밀번호를 받아야한다. -> 받을 dto만들기
  • ReqLoginDTO .java

LoginUserDTO를 ReqLoginDTO에 넣었다.

@AllArgsConstructor
@NoArgsConstructor
@Getter
public class ReqLoginDTO {
    // private LoginUserDTO loginUserDTO;
    
    private User user;

    @AllArgsConstructor
    @NoArgsConstructor
    @Getter
    public static class User{
        private String id; 
        private String password;
    }
}
  • AuthServiceApiV1.java
    public ResponseEntity<?> login (ReqLoginDTO dto, HttpSession session){
        
        // 
        Optional<UserEntity> userEntityOptional = userRepository.findById(dto.getUser().getId());

        // 엔티티가 null이면 아이디를 잘못 입력한 것
        if(userEntityOptional.isEmpty()){
            return new ResponseEntity<>(
                "해당 아이디가 존재하지 않습니다.",
                HttpStatus.BAD_REQUEST
            );
        }
        // 옵셔널에서 유저엔티티 가져오기
        UserEntity userEntity = userEntityOptional.get();

        // 비밀번호 체크해서 다르면 잘못 입력한 것
        if(!userEntity.getPassword().equals(dto.getUser().getPassword())){
            return new ResponseEntity<>(
                "비밀번호가 일치하지 않습니다.",
                HttpStatus.BAD_REQUEST
            );
        }

        // 인증완료. 세션에 유저 정보 입력 
        session.setAttribute("idx", userEntity.getIdx());
        session.setAttribute("id", userEntity.getId());

        // 컨트롤러에게 로그인 성공 객체 보내기
        return new ResponseEntity<>(
            "로그인에 성공하였습니다.",
            HttpStatus.OK
        );
    }
  • authServiceApiV1.java

@RestController안에 @ResponseBody 가 있어서 생략이 가능하다.

  • AuthControllerApiV1.java 전체코드
@RestController // @RestController안에 @ResponseBody 있어서 생략가능 , Responsebody로 json으로 보내는 컨트롤러 
@RequestMapping("/api/v1/auth") // 주소값만 인식 , AuthController 와 분리하기 위해 붙인다.
public class AuthControllerApiV1 {

    @Autowired
    private AuthServiceApiV1 authServiceApiV1;
    
    @PostMapping("/join") // @PostMapping 데이터를 삽입하거나 받는 역할
    public @ResponseBody ResponseEntity<?> join( @RequestBody ReqJoinDTO dto){ // 아이디랑 비밀번호를 받아야한다. -> 받을 dto만들기 /@RequestBody 객체받을때 
        // json데이터를 받을 때 @RequestBody , @RequestBody 사용자 요청을 받고 (원래는 파싱 해야하는데  스프링이 바꿔줌)
        //  @ResponseBody json데이터로 바꿔줌. 서버에 응답해주기위해
        // 서버가 유저에게 보내는게 응답이다.
        // System.out.println(dto.getJoinUserDTO().getId());
        // System.out.println(dto.getJoinUserDTO().getPassword());

        ResponseEntity<?> responseEntity = authServiceApiV1.join(dto);

        return responseEntity;
    }
    
    @PostMapping("/login")
    public ResponseEntity<?> login (@RequestBody ReqLoginDTO dto, HttpSession session){ // 아이디랑 비밀번호를 받아야한다. -> 받을 dto만들기
        // session 해당 유저가 입력한 정보가 들어가있다.

        return authServiceApiV1.login(dto, session);
    }
}
  • login.html

로그인함수 만들기

<script>
    //로그인함수 만들기

    const requestLogin = () => {

        const idInputTag = document.querySelector("#id"); // querySelector 쓰면 조건에 맞는 애들을 더 쉽게 가져올 수 있다. (getElement보다)
        const passwordInputTag = document.querySelector("#password");
        
        if(idInputTag.value == ""){
            alert("아이디를 입력해주세요.")
            return;
        }
        if(passwordInputTag.value == ""){
            alert("비밀번호를 입력해주세요.")
            return;
        }

        const dto = {
            user : {
                id : idInputTag.value,
                password : passwordInputTag.value
            }
        }

         // request
         fetch("/api/v1/auth/login",{
                method : "POST",
                headers : {
                    "Content-Type" : "application/json" // 꼭 입력해야한다.
                },
                body : JSON.stringify(dto) // dto 는 자바스크립트 객체이므로 json으로 바꿔서 보내야한다.
            })

            // response
            .then(response => response.text()) // fetch 리턴값이 프로미스라서 then
            .then(result => {
                alert(result);
            });
    }


</script>

  • 실행


스프링 부트 프로젝트 만들기

프로젝트 화면 html로 만들기
프로젝트 DB 및 테이블 만들기
(엔티티로 만들 사람은 생략)

컨트롤러 만들기 + html연결하기

엔티티 만들기

리파지토리 만들기

서비스 만들기

html에 타임리프 문법으로 데이터 넣기

api컨트롤러 만들기

api 서비스 만들기

fetch로 기능 연결하기

1개의 댓글

comment-user-thumbnail
2023년 8월 1일

글 잘 봤습니다.

답글 달기