Http Method에 대해(POST Method 실습)

서지우·2023년 7월 31일
0

Spring Boot

목록 보기
6/18

REST

Http Method에 대해서 알기 위해서, 먼저 정의되는 것이 REST 이다.


REST란?

Representational State Transfer의 약자이며, 다음과 같다.

자원(Resource): URI
행위(Verb): HTTP Method
표현(Representations)

여기서 HTTP Method는 즉, REST를 지키면서 행위를 전달하는 방법이다 라고 생각하면 될 것 같다.


HTTP (HyperText Transfer Protocol)란?

텍스트 기반의 통신 규약으로 인터넷에서 데이터를 주고받을 수 있는 프로토콜이다.
이렇게 규약을 정해두었기 때문에 모든 프로그램이 이 규약에 맞춰 개발해서 서로 정보를 교환할 수 있게 되었다.


HTTP 동작

사용자가 브라우저를 통해서 어떠한 서비스를 url을 통하거나 다른 것을 통해서 요청(request)을 하면 서버에서는 해당 요청사항에 맞는 결과를 찾아서 사용자에게 응답(response)하는 형태로 동작한다.

요청 : client -> server
응답: server -> client

서버 : 어떠한 자료에 대한 접근을 관리하는 네트워크 상의 시스템 (요청에 대한 응답을 보내준다.)

클라이언트 : 그 자료에 접근할 수 있는 프로그램

Ex) 웹 브라우저, 핸드폰 어플리케이션 등...

HTML 문서만이 HTTP 통신을 위한 유일한 정보 문서는 아니다.

Plain text로 부터 JSON 데이터 및 XML과 같은 형태의 정보도 주고 받을 수 있으며, 보통은 클라이언트가 어떤 정보를 HTML 형태로 받고 싶은지, JSON 형태로 받고 싶은지 명시해주는 경우가 많다.


HTTP 특징

- HTTP 메시지는 HTTP 서버와 HTTP 클라이언트에 의해 해석이 된다.
- TCP/ IP를 이용하는 응용 프로토콜이다.
   (컴퓨터와 컴퓨터간에 데이터를 전송 할 수 있도록 하는 장치로 인터넷이라는 
   거대한 통신망을 통해 원하는 정보(데이터)를 주고 받는 기능을 이용하는 응용 프로토콜)
- HTTP는 연결 상태를 유지하지 않는 비연결성 프로토콜이다.
   (이러한 단점을 해결하기 위해 Cookie와 Session이 등장하였다.)
- HTTP는 연결을 유지하지 않는 프로토콜이기 때문에 요청/응답 방식으로 동작한다.


Http Method - 리퀘스트

HTTP Method는 크게 GET, POST, PUT, DELETE가 대표적이다.
보통 CRUD에서 다음과 같이 이용한다.

GET - 서버에서 데이터 가져오기
POST - 서버로 데이터 보내기
PUT - 서버의 데이터 수정하기
DELETE - 서버의 데이터 삭제하기

참고자료
REST 참고자료는 꼭 읽어보길..
HTTP Method란?
REST와 REST API란?


HTTP 상태코드

많은 코드가 있지만 그 중에 중요한 것만 적어놨다.

200 : 정상
400 : 유저가 잘못함
401 : 로그인 안함
403 : 권한 없음
404 : 페이지 없어
405 : 메소드 없어
500 : 개발자가 잘못만듦

참고자료
HTTP 상태코드 응답표


POST방식 실습

main.html

새 지역을 추가하기 위해 html에 버튼을 만들어준다.

    <div>
      <input id="newRegion" type="text" placeholder="새 지역" />
      <button id="addButton">추가</button>
    </div>

RegionsEntity.java

hr데이터베이스의 regions 테이블을 가져온다.
(주석으로 설명)

package com.example.hr1.model.regions.entity;
// DB 테이블명 + Entity

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

// 엔티티임을 명시
@Entity
// 데이터베이스의 테이블이름과 연동
@Table(name = "regions")
@NoArgsConstructor
@AllArgsConstructor
@Builder
@Getter
// 엔티티에서 setter는 꼭 필요할 때만 직접 만드는 것을 추천
// toString도 직접 만드는 것을 추천
public class RegionsEntity {

