오늘은 백앤드분이 만든 위스타그램 회원가입, 로그인 댓글 등의 기능과
우리가 만든 예쁜 껍데기(ㅋㅋㅋ....)를 합쳐보는 세션이 있었다!!! 완전 짱잼 졸잼!!!!
대강의 진행 순서는 이렇다!!
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라는 객체의messagekey 값으로 접근한 것이다!
이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 요청을 보낸다!!!!!!
새로고침해도 댓글이 없어지지 않는다~~~!!!
(물론 댓글 지우는건 껍데기만 지우는거라 새로고침하면 지워던 댓글 다시 생김.....ㅎ)
ㅠㅠㅠㅠㅠ진짜 환일님이랑 맞출때 막 무한루프 돌아서 맥북 수명 줄고 계속 에러뜨고 그랬는데...
열심히 머리 맞대서 딱 맞춰지고 댓글 몇십개가 주르륵 뜨는 순간.....!!!
진짜 너무 짜릿하고 너무 기분 좋았다~!!!!!!! 완전 신나신나><👍
.png)
고생많으셨어요 ~~