<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://071yoon.github.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://071yoon.github.io/" rel="alternate" type="text/html" /><updated>2026-01-18T06:42:30+00:00</updated><id>https://071yoon.github.io/feed.xml</id><title type="html">YeongGi’s tech blog</title><subtitle>This is YeongGi&apos;s tech blog. I post IT related items.</subtitle><author><name>071yoon</name></author><entry><title type="html">AI 시대에 우리가 공부해야 할 본질에 대하여</title><link href="https://071yoon.github.io/ai/2026/01/18/next-programmer.html" rel="alternate" type="text/html" title="AI 시대에 우리가 공부해야 할 본질에 대하여" /><published>2026-01-18T00:00:00+00:00</published><updated>2026-01-18T00:00:00+00:00</updated><id>https://071yoon.github.io/ai/2026/01/18/next-programmer</id><content type="html" xml:base="https://071yoon.github.io/ai/2026/01/18/next-programmer.html"><![CDATA[<h2 id="변화하는-개발자의-role">변화하는 개발자의 Role</h2>

<p>예전에는 개발자의 실력을 논할 때 Muscle Memory 이라는 표현이 어울렸던 것 같다. 디자인 패턴을 몸에 익히고, Side Effect를 줄이기 위해 함수형 프로그래밍을 적용하며, 유지보수하기 쉬운 설계를 위해 IoC나 객체지향 원칙을 실전에 바로바로 녹여내는 것이 개발자의 가장 큰 미덕이자 실력이었다.</p>

<p>하지만 최근 ‘바이브 코딩’을 체험하며 느낀 점은, 이제 그런 ‘구현’의 영역은 AI가 메인으로 수행하는 시대가 되었다는 것이다. 이제 개발자의 역할은 직접 코드를 작성하는 ‘Writer’에서, AI가 작성한 초안을 검토하고 교정하는 <strong>‘Code Reviewer’</strong>에 더 가까워지고 있다.</p>

<h2 id="ai는-만능이-아니다-여전히-기본기가-중요한-이유">AI는 만능이 아니다: 여전히 기본기가 중요한 이유</h2>

<p>AI가 코드를 쏟아낸다고 해서 개발자가 뇌를 비워도 된다는 뜻은 아니다. 오히려 그 반대다. 최근 출장에서 경험했듯, AI는 복잡한 보안 환경이나 특정 프로토콜(예: MQTT TCP Connection 유지) 문제에서 비효율적이거나 불가능한 답변을 내놓기도 한다.</p>

<p>이런 상황에서 우리가 길을 잃지 않기 위해 필요한 것이 바로 <strong>컴퓨터 공학의 기본기</strong>다.</p>

<ul>
  <li><strong>방향성 제시</strong>: AI는 구현 그 자체를 목적으로 삼지만, 개발자는 그 결과물이 ‘우아한 방향’으로 갈 수 있도록 가이드해야 한다.</li>
  <li><strong>질문의 수준</strong>: Webpack, Vite, Turbopack의 차이를 이해하려면 CSR, JS 모듈 시스템, Babel 같은 근본 개념을 알아야 한다. 이런 지식이 있어야만 AI에게 제대로 된 질문을 던질 수 있다.</li>
  <li><strong>검증 능력</strong>: AI가 짠 알고리즘이 오버헤드를 일으켜 브라우저를 뻗게 만들 때, 이를 잡아낼 수 있는 것은 결국 자료구조와 알고리즘 같은 기초 지식이다.</li>
</ul>

<h2 id="깊이만큼-중요한-넓은-시야">‘깊이’만큼 중요한 ‘넓은 시야’</h2>

<p>과거에는 프론트엔드 개발자라면 FE 스택만 깊게 파는 것이 정석이었다. 하지만 이제는 쏟아지는 수많은 패키지와 프레임워크들의 아이디어를 <strong>넓고 다양하게 파악하는 능력</strong>이 중요해졌다고 생각한다.</p>

<p>직접 오픈소스를 포크해서 밑바닥까지 공부하지 않더라도, “이런 패러다임이 있구나”를 알고 있으면 AI와 대화할 때 “이런 개념을 참고해서 구현해줘”라고 제안할 수 있다. i18n이나 다크모드 구현처럼 매번 설정법이 바뀌어 러닝커브가 발생하는 지점들을 AI를 통해 효율적으로 해결하되, 개발자는 그 상위의 구조를 설계하는 데 집중해야 한다.</p>

<h2 id="회고-결국은-본질로">회고: 결국은 본질로</h2>

<p>재작년에 SQLD와 정보처리기사를 취득하며 기초 이론을 다시 다졌던 경험이 떠오른다. 당시에는 “실무에서 굳이?”라는 생각이 들 수도 있었지만, 결국 데이터베이스의 정규화나 네트워크의 기본 개념 같은 본질적인 지식들이 AI의 결과물을 리뷰하는 가장 강력한 무기가 되고 있다.</p>

<p>컴퓨터 공학의 큰 틀은 쉽게 바뀌지 않는다. 새로운 패러다임이 나와도 그 뿌리는 같다. 앞으로의 개발자는 AI라는 뛰어난 신입 개발자를 옆에 두고, 탄탄한 기본기를 바탕으로 정답을 골라내고 최적의 경로를 지시하는 <strong>‘오케스트라의 지휘자’</strong> 같은 역량을 키워야 하지 않을까 싶다.</p>

<p>앞으로도 단순히 기술을 소비하는 것을 넘어, 기본기를 채우고 트렌드를 넓게 읽는 공부를 계속해 나아가자.</p>]]></content><author><name>071yoon</name></author><category term="ai" /><category term="ai" /><category term="develop" /><category term="thought" /><summary type="html"><![CDATA[변화하는 개발자의 Role]]></summary></entry><entry><title type="html">바이브 코딩</title><link href="https://071yoon.github.io/ai/2025/06/02/about-vibe-coding.html" rel="alternate" type="text/html" title="바이브 코딩" /><published>2025-06-02T00:00:00+00:00</published><updated>2025-06-02T00:00:00+00:00</updated><id>https://071yoon.github.io/ai/2025/06/02/about-vibe-coding</id><content type="html" xml:base="https://071yoon.github.io/ai/2025/06/02/about-vibe-coding.html"><![CDATA[<h2 id="바이브-코딩">바이브 코딩</h2>

<p>저번달에 출장가서 바이브 코딩을 체험해보았다.</p>

<p>바이브 코딩은 실제로 코드를 작성하는 것이 아니라, AI와 대화하며 코드를 작성하는 방식으로, 개발자들이 코드 작성에 소요되는 시간을 줄이고, 더 창의적인 작업에 집중할 수 있도록 돕는 것을 목표로 한다.</p>

<p>사실 Copilot 같은 경우 출시가 된지 꽤 되었고, 실제로 사용해본 경험이 있어서, 사실 바이브 코딩에 대한 기대감은 그렇게 크지 않았다. 그냥 말을 조금 더 잘 듣는 AI가 나왔구나 정도로 생각하였다.</p>

<p>현재 내가 서비스하고 있는 조그만 프로젝트에 적용해보았는데, 생각보다 많이 인상적이였다.</p>

<p>그리고 리팩토링이 아닌 처음부터 바이브코딩으로 시작하는 경우 더 빠르고 편하게 개발이 가능할거라 생각해서 데블스 플랜을 보다 마음에 들었던 게임 하나를 바이브 코딩을 통해서 구현해보았다.</p>

<h2 id="구현">구현</h2>

<p>구현은 데블스플랜2에 나온 히든게임인 기사의 여행을 구현해보았다. 넷플릭스가 만든 게임도 아니고, 원래부터 유명한 수학 알고리즘 게임이여서 저작권 걱정없이 재밌게 구현이 가능했다.</p>

<p>게임은 <a href="https://071yoon.github.io/knights-tour/">기사의 여행</a> 여기서 볼 수 있고 코드는 <a href="https://github.com/071yoon/knights-tour">소스코드</a> 여기서 확인해볼 수 있다.</p>