    // 기본키 (PK)에 @Id를 붙인다
    @Id
    // 데이터베이스에 있는 컬럼명을 연결
    // 컬럼의 속성을 맞춰주는 것이 좋다.
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "region_id", nullable = false, unique = true)
    private Integer regionId;

    @Column(name = "region_name", nullable = true)
    private String regionName;

    public void setRegionName(String regionName){
        this.regionName = regionName;
    }

    @Override
    public String toString() {
        return "RegionsEntity [regionId=" + regionId + ", regionName=" + regionName + "]";
    }

    
}

RegionsReposiotory.java

entity를 가져오기 위해 jpa를 이용해서 Repository를 만들어준다.
(주석으로 설명)

package com.example.hr1.model.regions.repository;

import java.util.List;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import com.example.hr1.model.regions.entity.RegionsEntity;


@Repository
public interface RegionsReposiotory extends JpaRepository<RegionsEntity, Integer> {
    // 특정 엔티티 단일 데이터 가져오기
    // select * from regions where region_id =? (밑에랑 같은 거)
    RegionsEntity findByRegionId(Integer regionId);

    // region_name으로 데이터 가져오기
    // region_name은 유니크하지 않기 때문에 여러개 가져올 수 있다.
    // RegionsEntity findByRegionName(String regionName);
    List<RegionsEntity> findByRegionName(String regionName);

    // region_id와 region_name이 둘다 조건에 맞을 때 == 단일값
    // find - select * from regions
    // by - where
    // and - and
    RegionsEntity findByRegionIdAndRegionName(Integer regionId, String regionName);
}

MainService.java

(특정 부분만 가져왔고, 주석으로 설명)

// 약속
// entity객체는 Service에서 빠져나가지 못한다.
// entity -> dto

@Service
@Transactional(readOnly = true) // 읽어온다
public class MainService {

    // IoC 컨테이너에서 RegionsRepository타입의 객체를 가져온다
    // 의존성 주입 DI
    @Autowired
    private RegionsReposiotory regionsReposiotory;

    @Transactional
    public void postMainData(ReqInsertMainDTO reqInsertMainDTO){

        // long count = regionsReposiotory.count();

        RegionsEntity regionsEntity = RegionsEntity.builder()
        // .regionId((int)count + 1)
        .regionName(reqInsertMainDTO.getRegionsName())
        .build();

        regionsReposiotory.save(regionsEntity);
    }
}

DTO를 만들어줘야함.


ReqInsertMainDTO

DTO는 화면에 필요한 것만 가져오면 된다. 지역이름만 필요하기 때문에 그것만 가져왔다.

package com.example.hr1.domain.main.dto;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.ToString;

@NoArgsConstructor
@AllArgsConstructor
@Getter
@ToString
public class ReqInsertMainDTO {
    private String regionsName;
}

MainControllerApiV1.java

화면이 아니라 데이터를 출력할 controller를 하나 만들어준다.

@RestController // 화면이 아니라 데이터를 출력하고 싶으면 사용, controller랑 responsebody를 포함
@RequestMapping("/api/v1/main") // 공통된 부분을 하나로 합치는 것
public class MainControllerApiV1 {

    @Autowired
    private MainService mainService;

    @GetMapping
    public @ResponseBody List<ResMainDTO> getMainData() { // 화면이 아니라 데이터를 보내겠다는 말
        return mainService.getMainPageData();
    }

