자바풀스택 과정/자바 풀 스택 : 수업내용정리

자바 풀 스택 3/21 하루 기록 079

파티피플지선 2025. 3. 21. 18:05

9:28경 학원 도착

 

 

 

 

 

<9:30 1교시>

어제 엊그제 수업 내용 일단 간신히 따라갔고,

 

 

npm 패키지에 코드 작성 예제에서 text area에서 코드 작성하기에 편리한 라이브러리 3가지 설치

 

 

 

<10:30 2교시~4교시>

// src/pages/Home.jsx

import axios from 'axios';
import React, { useRef, useState } from 'react';
import { Alert, Button, Form } from 'react-bootstrap';
import MarkDown from 'react-markdown';

function Home(props) {
    

    return (
        <div>
            <h1>인덱스 페이지 입니다.</h1>
            <button onClick={()=>{
                axios.get("/ping")
                .then(res=>{
                    alert(res.data);
                })
                .catch(error=>{
                    alert("응답하지 않음");
                });
            }}>Ping 요청 해보기</button>

            <Quiz />

        </div>
    );
}

function Quiz(){
    let quizs = [
        "콘솔창에 1~10 까지 순서대로 출력하는 code를 javascript 로 작성해 보세요",
        "myName 이라는 변수를 만들고 본인의 이름을 대입해 보세요",
        "object 에  name 이라는 키값으로 본인의 이름을 넣고 addr 이라는 키값으로 주소를 넣어보세요"
    ]; 
    
    const handleSubmit = ()=>{
        //질문과 입력한 답을 json 으로 전송한다.
        axios.post("/gemini/quiz", {
            quiz:quizs[state.index],
            answer:state.inputCode //state 에 있는 내용을 전송한다 
        })
        .then(res=>{
            // res.data 는 이런 모양의 object 이다 {isCorrect:true or false, comment:"마크다운"}
            console.log(res.data);
            setState({
                ...state,
                ...res.data,
                isAnswered:true
            })
        })
        .catch(error=>console.log(error));
    }

    const [state, setState] = useState({
        index:0, //문제의 index 값 state 로 관리 
        isAnswered:false,
        isCorrect:false,
        inputCode:"" //입력한 code 를 state 로 관리  
    });
    //다시 풀기 버튼을 눌렀을때 실행되는 함수
    const handleRetry = ()=>{
        setState({
            ...state, 
            isAnswered:false
        });
    }
    const handleNext = ()=>{
       //문제의 index 1 증가, isAnswered : false, inputCode:""
       setState({
            ...state,
            index:state.index+1,
            isAnswered:false,
            inputCode:""
       });
    }

    const handleChange = (e)=>{
        //입력한 내용을 바로 바로 state 에 반영하기
        setState({
            ...state,
            inputCode:e.target.value
        });
    }
   
    return (
        <>  
            { state.isAnswered ? 
                <div>
                    <h3>체점 결과</h3>
                    { state.isCorrect ?
                        <Alert variant='success' >축하 합니다 정답 입니다</Alert>
                        :
                        <Alert variant='danger' >오답 입니다</Alert>
                    }
                    <MarkDown >{state.comment}</MarkDown>
                    <Button onClick={handleRetry} variant='warning' className="me-3"> &larr; 다시 풀기</Button>
                    <Button onClick={handleNext} variant='success'>다음 문제 &rarr;</Button>
                </div>
            :
                <div>
                    <Form.Group className='mb-3'>
                        <Form.Label>{quizs[state.index]}</Form.Label>
                        <Form.Control onChange={handleChange} value={state.inputCode} as="textarea" rows="10"></Form.Control>
                    </Form.Group>
                    <Button onClick={handleSubmit}>제출</Button>
                </div>
            }
        </>
    )
}

export default Home;

 

