<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>feel_so_fine.log</title>
        <link>https://velog.io/</link>
        <description></description>
        <lastBuildDate>Sun, 16 Nov 2025 15:44:17 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>feel_so_fine.log</title>
            <url>https://velog.velcdn.com/images/feel_so_fine/profile/96ac4f3e-7dd9-43d4-85f2-487660d180e3/image.png</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. feel_so_fine.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/feel_so_fine" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[LG U+ Why Not SW CAMP 7기 27주차 회고]]></title>
            <link>https://velog.io/@feel_so_fine/LG-U-Why-Not-SW-CAMP-7%EA%B8%B0-27%EC%A3%BC%EC%B0%A8-%ED%9A%8C%EA%B3%A0</link>
            <guid>https://velog.io/@feel_so_fine/LG-U-Why-Not-SW-CAMP-7%EA%B8%B0-27%EC%A3%BC%EC%B0%A8-%ED%9A%8C%EA%B3%A0</guid>
            <pubDate>Sun, 16 Nov 2025 15:44:17 GMT</pubDate>
            <description><![CDATA[<h1 id="스프린트5">스프린트5</h1>
<p>끝이 보입니다..</p>
<p>이번 스프린트에서는 이제 기능을 마무리하고 배포에 들어가야했습니다.
도커파일 만들고 이미지를 빌드해서 ecr에 푸시하고 그걸 ec2로 풀해와 배포를 하는 흐름을 선택하였습니다.</p>
<p>백과 프론트 각각의 ecr과 ec2로 구성하였습니다.</p>
<h2 id="기능-개발-마무리">기능 개발 마무리</h2>
<p>뱃지와 알림 쿡테스트까지 기능에 대해서는 개발이 마무리 외었습니다. 하... 진짜 하얗게 불태웠다...</p>
<h3 id="배포의-시작">배포의 시작</h3>
<p>두려움의 결정체 배포가 왔습니다.</p>
<p>저는 도커 이미지 빌드와 ecr로의 푸시를 맡았습니다.
다른 팀원분께서 ec2로 풀과 백 프론트 연결, 배포를 맡으셨구요!</p>
<p>그동안 다른 팀원분들은 산출물 문서 정리를 맡아주셨습니다.
역할분배 아주 좋아요</p>
<p>자 그래서 이미지를 ecr로 그리고 ec2로 푸시까지는 꽤나 순조롭게 되었습니다.
그런데 이제 문제가... 배포에서 생겼습니다..</p>
<p>ec2 IP연결도, 라우터도, vite_api_url도 무언가 프록시가 잘못되었던 모양이에요ㅜ
백엔드 호출이 안되는 문제가 계속해서 발생했습니다.</p>
<p>결국 시간안에 해결이 안돼서 귀가 후에 야근으로 해결이 되었다는 슬픈 소식입니다...
어쨋든 됐자나요!?!??!</p>
<p>그리고 다음날 !</p>
<h4 id="깃-액션">깃 액션</h4>
<p>바로 자동화를 도전해보기로 하였습니다.
깃에 소스코드가 수정이 되어서 푸시를 하면 해당 레포지토리(백이나 프론트)의 워크플로를 이용하여 이미지 빌드와 푸시, 배포까지 한번에 되게 하는 거였습니다!</p>
<p>이것도 우여곡절이 많았지만 잘 해결하여 이제 수정할 사항이 생겨도 수정할때마다 직접 빌드부터 배포까지 사람이 해도 되지 않아 편해졌습니다!</p>
<h3 id="대시보드">대시보드</h3>
<p>명색이 데이터 분석 과정인데 데이터 분석이 너무 안들어간 느낌이 강하여 대시보드를 좀더 구체적으로 구현해보았습니다.</p>
<p>사용자와 비슷한 식습관이나 연령대를 가진 사람들음 어떤 레시피를 선호하는지, 어떤 특징을 가지고 있는지를 보여줄 수 있었습니다.</p>
<p>이렇게 구축을 해보니 추천 알고리즘에 이 결과를 추가한다면 더욱더 고도화된 맞춤형 레시피 추천이 가능할 것으로 예상이 되었습니다.
향후의 발전 가능성에 대해서도 충분한 확신이 생긴 순간이 되었습니다.</p>
<h3 id="스프린트-미팅">스프린트 미팅</h3>
<p>강사님과 스프린트 미팅을 팀별로 가졌습니다.
통합테스트의 느낌으로 진행되었습니당...</p>
<p>약점도 꽤 있었고 아무래도 기획을 중간에 틀었다 보니 짧아진 기획의 부분에 아쉬움이 좀 남긴 했습니다.</p>
<p>그러나 완성도 측면에서는 좋았기 때문에 또 아쉽기만 한 결과는 아니라고 생각이 듭니다.</p>
<p>위에서 말했듯이 대시보드로 얻을 수 있는게 상당히 많았고, 어필할 수 있는 기획적 부분도 꽤 있었습니다.</p>
<p>그리고 프론트를 제가 맡아서 이정도 완성도가 나온것 같다고 해주셧는데.. 팀원분들이 동의 해주셔서 너무나... 너무나 감동이었습니다😭😭</p>
<p>팀원분들도 각자의 역할을 완벽히 다해주셔서 제가 제 할일에 집중할 수 있었던게 아니었나 싶습니다🩷</p>
<h3 id="마지막-멘토링">마지막 멘토링</h3>
<p>이제 마지막 멘토링이고.. 오늘이 지나면 딱 5일이 남습니다.. 이게 정말 끝이 나네요..</p>
<p>자 ! 아무튼 제가 감기몸살이 왔습니다.</p>
<blockquote>
<p>그래도 해야지 어떡해</p>
</blockquote>
<p>멘토링은 발표로 시작해서 ppt 수정, 산출물 점검, ui 점검, 시연연상 구상, 발표 스크립트 수정 등을 하였습니다.</p>
<p>일단 ui를 좀 수정하였습니다. 카테고리들은 아래로 내리고 윗 헤더 부분에는 메인 버튼들을 넣었습니다.</p>
<blockquote>
<p>고생을 또 했지요~</p>
</blockquote>
<p>그리고 추천의 정확도가 좀 이슈가 있었던 터라 프롬프트 수정고 같이 하는 중입니다. </p>
<blockquote>
<p>할 수 있어요</p>
</blockquote>
<p>발표준비는 멘토님과 함께 해서 잘 진행이 되고 있고 차근차근 또 일주일을 잘 살아내면 좋은 결과를 얻을 수 있을 거라 생각합니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[LG U+ Why Not SW CAMP 7기 26주차 회고]]></title>
            <link>https://velog.io/@feel_so_fine/LG-U-Why-Not-SW-CAMP-7%EA%B8%B0-26%EC%A3%BC%EC%B0%A8-%ED%9A%8C%EA%B3%A0</link>
            <guid>https://velog.io/@feel_so_fine/LG-U-Why-Not-SW-CAMP-7%EA%B8%B0-26%EC%A3%BC%EC%B0%A8-%ED%9A%8C%EA%B3%A0</guid>
            <pubDate>Sun, 16 Nov 2025 15:21:53 GMT</pubDate>
            <description><![CDATA[<h1 id="스프린트4">스프린트4</h1>
<p>스프린트 4에는 일단 기본 기능들을 모두 구현을 하였습니다.
로그인과 로그아웃, 회원 탈퇴, 재료 입력, 레시피 추천 받기와 캘린더에 추가, 캘린더에서 관리, 마이페이지 까지 완료를 하였습니다.</p>
<h3 id="기능의-추가">기능의 추가</h3>
<p>그럼 이렇게까지 개발을 당겨서 열심히 달렸으니 시간이 남지 않습니까?
그래서 기획서를 쓸때 시간 관계상 우선순위에서 밀렸던 기능들을 찾아왔습니다.</p>
<ul>
<li>영양제 추천, 트래킹</li>
<li>뱃지 기능</li>
<li>커뮤니티 기능</li>
</ul>
<p>이렇게 3개입니다.
먼저 영양제 추천은 식단 추천 기획을 할때에 잠시 만들어뒀던 룰기반의 간단한 부가 기능이라 그것을 추가하였구요</p>
<p>뱃지 기능과 커뮤니티 기능은 사용자의 입장에서 우리의 시스템을 계속 사용하게 할 이유를 만들어 주는 그런 기획적인 요소 였습니다.</p>
<p>커뮤니티는 좀 뻔한 느낌이라서 <strong>쿡테스트</strong> 라는 캐글 대회처럼 기능을 넣었습니다.</p>
<p>본인의 레시피를 게시글로 올려서 좋아요 수로 순위를 매겨 리워드를 주는 방식을 생각하였습니다.</p>
<p>또 뱃지 기능은 정해져 있는 미션들을 완료하면 부여되는데요.
레시피 최초 추천이라던가, 대회 첫 참여, 대회 1등, 게시글 몇개 이상등 프로세스를 만들어서 실시간으로 집계하여 부여하게 됩니다!</p>
<p>그리고 그 뱃지는 프로필 뱃지로도 설정하게 하여 다른사람들에게 보여지게도 할 수 있는 상태입니다. 추후에는 그런 뱃지별 미션이나 자랑하기의 느낌도 추가하여 게임처럼 활용하면 어떨까 라는 생각도 해봅니당...</p>
<h3 id="시나리오">시나리오</h3>
<p>시나리오 테스트도 해보았습니다.
단위 테스트였고 결과는 대체로 예상 결과와 같았습니다.</p>
<h3 id="스프린트-4의-회고">스프린트 4의 회고</h3>
<p>기능의 추가로 또 엄청난 스프린트였습니다. 하하</p>
<p>속도도 빠르고 결과도 잘 나옵니다👍</p>
<p>물론 뱃지를 주는 프로세스와 그 집계에 대한 부분이 꽤 어려웠고 우여곡절도 많았는데 함께 이슈를 보고 잡아보면서 잘 해결이 되었습니다.</p>
<p>테이블의 추가도 많았고, api 명세의 추가, 개발의 추가 전부를 또 이겨내봅니다🔥</p>
<p>-&gt; 누가 뭐래도 우리팀이 최고고, 제일 대단합니다</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[LG U+ Why Not SW CAMP 7기 25주차 회고]]></title>
            <link>https://velog.io/@feel_so_fine/LG-U-Why-Not-SW-CAMP-7%EA%B8%B0-25%EC%A3%BC%EC%B0%A8-%ED%9A%8C%EA%B3%A0</link>
            <guid>https://velog.io/@feel_so_fine/LG-U-Why-Not-SW-CAMP-7%EA%B8%B0-25%EC%A3%BC%EC%B0%A8-%ED%9A%8C%EA%B3%A0</guid>
            <pubDate>Sun, 16 Nov 2025 15:09:14 GMT</pubDate>
            <description><![CDATA[<h1 id="스프린트3">스프린트3</h1>
<p>왔습니다아 스프린트3가 왔어요!!</p>
<p>깜짝 놀라십니다... 레전드 스프린트에요...</p>
<h2 id="개발">개발</h2>
<p>먼저 api명세를 써둔 것을 기반으로 개발을 시작하였습니다.</p>
<p>저는 리액트를 사용하여 개발을 하였습니다. 코덱스와 함께하였는데요. 바이브코딩이지만 당연히 수정은 제가 해야하고 오류가 난다면 어디가 문제인지는 알아볼 수 있어야 하기 때문에 책까지 사가면서 리액트 공부를 참 많이 하였습니다.</p>
<p>계속 찾아보고 검토해보면서 어떻게 동작을 하는건지 파악이 되기 시작했고 그게 되면서 속도도 빨라지게 되었습니다.</p>
<p>-&gt; 여러분 하면 됩니다 진짜</p>
<p>팀원 분들도 추천 로직 짜시고 erd계속 수정하고 DB 보시고 데이터 계속 보시면서 바쁘셔서 로그인이나 로그아웃, jwt토큰, 마이페이지, 재료입력, 캘린더 같은 부분을 풀스택 개발자 마냥 백과 프론트를 모두 제가 해보았습니다.</p>
<p>-&gt; 이게 또 백단의 코드를 합쳐서 프론트로 받을 때 잠깐이라도 혼자 해봤다고 도움이 되더라구요</p>
<p>모두들 고생 엄청 하시는데 제가 이렇게라도 탄탄하게 좀 진행을 받치고 있어야 흔들리지 않을 것 같았어요😭</p>
<p>이번 스프린트도 너무 고생 많았다구요ㅠㅠ</p>
<h3 id="개발-멘토링">개발 멘토링</h3>
<p>왜 그렇게 달렸냐구요??</p>
<p>바로 개발 멘토님이 오시는 멘토링이 있었기 때문입니다..
저희가 AWS를 이용하여 배포를 해야하는데 정말 그쪽으로는 거의 아무거또 몰라여 상태였기 때문에 최대한 아키텍쳐와 도커, 빌드, deploy에 대해서 같이 진행을 해야했어요</p>
<p>휴..</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[LG U+ Why Not SW CAMP 7기 24주차 회고]]></title>
            <link>https://velog.io/@feel_so_fine/LG-U-Why-Not-SW-CAMP-7%EA%B8%B0-24%EC%A3%BC%EC%B0%A8-%ED%9A%8C%EA%B3%A0</link>
            <guid>https://velog.io/@feel_so_fine/LG-U-Why-Not-SW-CAMP-7%EA%B8%B0-24%EC%A3%BC%EC%B0%A8-%ED%9A%8C%EA%B3%A0</guid>
            <pubDate>Sun, 16 Nov 2025 14:57:21 GMT</pubDate>
            <description><![CDATA[<h1 id="기획을-바꾸고-그-후">기획을 바꾸고 그 후..</h1>
<p>자! 저희의 기획은 바뀌었습니다.
바로 <strong>사용자 보유 재료 기반의 맞춤형 레시피 추천 시스템</strong>입니다.</p>
<p>... 일주일을 정말 정신없이 달렸는데요...
팀원들께 정말.. 감사한 마음 뿐입니다</p>
<p>먼저 역할 분담부터 착착 진행했습니다.
빠르게 달려보아야 하는 만큼 가장 중요한게 각자의 역할을 하는 거겠죠!</p>
<p>데이터를 많이 만지시고 봐주실 두분과, 백단의 프롬프팅을 해주실분, 그리고 제가 앞단을 맡기로 했습니다.</p>
<h3 id="저도-프론트는-처음이라">저도 프론트는 처음이라...</h3>
<p>사실 저는 팀장을 맡으면서 팀원분들이 하고싶은 걸 최대한 하게 해주고 싶었습니다. 각자 포트폴리오에 중점적으로 넣고 싶을 것도 다를 것이고 해보고 싶은 것도 다 있을텐데, 제가 다 정하거나 밀어붙이는 건 좋지 않겠다고 생각했어요.</p>
<p>그 마음이 전해졌을지는 잘 모르겠지만..</p>
<p>아무튼!
제가 프론트를 맡은 이유도 그거였습니다. 사실 저는 이것저것 다 해보고 싶은 사람이라 맡으면 열심히 잘할 자신있었습니다.</p>
<p>이것도 어쨋든 팀원분들이 믿어주셔서 가능한 일이 아닐까 하구요..</p>
<h2 id="스프린트2">스프린트2</h2>
<p>자 그래서 스프린트 2 다시 시작합니다🔥</p>
<p>멘토링 내용을 다시한전 리뷰하면서 기획의 요구사항 정의부터 기획서까지 쓰고 일단 주요 추천기능을 들고 바로 poc로 넘어가게 되었습니다.</p>
<p>주요기능을 완성시켜두고 부가 기능을 추가하고 붙이는 방향으로 해야 적어도 완성을 할 수 있다고 판단하였습니다.</p>
<p>그래서 앞단의 모양과 테마를 정하고 레시피 데이터를 크롤링하고 전처리를 하고 검색하는 쿼리를 짜고 프롬프팅을 해서 결과가 나오는 것까지 확인을 해보며 poc를 마쳤습니다...</p>
<p>일주일이 정말... 진짜 스프린트였는데요</p>
<p>이게 갓생이지 뭐가 갓생이여</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[LG U+ Why Not SW CAMP 7기 23주차 회고]]></title>
            <link>https://velog.io/@feel_so_fine/LG-U-Why-Not-SW-CAMP-7%EA%B8%B0-2%EC%A3%BC%EC%B0%A8-%ED%9A%8C%EA%B3%A0</link>
            <guid>https://velog.io/@feel_so_fine/LG-U-Why-Not-SW-CAMP-7%EA%B8%B0-2%EC%A3%BC%EC%B0%A8-%ED%9A%8C%EA%B3%A0</guid>
            <pubDate>Sun, 16 Nov 2025 14:44:38 GMT</pubDate>
            <description><![CDATA[<h2 id="스프린트2의-시작">스프린트2의 시작</h2>
<p>추석 연휴가 끝나고 다시 프로젝트로 돌아왔다.
다시 달려야지!!</p>
<h3 id="스프린트2의-목표는-타당성-검증">스프린트2의 목표는 타당성 검증!</h3>
<p>먼저 음식 데이터들을 수집하고 쓸 수 있는 모양으로 전처리를 하였다.
그 쓸 수 있는 모양이라는 것 자체가 매우 추상적이고 어려워서 수작업도 굉장히 많았고, 데이터를 왜 비싼 돈을 주고 사고 파는지, 수집한 데이터를 왜 공개하지 않는 건지, 남의 데이터를 가져다 쓴다는게 얼마나 어려운 일인지를 느끼게 되는 시간이었다....</p>
<ul>
<li>사용자의 목표에 맞는 식단을 추천해주려면 태그라는 컬럼이 중요했다. </li>
</ul>
<p>태그로 그 음식의 특징을 지정해 놓아야 유사도 기반으로 찾아올때 유리하고, 음식 이름으로 찾아오는 그런 불상사를 막을 수가 있다.</p>
<ul>
<li>프롬프팅도 쉬운 건 아니다.
우리가 원하는 결과, 즉 사용자가 보았을때 딱 아! 이게 일주일치 식단이구나! 라고 느끼게 할정도의 결과가 나와야 한다.</li>
</ul>
<h3 id="기획-멘토링">기획 멘토링</h3>
<p>열심히 달려 토요일에는 기획을 담당하시는 멘토님이 오셨다.</p>
<ul>
<li>결론만 이야기 하겠습니다.
예... 기획을 틀었습니다.</li>
</ul>
<p>이유가 뭐냐구요?</p>
<p>사용자가 입력해야할게 너무 많아요.
그리고 일주일치 식단을 주면... 그것에 맞게 장을 보고 그것에 맞춰가며 하루하루를 살아갈.... 그런 사용자들이 있을까? 라는 근본적인, 아주 기초적인 그런 문제였습니다..</p>
<p>프로젝트를 시작한지 거의 2주가 지난 상태에서 기획을 트는 것은 위험한 선택이 아니냐 라고 충분히 생각할 수 있는데요.
저희 팀은 값진 경험이라고 생각하고 나아가보기로 했습니다.</p>
<p>llm을 이용하여 레시피를 추천해주는 기능이 주로 들어가는 시스템을 다시 기획해 볼겁니다.</p>
<p>-&gt; 할 수 있다!!!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[LG U+ Why Not SW CAMP 7기 19주차 회고]]></title>
            <link>https://velog.io/@feel_so_fine/LG-U-Why-Not-SW-CAMP-7%EA%B8%B0-19%EC%A3%BC%EC%B0%A8-%ED%9A%8C%EA%B3%A0</link>
            <guid>https://velog.io/@feel_so_fine/LG-U-Why-Not-SW-CAMP-7%EA%B8%B0-19%EC%A3%BC%EC%B0%A8-%ED%9A%8C%EA%B3%A0</guid>
            <pubDate>Wed, 01 Oct 2025 00:35:48 GMT</pubDate>
            <description><![CDATA[<h3 id="마지막-프로젝트가-시작되기-전-주라-휴가를-써보았다">마지막 프로젝트가 시작되기 전 주라 휴가를 써보았다.</h3>
<p>월, 목을 쉬었고 금요일에 프로젝트 킥오프를 하였다.
프로젝트 헌장이라는 것이 뭔지 보고 살짝 작성도 해보고 어떻게 프로젝트를 진행할지 상의도 하는 시간을 가졌다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[LG U+ Why Not SW CAMP 7기 20주차 회고]]></title>
            <link>https://velog.io/@feel_so_fine/LG-U-Why-Not-SW-CAMP-7%EA%B8%B0-20%EC%A3%BC%EC%B0%A8-%ED%9A%8C%EA%B3%A0</link>
            <guid>https://velog.io/@feel_so_fine/LG-U-Why-Not-SW-CAMP-7%EA%B8%B0-20%EC%A3%BC%EC%B0%A8-%ED%9A%8C%EA%B3%A0</guid>
            <pubDate>Wed, 01 Oct 2025 00:31:31 GMT</pubDate>
            <description><![CDATA[<h1 id="프로젝트-스프린트1--멘토링1">프로젝트 스프린트1 &amp; 멘토링1</h1>
<ul>
<li>9/23 ~ 9/30 스프린트 1  - 6 days<ul>
<li>스프린트 미팅, 데일리 스크럼</li>
<li>계획서, WBS, 요구사항정의서 등</li>
<li>멘토링 준비</li>
<li>9/27 1차 멘토링</li>
<li>9/30 스프린트 리뷰 &amp; 전체 회고</li>
</ul>
</li>
</ul>
<h2 id="스프린트1의-목표">스프린트1의 목표</h2>
<ul>
<li>기획 및 요구사항 정의<ul>
<li>서비스 목표 설정, 핵심 기능 정의, 사용자 흐름 및 UX 설계</li>
</ul>
</li>
</ul>
<h3 id="한-일과-잘된-점">한 일과 잘된 점</h3>
<p>1) 그라운드 룰 정의, 깃 저장소 생성, 기획서 작성 시작, wbs 스프린트1 작성 중 공유 문서로 작업할 때 각자 파트를 하나씩 맡아서 한 후 같이 검토함</p>
<p>2) 시스템 흐름도를 그려보았다. 기능과 보여지는 화면에 대해서 더욱 깊게 생각해볼 수 있었고, 막막했지만 컨펌을 받아가면서 차근차근 진행하였다.</p>
<p>3) 사용자 ui 구성(피그마), 사용할 데이터 조사, 기능별로 사용할 기술 조사  -&gt; 데이터와 기술 조사를 두명, 두명 나눠서 빠르게 해결하고 검토 후 다시 아키텍쳐로 넘어감.</p>
<p>4) UI를 구성하다가 너무 세부 설계라는 피드백을 받아 데이터 개념 모델링을 진행하였다. 꽤 구체적으로 필요한  개체와 속성들을 정의했다.</p>
<p>5) 데이터 전처리, 식단 추천 기술 테스트 -&gt; 데이터 전처리를 함께 상의하여 정하고 최종  파일로 각자 파인콘 적재, rag 구현하여 비교해 보았다.</p>
<p>6) 멘토링 내용 논의 + 요구사항 정의서 수정, 그에 맞춰 흐름도를 수정하고 아키텍쳐 보완. 기획을 구체화해가고 있는데 이야기도 많이하고 고민도 꽤 많이 한 시간이었다.</p>
<h3 id="다음날-할-일과-개선할-점">다음날 할 일과 개선할 점</h3>
<p>1) 요구사항 정의서, UI 구성 -&gt; 첫 날이라 개선할 점이 크게 느껴지진 않음</p>
<p>2) 오늘 그린 시스템 흐름도를 바탕으로 아키텍쳐를 구성하고 사용자 ui에 대해 생각해볼 것이다.  추천을 할 때 rag를 쓰려고 하는데 꼭 벡터 DB를 이용해야하는지 생각해볼 필요가 있을 것 같다.</p>
<p>3) 사용자 ui 구성을 마무리 하면서 생각했던 기능들을 구체화 하고 수정하여 요구사항 정의서 보완하기, RAG에 사용할 모델들과 벡터DB 고민, 시간이 남는다면 찾아둔 데이터를 보고 ERD 구성하기</p>
<p>4) oracle 클라우드에 다시 가입을 해볼 예정 -&gt; 음식에 대한 데이터들을 수집하고 전처리해서 간단하게 rag를 구현해 볼 예정</p>
<p>5) 멘토님과 지금까지 한 산출물 공유하고 컨펌, 이야기 나누기, 스프린트2 wbs 작성하기, 기술 테스트에서 성능을 더 좋게 하려면 어떤방법을 써야하는지 고민해보기, 오라클 클라우드 집에가서 가입해보기</p>
<p>6) 일단 스프린트1의 발표자료 PPT를 만들고 화면 와이어프레임을 구성해보려고 한다. 구체화해둔 기능으로 받아온 정보를 어떤식으로 보여줄지를 고민하다보면 더 이해가 깊어질 수 있지 않을까 기대한다.</p>
<h3 id="장애물-또는-이슈와-제안사항">장애물 또는 이슈와 제안사항</h3>
<p>1) figma 툴 사용 미숙</p>
<p>2) 시스템 쪽에 자신이 없는 편이라 흐름도와 아키텍쳐를 그려보는데 시간도 좀 걸리고 어려운 것 같다.  </p>
<p>3) 기능에 대해서 꽤 고민하고 정해놨다 생각했는데 ui를 설계하다보니 더 구체적으로 생각해봐야 할 점이 생기는 것 같다. 배포 환경에 관련해서는 더 고민하고 aws 특강 이후에 아키텍쳐를 다시 손보는 게 좋을 것 같다.</p>
<p>4) 오라클 클라우드 가입 실패 - 요청 초과라고 함...</p>
<p>5) 임베딩할 때 text로 들어갈 내용들을 잘 선택해서 넣어줘야 검색 성능을 높일 수 있음. 이름으로만 하면 정말 비슷한 제품만 찾아와서 매번 비슷한 음식들만 나오게 됨.</p>
<p>6) 멘토링을 하고 나서 기획이 좀 막막하고 막히는 느낌이 나서 좀 힘들었다.
생각해둔 기능을 타당성 검증을 해보는 시간을 가져야겠다.</p>
<h2 id="스프린트-1-발표">스프린트 1 발표</h2>
<ul>
<li>자신이 없었지만 ppt를 만들면서 더 이야기를 하며 살짝 자신감 충전이 됨</li>
<li>결정한 것에 대한 이유와 근거의 스토리를 발표에 녹였으면 좋겠다는 피드백을 받음</li>
</ul>
<h2 id="스프린트2의-계획과-방향">스프린트2의 계획과 방향</h2>
<ul>
<li>타당성 검증의 시간을 가져야 한다.</li>
<li>멘토님이 요청하신 프로젝트 계획서를 드리고 논의</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[LG U+ Why Not SW CAMP 7기 18주차 회고]]></title>
            <link>https://velog.io/@feel_so_fine/LG-U-Why-Not-SW-CAMP-7%EA%B8%B0-18%EC%A3%BC%EC%B0%A8-%ED%9A%8C%EA%B3%A0</link>
            <guid>https://velog.io/@feel_so_fine/LG-U-Why-Not-SW-CAMP-7%EA%B8%B0-18%EC%A3%BC%EC%B0%A8-%ED%9A%8C%EA%B3%A0</guid>
            <pubDate>Mon, 15 Sep 2025 09:10:16 GMT</pubDate>
            <description><![CDATA[<h2 id="liked">Liked</h2>
<ul>
<li><p><strong>캐싱 전 구동 → 인메모리/Redis</strong></p>
<ul>
<li><code>InMemoryCache</code>로 같은 질문 반복 시 0s → 첫 실행은 오래걸림</li>
<li>Redis 연결 테스트까지 했고 LangChain의 <code>RedisCache</code>로 LLM 응답 캐싱도 동작!</li>
</ul>
</li>
<li><p><strong>프롬프트 템플릿 → ChatPromptTemplate</strong></p>
<ul>
<li><code>PromptTemplate</code>로 변수만 바꿔 프롬프트 재사용</li>
<li><code>ChatPromptTemplate</code>로 system/human/ai 구조화</li>
</ul>
</li>
<li><p><strong>Output Parser</strong></p>
<ul>
<li><code>JsonOutputParser</code> + 지시문을 프롬프트에 → 파싱 실패 없이 JSON 획득</li>
</ul>
</li>
<li><p><strong>LCEL 파이프라인</strong></p>
<ul>
<li><code>prompt | llm</code>으로 실행</li>
</ul>
</li>
<li><p><strong>임베딩 비교 실험</strong></p>
<ul>
<li>OpenAI, Upstage, Ollama까지 코사인 유사도 비교.</li>
<li>king–왕에서 모델별 유사도 차이</li>
</ul>
</li>
<li><p><strong>Pinecone</strong></p>
<ul>
<li>3차원 인덱스 생성→업서트→필터 쿼리까지 확인</li>
</ul>
</li>
<li><p>위키 100개 샘플: <code>datasets</code>로 위키 로드 → <code>RecursiveCharacterTextSplitter(400/20)</code>로 쪼개기 → <code>text-embedding-3-small(1536차원)</code>으로 임베딩 → Pinecone 업서트(배치 20 + sleep) → <code>query()</code>로 바로 검색까지</p>
</li>
<li><p>리트리벌 비교:</p>
<ul>
<li><code>wiki_index.query(..., include_metadata=True)</code></li>
<li><code>PineconeVectorStore(..., text_key=&#39;full_text&#39;).similarity_search()</code></li>
</ul>
</li>
<li><p>세금 문서 RAG: <code>Docx2txtLoader</code> → <code>split(1500/200)</code> → <code>Chroma.persist</code>로 로컬 저장 → <code>ChatOpenAI</code>로 컨텍스트 기반 답변 생성</p>
</li>
<li><p>질의 정규화(정규식/치환) → 바로 성과</p>
<ul>
<li>연봉 5천만원을 과세표준 5,000만원으로 바꾸니 세율 표(제55조)가 정확히 걸렸고 624만원(= 84만 + 3,600만×15%)을 안정적으로 뽑아냈다.</li>
<li>9월 급여 미지을 12월 31일 원천징수 시기로 유도하니 제135조 특례가 바로 리트리브되어 12/31에 지급 간주 → 원천징수라는 핵심 규정이 깔끔히 나왔다.</li>
</ul>
</li>
<li><p>사전 기반 용어 표준화가 유효</p>
<ul>
<li>직장인→거주자, 월급→근로소득, 세금 떼다→원천징수 같은 치환이 검색 분산을 줄이고 법 조문 제목/본문 키워드와 정합성을 높여줌.</li>
</ul>
</li>
<li><p>LCEL 체이닝 구조가 읽기 쉬움</p>
<ul>
<li><code>dictionary_chain → qa_chain</code> 흐름이 명확하고 나중에 모듈별로 성능 비교하기 좋아 보였다.</li>
</ul>
</li>
<li><p>LangSmith 평가 프레임 설계</p>
<ul>
<li>실행은 안 했지만 정확도/도움됨/할루시네이션 3축으로 평가 루프를 준비해둔 점이 좋았다.</li>
</ul>
</li>
<li><p>소믈리에 페르소나</p>
<ul>
<li>시스템 프롬프트가 입력 부족 시 묻기 → 기본 출력 포맷까지 포함해서 재사용성이 높다. 이미지가 들어와도 안정적으로 제안이 나오는 것 확인.</li>
</ul>
</li>
</ul>
<h2 id="learned">Learned</h2>
<ul>
<li><p><strong>캐시의 종류</strong></p>
<ul>
<li><p>정확 일치 캐시: 프롬프트가 글자 하나까지 똑같아야 저장된 응답을 씀.</p>
<p>  → 서울 프렌치 레스토랑 추천해줘와 서울에서 프렌치 레스토랑 추천해줘는 달라서 다른 응답 생성</p>
</li>
<li><p>시맨틱 캐시: 프롬프트를 임베딩으로 바꾸고 코사인 유사도로 비교해서 비슷하면 같은 응답을 씀.</p>
<p>  → 표현만 다르게 해도 같은 뜻이면 응답 재사용 가능.</p>
</li>
<li><p>코드에서 <code>InMemoryCache</code> → 속도 빠름, 종료 시 데이터 사라짐.</p>
<p>  <code>RedisCache</code> → 여러 서버 공유, 껐다 켜도 데이터 유지.</p>
</li>
</ul>
</li>
<li><p><strong>프롬프트 템플릿</strong></p>
<ul>
<li>변수를 넣는 자리를 미리 틀로 만들어서 재사용 가능.</li>
<li><code>PromptTemplate</code> → 서울에서 유명한 프렌치 레스토랑을 알려줘 같은 문장을 변수만 바꿔 자동 생성.</li>
<li><code>ChatPromptTemplate</code> → system / human / ai 역할을 나눠서 대화 프롬프트를 안정적으로 만들 수 있음.</li>
</ul>
</li>
<li><p><strong>Output Parser</strong></p>
<ul>
<li>LLM 답변을 JSON 같은 구조로 뽑아내는 도구.</li>
<li><code>JsonOutputParser</code> + <code>Pydantic</code> 스키마로 내가 원하는 필드(<code>sender_name</code>, <code>title</code>, <code>content</code>)만 딱딱 뽑을 수 있었음.</li>
<li>포인트: <code>parser.get_format_instructions()</code>를 프롬프트에 넣으니 LLM이 정해진 JSON 구조로 잘 출력해줌.</li>
</ul>
</li>
<li><p><strong>LCEL 체인</strong></p>
<ul>
<li><code>prompt | llm</code> 처럼 파이프라인으로 연결</li>
<li>여러 단계를 차례대로 묶을 땐 <code>SequentialChain</code>처럼 사용할 수 있지만 LCEL이 더 직관적이고 가볍다.</li>
</ul>
</li>
<li><p>차원 일치의 중요성</p>
<ul>
<li>인덱스마다 차원 다름: quickstart(1024), wiki(1536).</li>
<li>임베딩 모델이 뱉는 벡터 차원과 인덱스 차원이 정확히 맞아야 함(안 맞으면 바로 에러).</li>
</ul>
</li>
<li><p>텍스트 스플릿 전략</p>
<ul>
<li><code>RecursiveCharacterTextSplitter(chunk_size=400, overlap=20)</code>로 위키 텍스트를 쪼개고 35KB 초과는 스킵.</li>
<li>위키: 400/20 → 짧아서 정확히 맞는 문단을 잘 끌어옴.</li>
<li>세금 문서: 1500/200 → 길어서 문맥은 잘 유지되는데, 가끔 필요 없는 내용이 같이 따라옴.</li>
</ul>
</li>
<li><p>RAG 파이프라인</p>
<ol>
<li>Retrieval: 벡터DB에서 k개 뽑기</li>
<li>Augmentation: 컨텍스트 묶기</li>
<li>Generation: LLM에 컨텍스트만 참고, 조건 프롬프트로 답변</li>
</ol>
<ul>
<li>세금 문서(<code>docx2txt → split → Chroma.persist</code>)로 질문 → 관련 문단 → 근거 기반 답변</li>
</ul>
</li>
<li><p>질의 끝에 누진공제를 적용해 계산을 붙이는 것만으로도 모델이 제55조 근처로 강하게 수렴. 원천징수, 시기, 간이세액표 같은 단어도 리트리버를 올바른 조문으로!</p>
</li>
<li><p>RagBot 패턴</p>
<p>  <code>retrieve_docs()</code> → <code>invoke_llm()</code>에서 문맥을 system에 고정해 주면 헛소리가 줄어든다. 다만 발췌 범위/길이 관리가 중요(너무 길면 분산)</p>
</li>
<li><p>LLM 판단 주의</p>
<p>  LangSmith LLM 평가자는 프롬프트 편향을 타니 샘플 다양성과 정답 스키마를 갖춘 데이터셋이 필요. 그래야 점수가 의미 있게 나온다.</p>
</li>
</ul>
<h2 id="lacked">Lacked</h2>
<p><strong>프롬프트 표준화가 왜 중요한지 감은 오지만 막상 적용은..</strong></p>
<ul>
<li>프로젝트나 실제는 질문이 매번 다르게 들어올 텐데… 그걸 어떻게 표준화하지? 라는 고민..</li>
<li>코드로는 단순히 <code>{city}</code>, <code>{topic}</code>처럼 바꾸면 되지만 실제 데이터에서는 훨씬 복잡할 것 같다.</li>
</ul>
<p>시간 관계상 생각보다 굉장히 빨라서 따로 리뷰하는 시간을 꼭 가져야한다…  </p>
<ul>
<li><p>메타데이터에 <code>full_text</code>를 통째로 넣음:</p>
<p>  임베딩은 <code>chunk</code>로 했는데 메타데이터 텍스트 키를 <code>full_text</code>로 두니 각 청크가 전부 원문 전체를 달고 다니는 구조가 됨.</p>
</li>
<li><p>세금 RAG 근거 표기 부족:</p>
<p>  답변은 나왔지만 어느 조항/문단에서 왔는지를 제목/페이지/문단ID로 알아보기가 어려움</p>
</li>
</ul>
<h2 id="longed-for">Longed for</h2>
<ul>
<li><p><strong>프롬프트 포맷 고정하기</strong></p>
<ul>
<li>같은 질문이면 같은 형식으로 들어가게 만들어보기</li>
<li>시스템 프롬프트 + 사용자 입력 + 버전 태그로 캐시 키를 일정하게 유지해보기</li>
</ul>
</li>
<li><p><strong>TTL / 로그 붙이기</strong></p>
<ul>
<li>자주 바뀌는 것</li>
<li>로그: <code>hit/miss, sim_score, latency, tokens, cost</code> 저장해서 캐시 성능을 숫자로 확인!</li>
</ul>
</li>
<li><p>질의 강화</p>
<ul>
<li>위키: 주기율표 78번 → 원소 78 백금, 화학적 성질/용도처럼 키워드 보강</li>
<li>세금: 연봉 5천만 원 소득세 → 근로소득 간이세액/과세표준/세액공제 키워드 자동 추가.</li>
</ul>
</li>
<li><p>RAG 근거 표준화</p>
<ul>
<li>세금 답변에 <code>출처: [문서명] 섹션/문단ID</code> 템플릿 고정.</li>
<li>위키도 <code>title | url | chunk_id | score</code>를 함께 보여주기.</li>
</ul>
</li>
<li><p>메타데이터 스키마 확정 + 재업서트</p>
<ul>
<li>필드: <code>country, variety, price, points, winery, title, region_1</code></li>
<li><code>filter={&quot;price&quot;:{&quot;$lte&quot;:30000}}</code></li>
</ul>
</li>
<li><p>필터+검색 결합 쿼리</p>
<ul>
<li>가벼운 바디 &amp; 산도 높은 화이트, 2–4만, 프랑스/이탈리아</li>
<li><code>similarity_search(query, k, filter={...})</code> 패턴 확보.</li>
</ul>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[LG U+ Why Not SW CAMP 7기 17주차 회고]]></title>
            <link>https://velog.io/@feel_so_fine/LG-U-Why-Not-SW-CAMP-7%EA%B8%B0-17%EC%A3%BC%EC%B0%A8-%ED%9A%8C%EA%B3%A0</link>
            <guid>https://velog.io/@feel_so_fine/LG-U-Why-Not-SW-CAMP-7%EA%B8%B0-17%EC%A3%BC%EC%B0%A8-%ED%9A%8C%EA%B3%A0</guid>
            <pubDate>Sat, 06 Sep 2025 13:56:40 GMT</pubDate>
            <description><![CDATA[<h2 id="liked">Liked</h2>
<ul>
<li><p>같은 문제를 여러 프레임워크로 직접 구현해 봄:</p>
<ul>
<li>scikit-learn <code>MLPClassifier</code>로 빠른 베이스라인 확인</li>
<li>TF1(placeholder, <code>tf.matmul</code>)로 W·b·행렬 곱 흐름을 손으로 느낀 점이 좋았다</li>
<li>Keras(TF2) <code>Sequential</code>/함수형 API(concatenate) 로 모델 쌓는 감각이 생김</li>
<li>PyTorch는 학습 루프(순전파→손실→역전파→step) 가 눈에 보여서 이해가 쉬웠다</li>
</ul>
</li>
<li><p>모듈 바꿔가며 효과 체감:</p>
<ul>
<li><code>sigmoid</code> ↔ <code>relu</code> ↔ <code>PReLU</code>, <code>ELU</code>, <code>BatchNormalization</code>, <code>Dropout</code>, <code>he_normal</code>, <code>RandomNormal</code> 등 한두 줄 교체로 학습 느낌이 달라지는 걸 직접 확인</li>
<li>Keras에서 모델 저장/로드(<code>.keras</code>, <code>.to_json()</code>) 까지 해보니 파이프라인 감이 잡힘</li>
</ul>
</li>
<li><p><strong>흐름 구성</strong>: <code>tf</code>/GPU 확인 → MNIST 로드, 정규화(<code>/255.0</code>) → CNN 설계(Conv→Pool→Dropout→Flatten→Dense) → 학습/평가까지 한 흐름으로 정리됨.</p>
</li>
<li><p><strong>드롭아웃</strong>: 0.1 → 0.25 → 0.5로 깊어질수록 규제를 강화해 과적합을 의식한 구조가 좋았음.</p>
</li>
<li><p><strong>전이학습</strong>:</p>
<ul>
<li>ImageNet 사전학습 ResNet50로 단일 이미지 분류(<code>decode_predictions</code>)를 해봄.</li>
<li><code>include_top=False</code>로 <strong>Flatten→Dense(1024)→Dense(3)</strong>  3분류 실험을 구성.</li>
</ul>
</li>
<li><p><strong>데이터 준비와 증강</strong>: zip 해제 → <code>flow_from_directory</code>로 train/test 분리, 회전/이동/좌우반전 증강으로 데이터 다양성 확보.</p>
</li>
<li><p>원격·로컬 추론 연결</p>
<p>  Roboflow <code>InferenceHTTPClient.infer()</code>로 배포 모델(<code>rock-paper-scissors-sxsw/14</code>)을 바로 불러보고 로컬에선 <code>YOLO(&#39;yolov8n.pt&#39; | &#39;best.pt&#39;)</code>로 재확인</p>
</li>
<li><p>결과 파싱 &amp; 시각화</p>
<p>  Roboflow JSON의 <code>x,y,width,height,confidence,class</code>를 읽고 xywh → xyxy 변환해서 <code>cv2.rectangle</code>, <code>cv2.putText</code>로 박스 그리기</p>
</li>
<li><p>YOLOv8 핵심 모듈</p>
<p>  Detection → Segmentation → Pose를 빠르게 한 사이클 돌렸다. 결과 구조(boxes/masks/keypoints)가 서로 어떻게 다른지 확인</p>
</li>
</ul>
<h2 id="learned">Learned</h2>
<ul>
<li><p>소프트맥스·시그모이드 어디에 둘지!</p>
<ul>
<li>다중분류는 마지막 층에 <code>softmax</code>로 확률을 만든다(Keras/TensorFlow)</li>
<li>PyTorch의 <code>CrossEntropyLoss</code>는 softmax 이전 로짓을 기대한다 → 모델 끝 <code>Softmax</code>는 빼고 손실이 내부에서 처리한다는 것</li>
</ul>
</li>
<li><p>라벨 ↔ 출력 유닛 수 정합(와인 데이터 포인트)</p>
<ul>
<li>원 라벨이 <code>3~8</code>이라 고유 클래스는 6개지만 인덱스가 0부터가 아님.</li>
<li>선택지 두 개:<ol>
<li>재인코딩(0~5) → <code>Dense(6, softmax)</code></li>
<li>원 라벨 유지(3<del>8) → 최소 <code>Dense(9, softmax)</code> (0</del>8 공간)</li>
</ol>
</li>
<li>베이스 코드가 <code>Dense(10)</code>을 쓰기도 했는데 동작은 하지만 0,1,2,9가 비며 비효율. 내가 만든 모델에서 <code>Dense(9)</code>로 맞춘 이유!</li>
</ul>
</li>
<li><p>순전파/역전파 흐름을 TF1로 배움</p>
<ul>
<li>shape가 한 번 어긋나면 전체가 멈춤(이전 디버깅 때도 행렬 곱 차원 에러 겪음).</li>
<li>결국 행렬 크기와 dtype을 계속 의식해야 한다는 걸 배움</li>
</ul>
</li>
<li><p>훈련 vs 평가 지표 차이</p>
<ul>
<li><code>fit(...)</code> 도중 보이는 건 훈련셋 기준, <code>evaluate(...)</code>는 테스트셋 기준 → 다르게 나오는 게 정상</li>
<li>아이리스에서 훈련 동안 보인 값과 최종 <code>evaluate</code>가 조금 다른 것도 이 때문</li>
</ul>
</li>
<li><p>모델 구조의 작은 차이가 수렴에 영향</p>
<ul>
<li><code>Dense → BatchNorm → Activation → Dropout</code> 순서로 둔 모델이 안정적으로 학습되는 느낌</li>
<li><code>PReLU()</code>는 <code>Dense(..., activation=PReLU())</code>가 아니라 별도 레이어로 추가해야 층이 깨끗이 잡힌다(이번 코드에서 그렇게 처리)</li>
</ul>
</li>
<li><p><strong>CNN 블록의 역할 분담</strong>:</p>
<ul>
<li><code>Conv2D</code> → 작은 3×3 창(커널)을 굴리며 모서리, 선 같은 저수준 패턴을 감지하고, 층이 깊어질수록 복잡한 패턴으로 확장됨.</li>
<li><code>MaxPooling2D</code> → 특징 지도의 가로, 세로 크기를 절반으로 줄여 계산량↓, 작은 위치 변화에 덜 민감해짐(견고성↑).</li>
<li><code>Flatten → Dense</code> → 2D 특징 지도를 1D 벡터로 펼친 뒤 그 특징들을 결정 경계로 바꿔 클래스 확률을 내게 함.</li>
</ul>
</li>
<li><p><strong>손실함수, 라벨 타입 매칭</strong></p>
<ul>
<li><code>sparse_categorical_crossentropy</code> ↔ 라벨이 정수</li>
<li><code>categorical_crossentropy</code> ↔ 라벨이 원-핫 벡터</li>
</ul>
</li>
<li><p><strong>전이학습</strong></p>
<ol>
<li>두 가지 사용 흐름을 체감함</li>
</ol>
<ul>
<li>(A) 사전학습 모델 그대로 사용: <code>ResNet50(weights=&#39;imagenet&#39;)</code>로 불러와 단일 이미지를 <code>(224,224)</code>로 맞추고 <code>predict → decode_predictions</code>로 ImageNet  1000클래스 예측을 확인.</li>
<li>(B) include_top=False: <code>include_top=False</code>로 분류기 빼고 가져온 뒤 위에 <code>Flatten → Dense(1024, relu) → Dense(3, softmax)</code>를 쌓아 3클래스 문제에 맞게 학습.</li>
</ul>
<ol>
<li>데이터 준비, 증강</li>
</ol>
<ul>
<li>zip 해제 후 <code>flow_from_directory(train/test)</code>로 폴더 구조 = 라벨 매핑 자동화.</li>
<li><code>rotation/shift/horizontal_flip</code> 증강으로 데이터 다양성↑ → 과적합 완화에 도움.</li>
</ul>
</li>
<li><p><strong>GPU 활용 체크</strong></p>
<ul>
<li><code>tf.config.list_physical_devices(&#39;GPU&#39;)</code>로 확인. → 
리스트에 <code>GPU:0</code> 보이면 GPU 사용 가능</li>
</ul>
</li>
<li><p>Roboflow와 Ultralytics의 반환 구조 차이</p>
<ul>
<li><p>Roboflow: 딕셔너리(JSON) 중심, 바로 <code>predictions</code> 리스트 순회</p>
</li>
<li><p>Ultralytics: <code>result[0].boxes/masks/keypoints</code>처럼 객체화된 구조 + <code>result[0].plot()</code> 제공</p>
<p>  → 같은 박스 그리고 라벨 찍기라도 접근 방식이 다름!</p>
</li>
</ul>
</li>
<li><p>confidence/overlap 인자 스케일</p>
<p>  Roboflow 에서 <code>confidence=40, overlap=30</code>처럼 퍼센트(%) 스케일을 넣는 패턴을 익혔다. (Ultralytics 추론은 보통 0~1 스케일 conf를 옵션으로 조절)</p>
</li>
<li><p>best 가중치 검증 루틴</p>
<p>  <code>YOLO(&#39;runs\\detect\\train\\weights\\best.pt&#39;) → .val()</code>로 학습 결과를 같은 데이터셋으로 재검증하는 루틴이 안정화. 모델 비교가 훨씬 수월해짐.</p>
</li>
<li><p>튜닝 파일을 실제 학습에 반영하는 법</p>
<p>  <code>best_hyperparameters.yaml</code>을 <code>yaml.safe_load</code>로 읽어 <code>train(**hyp_dict)</code>에 주입하는 흐름을 익힘. 탐색→적용</p>
</li>
</ul>
<h2 id="lacked">Lacked</h2>
<ul>
<li><p>평가 지표의 다양성 부족: 아이리스에서 <code>accuracy</code>만 보거나 <code>crosstab</code>만 봤다. 혼동행렬, macro F1까지 같이 봤으면 클래스별 밸런스를 더 명확히 확인했을 것</p>
</li>
<li><p>학습 곡선 시각화 미흡: <code>history</code>를 바로 그래프로 그려 과적합 시점을 잡는 습관이 아직 부족했다</p>
</li>
<li><p>결정성(Seed) 통제 부족: 실행할 때마다 초기값/셔플 때문에 결과가 조금씩 달라지는 걸 확인했지만, 프레임워크별 시드 통일은 덜 했다</p>
</li>
<li><p>PyTorch 규칙 반영 미완: 이번 노트에선 모델 끝에 <code>Softmax(dim=1)</code>를 둔 상태로 <code>CrossEntropyLoss</code>를 썼다. 다음엔 Softmax 제거 + y를 처음부터 <code>long</code> 으로 잡아보기</p>
</li>
<li><p><strong>평가 지표 확장 부족</strong>: 최종 <code>evaluate</code>에 accuracy만 사용해보아 손실과 정확도로만 평가를 해봄</p>
</li>
<li><p>실행을 할 때마다 결과가 달라짐 → 시드를 고정해보기</p>
</li>
<li><p>horizontal_flip=True 에서 만약 데이터의 좌우 정보가 중요하다면.. 성능에 안좋은 영향을 미칠 수 있을 것 같음</p>
</li>
<li><p>지표 뜻/우선순위가 직관적이지 않음</p>
<p>  <code>mAP50</code>은 오르는데 <code>mAP50-95</code>가 정체 → 좋은 건가 나쁜 건가?가 애매했음. 얼리스탑의 fitness가 mAP50-95 비중이 큼도 뒤늦게 연결됨.</p>
</li>
<li><p>학습/검증 데이터 경로가 섞여 보임</p>
<p>  <code>./datasets1/data.yaml</code>와 <code>numbers/data.yaml</code>를 오가며 돌려서 지금 이 best.pt는 어느 데이터로 학습된 거지?가 즉시 안 보였음.</p>
</li>
<li><p>QA에 context 없이 질문만 넣음 → 모델이 답을 못 찾아서 공백/개행을 답으로 고름.</p>
</li>
<li><p>요약에서 길이(512 토큰) 초과 경고남 → 너무 길어서</p>
</li>
<li><p>결과에  E 토큰이 섞여 나옴 → 예측 후처리(토큰 제거, E 이전 컷)가 빠졌음.</p>
</li>
</ul>
<h2 id="longed-for">Longed for</h2>
<ul>
<li><p>내 표준 틀 만들기</p>
<ul>
<li><code>plot_history(history)</code>, <code>print_report(y_true, y_pred)</code> 유틸을 만들어 학습 곡선 + 혼동행렬 + macro F1을 항상 같이 보는 것?</li>
<li>(PyTorch) Softmax 없는 모델 + <code>CrossEntropyLoss</code> + <code>y.long()</code> 세트로 템플릿 고정!</li>
</ul>
</li>
<li><p>와인 라벨 전략 비교 실험</p>
<ul>
<li>Dense(6)+재인코딩(0<del>5) vs Dense(9)+원라벨(3</del>8) 를 같은 조건으로 비교해서 내 데이터에서 어떤 게 더 안정적으로 나오는지 체크</li>
</ul>
</li>
<li><p>실행 결과가 동일하게 나올 수 있도록 통일할 수 있는 시드가 어떤 것이 있는지 찾아봐야겠다.</p>
</li>
<li><p>모델 평가에서 다른 지표들을 활용해봐야겠다.</p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[LG U+ Why Not SW CAMP 7기 16주차 회고]]></title>
            <link>https://velog.io/@feel_so_fine/LG-U-Why-Not-SW-CAMP-7%EA%B8%B0-16%EC%A3%BC%EC%B0%A8-%ED%9A%8C%EA%B3%A0</link>
            <guid>https://velog.io/@feel_so_fine/LG-U-Why-Not-SW-CAMP-7%EA%B8%B0-16%EC%A3%BC%EC%B0%A8-%ED%9A%8C%EA%B3%A0</guid>
            <pubDate>Sun, 31 Aug 2025 12:41:03 GMT</pubDate>
            <description><![CDATA[<h1 id="2차-프로젝트-회고">2차 프로젝트 회고</h1>
<h2 id="1일차">1일차</h2>
<p>ERD 다이어그램을 설계하는 데에 생각보다 시간이 많이 들었고, </p>
<p>데이터를 얻기가 어려워 가상의 데이터를 만들기로 하고 랜덤으로 데이터를 생성하는 페이지를 구성해 가져왔는데 만든 것도 활용하려 해보니 허점이 많았다. 데이터를 잘 가공해서 원하는 대로 만들어 최대한 결과를 끌어내봐야겠다.</p>
<h2 id="2일차">2일차</h2>
<p>오늘은 대시포드 탭 중 머신러닝 부분에 집중했는데 샘플/가공 데이터라 날짜 가용성, 요일/시간대 불균형, 결측 처리에 시간이 많이 들었다. 쓸만한 신뢰도의  검증점수가 나와야 하는데 결과 안정성이 낮다고 느껴졌다. 시간이나 요일별로 분포를 잘 고려하여 만들었어야 한다고 생각했다. </p>
<p>대시보드는 로컬 구현은 대체로 잘 됐지만 API 연동을 살짝 시도하니 이슈가 겹쳐 쉽지 않았다…</p>
<h2 id="3일차">3일차</h2>
<p>코드를 합칠 때에는 csv파일을 불러와서 실행하는 흐름이었는데 오늘은 api 연동으로 바꿔서 데이터를 끌어와서 보여줄 수 있게 코드를 수정하였다. DB에서 데이터를 불러와 그걸 함수의 매개변수로 넘겨주어 스트림릿으로 보여지게 하였다.</p>
<p>소상공인 정책자금 홈페이지에서 공지사항에 첨부된 파일들을 크롤링하여 저장하는데 잘 되다가 중간에 구조가 이상한 페이지가 있어서 에러가 났다 -&gt; 원하는 태그가 있어도 내용이 비어있으면 스킵하도록 예외처리를 구현하였다.</p>
<p>내일은 가져온 파일들을 텍스트로 잘 변환하고 청킹, 임베딩까지 해보려고 한다.</p>
<h2 id="4일차">4일차</h2>
<p>대시보드에 관련해서 명확한 목적이 필요하다는 생각이 들었다. 데이터로 관리자에게 보여줄 수 있는 좋은 인사이트가 무엇인지를 생각해서 3차 프로젝트 시작할 때 더 구체적인 대시보드를 구현해봐야겠다고 생각한다.</p>
<p>현재는 어제 크롤링해온 문서들을 원하는 형태로 변환하는 작업을 수행 중인데,  자르는 건 둘째 치고 pdf와 hwp파일을 변환하는 것 부터 큰 난관에 봉착했다. 일단은 문서 하나만 텍스트 파일로 변환하여 청킹을 해봤는데 붙으면 안되는 글자가 붙어있고, 띄어 쓰면 안되는 글자가 떨어져 있어서 원하는 형태에 도달하기까지는 시간이 걸릴 것 같다.</p>
<h2 id="5일차">5일차</h2>
<p>오늘은 프로젝트의 마지막 날이라 임베딩까지 해보고 싶었다. 청킹은 문서 하나로 정규표현식을 이용하여 하였고, 임베딩은 팀원 각자 찾아본 모델로 다르게 진행해보았다. 검색할 때에는 모델마다 당연히 차이가 있었고, 어떤 기준으로 검색을 해오는 지는 아직 잘 파악하지 못하였다.
최종 발표에서는 대시보드에 대한 피드백을 주셨다.
현재 만들어둔 대시보드는 솔직하게 허점도 많고 쓰일 수 있을 만한 내용이 없다는 것이었고, 어떤 화면에서 그 데이터들을 가져오고, 저장하고 보여줄지 생각을 잘 안해본 점이  많이 아쉬움으로 남았다.
2차 프로젝트가 대시보드를 구현하는 것이 목적이었지만 우리 팀은 청킹과 임베딩을 해보는 것에 욕심을 두고 진행하여서 당연한 결과가 아니었을까 싶지만 3차 프로젝트를 위해 천천히 다시 생각해볼 필요가 있을 듯 하다.</p>
<p>상담사가 보는 화면을 기준으로 어떤 정보를 입력하고 들어온 데이터를 어떻게 저장하고 그걸 활용하며 어떤 정보를 보여줄 것인지, 프로젝트 시작 전에 각자 스트림릿 실습으로 만들어보았던 ui를 합쳐보는 것도 방법이 될 수 있을 것 같다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[LG U+ Why Not SW CAMP 7기 15주차 회고]]></title>
            <link>https://velog.io/@feel_so_fine/LG-U-Why-Not-SW-CAMP-7%EA%B8%B0-15%EC%A3%BC%EC%B0%A8-%ED%9A%8C%EA%B3%A0-0jizgdyv</link>
            <guid>https://velog.io/@feel_so_fine/LG-U-Why-Not-SW-CAMP-7%EA%B8%B0-15%EC%A3%BC%EC%B0%A8-%ED%9A%8C%EA%B3%A0-0jizgdyv</guid>
            <pubDate>Sat, 23 Aug 2025 06:38:51 GMT</pubDate>
            <description><![CDATA[<h2 id="liked">Liked</h2>
<ul>
<li><p>세 가지 도구(Matplotlib, Seaborn, Plotly)를 오가며 같은 개념을 구현해 봄</p>
<p>  → 라이브러리별 접근 방식의 차이를 비교</p>
</li>
<li><p>다중 축 차트(2중, 3중축)와 스펙 아웃 강조, 로그 스케일 변환 등을 직접 구현해보며 상황에 따라 어떤 시각화가 효과적인지 익힘</p>
</li>
<li><p>데이터 해석에 도움이 되는 시각화 기법(스펙아웃 강조, 로그 변환으로 기하급수적 증가 포착)을 접목한 점이 좋았다.</p>
</li>
<li><p>스트림릿 기본 문법 익힘</p>
<p>  → <code>st.title</code>, <code>st.header</code>, <code>st.subheader</code>, <code>st.write</code>, <code>st.text</code>, <code>st.markdown</code> 등을 써보면서 웹 UI에 다양한 텍스트와 스타일을 적용할 수 있다는 점이 재미있었다.</p>
</li>
<li><p>다양한 위젯</p>
<p>  → 버튼, 체크박스, 토글, 라디오, 멀티셀렉트, 슬라이더, 텍스트 입력 등 인터랙티브 요소를 다양하게 써보았다. 버튼 클릭 시 이벤트 핸들링(<code>on_click</code>)이나 세션 상태(<code>st.session_state</code>) 관리까지 해보니 실제 대시보드처럼 확장 가능성이 크게 느껴졌다.</p>
</li>
<li><p>데이터 시각화 연동</p>
<p>  → CSV 파일 업로드 → 데이터 테이블 출력 → Plotly 시각화까지 연결해서 데이터 분석 결과를 바로 시각적으로 확인할 수 있는 흐름을 봤다.</p>
</li>
<li><p>UI 구성 요소 연습</p>
<p>  → 사이드바, 컬럼, 탭, 익스팬더 등 레이아웃 기능을 연습하면서 진짜 서비스 UI처럼 구조를 잡을 수 있다는 걸 알게 되었다.</p>
</li>
<li><p>검색부터 투자 보고서까지 한 흐름을 처음부터 끝까지 연결해본 게 좋았음.</p>
</li>
<li><p>파일을 역할별로 나눠서(<code>search.py</code>, <code>stock_info.py</code>, <code>report_service.py</code>, <code>app.py</code>) 코드가 훨씬 깔끔하게 정리된 게 만족스러움.</p>
</li>
<li><p><code>.env</code> 파일로 키를 관리해서 보안에도 조금 더 신경 쓸 수 있게 된 점이 좋았음.</p>
</li>
<li><p>검색창에 Select Here! 같은 기본값을 둬서 바로 불러오지 않게 한 것도 좋았음.</p>
</li>
</ul>
<h2 id="learned">Learned</h2>
<ul>
<li><p>x축 시계열 라벨 제어:</p>
<ul>
<li>Matplotlib은 <code>ConciseDateFormatter</code>, Plotly는 <code>tickformat</code>을 활용해야 라벨을 원하는 형식으로 깔끔하게 만들 수 있다.</li>
</ul>
</li>
<li><p>다중 축 구현:</p>
<ul>
<li>Matplotlib은 <code>ax.twinx()</code>와 spine 위치 조정으로 확장.</li>
<li>Plotly는 <code>make_subplots(secondary_y=True)</code> + <code>yaxis</code> 설정(<code>overlaying</code>, <code>position</code>)으로 확장 가능.</li>
</ul>
</li>
<li><p>범례 위치:</p>
<ul>
<li>seaborn은 <code>bbox_to_anchor</code>, plotly는 <code>legend=dict(x= , y= )</code>.</li>
</ul>
</li>
<li><p>조건 강조:</p>
<ul>
<li>seaborn FacetGrid에서 <code>map</code> vs <code>map_dataframe</code>의 차이를 이해.</li>
<li>데이터 조건(<code>spec_out=True</code>)을 활용해 특정 점만 annotate, 그래프 테두리 강조 → 포인트를 시각적으로 직관화.</li>
</ul>
</li>
<li><p>로그 스케일:</p>
<ul>
<li>데이터가 기하급수적으로 커질 때 log 변환이 해석의 핵심 도구가 된다는 것 확인.</li>
</ul>
</li>
<li><p>색상 팔레트:</p>
<ul>
<li>데이터 특성(연속/범주/양극형/주기성)에 맞는 팔레트를 고르는 게 중요.</li>
</ul>
</li>
<li><p>버튼과 key 충돌 문제</p>
<p>  → 동일한 버튼을 여러 개 만들 때 key를 반드시 지정해줘야 DuplicateWidgetID 오류가 발생하지 않는다는 걸 배움.</p>
</li>
<li><p>세션 상태 활용법</p>
<p>  → <code>st.session_state</code>를 활용하면 체크박스 상태나 사용자 입력을 저장해서 페이지 갱신 후에도 이어갈 수 있다는 개념을 이해했다. → 대시보드/설정 페이지 구현 시 핵심</p>
</li>
<li><p>시각화에서 옵션 처리</p>
<p>  → <code>hue_option=None</code> 같은 조건을 걸어야 색상 컬럼을 선택 안 해도 코드가 에러 없이 돌아가는 걸 확인함.</p>
</li>
<li><p>탭과 사이드바</p>
<p>  → 같은 페이지 안에서 탭으로 화면을 나눌 수도 있고 사이드바로 메뉴 이동을 구현할 수도 있는 앱 구조 설계 방법을 배웠다.</p>
</li>
<li><p>Meilisearch로 회사명을 검색하고 그걸 yfinance로 연결해서 실제 데이터(재무제표와 기본정보)를 가져오는 법을 배움.</p>
</li>
<li><p>LLM에 데이터를 넣어서 투자 보고서 같은 문서를 자동으로 만들어내는 방법을 배움.</p>
</li>
<li><p>코드를 기능별로 나누면 관리가 쉽다는 걸 다시 느낌.</p>
</li>
</ul>
<h2 id="lacked">Lacked</h2>
<ul>
<li><p>Plotly에서 3중축 이상을 세팅할 때 <code>overlaying</code>, <code>position</code> 등 속성이 헷갈려서 몇 번 시행착오가 있었다. → 축 좌표 시스템을 조금 더 체계적으로 정리할 필요가 있을 듯…</p>
</li>
<li><p>seaborn FacetGrid의 <code>map</code>과 <code>map_dataframe</code> 차이 때문에 함수 인자 처리에서 에러를 많이 겪었다.</p>
</li>
<li><p>조건 강조 annotate 해볼 때 로직이 동작은 했지만 <code>iterrows</code>/<code>itertuples</code>/<code>zip</code> 등 여러 방식을 왔다갔다하며 구현해봤는데 아직 가장 깔끔한 패턴을 스스로 정리하지 못했다는 아쉬움이 있다.</p>
</li>
<li><p>UI 세부 꾸미기 부족
→ 기본 레이아웃과 위젯은 익혔지만 색상이나 스타일링 부분(멀티셀렉트 색상, 버튼 디자인 등)은 커스터마이징까지는 못해본 게 아쉬움.</p>
</li>
<li><p>실제 데이터셋 적용 미흡
→ tips, covid, 업로드한 csv 정도만 써봤는데, 내 프로젝트나 분석 데이터와 직접 연결해보진 못한게 살짝 아쉬움</p>
</li>
<li><p>시간이 많이 부족했던 것 같긴 한데 예외처리나 그런 것들을 꼼꼼히 생각해 봐야겠다고 느낌.</p>
</li>
<li><p>Streamlit에서 표를 그냥 <code>st.write</code>로 찍으니 예쁘게 안 보일 때가 있음 ㅜ</p>
</li>
<li><p>검색어를 잘못 넣거나 빈칸으로 두면 결과가 없을 때 안내가 없음.</p>
</li>
<li><p>투자 초보자한테는 설명이 여전히 어려울 수 있음 → 프롬프트 자체에 대한 고민이 더 필요할 듯 함.</p>
</li>
</ul>
<h2 id="longed-for">Longed For</h2>
<ul>
<li><p>시각화 기법들을 팀 프로젝트에 어떻게 녹여낼 수 있을지 고민해봐야겠다.</p>
<ul>
<li>상담 지원 AI의 추천 정확도나 요약 품질을 다중 축 그래프로 비교하면 한 그래프 안에서 모델별 성능 차이를 직관적으로 파악할 수 있지 않을까.</li>
<li>특정 조건(상담 불만 점수, 응답 지연 시간)에 해당하는 케이스를 강조하면 문제 상담 건을 빨리 찾아낼 수 있지 않을까.</li>
</ul>
</li>
<li><p>색상 팔레트도 상담 유형별이나 위험도별로 직관적인 색 체계를 정해 실무자가 빠르게 판단할 수 있게 만드는 게 필요하다는 생각이 든다.</p>
</li>
<li><p>팀플 툭툭 대시보드에 적용</p>
<p>  →  연습한 사이드바 메뉴 전환, 탭 구성, 파일 업로더 → 시각화 흐름을 툭툭 상담 대시보드에 맞게 적용해보고 싶다. 관리자용, 상담사용 페이지를 나눠서 실제 시나리오처럼 만들면 좋을 것 같다.</p>
</li>
<li><p>UI 커스터마이징</p>
<p>  → 버튼 색상, 멀티셀렉트 색상, 테마 적용 등 디자인을 조금 더 예쁘게 꾸며보고 싶다.</p>
</li>
<li><p>실시간/자동 업데이트</p>
<p>  → 슬라이더로 업데이트 주기(sec)만 넣아봤는데 진짜로 주기적으로 데이터가 갱신되는 대시보드도 구현해보고 싶다.</p>
</li>
<li><p>재무제표는 데이터프레임 형태로 더 깔끔하게 보여주기.</p>
</li>
<li><p>검색어가 비었을 때는 회사명을 입력해주세요 같은 안내 메시지 띄워주기.</p>
</li>
<li><p>보고서 프롬프트를 고쳐서 투자 초보자도 이해하기 쉽게 핵심 요약 같은 항목을 넣어보고 싶음.</p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[LG U+ Why Not SW CAMP 7기 14주차 회고]]></title>
            <link>https://velog.io/@feel_so_fine/LG-U-Why-Not-SW-CAMP-7%EA%B8%B0-14%EC%A3%BC%EC%B0%A8-%ED%9A%8C%EA%B3%A0</link>
            <guid>https://velog.io/@feel_so_fine/LG-U-Why-Not-SW-CAMP-7%EA%B8%B0-14%EC%A3%BC%EC%B0%A8-%ED%9A%8C%EA%B3%A0</guid>
            <pubDate>Sat, 16 Aug 2025 14:17:07 GMT</pubDate>
            <description><![CDATA[<h2 id="liked">Liked</h2>
<ul>
<li>크롤링 코드에서 댓글, 전체 HTML(풀 콘텐츠), URL 추출까지 흐름이 잡혀감.</li>
<li>soup.select()로 a 태그에서 href만 뽑는 방법을 다시 복습했고 원하는 데이터 위치를 더 정확하게 파악하게 됨.</li>
<li>MariaDB 연동하면서 컬럼 문제나 데이터 길이 문제도 직접 겪어보니까 DB 구조를 더 신경 써야겠다는 감이 옴.</li>
<li>SQL 문제(2018년도 지하철 최대/최소 이용자 월)도 RANK() 함수 활용해서 해결 완료!</li>
</ul>
<ol>
<li>API 연동 및 데이터 수집</li>
</ol>
<ul>
<li>공공데이터 API를 활용해 다량의 데이터를 가져오고 요청 파라미터 설정과 응답 구조 분석을 직접 해봄.</li>
<li>반복 요청 구조를 적용해 한 번의 실행으로 전체 데이터를 수집할 수 있도록 했다.</li>
</ul>
<ol start="2">
<li>MariaDB 적재</li>
</ol>
<ul>
<li>Python → MariaDB 연결까지 성공, INSERT로 API 데이터를 DB 테이블에 저장</li>
<li>테이블 스키마를 API 데이터에 맞춰 설계하고 한글 컬럼명 문제 없이 적재!</li>
<li>DB에서 직접 SELECT 조회하여 데이터가 정상 저장된 것을 확인!</li>
</ul>
<ol start="3">
<li>DuckDB 실습 시도</li>
</ol>
<ul>
<li><p>MariaDB 데이터와 별개로 CSV 기반 DuckDB 적재를 시도!</p>
</li>
<li><p><strong>여러 도구를 직접 설치·연결해 본 경험</strong></p>
<p>  Grafana, Prometheus, Windows Exporter, Metabase, Elasticsearch, Logstash, Kibana, MariaDB 커넥터까지 각각의 역할과 특징</p>
</li>
<li><p><strong>실제 데이터 흐름을 만들어봄</strong></p>
<p>  MariaDB → Logstash(JDBC) → Elasticsearch → Kibana로 데이터가 흘러서 테이블로 뜨는 걸 확인</p>
</li>
<li><p><strong>UI 도구들의 차이 이해</strong></p>
<p>  Grafana(실시간 모니터링), Metabase(비즈니스 분석), Kibana(로그·검색)</p>
</li>
</ul>
<h2 id="learned">Learned</h2>
<ul>
<li>MariaDB에서 Data too long for column 에러 → 컬럼 길이 조정이나 TEXT 타입 변경 필요.</li>
<li>Incorrect string value 에러 → UTF-8 인코딩 설정 중요</li>
</ul>
<ol>
<li>API → DB 적재 흐름</li>
</ol>
<ul>
<li>API 호출 후 바로 DB에 넣는 경우, 데이터 타입 변환과 컬럼 매핑이 중요함.</li>
<li>MariaDB에 적재 시 문자열 길이 제한, 날짜 포맷, 인코딩 이슈를 사전 확인해야 함.</li>
</ul>
<ol start="2">
<li>MariaDB 연결</li>
</ol>
<ul>
<li>Python mariadb 모듈로 커넥션 후 executemany()로 다중 데이터 삽입 시 속도가 향상!</li>
<li>테이블 존재 여부 확인 후 없으면 생성하는 로직을 넣어야 안전.</li>
</ul>
<ol start="3">
<li>DuckDB 차이점</li>
</ol>
<ul>
<li><p>파일 기반 DB라서 경로/권한 문제가 바로 영향을 미침ㅠ</p>
</li>
<li><p>pandas DataFrame을 바로 테이블로 등록 가능하고, SQL로 즉시 조회 가능함!</p>
</li>
<li><p><strong>Prometheus + Grafana 구조</strong></p>
<p>  데이터 수집(백엔드)과 시각화(UI) 역할을 분리하는 이유</p>
</li>
<li><p><strong>Windows Exporter 사용법</strong></p>
<p>  로컬·서버의 CPU, 메모리, 디스크 지표를 Prometheus로 수집 후 Grafana 대시보드에 표시</p>
</li>
<li><p><strong>Elasticsearch</strong></p>
<p>  8.x 버전에서 설치 시 기본 비밀번호·CA·토큰이 자동 생성, 클러스터 확장 시 토큰이 필요하다는 것</p>
</li>
<li><p><strong>Logstash JDBC</strong></p>
<p>  MariaDB 커넥터 설정</p>
</li>
<li><p><strong>Kibana 인덱스 조회 및 시각화</strong></p>
<p>  Elasticsearch 데이터가 Kibana에서 어떻게 나타나는지 확인</p>
</li>
</ul>
<h2 id="lacked">Lacked</h2>
<ul>
<li><p>크롤링 데이터 중 일부 페이지에서 태그 구조가 달라서 에러 처리 로직이 부족했음.</p>
</li>
<li><p>DB 저장 전 컬럼 타입과 길이를 미리 설계 안 해서 중간에 계속 에러가 발생.</p>
</li>
<li><p>API 수집 시 실패한 요청이나 빈 데이터 페이지에 대한 예외 처리 로직이 부족했다.</p>
</li>
<li><p>MariaDB 적재 시 대량 데이터 삽입에 대한 성능 최적화를 처음부터 적용하지 못했다.</p>
</li>
<li><p>DuckDB 연결 오류 → 환경 충돌이었다….</p>
<h2 id="longed-for">Longed For</h2>
</li>
<li><p>MariaDB 테이블 설계부터 크롤링 컬럼 길이, 인코딩까지 처음부터 세팅해보기.</p>
</li>
<li><p>SQL 문제 풀 때 MySQL/MariaDB 전용 문법과 다른 DB 문법 비교 학습.</p>
</li>
<li><p>크롤링한 데이터를 CSV로 저장해서 분석까지 연결해보기</p>
</li>
<li><p>중간중간 실무에서 어떤 방식과 흐름이 쓰이는지 강사님이 직접 설명해주셔서 상당히 유익한 시간이었다고 생각한다.</p>
</li>
<li><p>다만 진행 속도와 시간 제약 때문에 내가 작성한 코드나 흐름을 직접 리뷰해보는 시간이 없었던 점은 조금 아쉬웠다.</p>
</li>
<li><p>어쩔 수 없는 부분이지만 따로 시간을 내어 혼자 코드를 점검·정리하고, 잘못된 부분이나 개선 포인트를 직접 찾아보는 습관을 들여야겠다.</p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[LG U+ Why Not SW CAMP 7기 13주차 회고]]></title>
            <link>https://velog.io/@feel_so_fine/LG-U-Why-Not-SW-CAMP-7%EA%B8%B0-13%EC%A3%BC%EC%B0%A8-%ED%9A%8C%EA%B3%A0-6tied5y8</link>
            <guid>https://velog.io/@feel_so_fine/LG-U-Why-Not-SW-CAMP-7%EA%B8%B0-13%EC%A3%BC%EC%B0%A8-%ED%9A%8C%EA%B3%A0-6tied5y8</guid>
            <pubDate>Sat, 16 Aug 2025 14:10:47 GMT</pubDate>
            <description><![CDATA[<h2 id="liked">Liked</h2>
<ul>
<li><p>각 함수가 어떻게 동작하는지 이해하고 확인하며 학습했다.</p>
</li>
<li><p><code>aggregate</code>를 통해 자주 쓰이는 집계 방식을 직접 구현해봄으로써 RDD 연산의 원리를 이해하려 하였다.</p>
</li>
<li><p>에러가 발생했을 때 스킵하지 않고 하나씩 원인을 파악해가며 Spark 문법의 특징과 Python의 차이를 인식해 갔다.</p>
<h2 id="learned">Learned</h2>
</li>
<li><p><code>fold()</code> 함수</p>
<p>  <code>fold(zeroValue, func)</code>는 모든 파티션마다 <code>zeroValue</code>가 하나씩 적용되어 누적 계산된다.</p>
<p>  <code>sc.parallelize([2,3,4], 4)</code>처럼 파티션 수가 데이터 수보다 많다면 빈 파티션에도 <code>zeroValue</code>가 쓰이고 결과가 예상보다 커질 수 있다.</p>
</li>
<li><p><code>aggregate()</code></p>
<ul>
<li><code>aggregate(zeroValue, seqOp, combOp)</code>는 <code>zeroValue</code>에 대해 파티션 내외 두 가지 함수를 적용함으로써 평균 계산, 문자열 누적 등 복합 연산이 가능하다.</li>
<li><code>(합계, 개수)</code>를 튜플로 전달하여 전체 평균을 계산하는 방식은 <code>fold()</code>보다 명확하게 병렬 환경에서 상태를 유지할 수 있다.</li>
</ul>
</li>
<li><p>문자열 누적 예제 (<code>hello</code>, <code>world</code>, <code>spark</code>)</p>
<ul>
<li><code>aggregate</code>를 사용하면 문자열을 순차적으로 이어붙이면서 줄번호까지 함께 조작할 수 있다.</li>
<li><code>seqOp</code>과 <code>combOp</code>의 역할을 분리해 생각하는 것이 중요했고 <code>combOp</code>에서 index가 기대와 다르게 누적되는 이유는 각 파티션의 index가 별도로 관리되며 단순히 누적되어 최종 index가 커지는 구조이기 때문이다.</li>
</ul>
</li>
<li><p>RDD의 파티션 구조가 연산에 영향을 미친다는 것</p>
<ul>
<li><code>.glom().collect()</code>을 통해 파티션 구성을 확인함으로써 연산 결과가 어떻게 나오는지를 납득할 수 있었다.</li>
<li><code>[1, 5, 3, 9], [2, 8, 4, 7, 6]</code> 처럼 2개 파티션으로 구성되면 각 파티션마다 seqOp → combOp 순서로 집계됨을 직접 확인하였다.</li>
</ul>
</li>
<li><p><code>groupBy()</code>의 작동 방식</p>
<ul>
<li><code>groupBy(func)</code>는 값 전체를 그룹핑하여 이터레이터로 반환! 후처리 (<code>sorted</code>, <code>list(y)</code>)가 필요하다.</li>
<li>예제에서 짝/홀수 그룹, 카테고리별 매출 집계, 과목별 평균 성적 구하기를 실습하며 다양한 그룹 기준을 적용해볼 수 있었다.</li>
<li><code>groupBy</code>는 단순 그룹핑, <code>reduceByKey</code>는 그룹 후 연산 포함이라는 점도 이해하였다.</li>
</ul>
</li>
<li><p>PySpark에서의 논리 연산자 오류</p>
<ul>
<li><code>df.filter(df.col1 == &#39;A&#39; or df.col2 == &#39;B&#39;)</code> → Python에서는 작동하지만 Spark에서는 오류 발생</li>
<li>비트 연산자 (<code>|</code>, <code>&amp;</code>)를 써야 하며 각 조건은 괄호로 묶어야 오류 없이 작동한다는 걸 알게 되었다.</li>
<li><code>=&gt; df.filter((df.col1 == &#39;A&#39;) | (df.col2 == &#39;B&#39;))</code></li>
</ul>
<ul>
<li><code>StringIndexer</code>는 학습할 때(<code>.fit()</code>) 문자열 값을 숫자로 바꾸는 규칙을 미리 만들어두고
<code>OneHotEncoder</code>는 그 숫자를 벡터로 바꿀 수 있도록 틀을 준비해두고
<code>StandardScaler</code>는 숫자들을 정규화하기 위해 평균과 표준편차 같은 기준값을 미리 계산해두는 것</li>
</ul>
</li>
<li><p><code>VectorAssembler</code>는 단일 컬럼도 리스트로 받아야 하고 정규화를 위해 반드시 벡터형태로 먼저 만들어야 한다.</p>
</li>
<li><p>각 단계는 순차적으로 연결되며 <code>inputCol</code>과 <code>outputCol</code>을 꼼꼼히 맞춰야 전체 파이프라인이 오류 없이 작동한다는 점!</p>
</li>
<li><p>파이프라인을 통해 전처리를 코드로 반복 없이 구성할 수 있고 <code>.fit()</code> 한 번이면 test 데이터에도 동일한 기준으로 처리할 수 있음</p>
</li>
</ul>
<h2 id="lacked">Lacked</h2>
<ul>
<li><p><code>aggregate</code> 결과에서 index 값이 왜 예상보다 커지는지 이해하는 데 시간이 걸렸다. (→ 사실은 각 파티션이 독립적으로 index를 누적해서였다….)</p>
</li>
<li><p>PySpark 연산자에서 Python 스타일로 조건을 썼다가 연산자 우선순위 문제 + Py4JError 발생</p>
</li>
<li><p>오늘 뭔가 집중력이 평소보다 흐려진 느낌이 있었고 열심히 이해하려고 따라가긴 했지만 내가 이걸 진짜 알고 있나? 하는 찝찝함이 남기도 했다.</p>
</li>
<li><p>처음에 Logical/Optimized/Physical Plan을 해석하는 과정이 너무 낯설고 어렵게 느껴졌고 튜닝과 관련해서도 개념은 이해했지만 감이 안 잡혔다.</p>
</li>
<li><p>서비스존별 승차/하차 집계를 할 때 중복 조인, groupBy 위치 문제로 인한 이상 결과가 출력되는 상황을 디버깅하는 데 시간이 오래 걸렸다.</p>
</li>
<li><p><code>join → groupBy</code>와 <code>groupBy → join</code>의 순서 차이에 따라 결과가 완전히 달라진다는 걸 실습하면서 딱 문제로 만나 로직 설계 시 좀 더 미리 고민이 필요하다는 점을 느꼈다.</p>
</li>
</ul>
<h2 id="longed-for">Longed For</h2>
<ul>
<li>배운 파이프라인 구조를 바탕으로 내일은 실습 데이터셋에 적용해서 실제 의미 있는 분석을 수행하는 경험으로 연결하고 싶음!</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[LG U+ Why Not SW CAMP 7기 12주차 회고]]></title>
            <link>https://velog.io/@feel_so_fine/LG-U-Why-Not-SW-CAMP-7%EA%B8%B0-12%EC%A3%BC%EC%B0%A8-%ED%9A%8C%EA%B3%A0</link>
            <guid>https://velog.io/@feel_so_fine/LG-U-Why-Not-SW-CAMP-7%EA%B8%B0-12%EC%A3%BC%EC%B0%A8-%ED%9A%8C%EA%B3%A0</guid>
            <pubDate>Tue, 05 Aug 2025 05:27:26 GMT</pubDate>
            <description><![CDATA[<h2 id="liked">Liked</h2>
<ul>
<li>실제로 버튼 클릭, 입력창 전송, 링크 클릭 후 <code>driver.back()</code> 등 브라우저 내에서의 행동을 자동화하는 느낌이 직관적이었다.</li>
<li><code>implicitly_wait</code>, <code>WebDriverWait</code>을 통해 단순 <code>sleep()</code>보다 훨씬 유연한 대기 처리를 이해하게 된 점</li>
<li>HTTP 메서드별 목적과 구조 정리는 추후 API 테스트나 크롤링할 때도 큰 도움이 될 거라 느꼈다.</li>
<li>웹툰 정보 전체 흐름(목록 → 상세 → 저장)을 처음부터 끝까지 스스로 구현한 실습 경험 자체가 의미 있었음.</li>
<li><code>드라이버 껐다 켰다 하지 않기</code>, <code>driver.current_url</code>로 로그인 감지하기 등의 트러블슈팅을 적용해봤던 점이 좋았음.</li>
<li>연령 정보 추출을 <code>글자 그대로 가져오기</code>로 단순화한 게 정확도와 속도를 동시에 챙긴 선택이라고 생각.</li>
<li>크롤링하면서 발생하는 오류도 예외처리로 <code>오류 발생</code>이라 명시해둔 점이 안정적인 데이터 수집에 도움됨.</li>
</ul>
<h2 id="learned">Learned</h2>
<ul>
<li><code>webdriver.Chrome()</code>객체를 사용해 브라우저를 자동으로 실행하고 유지하는 방법</li>
<li><code>find_element</code>, <code>find_elements</code>의 차이와 요소 탐색 방식 (<code>by=&#39;id&#39;</code>, <code>&#39;name&#39;</code>, <code>&#39;css selector&#39;</code>, <code>&#39;link text&#39;</code> 등)</li>
<li>HTML 태그 구조를 기반으로 요소를 추적하고 값을 입력하고 클릭하는 방법</li>
<li><code>send_keys()</code>를 통해 실제 사용자처럼 폼 전송을 자동화하는 흐름</li>
<li><code>implicitly_wait</code> vs <code>WebDriverWait</code>을 통한 동기 vs 비동기 로딩 대기 처리</li>
<li><code>requests</code>로 단순 HTTP 요청을 보낼 수 있지만 비동기 로딩된 데이터는 Selenium으로만 처리 가능하다는 개념적 차이 확인</li>
<li>HTTP 메서드(GET, POST, PUT, PATCH)의 용도와 전송 방식</li>
<li><code>Selenium</code>과 <code>BeautifulSoup</code>을 함께 사용하여 동적 웹페이지에서 정보를 수집!</li>
<li>상세페이지로 자동 이동할 때 로그인 페이지로 리디렉션되는 경우 URL을 통해 감지하는 방법을 적용해봄.</li>
<li><code>.select_one().next_sibling.strip()</code>을 활용하면 태그에서 연령등급 같은 정보를 자연스럽게 추출할 수 있다는 걸 배움 (형제 태그에 적용이 된다고 함).</li>
<li><code>DataFrame.itertuples()</code>을 사용해서 <code>pymysql</code>과 함께 MySQL에 효율적으로 데이터를 삽입하는 방법을 익힘.</li>
<li>크롤링한 데이터를 DataFrame → CSV → MySQL로 이어지는 흐름으로 처리하면서 데이터 파이프라인 감각을 배움.</li>
<li>Docker의 전체 구조와 흐름을 처음부터 따라가며 이해하려 노력했다.<ul>
<li>컨테이너는 마치 독립된 가상 머신처럼 동작하지만 훨씬 가볍고 빠르며 그 핵심은 이미지 기반 실행이라는 것을 알게 됐다.</li>
</ul>
</li>
<li>Ubuntu에서 Docker를 설치하는 과정을 직접 따라가며 GPG 키, 저장소 등록, 패키지 설치의 개념을 배웠다.</li>
<li>Nginx 웹 서버를 도커 컨테이너로 띄우고 실제 브라우저로 접근하는 실습을 했다.</li>
<li>IP, 포트, 호스트 이름, DNS 등 네트워크 통신의 기초 개념에 대해 정리했다. 단순히 주소만 있는 게 아니라 포트가 어떤 프로그램인지 지정해주는 역할이라는 것도 알았다.</li>
</ul>
<h2 id="lacked">Lacked</h2>
<ul>
<li>Selenium과 Requests의 역할 구분은 배웠지만, 실제로 어떤 사이트가 비동기인지 아닌지를 직접 판별하고 선택하는 능력은 부족하다고 느낌.</li>
<li>알아낸 것만으로 만족하고 넘겨버린 태도<ul>
<li>코드가 돌아가면 됐지하고 다음으로 넘어간 경우가 있었음.</li>
<li>왜 그런 방식이 더 좋은지, 예외 상황에선 어떻게 될지까지 고민해보는 깊이가 부족했다고 느낌</li>
</ul>
</li>
<li>페이지 로딩이 느릴 경우 <code>WebDriverWait</code>이 아닌 <code>time.sleep()</code>만 사용한 점이 비효율적일 수 있음.</li>
<li>Selenium으로 여러 링크를 열 때 브라우저 창이 안 뜨는 현상이 있었고 원인을 명확히 파악하진 못했음.</li>
<li>원하는 요소를 제대로 가져오지 못하는 경우가 꽤 있었음.</li>
<li><code>컨테이너랑 내 컴퓨터랑 포트를 어떻게 연결하는지</code>, <code>호스트네임이 뭐고, IP는 뭘 쓰는 건지</code> 이런 기본 개념이 아직도 좀 헷갈린다. 단어가 너무 생소해서 명확하게 구분이 안 된다. 내 로컬 IP가 뭔지 컨테이너 내부 IP가 뭔지처럼…?</li>
<li><code>docker volume</code> 개념도, 그냥 <code>v</code> 옵션을 쓰면 되는 줄 알았는데 빈 디렉토리일 때만 제대로 작동한다는 조건이 있다는 게 처음엔 이해가 안 됐다. 실습해보고 덮어쓰기 되는 걸 눈으로 보니까 알겠는데 아직도 왜 그런지 납득되진 않았다.</li>
<li>GitHub에 올릴 때는 또 인증이 안 되고 충돌이 나고, <code>pull</code>, <code>push</code>, <code>merge</code>가 계속 오류나서 정신이 없었다. 토큰 로그인, 브랜치 이름 문제, 리드미 병합 충돌... 진짜 혼란 그 자체였다.</li>
</ul>
<h2 id="longed-for">Longed For</h2>
<ul>
<li>공모전에서 써먹을 수 있는 자동화 파이프라인을 직접 만들어보고 싶다<ul>
<li>데이터를 주는 곳은 많은데 수집, 정제, 저장까지 자동화되면 시간도 아끼고 완성도도 높아질 것 같다.</li>
</ul>
</li>
<li>요즘 너무 졸리고 머리도 자주 아프고..<ul>
<li>하고 싶은 건 많은데 몸이 따라주지 않을 때는…… 리듬 잘 챙겨야겠다…!</li>
</ul>
</li>
<li>아침에 자동으로 날씨 크롤링해서 슬랙 정도?로 알려주는 봇 만들어보고 싶다<ul>
<li>실제 생활에 딱 붙는 자동화일 것 같고 친구들이랑 공유하면 뭔가 뿌듯할 것 같음 ㅎㅎ</li>
</ul>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[LG U+ Why Not SW CAMP 7기 11주차 회고]]></title>
            <link>https://velog.io/@feel_so_fine/LG-U-Why-Not-SW-CAMP-7%EA%B8%B0-11%EC%A3%BC%EC%B0%A8-%ED%9A%8C%EA%B3%A0</link>
            <guid>https://velog.io/@feel_so_fine/LG-U-Why-Not-SW-CAMP-7%EA%B8%B0-11%EC%A3%BC%EC%B0%A8-%ED%9A%8C%EA%B3%A0</guid>
            <pubDate>Mon, 28 Jul 2025 23:59:41 GMT</pubDate>
            <description><![CDATA[<h2 id="liked">Liked</h2>
<ul>
<li>단순 선형 회귀에 비해 다항 회귀로 성능이 확실히 향상된다는 점을 확인했다.</li>
<li>다항차수를 1~5까지 올리면서 RMSE, R2의 변화를 시각화하여 과적합 구간을 정확히 파악한 점이 좋았다.</li>
<li>성능 수치만 보는 것이 아니라 랜덤포레스트와 비교하며 모델 선택에 대해 고민한 것이 인상 깊었다.</li>
<li>단순히 PCA → KMeans의 조합이 아닌 2~10개의 주성분을 for문으로 반복 실험하여
explained_variance_ratio_와 silhouette_score를 병렬로 기록하였다.</li>
<li>분산 설명력과 군집 품질 간 trade-off를 수치 기반으로 확인했다.</li>
<li>군집 수를 고정한 KMeans와 군집 수를 자동으로 찾는 DBSCAN을 모두 실험해보며 클러스터링 알고리즘의 특성과 장단점을 실습을 통해 배웠다.</li>
</ul>
<h2 id="learned">Learned</h2>
<ul>
<li><p><strong>MSE와 RMSE의 차이와 해석 방법</strong></p>
<ul>
<li>개념: MSE는 오차의 제곱 평균으로 단위가 커지고 직관성이 낮다. RMSE는 단위를 실제값과 맞춰 직관적인 해석이 가능하다.</li>
<li>느낀 점: <code>MSE</code>가 3천만 단위여도 이상한 게 아니며 실제 오차 규모를 판단할 땐 <code>RMSE</code>를 봐야 한다는 걸 직접 체감했다.</li>
</ul>
</li>
<li><p><strong>R2(결정계수)의 의미와 한계</strong></p>
<ul>
<li>개념: R2는 예측 모델이 실제 데이터를 얼마나 잘 설명하는지를 0~1 사이로 나타낸 지표로 1에 가까울수록 좋다.</li>
<li>느낀 점: 단순 선형에서는 R2가 낮았지만 2차 다항에서 급격히 올라가는 걸 보며 비선형성을 잘 반영하는 모델이 더 설명력이 크다는 걸 이해했다.</li>
</ul>
</li>
<li><p><strong>다항 회귀의 차수와 과적합 관계</strong></p>
<ul>
<li>개념: 다항 회귀는 차수가 높아질수록 데이터에 더 잘 맞지만 과도하면 학습 데이터에만 특화되어 새로운 데이터에 약해지는 과적합 문제가 발생한다.</li>
<li>느낀 점: 3~5차 회귀에서 RMSE와 R2가 다시 나빠지는 것을 보고 복잡하다고 좋은 게 아니라는 걸 명확히 알게 되었다.</li>
</ul>
</li>
<li><p><strong>랜덤포레스트의 비선형적 특성과 다항 특성의 효과</strong></p>
<ul>
<li>개념: 랜덤포레스트는 이미 트리 구조로 비선형 경계를 학습할 수 있어서 추가적인 다항 특성을 굳이 넣지 않아도 복잡한 관계를 학습할 수 있다.</li>
<li>느낀 점: 선형 모델에서는 다항 특성 추가가 효과적이지만 RF에서는 오히려 성능이 정체되거나 떨어졌고, 모델 특성에 맞는 전처리가 중요하다는 걸 배웠다.</li>
</ul>
</li>
<li><p><strong>cross_val_score를 활용한 일반화 성능 평가</strong></p>
<ul>
<li>개념: train_test_split은 단 1회의 분할이라서 운에 따라 결과가 달라질 수 있지만 교차검증은 데이터를 여러 번 나눠 평균적으로 성능을 측정하므로 일반화 성능 파악에 더 적합하다.</li>
<li>느낀 점: 같은 모델이라도 교차검증 점수가 낮게 나올 수 있고 과대평가된 테스트셋 점수만 믿으면 안 된다는 걸 실제 차이로 느꼈다.</li>
</ul>
</li>
<li><p>make_scorer를 활용한 cross_val_score 커스터마이징 방법을 익혔다.</p>
</li>
<li><p>scikit-learn에서 로그값을 타겟으로 사용할 때  역변환 기반으로 평가 지표를 정의해야 모델 성능을 실제 해석 단위로 비교할 수 있다는 점을 이해했다.</p>
</li>
<li><p>불균형 이진 피처 제거의 효과 (중고차 데이터)
전체 피처 중 bool 타입의 칼럼에서 불균형 분포(0.05 미만 또는 0.95 초과)를 제거하니 약 70개 이상이 제외되었고 모델 성능에 긍정적인 영향을 준다. 불필요한 노이즈를 줄여줌.</p>
</li>
<li><p><strong>KMeans 알고리즘</strong>은 중심점을 기준으로 데이터를 군집화하는 방식!</p>
<ul>
<li>군집의 수(k)를 미리 지정해야 하고,구형 형태의 군집에 적합하다는 특징이 있다.</li>
<li>실루엣 분석과 엘보우 기법 등을 통해 적절한 k를 찾을 수 있으며 각 군집의 응집도와 분리도를 시각적으로 평가할 수 있다.</li>
</ul>
</li>
<li><p><strong>PCA (주성분 분석)</strong>는 고차원 데이터를 더 적은 차원으로 줄이면서도 최대한 정보(분산)를 보존하려는 방법이라는 점!</p>
<ul>
<li>각 주성분은 데이터의 변동을 많이 담는 방향으로 정렬되며 서로 직교한다는 수학적 구조 덕분에 불필요한 차원을 제거하고 시각화나 모델 성능 향상에 큰 도움이 된다.</li>
<li>스크리 차트와 누적 설명 분산 비율 개념은 주성분 개수 선택에 핵심적임!</li>
</ul>
</li>
<li><p><strong>DBSCAN 알고리즘</strong>은 KMeans의 한계를 보완하는 밀도 기반 군집화 기법</p>
<ul>
<li>군집 수를 미리 지정할 필요 없이 데이터의 밀도 차이를 기반으로 자율적으로 군집을 형성한다는 점이 가장 인상 깊었다.</li>
<li>잡음 포인트(-1)를 별도로 구분해내고 복잡한 모양의 군집도 잘 탐지할 수 있는 구조라서 노이즈가 많거나 비선형 구조의 데이터에 매우 강력한 도구임을 알게 되었다.</li>
<li><strong>eps와 min_samples</strong>는 DBSCAN의 핵심 파라미터로 밀도의 기준을 정하는 중요한 요소임을 배웠다.</li>
</ul>
</li>
<li><p>고차원 데이터에서는 DBSCAN의 거리 개념이 왜곡될 수 있다는 점도 알게 되었고 이를 보완하기 위해 PCA와 함께 사용하는 것이 효과적이라는 점을 통해  차원 축소와 군집화가 함께 연동되어야 하는 경우가 많다는 걸 이해하게 되었다.</p>
</li>
</ul>
<h2 id="lacked">Lacked</h2>
<ul>
<li><p>다항 차수 증가 시 학습 시간이나 feature 수 증가에 따른 모델 복잡도에 대한 평가는 아직 미흡했다.</p>
</li>
<li><p>변수 중요도 관점에서 선형 모델과 트리 기반 모델의 차이를 비교해보는 시도는 부족했다.</p>
</li>
<li><p>모델별로 오차가 큰 구간이 어디인지 등 잔차 분석이나 예측 오류 시각화는 조금 부족했다.</p>
</li>
<li><p>중고차 데이터에서 모델별 성능 차이가 뚜렷하게 드러나지 않았고 모든 모델의 성능이 비슷하게 낮은 것으로 나타났다.</p>
<p>  → 이는 인코딩 오류,  feature 설계 미흡, 불필요한 컬럼 존재 등이 원인일 수 있음.</p>
</li>
<li><p>하이퍼파라미터 튜닝 전 성능 평가에서 정리 부족</p>
</li>
<li><p>현재 상태에서 XGBoost가 Test RMSE는 가장 낮지만 CV RMSE 기준으로는 RandomForest가 앞서기도 하는 결과가 나왔음. 이 차이가 왜 발생하는지 모델의 구조와 학습 방식 차이 측면에서 해석해보는 시도가 부족했다.</p>
</li>
</ul>
<h2 id="longed-for">Longed For</h2>
<ul>
<li>다항 특성 확장 후의 feature 수 증가, 모델 학습 시간, 과적합 경향을 더 체계적으로 분석하는 방향으로 확장해 보고 싶다.</li>
<li>성능 외에도 학습 속도, 해석 가능성, 튜닝 편의성 등 다양한 관점에서 모델들을 비교 분석해보고 싶다.</li>
<li>불균형 대응 전략 확장<ul>
<li>다양한 오버샘플링 방식 실험</li>
<li>언더샘플링과 앙상블 결합</li>
</ul>
</li>
<li>모델 해석성 강화<ul>
<li>SHAP값 시각화로 XGBoost 모델의 예측 근거를 고객 단위로 해석</li>
</ul>
</li>
<li>모델 앙상블<ul>
<li>GradientBoosting + XGBoost의 soft voting 실험</li>
<li>stacking 기법 적용</li>
</ul>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[LG U+ Why Not SW CAMP 7기 10주차 회고]]></title>
            <link>https://velog.io/@feel_so_fine/LG-U-Why-Not-SW-CAMP-7%EA%B8%B0-10%EC%A3%BC%EC%B0%A8-%ED%9A%8C%EA%B3%A0</link>
            <guid>https://velog.io/@feel_so_fine/LG-U-Why-Not-SW-CAMP-7%EA%B8%B0-10%EC%A3%BC%EC%B0%A8-%ED%9A%8C%EA%B3%A0</guid>
            <pubDate>Sun, 20 Jul 2025 08:48:17 GMT</pubDate>
            <description><![CDATA[<h2 id="liked">Liked</h2>
<ul>
<li><p>하이퍼파라미터 튜닝을 단순히 점수만 보는 게 아니라 best_params와 best_score 그리고 실제</p>
<p>  accuracy를 함께 비교하면서 교차검증 기준 vs 테스트셋 기준이 다를 수 있음을 인지했다.</p>
<p>  → 모델이 교차검증에선 안정적으로 보이지만 테스트셋에서는 성능이 다를 수 있다는 점까지 연결된 점이 좋았다.</p>
</li>
<li><p>라벨 인코딩(<code>LabelEncoder</code>)과 원-핫 인코딩(<code>get_dummies</code>)의 차이를 실제 성능으로 비교해보고</p>
<p>  모델이 어느 정도 영향을 받는지 탐색했다는 점이 좋았다.</p>
<p>  → 인코딩 방식이 의미하는 바까지 고민</p>
</li>
<li><p>단순히 모델 학습에 그치지 않고 Precision-Recall Curve를 활용한 threshold 튜닝까지 진행했다는 점이 가장 만족스러웠다.</p>
</li>
<li><p>XGBoost와 LightGBM 등의 앙상블 모델 비교를 통해 모델 간 성능 차이를 분석할 수 있었다.</p>
</li>
<li><p>SMOTE를 통해 불균형 클래스 문제를 실제로 해결해보며 모델 성능이 어떻게 변하는지 알 수 있었다.</p>
</li>
<li><p>피처 중요도 시각화를 통해 모델이 어떤 변수에 더 많이 의존하는지를 파악할 수 있었고 데이터 인사이트까지 연결해볼 수 있었다.</p>
</li>
<li><p>실습 흐름이 구조화되어 있어 실전 데이터 분석 프로젝트처럼 느껴졌다.</p>
<h2 id="learned">Learned</h2>
</li>
<li><p>데이터를 모델에 넣기 전, 항상 <code>X</code> (입력 피처)와 <code>y</code> (타겟 값)를 명확하게 구분해야 한다.</p>
</li>
<li><p>교차검증 기반 하이퍼파라미터 튜닝 흐름을 배웠다.</p>
<ul>
<li><p><code>GridSearchCV</code> 를 사용하여 best_params를 찾아보았다.</p>
</li>
<li><p>결정트리 모델에서 <code>max_depth</code>, <code>min_samples_split</code>, <code>min_samples_leaf</code>를 튜닝했을 때</p>
<p>  실제 성능이 어떻게 달라지는지를 직접 확인해보았다.</p>
</li>
</ul>
</li>
<li><p>원-핫 인코딩과 라벨 인코딩의 적용 차이</p>
<p>  → 타이타닉 데이터에서 <code>pd.get_dummies()</code>와 <code>LabelEncoder</code>가 모델 성능에 직접 어떤 영향을 주는지     직접 보았다.</p>
</li>
<li><p>교차검증의 필요성</p>
<p>  데이터가 적거나 분포가 불균형할 경우, 한 번의 train/test 분할로는 모델을 신뢰할 수 없음</p>
<blockquote>
<p>StratifiedKFold는 클래스 불균형이 있는 분류 문제에서 클래스 비율 유지라는 큰 장점이 있음.</p>
</blockquote>
</li>
<li><p>피처 중요도 = 계수의 의미: <code>lr.coef_</code>을 <code>pd.Series</code>로 바꿔서 <code>.sort_values()</code>로 정렬하면, 각 피처가 생존 예측에 얼마나 영향 미치는지 확인할 수 있다는 걸 배웠다.</p>
</li>
<li><p>Threshold 조정의 의미와 적용법: <code>predict_proba()</code>로 확률을 얻은 뒤 <code>threshold</code>를 바꿔가며 예측 결과를 바꾸는 방식 <code>custom_proba</code> 가 모델의 재현율이나 F1-score을 컨트롤할 수 있다는 걸 직접 확인했다.</p>
</li>
<li><p>XGBoost와 LightGBM 사용 시 주의사항:</p>
<ul>
<li>XGBoost는 타겟 레이블이 반드시 0부터 시작해야 함 (<code>[0, 1, 2, ...]</code>)</li>
<li>LightGBM은 피처 이름에 <code>()</code>, , <code>,</code> 같은 JSON 특수문자가 있으면 에러를 발생시킨다는 것!</li>
<li>각각의 모델이 쓰기 전엔 몰랐던 제약 조건이 있다는 걸 깨달음.   </li>
</ul>
</li>
<li><p><code>classification_report</code>를 통해 Accuracy보다 정밀도(Precision), 재현율(Recall), F1-score가 얼마나 중요한지 다시 한번 느꼈다.</p>
</li>
<li><p>모델에 따라 특정 성별의 Recall이 유독 낮아질 수 있음을 확인했고, 이는 데이터 불균형 혹은 피처 편향성과 연결될 수 있다는 점도 이해했다.</p>
<h2 id="lacked">Lacked</h2>
</li>
<li><p>random_state=42를 습관적으로 쓰고 있었지만 정확한 의미나 이유 없이 외우고 있었던 것을 돌아보게 됐다.</p>
</li>
<li><p>스케일링(LogisticRegression) 유무가 성능에 영향을 주지 않았던 것에 대해선</p>
<p>  모델 구조에 따라 전처리 영향력이 다르다는 인사이트로 남기기로……</p>
</li>
<li><p>하이퍼파라미터 튜닝은 일부만 수행되었고 GridSearch나 CrossValidation 등을 적용해 모델 성능을 더 체계적으로 높여볼 여지가 있었다.</p>
</li>
<li><p>성별이라는 특성을 예측하는 문제이니만큼 편향성에 대해 더 깊게 접근할 필요가 있다는 점도 떠올랐지만 깊이 다루진 못했다.</p>
</li>
<li><p>SMOTE를 적용했을 때 학습 데이터와 실제 평가 데이터 간의 분포 차이를 좀 더 정밀하게 비교하지 못한 점이 아쉬웠다. 실제 데이터에선 오히려 과적합이 될 수도 있다는 생각이 들긴했는데… 오버샘플링 후 리스크 분석이 부족했다.</p>
</li>
<li><p>너무 많은 개념과 용어를 한꺼번에 접하다 보니, 어느 순간부터 정신이 멍해졌다.</p>
</li>
<li><p>특히 어려웠던 건:</p>
<ul>
<li>조건부 확률에서 계산하는 것….</li>
<li>베이즈 정리에서 어떤 게 사전이고 어떤 게 사후인지….</li>
<li><code>binom.cdf()</code>로 계산한 값이 실제로 뭘 의미하는지</li>
<li>이상(≥), 이하(≤)를 바꿔 쓸 때 왜 1에서 빼는지</li>
<li>시각화 그래프에서 왜 특정 막대만 색을 바꾸는지</li>
</ul>
</li>
<li><p>확률분포 그래프를 그렸지만 그게 내 머릿속에 정리되는 건 아니었다.</p>
<p>  그냥 그래프가 생기긴 했는데… 그랬구나…&quot;하는 느낌이었다.</p>
</li>
</ul>
<h2 id="longed-for">Longed For</h2>
<ul>
<li><p>앙상블 모델을 단순 Voting이 아닌 <strong>Stacking 기법으로 구성</strong>해보고, 복수 모델 조합의 시너지를 확인해보고 싶다.</p>
</li>
<li><p>파생변수 생성을 더 적극적으로 해보고 싶다.
총구매금액 대비 환불 비율, 방문당 평균 구매액, 주구매상품의 전체 내 비중 같은 변수들을 새로 만들면 모델이 고객의 구매 패턴을 더 잘 학습할 수 있을 것 같다.
이번에는 잘 몰라서 시도하지 못했지만 다음 분석에서는 필요하다면 도전해봐야겠다.</p>
</li>
<li><p>확률분포 그래프도 그냥 그리는 게 아니라</p>
<p>  이 막대 하나가 무슨 의미인지 직접 말로 설명할 수 있을 정도의 감각을 갖고 싶다.</p>
</li>
<li><p>그리고... 아직 포아송, 정규, 베르누이 같은 말들도 내 언어가 된 건 아닌 것 같다.</p>
<p>  너무 많은 걸 한 번에 보지 말고 내일은 천천히 다시 보는 걸 목표로 해보고 싶다.</p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[LG U+ Why Not SW CAMP 7기 9주차 회고]]></title>
            <link>https://velog.io/@feel_so_fine/LG-U-Why-Not-SW-CAMP-7%EA%B8%B0-9%EC%A3%BC%EC%B0%A8-%ED%9A%8C%EA%B3%A0</link>
            <guid>https://velog.io/@feel_so_fine/LG-U-Why-Not-SW-CAMP-7%EA%B8%B0-9%EC%A3%BC%EC%B0%A8-%ED%9A%8C%EA%B3%A0</guid>
            <pubDate>Tue, 15 Jul 2025 03:03:08 GMT</pubDate>
            <description><![CDATA[<h2 id="liked">Liked</h2>
<ul>
<li><p><code>EXPLAIN ANALYZE</code>를 통해 <code>Filter</code>, <code>Index range scan</code>, <code>Table scan</code>, <code>Covering index</code> 등 각 키워드를 하나하나 직접 찾아보았다. → 이해는 아직 잘……</p>
</li>
<li><p><code>EXPLAIN ANALYZE</code>를 통해 옵티마이저의 예상과 실제 실행 결과가 얼마나 다를 수 있는지 비교할 수 있었다.</p>
</li>
<li><p><code>ON DELETE CASCADE</code>나 <code>ADD CONSTRAINT</code> 구문에서 구조적인 의존관계를 파악하고 적용하는 것 같았다.</p>
</li>
<li><p>이름 없이도 되는 거 아닐까처럼 혼자 의문을 던지고 질문을 구성했던 흐름이 연습하기에 좋았던 것 같다.</p>
</li>
<li><p>ERD에서 흔히 나오는 관계(1:N, N:M)의 개념과 실체를 정확히 이해하고, 이를 수강신청, 도서 주문, 리뷰 작성 등 다양한 시나리오에 구체적으로 적용해보는 과정을 통해 구조 이해를 넘어 관계형 사고가 무엇일까 고민해보게 됨.</p>
<ul>
<li>개념 모델링 → 논리 모델링 → 물리 모델링의 세 단계 모델링 흐름을 실제 온라인서점 시나리오에 적용해 보며 단계마다 표현 수준과 추상도가 어떻게 다른지 분명히 체감했다.</li>
<li>개념 모델링: 학생이 수강신청한다 / 고객이 리뷰를 남긴다 같은 현실의 개체와 관계 정의</li>
<li>논리 모델링: 실제 엔티티, 속성, 관계, 다중성을 명확히 표기한 ERD 설계</li>
<li>물리 모델링: SQL 테이블(CREATE TABLE) 수준으로 변환할 준비</li>
</ul>
</li>
<li><p>WITH AS (CTE) 활용과 DENSE_RANK()를 조합해 고객별 구매 순서를 정하고이를 통해 재구매 간격 분석까지 흐름을 설계하는 능력이 생김!</p>
</li>
</ul>
<h2 id="learned">Learned</h2>
<ul>
<li><p>윈도우 함수(RANK, DENSE_RANK) 의 동작 원리와 차이를 예제와 함께 익혔고 쿼리에서 이 함수들을 어떻게 활용할 수 있는지도 정리했다.</p>
</li>
<li><p>뷰(View)에 INSERT 할 때 기반 테이블의 제약조건까지 영향을 준다는 점을 배웠고 오류 해결을 위해 기본값을 설정하거나 명시적으로 값을 주는 방식도 함께 익혔다.</p>
</li>
<li><p><code>DECIMAL(4,1)</code> 의 구조, <code>MODIFY</code>와 <code>ADD CONSTRAINT</code>의 차이, 외래키 제약조건 수정 불가 등의 DDL 관련 규칙과 예외 사항도 체계적으로 정리되었다.</p>
</li>
<li><p><code>WITH</code>(CTE)와 서브쿼리의 구조적 차이와 장단점도 정리하며 가독성과 유지보수 측면에서 CTE의 유용성을 느꼈다.</p>
</li>
<li><p>외래키 제약조건은 수정 불가능하며 기존 외래키 옵션을 바꾸려면 반드시 DROP 후 ADD를 해야 한다는 점.</p>
</li>
<li><p>함수적 종속성 개념을 이해하고 어떤 속성이 어떻게 결정되는지를 직접 분석해보았다.</p>
</li>
<li><p><code>고객ID + 도서번호 + 대여일자</code>처럼 복합키 기반 함수적 종속성을 실제 테이블로 풀어보며 부분 종속과 이행 종속의 차이도 이해할 수 있었다.</p>
</li>
<li><p>2정규화(2NF), 3정규화(3NF) 과정을 통해 테이블을 세분화하며 이상현상을 줄이는 과정을 직접 해보았고 ERD에서의 관계선 방향, 기본키/외래키 설정, 대여번호(PK) 도입의 필요성까지 현실적인 설계 감각도 익힐 수 있었다.</p>
</li>
<li><p>반정규화의 개념과 장단점을 예시와 함께 이해하여 정규화와 성능 사이의 딜레마(?)를 고민하게 되었다.</p>
</li>
<li><p>t검정(t-test)의 의미와 적용 방식을 구체적으로 이해했다.</p>
<p>  단일표본 t검정에서는 모집단 평균과의 차이를 이표본 t검정에서는 두 집단 평균 간 차이를 검정하는 목적임을 파악했다.</p>
</li>
<li><p><code>t값</code>은 표본 평균이 기준 평균에서 얼마나 떨어져 있는지를 표준오차 단위로 나타낸 값이고 <code>p값</code>은 이런 정도의 차이가 우연히 나타날 확률이라는 걸 수치적으로 받아들일 수 있었다.</p>
</li>
<li><p><code>t = 5.331</code>, <code>p = 0.0000604698</code>처럼 구체적인 값으로 해석할 때 표준오차의 5배 이상 차이가 난다면 이는 통계적으로도 실제로도 큰 차이라는 표현이 설득력 있게 다가왔다.</p>
</li>
</ul>
<h2 id="lacked">Lacked</h2>
<ul>
<li><p>강제 인덱스 사용 시 예상 <code>rows=1</code>이 실제로는 <code>24</code>가 나오는 등 옵티마이저의 판단 오류를 본 사례에서 왜 통계 정보가 잘못됐는지를 구조적으로 해석하긴 어려웠다. → <code>ANALYZE TABLE</code> 보는 연습이 필요함을 느꼈다.</p>
</li>
<li><p>뷰에 INSERT 시 테이블의 제약조건까지 고려하지 못하고 단순히 보이는 구조로만 생각한 점은 실수였다.</p>
</li>
<li><p><code>COUNT(*)</code> 와 <code>COUNT(DISTINCT ...)</code>의 차이를 처음엔 직관적으로 구분하지 못했고 GROUP BY 이후 컬럼 구조가 바뀐다는 개념을 좀 더 명확히 할 필요가 있을 것 같다.</p>
</li>
<li><p>데이터 타입 자동 변환(BETWEEN &#39;20&#39; AND &#39;29&#39;)에 의존하는 습관도 위험할 수 있다는 점을 다시 생각하게 되었다.</p>
</li>
<li><p>개념모델링에서 정의한 관계를 논리모델링으로 풀어내는 과정에서중간에 속성인지 엔티티인지 구분이 애매했던 지점이 몇 번 있었고다중성 표현(1:N, N:M)도 명확하지 않았음.</p>
</li>
<li><p>ERD에서 점선/실선의 의미나 관계를 속성으로 표현하는 방식 vs 별도 관계로 분리하는 방식의 선택 기준이 판단이 어려워 더 실습이 필요하다고 느낌.</p>
</li>
</ul>
<p><code>p값이 작으면 왜 귀무가설을 기각하는 걸까?</code></p>
<p><code>기각하면 무조건 대립가설이 맞다는 뜻일까?</code> 같은 의문이 들었고</p>
<p>그때그때 설명을 다시 읽으면서 조금씩 이해해 나갔다.</p>
<p><code>t값</code>과 표준오차의 관계도 처음엔 수식적으로만 아는 느낌이었지</p>
<p>실제로 표본 평균이 얼마나 많이 다른지를 생각해보는건 부족했다.</p>
<p><code>t = 5.3이면 차이 크네라고 받아들이기보단 그냥 숫자로만 봤던 것 같다.</code></p>
<p>그 차이가 실제로 얼마나 흔치 않은지 얼마나 의미 있는지를 해석하는 능력이 더 필요하다고 느꼈다.</p>
<h2 id="longed-for">Longed For</h2>
<ul>
<li>논리모델링까지 해둔 실습을 실제 SQL DDL 코드로 정규화된 테이블로 만들어보고 예시 데이터를 직접 INSERT 해보고 싶다.</li>
<li>정규화된 구조에서 JOIN 쿼리를 작성해보고 반정규화된 구조와 비교해 쿼리 복잡도와 속도 차이도 분석해보고 싶다.</li>
<li>반정규화가 적용된 사례나 실무 시스템에서 어떤 기준으로 정규화를 타협하는지 예시를 찾아봐야겠다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[LG U+ Why Not SW CAMP 7기 8주차 회고]]></title>
            <link>https://velog.io/@feel_so_fine/LG-U-Why-Not-SW-CAMP-7%EA%B8%B0-8%EC%A3%BC%EC%B0%A8-%ED%9A%8C%EA%B3%A0</link>
            <guid>https://velog.io/@feel_so_fine/LG-U-Why-Not-SW-CAMP-7%EA%B8%B0-8%EC%A3%BC%EC%B0%A8-%ED%9A%8C%EA%B3%A0</guid>
            <pubDate>Tue, 08 Jul 2025 02:49:03 GMT</pubDate>
            <description><![CDATA[<h2 id="liked">Liked</h2>
<p>예전에 오라클로 SQL 짰던 기억이 하나둘씩 떠오르면서 감각이 되살아나는 느낌이라 되게 재밌었다.</p>
<p>LIKE, BETWEEN, DISTINCT, IN 같은 키워드들이 손에 익는 느낌이 있었고</p>
<p>내가 직접 조건을 걸고 데이터 필터링해보는 과정에서 그때도 자주 썼었지 싶은 익숙함이 돌아와서 공부가 좀 더 수월하게 느껴졌다.</p>
<p>그냥 문법만 배운 게 아니라 다양한 조건을 조합해서 내가 원하는 대상을 정확히 골라내는 훈련이 된 것 같아서 좋았다.</p>
<ul>
<li><p>SELF JOIN, OUTER JOIN을 연습하면서 단순히 문법만 확인한 게 아니라 쿼리의 해석 구조와 출력 결과까지 논리적으로 따져본 점이 정말 좋았다.</p>
</li>
<li><p><code>선배-후배 관계</code>, <code>사원이 없는 부서</code>, <code>부서가 없는 사원</code> 문제를 풀면서 고민을 오래 해봤다.</p>
</li>
<li><p><code>UNION</code>으로 FULL OUTER JOIN을 흉내내는 방식이 신선했다.</p>
<h2 id="learned">Learned</h2>
</li>
<li><p><code>SHOW COLUMNS FROM</code>이 <code>DESCRIBE</code>보다 조금 더 유연하고 뷰에도 적용할 수 있다는 걸 새롭게 알게 됐고</p>
</li>
<li><p><code>information_schema.tables</code>를 조회하면 현재 데이터베이스에 어떤 테이블들이 있는지 확인할 수 있다는 것도 다시 익혔다.</p>
</li>
<li><p><code>LIKE &#39;%45&#39;</code>는 문자열이 &#39;45&#39;로 끝나는 경우이고</p>
<p>  <code>LIKE &#39;%45%&#39;</code>는 어디든 &#39;45&#39;가 포함된 경우라는 걸 예제로 직접 써보며 구분했다.</p>
</li>
<li><p><code>BETWEEN A AND B</code>는 양쪽 경계값을 포함한다는 점을 실습하면서 다시 짚었고</p>
</li>
<li><p><code>DISTINCT 지역, 도시</code>는 각각의 컬럼 기준이 아니라 두 컬럼이 함께 중복되지 않는 조합 기준이라는 점을 알았다.</p>
</li>
<li><p><code>IN</code> 조건은 정확히 일치해야만 작동하고 조금이라도 다르면 잡히지 않는다는 걸 다시 확인하면서</p>
<p>  텍스트 조건을 쓸 땐 <code>LIKE</code>가 더 유연하게 쓸 수 있다는 걸 정리했다.</p>
</li>
</ul>
<p>전체적으로는 다시 쓰니까 기억이나고 쓰면서 더 확실해지는 그런 시간이었다.</p>
<ul>
<li><code>LEFT JOIN</code>과 <code>RIGHT JOIN</code>을 <code>UNION</code>으로 합치면 MySQL에서 <code>FULL OUTER JOIN</code>을 구현할 수 있다는 것을 확실하게 이해했다.</li>
<li><code>SELF JOIN</code>은 꼭 관리자-사원 구조뿐 아니라 입사일 기준 비교 마일리지 비교 처럼 자기 자신과의 상대적 관계를 분석할 때 자주 쓰인다는 걸 배웠다.</li>
<li><code>GROUP BY</code>는 집계 함수 없이 사용하면 의도와 다르게 그룹 단위로 묶여서 정보가 사라질 수 있다는 걸 여러 연습을 통해 확인할 수 있었다.</li>
<li><code>MAX(마일리지)</code>를 서브쿼리 없이 <code>SELF JOIN</code>으로 구하는 방식은 기존에 잘 몰랐던 생각법이라 기억에 남는다….</li>
</ul>
<h2 id="lacked">Lacked</h2>
<p>조건문을 다양하게 조합해서 실습해보는 중에</p>
<p><code>IN</code>, <code>BETWEEN</code>, <code>LIKE</code> 등이 서로 어떤 상황에서 더 적절한지 정확하게 알고는 있지만</p>
<p>조건이 2~3개씩 들어가는 상황에서는 우선순위나 괄호 사용에 대한 확신이 조금 부족하다는 걸 느꼈다.</p>
<p>괄호 없이도 작동은 하지만 명확하게 표현하고 실수를 줄이기 위해선 항상 괄호로 묶는 습관이 중요하다는 걸 다시 느꼈다.</p>
<p><code>AND</code>, <code>OR</code>이 같이 들어갈 때는 눈으로만 판단하지 말고 괄호로 구조를 분명하게 표현하는 게 안전하겠다는 생각이 들었다.</p>
<p>실습 중 <code>DISTINCT</code> 에서 지역 하나, 도시 하나씩만 보이게 한다는 말을 내가 쿼리로 표현했을 때 SQL은 그걸 (지역, 도시) 조합 하나씩으로 정확히 해석했다.</p>
<p>결과적으로 내가 의도한 대로 잘 작동했지만 이런 부분에서 내가 생각한 의미와 SQL이 해석하는 방식 사이의 살짝의 어긋남이 있을 수 있다는 걸 다시 느꼈다.</p>
<p>단순히 쿼리를 잘 쓰는 걸 넘어서 데이터를 SQL이 어떻게 읽고 판단하는지를 감각적으로 이해하는 게 더 중요하겠다는 생각이 들었다.</p>
<ul>
<li>처음에 <code>UNION</code>을 썼을 때 후배가 나오지 않아서 혼란이 있었는데, 그 원인이 <code>SELECT 열 개수/순서/이름이 첫 SELECT 기준으로 고정된다</code>는 SQL의 룰이라는 걸 뒤늦게 확인했다.</li>
<li><code>GROUP BY</code>를 쓰면서도 왜 에러가 나는지 어떤 경우에 SELECT에 포함된 컬럼과 맞춰줘야 하는지를 아직 완전히 알지 못한 부분이 있다.</li>
<li>어렵당….</li>
</ul>
<h2 id="longed-for">Longed for</h2>
<p>3년 전에 오라클로 쿼리를 짤 때도 자주 썼던 기억이 있지만 막상 지금 다시 하려니까 손이 바로 움직이지는 않는다는 게 느껴졌다.</p>
<p>그래서 더욱 배우면서 기억이 돌아오고 내가 생각보다 많이 알고 있었다는 걸 다시 확인하는 경험이 기대된다.</p>
<p>실습 예제들이 단순히 문법 연습에 그치지 않고 실제 데이터를 요약하거나 비교 분석하는 데까지 이어졌으면 좋겠다.</p>
<p>JOIN 이랑 서브쿼리는 다시 배웠는데.. 왜 SQL이 그때도 쉽지 않았는지 기억이 날 것 같다…ㅋㅋㅋ</p>
<p>UPDATE 제품 SET 단가 = 카테고리 평균처럼 그룹 단위 평균을 기준으로 전체 일괄 업데이트하는 것도 JOIN + 서브쿼리로 도전해보고 싶다.</p>
<p>→ 그때는 성능까지 비교하면서 해보면 더 좋을 것 같다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[LG U+ Why Not SW CAMP 7기 7주차 회고]]></title>
            <link>https://velog.io/@feel_so_fine/LG-U-Why-Not-SW-CAMP-7%EA%B8%B0-7%EC%A3%BC%EC%B0%A8-%ED%9A%8C%EA%B3%A0</link>
            <guid>https://velog.io/@feel_so_fine/LG-U-Why-Not-SW-CAMP-7%EA%B8%B0-7%EC%A3%BC%EC%B0%A8-%ED%9A%8C%EA%B3%A0</guid>
            <pubDate>Tue, 08 Jul 2025 02:46:32 GMT</pubDate>
            <description><![CDATA[<h2 id="liked">Liked</h2>
<ul>
<li><p>비행기편 지연 데이터를 분석하면서 하나의 흐름으로 정리하면서 보는 재미가 있었다.</p>
<p>  단순히 숫자만 보는 게 아니라 어떤 항공사가 왜 지연이 많은지를 하나씩 파악해 나가니까 점점 흥미가 생겼다.</p>
</li>
<li><p>carrier, atc, weather 각각 따로 비교하고 막대그래프랑 선그래프 같이 그려보면서</p>
<p>  아 이 항공사는 운항 수는 많은데 생각보다 지연은 적네? 같은 걸 직접 눈으로 확인할 수 있었던 게 좋았다.</p>
</li>
<li><p>결측치를 무작정 제거하거나 무시하지 않고</p>
<p>  ‘지연률 3종 모두 결측’이라는 상황적 의미를 먼저 파악한 후 삭제 여부를 결정했다.</p>
</li>
<li><p><code>describe()</code> 표를 해석하면서 각 항공사의 지연률 통계가 무엇을 말해주는지</p>
<p>  단순히 수치 나열이 아니라 스토리로 정리해낼 수 있었다.</p>
<p>  <code>carrier</code>, <code>atc</code>, <code>weather</code> 각각의 특성과 항공사별 분포가 달라지는 부분에서</p>
<p>  왜 이 값이 중요한가를 설명할 수 있게 된 점이 큰 수확인 것 같다.</p>
</li>
<li><p>결측치 비중이 적어도 보고서에 내가 처리한 근거를 명확히 문장으로 작성하면서</p>
<p>  읽히는 보고서를 작성하는 시각을 얻었다.</p>
<h2 id="learned">Learned</h2>
</li>
<li><p><code>pd.cut()</code>으로 구간을 나눠서 도수분포표처럼 시각화할 수 있다는 거 처음 알았고</p>
<p>  그냥 <code>value_counts()</code>만 쓰는 것보다 훨씬 시각적으로 보기 좋다는 것도 배웠다.</p>
</li>
<li><p><code>twinx()</code>로 막대그래프랑 선그래프를 같은 x축에 겹쳐서 표현하는 것도 해봤는데</p>
<p>  이걸로 지연률과 전체 항공편 수를 한 번에 비교할 수 있는 게 신기하고 유용했다.</p>
</li>
<li><p><code>&#39;tab:blue&#39;</code>, <code>&#39;tab:orange&#39;</code> 같은 색상 표현도 있다는 걸 알게 돼서 그래프 색감 조절할 때 도움될 것 같다.</p>
</li>
<li><p><code>import</code> 방식에서 <code>from ... import ...</code>와 <code>import ... as ...</code>의 차이를</p>
<p>  이론이 아니라 코드 흐름 속에서 명확히 이해하게 되었다.</p>
</li>
<li><p><code>dropna(subset=[...])</code>을 이용해 조건부 결측치 제거를 실제 분석에서 자연스럽게 사용할 수 있게 되었다.</p>
<p>  지금까지는 그냥 전체 dropna()만 썼던 나에게 정제된 도구가 생긴 느낌이었다.</p>
</li>
<li><p>분석 보고서는 데이터를 읽을 줄 모르는 사람들에게 설명하는 도구이다.</p>
<h2 id="lacked">Lacked</h2>
</li>
<li><p>처음엔 무슨 그래프부터 그려야 할지 순서가 헷갈렸고,</p>
<p>  변수별로 뭘 분석해야 하는지도 정리되지 않은 상태에서 시작해서 약간 헤맸다.</p>
</li>
<li><p>각 항공사의 지연 원인을 조금 더 깊이 파고들고 싶었는데</p>
<p>  carrier, atc, weather를 단순히 평균값만 보고 끝낸 게 살짝 아쉬웠다.</p>
</li>
<li><p>통계량과 데이터를 보면 그냥 그렇구나… 싶었는데 계속 생각을 해봐야 하는게 조금 힘들었다.</p>
</li>
<li><p>처음에는 describe() 표를 봐도 수치 하나하나가 어떤 의미를 가지는지 해석이 잘 안됐다.</p>
<p>  IQR, 최대값 같은 값을 단순히 크다/작다로만 보려다 이 값이 왜 커졌는지, 어떤 구조가 숨어있는지까지 생각하는 게 힘들었다.</p>
</li>
<li><p>결측치를 무시하려는 마음이 잠깐 들었던 것도 반성해야 할 부분이다.</p>
<p>  데이터 수가 적다는 이유만으로 처리를 하지 않을 건지 고민 없이 판단하려 했다는 건</p>
<p>  앞으로 예측에서 실수를 만들 수 있는 여지였다고 생각한다.</p>
</li>
<li><p>보고서에서 자연스러운 문장을 작성하려다 보니 글을 쓰는 것도 꽤 어려웠다.</p>
<p>  내용을 잘 포함하면서 이해하기 쉽게라는 기준을 유지하는 데 시간이 꽤 걸렸다.</p>
</li>
</ul>
<h2 id="longed-for">Longed for</h2>
<ul>
<li><p>요일별, 시간대별로도 지연이 몰리는 패턴이 있는지 분석해보고 싶다.</p>
</li>
<li><p>분석한 내용을 기반으로 한눈에 보기 쉽게 항공사별 정리 리포트처럼 만들어보는 것도 해보고 싶다.</p>
</li>
<li><p>더 힘들겠지만.. 항공사별 지연률을 시간대/요일별로 나눠보면 더 재미있는 인사이트가 나올 것 같다.</p>
<p>  특정 항공사는 주말 밤에 지연이 많다든지 어떠한 시간대만 이슈가 집중된다든지 하는 패턴이 궁금해졌다.</p>
</li>
<li><p>보고서 시각화도 단순히 subplot이 아니라 대비를 더 강조할 수 있는 색상, 인포그래픽 스타일로 발전시키고 싶은 욕심도 생겼다.</p>
<p>  시각화 자체도 잘 읽히게 하는 게 목표라고 생각한다.</p>
</li>
</ul>
<h1 id="프로젝트">프로젝트</h1>
<p>툭툭 프로젝트의 전체 구조와 문제 정의를 정리하면서 왜 우리가 이 시스템을 만들고 있는지를 다시 되짚는 시간이었다.
가장 기억에 남는 건 상담사 중심의 시선으로 문제를 재구성해본 것이다.</p>
<p>초반에는 사용자인 고객 중심 문장이 많았는데 회의와 피드백을 통해</p>
<blockquote>
<p>지금 이 시스템은 상담사에게 보여지는 시스템이다
라는 점을 명확히 하면서 문장의 방향과 용어 선택도 많이 바뀌었다.</p>
</blockquote>
<p>또 하나 의미 있었던 건 디자인 관점에서 지나치게 AI가 모든 걸 대신하는 것처럼 보이지 않게 하기를 고민한 점이라 생각한다.
툭툭은 상담사를 돕는 보조자라는 메시지를 전달해야 하니까
그런 부분을 시각적으로 그리고 슬로건이나 표 형식에도 녹이려고 애썼다.</p>
<p>작업을 하면서 정리했던</p>
<p>문제 상황 → 해결방식 → 기술 요소 흐름
이 자연스럽게 잡혀가서 한층 팀 프로젝트의 아이덴티티가 명확해진 느낌이다.</p>
<p>피그마 디자인 시도에 이어 툭툭 시스템이 실제로 어떻게 동작하는지를 설명할 수 있는 흐름도(Flow Diagram)를 그리는 작업에 집중했다.
단순한 기능 나열이 아니라</p>
<blockquote>
<p>툭툭이 상담사의 어떤 업무를 어떻게 도와주는가?를 스스로 납득할 수 있어야 설명과 특색이 명확해지기 때문에 그걸 시각적으로 정리하는 게 오늘의 가장 큰 목표였다.</p>
</blockquote>
<p>중간중간 헷갈렸던 건
이 기능은 사용자에게 보이는 건가, 백엔드 처리인가?
같은 부분이었는데 gpt 한테도 물어보고 직접 그리면서 만드는 시스템을 더 깊게 이해하게 되는 경험이었다.</p>
<p>느낀 점
흐름을 명확히 잡는 게 먼저라는 것.
오늘은 이 기술이 이 시점에 이런 방식으로 상담사에게 도움이 된다는 설명이 가능해지는 느낌!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[LG U+ Why Not SW CAMP 7기 6주차 회고]]></title>
            <link>https://velog.io/@feel_so_fine/LG-U-Why-Not-SW-CAMP-7%EA%B8%B0-6%EC%A3%BC%EC%B0%A8-%ED%9A%8C%EA%B3%A0</link>
            <guid>https://velog.io/@feel_so_fine/LG-U-Why-Not-SW-CAMP-7%EA%B8%B0-6%EC%A3%BC%EC%B0%A8-%ED%9A%8C%EA%B3%A0</guid>
            <pubDate>Tue, 08 Jul 2025 02:39:36 GMT</pubDate>
            <description><![CDATA[<h2 id="liked">Liked</h2>
<ul>
<li><p>실제 파일 입출력 시 발생할 수 있는 오류나 예외를 실습 기반으로 자연스럽게 마주하면서 해결할 수 있었다는 점이 좋았다.</p>
</li>
<li><p>단순히 코드 결과만 보는 게 아니라 왜 그렇게 동작하는지를 계속 고민해보면서 원리를 알게 된 느낌이었다.</p>
</li>
<li><p>연습 문제들을 많이 주셔서 스스로 학습해볼 수 있는 시간이 생겨 좋았다.</p>
</li>
</ul>
<h2 id="learned">Learned</h2>
<ul>
<li><p><strong>넘파이</strong></p>
<ul>
<li>정수 인덱싱은 해당 축을 제거하고, 리스트나 슬라이싱은 차원을 유지한다는 점!</li>
<li><code>arr[[i, j], [k, l]]</code>은 팬시인덱싱으로 작동해 특정 위치만 추출함</li>
<li><code>np.diff()</code> 로 비교하는 방식과 슬라이싱으로 비교하는 방식 (<code>arr[1:] &gt; arr[:-1]</code>)</li>
<li><code>NaN</code>은 float 배열에서만 가능하므로 <code>astype(float)</code> 처리가 필요함!</li>
</ul>
</li>
<li><p><strong>판다스</strong></p>
<ul>
<li>Series는 1차원 DataFrame은 2차원 구조로 딕셔너리나 배열 기반으로 쉽게 생성할 수 있다</li>
<li>DataFrame에서 <code>index.name</code>으로 인덱스에 이름을 지정할 수 있음</li>
<li>Series의 인덱스를 따로 정리하지 않고 DataFrame 인덱스를 강제로 지정하면 NaN이 생길 수 있음!</li>
<li>Series들의 인덱스를 한 번에 바꿀 수 있는 방법 (<code>.index = [...]</code>)</li>
<li><code>np.argmax(..., axis=1)</code> 결과를 요일 이름으로 변환하는 방법 (리스트 매핑)</li>
</ul>
</li>
<li><p>CSV 파일 입출력의 정확한 방식을 배웠다. <code>csv.reader</code>로 읽으면 빈 줄이 나올 수 있는데 그 이유는 파일을 저장할 때 <code>newline=&#39;&#39;</code>를 지정하지 않았기 때문이라는 걸 처음 알았다.</p>
</li>
<li><p><code>pickle</code>을 이용한 직렬화/역직렬화의 개념과 목적을 확실히 이해했다. 데이터를 파일로 저장하거나 네트워크로 전송할 때 왜 바이너리 형태가 필요한지 그리고 왜 <code>&#39;wb&#39;</code>와 <code>&#39;rb&#39;</code> 모드를 써야 하는지도 명확해졌다.</p>
</li>
<li><p>Pandas에서의 컬럼 정렬 (알파벳 순) 과 값 정렬 (예: age 오름차순) 방법을 익혔다. <code>df.columns.sort_values()</code>는 컬럼 이름만 정렬된 리스트를 반환하고 실제 DataFrame을 바꾸지는 않는다는 것도 헷갈렸는데 <code>df = df[sorted(df.columns)]</code>처럼 적용해야 한다는 걸 배웠다.</p>
</li>
</ul>
<h2 id="lacked">Lacked</h2>
<ul>
<li><p>CSV 파일을 열었을 때 <code>Unnamed: 0</code> 열이 왜 생기는지 처음엔 잘 몰랐고 <code>index=False</code> 설정의 중요성을 간과했던 것 같다.</p>
</li>
<li><p><code>df.loc[range(5), range(5)]</code>처럼 NumPy 스타일을 Pandas에서 쓰려다 에러가 나기도 했는데loc/iloc 차이를 좀 더 체계적으로 복습할 필요가 있다고 느꼈다.</p>
</li>
</ul>
<h2 id="longed-for">Longed for</h2>
<ul>
<li><p>CSV, JSON, Pickle 같은 직렬화 포맷들의 차이점과 언제 어떤 걸 써야 하는지 실제 예시와 함께 더 정리해보고 싶다.</p>
</li>
<li><p>Pandas 정렬을 하면서 결측치가 있을 경우의 처리 그리고 정렬 후 인덱스 리셋 여부 같은 실무에서 자주 마주칠 수 있는 세세한 부분도 더 익히고 싶다.</p>
</li>
<li><p>시리즈나 데이터프레임을 만들 때 인덱스와 열을 실수 없이 관리하는 법을 더 연습하고 싶다</p>
</li>
<li><p>넘파이에서 조건에 따라 데이터를 바꾸거나 요약하는 방법들을 연습해보고 싶다</p>
</li>
<li><p>데이터프레임을 만들고 나서 행이나 열을 추가/삭제하거나 정렬하는 기본적인 조작들도 앞으로 더 익혀보고 싶다</p>
</li>
</ul>
<p>기능을 익히는 데 그치지 않고 내가 왜 이걸 쓰는지, 왜 이런 결과가 나오는지를 계속 확인하며 실험하려고 노력했다.</p>
<blockquote>
<p>단순한 결과에 만족하지 않고 그 과정을 스스로 납득하며 가는 연습을 통해 데이터 전처리와 시각화에 대한 자신감이 조금씩 생겼으면 한다.</p>
</blockquote>
]]></description>
        </item>
    </channel>
</rss>