    @PostMapping
    public ResponseDTO<Object> postMainData(@RequestBody ReqInsertMainDTO reqInsertMainDTO) { // 객체를 받을때
        // System.out.println(reqInsertMainDTO);
        mainService.postMainData(reqInsertMainDTO);

        return ResponseDTO.builder()
                .code(0)
                .message("region 등록에 성공했습니다.")
                .build();

    }

실습을 하고 화면 사진을 못찍었다..😥

ResponseDTO.java

응답받는 DTO를 하나 만들어 밑에 POSTMAN으로 테스트할 때 볼 수 있도록 한다.
폴더 구조

package com.example.hr1.common.dto;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
@NoArgsConstructor
@AllArgsConstructor
@Builder
@Getter
public class ResponseDTO<T> {
    private Integer code;
    private String message;
    private T data;
}

@RestController란?

스프링프레임워크 4.x 버전 이상부터 사용가능한 어노테이션으로 @Controller에 @ResponseBody가 결합된 어노테이션

컨트롤러 클래스에 @RestController를 붙이면, 컨트롤러 클래스 하위 메서드에 @ResponseBody 어노테이션을 붙이지 않아도 문자열과 JSON 등을 전송할 수 있다.


@Controller와 @RestController 차이점

@Controller은 뷰에 표시될 데이터가 있는 Model 객체를 만들고 올바른 뷰를 선택하는 일을 담당한다.
또한, @ResponseBody를 사용하여 HTTP Response Body에 데이터를 담아 요청을 완료할 수 있다.

@RestController을 사용하여 동일한 기능을 제공할 수 있다.
@Controller@ResponsBody의 동작을 하나로 결합한 편의 컨트롤러라 보면 된다.


@RequestBody란?

HTTP body안에 JSON을 VO에 맵핑하는 스프링 어노테이션

맵핑이 뭐냐면 그냥 값을 넣어줬다는 소리.

우리 시스템으로 날아온 JSON 형태의 데이터를 JAVA 객체에 자동으로 값을 넣어주는 어노테이션이@RequestBody다.

어노테이션을 선언해주는 것으로 VO(value object, 자바 객체)에 값이 자동으로 들어가기 때문이다
사용 예제는 아래와 같다.

@RestController
public class LoginController{   
    @RequestMapping("/login")
    public LoginVO test(@RequestBody User user){
        LoginVO loginVo = userService.login(user); 
        return loginVo;
    }
}

@ResponseBody란?

VO 객체를 JSON으로 바꿔서 HTTP body에 담는 스프링 어노테이션

@RequestBody와 반대로 @ResponseBody는 VO(value object, 자바 객체)를 JSON 형태로 변환해서 HTTP BODY에 담는 어노테이션이다.

@ResponseBody
@RequestMapping(value = "/test")
public LoginVO test() throws Exception {

  LoginVO loginVO = new LoginVO();
  loginVO.setId("admin");

  return loginVO;
}

@ResponseBody를 생략하는 방법
@RestController를 사용하면 리턴 값에 자동으로 @ResponseBody가 붙는 효과가 있다.

@RestController
public class LoginController{  
    @RequestMapping("/login")
    public LoginVO test(@RequestBody User user){
        LoginVO loginVo = userService.login(user); 
        return loginVo;
    }
}

POSTMAN 설치 및 사용

json formatter
크롬 확장도구에서 설치를 하면 여기서
아래와 같이 보기 편하게 나온다.


구글창에 POSTMAN검색해서 페이지에 들어가 download를 클릭해준다.

운영체제에 맞게 설치한다.

get방식으로 url을 적어서 send하면 지역 리스트가 나온다.

위의 지역을 추가하기 위해 PostMapping을 사용하였기 때문에 POSTMAN에서 서버 테스트를 해본다.

localhost주소를 적어 send를 보냈을 때 이렇게 400에러가 나는 것은 개발자가 잘못한게 아니라 클라이언트가 잘 못 입력했기 때문이다.

그래서 post로 raw, json을 클릭해서 지역을 넣어주고 send해주면 200이 뜨는 것을 확인할 수 있다.
정상으로 들어간 것이다.
(콘솔에서도 확인해야 한다!!)

원래 responseDTO를 만들고 넣고 실행한 건데 후에 업로드를 하느라 좀 뒤죽박죽이다..이해해주세욤..🙇🏻‍♀️

message에 등록에 성공했다는 것이 나오고 DB에 들어가면 들어간 것을 볼 수 있다.

profile
미래가 기대되는 풀스택개발자 공부 이야기~~

0개의 댓글