Notice
Recent Posts
Recent Comments
Link
«   2024/10   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31
Tags
more
Archives
Today
Total
관리 메뉴

wintertreey 님의 블로그

RESTful API_ application.yml, @RestController, Postman, 배포까지 본문

React

RESTful API_ application.yml, @RestController, Postman, 배포까지

wintertreey 2024. 8. 6. 09:35

리액트에서 ajax요청 +  spring에서 결과 보내주기(json)

db작업

create table memrest(num int primary key auto_increment,
name varchar(10), addr varchar(50));

insert into memrest(name, addr) values('신기해', '강남구 역삼1동 123번지');
insert into memrest(name, addr) values('고소해', '강남구 역삼2동 13번지');


백엔드 서버사이드 스프링작업

application.yml

 

자동으로 띄어쓰기가 안된다. 굉장히 불편..

 

application.yml은 application.properties 와 같은 일을 하는 파일로, 선택적으로 적용가능하다.

yml은 properties와 다르게 겹치는 앞부분은 적지않으며 띄어쓰기의 형식이 있다. 형식을 지키지 않으면 에러가 발생.

 

 

DTO

 

SQL문

4가지의 sql문 방법 중 이번에는 mybatis를 사용하는 방법

mapper에 이름을 붙여주었다. member라는,

 

 

Controller

평상시 정보전달방식은 임의로 자기가 원하는 정보전달방식(GET, POST) 중 하나를 선택하고,

매핑키워드도 (예: /go) 임의로 만들었었다. 

 

일반적인 get, post 방식으로 받아, spring이 처리.

package pack.controller;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import pack.dto.MemberDto;
import pack.repository.MemberDao;

@Controller
public class MemberController {
	@Autowired
	private MemberDao dao;

// 전체회원정보읽기
	@GetMapping("/members")
	public String list(Model model) {
		List<MemberDto> list = dao.getList();
		model.addAttribute("list", list);
		return "list";
	}
// 회원추가폼	
	@GetMapping("/insertform")
	public String insertfrom(Model model) {
		List<MemberDto> list = dao.getList();
		model.addAttribute("list", list);
		return "insertform";
	}
// 회원추가	
	@PostMapping("/insert")
	public String insert(@RequestParam("name") String name, @RequestParam("addr") String addr) {
		MemberDto dto = new MemberDto();
		dto.setName(name);
		dto.setAddr(addr);
		dao.insert(dto);
		return "redirect:/members";
	}

 

 

get메소드를 RESTful 하게 바꿔보자.

 

@ResponseBody

@ResponseBody 어노테이션을 메소드 레벨이나 메소드의 리턴 타입으로 붙이면, 메소드가 리턴하는 값을 HttpMessageConverter를 통해 Response body로 직렬화(serialization)하게 된다.

응답받는 데이터의 타입을 json으로 지정해준다.

 

@RestController

= @Controller + @ResponseBody

restful프로그램. 비동기처리 ajax처리.
비동기처리에서 사용. 객체데이터를 json형태로 변환하여 반환하는 역할.

 

@RestController 
public class MemberController {

@GetMapping("/members") // +@ResponseBody. 
	public MemberDto list(Model model) {
		//return "나이스"; //문자열그대로 클라이언트에게 리턴.
		
		MemberDto dto = new MemberDto();
		dto.setNum(1);
		dto.setName("주먹밥");
		dto.setAddr("강남구 역삼동");
		return dto; //{"num":1,"name":"주먹밥","addr":"강남구 역삼동"} 
        //자바객체를 json형태로 클라이언트에게 리턴
	}

 

만약 return "나이스";라고 적는다면, 문자열 그대로 즉 "나이스" 그대로 클라이언트에게 리턴해준다.

 

이를 이용하면 model.addAttribute를 사용하지 않고도 return이 된다.

dto형태로 리턴을 하면, 주석으로 적힌 것처럼 적힌 부분이 넘어간다.

 


앞서 적은 부분과 수정, 삭제부분을 포함하여

Restful 하게 변형해보자. 그러기 전에 RESTful하다~는것에 대해 살펴보고 넘어가자. 

restful하다는게 뭘까?

 

RESTful이란?

REST(Representational State Transfer)는 웹의 장점을 최대한 활용할 수 있는 아키텍처로, 최근의 서버 프로그램은 다양한 브라우저와 모바일 디바이스에서도 통신을 할 수 있어야 한다. REST 아키텍처는 Hypermedia API의 기본을 충실히 지키면서 범용성을 보장한다.


그러나 Rest API를 사용했다고 해서 모두 RESTful한 시스템이 되는것은 아니다.모든 CRUD 기능을 POST로 처리 하는 API, URI 규칙을 올바르게 지키지 않은 API는  
REST API를 사용하였더라도 설계규칙을 올바르게 지키지 못하였기에 RESTful 하지 못한 시스템이 된다.

 

REST 구성 3요소

