Layered Architecture
๋ณต์กํ ์ํํธ์จ์ด๋ฅผ ๊ตฌ์กฐ์ ์ผ๋ก ๋๋ ์ ์ ์ง๋ณด์์ ํ์ฅ, ํ ์คํธ, ํ์ ์ ๋ ์ฝ๊ฒ ํ๋ ค๊ณ ๋ง๋ค์ด์ง ์ค๊ณ ๋ฐฉ์์ด๋ค.
์ฝ๋ ์ํด(Spaghetti code)๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด ์ ๋ ฅ/์ฒ๋ฆฌ/์ ์ฅ/์ถ๋ ฅ ๋ฑ์ ๊ฐ ๋จ๊ณ๋ก ์ญํ ๋ณ๋ก ๋ถ๋ฆฌํ์ฌ ๊ตฌ์ฑํ๋ค.
์ด์ ์ผ๋ก๋ ์๋์ ๊ฐ๋ค
1) ์ ๋ ฅ,์ฒ๋ฆฌ, ์ถ๋ ฅ ๋ก์ง์ ๋๋ ์ ๋ณต์ก๋๋ฅผ ๋ฎ์ถค
2) ๊ธฐ๋ฅ ์ถ๊ฐ๋ ์์ ์ ์ํฅ ๋ฒ์๊ฐ ์ค์ด๋ฆ
3) ๊ฐ ๋ ์ด์ด ๋จ์๋ก ๋จ์ ํ ์คํธ๊ฐ ๊ฐ๋ฅํจ
4) ๊ณตํต ๋ก์ง์ Service๋ Repository๋ก ๋ถ๋ฆฌํด์ ์ฌ์ฌ์ฉ ๊ฐ๋ฅํจ
5) UI, DB ๋ฑ ํน์ ๋ ์ด์ด ๊ธฐ์ ์ ๋ฐ๊พธ๊ธฐ ์ฌ์(์: JDBC->JPA)
์ฐธ๊ณ ๋ก ๋ฐ์ดํฐ ํ๋ฆ์ ์๋์ ๊ฐ๋ค.
ํด๋ผ์ด์ธํธ ↔ (HTTP) ↔ Controller→ Service→ Repository→ Database
์ดํด๋ฅผ ๋๊ธฐ ์ํ ์์
๋ ์คํ ๋ ์ฃผ๋ฌธ
[์ญํ ์ ๋ฐ๋ฅธ ๋ถ๋ฅ]
๊ณ ๊ฐ
์จ์ดํฐ - Controller
์ฃผ๋ฐฉ์ฅ - Service
์ฐฝ๊ณ - Repository
์ ์/๋ฐ์ค - Response
- ๊ณ ๊ฐ, ์จ์ดํฐ, ์ฃผ๋ฐฉ์ฅ, ์ฐฝ๊ณ , ์ ์/๋ฐ์ค๊ฐ ์กด์ฌํ๋ค.
- ๊ณ ๊ฐ์ด "ํผ์ ํ ํ ์ฃผ์ธ์" ์ฃผ๋ฌธ. ->์น ๋ธ๋ผ์ฐ์ ,์ฑ์์ HTTP์์ฒญ
- ์ฃผ๋ฌธ์๋ฅผ ๋ฐ๊ณ ์ฃผ๋ฐฉ์ฅ์๊ฒ ์ ๋ฌ -> @Controller/ @RestController
- ๋ ์ํผ๋๋ก ํผ์๋ฅผ ๋ง๋ค๊ณ ์์ค, ํ ํ์ ์ค๋นํ๋ค -> ๋น์ฆ๋์ค ๋ก์ง(๊ฒ์ฆ, ๊ณ์ฐ, ํธ๋์ญ์ )
- ๋ฐ๊ฐ๋ฃจ, ์น์ฆ ๊ฐ์ ์ฌ๋ฃ๋ฅผ ๊บผ๋ด๋ ๊ณณ -> DB์์ Entity ๊บผ๋ด๊ธฐ, ์ ์ฅํ๊ธฐ
- ์๋์๊ฒ ์์์ ๋ด์ ๋ด์ค๋ ๊ทธ๋ฆ, ํฌ์ฅ๋ฐ์ค -> Viewํ ํ๋ฆฟ ๋ ๋๋ง ๋๋ JSON์๋ต
์ ์์๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ๋ ์์ธํ ๋น๋์ด ๋ณด๊ฒ ๋ค.
1. ๊ณ ๊ฐ์ด ์ฃผ๋ฌธ์ (Request DTO)๋ฅผ ์์ฑ
{ "menu": "ํผ์", "size": "L", "toppings": ["์น์ฆ","ํํผ๋ก๋"] }
2. ์จ์ดํฐ(Controller)๊ฐ ์ฃผ๋ฌธ์๋ฅผ ๋ฐ์
๋งค์ฅ ์์ฌ์ฉ์ด๋ฉด ๊ทธ๋ฆ์ ๋ด์์ค -> ๋ทฐ ๋ฐํ
ํฌ์ฅ ์ฃผ๋ฌธ์ด๋ฉด ๋ฐ์ค์ ๋ด์์ค-> JSON๋ฐํ
3. ์จ์ดํฐ๊ฐ ์ฃผ๋ฐฉ์ฅ(Service)์๊ฒ
"์ด ์๋ ํผ์ ๋ง๋ค์ด์ฃผ์ธ์"
4. ์ฃผ๋ฐฉ์ฅ(Service)์
์ฌ๋ฃ๊ฐ ์ถฉ๋ถํ์ง ํ์ธ(Validation)
์ฐฝ๊ณ (Repository)์์ ๋ฐ๊ฐ๋ฃจ์ ์น์ฆ๋ฅผ ๊บผ๋ด๊ณ
๋ ์ํผ(๋น์ฆ๋์ค ๋ก์ง)์ ๋ฐ๋ผ ํผ์ ์์ฑ.
๋ง๋ค์ด์ง ํผ์๋ฅผ ๋ค์ ์จ์ดํฐ์๊ฒ ์ ๋ฌํ๋ค.
5. ๋งค์ฅ ์์ฌ๋ฉด ํ ํ๋ฆฟ ์ด๋ฆ์ ์๋ ค์ฃผ๊ฑฐ๋
ํฌ์ฅ ์ฃผ๋ฌธ์ด๋ฉด JSON์ผ๋ก ํฌ์ฅ ๋ฐ์ค์ ์ค์ด ์๋์๊ฒ ๋๋ ค์ค๋ค.
์ ์์๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ์ฝ๋์ ๋์ ํด ๋ณด๊ฒ ๋ค.
// 1) ์จ์ดํฐ(Controller)
@RestController // “ํฌ์ฅ ์ฃผ๋ฌธ ์ ๋ฌธ” (@Controller + @ResponseBody)
@RequestMapping("/orders") // /orders/** ๊ธฐ๋ณธ ๊ฒฝ๋ก
public class OrderController {
private final OrderService svc;
public OrderController(OrderService svc) { this.svc = svc; }
@PostMapping // ์๋์ด POST /orders ๋ก ์ฃผ๋ฌธ์ ์ ์ก
public OrderResponseDto order(
@RequestBody OrderRequestDto req // JSON ์ฃผ๋ฌธ์ → OrderRequestDto
) {
return svc.placeOrder(req); // ์ฃผ๋ฐฉ์ฅ์๊ฒ ์ฃผ๋ฌธ์ ๊ฑด๋ค๊ณ ๊ฒฐ๊ณผ ๋ฐ์
}
}
// 2) ์ฃผ๋ฐฉ์ฅ(Service)
@Service
@Transactional
public class OrderService {
private final IngredientRepo repo;
public OrderService(IngredientRepo repo) { this.repo = repo; }
public OrderResponseDto placeOrder(OrderRequestDto req) {
// 2-1) ์ฌ๋ฃ ์ฐฝ๊ณ ์์ ํ์ํ ์ฌ๋ฃ ๊บผ๋ด๊ธฐ
Ingredient dough = repo.findByName("๋ฐ๊ฐ๋ฃจ").get();
// 2-2) ๋ ์ํผ๋๋ก ํผ์ ๋ง๋ค๊ธฐ(๊ฒ์ฆ·๊ณ์ฐ ๋ฑ)
Pizza pizza = new Pizza(dough, req.getToppings());
// 2-3) ํผ์ ์์ฑ → ์๋์๊ฒ ์ ๋ฌํ DTO ์์ฑ
return new OrderResponseDto("์ฃผ๋ฌธ ์๋ฃ!", pizza.getSize());
}
}
// 3) ์ฐฝ๊ณ (Repository)
@Repository
public interface IngredientRepo extends JpaRepository<Ingredient, Long> {
Optional<Ingredient> findByName(String name);
}
์ด๋ ์์ ์ผ๋ก๋
1. Controller(์จ์ดํฐ)
์ฃผ๋ฌธ์ ๋ฐ๊ธฐ -> Service์ ์ ๋ฌ -> ๊ฒฐ๊ณผ ๋ฐ์์ ์๋์๊ฒ ๋๋ ค์ค
@RestController๋ฉด ์๋์ผ๋ก JSONํฌ์ฅ ๋ฐ์ค์ ๋ด์์ค
2. Service(์ฃผ๋ฐฉ์ฅ)
์ฌ๋ฃ ํ์ธ, ๊ฒ์ฆ, ์กฐ๋ฆฌ(๋น์ฆ๋์ค ๋ก์ง) -> ์์ ํ๊ฒ ํธ๋์ญ์ ์ฒ๋ฆฌ
3. Repository (์ฐฝ๊ณ )
DB์์ Entity(์ฌ๋ฃ) ๊บผ๋ด์ฃผ๊ธฐ, ๋ณด๊ดํ๊ธฐ
4. DTO vs Entity
DTO: ์ฃผ๋ฌธ์, ๋ฐ์ค(Controller <-> Service)
Entity: ์ฐฝ๊ณ ์ ์ค์ ์ฌ๋ฃ(Service <-> Repository)
์ดํด๊ฐ ๋์ผ๋ ์ด์ ๋ณธ๊ฒฉ์ ์ผ๋ก ์ด์ด๊ฐ ๋ณด๊ฒ ๋ค.
์ ์ฒด ์ํคํ ์ฒ ๊ฐ์
ํด๋ผ์ด์ธํธ ↔ (HTTP) ↔ Controller → Service → Repository → Database
๊ตฌํ ๋ก๋๋งต (๋จ๊ณ๋ณ ์์)
1) DTO ์ ์ (Controller ↔ Service)
2) Entity ์ ์ (Service ↔ Repository)
3) Repository ์ธํฐํ์ด์ค ์์ฑ
4) Service ๋ก์ง ๊ตฌํ
5) Controller ์๋ํฌ์ธํธ ๊ตฌํ
์ ๊ตฌํ ๋ก๋๋งด์ ๋ฐ๋ผ ์์๋๋ก ์ค๋ช ํ๊ณ ์ ํ๋ค.
1) DTO ์ ์ (Controller ↔ Service)
// src/main/java/com/example/demo/dto/OrderRequestDto.java
package com.example.demo.dto;
/**
* ํด๋ผ์ด์ธํธ(๊ณ ๊ฐ)๊ฐ ์๋ฒ์ ๋ณด๋ด๋ ์ฃผ๋ฌธ์ DTO
*/
public record OrderRequestDto(
String menu, // ์ฃผ๋ฌธํ ์ํ๋ช
, e.g. "ํผ์"
String size, // ๋ฉ๋ด ํฌ๊ธฐ, e.g. "L"
List<String> toppings // ์ถ๊ฐ ํ ํ ๋ชฉ๋ก
) {}
// src/main/java/com/example/demo/dto/OrderResponseDto.java
package com.example.demo.dto;
/**
* ์๋ฒ(์ฃผ๋ฐฉ)๊ฐ ํด๋ผ์ด์ธํธ์๊ฒ ๋๋ ค์ฃผ๋ ์๋ต DTO
*/
public record OrderResponseDto(
String status, // ์ฒ๋ฆฌ ๊ฒฐ๊ณผ ๋ฉ์์ง, e.g. "์ฃผ๋ฌธ ์๋ฃ!"
String size // ์์ฑ๋ ํผ์ ํฌ๊ธฐ ํ์ธ์ฉ
) {}
- OrderRequestDto: Controller๊ฐ ํด๋ผ์ด์ธํธ๋ก๋ถํฐ ๋ฐ์ JSON์ ๋งคํ
- OrderResponseDto: Service ๊ฒฐ๊ณผ๋ฅผ Controller๊ฐ JSON์ผ๋ก ๋ฐํ
2) Entity ์ ์ (Service ↔ Repository)
// src/main/java/com/example/demo/entity/Ingredient.java
package com.example.demo.entity;
import jakarta.persistence.*;
/**
* ์ฐฝ๊ณ (Repository)์์ ๊ด๋ฆฌํ๋ ์ค์ ์ฌ๋ฃ ์ํฐํฐ
* - DB์ ingredients ํ
์ด๋ธ๊ณผ 1:1 ๋งคํ๋จ
*/
@Entity
public class Ingredient {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id; // PK
private String name; // ์ฌ๋ฃ๋ช
, ์: "๋ฐ๊ฐ๋ฃจ", "์น์ฆ"
private int quantity; // ์ฌ๊ณ ์๋
// JPA ์คํ์ ๋ฐ๋์ ํ์ํ ๊ธฐ๋ณธ ์์ฑ์ (protected ๊ถ์ฅ)
protected Ingredient() {}
/**
* ์ ๊ท ์ฌ๊ณ ์ถ๊ฐ·์์ฑ์ฉ ์์ฑ์
* @param name ์ฌ๋ฃ๋ช
* @param quantity ์ด๊ธฐ ์ฌ๊ณ ์๋
*/
public Ingredient(String name, int quantity) {
this.name = name;
this.quantity = quantity;
}
// ————— ์ ๊ทผ์ ๋ฉ์๋ —————
public Long getId() {
return id;
}
public String getName() {
return name;
}
public int getQuantity() {
return quantity;
}
// ————— ๋๋ฉ์ธ ๋ก์ง ๋ฉ์๋ —————
/**
* ์ฌ๊ณ ๋ฅผ ์ฐจ๊ฐํ ๋ ์ฌ์ฉํ๋ ๋ฉ์๋
* @param amount ์ฐจ๊ฐํ ์๋
* @throws IllegalArgumentException ์ฌ๊ณ ๊ฐ ๋ถ์กฑํ๋ฉด ์์ธ ๋ฐ์
*/
public void decrease(int amount) {
if (amount < 0 || amount > this.quantity) {
throw new IllegalArgumentException("์ฌ๊ณ ๊ฐ ๋ถ์กฑํฉ๋๋ค. ํ์ฌ ์๋: " + this.quantity);
}
this.quantity -= amount;
}
}
- ์ด ํด๋์ค๋ Service์์ ๊บผ๋ด์จ Ingredient ๊ฐ์ฒด๋ฅผ ๊ฐ์ง๊ณ
์ค์ ์ฌ๊ณ ๋ฅผ ๊ฒ์ฆ·์ฐจ๊ฐํ๋ ๋น์ฆ๋์ค ๋ก์ง(๋๋ฉ์ธ ๋ฉ์๋)์ ํฌํจํ๋ค. - JPA ์ด๋
ธํ
์ด์
(@Entity, @Id, @GeneratedValue)์ผ๋ก
DB ํ ์ด๋ธ ๋งคํ ์ ๋ณด๋ฅผ ์ ์ธํ๋ค.
3) Repository ์ธํฐํ์ด์ค ์์ฑ
// src/main/java/com/example/demo/repository/IngredientRepository.java
package com.example.demo.repository;
import com.example.demo.entity.Ingredient;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.util.Optional;
/**
* ์ฐฝ๊ณ (Repository) ์ญํ ์ ์ํํ๋ ์ธํฐํ์ด์ค
* - JpaRepository๋ฅผ ํ์ฅํด ๊ธฐ๋ณธ CRUD ๊ธฐ๋ฅ ์ ๊ณต
* - ํ์ํ ๊ฒฝ์ฐ ๋ฉ์๋ ์๊ทธ๋์ฒ๋ง ์ ์ธํ๋ฉด Spring Data JPA๊ฐ ๊ตฌํ์ฒด ์๋ ์์ฑ
*/
@Repository
public interface IngredientRepository extends JpaRepository<Ingredient, Long> {
/**
* ์ฌ๋ฃ ์ด๋ฆ์ผ๋ก ๊ฒ์
* @param name ์ฌ๋ฃ๋ช
* @return ์ฌ๋ฃ ์ํฐํฐ Optional
*/
Optional<Ingredient> findByName(String name);
}
- JpaRepository<Ingredient, Long>
→ save(), findById(), findAll(), delete() ๋ฑ CRUD ๋ฉ์๋ ๊ธฐ๋ณธ ์ ๊ณต - findByName(String) ์๊ทธ๋์ฒ๋ง ์ ์ธํ๋ฉด, Spring Data JPA๊ฐ ๋ด๋ถ์ ์ผ๋ก SELECT * FROM ingredient WHERE name = ? ์ฟผ๋ฆฌ๋ฅผ ์์ฑํด ์ค๋ค.
4) Service ๋ก์ง ๊ตฌํ
// src/main/java/com/example/demo/service/OrderService.java
package com.example.demo.service;
import com.example.demo.dto.OrderRequestDto;
import com.example.demo.dto.OrderResponseDto;
import com.example.demo.entity.Ingredient;
import com.example.demo.repository.IngredientRepository;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
/**
* ์ฃผ๋ฐฉ์ฅ(Service) ์ญํ ์ ํ๋ ํด๋์ค
* - @Service: ์คํ๋ง ๋น์ผ๋ก ๋ฑ๋ก
* - @Transactional: ๋ฉ์๋ ์ ์ฒด๋ฅผ ํ๋์ ํธ๋์ญ์
์ผ๋ก ๋ฌถ์ด,
* ์ค๊ฐ์ ์์ธ ๋ฐ์ ์ ์๋ ๋กค๋ฐฑ ์ฒ๋ฆฌ
*/
@Service
@Transactional
public class OrderService {
private final IngredientRepository ingredientRepository;
// ์์ฑ์ ์ฃผ์
: IngredientRepository ๋น์ด ์๋ ์ฃผ์
๋จ
public OrderService(IngredientRepository ingredientRepository) {
this.ingredientRepository = ingredientRepository;
}
/**
* ์ฃผ๋ฌธ ์ฒ๋ฆฌ ๋น์ฆ๋์ค ๋ก์ง
* 1) ๋์ฐ ์ฌ๋ฃ ์กฐํ ๋ฐ ์ฌ๊ณ ์ฐจ๊ฐ
* 2) ํ ํ ์ฌ๋ฃ ์กฐํ ๋ฐ ์ฌ๊ณ ์ฐจ๊ฐ
* 3) ์ฃผ๋ฌธ ์ฌ์ด์ฆ ํ์ธ (์ถ๊ฐ ๊ณ์ฐ·ํ ์ธ ๋ก์ง ๋ฑ ํ์ฅ ๊ฐ๋ฅ)
* 4) ์ฃผ๋ฌธ ์๋ฃ ๋ฉ์์ง + ์ฌ์ด์ฆ๋ฅผ ๋ด์ ์๋ต DTO ๋ฐํ
*/
public OrderResponseDto placeOrder(OrderRequestDto request) {
// 1) ๋์ฐ ์ฌ๋ฃ(๋ฐ๊ฐ๋ฃจ) ์กฐํ → ์์ธ ์ฒ๋ฆฌ → ์ฌ๊ณ ์ฐจ๊ฐ
Ingredient dough = ingredientRepository.findByName("๋ฐ๊ฐ๋ฃจ")
.orElseThrow(() -> new IllegalArgumentException("๋์ฐ ์ฌ๋ฃ๊ฐ ์์ต๋๋ค: ๋ฐ๊ฐ๋ฃจ"));
dough.decrease(1);
ingredientRepository.save(dough);
// 2) ์์ฒญ๋ ๊ฐ ํ ํ๋ง๋ค ๋์ผ ์ฒ๋ฆฌ
for (String toppingName : request.toppings()) {
Ingredient topping = ingredientRepository.findByName(toppingName)
.orElseThrow(() -> new IllegalArgumentException("ํ ํ ์ฌ๋ฃ๊ฐ ์์ต๋๋ค: " + toppingName));
topping.decrease(1);
ingredientRepository.save(topping);
}
// 3) ์ฃผ๋ฌธ ํฌ๊ธฐ ํ์ธ (์ฌ๊ธฐ์ ์ถ๊ฐ ๋ก์ง์ ๋ถ์ผ ์ ์์)
String size = request.size();
// 4) ์ต์ข
์๋ต DTO ์์ฑ
return new OrderResponseDto(
"์ฃผ๋ฌธ ์๋ฃ! " + size + " ์ฌ์ด์ฆ ํผ์ ์ค๋น๋์์ต๋๋ค.",
size
);
}
}
- @Service: ๋น์ฆ๋์ค ๋ก์ง ๊ณ์ธต(Service Layer)์ ๋ํ๋.
- @Transactional: ๋ฉ์๋๊ฐ ํ๋์ ํธ๋์ญ์ ์ผ๋ก ์คํ๋๋ฉฐ, ์ค๊ฐ์ ์์ธ๊ฐ ํฐ์ง๋ฉด ๋ชจ๋ DB ๋ณ๊ฒฝ์ ๋กค๋ฐฑ.
- ingredientRepository.findByName(...): ์ฌ๊ณ ์กฐํ → ์์ผ๋ฉด IllegalArgumentException ๋ฐ์.
- decrease(1): Ingredient ์ํฐํฐ์ ๋๋ฉ์ธ ๋ฉ์๋๋ก ์ฌ๊ณ ์ฐจ๊ฐ, ๋ถ์กฑ ์ ์์ธ ๋ฐ์.
- ingredientRepository.save(...): ๋ณ๊ฒฝ๋ ์ฌ๊ณ ๋ฅผ DB์ ๋ฐ์.
- ๋ฐ๋ณต๋ฌธ ์์์ ์์ฒญ๋ ๋ชจ๋ ํ ํ๋ ๋์ผํ๊ฒ ์ฒ๋ฆฌํ๋ฉฐ, ์ดํ OrderResponseDto๋ฅผ ๋ง๋ค์ด Controller์ ๋ฐํํ๋ค.
5) Controller ์๋ํฌ์ธํธ ๊ตฌํ
// src/main/java/com/example/demo/controller/OrderController.java
package com.example.demo.controller;
import com.example.demo.dto.OrderRequestDto;
import com.example.demo.dto.OrderResponseDto;
import com.example.demo.service.OrderService;
import org.springframework.web.bind.annotation.*;
/**
* ์จ์ดํฐ(Controller) ์ญํ ์ ์ํํ๋ ํด๋์ค
* - @RestController: JSON API ์ ์ฉ ์ปจํธ๋กค๋ฌ
* - @RequestMapping("/orders"): ๊ณตํต URL ๊ธฐ๋ณธ ๊ฒฝ๋ก ์ค์
*/
@RestController
@RequestMapping("/orders")
public class OrderController {
private final OrderService orderService;
// ์์ฑ์ ์ฃผ์
: OrderService ๋น์ด ์๋์ผ๋ก ์ฃผ์
๋จ
public OrderController(OrderService orderService) {
this.orderService = orderService;
}
/**
* ์ฃผ๋ฌธ ์์ฑ ์๋ํฌ์ธํธ
* POST /orders
* - @RequestBody: ๋ค์ด์จ JSON ์์ฒญ ๋ฐ๋๋ฅผ OrderRequestDto๋ก ๋งคํ
* - ๋ฐํ๊ฐ OrderResponseDto๋ ์๋์ผ๋ก JSON ์ง๋ ฌํ๋์ด ์๋ต ๋ฐ๋์ ๋ด๊น
*/
@PostMapping
public OrderResponseDto createOrder(
@RequestBody OrderRequestDto requestDto
) {
// Service ๊ณ์ธต์ ์ฃผ๋ฌธ ์ฒ๋ฆฌ ๋ก์ง ์์ → ๊ฒฐ๊ณผ DTO ๋ฐํ
return orderService.placeOrder(requestDto);
}
/**
* (์ ํ) ์ ์ฒด ์ฌ๊ณ ์กฐํ ์์ ์๋ํฌ์ธํธ
* GET /orders/ingredients
* - ์์ฒญ ์์ด ํธ์ถ ์, Service์์ ์ฌ๊ณ ๋ชฉ๋ก์ ์กฐํํด ์ฌ ์ ์์
* - ์๋ ์์๋ Optional; ๋ฐ๋์ ํ์ํ์ง๋ ์์
*/
// @GetMapping("/ingredients")
// public List<IngredientDto> getAllIngredients() {
// return orderService.listAllIngredients();
// }
}
- @RestController
→ @Controller + @ResponseBody - @RequestMapping("/orders")
→ ์ด ํด๋์ค ๋ด๋ถ์ ๋ชจ๋ ๋ฉ์๋๋ /orders ๊ฒฝ๋ก๋ฅผ ๊ธฐ์ค์ผ๋ก ๋งคํ - @PostMapping
→ HTTP POST ์์ฒญ(POST /orders)์ ์ฒ๋ฆฌ - @RequestBody OrderRequestDto requestDto
→ ํด๋ผ์ด์ธํธ๊ฐ ๋ณด๋ธ JSON ์ฃผ๋ฌธ์๊ฐ OrderRequestDto๋ก ์๋ ๋ณํ - return orderService.placeOrder(requestDto)
→ Service์์ ์ฒ๋ฆฌ๋ OrderResponseDto๋ฅผ JSON์ผ๋ก ์๋ต
Postman(๋๋ curl)์ผ๋ก ํ ์คํธ
์ฃผ๋ฌธ ์์ฑ (POST /orders)
- URL: http://localhost:8080/orders
- Method: POST
- Header: Content-Type: application/json
- Body (raw JSON):
{
"menu": "ํผ์",
"size": "L",
"toppings": ["์น์ฆ", "ํํผ๋ก๋"]
}
์์ ์๋ต (200 OK):
{
"status": "์ฃผ๋ฌธ ์๋ฃ! L ์ฌ์ด์ฆ ํผ์ ์ค๋น๋์์ต๋๋ค.",
"size": "L"
}
'Backend > ๐ฑ Spring' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
| [Spring]์์กด๊ด๊ณ ์ฃผ์ (DI) (2) | 2025.07.28 |
|---|---|
| [Spring]Spring Bean (2) | 2025.07.28 |
| [Spring] Mapping (1) | 2025.07.23 |
| [Spring]MVC (4) | 2025.07.23 |
| [Spring] Spring! (1) | 2025.07.22 |