@Transactional
    public long createReview(CreateReviewRequest request) {
        ReviewGroup reviewGroup = validateReviewGroupByRequestCode(request.reviewRequestCode());
        Template template = templateRepository.findById(reviewGroup.getTemplateId())
                .orElseThrow(() -> new TemplateNotFoundByReviewGroupException(
                        reviewGroup.getId(), reviewGroup.getTemplateId()));
        validateSubmittedQuestionsContainedInTemplate(reviewGroup.getTemplateId(), request);
        validateOnlyRequiredQuestionsSubmitted(template, request);

        return saveReview(request, reviewGroup);
    }
@Test
    void 필수_질문에_모두_응답하는_경우_예외가_발생하지_않는다() {
        // 리뷰 그룹 저장
        String reviewRequestCode = "1234";
        reviewGroupRepository.save(new ReviewGroup("리뷰어", "프로젝트", reviewRequestCode, "12341234"));

        // 필수 선택형 질문, 섹션 저장
        Question alwaysRequiredQuestion = questionRepository.save(
                new Question(true, QuestionType.CHECKBOX, "질문", "가이드라인", 1)
        );
        OptionGroup alwaysRequiredOptionGroup = optionGroupRepository.save(
                new OptionGroup(alwaysRequiredQuestion.getId(), 1, 2)
        );
        OptionItem alwaysRequiredOptionItem1 = optionItemRepository.save(
                new OptionItem("선택지", alwaysRequiredOptionGroup.getId(), 1, OptionType.KEYWORD)
        );
        OptionItem alwaysRequiredOptionItem2 = optionItemRepository.save(
                new OptionItem("선택지", alwaysRequiredOptionGroup.getId(), 2, OptionType.KEYWORD)
        );
        Section alwaysRequiredSection = sectionRepository.save(
                new Section(VisibleType.ALWAYS, List.of(alwaysRequiredQuestion.getId()), null, "섹션명", "말머리", 1)
        );

        // 필수가 아닌 서술형 질문 저장
        Question notRequiredQuestion = questionRepository.save(
                new Question(false, QuestionType.TEXT, "질문", "가이드라인", 1)
        );
        Section notRequiredSection = sectionRepository.save(
                new Section(VisibleType.ALWAYS, List.of(notRequiredQuestion.getId()), null, "섹션명", "말머리", 1)
        );

        // optionItem 선택에 따라서 required 가 달라지는 섹션1 저장
        Question conditionalTextQuestion1 = questionRepository.save(
                new Question(true, QuestionType.TEXT, "질문", "가이드라인", 1)
        );
        Question conditionalCheckQuestion = questionRepository.save(
                new Question(true, QuestionType.CHECKBOX, "질문", "가이드라인", 1)
        );
        OptionGroup conditionalOptionGroup = optionGroupRepository.save(
                new OptionGroup(conditionalCheckQuestion.getId(), 1, 2)
        );
        OptionItem conditionalOptionItem = optionItemRepository.save(
                new OptionItem("선택지", conditionalOptionGroup.getId(), 1, OptionType.KEYWORD)
        );
        Section conditionalSection1 = sectionRepository.save(
                new Section(VisibleType.CONDITIONAL,
                        List.of(conditionalTextQuestion1.getId(), conditionalCheckQuestion.getId()),
                        alwaysRequiredOptionItem1.getId(), "섹션명", "말머리", 1)
        );

        // optionItem 선택에 따라서 required 가 달라지는 섹션2 저장
        Question conditionalQuestion2 = questionRepository.save(
                new Question(true, QuestionType.TEXT, "질문", "가이드라인", 1)
        );
        Section conditionalSection2 = sectionRepository.save(
                new Section(VisibleType.CONDITIONAL, List.of(conditionalQuestion2.getId()),
                        alwaysRequiredOptionItem2.getId(), "섹션명", "말머리", 1)
        );

        // 템플릿 저장
        templateRepository.save(new Template(
                List.of(alwaysRequiredSection.getId(), conditionalSection1.getId(),
                        conditionalSection2.getId(), notRequiredSection.getId())
        ));

        // 각 질문에 대한 답변 생성
        CreateReviewAnswerRequest alwaysRequiredAnswer = new CreateReviewAnswerRequest(
                alwaysRequiredQuestion.getId(), List.of(alwaysRequiredOptionItem1.getId()), null);
        CreateReviewAnswerRequest conditionalTextAnswer1 = new CreateReviewAnswerRequest(
                conditionalTextQuestion1.getId(), null, "답변".repeat(30));
        CreateReviewAnswerRequest conditionalCheckAnswer1 = new CreateReviewAnswerRequest(
                conditionalCheckQuestion.getId(), List.of(conditionalOptionItem.getId()), null);
        CreateReviewAnswerRequest conditionalTextAnswer2 = new CreateReviewAnswerRequest(
                conditionalQuestion2.getId(), null, "답변".repeat(30));

        // 상황별로 다르게 구성한 리뷰 생성 dto
        CreateReviewRequest properRequest = new CreateReviewRequest(
                reviewRequestCode, List.of(alwaysRequiredAnswer, conditionalTextAnswer1, conditionalCheckAnswer1));
        CreateReviewRequest selectedOptionIdQuestionMissingRequest1 = new CreateReviewRequest(
                reviewRequestCode, List.of(alwaysRequiredAnswer));
        CreateReviewRequest selectedOptionIdQuestionMissingRequest2 = new CreateReviewRequest(
                reviewRequestCode, List.of(alwaysRequiredAnswer, conditionalTextAnswer1));
        CreateReviewRequest selectedOptionIdQuestionMissingRequest3 = new CreateReviewRequest(
                reviewRequestCode, List.of(alwaysRequiredAnswer, conditionalCheckAnswer1));
        CreateReviewRequest unnecessaryQuestionIncludedRequest = new CreateReviewRequest(
                reviewRequestCode, List.of(alwaysRequiredAnswer, conditionalTextAnswer1,
                conditionalCheckAnswer1, conditionalTextAnswer2));

        // when, then
        assertThatCode(() -> createReviewService.createReview(properRequest))
                .doesNotThrowAnyException();
        assertThatCode(() -> createReviewService.createReview(selectedOptionIdQuestionMissingRequest1))
                .isInstanceOf(MissingRequiredQuestionException.class);
        assertThatCode(() -> createReviewService.createReview(selectedOptionIdQuestionMissingRequest2))
                .isInstanceOf(MissingRequiredQuestionException.class);
        assertThatCode(() -> createReviewService.createReview(selectedOptionIdQuestionMissingRequest3))
                .isInstanceOf(MissingRequiredQuestionException.class);
        assertThatCode(() -> createReviewService.createReview(unnecessaryQuestionIncludedRequest))
                .isInstanceOf(UnnecessaryQuestionIncludedException.class);
    }