[TIL] 데이터 통신

신재욱·2023년 3월 15일
0
post-thumbnail

📒 오늘 공부한 내용

🔍수업목차

[3-1] 데이터 통신 기초
[3-2] HTTP
[3-3] JSON
[3-4] API
[3-5] CRUD
[3-6] API 명세서

✅ 데이터 통신 기초


보통 인터넷에 있는 데이터를 요청할 때에는 HTTP라는 프로토콜을 사용하며, 주소(URL, URI)를 통해 API에 접근할 수 있게 된다.

클라이언트와 서버는 웹에서 HTTP 프로토콜을 사용해서 통신한다.
클라이언트는 서버로 요청을 보내고, 서버는 요청에 따라 적절한 응답을 클라이언트로 회신한다.
필요에 따라 서버는 데이터베이스에 요청을 보내고, 회신 받은 응답을 활용한다.

💡 Client(클라이언트)란?

  • 클라이언트는 인터넷에 연결된 사용자의 디바이스, 또는 웹에 접근할 수 있는 소프트웨어를 뜻한다.
  • 대표적인 예로 브라우저가 있다.
  • 브라우저는 HTML, CSS, JavaScript 등으로 작성된 코드를 내부 엔진으로 해독하여 사용자가 쉽게 이해할 수 있는 형태의 컨텐츠로 보여주는 역할을 한다.

💡 Server(서버)란?

  • 서버는 클라이언트가 어떤 자원을 요청하면 해당 요청을 적절하게 처리하는 역할을 한다.

FTP : 파일을 주고 받을때

SMTP : 메일을 전송

HTTP : 텍스트 또는 라이퍼텍스트 HTML을 전송

✅ HTTP


💡 HTTP란?

  • 이렇게 클라이언트와 서버가 서로 요청과 응답을 주고받을 수 있는 것은 HTTP라는 통신 규약 덕분이다.

프로트에서 백엔드에 데이터를 요청하면 백엔드는 응답한다.
요청과 응답을 할때 그냥 보내는게 아니라 일정한 양식을 갖은 형태로 담아 전송한다.
주고받는 데이터 양식은 간략하게 헤더와 바디로 나눠진다.
헤더부분 : 보내는이, 보내는형태
바디부분 : 주요 내용

요청을 받은 백엔드는 DB에 저장된 자료를 찾아 응답한다.
응답역시 그냥 주는 것이 아닌 일정한 양식을 갖은 동일한 형태로 돌려준다.

💡 상태코드란?

  • 상태 코드는 3자리 숫자로 만들어져 있으며, 첫번째 자리는 1에서 5까지 제공된다.
  • 첫번째 자리가 4와 5인 경우는 정상적인 상황이 아니기 때문에 사이트 관리자가 즉시 알아야 하는 정보다.
  • 간략하게 상태코드에 대해 설명하자면 다음과 같다

1xx(정보) : 요청을 받았으며 프로세스를 계속 진행합니다.
2xx(성공) : 요청을 성공적으로 받았으며 인식했고 수용하였습니다.
3xx(리다이렉션) : 요청 완료를 위해 추가 작업 조치가 필요합니다.
4xx(클라이언트 오류) : 요청의 문법이 잘못되었거나 요청을 처리할 수 없습니다.
5xx(서버 오류) : 서버가 명백히 유효한 요청에 대한 충족을 실패했습니다.

📚 상태코드 정리

✅ JSON


💡JSON란?

서버에서 클라이언트로 데이터를 보낼 때 사용하는 양식. 클라이언트가 사용하는 언어에 관계 없이 통일된 데이터를 주고받을 수 있도록, 일정한 패턴을 지닌 문자열을 생성해 내보내면 클라이언트는 그를 해석해 데이터를 자기만의 방식으로 온전히 저장, 표시할 수 있는 것은 JSON 덕분이다.

JSON의 특징

  • 서버와 클라이언트 간의 교류에서 일반적으로 많이 사용된다.
  • 자바스크립트 객체 표기법과 유사
  • 자바스크립트를 이용하여 JSON 형식의 문서를 쉽게 자바스크립트 객채로 변환할 수 있다.
  • 자바스크립트의 문법과 굉장히 유사하지만 텍스트 형식일 뿐이다.
  • 특정 언어에 종속되지 않으며, 대부분의 프로그래밍 언어에서 JSON 포맷의 데이터를 핸들링 할 수 있는 라이브러리를 제공한다.