<p>시간은 약 2시간 정도 소요되었고, 실제 코드 작성을 최소화 하고, 채팅을 통해서 동작들을 검증해나가며 구현해보았다.</p>

<p>사실 개발 자체를 너무 잘해서 개발자가 뇌를 비우고 개발을 할 수 있다 정도는 아니였다.</p>

<p>아무래도 기사의 여정 같은 경우 알고리즘도 다양하고, 최적화 알고리즘이 다양하며 실제로 개발자가 테스트를 해보며 최적화가 잘 되어 있는지 확인하는 과정도 많이 필요하다. AI가 처음에 알고리즘을 너무 이상하게짜서 오버헤드가 너무 커지거나 연산이 너무 많아서 브라우저가 뻗어버리는 경우도 있었다. 그럼에도 불구하고 정말 구현 단계에서는 생산성이 정말 말도안되게 향상됨을 느낄 수 있었다. 비슷한 리뷰들도 많지만, 정말 열정적인 개발 신입을 옆에 데리고 개발을 하는 느낌이다.</p>

<p>특히나 매번 버전업이 될 때마다 사용법이 달라지는 i18n 이나, 다크모드 등 이런거는 정말 프레임워크 혹은 최신 라이브러리에 의존하여 구현하는 경우가 많아, 러닝커브도 높고 이러한 공부를 해야하는 시간도 아까웠는데, 바이브 코딩을 통해서 이러한 부분을 쉽게 구현할 수 있었던게 정말 좋았다.</p>

<p>그리고 이번 AI코딩툴 활용은 커서 IDE 와 StageWise 란 오픈소스를 같이 활용해서 사용을 했는데, 사용성이 정말 좋았다. 우선 IDE 가 AI를 공식적으로 서포트 한다는건 처음 신기한 경험이였는데, 단순하게 코드를 작성하는 것 뿐만 아니라, 채팅을 통해 마치 대화를 하며 코드 작성을 도와주고 개발해주어 실제로 혼자 개발을 하는것이 아닌 생산성이 정말 높은 개발자가 있는 듯한 느낌을 받았다. 그리고 자동으로 Import/Terminal을 통해 command 제어까지 실행해주는건 정말 편리했다. 그 외로도 commit 로그나, auto import 등 IDE 자체에서 AI를 활용하는 부분이 편의성 하나는 제대로 갖추고 있다는 생각이 들었다.</p>

<p>그리고 StageWise 란 UI 딴에서 AI 활용을 좀 도와줄 수 있는 open source 도 같이 사용을 하였는데, 솔직히 아직까지는 early-access 의 단계라서 사용성은 조금 아쉬웠다. 그래도 이렇게 도움을 줄 수 있다는 아이디어나 가능성은 잘 열어 두었다고 생각이 들었다.</p>

<h2 id="내-생각">내 생각</h2>

<p>실제로 AI가 개발자를 대체할 수 있을까? 라는 주제로 접근을 해본다면 100% 대체를 불가능하다고 생각을 한다. 특히나 최근 출장을 가서 단순 개발이 아니라 사내망에서 개발을 하며 방화벽, 보안, 망 접근 등 다양한 관점에서 개발을 해야되는 상황이 많았는데, 이러한 문제가 생겼을 경우 AI의 도움을 받아도 해결하기가 참 어려웠다. 하나 극단적인 예를 들자면 최근에 MQTT 통신을 통해 IoT 디바이스 통신을 구현하는데, 통신을 최소화 하기 위해 TCP Connection 이 끊어지지 않도록 하는 방법을 찾아야 했는데, AI가 알려주는 방법은 너무 비효율적이거나, 실제로는 불가능한 방법이였다. 이러한 부분은 결국 개발자가 직접 찾아서 해결해야 하는 문제고 이러한 방법을 직접 개발자가 찾고 이해하기 위해서는 개발자가 직접 CS 공부를 하고 해결방법을 찾은 후 AI와 같이 대화를 하며 해결해야 하는 문제라고 생각이 되었다. 왜냐하면 물어보는 Prompt를 개발자가 100% 이해하고, 문제 상황에 대해 100% 이해하고 있어야 AI가 제대로 된 답변을 해줄 수 있기 때문이다.</p>

<p>대신 구현에 대해서는 정말 개발자의 역량이 많이 줄어들었다고 생각한다. 특히나 반복적인 작업이나, 단순하게 구현하는 부분에 대해서는 AI가 정말 잘 도와주고, 개발자가 직접 코드를 작성하는 것보다 훨씬 빠르게 개발을 할 수 있다고 생각한다. 특히 앞서 언급했던 i18n 이나 다크모드 등 프레임워크를 사용하는 경우, AI 가 오히려 사람보다 더 효율적이고 최신 기술을 잘 알고 있어서, 개발자가 직접 구현하는 것보다 훨씬 빠르게 개발을 할 수 있을 것 같다.</p>

<p>앞으로의 개발자는 어떤 방향으로 나아가야 될까? 물론 내 생각이 100% 맞는것도 아니고 그냥 주니어의 입장에서 서술할 뿐이지만, 우선 AI와 함께 개발을 하는 방법을 익히는 것이 중요하다고 생각한다. 특히 프롬프트 엔지니어링이란 단어가 생길 정도로 AI와 대화하는 방법을 익히는 것이 중요하다고 생각한다. 대화를 해보면서 키워드 중심으로 말을 해야 잘 알아듣는게 마치 google 검색 시 색인과 검색어 조건 SEO 등을 잘 맞춰야 검색 결과가 잘 나오는 것과 비슷하다고 생각한다.</p>

<p>그리고 아무래도 Computer Science의 기본적인 지식은 여전히 중요하다고 생각한다. AI가 코드를 작성해주고, 개발을 도와주지만, 결국 AI가 작성한 코드를 이해하고, 최적화하고, 문제를 해결하기 위해서는 개발자가 기본적인 CS 지식을 가지고 있어야 한다. 특히 알고리즘이나 자료구조에 대한 이해는 정말 중요하다고 생각한다.</p>

<p>그리고 또 하나 보자면 코드 리뷰 능력이라고 생각한다. AI가 작성한 코드를 리뷰하고, 최적화하는 능력은 개발자가 가져야 할 중요한 역량이라고 생각한다. AI가 작성한 코드가 항상 최적화되어 있거나, 효율적인 것은 아니기 때문에, 개발자가 AI가 작성한 코드를 리뷰하고, 개선할 수 있는 능력을 가져야 한다.</p>]]></content><author><name>071yoon</name></author><category term="ai" /><category term="ai" /><category term="llm" /><summary type="html"><![CDATA[바이브 코딩]]></summary></entry><entry><title type="html">Chrome Web Store 유지보수</title><link href="https://071yoon.github.io/web/2025/03/16/maintain-chrome-extension.html" rel="alternate" type="text/html" title="Chrome Web Store 유지보수" /><published>2025-03-16T00:00:00+00:00</published><updated>2025-03-16T00:00:00+00:00</updated><id>https://071yoon.github.io/web/2025/03/16/maintain-chrome-extension</id><content type="html" xml:base="https://071yoon.github.io/web/2025/03/16/maintain-chrome-extension.html"><![CDATA[<h2 id="chrome-extension-console">Chrome Extension Console</h2>

<p>예전에 크롬 웹 익스텐션을 개발한 적이 있다.
처음에는 단순히 게임하면서 내가 활용하려고 개발하였다가, 같이 쓸 수 있으면 좋겠다고 생각해서 공유를 했었다.</p>

<blockquote>
  <p><a href="https://071yoon.github.io/til/2023/09/18/make-chomre-web-extension.html">블로그 링크</a> 는 여기서</p>
</blockquote>

<p>그러던 어느날, 그냥 extension 이 잘 살아있는지? 사람들은 잘 쓰고 있는지 궁금해서 Web Extension Console 에 들어가서 한번 통계를 살펴 봤었다.</p>

