Spring Boot

Spring Controller Annotations & CRUD

sounglikane 2024. 9. 30. 21:24

1. Spring Controller Annotations

1-1. @PathVariable

 

  • 하는 일: @PathVariable annotation은 요청 URL 경로에서 값을 추출하여 메서드 매개변수로 전달합니다.
  • 언제 사용: URL 자체에서 특정 값을 (예: ID) 가져와서 메서드의 인자로 사용할 때 @PathVariable을 사용합니다.
public class Star {
    String name;
    int age;

    public Star(String name, int age) {
        this.name = name;
        this.age = age;
    }
}

Java Class (Star)

 

@Controller
@RequestMapping("/hello/request")
public class RequestController {
    @GetMapping("/form/html")
    public String helloForm() {
        return "hello-request-form";
    }
// [Request sample]
@GetMapping("/star/{name}/age/{age}")
@ResponseBody
public String helloRequestPath(@PathVariable String name, @PathVariable int age)
{
    return String.format("Hello ! <br> name = %s, age = %d", name, age);
}

 

1-2. @RequestParam

 

  • 역할: @RequestParam annotation은 URL의 쿼리 매개변수에서 값을 추출합니다. 쿼리 매개변수는 URL에서 물음표(?) 뒤에 나오는 key-value 쌍입니다.
  • 언제 사용: URL의 쿼리 스트링에 포함된 매개변수를 추출할 때 @RequestParam을 사용합니다.
// [Request sample]
@GetMapping("/form/param")
@ResponseBody
public String helloGetRequestParam(@RequestParam (required = false) String name,  int age) {
    return String.format("Hello ! <br> name = %s, age = %d", name, age);
}

1-3.@ModelAttribute

 

  • 역할: @ModelAttribute annotation은 요청 데이터(폼 데이터나 쿼리 매개변수)를 모델 객체에 바인딩합니다. 주로 여러 필드를 가진 폼 데이터를 객체에 매핑할 때 사용합니다.
  • 언제 사용: 복잡한 폼 데이터를 처리하거나 여러 요청 매개변수를 객체에 직접 바인딩하고 싶을 때 @ModelAttribute를 사용합니다.
// [Request sample]
// Header
//  Content type: application/x-www-form-urlencoded
// Body
//  name=abdcd&age=122
@PostMapping("/form/model")
@ResponseBody
public String helloRequestBodyForm(@ModelAttribute Star star) {
    return String.format("Hello ! <br> (name = %s, age = %d) ", star.name, star.age);
}

1-4.@RequestBody

 

  • 하는 일: @RequestBody annotation은 요청 데이터(폼 데이터나 쿼리 매개변수)를 모델 객체에 바인딩합니다. 주로 여러 필드를 가진 폼 데이터를 객체에 매핑할 때 사용합니다.
  • 언제 사용: 복잡한 폼 데이터를 처리하거나 여러 요청 매개변수를 객체에 직접 바인딩하고 싶을 때 @ModelAttribute를 사용합니다.
// [Request sample]
// Header
//  Content type: application/json
// Body
//  {"name":"abcd","age":"123"}
@PostMapping("/form/json")
@ResponseBody
public String helloPostRequestJson(@RequestBody Star star) {
    return String.format("Hello, @RequestBody.<br> (name = %s, age = %d) ", star.name, star.age);
}

 

주요 포인트:

  • 데이터는 URL이나 쿼리 매개변수가 아닌, 요청의 본문(body) 에 담겨서 전송됩니다.
  • Spring은 메시지 변환기(예: Jackson)를 사용하여 요청 본문을 자바 객체로 변환합니다.

사용 사례:

다음과 같은 상황에서 @RequestBody를 자주 사용합니다:

  • RESTful API 작업 시.
  • 클라이언트가 JSON 또는 XML 데이터를 서버로 전송할 때.
  • 요청 본문에 있는 데이터를 자바 객체에 매핑하여 쉽게 처리하고 싶을 때.

 

Controller
Annotation 생략 가능
@PathVariable X
@RequestParam O
@ModelAttribute O
@RequestBody X

 

2. CRUD (Create - Read - Update - Delete)

DTO (Data Transfer Object)

DTO는 애플리케이션의 다른 부분들 사이에서 데이터를 전송하는 데 사용되는 간단한 객체입니다. 특히, 계층 간 데이터 전송(예: 서비스 계층에서 controller로, 또는 controller에서 client로)에서 자주 사용됩니다.

 

DTO 사용하는 이유

 

  • 보안: DTO를 사용하면 내부 구조(예: Database entity)를 클라이언트에게 노출시키지 않고, 필요한 데이터만 전달할 수 있습니다.
  • 데이터 구조화: Entity의 모든 필드를 반환할 필요가 없는 경우가 많습니다. DTO를 사용하면 전송할 데이터를 제어할 수 있습니다.
  • 관심사의 분리: DTO를 사용함으로써 비즈니스 로직과 데이터 전송 및 표시를 분리할 수 있습니다.
  • 직렬화 용이성(Easy Serialization): DTO는 단순한 객체이므로 JSON이나 XML로 쉽게 직렬화/역직렬화할 수 있습니다.

Sum up

 