✅ API


우리는 실제로 앱을 만들때 통신을 한다는 건 필요한 도구들을 다운로드 받고 그 도구들을 활용하는 방식으로 통신하고 API가 바로 그것이다.

💡 API란?

이전에도 말했던 것처럼 API는 쉽게 생각해서 메뉴판이다.

  • 클라이언트가 서버에 요청할 때는 정확한 주문 방법에 따라 요청해야한다.
  • 서버는 클라이언트에게 리소스를 잘 활용할 수 있도록 인터페이스(interface)를 제공해줘야 한다.
    • 클라이언트는 서버가 어떻게 구성되어 있는지 알 방법이 없기 때문에 서버가 인터페이스를 제공해야한다. 이것을 API(Application Programming Interface)라고 한다.

API의 종류는 크게 rest-API, graphql-API 로 2가지가 있다.
rest-API 와 graphql-API 는 몇가지 차이점이 있다.

1. 함수 이름의 차이

  • rest-API는 API 이름이 마치 홈페이지 주소처럼 생겼다.
  • graphql-API는 API 이름이 일반적인 함수와 같다.

2. 응답 결과물의 차이

  • rest-API 는 응답 결과로 back-end 개발자가 만든 함수에서 보내주는 모든 데이터를 받아야만 한다.
  • graphql-API 는 back-end 개발자가 만든 함수에서 필요한 데이터만 골라 받을 수 있다.

이러한 이유로, 각 API에 전송을 요청하는 담당자도 다르다.

  • rest-API 에 요청하는 요청담당자는 axio 다.
  • graphql-API 에 요청하는 요청담당자는 apollo-client 다.

마지막으로 graphql필요한 데이터만 골라 받을 수 있는 장점이 있어서, 효율적인 통신을 할 수 있다.

3. 설치해야 할 프로그램의 차이

✅ CRUD


CRUD는 대부분의 컴퓨터 소프트웨어가 가지는 기본적인 데이터 처리 기능인 Create(생성), Read(읽기), Update(갱신), Delete(삭제)를 묶어서 일컫는 말이다. 사용자 인터페이스가 갖추어야 할 기능(정보의 참조/검색/갱신)을 가리키는 용어로서도 사용된다.

생성, 수정, 삭제, 조회에 따라 요청 명령어가 있는데 GRAPHQL은 생성, 수정, 삭제를 하나로 통합한다. 그러기에 MUTATION은 신중해야 된다.

실제 사용 방법은 위와 같다.

💡 한장에 정리

✅ API 명세서


💡 API 명세서란?

  • API 사용 설명서
  • 홈페이지를 만들기 전, Back-end 개발자가 만들어 놓은 API 가 몇 개 있고, 어떻게 구성되어있는지 확인하기 위해 필요하다.
  • API명세서는 Back-end 개발자에게 받아야 한다.
  • Back-end 개발자는 자신이 만든 API를 직접 문서 형태로 작성하거나, swagger 라는 프로그램을 설치해서 만든다.

✦ 출처

📚 코드캠프

📌 GRAPHQL _ playGround 실습


mutation{
  createProfile(name: "철수", age: 12, school: "다람쥐초등학교"){
    number
    message
  }
}
query{
  fetchProfile(name: "철수"){
    name
    age
    school
  }
}
mutation{
  createBoard(writer: "영희", title: "안녕하세요~", contents: "반갑습니다"){
    _id
    number
    message
  }
}
query{
  fetchBoard(number: 1204){
    title
    contents
  }
}
mutation{
  createProduct(
    seller: "철수"
    createProductInput: {
        name: "마우스",
      detail: "정말 좋은 마우스",
      price: 3000
      }
  ){
    _id
    number
    message
  }
}
query{
  fetchProduct(productId: "da4be0d5-505b-4ffe-90a9-997db1d4c496"){
    seller
    name
    price
  }
  }
mutation{
  updateProduct(
    productId: "da4be0d5-505b-4ffe-90a9-997db1d4c496"
    updateProductInput: {
      name: "키보드",
      price: 100000
    }
  ){
    _id
    number
    message
  }
}
query{
  fetchBoardsCount
}

📌 오늘 실습 결과

이미지

JSX