<p>그런데 웬걸, 생각보다 내가 개발한 익스텐션이 검색에 상위 노출이 되었고, 지속적으로 다운로드가 되고 있었다.</p>

<p>나름 Auto Scroll Extension 이라고 치면 상위 3등으로 검색이 되어 있었다.
<img width="1345" alt="Image" src="https://github.com/user-attachments/assets/0e077026-83e1-4a0a-982b-dcc0ea1bddab" /></p>

<p>여튼 그런데 통계를 보니까 처음에는 한국인 기준으로 개발을 했었는데, 생각보다 해외에서 다운로드가 많았다.</p>

<p>익스텐션 같은 경우에는 구글에서 승인을 받아야지 올릴 수가 있어서, 설명이나 주석 같은것들을 전부 영어로 작성해서 그래서 외국인 유입이 좀 많았나보다.</p>

<p>여튼 그래서 기왕 상위 노출도 되고, 외국인들도 많이 쓰는것 같으니 조금 유지보수를 해서 영어 지원도 하고 일반 사용자들이 사용하기 쉽게 만들어 보기로 했다.</p>

<p>작년 초 기준 (유지보수 하기 전) 최고 97이고 평균적으로 일일 방문자 30명 정도에 설치수는 10회 정도로 보였다.</p>

<p><img width="504" alt="Image" src="https://github.com/user-attachments/assets/8cdaccf4-0073-40d4-a6f4-af5e81a48d8b" /></p>

<p><img width="524" alt="Image" src="https://github.com/user-attachments/assets/2b966638-a59a-496a-9746-eb19e7b46bd6" /></p>

<h2 id="유지보수">유지보수</h2>

<p>우선 다국어 지원을 통해 외국인 사용자들이 조금 더 유입이 편하도록 수정하고, 조금더 사용성이 용이할 수 있게 자동 모드 등을 포함시켰다.</p>

<blockquote>
  <p><a href="https://github.com/071yoon/auto-scroll-extension/commit/33a99118b0366ed703338a95d6af968554a68c03">수정사항 커밋</a></p>
</blockquote>

<p>코드는 조금 날림으로 쓰고 이따 천천히 리팩토링도 하고 수정도 해야지 해야지 하는데 요즘 일에 치이고 시간도 없고 귀찮아서 자꾸만 밀린다… ㅠ</p>

<h2 id="비교-분석">비교 분석</h2>

<p>여튼 이렇게 수정하고 나니 확실히 조회수나 설치수도 눈에 띄게 늘었다. 일일 조회수는 이제 평균적으로 50 명 정도로 늘었고, 설치수도 20회 정도로 물론 날마다 차이는 있지만, 큰 흐름으로 보았을 때 우상향으로 증가했다.</p>

<p><img width="555" alt="Image" src="https://github.com/user-attachments/assets/3628ae9c-ade5-4d39-97e3-c056e47db8cd" /></p>

<p><img width="589" alt="Image" src="https://github.com/user-attachments/assets/fcfa4fef-e0db-4da7-9c50-8d22a0c1c60f" /></p>

<p>특히 1년간 사용자의 증가 추이를 보면, 천천히지만 증가하는 모습을 볼 수 있다. 그리규 유지보수를 진행했던 10월을 기점으로 확실히 사용자가 확 늘어남을 눈으로 확인할 수 있다.</p>

<p><img width="1087" alt="Image" src="https://github.com/user-attachments/assets/c3956b94-3dc7-46ef-ad05-7772289541d1" /></p>

<p>여기서 google analytics 등록하여 페이지 조회를 하면 더 자세한 내용을 볼 수 있는데, 국가 통계를 보면 다음과 같다.</p>

<p><img width="1308" alt="Image" src="https://github.com/user-attachments/assets/1881880b-dfc6-4a12-82b4-ea04649abac7" /></p>

<p>아쉽게도 기간으로 보는 법은 없어서 해외 유입이 얼마나 증가했는지는 볼 수 없지만, 예전에 비해서는 정말 해외 비율이 많아졌다.</p>

<p>버저닝으로 사용자가 얼마나 많아졌는지 보는 방법도 있었는데, 해당 그래프틑 다음과 같다.</p>

<p><img width="735" alt="Image" src="https://github.com/user-attachments/assets/8c439595-0a74-4fc6-8ee3-09b02f778e19" /></p>

<p>1.0.2.0 버전 기준에서 천천히 증가를 하다 (300 - 600 까지 7개월) 업데이트 후 600 - 1200 까지 5개월만에 달성하였다.</p>

<h2 id="회고">회고</h2>

<p>사실 이때까지 몇가지 프로젝트를 하고, 유지보수를 포기한 프로젝트도 많고 (거의 90%) 정말 공을 들였지만 사람들이 쓰지 않아서 망했던 프로젝트들도 참 많은데, 역시 사람일은 모르는것 같다.</p>

<p>예전에 사이드 프로젝트로 억대 연봉을 버는 사람 말이 생각나는데, <code class="language-plaintext highlighter-rouge">사이드 프로젝트 그냥 그거 일주일에 하나씩 만들다 보면 하나는 대박 터져요</code> 가 참 맞는 말인것 같다.</p>

<p>그리고 유지보수를 통해서 확실히 통계적으로 수치가 증가하는걸 보면 참 뿌듯하다.. 앞으로 비슷한거 많이 양산해야지 ㅎ.ㅎ</p>]]></content><author><name>071yoon</name></author><category term="web" /><category term="web" /><category term="extension" /><summary type="html"><![CDATA[Chrome Extension Console]]></summary></entry><entry><title type="html">SQLD / 정보처리기사 취득기</title><link href="https://071yoon.github.io/til/2024/07/07/certificates.html" rel="alternate" type="text/html" title="SQLD / 정보처리기사 취득기" /><published>2024-07-07T00:00:00+00:00</published><updated>2024-07-07T00:00:00+00:00</updated><id>https://071yoon.github.io/til/2024/07/07/certificates</id><content type="html" xml:base="https://071yoon.github.io/til/2024/07/07/certificates.html"><![CDATA[<h2 id="취득-배경">취득 배경</h2>

<p>이번 상반기에 회사를 다니며 어떤걸 해볼까? 하다 자격증 취득에 관심이 생겨 SQLD 와 정보처리기사를 취득해보게 되었다. 두 자격증 다 운이 좋게도 한번에 취득을 했고, 사실 공부한 노력과 시간에 비례하여 쉽게 취득을 한 것 같다. 하지만 해당 자격증들은 조금 호불호가 있는 자격증들이다. 특히나 정보처리기사 같은 경우에는 <code class="language-plaintext highlighter-rouge">엥 컴공생이 정보처리기사를 왜 따?</code> 라는 말이 있을정도로 인기 및 필요가 없다는 인식이 꽤나 있는 자격증이다. 그럼 내가 왜 해당 자격증을 따게 되었을까?</p>

<p>우선 SQLD 같은 경우에는, 내가 Database 과목에 취약하다는 생각이 들어서 공부하게 되었다. 내가 프론트엔드 공부를 한다는 핑계로 DB 쪽 공부에 소홀했던것도 사실이고(학교 수업은 어찌저찌 A+를 받긴 했다), 해당 과목을 배울 당시에 제대로 Database 관련 실습을 할 수 도 없어 많이 흥미가 떨어지는 과목 중 하나였다. 하지만 막상 회사를 다니며 직접 DB Query 및 Tablespace/User 관점에서 수정하는 일이 빈번하게 발생해서 제대로 공부를 할 필요를 느껴 자격증 공부를 하게 되었다.</p>