 - 자원(Resource) - HTTP URI

  • RESTful 시스템에서는 모든 것이 자원이다. 자원은 URI(Uniform Resource Identifier)를 통해 식별된다.
  • 예를 들어, 사용자의 정보를 얻으려면 /users라는 URI를 사용할 수 있다.
  • 예 1: 사용자(User)
    • 자원 설명: 사용자 정보
    • URI 예시:
      • GET /users: 모든 사용자 목록을 가져온다.
      • GET /users/{id}: 특정 ID를 가진 사용자의 정보를 가져온다.
      • POST /users: 새로운 사용자를 생성한다.
      • PUT /users/{id}: 특정 ID를 가진 사용자의 정보를 업데이트한다.
      • DELETE /users/{id}: 특정 ID를 가진 사용자를 삭제한다.
    예 2: 블로그 게시물(Blog Post)
    • 자원 설명: 블로그 게시물
    • URI 예시:
      • GET /posts: 모든 블로그 게시물 목록을 가져온다.
      • GET /posts/{id}: 특정 ID를 가진 블로그 게시물의 정보를 가져온다.
      • POST /posts: 새로운 블로그 게시물을 생성한다.
      • PUT /posts/{id}: 특정 ID를 가진 블로그 게시물을 업데이트한다.
      • DELETE /posts/{id}: 특정 ID를 가진 블로그 게시물을 삭제한다.

 - 행위(Verb) - HTTP Method (GET, PUT, POST, DELETE 등)


 - 표현(Representations) - HTTP Message PayLoad( 전송되는 데이터 )

  • 자원은 다양한 형식(예: JSON, XML, HTML 등)으로 표현될 수 있다.
  • 클라이언트는 요청 헤더에서 원하는 표현 형식을 지정할 수 있다.
  • 표현의 주요 개념
      • 자원은 여러 가지 형식으로 표현될 수 있다. 가장 일반적인 형식은 JSON(JavaScript Object Notation)과 XML(Extensible Markup Language)이다.
      • 예를 들어, 사용자 자원은 JSON 또는 XML 형식으로 표현될 수 있다.
      • 서버는 응답할 때 Content-Type 헤더를 사용하여 표현의 형식을 명시한다.
      • 예: Content-Type: application/json은 응답이 JSON 형식임을 나타낸다.
      • 클라이언트는 요청할 때 Accept 헤더를 사용하여 원하는 표현 형식을 지정할 수 있다.
      • 예: Accept: application/json은 클라이언트가 JSON 형식의 응답을 원함을 나타낸다.
      • 서버는 클라이언트의 요청에 따라 자원을 적절한 형식으로 변환하여 응답할 수 있다.
      • 자원 자체는 변하지 않지만, 표현 형식은 클라이언트의 요구에 맞게 변경다.

         

서버 응답: 클라이언트가 JSON 형식을 원할 때:
GET /users/123
Accept: application/json

서버 응답:
HTTP/1.1 200 OK
Content-Type: application/json


    "id": 123,
    "name": "얼씨구",
    "email": "esg@example.com"
}

 

            메세지

상품명이 진라면인 상품생산한다.

자원                                   메소드(행위)

 

HTTP  POST   http://localhost/product

 

product

{

"name" : "진라면",

"price": "1000"

}


 

http 바디구조

HyperText Transfer Protocol