import axios from 'axios';
import React, { useEffect, useState } from 'react';
import { Alert, Button, Form, ProgressBar } from 'react-bootstrap';
// gemini 가 응답한 markdown 을 해석하기 위한 페키지 설치 및 import
import MarkDown from 'react-markdown';
// CodeMirror 를 사용하기 위해 3개의 페키지를 설치 하고 import 해야 한다 
import CodeMirror from "@uiw/react-codemirror";
import { javascript } from "@codemirror/lang-javascript";
import { dracula } from "@uiw/codemirror-theme-dracula";
// MarkDown 에  코드 블럭을 prettify 하기 위해 
import rehypeHighlight from "rehype-highlight";
import "highlight.js/styles/github.css"; //github 과 동일한 스타일로 코드 디자인이 된다.
//import "highlight.js/styles/atom-one-dark.css"  // dark 테마 스타일 코드 

function Quiz(){
    const quizs = [
        { content: "1부터 10까지 숫자를 콘솔에 출력하는 JavaScript 코드를 작성하세요.", score: 10 },
        { content: "변수 `name`에 본인의 이름을 저장하는 코드를 작성하세요.", score: 10 },
        { content: "`num1`과 `num2` 두 숫자의 합을 구해서 출력하는 코드를 작성하세요.", score: 10 },
        { content: "`for` 문을 사용하여 1부터 5까지의 합을 계산하는 코드를 작성하세요.", score: 10 },
        { content: "`if`문을 사용하여 어떤 숫자가 짝수인지 홀수인지 출력하는 코드를 작성하세요.", score: 10 },
        { content: "객체 `person`을 만들고, 그 안에 `name`, `age` 속성을 추가해 보세요.", score: 10 },
        { content: "배열 `[1, 2, 3, 4, 5]`의 모든 요소를 순회하며 출력하는 코드를 작성하세요.", score: 10 },
        { content: "`function` 키워드를 사용해서 두 수를 곱하는 함수를 작성하세요.", score: 10 },
        { content: "`setTimeout`을 사용해서 3초 후에 'Hello'를 출력하는 코드를 작성하세요.", score: 10 },
        { content: "현재 날짜와 시간을 콘솔에 출력하는 코드를 작성하세요.", score: 10 }
      ];

    useEffect(()=>{
        //DB 에서 불러온 데이터를 state 에 넣어준다.
        setState({
            ...state,
            list:quizs
        })
    }, []);
    
    const handleSubmit = ()=>{
        //질문과 입력한 답을 json 으로 전송한다.
        axios.post("/gemini/quiz", {
            quiz:state.list[state.index],
            answer:state.inputCode //state 에 있는 내용을 전송한다 
        })
        .then(res=>{
            // res.data 는 이런 모양의 object 이다 {isCorrect:true or false, comment:"마크다운"}
            console.log(res.data);
            setState({
                ...state,
                ...res.data,
                isAnswered:true
            })
        })
        .catch(error=>console.log(error));
    }

    const [state, setState] = useState({
        list:[],
        index:0, //문제의 index 값 state 로 관리 
        isAnswered:false,
        isCorrect:false,
        inputCode:"" //입력한 code 를 state 로 관리  
    });
    //다시 풀기 버튼을 눌렀을때 실행되는 함수
    const handleRetry = ()=>{
        setState({
            ...state, 
            isAnswered:false
        });
    }
    const handleNext = ()=>{
       //문제의 index 1 증가, isAnswered : false, inputCode:""
       setState({
            ...state,
            index:state.index+1,
            isAnswered:false,
            inputCode:""
       });
    }
    return (
        <>  
            <h1> javascript 문제</h1>
            <ProgressBar now={50} label={"50%"} animated variant='success'/>
            { state.isAnswered ? 
                <div>
                    <h3>체점 결과</h3>
                    { state.isCorrect ?
                        <Alert variant='success' >축하 합니다 정답 입니다</Alert>
                        :
                        <Alert variant='danger' >오답 입니다</Alert>
                    }
                    <MarkDown rehypePlugins={rehypeHighlight}>{state.comment}</MarkDown>
                    <Button onClick={handleRetry} variant='warning' className="me-3"> &larr; 다시 풀기</Button>
                    <Button onClick={handleNext} variant='success'>다음 문제 &rarr;</Button>
                </div>
            :
                <div>
                    <p>
                        <strong>{`${state.index+1}.`}</strong> 
                        <MarkDown rehypePlugins={rehypeHighlight}>{state.list[state.index]}</MarkDown>
                    </p>
                    <CodeMirror style={{fontSize:"20px"}}
                        extensions={[javascript()]}
                        theme={dracula}
                        height='300px'
                        value={state.inputCode}
                        onChange={value => setState({...state, inputCode:value})}/>
            
                    <Button onClick={handleSubmit}>제출</Button>
                </div>
            }
        </>
    )
}