<p>다음 정보처리기사 같은 경우에는 좀 여러가지 이유가 있었다. 우선 나는 대학 입학 당시에만 하더라도 컴퓨터공학 전공이 아니였다. 기계/전자 쪽에 가까웠기에 그 때 전자/전기 기사 자격증에 대한 막연한 동경이 있었고, 아무래도 <code class="language-plaintext highlighter-rouge">4년을 한 과목에 공부를 한다 === 기사 자격증이 있다</code> 라는 인식이 있었다. 그래서 전과를 한 이후에도 언젠가는 컴퓨터공학 관련 기사를 따야지 라고 생각을 했고, 그게 마침 정보처리기사였던 것이다. 또 하나는 SQLD를 취득하고 난 후 기초적인 이론 공부가 재미있었고, 나름 배우는게 많았다 보니 정보처리기사를 취득하며 부족했던 나의 기초적인 이론 지식을 조금 더 다듬을 생각이였다. 하지만 해당 부분은 추후에 후술하겠지만, SQLD 만큼 썩 만족스럽지는 않았다.</p>

<h2 id="공부">공부</h2>

<h3 id="sqld">SQLD</h3>

<p>SQLD는 제일 유명한 수험서인 노랭이 책으로 기본을 공부하고, 모의고사가 잘 되어 있어 모의고사를 많이 풀고가면 쉽게 합격할 수 있다. 나같은 경우, 노랭이 1회독을 하고 모의고사만 인터넷에 떠돌아 다니는걸로 달달 풀고 갔다.</p>

<p>특히 내가 시험보는 회차(52회)부터 주관식이 없어지고 전부 객관식으로 바뀌어 문제가 더욱 쉬워졌다. 쿼리문 같은 경우에, 긴장하지 않고 천천히 풀면 된다.</p>

<p><img src="https://github.com/071yoon/071yoon.github.io/assets/66371206/4a4bc089-908d-4cfd-8e87-d587e0d02d90" alt="SQLD" /></p>

<p>아마 데이터베이스 수업을 들은 전공자 기준, 기본서만 1회독 하고 간다면 충분히 쉽게 합격을 할 수 있다고 생각한다. 공부기간은 길게 잡아서 3주, 벼락치기 한다면 2-3일이 이라고 생각한다.</p>

<h3 id="정보처리기사">정보처리기사</h3>

<p>정보처리기사 같은 경우, 책이 정말 많고 책들이 전부 매우 두껍다. 회사 지원금이 나와서, 지원금으로 사도 되지만, 목차를 보았을 때 조금 필요없는 부분들도 많고 쓸데없이 자세한 내용들이 많아 책은 따로 구매하지 않았다.</p>

<p>필기같은 경우에는, 합격률도 정말 높고 문제은행식으로 나온다는 이야기가 많아서 그냥 모의고사만 3회정도 풀고 들어갔다. 만약 학교 공부를 꾸준히 들었다면, 따로 노력을 들이지 않아도 필기는 쉽게 합격을 할 수 있을거라 생각한다. 꽤나 예전에 본 시험이고, CBT로 진행하여 점수가 기억이 나지는 않지만, 생각보다 안정적이게 합격했던것 같다.</p>

<p>실기같은 경우에는, 앞서 말했지만 범위가 정말 많다. 만약 내가 정말 이론적인 공부를 하는것이 시험의 목표라고 한다면, 두꺼운 시험공부 서적을 한권 구매한 후 천천히 읽어볼 것 같다. 나도 처음에는 기본 컴퓨터공학 공부를 다시 공부하는것이 목표였지만,, 정말 두꺼운 이론책을 보고나서 마음이 바뀌게 되었다. 우선 모의고사들을 분석 후 시험 트렌드를 공부했다. 내가 느낀 트렌드는 개정 후 프로그래밍 문제가 60%, 이론문제가 40% 나온다는 것.. 그리고 프로그래밍은 주로 C/JAVA/PYTHON 으로 나오기에 해당 부분들을 조금 공부해서 100% 맞추고, 이론 문제는 아는것만 푸는것으로 방향을 바꿔보았다.</p>

<p>그래서 실기도 마찬가지로 3일의 전사로, 오랜만에 포인터나 기본적인 java의 overriding 이나 상속 결과들을 조금 공부하고, 이론은 디자인패턴이나 네트워크 등 평소에 잘 아는것을 100% 맞춘다는 생각으로 공부했다. 아무래도 실기가 100% 필기로 진행되다보니 결과가 나오기까지 꽤나 시간이 걸렸지만 내 생각보다 점수가 높게 나오게 되었다.</p>

<p><img width="743" alt="정보처리기사" src="https://github.com/071yoon/071yoon.github.io/assets/66371206/5eddcd16-7c95-40c1-919c-b32b0e2e3843" /></p>

<p>이번 시험이 조금 쉽게 나온것 같긴 하지만, 그래도 전공자 벼락치기 기준 필기 1일, 실기 3일 정도, 넉넉하게 준비한다면 필기 1주, 실기 3주면 충분할 듯 하다.</p>

<h2 id="취득-후기">취득 후기</h2>

<p>SQLD 같은 경우에는 시험공부를 하며 배운것도 많았고, 데이터베이스를 완전 기본부터 정규화 등 다시 공부를 하는것도 마음에 들었고, Query 문도 단순히 SELECT 가 아닌 정말 처음보는 LEVEL 등의 개념도 볼 수 있어 많이 배울 수 있어 좋았다. 정말 자격증만 따고 싶다면, 그렇게 점수 컷이 높지 않아 어려운 부분을 다 건너 뛰어도 합격은 할 수 있다 생각하지만, 한번쯤 1회독을 하며 Database 공부를 천천히 복기하는걸 추천한다.</p>

<p>정보처리기사 같은 경우, 내가 시간이 없다는 핑계로 많이 공부하지 않아 사실 자격증 공부를 하며 많이 배웠다고 할 수는 없을것 같다. (그런데 진짜 책 너무 두꺼워서 공부할 엄두가 안남) 그래도 뭐 합격을 하니 기분은 좋더라,, 그리고 졸업하면서 기사 자격증 하나쯤은 가지고 싶었기에 만족한다.</p>

<p>다음 자격증은 아마 리눅스마스터1급이 되지 않을까 싶다. (점점 프론트엔드에서 멀어져 가는 이 느낌은 뭘까)</p>]]></content><author><name>071yoon</name></author><category term="TIL" /><category term="TIL" /><summary type="html"><![CDATA[취득 배경]]></summary></entry><entry><title type="html">굵기가 있는 div 만들기</title><link href="https://071yoon.github.io/web/2024/05/27/make-3d-div.html" rel="alternate" type="text/html" title="굵기가 있는 div 만들기" /><published>2024-05-27T00:00:00+00:00</published><updated>2024-05-27T00:00:00+00:00</updated><id>https://071yoon.github.io/web/2024/05/27/make-3d-div</id><content type="html" xml:base="https://071yoon.github.io/web/2024/05/27/make-3d-div.html"><![CDATA[<h2 id="굵기가-있는-div-만들기">굵기가 있는 div 만들기</h2>

<p>요즘 kinetic animation 이 대세이다. 대충 이러한 <a href="https://www.youtube.com/watch?v=V8SjH8URkuc">[SAMSUNG AI]</a> 애니메이션들이라 볼 수 있다.</p>

<p>위와 같은 애니메이션은 사실 그렇게 어렵지 않게 캔버스 없이도 웹으로 구현이 가능하다. 아주 동일하지는 않지만, bezier curve를 대충 그린다면 <a href="https://071yoon.github.io/kinetic/samsung/ai">이렇게</a> 구현을 할 수 있다.</p>

<p>하지만 만약 3D animation 이라면 이야기가 조금 달라진다. LG 로고의 예시를 봐보자.</p>

<p><a href="https://www.youtube.com/shorts/0ak8UT3zt4w">눈도 반짝 입도 활짝, 저 뭐 달라진거 없나요?</a> 해당 영상을 보면 로고가 다채롭게 움직이는걸 볼 수 있다.</p>

<p>물론 해당 이미지는 canvas 를 활용하면 손쉽게 3D animation 으로 구현할 수 있지만, 문서안 혹은 텍스트 사이에 사용하기 쉽지 않아, div 로 구현을 해보려고 한다.</p>

<h2 id="div-만들기">DIV 만들기</h2>

