[Spring Boot] REST API 구현 연습해보기

Sarah·2025년 12월 17일

Spring Boot

목록 보기
15/17

지금까지 배운 rest api 구현을 연습해보려고 한다! 책이랑 정리한 내용 보지 않고 패턴과 흐름을 이해한대로 스스로 구현해보았다.

Entity

package com.example.firstproject.entity;

import com.example.firstproject.dto.PizzaDto;
import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.ToString;
import org.springframework.web.service.annotation.GetExchange;

@Entity
@AllArgsConstructor
@NoArgsConstructor
@Getter
@ToString
public class Pizza {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @Column
    private String name;
    @Column
    private String price;

    public static Pizza toEntity(PizzaDto dto) {
        if(dto.getId() != null) throw new IllegalArgumentException("피자 생성 실패! id가 없어야 합니다.");
        return new Pizza (
                dto.getId(),
                dto.getName(),
                dto.getPrice()
        );
    }

    public void patch(PizzaDto dto) {
        if(!this.getId().equals(dto.getId())) throw new IllegalArgumentException("피자 수정 실패! id가 일치하지 않습니다.");
        if(dto.getName() != null) this.name = dto.getName();
        if(dto.getPrice() != null) this.price = dto.getPrice();
    }
}

Repository

package com.example.firstproject.respository;

import com.example.firstproject.entity.Pizza;
import org.springframework.data.jpa.repository.JpaRepository;

public interface PizzaRepository extends JpaRepository<Pizza, Long> {
}

Dto

package com.example.firstproject.dto;

import com.example.firstproject.entity.Pizza;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.ToString;

@AllArgsConstructor
@NoArgsConstructor
@ToString
@Getter
public class PizzaDto {
    private Long id;
    private String name;
    private String price;

    public static PizzaDto createDto(Pizza p) {
        return new PizzaDto(
                p.getId(),
                p.getName(),
                p.getPrice()
        );
    }
}

ApiController

package com.example.firstproject.api;

import com.example.firstproject.dto.PizzaDto;
import com.example.firstproject.entity.Pizza;
import com.example.firstproject.service.PizzaService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
public class PizzaApiController {
    @Autowired
    PizzaService pizzaService;

    @GetMapping("/api/pizza")
    public ResponseEntity<List<PizzaDto>> index() {
        List<PizzaDto> pizzas = pizzaService.index();
        return ResponseEntity.status(HttpStatus.OK).body(pizzas);
    }

    @GetMapping("/api/pizza/{id}")
    public ResponseEntity<PizzaDto> show(@PathVariable Long id) {
        PizzaDto pizza = pizzaService.show(id);
        return ResponseEntity.status(HttpStatus.OK).body(pizza);
    }

    @PostMapping("/api/pizza")
    public ResponseEntity<PizzaDto> create(@RequestBody PizzaDto dto) {
        PizzaDto created = pizzaService.create(dto);
        return ResponseEntity.status(HttpStatus.OK).body(created);
    }

    @PatchMapping("/api/pizza/{id}")
    public ResponseEntity<PizzaDto> update(@PathVariable Long id, @RequestBody PizzaDto dto) {
        PizzaDto updated = pizzaService.update(id, dto);
        return ResponseEntity.status(HttpStatus.OK).body(updated);
    }

    @DeleteMapping("/api/pizza/{id}")
    public ResponseEntity<PizzaDto> delete(@PathVariable Long id) {
        PizzaDto deleted = pizzaService.delete(id);
        return ResponseEntity.status(HttpStatus.OK).body(deleted);
    }
}

Service

package com.example.firstproject.service;

import com.example.firstproject.dto.PizzaDto;
import com.example.firstproject.entity.Pizza;
import com.example.firstproject.respository.PizzaRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;

@Service
public class PizzaService {
    @Autowired
    private PizzaRepository pizzaRepository;



    public List<PizzaDto> index() {
        List<Pizza> pizzas = pizzaRepository.findAll();
        List<PizzaDto> dtos = new ArrayList<>();
        for(int i=0 ; i<pizzas.size() ; i++) {
            Pizza p = pizzas.get(i);
            PizzaDto dto = PizzaDto.createDto(p);
            dtos.add(dto);
        }
        return dtos;
    }

    public PizzaDto show(Long id) {
        Pizza pizza = pizzaRepository.findById(id)
                .orElseThrow(()-> new IllegalArgumentException("피자 조회 실패! 해당하는 피자가 없습니다."));
        PizzaDto dto = PizzaDto.createDto(pizza);
        return dto;
    }

    @Transactional
    public PizzaDto create(PizzaDto dto) {
        Pizza pizza = Pizza.toEntity(dto);
        Pizza created = pizzaRepository.save(pizza);
        return PizzaDto.createDto(created);
    }

    @Transactional
    public PizzaDto update(Long id, PizzaDto dto) {
        Pizza target = pizzaRepository.findById(id)
                .orElseThrow(()-> new IllegalArgumentException("피자 수정 실패! 해당하는 피자가 없습니다."));
        target.patch(dto);
        Pizza updated = pizzaRepository.save(target);
        return PizzaDto.createDto(updated);
    }

    @Transactional
    public PizzaDto delete(Long id) {
        Pizza target = pizzaRepository.findById(id)
                .orElseThrow(()-> new IllegalArgumentException("피자 삭제 실패! 해당하는 피자가 없습니다."));
        pizzaRepository.delete(target);
        return PizzaDto.createDto(target);
    }
}

정상작동!!!

아직 배운지 얼마되지 않아서 깔끔하고 완벽한 설계는 아니지만... 그래도 REST API CRUD를 구현할 수 있다는 것 만으로 나 자신을 칭찬해주고 싶다 ^^~

  • 추가로 로그를 어디에 찍어야 할지 더 생각해봐야 할 것 같다.
  • for문도 stream으로 작성하는 법을 더 익혀야 할 것 같다.
  • 테스트 코드도 작성하는 연습도 해야 할 것 같다...
profile
헤맨 만큼 내 땅

0개의 댓글