인스타그램 클론 프로젝트-(4)

회원정보 수정

  1. 회원정보 불러오기

1) 방법1
회원정보 페이지에 회원정보를 넣으려면, 세션에 저장된 유저정보를 Model에 담아 view 페이지로 넘겨줘야 한다.

2) 더 간단한 방법

각 view의 jsp에는 아래와 같이 header가 공통적으로 들어가는데 이를 이용해서 header에서 설정하는 방법이다.

pom.xml에서 spring-security-taglibs 를 디펜던시에 넣어 설정하고,

header.jsp에서 상단에서 미리 설정한 sec 의 기능을 이용해 인증된 정보에 접근하는 방법(isAuthenticated())으로 설정한다.
6줄 : property="principal" 라고 하면, 세션 정보에 접근이 되는 키워드/ var="principal" >>>principalDetails를 principal 변수에 담는다.

그럼 방법1에서처럼 Model에 따로 담아서 넘기지 않아도 바로 접근이 된다.

그러므로 유저네임 등을 불러올 때는 principal.user >> principalDetails.getUser() 와 같으므로 user를 중간에 넣어야 한다.

2.회원정보 수정하기 버튼 누르면 업데이트

update.jsp에서 수정하기 버튼을 누르면 자바스크립트의 update() 기능이 작동하게 한다.

update.js에서 userId를 파라미터로 폼태그가 가지고 있는 정보를 가져와서 서버로 전송할 수 있다.

제이쿼리를 사용해서 data에 정보를 담아주는데,

프로파일업데이트는 폼태그의 이름을 말하는 것으로 jsp에서 해당하는 폼태그를 찾아서 모든 info 값을 serialize를 이용해 data에 모든 정보를 담고 서버로 던진다. (헤더에 제이쿼리 정의해서 제이쿼리를 사용할 수 있음)

서버에 던질 때는 ajax를 사용한다.

8~13줄 : 자바스크립트 오브젝트를 넣음
9줄 : PutMapping을 이용
11줄 : 던질 데이터를 의미하는데 위에서 data 변수에 담았으므로,
12줄 : 콘솔.로그에서 보면 데이터들이 key=value&& 이런식으로 이어지는데 이러한 형태를 x-www-form-urlencoded 라고 한다.
13줄 : 제이슨의 형태로 데이터를 보낸다.
14줄 : json을 js(자바스크립트)로 파싱(분석)해서 res에 응답을 받는다. 그래서 res는 자바스크립트 오브젝트가 된다.

실행은 안되는데 url에 해당하는 컨트롤러가 없기 때문이다.>>만들어줌

17줄 : ajax는 파일이 아닌 데이터로 응답을 한다. 데이터로 응답 (API)
23줄 : 반환해주는 타입을 Entity를 넘기기 위해 CMResDto로 해준다.
27줄 : 업데이트된 정보가 세션에도 저장되도록 principalDetails에 userEntity를 넣어준다.
29줄 : 1은 성공을 의미한다.

DTO에서 필수인 변수와 기재 안해도 되는 변수가 있기 때문에 Vaildation 체크가 필요하다.(이름, 패스워드를 기재 안하면 문제가 된다 >> 이후에 수정할 예정)

19줄 : 수정 >> write니깐 @Transactional을 붙여준다.
22~38줄 : 서비스에서 해야하는 것은 아래와 같다.
(1) 영속화
23줄 : get()을 하는 이유는??
findById()에서 해당 Id가 없어서 null일 때를 대비해서 Optional이란걸 만들준다. 이 Optional을 사용하면 3가지 조건을 사용할 수 있다.

  • 무조건 찾았다 >> get()
  • 못 찾았으니 익셉션 발동 >> orElseThrow()
  • 그외(별로 중요하지 않음)

(2)영속화된 오브젝트를 수정-더티체킹 (업데이트 완료)

25~36줄 : 그리고 영속화된 오브젝트를 수정 하면 자동으로 DB에 반영이 된다. 이때, 비밀번호는 암호화시켜서 수정한다.

"영속화가 됐다" 의미
스프링부트 서버에서 findById()로 DB 유저정보에서 그 id에 해당하는 객체를 찾아서 들고오면, 서버와 DB 사이의 영속성 컨텍스트 라는게 있는데 그 안에 찾은 객체가 쏙 들어가는데 그걸 영속화가 됐다고 한다.

(세션정보도 바뀌게 해준다.)

그리고 Update.js에서 수정 후 유저의 페이지로 돌아오게 만든다.

그런데 오류가 계속 난다.....수정하기만 누르면 저렇게 뜬다...

그리고 에러메시지....

[org.springframework.web.method.annotation.MethodArgumentTypeMismatchException: Failed to convert value of type 'java.lang.String' to required type 'int'; nested exception is java.lang.NumberFormatException: For input string: "${userId}"]

