<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>sinwoo_dev.log</title>
        <link>https://velog.io/</link>
        <description>저는 현재 경북소프트웨어고등학교에서 프로그래밍 공부를 하면서 개발하는 활기차고 도전적인 학생 개발자 김신우 입니다.</description>
        <lastBuildDate>Fri, 03 Jan 2025 14:04:39 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>sinwoo_dev.log</title>
            <url>https://velog.velcdn.com/images/sinwoo_dev/profile/850d6ee7-22f3-4bf7-8d45-f60f6286794a/image.jpeg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. sinwoo_dev.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/sinwoo_dev" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[2학년 1학기 까지 놀던 고등학생의 두번째 프로젝트 feat.프로젝트 설명 아님]]></title>
            <link>https://velog.io/@sinwoo_dev/2%ED%95%99%EB%85%84-1%ED%95%99%EA%B8%B0-%EA%B9%8C%EC%A7%80-%EB%86%80%EB%8D%98-%EA%B3%A0%EB%93%B1%ED%95%99%EC%83%9D%EC%9D%98-%EB%91%90%EB%B2%88%EC%A7%B8-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8</link>
            <guid>https://velog.io/@sinwoo_dev/2%ED%95%99%EB%85%84-1%ED%95%99%EA%B8%B0-%EA%B9%8C%EC%A7%80-%EB%86%80%EB%8D%98-%EA%B3%A0%EB%93%B1%ED%95%99%EC%83%9D%EC%9D%98-%EB%91%90%EB%B2%88%EC%A7%B8-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8</guid>
            <pubDate>Fri, 03 Jan 2025 14:04:39 GMT</pubDate>
            <description><![CDATA[<p>12월 27일 부터 학교에서 예비취업맞춤반을 한다고 해서 신청해서 들어갔다.
나는 프론트에 대해서 자세하게 알려주는 수업인 줄 알았으나... 프로젝트를 만들면서 배우는 그런것이였다.
<img src="https://velog.velcdn.com/images/sinwoo_dev/post/6db5ebf2-a366-4540-aee3-8179dc15ef99/image.png" alt=""></p>
<p>뭔가 재미도 있을것같고 해서 시작을 하게 되었다.
일단 처음은 프로젝트 주제를 선택을 하였다.</p>
<hr>
<h2 id="주제-선정">주제 선정</h2>
<p>학교에서 구글폼을 사용하여서 급식 선호도 조사를 하는것이 생각이 났다.</p>
<p><img src="https://velog.velcdn.com/images/sinwoo_dev/post/6694036b-410e-4673-84db-11a995b4df53/image.png" alt=""></p>
<p>그럼 급식 선호도 조사? 라는 생각을 하였고 그대로 급식 선호도 조사로 정하였다.</p>
<blockquote>
<p>주제 : 급식 선호도 조사</p>
</blockquote>
<p>그럼 주제를 선정을 하였으니 이제 이름과 필요 기능을 생각을 할 차례였다.</p>
<hr>
<h2 id="기능-및-프로젝트-이름-선정">기능 및 프로젝트 이름 선정</h2>
<h3 id="기능-상세"><strong>기능 상세</strong></h3>
<ol>
<li><p><strong>매일 제공되는 급식 메뉴 확인</strong></p>
<ul>
<li><strong>학생:</strong> 해당 날짜의 급식 메뉴를 간단히 확인.</li>
<li><strong>관리자(영양사):</strong> 급식 메뉴를 등록 및 수정 가능.</li>
</ul>
</li>
<li><p><strong>좋아요/싫어요 투표</strong></p>
<ul>
<li>아침, 점심, 적녁에서 모든 메뉴중 하고 그 안에서 어떤 메뉴가 좋았는지 각각 3가지를 선택하고 다음으로 어떤것이 제일 불호였는지 각각 3가지를 선택후 제출.</li>
<li>투표 수는 실시간으로 업데이트.</li>
</ul>
</li>
<li><p><strong>급식 만족도 분석</strong></p>
<ul>
<li>날짜별 좋아요/싫어요 비율 차트 제공.</li>
<li>가장 인기 있거나 불호가 많은 메뉴 통계.</li>
</ul>
</li>
<li><p><strong>영양사 메뉴</strong></p>
<ul>
<li><p>접속후 영양사 글자를 클릭하여서 관리자 페이지에 들어가면 학생이 투표한 싫어하는 메뉴와 좋아하는 메뉴를 1위 부터 3위까지 db에 저장을 한다.</p>
</li>
<li><p>openai API를 이용하여서 gpt에게 프롬프트를 입력하여서 결과를 받아서 db에 저장을 한다.
각각 저장을 한다.</p>
<h3 id="가장-중요하게-생각하는-사항">가장 중요하게 생각하는 사항</h3>
</li>
</ul>
</li>
</ol>
<ul>
<li><strong>UI/UX:</strong> 학생들이 사용하기 쉽게 직관적인 디자인 적용.</li>
<li><strong>데이터 시각화:</strong> 급식 만족도를 효과적으로 보여주는 통계 그래프.</li>
</ul>
<p><strong>많이 생각을 해본 결과 이렇게 하면 될거 같다고 생각을 하여서 이대로 진행을 하였다.</strong></p>
<hr>
<p>이렇게 다 선정을 하였는데 급식 데이터는 어디서 가져올것인지를 찾아보았다.
찾아보니 <strong>교육정보 개방 포털 사이트</strong>를 알게되었다.
일단 그럼 openai API와 교육정보 개방 포털 사이트를 이용하여서 만들고 디자인은 어떻게 할지 한번 구성을 해보았다.<img src="https://velog.velcdn.com/images/sinwoo_dev/post/5169edd9-da24-4797-b115-b4842475f966/image.png" alt="">
이런 느낌으로 구성을 할려고 하였다.</p>
<p>더 자세히 보고 싶은분들을 위해서 링크를 남겨드리겠습니다.
<a href="https://www.figma.com/design/eDqMiEwjxdfsOiZH2nVYMN/Untitled?node-id=0-1&amp;t=yKNKisDZDIHJkv4O-1">Figma 디자인 보러 가기</a></p>
<hr>
<p>이후 프론트엔드와 백엔드에서 어떤것을 사용을 할지 생각여서 작성을 하였다.</p>
<blockquote>
<p>front-end</p>
<ul>
<li>사용 기술<ul>
<li>axios</li>
<li>react-router-dom</li>
<li>react-device-detect</li>
<li>mui</li>
<li>recharts</li>
<li>@mui/material</li>
<li>@emotion/react</li>
<li>@emotion/styled</li>
</ul>
</li>
</ul>
</blockquote>
<blockquote>
<p>back-end</p>
<ul>
<li>사용 기술<ul>
<li>openai</li>
<li>bcrypt</li>
<li>prisma</li>
<li>jsonwebtoken</li>
<li>dotenv</li>
<li>cors</li>
<li>express</li>
</ul>
</li>
</ul>
</blockquote>
<p>일단 지금 프로젝트에서 사용할만한 라이브러리들을 선택하여서 정리를 하였다.
프론트에서 react-device-detect를 이용하여서 모바일과 데스크탑을 구분하여서 react-router-dom으로 페이지 라우팅을 해주었다.
3일동안은 프론트의 기본틀을 잡고 그리고 퍼블리싱을 잠을 줄이면서 하였다..
근데 생각해보니 캡스톤이 있어서 캡스톤도 한다고 하루에 3일동안 잠을 하루에 4시간 ~ 3시간 사이로 잤다..
<img src="https://velog.velcdn.com/images/sinwoo_dev/post/7c0ef526-8b89-49dc-81ea-27ff06b1ae58/image.png" alt="">
원래 나는 잠이 많은 사람인데... 잠 자고 싶다...
.
.
.
그렇게 프론트엔드의 퍼블리싱이 어느정도 끝나고 이제 백엔드도 만들어야겠다는 생각이 들어서 백엔드도 만들기 시작을 하였다...
근데 더 충격... 캡스톤의 백엔드에서 ai 불러오는것이 있는데 여기서 요청을 보내면 500 에러가 뜬다...
<img src="https://velog.velcdn.com/images/sinwoo_dev/post/d02f4a10-5885-4716-97a7-af3df4b15615/image.png" alt="">
음... 어떻하지... 지금 새벽 2시인데... 친구를 깨워야하나 생각이 들었다...
결국에는 깨워서 백엔드에 문제 있는것 같다고 말을 하였다...
<img src="https://velog.velcdn.com/images/sinwoo_dev/post/c60d77bc-d036-42c2-8484-5c870605ec4f/image.png" alt="">
친구가 잠이 덜깨었는지 뭐라고 말했는데 못들었는데 친구가 다시 잠을 잤다...
낼 해결 해주겠지... 하면서 그냥 나와서 최대한 할 수 있는것들을 하였다...
그러고 캡스톤 발표날전에 캡스톤 프로젝트와 급식 선호도 조사 프로젝트를 함께하면서 그날 새벽 4시에 잠을 자고 5시에 일어나 학교로 출발을 하였다...(피곤해 죽는줄)
<img src="https://velog.velcdn.com/images/sinwoo_dev/post/8b6dbc20-3c51-4886-bca9-f137006d0a96/image.png" alt="">
그리고 학교가서 발표를 하고 마치고 이제 다시 올라서 급식 선호도 조사 백엔드를 계속해서 짜면서 프론트에서 axios를 연결하고 오류 해결하고 이걸 2일 동안 28시간 반복하여서 완성을 하였고 여기서 배포를 해보자 하여서 도커로 배포를 할려고 하였는데..</p>
<h1 id="헉">헉!</h1>
<p><img src="https://velog.velcdn.com/images/sinwoo_dev/post/a550f7bb-ffda-4824-8eb6-02eb2cbcbe8d/image.png" alt=""></p>
<p><strong>무슨 도커 파일로 올리니까 localhost:3306 mysql를 못 찾겠다는 것이다...</strong>
아니 docker에 mysql 올라가있는데 이게 무슨 일이지??? 해서 찾아보다가 localhost대신해서 docker 컨테이너의 ip를 가져와서 넣어보라는 글을 봤다.
그래서 해보니까 4시간동안 개고생한게 해결이 되었다...
<img src="https://velog.velcdn.com/images/sinwoo_dev/post/859dbc94-f881-4bc6-b31b-6963ed979ed4/image.png" alt="">
진짜 모니터 부실뻔 했다...</p>
<p>이대로 백엔드를 배포를 할려고 지금 docker하고 aws에 대해서 공부하는 중이다...
나중에 배포가 완료되면 더 자세하게 프로젝트에 대해서 설명을 하고 완성 화면을 보여드릴게요..
지금 너무 피곤하네요..
이제 저 9시간 잘 수 있어요... 잘자요 여러분~
<img src="https://velog.velcdn.com/images/sinwoo_dev/post/665a18b8-9dc2-42d8-a929-f24763b51885/image.png" alt="">
<img src="https://velog.velcdn.com/images/sinwoo_dev/post/3cf30966-d861-458b-870f-b3276e1dc88a/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[리액트 라우터 조금더 똑똑하게 쓰자]]></title>
            <link>https://velog.io/@sinwoo_dev/%EB%A6%AC%EC%95%A1%ED%8A%B8-%EB%9D%BC%EC%9A%B0%ED%84%B0-%EC%A1%B0%EA%B8%88%EB%8D%94-%EB%98%91%EB%98%91%ED%95%98%EA%B2%8C-%EC%93%B0%EC%9E%90</link>
            <guid>https://velog.io/@sinwoo_dev/%EB%A6%AC%EC%95%A1%ED%8A%B8-%EB%9D%BC%EC%9A%B0%ED%84%B0-%EC%A1%B0%EA%B8%88%EB%8D%94-%EB%98%91%EB%98%91%ED%95%98%EA%B2%8C-%EC%93%B0%EC%9E%90</guid>
            <pubDate>Wed, 12 Jun 2024 03:28:27 GMT</pubDate>
            <description><![CDATA[<p>일단 우리가 라우터를 사용을 할때 이런 형식으로 사용을 한다.</p>
<pre><code>&lt;Routes&gt;
    &lt;Route path = &quot;/&quot; element={&lt;MainPage/&gt;}/&gt;
    &lt;Route path = &quot;contents&quot; element={&lt;contents/&gt;}
    &lt;Route path = &quot;/login&quot; element{&lt;Login/&gt;} /&gt;
&lt;/Routes&gt;</code></pre><p>근데 우리가 로그인 페이지에서는 헤더 부분을 안보여 주고 싶고 메인 페이지에서는 헤더 부분을 보여 주고 싶을때는 어떻게 해야할까?</p>
<p><strong>일단 우리는 헤더 컴포넌트를 만들고 시작을 해보자</strong></p>
<p>현재 우리가 App.jsx라는 파일 안에서 만들고 있다고 하자</p>
<pre><code>function Header() {
    return (
        &lt;div&gt;
            &lt;div&gt;
                &lt;Link to=&quot;/&quot;&gt;홈&lt;/Link&gt;
                &lt;Link to=&quot;/contents&quot;&gt;컨텐츠&lt;/Link&gt;
            &lt;/div&gt;
            &lt;div&gt;
                &lt;Link to=&quot;/login&quot;&gt;로그인&lt;/Link&gt;
            &lt;/div&gt;
        &lt;div/&gt;
    )
}</code></pre><p><strong><em>컴포넌트를 만들때는 무조건 대문자로 시작해야 한다.</em></strong></p>
<p>일단 대충 헤더 컴포넌트를 만들었다.
그럼 우리는 이것을 사용해볼 것이다.</p>
<p>헤더를 표시를 해줄려면 이렇게 해주면 된다.</p>
<pre><code>function App() {
    return(
        &lt;div&gt;
            &lt;Header /&gt;
            &lt;Routes&gt;
                &lt;Route path = &quot;/&quot; element={&lt;MainPage/&gt;}/&gt;
                &lt;Route path = &quot;/contents&quot; element={&lt;contents/&gt;}
                &lt;Route path = &quot;/login&quot; element={&lt;Login/&gt;} /&gt;
            &lt;/Routes&gt;
        &lt;/div&gt;
    )
}</code></pre><p>근데 이렇게하면 우리는 로그인 페이지에 접속을 해도 똑같이 헤더가 표시가 되는 것을 볼 수 있다.
이런것도 분리를 해주고 싶으면 우리는 이런 방법을 쓰면 된다.</p>
<blockquote>
<p>Route 안에 있는 element에는 여러 컴포넌트를 넣을 수 있다.
또한 라우터도 여러 주소로 사용을 할 수 있는데 예시를 보여주겠다.</p>
</blockquote>
<pre><code>&lt;Routes&gt;
    &lt;Route path = &quot;/&quot; element={&lt;MainPage/&gt;}
    &lt;Route path = &quot;/contents&quot; element={&lt;contents/&gt;}&gt;
        &lt;Route path = &quot;components&quot; element={&lt;components/&gt;}
    &lt;/Route&gt;
    &lt;Route path = &quot;/login&quot; element{&lt;Login/&gt;} /&gt;
&lt;/Routes&gt;</code></pre><p>이런 방식으로 쓰면 주소를 /contents로 이동을 했을때는 contents의 내용을 보여주고 /contents/components로 이동을 하면 components의 내용을 보여준다.</p>
<blockquote>
<p>그리고 헤더 부분을 나눠서 사용을 하고 싶을때</p>
</blockquote>
<pre><code>&lt;Route 
path =&quot;/&quot; 
element={
    &lt;div&gt;
        &lt;Header /&gt;
        &lt;MainPage /&gt;
    &lt;/div&gt;
} /&gt;
&lt;Route 
path = &quot;/login&quot;
element = {
    &lt;Login/&gt;
}</code></pre><p>그냥 진짜로 간단하게 해결 할 수 있다...
이런걸로 포스트 올리는게 맞나 싶지만 복습할겸 올립니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[리액트 페이지간 이동(라우터)]]></title>
            <link>https://velog.io/@sinwoo_dev/%EB%A6%AC%EC%95%A1%ED%8A%B8-%ED%8E%98%EC%9D%B4%EC%A7%80%EA%B0%84-%EC%9D%B4%EB%8F%99%EB%9D%BC%EC%9A%B0%ED%84%B0</link>
            <guid>https://velog.io/@sinwoo_dev/%EB%A6%AC%EC%95%A1%ED%8A%B8-%ED%8E%98%EC%9D%B4%EC%A7%80%EA%B0%84-%EC%9D%B4%EB%8F%99%EB%9D%BC%EC%9A%B0%ED%84%B0</guid>
            <pubDate>Wed, 20 Mar 2024 10:37:55 GMT</pubDate>
            <description><![CDATA[<p>우리는 html을 배울게 a태그로 페이지 이동을 했을것이다.
리액트에서는 라우터라는것을 사용하여 이동을 해야한다.</p>
<p>리액트 생성하는 방법은 VSCode에서 터미널을 열어서 다음과 같이 입력해준다.
*
npx creat-react-app &lt;자신이 원하는 파일명&gt;</p>
<p>그러면 설치가 된것을 볼 수 있다.</p>
<p>다음은 우리가 라우터를 사용하기 위해서는 설치가 필요한데</p>
<p>그전에 리액트 파일로 이동해야한다.</p>
<p>터미널에 다음과 같이 입력을 해주어야 한다.</p>
<p>*
cd &lt;자신이 만든 파일명&gt;</p>
<p>다음에는 터미널에 다음과 같이 입력을 해준다.
*
npm react-router-dom</p>
<p>다음과 같이 입력하면 설치가 완료될것이다.
그러면 우리는 라우터 사용할 준비가 완료되었다 🥳</p>
<hr>
<p>그럼 우리는 코드를 짜볼것이다.
간단하게 우리는 src 폴더에 MainPage.jsx와 LoginPage.jsx를 만들것이다.
App.js에 다음과 같은 코드를 짜준다.</p>
<pre><code>import { Routes,Route } from &#39;react-router-dom&#39;
import MainPage from &#39;./MainPage&#39;;
import LoginPage from &#39;./LoginPage&#39;;

function App() {
  return (
    &lt;Routes&gt;
      &lt;Route path=&#39;/&#39; element={&lt;MainPage/&gt;} /&gt;
      &lt;Route path=&#39;/login&#39; element={&lt;LoginPage/&gt;} /&gt;
    &lt;/Routes&gt;
  );
}

export default App;</code></pre><hr>
<p>다음과 같이 짜면 작동이 안될것이다.
이유는 인덱스에 코드를 라우터 지정을 안해줬기 때문이다.
index.js에 다음과 같이 코드를 짜준다.    </p>
<pre><code>  &lt;React.StrictMode&gt;
    &lt;App /&gt;
  &lt;/React.StrictMode&gt;</code></pre><p>이 부분을 이렇게 바꿔준다.</p>
<pre><code>  &lt;BrowserRouter&gt;
    &lt;App /&gt;
  &lt;/BrowserRouter&gt;</code></pre><p>그러면 라우터가 정상 작동 할것이다.</p>
<p>서버를 실행하는 법은 터미널에 다음과 같이 입력하면 된다.</p>
<p>*
npm start 또는 npm run start를 입력하면 된다.</p>
<hr>
<p>그러면 우리는 이제 Link라는 태그를 사용해서 페이지 이동을 해볼것이다.</p>
<pre><code>import { Link } from &quot;react-router-dom&quot;

function MainPage(){
    return(
        &lt;div&gt;
            메인페이지 입니다.
            &lt;br /&gt;
            &lt;Link to=&quot;/login&quot;&gt;로그인 페이지&lt;/Link&gt;
        &lt;/div&gt;
    )
}

export default MainPage</code></pre><p>다음과 같은 코드를 짜면 화면에 다음과 같이 나올것이다.</p>
<p><img src="https://velog.velcdn.com/images/sinwoo_dev/post/6a6488a5-5288-48bf-bf2b-14ba300faa75/image.png" alt=""></p>
<p>저기에 있는 로그인 페이지를 누르면 주소창이 &quot;localhost:3000/login&quot;으로 바뀐것을 볼 수 있다.
<img src="https://velog.velcdn.com/images/sinwoo_dev/post/604a6c61-50af-4bc4-b5f5-d742e026e220/image.png" alt=""></p>
<p>그럼 우리는 라우터 사용하는 법을 배운것이다.</p>
]]></description>
        </item>
    </channel>
</rss>