import { useState } from "react"
//==============================================>게시물 수정
import {
    Wrapper,
    Container,
    //--------------------> Box :)
    InPutBox,
    TwoBox,
    HeaderBox,
    AddressBox,
    YoutubeBox,
    AttachPicturesBox,
    MainSettingBox,
    RegistrationBox,
    //--------------------> 기타 :)
    Title,
    Label,
    Writer,
    Password,
    ZipButton,
    Pictures,
    RadioButton,
    RadioLabel,
    SubmitButton,
    CancelButton,
    PicturesOut,
    RadioOut,
    Error,
    //--------------------> Text :)
    WriterText,
    PasswordText,
    TitleText,
    ContentsText,
    ZipText,
    AddressText,
    YoutubeText,
} from "../../styles/Day2";

export default function BoardsNewPage() {


    //-------------------------------------------------------> Input에 들어가는 문구 :)
    const [writer, setWriter] = useState("")
    const [password, setPassword] = useState("")
    const [title, setTitle] = useState("")
    const [contents, setContents] = useState("")
    const [zip, setZip] = useState("07250")
    const [youtube, setYoutube] = useState("")

    //---------------------------------------------------------> Input error :(
    const [writerError, setWriterError] = useState("")
    const [passwordError, setPasswordError] = useState("")
    const [titleError, setTitleError] = useState("")
    const [contentsError, setContentsError] = useState("")
    const [zipError, setZipError] = useState("")

    //----------------------------------------------------------> event.target.value :)

    function onWriter(event) {
        setWriter(event.target.value)
        if (event.target.value !== "") {
            setWriterError("")
        }
    }

    function onPassword(event) {
        setPassword(event.target.value)
        if (event.target.value !== "") {
            setPasswordError("")
        }
    }

    function onTitle(event) {
        setTitle(event.target.value)
        if (event.target.value !== "") {
            setTitleError("")
        }
    }

    function onContents(event) {
        setContents(event.target.value)
        if (event.target.value !== "") {
            setContentsError("")
        }
    }

    //---------------------------------------------------------------> 1. 검증하기

    function onChangeSignup() {

        if (writer === "") {
            setWriterError("작성자를 다시 작성해주세요.")
        }
        if (password === "" && password.length < 3) {
            setPasswordError("비밀번호를 다시 작성해주세요.")
        }
        if (title === "") {
            setTitleError("제목을 다시 작성해주세요.")
        }
        if (contents === "") {
            setContentsError("내용을 다시 작성해주세요.")
        }
        if (writer !== "" && password !== "" && title !== "" && contents !== "") {
            alert("회원가입을 축하합니다!!")
        }

    }

    //------------------------------------------------------------->HTML :)

    return (
        <Wrapper>
            <Container>
                <HeaderBox>
                    <Title>게시물 수정</Title>
                </HeaderBox>
                <TwoBox>
                    <Writer>
                        <Label>작성자</Label>
                        <WriterText type="text" onChange={onWriter} placeholder="이름을 작성해주세요." />
                        <Error>{writerError}</Error>
                    </Writer>
                    <Password>
                        <Label>비밀번호</Label>
                        <PasswordText type="password" onChange={onPassword} placeholder="비밀번호를 작성해주세요." />
                        <Error>{passwordError}</Error>
                    </Password>
                </TwoBox>
                <InPutBox>
                    <Label>제목</Label>
                    <TitleText type="text" onChange={onTitle} placeholder="제목을 작성해주세요." />
                    <Error>{titleError}</Error>
                </InPutBox>
                <InPutBox>
                    <Label>내용</Label>
                    <ContentsText type="text" onChange={onContents} placeholder="내용을 작성해주세요." />
                    <Error>{contentsError}</Error>
                </InPutBox>
                <AddressBox>
                    <Label>주소</Label>
                    <ZipText type="text" placeholder="07250" />
                    <ZipButton>우편변호 검색</ZipButton>
                    <AddressText type="text" placeholder="" />
                    <AddressText type="text" placeholder="" />
                </AddressBox>
                <YoutubeBox>
                    <Label>유튜브</Label>
                    <YoutubeText type="text" placeholder="링크를 복사해주세요." />
                </YoutubeBox>
                <AttachPicturesBox>
                    <Label>사진 첨부</Label>
                    <PicturesOut>
                        <Pictures>+</Pictures>
                        <Pictures>+</Pictures>
                        <Pictures>+</Pictures>
                    </PicturesOut>
                </AttachPicturesBox>
                <MainSettingBox>
                    <Label>메인 설정</Label>
                    <RadioOut>
                        <RadioButton type="radio" name="myaRadio" />
                        <RadioLabel>유튜브</RadioLabel>
                        <RadioButton type="radio" name="myaRadio" />
                        <RadioLabel>사진</RadioLabel>
                    </RadioOut>
                </MainSettingBox>
                <RegistrationBox>
                    <CancelButton>취소하기</CancelButton>
                    <SubmitButton onClick={onChangeSignup}>등록하기</SubmitButton>
                </RegistrationBox>
            </Container>
        </Wrapper>
    );
}