<p>전체 애니메이션을 따라 만들기에는 시간이 부족하니 우선 3D 부분이 눈에 띄는 눈 부분을 제작해보기로 하자.</p>

<h3 id="아이디어-생각">아이디어 생각</h3>

<p>처음 드는 생각은 눈 자체를 동그란 형식으로 만든 뒤 rotateX 혹은 rotate3D를 통해 돌리는 방안이 제일 먼저 떠오른다.</p>

<p>하지만 그렇게 설계하고 구현할 경우, 굵기를 표현하기가 어려운데, 간단하게 이미지로 예시를 들어보면 다음과 같다.</p>

<p><img src="https://github.com/071yoon/071yoon.github.io/assets/66371206/8613452b-b7f5-4e3e-acf2-8f46c8cddb9f" alt="image" /></p>

<p>이를 만약 우리가 보는 화면 기준에서 바라본다면.</p>

<p><img src="https://github.com/071yoon/071yoon.github.io/assets/66371206/7cb1ebca-84de-4851-990b-38bbed5f2c55" alt="image" /></p>

<p>이런 형식으로 보이게 될 것이다.</p>

<blockquote>
  <p>전혀 3D 처럼 보이지 않는다.</p>
</blockquote>

<p>이는 perspective 나 3D 로테이션을 준다 하여도 thickness 자체를 주기는 어려워보인다.</p>

<p>실제 현실에서 어떤식으로 구현이 되어야 하는지 한번 생각해보면 다음과 같다.</p>

<p><img src="https://github.com/071yoon/071yoon.github.io/assets/66371206/f3f4bab6-efb2-4ed9-8740-fd63c57c7f3a" alt="image" /></p>

<p><img src="https://github.com/071yoon/071yoon.github.io/assets/66371206/6446390b-3c8a-4146-99cb-03790f8cbbc7" alt="image" /></p>

<p>이런식으로 표현 될 수 있다.</p>

<p>이를 dom 을 통해 구현해보자.</p>

<h3 id="구현해보기">구현해보기</h3>

<p>정작 그림에 필요한 부분을 따로 본다면 다음 이미지 처럼 볼 수 있다.</p>

<p><img src="https://github.com/071yoon/071yoon.github.io/assets/66371206/fecbc43e-3f31-42df-b54a-c3783db9870c" alt="image" /></p>

<p>즉 간단하게 도식화 해서 살펴보자면 해당 부분만 구현을 하면 3D 처럼 보일 수 있다.</p>

<p><img src="https://github.com/071yoon/071yoon.github.io/assets/66371206/76151c39-2111-47e4-b658-3eef73b81b3c" alt="image" /></p>

<p>그리고 이미 원 부분은 간단하게 그린 후 <code class="language-plaintext highlighter-rouge">rotateX(90)</code> 으로 해결이 되므로 위 막대만 위치에 맞춰 회전 시켜주면 된다.</p>

<p>그럼 대충 이런 형식으로 그릴 수 있다.</p>

<p><img src="https://github.com/071yoon/071yoon.github.io/assets/66371206/2894f60d-f2ef-4747-ba13-36e46fad7c4b" alt="image" /></p>]]></content><author><name>071yoon</name></author><category term="web" /><category term="web" /><summary type="html"><![CDATA[굵기가 있는 div 만들기]]></summary></entry><entry><title type="html">Lighthouse 점수 개선기</title><link href="https://071yoon.github.io/web/2024/04/07/lighthouse-improvement.html" rel="alternate" type="text/html" title="Lighthouse 점수 개선기" /><published>2024-04-07T00:00:00+00:00</published><updated>2024-04-07T00:00:00+00:00</updated><id>https://071yoon.github.io/web/2024/04/07/lighthouse-improvement</id><content type="html" xml:base="https://071yoon.github.io/web/2024/04/07/lighthouse-improvement.html"><![CDATA[<h2 id="배경">배경</h2>

<p>내 정보를 보여주는 웹사이트를 대충 만든지 8개월이 지났다. 가끔 자격증을 따거나 업데이트 소식이 있을 때 사용했었는데, 오랜만에 들어가서 보니 light house 점수가 말이 아니였다.</p>

<p>여유로운 주말에 점수나 올려보자 시작된 웹 개선기.</p>

<h2 id="수정-사항">수정 사항</h2>

<p>처음에 모바일도 고려해서 만들었기에, CLS 같은 류는 점수가 그렇게 낮지는 않았다. 그래서 우선 light house를 한번 돌려본 후 알려주는 수정사항만 추가해보았다.</p>

<h3 id="sufficient-contrast-ratio">Sufficient Contrast Ratio</h3>

<p>글을 배경에 비해서 contrast 가 존재해야 되는데, 흰 배경에 회식글을 작성해서 생긴 문제였다. 디자이너가 없는 사이트였기에, 나 혼자 디자인이랍시고 회색으로 a tag를 만들었었는데, 구글을 마음에 들지 않았나보다. 적당히 색을 검정에 가까운 회색으로 수정하여 해결</p>

<h3 id="links-must-have-discernible-text">Links must have discernible text</h3>

<p>링크에 label이 없어서 생긴 문제. 각 링크별로 label로 어떤 역할을 하는지 알려줘야 링크에 대한 속성을 알 수 있어 screen leader가 읽을 수 있는데, 적지 않아서 생긴 문제. 예전에 image에 대한 것들은 alt prop으로 추가해두었는데, 링크에 대한 부분은 그냥 a tag 내부에 있는걸 읽을것으로 예상해서 문제가 없을 줄 알았는데 틀렸나보다.</p>

<p>a tag에 aria label 속성을 추가하여 해결</p>

<h3 id="console에-나오는-에러-해결">Console에 나오는 에러 해결</h3>

<p>이거는 light house 보다 Next.js에서 warning 이나 error가 나오는 부분이 console에 찍히고, 개선하라고 나온 문제였다.</p>

<p>오류 자체는 Next.js 13 이상의 이미지에서는 style prop을 지원하기에, 원래 Image tag에 바로 적용했던 style 속성을 Image -&gt; style -&gt; prop 으로 수정해서 해결</p>

<h3 id="lcp">LCP</h3>

<p>LCP(Largest Content Paint)는 웹 화면의 첫 로딩 속도에 문제가 생길 경우 낮게 점수가 나온다. 보통 이미지의 사이즈가 큰 경우 로딩에 문제가 생기고, 마찬가지로 나도 사이트에 gif 이미지를 넣어, 로딩이 오래 걸렸었다. 해당 문제는 Next.js image의 priority 속성을 추가해 높은 우선순위를 주어 LCP 의 로딩속도를 개선하여 해결</p>

<h3 id="seo">SEO</h3>

<p>링크만 타고 올거라 예상한 사이트였기에, 따로 SEO 설정을 하지 않았는데, 점수가 낮게 나와 간단하게 robots.txt 와 sitemap.xml을 추가하여 해결</p>

<h2 id="결과">결과</h2>

<p>사실 light house는 본인의 컴퓨터 성능이나, 웹 캐시 등 다양한 이슈에 따라 점수가 다르기에 절대적인 지표는 절대 아니다.</p>

<p>내 사이트 또한 로컬 배포된 환경에서 실행하고 light house에서 알려주는 문제만 해결했기에, 완벽하게 최적화된 사이트라고 볼 수는 없다. 하지만 우선 높은 점수를 받은걸로 만족하고, 다음에는 조금 더 절대적인 사이트 최적화를 진행해보도록 하자.</p>

<p><img width="593" alt="스크린샷 2024-04-07 오후 12 25 19" src="https://github.com/071yoon/071yoon.github.io/assets/66371206/840de045-79eb-43f8-be16-be548cd7d699" /></p>]]></content><author><name>071yoon</name></author><category term="web" /><category term="web" /><summary type="html"><![CDATA[배경]]></summary></entry><entry><title type="html">Github Action starter 오류 수정 이야기</title><link href="https://071yoon.github.io/til/2024/04/01/opensource-github-action.html" rel="alternate" type="text/html" title="Github Action starter 오류 수정 이야기" /><published>2024-04-01T00:00:00+00:00</published><updated>2024-04-01T00:00:00+00:00</updated><id>https://071yoon.github.io/til/2024/04/01/opensource-github-action</id><content type="html" xml:base="https://071yoon.github.io/til/2024/04/01/opensource-github-action.html"><![CDATA[<h2 id="서론">서론</h2>