  • 하이퍼텍스트(HTML) 문서를 교환하기 위해 만들어진 protocol(통신 규약).
  • 즉 웹상에서 네트워크로 서버끼리 통신을 할때 어떠한 형식으로 서로 통신을 하자고 규정해 놓은 "통신 형식" 혹은 "통신 구조" 라고 보면 된다.
    프론트앤드 서버와 클라이언트간의 통신에 사용된다.
    또한 백앤드와 프론트앤드 서버간에의 통신에도 사용된다.
  • HTTP는 TCP/IP 기반으로 되어있다.
  • HTTP는 Stateless 이다.
    Stateless 란 말그대로 state(상태)를 저장하지 않는 다는 뜻.
    즉, 요청이 오면 그에 응답을 할뿐, 여러 요청/응답 끼리 연결되어 있지 않다는 뜻이다. 즉 각각의 요청/응답은 독립적인 요청/응답 이다.
    예를 들어, 클라이언트가 요청을 보내고 응답을 받은후, 조금 있다 다시 요청을 보낼때, 전에 보낸 요청/응답에 대해 알지 못한다는 뜻이다.
    그래서 만일 여러 요청과응답 의 진행과정이나 데이터가 필요할때는 쿠키나 세션 등등을 사용하게 된다.

HTTP Request 구조

HTTP request 메세지는 크게 3부분으로 구성된다:

  • start line
  • headers
  • body

Start Line

예시 ) GET /search HTTP/1.1

  • HTTP Method
    해당 request가 의도한 action을 정의하는 부분.
    HTTP Methods에는 GET, POST, PUT, DELETE, OPTIONS 등등이 있다.
    주로 GET 과 POST과 쓰임.
  • Request target
    해당 request가 전송되는 목표 uri.
    예를 들어 /login.
  • HTTP Version
    말 그대로 사용되는 HTTP 버젼. 버젼에는 1.0, 1.1, 2.0 등이 있다

Headers

  • 해당 request에 대한 추가 정보(addtional information)를 담고 있는 부분.
    예를 들어, request 메세지 body의 총 길이 (Content-Length) 등.
  • Key:Value 값으로 되어있다 (: 이 사용됨).
    key:value
    HOST: google.com => Key = HOST, Value = google.com

Body

해당 reqeust의 실제 메세지/내용.
Body가 없는 request도 많다.
예를 들어, GET request들은 대부분 body가 없는 경우가 많음.

 


@Responsebody, @Requestbody

스프링에서 비동기 처리를 하는 경우 @RequestBody , @ResponseBody를 사용한다.

클라이언트 -> 서버 요청 : @RequestBody 서버 -> 클라이언트 응답 : @ResponseBody

클라이언트에서 서버로 통신하는 메시지를 요청(request) 메시지라고 하며, 서버에서 클라이언트로 통신하는 메시지를 응답(response) 메시지라고 한다.

웹에서 화면전환(새로고침) 없이 이루어지는 동작들은 대부분 비동기 통신으로 이루어진다.

비동기통신을 하기위해서는 클라이언트에서 서버로 요청 메세지를 보낼 때, 본문에 데이터를 담아서 보내야 하고, 서버에서 클라이언트로 응답을 보낼때에도 본문에 데이터를 담아서 보내야 한다. 

이 본문이 바로 body 이다.

즉, 요청본문 requestBody, 응답본문 responseBody 을 담아서 보내야 한다. 

 

이때 본문에 담기는 데이터 형식은 여러가지 형태가 있겠지만 가장 대표적으로 사용되는 것이 JSON 이다.

즉, 비동기식 클라-서버 통신을 위해 JSON 형식의 데이터를 주고받는 것이다. 

 

@RequestBody 

json 기반의 HTTP Body를 자바 객체로 변환. @RequestBody 는 본문의 내용을 매핑해서 Entity 객체를 생성한다.

이 어노테이션이 붙은 파라미터에는 http요청의 본문(body)이 그대로 전달된다.

 

일반적인 GET/POST의 요청 파라미터라면 @RequestBody를 사용할 일이 없을 것이다.

반면에 xml이나 json기반의 메시지를 사용하는 요청의 경우에 이 방법이 매우 유용하다.

HTTP 요청의 바디내용을 통째로 자바객체로 변환해서 매핑된 메소드 파라미터로 전달해준다. 

 

