오늘은 백앤드분이 만든 위스타그램 회원가입, 로그인 댓글 등의 기능과
우리가 만든 예쁜 껍데기(ㅋㅋㅋ....)를 합쳐보는 세션이 있었다!!! 완전 짱잼 졸잼!!!!
대강의 진행 순서는 이렇다!!
userInput
의 값이 바뀔때마다 onChange
이벤트로 값을 받아서 state
에 저장 한다.
유저가 로그인 버튼을 눌렀을때 onClick
이벤트가 실행된다.
이 onClick
이벤트 안에 fetch
함수를 이용해서 백앤드한테 데이터를 전달한다.
이 때, 데이터를 백앤드한테 전달하는 것이므로 method
는 get
이 아닌 post
를 이용
바로 코드 보시죠!!!
fetch
를 post
로 쓸때는 2개의 인자를 받는다.
fetch("api 주소", { 전달할 데이터 })
이 { 전달할 데이터 }
객체 안에는 method
, body
, header
등 여러가지 key:value
가 들어가는데, 생략해도 오류는 안나긴 한다.
실제로 아래에서 get
으로 데이터를 받아올때는 생략했다!
method: 'post'
⇒fetch
의 성질을 정의해준다. 기본값은get
body: 전달할 데이터
⇒ 첫번째 인자로 들어온api 주소
로 보내줄 데이터를 입력한다.
우리의 정보는 javascript의 객체이다. 그렇기 때문에, 백앤드한테 줄때는 JSON 형태로 바꿔줘야한다.
JSON.stringify()
이라는 메서드를 body의 value로 넣어준다.
여기에 인자로 userId
, userPw
를 담는 객체가 들어간다.
데이터를 담는 개체 대신,
this.state
로 모든 정보를 보내줄 수도 있다.
근데 항상this.state
를 쓸 수 있는건 아님!!! 백엔드에서 요청하는 key 값과 우리가state
에 저장할때 입력한 key 값이 일치해야 한다.
만약 우리가state
에userId
라고 지정해놨는데, 백에서 지정한 유저 id의key
값은
email : this.state.userId
를 객체에 담아서 보내주면 된다!!!!
여기까지가 하나의 fetch call
즉, fetch
요청이다.
이 요청에 대한 응답은 백엔드에서 보내준다.
백앤드로부터 응답이 오고난 후, 그 응답에 대한 .then
함수가 실행된다.
(단, 이때의 응답은 json 데이터 형태로 오기 때문에 다시 우리가 사용할 수 있는 javascript의 객체 타입으로 변환해야 한다.)
clickPostHandler = () => {
fetch('http://10.58.7.42:8000/user/signin/', { // 서버 주소!
method: 'post',
body: JSON.stringify({
user_id: this.state.userId,
password: this.state.userPw,
// user_id, password 라고 되어있는 key 값은 백앤드와 소통해서 일치시켜야 한다.
}),
})
};
회원가입은 유저가 입력한 id 와 password를 객체에 담아서 JSON 형태로 전달해주기만 하면 된다.
로그인은 회원가입과는 다르다~!
회원가입은 백엔드의 DB에 바로 저장되는거고, 로그인은 저장된 데이터와 대조해서 확인을 해야하니까!
정상적으로 로그인이 됐다면 백앤드에서 access_token
을 발행한다.
HTTP의 stateless 특성때문에 유저는 매 요청마다, 로그인을 해야하는 불편함이 있다.
그래서 로그인 후에 백앤드에서 발행한 access_token
을 받아서, 유저가 HTTP 요청을 할때마다 id, pw 입력 대신 이 access_token
을 백앤드에게 전달하여 유저가 매번 로그인해야하는 불편함을 없애줘야 한다!!
댓글은 로그인 후 발급받은 access_token
을 user id, pw 대신 body
에 담아서 보내준다!!
그럼 백앤드는 이 access_token
을 보고, 댓글을 작성한 유저의 아이디를 확인해서 DB에 저장한다.
local storage에 저장된 access_token
을 가져올땐!
localStorage.getItem('지정한 access_token의 key 값')
으로 가져온다!
headers: {
Authorization: localStorage.getItem('access_token')
}
를 method
랑 body
사이에 넣어준다!
참고로 headers
안에 Authorization
key값은 마음대로 이름 붙일 수 있는게 아니라 고정된 key 임!
일단 우리는 백앤드 분의 노트북을 서버로 쓰는 것이기 때문에 백앤드와 와이파이를 맞춰야 한다.....
⇒ 이거 때문에 안되서 한참 끙끙댔음😅
준모님이랑 붙여봤당!!!!!
clickPostHandler = () => {
console.log(this.state);
// POST
fetch('http://10.58.1.243:8000/SignUp/', {
method: 'post',
body: JSON.stringify({
user_id: this.state.userId,
email: "rkdthfal132@gmail.com",
password: this.state.userPw,
// account, password key 값은 백앤드와 소통해서 일치시켜야 한다.
}),
})
.then((res) => res.json()) // 로그인이 성공했다는 가정 하에 실행됨
.then((res) => console.log(res.message));
};
우왕!!!!!!😆😆😆😆😆
참고로 여기서
body
안의 key 값은 백앤드와 일치시켜야 한다!!
위 예시에서user_id
,password
는 백앤드에서 지정한 key 값 인것!!!
clickPostHandler = () => {
console.log(this.state);
// POST
fetch('http://10.58.1.243:8000/Login/', {
method: 'post',
body: JSON.stringify({
user_id: this.state.userId,
password: this.state.userPw,
// account, password key 값은 백앤드와 소통해서 일치시켜야 한다.
}),
})
.then((res) => res.json()) // 로그인이 성공했다는 가정 하에 실행됨
.then((res) => console.log(res.token));
};
우왕 신기!!!!
근데 이렇게 로그인 해서 access_token
잘 받아도 새로고침하면 다 날아간다 ㅠㅠㅠㅠㅠㅠ
그러니까 우리 프론트앤드는 이렇게 받은 access_token
을 브라우저의 local storage 에 저장해야 한다!
( 물론 실제로는 쿠키 등에 저장하겠지만, 실습할때는 브라우저의 local storage에 저장했다. )
console.log()
자리에 데이터를 local storage 에 저장하는 메서드를 넣어준다!
.then((res) => localStorage.setItem('access_token', res.token));
개발자 도구의 local storage에 들어가서 확인해보면 잘 나온다!!!!
참고로 여기서
body
안의 key 값은 백앤드와 일치시켜야 한다!!
위 예시에서user_id
,password
는 백앤드에서 지정한 key 값 인것!!!
이미 가입된 이메일로 또 회원가입 해보세요!
404 (Not Found, 찾을 수 없음)
: 서버가 요청한 페이지(Resource)를 찾을 수 없다. 예를 들어 서버에 존재하지 않는 페이지에 대한 요청이 있을 경우 서버는 이 코드를 제공한다.
없는 아이디로 로그인 해보세요!
400 (잘못된 요청)
: 서버가 요청의 구문을 인식하지 못했다.
KeyError 내보세요! ( KeyError? 백앤드에서 지정한 key 값과 프론트에서 보내는 key 값이 다른 에러)
404 (Not Found, 찾을 수 없음)
댓글은 한국님이랑 붙여봤다!!!
Uploadcomment
component 에서 addFormHandler
이벤트 안에 아래 태그 추가!!!
addFormHandler = () => {
// 댓글 POST
fetch('http://10.58.5.169:8000/comment/posting', {
method: 'post',
headers: {
Authorization: localStorage.getItem('access_token'), // access_token을 Authorization로 백앤드한테 보내줌
},
body: JSON.stringify({
comments: this.state.userInput, // userInput을 comment로 백앤드한테 보내줌
}),
}).then(() => {
if (this.state.userInput) {
this.setState({ userInput: '' }
}
});
};
여기서
body
안의comments
라는 key 값은 백앤드가 저장한 이름과 일치시켜줘야 한다.
짤이 잘 안보이는데 대충 내가 친 test~~~
라는 댓글이 전송되어서, 백앤드분이 확인했다는 내용임!!!!
뭔가 post
를 하고 나니, get
도 할 수 있지 않을까? 싶었다.
옆자리 환일님이랑 도전!!!!!!!
handleData = () => {
fetch('http://10.58.5.169:8000/comment/posting')
.then((res) => res.json())
.then((res) => this.setState({ commentArr: res.message }));
};
get
해오는 함수를 정의해주고~!~!~!!!
댓글을 새로 쓸때마다 매번 get 해오면서 commentArr
를 setState
로 매번 대치시켜주면 성능에 문제가 생기지 않을까 했는데 멘토님이 전혀! 괜찮다! 고 하셨당😆
💁🏻♀️
res.message
부분은 백앤드에서 보내주는 응답이 딕셔너리(객체) 형태이기 때문에res
라는 객체의message
key 값으로 접근한 것이다!
이message
의 value는 리스트(배열) 형태이기 때문에,commentArr
라는 빈 배열을 바로 대치만 시켜주면 미리 작성해놓았던map
메서드로 돌릴 수 있다.
이때의key
값 또한 백앤드에서 지정한 값과 일치시켜줘야 한다.
(위 코드에서는 환일님이 유저 댓글의 key 값을message
라고 지정해놓으셔서 나도 그에 맞춘것!)
우선 서버에 저장된 어제 쓴 댓글, 지난주에 쓴 댓글, 지지난주에 쓴 댓글들도 모두 가져와야 하니까 componentDidMount
메서드로 mount 직후에 서버에 저장되어있던 댓글을 한번 가져온다.
componentDidMount() {
this.handleData();
}
여기까진 쉬웠는데, 새로 댓글을 쓰면 다시 post
를 보내고, 그렇게 해서 저장된 댓글을 다시 get
으로 가져와야 하는 부분이 어려웠다....
준식님의 도움으로 이렇게 코드를 짰다!!!
addFormHandler = () => { // 게시 버튼 이벤트
// 댓글 POST
fetch('http://10.58.5.169:8000/comment/posting', {
method: 'post',
headers: {
Authorization: localStorage.getItem('access_token'), // access_token을 Authorization로 백앤드한테 보내줌
},
body: JSON.stringify({
comments: this.state.userInput, // userInput을 comment로 백앤드한테 보내줌
}),
}).then(() => { // 앞의 post가 완료되면 실행!
// 댓글을 새로 쓸때마다, 서버에 댓글 post 하고 get 해옴!
if (this.state.userInput) {
this.setState({ userInput: '' }, () => this.handleData()); // handleData는 콜백 함수로 들어옴
}
});
};
이렇게!!! 서버에서 가져온 모든 댓글이 처음 mount 됐을 때 출력되고!!!
댓글을 새로 쓰면 post 요청을 보내고, 그 요청에 대한 응답이 오면 바로 get 요청을 보낸다!!!!!!
새로고침해도 댓글이 없어지지 않는다~~~!!!
(물론 댓글 지우는건 껍데기만 지우는거라 새로고침하면 지워던 댓글 다시 생김.....ㅎ)
ㅠㅠㅠㅠㅠ진짜 환일님이랑 맞출때 막 무한루프 돌아서 맥북 수명 줄고 계속 에러뜨고 그랬는데...
열심히 머리 맞대서 딱 맞춰지고 댓글 몇십개가 주르륵 뜨는 순간.....!!!
진짜 너무 짜릿하고 너무 기분 좋았다~!!!!!!! 완전 신나신나><👍
고생많으셨어요 ~~