CSS

import styled from "@emotion/styled";

export const Wrapper = styled.div`
  width: 1200px;
  /* height: 1847px; */
  border: 1px solid black;
  margin: 100px;
  padding-top: 80px;
  padding-bottom: 100px;
  padding-left: 102px;
  padding-right: 102px;
  display: flex;
  flex-direction: column;
  align-items: center;
  border: none;
  box-shadow: 0px 0px 10px gray;
`;

export const Container = styled.div`
width: 1000px;
`;

export const HeaderBox = styled.div`
font-weight: 700;
font-size: 36px;
line-height: 53px;
margin-bottom: 50px;
display: flex;
flex-direction: row;
justify-content: center;
cursor: pointer;
`;

export const InPutBox = styled.div`
margin-bottom: 50px;
display: flex;
flex-direction: column;
`;

export const TwoBox = styled.div`
margin-bottom: 50px;
display: flex;
flex-direction: row;
justify-content: space-between;
`;

export const AddressBox = styled.div`
`;

export const YoutubeBox = styled.div`

`;

export const AttachPicturesBox = styled.div`

`;

export const MainSettingBox = styled.div`

`;

export const RegistrationBox = styled.div`
display: flex;
align-items: center;
justify-content: center;
`;


export const Title = styled.div`

`;

export const Label = styled.div`
font-weight: 500;
font-size: 16px;
margin-bottom: 10px;
`;

export const Writer = styled.div`

`;


export const WriterText = styled.input`
width: 486px;
height: 52px;
padding-left: 20px;
`;

export const Password = styled.div`

`;

export const PasswordText = styled.input`
width: 486px;
height: 52px;
padding-left: 20px;
`;

export const TitleText = styled.input`
width: 1000px;
height: 52px;
padding-left: 20px;
`;

export const ContentsText = styled.input`
width: 1000px;
height: 480px;
display: flex;
padding-bottom: 430px;
padding-left: 20px;
`;

export const ZipText = styled.input`
width: 77px;
height: 52px;
margin-right: 20px;
padding-left: 18px;
`;

export const ZipButton = styled.button`
width: 124px;
height: 52px;
background: #000000;
color: white;
border-radius: 3px;
border: none;
cursor: pointer;

`;

export const AddressText = styled.input`
width: 1000px;
height: 52px;
margin-top: 15px;
margin-bottom: 20px;
padding-left: 20px;
`;

export const YoutubeText = styled.input`
width: 1000px;
height: 52px;
margin-bottom: 30px;
padding-left: 20px;
`;

export const PicturesOut = styled.div`
display: flex;
`;

export const Pictures = styled.button`
background-color: #BDBDBD;  
width: 78px;
height: 78px;
margin-right: 20px;
margin-top: 10px;
margin-bottom: 30px;
display: flex;
justify-content: center;
align-items: center;
border: none;
cursor: pointer;
&:hover {
  background: #aDaDaD;
  }
`;

export const RadioOut = styled.div`
display: flex;
align-items: center;
margin-bottom: 50px;
`;


export const RadioButton = styled.input`
width: 20px;
height: 20px;
cursor: pointer;
`;

export const RadioLabel = styled.div`
margin-left: 10px;
margin-right: 20px;
font-weight: 500;
font-size: 18px;
`;

export const SubmitButton = styled.button`
width: 179px;
height: 52px;
background: #FFe600;
border: none;
border-radius: 3px;
font-weight: 500;
font-size: 16px;
cursor: pointer;
&:hover {
  background: #FFd600;
  }
`;

export const CancelButton = styled.button`
width: 179px;
height: 52px;
background: #BDBDBD;
border: none;
border-radius: 3px;
font-weight: 500;
font-size: 16px;
margin-right: 20px;
cursor: pointer;
&:hover {
  background: #aDaDaD;
  }
`;

export const Error = styled.div`
font-size: 13px;
color: tomato;
margin-top: 5px;
margin-left: 10px;
`;

profile
1년차 프론트엔드 개발자

0개의 댓글