@ResponseBody 

자바 객체를 json 기반의 HTTP Body로 변환

자바객체를 HTTP요청의 바디내용으로 매핑하여 클라이언트로 전송한다.

@ResponseBody 가 붙은 파라미터가 있으면 HTTP요청의 미디어타입과 파라미터의 타입을 먼저 확인한다.

 

 

다음은 restful의형식에 맞춰서 바꿔본 controller 부분이다.

@GetMapping("/members") //전체자료읽기
	public List<MemberDto> getList(){
		System.out.println("❄️get요청했네❄️");
		return dao.getList();// 자료를 읽어 그대로 리턴.
	}
	
	@PostMapping("/members") //자료추가하기
	public Map<String, Object> insert(@RequestBody MemberDto dto){
		//넣는작업은 끝남. 성공실패여부 확인해보고자 하단 작업 실시.
		Map<String, Object> map = new HashMap<String, Object>();
		map.put("isSuccess", true);
		return map;
		//상단의 3줄과 return Map.of("isSuccess", true); 동일
	}
	
	@GetMapping("/members/{num}") //자료1개읽기 //http://localhost:80/members/3
	//받을 내용만 {}이렇게 중괄호로 표시해준다. 그 안의 이름은 맘대로 설정가.
	public MemberDto getData(@PathVariable("num") int num){
		
		return dao.getData(num);
	}
	
	@PutMapping("/members/{num}") //자료수정하기
	public Map<String, Object> update(@PathVariable("num") int num, @RequestBody MemberDto dto){
		dto.setNum(num);
		dao.update(dto);
		
		return Map.of("isSuccess", true);
	}
	
	@DeleteMapping("/members/{num}")
	public Map<String, Object> delete(@PathVariable("num") int num){
		dao.delete(num);
		return Map.of("isSuccess", true);

	}

 

DAO

package pack.repository;

import java.util.List;

import org.apache.ibatis.session.SqlSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import pack.dto.MemberDto;

@Repository
public class MemberDao {
	
	@Autowired
	private SqlSession session;
	
	//회원자료 전체읽기
	public List<MemberDto> getList(){
		return session.selectList("member.getList");
	}
	
	//회원자료 추가하기
	public void insert(MemberDto dto) {
		session.insert("member.insert", dto);
	}
	//--------여기서부턴 리액트에서 수행--------------
	//회원자료 1개 읽어오기
	public MemberDto getData(int num) {
		return session.selectOne("member.getData", num);
	}
	
	//회원자료 수정하기
	public void update(MemberDto dto) {
		session.insert("member.update", dto);
	}
	// 회원자료 삭제하기
	public void delete(int num) {
		session.insert("member.delete", num);
	}
	
}

Postman

memberController.java작업 후 

리액트로 클라이언트사이드 작업하여 확인하기 전 

서버사이드가 제대로 굴러가는지 확인해볼수 있도록 도와주는 확장 프로그램

 

 

chrome에서 확장프로그램 > 웹 스토어에 방문> Postman을 다운받는다

 

전체자료읽기

 

추가
추가

REST의 3요소를 다음과 같이 확인할 수 있다. 

삭제

삭제할때는 respresentation이 없어도 무방하다.

 

 

이처럼 postman으로 확인할 수 있다.

이제 그럼 클라이언트사이드인 리액트를 구현하면 된다.


프론트엔트 클라이언트사이드 리액트작업

 

세팅작업

 

라우터설치

npm install react-router-dom

이번엔 fetch 대신 axios 쓰자.설치하기

npm install axios

 

package.json작업(이클립스의 스프링 아파치톰캣서버의 데이터를 json으로 받아와야하기에)

"proxy":"http://localhost:80"

 

필요할경우 부트스트랩도 설치

 

 

 

 

 

 index.js에서 라우트작업.

이렇게 브라우져라우터작업을 해줌으로써 해당  프로젝트 내에는 모두 라우터 작업이 됨.

 

Member.js

import { useState, useEffect } from "react";
import { Link, useNavigate } from "react-router-dom";
import axios from "axios";

