diff --git a/backend/src/main/java/net/pengcook/category/controller/CategoryController.java b/backend/src/main/java/net/pengcook/category/controller/CategoryController.java deleted file mode 100644 index 2c4434d6..00000000 --- a/backend/src/main/java/net/pengcook/category/controller/CategoryController.java +++ /dev/null @@ -1,25 +0,0 @@ -package net.pengcook.category.controller; - -import java.util.List; -import lombok.RequiredArgsConstructor; -import net.pengcook.category.dto.RecipeOfCategoryRequest; -import net.pengcook.category.service.CategoryService; -import net.pengcook.recipe.dto.MainRecipeResponse; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.ModelAttribute; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; - -@RestController -@RequiredArgsConstructor -@RequestMapping("/api/categories") -public class CategoryController { - - private final CategoryService categoryService; - - @GetMapping - public List readRecipesOfCategory(@ModelAttribute RecipeOfCategoryRequest request) { - return categoryService.readRecipesOfCategory(request); - } -} diff --git a/backend/src/main/java/net/pengcook/category/service/CategoryService.java b/backend/src/main/java/net/pengcook/category/service/CategoryService.java index 535d85f4..d0ae0d37 100644 --- a/backend/src/main/java/net/pengcook/category/service/CategoryService.java +++ b/backend/src/main/java/net/pengcook/category/service/CategoryService.java @@ -22,22 +22,11 @@ public class CategoryService { private final CategoryRepository categoryRepository; private final CategoryRecipeRepository categoryRecipeRepository; - private final RecipeRepository recipeRepository; - private final RecipeService recipeService; public void saveCategories(Recipe recipe, List categories) { categories.forEach(category -> saveCategoryRecipe(recipe, category)); } - public List readRecipesOfCategory(RecipeOfCategoryRequest request) { - String categoryName = request.category(); - Pageable pageable = PageRequest.of(request.pageNumber(), request.pageSize()); - List recipeIds = categoryRecipeRepository.findRecipeIdsByCategoryName(categoryName, pageable); - - List recipeDataResponses = recipeRepository.findRecipeData(recipeIds); - return recipeService.convertToMainRecipeResponses(recipeDataResponses); - } - private void saveCategoryRecipe(Recipe recipe, String name) { Category category = categoryRepository.findByName(name) .orElseGet(() -> categoryRepository.save(new Category(name))); diff --git a/backend/src/main/java/net/pengcook/recipe/controller/RecipeController.java b/backend/src/main/java/net/pengcook/recipe/controller/RecipeController.java index 3a63a744..cb3d0f7f 100644 --- a/backend/src/main/java/net/pengcook/recipe/controller/RecipeController.java +++ b/backend/src/main/java/net/pengcook/recipe/controller/RecipeController.java @@ -2,10 +2,12 @@ import java.util.List; import lombok.RequiredArgsConstructor; +import net.pengcook.category.dto.RecipeOfCategoryRequest; import net.pengcook.recipe.dto.MainRecipeResponse; import net.pengcook.recipe.dto.RecipeStepResponse; import net.pengcook.recipe.service.RecipeService; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; @@ -27,4 +29,9 @@ public List readRecipes(@RequestParam int pageNumber, @Reque public List readRecipeSteps(@PathVariable long id) { return recipeService.readRecipeSteps(id); } + + @GetMapping("/search") + public List readRecipesOfCategory(@ModelAttribute RecipeOfCategoryRequest request) { + return recipeService.readRecipesOfCategory(request); + } } diff --git a/backend/src/main/java/net/pengcook/recipe/service/RecipeService.java b/backend/src/main/java/net/pengcook/recipe/service/RecipeService.java index 8556e55f..b511f033 100644 --- a/backend/src/main/java/net/pengcook/recipe/service/RecipeService.java +++ b/backend/src/main/java/net/pengcook/recipe/service/RecipeService.java @@ -5,6 +5,8 @@ import java.util.List; import java.util.stream.Collectors; import lombok.RequiredArgsConstructor; +import net.pengcook.category.dto.RecipeOfCategoryRequest; +import net.pengcook.category.repository.CategoryRecipeRepository; import net.pengcook.recipe.domain.RecipeStep; import net.pengcook.recipe.dto.AuthorResponse; import net.pengcook.recipe.dto.CategoryResponse; @@ -24,6 +26,7 @@ public class RecipeService { private final RecipeRepository recipeRepository; private final RecipeStepRepository recipeStepRepository; + private final CategoryRecipeRepository categoryRecipeRepository; public List readRecipes(int pageNumber, int pageSize) { Pageable pageable = PageRequest.of(pageNumber, pageSize); @@ -38,13 +41,22 @@ public List readRecipeSteps(long id) { return convertToRecipeStepResponses(recipeSteps); } + public List readRecipesOfCategory(RecipeOfCategoryRequest request) { + String categoryName = request.category(); + Pageable pageable = PageRequest.of(request.pageNumber(), request.pageSize()); + List recipeIds = categoryRecipeRepository.findRecipeIdsByCategoryName(categoryName, pageable); + + List recipeDataResponses = recipeRepository.findRecipeData(recipeIds); + return convertToMainRecipeResponses(recipeDataResponses); + } + private List convertToRecipeStepResponses(List recipeSteps) { return recipeSteps.stream() .map(RecipeStepResponse::new) .toList(); } - public List convertToMainRecipeResponses(List recipeDataResponses) { + private List convertToMainRecipeResponses(List recipeDataResponses) { Collection> groupedRecipeData = recipeDataResponses.stream() .collect(Collectors.groupingBy(RecipeDataResponse::recipeId)) .values(); diff --git a/backend/src/test/java/net/pengcook/category/controller/CategoryControllerTest.java b/backend/src/test/java/net/pengcook/category/controller/CategoryControllerTest.java deleted file mode 100644 index e8da0b58..00000000 --- a/backend/src/test/java/net/pengcook/category/controller/CategoryControllerTest.java +++ /dev/null @@ -1,57 +0,0 @@ -package net.pengcook.category.controller; - -import io.restassured.RestAssured; -import net.pengcook.RestDocsSetting; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.test.context.jdbc.Sql; - -import static com.epages.restdocs.apispec.RestAssuredRestDocumentationWrapper.document; -import static org.hamcrest.Matchers.is; -import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; -import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields; -import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; -import static org.springframework.restdocs.request.RequestDocumentation.queryParameters; - -@Sql(value = "/data/category.sql") -class CategoryControllerTest extends RestDocsSetting { - - @Test - @DisplayName("레시피 개요 목록을 조회한다.") - void readRecipes() { - RestAssured.given(spec).log().all() - .filter(document(DEFAULT_RESTDOCS_PATH, - queryParameters( - parameterWithName("category").description("카테고리"), - parameterWithName("pageNumber").description("페이지 번호"), - parameterWithName("pageSize").description("페이지 크기") - ), - responseFields( - fieldWithPath("[]").description("레시피 목록"), - fieldWithPath("[].recipeId").description("레시피 아이디"), - fieldWithPath("[].title").description("레시피 제목"), - fieldWithPath("[].author").description("작성자 정보"), - fieldWithPath("[].author.authorId").description("작성자 아이디"), - fieldWithPath("[].author.authorName").description("작성자 이름"), - fieldWithPath("[].author.authorImage").description("작성자 이미지"), - fieldWithPath("[].cookingTime").description("조리 시간"), - fieldWithPath("[].thumbnail").description("썸네일 이미지"), - fieldWithPath("[].difficulty").description("난이도"), - fieldWithPath("[].likeCount").description("좋아요 수"), - fieldWithPath("[].description").description("레시피 설명"), - fieldWithPath("[].category").description("카테고리 목록"), - fieldWithPath("[].category[].categoryId").description("카테고리 아이디"), - fieldWithPath("[].category[].categoryName").description("카테고리 이름"), - fieldWithPath("[].ingredient").description("재료 목록"), - fieldWithPath("[].ingredient[].ingredientId").description("재료 아이디"), - fieldWithPath("[].ingredient[].ingredientName").description("재료 이름"), - fieldWithPath("[].ingredient[].requirement").description("재료 필수 여부") - ))) - .queryParam("category", "한식") - .queryParam("pageNumber", 0) - .queryParam("pageSize", 3) - .when().get("/api/categories") - .then().log().all() - .body("size()", is(3)); - } -} diff --git a/backend/src/test/java/net/pengcook/category/service/CategoryServiceTest.java b/backend/src/test/java/net/pengcook/category/service/CategoryServiceTest.java index 839fa0d3..89081ca1 100644 --- a/backend/src/test/java/net/pengcook/category/service/CategoryServiceTest.java +++ b/backend/src/test/java/net/pengcook/category/service/CategoryServiceTest.java @@ -6,19 +6,13 @@ import java.time.LocalDate; import java.time.LocalTime; import java.util.List; -import java.util.stream.Stream; -import net.pengcook.category.dto.RecipeOfCategoryRequest; import net.pengcook.category.repository.CategoryRecipeRepository; import net.pengcook.category.repository.CategoryRepository; import net.pengcook.recipe.domain.Recipe; -import net.pengcook.recipe.dto.MainRecipeResponse; import net.pengcook.recipe.service.RecipeService; import net.pengcook.user.domain.User; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.Arguments; -import org.junit.jupiter.params.provider.MethodSource; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; import org.springframework.context.annotation.Import; @@ -52,27 +46,4 @@ void saveCategories() { () -> assertThat(categoryRecipeRepository.count()).isEqualTo(INITIAL_CATEGORY_RECIPE_COUNT + 2) ); } - - @ParameterizedTest - @MethodSource("provideParameters") - @DisplayName("특정 카테고리의 레시피를 찾는다.") - void readRecipesOfCategory(int pageNumber, int pageSize, List expected) { - RecipeOfCategoryRequest request = new RecipeOfCategoryRequest("한식", pageNumber, pageSize); - - List mainRecipeResponses = categoryService.readRecipesOfCategory(request); - List actual = mainRecipeResponses.stream().map(MainRecipeResponse::recipeId).toList(); - - assertAll( - () -> assertThat(actual.size()).isEqualTo(pageSize), - () -> assertThat(actual).containsAll(expected) - ); - } - - static Stream provideParameters() { - return Stream.of( - Arguments.of(0, 2, List.of(2L, 3L)), - Arguments.of(1, 2, List.of(7L, 9L)), - Arguments.of(1, 3, List.of(9L, 14L, 15L)) - ); - } } diff --git a/backend/src/test/java/net/pengcook/recipe/controller/RecipeControllerTest.java b/backend/src/test/java/net/pengcook/recipe/controller/RecipeControllerTest.java index 74acce12..6c061f07 100644 --- a/backend/src/test/java/net/pengcook/recipe/controller/RecipeControllerTest.java +++ b/backend/src/test/java/net/pengcook/recipe/controller/RecipeControllerTest.java @@ -1,28 +1,21 @@ package net.pengcook.recipe.controller; +import static com.epages.restdocs.apispec.RestAssuredRestDocumentationWrapper.document; import static org.hamcrest.Matchers.is; +import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; +import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields; +import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; +import static org.springframework.restdocs.request.RequestDocumentation.queryParameters; import io.restassured.RestAssured; import io.restassured.http.ContentType; -import org.junit.jupiter.api.BeforeEach; +import net.pengcook.RestDocsSetting; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; -import org.springframework.boot.test.web.server.LocalServerPort; import org.springframework.test.context.jdbc.Sql; -@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) @Sql(value = "/data/recipe.sql") -class RecipeControllerTest { - - @LocalServerPort - private int port; - - @BeforeEach - void setUp() { - RestAssured.port = port; - } +class RecipeControllerTest extends RestDocsSetting { @Test @DisplayName("레시피 개요 목록을 조회한다.") @@ -45,4 +38,43 @@ void readRecipeSteps() { .then().log().all() .body("size()", is(3)); } + + @Test + @DisplayName("카테고리별 레시피 개요 목록을 조회한다.") + void readRecipesOfCategory() { + RestAssured.given(spec).log().all() + .filter(document(DEFAULT_RESTDOCS_PATH, + queryParameters( + parameterWithName("category").description("카테고리"), + parameterWithName("pageNumber").description("페이지 번호"), + parameterWithName("pageSize").description("페이지 크기") + ), + responseFields( + fieldWithPath("[]").description("레시피 목록"), + fieldWithPath("[].recipeId").description("레시피 아이디"), + fieldWithPath("[].title").description("레시피 제목"), + fieldWithPath("[].author").description("작성자 정보"), + fieldWithPath("[].author.authorId").description("작성자 아이디"), + fieldWithPath("[].author.authorName").description("작성자 이름"), + fieldWithPath("[].author.authorImage").description("작성자 이미지"), + fieldWithPath("[].cookingTime").description("조리 시간"), + fieldWithPath("[].thumbnail").description("썸네일 이미지"), + fieldWithPath("[].difficulty").description("난이도"), + fieldWithPath("[].likeCount").description("좋아요 수"), + fieldWithPath("[].description").description("레시피 설명"), + fieldWithPath("[].category").description("카테고리 목록"), + fieldWithPath("[].category[].categoryId").description("카테고리 아이디"), + fieldWithPath("[].category[].categoryName").description("카테고리 이름"), + fieldWithPath("[].ingredient").description("재료 목록"), + fieldWithPath("[].ingredient[].ingredientId").description("재료 아이디"), + fieldWithPath("[].ingredient[].ingredientName").description("재료 이름"), + fieldWithPath("[].ingredient[].requirement").description("재료 필수 여부") + ))) + .queryParam("category", "한식") + .queryParam("pageNumber", 0) + .queryParam("pageSize", 3) + .when().get("/api/recipes/search") + .then().log().all() + .body("size()", is(3)); + } } diff --git a/backend/src/test/java/net/pengcook/recipe/repository/RecipeRepositoryTest.java b/backend/src/test/java/net/pengcook/recipe/repository/RecipeRepositoryTest.java index b1bacf95..cec70361 100644 --- a/backend/src/test/java/net/pengcook/recipe/repository/RecipeRepositoryTest.java +++ b/backend/src/test/java/net/pengcook/recipe/repository/RecipeRepositoryTest.java @@ -29,21 +29,21 @@ void findRecipeIds() { List recipeIds = repository.findRecipeIds(pageable); - assertThat(recipeIds).containsExactly(4L, 3L, 2L); + assertThat(recipeIds).containsExactly(15L, 14L, 13L); } @Test @DisplayName("레시피 id에 해당되는 세부 정보를 반환한다.") void findRecipeData() { List recipeIds = List.of(4L, 3L); - RecipeDataResponse expectedData = new RecipeDataResponse(4, "흰쌀밥", 1, "loki", "loki.jpg", LocalTime.of(0, 40), - "흰쌀밥이미지.jpg", 2, 4, "흰쌀밥 조리법", 3, "채식", 2, "쌀", REQUIRED + RecipeDataResponse expectedData = new RecipeDataResponse(4, "토마토스파게티", 1, "loki", "loki.jpg", LocalTime.of(0, 30), + "토마토스파게티이미지.jpg", 3, 2, "토마토스파게티 조리법", 2, "양식", 2, "쌀", REQUIRED ); List recipeData = repository.findRecipeData(recipeIds); assertAll( - () -> assertThat(recipeData).hasSize(8), + () -> assertThat(recipeData).hasSize(6 + 3), () -> assertThat(recipeData).contains(expectedData) ); } diff --git a/backend/src/test/java/net/pengcook/recipe/service/RecipeServiceTest.java b/backend/src/test/java/net/pengcook/recipe/service/RecipeServiceTest.java index 9fe07511..6fe915f1 100644 --- a/backend/src/test/java/net/pengcook/recipe/service/RecipeServiceTest.java +++ b/backend/src/test/java/net/pengcook/recipe/service/RecipeServiceTest.java @@ -1,15 +1,20 @@ package net.pengcook.recipe.service; import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertAll; import java.util.Arrays; import java.util.List; +import java.util.stream.Stream; +import net.pengcook.category.dto.RecipeOfCategoryRequest; import net.pengcook.recipe.dto.MainRecipeResponse; import net.pengcook.recipe.dto.RecipeStepResponse; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.CsvSource; +import org.junit.jupiter.params.provider.MethodSource; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; import org.springframework.context.annotation.Import; @@ -24,7 +29,7 @@ class RecipeServiceTest { private RecipeService recipeService; @ParameterizedTest - @CsvSource(value = {"0,2,4", "1,2,2", "1,3,1"}) + @CsvSource(value = {"0,2,15", "1,2,13", "1,3,12"}) @DisplayName("요청받은 페이지의 레시피 개요 목록을 조회한다.") void readRecipes(int pageNumber, int pageSize, int expectedFirstRecipeId) { List mainRecipeResponses = recipeService.readRecipes(pageNumber, pageSize); @@ -46,4 +51,27 @@ void readRecipeSteps() { assertThat(recipeStepResponses).isEqualTo(expectedRecipeStepResponses); } + + @ParameterizedTest + @MethodSource("provideParameters") + @DisplayName("특정 카테고리의 레시피를 찾는다.") + void readRecipesOfCategory(int pageNumber, int pageSize, List expected) { + RecipeOfCategoryRequest request = new RecipeOfCategoryRequest("한식", pageNumber, pageSize); + + List mainRecipeResponses = recipeService.readRecipesOfCategory(request); + List actual = mainRecipeResponses.stream().map(MainRecipeResponse::recipeId).toList(); + + assertAll( + () -> assertThat(actual.size()).isEqualTo(pageSize), + () -> assertThat(actual).containsAll(expected) + ); + } + + static Stream provideParameters() { + return Stream.of( + Arguments.of(0, 2, List.of(2L, 3L)), + Arguments.of(1, 2, List.of(7L, 9L)), + Arguments.of(1, 3, List.of(9L, 14L, 15L)) + ); + } } diff --git a/backend/src/test/resources/data/recipe.sql b/backend/src/test/resources/data/recipe.sql index 6cbd2ad3..0731e34b 100644 --- a/backend/src/test/resources/data/recipe.sql +++ b/backend/src/test/resources/data/recipe.sql @@ -38,7 +38,56 @@ VALUES ('한식'), ('양식'), ('채식'), ('건강식'), - ('간편식'); + ('간편식'), + ('디저트'), + ('해산물'), + ('면요리'), + ('샐러드'), + ('스프'); + +INSERT INTO recipe (title, author_id, cooking_time, thumbnail, difficulty, like_count, description) +VALUES ('김치볶음밥', 1, '00:30:00', '김치볶음밥이미지.jpg', 3, 2, '김치볶음밥 조리법'), + ('김밥', 1, '01:00:00', '김밥이미지.jpg', 8, 1, '김밥 조리법'), + ('김치찌개', 1, '00:30:00', '김치찌개이미지.jpg', 3, 2, '김치찌개 조리법'), + ('토마토스파게티', 1, '00:30:00', '토마토스파게티이미지.jpg', 3, 2, '토마토스파게티 조리법'), + ('간장계란밥', 1, '00:10:00', '간장계란밥이미지.jpg', 1, 3, '간장계란밥 조리법'), + ('피자', 1, '00:30:00', '피자이미지.jpg', 3, 2, '피자 조리법'), + ('된장찌개', 1, '00:30:00', '된장찌개이미지.jpg', 3, 2, '된장찌개 조리법'), + ('햄버거', 1, '00:30:00', '햄버거이미지.jpg', 3, 2, '햄버거 조리법'), + ('흰쌀밥', 1, '00:40:00', '흰쌀밥이미지.jpg', 2, 4, '흰쌀밥 조리법'), + ('샐러드', 1, '00:15:00', '샐러드이미지.jpg', 1, 5, '샐러드 조리법'), + ('연어스테이크', 1, '00:45:00', '연어스테이크이미지.jpg', 4, 3, '연어스테이크 조리법'), + ('초콜릿 케이크', 1, '01:20:00', '초콜릿케이크이미지.jpg', 5, 6, '초콜릿 케이크 조리법'), + ('베지터블 스프', 1, '00:50:00', '베지터블스프이미지.jpg', 3, 2, '베지터블 스프 조리법'), + ('카레라이스', 1, '00:30:00', '카레라이스이미지.jpg', 3, 2, '카레라이스 조리법'), + ('새우볶음밥', 1, '00:25:00', '새우볶음밥이미지.jpg', 2, 3, '새우볶음밥 조리법'); + +INSERT INTO category_recipe (category_id, recipe_id) +VALUES (1, 2), -- 김밥은 한식 + (3, 2), -- 김밥은 채식 + (1, 3), -- 김치찌개는 한식 + (5, 3), -- 김치찌개는 간편식 + (2, 4), -- 토마토스파게티는 양식 + (4, 5), -- 간장계란밥은 건강식 + (5, 5), -- 간장계란밥은 간편식 + (2, 6), -- 피자는 양식 + (5, 6), -- 피자는 간편식 + (1, 7), -- 된장찌개는 한식 + (5, 7), -- 된장찌개는 간편식 + (2, 8), -- 햄버거는 양식 + (5, 8), -- 햄버거는 간편식 + (1, 9), -- 흰쌀밥은 한식 + (9, 10), -- 샐러드는 샐러드 + (4, 10), -- 샐러드는 건강식 + (7, 11), -- 연어스테이크는 해산물 + (2, 11), -- 연어스테이크는 양식 + (6, 12), -- 초콜릿 케이크는 디저트 + (10, 13),-- 베지터블 스프는 스프 + (3, 13), -- 베지터블 스프는 채식 + (1, 14), -- 카레라이스는 한식 + (5, 14), -- 카레라이스는 간편식 + (7, 15), -- 새우볶음밥은 해산물 + (1, 15); -- 새우볶음밥은 한식 INSERT INTO ingredient (name) VALUES ('김'), @@ -49,36 +98,51 @@ VALUES ('김'), ('후추'), ('간장'), ('소금'), - ('햄'); - -INSERT INTO recipe (title, author_id, cooking_time, thumbnail, difficulty, like_count, description) -VALUES ('김밥', 1, '01:00:00', '김밥이미지.jpg', 8, 1, '김밥 조리법'), - ('김치볶음밥', 2, '00:30:00', '김치볶음밥이미지.jpg', 3, 2, '김치볶음밥 조리법'), - ('간장계란밥', 3, '00:10:00', '간장계란밥이미지.jpg', 1, 3, '간장계란밥 조리법'), - ('흰쌀밥', 1, '00:40:00', '흰쌀밥이미지.jpg', 2, 4, '흰쌀밥 조리법'); - -INSERT INTO category_recipe (category_id, recipe_id) -VALUES (1, 1), - (4, 1), - (1, 2), - (3, 2), - (1, 3), - (5, 3), - (1, 4), - (3, 4); + ('햄'), + ('토마토'), + ('밀가루'), + ('새우'), + ('버터'), + ('설탕'), + ('초콜릿'), + ('버섯'), + ('양파'), + ('피망'); INSERT INTO ingredient_recipe (ingredient_id, recipe_id, requirement) -VALUES (1, 1, 'REQUIRED'), - (2, 1, 'REQUIRED'), - (3, 1, 'ALTERNATIVE'), - (4, 1, 'OPTIONAL'), - (2, 2, 'REQUIRED'), - (3, 2, 'OPTIONAL'), - (4, 2, 'REQUIRED'), - (2, 3, 'REQUIRED'), - (3, 3, 'REQUIRED'), - (7, 3, 'REQUIRED'), - (2, 4, 'REQUIRED'); +VALUES (1, 1, 'REQUIRED'), -- 김치볶음밥 + (2, 1, 'REQUIRED'), -- 김치볶음밥 + (3, 1, 'ALTERNATIVE'), -- 김치볶음밥 + (4, 1, 'OPTIONAL'), -- 김치볶음밥 + (2, 2, 'REQUIRED'), -- 김밥 + (3, 2, 'OPTIONAL'), -- 김밥 + (4, 2, 'REQUIRED'), -- 김밥 + (2, 3, 'REQUIRED'), -- 김치찌개 + (3, 3, 'REQUIRED'), -- 김치찌개 + (7, 3, 'REQUIRED'), -- 김치찌개 + (2, 4, 'REQUIRED'), -- 토마토스파게티 + (5, 4, 'OPTIONAL'), -- 토마토스파게티 + (10, 4, 'REQUIRED'), -- 토마토스파게티 + (8, 5, 'REQUIRED'), -- 간장계란밥 + (3, 5, 'REQUIRED'), -- 간장계란밥 + (9, 6, 'REQUIRED'), -- 피자 + (6, 6, 'OPTIONAL'), -- 피자 + (4, 7, 'REQUIRED'), -- 된장찌개 + (2, 7, 'REQUIRED'), -- 된장찌개 + (8, 8, 'OPTIONAL'), -- 햄버거 + (9, 8, 'REQUIRED'), -- 햄버거 + (2, 9, 'REQUIRED'), -- 흰쌀밥 + (1, 9, 'OPTIONAL'), -- 흰쌀밥 + (5, 10, 'REQUIRED'), -- 샐러드 + (8, 10, 'OPTIONAL'), -- 샐러드 + (11, 6, 'REQUIRED'), -- 피자 + (12, 15, 'REQUIRED'), -- 새우볶음밥 + (13, 15, 'OPTIONAL'), -- 새우볶음밥 + (14, 12, 'REQUIRED'), -- 초콜릿 케이크 + (15, 12, 'REQUIRED'), -- 초콜릿 케이크 + (16, 13, 'REQUIRED'), -- 베지터블 스프 + (17, 13, 'REQUIRED'), -- 베지터블 스프 + (18, 14, 'OPTIONAL'); -- 카레라이스 INSERT INTO recipe_step (recipe_id, image, description, sequence) VALUES (1, '레시피1 설명1 이미지', '레시피1 설명1', 1),