<p>github action 의 starter workflows는 github의 기본적으로 page를 deploy 할 시 등 가장 기본적으로 사용되는 workflow이다. 아마 많은 FE 개발자 혹은 github pages를 통하여 블로그를 만드시는 분들은 많이들 사용해 봤을 것이라 생각된다.</p>

<p>보통 이러한 workflow는 보통, github deploy 페이지에서 GUI로 선행되어 repository 까지 갈 일이 보통 없다. 그런데, 꽤나 예전에 평소처럼 github page에서 Next.js deploy를 하였는데 문제가 생겼던 경험이 있다. 해당 문제를 타고보니 starter-workflows 에서 최신 Next.js를 지원하지 않아서 문제가 발생했고, 현재 수정이 되었는데, 해결과정을 서술해보도록 하겠다.</p>

<h2 id="문제-파악">문제 파악</h2>

<p>우선 문제는 크게 두가지였다.</p>

<ol>
  <li>Next.js v.14에서는 node 버전을 공식적으로 node v.18 이상을 사용해야된다 &gt; <a href="https://nextjs.org/docs/pages/building-your-application/upgrading/version-14">참고</a></li>
  <li>next config 에서 default output을 export로 지정하고, static HTML export를 따로 실행하지 않는것으로 바뀌었다 &gt; <a href="https://nextjs.org/docs/app/building-your-application/deploying/static-exports">참고</a></li>
</ol>

<p>해당 두 가지 문제를 해결하기 위해서는 next.config.js 파일도 수정해야 하지만 github action workflow에도 수정이 필수적으로 필요했다.</p>

<p>5개월 전 삽질의 흔적을 보니 로컬에서는 변경 후 잘 작동 했던것으로 보인다.</p>

<p><img src="https://github.com/071yoon/071yoon.github.io/assets/66371206/4d74aac6-1196-4e46-98ed-708d89d34171" alt="image" /></p>

<p>여기서 나의 문제는 해결 되었지만, 아무래도 공식 workflow 에서 수정하지 않으면 나와 비슷한 사람들이 많을 것 같아 repository 까지 들어가보며 확인을 해 보았다.</p>

<h2 id="공식적으로-해결해보기">공식적으로 해결해보기</h2>

<p>우선 꽤나 많은 사람들이 사용하는 workflow template 인데, 나만 문제가 생겼을거라 생각하지 않아 pull request 를 살펴보니 비슷한 문제들이 많이 있었다.</p>

<blockquote>
  <p>문제를 기술 및 해결한 <a href="https://github.com/actions/starter-workflows/pull/2204">PR LINK</a></p>
</blockquote>

<p>여기서는 앞서 문제 파악에서의 2번 문제 즉 yaml 에서 static HTML export를 하는 부분을 삭제 해주기는 하였지만, node 버전 수정을 하지는 않았다. 이 부분은 편하게 댓글을 달아 수정 요청사항을 추가해서 반영토록 도와주웠다.</p>

<p><img width="933" alt="image" src="https://github.com/071yoon/071yoon.github.io/assets/66371206/e43305c9-5436-4e79-849d-ba99e51a33ad" /></p>

<p>그리고 무려 PR이 올라간지 5개월이 지난 현재 잘 수정되었다고 메일이 왔다.</p>

<p><img width="952" alt="image" src="https://github.com/071yoon/071yoon.github.io/assets/66371206/6af5eb93-4eec-4c66-a4c9-e5c73f0fb430" /></p>

<p>한가지 아쉬웠던 점은, 따로 PR로 빼서 날렸으면 나도 contributor badge를 받을 수 있었을텐데, 귀찮아서 댓글만 남기고 넘어갔던 것 정도,,</p>

<blockquote>
  <p>그리고 진짜 간단한 PR인데, 되게 여유롭게 일 하시는듯</p>
</blockquote>

<p>여튼 좋은 일 하나 하기 성공</p>]]></content><author><name>071yoon</name></author><category term="TIL" /><category term="TIL" /><summary type="html"><![CDATA[서론]]></summary></entry><entry><title type="html">Firebase JWT 에러</title><link href="https://071yoon.github.io/web/2024/03/28/firebase-jwt.html" rel="alternate" type="text/html" title="Firebase JWT 에러" /><published>2024-03-28T00:00:00+00:00</published><updated>2024-03-28T00:00:00+00:00</updated><id>https://071yoon.github.io/web/2024/03/28/firebase-jwt</id><content type="html" xml:base="https://071yoon.github.io/web/2024/03/28/firebase-jwt.html"><![CDATA[<h2 id="문제-확인">문제 확인</h2>

<p>최근 운영하고 있던 서버 중 하나에 정말 큰 문제가 생겼다. 갑자기 모든 화면이 보이지 않는다는것.</p>

<p>현재 DB를 Firebase를 쓰고 있었는데, 혹시나 firebase DB를 너무 많이 써서 초기화를 시켜버리거나 하지는 않았을까? 백업을 안한지 오래됐는데 혹시 파일이 날라가면 어떡하지 두근두근 거리며 확인을 했더니 데이터는 다행히 살아있었고, 즉 firebase 문제는 아니였다.</p>

<p>모든 데이터가 보이지 않고, 작성/수정/삭제 등 모든 기능이 정지되었다. 흠,, 그렇게 되면 사실 데이터를 가져오는 곳에서 문제가 생겼다는 것이고 높은 확률로 fetch 부분이였기에 그부분을 자세히 살펴보았다. 그러던 중 이러한 코드를 발견</p>

<div class="language-typescript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">const</span> <span class="nx">auth</span> <span class="o">=</span> <span class="p">(</span><span class="nx">token</span><span class="p">:</span> <span class="kr">string</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
  <span class="kd">const</span> <span class="nx">decoded</span> <span class="o">=</span> <span class="nx">jwtDecode</span><span class="p">(</span><span class="nx">token</span><span class="p">,</span> <span class="p">{</span> <span class="na">header</span><span class="p">:</span> <span class="kc">true</span> <span class="p">});</span>
  <span class="k">if</span> <span class="p">(</span>
    <span class="nx">decoded</span><span class="p">.</span><span class="nx">kid</span> <span class="o">===</span> <span class="nx">process</span><span class="p">.</span><span class="nx">env</span><span class="p">.</span><span class="nx">NEXT_PUBLIC_FIREBASE_CERT_ONE</span> <span class="o">||</span>
    <span class="nx">decoded</span><span class="p">.</span><span class="nx">kid</span> <span class="o">===</span> <span class="nx">process</span><span class="p">.</span><span class="nx">env</span><span class="p">.</span><span class="nx">NEXT_PUBLIC_FIREBASE_CERT_TWO</span>
  <span class="p">)</span> <span class="p">{</span>
    <span class="k">return</span> <span class="kc">true</span><span class="p">;</span>
  <span class="p">}</span>
  <span class="k">return</span> <span class="kc">false</span><span class="p">;</span>
<span class="p">};</span>
</code></pre></div></div>

<p>꽤나 최근에 작성된 코드였는데, jwt 인증 토큰을 가지고 kid 를 비교해서 올바른 token인지 확인하는 과정이였다.</p>

<p>해당 코드를 작성하게된 계기는 웹사이트 인증수단이 필요했고, 모든 get/update/delete 등 firebase api를 활용할 때 인가를 주기 위해서였다.</p>

<p>그리고 firebase website 내에서도 <code class="language-plaintext highlighter-rouge">마지막으로, 토큰의 kid 클레임에 해당하는 비공개 키로 ID 토큰이 서명되었는지 확인합니다.</code> 이렇게 작성이 되어 있어, 서명 확인을 조금 단순하게 kid key 값을 가져와 env로 설정하여 진행했었는데, 바로 이 부분에서 문제가 생겼다.</p>