export default function Member(){
    const [members, setMembers] = useState([]);

    const refresh = () => {
        //ajax 요청 설정(GET방식)
        axios.get("/members")
        .then(res => {
            //서버로부터 응답된 데이터를 이용해 state수정.
            setMembers(res.data)
        })
        .catch(error =>{ //에러발생시 
            console.log(error); //콘솔에 출력되게 함
        })
    }

    useEffect(() => {
        refresh(); //ajax 요청 처리 시작
    }, [])

    // 삭제 버튼 클릭시 이벤트핸들러함수
    const handleDelete = (num) => {
        //ajax 요청 설정(DELETE방식)
        axios.delete("/members/" + num)
        .then(res => {
            //삭제 후 목록보기
            refresh();
        })
        .catch(error =>{ //에러발생시 
            console.log(error); //콘솔에 출력되게 함
        })
    }
    
    //페이지이동함수
    const navigate = useNavigate(); //페이지이동시사용
 
    return(
        <>
         <Link to="/">홈페이지</Link>&nbsp;&nbsp;
         <Link to="/members/new">회원추가</Link>
         <h1>회원 목록</h1>
         <table>
            <thead>
                <tr>
                 <th>번호</th><th>이름</th><th>주소</th><th>수정</th><th>삭제</th>
                </tr>
            </thead>
            <tbody>
                {members.map(item => <tr key={item.num}>
                 <td>{item.num}</td><td>{item.name}</td><td>{item.addr}</td>
                 <td>
                    <button onClick={() => {
                    navigate(`/members/${item.num}/edit`)
                    }}>수정</button>
                 </td>
                 <td>
                    <button onClick={() => handleDelete(item.num)}>삭제</button>
                 </td>
                </tr>)}
            </tbody>
         </table>
        </>
    )
}

Link : 단순하게 페이지 이동을 할 경우 사용
 useNavigate(): 특정 이벤트를 실행하면 동작하도록하거나, 추가적인 로직이 필요한경우 사용

 

 

MemberForm.js

import axios from "axios";
import { useState } from "react";
import { useNavigate } from "react-router-dom";

export default function MemberForm(){
    const navigate = useNavigate();
    const [state, setState] = useState({});

    const handleChange = (e) => {
        setState({
            ...state,//전개연산자에의해 풀림
            [e.target.name]:e.target.value
        })
    }
    //추가버튼 클릭에 의한 이벤트 핸들러
    const handleSave = () => {
        //ajax 요청 설정(POST방식)
        axios.post("/members", state)
        .then(res => {
            if(res.data.isSuccess){
                alert("추가성공");
                navigate("/members") //추가 후 목록보기
                //페이지이동방법2: link. navigate. 
                //navigate는 이벤트에 의해서 페이지이동할경우 사용.
            }
        })
        .catch(error =>{ //에러발생시 
            console.log(error); //콘솔에 출력되게 함
        })
    }

    return(
        <>
         <h2>❄️회원 입력❄️</h2>
         <input onChange={handleChange} type="text" name="name" placeholder="이름을 입력하시오"></input>
         <br/>
         <input onChange={handleChange} type="text" name="addr" placeholder="주소를 입력하시오"></input>
         <br/>
        <button onClick={handleSave}>추가</button>
        </>
    )
}

 

MemberUpdateForm.js

import axios from "axios";
import { useState, useEffect} from "react";
import { useNavigate, useParams } from "react-router-dom";

export default function MemberUpdateForm(){
    // /members/:num/edit num값 읽기
    const {num} = useParams();

    //수정할 정보 state로 관리
    const [state, setState] = useState({
        num:0,
        name:"",
        addr:""

    });

    useEffect(() => {
        //ajax 요청 설정(GET방식): 수정자료1개읽기
        axios.get("/members" + num)
        .then(res => {
            //서버로부터 응답된 데이터를 이용해 state수정.
            //res.data는 {num:1, name: 홍길동, addr: 강남구}의 형태
            setState(res.data)
        })
        .catch(error =>{ //에러발생시 
            console.log(error); //콘솔에 출력되게 함
        })
    }, [num])

    const handleChange = (e) => {
        setState({
            ...state,//전개연산자에의해 풀림
            [e.target.name]:e.target.value
        })
    }

    const navigate = useNavigate();

    //수정버튼 클릭에 의한 이벤트 핸들러
    const handleSave = () => {
        //ajax 요청 설정(PUT방식)
        axios.put("/members/" + num, state)
        .then(res => {
                navigate("/members") //수정 후 목록보기
                //페이지이동방법2: link. navigate. 
                //navigate는 이벤트에 의해서 페이지이동할경우 사용.
        })
        .catch(error =>{ //에러발생시 
            console.log(error); //콘솔에 출력되게 함
        })
    }

    return(
        <>
        <h2>회원정보수정</h2>
        <div>
            <label>이름: </label>
            <input type="text" name="name" onChange={handleChange}></input>
        </div>
        <div>
            <label>주소: </label>
            <input type="text" name="addr" onChange={handleChange}></input>
        </div>
        <button onClick={handleSave}>수정확인</button>
        </>
    );
}

 