어디에선가 userId를 String으로 인식하는 것 같은데 그게 어디서 왜 그러는지 모르겠다. id는 int 값이라서 믹스매칭타입 오류가 뜨는 것 같음...

<<오류해결>>
정말 간단한 거였다. console에서 보면 Request URL이 이상하다. int id 값(예:1)이여야 하는데 String같은게 들어 있음. 그리고 Status Code가 400이다. 400은 클라이언트 측에서 애초에 요청을 잘못해서 서버가 알아들을 수 없다는 뜻 이므로 js파일을 확인해봄.


url 주소를 문자로 인식하고 있다는 것! >> url에서 주소를 쓸 때는 '' 가 아니였다........ 그래서 숫자 1 옆의 것으로 바꿔주는걸로 해결함. ㅠㅠ
바보다 증말..

  1. 유효성 검사

1) name, password가 공백으로 처리되는 것을 막기
앞단에서 처리 할 수 있다.>>값 검증

(1) 프론트단
update.jsp에서 공백이면 안되는 값에 required="required"를 넣어준다.

<button type="button" onclick="update(${principal.user.id})"> 

이걸 form 태그 안에 onsubmit 하고 넣어준다.

<form id="profileUpdate" onsubmit="update(${principal.user.id},event)">

event를 넣는 이유 : 버튼을 눌러서 submit하면 js의 update() 함수가 실행이 되고 다시 메인페이지로 가야 하는데 안 가고 있기 때문에 event를 날리고 update.js에서 event를 받는다.

event.preventDefault();

그리고 이걸 넣어서 폼태그의 액션을 막아 더 진행되지 않게 한다.

(2) 유효성검사

30줄 : BindingResult는 꼭 @Valid가 적혀있는 다음 파라미터에 적어야 한다.(잘 안 먹음)
39~47줄 : AuthController에서 했던 유효성 검사 및 익셉션 코드를 가져오고, 별도의 커스텁API익셉션(이름만 다르고 내용은 같아도 됨)을 만들어준다. 그리고 핸들러에서 아래와같이 CMResDto의 타입으로 리턴 받게 만든다.(Ajax는 CMResDto으로 받음)

그리고 update.js의 ajax에서 성공과 실패를 구분하려면 HttpStatus 코드가 필요하므로 ControllerExceptionHandler에서 HttpStatus코드를 같이 보내는 방법으로 수정해본다. (성공 res >>HttpStatus코드가 200번대 /실패 error >> HttpStatus코드가 200번 외의 코드)

BAD_REQUEST >> 400번대 >> ajax의 fail이 실행됨

성공

실패

22줄 : 콘솔에서 봤던 메세지와 '공백일 수 없습니다' 메시지를 알람창으로 띄워줄 수도 있다. stringfy >> js 오브젝트를 json 문자열로 변경해줌

2) 1번 유저를 수정해서 영속화하고자 할 때, 1번 유저가 없는 경우?
뒷단(데이터베이스단)에서 처리한다.

(1)
영속화 부분에서 findById(id).get()을 썼을 때, null이 튀어나와서 오류가 발생한다. >> null이 발생시 익셉션을 발동시키도록 orElseThrow() 로 바꿔준다.

26~30줄 : orElseThrow() 안에 들어올 수 있는 타입이 Supplier 타입이고, 이때 발생할 익셉션은 IllegalArgumentException >> "괄호 안에 잘못된 argument(예:10 >> DB에 없는 유저)를 넣었다." 는 의미이다. 그리고 get() 오버라이드 해주면 리턴하는 메세지가 콘솔에 찍힘. 이걸 익셉션핸들러에서 낚아채서 익셉션에 대한 처리를 해주면 된다.

(2) 이 방법을 람다식으로 해보기 (더 간단)

익셉션 처리하기

새로운 익셉션을 만들기보단 기존의 익셉션을 이용하고자 커스텀익셉션을 터트려주고, 익셉션핸들러에서 가로채가게 한다.

그 전에, 이 경우의 익셉션은 errorMap에 오류에 대한 내용을 담을 필요 없이 에러메세지만을 띄우면 되기 때문에 18~21줄과 같이 String message만을 파라미터로 하는 메서드를 별도로 만든다. 그리고 CustomValidationApiException 이터지게 되었을 때, 핸들러에서 가로채가서 익셉션에 대한 메세지와 HttpStatus 코드를 리턴한다.

실패 코드는 Update.js에서 받아서 alert창을 띄우는데, 이 익셉션은 data가 DB에 존재하지 않을 경우, 즉 null일 경우에 발생하므로 ifelse로 분기를 해서 상황에 맞는 alert창을 띄우게 한다.

이것으로 회원정보 수정에 대한 전후처리를 마무리 함.

좋은 웹페이지 즐겨찾기