서버와 통신하는 fetch 함수 사용해보기

박은정·2021년 9월 8일
2

프로젝트

목록 보기
22/34

통신하는 코드 살펴보기

fetch()함수에 대해 알아보기

(..코드생략..)

handleLogin = () => {
  fetch('http://10.58.3.28:8000/users/signin', {
    method: 'POST'
    body: JSON.stringfy({
      email: this.state.id
      password: this.state.password,
  	})
  }
  .then(response => response.json())
  .then(response => {
    if (response.token) {
      localStorage.setItem('token', response.token);
      this.props.history.push('/main');
    } else alert ('아이디 / 비밀번호를 다시 입력해주세요!');
  })
}

(..코드생략..)

<button
  className={`${isInputVaild ? "active" : "" }`}
  type="button"
  onClick={this.handleLogin}>

이 코드를 보자면

버튼을 클릭하면 함수 실행

onClick={this.handleLogin}

버튼을 눌렀을 때 handleLogin 함수를 실행한다

더 알아보고 내용 추가하기

onCLick에 바로 arrow function을 주지 않은 이유는
onClick={this.handleLogin()}이라고 주게 되면 무한으로 실행되는? 오류가 발생해서 () 없이 새로 만든 함수명만 입력하게 된 것 같다

버튼을 실행되는 handleLogin() 함수

handleLogin 함수 안에 있는 fetch() 함수는 인자를 2개 받게 되는데

  1. 첫 번째 인자 : 서버로 요청할 API 주소
'http://10.58.3.28:8000/users/signin'
  1. 두 번째 인자 : HTTP 통신을 어떠한 방식으로 할 지에 대한 설정값
    • dictionary 형태
    • POST 혹은 GET 메서드로 서버에 요청보내는지 설정한다
      (GET는 기본값이라 생략 가능)
    • body : 클라이언트에서 서버로 담아서 전달하는 정보
      서버에서 request를 받아서 내용확인할 때의 정보이다
{
    method: 'POST'
    body: JSON.stringfy({
      email: this.state.id
      password: this.state.password,
    })
}
  1. .then() : 서버에서 받은 응답 request 을 처리하는 부분
    • 서버에서 받은 response를 json으로 변환하고
    • response에서 받은 정보에 따라 frontend에서는 분기를 나눌 수 있다
.then(response => response.json())
  .then(response => {
    if (response.token) {
      localStorage.setItem('token', response.token);
      this.props.history.push('/main');
    } else alert ('아이디 / 비밀번호를 다시 입력해주세요!');
  })

실제 웹사이트 화면에서 통신하기

서버를 통한 통신 오류 failed

실제로 웹사이트 화면을 통해 로그인을 한다고 가정하고 아이디 및 비밀번호를 입력했는데 뭔가 실행이 안되는 것 같을 때에는 우선 네트워크 탭을 확인해야 한다

만약 네트워크 패널에서 failed이라는 결과가 나온다면

  1. 서버를 안켰는가?
  2. 서버에 잘못된 API 주소로 요청을 주었는가?
    (= 클라이언트와 서버의 API 주소가 일치하지 않은가?)
  3. 클라이언트와 서버가 서로 다른 와이파이를 사용하는가?
NameStatusTypeInitiar
signin(failed)fetchLogin.js:11
// server terminal?
Starting development server at http://127.0.0.1:8000/

처럼 로컬서버를 키면 안되고 client에서도 접속할 수 있도록
runserver 0:8000 처럼 서버를 켜줘야 한다

클라이언트를 통한 통신 오류 400번대

404 error

NameStatusTypeInitiar
signin404fetchLogin.js:11

이런식으로 404 에러가 발생한 것을 확인이 될 때에는
front에서의 문제이기 때문에 frontend의 코드를 살펴보면 된다

404 error
= not found error
= 페이지를 찾을 수 없다
= 주소가 잘못 되었다

클라이언트와 서버와의 통신 자체는 성공했는데
로직을 돌리는 과정에서 잘못된 것이다
클라이언트의 fetch() 함수에서 syntax 오류이거나 key 값이 오류인지 확인해야 한다

그래서 fetch 함수의 첫번째 인자인 API주소를 살펴봤는데
signup기능을 구현할 건데 endpoint가 signin같이 잘못 입력된 것을 확인할 수 있는데 수정해주면 된다

'http://10.58.3.28:8000/users/signin'
→ 'http://10.58.3.28:8000/users/signup' 수정

백엔드에서도 주소가 맞는지 확인할 수 있다

vi views.py
vi urls.py

터미널에서 이러한 명령어로 우선 views.py 안에 있는 urls.py를 확인하면 (?) 정확하지는 않다...

이러한 코드를 확인할 수 있다

urlpatterns = [
	path('/signup', SignUpView.as_view()),
    path('/signin', SignInView.as_view()),
]
  • '/signup' 라는 endpotin를 통한 url를 통해 → SignUpView.as_view() 기능에 접근하고
  • '/signin' 라는 endpotin를 통한 url를 통해 →
    SignInView.as_view() 기능에 접근한다는 뜻이다

'http://10.58.3.28:8000/users/signin'
이 url또한 서버에서 확인할 때에는

urlpattern = [
	path('/users', include('user.url')),
]

user라는 endpoint가 들어오면 무조건 user.url 파일로 연결한다는 뜻이다

최종적으로 fetch() 함수로 받은 url 은 2개의 endpoint (=2개의 url 파일?)이 합쳐진 하나의 주소인 것을 알 수 있다

400 error

또다시 아이디 및 비밀번호를 입력했음에도 400 에러가 발생했다면

프론트엔드는

네트워크 패널에서 해당 오류된 부분을 클릭해서 Headers 영역에서 url 과 하단의 Request Payload 를 확인하면 되는데
여기서 passwrod 이 부분이 오타인 것을 확인 할 수 있다

Request Payload
{ email: "test07@gamil.com", passwrod: "testtest"}

백엔드개발자는 서버에서
"POST /users/signup HTTP/1.1" 400 24 라는 부분에서 400 에러가 뜬 것을 확인할 수 있다

한편
동일한 유저가 한 번 더 회원가입을 시도하려고 하면 400 에러가 발생하고
response 탭에서 response message를 확인하면 되는데 이러한 메시지 값을 통해 frontend에서 로직을 구현할 수 있다
이 때, response에서 key값을 text로 주는지 message로 주는지도 같이 확인하면 좋다

{"message": "USER_ALREADY_EXISTS"}

클라이언트와 서버의 통신이 성공했을 때의 200, 201 status

별 문제없이 200이나 201로 통신이 된 것을 확인이 되면 Headerssk Response로 관련된 내용을 확인할 수 있거나

서버를 통해서는 아래와 같이 내용을 확인할 수 있다

------------ [ 2. row ] -------------
id | 2
email | test07@gmail.com
password | $2b$12 ~~~ 
account | <null>
name | <null>
phone | <null>

비밀번호의 경우, 암호화되어있어서 서버에서도 비밀번호가 뭔지 확인이 안된다

로그인 성공했을 때의 token

이렇게 회원가입이 성공적으로 이루웠을 때 서버에 요청하는 API 주소의 endpoint 도 /signin으로 수정하고 다시 로그인페이지에 이동해서
올바른 아이디 및 비밀번호로 입력하면 로그인 성공이 되는데

이 때 서버에서 토큰을 받았는지 확인해야 한다

네트워크 탭에서 해당하는 signin 200 요소를 선택하고 response에서
{"token": ""} 의 형태로 frontend가 토근을 잘 받았는지 확인할 수 있다

frontend 에서는 이러한 token을 잘 받아야 한다

response 결과에 따른 분기로직 구현하기

이렇게 받은 토큰을 이용해 분기처리를 해주는데

.then(response => response.json())
  .then(response => {
    if (response.token) {
      localStorage.setItem('token', response.token);
      this.props.history.push('/main');
    } else alert ('아이디 / 비밀번호를 다시 입력해주세요!');
  })
  1. 만약 response에 token이라는 key가 존재한다면
    • localStoragedp token이라는 item에 response에 token 내용을 저장하고
    • main 페이지로 이동한다
if (response.token) {
  localStorage.setItem("token", response.token);
  this.props.history.push("/main");
}
  1. 만약 response에 token이라는 key가 없다면 alert를 띄운다
else alert ('아이디 / 비밀번호를 다시 입력해주세요!');

response 주의!!

response에는 특별하게 정해진 구조가 없기 때문에
클라이언트는 서버에서 어떻게 response를 보내주는지 console.log() 을 통해 직접 확인하고
서버에서 보내주는 response에 따라 로직을 구현하면 된다

💡 method: POSTMAN

서버에서 클라이언트 역할을 하는 건데
frontend와 backend가 바로 맞춰볼 수 없을 때
backend 혼자 테스트할 때 사용된다

API 명세서처럼 어떤 주소로 요청하면
어떤 데이터로 response 응답이 나가는지 정리하고 공유할 수 있다

이러한 특성을 통해서 frontend에서도 기능이 완성이 안되도
mock data를 통해 테스트를 하면서 데이터를 받는 test를 할 수 있다

프론트와 백엔드의 소통

따라서 frontend 와 backend는 구조나 key값 같은 내용을 서로서로 공유하면 좋은데
스프레드시트나 스웨거같은 tool을 사용해서 API 정의서를 만드는 것이 기본적이다

통신을 하기 전에 어떤 API가 있을 것이고
이러한 API들은 어떤 key이 있을 것인지, 어떤 response를 전달할 것인지 소통을 해야 한다

profile
새로운 것을 도전하고 노력한다

0개의 댓글