floatfirstTOC: right
1️⃣ 현재 상태
⏺️ 서버를 돌리고
http://localhost:8080/joinForm
페이지 접속
⏺️ 회원가입 메뉴 클릭 후
⏺️ 회원 정보 입력, 그리고 회원가입 클릭⏺️ 아래와 같이
localhost:8080/join
으로 리다이렉팅 되지만 페이지는 없다.
⏺️ 요 서비스를 구현해야됨2️⃣ 프론트 영역확인 먼저 (html 확인)
⏺️
joinForm.html
>> <form>
태그 내부 구조 확인
⏺️ action=”/join”
확인 : URL로 /join
페이지 요청이 들어왔을 때 해당 폼태그 실행
⏺️ method=”post
확인 : DB에 가입정보를 넣어 변경하는 행동이기 때문에 post
⏺️ x-www-form-urlencoded
확인 : 해당 설정이 있어야지, 사용자가 정보를 제출하면 브라우저가 xform 데이터 형식에 맞춰서 인코딩해준다. 이는 서버가 파싱하기 좋게 바꿔준다는 말이다.
⏺️ name= “(키값)“
확인 : 해당 input 태그에 이 값이 User의 필드값이랑 이름이 일치해야지 브라우저가 인코딩할 수 있다.
⏺️ <button type=”submit”>
확인 : 폼태그 내부에 버튼이 위치하고 타입이 submit
이 되어야지 사용자가 ‘회원가입’을 클릭했을 때, 입력정보가 xform데이터로 서버에 전송이 된다.
⏺️ input
타입이 text,password,email
으로 설정되어있으면 password입력란은 자동 글자숨김기능이 구현되고, email입력란은 자동으로 @가 있는지 유효성 검사를 한다.
3️⃣ 컨트롤러 책임 이해
컨트롤러 책임은 무엇인가????
컨트롤러
🔹 요청받기 (URL)
🔹 http body는 어떻게? (DTO)
🔹 기본 mime 전략 : x-www-form-urlencoded (username=ssar&password=1234)
🔹 유효성 검사하기 (body 데이터가 있다면)
🔹 클라이언트가 View만 원하는지? 혹은 DB 처리 후 View도 원하는지?
🔹 View만 원하면 view를 응답하면 끝
🔹 DB처리를 원하면 Model(DAO)에게 위임 후 view를 응답하면 끝
4️⃣ 리다이렉션 확인
🔹 일단 회원 가입버튼을 누르고 리다이렉션이 이루어지는지 확인한다.
🔹 다음 코드를 컨트롤러에 구현하자.
@Controller //스프링 컨테이너에 빈 객체로 등록하게 해주는 어노테이션 (IoC의 객체역할) public class UserController { // URL경로 매핑 어노테이션 : 식별자 '/join'이 요청되면 해당 메소드를 연결해준다. @PostMapping("/join") public String join (){ // 리다이렉션 기능이기 때문에, 요청에 "/join" "/loginForm" 다 존재헤야된다. return "redirect:/loginForm"; }
🔹 아래 URL로 접속하여서 joinForm에서 회원가입을 시도해본다.
http://localhost:8080/joinForm //페이지 접속
⏺️ F12를 눌러서 개발자 도구를 들어가본다.
⏺️ 메뉴에서 Network에 들어간다.
⏺️ 회원가입을 누르면 joinForm과 join 페이지 모두 호출되어야 된다.
⏺️ 작동확인 완료!
5️⃣ DTO 만들기
DTO 만들기! DTO란??
데이터 전송 객체(DTO)란 프로세스 사이에서 데이터를 전송하는 객체를 말한다. DTO 기법을 사용하면 중요한 정보를 노출시키지 않고 두 시스템(API와 서버 등) 간 통신을 원활하게 촉진할 수 있다. DTO는 프로그래밍 직업을 가진 사람들이 흔히 사용하는 솔루션이라고 볼 수 있다.
회원 가입 창을 보면서 어떤 정보를 받아야 되는지 확인한다
사용자 username
사용자 password
사용자 email
필요하다!package shop.mtcoding.blog.user; import lombok.Data; //요청에 관한 정보를 담을 객체 생성 public class UserRequest { @Data //Lombok어노테이션으로 Getter,Setter,toString을 사용할 수 있게 해준다. public static class JoinDTO { //요청중 회원가입에 전달되는 정보를 담을 객체 private String username; private String password; private String email; } }
요청이 잘 전달 되는지 확인
🔹 먼저 join메서드에 파라메터로
UserRequest.JoinDTO requestDTO
를 넣는다.
🔹 내부에 sout으로 requestDTO를 담는다. @PostMapping("/join") public String join (UserRequest.JoinDTO requestDTO){ System.out.println(requestDTO); // 테스트 코드 return "user/loginForm"; }
그리고
/joinForm
페이지에서 아래와 같이 입력하고 회원가입 클릭하고 콘솔을 확인해보자.콘솔확인! 잘 작동한것 같다!
6️⃣ UserRepository구현
사용자의 정보를 DB에 입력시켜줄 로직이 필요하다!
package shop.mtcoding.blog.user; import jakarta.persistence.EntityManager; import jakarta.persistence.Query; import jakarta.transaction.Transactional; import org.springframework.stereotype.Controller; @Repository //스프링컨테이너에 현재 객체를 Bean으로 등록 public class UserRepository { // DB와 상호작용 할 수 있게 도와주는 객체 - 쿼리문을 사용가능하게 한다. // 스프링이 만들어논 객체이고 이미 IoC에 담겨있다. - 가져다 쓰면됨 private EntityManager em; // 생성자에 의존성 주입 - 이 코드가 있어야 가져다 쓸수 있다. public UserRepository(EntityManager em) { this.em = em; } @Transactional // DB를 변경하는 작업을 할 때 동기화 시켜주는 어노테이션, 꼭 필요!!! public void save(UserRequest.JoinDTO requestDTO) { Query query = em.createNativeQuery("insert into user_tb(username, password, email, created_at) values (?,?,?, now()"); query.setParameter(1, requestDTO.getUsername()); query.setParameter(2, requestDTO.getPassword()); query.setParameter(3, requestDTO.getEmail()); query.executeUpdate(); // 쿼리 발송 flush()기능 } }
Query객체를
import
할땐 jakarta.persistence
로 해야된다.테스트 중 에러 목록
"this.userRepository" is null
펼쳐보기
에러 500번은 서버에러
"this.userRepository" is null
이 뜸확인 해보니 UserController 20번째 줄에서 에러
친절하게 왜 userRepository가 널인지 말해준다는데, 그냥 찾아봐야
확인해보니 생성자가 없어서 참조가 안되고 있었음.
생성자를 만들 수 도 있지만,
@RequriedArgsConstructor
를 사용하여 final
처리하기로 함다시 되는지 확인했는데, 이번에는 다른 에러가 뜬거 같음,
Syntax error in SQL
이 뜬거 보니 문법도 잘못 된거 같음Syntax error in SQL statement
펼쳐보기
테이블이 나오는 것을 보니, 이전 에러는 줄을 넘긴 것같고, 쿼리문은 잘 들어간 것 같으나 쿼리발송에서 에러가 난 것 같다.
마지막 괄호가 없다..
문법 다시 정리하고, 다시 확인. 다행이 정상적으로 처리가 됨
마지막 확인 payload로 들어가서 값도 정상적으로 전달이 되었는지 확인
이렇게 브라우저로 값이 조회가 가능한거 자체가 보안에 취약할 것 같지만,
아직 그런 진도는 나가지 않았으므로 넘어감.
7️⃣ 컨트롤러 구현
@RequiredArgsConstructor //final이 붙은 객체를 자동 초기화 @Controller//현재 객체를 Spring컨테이너에 등록 public class UserController { private final UserRepository userRepository; // DB와 소통할 객체 의존성 주입 @PostMapping("/join") // DB를 변경하는 메서드이므로 Post요청 public String join(UserRequest.JoinDTO requestDTO){ // join메서드의 매개변수로 가입DTO전달 // 1. 유효성 검사 -- 이건 이따가 // 2. Model에게 위임하기 - DB와 상호작용할 객체와 메소드 구현 필요!! userRepository.save(requestDTO); return "redirect:/loginForm"; // 요청이 완료되면 loginForm으로 전달 }
8️⃣ h2 DB 확인
h2 database에도 잘 들어가는지 확인
이 설정은
application-dev.yml
에 설정이 되어있으므로
주소창에 입력만 해보면 된다.
설정에는 아이디 sa 비번은 없다.//주소 http://localhost:8080/h2-console/
h2 접속중 에러
Database "C:/Users/chugu/test" not found,
에러 펼쳐보기
Database "C:/Users/chugu/test" not found 를 찾지 못했다고 함.
application-dev.yml 내부의 url주소가 같아야된다.
jdbc:h2:mem:test
JDBC URL에 붙여넣기
접속후 user_tb 생성까지 확인
DB연결 확인
8️⃣ 컨트롤러 유효성검사
이제 DB에 들어갈 정보를 검사하여 걸러내는 기능을 컨트롤러에 추가.
⏺️ 사용자 이름이 3자 이하 제한
⏺️ 에러조건 충족시 400번 페이지 연결
@RequiredArgsConstructor //final이 붙은 객체를 자동 초기화 @Controller//현재 객체를 Spring컨테이너에 등록 public class UserController { private final UserRepository userRepository; // DB와 소통할 객체 의존성 주입 @PostMapping("/join") // DB를 변경하는 메서드이므로 Post요청 public String join(UserRequest.JoinDTO requestDTO){ // join메서드의 매개변수로 가입DTO전달 // 1. 유효성 검사 - 사용자id가 3자 이하인경우 400번 에러메시지 전달 if(requestDTO.getUsername().length() < 3){ return "error/400"; } // 2. Model에게 위임하기 - DB와 상호작용할 객체와 메소드 구현 필요!! userRepository.save(requestDTO); return "redirect:/loginForm"; // 요청이 완료되면 loginForm으로 전달 }
⏺️ 에러 디렉토리 만들기
template
>> error
⏺️ 디렉토리 내부
400.mustache
파일 생성
⏺️ mustache 템플릿엔진을 사용해서 html 페이지 작성html5 입력후 자동 추천 메뉴 클릭
🔹 안뜨면 글자 넣고
ctrl
+ space
누르면 뜬다.400.mustache 페이지 내부 구현
// 400.mustache 페이지 내부 <!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> </head> <body> <h1>잘못된 요청을 하셨습니다. 400</h1> </body> </html>
의도적으로 username 두글자 넣어서 테스트
유효성검사 작동 확인
Share article