export default Quiz;

 

 

 

 

<14:30 5교시>

object를 json으로 json을 object로 만들기

Progress 바 기능 수정

 

 

<15:30 6교시>

reduce 함수는 배열의 방의 갯수만큼 호출되는데, sum 자리에는 최초호출시에는 초기값(0), 그리고 최종으로 함수에서 리턴한 값이 전달되고(cf. reduce 함수는 가장 마지막에 리턴한 값이 리턴된다), item 에는 배열에 저장된 아이템이 순서대로 전달된다.

 

배열에 저장된 모든 아이템을 활용해서 하나의 결과값을 얻어낸다.

 

<16:30 7교시>

 

 

어으 일단 어케어케 기능은 안되는 채로 따라왔다. 이따가 API 커밋해달라고 해야징.

import axios from 'axios';
import React, { useEffect, useState } from 'react';
import { Alert, Button, Form, ProgressBar } from 'react-bootstrap';
// gemini 가 응답한 markdown 을 해석하기 위한 페키지 설치 및 import
import MarkDown from 'react-markdown';
// CodeMirror 를 사용하기 위해 3개의 페키지를 설치 하고 import 해야 한다 
import CodeMirror from "@uiw/react-codemirror";
import { javascript } from "@codemirror/lang-javascript";
import { dracula } from "@uiw/codemirror-theme-dracula";
// MarkDown 에  코드 블럭을 prettify 하기 위해 
import rehypeHighlight from "rehype-highlight";
import "highlight.js/styles/github.css"; //github 과 동일한 스타일로 코드 디자인이 된다.
import ConfirmModal from '../components/ConfirmModal';
import { useNavigate } from 'react-router-dom';
//import "highlight.js/styles/atom-one-dark.css"  // dark 테마 스타일 코드 
import { AnimatePresence, motion } from "framer-motion";

