<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>learner</title>
        <link>https://velog.io/</link>
        <description>STEP BY STEP</description>
        <lastBuildDate>Sun, 21 Sep 2025 09:26:19 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>learner</title>
            <url>https://velog.velcdn.com/images/data_sy/profile/5caf9d44-df17-49d6-add5-9e1ddb85c555/image.png</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. learner. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/data_sy" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[[AI를 활용한 타이머 앱 개발기] 주간 회고 #9]]></title>
            <link>https://velog.io/@data_sy/AI%EB%A5%BC-%ED%99%9C%EC%9A%A9%ED%95%9C-%ED%83%80%EC%9D%B4%EB%A8%B8-%EC%95%B1-%EA%B0%9C%EB%B0%9C%EA%B8%B0-%EC%A3%BC%EA%B0%84-%ED%9A%8C%EA%B3%A0-9</link>
            <guid>https://velog.io/@data_sy/AI%EB%A5%BC-%ED%99%9C%EC%9A%A9%ED%95%9C-%ED%83%80%EC%9D%B4%EB%A8%B8-%EC%95%B1-%EA%B0%9C%EB%B0%9C%EA%B8%B0-%EC%A3%BC%EA%B0%84-%ED%9A%8C%EA%B3%A0-9</guid>
            <pubDate>Sun, 21 Sep 2025 09:26:19 GMT</pubDate>
            <description><![CDATA[<blockquote>
<h3 id="⏰-퀵라벨타이머-quicklabeltimer">⏰ 퀵라벨타이머 (QuickLabelTimer)</h3>
<p><strong>플랫폼·기술</strong>: iOS 앱, SwiftUI
<strong>앱 컨셉</strong>: 시간을 빠르게 설정할 수 있는 <strong>퀵 타이머</strong>에, ‘왜 맞췄는지’를 기록할 수 있는 <strong>라벨 기능</strong>을 결합한 타이머 앱
<strong>개발 목적</strong>: AI-Assisted Programming을 실제 서비스 개발에 적용하여 장단점을 살펴보고, <strong>서비스 완성 및 운영 경험</strong>을 통해 <strong>설계 능력과 문제 해결 능력을 강화</strong>하고자 함
<strong>GitHub</strong>: <a href="https://github.com/data-sy/quick-label-timer">https://github.com/data-sy/quick-label-timer</a></p>
</blockquote>
<br/>
<br/>

<h2 id="이번-주에-한-일">이번 주에 한 일</h2>
<p>드디어 앱을 출시했다. 🎉🎉🎉 지난 두 달간의 여정이 이렇게 마무리되었다.</p>
<br/>

<p><strong>[ 주요 작업 요약 ]</strong></p>
<ul>
<li>앱 심사 리젝 대응 및 재제출</li>
<li>출시 이후로 보류해 둔 아이디어들 정리하기</li>
</ul>
<br/>

<p>심사를 한 번에 통과한 건 아니었다. 리젝됐을 때 두 가지 피드백을 받았는데, </p>
<ul>
<li><p><strong>피드백1: 백그라운드 오디오 옵션</strong>
  오디오 옵션이 켜져 있는데 실제 앱에서는 오디오 세션을 사용하지 않는다는 피드백을 받았다. 사실 예전 정책 때문에 켜둔 걸 그대로 두었던 건데, 정책이 바뀐 뒤에는 옵션도 같이 꺼야 한다는 걸 놓쳤다. 와 이렇게 디테일하게 점검하다니… 개발 과정에서 <em>Suspended*문제</em>(링크 연결 예정)<em>를 다룰 때도 느꼈지만, Apple은 *</em>사용자 기기 리소스 관리**에 진심인 것 같다.</p>
</li>
<li><p><strong>피드백2: iPad 미리보기 스크린샷</strong>
  기본 설정으로 iPad 지원 옵션이 켜져 있었는데, 제출한 미리보기 이미지는 아이폰 화면이라서 불일치 문제가 발생했다. 이 옵션을 끄고 다시 제출했다.</p>
</li>
</ul>
<p>이렇게 수정하고 다시 제출하니 <strong>통과!!!</strong> 드디어 한국 마켓에 앱이 올라왔다.
내가 <strong>필요하다고 생각했던 앱</strong>을 직접 만들어 스토어에 내놓으니 신기했다. 다른 아이디어들도 얼른 현실화 시켜보고 싶다.</p>
<p>👉 <a href="https://apps.apple.com/kr/app/%ED%80%B5%EB%9D%BC%EB%B2%A8%ED%83%80%EC%9D%B4%EB%A8%B8/id6752611917">App Store에서 퀵라벨타이머 확인하기</a></p>
<p><img src="https://velog.velcdn.com/images/data_sy/post/2f1def0b-842b-4789-8d4e-93dc52e0731a/image.png" alt=""></p>
<p>재제출 후에는, 지금까지 <code>Inbox</code>에 쌓아뒀던 리팩토링·기능 아이디어들을 다시 정리했다. 지난 두 달 개발을 하면서, <strong>개선은 개발자 추측이 아니라 사용자 반응과 데이터를 기반으로 해야 한다</strong>는 걸 배웠다. 그 시각으로 보니 지금은 맞지 않는 아이디어도 있었고, 반대로 당시에는 보류했지만 지금 보니 괜찮아 보이는 것도 있었다. 그래서 <strong>우선순위를 새로 정리</strong>했고, 아이젠하워 매트릭스를 활용해 <strong>시급성과 중요도에 따라 분류</strong>했다. 앞으로는 그 우선순위에 맞춰 하나씩 개선해 나갈 예정이다.
<img src="https://velog.velcdn.com/images/data_sy/post/c4e50d35-a468-4810-848f-d20372a0849b/image.png" alt=""></p>
<br/>
<br/>

<h2 id="배운-점">배운 점</h2>
<ul>
<li><strong>Apple 심사에서 배운 ‘사용자 중심’ 시각</strong><br>  리젝 사유가 모두 사용자 리소스 낭비 방지, 경험 최적화와 관련 있었다. Apple은 개발 편의보다 <strong>사용자 경험을 최우선</strong>으로 한다는 걸 다시 한 번 깨달았다.    </li>
<li><strong>기록의 가치</strong>
  <code>Inbox</code>에 그때그때 적어둔 아이디어들이 시간이 지나 다시 보니 의외로 <strong>도움이 되었다.</strong> 즉흥적인 기록도 결국은 다시 꺼내볼 만한 <strong>자원</strong>이 된다는 걸 알았다.   </li>
<li><strong>출시는 끝이 아니라 시작</strong>
  앱이 올라갔다고 끝난 게 아니라, 이제부터는 <strong>사용자 반응과 데이터를 기반으로 개선</strong>을 이어가야 한다. <strong>사용자 반응을 어떻게 수집할 수 있을지</strong> 고민해봐야겠다.</li>
</ul>
<br/>
<br/>

<h2 id="다음-주에-할-일">다음 주에 할 일</h2>
<ul>
<li>영어권으로 확장 출시 준비</li>
<li>앱 홍보 채널 만들기</li>
</ul>
<br/>
<br/>

]]></description>
        </item>
        <item>
            <title><![CDATA[[AI를 활용한 타이머 앱 개발기] 주간 회고 #8]]></title>
            <link>https://velog.io/@data_sy/AI%EB%A5%BC-%ED%99%9C%EC%9A%A9%ED%95%9C-%ED%83%80%EC%9D%B4%EB%A8%B8-%EC%95%B1-%EA%B0%9C%EB%B0%9C%EA%B8%B0-%EC%A3%BC%EA%B0%84-%ED%9A%8C%EA%B3%A0-8</link>
            <guid>https://velog.io/@data_sy/AI%EB%A5%BC-%ED%99%9C%EC%9A%A9%ED%95%9C-%ED%83%80%EC%9D%B4%EB%A8%B8-%EC%95%B1-%EA%B0%9C%EB%B0%9C%EA%B8%B0-%EC%A3%BC%EA%B0%84-%ED%9A%8C%EA%B3%A0-8</guid>
            <pubDate>Sun, 14 Sep 2025 13:03:17 GMT</pubDate>
            <description><![CDATA[<blockquote>
<h3 id="⏰-퀵라벨타이머-quicklabeltimer">⏰ 퀵라벨타이머 (QuickLabelTimer)</h3>
<p><strong>플랫폼·기술</strong>: iOS 앱, SwiftUI
<strong>앱 컨셉</strong>: 시간을 빠르게 설정할 수 있는 <strong>퀵 타이머</strong>에, ‘왜 맞췄는지’를 기록할 수 있는 <strong>라벨 기능</strong>을 결합한 타이머 앱
<strong>개발 목적</strong>: AI-Assisted Programming을 실제 서비스 개발에 적용하여 장단점을 살펴보고, <strong>서비스 완성 및 운영 경험</strong>을 통해 <strong>설계 능력과 문제 해결 능력을 강화</strong>하고자 함
<strong>GitHub</strong>: <a href="https://github.com/data-sy/quick-label-timer">https://github.com/data-sy/quick-label-timer</a></p>
</blockquote>
<br/>
<br/>

<h2 id="이번-주에-한-일">이번 주에 한 일</h2>
<table>
<thead>
<tr>
<th><img src="https://velog.velcdn.com/images/data_sy/post/75ce3975-0065-4325-b61b-0f88f52a482e/image.png" alt=""></th>
<th><img src="https://velog.velcdn.com/images/data_sy/post/f10289b0-c729-4338-a804-03efb5a670fb/image.png" alt=""></th>
</tr>
</thead>
<tbody><tr>
<td>이번 주는 남은 버그와 Warning을 해결하고 로그 시스템과 접근성을 붙여 <strong>v1.0.0 개발을 마무리했다.</strong> 그리고 스토어에 올릴 메타데이터(제목, 설명, 미리보기 등)를 준비해서 해 드디어 <strong>심사를 제출했다.</strong></td>
<td></td>
</tr>
</tbody></table>
<br/>

<p><strong>[ 주요 작업 요약 ]</strong></p>
<ul>
<li>버그 개선 및 <code>Warning</code> 정리</li>
<li>로그 시스템 Crashlytics 연동</li>
<li>VoiceOver 접근성 추가</li>
<li>스토어 메타데이터 작성 및 심사 제출</li>
</ul>
<br/>

<p>이전 프로젝트인 <a href="https://www.my-math-teacher.com/"><strong>MMT 웹사이트</strong></a>를 개발할 때는 의식하지 못했지만, 앱을 만들면서 새롭게 챙겨야 하는 부분들이 있었다. <strong>웹</strong>은 사용자가 내 서버에 <strong>“접속”</strong>하지만, <strong>앱</strong>은 프로그램이 사용자의 기기에 <strong>“설치”</strong>되기 때문이지 않을까 싶었다. 먼저, 강제 종료 같은 크래시는 서버에 기록이 남지 않기 때문에 따로 수집기가 필요하다. 그래서 <strong>Firebase Crashlytics</strong>를 연동했다. 또 시각장애인이나 화면을 보지 않고 조작하는 상황을 고려해 <strong>VoiceOver</strong> 접근성을 지원했다. 기능만 구현하는 걸 넘어서서 접근성을 함께 챙기며 <strong>다양한 사용자를 고려</strong>해야 함을 알게 되었다.</p>
<p>이렇게 구현을 마무리한 뒤 앱스토어에 제출하기 위해 제목, 소개글, 브랜드네임 등의 메타데이터를 준비했다. 특히 브랜드네임을 정할 때 AI가 많은 도움이 되었다. <strong>저작권 문제가 없으면서, 검색하기 어렵지 않으면서, 적당히 기억에 남는 이름을 찾아야 했는데</strong>😵 혼자 만들었다면 정말 오래 걸렸을 것 같다. AI는 내가 원하는 느낌이 나올 때까지 끝없이 이름을 뽑아내 줘서 비교적 빠르게 정할 수 있었다. 그리고 선택한 이름이 혹시 저작권에 문제가 되지는 않는지, 부정적인 밈이나 속어로 쓰이고 있지는 않은지 등을 <strong>Gemini의 딥리서치</strong>로 검증하였다. 최종적으로 <strong>OddMuffin</strong>이라는 귀여운 브랜드명을 갖게 되었다. 미리보기 이미지는 <strong>Figma</strong>로 작업했다. iOS에서 제공하는 공식 컴포넌트를 활용해 보면서 Figma에 대해서도 더 알게 되었고, 개발과는 또 다른 재미가 있었다.
<img src="https://velog.velcdn.com/images/data_sy/post/dfd9c60d-9f02-4462-9a6a-c59f7ccd2dfd/image.png" alt=""></p>
<br/>
<br/>

<h2 id="배운-점">배운 점</h2>
<ul>
<li><p><strong>웹과 앱의 차이</strong>
웹 개발에서는 서버 로그로도 충분했지만, 앱은 사용자의 기기에서 발생하는 크래시를 별도로 수집해야 한다는 걸 알았다. <strong>플랫폼</strong>이 달라지면 디버깅 방식도 달라지는 걸 배웠다.</p>
</li>
<li><p><strong>접근성의 중요성</strong>
처음엔 기능 구현만 생각했는데, VoiceOver를 붙이면서 다양한 사용자를 고려해야 한다는 걸 알았다. “작동하는 것”과 <strong>“누구나 쓸 수 있는 것”</strong>은 다르다. 다음 개발에서도 이런 점을 고려하는 습관을 들여야겠다.</p>
</li>
<li><p><strong>iOS 업데이트와 유지보수</strong>
앱 제출 직후 <strong>iOS26 리퀴드 글래스</strong>로 디자인 업데이트가 일어나 기존 레이아웃이 깨지는 걸 발견했다. 출시 후에도 꾸준한 유지보수가 필요하다는 걸 실감했다.</p>
</li>
</ul>
<br/>
<br/>

<h2 id="다음-주에-할-일">다음 주에 할 일</h2>
<ul>
<li>심사 결과를 기다리며, 출시 이후로 보류해 둔 아이디어들 정리하기</li>
<li>리젝 될 경우, 피드백에 맞춰 수정하고 재제출하기</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[AI를 활용한 타이머 앱 개발기] 주간 회고 #7]]></title>
            <link>https://velog.io/@data_sy/AI%EB%A5%BC-%ED%99%9C%EC%9A%A9%ED%95%9C-%ED%83%80%EC%9D%B4%EB%A8%B8-%EC%95%B1-%EA%B0%9C%EB%B0%9C%EA%B8%B0-%EC%A3%BC%EA%B0%84-%ED%9A%8C%EA%B3%A0-7</link>
            <guid>https://velog.io/@data_sy/AI%EB%A5%BC-%ED%99%9C%EC%9A%A9%ED%95%9C-%ED%83%80%EC%9D%B4%EB%A8%B8-%EC%95%B1-%EA%B0%9C%EB%B0%9C%EA%B8%B0-%EC%A3%BC%EA%B0%84-%ED%9A%8C%EA%B3%A0-7</guid>
            <pubDate>Sun, 31 Aug 2025 02:20:05 GMT</pubDate>
            <description><![CDATA[<blockquote>
<h3 id="⏰-퀵라벨타이머-quicklabeltimer">⏰ 퀵라벨타이머 (QuickLabelTimer)</h3>
<p><strong>플랫폼·기술</strong>: iOS 앱, SwiftUI
<strong>앱 컨셉</strong>: 시간을 빠르게 설정할 수 있는 <strong>퀵 타이머</strong>에, ‘왜 맞췄는지’를 기록할 수 있는 <strong>라벨 기능</strong>을 결합한 타이머 앱
<strong>개발 목적</strong>: AI-Assisted Programming을 실제 서비스 개발에 적용하여 장단점을 살펴보고, <strong>서비스 완성 및 운영 경험</strong>을 통해 <strong>설계 능력과 문제 해결 능력을 강화</strong>하고자 함
<strong>GitHub</strong>: <a href="https://github.com/data-sy/quick-label-timer">https://github.com/data-sy/quick-label-timer</a></p>
</blockquote>
<br/>
<br/>

<h2 id="이번-주에-한-일">이번 주에 한 일</h2>
<table>
<thead>
<tr>
<th><img src="https://velog.velcdn.com/images/data_sy/post/9d126020-fa19-4573-a22f-eb4f2147b50d/image.png" alt=""></th>
<th><img src="https://velog.velcdn.com/images/data_sy/post/9b3ce40e-f5bb-4861-aad1-075e6d863815/image.png" alt=""></th>
</tr>
</thead>
<tbody><tr>
<td>이번 주는 <strong>버그 수정과 리팩토링</strong>을 주로 진행했다. 그 과정에서 알림 동작과 관련된 <strong>예상치 못한 문제를 발견했고</strong>, 정책을 조금 더 <strong>안정적인 방향으로 바꾸게 되었다.</strong> 출시 전에 발견해서 다행이었다.</td>
<td></td>
</tr>
</tbody></table>
<br/>

<p><strong>[ 주요 작업 요약]</strong> </p>
<ul>
<li>주요 버그 해결</li>
<li>타이머, 프리셋 정책 재정의 (영속성, 속성, 개수 제한)</li>
<li>정책 변경에 따른 사이드 이펙트</li>
</ul>
<br/>

<p>버그를 해결하는 과정은 <strong>연쇄적인 결정의 흐름</strong>으로 이어졌다. 예를 들어,</p>
<p><strong>[예시 1]</strong>
앱을 강제 종료하면 실행 중이던 타이머는 사라지는데, 예약된 알림은 그대로 울려버리는 문제
→ 이를 개선하기 위해 앱 재실행 후에도 타이머를 유지하기로 했고,
→ 그러려면 <strong>영속성(<code>UserDefaults</code>) 로직을 추가</strong>해야 했으며,
→ 타이머가 남아있게 되니 <strong>프리셋을 숨기는 대신 실행 중 상태로 덮는</strong> 오버레이 방식으로 UI를 변경했고,
→ 오버레이 방식에서의 최신순 정렬은 공간적 일관성이 깨져 보여서, 정렬 기준을 <strong>최신순에서 생성순으로 바꿔야 했다.</strong></p>
<p><strong>[예시 2]</strong>
알림 개수에는 시스템 한계가 있으므로 <strong>실행 중인 타이머 개수를 5개로 제한하기로 함</strong>
→ 타이머는 최대 5개인데, 즐겨찾기를 무제한 저장하는 건 UX적으로 어색하니 <strong>즐겨찾기 개수도 20개로 제한</strong>을 두기로 했고,
→ 그러다 보니 기존 모델 구조(<code>Bool isFavorite</code>)로는 다음 버그를 해결하기 복잡했다.</p>
<blockquote>
<p>즐겨찾기가 19개 저장된 상태에서 실행중인 타이머 5개를 즐겨찾기 토글(⭐️)로 예약 할 수 있음.
이 때문에 사용자는 20개 이상 프리셋을 저장할 수 있다고 착각하지만, 실제로 저장 버튼을 누를 때 제한에 걸려 실패.
결국 <strong>UI와 데이터 상태가 불일치</strong>하는 버그 발생</p>
</blockquote>
<p>  → 그래서 속성을 <code>Enum endAction</code>으로 바꾸어 상태를 더 명확히 표현했고,
  → 그 결과 <strong>데이터 마이그레이션, 모델 관련 로직 전면 수정</strong>이 뒤따랐다.</p>
<br/>

<p>하나의 버그 수정에서 예상하지 못했던 사이드 이펙트들이 팡팡 터졌다. <strong>마치 100층짜리 탑에서 99층을 고치려다 10층이 흔들리는 느낌이랄까?</strong> 앱이 완성에 가까워질수록 작은 수정이 전체 구조에 큰 파장을 미친다는 걸 실감한 한 주였다.</p>
<br/>

<br/>

<h2 id="배운-점">배운 점</h2>
<ul>
<li><strong>문제 재정의</strong>
iOS 정책은 내가 바꿀 수 없는 부분이 많다. 억지로 뚫으려다 막히기보다는, <strong>문제를 관점 전환으로 풀어내 재정의함으로써, 버그를 기능처럼 녹여내는 방법</strong>이 더 효과적이었다. 그렇게 해서 “버그처럼 보였던 걸 버그가 아닌 걸로 만든” 셈인데, 앞으로도 이런 시각이 필요하다고 느꼈다.</li>
<li><strong>버그 수정의 연쇄 효과</strong>
하나의 버그를 잡으면 끝나는 게 아니라, <strong>그 수정이 또 다른 문제를 불러온다</strong>는 걸 뼈저리게 느꼈다. 정책을 고치다 보니, 데이터 구조를 손봐야 했고, 거기에 맞춰 UX까지 바꿔야 했다. 버그 하나를 고칠 때, <strong>뒤따라올 사이드 이펙트까지 고민</strong>해보는 습관을 가져야겠다.</li>
<li><strong>AI를 통해 초급자도 중</strong>•<strong>고급 단계의 지식을 경험할 수 있음</strong>
사실 나는 <strong>리팩토링에 패턴 이론이 있다는 것조차 몰랐다.</strong> 그런데 AI에게 “모델의 속성을 안전하게 바꾸는 방법이 있을까?”라고 물어봤더니, <strong>마틴 파울러의 리팩토링 패턴</strong> 중 하나인 Parallel Change(병렬 변경)를 알려주었다. 그제서야 “아, 디자인 패턴처럼 리팩토링에도 정식으로 이름 붙은 방법론이 있구나”라는 걸 알게 되었다. 이 경험을 통해, <strong>지식을 선형적으로 쌓아가는 게 아니라 필요한 순간 필요한 지식을 경험</strong>할 수 있다는 것이 AI의 큰 장점이라는 걸 느꼈다.</li>
</ul>
<br/>
<br/>

<br/>

<h2 id="다음-주에-할-일">다음 주에 할 일</h2>
<p>이번 주에 진행하려 했으나 버그 수정 규모가 커서 한 주 미룬 작업들:</p>
<ul>
<li>Crashlytics 에러 로깅 추가, 접근성 개선</li>
<li>사운드 음원 정책(3초)에 맞춘 편집</li>
<li>스토어 메타데이터 준비</li>
</ul>
<br/>
<br/>]]></description>
        </item>
        <item>
            <title><![CDATA[[AI를 활용한 타이머 앱 개발기] 주간 회고 #6]]></title>
            <link>https://velog.io/@data_sy/AI%EB%A5%BC-%ED%99%9C%EC%9A%A9%ED%95%9C-%ED%83%80%EC%9D%B4%EB%A8%B8-%EC%95%B1-%EA%B0%9C%EB%B0%9C%EA%B8%B0-%EC%A3%BC%EA%B0%84-%ED%9A%8C%EA%B3%A0-6</link>
            <guid>https://velog.io/@data_sy/AI%EB%A5%BC-%ED%99%9C%EC%9A%A9%ED%95%9C-%ED%83%80%EC%9D%B4%EB%A8%B8-%EC%95%B1-%EA%B0%9C%EB%B0%9C%EA%B8%B0-%EC%A3%BC%EA%B0%84-%ED%9A%8C%EA%B3%A0-6</guid>
            <pubDate>Sun, 24 Aug 2025 10:56:34 GMT</pubDate>
            <description><![CDATA[<blockquote>
<h3 id="⏰-퀵라벨타이머-quicklabeltimer">⏰ 퀵라벨타이머 (QuickLabelTimer)</h3>
<p><strong>플랫폼·기술</strong>: iOS 앱, SwiftUI
<strong>앱 컨셉</strong>: 시간을 빠르게 설정할 수 있는 <strong>퀵 타이머</strong>에, ‘왜 맞췄는지’를 기록할 수 있는 <strong>라벨 기능</strong>을 결합한 타이머 앱
<strong>개발 목적</strong>: AI-Assisted Programming을 실제 서비스 개발에 적용하여 <strong>장단점</strong>을 살펴보고, <strong>서비스 완성 및 운영 경험</strong>을 통해 <strong>설계 능력과 문제 해결 능력을 강화</strong>하고자 함
<strong>GitHub</strong>: <a href="https://github.com/data-sy/quick-label-timer">https://github.com/data-sy/quick-label-timer</a></p>
</blockquote>
<br/>
<br/>

<h2 id="이번-주에-한-일">이번 주에 한 일</h2>
<table>
<thead>
<tr>
<th><img src="https://velog.velcdn.com/images/data_sy/post/14afaa66-de3b-4730-9697-71d0d3d130e0/image.png" alt=""></th>
<th><img src="https://velog.velcdn.com/images/data_sy/post/f5f16cdc-bb15-4f99-8a5c-e4c5f548593d/image.png" alt=""></th>
</tr>
</thead>
</table>
<p>이번 주에는 드디어 <strong>알람 기능을 마무리</strong>했다! 
지난주에 정리한 정책대로 <strong>&#39;로컬 알림을 짧은 간격으로 연속 울리기&#39;</strong>방식을 적용했고, 그 과정에서 파생된 <strong>UI 정책 수정</strong>까지 함께 진행했다.</p>
<br/>

<p>**[ 주요 작업 요약 ] **</p>
<ul>
<li>로컬 알림 기반 알람 기능 구현</li>
<li>소리·진동 UI 정책 수정 (4가지 → 3가지 선택지로 단순화)</li>
</ul>
<br/>

<p>지난주에 <strong>단위 테스트와 실기기 동작이 달랐던 경험</strong>이 있어서, 이번에는 <strong>실기기에서 직접 가설을 검증</strong>하는 방식을 썼다. 예를 들어, *&quot;제목·본문 없이 sound만 넣은 알림은 배너가 안 뜨고 소리만 울릴 것이다&quot;* 라는 가설을 세웠지만, <strong>실제 결과는 배너 자체가 뜨지 않았다.</strong></p>
<blockquote>
</blockquote>
<p>두 케이스는 예약(<code>pending_count</code>) 수치는 동일하지만, <strong>배달(<code>delivered_count</code>)에서 차이</strong>를 보인다.</p>
<blockquote>
</blockquote>
<ul>
<li><strong>제목, 본문 모두 <code>nil</code> 또는 <code>“”</code> 일 때:</strong> 예약은 정상적으로 되었지만, 실제 알림은 도착하지 않음 (<strong><code>delivered_count=0</code></strong>)
<img src="https://velog.velcdn.com/images/data_sy/post/4fece5e5-7fd7-4375-b6e3-069361df4e18/image.png" alt=""><blockquote>
</blockquote>
</li>
<li><strong>본문을 넣었을 때:</strong> 알림이 정상적으로 배달됨 (<strong><code>delivered_count=9</code></strong>)
<img src="https://velog.velcdn.com/images/data_sy/post/a3b6a9a7-01e7-40d2-b3a2-2285551d6a9f/image.png" alt=""> <blockquote>
</blockquote>
</li>
</ul>
<p>즉, &#39;알림이 정상적으로 울리려면 제목과 본문 중 최소 하나는 반드시 포함되어야 한다&#39;는 사실을 확인할 수 있었다. 코드 단위테스트만 했다면 “예약이 됐으니 성공이다”라고 착각했을 텐데, <strong>실기기 단위 검증 덕분에 미리 문제를 발견할 수 있었다.</strong>
이런 검증 과정을 거쳐 사용 가능한 기능과 불가능한 기능을 정리했고, 그에 따라 <strong>백그라운드, 포그라운드, 엣지케이스 각각에 맞는 정책</strong>을 마련할 수 있었다.</p>
<br/>

<p>또 하나 재미있었던 포인트는 <strong>소리·진동 조합 문제</strong>였다.</p>
<p>원래는 사용자가 소리/진동을 각각 On·Off로 고를 수 있게 하려 했는데, 로컬 알림으로 정책을 바꾸니 <strong>“소리 O·진동 X”</strong>을 선택하면, 무음 모드일 때 <strong>정반대로 “소리 X·진동 O”</strong>이 울리는 상황이 벌어졌다. 😂
혼란스러운 UX이므로 최종적으로는 옵션을 <strong>소리 / 진동 / 무음</strong> 3가지만 제공하는 걸로 단순화했다.</p>
<table>
<thead>
<tr>
<th><img src="https://velog.velcdn.com/images/data_sy/post/1c724011-149e-498b-8a24-91baff75993c/image.png" alt=""></th>
<th><strong>➔</strong></th>
<th><img src="https://velog.velcdn.com/images/data_sy/post/83663a9b-8a81-4c10-8a3b-4e8315e6dcaa/image.png" alt=""></th>
</tr>
</thead>
</table>
<br/>

<br/>

<h2 id="배운-점">배운 점</h2>
<ul>
<li><strong>실기기 테스트의 중요성</strong>
이번 경험은 지난주에 겪었던 <strong>Suspended 상태 이슈</strong>와도 맞닿아 있다. 코드 단위테스트로 예약 성공 여부까지는 확인할 수 있지만, 실제 기기에서는 iOS 정책과 환경 변수 때문에 <strong>코드상으론 정상인데 실제론 동작하지 않는 경우</strong>가 발생했다. 알람 기능 구현 과정을 통해, 핵심 기능은 <strong>실기기 검증을 병행해야 한다</strong>는 걸 확실히 배웠다.</li>
<li><strong>문서화의 힘</strong>
ADR 문서로 과정과 근거를 남겨두니, 정책을 바꿀 때 훨씬 수월했다. “왜 이 결정을 했는가”를 설명할 필요 없이 기록을 찾아보고 <strong>맥락을 바로 파악</strong>할 수 있었다. 다음부터도 중요한 변화가 있을 때는 기록을 잘 해두어야겠다.</li>
<li><strong>아키텍처의 힘</strong>
지난주에 적용한 클린 아키텍처가 이번 구현에 큰 도움이 됐다. 각 클래스 역할이 명확히 분리돼 있어서, 어떤 기능을 어디에 넣어야 할지 고민이 줄었고, 복잡한 문제도 작은 단위로 나눠 해결할 수 있었다.</li>
</ul>
<br/>

<br/>

<h2 id="다음-주에-할-일">다음 주에 할 일</h2>
<ul>
<li>남은 자잘한 버그들 수정</li>
<li>크래시, 접근성 등의 마무리 작업</li>
<li><strong>스토어 메타데이터 준비 - 출시 가즈아 🚀</strong></li>
</ul>
<br/>

<br/>

<h3 id="관련-문서">관련 문서</h3>
<ul>
<li><a href="https://splashy-shear-9ec.notion.site/ADR-012-Suspended-254dbe50bc0380b8b58cc99cb46f83bc?pvs=74">[ADR-012] Suspended 상태 대응을 위한 백그라운드 알람 정책</a></li>
<li><a href="https://splashy-shear-9ec.notion.site/ADR-013-254dbe50bc038094a7a2d7e2cb334b86?pvs=74">[ADR-013] 백그라운드 알람 정책과의 일관성을 위한 포그라운드 알람 정책</a></li>
</ul>
<br/>

]]></description>
        </item>
        <item>
            <title><![CDATA[[AI를 활용한 타이머 앱 개발기] 주간 회고 #5]]></title>
            <link>https://velog.io/@data_sy/AI%EB%A5%BC-%ED%99%9C%EC%9A%A9%ED%95%9C-%ED%83%80%EC%9D%B4%EB%A8%B8-%EC%95%B1-%EA%B0%9C%EB%B0%9C%EA%B8%B0-%EC%A3%BC%EA%B0%84-%ED%9A%8C%EA%B3%A0-5</link>
            <guid>https://velog.io/@data_sy/AI%EB%A5%BC-%ED%99%9C%EC%9A%A9%ED%95%9C-%ED%83%80%EC%9D%B4%EB%A8%B8-%EC%95%B1-%EA%B0%9C%EB%B0%9C%EA%B8%B0-%EC%A3%BC%EA%B0%84-%ED%9A%8C%EA%B3%A0-5</guid>
            <pubDate>Sun, 17 Aug 2025 01:54:46 GMT</pubDate>
            <description><![CDATA[<blockquote>
<h3 id="⏰-퀵라벨타이머-quicklabeltimer">⏰ 퀵라벨타이머 (QuickLabelTimer)</h3>
<p><strong>플랫폼·기술</strong>: iOS 앱, SwiftUI
<strong>앱 컨셉</strong>: 시간을 빠르게 설정할 수 있는 <strong>퀵 타이머</strong>에, ‘왜 맞췄는지’를 기록할 수 있는 <strong>라벨 기능</strong>을 결합한 타이머 앱
<strong>개발 목적</strong>: AI-Assisted Programming을 실제 서비스 개발에 적용하여 <strong>장단점</strong>을 살펴보고, <strong>서비스 완성 및 운영 경험</strong>을 통해 <strong>설계 능력과 문제 해결 능력을 강화</strong>하고자 함
<strong>GitHub</strong>: <a href="https://github.com/data-sy/quick-label-timer">https://github.com/data-sy/quick-label-timer</a></p>
</blockquote>
<br/>
<br/>

<h2 id="이번-주에-한-일">이번 주에 한 일</h2>
<table>
<thead>
<tr>
<th><img src="https://velog.velcdn.com/images/data_sy/post/e969c48c-e752-4afa-9846-81333ff31f80/image.png" alt=""></th>
<th><img src="https://velog.velcdn.com/images/data_sy/post/69f08667-b50a-4bff-aca4-1680e711adc0/image.png" alt=""></th>
</tr>
</thead>
</table>
<p>이번 주는 <strong>삽질의 주</strong>였다.😭
앱의 핵심 기능인 <strong>알람 기능 구현</strong>에 도전했고, 지난주에 경험한 SRP 원칙을 적용해 보고자 <strong>클린 아키텍처 리팩토링을</strong> 진행했다. </p>
<br/>

<p><strong>[ 주요 작업 요약 ]</strong></p>
<ul>
<li>알람 기능 구현 시도</li>
<li>클린 아키텍처 적용 (TimerManager → Repository &amp; Service 분리)</li>
</ul>
<br/>

<h3 id="1-알람-기능">1. 알람 기능</h3>
<p>알람 기능을 구현할 때 가장 중요한 건 무엇일까?</p>
<p>(간격 주는 용도의 짤. 넣을 예정)</p>
<p>바로 <strong>애플워치를 벗는 것</strong>이다!!
단위 테스트도 잘 통과하고 시뮬레이터에서도 문제없었는데, 정작 실기기에서 소리가 안 났다.
혹시 iOS 정책 때문인가 싶어 헤맸는데…원인은 단순했다. 내가 워치를 차고 있었던 것 😱
(워치를 착용하면 iPhone 알림은 Apple Watch로 라우팅 된다)</p>
<p><strong>iOS에서 알람 기능을 만드신다면,</strong> <code>local notification</code>을 테스트할 때 아래 항목은 꼭 체크해 보시길…</p>
<ul>
<li>애플워치를 벗었는지</li>
<li>무음 모드이진 않은지</li>
<li>소리 볼륨이 0은 아닌지</li>
</ul>
<br/>

<p>이제 실제 구현 과정을 회고하자면, 그야말로 <strong>삽질의 연속</strong>이었다.
처음엔 정책을 이렇게 정리했다.</p>
<ul>
<li>시각적 신호: 로컬 알림</li>
<li>소리·진동: 오디오 세션</li>
</ul>
<p>화면에는 <strong>로컬 알림</strong>이 배너로 뜨고, 소리와 진동은 <strong>오디오 세션</strong>을 통해 사용자가 확실히 인지할 때까지 울리도록 설계했다.
(이미지 위치 조절 예정)
<img src="https://velog.velcdn.com/images/data_sy/post/ceded0f5-7fe2-43b2-af01-aa7d2b1d5d00/image.jpg" width="300px" align="left" style="margin:0; padding:0; display:block; line-height:0;"></p>
<p>단위 테스트도 잘 통과하고, 간단한 실기기 테스트에서도 정상적으로 동작했다.
“됐다!” 싶었던 순간…</p>
<p><strong>타이머 시간을 조금 길게 설정하자, 소리·진동이 울리지 않았다.</strong></p>
<br/>

<p>원인은 바로 <strong>iOS의 Suspended 상태</strong>였다.
<img src="https://velog.velcdn.com/images/data_sy/post/b6bda116-43df-4c05-8404-2a30070a997e/image.png" width="400" style="display:block; margin:0; padding:0"/>
iOS는 앱이 사용되지 않으면 자동으로 <strong>Suspended</strong> 상태로 전환하고 개발자는 임의로 <strong>이 진입을 막을 수 없다.</strong> 애플이 허용한 일부 백그라운드 모드에서만 제한적으로 실행을 이어갈 수 있는데, 알람 어플은 해당 사항이 없다. 즉, 앱이 한 번 <strong>Suspended로 전환되면 실행이 완전히 멈추기 때문에</strong>, 오디오 세션을 실행시키는 함수가 호출 자체가 안 된 것이다.
어쩐지 구글링을 해도, 스택 오버플로우를 디깅해도 정보가 없더라니… <em>“시중 앱에서 가능하니까 방법이 있겠지”</em> 생각하고 넘긴 게 안일한 판단이었다.
눈물이 앞을 가리니 더 이상의 자세한 설명은 생략한다... 👉 <a href="https://velog.io/@data_sy/%EC%95%8C%EB%9E%8C-%EA%B8%B0%EB%8A%A5-%ED%8A%B8%EB%9F%AC%EB%B8%94-%EC%8A%88%ED%8C%85">삽질 기록은 여기...</a>  (추가 예정)</p>
<br/>

<p>최종적으로, <u>사용자 기기 설정(무음 모드, 소리 볼륨 등)에 영향을 받지 않는</u> 알람 앱을 만들기 위해
<strong>피할 수 없는 정책적/기술적 관문</strong>은 다음과 같다.</p>
<ul>
<li><strong><a href="https://www.reddit.com/r/iOSProgramming/comments/1h7x53c/apple_wont_allow_proper_3rd_party_alarm_apps/?tl=ko&amp;utm_source=share&amp;utm_medium=web3x&amp;utm_name=web3xcss&amp;utm_term=1&amp;utm_content=share_button">iOS는 서드파티 알람 앱에 엄격하다. (2024.12)</a></strong></li>
<li><strong>백그라운드 유지 기법</strong> 없이는 사실상 구현이 어렵다.</li>
<li><strong>실제로, 업계 1위 알람 앱도 백그라운드 유지 기법을 사용하는 것으로 보인다.</strong>
(<strong><a href="https://brunch.co.kr/@jaemyungshin/1">Alarmy 대표님이 블로그 글</a></strong>에서 직접 언급한 바 있다.(2018) 현재도 앱을 강제 종료하면 _“앱이 꺼지면 알람이 안 울려요”_라는 로컬 알림이 뜨는 걸 보면, 이 방식은 <strong>여전히 유지되고 있는 것으로 추측된다.</strong>)</li>
</ul>
<h3 id="구현-방식-정리">구현 방식 정리</h3>
<table>
<thead>
<tr>
<th>방법</th>
<th>원리</th>
<th>장점</th>
<th>단점</th>
<th>대안</th>
</tr>
</thead>
<tbody><tr>
<td>로컬 알림</td>
<td>iOS가 예약·발송</td>
<td><strong>Suspended 상태에서도 알림 가능</strong></td>
<td>기기 설정에 종속</td>
<td>무음 모드 시 울리지 않는다고 안내</td>
</tr>
<tr>
<td>오디오 세션</td>
<td>앱이 직접 제어</td>
<td>기기 설정과 상관없이 소리/진동 울림</td>
<td><strong>Suspended 상태에서 동작 안 함</strong></td>
<td><strong>(iOS 정책 우회) 무음 사운드를 틀어 백그라운드 유지</strong></td>
</tr>
</tbody></table>
<br/>
<br/>

<p>이 제약을 고려해 떠올린 시나리오는 이랬다:</p>
<blockquote>
<ol>
<li><strong>외부 푸시 알림</strong>으로 타이머 종료 시간 5분 전 앱을 깨우기 </li>
<li><strong>5분간 무음 사운드</strong>를 재생해 앱이 Suspended 상태가 되지 않도록 유지</li>
<li>타이머 종료 시점에 <strong>오디오 세션</strong>으로 알람 울리기</li>
</ol>
</blockquote>
<p>하지만 이 방식은 구현 과정에서 <strong>실패할 가능성</strong>이 있고, iOS 정책을 우회하는 방법이라 <strong>리젝 리스크</strong>가 있어 고민이 되었다. 이때, 지난주 회고에서 정리했던 말이 떠올랐다. <code>좋은 UX는 머릿속 상상이 아니라 실제 피드백으로 검증된다.</code> 기능 구현도 마찬가지일 것이다. 이번에는 <strong>‘완벽 대신 완성’</strong>을 모토로, 우선 *<em>로컬 알림 기반 MVP를 *</em> 내기로 결정했다. </p>
<ul>
<li><strong>장점:</strong> iOS가 예약·발송하므로 <strong>Suspended 상태에서도 알림 가능</strong></li>
<li><strong>단점:</strong> <strong>기기 설정에 종속</strong> (무음모드, 소리볼륨 등)</li>
<li><strong>대안:</strong> 무음 모드 시, 소리가 울리지 않는다고 사용자에게 안내</li>
</ul>
<br/>

<h3 id="2-클린-아키텍처-적용">2. 클린 아키텍처 적용</h3>
<p>지난주에 <strong>SRP의 중요성</strong>을 크게 느낀 뒤, 이번 주에는 아키텍처 개선을 시도했다.</p>
<ul>
<li><code>TimerManager</code>의 책임을 <strong>Repository</strong>와 <strong>Service</strong>로 분리</li>
<li>파일 네이밍도 아키텍처 규칙에 맞는지 점검</li>
</ul>
<p>완벽하게 원칙을 따르려면 더 작은 단위(엔진 등)까지 쪼갤 수 있었지만, 지난 2주 동안 경험했듯이 <strong>과도하게 깊이 파고들면 우선순위가 밀린다</strong>는 걸 알았다.
그래서 이번에는 <strong>Service/Repository 수준까지만 분리</strong>하고 마무리했다.
(이전 아키텍처 다이어그램 → 새로운 아키텍처 다이어그램 첨부 예정)</p>
<p>이번 개선 과정에서 클린 아키텍처를 공부하며 도움이 된 블로그 링크도 함께 남겨본다. <a href="https://mini-min-dev.tistory.com/284">[iOS] Clean Architecture + MVVM + Observable 사용해서 날씨앱 리팩토링하기</a></p>
<br/>

<h2 id="배운-점">배운 점</h2>
<ul>
<li><strong>핵심 기능은 초반에 직접 검증하자.</strong>
“시중 앱들이 다 되니까 나도 되겠지”라는 안일한 생각이 큰 삽질로 이어졌다.
이번 일을 통해 <strong>핵심 기능은 반드시 초기에 정확히 검증해야 한다</strong>는 걸 배웠다. 단순히 코드 로직뿐 아니라 <strong>기기나 환경까지</strong>(워치 착용, suspended 상태 등) 고려해야 한다는 것도 알게 되었다.</li>
<li><strong>디버깅 능력이 좋을수록 AI 활용의 질도 높아진다.</strong>
사운드 재생 이슈에서 <strong>AI가 처음에는 다소 범용적인 답만 내놓았다.</strong> 하지만 직접 함수 호출 시점을 하나씩 디버깅하며 원인을 좁혀가니 “세션 생성 위치를 바꿔야 하지 않을까?”라는 가설에 도달할 수 있었다. 그 가설을 AI에게 제시하자,  그제야 맞는 해결책이 나와 이슈를 풀 수 있었다.
결국 AI는 답을 대신 내주는 도구가 아니라, <strong>내가 문제를 어떻게 정의하느냐에 따라 성과가 달라지는 도구</strong>라는 걸 체감했다.</li>
</ul>
<br/>

<h2 id="다음-주에-할-일">다음 주에 할 일</h2>
<ul>
<li>로컬 알림을 사용한 알람 정책 설계 &amp; 구현</li>
<li>자잘하게 쌓인 버그들 정리</li>
</ul>
<br/>
<br/>]]></description>
        </item>
        <item>
            <title><![CDATA[[AI를 활용한 타이머 앱 개발기] 주간 회고 #4]]></title>
            <link>https://velog.io/@data_sy/AI%EB%A5%BC-%ED%99%9C%EC%9A%A9%ED%95%9C-%ED%83%80%EC%9D%B4%EB%A8%B8-%EC%95%B1-%EA%B0%9C%EB%B0%9C%EA%B8%B0-%EC%A3%BC%EA%B0%84-%ED%9A%8C%EA%B3%A0-4</link>
            <guid>https://velog.io/@data_sy/AI%EB%A5%BC-%ED%99%9C%EC%9A%A9%ED%95%9C-%ED%83%80%EC%9D%B4%EB%A8%B8-%EC%95%B1-%EA%B0%9C%EB%B0%9C%EA%B8%B0-%EC%A3%BC%EA%B0%84-%ED%9A%8C%EA%B3%A0-4</guid>
            <pubDate>Sat, 09 Aug 2025 19:10:21 GMT</pubDate>
            <description><![CDATA[<blockquote>
<h3 id="⏰-퀵라벨타이머-quick-label-timer">⏰ 퀵라벨타이머 (Quick Label Timer)</h3>
</blockquote>
<ul>
<li><strong>플랫폼·기술</strong>: iOS 앱, SwiftUI</li>
<li><strong>앱 컨셉</strong>: 시간을 빠르게 설정할 수 있는 <strong>퀵 타이머</strong>에, ‘왜 맞췄는지’를 기록할 수 있는 <strong>라벨 기능</strong>을 결합한 타이머 앱</li>
<li><strong>개발 목적</strong>: AI-Assisted Programming을 실제 서비스 개발에 적용하여 <strong>장단점</strong>을 살펴보고, <strong>서비스 완성 및 운영 경험</strong>을 통해 <strong>설계 능력과 문제 해결 능력을 강화</strong>하고자 함</li>
<li><strong>GitHub</strong>: <a href="https://github.com/data-sy/quick-label-timer">https://github.com/data-sy/quick-label-timer</a></li>
</ul>
<br/>
<br/>

<h2 id="이번-주에-한-일">이번 주에 한 일</h2>
<table>
<thead>
<tr>
<th><img src="https://velog.velcdn.com/images/data_sy/post/adff6c4e-13c1-4cf5-aa60-36e1f5bffedd/image.png" alt=""></th>
<th><img src="https://velog.velcdn.com/images/data_sy/post/11c24257-d7e8-4cd8-afdb-0bd073afe549/image.png" alt=""></th>
</tr>
</thead>
</table>
<p>이번 주는 <strong>구조 리팩토링의 주</strong>였다. 정책이 변경될 때마다 기존 코드를 수정하는 일이 잦아지면서 <strong>구조의 한계</strong>가 느껴졌다. 이런 불편함을 느끼는 시점이 딱 리팩토링 할 시기라는 판단이 들었다. 출시가 좀 늦어지더라도, 이번 개발은 <strong>학습 목적</strong>도 크기 때문에 <strong>구조 설계를 고민하고 개선</strong>하는 시간을 가졌다. </p>
<br/>

<p><strong>[ 주요 작업 요약 ]</strong></p>
<ul>
<li>타이머 라이프사이클 <strong>정책 변경</strong> (기본값: 보관→삭제)<ul>
<li>완료 시 n초 후 자동 삭제</li>
<li>필요시 ‘즐겨찾기’로 보관 가능</li>
</ul>
</li>
<li>단일 화면 → 복합 화면 전환</li>
<li>MVVM 패턴·핸들러를 적용하여 <strong>유지보수성 향상</strong></li>
</ul>
<br/>

<p>앱의 <strong>USP(차별 포인트)</strong> — “퀵”, “라벨”— 을 살리기 위해 세워둔 원칙은 이것이었다.</p>
<ol>
<li>타이머 생성을 첫 화면에 둘 것</li>
<li>타이머 완료 후 확인 버튼 없이 앱 진입만으로 꺼질 것</li>
</ol>
<p>그중 2번, 앱 진입만으로 타이머를 종료시키려다 보니 <strong>완료된 타이머를 어디로 보낼지가 고민</strong>이었다. 기존 정책은 &#39;완료된 타이머는 자동으로 보관 목록으로 이동&#39;이었다. 하지만 확인 버튼도 없는데 보관까지 자동으로 되면 사용자가 헷갈릴 것 같았다. 그래서 <strong>완료 시 n초 후 ‘자동 삭제’</strong>로 바꾸고, 남기고 싶은 타이머만 사용자가 직접 <strong>‘즐겨찾기’로 보관</strong>하도록 했다. 이렇게 해서 <strong>“즐겨찾기에 추가하지 않으면 사라진다”는 흐름이 자연스럽게 전달되고</strong>, UX도 간결해졌다!!</p>
<p>기존의 정책에서는 ‘보관 목록으로 이동’이 보여야 해서 화면 분리가 어려웠지만, 이제는 즐겨찾기를 별도 화면으로 옮길 수 있게 되었다. 덕분에 <strong>단일 화면을 복합 화면으로 전환</strong>할 수 있었다. </p>
<p>정책 변경에 맞춰 리팩토링을 진행하면서 <strong>유지보수성이 왜 중요한지</strong> 뼈저리게 느꼈다. 😂😂
<code>View</code>에 섞여 있던 로직을 <code>ViewModel</code>로 <strong>분리</strong>하고, 타이머와 관련된 모든 기능을 담당하던 <code>TimerManager</code>에서 ‘완료 후 처리’만 따로 <strong>분리</strong>해서  <code>Handler</code>로 만들었다. 유지보수의 어려움을 직접 경험하고 나니 <strong>SRP(단일 책임 원칙)의미와 필요성</strong>이 확실히 와닿았다.</p>
<br/>
<br/>

<h2 id="배운-점">배운 점</h2>
<ul>
<li><p><strong>좋은 UX는 사용자의 피드백에서 나온다.</strong>
회고를 쓰면서 이번 주를 돌아보니, 혼자 머릿속에서만 ‘완벽한 UX가 뭘까’를 오래 고민했다는 생각이 들었다. 사실 좋은 UX는 <strong>사용자의 실제 피드백을 통해 개선</strong>해 가는 것인데 말이다. 다음부터는 완벽하게 만들겠다는 생각에 너무 오래 붙잡히지 말고, 적당한 시점에서 구현해보고 <strong>검증</strong>하는 흐름을 가져가야겠다.</p>
</li>
<li><p><strong>하나의 클래스, 모듈은 한 가지 역할만 수행하도록 하자.</strong></p>
</li>
<li><p><em>SRP(단일 책임 원칙)*</em>는 하나의 클래스나 모듈이 한 가지 역할만 수행하도록 하는 설계 원칙인데, 이번 리팩토링을 통해 유지보수 과정에서 그 필요성을 몸소 체감했다.</p>
</li>
</ul>
<br/>
<br/>

<h2 id="다음-주에-할-일">다음 주에 할 일</h2>
<ul>
<li>알림 기능 만들기
4주 차 동안 리팩토링에 많은 시간을 들였지만, 그 과정에서 <strong>아키텍처 패턴을 적용하는 이유</strong>와 <strong>SRP를 지키면 좋은 점</strong>을 확실히 이해할 수 있었다. 이번 리팩토링 덕분에 다음 주 알림 기능 개발이 한층 수월해지지 않을까 기대된다.</li>
</ul>
<br/>
<br/>
]]></description>
        </item>
        <item>
            <title><![CDATA[[AI를 활용한 타이머 앱 개발기] 주간 회고 #3 <- 이름 수정. Ai-assistent 키워드 박고. 얘는 v1.0개발기. 에이아이에이전트는 v1.1 개선기]]></title>
            <link>https://velog.io/@data_sy/AI%EB%A5%BC-%ED%99%9C%EC%9A%A9%ED%95%9C-%ED%83%80%EC%9D%B4%EB%A8%B8-%EC%95%B1-%EA%B0%9C%EB%B0%9C%EA%B8%B0-%EC%A3%BC%EA%B0%84-%ED%9A%8C%EA%B3%A0-3</link>
            <guid>https://velog.io/@data_sy/AI%EB%A5%BC-%ED%99%9C%EC%9A%A9%ED%95%9C-%ED%83%80%EC%9D%B4%EB%A8%B8-%EC%95%B1-%EA%B0%9C%EB%B0%9C%EA%B8%B0-%EC%A3%BC%EA%B0%84-%ED%9A%8C%EA%B3%A0-3</guid>
            <pubDate>Sun, 03 Aug 2025 03:14:47 GMT</pubDate>
            <description><![CDATA[<blockquote>
<h3 id="⏰-퀵라벨타이머-quick-label-timer">⏰ 퀵라벨타이머 (Quick Label Timer)</h3>
</blockquote>
<ul>
<li><strong>플랫폼·기술</strong>: iOS 앱, SwiftUI</li>
<li><strong>앱 컨셉</strong>: 시간을 빠르게 설정할 수 있는 <strong>퀵 타이머</strong>에, ‘왜 맞췄는지’를 기록할 수 있는 <strong>라벨 기능</strong>을 결합한 타이머 앱</li>
<li><strong>개발 목적</strong>: AI-Assisted Programming을 실제 서비스 개발에 적용하여 <strong>장단점</strong>을 살펴보고, <strong>서비스 완성 및 운영 경험</strong>을 통해 <strong>설계 능력과 문제 해결 능력을 강화</strong>하고자 함</li>
<li><strong>GitHub</strong>: <a href="https://github.com/data-sy/quick-label-timer">https://github.com/data-sy/quick-label-timer</a></li>
</ul>
<br/>
<br/>

<h2 id="이번-주에-한-일">이번 주에 한 일</h2>
<table>
<thead>
<tr>
<th><img src="https://velog.velcdn.com/images/data_sy/post/8d2721ef-a948-4834-8002-ea6b33d3390f/image.png" alt=""></th>
<th><img src="https://velog.velcdn.com/images/data_sy/post/3feb375d-d92b-4e07-8539-c9fe6a8991bf/image.png" alt=""></th>
</tr>
</thead>
</table>
<p>이번 주에는 <strong>타이머 수정 화면</strong>과 <strong>설정 화면</strong>을 구현했다. 
그리고 그 과정에서 알림/진동 설정의 책임을 <code>Model</code>로 이관하는 <strong>리팩토링</strong>도 진행했다.</p>
<p>타이머 수정 화면 구현은 생각보다 금방 끝났다.
이전에 사용자 입력 화면을 컴포넌트 단위로 만들어 둔 덕분에, 그것들을 가져다 조립만 하면 되었다. <strong>컴포넌트화의 효용</strong>을 몸소 체감했다. 나중에 디자인을 수정하거나 기능을 추가할 때, 입력 화면과 수정 화면을 각각 손대지 않아도 될 테니 <strong>유지보수</strong>에도 좋을 것 같다.</p>
<p>반면, 설정 화면 구현은 예상보다 시간이 많이 들었다.
중요도에 비해 신경 써야 할 것이 많았기 때문이다. 또 보태보태병(?)에 걸려 ‘이 기능도, 저 기능도 필요하지 않을까’하는 욕심에 계속 손이 가게 됐다. 지금 생각하면, 오히려 <strong>출시 후에 추가</strong>해도 됐겠다는 아쉬움이 남는다. 하지만, 설정의 기본 사운드 기능을 만드는 과정에서 <strong>설계 리팩토링 지점</strong>을 발견했으니 럭키비키자나~🍀</p>
<p>기본 사운드 설정 기능을 구현하는 과정에서, 기존처럼 별도의 <code>UserSettings</code> 모델을 만드는 게 맞는지 의문이 생겼다. 소리/진동의 on·off는 각 타이머가 가지는 속성이기 때문이다. 그래서 설정 관리 책임을 <code>TimerData</code> 모델로 이관하는 리팩토링을 진행했다. 이 과정에서 <strong>AI-Assisted Programming의 한계</strong>를 체감했다. AI가 짜주는 대로만 따라가면 세부 설계까지 챙겨주지 않기 때문에 <strong>내가 직접 설계를 고민하고, 필요한 리팩토링을 주도해야 한다</strong>는 점을 확실히 느꼈다.</p>
<br/>
<br/>

<h2 id="배운-점">배운 점</h2>
<ul>
<li><p><strong>컴포넌트화의 힘</strong>
초반에 컴포넌트 단위로 만들어둔 덕분에, 새 화면을 추가할 때 빠르게 조립하고, 일관된 디자인을 유지할 수 있었다. 앞으로도 <strong>재사용성</strong>을 신경 써서 개발해야겠다.</p>
</li>
<li><p><strong>설정 화면의 함정(?)</strong>
눈에 보이지 않는 기능이라도, 구현에 들어가는 리소스가 의외로 많을 수 있다. 앞으로는 “금방 만들 것 같다”는 이유만으로 우선순위를 올리지 않고, 정말 <strong>필요한 기능부터</strong> 차근차근 추가하는 습관을 들여야겠다.</p>
</li>
<li><p><strong>설계는 내가, 코드는 AI가</strong>
AI의 도움으로 코드 작성은 빨라졌지만, <strong>도메인을 이해하고 서비스 구조를 설계하는 일은 개발자의 몫</strong>이다. 이 주도권을 놓치지 않아야 한다는 점을 다시 한번 느꼈다.</p>
</li>
</ul>
<br/>
<br/>

<h2 id="다음-주에-할-일">다음 주에 할 일</h2>
<ul>
<li>타이머 상태 변화에 따른 UI/UX/기능의 빈틈을 개선할 예정이다.<ul>
<li>예) 타이머 종료 후 언제까지 실행 중 목록에 둘 것인지 등</li>
</ul>
</li>
<li>‘실행 중 목록‘과 ’타이머 목록‘을 컨테이너를 사용해 <strong>레이아웃을 통일</strong>하려 한다.<ul>
<li>AS-IS :  완료된 타이머에 깜빡임 기능을 주기 위해, 실행중 목록은 Vstack을 사용 (타이머 목록은 List)</li>
<li>TO-BE : ‘n초 후 삭제’ UX 도입으로 Vstack을 고집할 필요가 없어짐. 삭제 스와이프를 일관되게 적용하기 위해 모두 List로 변경</li>
<li><strong>이를 통해 유지보수가 더 쉬워질 것이다.</strong></li>
</ul>
</li>
</ul>
<br/>
<br/>]]></description>
        </item>
        <item>
            <title><![CDATA[Spring AOP의 런타임 위빙 동작 과정]]></title>
            <link>https://velog.io/@data_sy/Spring-AOP%EC%9D%98-%EB%9F%B0%ED%83%80%EC%9E%84-%EC%9C%84%EB%B9%99-%EB%8F%99%EC%9E%91-%EA%B3%BC%EC%A0%95</link>
            <guid>https://velog.io/@data_sy/Spring-AOP%EC%9D%98-%EB%9F%B0%ED%83%80%EC%9E%84-%EC%9C%84%EB%B9%99-%EB%8F%99%EC%9E%91-%EA%B3%BC%EC%A0%95</guid>
            <pubDate>Wed, 24 Jul 2024 06:50:09 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/data_sy/post/e1e86bc7-4d07-46cd-8aa0-df379d927dbd/image.png" alt=""></p>
<p>Spring AOP의 런타임 위빙 동작 방식을 다음 이미지 내용을 바탕으로 설명하겠습니다.</p>
<h3 id="spring-aop의-런타임-위빙-동작-과정">Spring AOP의 런타임 위빙 동작 과정</h3>
<ol>
<li><p><strong>빈 객체 생성</strong>:</p>
<ul>
<li>스프링 컨테이너는 애플리케이션 컨텍스트 초기화 과정에서 <code>A 객체</code>를 생성합니다.</li>
</ul>
</li>
<li><p><strong>빈 후처리기 전달</strong>:</p>
<ul>
<li>생성된 <code>A 객체</code>는 빈 후처리기 (Bean Post Processor)에게 전달됩니다. 빈 후처리기는 스프링 컨테이너에서 빈이 생성되고 초기화된 후에 특정 작업을 수행하기 위해 사용됩니다.</li>
</ul>
</li>
<li><p><strong>프록시 객체로 변환 (바꿔치기)</strong>:</p>
<ul>
<li>빈 후처리기는 <code>A 객체</code>가 AspectJ 모듈에 정의된 포인트컷(Pointcut)에 해당하는지를 검사합니다.</li>
<li>만약 <code>A 객체</code>가 포인트컷에 해당하면, 빈 후처리기는 <code>A 객체</code>를 프록시 객체(<code>A 프록시</code>)로 바꿔치기합니다. 이 프록시 객체는 AspectJ 모듈에서 정의된 로직을 가로채서 실행할 수 있도록 설계됩니다.</li>
<li>프록시 객체는 실제 <code>A 객체</code>를 감싸고 있으며, <code>A 객체</code>에 대한 메서드 호출을 가로챕니다.</li>
</ul>
</li>
<li><p><strong>프록시 객체 등록</strong>:</p>
<ul>
<li>변환된 <code>A 프록시</code>는 스프링 컨테이너의 빈 저장소에 <code>beanA</code>라는 이름으로 등록됩니다.</li>
<li>이후 스프링 애플리케이션은 <code>beanA</code>를 참조할 때 <code>A 프록시</code> 객체를 사용하게 됩니다.</li>
</ul>
</li>
<li><p><strong>프록시 객체의 메서드 호출</strong>:</p>
<ul>
<li>클라이언트가 <code>A 프록시</code>의 메서드를 호출하면, 프록시 객체는 메서드 호출을 가로채고, AspectJ 모듈에서 정의한 로직 (예: 로깅, 트랜잭션 관리 등)을 실행합니다.</li>
<li>그 후 프록시 객체는 실제 <code>A 객체</code>의 메서드를 호출하여 원래의 비즈니스 로직을 실행합니다.</li>
<li>최종적으로 프록시 객체는 결과를 클라이언트에게 반환합니다.</li>
</ul>
</li>
</ol>
<h3 id="요약">요약</h3>
<ul>
<li><strong>프록시 객체 생성</strong>: 빈 후처리기에서 AspectJ 모듈의 포인트컷에 해당하는 빈을 프록시 객체로 변환합니다.</li>
<li><strong>메서드 호출 가로채기</strong>: 클라이언트가 프록시 객체의 메서드를 호출할 때 프록시 객체는 호출을 가로채고, 추가 로직을 실행한 후 실제 메서드를 호출합니다.</li>
<li><strong>결과 반환</strong>: 프록시 객체는 원래 메서드의 결과를 클라이언트에게 반환합니다.</li>
</ul>
<p>이 과정을 통해 Spring AOP는 런타임 시점에서 빈에 대해 횡단 관심사를 적용하며, 코드의 모듈화와 재사용성을 높입니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[웹페이지 접속 과정]]></title>
            <link>https://velog.io/@data_sy/%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC-%ED%9D%90%EB%A6%84</link>
            <guid>https://velog.io/@data_sy/%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC-%ED%9D%90%EB%A6%84</guid>
            <pubDate>Tue, 23 Jul 2024 21:59:38 GMT</pubDate>
            <description><![CDATA[<h3 id="-목차-">[ 목차 ]</h3>
<ul>
<li>웹 페이지 접속 과정<ul>
<li>심플 버전</li>
<li>디테일 버전</li>
</ul>
</li>
<li>로드밸런서</li>
<li>웹 페이지 접속 과정 - 스프링</li>
</ul>
<br/>
<br/>

<h3 id="ㅇ-웹-페이지-접속-과정-1---심플-버전">ㅇ 웹 페이지 접속 과정 1 - 심플 버전</h3>
<ul>
<li>사용자가 URL(도메인)을 웹 브라우저에 입력</li>
<li>웹 브라우저는 입력한 URL을 바탕으로 DNS(Domain Name System)서버에 연결할 IP를 요청</li>
<li>DNS서버는 IP주소를 웹 브라우저에게 응답으로 제공</li>
<li>웹 브라우저는 DNS서버에서 받은 IP를 통해 웹 서버와 TCP/IP 연결을 통해 세션 수립</li>
<li>HTTP 요청을 보내고, 웹 서버는 받은 HTTP 요청에 응답. 응답은 웹 페이지와 필요한 리소스를 포함</li>
<li>웹 브라우저는 받은 응답을 바탕으로 사용자에게 웹 페이지를 보여줌
<img src="https://velog.velcdn.com/images/data_sy/post/cb846987-161d-4391-b8e8-e7e3fa8d0170/image.jpeg" alt=""></li>
</ul>
<br/>
<br/>

<h3 id="ㅇ-웹-페이지-접속-과정-2---디테일-버전">ㅇ 웹 페이지 접속 과정 2 - 디테일 버전</h3>
<ul>
<li>사용자가 URL(도메인)을 웹 브라우저에 입력<ul>
<li>브라우저의 URL 파싱 : 주소창에 입력된 문자열이 URL 형식을 띄고 있는지 확인 (아니라면 검색 기능 작동)</li>
<li>브라우저 캐시 확인 : 브라우저 캐시에 저장된 데이터가 있다면, 서버에 접속하지 않고 캐시에서 데이터를 사용</li>
<li>HSTS 조회 : HTTP 요청은 HTTPS 요청으로 변환 (HTTP Strict Transport Security) </li>
</ul>
</li>
<li>웹 브라우저는 입력한 URL을 바탕으로 DNS(Domain Name System)서버에 연결할 IP를 요청<ul>
<li>로컬 DNS 캐시 확인 : DNS 정보가 로컬 DNS 캐시에 이미 존재하고, 캐시의 TTL ( Time To Live (DNS 레코드의 캐시 유효 시간)) 값이 유효하다면, DNS 서버에 요청을 보내지 않고, 로컬 DNS 캐시에서 해당 정보를 가져옴</li>
<li>연쇄적인 DNS 서버 조회 : Root DNS 서버 -&gt; TLD(Top-Level Domain) DNS 서버 -&gt; Authoritative DNS 서버를 순차적으로 조회하여 IP 주소 반환
<img src="https://velog.velcdn.com/images/data_sy/post/43ff589d-36dd-47a3-941c-16a87f7b97d5/image.gif" alt=""></li>
</ul>
</li>
<li>DNS서버는 IP주소를 웹 브라우저에게 응답으로 제공</li>
<li>웹 브라우저는 DNS서버에서 받은 IP를 통해 웹 서버와 TCP/IP 연결을 하고 세션 수립<ul>
<li>IP 주소와 라우터를 이용한 웹 서버 추적 : <ul>
<li>라우팅 테이블 점검 : DNS 서버에서 획득한 IP주소가 라우팅 테이블에 존재한다면 이를 사용하여 웹 서버를 추적, 존재하지 않는다면 라우팅 알고리즘을 통해 해당 서버의 게이트웨이까지 이동</li>
<li>ARP (Address Resolution Protocol)를 통한 MAC 주소 획득 : ARP 를 통해 목적지와 실질적으로 통신을 하기위해 ARP Table 내에서 IP 주소를 MAC 주소와 매칭</li>
</ul>
</li>
<li>TCP/IP 연결 : -way handshake 과정(SYN, SYN-ACK, ACK)을 통해 연결을 수립</li>
</ul>
</li>
<li>HTTP 요청을 보내고, 웹 서버는 받은 HTTP 요청에 응답<ul>
<li>응답은 웹 페이지와 필요한 리소스를 포함</li>
<li>웹 서버에서 컨텐츠를 전송할 때는 로드 밸런싱(Elastic Load Balancing, ELB) 기능을 이용해 서버를 분산해 부하를 줄여줌</li>
</ul>
</li>
<li>웹 브라우저는 받은 응답을 바탕으로 사용자에게 웹 페이지를 표시<ul>
<li>콘텐츠 렌더링 : 응답을 받은 웹 브라우저는 HTML, CSS, JavaScript 등의 웹 자원을 처리하여 웹 페이지를 렌더링하고 사용자에게 표시 (CSR)</li>
</ul>
</li>
</ul>
<br/>
<br/>


<h3 id="ㅇ-load-balancing">ㅇ Load Balancing</h3>
<ul>
<li>둘 이상의 중앙처리장치/저장장치와 같은 컴퓨터 자원들에게 작업(Work), 즉, 부하(Load)를 나누는 것<ul>
<li>자원 사용 최적화</li>
<li>처리량 극대화</li>
<li>응답 시간 줄이기</li>
<li>고장 허용성 보장</li>
</ul>
</li>
<li>Scale-out<ul>
<li>하나의 Server 보다는 여러 대의 Server가 나눠서 일을 하는 방법</li>
<li>(vs) Scale-up : Server가 더 빠르게 동작하기 위해 하드웨어 성능을 올리는 방법</li>
<li>하드웨어 향상하는 비용보다 서버 한대 추가 비용이 더 적음</li>
<li>여러 대의 Server 덕분에 무중단 서비스를 제공 가능</li>
<li><strong>여러 대의 Server에게 균등하게 Traffic을 분산시켜주는 역할을 하는 것이 Load Balancer</strong></li>
</ul>
</li>
<li>주요 기능<ul>
<li>트래픽 분산 : 트래픽을 분산시켜 각 서버의 부하를 균일하게 관리</li>
<li>오토 스케일링 : 조건에 맞춰 필요시 server에 컴퓨터 수를 늘리거나 줄여서 부하 관리 가능 (Scale out, Scale in)</li>
<li>Health Check : 해당 포트에 트래픽을 보내 애플리케이션이 올바르게 작동하는지 여부를 판별</li>
<li>보안 서비스: 웹 애플리케이션 방화벽(WAF)과 네트워크 주소 변환(NAT) 같은 보안 기능을 통해 외부 공격으로부터 내부 네트워크를 보호</li>
</ul>
</li>
<li>종류<ul>
<li>L2 : Mac주소를 바탕으로 Load Balancing</li>
<li>L3<ul>
<li>네트워크 계층 (OSI 7계층의 제 3계층)</li>
<li>IP 주소를 바탕으로 Load Balancing</li>
<li>이 과정에서 NAT(Network Address Translation)가 사용될 수 있음</li>
<li>네트워크 계층의 로드 밸런싱은 라우팅 결정을 기반으로 작동하며, 패킷의 전달 경로를 조정하는 역할을 함</li>
</ul>
</li>
<li>L4<ul>
<li>전송 계층 (OSI 7계층의 제 4계층)</li>
<li>Transport Layer(IP와 TCP/UDP Port) Level에서 Load Balancing </li>
<li>TCP 연결 또는 UDP 흐름을 감지하고, 이를 기반으로 서버들 사이에 트래픽을 분산</li>
<li>전송 계층의 로드 밸런싱은 세션 기반의 결정을 포함하며, 클라이언트와 서버 사이의 연결을 유지하는 데 중요한 역할을 함</li>
</ul>
</li>
<li>L7 : Application Layer(사용자의 Request) Level에서 Load Balancing (HTTP, HTTPS, FTP)</li>
<li>트래픽 분산이 목적이라면 네트워크 계층에서의 로드 밸런싱이 효과적일 수 있으며, 세션 유지가 중요한 애플리케이션에서는 전송 계층에서의 로드 밸런싱이 더 적합할 수 있음</li>
</ul>
</li>
<li>로드밸런싱 알고리즘<ul>
<li>라운드 로빈 (Round Robin) : 각 서버에 순차적으로 요청을 분배하는 가장 단순한 형태의 로드 밸런싱 방법</li>
<li>최소 연결 (Least Connections) : 연결 개수가 가장 적은 서버를 선택. 트래픽으로 인해 세션이 길어지는 경우 효과적</li>
<li>소스 (Source) : 사용자의 IP를 Hashing하여 분배. 사용자가 항상 같은 서버로 연결되는 것을 보장</li>
</ul>
</li>
</ul>
<br/>
<br/>

<h3 id="ㅇ-스프링-관점에서의-웹-페이지-접속-과정">ㅇ 스프링 관점에서의 웹 페이지 접속 과정</h3>
<p>(스프링부트, 스프링MVC 사용)</p>
<ul>
<li>사용자가 URL(도메인)을 웹 브라우저에 입력</li>
<li>브라우저의 요청<ul>
<li>브라우저는 입력한 URL을 DNS를 통해 IP 주소로 변환하고, 웹 서버와 TCP/IP 연결을 수립합</li>
<li>HTTP 요청을 서버에 보냄</li>
</ul>
</li>
<li><strong>스프링 서버의 요청 처리</strong><ul>
<li>요청 수신<ul>
<li>스프링 부트 애플리케이션이 HTTP 요청을 수신합니다. 스프링 부트는 내장 서버(예: Tomcat, Jetty, Undertow)를 사용하여 요청을 처리합니다.</li>
</ul>
</li>
<li>디스패처 서블릿(DispatcherServlet)<ul>
<li>스프링 부트는 DispatcherServlet이라는 중앙 서블릿을 통해 모든 HTTP 요청을 처리합니다. 이 서블릿은 요청을 적절한 컨트롤러로 전달합니다.</li>
</ul>
</li>
<li>컨트롤러 매핑<ul>
<li>DispatcherServlet은 요청의 URL 패턴에 맞는 컨트롤러를 찾기 위해 요청 매핑(Handler Mapping)을 사용합니다. 요청 URL과 일치하는 컨트롤러의 메서드를 찾습니다.</li>
</ul>
</li>
<li>컨트롤러 메서드 호출<ul>
<li>요청이 일치하는 컨트롤러의 메서드가 호출됩니다. 이 메서드는 비즈니스 로직을 처리하고, 필요한 데이터를 모델에 담아 뷰에 전달합니다.</li>
</ul>
</li>
<li>모델과 뷰 반환<ul>
<li>컨트롤러는 데이터(모델)와 뷰 이름을 반환합니다. 뷰 이름은 보통 HTML 템플릿의 파일 이름을 의미합니다.</li>
</ul>
</li>
<li>뷰 리졸버(View Resolver)<ul>
<li>DispatcherServlet은 뷰 리졸버를 통해 컨트롤러가 반환한 뷰 이름을 실제 뷰(예: Thymeleaf, JSP 파일)로 변환합니다. 이 뷰는 최종 HTML 페이지를 생성하는 역할을 합니다.</li>
</ul>
</li>
<li>뷰 렌더링<ul>
<li>선택된 뷰 템플릿 엔진(예: Thymeleaf, JSP)이 모델 데이터를 기반으로 최종 HTML 페이지를 렌더링합니다. 렌더링된 HTML 페이지는 HTTP 응답으로 반환됩니다.</li>
</ul>
</li>
<li>반호</li>
</ul>
</li>
<li>HTTP 응답 전송<ul>
<li>렌더링된 HTML 페이지가 HTTP 응답으로 웹 브라우저에 전송됩니다.</li>
</ul>
</li>
<li>웹 브라우저에서 페이지 표시<ul>
<li>웹 브라우저는 HTTP 응답으로 받은 HTML 페이지를 화면에 표시합니다. 브라우저는 추가적인 리소스(예: CSS, JavaScript, 이미지)를 요청할 수 있으며, 이 리소스들도 동일한 방식으로 서버에서 처리됩니다.</li>
</ul>
</li>
<li>REST API 사용 시 뷰 반환 처리:<ul>
<li>컨트롤러는 보통 뷰 대신 데이터만을 포함한 응답을 반환합니다. 이 경우, 뷰 이름이 비어 있으며(null), 반환되는 데이터 객체는 HTTP 응답 본문으로 직접 변환됩니다.</li>
<li>응답 변환 처리: 데이터는 @ResponseBody 어노테이션이 붙은 컨트롤러 메서드에서 반환될 수 있으며, 스프링의 메시지 컨버터(HttpMessageConverter)를 통해 클라이언트가 요청한 형식(JSON, XML 등)으로 자동 변환되어 응답됩니다.</li>
<li>@RestController의 역할: @RestController 어노테이션은 클래스 레벨에서 사용되며, 이는 해당 컨트롤러의 모든 메서드가 @ResponseBody를 암묵적으로 가진다는 것을 의미합니다. 따라서, REST API를 제공하는 컨트롤러에서는 별도의 뷰를 관리하지 않고, 데이터를 직접 HTTP 응답으로 매핑합니다.</li>
</ul>
</li>
</ul>
<br/>
<br/>

<hr>
<h4 id="출처">출처</h4>
<ul>
<li><a href="https://medium.com/@2kunhee94/%EB%B8%8C%EB%9D%BC%EC%9A%B0%EC%A0%80%EC%9D%98-%EC%A3%BC%EC%86%8C%EC%B0%BD%EC%97%90-url%EC%9D%84-%EC%9E%85%EB%A0%A5%ED%95%98%EB%A9%B4-%EC%9D%BC%EC%96%B4%EB%82%98%EB%8A%94-%EC%9D%BC-97a0837b8bf8">https://medium.com/@2kunhee94/브라우저의-주소창에-url을-입력하면-일어나는-일-97a0837b8bf8</a></li>
<li>DNS : <a href="https://opentutorials.org/course/3276">https://opentutorials.org/course/3276</a></li>
<li>로드밸런싱 : <a href="https://nesoy.github.io/articles/2018-06/Load-Balancer">https://nesoy.github.io/articles/2018-06/Load-Balancer</a></li>
<li>스프링 관점에서의 웹 페이지 접속 과정 : ChatGPT</li>
</ul>
<br/>

]]></description>
        </item>
        <item>
            <title><![CDATA[[Form Check Gym] 관련 논문 검색]]></title>
            <link>https://velog.io/@data_sy/%EB%85%BC%EB%AC%B8</link>
            <guid>https://velog.io/@data_sy/%EB%85%BC%EB%AC%B8</guid>
            <pubDate>Thu, 14 Oct 2021 16:44:03 GMT</pubDate>
            <description><![CDATA[<ul>
<li>딥러닝 기반 영상처리 기법 및 표준 운동 프로그램을
활용한 비대면 온라인 홈트레이닝 어플리케이션 연구 2021.08</li>
</ul>
<p><img src="https://images.velog.io/images/data_sy/post/e9947320-31a8-43a2-8aaa-7c0ad1280590/image.png" alt=""></p>
<p><img src="https://images.velog.io/images/data_sy/post/b282936b-f465-42ea-9451-76bb17c39486/image.png" alt=""></p>
<ul>
<li><p>인체 자세 인식 딥러닝을 이용한 운동 자세 훈련 시스템 개발
<img src="https://images.velog.io/images/data_sy/post/9e7dde58-2116-4660-ae41-588978d91189/image.png" alt=""></p>
</li>
<li><p>기계 학습 기반 목의 기울기 별 앉은 자세 인식을 이용한 거북목 식별 방법 및 장치
<img src="https://images.velog.io/images/data_sy/post/c1e7f342-8bea-4b20-9320-07bcf5e9f4a7/image.png" alt="">
<img src="https://images.velog.io/images/data_sy/post/234fc9d1-74c6-404f-bc16-e1e722da5451/image.png" alt="">
<img src="https://images.velog.io/images/data_sy/post/a8d0bddb-304f-4ebd-b1ec-2e2bf40f9eb0/image.png" alt=""></p>
</li>
</ul>
<ul>
<li>딥러닝 CNN을 이용한 자세, 동작 피드백이 가능한 운동프로그램 개발 2021.04</li>
<li>원문 링크 
<a href="https://dcollection.skku.edu/public_resource/pdf/000000165345_20211015013412.pdf">https://dcollection.skku.edu/public_resource/pdf/000000165345_20211015013412.pdf</a></li>
<li><a href="http://www.riss.kr/search/detail/DetailView.do?p_mat_type=be54d9b8bc7cdb09&amp;control_no=f60d79c209a91f08ffe0bdc3ef48d419&amp;outLink=K">http://www.riss.kr/search/detail/DetailView.do?p_mat_type=be54d9b8bc7cdb09&amp;control_no=f60d79c209a91f08ffe0bdc3ef48d419&amp;outLink=K</a></li>
</ul>
<p><img src="https://images.velog.io/images/data_sy/post/893ec823-d428-4c80-992b-b50cb8d72ef2/image.png" alt="">
<img src="https://images.velog.io/images/data_sy/post/6c267c8c-150b-4890-86e7-a9275fbfe364/image.png" alt="">
<img src="https://images.velog.io/images/data_sy/post/1139c35a-cd9a-4d13-bf73-95107c61a966/image.png" alt=""></p>
<ul>
<li>인공지능 기반 초기 움직임에서의 동작 인식 2020.02 <strong>(lstm, gru) 사용한</strong>
<a href="http://www.riss.kr/search/detail/DetailView.do?p_mat_type=be54d9b8bc7cdb09&amp;control_no=df59e6cbce7b07afffe0bdc3ef48d419&amp;outLink=K">http://www.riss.kr/search/detail/DetailView.do?p_mat_type=be54d9b8bc7cdb09&amp;control_no=df59e6cbce7b07afffe0bdc3ef48d419&amp;outLink=K</a></li>
</ul>
<p><img src="https://images.velog.io/images/data_sy/post/fd91db85-a394-4fed-beb1-11832e8ec9b1/image.png" alt=""></p>
<ul>
<li><p>낙상탐지: 얘도 lstm, gru 사용하는데
포인트가 결국 <strong>행동을 예측</strong>해서 낙상을 방지하는 거...</p>
</li>
<li><p>lstm, gru 얘들은 다 이상행동 감지, 행동 인식 쪽
<a href="https://scienceon.kisti.re.kr/srch/selectPORSrchArticle.do?cn=JAKO202116739584326">https://scienceon.kisti.re.kr/srch/selectPORSrchArticle.do?cn=JAKO202116739584326</a></p>
</li>
<li><p>딥러닝 기반 포즈인식을 이용한 체력측정 시스템 2020
얘는 체력 측정
근데 디테일에 자세 교정 부분 있고 우리가 원하는 방향이야
이 파일 더 보자!</p>
</li>
</ul>
<ul>
<li>딥러닝을 활용한 운동 자세 분석 기술 및 인공지능 PT(Personal Training) 시스템 개발
(비공개라 열람 불가)
<a href="https://scienceon.kisti.re.kr/srch/selectPORSrchReport.do?cn=TRKO201900017823">https://scienceon.kisti.re.kr/srch/selectPORSrchReport.do?cn=TRKO201900017823</a></li>
</ul>
<ul>
<li><p>자석 기반 웨어러블 센서와 딥러닝 알고리즘을
이용한 거북목, 굽은 어깨, 비대칭어깨 종합 검사 및
장거리 운전자 피로 분석에의 응용 2020.02
결국 기준은 직접 만들어야 하나..
<img src="https://images.velog.io/images/data_sy/post/3430f977-75a9-4996-ab20-447812e7e7f2/image.png" alt=""></p>
</li>
<li><p>홈트레이닝을 위한 관절 특징점 검출 및 행동 유사도 측정 2020
이게 유튜브 따라하기를 한다면 가장 유사
우리 첫 아이디어랑 완전 똑같아 ㅋㅋㅋㅋ
<img src="https://images.velog.io/images/data_sy/post/f61c9700-71a8-4bcb-8510-9c519c0e7f2f/image.png" alt=""></p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Spring] 객체 바인딩]]></title>
            <link>https://velog.io/@data_sy/8%EC%9B%94-18%EC%9D%BC-%EC%88%98%EC%9A%94%EC%9D%BC-6</link>
            <guid>https://velog.io/@data_sy/8%EC%9B%94-18%EC%9D%BC-%EC%88%98%EC%9A%94%EC%9D%BC-6</guid>
            <pubDate>Wed, 18 Aug 2021 01:57:03 GMT</pubDate>
            <description><![CDATA[<p>&lt;목차&gt;
(실습 1 : 게시판 만들기)</p>
<p>ㅇ 객체 바인딩
ㅇ Model</p>
<br/>
<br/>

<h3 id="ㅇ-객체-바인딩">ㅇ 객체 바인딩</h3>
<ul>
<li><p>계층 간 데이터 교환 : 컨트롤러와 jsp가 데이터를 어떻게 주고 받는지 (젤 중요한 부분!!)</p>
</li>
<li><p>객체 바인딩 : 특정 객체(메모리)에 담아서 서로 다른 계층이 넣고 빼고 할 수 있게 하는 기술</p>
</li>
<li><p>아이디어</p>
<ul>
<li>데이터를 특정 메모리에 셋어트리뷰터 해두고 -&gt; jsp로 포워딩이 될 때 넘겨주면 -&gt; jsp에서 겟어트리뷰트로 꺼내주는</li>
<li>특정 메모리에 객체를 연결시켜두고 다른 쪽에서 객체를 꺼내 가는</li>
</ul>
</li>
<li><p>HttpServletRequest 객체를 활용하면</p>
<ul>
<li>Controller에서 메서드 입력인자로 사용하여 셋어트리뷰트 
<img src="https://velog.velcdn.com/images/data_sy/post/a17e5cd1-5e06-4c2f-9f0b-ce8da0390c45/image.png" alt=""></li>
<li>jsp에서 꺼내기 : 겟 어트리뷰트<img src="https://velog.velcdn.com/images/data_sy/post/f8ef07e7-f762-435a-980a-b18f50c51b2e/image.png" alt="">그리고 tr부분에서 반복문 돌려서 게터로 뿌려줘<img src="https://velog.velcdn.com/images/data_sy/post/c7620bd1-5eb1-437c-8c5f-af10252153ed/image.png" alt=""></li>
</ul>
</li>
<li><p>HttpServletRequest 사실 요청을 위한 객체 (서블릿에서 제공하는)
세션이나 쿠키는 상태유지기법에서 쓰는 애들
=&gt; 즉, 객체 바인딩을 위한 애가 따로 있어. (스프링에서 제공하는)</p>
</li>
</ul>
<br/>
<br/>

<h3 id="ㅇ-model">ㅇ Model</h3>
<ul>
<li>스프링에서 객체 바인딩을 위해 제공해 주는 메모리</li>
<li>HttpServletRequest 대신 Model을 사용하자</li>
<li>call by reference</li>
<li>내부적으로 클래스가 연동되는 부분은 관여할 필요 없어. 스프링이 알아서 다 만들어뒀어 =&gt; 프레임워크의 장점
<img src="https://velog.velcdn.com/images/data_sy/post/46918e47-2bfe-4888-bcb8-932b65edac9c/image.png" alt=""></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Spring] POJO, DAO, DTO, VO]]></title>
            <link>https://velog.io/@data_sy/8%EC%9B%94-18%EC%9D%BC-%EC%88%98%EC%9A%94%EC%9D%BC-5</link>
            <guid>https://velog.io/@data_sy/8%EC%9B%94-18%EC%9D%BC-%EC%88%98%EC%9A%94%EC%9D%BC-5</guid>
            <pubDate>Wed, 18 Aug 2021 01:56:58 GMT</pubDate>
            <description><![CDATA[<p>&lt;목차&gt;
(실습 1 : 게시판 만들기)</p>
<p>ㅇ 포조
ㅇ @ 어노테이션
ㅇ 흐름
ㅇ 메소드
ㅇ WEB-INF
ㅇ 뷰
ㅇ DAO, DTO, VO
ㅇ lombok (롬복)</p>
<br/>
<br/>

<hr>
<br/>

<p>(실습1 : 게시판 만들기)</p>
<ul>
<li>실습1은 서비스 레이어 없이</li>
<li>샘플들은 지우자 (홈컨트롤러)</li>
</ul>
<br/>

<h3 id="ㅇ-포조">ㅇ 포조</h3>
<ul>
<li>일단 클라이언트가 요청이 오면 그 요청을 받는 알바생부터 만들자 =&gt; 포조!</li>
<li>컨트롤러라고 해서 무조건 서블릿 생각하면 안 돼. =&gt; 자바 일반 클래스</li>
<li>이름 : 게시판이니까 board 포조니까 Controller =&gt; boardController</li>
</ul>
<p>cf. 스프링 프레임워크 나오기 전에는 스트럿츠라는 프레임워크를 많이 썼었나봐
프레임워크의 춘추전국시대 있었어. 개발 할 때마다 프레임워크 바꾸기 엄청 힘들었어
프레임워크의 겨울이 있었어
이걸 다 통합해서 프레임웍을 만든게 스프링이라고 이름 지은거야 그래서 봄!!
프레임워크가 통합이 안돼서 개발자들이 너무 힘들어 했어
스트럿츠에서는 컨트롤러 말고 액션을 많이 썼어. 스프링으로 넘어오면서 컨트롤러를 많이 써</p>
<br/>

<h3 id="ㅇ-어노테이션-기호">ㅇ @(어노테이션) 기호</h3>
<ul>
<li>스프링은 내부적으로 일을 하니까, 이 클래스는 이런 용도입니다, 저 클래스는 저런 용도입니다. 표시를 해줘야 해 =&gt; @ 사용</li>
<li>@ 기호가 붙어있으면 파이선에서 전처리같은 거야</li>
<li>포조는 @Controller</li>
<li>요청을 받는 건 @RequestMapping<ul>
<li>요청이 왔을 때 처리할 메소드를 매핑</li>
<li>핸들러 매핑이 해줘</li>
</ul>
</li>
</ul>
<br/>
<br/>

<h3 id="ㅇ-흐름">ㅇ 흐름</h3>
<p><img src="https://velog.velcdn.com/images/data_sy/post/83251978-2b2e-48d9-8a87-26afba72f456/image.png" alt="">
① 브라우저에 http:/120.0.0.1:8080/web/boardList.do를 치면 boardList.do를 보여주세요~ 라는 요청이 들어와
② @Controller를 보고 포조로 들어와서
③ @RequestMapping 중에 boardList.do를 찾아가
④ 그 아래 이걸 처리할 메서드가 연결될 거야
⑤ 그게 디비랑 연동해가지고 게시판 리스트를 가지고 온 다음에
⑥ 객체 바인딩을 하고 
⑦ JSP한테 포워딩 해서
⑧ JSP가 게시판 리스트를 만들어서 뿌려줘</p>
<ul>
<li>스프링은 안에 연결하는 연결 고리들을 이해하는 게 중요<ul>
<li>이미 만들어진거라 코드를 짤 일이 없어. 연결만 시켜주면 돼</li>
</ul>
</li>
</ul>
<br/>
<br/>

<h3 id="ㅇ-메소드">ㅇ 메소드</h3>
<ul>
<li>메소드 이름은 URL이름과 같이</li>
<li>리턴은 보낼 JSP이름
<img src="https://velog.velcdn.com/images/data_sy/post/78f12ea3-1d30-4b6d-b072-d7c5363f8a69/image.png" alt=""></li>
</ul>
<br/>
<br/>

<hr>
<br/>
<br/>


<h3 id="ㅇ-web-inf">ㅇ WEB-INF</h3>
<ul>
<li>src/main/webapp/WEB-INF/views 안에 jsp파일 만들기</li>
<li>WEB-INF라는 단계가 하나 더 추가 된 이유<ul>
<li>클라이언트의 모든 요청을 C가 처리할 수 있게</li>
<li>클라이언트가 View에 접근하지 못하게 하기 위해</li>
<li>WEB-INF는 톰캣의 보안 디렉토리라서 브라우저 상에 나오지 않아 =&gt; 접근 불가능</li>
</ul>
</li>
<li>이제 스프링에서 바로 JSP 실행할 수 없어. 스프링은 MVC를 철저히 지키도록 함</li>
</ul>
<br/>
<br/>


<h3 id="ㅇ-뷰">ㅇ 뷰</h3>
<ul>
<li>부트스트랩 템플릿 이용하자 <a href="https://www.w3schools.com/">https://www.w3schools.com/</a></li>
<li>부트스트랩, 제이쿼리, 자바스크립트 http 링크는 필수 !!</li>
</ul>
<br/>
<br/>

<hr>
<br/>
<br/>

<h3 id="ㅇ-dao-dto-vo">ㅇ DAO, DTO, VO</h3>
<ul>
<li>DAO(Data Access Object)<ul>
<li>데이터베이스의 data에 접근하기 위한 객체입</li>
<li>DB접근 로직과 비지니스 로직 분리</li>
</ul>
</li>
<li>DTO(Data Transfer Object)<ul>
<li>계층 간 데이터 교환을 위한 객체</li>
<li>로직 없이 getter &amp; setter 만 가진 클래스</li>
</ul>
</li>
<li>VO(Value Object)<ul>
<li>값 오브젝트</li>
<li>read-Only (사용하는 도중에 변경 불가능. 오직 읽기만 가능)</li>
<li>DTO와 유사하지만 DTO는 setter를 가지고 있어 값이 변할 수 있음</li>
</ul>
</li>
<li>클라이언트가 보낸 데이터 -&gt; DTO(혹은 VO)에 담아서 이동, 처리 -&gt; DAO에서 DB에 보냄</li>
</ul>
<br/>

<h3 id="ㅇ-lombok-롬복">ㅇ lombok (롬복)</h3>
<ul>
<li>게터세터 메소드 자동으로 만들어주는 api</li>
<li><a href="https://projectlombok.org/">https://projectlombok.org/</a></li>
<li>스프링에서 롬복은 필수적</li>
<li>다운받은 뒤 설치(이클립스와 롬복을 연결)도 해야 해</li>
<li>이클립스에 api 디펜던시도 해야 해</li>
<li>게터세터 어노테이션 : @Data</li>
<li>생성자 어노테이션 : @AllArgsConstructor, @NoArgsConstructor, @RequiredArgsConstructor</li>
<li>널이 아니다 : @NonNull</li>
<li>예) 게시판 데이터 BoardVO에 적용</li>
</ul>
<br/>
<br/>

<p><img src="https://velog.velcdn.com/images/data_sy/post/c46a742a-6723-478a-8564-bddb4dcb5498/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Spring] 3 Tier Architecture]]></title>
            <link>https://velog.io/@data_sy/8%EC%9B%94-17%EC%9D%BC-%ED%99%94%EC%9A%94%EC%9D%BC-8</link>
            <guid>https://velog.io/@data_sy/8%EC%9B%94-17%EC%9D%BC-%ED%99%94%EC%9A%94%EC%9D%BC-8</guid>
            <pubDate>Tue, 17 Aug 2021 05:00:43 GMT</pubDate>
            <description><![CDATA[<p>&lt;목차&gt;</p>
<p>ㅇ 3 Tier Architecture (3계층 구조)
ㅇ 환경 설정
ㅇ API 검색 사이트
ㅇ 단계 요약</p>
<br/>

<hr>
<br/>


<h3 id="ㅇ-3-tier-architecture-3계층-구조">ㅇ 3 Tier Architecture (3계층 구조)</h3>
<ul>
<li><p>Presentation Layer (Web Layer)</p>
<ul>
<li>클라이언트가 요청이 오면 응답하는 계층</li>
<li>HTML, JSP, POJO</li>
<li>데이터를 표현</li>
</ul>
</li>
<li><p>Persistence Layer</p>
<ul>
<li>Model(Repository)</li>
<li>데이터를 읽고 저장</li>
<li>퍼시스턴스(영속성)라는 단어 나오면 DB와 관련된 로직이라 보면 돼</li>
</ul>
</li>
<li><p>위의 두 레이어를 딱 붙이면 힘들어져
그래서 그 사이에 비즈니스 레이어를 집어 넣었어</p>
</li>
<li><p>Business Layer(Service Layer)</p>
<ul>
<li>이 레이어를 넣는 게 어려워</li>
<li>이 레이어가 꼭 필요한가 싶을 텐데
대형, 프로젝트 규모가 크면 비즈니스 레이어가 들어가게 되어 있어
<img src="https://velog.velcdn.com/images/data_sy/post/2297bc32-e2b6-4c01-be46-f4feb94569c7/image.png" alt=""></li>
</ul>
</li>
<li><p>스프링은 이렇게 3티어 기반으로 틀이 짜여져 있어</p>
<ul>
<li>1차 플젝 때는 만들다보면 서로 섞이고 했을 거야.</li>
<li>근데 스프링은 믹스 x. 룰이 정해져 있기 때문에
<img src="https://velog.velcdn.com/images/data_sy/post/5c8dd307-4e38-43b7-9e4b-7b73d28f72ba/image.png" alt=""></li>
</ul>
</li>
</ul>
<br/>
<br/>

<hr>
<br/>


<p>cf. 우리는 모든 코드를 다 알 필요 없어. 그렇게 할 일도, 할 수도 없어
구글링을 잘 해서 내껄로 만드는 게 개발자야
안 해본 것은 구글링 -&gt; 오류나 -&gt; 물어봐 -&gt; 다시 복붙해서 -&gt; 잘 연결만 하면 해결!</p>
<br/>


<hr>
<br/>
<br/>

<p>이제 실습 시작!</p>
<h3 id="ㅇ-환경-설정">ㅇ 환경 설정</h3>
<br/>

<p>ㅇ maven(메이븐)</p>
<ul>
<li>스프링 프로젝트를 관리하는 툴</li>
<li>api관리, 버전관리, 패키지압축, 배포 등등 아주 포괄적인 관리</li>
<li>프로젝트 아이콘 : s는 spring, m은 maven을 의미 (그만큼 스프링에서 중요!!)
<img src="https://velog.velcdn.com/images/data_sy/post/8c3911cf-dd1b-4d8a-ad3f-2647e90e6d33/image.png" alt=""></li>
<li><strong>pom.xml이라는 설정 파일</strong> 이용해서 라이브러리를 관리
<img src="https://velog.velcdn.com/images/data_sy/post/3052b8f3-f5e8-4665-85bf-275c94257447/image.png" alt=""></li>
<li>지금 스프링 버전은 3.1.1 (스프링은 5.x까지 나왔고, 전자정부는 보통 4.x 사용)</li>
<li>숫자를 바꾸면 자동으로 업데이트가 돼
확인은 Maven Dependency에서 할 수 있어</li>
</ul>
<br/>

<p>ㅇ Maven Dependency</p>
<ul>
<li>현재 다운로드 된 API들</li>
<li>pom.xml에 설정이 되어 있어서 다운로드 됐던 거야
<img src="https://velog.velcdn.com/images/data_sy/post/95471a94-ad7a-46ab-8bc2-dbd17d37c6dc/image.png" alt=""></li>
</ul>
<br/>

<p>ㅇ pom.xml의 properties</p>
<ul>
<li>스프링 버전 바꾸기 : 숫자만 바꾸면 자동으로 업데이트 된다.</li>
<li>4.3.14 숫자 바꾸고 저장하니까 5초 뒤에 자동으로 바껴
<img src="https://velog.velcdn.com/images/data_sy/post/5cdf5149-201d-4ad9-bfdf-b521f2e91729/image.png" alt=""><img src="https://velog.velcdn.com/images/data_sy/post/829caa29-5be2-46a1-9329-31be98925ab5/image.png" alt=""></li>
</ul>
<br/>

<p>ㅇ pom.xml의 dependency</p>
<ul>
<li>디펜던시 = 의존하다 = 개발하다가 이 기능 만들기 위해 api가 필요하다.</li>
<li>필요한 api들이 하나 하나 설정되어 있어</li>
<li>레파지토리(메이븐 서버)에서 설정 파일을 보고 다운로드 해주는 거야</li>
<li>디펜던시를 넣고, 빼고 하는 것에 따라 api가 추가되고 없어지고 하는 것
숫자를 바꾸면 버전이 업데이트 되고</li>
<li><strong>스프링은 api관리가 매우 쉽다!!</strong>
그 전에는 jar파일 받아다가 이래저래 연결했어야 했잖아.</li>
</ul>
<br/>

<h3 id="ㅇ-api-검색-사이트">ㅇ API 검색 사이트</h3>
<ul>
<li><a href="https://mvnrepository.com/">https://mvnrepository.com/</a></li>
<li>자바 웹을 하면서 이 사이트를 모른다? 하면 간첩!!!</li>
</ul>
<br/>

<p>ㅇ GSON</p>
<ul>
<li>이제 GSON이라는 api가 필요해</li>
<li>json데이터포맷을 핸들링할 때 사용. 구글에서 만듦</li>
<li>GSON 검색 -&gt; usages 가장 많이 쓰는 버전이 2.8.5 를 클릭하면 디펜던시가 나와
이거 복사해서 붙여넣기 하면 돼
<img src="https://velog.velcdn.com/images/data_sy/post/a5d6e525-660b-43cf-b5dc-76855c217715/image.png" alt=""></li>
<li>위의 주석 : 이 디펜던시를 넣으면 주석에 적힌 레파지토리에서 다운로드 하겠다. 는 의미</li>
<li>디펜던시 복붙하고 저장하면 api 생겨나
<img src="https://velog.velcdn.com/images/data_sy/post/829d1fc9-1ad2-481b-85e3-8ce7914d0b88/image.png" alt=""></li>
</ul>
<br/>

<p>ㅇ 실제 다운로드된 위치는?</p>
<ul>
<li>기본은 여기가 로컬 레파지토리로 설정되어 있어
<img src="https://velog.velcdn.com/images/data_sy/post/35203b2f-ff1f-49b3-a3ad-1af75d923b59/image.png" alt=""><img src="https://velog.velcdn.com/images/data_sy/post/a7de0588-8c9f-4c8f-acf4-d1e24796e5f6/image.png" alt=""></li>
<li>서버저장소는 mv레파지토리고 (아까 그 사이트), 다운로드 되면 로컬 레파지토리(내 컴퓨터)로</li>
</ul>
<br/>
<br/>

<p>ㅇ Java 버전을 1.6에서 1.8로 바꾸기 (8버전이 보편적이라서)</p>
<ul>
<li>147라인 보면 compiler 있어 =&gt; source(152라인), target(153라인)을 1.8로 바꾸자</li>
<li>컴파일러버전은 전체 자바 코드에 영향을 미치기 때문에 숫자만 바꾼다고 바로 버전이 바뀌진 않아 =&gt; 강제로 업데이터 해야 해</li>
<li>프로젝트를 업데이트한다 = pom.xml의 수정사항을 반영한다</li>
<li>스프링 프로젝트 -&gt; 마우스 우클릭 -&gt; 메이븐 -&gt; 업데이트 프로젝트 -&gt; 포스에 체크(강제)
<img src="https://velog.velcdn.com/images/data_sy/post/7c17df0a-66d1-4d8c-9b39-02a46d37579c/image.png" alt=""><img src="https://velog.velcdn.com/images/data_sy/post/b1270bf5-5394-4ad8-960d-8176a5981676/image.png" alt=""></li>
</ul>
<br/>
<br/>

<h3 id="ㅇ-단계-요약">ㅇ 단계 요약</h3>
<p>1 자바 컴파일러 버전을 바꾼다. &amp; 업데이트 프로젝트
2 스프링 프레임워크 버전을 바꾼다
3 나머지 api는 필요할 때 디펜던시를 넣는다
(4 내일 db연동에 필요한 api들 추가해볼거야)</p>
<br/>
<br/>




]]></description>
        </item>
        <item>
            <title><![CDATA[[Spring] 스프링 내부 흐름]]></title>
            <link>https://velog.io/@data_sy/8%EC%9B%94-17%EC%9D%BC-%ED%99%94%EC%9A%94%EC%9D%BC-7</link>
            <guid>https://velog.io/@data_sy/8%EC%9B%94-17%EC%9D%BC-%ED%99%94%EC%9A%94%EC%9D%BC-7</guid>
            <pubDate>Tue, 17 Aug 2021 05:00:37 GMT</pubDate>
            <description><![CDATA[<p>&lt;목차&gt;</p>
<p>ㅇ Handler Mapping
ㅇ ViewResolver (뷰 리졸버)
ㅇ 스프링 웹 MVC
ㅇ 스프링의 핵심 기능들은 내부적으로 다 만들어져 있어
ㅇ 최종 경로
ㅇ 데이터 공유는? Model 모델</p>
<br/>

<hr>
<br/>

<h3 id="ㅇ-handler-mapping">ㅇ Handler Mapping</h3>
<br/>

<ul>
<li>프론트 컨트롤러가 알바생한테 : 포조야 list.do 해줘, insert.do 해줘, delete.do 해줘, update.do해줘 이렇게 요청하겠지<ul>
<li>이런 클라이언트의 요청을 &#39;핸들&#39;이라고 해 (운전사 핸들을 좌/우로 틀면 그대로 가듯)</li>
<li>이 요청도 직접 하는 게 아냐. 중간에 또 다른 사람을 거쳐
<img src="https://images.velog.io/images/data_sy/post/398ffeda-eb47-4e7b-ae71-a6c906ac3231/image.png" alt=""></li>
</ul>
</li>
<li>Handler Mapping : 이런 핸들을 연결시켜주는 클래스
요청을 선택해서 = choose handler해서 알바생한테 연결시켜줘
<img src="https://velog.velcdn.com/images/data_sy/post/ee469431-9e18-41cf-8945-fe18088563d7/image.png" alt=""></li>
<li>핸들러매핑도 파란색이야. 스프링이 제공해 줘</li>
</ul>
<br/>

<p>ㅇ 핸들러 매핑 어디 있나</p>
<ul>
<li>톰캣 서버를 실행하면, 콘솔창에 핸들러매핑 검은 글씨(=이 클래스가 동작한다.)</li>
<li>핸들러매핑은 내부적으로 일하는 클래스
(은행에서 일을 하지만 고객 눈에는 안 보이는 사람들 있듯이)</li>
<li>mapped / : 슬러시라는 요청이 오면
<img src="https://images.velog.io/images/data_sy/post/92f168c1-5223-4053-96e6-da6517ab4257/image.png" alt="">
(쭉 오른쪽으로 이동) 알바생 홈콘트롤러의 홈이라는 메서드를 실행하라 라고 해석이 돼
<img src="https://images.velog.io/images/data_sy/post/00daac58-c49c-46fd-bde1-c30eb06e3e6a/image.png" alt=""></li>
<li>실제 웹 페이지에서 슬러시가 오면 홈이라는 메서드를 처리하게 되어 있어
<img src="https://images.velog.io/images/data_sy/post/665b47bf-31f6-4738-b2d0-1b99d22f651d/image.png" alt=""></li>
<li>톰캣 서버가 시~작!하면 이렇게 이미 스탠바이를 하고 있어
: 슬러시가 오면 홈컨트롤러 클래스의 홈이라는 메소드가 동작이 되어야 한다</li>
<li>그래서 주소 적고 엔터를 빵 하면, 이 /에 의해 home 메소드가 동작이 되는 거야</li>
</ul>
<br/>

<p>ㅇ 핸들러 매핑 실행 과정</p>
<ul>
<li>톰캣 서버 실행 시 스탠바이 중 (<strong>핸들러매핑에 의해</strong>) -&gt;  엔터 빵 하면 home 메소드 실행 -&gt; 메소드 내부의 것들 실행 되고 (로거로 찍기, 날짜 만들기) -&gt; 모델에 값을 담아서 -&gt; home 이라는 jsp 리턴 -&gt; 뷰에 home.jsp로 넘어가서 -&gt; 헬로월드가 동작하는거야
<img src="https://velog.velcdn.com/images/data_sy/post/2c49b849-9a54-4f84-8efb-859e337070c3/image.png" alt=""></li>
<li>포조에서 이걸 연결하는 부분이 메소드 위의 @RequestMapping
누가 오면 어떤 메소드로 갈지 이미 맵핑을 쫙 해둬지고 있어
<img src="https://images.velog.io/images/data_sy/post/c8c0d8bb-a5cd-4731-932a-9f710593537c/image.png" alt=""></li>
<li>우리가 프론트컨트롤러랑 핸들러매핑을 직접 만들지는 않지만, 얘들이 뭔지는 알고 있어야 하는 거야 </li>
</ul>
<br/>

<p>ㅇ 리턴은 어디로? =&gt; 프론트 컨트롤러로
<img src="https://velog.velcdn.com/images/data_sy/post/c5e6fff8-8430-41f1-bee3-bf55f056ca6a/image.png" alt=""></p>
<ul>
<li>return home;</li>
<li>이 문자열 home을 프론트 컨트롤러가 받으면, 프론트컨트롤러는 홈이 뭔지 전혀 몰라</li>
<li>home은 논리적인 이름</li>
<li>접두사(/WEB-INF/views)와 접미사(jsp)를 붙여 물리적인 경로이름으로 바꿔야 해
<img src="https://images.velog.io/images/data_sy/post/513acd3d-bd23-43d9-a93e-8adaa56610e4/image.png" alt="">
Q. return에 그냥 경로를 주면 되는 거 아닌가요?
A. 나중에 views라는 폴더 이름이 수정되면 유지보수 어려워져</li>
<li>그래서 접두사와 접미사를 붙이는 역할을 해 줄 클래스가 하나 더 필요 =&gt; ViewResolver</li>
</ul>
<br/>
<br/>

<hr>
<br/>
<br/>

<h3 id="ㅇ-viewresolver-뷰-리졸버">ㅇ ViewResolver (뷰 리졸버)</h3>
<br/>

<ul>
<li>뷰에 경로를 만들어 줌. 논리적 경로를 물리적 경로로 바꿔 줌</li>
<li>접두사와 접미사를 붙여서 경로를 만든 뒤(⑥) 다시 프론트 컨트롤러에게 줘 (⑦)
<img src="https://images.velog.io/images/data_sy/post/3bc23a4d-cd73-4c31-a761-24a51305f8fc/image.png" alt=""></li>
<li>프런트 컨트롤러 -&gt; 핸들러 매핑 -&gt; 포조 -&gt; 핸들러매핑 -&gt; 프런트 컨트롤러 -&gt; 뷰 리졸버</li>
<li>뷰 리졸버도 스프링이 제공해 줘 (파란색)</li>
</ul>
<p>ㅇ 뷰 리졸버 위치 : <strong>서블릿-컨텍스트.xml</strong></p>
<ul>
<li><p>서블릿-컨텍스트.xml에 들어가면 접두사 prefix와 접미사 suffix 설정되어 있음</p>
</li>
<li><p>이 클래스가 이미 등록이 되어 있어
<img src="https://velog.velcdn.com/images/data_sy/post/c49f307d-de80-4b49-a9f7-ccdb54728112/image.png" alt=""></p>
</li>
<li><p>그래서 소스코드를 수정하는 게 아니라 여기 경로를 바꿔주면 끝나는거야</p>
</li>
</ul>
<br/>
<br/>

<hr>
<br/>
<br/>

<h3 id="ㅇ-스프링의-핵심-기능-3가지는-내부적으로-다-만들어져-있어">ㅇ 스프링의 핵심 기능 3가지는 내부적으로 다 만들어져 있어</h3>
<br/>

<p>ㅇ 프론트 컨트롤러, 핸들러 매핑, 뷰 리졸버</p>
<ul>
<li>겉으로 드러나진 않지만 내부에서 스프링 프레임워크를 동작시키고 있는 핵심 </li>
<li>이 3가지가 스프링 내부에 이미 만들어져 있으니 직접 코딩할 필요 x =&gt; 얼마나 효율적이야</li>
<li>우리는 포조만 만들면 돼</li>
</ul>
<br/>
<br/>

<hr>
<br/>
<br/>

<h3 id="ㅇ-최종-경로">ㅇ 최종 경로</h3>
<p><img src="https://velog.velcdn.com/images/data_sy/post/9c63744e-9f1d-4813-adb5-3359e887d4f6/image.png" alt=""></p>
<ul>
<li>프론트 컨트롤러가 중심<ul>
<li>요청이 들어오면</li>
<li>핸들러 매핑에게 보내서 -&gt; 매핑해 둔 곳으로 가서 -&gt; 포조가 일을 하고 -&gt; 돌려 받아</li>
<li>그걸 뷰 리졸버에게 보내서 접두사 , 접미사 붙인 경로로 돌려 받아</li>
<li>그 경로에 해당하는 뷰로 보내서 JSP한테 포워딩 -&gt; 결과를 돌려 받아서</li>
<li>응답해 줘</li>
</ul>
</li>
</ul>
<br/>
<br/>

<hr>
<br/>
<br/>

<h3 id="ㅇ-데이터-공유는-model-모델">ㅇ 데이터 공유는? Model 모델</h3>
<ul>
<li>기존 Servlet과 JSP<ul>
<li>특정 메모리에다가 값을 셋어트리뷰트로 담고 -&gt; RequestDispacher로 포워딩 후 -&gt; JSP에서 다시 겟어트리뷰트로 꺼내서 뷰를 만들었어</li>
<li>리퀘스트 바인딩으로 값을 계속 공유해야 해</li>
</ul>
</li>
<li>스프링에서는 모델이 그런 역할을 해</li>
<li>스프링에서 모델도 제공해 줘 (파란색)
<img src="https://velog.velcdn.com/images/data_sy/post/a018a742-51ea-483b-ae0f-a87fd705097e/image.png" alt=""></li>
</ul>
<p>=&gt; <strong>그래서 우리는 포조와 JSP뷰단만 만들면 끝</strong></p>
<ul>
<li>샘플코드도 포조와 뷰만 있어 
<img src="https://velog.velcdn.com/images/data_sy/post/5e8ff641-457e-41b3-b87e-9f94d0e6ae6a/image.png" alt=""></li>
<li>DB 연결할 모델 만들면 MVC 끝이야</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Spring]  기본 동작 흐름]]></title>
            <link>https://velog.io/@data_sy/8%EC%9B%94-17%EC%9D%BC-%ED%99%94%EC%9A%94%EC%9D%BC-6</link>
            <guid>https://velog.io/@data_sy/8%EC%9B%94-17%EC%9D%BC-%ED%99%94%EC%9A%94%EC%9D%BC-6</guid>
            <pubDate>Tue, 17 Aug 2021 05:00:32 GMT</pubDate>
            <description><![CDATA[<p>&lt;목차&gt;</p>
<p>ㅇ 컨텍스트 등록
ㅇ FrontController와 POJO
ㅇ web.xml의 DispatcherServlet
ㅇ 기본 동작 흐름</p>
<br/>

<hr>
<br/>

<h3 id="ㅇ-컨텍스트-등록">ㅇ 컨텍스트 등록</h3>
<br/>

<p>ㅇ 컨텍스트 등록 : 웹 서버에 등록하기</p>
<ul>
<li>우리가 만든 이 프로젝트를 톰캣이라는 서버에 등록 해줘야 해
건물이 지어졋으면 등기를 해서 번지를 지어줘야 사람이 살 수 있듯이,
우리 프로젝트를 톰캣 서버가 등록을 해줘야 톰캣 서버가 우리 어플리케이션을 찾아갈 수 있는거야</li>
<li>톰캣 - 마우스우클릭 - 애드 - 우리프로젝트를 등록<img src="https://images.velog.io/images/data_sy/post/6e246cbe-5426-4729-8c7e-461171c280ba/image.png" alt="">
<img src="https://images.velog.io/images/data_sy/post/6ab35fe7-d39b-4421-81e0-248970480d30/image.png" alt=""></li>
</ul>
<p>ㅇ 등록 확인</p>
<ul>
<li>서버 -&gt; 서버.xml -&gt; context 가면 path속성 있어 (152번째 줄)
<img src="https://images.velog.io/images/data_sy/post/f9e7252b-fc80-4b9a-9ac0-fa97a7552b1d/image.png" alt=""></li>
<li>등록을 하게 되면 소스코드에 들어가. 이게 컨텍스트 패스</li>
<li>등록 되어 있어야 우리 프로젝트를 톰캣 서버가 찾아갈 수 있어</li>
<li>컨텍스트 패스 이름으로 요청을 해야 톰캣 서버가 찾아 가는거야</li>
</ul>
<p>ㅇ 결론 </p>
<ul>
<li>클라이언트가 <a href="http://localhost:8081/web">http://localhost:8081/web</a> 을 요청했을 때,
web이라는 이름이 컨택스트 패스에 있어야 톰캣 서버가 찾아갈 수 있어
<img src="https://images.velog.io/images/data_sy/post/7fcaa3d1-daed-4d71-a9e1-1af3b3749a5f/image.png" alt=""></li>
</ul>
<br/>

<p>ㅇ 톰캣 포트번호 바꾸기</p>
<ul>
<li>원래 톰캣 서버의 기본 포트가 8080 인데 오라클이 1521 포트와 8080포트를 쓰고 있어</li>
<li>그래서 8081로 바꾸자
<img src="https://velog.velcdn.com/images/data_sy/post/0cd4a84c-6cd3-4845-b0ca-56afcae08add/image.png" alt=""></li>
</ul>
<br/>

<p>ㅇ 동작 과정</p>
<ul>
<li>톰캣은 기다리고 있어</li>
<li>톰캣 서버한테 이제 헬로 월드 보여줘~ 요청하면
톰캣 서버가 뭔가를 찾아서 우리한테 헬로 월드를 보여줄거야 = 요청에 맞는 응답을 해줄거야</li>
</ul>
<br/>

<p>ㅇ 요청하기</p>
<ul>
<li>클라이언트가 서버의 ip를 요청할 거야<ul>
<li>https:// ip주소 혹은 도메인주소</li>
</ul>
</li>
<li>3가지 방법<ul>
<li>1, 2 : 내 컴퓨터에 직접 요청 =&gt; 127.0.0.1 또는 localhost</li>
<li>3 : ipconfig로 찾은 ip주소
<img src="https://velog.velcdn.com/images/data_sy/post/09c5b7a2-12e1-4c5f-9340-52c78a0f2df7/image.png" alt=""></li>
</ul>
</li>
<li>그 뒤에 톰캣 서버에 요청해야 하니까 :8081</li>
<li>그 뒤에 이름은 web</li>
<li><a href="http://127.0.0.1:8081/web/">http://127.0.0.1:8081/web/</a></li>
<li><a href="http://127.0.0.1:8081/web">http://127.0.0.1:8081/web</a> : web까지만 적으면 기본은 /(루뜨)가 들어가</li>
</ul>
<br/>

<p>cf. 루뜨(/)는 뭐냐 </p>
<ul>
<li><p>리퀘스트매핑의 값에 적힌 /</p>
</li>
<li><p>주소의 슬러시(/)가 요청이 들어와서 String home 메서드가 처리가 되는 거야
<img src="https://images.velog.io/images/data_sy/post/7cafc986-c840-498a-9fae-134cc4893e19/image.png" alt=""></p>
</li>
<li><p>만약 /test가 걸려 있으면 /web/test해야 이 메소드가 처리 되는거야
<img src="https://images.velog.io/images/data_sy/post/74c70564-82bf-4d2e-9ede-849aa417a750/image.png" alt=""></p>
</li>
<li><p><strong>요청이 들어오면 c(컨트롤러)로 갔다가 m(모델)으로 갔다가 v(뷰)로 가는 과정이 프레임워크 안에 숨어 있어</strong></p>
</li>
</ul>
<br/>
<br/>

<hr>
<br/>
<br/>

<h3 id="ㅇ-frontcontroller와-pojo">ㅇ FrontController와 POJO</h3>
<br/>

<p>ㅇ 은행에 비유</p>
<ul>
<li>은행문을 열기 전 불도 켜고, 컴퓨터도 켜 두고 등등 셋팅을 다 해둬야 9시땡 하면 고객이 들어올 수 있는 것 처럼 = 톰캣 서버를 시~작 한다는 것은 클라이언트의 요청이 들어오기 전에 스탠바이 상태를 만들어 둔다는 것 (메모리, 데이터베이스연결 등의 준비 절차) = xml 파일을 읽어들임</li>
<li>고객이 들어옴 = 클라이언트한테 요청이 옴</li>
<li>은행문 딱 열고 우리를 반겨주는 경비원 (어떤 업무를 보러 오셨습니까. 하는 사람) = FrontController<ul>
<li>경비원(프론트컨트롤러)는 요청에 맞는 영역으로 일을 보내면 돼</li>
</ul>
</li>
<li>출입명부, 발열체크 등을 해 줄 알바생 = POJO (Plain Old Java Object)</li>
</ul>
<br/>

<p>ㅇ FrontController</p>
<ul>
<li>클라이언트가 요청을 제일 먼저 받는 사람은 컨트롤러</li>
<li>컨트롤러 중에서도 클라이언트의 모든 요청을 다~ 받는 컨트롤러가 있어 =&gt; FrontController </li>
<li>여기를 통과하지 않고 다른데로 갈 수 없어</li>
<li>서블릿</li>
<li>web.xml의 DispatcherServlet</li>
</ul>
<p>ㅇ POJO</p>
<ul>
<li>구체적인 업무를 프론트컨트롤러가 다 하려면 로드가 길어져</li>
<li>프론트컨트롤러가 해야 할 일을 대신해주는 알바생들을 필요로 해</li>
<li>POJO도 크게 보면 컨트롤러야</li>
<li>HomeController.java</li>
</ul>
<p>ㅇ FrontController와 POJO의 차이</p>
<ul>
<li>프론트컨트롤러는 서블릿으로 만드는데 포조는 그냥 자바로 만들어야 해</li>
<li>프론트컨트롤러는 일을 시키는 애, 실제 일을 하는 애는 포조</li>
<li>프로젝트할 때는 포조를 잘 만들어야 해</li>
</ul>
<p><img src="https://images.velog.io/images/data_sy/post/1e64f132-e49e-43f3-af3b-9c61249d7216/image.png" alt=""></p>
<p>ㅇ 퀴즈 : 우리 프로젝트에서 HomeController는 FrontController일까 POJO일까?</p>
<ul>
<li>.java 파일이므로 POJO야</li>
<li>서블릿 형태면 프론트컨트롤러였겠지?</li>
<li>그러면 FrontController는 어디 있나? =&gt; 스프링은 알아서 제공 해 줘 (어딘가에 만들어져 있어)
=&gt; web.xml의 DispatcherServlet</li>
</ul>
<br/>

<h3 id="ㅇ-webxml의-dispatcherservlet">ㅇ web.xml의 DispatcherServlet</h3>
<ul>
<li>우리 어플리케이션이 톰캣에 등록되어 있으므로 톰캣 서버를 시~작 하면 우리 어플리케이션에서 해야할 일들을 <strong>web.xml부터 처리를 해</strong></li>
<li>src-&gt; main -&gt; webapp -&gt; WEB-INF -&gt; views -&gt; web.xml
<img src="https://images.velog.io/images/data_sy/post/f6082053-871b-4d13-b4d7-efa27b73a0a0/image.png" alt=""></li>
</ul>
<p>ㅇ xml 파일</p>
<ul>
<li>작업지시서 : 프레임워크한테 이렇게 이렇게 일 좀 해주세요~ 하고 설정하는 것</li>
<li>톰캣 서버가 시작되면 이런 xml들을 다 읽어갈 건데 순서가 있어 =&gt;가장 먼저 web.xml</li>
<li>xml파일 4개가 기본으로 있어 (더 추가적으로 만들게 될 거야)
<img src="https://images.velog.io/images/data_sy/post/be8bb8fc-b91d-46b4-a3c5-d1d77edc5f47/image.png" alt=""></li>
</ul>
<p>ㅇ DispatcherServlet</p>
<ul>
<li>web.xml 안에 processes application requests(리퀘스트 요청을 받는 프로세스)로 서블릿이 있어</li>
<li>이름이 디스패쳐서블릿. 이게 프론트 컨트롤러가 돼
<img src="https://images.velog.io/images/data_sy/post/3fa4de3b-f4b8-4975-b9e9-c1fa545d2732/image.png" alt=""></li>
<li>API로 다운로드 되서 프로젝트 안에 있어</li>
<li>스프링은 프론트 컨트롤러가 미리 정해져 있고 우리가 만들 필요가 없어
스프링은 프론트 컨트롤러 이름이 DispatcherServlet
어떤 클래스죠? 하면 &quot;web.xml의 DispatcherServlet에요&quot; 하면 돼</li>
</ul>
<br/>
<br/>

<hr>
<br/>
<br/>

<h3 id="ㅇ-기본-동작-흐름">ㅇ 기본 동작 흐름</h3>
<br/>

<p>스프링에서는 이 구조를 이해하는 게 중요해
<img src="https://velog.velcdn.com/images/data_sy/post/54fc99e5-b6ce-497e-994a-b8b3de5c5f38/image.png" alt=""></p>
<ul>
<li>ⓐ FrontController ⓑ POJO</li>
<li>이 둘 사이에 이걸 핸들링 해주는 핸들러매핑 등등이 있음<ul>
<li>결합도를 낮추고, 응집도 높이는 방법이야</li>
<li>둘 사이에 뭔가가 들어가서 그 연결을 끊어버리는 것</li>
</ul>
</li>
<li>스프링은 이렇게 계속 결합도를 낮추면서 사이를 벌리다 보니 복잡해져
구조는 복잡해지지만 효율적으로 되는거지</li>
<li>provided by Spring Source<ul>
<li>파란색들은 다 스프링 소스에 의해 제공이 되어진다!</li>
</ul>
</li>
<li>FrontController는 스프링이 제공하지만, POJO는 우리가 만들어야 해<ul>
<li>샘플로 제공되는 POJO : HomeController.java</li>
</ul>
</li>
</ul>
<br/>
<br/>

]]></description>
        </item>
        <item>
            <title><![CDATA[[Spring] 스프링 프레임워크를 쓰는 이유]]></title>
            <link>https://velog.io/@data_sy/8%EC%9B%94-17%EC%9D%BC-%ED%99%94%EC%9A%94%EC%9D%BC-5</link>
            <guid>https://velog.io/@data_sy/8%EC%9B%94-17%EC%9D%BC-%ED%99%94%EC%9A%94%EC%9D%BC-5</guid>
            <pubDate>Tue, 17 Aug 2021 05:00:28 GMT</pubDate>
            <description><![CDATA[<p>&lt;목차&gt;</p>
<p>ㅇ 스프링 프레임워크를 쓰는 이유
ㅇ 전자정부 표준 프레임워크
ㅇ 스프링 웹 MVC
ㅇ 기본틀 살펴보기</p>
<br/>

<hr>
<br/>

<h3 id="ㅇ-스프링-프레임워크를-쓰는-이유">ㅇ 스프링 프레임워크를 쓰는 이유</h3>
<br/>

<p>ㅇ JDBC 단점</p>
<ul>
<li>1.유지, 보수 어려워 : 자바소스코드에 SQL쿼리를 믹스하니까</li>
<li>2.개발 속도가 느려. 즉, 생산성이 떨어진다.<ul>
<li>클래스 만들고, 커넥션하고, sql의 인서트, 딜리트 등을 직접 다 코딩해야 하니까</li>
</ul>
</li>
<li>해결 : 프레임워크를 사용해서 생산성을 높이자</li>
</ul>
<br/>

<p>ㅇ MyBatis </p>
<ul>
<li>Database 프레임워크</li>
<li>자바코드와 SQL쿼리를 분리해서 코드를 짜</li>
<li>연결은 mapping해서 사용</li>
<li>유지보수 쉽고, 개발속도 빠르다.</li>
</ul>
<br/>

<p>ㅇ 기존의 MVC 패턴</p>
<ul>
<li>C 컨트롤러 : servlet</li>
<li>V 뷰 : jsp (+ html, css, js(제이쿼리))</li>
<li>M 모델 : 일반 자바 클래스 (dao, dto, 디비와 연동하는 건 모델에서 커버)</li>
</ul>
<br/>

<p>ㅇ 스프링 배우게 되면</p>
<ul>
<li>jsp &amp; servlet 안 써 (기초부분이긴 하지만 현장에서는 쓰이지 않아. 10년 전 기술)</li>
<li>스프링쪽은 취업 문이 많이 열려 있으니까 수업 수강하면서 길을 잃은 친구들은 여기도 생각해 봐</li>
</ul>
<br/>

<p>ㅇ 스프링 다 다루려면 시간 많이 걸려 =&gt; 핵심만 실습으로 고고</p>
<ul>
<li>배우는 방법이 상당이 어려워. 진입하기도 어렵고, 방대한 이론 다 배울 수 없어</li>
<li>쌤이랑 게시판 로직을 스프링 프레임워크로 만들어보면서 실습을 같이 하는 게 가장 빠른 방법</li>
<li>프레임워크는 방법론이므로 이론보다는 실습 위주로</li>
</ul>
<br/>
<br/>

<hr>
<br/>
<br/>

<h3 id="ㅇ-전자정부-표준-프레임워크">ㅇ 전자정부 표준 프레임워크</h3>
<br/>

<p>ㅇ 전자정부 표준 프레임워크</p>
<ul>
<li>기존에 만들어져 있는 이클립스 받아다가 우리나라에 맞게 커스터마이즈 한 것</li>
<li>우리나라에서 필요로 하는 모듈을 플러그인 해서 탑재해 둔 것</li>
</ul>
<br/>

<p>ㅇ 설치</p>
<ul>
<li>다운로드 한 exe 파일 더블클릭해서 설치 (c:\ (c루트)에 설치하기)</li>
<li>c 드라이브 들어가면 eGovFrame-3.10.0 폴더가 새로 생성되면서 설치가 될 거야</li>
<li>여기에 이클립스, JDK, mysql, 톰캣, 안드로이드 개발 sdk 다 들어있어서 환경설정을 별도로 할 필요 없어
<img src="https://images.velog.io/images/data_sy/post/eee42a40-9d69-465c-be9f-3621bf272700/image.png" alt=""></li>
<li>이제는 eGovFrame.edu로 작업할 거야
<img src="https://images.velog.io/images/data_sy/post/7d25a4ce-c954-4c5a-b6a8-8a738409abc2/image.png" alt=""></li>
</ul>
<br/>

<p>ㅇ workspace.edu에 있는 학습을 위한 샘플 프로젝트들 지우기
<img src="https://images.velog.io/images/data_sy/post/0000ab69-c2fd-4f68-ba59-b2573a9ac7f8/image.png" alt=""></p>
<ul>
<li>다른 샘플 파일들은 다 지우자. 서버는 지우면 안돼!!</li>
</ul>
<br/>
<br/>

<hr>
<br/>
<br/>

<h3 id="ㅇ-스프링-웹-mvc">ㅇ 스프링 웹 MVC</h3>
<br/>

<p>ㅇ 스프링 레거시 프로젝트</p>
<ul>
<li>집을 지을 때 집의 큰 골격이 있듯이, 건물에 전체적인 구조가 있듯이 구조를 제공해 줘</li>
<li>스프링 프레임워크는 엄청 광범위 - 우리는 그 중 web MVC를 배워보자.
(스프링 시퀴즈, 스프링 aop , 스프링 di, 스프링 jpa 등)</li>
</ul>
<br/>

<p>ㅇ 스프링 웹 MVC</p>
<ul>
<li>프로젝트 이름 : SpringMVC</li>
<li>템플릿 : Spring MVC Project
<img src="https://images.velog.io/images/data_sy/post/057ccb6c-5626-416f-82dc-fa6650374882/image.png" alt=""></li>
<li>프로젝트 패키지는 3단계로 : 
<img src="https://images.velog.io/images/data_sy/post/05470baf-db36-4067-99b4-699ab72275ae/image.png" alt=""><ul>
<li>.myapp* : 맨 뒤에 *가 붙어 있는 건 세번째 이름이 context path라는 의미</li>
<li>context path : 3레벨(web)이 프로젝트를 접근하는 이름이야.</li>
</ul>
</li>
</ul>
<br/>
<br/>

<hr>
<br/>
<br/>

<h3 id="ㅇ-기본틀-살펴보기">ㅇ 기본틀 살펴보기</h3>
<br/>

<p>ㅇ 프레임워크 방법론</p>
<ul>
<li>디렉토리 구조가 자동으로 만들어짐 (뼈대)
뼈대는 만질 수 없어. 프로그램은 만질 수 없어. 방법론을 이해해야 해</li>
<li><strong>연결 흐름을 머릿속에서 아는 것이 프레임워크를 아는 방법이야</strong></li>
</ul>
<br/>

<p>ㅇ 디렉토리 구조 확인
<img src="https://images.velog.io/images/data_sy/post/156fb9f6-83d6-4dc8-93d5-4a290123c912/image.png" alt=""></p>
<ul>
<li>java Resources -&gt; kr.smhrd.web 패키지에 들어가면 자바 파일 HomeController.java 가 있고</li>
<li>wepapp -&gt; WEB-INF -&gt; views 에 들어가면 home.jsp 파일 있어
(webapp = 이전 프로젝트에서 webcontent폴더 (jsp, html))
<img src="https://images.velog.io/images/data_sy/post/1b8c41aa-2805-4169-aeb6-1f2b03b715a3/image.png" alt=""></li>
</ul>
<hr>
<br/>
<br/>]]></description>
        </item>
        <item>
            <title><![CDATA[프로젝트 산출문서 작성법2]]></title>
            <link>https://velog.io/@data_sy/%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EC%82%B0%EC%B6%9C%EB%AC%B8%EC%84%9C-%EC%9E%91%EC%84%B1%EB%B2%952</link>
            <guid>https://velog.io/@data_sy/%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EC%82%B0%EC%B6%9C%EB%AC%B8%EC%84%9C-%EC%9E%91%EC%84%B1%EB%B2%952</guid>
            <pubDate>Tue, 13 Jul 2021 16:55:52 GMT</pubDate>
            <description><![CDATA[<h3 id="ㅇ-분석">ㅇ 분석</h3>
<p>ㅇ 요구사항 정의서
서비스와 기능을 자세히 적은 것
<img src="https://images.velog.io/images/data_sy/post/e54fedef-3eea-4108-8a18-56c9b06120e3/image.png" alt=""></p>
<p>ㅇ유스케이스 다이어그램
<img src="https://images.velog.io/images/data_sy/post/7d60a33f-57b8-42b0-aa85-5f30a08f5ba5/image.png" alt="">
이 프로그램을 누가 사용할 건지 결정해야 해
사용자가 누구냐에 따라 제공되는 서비스가 달라지니까
<img src="https://images.velog.io/images/data_sy/post/76fa24cb-2ed6-4df9-9a3a-7f611f69fd15/image.png" alt="">
지금 샘플은 통역앱 명소추천서비스</p>
<p>회원 가입이 있으면 사용자와 회사를 연결하는 구조가 나올 수도 있어
<img src="https://images.velog.io/images/data_sy/post/1db0a86a-60b7-449e-ab36-19d8184481c7/image.png" alt=""></p>
<p>ㅇ유스케이스명세
다이어그램을 텍스트로 표현
아이디는 중복되지 않게 결정
요구사항 : 서비스 제공에 필요한 세부 기능들
<strong>선행조건은 그냥 n/a로 해버려</strong>
관련 액터는 사용자인지 카페 주인인지 이런 거
이벤트 흐름 : 어떤 식으로 요청이 들어오고 내부에서 처리가 되서 사용자에게 돌려주는지
<img src="https://images.velog.io/images/data_sy/post/ad98d2d7-6638-4e61-9f0a-6f9186ed7319/image.png" alt="">
종료 조건 : 회원가입이면 회원가입이 완ㄹ되었습니다~가 종료 조건
<strong>사후조건, 기타 요구사항은 - 없음</strong>
다이어그램에 나타나있는 모든 서비스를 대상으로 명세서를 작성하면 돼</p>
<p>ㅇ 기능과 비기능
기능 : 서비스 제공에 필요한 세부 단위 프로그램
비기능 : 성능과 관련된 요소</p>
<p>ㅇ 기능 요구사항
가운데 줄 그어진 건 삭제 느낌
설계 때는 필요하다고 생각했는데 개발 과정에서 필요없어진 부분
설계 문서는 변경에 대한 이력관리가 필요하기 때문에 실제로 삭제하는 게 아니라 삭제한다고 표현
실제 보고서 제출할 때는 삭제해서 제출하긴 해야 해</p>
<p>ㅇ 비기능 요구사항
우리가 할 수 있는 부분이 아니야
현업에서도 외부 기관에 인증. 성능 테스트 해주는 
하드웨어적이라서 <strong>작성 안하는 쪽으로 생각하면 돼</strong>
iot - 센서의 활용률, 수집률
빅데이터 인공지능 - 우리가 만든 분석 모델의 적중률</p>
<hr>
<h3 id="ㅇ-설계">ㅇ 설계</h3>
<p>지금 있는 파일들 + 시스템 구조에 대한 설계도 해야 해
근데 시스템 구조는 하드웨어나 네트워크에 대한 내용들이 들어가야 해서 현재 할 수 없는 부분이라서 뺌</p>
<p>ㅇ 화면설계서
사용자 ui 설계
이거 설계하기 엄청 어려울 거야 
그러니까 이 부분은
<strong>실제로 개발한 것을 역으로 부어주는 형태로 진행해도 좋을 듯</strong>
물론 개발 하기 전에 사전에 인터페이스 만들 수 있다면 정말 좋겠지! 할 수 있으면 하면 좋아~
그게 어려운 팀들은 <strong>화면 설계에 관해서만 동시진행</strong> </p>
<p>ㅇ 데이터베이스 요구사항 분석서
데이터 수집 저장을 위해
세부적인 부분은 디비설계 수업시간에</p>
<p>1요구사항정의서
어떤 db를 만들기 위해서 사용자의 니즈를 분석하는 단계
향후 테이블이 되어야 할 컬럼, 컬럼들의 관계
<img src="https://images.velog.io/images/data_sy/post/0ff0e444-f033-4f8e-b88f-85c8b574423b/image.png" alt="">
2 객체 정의서
이걸 크리에이트 테이블로 구현하면 돼
<img src="https://images.velog.io/images/data_sy/post/d0e120f1-de52-4c3e-a87b-8d7ba2dd5006/image.png" alt="">
3 e-r 다이어그램
테이블간의 관계를 다이어그램으로
<img src="https://images.velog.io/images/data_sy/post/0d380e91-6cfd-437d-be2a-70ed6882fb4e/image.png" alt=""></p>
<p>ㅇ 테이블 명세서
요구사항 정의서에서 나온 것들을 적으면 돼
<img src="https://images.velog.io/images/data_sy/post/230dfc8c-2a15-4b5e-9721-dab405bdbf1b/image.png" alt="">
<strong>인덱스는 생략</strong>
마지막 큰 칸에는 실제 명령어
<img src="https://images.velog.io/images/data_sy/post/6293041b-f144-4992-bd5b-cbf056bd38b9/image.png" alt=""></p>
<hr>
<h3 id="ㅇ-구현">ㅇ 구현</h3>
<p>구현은 따로 산출문서 없이 그냥 개발하면 돼</p>
<h1 id="42분-40초까지-봄">42분 40초까지 봄</h1>
]]></description>
        </item>
        <item>
            <title><![CDATA[프로젝트 산출문서 작성법]]></title>
            <link>https://velog.io/@data_sy/%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EC%82%B0%EC%B6%9C%EB%AC%B8%EC%84%9C-%EC%9E%91%EC%84%B1%EB%B2%95</link>
            <guid>https://velog.io/@data_sy/%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EC%82%B0%EC%B6%9C%EB%AC%B8%EC%84%9C-%EC%9E%91%EC%84%B1%EB%B2%95</guid>
            <pubDate>Sun, 04 Jul 2021 15:04:13 GMT</pubDate>
            <description><![CDATA[<p>ㅇ 산출문서 왜 필요하냐</p>
<ul>
<li>설계 도면의 역할 : 프로젝트 일정, 방법 등 </li>
<li>결과물 구현을 검증하는 잣대</li>
</ul>
<br/>
<br/>

<p>ㅇ 실제 현업에서 기본적으로 프로젝트를 진행하는 단계야</p>
<ul>
<li>계획</li>
<li>분석 : 사용자들의 니즈를 파악하고 그를 위해 어떤 서비스를 제공해야 하는지 분석</li>
<li>설계 : 기반을 마련, 데이터베이스 설계, 인터페이스 ui 등</li>
<li>구현</li>
<li>시험 : 우리가 요구하는대로 잘 구현 됐는지</li>
<li>관리</li>
</ul>
<br/>
<br/>

<p>ㅇ 계획</p>
<ul>
<li>프로젝트 방향성 : 기술, 현황 등을 미리 필터링하면 주제 뽑을 때 훨씬 더 도움 받을 수 있을거야. 관련된 주제들 나눠 놓으면 하나 정할 때 도움 돼</li>
<li>주제 : 기능 + 서비스<ul>
<li>어떤 기술을 기반으로 어떤 서비스를 제공하겠다. 가 어필 되어야 해</li>
<li>주제만 보고도 뭘 하려는지 정확히 알 수 있도록</li>
</ul>
</li>
<li>제안 배경 및 필요성<ul>
<li>현 시장 상황은 이렇더라</li>
<li>상황 분석을 해봤더니 어떠한 서비스가 필요하고, 그 서비스를 제공하는 현재 상황에 이러이러한 문제점이 보여지더라</li>
<li>문제가 있다면 개선을 해야겠지 -&gt; 서비스 &amp; 기능</li>
<li>즉, 왜 이 프로젝트를 해야하는지 이유를 적는거야!</li>
</ul>
</li>
<li>유사 제품 현황 및 비교<ul>
<li>유사 제품과 비교분석</li>
<li>a사 b사 우리제품 표로 만들면 좋아</li>
<li>어떤 서비스 제공하는지, 어떤 기능이 필요한지, 대상은 누군지, 각각의 장점과 단점</li>
<li><img src="https://images.velog.io/images/data_sy/post/0b7b5bbe-29b7-4687-b972-41b98c409820/image.png" alt=""></li>
<li>어떤 기능은 가져다 쓰고, 없는 기술은 집어 넣어야 겠다 분석 할 수 있어</li>
<li>우리 제품이 다른 제품보다 뛰어나다는 우수성, 독창성</li>
</ul>
</li>
<li>제안 내용 - 개발 목표<ul>
<li>정성적으로 쓰기</li>
<li>시장이 이렇고 문제가 있고 개선하기 위해 우리 프로젝트가 필요하다</li>
<li>예) <img src="https://images.velog.io/images/data_sy/post/8086639b-06ce-4cc7-920d-00d4fb4686a0/image.png" alt=""></li>
<li>누구를 대상으로 / 어떤 서비스를 제공함으로써 / 어떤 결과를 얻어내겠다</li>
</ul>
</li>
<li>제안 내용 - 개발 내용<ul>
<li>정량적으로 쓰기</li>
<li>목표에서 언급한 서비스를 구현하기 위한 기능들</li>
<li>분석 모듈 / 센서 모듈을 개발하게 된다면 이런 것도 적어주기</li>
<li>인터페이스</li>
<li><img src="https://images.velog.io/images/data_sy/post/a9ff9ed9-d9ca-4113-818a-f3b123d9c31a/image.png" alt=""></li>
</ul>
</li>
<li>수행 방법<ul>
<li>데이터를 수집하는 방법 : 예) 크롤링, 공공data, 민간data</li>
<li>데이터 출처, 데이터 수집 건수 . 이런 것들이 데이터 신뢰성</li>
<li>추진 전략 : 계획-분석-설계-구현-시험-관리 이대로 표를 만들어
<img src="https://images.velog.io/images/data_sy/post/52e01028-d939-433b-ae38-59a2ad8c8376/image.png" alt=""><ul>
<li>각 영역마다 수행 내용, 수행 일정, 담당자</li>
<li>각 단계별로 나오는 산출 문서들</li>
<li>동봉된 wbs 문서 : 날마다 진척률 관리를 해
<img src="https://images.velog.io/images/data_sy/post/f034a9fc-bacc-4924-be8d-0ef23733a315/image.png" alt=""></li>
<li>추진 전략에는 대분류 항목들에 대한 내용 - 담당자 - 산출문서를 간단히 요약해서 적으면 돼</li>
</ul>
</li>
<li>팀원 및 역할</li>
<li>제안 내용 안에서 수치로 적어두었던 개발 내용을 여기서 역할 분담 </li>
<li>누구는 어떤 서비스 어떤 기능을 하겠다.</li>
<li>여기에 ppt작성, 문서 작성 이런 건 안 넣었으면 좋겠어.</li>
<li>넣을거면 설계 문서 작성 이런 식으로 써야 어필되는 거지 그냥 문서작성은 팀원이 개발 업무에 참여를 안 하는 것 처럼 보여버려
<img src="https://images.velog.io/images/data_sy/post/63ba104e-603b-41e6-a762-a7b69f2dc030/image.png" alt=""></li>
</ul>
</li>
<li>기대효과 및 활용방안<ul>
<li>기대효과 : 아까 개선하겠다 한 거</li>
<li>활용방안 : a분야에 적용 시켰는데 이 기능들이 다른 분야에도 적용시킬 수 있을 때</li>
</ul>
</li>
</ul>
<h3 id="우선-계획단계까지만-들음---22분-30초">우선 계획단계까지만 들음 - 22분 30초</h3>
]]></description>
        </item>
        <item>
            <title><![CDATA[플로깅 관련 자료들]]></title>
            <link>https://velog.io/@data_sy/%ED%94%8C%EB%A1%9C%EA%B9%85-%EA%B4%80%EB%A0%A8-%EC%9E%90%EB%A3%8C%EB%93%A4</link>
            <guid>https://velog.io/@data_sy/%ED%94%8C%EB%A1%9C%EA%B9%85-%EA%B4%80%EB%A0%A8-%EC%9E%90%EB%A3%8C%EB%93%A4</guid>
            <pubDate>Sun, 04 Jul 2021 14:13:31 GMT</pubDate>
            <description><![CDATA[<p>ㅇ 1박 2일 21년 5월 9일 방송
<a href="https://tv.naver.com/v/20102808">https://tv.naver.com/v/20102808</a>
<a href="https://tv.naver.com/v/20102971">https://tv.naver.com/v/20102971</a></p>
<br/>
<br/>
<br/>

<p>ㅇ 스브스 뉴스
<a href="https://www.youtube.com/watch?v=s3CH6gNqFGk">https://www.youtube.com/watch?v=s3CH6gNqFGk</a></p>
<br/>
<br/>
<br/>

<p>ㅇ 환경부 유투브
<a href="https://www.youtube.com/watch?v=5WsOJYkG6cA">https://www.youtube.com/watch?v=5WsOJYkG6cA</a></p>
<br/>
<br/>
<br/>

<p>ㅇ 다양한 캠페인
ㅇ 볼보 : 헤이 플로깅 이벤트
<a href="https://www.asiae.co.kr/article/2021060110173742765">https://www.asiae.co.kr/article/2021060110173742765</a>
<a href="https://www.youtube.com/watch?v=ImIXw9L1T2g">https://www.youtube.com/watch?v=ImIXw9L1T2g</a></p>
<p>ㅇ 그린피스 : 어스 앤 런 이벤트 21년 6월
<a href="https://www.greenpeace.org/korea/update/17631/blog-plastic-earth-and-run-plogging/">https://www.greenpeace.org/korea/update/17631/blog-plastic-earth-and-run-plogging/</a></p>
<p>ㅇ 투썸 플레이스
<a href="https://www.youtube.com/watch?v=hWGRJ9QUbsQ">https://www.youtube.com/watch?v=hWGRJ9QUbsQ</a></p>
<p>ㅇ 이시영
<a href="https://www.youtube.com/watch?v=LmtSAZhzwKk">https://www.youtube.com/watch?v=LmtSAZhzwKk</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[6월 30일 수요일 8 프로젝트 일정]]></title>
            <link>https://velog.io/@data_sy/6%EC%9B%94-30%EC%9D%BC-%EC%88%98%EC%9A%94%EC%9D%BC-8</link>
            <guid>https://velog.io/@data_sy/6%EC%9B%94-30%EC%9D%BC-%EC%88%98%EC%9A%94%EC%9D%BC-8</guid>
            <pubDate>Tue, 29 Jun 2021 23:44:56 GMT</pubDate>
            <description><![CDATA[<ul>
<li>멘토링 전에 해당 결과물이 있어야 피드백 받을 수 있다.</li>
<li><strong>일정 안에 내라는 자료는 꼭 내자!!</strong></li>
<li>아이디어는 최소 3~4개 정도 준비</li>
<li>강의장 저녁 7시까지 오픈</li>
</ul>
<p><img src="https://velog.velcdn.com/images/data_sy/post/8866b7e8-2029-479f-8f5f-dff0c0158b24/image.png" alt=""></p>
<ul>
<li><p>6월 30일 : 프로젝트 특강 (옆 반과 합동 진행)
앞으로 프로젝트 할 때 아이디어 도출 해야 해
직접 만들어야 하는데 어떻게 만들어야 하고 어떠한 주제를 도출해야 하는지</p>
</li>
<li><p>7월 7일 멘토링 진행
프로젝트 전문 지도하시는 분 들어와서 아이디어 주제 나온 걸 봐 드릴 거야
★ 준비 (7/6까지) : 아이디어 브레인스토밍 ★
프로젝트 최소 3~4개 준비 =&gt; 실현 가능성 정도, 보완 정도 체크</p>
</li>
<li><p>7월 8일 ~ 9일 : UI/UX 디자인 강의
카카오 오븐으로 간단히 웹페이지 만들 수 있는 방법
★ 준비 : 기획한 화면 ★</p>
</li>
<li><p>7월 12일 : 기획 발표
내외부 심사위원 초청 기획 발표
★ 준비 : 기획 문서, 피피티 ★
★ 7월 11일 거의 확정된다고 생각하면 돼!!!!
이 날 거의 모든 게 결정. 픽스 된다고 생각하면 돼</p>
</li>
<li><p>7월 15일 : 깃 강의
깃 : 협업 도구. 수업 2시간
★ 준비 (7/14) : 깃헙 계정 만들기 ★</p>
</li>
<li><p>7월 20일까지 
★ 여러 산출물들 제출 - 예) 요구사항계획서</p>
</li>
<li><p>7월 21~22일 : DB 멘토링
★ 준비 : 데이터베이스 설계서 ★</p>
</li>
<li><p>7월 23일 : uiux 점검</p>
</li>
<li><p>7/26 ~ 8/4 : 프로젝트 진행
아직 빅데이터 안 배웠으니 웹사이트 만드는 것 위주로</p>
</li>
</ul>
]]></description>
        </item>
    </channel>
</rss>