<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>yeeeerim_.log</title>
        <link>https://velog.io/</link>
        <description>:)</description>
        <lastBuildDate>Thu, 15 Jun 2023 15:34:46 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>yeeeerim_.log</title>
            <url>https://velog.velcdn.com/images/yeeeerim_/profile/d340acfb-65d4-408a-af10-db168c15b60c/image.jpeg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. yeeeerim_.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/yeeeerim_" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[패스트캠퍼스 백엔드 과정 4기 부트캠프 #07. 파이널 프로젝트 중간회고 🗓️]]></title>
            <link>https://velog.io/@yeeeerim_/%ED%8C%A8%EC%8A%A4%ED%8A%B8%EC%BA%A0%ED%8D%BC%EC%8A%A4-%EB%B0%B1%EC%97%94%EB%93%9C-%EA%B3%BC%EC%A0%95-4%EA%B8%B0-%EB%B6%80%ED%8A%B8%EC%BA%A0%ED%94%84-07.-%ED%8C%8C%EC%9D%B4%EB%84%90-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EC%A4%91%EA%B0%84%ED%9A%8C%EA%B3%A0</link>
            <guid>https://velog.io/@yeeeerim_/%ED%8C%A8%EC%8A%A4%ED%8A%B8%EC%BA%A0%ED%8D%BC%EC%8A%A4-%EB%B0%B1%EC%97%94%EB%93%9C-%EA%B3%BC%EC%A0%95-4%EA%B8%B0-%EB%B6%80%ED%8A%B8%EC%BA%A0%ED%94%84-07.-%ED%8C%8C%EC%9D%B4%EB%84%90-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EC%A4%91%EA%B0%84%ED%9A%8C%EA%B3%A0</guid>
            <pubDate>Thu, 15 Jun 2023 15:34:46 GMT</pubDate>
            <description><![CDATA[<h2 id="intro">Intro</h2>
<p>과정수료를 2주 앞두고 남겨놓은 지금 파이널 프로젝트를 하느라 정신이 없다ㅠ ㅠ 
정말 올해는 살면서 가장 빠르게 지난것같다.. 벌써 여름이라니 ㅠ ㅠ 
패캠을 들어오게 된 가장 큰 이유 ! 기업 연계 프로젝트를 지금 진행하고 있다. </p>
<p>패캠의 파이널 프로젝트는 BE+FE+UX/UI+PM이 다같이 하는 팀프로젝트다. 
특히 PM분들과 UX/UI분들과의 첫협업인데 저번 미니프로젝트에서는 UI로인한 아쉬움, 기획의 부족함으로 인한 아쉬움들이 꽉꽉 채워지는 느낌이랄까?</p>
<p>나는 1순위로 선택한 기업프로젝트에 참여하게 되었다 🙂
좋은 기업들도 많았지만 나는 자유도가 높은 프로젝트에 참여해서 생각지 못했던 기능들도 해보고 싶었기 때문이다</p>
<p>파이널의 조편성은 프로젝트 참여 기업들의 소개를 보고 원하는 기업을 3순위까지 결정해서 설문참여를 하면 매니저님들이 조절해서 조편성을 해준다. 
1순위로 넣은 기업들이 경쟁률이 높다면 과정참여도로 결정하신다니 패캠 부트캠프에 참여하시는 분들은 참고하시길 <del>~</del></p>
<h2 id="프로젝트-설계">프로젝트 설계</h2>
<h3 id="프로젝트-소개">프로젝트 소개</h3>
<p>옷장정리 서비스를 지원하는 열다 기업의 어드민 자동화, 웹페이지 구축을 요구사항으로 프로젝트를 진행하고 있다. 
주요기능으로는 예약 폼 접수, 매니저 지원폼 접수, 매니저 매칭(자동화), 알림톡 전송(프로세스에 맞게 자동전송), 예약관리, 고객관리, 리뷰관리 등이 있다. (이 부분에 대해서는 프로젝트 마무리 후 자세하게 포스팅 할 예정이다)</p>
<h3 id="기술스택">기술스택</h3>
<p><img src="https://velog.velcdn.com/images/yeeeerim_/post/002aff40-bd9a-411d-b951-a81fec03ec45/image.png" alt="">
저번 미니 프로젝트에서는 인프라 구축을 너무 늦게해 아쉬운 점이 많아 이번 프로젝트에서는 처음 시작할때부터 인프라 구축을 하고 시작했다.. 
근데 너무 빨리해서 비용은 많이 나오는데 ... 초반에는 프론트 분들이 웹페이지 제작하시느라 API를 쓰지 않았어서 아쉬운 부분이다. 
그 외에 리뷰 이미지를 저장하는 S3, 배포시 필요한 EC2, 로드밸런서 등의 기술을 사용중이다 ! </p>
<h3 id="주요-flow-chart">주요 Flow Chart</h3>
<p><img src="https://velog.velcdn.com/images/yeeeerim_/post/87e1b7ad-1c99-40c8-a4ed-ed9ac396f4ce/image.png" alt="">
<img src="https://velog.velcdn.com/images/yeeeerim_/post/be7287a7-ac4b-4f8f-96b8-9e5c3bfacd87/image.png" alt=""></p>
<h3 id="erd">ERD</h3>
<p><img src="https://velog.velcdn.com/images/yeeeerim_/post/5d780a9c-2244-49de-b562-2fcbb6e06af4/image.png" alt="">
몇 번의 수정을 거듭하고 비로소 틀이 잡힌 ERD이다. 
처음에 요구사항에 예약폼을 어드민이 수정할 수 있다. 라는 조건이 있어서 예약폼을 저런식으로 설계해놨는데 시간관계상 예약폼은 수정할 수 없고 고정으로 갈 것 같다. </p>
<p>모든 테이블이 다 중요하지만 특히 매니저 테이블은 설계할때 고민이 많았다. 
하나의 매니저는 활동요일과 활동지역을 여러개 선택할 수 있다. 
하지만 활동요일과 활동지역은 한정되어 있어 ManyToMany관계가 되어서 테이블을 어떻게 쪼갤까 <del>~</del> 고민하다 나온 결과이다.
활동요일에는 True False로 True인 요일들만 표시하는 방식으로, 
매칭에 필요한 Area테이블은 중간테이블(AreaManager)를 둬 ManyToMany를 풀어줬다
팀원분이 활동요일테이블 아이디어를 내주셨는디 정말 난 듣고 천재라고 생각했다..💡
그리고 팀장님은 AreaManager에 ID값은 따로 두지 말고 복합키로 관리해서 중복되는 데이터가 없게 설계하자고 하셨는데 지금와서 보니 저것도 신의한수였다! 🤩</p>
<p>하나의 예약이 들어오면 서비스 주소에 맞는 지역의 매니저들의 Match데이터가 생성되고 그 안에 매칭정보를 저장해둔다. </p>
<p>나머지테이블들은 일반적인 관계들이라 따로 설명은 하지 않겠다 ~!</p>
<h3 id="마무리">마무리</h3>
<p>파이널도 거의 반이 지났다. 
사실 이번주까지는 거의 프론트 백 따로따로 작업했는데 내일부터는 본격적으로 프론트랑 합치는 작업을 많이 할 것 같다.
바쁘겠지만 우리팀원분들은 모두 열심히 해주셔서 트러블 하나없이 순조롭게 진행중이다 🙂
이번 프로젝트를 하며 마지막으로 많은 배움을 얻어가 모두들 좋은곳에 취업했으면 좋겠다 ! 
화이팅화이팅</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[패스트캠퍼스 백엔드 과정 4기 부트캠프 #06. 미니프로젝트 회고 🗓️]]></title>
            <link>https://velog.io/@yeeeerim_/%ED%8C%A8%EC%8A%A4%ED%8A%B8%EC%BA%A0%ED%8D%BC%EC%8A%A4-%EB%B0%B1%EC%97%94%EB%93%9C-%EA%B3%BC%EC%A0%95-4%EA%B8%B0-%EB%B6%80%ED%8A%B8%EC%BA%A0%ED%94%84-06.-%EB%AF%B8%EB%8B%88%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%ED%9A%8C%EA%B3%A0</link>
            <guid>https://velog.io/@yeeeerim_/%ED%8C%A8%EC%8A%A4%ED%8A%B8%EC%BA%A0%ED%8D%BC%EC%8A%A4-%EB%B0%B1%EC%97%94%EB%93%9C-%EA%B3%BC%EC%A0%95-4%EA%B8%B0-%EB%B6%80%ED%8A%B8%EC%BA%A0%ED%94%84-06.-%EB%AF%B8%EB%8B%88%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%ED%9A%8C%EA%B3%A0</guid>
            <pubDate>Tue, 30 May 2023 17:18:19 GMT</pubDate>
            <description><![CDATA[<h1 id="🗓️-panrty">🗓️ Panrty</h1>
<h2 id="연차당직-관리-시스템"><a href="https://github.com/MiniTeam6/MiniProject_BE">연차/당직 관리 시스템</a></h2>
<h2 id="프로젝트-주제">프로젝트 주제</h2>
<blockquote>
<p>🔥 <strong>주제: 연차/당직 프로젝트 만들기</strong></p>
</blockquote>
<hr>
<h2 id="프로젝트-기간">프로젝트 기간</h2>
<ul>
<li><strong>프로젝트 설명</strong> : <code>2023년 4월 25일(화)</code></li>
<li><strong>총 기간</strong> : <code>2023년 5월 2일(화)</code> - <code>2023년 5월 19일(금)</code></li>
<li><strong>결과물 제출</strong>: <code>2023년 5월 16일(화)</code> <code>~15:00</code></li>
<li><strong>발표회 / 공유회 기간</strong>: <code>2023년 5월 17일(수)</code> - <code>2023년 5월 19일(금)</code></li>
<li><strong>진행 장소</strong> : <code>온라인(줌)</code>  / <code>오프라인 강의장</code></li>
</ul>
<hr>
<h2 id="주요-기능">주요 기능</h2>
<h3 id="🔐--로그인--회원가입--유저-관리권한">🔐  로그인 / 회원가입 / 유저 관리권한</h3>
<ul>
<li>JWT 토큰 발급을 이용한 로그인 구현</li>
<li>user/admin api 구분</li>
<li>회원가입시 가입 요청대기 </li>
</ul>
<h3 id="📇-연차--당직-신청">📇 연차 / 당직 신청</h3>
<ul>
<li>날짜 선택 및 연차/당직 신청</li>
<li>연차 보유개수보다 신청 연차일이 더 많으면 신청불가</li>
</ul>
<h3 id="📨-연차--당직-승인">📨 연차 / 당직 승인</h3>
<ul>
<li>Admin결재 -&gt; 승인/반려 </li>
<li>승인시 연차 보유개수 다시 한 번 검증, 문제 없다면 신청일 만큼 보유개수에서 차감</li>
<li>승인 리스트 검색 가능</li>
</ul>
<h3 id="🗓️-모든-유저-연차당직-월별-조회">🗓️ 모든 유저 연차/당직 월별 조회</h3>
<hr>
<h2 id="프로젝트-구조">프로젝트 구조</h2>
<p><img src="https://velog.velcdn.com/images/yeeeerim_/post/b3bd3d2d-6acd-4d49-b75d-bed38bea8370/image.png" alt=""></p>
<hr>
<h2 id="tech-stack">Tech Stack</h2>
<p><strong>웹 서버 (프로젝트 요구사항)</strong>
Spring boot 2.7.11
JDK 11
Gradle 7.6.1</p>
<p><strong>환경 세팅</strong>
Docker</p>
<p><strong>데이터 베이스</strong>
MySQL 5.7
H2(테스트)</p>
<p><strong>이미지 처리</strong>
AWS S3
Thumbnailator</p>
<p><strong>인증 관리</strong>
JWT</p>
<p><strong>배포</strong>
AWS EC2
CI/CD
Github Actions</p>
<p><strong>테스트</strong>
JUnit
Mokito</p>
<p><strong>문서화</strong>
Asciidoctor
Rest Docs</p>
<p><strong>로그 모니터링</strong>
Sentry</p>
<hr>
<h2 id="프로젝트-결과물">프로젝트 결과물</h2>
<h3 id="api-명세서"><a href="https://bustling-sturgeon-704.notion.site/API-f0f8c46a238449178a9080d45b66b041">API 명세서</a></h3>
<h3 id="💡-user---회원관련-기능">💡 User - 회원관련 기능</h3>
<table>
<thead>
<tr>
<th>API Path</th>
<th>HTTP Method</th>
<th>기능</th>
</tr>
</thead>
<tbody><tr>
<td>/api/signup</td>
<td>POST</td>
<td>🌟 회원가입</td>
</tr>
<tr>
<td>/api/login</td>
<td>POST</td>
<td>🌟 로그인</td>
</tr>
<tr>
<td>/api/email</td>
<td>GET</td>
<td>🌟 이메일 중복체크</td>
</tr>
<tr>
<td>/api/user/users</td>
<td>GET</td>
<td>🌟 유저 리스트</td>
</tr>
<tr>
<td>/api/user/users/{id}</td>
<td>GET</td>
<td>🌟 유저 상세정보</td>
</tr>
<tr>
<td>/api/user/myinfo</td>
<td>GET</td>
<td>🌟 마이페이지</td>
</tr>
<tr>
<td>/api/user/myinfo</td>
<td>POST</td>
<td>🌟 내 정보 수정</td>
</tr>
</tbody></table>
<h3 id="💡-admin---회원관련-기능">💡 Admin - 회원관련 기능</h3>
<table>
<thead>
<tr>
<th>API Path</th>
<th>HTTP Method</th>
<th>기능</th>
</tr>
</thead>
<tbody><tr>
<td>/api/admin/signup</td>
<td>GET</td>
<td>💖 회원가입 요청 리스트</td>
</tr>
<tr>
<td>/api/admin/status</td>
<td>POST</td>
<td>💖 회원가입 승인</td>
</tr>
<tr>
<td>/api/admin/role/list</td>
<td>GET</td>
<td>💖 전체유저 정보리스트</td>
</tr>
<tr>
<td>/api/admin/role/update</td>
<td>GET</td>
<td>💖 회원권한 업데이트</td>
</tr>
<tr>
<td>/api/admin/search</td>
<td>GET</td>
<td>💖 회원 검색(유저정보 출력)</td>
</tr>
</tbody></table>
<h3 id="💡-user---연차당직관련-기능">💡 User - 연차/당직관련 기능</h3>
<table>
<thead>
<tr>
<th>API Path</th>
<th>HTTP Method</th>
<th>기능</th>
</tr>
</thead>
<tbody><tr>
<td>/api/user/myannual</td>
<td>GET</td>
<td>🌟 내 연차 리스트</td>
</tr>
<tr>
<td>/api/user/myduty</td>
<td>GET</td>
<td>🌟 내 당직 리스트</td>
</tr>
<tr>
<td>/api/user/nextevent</td>
<td>GET</td>
<td>🌟 가장 빠른 연차당직 (D-day계산)</td>
</tr>
<tr>
<td>/api/user/event/add</td>
<td>POST</td>
<td>🌟 연차/당직 신청</td>
</tr>
<tr>
<td>/api/user/event/cancel</td>
<td>POST</td>
<td>🌟 연차/당직 신청취소(결재 전에만 가능)</td>
</tr>
<tr>
<td>/api/user/event/modify</td>
<td>POST</td>
<td>🌟 연차/당직 신청수정(결재 전에만 가능)</td>
</tr>
<tr>
<td>/api/user/event/list</td>
<td>GET</td>
<td>🌟 모든 유저 연차/당직 리스트(월별조회)</td>
</tr>
</tbody></table>
<h3 id="💡-admin---연차당직관련-기능">💡 Admin - 연차/당직관련 기능</h3>
<table>
<thead>
<tr>
<th>API Path</th>
<th>HTTP Method</th>
<th>기능</th>
</tr>
</thead>
<tbody><tr>
<td>/api/admin/annual/order</td>
<td>POST</td>
<td>💖 연차 승인</td>
</tr>
<tr>
<td>/api/admin/duty/order</td>
<td>POST</td>
<td>💖 당직 승인</td>
</tr>
<tr>
<td>/api/admin/annual/request</td>
<td>GET</td>
<td>💖 연차신청 리스트</td>
</tr>
<tr>
<td>/api/admin/duty/request</td>
<td>GET</td>
<td>💖 당직신청 리스트</td>
</tr>
<tr>
<td>/api/admin/annual/approval</td>
<td>GET</td>
<td>💖 결재된 연차 리스트</td>
</tr>
<tr>
<td>/api/admin/duty/approval</td>
<td>GET</td>
<td>💖 결재된 당직 리스트</td>
</tr>
<tr>
<td>---</td>
<td></td>
<td></td>
</tr>
<tr>
<td>## 화면구성</td>
<td></td>
<td></td>
</tr>
<tr>
<td>### 로그인/회원가입</td>
<td></td>
<td></td>
</tr>
<tr>
<td><strong>로그인</strong></td>
<td></td>
<td></td>
</tr>
<tr>
<td><img src="https://velog.velcdn.com/images/yeeeerim_/post/21fd3d84-d60e-4fec-b7ce-aa1b99a727ce/image.png" alt=""></td>
<td></td>
<td></td>
</tr>
<tr>
<td><strong>회원가입</strong></td>
<td></td>
<td></td>
</tr>
<tr>
<td><img src="https://velog.velcdn.com/images/yeeeerim_/post/8167067c-61e4-43de-8c10-5706afcbe39f/image.png" alt=""></td>
<td></td>
<td></td>
</tr>
</tbody></table>
<h3 id="유저-페이지">유저 페이지</h3>
<p><strong>메인 페이지 연차 / 당직 현황</strong>
<img src="https://velog.velcdn.com/images/yeeeerim_/post/4e918b7d-7231-479e-b8f6-27636e0d6bbd/image.png" alt="">
<strong>마이 페이지</strong>
<img src="https://velog.velcdn.com/images/yeeeerim_/post/51f839e1-c57c-4622-87e3-78021d8fccb3/image.png" alt="">
<strong>메인 페이지 모달 캘린더</strong>
<img src="https://velog.velcdn.com/images/yeeeerim_/post/354f13ce-f877-4e0b-b5d7-2e84800cb9cc/image.png" alt=""></p>
<h3 id="관리자-페이지">관리자 페이지</h3>
<p><strong>관리자 권한 수정</strong>
<img src="https://velog.velcdn.com/images/yeeeerim_/post/2336d23d-8b0f-4599-b71b-60217d82df1a/image.png" alt="">
<strong>계정 승인</strong>
<img src="https://velog.velcdn.com/images/yeeeerim_/post/2154cc02-294b-41a5-bcb7-56bb767e606f/image.png" alt="">
<strong>연차/당직 승인</strong></p>
<hr>
<h2 id="회고">회고</h2>
<p>프로젝트가 모두 끝나고 FE와 BE팀원들이 모여 프로젝트 기간동안 아쉬웠던 점을 얘기해보며 회고하는 시간도 가졌다!
아래는 내가 아쉬웠던 점이다. </p>
<h3 id="아쉬운-점">아쉬운 점</h3>
<ol>
<li>피그마페이지를 보고 대략적으로 API명세서 작성하고 기능을 구현하려고 하니 정확히 어떤 데이터가 필요한지 모르겠었고 그로인해 변동사항도 수정사항이 점점 많아졌던 점</li>
<li>기능구현 유무에만 집중을 하고 DB에서 데이터를 더 효율적으로 가져오는 것과 같은 백엔드에서 고려해야할 사항들에 대해서는 신경쓰지 못했던 점</li>
<li>역할분담을 도메인별로 하지않고 user, admin으로 나눠서 로직이 서로 겹치거나 같은 레포지토리에 접근해 같은 메소드를 썼는데 변경사항이 생겼을때 오류가 나서 다시 만들어야했던 점 </li>
<li>프론트와 협의 후 어떤 페이지에 무슨 데이터가 필요한지 정확하게 물어봤어야 함</li>
<li>기능 구현뿐만 아니라 성능에도 신경쓰며 개발해야함 , 리팩토링 과정 필요</li>
<li>요구사항을 정확히 파악하고 역할분담을 좀 더 효율적으로 배분</li>
</ol>
<h3 id="프로젝트를-마치며">프로젝트를 마치며</h3>
<p>처음해보는 프론트와의 협업이였는데 사실 백엔드 멘토분이 앞 기수 파이널 프로젝트 중인데 프론트와 백끼리 트러블이 많아 고민중이라고 하셔서 처음에 걱정을 많이 했었는데 다행히 우리조는 큰 트러블 없이 프로젝트를 마무리 할 수 있었다. </p>
<p>아쉬운 부분들도 많았지만 그래도 배울 점이 훨씬 많은 프로젝트여서 난 만족한다 ! 
과정이 모두 끝나고 아쉬운 부분들은 추후에 개인적으로라도 리팩토링 과정을 거쳐 더 완벽하게 만들고 싶은 마음이다:) 
지금 파이널 프로젝트를 진행하고 있는데 이것도 화이팅이다 ! </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[패스트캠퍼스 백엔드 과정 4기 부트캠프 #05. 기자단 중간회고 👩🏻‍💻]]></title>
            <link>https://velog.io/@yeeeerim_/%ED%8C%A8%EC%8A%A4%ED%8A%B8%EC%BA%A0%ED%8D%BC%EC%8A%A4-%EB%B0%B1%EC%97%94%EB%93%9C-%EA%B3%BC%EC%A0%95-4%EA%B8%B0-%EB%B6%80%ED%8A%B8%EC%BA%A0%ED%94%84-05.-%EA%B8%B0%EC%9E%90%EB%8B%A8-%EC%A4%91%EA%B0%84%ED%9A%8C%EA%B3%A0</link>
            <guid>https://velog.io/@yeeeerim_/%ED%8C%A8%EC%8A%A4%ED%8A%B8%EC%BA%A0%ED%8D%BC%EC%8A%A4-%EB%B0%B1%EC%97%94%EB%93%9C-%EA%B3%BC%EC%A0%95-4%EA%B8%B0-%EB%B6%80%ED%8A%B8%EC%BA%A0%ED%94%84-05.-%EA%B8%B0%EC%9E%90%EB%8B%A8-%EC%A4%91%EA%B0%84%ED%9A%8C%EA%B3%A0</guid>
            <pubDate>Thu, 18 May 2023 16:57:52 GMT</pubDate>
            <description><![CDATA[<h2 id="intro">Intro</h2>
<p>22년 11월, 졸업 후 바로 취업하는 것보다 포트폴리오, 프로젝트의 중요성을 느끼고 공부를 하고 포트폴리오를 제대로 만들어 취업을 해야겠다는 결정을 했고 국비지원 부트캠프에 대해 많이 검색해보고 알아보았다. 
많은 부트캠프들이 있었지만 그 중 패스트캠퍼스가 가장 내가 원하는 기술을 배울 수 있고 커리큘럼이 탄탄하다고 느껴져 패스트캠퍼스에 지원해 지금 과정에 참여하고 있다. </p>
<p>지원 전 과정에서 아쉬운 점이 있었다면 패스트캠퍼스 국비지원 과정에 참여한 실제 수강생들의 후기들은 거의 찾아볼 수 없었다는 점이였다. 학원자체에서 수강생 후기라고 적어놓은 페이지는 확인할 수 있었지만 과정에 참여한다면 온라인으로만 참여하는데 출석관리나 수업은 어떤식으로 이루어지는지, 또 어떤 학습자료들을 제공하는지, 온라인 강의만 제공하는건지 실시간강의만 제공하는건지 실제 과정에 참여해야 알 수 있는 자세한 정보들은 찾지 못했었다🥺</p>
<p><img src="https://velog.velcdn.com/images/yeeeerim_/post/141af707-e7d4-4d70-94d2-f69efe40cc9e/image.png" alt="">
그래서 나도 이 과정에 참여한다면 나중에 블로그에 후기를 남겨봐야겠다라는 생각을 가지고 있었는데 어느날 슬랙에 기자단 모집이라는 아주 반가운 공지가 올라왔다🙂 원래도 하려고 했었는데 기자단 혜택까지 있어 이건 안할 이유가 없다고 생각해 고민도 하지 않고 지원하게 되었고 2월부터 매월 2개의 포스팅을 하고 있다. </p>
<p><img src="https://velog.velcdn.com/images/yeeeerim_/post/1a6c1e42-9b7b-4f14-a716-85fb60eba243/image.png" alt="">
기자단 활동으로 작성하는 포스팅이라 광고성이라고 생각하시는 분들도 있을텐데 학원측에서는 그런 가이드를 제공하고 있지 않다. 
블로그 작성 가이드에도 제목 형식, 분량, 해시태그에만 관여하지 내용에 관해서는 터치하지 않는다는 뜻이다. 
맨 첫 줄에도 나와있다시피  <strong>솔직하고 생생한 후기가 담긴 글</strong>을 쓰는 것이 기자단의 목적이다🌟 
그러니 좋은말만한다고 생각하지 않으셔도 된다는 말씀 ! </p>
<h2 id="📢-기자단-선발-후-첫-공지">📢 기자단 선발 후 첫 공지</h2>
<p><img src="https://velog.velcdn.com/images/yeeeerim_/post/e269f07a-ef72-4393-8684-e2e76984c55f/image.png" alt="">
기자단 첫 선발 이후 슬랙 워크스페이스에 초대되어 참여하였고, 첫 공지이다. 
사실 경쟁률이 치열할 것으로 생각에 안될 수 도 있다고 생각했었는데 지원한 사람들은 다 뽑힌 것 같기도 하고..? 잘 모르겠다 어쨌든 처음 선발되고 너무 좋았다! 
<img src="https://velog.velcdn.com/images/yeeeerim_/post/1641b65f-49a8-456f-ad98-d46744241a83/image.png" alt=""></p>
<p>그 이유는 기자단 혜택도 아주 좋기 때문이다^__^
혜택없어도 할 생각 있었음 + 기자단 혜택 = 바로 지원 -&gt; 합격 = 행복 💛</p>
<h3 id="첫-번째-포스팅">첫 번째 포스팅</h3>
<p><img src="https://velog.velcdn.com/images/yeeeerim_/post/d97c9bcf-4196-4669-bf23-7a1e804df754/image.png" alt="">
기자단 슬랙에 올라온 첫 공지이다. 
사실 장학금도 지급하다보니 학원의 상세한 가이드, 못해도 주제도 다 정해져 있을 줄 알았는데 1기 기자단은 과정이 시작하고 시간이 좀 지나고 시작해서 그런가 자유주제로 진행중이다. 
나는 이때 과정지원 전 내가 가장 궁금했었던 점인 지원과정, 수업방식🌟, 제공 학습자료, 출석체크, 훈련장려금, OT를 주제로 포스팅을 했었다. 바로 <a href="https://velog.io/@yeeeerim_/%ED%8C%A8%EC%8A%A4%ED%8A%B8-%EC%BA%A0%ED%8D%BC%EC%8A%A4-%EB%B0%B1%EC%97%94%EB%93%9C-%EA%B3%BC%EC%A0%95-4%EA%B8%B0-01.-1212112-%ED%9A%8C%EA%B3%A0-%EC%A7%80%EC%9B%90%EA%B3%84%EA%B8%B0-%EA%B3%BC%EC%A0%95-OT-%EA%B7%B8%EB%A3%B9%EC%8A%A4%ED%84%B0%EB%94%94-%EC%88%98%EC%97%85%EB%B0%A9%EC%8B%9D-%ED%9B%88%EB%A0%A8%EC%9E%A5%EB%A0%A4%EA%B8%88">Here!</a> 
확실히 내가 과정 지원 전에 궁금했던 점을 쓰다보니 글이 술술 적혔고 제출할 수 있었다 뿌듯 :) ! 
지금 포스팅을 올리는 벨로그에도 올리지만 검색할 때는 네이버블로그도 많이 쓴다고 생각해 똑같은 글을 네이버 블로그에도 포스팅했었다. 
실제 벨로그의 포스트 통계는 다음과 같이 30 정도인데 
<img src="https://velog.velcdn.com/images/yeeeerim_/post/799e9d7e-8a8e-41e4-8320-2be99475b5d0/image.png" alt="">
네이버는 더 늦게 올렸음에도 조회수가 97이여서 깜짝놀랬다😀
근데 바빠서 네이버에는 첫번째 포스트만 올리고 다른 포스트들은 옮기지 않았다.. 
이번 주말에 옮겨야겠다! 
<img src="https://velog.velcdn.com/images/yeeeerim_/post/d18be6ad-3bf4-49bd-97b2-4008cb4df380/image.png" alt=""></p>
<h3 id="두-번째-포스팅">두 번째 포스팅</h3>
<p>두 번째 포스팅도 역시 <code>자유주제</code> 공지가 나왔다. 
이땐 뭘쓰지 하다가 내가 이 당시 가장 만족했던 커리어 서비스를 중심으로 포스팅 했었다. 
이때도 마찬가지로 패캠에서 수강생들을 위해 어떤 활동들을 지원해주고 있는지 직접 수강생입장에서 후기를 쓰고 싶어서 썼던 기억이 있다. 두 번째 포스팅은 <a href="https://velog.io/@yeeeerim_/%ED%8C%A8%EC%8A%A4%ED%8A%B8%EC%BA%A0%ED%8D%BC%EC%8A%A4-%EB%B0%B1%EC%97%94%EB%93%9C-%EA%B3%BC%EC%A0%95-4%EA%B8%B0-%EB%B6%80%ED%8A%B8%EC%BA%A0%ED%94%84-02.-113212-%ED%9A%8C%EA%B3%A0-%EC%BB%A4%EB%A6%AC%EC%96%B4-%EC%BD%94%EC%B9%AD-%EA%B7%B8%EB%A3%B9%EC%8A%A4%ED%84%B0%EB%94%94-%EC%9B%8C%ED%81%AC%EC%83%B5">요기</a>에서 보면 된다. </p>
<h3 id="세-번째-포스팅">세 번째 포스팅</h3>
<p>세 번째 포스팅은 한 달간의 회고 형식이 아닌 거의 2달가량의 회고를 몰아서 했다. 
실시간 강의 소개부터, 그룹스터디 워크샵, 모의코딩 테스트에 대한 후기를 썼다. 
세 번째 포스팅은 <a href="https://velog.io/@yeeeerim_/%ED%8C%A8%EC%8A%A4%ED%8A%B8%EC%BA%A0%ED%8D%BC%EC%8A%A4-%EB%B0%B1%EC%97%94%EB%93%9C-%EA%B3%BC%EC%A0%95-4%EA%B8%B0-%EB%B6%80%ED%8A%B8%EC%BA%A0%ED%94%84-03.-21346-%ED%9A%8C%EA%B3%A0-%EC%8B%A4%EC%8B%9C%EA%B0%84-%EA%B0%95%EC%9D%98-2%EC%B0%A8-%EA%B7%B8%EB%A3%B9%EC%8A%A4%ED%84%B0%EB%94%94-%EC%9B%8C%ED%81%AC%EC%83%B5-%EB%AA%A8%EC%9D%98%EC%BD%94%EB%94%A9-%ED%85%8C%EC%8A%A4%ED%8A%B8">요기</a>에서 보면 된다.</p>
<h3 id="네-번째-포스팅">네 번째 포스팅</h3>
<p>가장 최근에 썼던 포스트이다. <a href="https://velog.io/@yeeeerim_/%ED%8C%A8%EC%8A%A4%ED%8A%B8%EC%BA%A0%ED%8D%BC%EC%8A%A4-%EB%B0%B1%EC%97%94%EB%93%9C-%EA%B3%BC%EC%A0%95-4%EA%B8%B0-%EB%B6%80%ED%8A%B8%EC%BA%A0%ED%94%84-04.-%EA%B7%B8%EB%A3%B9%EC%8A%A4%ED%84%B0%EB%94%94-%EC%82%AC%EC%9D%B4%EB%93%9C-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8%ED%98%B8%ED%85%94%EC%98%88%EC%95%BD-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8">요기</a>에서 보면 된다🤩
12월부터 4월까지 거의 4개월 조금 안되게 진행한 프로젝트를 소개하는 포스팅이였다 :)
다른 포스팅들도 정성스럽게 썼었지만 제일 내가 뿌듯해하는 포스트이다. 
처음에 학원에 들어온 목적이 프로젝트 경험을 쌓고 포트폴리오를 채우기였던 것만큼 몇 개월간 했던 프로젝트를 마무리하고 회고를 한다는 것이 정말 뿌듯했다. 
오늘자로 과정중에 자바 토이프로젝트 1개, 스프링부트 토이프로젝트 2개, 그룹스터디 프로젝트(이거), 미니프로젝트 총 5개의 프로젝트를 마무리 했는데 나머지 4개의 포스트도 곧 작성할 예정이다:) </p>
<h2 id="마무리">마무리</h2>
<p>이렇게 기자단 회고를 해보았는데 처음엔 기자단 중간회고를 할게 뭐가 있지? 라는 생각을 했었는데 막상 포스팅을 써보니 쓸게 많았다😀 이번주 화요일날 미니프로젝트 결과물을 제출하고 이제 파이널 프로젝트를 준비하고 있는데 정말 과정이 얼마 남지 않았다는 게 확 체감이 된다.. 😭 과정 시작 전에는 언제 7개월가지 했는데 정말 눈 깜짝할 새 5월말이다.. 끝까지 모두모두 화이팅이댜</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[패스트캠퍼스 백엔드 과정 4기 부트캠프 #04. 그룹스터디 사이드 프로젝트📚(호텔예약 프로젝트)]]></title>
            <link>https://velog.io/@yeeeerim_/%ED%8C%A8%EC%8A%A4%ED%8A%B8%EC%BA%A0%ED%8D%BC%EC%8A%A4-%EB%B0%B1%EC%97%94%EB%93%9C-%EA%B3%BC%EC%A0%95-4%EA%B8%B0-%EB%B6%80%ED%8A%B8%EC%BA%A0%ED%94%84-04.-%EA%B7%B8%EB%A3%B9%EC%8A%A4%ED%84%B0%EB%94%94-%EC%82%AC%EC%9D%B4%EB%93%9C-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8%ED%98%B8%ED%85%94%EC%98%88%EC%95%BD-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8</link>
            <guid>https://velog.io/@yeeeerim_/%ED%8C%A8%EC%8A%A4%ED%8A%B8%EC%BA%A0%ED%8D%BC%EC%8A%A4-%EB%B0%B1%EC%97%94%EB%93%9C-%EA%B3%BC%EC%A0%95-4%EA%B8%B0-%EB%B6%80%ED%8A%B8%EC%BA%A0%ED%94%84-04.-%EA%B7%B8%EB%A3%B9%EC%8A%A4%ED%84%B0%EB%94%94-%EC%82%AC%EC%9D%B4%EB%93%9C-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8%ED%98%B8%ED%85%94%EC%98%88%EC%95%BD-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8</guid>
            <pubDate>Wed, 26 Apr 2023 14:16:05 GMT</pubDate>
            <description><![CDATA[<h2 id="intro">Intro</h2>
<p>패캠 백엔드 과정을 작년 12월 12일에 시작했는데 어느덧 5월을 바라보고 있다.. 
정말정말 정~~말 금방이다ㅠ ㅠ
과정 처음시작하고 1주일인가? 뒤에 시작한 그룹스터디에서는 처음에 게시판 프로젝트를 만들어보고 본격적인 프로젝트로 <code>호텔 예약 프로젝트</code>를 진행했다 ! 
중간에 팀원도 한 분 나가셨구 처음이라 우왕좌왕했던 기억들이 많았지만 스터디 팀장이 정말 잘 이끌어주셔서 ㅋㅋㅋ ㅋ 그래도 프로젝트가 나름 성공적으로 끝이났다 ! 아래는 프로젝트의 대략적인 설명이다. </p>
<h1 id="🏠-호텔-예약-프로젝트">🏠 호텔 예약 프로젝트</h1>
<h2 id="✍🏻-erd">✍🏻 ERD</h2>
<p><img src="https://user-images.githubusercontent.com/79129475/228429497-fc381b6a-bdce-49cf-99b3-31b24186a0b0.png" alt="image"></p>
<h2 id="🌟-동작-방식">🌟 동작 방식</h2>
<p><img src="https://user-images.githubusercontent.com/95463650/234174340-58175af9-aa05-4933-8c59-64b42ffe88f2.jpg" alt="제목을 입력하세요 (2)"></p>
<h2 id="🧑🏻💻-배포기록">🧑🏻‍💻 배포기록</h2>
<p><a href="https://jaewoo2233.tistory.com/105">https://jaewoo2233.tistory.com/105</a></p>
<h2 id="💡-주요-기능">💡 주요 기능</h2>
<h3 id="1-spring-batch">1. Spring Batch</h3>
<ul>
<li>Spring 스케줄링을 통해 하루에 한 번씩 기간이 지난 예약 데이터들을 삭제하는 방식으로 구현했고, 처음에 호텔 Open API 데이터를 받는 것을
8080 서버에서 실행할 때 다 받아오도록 하려했는데 중간에 OpenApi 중단이 끊기게 되어서 해당 데이터를 사용하려 했는데 사용 못하게 되었었다.
그래서 현재 PC에 있는 호텔 데이터를 CSV 파일로 Batch 프로그램을 돌려 생성하고,  만든 CSV 파일을 통해 Mysql 컨테이너에 데이터를 넣었다.</li>
</ul>
<h3 id="span-stylebackground-colorfff5b12-redis-캐시관리"><span style="background-color:#fff5b1">2. Redis 캐시관리</h3>
<ul>
<li>호텔 자세히 보기에서 호텔 이미지를 캐시처리하였다.</li>
<li>사용자가 호텔 자세히보기를 클릭하면 Mysql에서 redis로 이미지가 저장된다.</li>
<li>redis에 있는 호텔을 클릭하면 hotelImage 테이블을 조회하지 않고 redis에서 이미지 정보를 가져온다.</li>
<li>호텔이미지에 수정사항이 있다면 redis에 저장된 이미지는 삭제처리한다.</li>
</ul>
<h3 id="3-kakao-api활용">3. KaKao API활용</h3>
<ul>
<li>Open API에 데이터는 위도 경도는 주지만 자세한 위치가 안 나오는 곳이 있어 해당 값으로 KaKao map으로 보여주기도 하고 해당 위도, 경도 데이터로 요청해서 도로명 주소를 받아오도록 구성했다.  </li>
</ul>
<h3 id="span-stylebackground-colorfff5b14-호텔-조회-·-저장-·-수정-·-삭제--리뷰-조회-·-저장-·-수정-·-삭제"><span style="background-color:#fff5b1">4. 호텔 조회 · 저장 · 수정 · 삭제 , 리뷰 조회 · 저장 · 수정 · 삭제</h3>
<h4 id="호텔-저장">호텔 저장</h4>
<ul>
<li>사용자가 호텔이름, 주소, 전화번호, 등 호텔 기본 정보를 입력하면 컨트롤러에서는 해당 요청을 받아 호텔의 주소를 프로젝트에서 구현한 카카오api를 이용해 위/경도로 변환해 서비스로 데이터를 넘긴다. </li>
<li>호텔 이미지와 호텔 Entity를 분리해 각각 저장한다. </li>
</ul>
<h4 id="호텔-리스트">호텔 리스트</h4>
<ul>
<li>Hotel 테이블에 저장되어있는 호텔이름과 HotelImage테이블에 있는 대표사진1개들을 리스트로 출력한다. (사진이 없을 경우 기본이미지로 출력)<br>한 화면당 12개의 호텔들을 페이징처리해 출력한다.  </li>
</ul>
<h4 id="호텔-자세히보기--리뷰조회">호텔 자세히보기 / 리뷰조회</h4>
<ul>
<li>Hotel 테이블에 있는 <code>id</code>, 이름, 주소, 전화번호 등을 출력하고 저장되어있는 주소를 위/경도로 변환하여 지도를 출력한다. </li>
<li>호텔에 남겨진 리뷰를 볼 수 있으며 남긴 리뷰 평점으로 호텔의 평균평점을 출력한다.</li>
</ul>
<h4 id="호텔-수정--삭제">호텔 수정 / 삭제</h4>
<ul>
<li>로그인한 사용자와 호텔 작성자가 같다면 호텔 수정, 삭제 버튼이 생성된다. </li>
<li>수정페이지에서는 이미지를 비롯한 호텔 정보들을 수정할 수 있다. </li>
<li>삭제페이지에서는 해당 호텔 삭제가 가능합니다.</li>
</ul>
<h4 id="리뷰저장">리뷰저장</h4>
<ul>
<li>별점을선택하고 리뷰를 작성하면 review테이블에 저장되고 선택한 별점은 숫자로 변환되어 DB에 저장된다.</li>
</ul>
<h4 id="리뷰-수정--삭제">리뷰 수정 / 삭제</h4>
<ul>
<li>로그인한 사용자와 리뷰 작성자가 같다면 리뷰 수정, 삭제 버튼이 생성된다.</li>
<li>리뷰 수정은 modal창으로 출력되며 별점과 리뷰 수정이 가능하다.</li>
<li>리뷰 삭제 버튼을 클릭하면 리뷰 삭제가 가능하다.</li>
</ul>
<h3 id="5-객실-조회-·-저장-·-수정-·-삭제">5. 객실 조회 · 저장 · 수정 · 삭제</h3>
<ul>
<li>호텔을 참조하는 FK를 들고있고 기본적인 CRUD를 구현, 그리고 호텔 자세히 보는 기능은 DB조회하기 전 Redis를 먼저 조회하고 없으면 DB를 조회하는 형식으로 구성함 한 번 조회한 데이터는 바로 Redis에 저장되게 된다. </li>
<li>룸 이미지는 S3 버킷을 사용해서 저장을 하는데 사장권한이 해당 호텔 룸을 저장할 때 여러 이미지를 저장할 수 있는데 이미지를 먼저 올릴 때 temp 디렉토리에 해당 이미지들이 저장되었다고 저장하기 버튼을 클릭시  temp파일에 있는 이미지들은 모두 삭제되고 S3 버킷에 해당 이미지들이 저장된다. 그리고 뒤로가기를 누를 경우에도 임시저장되었던 이미지 모두 삭제된다.</li>
</ul>
<h3 id="6-호텔-예약-·-예약취소">6. 호텔 예약 · 예약취소</h3>
<ul>
<li>예약저장 예약조회는 jpa를 사용해서 구현했고, 객실 조회를 할 때 유저가 선택한 체크인,체크아웃 날짜에 예약이 안된 객실을 보여주기 위해 따로 query를 작성해서 구현했다. 삭제의 경우 데이터를 삭제하지 않고, 예약내역에 deleted를 추가해서 삭제를 했을 경우 true로 바꾸는 방법을 사용했다.</li>
</ul>
<h3 id="7-마이페이지">7. 마이페이지</h3>
<ul>
<li>예약리스트 조회 및 예약한 객실 조회를 하는 페이지다. </li>
<li>이 페이지에서 예약취소가 가능하다.</li>
</ul>
<h3 id="8-회원가입-·-로그인">8. 회원가입 · 로그인</h3>
<h2 id="내가-구현한-프로젝트-화면-🖥️">내가 구현한 프로젝트 화면 🖥️</h2>
<p><img src="https://velog.velcdn.com/images/yeeeerim_/post/a9b83b99-ce03-4ac0-a805-cfb2bf81bed4/image.png" alt="">
<img src="https://velog.velcdn.com/images/yeeeerim_/post/e409f4e5-453a-4477-8c90-4c97e33749f1/image.png" alt="">
<img src="https://velog.velcdn.com/images/yeeeerim_/post/80e44a49-0ecc-44e0-be09-050ede68322b/image.png" alt="">
<img src="https://velog.velcdn.com/images/yeeeerim_/post/d24e58e4-3c6d-4520-be80-e49a7ea85e89/image.png" alt="">
<img src="https://velog.velcdn.com/images/yeeeerim_/post/20c8a45d-a513-44fb-9566-f0e3270c9a2c/image.png" alt="">
<img src="https://velog.velcdn.com/images/yeeeerim_/post/c6fec1e1-ab27-4195-a8e9-67f5c098cf89/image.png" alt=""></p>
<ul>
<li>화면은 부트스트랩으로 구현했는데.. 난 화면 꾸미는게 재밌드라.. 프론트갈걸 그랬나 ㅋㅅㅋ</li>
</ul>
<h2 id="프로젝트를-돌아보며-💬">프로젝트를 돌아보며 💬</h2>
<h3 id="기능">기능</h3>
<ul>
<li><p>내가 맡은 기능은 호텔(호텔이미지) 저장 / 조회 [list, 자세히보기] / 삭제 / 수정과  리뷰 CRUD였다.</p>
</li>
<li><p>호텔은 <code>@Controller</code>로 MVC로 , 리뷰는 <code>@RestController</code>로 구현했다.</p>
</li>
<li><p>다른 페이지는 괜찮은데 호텔 자세히보기 페이지에서는 쿼리가 3번 일어났었다. (호텔+호텔이미지+리뷰)
그래서 <code>fetchjoin</code>으로 호텔과 리뷰를 불러오고 리뷰보다 변경사항이 적은 호텔이미지를 redis에 저장한 뒤 가져오는 형태로 쿼리수를 줄이기 위해 노력했다</p>
</li>
<li><p>호텔자세히 보기를 처음 눌렀을때는 똑같이 쿼리가 2번 일어난다.(호텔+리뷰/호텔이미지)
그때 DB에서 가져온 호텔이미지를 redis에 저장하고 redis에서 호텔이미지를 가져다 준다. 이렇게 하면 캐시에 해당 호텔 이미지 정보를 저장해서 가져다 줘 호텔이미지에 변경사항이 없다면 redis에서 이미지 경로를 준다. </p>
</li>
<li><p>호텔 이미지가 삭제될때는 DB, 이미지 저장소, redis에 있는 모든 정보들이 삭제된다.  </p>
</li>
</ul>
<h3 id="회고">회고</h3>
<ul>
<li>학원에 처음 들어오면서 스프링에 대해 처음 공부해봤고 거의 백지인 상태에서 시작한 프로젝트라 정말 별것도 아닌걸로 오류도 많이 나서 짜증도 많이 났고 git pull만 받으면 자꾸 ㅋㅋㅋ ㅋ오류나서 그거 잡고 증맬 어려웠었다. 처음엔 무조건 기능 구현만 하면 된다고 생각하고 있었는데 스터디 팀장님이 그래도 경험이 많으신 분이라 이것저것 하시느라 고생이 많으셨다.. ^0^ 마지막엔 혼자 배포까지 하심.. 리스펙합니다
덕분에 쿼리 수를 줄이기 위해 BatchSize, Fetchjoin등 여러가지 방법들을 사용해보기도 했고 호텔이미지를 redis에 저장해 캐싱기능도 추가하기도 했다 !</li>
</ul>
<ul>
<li>가장 기억에 남았던 기능은  <del>(진짜 어려워서 짜증났던)</del> 호텔이미지 저장이였다.. 
호텔이미지의 이름까지 저장하는건 다했었는데 타임리프로 불러와야하는데 어떻게 화면에 띄우는지 몰라서 팀장님 설명도 듣곤 했는데 계속 이해못해서 며칠동안 진짜 씨름했던 기억이 ... ^^.. 근디 모든 기능들이 아주 하나하나 다 고비였음 사소한 오타하나로 자꾸 오류가 나기도 했고 .. 그냥 그랬다 </li>
</ul>
<ul>
<li><p>그거말고도 Controller와 Service, 아무것도 몰랐던 내가 스프링 실시간 수업을 시작하기 전부터 프로젝트를 진행하며 어느정도 이해를 할 수 있게 되었고 정말 백문이 불여일견이라는 말이 맞는 것 같다! 
물론 클론코딩도 좋겠지만 나에게 더 맞는 공부법은 정말 모르겠어도 일단 한 번 해보면서 학습하는 것 같다. </p>
</li>
<li><p>만약 검색을 통해 이 글을 보시고 패스트캠퍼스 부트캠프를 고민하신다면 그룹스터디에서 사이드 프로젝트 하는 것을 강추드린다! (혼자해도 좋겠지만 어렵기도 하고 문제가 생겼을때 팀원들이랑 같이 해결하는게 훠얼씬 나음)</p>
</li>
<li><p>다음주부터는 미니프로젝트를 시작해 그룹스터디도 이번주가 마지막이다..ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ ㅜ ㅜ
모두들 화이팅</p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[알고리즘]이건 꼭 풀어야 해 ! (백준 No_17390)]]></title>
            <link>https://velog.io/@yeeeerim_/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98%EC%9D%B4%EA%B1%B4-%EA%BC%AD-%ED%92%80%EC%96%B4%EC%95%BC-%ED%95%B4-%EB%B0%B1%EC%A4%80-No17390</link>
            <guid>https://velog.io/@yeeeerim_/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98%EC%9D%B4%EA%B1%B4-%EA%BC%AD-%ED%92%80%EC%96%B4%EC%95%BC-%ED%95%B4-%EB%B0%B1%EC%A4%80-No17390</guid>
            <pubDate>Tue, 25 Apr 2023 13:39:23 GMT</pubDate>
            <description><![CDATA[<h2 id="문제">문제</h2>
<p>숭실골 높은 언덕 깊은 골짜기에 출제로 고통 받는 욱제가 살고 있다!</p>
<p>욱제는 또 출제를 해야 해서 단단히 화가 났다. </p>
<p>그래서 욱제는 길이 N짜리 수열 A를 만들고, A를 비내림차순으로 정렬해서 수열 B를 만들어 버렸다!! 여기서 B를 출력하기만 하면 문제가 너무 쉬우니까 하나만 더 하자. 아래와 같은 질문이 무려 Q개나 주어진다!! (ㅎㅎ;; ㅈㅅ.. ㅋㅋ!!)</p>
<p>L R: BL + BL+1 + ... + BR-1 + BR 을 출력한다.</p>
<p>Figure 1. 모든 참가자가 문제를 풀 수 있을 것이라고 기대하는 욱제의 표정</p>
<p>욱제의 질문에 답하고 함께 엠티를 떠나자!!</p>
<hr>
<h3 id="입력">입력</h3>
<p>첫 번째 줄에 수열 A의 길이 N과 질문의 개수 Q가 공백으로 구분되어 주어진다. (1 ≤ N, Q ≤ 300,000)</p>
<p>두 번째 줄에 N개의 정수 A1, A2, ..., AN 이 공백으로 구분되어 주어진다. Ai 는 수열 A의 i 번째 수이다. (1 ≤ Ai ≤ 1,000)</p>
<p>세 번째 줄부터 Q개의 줄에 걸쳐 욱제의 질문을 의미하는 두 수 L, R이 공백으로 구분되어 주어진다. (1 ≤ L ≤ R ≤ N)</p>
<p>주어지는 모든 입력은 자연수이다.</p>
<hr>
<h3 id="출력">출력</h3>
<p>Q개의 줄에 걸쳐, 질문의 답을 순서대로 각각 출력한다.</p>
<hr>
<h2 id="코드">코드</h2>
<pre><code class="language-java">import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.StringTokenizer;

public class No_17390 {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st=new StringTokenizer(br.readLine());

        int n = Integer.parseInt(st.nextToken());
        int Q = Integer.parseInt(st.nextToken());
        int A[]=new int [n+1];
        int S[]=new int [n+1];
        int sum=0;

        st=new StringTokenizer(br.readLine());
        for(int i=1; i&lt;=n; i++){
            A[i]=Integer.parseInt(st.nextToken());
        }

        Arrays.sort(A);
        for(int i=1; i&lt;=n; i++){
            S[i]+=A[i]+S[i-1];
        }

        for(int i=0; i&lt;Q; i++){
            st=new StringTokenizer(br.readLine());
            int L=Integer.parseInt(st.nextToken());
            int R=Integer.parseInt(st.nextToken());
            System.out.println(S[R]-S[L-1]);
        }
    }
}
</code></pre>
<h3 id="풀이🤩">풀이🤩</h3>
<ul>
<li>먼저 수열 A를 입력 받은 뒤 문제 조건에 <code>비내림차순(오름차순)</code> 이라는 조건이 있으니 <code>Arrays.sort</code>로 정렬한다. </li>
<li>배열 S에는 A배열의 합을 계산해서 넣는다. ex) s[3]=a1+a2+a3  코드로 하면 <code>S[i]+=A[i]+S[i-1]</code> </li>
<li>문제의 구간을 입력 받은 후 S수열을 이용해 정답을 바로 출력한다 <h3 id="마무리">마무리</h3>
</li>
<li>나는 첨에 int L과 R을 for문 밖에 정의했었는데 자꾸 시간초과가 나서 for문안에 넣어봤더니 바로 통과했다.. 어려운 알고리즘의 세계^_^</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[알고리즘 개념] 구간 합]]></title>
            <link>https://velog.io/@yeeeerim_/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%EA%B0%9C%EB%85%90-%EA%B5%AC%EA%B0%84-%ED%95%A9</link>
            <guid>https://velog.io/@yeeeerim_/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%EA%B0%9C%EB%85%90-%EA%B5%AC%EA%B0%84-%ED%95%A9</guid>
            <pubDate>Tue, 25 Apr 2023 06:54:09 GMT</pubDate>
            <description><![CDATA[<h2 id="구간-합의-핵심이론">구간 합의 핵심이론</h2>
<p>구간 합 알고리즘을 활용하려면 먼저 합 배열을 구해야한다. 
배열 A가 있을 때 합 배열 S는 다음과 같이 정의한다. 
<code>S[i] = A[0] + A[1] + A[2] + ... + A[i-1] + A [i]</code></p>
<h3 id="합-배열-s를-만드는-공식">합 배열 S를 만드는 공식</h3>
<p><code>S[i] = S[i-1] +A[i]</code></p>
<h3 id="구간-합을-구하는-공식">구간 합을 구하는 공식</h3>
<p><code>S[j] - S[i-1]</code> </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Sping Security (1)🔒]]></title>
            <link>https://velog.io/@yeeeerim_/Sping-Security-1</link>
            <guid>https://velog.io/@yeeeerim_/Sping-Security-1</guid>
            <pubDate>Fri, 21 Apr 2023 06:34:42 GMT</pubDate>
            <description><![CDATA[<h2 id="용어">용어</h2>
<h3 id="💼-인증authentication">💼 인증(Authentication)</h3>
<blockquote>
<p><code>스스로를 증명하다</code>라는 뜻으로 흔히 말하는 로그인 개념이다. 
인증을 위해서 사용자는 자신이 알고 있는 자신의 정보를 제공하는데 아이디와 패스워드가 이에 속한다. </p>
</blockquote>
<h3 id="🙆🏻♀️-인가authorization">🙆🏻‍♀️ 인가(Authorization)</h3>
<blockquote>
<p><code>허가나 권한</code>이라는 개념과 같다. 인증이 된 사용자라고 해도 이에 접근 할 수 있는 권한이 있는지를 확인하는 과정을 의미한다. </p>
</blockquote>
<h3 id="🔒-접근-주체principal">🔒 접근 주체(Principal)</h3>
<blockquote>
<p>보호받는 리소스에 접근하는 대상</p>
</blockquote>
<h3 id="🏅-권한">🏅 권한</h3>
<blockquote>
<p>인증된 주체가 어플리케이션의 동작을 수행할 수 있도록 허락되어 있는지 결정</p>
</blockquote>
<ul>
<li>인증 과정을 통해 주체가 증명된 후 권한 부여 가능</li>
<li>권한 부여에 두 가지 영역이 존재하는데 <code>웹 요청 권한</code>과 <code>메서드 호출 및 도메인 인스턴스에 대한 접근권한 부여</code> 총 2가지가 있다. </li>
</ul>
<h2 id="spring-security-동작-방식">Spring Security 동작 방식</h2>
<p><img src="https://velog.velcdn.com/images/yeeeerim_/post/abb6ccc3-9fc7-415e-98c6-d925ee582645/image.png" alt=""></p>
<ol>
<li>요청 수신</li>
</ol>
<ul>
<li>사용자가 form을 통해 로그인 정보가 담긴 Request를 보낸다.</li>
</ul>
<ol start="2">
<li>토큰 생성</li>
</ol>
<ul>
<li>AuthenticationFilter가 요청을 받아서 UsernamePasswordAuthenticationToken토큰(인증용 객체)을 생성</li>
<li>UsernamePasswordAuthenticationToken은 해당 요청을 처리할 수 있는 Provider을 찾는데 사용</li>
</ul>
<ol start="3">
<li>AuthenticationFilter로 부터 인증용 객체를 전달 받는다.</li>
</ol>
<ul>
<li>Authentication Manager에게 처리 위임</li>
<li>Authentication Manager는 List형태로 Provider들을 갖고 있다.</li>
</ul>
<ol start="4">
<li>Token을 처리할 수 있는 Authentication Provider 선택</li>
</ol>
<ul>
<li>실제 인증을 할 AuthenticationProvider에게 인증용 객체를 다시 전달한다.</li>
</ul>
<ol start="5">
<li>인증 절차</li>
</ol>
<ul>
<li>인증 절차가 시작되면 AuthenticationProvider 인터페이스가 실행되고 DB에 있는 사용자의 정보와 화면에서 입력한 로그인 정보를 비교</li>
</ul>
<ol start="6">
<li>UserDetailsService의 loadUserByUsername메소드 수행</li>
</ol>
<ul>
<li>AuthenticationProvider 인터페이스에서는 authenticate() 메소드를 오버라이딩 하게 되는데 이 - 메소드의 파라미터인 인증용 객체로 화면에서 입력한 로그인 정보를 가져올 수 있다.</li>
</ul>
<ol start="7">
<li><p>AuthenticationProvider 인터페이스에서 DB에 있는 사용자의 정보를 가져오려면, UserDetailsService 인터페이스를 사용한다.</p>
</li>
<li><p>UserDetailsService 인터페이스는 화면에서 입력한 사용자의 username으로 loadUserByUsername() 메소드를 호출하여 DB에 있는 사용자의 정보를 UserDetails 형으로 가져온다. 만약 사용자가 존재하지 않으면 예외를 던진다. 이렇게 DB에서 가져온 이용자의 정보와 화면에서 입력한 로그인 정보를 비교하게 되고, 일치하면 Authentication 참조를 리턴하고, 일치 하지 않으면 예외를 던진다.</p>
</li>
<li><p>인증이 완료되면 사용자 정보를 가진 Authentication 객체를 SecurityContextHolder에 담은 이후 AuthenticationSuccessHandle를 실행한다.(실패시 AuthenticationFailureHandler를 실행한다.)</p>
</li>
</ol>
<h2 id="filter">Filter</h2>
<h3 id="🍎-usernamepasswordauthenticationfilter">🍎 (UsernamePassword)AuthenticationFilter</h3>
<blockquote>
<p>아이디와 비밀번호를 사용하는 <code>form</code> 기반 인증
설정된 로그인 URL로 오는 요청을 감시하며, 유저 인증 처리인 <code>AuthenticationManager를</code> 통한 인증 실행
인증이 성공한다면 인증용 객체를 <code>SecurityContext</code>에 저장 후 <code>AuthenticationSuccessHandler</code> 실행, 실패시에는 <code>AuthenticationFailureHandler</code> 실행</p>
</blockquote>
<h3 id="👩🏻💻-authenticationprovider">👩🏻‍💻 AuthenticationProvider</h3>
<blockquote>
<p>화면에서 입력한 로그인 정보와 DB정보를 비교
Spring Security의 <code>AuthenticationProvider</code>을 구현한 클래스로 <code>security-context</code>에 <code>provider</code>로 등록 후 인증절차를 구현한다.
login view에서 login-processing-url로의 form action 진행 시 해당 클래스의 supports() &gt; authenticate() 순으로 인증 절차 진행</p>
</blockquote>
<h3 id="🪴-userdetailsservice">🪴 UserDetailsService</h3>
<blockquote>
<p>UserDetailsService 인터페이스는 DB에서 유저 정보를 가져오는 역할
<img src="https://velog.velcdn.com/images/yeeeerim_/post/c94da833-bc18-4c09-baba-b83ae6b669bf/image.png" alt=""></p>
</blockquote>
<h3 id="👑-userdetails">👑 UserDetails</h3>
<blockquote>
<p>사용자의 정보를 담는 인터페이스, 직접 상속받아 사용한다.</p>
</blockquote>
<h2 id="reference">reference</h2>
<p><a href="https://velog.io/@kyungwoon/Spring-Security-%EB%8F%99%EC%9E%91-%EC%9B%90%EB%A6%AC">https://velog.io/@kyungwoon/Spring-Security-%EB%8F%99%EC%9E%91-%EC%9B%90%EB%A6%AC</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[HTTP란?]]></title>
            <link>https://velog.io/@yeeeerim_/HTTP%EB%9E%80</link>
            <guid>https://velog.io/@yeeeerim_/HTTP%EB%9E%80</guid>
            <pubDate>Fri, 14 Apr 2023 05:09:36 GMT</pubDate>
            <description><![CDATA[<h3 id="http">HTTP</h3>
<p><strong>HyperText Transfer Protocol</strong></p>
<ul>
<li>하이퍼텍스트(HTML) 문서를 교환하기 위해 만들어진 protocol(통신 규약).</li>
<li>즉 웹상에서 네트워크로 서버끼리 통신을 할때 어떠한 형식으로 서로 통신을 하자고 규정해 놓은 &quot;통신 형식&quot; 혹은 &quot;통신 구조&quot; 라고 보면 된다.</li>
<li>프론트앤드 서버와 클라이언트간의 통신에 사용된다.</li>
<li>또한 백앤드와 프론트앤드 서버간에의 통신에도 사용된다.</li>
<li>HTTP는 TCP/IP 기반으로 되어있다.</li>
<li>HTTP 기본적으로 request(요청)/response(응답) 구조로 되어있다.</li>
<li>클라이언트가 HTTP request를 서버에 보내면 서버는 HTTP response를 보내는 구조</li>
<li>클라이언트와 서버의 모든 통신이 요청과 응답으로 이루어 진다.</li>
</ul>
<hr>
<h3 id="request-message">Request Message</h3>
<p>HTTP Request Message는 공백(blank line)을 제외하고 3가지 부분으로 나누어진다.</p>
<p><strong>HTTP Request Message 구조</strong></p>
<ul>
<li>Start Line</li>
<li>Headers</li>
<li>Body
<img src="https://velog.velcdn.com/images/yeeeerim_/post/fb0f7fce-7228-49b1-8c0f-a667eb10bf95/image.png" alt=""></li>
</ul>
<h4 id="start-line">start line</h4>
<p>HTTP Request Message의 시작 라인
HTTP request의 start line 3가지 부분으로 구성</p>
<ul>
<li><p>HTTP method</p>
</li>
<li><p>Request target</p>
</li>
<li><p>HTTP version</p>
<pre><code>GET /test.html HTTP/1.1
[HTTP Method] [Request target] [HTTP version]</code></pre></li>
<li><p>HTTP method는 요청의 의도를 담고 있는 GET, POST, PUT, DELETE 등이 있습니다. GET은 존재하는 자원에 대한 요청, POST는 새로운 자원을 생성, PUT은 존재하는 자원에 대한 변경, DELETE는 존재하는 자원에 대한 삭제와 같은 기능을 가지고 있습니다.</p>
</li>
<li><p>Request target은 HTTP Request가 전송되는 목표 주소입니다.</p>
</li>
<li><p>HTTP version은 version에 따라 Request 메시지 구조나 데이터가 다를 수 있어서 version을 명시합니다.</p>
</li>
</ul>
<h4 id="headers">headers</h4>
<ul>
<li><p>해당 request에 대한 추가 정보(addtional information)를 담고 있는 부분</p>
</li>
<li><p>예를 들어, request 메세지 body의 총 길이 (Content-Length) 등 Key:Value 형태로 구성</p>
</li>
<li><p>headers도 크게 3가지 부분으로 나뉨(general headers, request headers, entity headers)</p>
</li>
</ul>
<pre><code>Host: google.com
Accept: text/html
Accept-Encoding: gzip, deflate
Connection: keep-alive</code></pre><ul>
<li><strong>Host</strong> 요청하려는 서버 호스트 이름과 포트번호</li>
<li><strong>User-agent</strong> 클라이언트 프로그램 정보. 이 정보를 통해 서버는 클라이언트 프로그램(브라우저)에 맞는 최적의 데이터를 보내줄 수 있다.</li>
<li><strong>Referer</strong> 바로 직전에 머물렀던 웹 링크 주소 </li>
<li><strong>Accept</strong> 클라이언트가 처리 가능한 미디어 타입 종류 나열</li>
<li><strong>If-Modified-Since</strong> 여기에 쓰여진 시간 이후로 변경된 리소스 취득. 페이지가 수정되었으면 최신 페이지로 교체한다.</li>
<li><strong>Authorization</strong> 인증 토큰을 서버로 보낼 때 쓰이는 Header</li>
<li><strong>Origin</strong> 서버로 Post 요청을 보낼 때 요청이 어느 주소에 시작되었는지 나타내는 값. 이 값으로 요청을 보낸 주소와 받는 주소가 다르면 CORS(Cross-Origin Resource Sharing) 에러가 발생한다.</li>
<li><strong>Cookie</strong> 쿠키 값이 key-value로 표현된다.</li>
</ul>
<h4 id="body">body</h4>
<ul>
<li>HTTP Request가 전송하는 데이터를 담고 있는 부분</li>
<li>전송하는 데이터가 없다면 body 부분은 비어있습니다.</li>
<li>보통 post 요청일 경우, HTML 폼 데이터가 포함되어 있습니다.</li>
</ul>
<pre><code>POST /test HTTP/1.1


Accept: application/json
Accept-Encoding: gzip, deflate
Connection: keep-alive
Content-Length: 83
Content-Type: application/json
Host: google.com
User-Agent: HTTPie/0.9.3

{
    &quot;test_id&quot;: &quot;tmp_1234567&quot;,
    &quot;order_id&quot;: &quot;8237352&quot;
}</code></pre><h3 id="response-message">Response Message</h3>
<ul>
<li><p>HTTP Response Message는 request와 동일하게 공백(blank line)을 제외하고 3가지 부분으로 나누어진다.</p>
</li>
<li><p>Status Line</p>
</li>
<li><p>Headers</p>
</li>
<li><p>Body</p>
</li>
</ul>
<p><img src="https://velog.velcdn.com/images/yeeeerim_/post/e962cb7a-33bd-4664-8206-f5b902de4210/image.png" alt=""></p>
<h4 id="status-line">status line</h4>
<ul>
<li>HTTP Response의 상태를 간략하게 나타내주는 부분</li>
<li>HTTP Response의 status line또한 3가지 부분으로 구성</li>
</ul>
<pre><code>HTTP version
Status Code
Status Text
HTTP/1.1 200 OK
[HTTP version] [Status Code] [Status Text]</code></pre><h4 id="headers-1">headers</h4>
<p>Response의 headers와 동일하다.
다만 response에서만 사용되는 header 값들이 있다.
예를 들어, User-Agent 대신에 Server 헤더가 사용된다.</p>
<h4 id="body-1">body</h4>
<p>Response의 body와 일반적으로 동일하다.
Request와 마찬가지로 모든 response가 body가 있지는 않다.
데이터를 전송할 필요가 없을경우 body가 비어있게 된다.</p>
<h2 id="참고🙇♀️">참고🙇‍♀️</h2>
<p><a href="https://hahahoho5915.tistory.com/62">https://hahahoho5915.tistory.com/62</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[패스트캠퍼스 백엔드 과정 4기 부트캠프 #03. 2/13~4/6 회고 (실시간 강의, 2차 그룹스터디 워크샵, 모의코딩 테스트)]]></title>
            <link>https://velog.io/@yeeeerim_/%ED%8C%A8%EC%8A%A4%ED%8A%B8%EC%BA%A0%ED%8D%BC%EC%8A%A4-%EB%B0%B1%EC%97%94%EB%93%9C-%EA%B3%BC%EC%A0%95-4%EA%B8%B0-%EB%B6%80%ED%8A%B8%EC%BA%A0%ED%94%84-03.-21346-%ED%9A%8C%EA%B3%A0-%EC%8B%A4%EC%8B%9C%EA%B0%84-%EA%B0%95%EC%9D%98-2%EC%B0%A8-%EA%B7%B8%EB%A3%B9%EC%8A%A4%ED%84%B0%EB%94%94-%EC%9B%8C%ED%81%AC%EC%83%B5-%EB%AA%A8%EC%9D%98%EC%BD%94%EB%94%A9-%ED%85%8C%EC%8A%A4%ED%8A%B8</link>
            <guid>https://velog.io/@yeeeerim_/%ED%8C%A8%EC%8A%A4%ED%8A%B8%EC%BA%A0%ED%8D%BC%EC%8A%A4-%EB%B0%B1%EC%97%94%EB%93%9C-%EA%B3%BC%EC%A0%95-4%EA%B8%B0-%EB%B6%80%ED%8A%B8%EC%BA%A0%ED%94%84-03.-21346-%ED%9A%8C%EA%B3%A0-%EC%8B%A4%EC%8B%9C%EA%B0%84-%EA%B0%95%EC%9D%98-2%EC%B0%A8-%EA%B7%B8%EB%A3%B9%EC%8A%A4%ED%84%B0%EB%94%94-%EC%9B%8C%ED%81%AC%EC%83%B5-%EB%AA%A8%EC%9D%98%EC%BD%94%EB%94%A9-%ED%85%8C%EC%8A%A4%ED%8A%B8</guid>
            <pubDate>Thu, 06 Apr 2023 11:09:03 GMT</pubDate>
            <description><![CDATA[<p>12월에 시작한 과정이 어느덧 중반을 넘어가고 있다.. 첨엔 7개월 어떻게 듣나했더니 듣다보니 적응되어버린,,,, ㅋㅋㅋㅋ ㅠㅠ 취업준비도 이제 슬슬해야하는데 어렵다 어려워 ~~ </p>
<p>이번회고는 2월 13일부터 오늘날짜인 4월6일까지의 회고를 작성해보려고 한다. </p>
<h2 id="📚-스프링-강의-시작">📚 스프링 강의 시작</h2>
<p>패캠 백엔드 과정은 거의 1시부터 6시까지 자습하고, 7시부터 10시까지 실시간 강의를 듣는다 !
자바 실시간 강의가 끝나고 스프링 실시간 강의를 듣게 되었다. 
그룹스터디에서 스프링부트 프로젝트를 하고있어 조금 알고있긴 하지만 이 과정에 들어오게 된 가장 큰 이유가 스프링을 배울 수 있어서기에 기대가 많이 됐었다. 
스프링 강사님의 강의는 녹화본도 제공되고, 강의자료나 판서까지 제공해주셔서 복습을 원활하게 할 수 있어서 좋다 ! ! 
<img src="https://velog.velcdn.com/images/yeeeerim_/post/d867e645-df04-4921-9ea7-d8896b59807b/image.png" alt=""></p>
<p>엉망진창 내 글씨.. 이럴줄 알았으면 아이패드 팔지 말걸~~:) ㅎㅎ
스프링 강사님은 하나부터 열까지 차근차근 풀어서 이해하기 쉽게 예시까지 들어서 설명해주셔서 어려운 스프링을 이해하는데 도움이 정말많이 된다.. 특히 개념들...?
<img src="https://velog.velcdn.com/images/yeeeerim_/post/6caa4e23-1497-4650-848d-b80c52094335/image.png" alt=""></p>
<p>실습코드 같은 것들도 직접 수업전에 준비해오셔서 깃에 올려주시고 clone받아 수업시간에 같이 학습하면 된다:) 
<img src="https://velog.velcdn.com/images/yeeeerim_/post/104f132a-f96e-4591-8bae-0d6152f7fd53/image.png" alt=""></p>
<p>강의 판서 ! </p>
<h2 id="🧐-데이터베이스--알고리즘--운영체제--컴퓨터구조-실시간강의">🧐 데이터베이스 / 알고리즘 / 운영체제 / 컴퓨터구조 실시간강의</h2>
<p>백엔드 과정에서 기본적으로 제공해주는 강의에 CS관련 강의가 있지만 실시간 강의로도 위의 과목들이 준비되어있다. 
특히 비전공자같은경우 CS지식을 독학하기엔 어려움이 많이 있을거라고 생각이 드는데 많은 도움이 될 것 같다
이 과목 강사님은 스펙이 완전 화려하시다.. 쿠팡이랑 삼성? 에서 일하셨다고 들은거같음.. 
강의자료는 블로그에 올리지 말아달라고 하셔서 올리지 못하지만 기본적으로 자료나 강의 구성이 이런것들이 정말 잘 정리되어 있다 ! </p>
<h2 id="🧑🏻🏫-2회차-그룹스터디-워크샵">🧑🏻‍🏫 2회차 그룹스터디 워크샵</h2>
<p>2회차 그룹스터디 워크샵은 조마다 주제를 하나 정해서 그 주제를 발표하는 형식으로 진행했다. 
1회차와 마찬가지로 워크샵 전에 멘토님과 30분씩 2번 미팅이 있다. 
원래 <code>영속성 컨텍스트</code>로 주제를 정하려고 했었는데 멘토님이 너무 어려울 것 같다고 <code>JWT</code>는 어떻겠냐고 제안해주셔서 우리조는 발표주제를 <code>JWT</code>로 정했따 !</p>
<p><img src="https://velog.velcdn.com/images/yeeeerim_/post/49a53312-40bf-4335-8da5-bca3cda23da4/image.png" alt=""></p>
<p>목차는 JWT설명할때 필요한 간단한 개념들(필터, 인증,인가) , 세션, JWT 이론 마지막으로 직접 팀장님이 JWT구현 코드를 짜서 설명하는 식으로 구성했다 ! </p>
<p><img src="https://velog.velcdn.com/images/yeeeerim_/post/84275ed6-b52e-498a-9cf9-adbbe924dbe8/image.png" alt="">
JWT 관련 정리한 내용은 내 블로그 포스팅에도 있다:p</p>
<p><img src="https://velog.velcdn.com/images/yeeeerim_/post/3581dfb2-4721-4da6-8688-937642f270aa/image.png" alt="">
짱이쥬? 
근데 멘토님이 발표끝나고 얘기하실때 우리조 얼굴 잘 봐두라고 하셔서 당황했음.. 코드는 팀장님이 다 짜셨는데용... ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ큐ㅠㅠㅠㅠ</p>
<p>다른 조들도 마찬가지로 정렬, BFS, 스프링 개념 등등 준비를 정말 열심히 해오셔서 원래 시간예정은 2시간이였는데 거의 3시간?정도하고 그룹스터디가 끝이 났다:)</p>
<p>이번 워크샵을 통해 다른 조들의 발표를 들으며 나의 지식도 +10정도 된 기분.... 까먹지 않겠어요 </p>
<h2 id="모의-코딩테스트">모의 코딩테스트</h2>
<p>지금까지 코딩테스트를 총 2번 봤다. 
<img src="https://velog.velcdn.com/images/yeeeerim_/post/018aea0c-83b4-4f89-91c6-3d045ccee268/image.png" alt="">
응시 전에 메일로 사전테스트 링크가 오고 여기서 테스트까지 같이본다 
문제는 총 4문제로 시간은 3시간 ? 정도이다. ! 
백준처럼 인텔리제이를 쓰지는 않고 프로그래머스에서 본다!
첨에 모의 코딩테스트봤을때 진짜 멘붕 그 잡채.. ㅋㅋ ㅋㅋ ㅋ너어무 어려워서 레벨 2는 무조건 넘을줄 알았는데 레벨 1문제를 내가 헤맨거더라 ~ 발전하자 </p>
<p><img src="https://velog.velcdn.com/images/yeeeerim_/post/e81ac707-b6ca-4fb3-a0ba-d53d0f3908c5/image.png" alt=""></p>
<p>테스트 시간이 끝나면 패캠에서 답안을 제공해준다. 이것들로 못풀었던 문제들을 회고할 수 있다 
그리고 수강생 전반적인 점수 분포도도 같이 제공해준다^__^ 나빼고 다 잘푸셨더라 ~~ ㅋㅋㅋ ㅋ ㅋ ㅋㅋ 그래도 2회차는 그나마 점수 더 받음 껄껄 아직 멀었다.. </p>
<p>미리 코딩테스트에 대한 중요도를 알고 경험할 수 있는 좋은활동이라고 생각한다 ! </p>
<h2 id="마무리">마무리</h2>
<p>앞서 말했듯이 벌써 4월이다 5월부터는 미니프로젝트 한다던데... 벌써 무섭다 
그때는 프론트랑 백이랑 같이 협업한다던데.... ㅋㅋㅋ 잘할수 있을까<del>?
암튼 화이팅이구만요 취업하는 그날까지 ~</del></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[알고리즘]_덧칠하기🎨(프로그래머스 Lv.1)]]></title>
            <link>https://velog.io/@yeeeerim_/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98%EB%8D%A7%EC%B9%A0%ED%95%98%EA%B8%B0%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-Lv.1</link>
            <guid>https://velog.io/@yeeeerim_/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98%EB%8D%A7%EC%B9%A0%ED%95%98%EA%B8%B0%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-Lv.1</guid>
            <pubDate>Mon, 20 Mar 2023 13:07:49 GMT</pubDate>
            <description><![CDATA[<h3 id="문제">문제</h3>
<p>어느 학교에 페인트가 칠해진 길이가 n미터인 벽이 있습니다. 벽에 동아리 · 학회 홍보나 회사 채용 공고 포스터 등을 게시하기 위해 테이프로 붙였다가 철거할 때 떼는 일이 많고 그 과정에서 페인트가 벗겨지곤 합니다. 페인트가 벗겨진 벽이 보기 흉해져 학교는 벽에 페인트를 덧칠하기로 했습니다.</p>
<p>넓은 벽 전체에 페인트를 새로 칠하는 대신, 구역을 나누어 일부만 페인트를 새로 칠 함으로써 예산을 아끼려 합니다. 이를 위해 벽을 1미터 길이의 구역 n개로 나누고, 각 구역에 왼쪽부터 순서대로 1번부터 n번까지 번호를 붙였습니다. 그리고 페인트를 다시 칠해야 할 구역들을 정했습니다.</p>
<p>벽에 페인트를 칠하는 롤러의 길이는 m미터이고, 롤러로 벽에 페인트를 한 번 칠하는 규칙은 다음과 같습니다.</p>
<p>롤러가 벽에서 벗어나면 안 됩니다.
구역의 일부분만 포함되도록 칠하면 안 됩니다.
즉, 롤러의 좌우측 끝을 구역의 경계선 혹은 벽의 좌우측 끝부분에 맞춘 후 롤러를 위아래로 움직이면서 벽을 칠합니다. 현재 페인트를 칠하는 구역들을 완전히 칠한 후 벽에서 롤러를 떼며, 이를 벽을 한 번 칠했다고 정의합니다.</p>
<p>한 구역에 페인트를 여러 번 칠해도 되고 다시 칠해야 할 구역이 아닌 곳에 페인트를 칠해도 되지만 다시 칠하기로 정한 구역은 적어도 한 번 페인트칠을 해야 합니다. 예산을 아끼기 위해 다시 칠할 구역을 정했듯 마찬가지로 롤러로 페인트칠을 하는 횟수를 최소화하려고 합니다.</p>
<p>정수 n, m과 다시 페인트를 칠하기로 정한 구역들의 번호가 담긴 정수 배열 section이 매개변수로 주어질 때 롤러로 페인트칠해야 하는 최소 횟수를 return 하는 solution 함수를 작성해 주세요.</p>
<hr>
<p><strong>제한사항</strong>
1 ≤ m ≤ n ≤ 100,000
1 ≤ section의 길이 ≤ n
1 ≤ section의 원소 ≤ n
section의 원소는 페인트를 다시 칠해야 하는 구역의 번호입니다.
section에서 같은 원소가 두 번 이상 나타나지 않습니다.
section의 원소는 오름차순으로 정렬되어 있습니다.</p>
<hr>
<h4 id="입출력-예">입출력 예</h4>
<table>
<thead>
<tr>
<th>n</th>
<th>m</th>
<th>section</th>
<th>result</th>
</tr>
</thead>
<tbody><tr>
<td>8</td>
<td>4</td>
<td>[2, 3, 6]</td>
<td>2</td>
</tr>
<tr>
<td>5</td>
<td>4</td>
<td>[1, 3]</td>
<td>1</td>
</tr>
<tr>
<td>4</td>
<td>1</td>
<td>[1, 2, 3, 4]</td>
<td>4</td>
</tr>
<tr>
<td><strong>입출력 예 설명</strong></td>
<td></td>
<td></td>
<td></td>
</tr>
</tbody></table>
<p><strong>입출력 예 #1</strong></p>
<p>예제 1번은 2, 3, 6번 영역에 페인트를 다시 칠해야 합니다. 롤러의 길이가 4미터이므로 한 번의 페인트칠에 연속된 4개의 구역을 칠할 수 있습니다. 처음에 3, 4, 5, 6번 영역에 페인트칠을 하면 칠해야 할 곳으로 2번 구역만 남고 1, 2, 3, 4번 구역에 페인트칠을 하면 2번 만에 다시 칠해야 할 곳에 모두 페인트칠을 할 수 있습니다.</p>
<p><img src="https://velog.velcdn.com/images/yeeeerim_/post/abb11a45-da9b-4880-901e-10b39f21e5b8/image.png" alt=""></p>
<p>2번보다 적은 횟수로 2, 3, 6번 영역에 페인트를 덧칠하는 방법은 없습니다. 따라서 최소 횟수인 2를 return 합니다.</p>
<p><strong>입출력 예 #2</strong></p>
<p>예제 2번은 1, 3번 영역에 페인트를 다시 칠해야 합니다. 롤러의 길이가 3미터이므로 한 번의 페인트칠에 연속된 3개의 구역을 칠할 수 있고 1, 2, 3번 영역에 페인트칠을 하면 한 번에 1, 3번 영역을 모두 칠할 수 있습니다.</p>
<p><img src="https://velog.velcdn.com/images/yeeeerim_/post/008f5b0d-dcac-4412-9e94-3b0d625910fb/image.png" alt=""></p>
<p>따라서 최소 횟수인 1을 return 합니다.</p>
<p><strong>입출력 예 #3</strong></p>
<p>예제 3번은 모든 구역에 페인트칠을 해야 합니다. 롤러의 길이가 1미터이므로 한 번에 한 구역밖에 칠할 수 없습니다. 구역이 4개이므로 각 구역을 한 번씩만 칠하는 4번이 최소 횟수가 됩니다.</p>
<p><img src="https://velog.velcdn.com/images/yeeeerim_/post/ae2d97e4-241b-47eb-b85e-cf46dbcbf3b4/image.png" alt=""></p>
<p>따라서 4를 return 합니다.</p>
<pre><code class="language-java">class Solution {
  public int solution(int n, int m, int[] section) {
      int answer = 0;
      int max = 0;

      for (int i = 0; i &lt; section.length; i++) {
          if (section[i] &lt; max) {
              continue;
          }

          answer += 1;
          max = section[i] + m;
      }

      return answer;
  }
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[알고리즘]_백트래킹_N과 M(1) (백준 No. 15649)]]></title>
            <link>https://velog.io/@yeeeerim_/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98%EB%B0%B1%ED%8A%B8%EB%9E%98%ED%82%B9N%EA%B3%BC-M1-%EB%B0%B1%EC%A4%80-No.-15649</link>
            <guid>https://velog.io/@yeeeerim_/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98%EB%B0%B1%ED%8A%B8%EB%9E%98%ED%82%B9N%EA%B3%BC-M1-%EB%B0%B1%EC%A4%80-No.-15649</guid>
            <pubDate>Wed, 15 Mar 2023 15:11:15 GMT</pubDate>
            <description><![CDATA[<h3 id="문제">문제</h3>
<p>자연수 N과 M이 주어졌을 때, 아래 조건을 만족하는 길이가 M인 수열을 모두 구하는 프로그램을 작성하시오.
1부터 N까지 자연수 중에서 중복 없이 M개를 고른 수열</p>
<hr>
<p><strong>입력</strong>
첫째 줄에 자연수 N과 M이 주어진다. (1 ≤ M ≤ N ≤ 8)</p>
<hr>
<p><strong>출력</strong>
한 줄에 하나씩 문제의 조건을 만족하는 수열을 출력한다. 중복되는 수열을 여러 번 출력하면 안되며, 각 수열은 공백으로 구분해서 출력해야 한다.
수열은 사전 순으로 증가하는 순서로 출력해야 한다.</p>
<hr>
<pre><code class="language-java">import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
import java.util.StringTokenizer;

public class Main {

    public static int[] arr;
    public static boolean[] visit;
    public static StringBuilder sb = new StringBuilder();

    public static void main(String[] args) throws IOException {

        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        StringTokenizer st = new StringTokenizer(br.readLine());

        int N = Integer.parseInt(st.nextToken());
        int M = Integer.parseInt(st.nextToken());

        arr = new int[M];
        visit = new boolean[N];
        dfs(N, M, 0);
        System.out.println(sb);

    }

    public static void dfs(int N, int M, int depth) {
        if (depth == M) {
            for (int val : arr) {
                sb.append(val).append(&#39; &#39;);
            }
            sb.append(&#39;\n&#39;);
            return;
        }

        for (int i = 0; i &lt; N; i++) {
            if (!visit[i]) {
                visit[i] = true;
                arr[depth] = i + 1;
                dfs(N, M, depth + 1);
                visit[i] = false;
            }
        }
    }

}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[패스트캠퍼스 백엔드 과정 4기 부트캠프 #02. 1/13~2/12 회고 ( 커리어 코칭/ 그룹스터디 워크샵 )]]></title>
            <link>https://velog.io/@yeeeerim_/%ED%8C%A8%EC%8A%A4%ED%8A%B8%EC%BA%A0%ED%8D%BC%EC%8A%A4-%EB%B0%B1%EC%97%94%EB%93%9C-%EA%B3%BC%EC%A0%95-4%EA%B8%B0-%EB%B6%80%ED%8A%B8%EC%BA%A0%ED%94%84-02.-113212-%ED%9A%8C%EA%B3%A0-%EC%BB%A4%EB%A6%AC%EC%96%B4-%EC%BD%94%EC%B9%AD-%EA%B7%B8%EB%A3%B9%EC%8A%A4%ED%84%B0%EB%94%94-%EC%9B%8C%ED%81%AC%EC%83%B5</link>
            <guid>https://velog.io/@yeeeerim_/%ED%8C%A8%EC%8A%A4%ED%8A%B8%EC%BA%A0%ED%8D%BC%EC%8A%A4-%EB%B0%B1%EC%97%94%EB%93%9C-%EA%B3%BC%EC%A0%95-4%EA%B8%B0-%EB%B6%80%ED%8A%B8%EC%BA%A0%ED%94%84-02.-113212-%ED%9A%8C%EA%B3%A0-%EC%BB%A4%EB%A6%AC%EC%96%B4-%EC%BD%94%EC%B9%AD-%EA%B7%B8%EB%A3%B9%EC%8A%A4%ED%84%B0%EB%94%94-%EC%9B%8C%ED%81%AC%EC%83%B5</guid>
            <pubDate>Wed, 15 Mar 2023 15:07:40 GMT</pubDate>
            <description><![CDATA[<p>추운 겨울을 지나 어느덧 따뜻한 봄이 오고 있습니다아 🌸 
처음 과정을 시작할때만 해도 언제 끝나나했는데 이제는 너무 적응해서 이젠 하루가 짧게 느껴질 정도.. 
이번 포스팅에서는 2회차 단위기간동안의 회고를 쓰려고 합니다 ! (1.13~2.12)</p>
<h2 id="💼-커리어-코칭">💼 커리어 코칭</h2>
<p><img src="https://velog.velcdn.com/images/yeeeerim_/post/e3ab8b3b-8c01-4cb5-861d-5d66d5c7e0b4/image.png" alt="">
패스트 캠퍼스 백엔드 과정에서는 취업을 위한 <code>커리어 코칭</code> 서비스를 제공하고 있다.
12월에 커리어 코칭 서비스 소개와 이력서 특강을 듣고 1월 말~ 2월 초에 담임기버를 매칭해 실제 현업에 계신 분들의 적극적인 도움을 받아 볼 수 있다 🙆🏻‍♀️</p>
<h3 id="--커리어-코칭-서비스-안내">- 커리어 코칭 서비스 안내</h3>
<blockquote>
<h3 id="11-커리어-코칭"><strong><code>1:1 커리어 코칭</code></strong></h3>
</blockquote>
<ul>
<li>이번 메가바이트스쿨 4기 수강생분들께는 <strong>개인당 3회씩</strong>, 1:1 커리어 코칭 서비스가 제공됩니다.</li>
<li><ul>
<li>3회차 커리어 서비스의 경우 커리어 서비스 성실 참가자 및 커리어 챌린지 참여자를 대상으로 제공됩니다*</li>
</ul>
</li>
<li>각 회차는 <strong>60분씩, 총 180분간</strong> 진행이 됩니다.</li>
<li>1:1 커리어 코칭은 <strong>Zoom, Notion</strong> 등을 활용하여 <strong>온라인으로 진행</strong>됩니다.</li>
<li>각 수강생에게는 <strong>최소 2명 이상의 전담 코치(기버)</strong>가 배정됩니다.</li>
</ul>
<p>정리하자면 현업에 종사하고 계신 개발자분들을 수강생들과 매치하여 원하는 시간대에 30분 / 30분(2회)로 코칭을 받거나 60분(1회)로 코칭을 받을 수 있는 서비스이다 !</p>
<h3 id="--후기">- 후기</h3>
<p>사전과제로 이력서&amp;포트폴리오와 전 질문을 커리어 코칭 하루 전까지 지정 노션페이지에 업로드 해야하는데 사실 과정을 시작한지 거의 2달 좀 안되었을때여서 취업에 대해 궁금한 점이나 이력서나 포트폴리오 작성하는게 막막하고 어떤식으로 그림조차 그려지지 않았었다 ㅜ ㅜ 
사실 하기 싫다는 생각도 좀 했었다,, 왜냐면 실시간 수업 끝나고 10시쯤 했기 때문에,,, (날짜와 시간은 미리 조율 가능)
그래도 일단 내가 해왔던 것중에서 쓸만한것들을 모아 이력서를 작성하고 사전 질문 리스트를 작성했다.</p>
<blockquote>
<h3 id="사전질문">사전질문</h3>
</blockquote>
<ul>
<li>여태까지 해왔던 프로젝트들은 제가 가고 싶은 백엔드 분야와는 다른 분야인 경우가 많습니다. 이 경우 이력서에서 다 빼야할까요?(ex. 이력서 수상내역 등 졸업작품)</li>
<li>5개월 간 학부 연구학생 경험이 있습니다. 하지만 백엔드 관련 연구주제는 아니여서 이력서에 써야할지 고민입니다.<code>연구 주제: 스마트 콘텐츠 저작 가이드라인 및 사용자 UX연구</code></li>
<li>이력서에 더 추가할 내용이나 빼야할 내용이 궁금합니다</li>
<li>포트폴리오는 어떻게 구성해야할지 몰라서 작성하지 못했습니다😟 어떤 식으로 작성하는게 좋을까요?</li>
<li>희망 직무(백엔드)관련 프로젝트 경험이 없습니다. 학원에서 그룹스터디를 하며 프로젝트 위주로 학습하려고 하는데 괜찮은 방향일까요?</li>
<li>앞으로 어떤 부분을 더 채워야할까요? 아직 처음이고 희망 기업도 정하지는 않은 상태라 막막합니다 🥲</li>
</ul>
<p>진짜 막막했던 부분들을 최대한 말로 풀어서 질문리스트를 작성했다.</p>
<h4 id="1차-코칭1">1차 코칭(1)</h4>
<p>사전에 이력서를 제출했지만 다시 더 세부적인 자기소개를 시작으로 코칭을 시작했다.
자기소개할때 물어보셨던 내용은 </p>
<ul>
<li>CS전공을 시작한 이유</li>
<li>학부다니면서 어떤 공부/활동을 했는지</li>
<li>백엔드를 선택하게 된 이유 </li>
<li>개발을 얼마나 잘한다고 스스로 생각하는지</li>
<li>코딩테스트는 얼마나 준비했는지</li>
<li>취업목표(목표 시기, 관심있는 직업, 직무, 희망연봉)</li>
<li>취업할때까지 어떤 것들을 준비해가고자 하는지</li>
<li>지금 가장 어려운점</li>
</ul>
<p>사실 자기 소개를 해달라고 했는데 내가 많이 버벅여서 이렇게 정리해서 차근차근 대답해달라고 하셨다ㅋㅋㅋㅋㅋㅋㅋㅋ미리 참고해서 준비하는 것도 좋을 것 같다. 
내가 가장 어려웠던 질문은 <code>백엔드를 선택하게 된 이유</code>였다. 
아무튼 자기소개를 마치고 사전질문에 대한 답변을 싹 해주셨다. 
<img src="https://velog.velcdn.com/images/yeeeerim_/post/c5b54616-c232-436a-87dc-027b198d0436/image.png" alt="">
정리한거는 간단해 보이지만 하나하나 이해가 가게 잘 풀어서 설명해주셔서 감사했다,, 
그리고 또 
<img src="https://velog.velcdn.com/images/yeeeerim_/post/7d7270a6-8055-4ead-a8b8-0d27369e6c26/image.png" alt="">
이런식으로 이력서, 포트폴리오, 프로젝트 경험과 관련한 내용을 정리해서 알려주셨고 
<img src="https://velog.velcdn.com/images/yeeeerim_/post/e97ecee9-ea87-439e-aaad-b7cd91110706/image.png" alt="">
to do list를 마지막으로 코칭을 마쳤다. </p>
<h4 id="1차-코칭2">1차 코칭(2)</h4>
<p>1차코칭 두번째 기버님은 실제 현업자에 계신분이셔서 더 더 도움이 많이 되었다. 
전날 했던 코칭시간 정리한것과 몇 가지의 질문을 기반으로 조언을 해주셨다. 
<img src="https://velog.velcdn.com/images/yeeeerim_/post/738a4de0-023c-4dd2-a8d4-b8a0eeed280c/image.png" alt=""></p>
<p>그리고 코딩테스트 꿀팁, 프로젝트, 나는 과정을 끝나고 바로 취준을 할 예정이기 때문에 현실적으로 올해 여름까지 어느 회사에 지원해야 하는지 등을 알려주셨다,, 
직접 개발자로 취업하기 전까지의 과정을 먼저 경험하셨던 분이였어서 때문에 조언들이 더 와닿았던 것 같다,, +현타는 서비스 ... ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅠㅠㅠ 열심히하면 나도 되겠지~?
내가 가장 어려워했던 질문인 <code>백엔드를 선택하게 된 이유</code>에 대해서도 내가 진짜 어떤 백엔드 개발자가 되고 싶은지 ex) 보안에 철저한 개발자 등등.. 꼭 정해야 한다고 하셨다,, ㅜ ㅜ
아직도 이 부분은 고민중에 있다 ! 
<img src="https://velog.velcdn.com/images/yeeeerim_/post/959eefbc-9380-45a0-b4a7-d56ffae14ad1/image.png" alt="">
이 코칭도 마찬가지로 to-do list를 마지막으로 종료했다. ! </p>
<p>사실 과정 초반이라 생각하지도 않았던 취업에 관한 얘기를 직접 전문가? 개발자분들이랑 하고나니 과정에 익숙해져 풀어졌던 나의 마음가짐을 잡을 수 있는 좋은 기회였다 만족 백만배 🤭</p>
<h2 id="🧑🏻💻-그룹스터디-워크샵">🧑🏻‍💻 그룹스터디 워크샵</h2>
<p>처음 과정 초반부터 시작했던 그룹스터디 활동을 과정 수강생들과 함께 공유하는 <strong>그룹스터디 워크샵</strong>에 참가했다! 
워크샵 전에 백엔드 멘토님과 2회씩 면담? 피드백 시간이 있다. 
우리 팀은 딱히 수정사항은 없었고 인사이트 발표할때 직접 팀원들이 돌아가면서 발표했으면 좋겠다는 아이디어를 주셔서 그렇게 발표자료를 준비했었다 ! 
우리 조 발표자료 구성은 <strong>스터디 목표 설정-&gt; 운영방식 -&gt; 진행상황 -&gt; 인사이트순</strong>으로 준비했다
<img src="https://velog.velcdn.com/images/yeeeerim_/post/08985736-eecc-4909-a042-ec5c0f004412/image.png" alt="">
<img src="https://velog.velcdn.com/images/yeeeerim_/post/bdb26b21-126d-4850-bb31-ecff6dce287c/image.png" alt="">
<img src="https://velog.velcdn.com/images/yeeeerim_/post/4691bf13-4da5-4d8c-92b9-0332f4573a09/image.png" alt="">
<img src="https://velog.velcdn.com/images/yeeeerim_/post/e03919ac-6725-4ea9-ab81-efd47c5724dc/image.png" alt="">
<img src="https://velog.velcdn.com/images/yeeeerim_/post/4bff45d7-b37c-498e-b0a6-b0c749e48028/image.png" alt=""></p>
<p>우리 팀은 사이드 프로젝트가 주된 목표였기 때문에 지금 진행중인 프로젝트 소개를 중심으로 목표와 진행상황을 소개했고, 그룹스터디에서 얻은 인사이트는 내가 직접 느낀 부분을 정리해서 발표자료로 만들었다 ! </p>
<p>다른 조들은 각양각색으로 발표주제를 선정해 발표했었다 ! 
어떤 조는 다익스트라를 활용해서 실제로 지하철 최단거리 구하는 프로젝트?를 발표했는데 인상깊었었다💡</p>
<p>사실 온라인 수업이라 다른 조들은 어떻게 스터디를 진행하는지 궁금할 때도 있었는데 이번 기회를 통해 알 수 있어서 좋았다 ! ! </p>
<h2 id="마무리">마무리</h2>
]]></description>
        </item>
        <item>
            <title><![CDATA[[알고리즘]_문자열_단어정렬(백준 No.1181)]]></title>
            <link>https://velog.io/@yeeeerim_/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98%EB%AC%B8%EC%9E%90%EC%97%B4%EB%8B%A8%EC%96%B4%EC%A0%95%EB%A0%AC%EB%B0%B1%EC%A4%80-No.1181</link>
            <guid>https://velog.io/@yeeeerim_/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98%EB%AC%B8%EC%9E%90%EC%97%B4%EB%8B%A8%EC%96%B4%EC%A0%95%EB%A0%AC%EB%B0%B1%EC%A4%80-No.1181</guid>
            <pubDate>Mon, 13 Mar 2023 06:34:46 GMT</pubDate>
            <description><![CDATA[<h3 id="문제">문제</h3>
<p>알파벳 소문자로 이루어진 N개의 단어가 들어오면 아래와 같은 조건에 따라 정렬하는 프로그램을 작성하시오.</p>
<p>길이가 짧은 것부터
길이가 같으면 사전 순으로
단, 중복된 단어는 하나만 남기고 제거해야 한다.</p>
<hr>
<p><strong>입력</strong>
첫째 줄에 단어의 개수 N이 주어진다. (1 ≤ N ≤ 20,000) 둘째 줄부터 N개의 줄에 걸쳐 알파벳 소문자로 이루어진 단어가 한 줄에 하나씩 주어진다. 주어지는 문자열의 길이는 50을 넘지 않는다.</p>
<hr>
<p><strong>출력</strong>
조건에 따라 정렬하여 단어들을 출력한다.</p>
<hr>
<h3 id="코드">코드</h3>
<pre><code class="language-java">import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;

public class No_1181 {
    public static void main(String[] args) throws IOException {
        BufferedReader br =new BufferedReader(new InputStreamReader(System.in));
        int N=Integer.parseInt(br.readLine());
        HashSet&lt;String&gt;input=new HashSet&lt;&gt;();
        List&lt;String&gt;output=new ArrayList&lt;&gt;();

        for(int i=0;i&lt;N;i++){
            input.add(br.readLine());
        }

        Iterator&lt;String&gt; iterator=input.iterator();
        while (iterator.hasNext()){
            output.add(iterator.next());
        }

        Collections.sort(output);
        Collections.sort(output,(String s1,String s2)-&gt; s1.length()-s2.length());
        for (String s:output) {
            System.out.println(s);
        }
    }
}
</code></pre>
<h3 id="풀이">풀이</h3>
<ul>
<li>문제 조건에 &#39;중복되는 단어는 모두 제거&#39; 라는 조건이 있어 HashSet으로 입력받아 중복되는 단어들을 모두 제거했다. </li>
<li>Set은 인덱스를 통해 접근할 수 없고 순서가 정해져 있지 않으므로 Iterator로 List에 Set에 있는 단어들을 모두 넣었다. </li>
<li>사전순서대로 한번 정렬해주고</li>
<li>문자열의 길이대로 정렬한다. </li>
<li>정렬이 끝난 문자열들을 출력한다. </li>
</ul>
<h3 id="마무리">마무리</h3>
<p>첨에 문제를 잘못읽어서 중복만 제거하고 정렬만하면 되는줄 알았는데 알고보니까 문자열 숫자대로 정렬하는 거였다.. 혹시나해서 찾아보니 문자열 길이대로 정렬하는 코드가 있더라아 <del>~</del> 천재님들 만재님들 감사합니댜 </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[알고리즘]_자료구조_듣보잡🤭(백준 No.1764)]]></title>
            <link>https://velog.io/@yeeeerim_/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98%EC%9E%90%EB%A3%8C%EA%B5%AC%EC%A1%B0%EB%93%A3%EB%B3%B4%EC%9E%A1%EB%B0%B1%EC%A4%80-No.1764</link>
            <guid>https://velog.io/@yeeeerim_/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98%EC%9E%90%EB%A3%8C%EA%B5%AC%EC%A1%B0%EB%93%A3%EB%B3%B4%EC%9E%A1%EB%B0%B1%EC%A4%80-No.1764</guid>
            <pubDate>Fri, 10 Mar 2023 05:35:23 GMT</pubDate>
            <description><![CDATA[<h3 id="문제">문제</h3>
<p>김진영이 듣도 못한 사람의 명단과, 보도 못한 사람의 명단이 주어질 때, 듣도 보도 못한 사람의 명단을 구하는 프로그램을 작성하시오.</p>
<hr>
<p><strong>입력</strong>
첫째 줄에 듣도 못한 사람의 수 N, 보도 못한 사람의 수 M이 주어진다. 이어서 둘째 줄부터 N개의 줄에 걸쳐 듣도 못한 사람의 이름과, N+2째 줄부터 보도 못한 사람의 이름이 순서대로 주어진다. 이름은 띄어쓰기 없이 알파벳 소문자로만 이루어지며, 그 길이는 20 이하이다. N, M은 500,000 이하의 자연수이다.
듣도 못한 사람의 명단에는 중복되는 이름이 없으며, 보도 못한 사람의 명단도 마찬가지이다.</p>
<hr>
<p><strong>출력</strong>
듣보잡의 수와 그 명단을 사전순으로 출력한다.</p>
<hr>
<pre><code class="language-java">import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;

public class No_1764 {

    public static void main(String[] args) throws IOException {

        BufferedReader br = new BufferedReader (new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer (br.readLine());

        int N = Integer.parseInt(st.nextToken());
        int M =  Integer.parseInt(st.nextToken());

        HashSet&lt;String&gt; nohear = new HashSet&lt;&gt;();
        List&lt;String&gt;nosee = new ArrayList&lt;&gt;();
        List&lt;String&gt;answer = new ArrayList&lt;&gt;();

        for(int i=0;i&lt;N;i++){//듣도 못한사람
            nosee.add(br.readLine());
        }
        for(int i=0;i&lt;M;i++){//보도 못한사람
            nohear.add(br.readLine());
        }

        for(int i = 0; i &lt; N; i++){
            if(nohear.contains(nosee.get(i))){
                answer.add(nosee.get(i));
            }
        }
        Collections.sort(answer);

        System.out.println(answer.size());

        for(String s:answer){
            System.out.println(s);
        }
    }
}
</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[알고리즘]_그리디 알고리즘_팰린드롬 만들기( 백준 No.1213)]]></title>
            <link>https://velog.io/@yeeeerim_/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98%EA%B7%B8%EB%A6%AC%EB%94%94-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98%ED%8C%B0%EB%A6%B0%EB%93%9C%EB%A1%AC-%EB%A7%8C%EB%93%A4%EA%B8%B0-%EB%B0%B1%EC%A4%80-No.1213</link>
            <guid>https://velog.io/@yeeeerim_/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98%EA%B7%B8%EB%A6%AC%EB%94%94-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98%ED%8C%B0%EB%A6%B0%EB%93%9C%EB%A1%AC-%EB%A7%8C%EB%93%A4%EA%B8%B0-%EB%B0%B1%EC%A4%80-No.1213</guid>
            <pubDate>Tue, 07 Mar 2023 11:35:07 GMT</pubDate>
            <description><![CDATA[<h3 id="문제">문제</h3>
<p>임한수와 임문빈은 서로 사랑하는 사이이다.</p>
<p>임한수는 세상에서 팰린드롬인 문자열을 너무 좋아하기 때문에, 둘의 백일을 기념해서 임문빈은 팰린드롬을 선물해주려고 한다.</p>
<p>임문빈은 임한수의 영어 이름으로 팰린드롬을 만들려고 하는데, 임한수의 영어 이름의 알파벳 순서를 적절히 바꿔서 팰린드롬을 만들려고 한다.</p>
<p>임문빈을 도와 임한수의 영어 이름을 팰린드롬으로 바꾸는 프로그램을 작성하시오.</p>
<hr>
<p><strong>입력</strong>
첫째 줄에 임한수의 영어 이름이 있다. 알파벳 대문자로만 된 최대 50글자이다.</p>
<hr>
<p><strong>출력</strong>
첫째 줄에 문제의 정답을 출력한다. 
만약 불가능할 때는 &quot;I&#39;m Sorry Hansoo&quot;를 출력한다. 
정답이 여러 개일 경우에는 사전순으로 앞서는 것을 출력한다.</p>
<hr>
<h3 id="코드">코드</h3>
<pre><code class="language-java">import java.io.IOException;
import java.util.Scanner;

public class No_1213 {
    public static void main(String[] args) throws IOException {
        Scanner scan = new Scanner(System.in);
        String input = scan.next();
        int size = input.length();

        int[] alp = new int[26];
        for(int i=0; i&lt;size; i++){        //문자열을 입력 받으며 알파벳 세기
            alp[input.charAt(i)-&#39;A&#39;]++;      //아스키 코드를 사용하여 해당 알파벳 위치 ++
        }

        //알파벳 갯수 중 홀수가 있다면 가운데 위치하는 것만 가능
        int center=0;
        //홀수의 갯수 세기
        int odd=0;
        for(int i=0; i&lt;alp.length; i++){
            if(alp[i]%2 != 0 ){
                center = i ;
                odd++;
            }
        }

        if(odd&gt;1 || (odd==1 &amp;&amp; size%2==0)) {              //홀수가 1개보다 많다면 만들 수 없다.
            System.out.println(&quot;I&#39;m Sorry Hansoo&quot;);
            return;
        }

        //홀수가 1개라면 가운데에 위치시키고 양쪽을 완성시킨다.
        StringBuffer result = new StringBuffer();

        for(int i=0; i&lt;alp.length; i++){
            for(int j=0; j&lt;alp[i]/2; j++){
                result.append((char)(i+&#39;A&#39;));
            }
        }
        StringBuffer tmp = new StringBuffer(result.toString());         //알파벳을 순서대로 출력
        if(odd==1)              //가운데 알파벳 출력
        {
            result.append((char)(center+&#39;A&#39;));
        }
        System.out.println(result.toString()+tmp.reverse());            //뒤집은 알파벳 출력
    }
}
</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[알고리즘]_그리디알고리즘_A->B
(백준 No.16953)]]></title>
            <link>https://velog.io/@yeeeerim_/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98%EA%B7%B8%EB%A6%AC%EB%94%94%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98A-B%EB%B0%B1%EC%A4%80-No.16953</link>
            <guid>https://velog.io/@yeeeerim_/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98%EA%B7%B8%EB%A6%AC%EB%94%94%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98A-B%EB%B0%B1%EC%A4%80-No.16953</guid>
            <pubDate>Thu, 02 Mar 2023 16:29:41 GMT</pubDate>
            <description><![CDATA[<h3 id="문제">문제</h3>
<p>정수 A를 B로 바꾸려고 한다. 가능한 연산은 다음과 같은 두 가지이다.</p>
<p>2를 곱한다.
1을 수의 가장 오른쪽에 추가한다. 
A를 B로 바꾸는데 필요한 연산의 최솟값을 구해보자.</p>
<hr>
<h4 id="입력">입력</h4>
<p>첫째 줄에 A, B (1 ≤ A &lt; B ≤ 109)가 주어진다.</p>
<hr>
<h4 id="출력">출력</h4>
<p>A를 B로 바꾸는데 필요한 연산의 최솟값에 1을 더한 값을 출력한다. 만들 수 없는 경우에는 -1을 출력한다.</p>
<hr>
<h3 id="코드">코드</h3>
<pre><code class="language-java">import java.io.*;
import java.util.*;

public class No_16953 {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());

        int A = Integer.parseInt(st.nextToken());
        int B = Integer.parseInt(st.nextToken());

        int cnt = 1;
        while (A != B){
            if (B &lt; A) {
                System.out.println(-1);
                System.exit(0);
            }
            if (B % 10 == 1) B /= 10;
            else if (B % 2 == 0) B /= 2;
            else {
                System.out.println(-1);
                System.exit(0);
            }
            cnt++;
        }
        System.out.println(cnt);
    }
}
</code></pre>
<h3 id="풀이">풀이</h3>
<ul>
<li>B가 A보다 작으면 -1를 출력하고 시스템을 종료한다. </li>
<li>B의 일의 자리가 1이면 <code>(B % 10 = 1)</code> 일의 자리를 없앤다. <code>(B /= 10)</code></li>
<li>그렇지 않고, B가 2로 나뉜다면 <code>(B % 2 = 0)</code> 2로 나누어준다. <code>(B /= 2)</code></li>
<li>둘 다 못한다면, B는 절대로 A가 될 수 없다.</li>
<li>A가 B로 나아가는 수단은 위 두 가지 밖에 없기 때문이다.</li>
<li>혹은, 위 과정을 거쳤지만 B가 A보다 작아진다면, 이 또한 B는 절대로 A가 될 수 없다.</li>
</ul>
<h3 id="참고🙇♀️">참고🙇‍♀️</h3>
<p><a href="https://waristo.tistory.com/48">https://waristo.tistory.com/48</a></p>
<h4 id="마무리">마무리</h4>
<p>그리디 문제는 풀 수 있지 ~ 하고 문제 봤는데 정말 그림조차 안그려져 풀이를 찾아봤다 
세상은 넓은데 내가 할 일 중에 쉬운건 왤케 없냐  </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[알고리즘]_BFS/DFS_단지번호 붙이기(백준 No.2667)]]></title>
            <link>https://velog.io/@yeeeerim_/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98BFSDFS%EB%8B%A8%EC%A7%80%EB%B2%88%ED%98%B8-%EB%B6%99%EC%9D%B4%EA%B8%B0%EB%B0%B1%EC%A4%80-No.2667</link>
            <guid>https://velog.io/@yeeeerim_/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98BFSDFS%EB%8B%A8%EC%A7%80%EB%B2%88%ED%98%B8-%EB%B6%99%EC%9D%B4%EA%B8%B0%EB%B0%B1%EC%A4%80-No.2667</guid>
            <pubDate>Thu, 02 Mar 2023 16:15:34 GMT</pubDate>
            <description><![CDATA[<h3 id="문제">문제</h3>
<p>&lt;그림 1&gt;과 같이 정사각형 모양의 지도가 있다. 1은 집이 있는 곳을, 0은 집이 없는 곳을 나타낸다. 철수는 이 지도를 가지고 연결된 집의 모임인 단지를 정의하고, 단지에 번호를 붙이려 한다. 여기서 연결되었다는 것은 어떤 집이 좌우, 혹은 아래위로 다른 집이 있는 경우를 말한다. 대각선상에 집이 있는 경우는 연결된 것이 아니다. &lt;그림 2&gt;는 &lt;그림 1&gt;을 단지별로 번호를 붙인 것이다. 지도를 입력하여 단지수를 출력하고, 각 단지에 속하는 집의 수를 오름차순으로 정렬하여 출력하는 프로그램을 작성하시오.
<img src="https://velog.velcdn.com/images/yeeeerim_/post/cc320e0d-7dd8-4457-82aa-d6aafdb716a2/image.png" alt=""></p>
<hr>
<h4 id="입력">입력</h4>
<p>첫 번째 줄에는 지도의 크기 N(정사각형이므로 가로와 세로의 크기는 같으며 5≤N≤25)이 입력되고, 그 다음 N줄에는 각각 N개의 자료(0혹은 1)가 입력된다.</p>
<hr>
<h4 id="출력">출력</h4>
<p>첫 번째 줄에는 총 단지수를 출력하시오. 그리고 각 단지내 집의 수를 오름차순으로 정렬하여 한 줄에 하나씩 출력하시오.</p>
<hr>
<h3 id="코드">코드</h3>
<pre><code class="language-java">import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;
import java.util.Queue;

public class No_2667 {
    static int[] ax = {1, 0, -1, 0};//우하좌상
    static int[] ay = {0, 1, 0, -1};
    static boolean visited[][];
    static int map[][];

    public static void main(String[] args) throws IOException {
        Scanner sc=new Scanner(System.in);
        int N = sc.nextInt();
        map = new int[N][N];
        visited = new boolean[N][N];
        ArrayList&lt;Integer&gt;apart=new ArrayList&lt;&gt;();

        for (int i = 0; i &lt; N; i++) {
            String input=sc.next();
            for (int j = 0; j &lt; N; j++) {
                map[i][j] = input.charAt(j)-&#39;0&#39;;
            }
        }
        int count = 0;
        for (int i = 0; i &lt; N; i++) {
            for (int j = 0; j &lt; N; j++) {
                if (map[i][j] == 1 &amp;&amp; !visited[i][j]) {
                    apart.add(BFS(i, j));
                    count++;
                }
            }
        }
        Collections.sort(apart);
        System.out.println(count);
        for (int i:apart) {
            System.out.println(i);
        }
    }

    private static int BFS(int i, int j) {
        Queue&lt;Node&gt; queue = new LinkedList&lt;&gt;();
        queue.add(new Node(i, j));

        visited[i][j] = true;
        int number=1; //처음 들어온 숫자도 있으니까 1부터 시작
        while (!queue.isEmpty()) {
            Node now = queue.poll();

            for (int k = 0; k &lt; 4; k++) {
                int nextX = now.x + ax[k];
                int nextY = now.y + ay[k];
                if (nextX &gt;= 0 &amp;&amp; nextY &gt;= 0 &amp;&amp; nextX &lt; visited.length &amp;&amp; nextY &lt; visited.length){
                    if(!visited[nextX][nextY]){
                        if(map[nextX][nextY]==1){
                            queue.add(new Node(nextX,nextY));
                            visited[nextX][nextY]=true;
                            number++;
                        }
                    }
                }
            }
        }
        return number;
    }

    static class Node {
        int x;
        int y;

        public Node(int x, int y) {
            this.x = x;
            this.y = y;
        }

    }
}
</code></pre>
<h3 id="풀이">풀이</h3>
<ul>
<li>유기농 배추와 푸는 방법이 유사하다</li>
<li>BFS 메서드에서 <code>number</code> 변수는 아파트 단지 수를 세는 용도이다</li>
<li>처음에 매개변수로 들어온 좌표도 아파트가 있는 곳이니 1부터 시작한다!</li>
</ul>
<h4 id="마무리">마무리</h4>
<p>처음으로 혼자 그래프 문제 생각해보고 유기농 배추 참고해서 풀어봤다 
뭔말인지 알겠어서 좀 재밌게 풀었다 사실 추가한거 별로 없음 그래도 이해한대로 풀어봤당 
코드 테스트 돌려보기가 너무 싫어서 ㅋ ㅋㅋ ㅋ .. 코드 맞게 짠거같아소 고냥 돌렸는데 계속 런타임에러나서 뭔가 봤더니 입력에서 공백을 안주고 그냥 입력값을 준거였다 휴 이거땜에 30분 넘게 엄한거 건드림 
글고 해결해서 다시 제출했는데 오류났다 number변수를 0부터 시작해서 틀렸었따 껄껄..</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[알고리즘]_BFS_유기농 배추(백준 No.1012)]]></title>
            <link>https://velog.io/@yeeeerim_/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98BFS%EC%9C%A0%EA%B8%B0%EB%86%8D-%EB%B0%B0%EC%B6%94%EB%B0%B1%EC%A4%80-No.1012</link>
            <guid>https://velog.io/@yeeeerim_/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98BFS%EC%9C%A0%EA%B8%B0%EB%86%8D-%EB%B0%B0%EC%B6%94%EB%B0%B1%EC%A4%80-No.1012</guid>
            <pubDate>Thu, 02 Mar 2023 15:01:25 GMT</pubDate>
            <description><![CDATA[<h3 id="문제">문제</h3>
<p>차세대 영농인 한나는 강원도 고랭지에서 유기농 배추를 재배하기로 하였다. 농약을 쓰지 않고 배추를 재배하려면 배추를 해충으로부터 보호하는 것이 중요하기 때문에, 한나는 해충 방지에 효과적인 배추흰지렁이를 구입하기로 결심한다. 이 지렁이는 배추근처에 서식하며 해충을 잡아 먹음으로써 배추를 보호한다. 특히, 어떤 배추에 배추흰지렁이가 한 마리라도 살고 있으면 이 지렁이는 인접한 다른 배추로 이동할 수 있어, 그 배추들 역시 해충으로부터 보호받을 수 있다. 한 배추의 상하좌우 네 방향에 다른 배추가 위치한 경우에 서로 인접해있는 것이다.</p>
<p>한나가 배추를 재배하는 땅은 고르지 못해서 배추를 군데군데 심어 놓았다. 배추들이 모여있는 곳에는 배추흰지렁이가 한 마리만 있으면 되므로 서로 인접해있는 배추들이 몇 군데에 퍼져있는지 조사하면 총 몇 마리의 지렁이가 필요한지 알 수 있다. 예를 들어 배추밭이 아래와 같이 구성되어 있으면 최소 5마리의 배추흰지렁이가 필요하다. 0은 배추가 심어져 있지 않은 땅이고, 1은 배추가 심어져 있는 땅을 나타낸다.
<img src="https://velog.velcdn.com/images/yeeeerim_/post/373b3606-c27d-46e7-9046-a3aa74609b34/image.png" alt=""></p>
<hr>
<p><strong>입력</strong>
입력의 첫 줄에는 테스트 케이스의 개수 T가 주어진다. 그 다음 줄부터 각각의 테스트 케이스에 대해 첫째 줄에는 배추를 심은 배추밭의 가로길이 M(1 ≤ M ≤ 50)과 세로길이 N(1 ≤ N ≤ 50), 그리고 배추가 심어져 있는 위치의 개수 K(1 ≤ K ≤ 2500)이 주어진다. 그 다음 K줄에는 배추의 위치 X(0 ≤ X ≤ M-1), Y(0 ≤ Y ≤ N-1)가 주어진다. 두 배추의 위치가 같은 경우는 없다.</p>
<hr>
<p><strong>출력</strong>
각 테스트 케이스에 대해 필요한 최소의 배추흰지렁이 마리 수를 출력한다.</p>
<hr>
<h3 id="코드">코드</h3>
<pre><code class="language-java">import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.StringTokenizer;
import java.util.Queue;

public class No_1012 {
    static int dx[] = {1, 0, -1, 0};
    static int dy[] = {0, 1, 0, -1};
    static boolean visited[][];
    static int map[][];//지도
    static int M,N;

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int T = Integer.parseInt(br.readLine());


        for (int i = 0; i &lt; T; i++) {
            StringTokenizer st = new StringTokenizer(br.readLine());

            M = Integer.parseInt(st.nextToken()); //배추밭 가로
            N = Integer.parseInt(st.nextToken()); //배추밭 세로
            int K = Integer.parseInt(st.nextToken()); //배추 개수

            map = new int[M][N];//배추밭 지도 가로줄 길이, 세로줄 길이 정의
            visited = new boolean[M][N]; //밭에 방문했는지 안했는지 체크

            for (int j = 0; j &lt; K; j++) {
                st = new StringTokenizer(br.readLine());//배추가 있는 좌표 입력받음
                int x = Integer.parseInt(st.nextToken());
                int y = Integer.parseInt(st.nextToken());

                map[x][y] = 1; //배추가 심어진 자리에 1
            }
            int count = 0;
            for (int j = 0; j &lt; M; j++) {
                for (int k = 0; k &lt; N; k++) {
                    if(map[j][k] == 1 &amp;&amp; !visited[j][k]){//배추가 심어져있고 방문하지 않았다면
                        bfs(j,k); //bfs메소드 실행 매개변수-&gt;j,k
                        count++; //배추벌레 증가
                    }
                }
            }
            System.out.println(count);


        }
    }
    private static void bfs(int j,int k) {

        Queue&lt;Node&gt; queue = new LinkedList&lt;&gt;();
        queue.add(new Node(j,k));

        visited[j][k] =true;

        while (!queue.isEmpty()){//queue에 아무것도 없어질때 까지 반복
            Node now = queue.poll();

            for (int i = 0; i &lt; 4; i++) {
                int nextX = now.x + dx[i]; //상하좌우
                int nextY = now.y + dy[i]; //상하좌우

                if(nextX &gt;= 0 &amp;&amp; nextY &gt;= 0 &amp;&amp; nextX &lt; M &amp;&amp; nextY &lt; N){ //0.0보다 작거나 배추밭 가로, 세로보다 커지면 안되니까
                    if(!visited[nextX][nextY]){
                        if(map[nextX][nextY] == 1){//배추가 심어져있다면
                            queue.add(new Node(nextX,nextY));//큐에 추가한다
                            visited[nextX][nextY] = true;//방문했음
                        }
                    }
                }
            }
        }
    }
    static class Node{
        int x;
        int y;
        public Node(int x,int y){
            this.x=x;
            this.y=y;
        }
    }
}
</code></pre>
<h3 id="풀이">풀이</h3>
<ul>
<li><p><code>dx[], dy []</code> : 배열의 인덱스를 통해 배추가 있는 좌표를 기준으로 상(0,1),하(0,-1) 우(1,0) 좌(-1,0)를 탐색할 수 있게 한다 </p>
</li>
<li><pre><code class="language-java">if(map[j][k] == 1 &amp;&amp; !visited[j][k]){//배추가 심어져있고 방문하지 않았다면
                      bfs(j,k); //bfs메소드 실행 매개변수-&gt;j,k
                      count++; //배추벌레 증가
                  }</code></pre>
</li>
<li><pre><code class="language-java">private static void bfs(int j,int k) {

      Queue&lt;Node&gt; queue = new LinkedList&lt;&gt;();
      queue.add(new Node(j,k));

      visited[j][k] =true;

      while (!queue.isEmpty()){//queue에 아무것도 없어질때 까지 반복
          Node now = queue.poll();

          for (int i = 0; i &lt; 4; i++) {
              int nextX = now.x + dx[i]; //상하좌우
              int nextY = now.y + dy[i]; //상하좌우

              if(nextX &gt;= 0 &amp;&amp; nextY &gt;= 0 &amp;&amp; nextX &lt; M &amp;&amp; nextY &lt; N){ //0.0보다 작거나 배추밭 가로, 세로보다 커지면 안되니까
                  if(!visited[nextX][nextY]){
                      if(map[nextX][nextY] == 1){//배추가 심어져있다면
                          queue.add(new Node(nextX,nextY));//큐에 추가한다
                          visited[nextX][nextY] = true;//방문했음
                      }
                  }
              }
          }
      }
  }
</code></pre>
</li>
</ul>
<p>: bfs 메서드에서는 배추가 심어져 있는 밭의 상하좌우를 탐색한다, 그리고 만약 상하좌우에 배추가 심어져 있다면 큐에 추가해 while문이 더 실행될 수 있게 한다. 그리고 방문배열의 값을 true로 변경한다. </p>
<h3 id="마무리">마무리</h3>
<ul>
<li>어려워서 시도도 못했었는데 오늘 스터디 시간에 팀장님이 알아듣기 쉽게 설명해주셔서 이해가 잘갔다 ^__^ 감사합니댱 </li>
<li>머리로는 알겠는데 정리하려니까 좀 어렵다 </li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Study] JWT]]></title>
            <link>https://velog.io/@yeeeerim_/Study-JWT</link>
            <guid>https://velog.io/@yeeeerim_/Study-JWT</guid>
            <pubDate>Thu, 02 Mar 2023 12:12:03 GMT</pubDate>
            <description><![CDATA[<h2 id="🧐-jwt-사용배경">🧐 JWT 사용배경</h2>
<p><img src="https://velog.velcdn.com/images/yeeeerim_/post/b0a91629-6bc9-49e6-8666-44b4055742a6/image.png" alt=""></p>
<ul>
<li>세션 기반 인증방식
: 서버에서 클라이언트에게 세션 ID 부여, 이 ID를 사용하여 사용자를 인증하고 권한 부여하는 식으로 처리한다. 
🚨 하지만, 세션 기반의 인증 방식은 서버 측에서 상태 유지 --&gt; 확장성 &amp; 분산처리에 제한이 있다. 
또 서버 측에서 상태를 유지하기 때문에 서버 부하가 크고 여러 서버를 사용할 경우 동기화 문제도 발생한다. </li>
</ul>
<h2 id="💡-jwt란">💡 JWT란?</h2>
<p><img src="https://velog.velcdn.com/images/yeeeerim_/post/9f71b0ad-234a-4da8-abe8-621f67db5b1b/image.png" alt=""></p>
<ul>
<li>JSON Web Token의 약어로 웹 애플리케이션에서 사용자 인증 및 권한 부여를 위한 인증 방식 중 하나이다. </li>
<li>클라이언트와 서버 간의 통신에서 사용</li>
<li><strong>자가수용적</strong>: 필요한 모든 정보를 자체적으로 지니고 있음, JWT 시스템에서 발급된 토큰은 토큰에 대한 기본정보, 전달할 정보, 토큰이 검증됐다는 것을 증명해주는 Signature 포함</li>
</ul>
<ol>
<li>클라이언트 -&gt; 로그인 요청</li>
<li>서버 -&gt; 사용자 정보를 기반으로 JWT 생성 및 클라이언트에게 반환</li>
<li>클라이언트 -&gt; 받은 JWT를 이후 요청에서 &#39;인증 헤더&#39;에 추가하여 서버가 해당 요청을 수락 할 수 있도록 함 즉, 이후 요청에서 JWT를 사용하여 자신이 인증된 사용자임을 증명함</li>
<li>서버 -&gt; JWT검증, 해당 사용자에 대한 요청 수락</li>
</ol>
<blockquote>
<p>🌟<strong>JWT</strong>
<strong>클라이언트</strong>-&gt; 상태 유지 
<strong>서버</strong>-&gt; 인증 처리</p>
</blockquote>
<ul>
<li>확장성과 분산처리에 용이 , 클라이언트와 서버 간의 통신에서 암호화된 문자열만 사용하기 때문에 동기화 문제도 발생하지 않는다. </li>
<li>따라서 JWT는 세션 기반의 인증 방식보다 보안적으로 강력하고, 확장성과 분산처리에 용이하며, 클라이언트 측에서 유지되므로 서버 부하도 줄일 수 있는 장점이 있어서 널리 사용되고 있다</li>
</ul>
<h2 id="🫥-jwt-구성요소">🫥 JWT 구성요소</h2>
<h4 id="header">Header</h4>
<ul>
<li>JWT 토큰이 어떤 종류인지와 어떤 알고리즘을 사용하여 서명이 되었는지를 나타내는 부분이다. 
  -typ: 토큰 타입 지정
  -alg: Signature 해싱 알고리즘 지정
<code>{&quot;alg&quot;: &quot;HS256&quot;, &quot;typ&quot;: &quot;JWT&quot;}</code></li>
</ul>
<h4 id="payload">Payload</h4>
<ul>
<li>JWT 토큰에서 실제로 전송하고자 하는 정보를 담고 있는 부분이다.
<code>{&quot;sub&quot;: &quot;1234567890&quot;, &quot;name&quot;: &quot;John Doe&quot;, &quot;iat&quot;: 1516239022}</code>
  -sub: JWT 토큰이 발급된 사용자를 구분할 수 있는 고유한 값
  -name: 사용자의 이름
  -iat: JWT 토큰이 발급된 시간<h4 id="signature">Signature</h4>
</li>
<li>JWT 토큰이 서명되어 있는 부분</li>
<li>Signature는 Header와 Payload를 조합한 후, 서버에서 사용하는 시크릿 키를 이용하여 해싱된 값
<code>HmacSHA256(base64UrlEncode(header) + &quot;.&quot; + base64UrlEncode(payload), secret)</code></li>
</ul>
<h2 id="📚-관련-라이브러리">📚 관련 라이브러리</h2>
<p>Okta와 OAuth 2.0은 모두 인증과 권한 부여를 관리하는 데 사용되는 프로토콜이나 서비스</p>
<h4 id="1-okta">1. Okta</h4>
<p>클라우드 기반의 IDaaS(Identity as a Service) 서비스</p>
<ul>
<li>개발자는 인증 및 권한 부여를 간편하게 관리</li>
<li>Okta는 SAML, OAuth 2.0, OpenID Connect와 같은 표준 기반 인증 및 권한 부여 프로토콜을 지원하며, API를 통해 애플리케이션과 Okta를 통합가능</li>
</ul>
<h4 id="2oauth-20">2.OAuth 2.0</h4>
<p>인증 및 권한 부여를 위한 프로토콜</p>
<ul>
<li>OAuth 2.0을 사용하면 사용자가 애플리케이션에 로그인할 때, 애플리케이션이 사용자의 권한을 위임받아 API나 다른 서비스에 접근</li>
<li>OAuth 2.0은 간편한 인증 및 권한 부여를 제공하며, 인증 및 권한 부여를 위한 여러 프로토콜을 제공</li>
<li>예를 들어, OAuth 2.0은 Authorization Code Grant, Implicit Grant, Client Credentials Grant 등 다양한 인증 방식을 지원</li>
</ul>
<p>Okta는 OAuth 2.0을 사용하여 인증 및 권한 부여를 처리한다. 
Okta는 OAuth 2.0을 지원하기 때문에, OAuth 2.0을 사용하는 다른 애플리케이션과도 통합이 용이</p>
<h2 id="😶-jwt한계">😶 JWT한계</h2>
<p><strong>1.JWT는 사용자 정보를 암호화하여 포함하고 있기 때문에, JWT의 크기가 큼</strong>
-&gt; 네트워크 대역폭을 낭비하고, 클라이언트와 서버 간의 통신 성능을 낮춤</p>
<p>해결 방법: JWT의 크기를 줄이기 위해 필요한 정보만 포함시키도록 페이로드(payload)를 최적화하고, 필요한 정보만 요청하는 등의 방법을 사용가능</p>
<p><strong>2. JWT는 한 번 발급되면 만료되기 전까지 계속 사용</strong>
-&gt;만약 JWT가 탈취되거나 조작된다면, 해당 사용자의 모든 정보가 노출될 수 있다.</p>
<p>해결 방법: JWT의 만료 시간을 짧게 설정하여 보안성을 높일 수 있음 또는, JWT를 발급할 때마다 서버 측에서 고유한 랜덤한 값을 추가하여, 조작 방지</p>
<p><strong>3. JWT는 서명되어 있지만, 데이터가 암호화되어 있지는 않음</strong>
-&gt;JWT를 가로채면 내용을 볼 수 있다.
해결 방법: JWT의 페이로드(payload)를 암호화하여 내용을 보호할 수 있습니다. 이를 위해 JWE(Json Web Encryption)를 사용</p>
<p><strong>4. JWT를 사용하면, 클라이언트 측에서 인증을 처리하기 때문에, XSS(Cross-Site Scripting)와 CSRF(Cross-Site Request Forgery)와 같은 공격에 노출위험</strong>
해결 방법: XSS와 CSRF와 같은 공격을 방지하기 위해서는, 적절한 보안 정책을 설정 및  클라이언트 측에서 JWT를 안전하게 보호
이를 위해 쿠키를 사용하거나, CSRF 토큰을 사용하는 등의 방법 있음</p>
<h3 id="출처-🙇♀️">출처 🙇‍♀️</h3>
<p><a href="https://velog.io/@mygomi/TIL-50-JWT%EC%97%90-%EB%8C%80%ED%95%B4-%EB%B0%9C%ED%91%9C%ED%95%B4%EB%B3%B4%EA%B2%A0%EC%8A%B5%EB%8B%88%EB%8B%A4">https://velog.io/@mygomi/TIL-50-JWT%EC%97%90-%EB%8C%80%ED%95%B4-%EB%B0%9C%ED%91%9C%ED%95%B4%EB%B3%B4%EA%B2%A0%EC%8A%B5%EB%8B%88%EB%8B%A4</a></p>
<p><a href="https://velog.io/@dnjscksdn98/JWT-JSON-Web-Token-%EC%86%8C%EA%B0%9C-%EB%B0%8F-%EA%B5%AC%EC%A1%B0">https://velog.io/@dnjscksdn98/JWT-JSON-Web-Token-%EC%86%8C%EA%B0%9C-%EB%B0%8F-%EA%B5%AC%EC%A1%B0</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[알고리즘]_다익스트라_알고스팟(백준 No.1261)]]></title>
            <link>https://velog.io/@yeeeerim_/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98%EB%8B%A4%EC%9D%B5%EC%8A%A4%ED%8A%B8%EB%9D%BC%EC%95%8C%EA%B3%A0%EC%8A%A4%ED%8C%9F%EB%B0%B1%EC%A4%80-No.1261</link>
            <guid>https://velog.io/@yeeeerim_/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98%EB%8B%A4%EC%9D%B5%EC%8A%A4%ED%8A%B8%EB%9D%BC%EC%95%8C%EA%B3%A0%EC%8A%A4%ED%8C%9F%EB%B0%B1%EC%A4%80-No.1261</guid>
            <pubDate>Wed, 01 Mar 2023 17:14:58 GMT</pubDate>
            <description><![CDATA[<h3 id="문제">문제</h3>
<p>알고스팟 운영진이 모두 미로에 갇혔다. 미로는 N<em>M 크기이며, 총 1</em>1크기의 방으로 이루어져 있다. 미로는 빈 방 또는 벽으로 이루어져 있고, 빈 방은 자유롭게 다닐 수 있지만, 벽은 부수지 않으면 이동할 수 없다.</p>
<p>알고스팟 운영진은 여러명이지만, 항상 모두 같은 방에 있어야 한다. 즉, 여러 명이 다른 방에 있을 수는 없다. 어떤 방에서 이동할 수 있는 방은 상하좌우로 인접한 빈 방이다. 즉, 현재 운영진이 (x, y)에 있을 때, 이동할 수 있는 방은 (x+1, y), (x, y+1), (x-1, y), (x, y-1) 이다. 단, 미로의 밖으로 이동 할 수는 없다.</p>
<p>벽은 평소에는 이동할 수 없지만, 알고스팟의 무기 AOJ를 이용해 벽을 부수어 버릴 수 있다. 벽을 부수면, 빈 방과 동일한 방으로 변한다.</p>
<p>만약 이 문제가 알고스팟에 있다면, 운영진들은 궁극의 무기 sudo를 이용해 벽을 한 번에 다 없애버릴 수 있지만, 안타깝게도 이 문제는 Baekjoon Online Judge에 수록되어 있기 때문에, sudo를 사용할 수 없다.</p>
<p>현재 (1, 1)에 있는 알고스팟 운영진이 (N, M)으로 이동하려면 벽을 최소 몇 개 부수어야 하는지 구하는 프로그램을 작성하시오.</p>
<hr>
<h4 id="입력">입력</h4>
<p>첫째 줄에 미로의 크기를 나타내는 가로 크기 M, 세로 크기 N (1 ≤ N, M ≤ 100)이 주어진다. 다음 N개의 줄에는 미로의 상태를 나타내는 숫자 0과 1이 주어진다. 0은 빈 방을 의미하고, 1은 벽을 의미한다.</p>
<p>(1, 1)과 (N, M)은 항상 뚫려있다.</p>
<hr>
<h4 id="출력">출력</h4>
<p>첫째 줄에 알고스팟 운영진이 (N, M)으로 이동하기 위해 벽을 최소 몇 개 부수어야 하는지 출력한다.</p>
<hr>
<h4 id="예제-입력-1">예제 입력 1</h4>
<p>3 3
011
111
110</p>
<h4 id="예제-출력-1">예제 출력 1</h4>
<p>3</p>
<hr>
<h3 id="코드">코드</h3>
<pre><code class="language-java">import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.PriorityQueue;
import java.util.StringTokenizer;

class Point implements Comparable&lt;Point&gt; {
    int x;
    int y;
    int cnt; // 벽을 부순 개수

    Point(int x, int y, int cnt) {
        this.x = x;
        this.y = y;
        this.cnt = cnt;
    }

    @Override
    public int compareTo(Point o) {
        return cnt - o.cnt;
    }
}

public class Main {
    static int[] rangeX = { -1, 0, 1, 0 };
    static int[] rangeY = { 0, 1, 0, -1 };
    static int N, M;
    static int[][] map;

    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
        StringTokenizer st = new StringTokenizer(br.readLine());

        M = Integer.parseInt(st.nextToken()); // 가로
        N = Integer.parseInt(st.nextToken()); // 세로

        map = new int[N + 1][M + 1];

        for (int i = 1; i &lt;= N; i++) {
            String input = br.readLine();
            for (int j = 1; j &lt;= M; j++) {
                map[i][j] = Character.getNumericValue(input.charAt(j - 1));
            }
        }

        int ans = BFS(1, 1);

        bw.write(ans + &quot;\n&quot;);
        bw.flush();
        bw.close();
        br.close();
    }

    public static int BFS(int x, int y) {
        // 벽을 부순 개수를 오름차순으로 정렬하도록 설정.
        PriorityQueue&lt;Point&gt; q = new PriorityQueue&lt;&gt;();

        q.offer(new Point(x, y, 0));
        boolean[][] visit = new boolean[N + 1][M + 1];
        visit[x][y] = true;

        int dx, dy;
        while (!q.isEmpty()) {
            Point p = q.poll();

            // 도착점에 도달했으면 종료.
            if (p.x == N &amp;&amp; p.y == M) {
                return p.cnt;
            }

            for (int i = 0; i &lt; 4; i++) {
                dx = p.x + rangeX[i];
                dy = p.y + rangeY[i];

                if (dx &lt; 1 || dy &lt; 1 || dx &gt; N || dy &gt; M) {
                    continue;
                }

                if (!visit[dx][dy] &amp;&amp; map[dx][dy] == 0) {
                    visit[dx][dy] = true;
                    q.offer(new Point(dx, dy, p.cnt));
                }

                if (!visit[dx][dy] &amp;&amp; map[dx][dy] == 1) {
                    visit[dx][dy] = true;
                    q.offer(new Point(dx, dy, p.cnt + 1));
                }
            }
        }
        return 0;
    }

}
</code></pre>
<h3 id="마무리">마무리</h3>
<p>스터디에서 알고리즘 몇 개 골라서 푸는중인데 아직까지는 그리디말고는 다익스트라, BFS는 혼자 풀기 너무 어렵다. 사실 이해도 잘 안갈때도 많댜 으앙...</p>
]]></description>
        </item>
    </channel>
</rss>