<h2 id="해결">해결</h2>

<p>앞 코드의 <code class="language-plaintext highlighter-rouge">NEXT_PUBLIC_FIREBASE_CERT_ONE/TWO</code> 같은 경우는 <a href="https://www.googleapis.com/robot/v1/metadata/x509/securetoken@system.gserviceaccount.com">google api 사이트</a>에서 직접 가져온 kid 코드였다.</p>

<p>작성 당시에는 문제가 없을거라 생각했는데, google api가 똑똑한것인지 kid 코드를 주기적으로 변경하여 생긴 문제였다. 임시방편으로 웹사이트에 들어가 새로운 kid로 env를 수정하니 생긴 오류는 막을 수 있었다.</p>

<p>다음은 주기적으로 같은 문제가 재발하지 않기위한 코드 수정이 남았다.</p>

<p>수정사항은 간단하다. google api 서버에 접속하여 kid를 실시간으로 가져온 후 jwt decode를 한 kid와 매칭시켜본다. 여기서 추가되는 부분은 <code class="language-plaintext highlighter-rouge">매번 google api 서버에 요청하기보다 한번 가져온 후 재사용할 수 있었으면 좋겠다</code> 였다.</p>

<p>나 혼자 작성해도 크게 문제될 것 없는 쉬운 문제이지만 reference는 언제나 좋으니 github을 뒤적거리다 좋은 소스를 발견했다.
바로 이름부터 신뢰가 가는 <a href="https://github.com/kriasoft/web-auth-library/blob/42a722e4cedc09ea2a86f92fe5aed73b19e5de94/google/credentials.ts#L43">web-auth-library</a>.</p>

<p>대충 보아하니, auth 인증이 된 유저 instance를 만들어 사용하는 방법인것 같은데, 내 서비스와 살짝 상황이 달랐다. 그래도, 싱글톤 instance로 관리하면 재요청 하지 않고 계속 쓰일 수 있을 것 같아 FirebaseCert Class를 만들어 관리하기로 했다.</p>

<div class="language-typescript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">private</span> <span class="k">async</span> <span class="nx">getCertificateFromServer</span><span class="p">()</span> <span class="p">{</span>
  <span class="kd">const</span> <span class="nx">response</span> <span class="o">=</span> <span class="k">await</span> <span class="nx">fetch</span><span class="p">(</span><span class="nx">CLIENT_AUTH_URL</span><span class="p">);</span>
  <span class="kd">const</span> <span class="nx">data</span> <span class="o">=</span> <span class="k">await</span> <span class="nx">response</span><span class="p">.</span><span class="nx">json</span><span class="p">();</span>
  <span class="k">this</span><span class="p">.</span><span class="nx">setCert</span><span class="p">(</span><span class="nx">data</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>

<p>대충 이런식으로 initialize를 1회 해주는 class를 만들어</p>

<div class="language-typescript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">const</span> <span class="nx">firebaseCert</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">FirebaseCert</span><span class="p">();</span>

<span class="kd">const</span> <span class="nx">auth</span> <span class="o">=</span> <span class="p">(</span><span class="nx">token</span><span class="p">:</span> <span class="kr">string</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
  <span class="kd">const</span> <span class="nx">decoded</span> <span class="o">=</span> <span class="nx">jwtDecode</span><span class="p">(</span><span class="nx">token</span><span class="p">,</span> <span class="p">{</span> <span class="na">header</span><span class="p">:</span> <span class="kc">true</span> <span class="p">});</span>
  <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">firebaseCert</span><span class="p">.</span><span class="nx">getCert</span><span class="p">()</span> <span class="o">||</span> <span class="o">!</span><span class="nx">decoded</span><span class="p">.</span><span class="nx">kid</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">return</span> <span class="kc">false</span><span class="p">;</span>
  <span class="p">}</span>
  <span class="kd">const</span> <span class="nx">arr</span> <span class="o">=</span> <span class="nb">Object</span><span class="p">.</span><span class="nx">keys</span><span class="p">(</span><span class="nx">firebaseCert</span><span class="p">.</span><span class="nx">getCert</span><span class="p">());</span>
  <span class="k">if</span> <span class="p">(</span><span class="nx">arr</span><span class="p">.</span><span class="nx">includes</span><span class="p">(</span><span class="nx">decoded</span><span class="p">.</span><span class="nx">kid</span><span class="p">))</span> <span class="p">{</span>
    <span class="k">return</span> <span class="kc">true</span><span class="p">;</span>
  <span class="p">}</span>
  <span class="k">return</span> <span class="kc">false</span><span class="p">;</span>
<span class="p">};</span>
</code></pre></div></div>

<p>이렇게 사용하도록 수정했다.</p>

<p>테스트해보니 fetch도 최초 1회만 하고, 페이지 전환을 하여도 client 세션이 만료되거나 새로고침 전에는 재 요청 하지 않음을 확인할 수 있었다.</p>

<p>오늘의 문제 해결 끝</p>]]></content><author><name>071yoon</name></author><category term="web" /><category term="web" /><summary type="html"><![CDATA[문제 확인]]></summary></entry><entry><title type="html">SQL 함수 알아보기</title><link href="https://071yoon.github.io/sql/2024/03/02/sql-functions.html" rel="alternate" type="text/html" title="SQL 함수 알아보기" /><published>2024-03-02T00:00:00+00:00</published><updated>2024-03-02T00:00:00+00:00</updated><id>https://071yoon.github.io/sql/2024/03/02/sql-functions</id><content type="html" xml:base="https://071yoon.github.io/sql/2024/03/02/sql-functions.html"><![CDATA[<h2 id="sql-함수-알아보기">SQL 함수 알아보기</h2>

<p>평소에 SELECT, INSERT, ALTER, CREATE 등 일반적인 DML, DDL문법만 사용하였는데 일을 하면서 다양한 문법들을 마주하고 공부하고 필요함이 느껴져 조금이나마 정리를 해보자고 한다</p>

<h2 id="coalesce">COALESCE</h2>

<blockquote>
  <p>NULl이 아닌 첫번째 값을 반환하는 함수</p>
</blockquote>

<p>행을 보고 COALESCE(col1, col2, col3) 이라면, 차례대로 col1, col2, col3 값을 보며 제일 먼저 null이 아닌 값을 반환하게 된다.</p>

<p>마지막 값에 static한 값을 넣어두면, NVL과 비슷한 형태로 사용할 수 있다.</p>

<h2 id="rollup">ROLLUP</h2>

<blockquote>
  <p>합계를 쉽게 사용하기 위해 사용</p>
</blockquote>

<ul>
  <li>GROUP BY ROLLUP</li>
  <li>GROUP BY GROUP_COLUMN WITH ROLLUP</li>
</ul>

<p>두가지 형태로 사용 가능하며, <code class="language-plaintext highlighter-rouge">GROUP BY</code> 를 하여 합계에 대한 새로운 row를 생성해준다.</p>

<h2 id="decode">DECODE</h2>

<p>ORACLE에서 사용하는 CASE WHEN 문법</p>

<p><code class="language-plaintext highlighter-rouge">DECODE(GENDER, 'M', 'Male', 'F', 'Female', 'others')</code></p>

<p>라 하면, GENDER가 ‘M’ 이면 ‘Male’, ‘F’면 ‘Female’, 둘 다 아니면 ‘others’인 문법</p>

<h2 id="character--varchar">CHARACTER / VARCHAR</h2>

<p>CHAR인 경우 크기가 고정되며, 만약 부족하다면 우측에 공백을 넣어 사이즈를 무조건 맞춘다.</p>

<p>VARCHAR인 경우, 가변 길이기에 공백을 넣는 방식이 아님.</p>

<h2 id="connect-by">CONNECT BY</h2>

<blockquote>
  <p>CONNECT BY, LEVEL, PRIOR 등 다양한 문법 세트
