개인 프로젝트/블로그 만들기

나의 블로그 만들기 프로젝트 (4일차) - 회원가입 처리

coon94 2023. 4. 1. 19:06

오늘 공부할 주제

RestAPI란?

Javascript를 사용하는 이유

 

Github 코드 보기


1. 회원가입 페이지 만들기

 

먼저 index.jsp파일을 복사하여 views 하위의 user폴더에 joinForm.jsp을 생성한다.

 

그리고 w3cschools.com에서 마음에 드는 폼을 가져와서 커스텀 한다.

 

아직 controller를 안만들었기에 VS를 이용하여 간이로 디자인을 확인한다.

 

깔끔하게 레이아웃 설정이 완료되었고, username, password, email 정도만 Client로부터 입력 받으면 될 듯하다.

 

이 때 회원가입 navbar의 href주소를 "/auth/joinForm"으로 설정하여 회원가입 페이지로 이동할 수 있도록 한다.

 

최신화된 css가 있으면 기존에 프로젝트에 추가한 style.css파일에 추가해주면 된다.

 

<div>
    <form>
        <div class="mb-3 mt-3">
            <label for="username" class="form-label"><strong>사용자</strong></label>
            <input type="username" class="form-control" id="username" placeholder="Enter username" name="username">
        </div>
        <div class="mb-3">
            <label for="password" class="form-label"><strong>비밀번호</strong></label>
            <input type="password" class="form-control" id="password" placeholder="Enter password" name="pswd">
        </div>
        <div class="mb-3">
            <label for="email" class="form-label"><strong>이메일</strong></label>
            <input type="email" class="form-control" id="email" placeholder="Enter email" name="email">
        </div>
    </form>
	<button id="btn-save" class="btn btn-primary"><strong>회원가입 완료</strong></button>
</div>

나는 button을 이용해 js로 데이터를 전송하기 위해 <form>태그에 action, method 옵션은 넣지 않았다.

 

button의 타입은 제거하고 <form>태그 바깥쪽으로 이동시킨다.

 


2. Controller, Repository 만들기

 

Controller

@Controller
public class UserController {
    @GetMapping("/auth/joinForm")
    public String joinForm(){
        return "/user/joinForm";
    }
}

회원가입 페이지를 리턴하는 것이기에 @Controller 어노테이션을 사용하고,

 

매핑 주소는 /auth/joinForm 으로 설정하였다.

 

