TIL) westagram - 프론트랑 백이랑 첫만남😍!!

solmii·2020년 6월 18일
1

React

목록 보기
8/10
post-thumbnail

오늘은 백앤드분이 만든 위스타그램 회원가입, 로그인 댓글 등의 기능과

우리가 만든 예쁜 껍데기(ㅋㅋㅋ....)를 합쳐보는 세션이 있었다!!! 완전 짱잼 졸잼!!!!


대강의 진행 순서는 이렇다!!

  1. userInput 의 값이 바뀔때마다 onChange 이벤트로 값을 받아서 state 에 저장 한다.

  2. 유저가 로그인 버튼을 눌렀을때 onClick 이벤트가 실행된다.

  3. onClick 이벤트 안에 fetch 함수를 이용해서 백앤드한테 데이터를 전달한다.

  4. 이 때, 데이터를 백앤드한테 전달하는 것이므로 methodget 이 아닌 post 를 이용

바로 코드 보시죠!!!


fetchpost 로 쓸때는 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 값이 일치해야 한다.

만약 우리가 stateuserId 라고 지정해놨는데, 백에서 지정한 유저 id의 key 값은 email 이라면?

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')
}

methodbody 사이에 넣어준다!

참고로 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, email, 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, 찾을 수 없음)


:: 댓글 - post

댓글은 한국님이랑 붙여봤다!!!

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~~~ 라는 댓글이 전송되어서, 백앤드분이 확인했다는 내용임!!!!


:: 댓글 - get

뭔가 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 해오면서 commentArrsetState 로 매번 대치시켜주면 성능에 문제가 생기지 않을까 했는데 멘토님이 전혀! 괜찮다! 고 하셨당😆

💁🏻‍♀️ 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 요청을 보낸다!!!!!!

새로고침해도 댓글이 없어지지 않는다~~~!!!
(물론 댓글 지우는건 껍데기만 지우는거라 새로고침하면 지워던 댓글 다시 생김.....ㅎ)

ㅠㅠㅠㅠㅠ진짜 환일님이랑 맞출때 막 무한루프 돌아서 맥북 수명 줄고 계속 에러뜨고 그랬는데...
열심히 머리 맞대서 딱 맞춰지고 댓글 몇십개가 주르륵 뜨는 순간.....!!!
진짜 너무 짜릿하고 너무 기분 좋았다~!!!!!!! 완전 신나신나><👍

profile
하루하루는 성실하게 인생 전체는 되는대로

2개의 댓글

comment-user-thumbnail
2020년 6월 19일

고생많으셨어요 ~~

1개의 답글