⏺️ 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로 들어가서 값도 정상적으로 전달이 되었는지 확인
이렇게 브라우저로 값이 조회가 가능한거 자체가 보안에 취약할 것 같지만,
아직 그런 진도는 나가지 않았으므로 넘어감.