중간에 auth를 넣은 이유는 나중에 security 필터에서 /auth/** 는 로그인 세션이 없더라도 들어올 수 있도록 하기위함이다.

 

return 값으로 String 형태로 joinForm.jsp의 path를 삽입해줄 때 prefix와 suffix는 생략해준다.

 

Repository

public interface UserRepository extends JpaRepository<User,Integer> {
}

repository 또한 JpaRepository를 상속받고 제네릭으로 User클래스와 PK의 타입인 Integer을 넣어준다.

 

 

이제 프로젝트를 실행 후 주소로 localhost:포트번호/auth/joinForm 을 입력하면

위와 같은 회원가입 페이지가 잘 나타나는 것을 알 수 있다.


3. Security Library 잠깐 주석처리

페이지를 지속적으로 확인하면서 작업을 해야하기 때문에 secuirt 설정을 하기 전까지는 security와 관련된 라이브러리를

 

주석처리한 뒤 오른쪽 위에 코끼리 모양의 Load Gradle Change를 클릭하면 된다.

 


4. joinForm에서 Controller로 데이터 전송

joinForm에 있는 button을 클릭하면 <form> 태그 안의 데이터를 controller로 전송시키는 javascript 코드를 작성하겠다.

 

javascript파일도 css와 동일하게 resources폴더 아래 static 폴더 아래의 js폴더 안에 user.js 형태로 생성해준다.

 

let index = {
    init: function() {

    },
}
index.init();

아직은 javascript 코드에 대해서는 자세히 알지 못하여 대략적인 방식만 설명하도록 하겠다.

 

index 변수안에 init()이라는 메소드를 생성해놓고 init() 메소드 안에 jquery를 이용하여

 

여러 동작에 따른 실행 함수들을 정의 할 예정이며

 

하단에 index.init() 코드를 통해 js파일 실행과 동시에 init 함수를 실행하도록 코딩한다.

 

let index = {
    init: function() {
    
    //juery문법으로 button의 id값일 경우 #id, class값일 경우 .class 를 입력해준다.
    //"click"이 일어날 경우 , 뒤의 값이 리턴되는데 람다 식을 이용하여 함수가 실행되도록 한다.
        $("#btn-save").on("click", () => {
            this.save();
        })
    },
    save: function (){
	//우리가 joinForm에서 보낼 값들을 호출한다.
     //마찬가지로 joinForm의 input태그안의 id값을 제대로 입력해주어야 한다.
        let data ={
            username: $("#username").val(),
            password: $("#password").val(),
            email: $("#email").val()
        };
        
      //ajax 통신을 이용하여 JSON의 타입으로 데이터를 전송한다.
      //POST타입의 Request로 "/auth/joinProc" 매핑주소를 가진 controller로 데이터를 전송한다.
        $.ajax({
            type: "POST",
            url:"/auth/joinProc",
            data: JSON.stringify(data),
            contentType: "application/json; charset=utf-8",
            dataType : "json"
            
            // 회원가입에 성공할 경우 로그인 페이지로 이동
            // 실패할 경우 회원가입 페이지로 다시 이동
        }).done(function (resp){
            alert("회원가입이 완료되었습니다.");
            location.href = "/auth/loginForm";
        }).fail(function(error) {
        	alert("회원가입이 실패하였습니다.");
            alert(JSON.stringify(error));
			location.href = "/auth/joinForm";
        });
    }
}
index.init();

javacript 코드에 대한 간단한 설명은 주석으로 설명을 해놓았다.

 

다만 ajax 통신과 람다식, JSON에 대한 설명은 차후에 따로 기술하겠다.


5. RestController에서 데이터 받고 Service를 이용한 비즈니스 로직 처리

@RestController
public class UserApiController {

    @PostMapping("/auth/joinProc")
    public void save(@RequestBody User user){
        System.out.println("UserApiController: save 호출됨");
    }
}

우리는 데이터를 받고 데이터를 리턴하기 위해서 @RestController를 사용하겠다.

 

JSON형태의 데이터는 HTTP 프로토콜에서 Body를 통해 전송되기 때문에 

 

@RequestBody 어노테이션을 통해 json데이터를 User객체로 담는다.

 

@Service
public class UserService {
    @Autowired
    private UserRepository userRepository;

    @Transactional
    public void 회원가입(User user){
        user.setRoleType(RoleType.USER);
        try {
            userRepository.save(user);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

service 패키지 안에 UserService 클래스를 생성한 뒤 @Service 어노테이션을 사용해준다.

 

차후에 비밀번호 해쉬화 권한 처리 등의 로직이 발생하면 모두 이곳에서 추가 처리하도록 하겠다.

 

지금은 간단하게 RoleType만 user에 추가로 setter 해준뒤

 

JpaRepository의 save 메소드를 사용하여 user 객체에 대한 ORM을 진행 해준다.

 

//UserApiController

@Autowired
private UserService userService;

@PostMapping("/auth/joinProc")
public void save(@RequestBody User user){
    System.out.println("UserApiController: save 호출됨");
    userService.회원가입(user);
}

다시 UserController로 돌아와 UserService클래스를 @Autowired하여 DI(의존성 주입)를 해준다.

 

의존성 주입을 할 경우 UserService클래스에 대한 new 객체생성을 Spring 컨테이너에서 관리하기 때문에 

 

직접 객체를 생성하는 것보다 효율적이고 적은 코드로 새로운 객체를 생성할 수 있다.

 

그리고 save() 메소드에서 UserService클래스의 회원가입() 메소드를 호출하면 회원가입이 완료된다.


5. 회원가입 성공 / 실패 처리를 위한 ResponseDto클래스 생성

@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class ResponseDto<T> {
    int status;
    T data;
}

다른 패키지와 동일한 패키지수준으로 dto 패키지를 생성하고 ResponseDto클래스를 생성한다.

 

RestController에서 만든 메소드들의 리턴은 모두 ResponseDto객체를 이용하여 Json으로 변환하여 리턴할 것이다.

//UserApiController

@PostMapping("/auth/joinProc")
public ResponseDto<Integer> save(@RequestBody User user){
    System.out.println("UserApiController: save 호출됨");
    Boolean result = userService.회원가입(user);
    return new ResponseDto<Integer>(HttpStatus.OK.value(),1);
}

이제 UserApiController의 save()메소드의 리턴값을 위와 같이 바꾸어준다.

 

이제 save()를 호출한 user.js파일의 ajax통신으로 해당 리턴값이 돌아가서 

 

회원가입이 성공한다면 .done(), 실패한다면 .fail() 의 로직이 수행될 것이다.


6. 회원가입 실행

 

1. 브라우저 주소: localhost:포트번호/

index.jsp

2. 브라우저 주소: localhost:포트번호/auth/joinForm

joinForm.jsp

3. 회원가입 시도

브라우저에서는 정상적으로 회원가입이 완료되었다고 나온다.

 

이제 DB를 살펴보자

4. DB 확인

id는 auto_increment로 자동으로 1부터 자동으로 +1로 들어갈 것이고

 

email, password, username은 입력한 값이 들어가며

 

roleType은 Service클래스에서 최초회원가입 시 USER로 셋팅 하게 해놓았다.

 

이로써 간단한 회원가입은 완료되었으나, 비밀번호 해쉬화 등의 업데이트 사항은 차차 진행하도록 하겠다.