function Quiz(){
    const quizs = [
        { content: "1부터 10까지 숫자를 콘솔에 출력하는 JavaScript 코드를 작성하세요.", score: 10 },
        { content: "변수 `name`에 본인의 이름을 저장하는 코드를 작성하세요.", score: 10 },
        { content: "`num1`과 `num2` 두 숫자의 합을 구해서 출력하는 코드를 작성하세요.", score: 10 },
        { content: "`for` 문을 사용하여 1부터 5까지의 합을 계산하는 코드를 작성하세요.", score: 10 },
        { content: "`if`문을 사용하여 어떤 숫자가 짝수인지 홀수인지 출력하는 코드를 작성하세요.", score: 10 },
        { content: "객체 `person`을 만들고, 그 안에 `name`, `age` 속성을 추가해 보세요.", score: 10 },
        { content: "배열 `[1, 2, 3, 4, 5]`의 모든 요소를 순회하며 출력하는 코드를 작성하세요.", score: 10 },
        { content: "`function` 키워드를 사용해서 두 수를 곱하는 함수를 작성하세요.", score: 10 },
        { content: "`setTimeout`을 사용해서 3초 후에 'Hello'를 출력하는 코드를 작성하세요.", score: 10 },
        { content: "현재 날짜와 시간을 콘솔에 출력하는 코드를 작성하세요.", score: 10 }
      ];

    useEffect(()=>{
        //DB 에서 불러온 데이터를 state 에 넣어준다.
        setState({
            ...state,
            list:quizs.map(item=>{
                //isCorrect 라는 키값으로 null 을 넣어준다. 
                item.isCorrect=null;
                return item;
            })
        })
    }, []);
    
    const handleSubmit = ()=>{
        //질문과 입력한 답을 json 으로 전송한다.
        axios.post("/gemini/quiz", {
            quiz:state.list[state.index].content,
            answer:state.inputCode //state 에 있는 내용을 전송한다 
        })
        .then(res=>{
            // res.data 는 이런 모양의 object 이다 {isCorrect:true or false, comment:"마크다운"}
            console.log(res.data);
            setState({
                ...state,
                ...res.data,
                isAnswered:true,
                list:state.list.map((item, index) => {
                    //만일 item 의 index 가 현재 문제를 푼 index 라면 
                    if(index === state.index){
                        //체점 결과를 넣어준다. 
                        item.isCorrect=res.data.isCorrect;
                    }
                    return item;
                }),
                progress: state.progress + state.list[state.index].score,
                isFinish:state.index===state.list.length-1
            })
        })
        .catch(error=>console.log(error));
    }

    const [state, setState] = useState({
        isFinish:false,
        progress:0,
        list:[],
        index:0, //문제의 index 값 state 로 관리 
        isAnswered:false,
        isCorrect:false,
        inputCode:"" //입력한 code 를 state 로 관리  
    });
    //다시 풀기 버튼을 눌렀을때 실행되는 함수
    const handleRetry = ()=>{
        setState({
            ...state, 
            isAnswered:false
        });
    }
    const handleNext = ()=>{
       //문제의 index 1 증가, isAnswered : false, inputCode:""
       setState({
            ...state,
            index:state.index+1,
            isAnswered:false,
            inputCode:""
       });
    }
    const handleFinish=()=>{
        //총점 계산하기
        // let totalScore=0
        // for(let i=0; i<state.list.length; i++){
        //     //i번째 item
        //     const item=state.list[i];
        //     //만일 정답을 맞췄으면
        //     if(item.isCorrect){
        //         //totalScore에 획득한 점수를 누적 시키기
        //         totalScore+=state.list[i].score
        //     }
        // }

        //reduce함수를 이용해서 총점 계산하기 
        const totalScore= state.list.reduce((sum,item)=>{
            if(item.isCorrect){
                return sum+item.score;
            }else{
                return sum
            }
        },0)

        //reduce함수 한줄로 쓰기
        //const totalScore3=state.list.reduce((sum,item)=>item.isCorrect?sum+item.score:sum,0)
        setModal({show:true,message:`${totalScore} 점입니다. 확인을 눌러 다시 풀거나 취소를 눌러 종료할 수 있습니다.`})
    }
    
    const handleYes=()=>{
        //초기상태로 만들기
        setState({ 
            isFinish:false,
            progress:0,
            list:quizs.map(item=>{
                //isCorrect 라는 키값으로 null 을 넣어준다. 
                item.isCorrect=null;
                return item;
            }),
            index:0, //문제의 index 값 state 로 관리 
            isAnswered:false,
            isCorrect:false,
            inputCode:""
        })
        setModal({show:false})
    }
    const navigate=useNavigate();

    const handleCancel=()=>{
        navigate("/")
        setModal({show:false})
    }
    const [modal, setModal]=useState({
        show:false, message:"",
    })
    const [show, setShow] = useState(true);
    return (
        
        <>  
             <button onClick={() => setShow(prev => !prev)}>토글</button>

            <AnimatePresence mode="wait">
            {show ? (
                <motion.p
                key="p1"
                initial={{ opacity: 0, y: 20 }}
                animate={{ opacity: 1, y: 0 }}
                exit={{ opacity: 0, y: -20 }}
                transition={{ duration: 0.3 }}
                >
                p1
                </motion.p>
            ) : (
                <motion.p
                key="p2"
                initial={{ opacity: 0, y: 20 }}
                animate={{ opacity: 1, y: 0 }}
                exit={{ opacity: 0, y: -20 }}
                transition={{ duration: 0.3 }}
                >
                p2
                </motion.p>
            )}
            </AnimatePresence>
            <ConfirmModal show={modal.show} message={modal.message} onYes={handleYes} onCancel={handleCancel}/>
            {/* <pre>{JSON.stringify(state, null, 2)}</pre> */}
            <h1> javascript 문제</h1>
            <ProgressBar now={state.progress} animated variant='success' className="mb-2"/>
            <ProgressBar>
                { state.list.map(item=> item.isCorrect !== null && 
                    <ProgressBar  now={item.score} animated variant={item.isCorrect ? "success" : "danger"}/>)}
            </ProgressBar>
            
            <button onClick={() => setShow(prev => !prev)}>토글</button>

            <AnimatePresence mode="wait">
            { state.isAnswered ? (
                <motion.p
                key="p1"
                initial={{ opacity: 0, y: 20 }}
                animate={{ opacity: 1, y: 0 }}
                exit={{ opacity: 0, y: -20 }}
                transition={{ duration: 0.3 }}
                >
                <div>
                    <h3>체점 결과</h3>
                    { state.isCorrect ?
                        <Alert variant='success' >축하 합니다 정답 입니다</Alert>
                        :
                        <Alert variant='danger' >오답 입니다</Alert>
                    }
                    <MarkDown rehypePlugins={rehypeHighlight}>{state.comment}</MarkDown>
                    <Button onClick={handleRetry} variant='warning' className="me-3"> &larr; 다시 풀기</Button>
                    {state.isFinish?
                        <Button onClick={handleNext} variant='success'>다음 문제 &rarr;</Button>
                    :
                        <Button onClick={handleFinish} variant='primary'>결과보기</Button>
                    }
                    
                </div>
                </motion.p>
            ) : (
                <motion.p
                key="p2"
                initial={{ opacity: 0, y: 20 }}
                animate={{ opacity: 1, y: 0 }}
                exit={{ opacity: 0, y: -20 }}
                transition={{ duration: 0.3 }}
                >
                {
                state.list.length > 0 && 
                <div>
                    <div>
                        <strong>{`${state.index+1}. 번 `}</strong> 
                        <strong>{`배점:${state.list[state.index].score}`}</strong>
                        <MarkDown rehypePlugins={rehypeHighlight}>{state.list[state.index].content}</MarkDown>
                    </div>
                    <CodeMirror style={{fontSize:"20px"}}
                        extensions={[javascript()]}
                        theme={dracula}
                        height='300px'
                        value={state.inputCode}
                        onChange={value => setState({...state, inputCode:value})}/>
            
                    <Button onClick={handleSubmit}>제출</Button>
                </div>
                }
                </motion.p>
            )}
            </AnimatePresence>
            {/* { state.isAnswered ? 
                <div>
                    <h3>체점 결과</h3>
                    { state.isCorrect ?
                        <Alert variant='success' >축하 합니다 정답 입니다</Alert>
                        :
                        <Alert variant='danger' >오답 입니다</Alert>
                    }
                    <MarkDown rehypePlugins={rehypeHighlight}>{state.comment}</MarkDown>
                    <Button onClick={handleRetry} variant='warning' className="me-3"> &larr; 다시 풀기</Button>
                    {state.isFinish?
                        <Button onClick={handleNext} variant='success'>다음 문제 &rarr;</Button>
                    :
                        <Button onClick={handleFinish} variant='primary'>결과보기</Button>
                    }
                    
                </div>
            :
                state.list.length > 0 && 
                <div>
                    <div>
                        <strong>{`${state.index+1}. 번 `}</strong> 
                        <strong>{`배점:${state.list[state.index].score}`}</strong>
                        <MarkDown rehypePlugins={rehypeHighlight}>{state.list[state.index].content}</MarkDown>
                    </div>
                    <CodeMirror style={{fontSize:"20px"}}
                        extensions={[javascript()]}
                        theme={dracula}
                        height='300px'
                        value={state.inputCode}
                        onChange={value => setState({...state, inputCode:value})}/>
            
                    <Button onClick={handleSubmit}>제출</Button>
                </div>
            } */}
        </>
    )
}

export default Quiz;

 


Get started with Motion for React | Motion for React (prev Framer Motion)

 

Get started with Motion for React | Motion for React (prev Framer Motion)

Get started with Motion for React with our installation guide and interactive examples.

motion.dev

 

위 링크에서 적용할 수 있는 애니메이션을 확인할 수 있다.

 

 

 

전체 페이지 전환에 대해서도 애니메이션을 부여할 수 있다.

 

 

<17:30 8교시> 

샘한테 코드 커밋해달라고 해서 긁어와서 해보니까 기능됐다. 내거는 뭐뭐 빠뜨려서 안된건지 비교해봐야지.