https://vaert.tistory.com/166 이사람의 블로그를 보면 쉽게 이해가 가능하다</p>
</blockquote>

<p>헷갈리는걸 정리 한번만 하자면 PRIOR 순서.</p>

<p><code class="language-plaintext highlighter-rouge">connect by 직속상사 = prior 직원</code> 이라면 <code class="language-plaintext highlighter-rouge">방금 전 행의 직원 값이 현재 행의 직속상사 값인 모든 행을 찾아라</code>
즉 이 순서라면 직속상사가 상위 계층(LEVEL 1) 으로 뻗어져가는 노드의 형태가 되고,</p>

<p><code class="language-plaintext highlighter-rouge">connect by prior 직속상사 = 직원</code> 이라면 <code class="language-plaintext highlighter-rouge">방금 전 행의 직속상사 값이 현재 행의 직원 값인 모든 행을 찾아라</code>
이 순서라면 제일 아래 직급이 상위의 계층이 되는 형태로 정렬이 된다.</p>

<h2 id="rank">RANK</h2>

<p>RANK는 <code class="language-plaintext highlighter-rouge">RANK() OVER()</code> 형태로 사용되며, 순위를 지정하는데 사용된다.
RANK 자체가 순위를 지정하기에, OVER 구문에 ORDER BY 로 순서를 지정해주어야 한다.</p>

<blockquote>
  <p>ex. RANK() OVER(ORDER BY SOMETHING DESC) as rank</p>
</blockquote>

<p>일반 RANK는 중복값이 들어갔을 경우, (1, 1, 3, 4, 5..) 이런 방향이라면 DENSE_RANK는 (1, 1, 2, 3, 4) 이렇게 중복과 순위의 측정 방식에 따라 다르다.</p>

<p>공부하다 새로운것이 생기면 더 정리할 것</p>]]></content><author><name>071yoon</name></author><category term="sql" /><category term="sql" /><summary type="html"><![CDATA[SQL 함수 알아보기]]></summary></entry><entry><title type="html">객체지향의 사실과 오해</title><link href="https://071yoon.github.io/book/2024/01/28/essence-of-oop.html" rel="alternate" type="text/html" title="객체지향의 사실과 오해" /><published>2024-01-28T00:00:00+00:00</published><updated>2024-01-28T00:00:00+00:00</updated><id>https://071yoon.github.io/book/2024/01/28/essence-of-oop</id><content type="html" xml:base="https://071yoon.github.io/book/2024/01/28/essence-of-oop.html"><![CDATA[<h2 id="객체지향의-사실과-오해">객체지향의 사실과 오해</h2>

<p>약 2년전에 사두고 시간이 없다는 핑계로 읽지 않았던 책을 이제야 읽게 되어 남기는 후기. (AKA 토끼책)</p>

<p>워낙 유명한 책인탓에, 내용을 정리하거나 분석해놓은 글은 정말 많기에, 읽으면서 느꼈던 나의 생각과 후기를 정리해보려고 한다.</p>

<h3 id="책에-관하여">책에 관하여</h3>

<p>이 책에서는 역할, 책임, 협력 그리고 객체의 자율성에 대한 개념을 끊임없이 강조하고 객체지향에 대해서 굉장히 추상적으로 정리한다.</p>

<p>객체란 클래스와 동의어가 아니며, 실세계와 일치시키려는 노력을 버리고 객체지향은 이런거야!를 설명한다. 이는, 전공생 기준 1학년 때 배우는 객체지향의 설명의 잘못된 점을 지적하고 개념을 새로이 정립하려는 의도로 보였다.</p>

<p>주로 1학년 때 배웠던 것은, 객체는 클래스에서 만든 instance이며, class라 함은 상속등을 통하여 다형성을 만족할 수 있다고 배운다. 무려 7년전 기억을 끄집어 내어 현재 내가 생각하는 객체지향과 한번 비교를 해보자.</p>

<h3 id="객체지향은-붕어빵인가">객체지향은 붕어빵인가</h3>

<p>생각해보면, 1학년 때는 객체지향을 붕어빵틀과 붕어빵, 혹은 다양한 종류의 피자들로 배웠던 기억이 난다. 실제로 1학년 때 교재의 첫장에는 이러한 글이 적혀있다.</p>

<blockquote>
  <p>클래스와 객체는 붕어빵틀과 붕어빵의 관계와 유사하다.</p>

  <p>클래스는 붕어빵을 찍어내는 틀이며, 객체는 붕어빵이다.</p>
</blockquote>

<p>이러한 비유법은 사실 나는 크게 나쁘다고 생각하지는 않는다. 처음 배우는 학생들에게 객체지향에 대한 진입장벽을 낮추고 쉽게 이해를 시킬 수 있는 좋은 수단이라고 생각한다.</p>

<p>하지만, 토끼책의 저자는 객체란 자율성을 부여받고 request와 response 관계가 있어야 한다는 점에서 이러한 예시는 정답이 아니라고 이야기한다.</p>

<p>이를 설명하기 위해 책에서는 커피의 주문을 예시로 둔다. 손님의 역할은 주문할 책임을 지는것으로, 바리스타에게 주문을 <code class="language-plaintext highlighter-rouge">request</code>하고 바리스타의 역할은 커피를 만들 책임을 지는것으로, 커피를 <code class="language-plaintext highlighter-rouge">response</code>로 전달한다.</p>

<p>즉 객체지향은 기능이 우선이 아닌, 이러한 <code class="language-plaintext highlighter-rouge">협력의 구조</code>가 우선시 되고 기능이 나오기에 붕어빵의 예시는 옳지 않다는 뜻이다. 또한, 현실 사물과 비교를 했을때의 문제는, 객체는 자율성을 가지고 판단을 할 수 있어야 하지만, 사물을 예시로 드는 순간, 사물이 판단을 해야 한다는 현실과의 괴리감이 생겨 오히려 이해가 어려울 수 있다는 말을 전달한다.</p>

<p>1학년 때 만약, 이 책을 읽었다면 오히려 이해가 되지 않거나 굉장히 객체지향은 복잡하다고 생각했을 것 같다. 하지만, 개발을 꽤나 해보고 항상 개발을 하기 전 구조를 작성하고 진행을 해서인지 교양책처럼 공감을 하며 읽었던것 같다.</p>

<h3 id="후기">후기</h3>

<p>해당 책에는 예시를 코드로 들지 않는다. 대신 그림이나 UML 다이어그램등을 잘 활용하여 표현한다. 이러한 부분을 오히려 이해하기 어렵다고 부정적으로 생각하는 사람도 있었지만, 나는 오히려 다이어그램이 저자가 말하고 싶은 협력의 부분을 더 강조하고 이해를 도와주어 이해하기가 편리했다.</p>

<p>사실 개발을 하다보면, 자연스럽게 책에서 말하고자 하는 바가 모두의 코드에 녹아들어 있을 수 밖에 없다고 생각한다. 하지만, 해당 책은 이러한 알고는 있지만, 말 혹은 글로 표현하기 어려운 점들을 글로 정말 잘 풀어 냈다고 생각한다. 그리고 개발을 하며 설계에 대해 한번쯤은 더 생각하게 만들어 주는 책이라 생각한다.</p>

<p>사실 해당 책은 객체지향을 하기전 무조건 읽어야된다! 혹은 객체지향의 바이블! 이런 느낌 보다는 이렇게 해야 확장성 혹은 누구나 쉽게 이해할 수 있는 코드가 되지 않을까? 에 가깝다고 생각한다.</p>

<p>개발트렌드가 있고 TDD, 함수형 프로그래밍이 뜨고 있는 시대 개발이론에 옳고그름은 없다 생각한다. 하나의 개발 교양도서로 한번쯤은 읽어보면 좋은 책이라 생각한다.</p>]]></content><author><name>071yoon</name></author><category term="book" /><category term="book" /><summary type="html"><![CDATA[객체지향의 사실과 오해]]></summary></entry></feed>