  • DTO는 데이터를 전송하는 목적으로 사용되며, 비즈니스 로직을 포함하지 않습니다.
  • 보안, 데이터 제어, 관심사의 분리를 위해 DTO를 사용합니다.
  • 특히 RESTful API에서 클라이언트와 서버 간 데이터를 간편하게 전송하기 위해 많이 사용됩니다.

 

 

2-1. Create

 

  • 역할: 새 데이터를 데이터베이스나 시스템에 추가합니다.
  • 예시: 새로운 사용자, 상품, 글을 시스템에 추가하는 것.
  • HTTP 메서드: RESTful API에서는 주로 POST가 사용됩니다
import com.sparta.memo.dto.MemoRequestDto;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

@Getter
@Setter
@NoArgsConstructor
public class Memo {
    private Long id;
    private String username;
    private String contents;

    public Memo(MemoRequestDto requestDto) {
        this.username = requestDto.getUsername();
        this.contents = requestDto.getContents();
    }

    public void update(MemoRequestDto requestDto) {
        this.username = requestDto.getUsername();
        this.contents = requestDto.getContents();
    }
}

Java Class Memo (Entity)

 

import com.sparta.memo.dto.MemoRequestDto;
import com.sparta.memo.dto.MemoResponseDto;
import com.sparta.memo.entity.Memo;
import org.springframework.web.bind.annotation.*;

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

@RestController
@RequestMapping("/api")
public class MemoController {

    private final Map<Long, Memo> memoList = new HashMap<>();

    //CREATE
    @PostMapping("/memos")
    public MemoResponseDto createMemo(@RequestBody MemoRequestDto requestDto) {
        // RequestDto -> Entity
        Memo memo = new Memo(requestDto);

        //Memo Max ID check
        //Long maxId = memoList.size() > 0 ? Collections.max(memoList.keySet()) + 1 : 1;
        Long maxId = !memoList.isEmpty() ? Collections.max(memoList.keySet()) + 1 : 1;
        memo.setId(maxId);

        //DB 저장
        memoList.put(memo.getId(), memo);

        //Entity -> ResponseDto
        MemoResponseDto memoResponseDto = new MemoResponseDto(memo);
        return memoResponseDto;
    }

 

2-2. Read

 

  • 역할: 데이터베이스나 시스템에서 데이터를 조회합니다.
  • 예시: 사용자 목록을 조회하거나 특정 상품의 세부 정보를 가져오는 것.
  • HTTP 메서드: RESTful API에서는 주로 GET이 사용됩니다.
//READ
@GetMapping("/memos")
public List<MemoResponseDto> getMemos() {
    //Map to List
    List<MemoResponseDto> responseList = memoList.values().stream()
            .map(MemoResponseDto::new).toList();

    return responseList;
}

2-3. Update

 

  • 역할: 데이터베이스나 시스템에 있는 기존 데이터를 수정합니다.
  • 예시: 사용자의 이메일 주소를 변경하거나 상품의 가격을 수정하는 것.
  • HTTP 메서드: PUT 또는 PATCH가 사용됩니다. PUT은 전체 업데이트, PATCH는 부분 업데이트에 주로 사용됩니다.
//UPDATE
@PutMapping("/memos/{id}")
public Long updateMemo(@PathVariable Long id, @RequestBody MemoRequestDto requestDto) {
    //해당 memo가 DB에 존재하는지 확인
    if (memoList.containsKey(id)) {
        //해당 memo 가져오기
        Memo memo = memoList.get(id);

        //memo 수정
        memo.update(requestDto);
        return memo.getId();

    } else {
        throw new IllegalArgumentException("선택한 memo는 존재하지 얺습니다.");
    }
}

2-4. Delete

 

  • 역할: 데이터베이스나 시스템에 있는 기존 데이터를 삭제합니다.
  • 예시: 특정 사용자를 삭제하거나 상품을 목록에서 제거하는 것.
  • HTTP 메서드: RESTful API에서는 주로 DELETE가 사용됩니다.
//DELETE
    @DeleteMapping("/memos/{id}")
    public Long deleteMemo(@PathVariable Long id) {
        //해당 memo가 DB에 존재하는지 확인
        if (memoList.containsKey(id)) {
            //해당 memo를 삭제하기
            memoList.remove(id);
            return id;
        } else {
            throw new IllegalArgumentException("\"선택한 memo는 존재하지 얺습니다.\"");
        }
    }

}

 

CRUD 작업 개요

작업 HTTP method API 예시
Create POST  @PostMapping("/memos")
Read GET @GetMapping("/memos")
Update PUT/PATCH @PutMapping("/memos/{id}")
Delete DELETE  @DeleteMapping("/memos/{id}")