전체자료
추가
수정
삭제


리액트완료. 

 

이클립스 스프링으로 들어가서 배포해보자.

 

package.json 에 homepage 부분 추가.

서버죽이고 npm run build

작업공간에서의 build 폴더 파일들 복사해서 

이클립스 프로젝트의 static안에 넣어준다.

 

이클립스 서버 다시 살려서 run as 

웹서버띄워보면 완성!

 

 


https://cafe.daum.net/flowlife/HrhB/57

 

RESTful web programming

RESTful이란? REST(Representational State Transfer)는 웹의 장점을 최대한 활용할 수 있는 아키텍처로, 최근의 서버 프로그램은 다양한 브라우저와 모바일 디바이스에서도 통신을 할 수 있어야 한다. REST 아

cafe.daum.net

 

https://velog.io/@bloomspes/yaml-%ED%8C%8C%EC%9D%BC-%EC%9E%91%EC%84%B1-%EC%9A%94%EB%A0%B9-%EA%B8%B0%EC%B4%88%ED%8E%B8-%EC%8A%A4%ED%94%84%EB%A7%81%ED%8E%B8

 

yaml 파일 작성 요령 (기초편, 스프링편)

파이프라인을 설계 할 때, 크론잡을 만들 때, Dockerfile을 작성하거나 Kubernetes를 구성할 때, 우리가 필수로 마주하는 요소가 있다. 바로 yaml/yml 파일이다. 회사에 입사한지 일주일만에 큰 언론사의

velog.io

https://amy-it.tistory.com/112

 

[Spring] @RequestBody, @ResponseBody로 JSON 전송하기

목차 클라이언트에서 서버로 HTTP 요청(Request) 메시지를 보내면 서버에서는 클라이언트로 HTTP 응답(Response) 메시지를 보냅니다. HTTP Request와 Response 메시지에는 body, 즉 본문이 존재하는데요, 스프

amy-it.tistory.com

https://velog.io/@teddybearjung/HTTP-%EA%B5%AC%EC%A1%B0-%EB%B0%8F-%ED%95%B5%EC%8B%AC-%EC%9A%94%EC%86%8C

 

HTTP 구조 및 핵심 요소

하이퍼텍스트(HTML) 문서를 교환하기 위해 만들어진 protocol(통신 규약).즉 웹상에서 네트워크로 서버끼리 통신을 할때 어떠한 형식으로 서로 통신을 하자고 규정해 놓은 "통신 형식" 혹은 "통신 구

velog.io

https://cheershennah.tistory.com/179

 

[Spring] @RequestBody / @ResponseBody 어노테이션 이란?

스프링에서 비동기 처리를 하는 경우 @RequestBody , @ResponseBody를 사용한다. 비동기 처리를 위해 이 어노테이션들은 어떻게 작동할까? 클라이언트와 서버의 비동기 통신 클라이언트에서 서버로 통

cheershennah.tistory.com

https://velog.io/@nomonday/Spring-RequestBody-ResponseBody-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0

 

[Spring] @RequestBody, @ResponseBody 이해하기

스프링 프레임워크에서 비동기 통신, 즉 API 통신을 구현하기 위해 @RequestBody와 @ResponseBody 어노테이션을 사용한다.클라이언트 -> 서버 요청 : @RequestBody서버 -> 클라이언트 응답 : @ResponseBodyjson 기반

velog.io