<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>0798_hyuk.log</title>
        <link>https://velog.io/</link>
        <description>스위트아메리카노</description>
        <lastBuildDate>Tue, 19 May 2026 03:17:47 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>0798_hyuk.log</title>
            <url>https://velog.velcdn.com/images/0798_hyuk/profile/0fd3d757-0d9a-4a36-9dbb-dcd0f913f47f/social_profile.jpeg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. 0798_hyuk.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/0798_hyuk" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[교내 해커톤 대회 대상 후기 및 소감]]></title>
            <link>https://velog.io/@0798_hyuk/%EA%B5%90%EB%82%B4-%ED%95%B4%EC%BB%A4%ED%86%A4-%EB%8C%80%ED%9A%8C-%EB%8C%80%EC%83%81-%ED%9B%84%EA%B8%B0-%EB%B0%8F-%EC%86%8C%EA%B0%90</link>
            <guid>https://velog.io/@0798_hyuk/%EA%B5%90%EB%82%B4-%ED%95%B4%EC%BB%A4%ED%86%A4-%EB%8C%80%ED%9A%8C-%EB%8C%80%EC%83%81-%ED%9B%84%EA%B8%B0-%EB%B0%8F-%EC%86%8C%EA%B0%90</guid>
            <pubDate>Tue, 19 May 2026 03:17:47 GMT</pubDate>
            <description><![CDATA[<p>교내에서 진행된 해커톤 대회에 참가하였다.</p>
<p>처음에는 참가자들이 5인이내로 구성된 팀을 꾸려오면 선착순으로 받아 진행되는 방식이였으나, 고학년과 저학년의 격차를 고려해 모집 이전에 고학년 3명 저학년 3명의 팀으로 수정되어 모집되었다.</p>
<p>우리 처음의 팀은 4명이었으나 어쩔수 없이 3명이서 나가게 되었다.</p>
<p>4학년이라 고학년으로 참여를 하였고 저학년 팀은 자동으로 매칭되는 시스템이였다.</p>
<p>사실 고학년 팀중에서도 해커톤의 경험이있는건 나뿐이여서 걱정이많았다.
저학년의 스펙도 궁금하였고,
어떤 프레임워크를 사용해야하고, 서로의 역할분배가 제일 걱정되었다.</p>
<p>이전에 참여했던 해커톤에서는 역할분배가 적절히 되지않아 고생했던 기억이있어서..
바이브 해커톤 대회라서 사실 혼자 개발하는게 더 나을지도 모르겠다는 생각을 한두번 한게 아니였기 때문이다.
그래서 이번 대회에서는 서로의 의사소통과 기준이되는 하나의 md 파일을 먼저 만드는것을 계속 중점으로 가지고 갔다.</p>
<p>서로 각자 다른 에이전트를 사용하기에 소통에서 하나의 문제라도 있으면 병합과정에 그것을 해결하는데 많은 시간을 쏟아야 하기 때문이다.</p>
<p>이번 해커톤에서는 중간에서 진행사항을 계속 물어보고 뭐해야하고 공유 파일 정리하고 .env 파일이나 통합 .md파일 공유 및 소통역할을 많이 하였다.</p>
<p>저학년친구들에게 깃헙 사용법을 알려주고 싶었지만 세명이 하나의 노트북에 붙어 기획에서 만들어진 요구서를 바탕으로 front ui 를 맡겼다.</p>
<p>깃헙을 대신해 작성된 코드파일을 .zip 파일로 요청을했고..ㅎㅎ.
나머지는 디자인과 발표자료를 부탁했다.</p>
<p>고학년중 클로드 결제를 한 친구가 .zip 파일을받아 처음에 아키텍처를 기획한대로 supabase 와 채팅을 위한 firebase 에 맡게 수정을 하였고 프론트 배포를 vercel 로 작업을 끝냈다.</p>
<p>기획에서 탄탄하게 팀원들과 맞춰갔기 때문에 개발 단계에서 별 문제없이 진행되었다
vercel 배포중에 한번 conflict가 났는데
이유는 중간에 한번 주제를 바꿈으로 인해 안쓰는 lib 파일이 배포중에 충돌이나 삭제만 해주고 바로 배포를 성공적으로 하였다.</p>
<p>시간이 다른조들보다 조금 남아 발표자료와 발표스크립트 등에 시간을 좀 더 쓸 수 있었다.</p>
<p>조원들이 잘 봐주어 발표를 담당한 나도 별 긴장없이 잘 준비할 수 있었다.</p>
<p><img src="https://velog.velcdn.com/images/0798_hyuk/post/373c292f-058b-4e6a-9677-d2821a6ad01f/image.jpg" alt=""></p>
<p><img src="https://velog.velcdn.com/images/0798_hyuk/post/2d4b3385-3e55-45ea-b533-fe7479b86295/image.jpg" alt=""></p>
<p>많은 사람들 앞에서 발표하는건 적응이 안되는 거 같다</p>
<p>다른 조분들이 발표를 너무 잘하여서 더 긴장했던 거 같다.
사실 3팀분의 발표가 너무 인상깊어 수상은 기대도 안했었다..</p>
<p>15팀의 모든 발표가 끝나고, 15분간의 심사봐주시는 교수님분들이 심사시간을 가졌다.</p>
<p>그리고 ..</p>
<p><img src="https://velog.velcdn.com/images/0798_hyuk/post/407c61f7-bfbe-478a-9b63-3db712d9fc5f/image.jpg" alt=""></p>
<p>감사하게도 좋게 봐주셔서 대상을 할 수 있었다.
팀원분들도 다들 밤샘 고생해줘서 얻을 수 있는 갚진 결과인 거 같았다.</p>
<p><img src="https://velog.velcdn.com/images/0798_hyuk/post/0d92a72e-734d-4436-875d-42d792f8cf52/image.jpg" alt=""></p>
<p>해커톤은 이번이 두번째인데 항상 나가면서 드는 생각이 
바이브코딩의 시대인 만큼 뛰어난 실력과 코딩 수준도 중요하지만
기획단계가 너무 중요한 거 같았다.
기획과 발표와 바로 보여지는 발표자료또한 중요한 거 같다.</p>
<p>그리고 우리 서비스를 설명할 수 있는 한문장으로 심사하시는 분들에게 어?라는 생각을 들게 해야한다</p>
<p>좋은 경험하고 다시는 밤샘은 못할 거 같다.. 아직도 패턴이 안돌아와..</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[매니페스트로 기획하고 google ai studio 랑 클로드로 개발해보기]]></title>
            <link>https://velog.io/@0798_hyuk/%EB%A7%A4%EB%8B%88%ED%8E%98%EC%8A%A4%ED%8A%B8%EB%A1%9C-%EA%B8%B0%ED%9A%8D%ED%95%98%EA%B3%A0-google-ai-studio-%EB%9E%91-%ED%81%B4%EB%A1%9C%EB%93%9C%EB%A1%9C-%EA%B0%9C%EB%B0%9C%ED%95%B4%EB%B3%B4%EA%B8%B0</link>
            <guid>https://velog.io/@0798_hyuk/%EB%A7%A4%EB%8B%88%ED%8E%98%EC%8A%A4%ED%8A%B8%EB%A1%9C-%EA%B8%B0%ED%9A%8D%ED%95%98%EA%B3%A0-google-ai-studio-%EB%9E%91-%ED%81%B4%EB%A1%9C%EB%93%9C%EB%A1%9C-%EA%B0%9C%EB%B0%9C%ED%95%B4%EB%B3%B4%EA%B8%B0</guid>
            <pubDate>Sun, 10 May 2026 05:36:33 GMT</pubDate>
            <description><![CDATA[<p>우선 요즘 따듯해지는 날씨에 러닝이 하고싶어졌다.</p>
<p>혼자하는 러닝앱은 많은데 친구와 같이하는 러닝앱이 없어 개발해서 
가능하면 배포(런칭) 까지 해보고싶다는 욕심이 생겨서 개발을 하게되었다.</p>
<p>가능하면 오늘 하루안에 다 해보고싶다..
이후 저녁약속이있어 7시 전까지 개발 완료 목표로 잡고
배포는 내일해도되니까</p>
<p>우선 매니페스트에 입력해
기능명세서와 유저플로우, 와이어프레임을 뽑았다.
와이어프레임은 베타버전이긴하나
하나하나 세부수정이 가능해 개발자가 원하는대로 뽑을 수 있었다. </p>
<p><img src="https://velog.velcdn.com/images/0798_hyuk/post/392ac0de-e711-44a5-83bc-39ba0b0fb357/image.png" alt=""></p>
<p>이 기획을 토대로 google ai studio 랑 제미나이 클로드 중 어느 에이전트를 사용해 개발할까 고민하다
둘다 구글이랑 클로드를 사용해보기로 했다.</p>
<p>클로드에게 맡겼을 때는 PRD 만 보고서는 잘 못짜서 더 요구사항을 넣으려다
내 토큰을 위해 아껴두었고</p>
<p>나머지를 google ai studio 한테 맡겼다.</p>
<p>지금 듣고있는 노래플리 : <a href="https://www.youtube.com/watch?v=Ckwc2PwMjPk">https://www.youtube.com/watch?v=Ckwc2PwMjPk</a></p>
<p>오래걸려서 노래 든는중..</p>
<p><img src="https://velog.velcdn.com/images/0798_hyuk/post/9ff2f435-1b9c-480e-a9c7-354f903aab28/image.png" alt=""></p>
<p>오 예쁘게 된 거 같다.
한번 배포까지 노력하고 다시 작성하겠다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[가트너 참고해서 msa 기반 아키텍처 다이어그램 설계하기]]></title>
            <link>https://velog.io/@0798_hyuk/%EA%B0%80%ED%8A%B8%EB%84%88-%EC%B0%B8%EA%B3%A0%ED%95%B4%EC%84%9C-msa-%EA%B8%B0%EB%B0%98-%EC%95%84%ED%82%A4%ED%85%8D%EC%B2%98-%EB%8B%A4%EC%9D%B4%EC%96%B4%EA%B7%B8%EB%9E%A8-%EC%84%A4%EA%B3%84%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@0798_hyuk/%EA%B0%80%ED%8A%B8%EB%84%88-%EC%B0%B8%EA%B3%A0%ED%95%B4%EC%84%9C-msa-%EA%B8%B0%EB%B0%98-%EC%95%84%ED%82%A4%ED%85%8D%EC%B2%98-%EB%8B%A4%EC%9D%B4%EC%96%B4%EA%B7%B8%EB%9E%A8-%EC%84%A4%EA%B3%84%ED%95%98%EA%B8%B0</guid>
            <pubDate>Sun, 10 May 2026 04:03:14 GMT</pubDate>
            <description><![CDATA[<p>학교 프로젝트를 하면 꼭 작성해야하는 설계서
그리고 기획서 등등..</p>
<p>거기에 빠지지않는 여러 다이어그램중 하나인 아키텍처 다이어그램을
msa 기반으로 만들어보려한다.</p>
<p>근데 msa 랑 soa 두개의 정의가 모호해
한번 내친구에게 물어보고 답을 얻었다.</p>
<pre><code>① 중앙 집중형 통신(ESB) vs 가볍고 단순한 통신(Smart Endpoints)
SOA (ESB 중심): SOA는 ESB(Enterprise Service Bus)라는 강력하고 지능적인 중앙 미들웨어를 둡니다. 이 ESB가 서로 다른 서비스 간의 프로토콜 변환, 메시지 라우팅, 데이터 포맷 변환 등을 전부 처리합니다. 시스템 전체의 비즈니스 오케스트레이션(흐름 제어)을 ESB가 쥐고 있기 때문에, ESB가 죽으면 시스템 전체가 마비되는 단점(Single Point of Failure)이 있습니다.

MSA (Dumb Pipes, Smart Endpoints): 반면 MSA는 &quot;통로(Pipe)는 가볍게 만들고, 끝단(Endpoint)을 똑똑하게 만들자&quot;는 철학을 가집니다. 중앙 버스 미들웨어 없이, 서비스들이 가벼운 HTTP REST API나 gRPC를 통해 직접 혹은 API Gateway를 거쳐 최소한의 규격으로 통신합니다.

② 데이터베이스 공유 vs 데이터베이스 격리 
SOA: 대개의 경우 서비스들은 쪼개져 있지만, 백엔드의 데이터베이스는 하나로 공유합니다. 이 때문에 특정 서비스의 스키마를 변경하려면 다른 서비스 개발팀과 상의해야 하며, DB 병목 현상이 발생하면 전체 시스템 성능이 저하됩니다.

MSA: &quot;Database Per Service&quot; 원칙을 고수합니다. 각 마이크로서비스는 자신만의 전용 데이터베이스를 가집니다. 서비스 A는 PostgreSQL을 쓰고, 서비스 B는 MongoDB를 써도 무방합니다. 서로의 DB에 직접 쿼리를 날릴 수 없고 오직 API를 통해서만 데이터를 주고받기 때문에 영속성 레이어의 독립성이 완벽히 보장됩니다.</code></pre><p>간략히 보면 msa 는 말그대로 micro 단위까지 독립적으로 설계된 아키텍처인 거 같았습니다.</p>
<p>그래서 msa하면 떠오르느 대표적인 회사인 Netflex의 아키텍처를 보면</p>
<p><img src="https://velog.velcdn.com/images/0798_hyuk/post/2138eaf1-6a4e-4a37-b283-5ddfd264c1a4/image.png" alt=""></p>
<p>이게 아키텍처 구조이다..</p>
<p>토나오는 비주얼</p>
<p>어쩄든 가트너가 제시한 msa 아키텍처 표준안을 살펴보고
내 서비스에 맞는 미들웨어들을 넣어
내 아키텍처를 작성해보았다.
<img src="https://velog.velcdn.com/images/0798_hyuk/post/565f025a-5f50-4939-b58c-1c26ff36aeea/image.png" alt=""></p>
<p>많이 비슷한 다이어그램의 모형인데, 똑같이 중요한 6가지가 있다.
오른쪽에 Outer Architecture Capability라고 적혀있는데</p>
<ol>
<li>External Gateway</li>
<li>Service Mesh</li>
<li>Runtime Platform</li>
<li>Backing Services</li>
<li>Tlelmetry</li>
<li>CI/ CD Automation</li>
</ol>
<p>이 6가지를 고수하며 작성해 보았다</p>
<p>무료 미들웨어들을 고집했고, 많이 추상적이라 개발하려고 하는 서비스 입에 맞춰서 수정이 더 필요하다..</p>
<p>더 수정이 필요한 부분은 수정해 다시 게시하도록 하겠다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[프로젝트]대충 그냥 공부하다가 가사 듣고싶은 노래가 있었는데 대충 공부하면서 가사보려고만든 서비스]]></title>
            <link>https://velog.io/@0798_hyuk/%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8%EB%8C%80%EC%B6%A9-%EA%B7%B8%EB%83%A5-%EA%B3%B5%EB%B6%80%ED%95%98%EB%8B%A4%EA%B0%80-%EA%B0%80%EC%82%AC-%EB%93%A3%EA%B3%A0%EC%8B%B6%EC%9D%80-%EB%85%B8%EB%9E%98%EA%B0%80-%EC%9E%88%EC%97%88%EB%8A%94%EB%8D%B0-%EB%8C%80%EC%B6%A9-%EA%B3%B5%EB%B6%80%ED%95%98%EB%A9%B4%EC%84%9C-%EA%B0%80%EC%82%AC%EB%B3%B4%EB%A0%A4%EA%B3%A0%EB%A7%8C%EB%93%A0-%EC%84%9C%EB%B9%84%EC%8A%A4</link>
            <guid>https://velog.io/@0798_hyuk/%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8%EB%8C%80%EC%B6%A9-%EA%B7%B8%EB%83%A5-%EA%B3%B5%EB%B6%80%ED%95%98%EB%8B%A4%EA%B0%80-%EA%B0%80%EC%82%AC-%EB%93%A3%EA%B3%A0%EC%8B%B6%EC%9D%80-%EB%85%B8%EB%9E%98%EA%B0%80-%EC%9E%88%EC%97%88%EB%8A%94%EB%8D%B0-%EB%8C%80%EC%B6%A9-%EA%B3%B5%EB%B6%80%ED%95%98%EB%A9%B4%EC%84%9C-%EA%B0%80%EC%82%AC%EB%B3%B4%EB%A0%A4%EA%B3%A0%EB%A7%8C%EB%93%A0-%EC%84%9C%EB%B9%84%EC%8A%A4</guid>
            <pubDate>Fri, 24 Apr 2026 10:05:54 GMT</pubDate>
            <description><![CDATA[<h4 id="1-카페에서-공부하다가">1. 카페에서 공부하다가..</h4>
<p>카페에서 공부하다 내가 좋아하는 빈지노의 aquaman 노래가 나오는데 가사가 생각이 안나서 네이버에 aquaman 가사를 검색했다. 
프로젝트 공부를 하며 가사를 보고싶었는데 네이버창을 계속 띄워두자니
내 작은 16인치의 노트북 화면을 가리는데 충분해서
그냥 미니앱과같은 서비스형식의 토이프로젝트를 바로 하려했다.</p>
<h4 id="2-어떤-기술">2. 어떤 기술</h4>
<p>어떻게 구현을 할까 고민을 하다 요전에 학교에서 진행한 p-project 에서 다른팀이 Electron 을 이용해 프론트를 구현한 기억이 나를 스쳤다.</p>
<p>바로 Electron 공부를 들어가려 했다가 머리가 아파 ..
클로드와 함께하는 개발시간..
바로 가이드라인 제시해서 만들어줘 시전했다.</p>
<p>기술 스택은 Electron, Node.js, Main/Render 프로세스와 IPC 흐름으로 구현을 했고 ,
가사 수집을 어떻게 할까 크롤링이나 공식 API 고민중 그냥 딸깍으로 만드려고 크롤링을 선택했다. 어짜피 나만 쓸 서비스니..
ui는 backdrop-filter와 프레임이거슬려 프레임이스창으로 만들었다</p>
<h4 id="3-트러블-슈팅">3. 트러블 슈팅?</h4>
<p>이라고 할게 있나? 클로드가 너무 잘짜줬다 한번에
ui 부분에서 가사와 아티스트명을 너무 길게 입력하면 화면이 오른쪽으로 쏠려 
가사부분 왼쪽이 짤림 현상이 있었는데 overflow: hidden 속성으로 고쳐주었다.</p>
<h4 id="4-실행">4. 실행</h4>
<p>바로 필요한 라이브러리들을 npm install 로 설치를 해주고
npm start 로 실행을 해보자.
<img src="https://velog.velcdn.com/images/0798_hyuk/post/b5245a21-5102-4562-8ba3-7e50b23e7057/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/0798_hyuk/post/c04933a4-a72f-4442-95b5-43a63e52bdc6/image.png" alt="">
위와 같은 창이 내 노트북 오른쪽 화면에 생긴다.</p>
<p>검색을 하면
<img src="https://velog.velcdn.com/images/0798_hyuk/post/9f574851-f7a0-4937-97dc-373055e6161d/image.png" alt="">
위와 같이 가사를 보며 공부를 같이 할 수 있게 되었다.
<del><em>결코 공부하기 싫어서 만든게아니ㅑ</em></del></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[클로드 코드 전코드 유출?]]></title>
            <link>https://velog.io/@0798_hyuk/%ED%81%B4%EB%A1%9C%EB%93%9C-%EC%A0%84%EC%BD%94%EB%93%9C-%EC%9C%A0%EC%B6%9C</link>
            <guid>https://velog.io/@0798_hyuk/%ED%81%B4%EB%A1%9C%EB%93%9C-%EC%A0%84%EC%BD%94%EB%93%9C-%EC%9C%A0%EC%B6%9C</guid>
            <pubDate>Sat, 04 Apr 2026 08:37:47 GMT</pubDate>
            <description><![CDATA[<p>요즘 개발 커뮤니티 보면 다들 한 번씩 얘기하는 이슈가 있죠. 바로 클로드(Claude) 코드 유출 사건.</p>
<p>나도 처음엔 “또 하나의 보안 사고인가 보다” 하고 넘기려다가, 내용 좀 보니까 생각보다 가볍게 넘길 일은 아니더라고요. 그래서 이걸 계기로 느낀 점이랑 정리 좀 해보려고 글 씁니다.</p>
<hr>
<h2 id="사건-배경-간단-정리">사건 배경 (간단 정리)</h2>
<p>최근에 Anthropic의 Claude 관련 내부 코드나 프롬프트 일부가 외부로 유출됐다는 얘기가 돌면서 꽤 이슈가 됐습니다.
정확히 어떤 경로로 유출됐는지는 아직 명확하게 다 공개된 건 아니지만, 핵심은 이거 하나예요.</p>
<blockquote>
<p>“AI 서비스도 결국 사람이 만드는 소프트웨어고, 보안이 뚫리면 똑같이 위험하다”</p>
</blockquote>
<p>사실 GPT든 Claude든 다들 되게 ‘대단한 AI’라고 생각하는데, 그 내부를 보면 결국 코드 + 프롬프트 + 데이터의 조합이거든요.
그게 유출됐다는 건 생각보다 큰 문제입니다.</p>
<hr>
<h2 id="내가-느낀-포인트">내가 느낀 포인트</h2>
<h3 id="1-프롬프트도-자산이다">1. 프롬프트도 ‘자산’이다</h3>
<p>이거 이번에 제일 크게 느낀 부분.</p>
<p>예전에는 그냥 “프롬프트 잘 짜면 좋다~” 정도였는데,
이제는 기업 입장에서는 프롬프트 자체가 거의 핵심 기술이에요.</p>
<ul>
<li>어떻게 답변하게 만드는지</li>
<li>어떤 방식으로 안전하게 필터링하는지</li>
<li>어떤 구조로 추론하게 만드는지</li>
</ul>
<p>이런 게 다 프롬프트에 녹아있거든요.</p>
<p>즉, 코드만 중요한 게 아니라
<strong>“AI를 어떻게 다루는 방식 자체”가 유출된 거</strong>라서 더 의미가 큼.</p>
<hr>
<h3 id="2-결국-보안은-기본-중의-기본">2. 결국 보안은 기본 중의 기본</h3>
<p>이거 보면서 든 생각 하나.</p>
<blockquote>
<p>“아무리 AI 시대라도, 기본적인 보안 못 하면 끝이다”</p>
</blockquote>
<p>요즘은 다들 AI, 모델, 성능 이런 얘기만 하는데
막상 서비스 터지는 건 항상 보안 쪽에서 터짐.</p>
<ul>
<li>API 키 관리</li>
<li>접근 권한 관리 (IAM 같은 거)</li>
<li>내부 코드 관리</li>
</ul>
<p>이거 하나라도 삐끗하면 바로 사고로 이어지는 구조임.</p>
<p>나도 AWS 쓰면서 느끼는 건데,
권한 설정 조금만 잘못해도 바로 위험해지는 게 이쪽임.</p>
<hr>
<h3 id="3-클로즈드-vs-오픈-논쟁-더-커질-듯">3. “클로즈드 vs 오픈” 논쟁 더 커질 듯</h3>
<p>이 사건 이후로 또 나올 얘기 뻔함.</p>
<ul>
<li>“어차피 유출될 거면 오픈소스가 낫다”</li>
<li>“그래도 기업 기술은 보호해야 한다”</li>
</ul>
<p>개인적으로는 둘 다 맞는 말 같음.</p>
<p>근데 확실한 건,
<strong>클로즈드 모델이라고 해서 완전히 안전하지 않다</strong>는 건 이번에 확실히 보여준 사례라고 생각함.</p>
<hr>
<h2 id="개발자로서-느낀-점">개발자로서 느낀 점</h2>
<p>솔직히 이거 보면서 좀 현실적으로 와닿은 게 하나 있음.</p>
<blockquote>
<p>“대단한 기술도 결국 관리 못 하면 무너진다”</p>
</blockquote>
<p>우리는 지금 AI 공부하고, 프로젝트 만들고, 서버 올리고 이런 거 하잖아요.</p>
<p>근데 그 과정에서</p>
<ul>
<li>.env 그냥 공유하고</li>
<li>키 그대로 올리고</li>
<li>권한 대충 주고</li>
</ul>
<p>이러면… 규모만 커졌을 때 똑같은 사고 나는 거임.</p>
<p>결국 중요한 건</p>
<ul>
<li>기술 잘 쓰는 거 +</li>
<li><strong>안전하게 쓰는 거</strong></li>
</ul>
<p>이 두 개를 같이 가져가야 한다는 거.</p>
<hr>
<h2 id="마무리">마무리</h2>
<p>이번 클로드 코드 유출 사건은 단순한 “사고 하나”라기보다,
AI 시대에서 우리가 뭘 중요하게 봐야 하는지 다시 보여준 케이스 같음.</p>
<p>정리하면 딱 이거:</p>
<ul>
<li>프롬프트도 자산이다</li>
<li>보안은 선택이 아니라 필수다</li>
<li>AI도 결국 소프트웨어다</li>
</ul>
<p>나도 이번 기회에
.env 관리, AWS 권한, 키 관리 이런 거 다시 한 번 점검해봐야겠다는 생각 들었음.</p>
<p>괜히 큰 서비스만의 문제가 아니라
우리 같은 개인 프로젝트에서도 충분히 터질 수 있는 문제니까.</p>
<hr>
<p>다음에는 이거 이어서
“개발하면서 실제로 보안 어떻게 챙겨야 하는지”도 정리해볼까 생각 중.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[JWT or Session? (프로젝트)]]></title>
            <link>https://velog.io/@0798_hyuk/JWT-or-Session-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8</link>
            <guid>https://velog.io/@0798_hyuk/JWT-or-Session-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8</guid>
            <pubDate>Tue, 31 Mar 2026 04:22:30 GMT</pubDate>
            <description><![CDATA[<h1 id="요구사항-분석-중-발생한-인증-방식-논쟁과-해결-과정-jwt-vs-session">요구사항 분석 중 발생한 인증 방식 논쟁과 해결 과정 (JWT vs Session)</h1>
<p>프로젝트를 시작하면서 가장 먼저 진행했던 작업은 요구사항 분석이었다.
기능 정의를 구체화하는 과정에서 예상보다 다양한 의견이 나왔는데, 그중에서도 가장 크게 의견이 갈렸던 부분은 <strong>사용자 인증 방식 선택</strong>이었다.</p>
<h2 id="문제-상황">문제 상황</h2>
<p>처음에는 단순히 “로그인 기능을 구현한다” 정도로 생각했지만,
구체적인 구현 방식을 논의하면서 자연스럽게 인증 방식에 대한 이야기가 나왔다.</p>
<p>팀 내에서는 크게 두 가지 의견으로 나뉘었다.</p>
<ul>
<li><strong>JWT 기반 인증을 사용하자는 의견</strong></li>
<li><strong>세션 기반 인증을 사용하자는 의견</strong></li>
</ul>
<p>처음에는 단순한 기술 선택처럼 보였지만, 이야기가 깊어질수록 각 방식의 장단점이 부각되면서 쉽게 결론이 나지 않았다.</p>
<h2 id="논쟁의-핵심">논쟁의 핵심</h2>
<p>JWT를 사용하자는 쪽에서는 다음과 같은 이유를 들었다.</p>
<ul>
<li>서버 상태를 최소화할 수 있어 확장성에 유리하다</li>
<li>MSA 구조를 고려하면 더 적합하다</li>
<li>최근 많이 사용되는 방식이라 학습 가치가 있다</li>
</ul>
<p>반면, 세션 기반을 선호한 쪽에서는 이런 의견이 나왔다.</p>
<ul>
<li>구현이 단순하고 안정적이다</li>
<li>로그아웃이나 인증 관리가 직관적이다</li>
<li>현재 프로젝트 규모에서는 과한 선택일 수 있다</li>
</ul>
<p>결국 이 논쟁의 본질은 단순히 기술의 문제가 아니라
<strong>“개발 속도를 우선할 것인지, 확장성과 구조를 고려할 것인지”</strong>에 대한 방향성 차이였다.</p>
<h2 id="해결-과정">해결 과정</h2>
<p>이 상태로는 아무리 토론을 이어가도 결론이 나기 어렵다고 판단했고,
기술 자체가 아니라 <strong>프로젝트의 목표를 기준으로 의사결정을 해야 한다고 생각했다.</strong></p>
<p>그래서 팀원들과 함께 다음과 같은 기준을 먼저 정리했다.</p>
<ol>
<li>이번 프로젝트의 목적은 단순 기능 구현이 아니라 학습과 경험에 있다</li>
<li>MSA 구조를 일부라도 경험해보는 것이 중요하다</li>
<li>일정 내 구현 가능한 수준이어야 한다</li>
</ol>
<p>이 기준을 바탕으로 다시 논의를 진행한 결과,
<strong>확장성과 학습 측면에서 장점이 있는 JWT 방식이 더 적합하다는 결론</strong>을 내릴 수 있었다.</p>
<p>다만, JWT의 단점으로 언급되었던 토큰 관리 문제는 그대로 두지 않고,
Redis를 활용해 보완하기로 했다.</p>
<h2 id="결과">결과</h2>
<p>결과적으로 JWT 기반 인증을 도입하면서 구조적인 설계 경험을 가져갈 수 있었고,
단순 구현을 넘어 실제 서비스 구조를 고민해볼 수 있는 계기가 되었다.</p>
<p>무엇보다 의미 있었던 점은,
기술 선택을 개인의 선호가 아닌 <strong>명확한 기준을 바탕으로 결정했다는 것</strong>이었다.</p>
<p>이 경험 이후로는 새로운 기능이나 기술을 선택할 때도
자연스럽게 “이 선택이 프로젝트 목표에 맞는가?”를 먼저 고민하게 되었다.</p>
<h2 id="마무리">마무리</h2>
<p>요구사항 분석 단계는 단순히 기능을 나열하는 과정이 아니라,
프로젝트의 방향을 결정하는 중요한 단계라는 것을 느꼈다.</p>
<p>그리고 그 과정에서 발생하는 논쟁은 피해야 할 문제가 아니라,
오히려 더 나은 결정을 위한 필수적인 과정이라고 생각하게 되었다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[토이 프로젝트] 아이폰으로 찍은 수업 사진을 노션에 바로 올리는 서비스 만들기]]></title>
            <link>https://velog.io/@0798_hyuk/%ED%86%A0%EC%9D%B4-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EC%95%84%EC%9D%B4%ED%8F%B0%EC%9C%BC%EB%A1%9C-%EC%B0%8D%EC%9D%80-%EC%88%98%EC%97%85-%EC%82%AC%EC%A7%84%EC%9D%84-%EB%85%B8%EC%85%98%EC%97%90-%EB%B0%94%EB%A1%9C-%EC%98%AC%EB%A6%AC%EB%8A%94-%EC%84%9C%EB%B9%84%EC%8A%A4%EB%A5%BC-%EB%A7%8C%EB%93%A0-%EC%9D%B4%EC%9C%A0</link>
            <guid>https://velog.io/@0798_hyuk/%ED%86%A0%EC%9D%B4-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EC%95%84%EC%9D%B4%ED%8F%B0%EC%9C%BC%EB%A1%9C-%EC%B0%8D%EC%9D%80-%EC%88%98%EC%97%85-%EC%82%AC%EC%A7%84%EC%9D%84-%EB%85%B8%EC%85%98%EC%97%90-%EB%B0%94%EB%A1%9C-%EC%98%AC%EB%A6%AC%EB%8A%94-%EC%84%9C%EB%B9%84%EC%8A%A4%EB%A5%BC-%EB%A7%8C%EB%93%A0-%EC%9D%B4%EC%9C%A0</guid>
            <pubDate>Mon, 23 Mar 2026 12:02:54 GMT</pubDate>
            <description><![CDATA[<p>수업을 들으면서 필기나 판서, 교수님 화면을 휴대폰으로 찍는 일은 자주 있었다.<br>문제는 사진을 찍는 것보다, 그 사진을 다시 정리하는 과정이 훨씬 번거롭다는 점이었다.</p>
<p>나는 원래 이런 식으로 작업했다.</p>
<ol>
<li>아이폰으로 사진을 찍는다.</li>
<li>카카오톡 <code>나에게 보내기</code>로 사진을 보낸다.</li>
<li>노트북에서 카카오톡을 열어 사진을 저장하거나 복사한다.</li>
<li>다시 노션을 열어서 붙여넣거나 업로드한다.</li>
</ol>
<p>사진 한 장만 옮길 때는 큰 문제가 아닌 것처럼 보이지만, 수업 시간 동안 이 과정을 반복하다 보면 수업을 이해하는 도중 흐름이 자꾸 끊겼다.<br>특히 여러 장을 연속으로 찍는 날에는, 사진 촬영보다 전송과 정리가 더 귀찮게 느껴졌다.</p>
<hr>
<h2 id="문제-상황">문제 상황</h2>
<p>내 환경은 다음과 같았다.</p>
<ul>
<li>휴대폰: 아이폰</li>
<li>노트북: LG 노트북</li>
<li>운영체제: Windows 11</li>
<li>정리 도구: Notion</li>
</ul>
<p>이 조합에서 내가 원했던 것은 단순했다.</p>
<p><code>방금 찍은 사진을 가능한 바로 노트북에서 쓰고 싶다.</code></p>
<p>하지만 실제 사용 경험은 그렇지 않았다.</p>
<h3 id="불편했던-점">불편했던 점</h3>
<ul>
<li>아이폰과 Windows 노트북 사이 사진 전달이 자연스럽게 이어지지 않는다.</li>
<li>매번 카카오톡이나 메신저를 중간 매개로 써야 한다.</li>
<li>사진을 전송한 뒤에도 다시 노션에 업로드하는 단계가 남아 있다.</li>
<li>수업 흐름 중간에 앱을 여러 번 오가야 해서 집중이 깨진다.</li>
<li>사진을 “찍는 행위”보다 “정리해서 옮기는 행위”가 더 피곤해진다.</li>
</ul>
<hr>
<h2 id="문제-정의">문제 정의</h2>
<p>이 프로젝트에서 정의한 핵심 문제는 아래와 같다.</p>
<h3 id="1-촬영과-정리-사이의-단계가-너무-많다">1. 촬영과 정리 사이의 단계가 너무 많다</h3>
<p>사용자는 단지 수업 사진을 기록하고 싶을 뿐인데,<br>실제로는 촬영 → 전송 → 저장 → 업로드라는 여러 단계를 거쳐야 한다.</p>
<p>즉, <strong>정보를 기록하는 행위보다 전달 과정이 더 무거운 문제</strong>가 있었다.</p>
<h3 id="2-아이폰--windows-조합에서는-즉시성이-부족하다">2. 아이폰 + Windows 조합에서는 즉시성이 부족하다</h3>
<p>애플 생태계 안에서는 비교적 자연스럽게 이어질 수 있는 기능들이 있지만,<br>아이폰과 Windows 노트북 조합에서는 사진을 바로 활용하기 위한 연결이 매끄럽지 않다.</p>
<p>즉, <strong>기기 조합 때문에 작업 흐름이 끊기는 문제</strong>가 있었다.
이는 안그래도 허약한 내 수업 집중상태를 끊는데 충분했다.</p>
<p>-&gt; 물론 이미 상용화된 많은서비스들이 있었겠지만 시장조사보다
내가 그냥 한번 만들어보고 싶다는생각이 더 컸던 거 같다.</p>
<h2 id="내가-원한-해결-방향">내가 원한 해결 방향</h2>
<p>이 프로젝트를 만들면서 내가 원한 경험은 명확했다.</p>
<ul>
<li>아이폰으로 사진을 찍는다.</li>
<li>그 사진이 바로 노트북으로 전달된다.</li>
<li>필요하면 노트북 클립보드에서도 바로 쓸 수 있다.</li>
<li>동시에 노션에도 자동으로 정리된다.</li>
<li>수업 시간에만 활성화되도록 해서 실제 사용 맥락에 맞춘다.</li>
</ul>
<p>즉, 내가 원한 것은 단순한 “사진 업로드 기능”이 아니라<br><strong>수업 기록 흐름을 끊지 않는 자동화된 연결 경험</strong>이었다.</p>
<hr>
<h2 id="이-프로젝트의-목표">이 프로젝트의 목표</h2>
<p>이 프로젝트의 목표는 다음과 같다.</p>
<p><strong>아이폰으로 찍은 수업 사진을, Windows 노트북과 Notion으로 최대한 즉시 연결해<br>중간 전달 과정을 줄이고 기록 흐름을 단순화하는 것</strong></p>
<p>정리하면, 이 서비스는 “사진을 잘 올리는 앱”이 아니라<br><strong>수업 중 기록 과정에서 발생하는 불필요한 전송 마찰을 줄이기 위한 도구</strong>로 시작했다.</p>
<hr>
<h2 id="한-줄로-정리하면">한 줄로 정리하면</h2>
<p><code>카카오톡 나에게 보내기 -&gt; 노트북 저장 -&gt; 노션 업로드</code><br>이 반복 작업이 너무 귀찮아서,</p>
<p><strong>아이폰에서 찍은 수업 사진이 노트북과 노션으로 바로 이어지는 흐름을 만들고 싶었다.</strong></p>
<p><img src="https://velog.velcdn.com/images/0798_hyuk/post/f12e356b-5a7d-4a27-88d1-2383f7d4f8d8/image.png" alt=""></p>
<p>위 사진처럼 잘 사진이 인식이 된다
다만 한가지 문제는 학교 와이파이는 보안이 심해서 연동이 안되어 내 핫스팟을 이용을 해야한다. 집 와이파이는 문제없이 구현이 된다.</p>
<p>깃헙 링크 : 
<a href="https://github.com/0798JiHyuk/class-photo-notion">https://github.com/0798JiHyuk/class-photo-notion</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[기술 경험]Grafana 처음 써본 후기 (삽질 포함)]]></title>
            <link>https://velog.io/@0798_hyuk/%EA%B8%B0%EC%88%A0-%EA%B2%BD%ED%97%98Grafana-%EC%B2%98%EC%9D%8C-%EC%8D%A8%EB%B3%B8-%ED%9B%84%EA%B8%B0-%EC%82%BD%EC%A7%88-%ED%8F%AC%ED%95%A8</link>
            <guid>https://velog.io/@0798_hyuk/%EA%B8%B0%EC%88%A0-%EA%B2%BD%ED%97%98Grafana-%EC%B2%98%EC%9D%8C-%EC%8D%A8%EB%B3%B8-%ED%9B%84%EA%B8%B0-%EC%82%BD%EC%A7%88-%ED%8F%AC%ED%95%A8</guid>
            <pubDate>Tue, 17 Mar 2026 05:21:32 GMT</pubDate>
            <description><![CDATA[<p>요즘 프로젝트 하면서
“서버 잘 돌아가고 있는지 한눈에 보고 싶다”는 생각이 계속 들었다.</p>
<p>로그 찍어서 보는 건 한계가 있어서
찾아보다가 <strong>Grafana</strong>를 알게 됐다.</p>
<hr>
<h2 id="1-grafana-처음엔-이게-뭔지-몰랐다">1. Grafana? 처음엔 이게 뭔지 몰랐다</h2>
<p>처음엔 그냥
“그래프 그려주는 툴인가?” 정도로 생각했는데</p>
<p>써보니까 느낌이 좀 다르다.</p>
<p><strong>데이터를 예쁘게 보여주는 도구</strong>인데
문제는 “데이터는 알아서 안 가져온다”는 거</p>
<p>이걸 모르고 한참 헤맸다...</p>
<hr>
<h2 id="2-일단-설치부터">2. 일단 설치부터</h2>
<p>복잡할 줄 알았는데 Docker로 바로 띄웠다.</p>
<pre><code class="language-bash">docker run -d -p 3000:3000 --name grafana grafana/grafana</code></pre>
<p>켜고 나서
<a href="http://localhost:3000">http://localhost:3000</a> 들어가니까 바로 화면 나옴</p>
<hr>
<h2 id="3-여기서부터-막혔다">3. 여기서부터 막혔다</h2>
<p>들어가보니까
“그래서 뭘 해야 하지?” 상태됨</p>
<p>아무 그래프도 안 보임
이유는 아무런 데이터가 없었기 떄문이다</p>
<p>Grafana는
혼자서는 아무것도 못하는 애였다...</p>
<hr>
<h2 id="4-prometheus-연결하면서-이해됨">4. Prometheus 연결하면서 이해됨</h2>
<p>찾아보니까 다들
Prometheus랑 같이 쓰길래 연결해봄</p>
<p>이때 깨달음</p>
<p>👉 Prometheus = 데이터 모으는 역할
👉 Grafana = 그걸 보여주는 역할</p>
<p>이거 이해하니까 갑자기 전체 흐름이 보였다</p>
<hr>
<h2 id="5-대시보드-만들기-재밌는-구간">5. 대시보드 만들기 (재밌는 구간)</h2>
<p>데이터 연결하고 나서
Dashboard 만들어봤는데</p>
<p>이때부터 좀 재밌어짐</p>
<p>쿼리 하나 넣었는데
그래프 바로 뜨는 거 보고 약간 감탄함</p>
<pre><code class="language-bash">rate(http_requests_total[1m])</code></pre>
<p>👉 “아 이래서 쓰는구나” 싶었다</p>
<hr>
<h2 id="6-써보면서-느낀-점">6. 써보면서 느낀 점</h2>
<p>좋았던 점</p>
<ul>
<li>생각보다 금방 익숙해짐</li>
<li>시각화가 진짜 직관적임</li>
<li>디버깅할 때 도움 많이 될 듯</li>
</ul>
<p>어려웠던 점</p>
<ul>
<li>처음에 개념 이해가 제일 어려움</li>
<li>데이터 없으면 아무것도 못함 (이거 핵심)</li>
</ul>
<hr>
<h2 id="7-한-줄-정리">7. 한 줄 정리</h2>
<p>👉 Grafana는 혼자 쓰는 게 아니라
👉 다른 도구랑 같이 써야 의미 있음</p>
<hr>
<h2 id="8-다음에-해볼-거">8. 다음에 해볼 거</h2>
<ul>
<li>서버 CPU / 메모리 모니터링 붙이기</li>
<li>API 응답속도 그래프로 보기</li>
<li>알림 설정까지 해보기</li>
</ul>
<hr>
<h2 id="마무리">마무리</h2>
<p>처음엔 좀 막막했는데
구조 이해하고 나니까 왜 쓰는지 알겠다</p>
<p>👉 로그만 보는 거랑은 차원이 다름</p>
<p>다음엔
Prometheus까지 같이 정리해볼 생각
할게 너무 많긴해 <img src="https://velog.velcdn.com/images/0798_hyuk/post/92d31f91-5771-43be-9755-d9b677046b1f/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[기술 해결]TypeScript로 만들었던 프로젝트를 Spring Boot로 다시 만들면서 생긴 기술 고민들]]></title>
            <link>https://velog.io/@0798_hyuk/TypeScript%EB%A1%9C-%EB%A7%8C%EB%93%A4%EC%97%88%EB%8D%98-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8%EB%A5%BC-Spring-Boot%EB%A1%9C-%EB%8B%A4%EC%8B%9C-%EB%A7%8C%EB%93%A4%EB%A9%B4%EC%84%9C-%EC%83%9D%EA%B8%B4-%EA%B8%B0%EC%88%A0-%EA%B3%A0%EB%AF%BC%EB%93%A4</link>
            <guid>https://velog.io/@0798_hyuk/TypeScript%EB%A1%9C-%EB%A7%8C%EB%93%A4%EC%97%88%EB%8D%98-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8%EB%A5%BC-Spring-Boot%EB%A1%9C-%EB%8B%A4%EC%8B%9C-%EB%A7%8C%EB%93%A4%EB%A9%B4%EC%84%9C-%EC%83%9D%EA%B8%B4-%EA%B8%B0%EC%88%A0-%EA%B3%A0%EB%AF%BC%EB%93%A4</guid>
            <pubDate>Sun, 08 Mar 2026 23:46:46 GMT</pubDate>
            <description><![CDATA[<p>이전에 TypeScript 기반으로 만들었던 프로젝트를 Spring Boot로 다시 구현하게 되었다.</p>
<p>처음에는 단순히</p>
<blockquote>
<p>&quot;같은 기능을 Java로 다시 구현하면 되겠지&quot;</p>
</blockquote>
<p>라고 생각했다.</p>
<p>하지만 막상 시작해보니 단순한 언어 변경이 아니라 <strong>아키텍처와 개발 방식 자체가 달라지는 작업</strong>이었다.</p>
<p>이번 글에서는 TypeScript 프로젝트를 Spring Boot로 다시 만들면서 생겼던 기술적인 고민과 해결 과정을 정리해보려고 한다.</p>
<hr>
<h1 id="왜-typescript-→-spring-boot로-다시-만들었을까">왜 TypeScript → Spring Boot로 다시 만들었을까</h1>
<p>처음 프로젝트는 다음과 같은 스택으로 만들어졌다.</p>
<pre><code class="language-id=&quot;d1a0k1&quot;">Node.js
TypeScript
Express
MySQL</code></pre>
<p>빠르게 기능을 만들기에는 좋았지만 프로젝트가 커지면서 몇 가지 아쉬움이 생겼다.</p>
<ul>
<li>서비스 구조 관리</li>
<li>인증 처리</li>
<li>코드 구조 유지보수</li>
</ul>
<p>그래서 백엔드 구조를 다시 고민하게 되었고 결국 <strong>Spring Boot 기반으로 다시 구현</strong>해보기로 했다.</p>
<hr>
<h1 id="문제-1-프로젝트-구조를-어떻게-설계할-것인가">문제 1. 프로젝트 구조를 어떻게 설계할 것인가</h1>
<p>TypeScript 프로젝트는 비교적 단순한 구조였다.</p>
<pre><code class="language-id=&quot;d9c2k0&quot;">controllers
services
routes
models</code></pre>
<p>하지만 Spring Boot 프로젝트는 일반적으로 이런 구조를 사용한다.</p>
<pre><code class="language-id=&quot;c1a2c3&quot;">controller
service
repository
entity</code></pre>
<p>여기서 고민이 생겼다.</p>
<blockquote>
<p>TypeScript 프로젝트 구조를 그대로 가져갈까?
아니면 Spring 방식으로 새로 설계할까?</p>
</blockquote>
<p>결론적으로 <strong>Spring의 레이어드 아키텍처를 따르기로 했다.</strong></p>
<pre><code class="language-id=&quot;l2a0d9&quot;">Controller
Service
Repository
Entity</code></pre>
<p>이렇게 구조를 정리하면서 코드의 역할이 더 명확해졌다.</p>
<hr>
<h1 id="문제-2-비동기-처리-방식-차이">문제 2. 비동기 처리 방식 차이</h1>
<p>TypeScript에서는 대부분 비동기 처리를 이렇게 했다.</p>
<pre><code class="language-id=&quot;b3c1a2&quot;">async / await</code></pre>
<p>예를 들어</p>
<pre><code class="language-id=&quot;s8c2x0&quot;">const user = await userRepository.findById(id)</code></pre>
<p>하지만 Spring Boot에서는 기본적으로 <strong>동기 방식</strong>으로 동작한다.</p>
<p>그래서 처음에는 이런 고민이 생겼다.</p>
<blockquote>
<p>Node는 비동기 기반인데
Spring은 왜 동기 방식일까?</p>
</blockquote>
<p>Spring은 <strong>멀티스레드 기반</strong>으로 요청을 처리하기 때문에 대부분의 경우 동기 방식으로도 충분한 성능을 낼 수 있다는 것을 알게 되었다.</p>
<hr>
<h1 id="문제-3-인증-처리-방식">문제 3. 인증 처리 방식</h1>
<p>TypeScript 프로젝트에서는 JWT 인증을 직접 구현했다.</p>
<p>구조는 대략 이렇게 되어 있었다.</p>
<pre><code class="language-id=&quot;f1k2c3&quot;">login
↓
JWT 발급
↓
middleware 인증</code></pre>
<p>하지만 Spring Boot에서는 보통</p>
<pre><code class="language-id=&quot;z3a9k1&quot;">Spring Security</code></pre>
<p>를 사용한다.</p>
<p>여기서 또 고민이 생겼다.</p>
<blockquote>
<p>기존 JWT 로직을 그대로 사용할까?
아니면 Spring Security를 사용할까?</p>
</blockquote>
<p>결국 <strong>Spring Security + JWT 방식</strong>으로 구현했다.</p>
<p>이 과정에서 가장 어려웠던 부분은</p>
<pre><code class="language-id=&quot;t1q2w3&quot;">Security Filter
JWT Filter</code></pre>
<p>구조를 이해하는 것이었다.</p>
<hr>
<h1 id="문제-4-orm-사용-방식-차이">문제 4. ORM 사용 방식 차이</h1>
<p>TypeScript 프로젝트에서는 보통 이런 방식으로 DB를 사용했다.</p>
<pre><code class="language-id=&quot;r4t5y6&quot;">SQL 직접 작성</code></pre>
<p>또는</p>
<pre><code class="language-id=&quot;j7k8l9&quot;">TypeORM</code></pre>
<p>하지만 Spring Boot에서는 보통</p>
<pre><code class="language-id=&quot;m0n1b2&quot;">JPA
Hibernate</code></pre>
<p>를 사용한다.</p>
<p>여기서 또 고민이 생겼다.</p>
<blockquote>
<p>SQL 중심으로 갈까?
ORM을 사용할까?</p>
</blockquote>
<p>결론적으로 <strong>JPA를 사용하되 복잡한 쿼리는 직접 작성</strong>하는 방식으로 정리했다.</p>
<hr>
<h1 id="문제-5-에러-처리-구조">문제 5. 에러 처리 구조</h1>
<p>TypeScript에서는 보통 이렇게 에러 처리를 했다.</p>
<pre><code class="language-id=&quot;u8i9o0&quot;">try / catch</code></pre>
<p>하지만 Spring에서는</p>
<pre><code class="language-id=&quot;p1q2w3&quot;">@ControllerAdvice
@ExceptionHandler</code></pre>
<p>같은 전역 에러 처리를 사용할 수 있었다.</p>
<p>이 구조를 적용하면서 코드가 훨씬 깔끔해졌다.</p>
<hr>
<h1 id="문제-6-환경-설정-관리">문제 6. 환경 설정 관리</h1>
<p>TypeScript 프로젝트에서는 환경변수를 보통 이렇게 관리했다.</p>
<pre><code class="language-id=&quot;a3s4d5&quot;">.env</code></pre>
<p>Spring Boot에서는</p>
<pre><code class="language-id=&quot;f6g7h8&quot;">application.yml
application.properties</code></pre>
<p>를 사용한다.</p>
<p>처음에는 설정이 많아 복잡하게 느껴졌지만 서비스 설정을 한 곳에서 관리할 수 있다는 장점이 있었다.</p>
<hr>
<h1 id="다시-만들면서-느낀-점">다시 만들면서 느낀 점</h1>
<p>같은 기능을 구현하는 프로젝트라도</p>
<pre><code class="language-id=&quot;g8h9j0&quot;">Node.js
Spring Boot</code></pre>
<p>는 개발 방식 자체가 많이 다르다는 것을 느꼈다.</p>
<p>특히 다음 부분에서 차이를 크게 느꼈다.</p>
<ul>
<li>프로젝트 구조</li>
<li>인증 처리 방식</li>
<li>ORM 사용 방식</li>
</ul>
<p>처음에는 단순한 언어 변경이라고 생각했지만 결과적으로는 <strong>백엔드 아키텍처를 다시 고민하는 과정</strong>이 되었다.</p>
<hr>
<h1 id="마무리">마무리</h1>
<p>기존 TypeScript 프로젝트를 Spring Boot로 다시 만들면서 단순히 코드를 옮기는 작업이 아니라 <strong>서비스 구조를 다시 설계하는 경험</strong>을 할 수 있었다.</p>
<p>특히 Spring의 구조적인 설계 방식이 프로젝트가 커질수록 유지보수에 유리하다는 것을 느꼈다.</p>
<p>다음 글에서는</p>
<ul>
<li>Spring Boot + JWT 인증 구현</li>
<li>AWS 서버 배포 과정</li>
</ul>
<p>도 정리해볼 예정이다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[기술 문제]JWT 로그인 구현하면서 고민했던 것들 (Access Token / Refresh Token 구조)]]></title>
            <link>https://velog.io/@0798_hyuk/JWT-%EB%A1%9C%EA%B7%B8%EC%9D%B8-%EA%B5%AC%ED%98%84%ED%95%98%EB%A9%B4%EC%84%9C-%EA%B3%A0%EB%AF%BC%ED%96%88%EB%8D%98-%EA%B2%83%EB%93%A4-Access-Token-Refresh-Token-%EA%B5%AC%EC%A1%B0</link>
            <guid>https://velog.io/@0798_hyuk/JWT-%EB%A1%9C%EA%B7%B8%EC%9D%B8-%EA%B5%AC%ED%98%84%ED%95%98%EB%A9%B4%EC%84%9C-%EA%B3%A0%EB%AF%BC%ED%96%88%EB%8D%98-%EA%B2%83%EB%93%A4-Access-Token-Refresh-Token-%EA%B5%AC%EC%A1%B0</guid>
            <pubDate>Sun, 08 Mar 2026 03:39:25 GMT</pubDate>
            <description><![CDATA[<p>팀 프로젝트에서 로그인 기능을 구현하면서 인증 방식을 고민하게 됐다.
처음에는 세션 기반 인증을 사용할까 고민했지만, 결국 <strong>JWT 기반 인증 방식</strong>을 선택했다.</p>
<p>하지만 막상 구현해보니 단순히 로그인 기능을 만드는 것보다 <strong>토큰 관리와 보안 문제</strong>에서 생각보다 많은 고민이 생겼다.</p>
<p>이번 글에서는 JWT 로그인 구조와 Access Token / Refresh Token을 사용하면서 고민했던 점들을 정리해보려고 한다.</p>
<hr>
<h1 id="jwt란-무엇인가">JWT란 무엇인가</h1>
<p>JWT(Json Web Token)는 <strong>사용자 인증 정보를 토큰 형태로 전달하는 방식</strong>이다.</p>
<p>기존 세션 방식과 가장 큰 차이는 이것이다.</p>
<pre><code>세션 인증
서버에 로그인 상태 저장</code></pre><pre><code>JWT 인증
토큰 안에 사용자 정보를 담아서 인증</code></pre><p>즉 서버가 로그인 상태를 저장하지 않아도 된다.</p>
<p>그래서 <strong>Stateless 인증 방식</strong>이라고 부른다.</p>
<hr>
<h1 id="jwt-구조">JWT 구조</h1>
<p>JWT는 크게 3가지로 구성된다.</p>
<pre><code>Header
Payload
Signature</code></pre><p>예시</p>
<pre><code>xxxxx.yyyyy.zzzzz</code></pre><p>각 역할은 다음과 같다.</p>
<h3 id="header">Header</h3>
<p>토큰 타입과 암호화 알고리즘 정보</p>
<h3 id="payload">Payload</h3>
<p>사용자 정보</p>
<p>예시</p>
<pre><code>userId
email
role</code></pre><h3 id="signature">Signature</h3>
<p>토큰 위조 방지를 위한 서명</p>
<hr>
<h1 id="jwt-로그인-흐름">JWT 로그인 흐름</h1>
<p>JWT 로그인 과정은 보통 다음과 같다.</p>
<pre><code>1. 사용자 로그인 요청
2. 서버에서 사용자 인증
3. JWT 토큰 발급
4. 클라이언트가 토큰 저장
5. API 요청 시 토큰 전달</code></pre><p>API 요청 시 보통 이렇게 전달한다.</p>
<pre><code>Authorization: Bearer {JWT}</code></pre><p>서버에서는 토큰을 검증한 후 요청을 처리한다.</p>
<hr>
<h1 id="access-token--refresh-token-구조">Access Token / Refresh Token 구조</h1>
<p>JWT 인증을 구현할 때 가장 많이 사용하는 방식이</p>
<pre><code>Access Token
Refresh Token</code></pre><p>구조이다.</p>
<h3 id="access-token">Access Token</h3>
<p>특징</p>
<ul>
<li>짧은 유효시간</li>
<li>API 요청 시 사용</li>
</ul>
<p>예</p>
<pre><code>15분
30분</code></pre><h3 id="refresh-token">Refresh Token</h3>
<p>특징</p>
<ul>
<li>Access Token 재발급</li>
<li>긴 유효시간</li>
</ul>
<p>예</p>
<pre><code>7일
14일</code></pre><p>로그인 구조는 보통 이렇게 된다.</p>
<pre><code>로그인
↓
Access Token 발급
Refresh Token 발급
↓
Access Token 만료
↓
Refresh Token으로 재발급</code></pre><hr>
<h1 id="jwt를-사용하면서-생긴-고민">JWT를 사용하면서 생긴 고민</h1>
<p>JWT 인증을 구현하면서 몇 가지 고민이 생겼다.</p>
<hr>
<h2 id="1-토큰-저장-위치">1. 토큰 저장 위치</h2>
<p>토큰을 어디에 저장할 것인가?</p>
<p>대표적인 선택지는</p>
<pre><code>LocalStorage
Cookie</code></pre><p>이다.</p>
<p>하지만 LocalStorage는 <strong>XSS 공격 위험</strong>이 있다.</p>
<p>그래서 최근에는</p>
<pre><code>HttpOnly Cookie</code></pre><p>방식을 많이 사용한다.</p>
<hr>
<h2 id="2-로그아웃-처리">2. 로그아웃 처리</h2>
<p>JWT는 Stateless 방식이라 서버에 세션이 없다.</p>
<p>그래서 로그아웃을 해도 토큰이 살아있다.</p>
<p>이 문제를 해결하기 위해 보통</p>
<pre><code>토큰 블랙리스트
Redis 관리</code></pre><p>같은 방법을 사용한다.</p>
<hr>
<h2 id="3-payload에-어디까지-넣어야-할까">3. Payload에 어디까지 넣어야 할까</h2>
<p>JWT Payload에는 사용자 정보를 넣을 수 있다.</p>
<p>예</p>
<pre><code>userId
email
role</code></pre><p>하지만 데이터를 많이 넣으면 토큰이 커진다.</p>
<p>그래서 보통</p>
<pre><code>userId
role</code></pre><p>정도만 넣는 경우가 많다.</p>
<hr>
<h2 id="4-refresh-token-저장-위치">4. Refresh Token 저장 위치</h2>
<p>Refresh Token을 어디에 저장할지도 고민이었다.</p>
<p>대표적인 방법은</p>
<pre><code>DB 저장
Redis 저장</code></pre><p>이다.</p>
<p>팀 프로젝트에서는 관리 편의성을 위해 <strong>DB에 저장하는 방식</strong>을 사용했다.</p>
<hr>
<h1 id="jwt를-사용하면서-느낀-점">JWT를 사용하면서 느낀 점</h1>
<p>JWT는 확실히 <strong>확장성과 분산 시스템에서 장점</strong>이 있는 인증 방식이다.</p>
<p>하지만 단순히 로그인 기능을 구현하는 것만 보면</p>
<pre><code>Session 방식이 더 단순할 수도 있다.</code></pre><p>특히 토큰 관리와 보안 문제까지 고려하면 JWT 구조를 제대로 설계하는 것이 중요하다고 느꼈다.</p>
<hr>
<h1 id="마무리">마무리</h1>
<p>JWT 인증을 구현하면서 느낀 점은 이것이다.</p>
<blockquote>
<p>JWT는 단순한 토큰 인증이 아니라 토큰 관리 구조를 설계하는 문제에 가깝다.</p>
</blockquote>
<p>Access Token / Refresh Token 구조와 토큰 보안 문제까지 고려해야 안정적인 인증 시스템을 만들 수 있다.</p>
<p>다음에는 실제로 <strong>Spring Security에서 JWT 인증을 구현하는 과정</strong>도 정리해볼 예정이다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[기술 문제]4년 전 Spring 프로젝트를 Spring Boot로 옮기면서 생긴 기술 고민들]]></title>
            <link>https://velog.io/@0798_hyuk/%EA%B8%B0%EC%88%A0-%EB%AC%B8%EC%A0%9C4%EB%85%84-%EC%A0%84-Spring-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8%EB%A5%BC-Spring-Boot%EB%A1%9C-%EC%98%AE%EA%B8%B0%EB%A9%B4%EC%84%9C-%EC%83%9D%EA%B8%B4-%EA%B8%B0%EC%88%A0-%EA%B3%A0%EB%AF%BC%EB%93%A4</link>
            <guid>https://velog.io/@0798_hyuk/%EA%B8%B0%EC%88%A0-%EB%AC%B8%EC%A0%9C4%EB%85%84-%EC%A0%84-Spring-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8%EB%A5%BC-Spring-Boot%EB%A1%9C-%EC%98%AE%EA%B8%B0%EB%A9%B4%EC%84%9C-%EC%83%9D%EA%B8%B4-%EA%B8%B0%EC%88%A0-%EA%B3%A0%EB%AF%BC%EB%93%A4</guid>
            <pubDate>Fri, 06 Mar 2026 10:59:57 GMT</pubDate>
            <description><![CDATA[<p>최근에 예전에 만들었던 Spring 프로젝트를 다시 열어보게 됐다.</p>
<p>4년 전에 만들었던 프로젝트라 그런지 구조도 꽤 낡아 있었고,
요즘 기준으로 보면 유지보수가 쉽지 않은 구조였다.</p>
<p>그래서 자연스럽게 이런 생각이 들었다.</p>
<blockquote>
<p>&quot;이 프로젝트를 Spring Boot로 옮겨볼까?&quot;</p>
</blockquote>
<p>Spring Boot는 요즘 대부분의 프로젝트에서 사용되고 있고
설정도 훨씬 간단해졌기 때문에 리팩토링 겸 마이그레이션을 해보려고 했다.</p>
<p>하지만 막상 시작해보니 생각보다 고민거리가 많았다.</p>
<hr>
<h1 id="1-xml-설정을-어떻게-처리해야-할까">1. XML 설정을 어떻게 처리해야 할까?</h1>
<p>예전 프로젝트를 열어보자마자 가장 먼저 보였던 건 <strong>엄청난 양의 XML 설정 파일</strong>이었다.</p>
<pre><code>applicationContext.xml
dispatcher-servlet.xml
mybatis-config.xml
security-context.xml</code></pre><p>Spring Boot는 기본적으로 <strong>Java Config 기반</strong>으로 동작하는데
이걸 전부 옮겨야 할까?</p>
<p>처음에는 단순하게 생각했다.</p>
<blockquote>
<p>&quot;XML을 그냥 import 하면 되는 거 아닌가?&quot;</p>
</blockquote>
<p>하지만 문제가 있었다.</p>
<p>Spring Boot는 <strong>Auto Configuration</strong> 기반으로 돌아가는데
기존 XML 설정이 충돌할 가능성이 있었다.</p>
<p>그래서 고민이 생겼다.</p>
<ul>
<li>기존 XML을 유지할까?</li>
<li>아니면 Java Config로 전부 바꿀까?</li>
</ul>
<p>지금 고민 중인 방향은 이렇다.</p>
<p><strong>핵심 설정만 Java Config로 옮기고
나머지는 점진적으로 제거하는 방식</strong></p>
<p>한 번에 다 바꾸면 리스크가 너무 커질 것 같다.</p>
<hr>
<h1 id="2-war-프로젝트를-jar로-바꿔야-할까">2. WAR 프로젝트를 JAR로 바꿔야 할까?</h1>
<p>예전 프로젝트는 <strong>Tomcat에 배포하는 WAR 구조</strong>였다.</p>
<pre><code>mvn package
→ war 파일 생성
→ tomcat/webapps 배포</code></pre><p>하지만 Spring Boot는 보통 이렇게 사용한다.</p>
<pre><code>java -jar application.jar</code></pre><p>여기서 고민이 생겼다.</p>
<blockquote>
<p>WAR 구조를 유지해야 할까
아니면 Boot 스타일 JAR로 바꿔야 할까?</p>
</blockquote>
<p>JAR로 바꾸면 장점이 많다.</p>
<ul>
<li>내장 Tomcat</li>
<li>배포 간단</li>
<li>Docker 사용 쉬움</li>
</ul>
<p>하지만 기존 프로젝트 구조가 WAR 기준으로 만들어져 있어서
생각보다 수정해야 할 부분이 많았다.</p>
<p>특히 다음 부분이 걸렸다.</p>
<pre><code>web.xml
Servlet 설정
Filter 설정
Listener 설정</code></pre><p>이걸 전부 <strong>Spring Boot 방식으로 바꿔야 한다.</strong></p>
<p>그래서 지금은 이 부분을 어떻게 정리할지 고민 중이다.</p>
<hr>
<h1 id="3-로그-시스템을-그대로-써도-될까">3. 로그 시스템을 그대로 써도 될까?</h1>
<p>기존 프로젝트는 로그를 이렇게 사용하고 있었다.</p>
<pre><code>log4j</code></pre><p>하지만 요즘 Spring Boot에서는 대부분</p>
<pre><code>logback</code></pre><p>을 사용한다.</p>
<p>그래서 또 고민이 생겼다.</p>
<blockquote>
<p>기존 log4j를 유지할까?
아니면 Boot 기본 로그 시스템을 사용할까?</p>
</blockquote>
<p>문제는 log4j 설정 파일이 꽤 많이 커스터마이징 되어 있다는 점이다.</p>
<pre><code>log4j.xml</code></pre><p>이걸 그대로 유지하면 빠르게 마이그레이션할 수 있지만
장기적으로 보면 Boot 기본 구조를 따르는 게 맞을 것 같기도 하다.</p>
<hr>
<h1 id="4-mybatis-설정은-그대로-써도-될까">4. MyBatis 설정은 그대로 써도 될까?</h1>
<p>이 프로젝트는 ORM 대신 <strong>MyBatis</strong>를 사용하고 있었다.</p>
<p>구조는 이런 식이었다.</p>
<pre><code>mapper.xml
SqlSessionFactory
SqlSessionTemplate</code></pre><p>Spring Boot에서는 <code>mybatis-spring-boot-starter</code>를 쓰면
설정이 훨씬 단순해진다.</p>
<p>하지만 또 고민이 생긴다.</p>
<p>기존 설정을 보면 이런 코드가 많다.</p>
<pre><code>SqlSessionFactoryBean
MapperScannerConfigurer</code></pre><p>Boot에서는 이런 설정이 대부분 필요 없어진다.</p>
<p>그래서 고민 중이다.</p>
<blockquote>
<p>기존 설정을 유지하면서 옮길까
아니면 Boot 방식으로 새로 구성할까</p>
</blockquote>
<hr>
<h1 id="5-패키지-구조를-바꿔야-할까">5. 패키지 구조를 바꿔야 할까?</h1>
<p>예전 프로젝트의 패키지 구조는 이랬다.</p>
<pre><code>controller
service
dao
vo
util
common</code></pre><p>전형적인 <strong>레이어드 구조</strong>다.</p>
<p>하지만 요즘은 이런 구조도 많이 보인다.</p>
<pre><code>user
order
payment</code></pre><p>즉 <strong>도메인 중심 구조</strong></p>
<p>그래서 또 고민이 생겼다.</p>
<blockquote>
<p>마이그레이션하면서 구조까지 바꿀까?</p>
</blockquote>
<p>하지만 지금 생각은 이렇다.</p>
<p><strong>구조까지 바꾸면 리팩토링 범위가 너무 커진다.</strong></p>
<p>그래서 일단은</p>
<ul>
<li>Boot 마이그레이션 먼저</li>
<li>구조 리팩토링은 나중</li>
</ul>
<p>이 방향으로 가는 게 맞을 것 같다.</p>
<hr>
<h1 id="6-의존성-충돌-문제">6. 의존성 충돌 문제</h1>
<p>마이그레이션을 하다 보니 가장 예상되는 문제는 이것이다.</p>
<pre><code>dependency 충돌</code></pre><p>예전 프로젝트는 이런 라이브러리를 사용하고 있었다.</p>
<pre><code>spring 4.x
jackson 2.x
commons-fileupload</code></pre><p>Spring Boot로 넘어오면
대부분 <strong>Boot가 버전을 관리한다.</strong></p>
<p>그래서 이런 문제가 생길 수 있다.</p>
<pre><code>ClassNotFoundException
NoSuchMethodError</code></pre><p>이 문제는 실제로 꽤 많이 발생한다고 한다.</p>
<p>그래서 dependency를 하나씩 확인하면서
Boot 기준으로 정리할 필요가 있을 것 같다.</p>
<hr>
<h1 id="아직-해결하지-못한-고민">아직 해결하지 못한 고민</h1>
<p>지금 이 마이그레이션을 하면서
여전히 고민 중인 것들이 있다.</p>
<ul>
<li>XML 설정을 어디까지 제거할까?</li>
<li>WAR 구조를 유지할까?</li>
<li>로그 시스템을 바꿀까?</li>
<li>MyBatis 설정을 다시 짤까?</li>
</ul>
<p>생각보다 단순한 작업이 아니었다.</p>
<p>하지만 이런 고민을 하다 보니
예전에 아무 생각 없이 쓰던 Spring 구조를
다시 이해하게 되는 계기가 된 것 같다.</p>
<hr>
<h1 id="앞으로-해보고-싶은-것">앞으로 해보고 싶은 것</h1>
<p>Spring Boot로 옮기면서
다음 것들도 같이 해보고 싶다.</p>
<ul>
<li>Docker 배포</li>
<li>CI/CD 구축</li>
<li>서버 구조 개선</li>
</ul>
<p>단순히 &quot;Spring Boot로 옮겼다&quot;가 아니라
<strong>프로젝트 구조 자체를 한번 정리하는 과정</strong>이 될 것 같다.</p>
<p>아직 마이그레이션은 진행 중이다.</p>
<p>이 과정에서 생기는 문제들을
하나씩 기록해보려고 한다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[기술 해결]AWS 프리티어 1GB 서버에서 Spring + MySQL + AI 모델을 돌리려다 서버가 터진 이야기]]></title>
            <link>https://velog.io/@0798_hyuk/%EA%B8%B0%EC%88%A0-%ED%95%B4%EA%B2%B0AWS-%ED%94%84%EB%A6%AC%ED%8B%B0%EC%96%B4-1GB-%EC%84%9C%EB%B2%84%EC%97%90%EC%84%9C-Spring-MySQL-AI-%EB%AA%A8%EB%8D%B8%EC%9D%84-%EB%8F%8C%EB%A6%AC%EB%A0%A4%EB%8B%A4-%EC%84%9C%EB%B2%84%EA%B0%80-%ED%84%B0%EC%A7%84-%EC%9D%B4%EC%95%BC%EA%B8%B0</link>
            <guid>https://velog.io/@0798_hyuk/%EA%B8%B0%EC%88%A0-%ED%95%B4%EA%B2%B0AWS-%ED%94%84%EB%A6%AC%ED%8B%B0%EC%96%B4-1GB-%EC%84%9C%EB%B2%84%EC%97%90%EC%84%9C-Spring-MySQL-AI-%EB%AA%A8%EB%8D%B8%EC%9D%84-%EB%8F%8C%EB%A6%AC%EB%A0%A4%EB%8B%A4-%EC%84%9C%EB%B2%84%EA%B0%80-%ED%84%B0%EC%A7%84-%EC%9D%B4%EC%95%BC%EA%B8%B0</guid>
            <pubDate>Fri, 06 Mar 2026 10:55:24 GMT</pubDate>
            <description><![CDATA[<p>프로젝트를 진행하면서 AWS 프리티어 EC2 서버를 사용하고 있었다.
프리티어 인스턴스의 메모리는 <strong>1GB</strong>라서 처음에는 가벼운 서비스 정도는 충분히 돌릴 수 있을 거라고 생각했다.</p>
<p>하지만 프로젝트가 커지면서 문제가 발생했다.</p>
<p>서비스 구조는 대략 이랬다.</p>
<ul>
<li>Backend: Spring Boot</li>
<li>Database: MySQL</li>
<li>AI Model: Python 기반 모델</li>
<li>Infrastructure: AWS EC2 (Free Tier)</li>
</ul>
<p>처음에는 모든 것을 <strong>하나의 서버에서 같이 실행</strong>했다.</p>
<pre><code>Spring Boot
MySQL
AI Model</code></pre><p>결과는 예상보다 빠르게 나타났다.</p>
<p><strong>서버 다운.</strong></p>
<hr>
<h2 id="문제-상황">문제 상황</h2>
<p>처음에는 단순히 서버가 느려지는 수준이었다.</p>
<ul>
<li>API 응답이 느려짐</li>
<li>MySQL 쿼리 지연</li>
<li>AI 모델 inference 시간이 길어짐</li>
</ul>
<p>하지만 어느 순간부터는 아예 서버가 멈췄다.</p>
<p>SSH 접속도 안 되고, EC2 상태를 보면 <strong>메모리 부족(OOM)</strong> 상황이었다.</p>
<p>1GB 메모리 환경에서 동시에 돌아가고 있던 것들:</p>
<ul>
<li>Spring Boot JVM</li>
<li>MySQL</li>
<li>Python AI 모델</li>
</ul>
<p>특히 <strong>Spring Boot의 JVM + Python 모델 메모리 사용량</strong>이 생각보다 컸다.</p>
<p>결국 구조 자체를 다시 고민하게 됐다.</p>
<hr>
<h2 id="고민-서버를-업그레이드할까-아니면-구조를-바꿀까">고민: 서버를 업그레이드할까? 아니면 구조를 바꿀까?</h2>
<p>가장 쉬운 방법은 EC2 인스턴스를 업그레이드하는 것이었다.</p>
<p>하지만 프로젝트 특성상 <strong>프리티어 환경에서 최대한 해결해보고 싶었다.</strong></p>
<p>그래서 두 가지 접근을 했다.</p>
<p>1️⃣ 백엔드와 DB의 <strong>메모리 사용량을 줄인다</strong>
2️⃣ AI 모델을 <strong>서버에서 분리한다</strong></p>
<hr>
<h2 id="1-spring-boot-메모리-튜닝">1. Spring Boot 메모리 튜닝</h2>
<p>Spring Boot는 기본 설정 그대로 실행하면 JVM 메모리를 꽤 많이 사용한다.</p>
<p>그래서 JVM 옵션을 조정했다.</p>
<pre><code>-Xms256m
-Xmx512m</code></pre><p>초기 메모리와 최대 메모리를 제한해서 <strong>Spring이 서버 메모리를 과도하게 점유하지 않도록 설정</strong>했다.</p>
<p>또한 불필요한 dependency를 제거하고
로깅 레벨도 최소화했다.</p>
<hr>
<h2 id="2-mysql-메모리-튜닝">2. MySQL 메모리 튜닝</h2>
<p>MySQL 역시 기본 설정으로 두면 메모리 사용량이 꽤 높다.</p>
<p>그래서 다음 설정을 조정했다.</p>
<p>대표적으로:</p>
<ul>
<li><code>innodb_buffer_pool_size</code></li>
<li><code>max_connections</code></li>
</ul>
<p>프리티어 서버 환경에 맞게 <strong>버퍼 크기를 줄이고 연결 수를 제한</strong>했다.</p>
<p>결과적으로 MySQL 메모리 사용량을 꽤 줄일 수 있었다.</p>
<hr>
<h2 id="3-ai-서버-분리-fastapi">3. AI 서버 분리 (FastAPI)</h2>
<p>가장 큰 문제는 <strong>AI 모델이었다.</strong></p>
<p>Python 기반 모델은 메모리를 꽤 많이 사용하고,
특히 모델이 로드될 때 메모리를 크게 차지했다.</p>
<p>그래서 구조를 다음처럼 변경했다.</p>
<h3 id="기존-구조">기존 구조</h3>
<pre><code>Client
   ↓
Spring Server
   ↓
AI Model (same server)</code></pre><h3 id="변경된-구조">변경된 구조</h3>
<pre><code>Client
   ↓
Spring Server
   ↓
FastAPI AI Server</code></pre><p>AI 모델은 <strong>별도의 서버에서 FastAPI로 운영</strong>했다.</p>
<p>Spring에서는 AI 요청이 필요할 때</p>
<pre><code>POST /predict</code></pre><p>API를 호출하도록 만들었다.</p>
<p>이렇게 하면서 얻은 장점은 명확했다.</p>
<ul>
<li>AI 모델이 <strong>Spring 서버 메모리를 사용하지 않음</strong></li>
<li>AI 서버를 <strong>독립적으로 확장 가능</strong></li>
<li>서비스 구조가 <strong>마이크로서비스 형태로 분리</strong></li>
</ul>
<hr>
<h2 id="결과">결과</h2>
<p>구조를 변경한 이후</p>
<ul>
<li>서버 다운 문제 해결</li>
<li>API 응답 안정화</li>
<li>AI inference 요청도 안정적으로 처리</li>
</ul>
<p>무엇보다 좋았던 점은 <strong>인프라 구조에 대해 더 깊이 고민하게 됐다는 것</strong>이다.</p>
<p>단순히 &quot;서버 사양을 올리는 것&quot;보다</p>
<ul>
<li>메모리 사용 구조</li>
<li>서비스 분리</li>
<li>API 기반 통신</li>
</ul>
<p>같은 것들을 실제로 경험해 볼 수 있었다.</p>
<hr>
<h2 id="배운-점">배운 점</h2>
<p>이번 경험을 통해 느낀 점은 하나였다.</p>
<p><strong>&quot;문제가 생기면 서버를 키우기 전에 구조를 먼저 고민해보자.&quot;</strong></p>
<p>특히 AI 서비스는</p>
<ul>
<li>Backend</li>
<li>Database</li>
<li>AI Inference</li>
</ul>
<p>를 <strong>분리하는 구조가 훨씬 안정적</strong>이라는 걸 직접 체감했다.</p>
<p>AWS 프리티어 같은 제한된 환경에서도
구조를 잘 설계하면 충분히 운영할 수 있다는 것도 배웠다.</p>
<hr>
<h2 id="다음-목표">다음 목표</h2>
<p>다음에는 다음 부분도 개선해보고 싶다.</p>
<ul>
<li>Docker 기반 서비스 분리</li>
<li>Nginx Reverse Proxy 적용</li>
<li>AI 서버 GPU 환경 실험</li>
</ul>
<p>아직 작은 프로젝트지만
이런 기술 고민들이 쌓여서 더 좋은 구조를 만들 수 있다고 생각한다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[개발자 일기]🏆 GDGoC 연합 해커톤 후기 – 취업난 속에서 우리가 만든 것]]></title>
            <link>https://velog.io/@0798_hyuk/%EA%B0%9C%EB%B0%9C%EC%9E%90-%EC%9D%BC%EA%B8%B0-GDGoC-%EC%97%B0%ED%95%A9-%ED%95%B4%EC%BB%A4%ED%86%A4-%ED%9B%84%EA%B8%B0-%EC%B7%A8%EC%97%85%EB%82%9C-%EC%86%8D%EC%97%90%EC%84%9C-%EC%9A%B0%EB%A6%AC%EA%B0%80-%EB%A7%8C%EB%93%A0-%EA%B2%83</link>
            <guid>https://velog.io/@0798_hyuk/%EA%B0%9C%EB%B0%9C%EC%9E%90-%EC%9D%BC%EA%B8%B0-GDGoC-%EC%97%B0%ED%95%A9-%ED%95%B4%EC%BB%A4%ED%86%A4-%ED%9B%84%EA%B8%B0-%EC%B7%A8%EC%97%85%EB%82%9C-%EC%86%8D%EC%97%90%EC%84%9C-%EC%9A%B0%EB%A6%AC%EA%B0%80-%EB%A7%8C%EB%93%A0-%EA%B2%83</guid>
            <pubDate>Sun, 15 Feb 2026 09:53:02 GMT</pubDate>
            <description><![CDATA[<h4 id="🏆-gdgoc-연합-해커톤-후기--취업난-속에서-우리가-만든-것">🏆 GDGoC 연합 해커톤 후기 – 취업난 속에서 우리가 만든 것</h4>
<p><a href="https://velog.velcdn.com/images/0798_hyuk/post/e96e74ac-5793-4e4e-9947-b79820a68012/image.jpg"></a></p>
<p>처음 해커톤에 나갔다.
결과는 장려상.</p>
<p>상보다 더 의미 있었던 건
“지금 시대에 개발자는 어떤 사람이 되어야 하는가”에 대한 생각이었다.</p>
<p><strong>📌 1. 주제 선정</strong></p>
<p>GDGoC 연합동아리에서 주최한 해커톤의 주제는 취업난이었다.</p>
<p>취준생인 나에게 이 주제는 멀지 않았다.</p>
<p>정보는 넘쳐난다.</p>
<p>하지만 정리할 시간은 없다.</p>
<p>뉴스는 보지만 면접 답변으로 연결하지 못한다.</p>
<p>우리는 여기서 문제를 정의했다.</p>
<p>“취준생은 정보가 부족한 게 아니라,
정보를 ‘면접에서 쓸 수 있는 형태’로 가공할 시간이 부족하다.”</p>
<p><strong>💡 우리가 만든 서비스 – 스포일러 (Spoiler)</strong>
한 줄 설명</p>
<p>관심 기업과 직무를 설정하면
AI가 면접 관점으로 요약해 푸시 알림으로 전달하는 초개인화 면접 비서</p>
<p><strong>🔎 문제 정의</strong></p>
<p>기업 분석은 중요하지만 지속하기 어렵다.</p>
<p>뉴스는 많지만 “면접 답변용”으로 정리되지 않는다.</p>
<p>앱을 매번 열어 확인하는 행동 자체가 피로하다.</p>
<p><strong>🚀 해결 전략</strong></p>
<p>우리는 역설적인 UX를 택했다.</p>
<p>“사용자가 앱을 켜지 않게 만드는 앱”</p>
<p>잠금화면 푸시 알림에서 1줄 핵심 요약</p>
<p>탭하면 3줄 요약 + 면접 활용 포인트</p>
<p>직무별 예상 질문 자동 생성</p>
<p><strong>🧠 기술 설계</strong></p>
<p>나는 팀에서 백엔드를 맡았다.</p>
<p>🔹 왜 Node.js를 선택했는가?</p>
<p>해커톤은 속도가 생명이라도 들었다
빠른 개발, JS 생태계 활용, 비동기 처리를 통한 뉴스 수집, 데이터 가공을 위해 선택했다.</p>
<p>🔹 왜 Express 기반 구조를 사용했는가?</p>
<p>빠른 REST API 구성</p>
<p>미들웨어 구조로 확장 가능</p>
<p>데모에 최적화된 가벼운 구조</p>
<p>해커톤에서는 “완벽한 아키텍처”보다
빠르고 안정적인 MVP 구현이 더 중요했다.</p>
<p>사실 익숙한 언어는 java 프레임워크는 Spring Boot 이였지만 처음이라 멋도 모르고 Node.js 로시작하였다..
그러고 후회는 엄청했다.</p>
<p>🔹 AI 파이프라인 설계</p>
<p>우리는 단순 요약이 아니라
“면접형 재해석”을 목표로 했다.</p>
<p>처리 흐름</p>
<ol>
<li><p>뉴스 수집 (API 기반)</p>
</li>
<li><p>필터링 (중복/광고 제거)</p>
</li>
<li><p>LLM 호출</p>
</li>
<li><p>직무별 질문 생성</p>
</li>
<li><p>DB 저장</p>
</li>
<li><p>푸시 전송</p>
</li>
</ol>
<p>여기서 핵심은 프롬프트 설계였다.</p>
<p>“이 뉴스를 면접관 관점에서 재해석하라.”</p>
<p>단순 요약이 아니라
질문으로 변환시키는 로직이 우리 서비스의 차별점이었다.</p>
<h3 id="회고록">[회고록]</h3>
<p>🔥 인상 깊었던 순간</p>
<p>해커톤 리더 분이 이런 말을 했다.</p>
<p>“이제는 코더가 아니라 리뷰어가 살아남는다.”</p>
<p>그 말이 머리에 계속 맴돌았다.</p>
<p>AI가 코드를 작성하는 시대에
개발자는 점점 코드 작성자에서
의사결정자, 검증자, 구조 설계자로 이동하고 있다.</p>
<p>이미 이전부터 느꼈지만 이번 해커톤에서 더 느낀거 같다.</p>
<p>AI가 코드 초안을 만들고</p>
<p>우리는 그걸 다듬고</p>
<p>구조를 설계하고</p>
<p>트레이드오프를 판단했다</p>
<p>이게 바로 “리뷰어로서의 개발”이 아닐까 생각했다.</p>
<p>🤝 팀 구성과 협업</p>
<p>총 4명 팀</p>
<p>나는 백엔드</p>
<p>해커톤은 첫 경험</p>
<p>처음이라 긴장도 많이 했다.</p>
<p>하지만:</p>
<p>역할 분배</p>
<p>API 스펙 정리</p>
<p>빠른 피드백 루프</p>
<p>이 과정을 겪으며
“개발은 혼자가 아니라 팀 스포츠”라는 걸 실감했다.</p>
<p>사실 고난도 있었다.
처음 해커톤이라 아키텍처 설계부터 시간분배 등등 빵꾸가 너무나도 많았다
솔직히 처음 기획한 api를 다 만들지도 못했다.
그래도 문제정의에서 해결하고자 한 기능들은 구현을 했고 핵심 로직또한 구현은 완료하였다.
그저 아쉬울뿐..</p>
<p>이번 해커톤을 통해 위처럼 힘든점도 있었지만 얻은것 또한 많았다</p>
<p>짧은시간안에 AI 파이프라인 설계하는 경험을 하였고
개인화 데이터 설계
직무 기반 동적 콘텐츠 설계등을 해볼 수 있었다.</p>
<p>두번쨰로는</p>
<p>나는 그동안 “기능 구현” 중심으로 생각했다.
이번에는 달랐다.
왜 이 기능이 필요한가?
사용자 행동은 어떻게 바뀌는가?
이 서비스가 실제 취준생에게 의미 있는가?</p>
<p>문제 정의 → 해결 설계 → 구현</p>
<p>이 흐름을 처음으로 제대로 경험했다.</p>
<h4 id="🏆-그리고-결과">🏆 그리고 결과</h4>
<p>장려상 수상.</p>
<p>물론 대상은 아니었지만,
처음 해커톤에서 이 정도 결과는 충분히 의미 있었다고 생각한다.</p>
<p>하지만 상보다 더 값진 건</p>
<p>“나는 단순 코더가 아니라
문제를 정의하려는 개발자가 되고 있다”</p>
<p>는 확신이었다.</p>
<p>🎯 앞으로의 방향</p>
<p>이번 해커톤을 통해 느꼈다.</p>
<p>AI 시대에 살아남는 개발자는:</p>
<p>코드를 많이 치는 사람이 아니라</p>
<p>구조를 설계하는 사람</p>
<p>문제를 정의하는 사람</p>
<p>AI를 도구로 활용하는 사람</p>
<p>나는 이제
코더가 아니라 리뷰어이자 설계자가 되기 위한 준비를 시작하려 한다.</p>
<p>마무리</p>
<p>취업난 속에서
우리는 또 하나의 취업 준비 서비스를 만들었다.</p>
<p>아이러니하지만,
그 과정이 나를 더 단단하게 만들었다.</p>
<p>다음 해커톤에서는
더 깊은 설계와 더 강한 문제 정의로 도전해보고 싶다.</p>
<p>notion : 
<a href="https://www.notion.so/GDGoC-2ff3762acb5c80f99e2ff0ff6ca51043">https://www.notion.so/GDGoC-2ff3762acb5c80f99e2ff0ff6ca51043</a></p>
<p>github : 
<a href="https://github.com/nalleum/nalleum_backend">https://github.com/nalleum/nalleum_backend</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[프로젝트 기록] 보이스피싱 대응 훈련 백엔드(청음) 개선기]]></title>
            <link>https://velog.io/@0798_hyuk/%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EA%B8%B0%EB%A1%9D-%EB%B3%B4%EC%9D%B4%EC%8A%A4%ED%94%BC%EC%8B%B1-%EB%8C%80%EC%9D%91-%ED%9B%88%EB%A0%A8-%EB%B0%B1%EC%97%94%EB%93%9C%EC%B2%AD%EC%9D%8C-%EA%B0%9C%EC%84%A0%EA%B8%B0</link>
            <guid>https://velog.io/@0798_hyuk/%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EA%B8%B0%EB%A1%9D-%EB%B3%B4%EC%9D%B4%EC%8A%A4%ED%94%BC%EC%8B%B1-%EB%8C%80%EC%9D%91-%ED%9B%88%EB%A0%A8-%EB%B0%B1%EC%97%94%EB%93%9C%EC%B2%AD%EC%9D%8C-%EA%B0%9C%EC%84%A0%EA%B8%B0</guid>
            <pubDate>Sun, 15 Feb 2026 09:16:59 GMT</pubDate>
            <description><![CDATA[<h1 id="프로젝트-기록-보이스피싱-대응-훈련-백엔드guardian-server-개선기">[프로젝트 기록] 보이스피싱 대응 훈련 백엔드(guardian-server) 개선기</h1>
<p>데이콘(공모전 주최) 링크 : <a href="https://dacon.io/competitions/official/236666/overview/description">https://dacon.io/competitions/official/236666/overview/description</a>
공용문서 링크 : 
<a href="https://www.notion.so/2fd189dee3ba80fb8e4ed264bd944ea2">https://www.notion.so/2fd189dee3ba80fb8e4ed264bd944ea2</a>
깃헙 링크 : 
<a href="https://github.com/0798JiHyuk/-repository">https://github.com/0798JiHyuk/-repository</a>
(추후 조직링크로 변경..)</p>
<h2 id="한-줄-소개">한 줄 소개</h2>
<p>실전형 보이스피싱 대응 학습을 위해, 숏폼/롱폼 훈련 결과를 자동 집계하고 주간 리포트까지 생성하는 백엔드 기능을 고도화했다.</p>
<h2 id="프로젝트-배경">프로젝트 배경</h2>
<p>이번 작업의 목표는 크게 두 가지였다.</p>
<ol>
<li>사용자 훈련 데이터를 끝나자마자 요약해 리포트로 제공하기</li>
<li>롱폼 시뮬레이터 답변 품질을 높이기 위해 대화 맥락(history)을 안정적으로 전달하기</li>
</ol>
<p>기존에는 <code>weekly_reports</code> 조회 API는 있었지만, 실제 리포트 생성 로직이 비어 있어 체감 가능한 피드백 경험이 약했다. 또한 롱폼 응답 생성 시 직전 맥락 반영이 제한적이라 답변 일관성이 흔들리는 문제가 있었다.</p>
<h2 id="이번에-구현한-핵심-작업">이번에 구현한 핵심 작업</h2>
<h3 id="1-주간-리포트-생성-서비스-구현">1) 주간 리포트 생성 서비스 구현</h3>
<p>파일: <code>src/services/reports.service.ts</code></p>
<p>기존 <code>export const reportsService = {};</code> 상태에서 실제 생성 로직을 완성했다.</p>
<ul>
<li>최근 7일 기준 기간 계산 (<code>from_date</code>, <code>to_date</code>)</li>
<li><code>training_results</code> 기준 훈련 횟수/평균 점수/정확도 집계</li>
<li>모드별 취약 유형 추출<ul>
<li><code>short</code>: <code>training_shorts.category_code</code></li>
<li><code>long</code>: <code>training_scenarios.category</code></li>
</ul>
</li>
<li>OpenAI Responses API를 호출해 한국어 요약 생성<ul>
<li><code>one_line_feedback</code></li>
<li><code>weak_patterns[]</code></li>
<li><code>action_guides[]</code></li>
</ul>
</li>
<li><code>weekly_reports</code> upsert 처리 (<code>ON CONFLICT</code>)</li>
<li>FK 이슈(에러코드 <code>23503</code>) 발생 시 <code>top_wrong_type_code=null</code>로 재시도하는 안전장치 추가</li>
</ul>
<p>핵심 포인트는 &quot;집계 SQL + AI 요약 + DB upsert&quot;를 한 사이클로 묶어, 조회 전에 데이터가 만들어지는 구조를 만든 것이다.</p>
<h3 id="2-훈련-종료-시-자동-리포트-생성-연결">2) 훈련 종료 시 자동 리포트 생성 연결</h3>
<p>파일:</p>
<ul>
<li><code>src/routes/trainingShort.routes.ts</code></li>
<li><code>src/routes/trainingLong.routes.ts</code></li>
</ul>
<p>숏폼/롱폼 세션 <code>finish</code> 시점에 <code>generateWeeklyReport(userId, mode)</code>를 호출하도록 연결했다.</p>
<ul>
<li>학습 직후 리포트 최신화</li>
<li>리포트 생성 실패가 학습 완료 응답 자체를 막지 않도록 <code>try/catch + warn</code> 처리</li>
</ul>
<p>즉, 사용자 경험 관점에서 &quot;훈련 완료 -&gt; 바로 리포트 확인&quot; 흐름이 자연스럽게 이어지게 했다.</p>
<h3 id="3-리포트-조회-api-안정성-개선">3) 리포트 조회 API 안정성 개선</h3>
<p>파일: <code>src/routes/reports.routes.ts</code></p>
<p><code>/api/reports/weekly</code>에서 다음을 개선했다.</p>
<ul>
<li>정렬 기준을 <code>generated_at DESC</code>로 변경해 가장 최근 생성본을 확실히 반환</li>
<li>요청/결과 로그 추가 (<code>[reports/weekly] request/result</code>)</li>
<li>예외 발생 시 503 + 구조화된 에러 코드(<code>REPORT_QUERY_FAILED</code>) 반환</li>
</ul>
<p>운영 중 장애 분석을 빠르게 하려는 목적이 컸다.</p>
<h3 id="4-롱폼-대화-맥락-전달history-개선">4) 롱폼 대화 맥락 전달(History) 개선</h3>
<p>파일:</p>
<ul>
<li><code>src/routes/trainingLong.routes.ts</code></li>
<li><code>src/services/ai.service.ts</code></li>
<li><code>src/services/simulator.service.ts</code></li>
<li><code>scripts/simulator_bridge.py</code></li>
</ul>
<p>변경 내용:</p>
<ul>
<li>서버가 <code>longform_messages</code>에서 기존 대화를 조회해 <code>history</code> 배열로 구성</li>
<li><code>aiGenerateLongformReply</code> 및 시뮬레이터 클라이언트 계층에 <code>history</code> 파라미터 추가</li>
<li>Python 브리지에서 받은 <code>history</code>를 시뮬레이터 메시지 컨텍스트로 재구성</li>
</ul>
<p>효과:</p>
<ul>
<li>턴이 누적되어도 답변 문맥 일관성 향상</li>
<li>역할(role) 매핑 정리(<code>ai -&gt; assistant</code>)로 모델 입력 안정화</li>
</ul>
<h3 id="5-텍스트-인코딩음성-생성-품질-보강">5) 텍스트 인코딩/음성 생성 품질 보강</h3>
<p>파일:</p>
<ul>
<li><code>feedback_agent.py</code></li>
<li><code>simulator_test_2.py</code></li>
</ul>
<p>주요 개선:</p>
<ul>
<li>UTF-8 안전 정제 함수 추가로 깨진 문자열/서로게이트 문자 대응</li>
<li>TTS 입력 텍스트 전처리 강화(기호 정리, 문장부호 정돈)</li>
<li>프롬프트 메시지를 JSON 형태로 stderr 출력해 디버깅 가시성 확보</li>
</ul>
<h2 id="트러블슈팅에서-배운-점">트러블슈팅에서 배운 점</h2>
<ol>
<li><p>리포트 기능은 &quot;조회 API&quot;만 만들면 끝이 아니었다.
실제 생성 트리거를 사용자 행동 지점(<code>finish</code>)에 붙여야 데이터가 살아 움직인다.</p>
</li>
<li><p>AI 요약은 항상 실패 가능성을 전제로 설계해야 한다.
API 키 누락, 파싱 실패, DB 제약 이슈를 각각 분리해 fallback/재시도를 넣어야 운영이 안정된다.</p>
</li>
<li><p>대화형 시스템에서 문맥(history)은 품질의 핵심이다.
한 턴의 입력만 보내는 구조보다, 정돈된 대화 이력을 전달할 때 응답 품질이 확실히 좋아진다.</p>
</li>
</ol>
<h2 id="현재-아키텍처-흐름요약">현재 아키텍처 흐름(요약)</h2>
<ol>
<li>사용자가 숏폼/롱폼 훈련 진행</li>
<li>세션 종료 API 호출</li>
<li>서버가 최근 7일 학습 데이터를 집계</li>
<li>AI가 취약 패턴/행동 가이드를 요약</li>
<li><code>weekly_reports</code> upsert</li>
<li><code>/api/reports/weekly</code>에서 최신 리포트 조회</li>
</ol>
<h2 id="기술-스택과-선택-이유">기술 스택과 선택 이유</h2>
<h3 id="사용-언어">사용 언어</h3>
<ul>
<li>TypeScript (Node.js): API 서버의 핵심 로직(라우팅, 서비스, DB 연동)을 타입 안정성 있게 운영하기 위해 선택했다. DTO/응답 스키마가 많은 백엔드에서 런타임 오류를 줄이고 리팩터링 안정성을 높이는 데 유리했다.</li>
<li>Python: 시뮬레이터 브리지와 피드백/음성 관련 실험 코드에 사용했다. AI/오디오 처리 라이브러리 생태계가 강하고, 프로토타이핑 속도가 빨라 모델 연동 실험에 적합했다.</li>
</ul>
<h3 id="사용-프레임워크라이브러리">사용 프레임워크/라이브러리</h3>
<ul>
<li>Express: REST API를 빠르게 구성하고 미들웨어 기반으로 인증, 에러 핸들링, 라우트 분리를 명확히 하기 쉬워서 사용했다.</li>
<li>PostgreSQL(<code>pg</code>): 훈련 결과 집계, 주간 리포트 upsert, 조인 기반 통계 쿼리가 핵심이라 관계형 DB가 적합했다.</li>
<li>Zod: 요청 유효성 검증을 스키마로 명시해 입력 신뢰도를 높이고, 잘못된 요청을 초기에 차단하기 위해 사용했다.</li>
<li><code>express-session</code>: 로그인 기반 사용자 식별(<code>req.session.user.id</code>)이 필요해 세션 인증 구조를 적용했다.</li>
<li>AWS S3 SDK(<code>@aws-sdk/client-s3</code>, <code>@aws-sdk/s3-request-presigner</code>): 음성 파일 업로드/조회 URL을 안전하게 관리하기 위해 presigned URL 방식을 사용했다.</li>
<li>OpenAI API(Responses/Chat): 주간 리포트 요약 생성, 대화형 시뮬레이터 응답, 피드백 분석 등 생성형 AI 기능을 백엔드 서비스 계층에 통합했다.</li>
</ul>
<h3 id="백엔드-관점에서의-선택-포인트">백엔드 관점에서의 선택 포인트</h3>
<ol>
<li>유지보수성: TypeScript + 계층형 구조(routes/services/repositories)로 기능 확장 시 영향 범위를 예측하기 쉬웠다.</li>
<li>운영 안정성: 리포트 생성 실패를 업무 실패로 전파하지 않고 fallback/재시도를 넣어 사용자 플로우를 보호했다.</li>
<li>데이터 신뢰성: PostgreSQL 집계 + <code>ON CONFLICT</code> upsert로 주간 리포트 생성의 중복/정합성 문제를 줄였다.</li>
<li>확장성: Express 라우트 분리와 서비스 모듈화 덕분에 숏폼/롱폼/리포트/업로드 기능을 독립적으로 진화시키기 좋았다.</li>
<li>실험 속도: AI 실험 영역은 Python으로, 운영 API는 TypeScript로 분리해 개발 속도와 안정성의 균형을 맞췄다.</li>
</ol>
<h2 id="마무리">마무리</h2>
<p>이번 작업으로 guardian-server는 단순 훈련 제공 백엔드에서, &quot;학습 결과를 자동으로 요약하고 다음 행동까지 제시하는 피드백 백엔드&quot;로 한 단계 올라갔다.</p>
<p>다음 단계로는 리포트 정확도 개선(카테고리 정규화), 장기 추세 리포트(4주/8주), 사용자별 개인화 코칭 템플릿을 확장해볼 계획이다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[개발자 일기]AI 발전으로 인한 내 일자리 지키기 ]]></title>
            <link>https://velog.io/@0798_hyuk/AI-%EB%B0%9C%EC%A0%84%EC%9C%BC%EB%A1%9C-%EC%9D%B8%ED%95%9C-%EB%82%B4-%EC%9D%BC%EC%9E%90%EB%A6%AC-%EC%A7%80%ED%82%A4%EA%B8%B0</link>
            <guid>https://velog.io/@0798_hyuk/AI-%EB%B0%9C%EC%A0%84%EC%9C%BC%EB%A1%9C-%EC%9D%B8%ED%95%9C-%EB%82%B4-%EC%9D%BC%EC%9E%90%EB%A6%AC-%EC%A7%80%ED%82%A4%EA%B8%B0</guid>
            <pubDate>Sun, 15 Feb 2026 08:54:13 GMT</pubDate>
            <description><![CDATA[<h4 id="-컴퓨터공학과-4학년이-마주한-현실">– 컴퓨터공학과 4학년이 마주한 현실</h4>
<p>2026년, 컴퓨터공학과 4학년이 되었다.</p>
<p>예전에는 “컴공이면 취업은 걱정 없다”는 말이 있었다.
하지만 지금은 다르다.</p>
<p>ChatGPT, Copilot, Claude 같은 AI가
코드를 대신 짜고, 리팩토링하고, 심지어 설계까지 제안한다.</p>
<p>나는 지금 이런 질문을 스스로에게 던지고 있다.</p>
<p>“내가 4년 동안 배운 것들이 AI보다 가치 있을까?”</p>
<h4 id="📌-현재-나의-스펙-정리">📌 현재 나의 스펙 정리</h4>
<p>FE 국비 수업 6개월 (NCS 과정)</p>
<p>BE·AI 개발자 취업 준비 국비 7개월</p>
<p>공모전 장려상</p>
<p>해커톤 장려상</p>
<p>포토샵 자격증</p>
<p>교내 프로제트 장려상</p>
<p>외 여러 토이 프로젝트 경험 등</p>
<p>나쁘지 않다.
하지만 솔직히 말하면 차별화는 부족하다.</p>
<p>요즘 신입 지원자들은:</p>
<p>토이 프로젝트 다수</p>
<p>깃허브 잔디 빽빽</p>
<p>블로그 운영</p>
<p>AI 활용 경험</p>
<p>단순히 “웹 서비스 만들어봤습니다”는
더 이상 경쟁력이 되지 않는 시대다.</p>
<h4 id="🔎-문제-정의">🔎 문제 정의</h4>
<p><strong>1️⃣ 단순 코더의 가치 하락</strong></p>
<p>CRUD 구현
로그인 기능
게시판 만들기</p>
<p>이제는 AI가 몇 분이면 만든다.</p>
<p>내가 “기능 구현자”로 남는다면
나는 대체 가능한 인력이 된다.</p>
<p><strong>2️⃣ 설계 경험의 부재</strong></p>
<p>학교에서는 이론을 배웠다.
국비에서는 기능을 만들었다.</p>
<p>하지만 나는 아직:</p>
<p>대규모 트래픽을 설계해본 적 없다.</p>
<p>장애 대응 경험이 없다.</p>
<p>실제 서비스 운영 경험이 없다.</p>
<p>즉, “문제 해결자”라기보다는
“문제 수행자”에 가깝다.</p>
<p><strong>3️⃣ AI를 경쟁자로 볼 것인가, 도구로 볼 것인가</strong></p>
<p>AI는 이미 개발자의 일부 업무를 대체하고 있다.</p>
<p>하지만 동시에
개발자의 생산성을 폭발적으로 올려주고 있다.</p>
<p>결국 질문은 이것이다.</p>
<p>AI를 쓰는 개발자가 될 것인가,
AI에게 밀리는 개발자가 될 것인가?</p>
<h4 id="🎯-앞으로-해결해야-할-것들">🎯 앞으로 해결해야 할 것들</h4>
<p><strong>1️⃣ 기능 구현자 → 문제 정의자</strong></p>
<p>코드를 짜는 사람이 아니라</p>
<p>왜 이런 구조가 필요한지 설명할 수 있는 사람</p>
<p>트레이드오프를 말할 수 있는 사람</p>
<p>기술 선택의 근거를 제시할 수 있는 사람</p>
<p>이 되어야 한다.</p>
<p><strong>2️⃣ CS 기초를 다시 잡기</strong></p>
<p>운영체제</p>
<p>네트워크</p>
<p>데이터베이스 인덱스</p>
<p>트랜잭션</p>
<p>동시성</p>
<p>이걸 모르면 설계를 할 수 없다.</p>
<p>“프레임워크 사용자”에서
“시스템 이해자”로 가야 한다.</p>
<p><strong>3️⃣ AI 활용 능력 키우기</strong></p>
<p>AI를 금지하는 게 아니라
AI를 지휘하는 개발자가 되어야 한다.
요즘은 AI오케스트레이션이라 한다고한다..</p>
<p>코드 리뷰에 AI 활용</p>
<p>리팩토링 보조</p>
<p>테스트 코드 생성</p>
<p>아키텍처 초안 설계</p>
<p>AI는 내 대체자가 아니라
내 생산성을 3배 올려주는 도구가 되어야 한다.</p>
<p><strong>🚀 단기 목표 (1년 이내)</strong></p>
<p>기술 블로그 주 1회 작성</p>
<p>단순 기능 프로젝트가 아닌 “구조 중심 프로젝트” 진행</p>
<p>백엔드 심화 학습 (DB 설계, 캐싱, 동시성)</p>
<p>코드 리뷰 습관화</p>
<p>기술 면접 대비 CS 정리</p>
<p><strong>📈 중기 목표 (3~5년)</strong></p>
<p>서비스 운영 경험 쌓기</p>
<p>트래픽 처리 경험</p>
<p>설계 참여</p>
<p>아키텍처 이해</p>
<p>기술 의사결정 경험</p>
<p>“시킨 것만 하는 개발자”가 아니라
“방향을 제시하는 개발자”가 되는 것.</p>
<p><strong>🧠 결론</strong></p>
<p>AI는 개발자를 없애지 않는다. <del>그러길 빈다.</del></p>
<p>하지만 평범한 개발자는 빠르게 줄어든다.</p>
<p>나는 지금 갈림길에 서 있다.</p>
<p>튜토리얼 개발자로 남을 것인가</p>
<p>문제 해결형 개발자로 성장할 것인가</p>
<p>이 블로그는
내 일자리를 지키기 위한 기록이다.</p>
<p>그리고
앞으로 성장 과정을 증명하는 공간이 될 것이다.</p>
]]></description>
        </item>
    </channel>
</rss>