<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>개발기록</title>
    <link>https://codingrecorder.tistory.com/</link>
    <description>개발기록</description>
    <language>ko</language>
    <pubDate>Sun, 1 Nov 2026 17:27:39 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>개발코딩기록</managingEditor>
    <image>
      <title>개발기록</title>
      <url>https://tistory1.daumcdn.net/tistory/7413137/attach/296524de3be54eaa9e3729c37e819112</url>
      <link>https://codingrecorder.tistory.com</link>
    </image>
    <item>
      <title>벡터 임베딩, FTS in Postgresql (코드 딱히 없음)</title>
      <link>https://codingrecorder.tistory.com/entry/%EB%B2%A1%ED%84%B0-%EC%9E%84%EB%B2%A0%EB%94%A9-FTS-in-Postgresql-%EC%BD%94%EB%93%9C-%EB%94%B1%ED%9E%88-%EC%97%86%EC%9D%8C</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;Vector Embedding과 FTS(Full Text Search) 차이부터 이해해보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선 벡터 임베딩 개념부터 말씀드리자면&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;사람은 눈으로 이해하지만, 컴퓨터는 눈이 없는데요?&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;컴퓨터가 정보를 이해하기 위해서는 모두 bit(0과 1)로 변형되어야 한다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;벡터 임베딩&lt;/b&gt; = 텍스트, 이미지, 오디오, 영상 같은 비정형 데이터를 [a, b, c, d, e, ...] 벡터화 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;임베딩은 뭔데?&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1354&quot; data-origin-height=&quot;360&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rzulM/dJMcaa8iyUW/ZImrTYWJzMD1sucEkvmVZ0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rzulM/dJMcaa8iyUW/ZImrTYWJzMD1sucEkvmVZ0/img.png&quot; data-alt=&quot;라는 의미랍니다&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rzulM/dJMcaa8iyUW/ZImrTYWJzMD1sucEkvmVZ0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FrzulM%2FdJMcaa8iyUW%2FZImrTYWJzMD1sucEkvmVZ0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1354&quot; height=&quot;360&quot; data-origin-width=&quot;1354&quot; data-origin-height=&quot;360&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;라는 의미랍니다&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;벡터는 실수 Array고, 임베딩은 비정형 데이터를 실수 Array로 변환하는 것을 의미함.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래 과일 이미지 Raw 데이터 = 1px Dot는 RGB 값으로 이루어진 숫자 리스트이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;RGB값을 기반으로 모니터에 출력된 이미지 = RGB 숫자 리스트.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이미지 = 숫자 리스트라는 의미.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;6400&quot; data-origin-height=&quot;3600&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b7EpiU/dJMcahTAz5y/X1kABdoouHK7hXRifXab10/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b7EpiU/dJMcahTAz5y/X1kABdoouHK7hXRifXab10/img.png&quot; data-alt=&quot;출처 IBM: https://www.ibm.com/kr-ko/think/topics/vector-embedding&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b7EpiU/dJMcahTAz5y/X1kABdoouHK7hXRifXab10/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb7EpiU%2FdJMcahTAz5y%2FX1kABdoouHK7hXRifXab10%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;6400&quot; height=&quot;3600&quot; data-origin-width=&quot;6400&quot; data-origin-height=&quot;3600&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처 IBM: https://www.ibm.com/kr-ko/think/topics/vector-embedding&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;학부 연구생 할 때 (2019년도) 석, 박사 행님들의 AI 세미나에서 줍줍했던 단어&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&quot;차원 축소&quot; Dimension Reduction =&amp;gt; 고차원의 데이터를 낮은 차원의 데이터로 '압축'하는 과정이다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;벡터 임베딩의 핵심은 '차원 축소'다. 이미지를 이루는 RGB 숫자 행렬(3 * 1920 * 1080 = &lt;span style=&quot;background-color: #ffffff; color: #16171a; text-align: start;&quot;&gt;6,220,800 개의 숫자 값, 0~255 사이의)을 적절히 학습된 임베딩 모델(블랙 박스라고 생각하고)에 넣어서 뚝딱하면 =&amp;gt; 1,024 개의 숫자(-1.0 ~ 1.0 실수 범위)의 리스트로 변환하면, 비슷한 이미지끼리 비슷한 공간에 매핑되는(?) 신기한 기술이다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #16171a; text-align: start;&quot;&gt;고차원의 정보량(6,220,800 개의 값)을 &quot;잘 학습된 임베딩 모델&quot;을 통해서 낮은 차원의 정보량(1,024개의 값, 이 때 1,024 차원으로 생각해도 좋음)으로 변환하는 것이다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #16171a; text-align: start;&quot;&gt;임베딩 했다치고, 이걸로 뭐 할 수 있는데요?&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #16171a; text-align: start;&quot;&gt;차원 줄이는것도 ㅇㅋ. 근데 줄여서 뭐할건데요?&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #16171a; text-align: start;&quot;&gt;고차원의 정보량이 차원 축소를 통해서 &lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;정보가 &quot;압축&quot;되면서 비슷한 성질을 띄는 데이터는 가까운 곳에 위치하게 되는 성질을 이용&lt;/span&gt;&lt;/b&gt;한다. 그래서 언제 쓰느냐.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #16171a; text-align: start;&quot;&gt;(x) 정확한 값을 찾을 때 =&amp;gt; SQL, 패턴 매칭 쓰시오&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #16171a; text-align: start;&quot;&gt;(x) 특정 단어가 들어간 문서 찾기 =&amp;gt; BM25 쓰시오. 빠르고 저렴하오&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #16171a; text-align: start;&quot;&gt;(o) A를 input으로 할 때, A` A`` 즉, &lt;span style=&quot;color: #ee2323; background-color: #f6e199;&quot;&gt;&lt;b&gt;A와 비슷한 데이터를 찾을 때&lt;/b&gt;&lt;/span&gt; 쓴다&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #16171a; text-align: start;&quot;&gt;그러니께, 다시 이미지로 생각해보자&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #16171a; text-align: start;&quot;&gt;아래 골든 리트리버(챱츄)를 다양한 이미지에서 찾을 때 어떻게 찾을거냐는거죠&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;422&quot; data-origin-height=&quot;350&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bZQlmN/dJMcagAv1Ff/5fnPKvcr7J4k8ubTxRzRW0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bZQlmN/dJMcagAv1Ff/5fnPKvcr7J4k8ubTxRzRW0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bZQlmN/dJMcagAv1Ff/5fnPKvcr7J4k8ubTxRzRW0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbZQlmN%2FdJMcagAv1Ff%2F5fnPKvcr7J4k8ubTxRzRW0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;422&quot; height=&quot;350&quot; data-origin-width=&quot;422&quot; data-origin-height=&quot;350&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(1) 비슷한 색상을 찾나? -&amp;gt; 불가능&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(2) 비슷한 모양을 찾나? -&amp;gt; 불가능&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1648&quot; data-origin-height=&quot;1392&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bJxEhF/dJMcad4OwFo/k8KO2NfWKNffdAMxtxPH6K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bJxEhF/dJMcad4OwFo/k8KO2NfWKNffdAMxtxPH6K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bJxEhF/dJMcad4OwFo/k8KO2NfWKNffdAMxtxPH6K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbJxEhF%2FdJMcad4OwFo%2Fk8KO2NfWKNffdAMxtxPH6K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;457&quot; height=&quot;1392&quot; data-origin-width=&quot;1648&quot; data-origin-height=&quot;1392&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;CV(Computer Vision)&lt;/b&gt;이라는 분야도 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컴퓨터가 숫자로 이루어진 데이터를 '사람의 눈 처럼' 이해하도록 만들기 위해 다양한 알고리즘을 개발하는 분야다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 분야의 기술이 막힌 부분이 개랑 고양이 구분하는 알고리즘이다.(라고 들었음 교수님한테)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;구분하도록 만들수는 있는데, '개 vs 고양이' 판별 전용 프로그램을 매번 만들어야한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개 vs 새 구분 프로그램이 필요하면, 이전에 만든 로직을 활용하기가 어렵거나, 불가능하거나, 가능할수도 있거나. 랜덤하다는 것.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;근데 벡터 임베딩을 쓰면?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;고차원의 데이터가 압축되면서 비슷한 성질을 가진 정보가 가까운 공간에 위치하게 된다는 것. &lt;span style=&quot;color: #9d9d9d;&quot;&gt;(이게 어떻게 되는거냐 라고 물어보면 임베딩 모델을 '학습'시킬 때 의미 기반의 공간이 되도록, 데이터와 정답지를 미리 주고 모델을 혹사시키면 짜잔! 된다고 함. 대조학습으로 주로 훈련을 하기 때문에, 부정어를 넣으면 이해하지 못함. 왜냐, input data와 기존 데이터가 '관련'있는지를 중심으로 학습되기 때문에. 리트리버를 찾지마, No 골든 리트리버 이따위로 넣으면 골든리트리버 이미지가 나올것이다 : &amp;gt; )&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기까지 벡터 임베딩&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;FTS, tsvector, tsquery가 뭐임?&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;TS = Text Search.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;FTS = Full Text Search = 전문 검색, 전사 검색이라고도 불림&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그게 뭔데?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문서에서 '단어', '문장'을 찾아주는 기술임&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;검색 엔진이라고도 불리는데&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 검색 엔진도 맞는데 이거 말고&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1188&quot; data-origin-height=&quot;1244&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/sVqaf/dJMcahMT2wf/VrYquC5H7labwYFwkKBphk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/sVqaf/dJMcahMT2wf/VrYquC5H7labwYFwkKBphk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/sVqaf/dJMcahMT2wf/VrYquC5H7labwYFwkKBphk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FsVqaf%2FdJMcahMT2wf%2FVrYquC5H7labwYFwkKBphk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1188&quot; height=&quot;1244&quot; data-origin-width=&quot;1188&quot; data-origin-height=&quot;1244&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(1) 검색엔진 = 진짜 네이버, 구글 검색엔진을 의미&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(2) &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;방대한 데이터&lt;/b&gt;&lt;/span&gt;에서 내가 찾으려는 '단어', '문장'의 조각을 &quot;연관성 점수로 정렬해서&quot; 찾는 기술&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;FTS 대표적인 기술, 엔진, 라이브러리 4종류&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한번 쯤 들어보셨을&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. Elastic Search(전문적인 검색 엔진)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. Mellisearch (최근에 나온 경량화 검색 엔진)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. Postgresql 이 제공하는 FTS(RDBMS에 내장된 기능)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. RediSearch (Redis에 붙은 인메모리 기반의 NoSQL FTS 기술)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;FTS 핵심 기능 3가지&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;FTS가 되기 위해서는 3가지 코어 기능을 제공해야한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. 텍스트 분석&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;텍스트를 쪼개고, 불용어(Stopword - NLP에서 쓰는 단어, 의미에 영향을 주지 않는 친구들을 제거하는것), 공통화(jumping, jumps, jumped, jump -&amp;gt; jump 1개로 일원화)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. 역색인&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Inverted Index 기술. 문장의 텍스트를 분석하고 -&amp;gt; 각 텍스트가 어떤 문서, 어디 위치에 있는지를 기록한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문서1&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나는 기린이 좋다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문서2&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나는 귀여운 고양이가 좋다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[Inverted Index]&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나는: 문서1-0, 문서2-0&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기린: 문서1-1&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;좋다: 문서1-2&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;귀여운: 문서 2-1&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;고양이: 문서 2-2&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. &lt;b&gt;랭킹 알고리즘&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단어의 등장 빈도 및 밀도를 기준으로 '연관성'이 높다고 판단하고, 이를 수치화해서 제공해준다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Vector Embedding vs FTS - 언제 어떤 기술을 사용할 것 인가?&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;키워드, 단어 중심의 검색이 필요하다 -&amp;gt; FTS = Full 전체 텍스트에서 찾으려는 아이를 발견하는 것&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;의미(문맥) 중심의 검색이 필요하다 -&amp;gt; Embedding = Vector base 검색이 필요한 것&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;query1: '시원한 여름 과일',&amp;nbsp; &amp;nbsp;원하는 답변: '수박'&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;FTS: 수박 못찾음. 정확한 단어 매칭이 안 됨&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Vector: 쌉가능. 왜? 비슷한 의미를 찾으니까&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;query2: 'Mac Book Air M2 13인치 16GB 스펙은?',&amp;nbsp; &amp;nbsp;원하는 답변: &quot;해당 모델의 제품 스펙&quot;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;FTS: &quot;정확히 해당 기기의 모델 스펙을 찾아줄 수 있음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Vector: 비슷한 모델, 기기로 오해 가능. Mac Book Pro M2 16인치 16GB 제품의 스펙을 가져올 수도 있음.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정리.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;FTS 쓰는 경우&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 정확한 명사, 코드, 규칙, 규격에 대한 검색이 중요한 경우에는&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. AI 도입 부담. 단순 블로그, 단순 게시판, 단순 검색 결과에 명확히 포함된 것만 보여줘도 되는. ㅕㅇ우&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Vector 쓰는 경우&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. LLM 기반의 AI 서비스(RAG로 확장): '우리 회사 휴가 규정 알려줘' =&amp;gt; 사내 문서중 필요, 관련된 문맥을 통해 검색가능&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 동의어, 유의어 등 질문의 의도 파악이 중요한 경우 =&amp;gt; 배 아플 때 먹는 약 추천 =&amp;gt; 의미기반 소화제, 진통제가 나와야 함&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 다국어 검색: Delicious Apple =&amp;gt; 맛있는 사과를 찾아줘야함&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. 추천 시스템&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <author>개발코딩기록</author>
      <guid isPermaLink="true">https://codingrecorder.tistory.com/48</guid>
      <comments>https://codingrecorder.tistory.com/entry/%EB%B2%A1%ED%84%B0-%EC%9E%84%EB%B2%A0%EB%94%A9-FTS-in-Postgresql-%EC%BD%94%EB%93%9C-%EB%94%B1%ED%9E%88-%EC%97%86%EC%9D%8C#entry48comment</comments>
      <pubDate>Sat, 10 Oct 2026 12:30:01 +0900</pubDate>
    </item>
    <item>
      <title>안 꾸준했죠?</title>
      <link>https://codingrecorder.tistory.com/entry/%EC%95%88-%EA%BE%B8%EC%A4%80%ED%96%88%EC%A3%A0</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;약 2달 방치해버린 꾸준지향 블로그&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마음한켠 '글써야지.. 커밋해야지...'&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;'꾸준한가요 계속 외쳐놓고 방치하는게 왠 말이냐 ..'&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;멈추게된 이유는 뭔가 잘못되고 있는 느낌이 들어서다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그냥 커밋하기 위한 커밋을 하고 있는 것 같아서.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;뭐가 잘못되었던걸까?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나는 목표가 없었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;구체적인 목표, N살까지는 어떤 목표를 달성할거야. 라는 개념이 아예 없었음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;블로그를 시작한 동기가 얕았기 때문에, 금방 사그라들었고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이걸 왜 하고 있는지 나도 모르니 -&amp;gt; 그냥 안 하게 된 것.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제는 구체적인 목표가 없어서다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아직도 없다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;근데, 문제 진단은 했잖아. 한잔해&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번주 주말에 해볼것은&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 3개월 남은 2026년 32살의 내 목표를 세우는 것&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 2027년 33살의 내가 연말에 달성할 목표를 세우는 것&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 35살이 될 때 만족할만한, 되고싶은 나의 모습을 목표로 그리는 것&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>당신은 꾸준한가요?</category>
      <author>개발코딩기록</author>
      <guid isPermaLink="true">https://codingrecorder.tistory.com/47</guid>
      <comments>https://codingrecorder.tistory.com/entry/%EC%95%88-%EA%BE%B8%EC%A4%80%ED%96%88%EC%A3%A0#entry47comment</comments>
      <pubDate>Sat, 10 Oct 2026 12:02:13 +0900</pubDate>
    </item>
    <item>
      <title>자기소개서 (이게 맞는지는 모르겠음)</title>
      <link>https://codingrecorder.tistory.com/entry/%EC%9E%90%EA%B8%B0%EC%86%8C%EA%B0%9C%EC%84%9C-%EC%9D%B4%EA%B2%8C-%EB%A7%9E%EB%8A%94%EC%A7%80%EB%8A%94-%EB%AA%A8%EB%A5%B4%EA%B2%A0%EC%9D%8C</link>
      <description>&lt;h2&gt;내가 스스로 생각하는 나&lt;/h2&gt;
&lt;h3&gt;이나모리 가즈오 - 왜 일하는가&lt;/h3&gt;
&lt;p&gt;일에 관련된 책 중 가장 좋아하는 책입니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&amp;quot;어제보다 한 걸음 더 앞으로 나아가라&amp;quot;&lt;/li&gt;
&lt;li&gt;&amp;quot;어려운 일일수록 정면으로 맞서라&amp;quot;&lt;/li&gt;
&lt;li&gt;&amp;quot;성공하기 위해서만 열심히 일해야 하는 것은 아니다. 인생은 살아가는 일 자체가 치열한 노력의 연속이다.&amp;quot;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;일에 대한 생각&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;기업가는 일을 일으키지만, 실무자는 일을 완성시킨다고 생각합니다.&lt;/li&gt;
&lt;li&gt;장인정신. 디테일을 완성시켜나가는 것이 업의 본질이라 믿습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;삶의 우선 원칙. 시간 그리고 밀도 있는 경험, 발전&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;시간, 돈 중에 더 중요한 가치는 시간이라고 생각합니다.&lt;/li&gt;
&lt;li&gt;회사까지 도보 5분 이내 거리에 거주하는 것을 선호합니다.&lt;/li&gt;
&lt;li&gt;단순하고 수동적인 일, 반복되면서 동시에 재미없는 일을 싫어합니다.&lt;/li&gt;
&lt;li&gt;편안한 일보다는 도전하고 성장하는 일을 선호합니다.&lt;/li&gt;
&lt;li&gt;강한 피드백을 받고 잠깐 감정적으로 불편한 것 보다 더 발전하는 나를 원합니다&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;학생 창업가로서의 2년&lt;/h2&gt;
&lt;p&gt;작은 아이디어에서 시작했습니다. 게이머들이 과외 선생님을 구하는 경험을 개선해보자.&lt;br&gt;게임 과외선생님을 구해 과외를 받았던 저의 경험과 프로게이머 구단에서 코치로 일하고 있는 친구의 조언과 함께 팀원을 모집했습니다. 저를 포함한 개발자 3명, 디자이너 1명이었습니다. 지원사업과 스마트파머 엑셀러레이터 보육사업을 함께 진행하며 스타트업에 대해 더 깊이 알게되었습니다. 하지만, 정작 서비스의 발전은 크게 진전되지는 않았습니다. 기획의 뿌리가 약했고, 사업이라는 돈을 벌기에는 도메인에 대한 지식도 부족했던 것 같습니다. 얕은 기획으로 초기 구상인 과외 선생님과 학생을 매칭시켜 수수료 취하는 BM에서 게이머들의 팀원 모집으로 방향이 바뀌기 시작했습니다. 고객이 중심이 아닌 우리가 생각하기에 유용한 기능들을 추가하며 점점 사업의 방향이 기울게 되었던 것 같습니다.&lt;/p&gt;
&lt;p&gt;돈을 번다는 혹은 유저를 폭발적으로 모으겠다는 본질이 아닌 사업을 위한 사업을 하게 되면서 팀원도 떠나게 되고, 저 스스로도 실패를 받아들이게되었습니다. 하지만, 이 과정에서 얻은 지식과 간절함을 통해 성장하는 경험은 남았다고 생각합니다. 완벽한 기획이 없었기에, 겁없이 뛰어들 수 있었고 또 성장할 수 있게 되었습니다.&lt;/p&gt;
&lt;p&gt;배운것: &lt;em&gt;완벽한 시작이 아닌, 부딪히며 성장하는 방법을 배웠습니다.&lt;/em&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;기획의 깊이에서 나오는 프로덕트의 디테일(상품)과 인간 욕망의 작동 원리(사업)에 대한 이해가 가장 중요하다&lt;/li&gt;
&lt;li&gt;부족하고 잘 모르더라도 행동하고 부딪히는 태도 역시 중요하다&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;프리랜서 개발자로서 1년&lt;/h2&gt;
&lt;p&gt;보육기업 기간이 끝난 후 모든 팀원과 헤어지고 학교 옆 원룸에서 다시 ‘돈을 버는 사업’을 해보자 생각하였습니다.이제 갓 4학년이 끝난 시점에 제가 할 수 있던 최선의 생각은 “돈 많은 사람들이 자주 들락날락하는 곳에 있자”였습니다. 정장을 입고 학교앞 부동산을 돌아다니며 매물 홍보를 무료로 도와드리겠다며 부동산 업무를 2달간 도와드리며 만난 여러 업종중 스마트스토어 쇼핑몰 운영하시는 분과 연결이되어 프리랜서 개발자로서 시간을 보냈습니다.&lt;/p&gt;
&lt;p&gt;운송장을 자동으로 입력해주는 프로그램, 경쟁사와 자사의 키워드별 상품 순위를 시간단위로 추적, 네이버 광고 API를 활용한 전환 성과를 자사의 데이터하우스로 축적하는 파이프라인 구축등의 일을 하였습니다. 쇼핑몰 대표님의 소개로 블로그 자동화 프로그램(글 발행, 매크로 봇 작업), 스마트폰 자동화 프로그램(인스타 댓글 수집, 스마트스토어 댓글 수집)을 만들었습니다.&lt;/p&gt;
&lt;p&gt;쇼핑몰 대표님을 통해 프리랜서 개발자로서 개발을 통해 돈을 버는 경험은 얻었지만, 사업의 근본이 없이 그때그때 돈 되는것을 만들어달라고 요청하는 것에서 더 발전할 수 없다고 느끼기 시작했습니다&lt;br&gt;개발자로서 성장이 멈추고 있다는 느낌. 크롤링/스크래핑 같은 외부 소스들을 겉핥기하는 업무가 아닌 내부의 핵심 코어를 만들기에는 역량도 경험도 부족하다는것을 느끼고 취업을 결심하였습니다.&lt;/p&gt;
&lt;h2&gt;허들러스의 개발자로서 1년&lt;/h2&gt;
&lt;p&gt;마케팅 도메인에 대한 지식이 있었고, 기업의 AX를 돕는다는 방향에 매력을 느껴 취업하게 되었습니다. 입사 2주차부터 시작했던 전략 기반 자동 입찰 서비스(클릭세이버)를 마케팅 대행사 리드스팟과 함께 만들며, 현재도 추가적인 기능들을 개발하고 있습니다. 전략 기반의 1시간 단위 입찰가 조정, 성과 기반의 정보를 구글 빅쿼리에 축적하여 시간 단위로 예산을 분배하는 기능, 연관 검색어 API와 전환 성과가 발생한 키워드의 관계를 그래프로 만들어 추가적인 키워드 아이디어를 얻는 도구등 다양한 도구를 만들어나가고 있습니다.&lt;/p&gt;
&lt;h3&gt;바이브코딩에 휩쓸린 2개월&lt;/h3&gt;
&lt;p&gt;입사후 1달 동안은 AI 소식 및 바이브코딩을 적극적으로 찾아보며 허들러스 회사에 기술을 알리며 개발팀에 새로운 도구들을 많이 실험해볼 수 있었습니다. 2025.07월 당시 허들러스에서 사용하던 AI Agent - Cursor에서 Amazon Q, Claude Code를 순차적으로 도입해보며 CTO님을 설득하여 Claude Code를 최종적으로 사용할 수 있게 되었습니다.&lt;/p&gt;
&lt;p&gt;하지만, 개인적으로는 무분별한 AI 사용으로 인해 지나친 AI에 대한 의존성과 스스로 코드 짜는 능력이 퇴화되고 더 복잡한 소프트웨어를 만들기 위한 나의 성장이 점점 적어진다는것을 느꼈습니다.2025년 09월부터는 AI에 대한 의존성을 줄이기 위해 기술을 직접 사용해보거나, PoC 단계에서 직접 API를 사용하며 mvp 수준으로 만들어보고, 사이드 프로젝트는 AI없이 직접 개발하는 등의 다양한 시도를 하였습니다.&lt;/p&gt;
&lt;h3&gt;입찰 자동화 서비스 개발&lt;/h3&gt;
&lt;p&gt;2025.08월 ~ 2026.09월 약 1년의 기간동안 클릭세이버의 자동입찰 엔진과 운영 서버를 설계하고 개발했습니다. 현재 취급 광고 금액 2억원, 주요 고객사: 카스(맥주), 아레나(수영복), 쟈뎅(커피)&lt;/p&gt;
&lt;p&gt;처음 받은 요구사항은 &amp;quot;성과가 좋은 광고에 예산을 더 쓰고, 입찰가를 조정하자&amp;quot;였습니다. 이 한 문장에서 시작하여, 협력사인 리드스팟에 매주 방문하여 광고 도메인에 대한 이해도를 높이며, 네이버 API를 조사하였습니다.&lt;/p&gt;
&lt;p&gt;가장 오래 붙잡고 있던 문제는 광고주별로 상이한 광고의 규모와 API 호출량에 대한 제약이었습니다. 하루에 약 355,000개의 광고를 처리해야 했고, 네이버 검색광고 API는 광고주별로 호출 제한이 있었습니다. 유스케이스간의 복잡한 관계들 속에서 모듈 단위로 핵심 엔진이 작동되도록 설계하였습니다.한 광고주의 credential 문제나 API 오류가 전체 엔진을 멈추게 하면 안 된다는 것이 기준이었습니다. queue, rate limit, 데이터 저장소를 모두 광고주 단위로 쪼개면서 장애의 범위를 한 광고주 안에서 다룰 수 있도록 방향으로 설계했습니다.&lt;/p&gt;
&lt;p&gt;이 일을 하면서 가장 크게 바뀐 생각은, 이 코드가 광고주의 광고 예산에 크게 영향을 미치는 코드라는 책임감이었습니다. 고려하지 못한 정책, 예외상황으로 인해 입찰가나 예산이 크게 변하는 것에 대해서 계속 고려하였습니다. 서비스를 운영하는 과정중에 광고주, SA 마케터 분들의 질문이 많이 있었습니다.&amp;quot;이 광고그룹은 왜 입찰가가 안 올라갔나요?&amp;quot;라는 질문에 대해 매번 코드를 들여다보는 것이 아니라 감사로그 그 자체로 답변을 할 수 있어야 한다고 생각했습니다. 외부 API에 크게 의존적인 서비스 특성상 도메인 상태 변화가 중심이 아닌 판단 및 판단의 근거를 남기는 것이 서비스의 핵심 도메인 이라는 것을 이해하게 되었습니다.&lt;/p&gt;
&lt;p&gt;2025년 9월 런칭 이후 광고주와 처리 광고 수는 계속 늘어나며 서비스가 정교해지기도 하였습니다. 하지만, 요구사항이 크게 바뀌기거나 기획의 뿌리, 결이 없는 상태로 요구사항이 추가되며 구조를 크게 뒤엎기도 하고 필요하다는 요청으로 만들었지만 사용되지 않는 서비스를 만드는 경험을 하기도 하였습니다. 개발자, 기획자 2가지 역할을 하였다고 생각합니다. 조금 아쉬웠던 것은 서비스를 만들어 운영하는 것이 회사 자체에서도 처음이다보니 조언을 구할곳이 없었다는 것 입니다.&lt;/p&gt;
&lt;p&gt;배운것:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;돈을 움직이는 코드에는 기능보다 먼저 검증 수단과 기록이 있어야 한다&lt;/li&gt;
&lt;li&gt;운영자가 스스로 상태를 확인할 수 없는 시스템은 완성된 것이 아니다&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;실리콘밸리 개발자와 과외, 엔지니어링에 대해 알아가고 있습니다&lt;/h3&gt;
&lt;p&gt;2025.09월 사수의 부재, 혼자서 성장의 한계를 느끼고 다양한 과외 플랫폼 및 지인을 통해 시니어 개발자를 컨택하기 시작하였습니다. 아마존 이미지 의류 피팅 모델 및 핵심 시스템을 개발하고 엑싯하신 실리콘 밸리 개발자(한국인)님을 선생님으로 모시고 개발자를 넘어 엔지니어의 세계에 대해서 배워나가고있습니다 (주 2회, 1회당 2시간 수업, 현재 1년째입니다). 기초적인 개념의 중요성을 이해하게 되었고 개발 실력을 한 단계씩 향상 시켜나가고 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;기능 구현 중심의 개발을 넘어 산업의 핵심을 설계할 수 있는 엔지니어가 되고싶습니다.&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;회사에 AI-세션 3개월 운영, 스터디 도입&lt;/h3&gt;
&lt;p&gt;저는 공부하고 배우는것을 좋아합니다.&lt;br&gt;2025 09월 2026 01월까지 매주 금요일 1시간 그로스팀과 개발팀을 타겟으로 AI 소식 및 기본적인 원리에 대해서 30분씩 자료를 준비하여 발표하며 정보를 공유하였습니다. 원천이 된 지식은 2019년 1월 ~ 2020년 4월까지의 시각연구실 학부연구생을 경험하며 알게되었던 정보들을 기반으로 가벼운 수준으로 AI의 원리, 비결정성에 대한 관점, AI Agent의 작동 근간 원리등을 공유하는 시간을 가졌습니다.&lt;/p&gt;
&lt;p&gt;2026년 11월부터 시작된 개발팀 스터디에서 실리콘밸리 개발자 선생님으로부터 배운 내용을 공유하거나, AI 세션에서 발표한 내용의 실제 작동 코드들을 함께 타이핑하는 시간을 가지며 AI 시대에서 실력을 키우는 방법은 역설적으로 나의 개발 실력, 설계 실력이라는 메시지를 계속 전달하였습니다.&lt;/p&gt;</description>
      <author>개발코딩기록</author>
      <guid isPermaLink="true">https://codingrecorder.tistory.com/46</guid>
      <comments>https://codingrecorder.tistory.com/entry/%EC%9E%90%EA%B8%B0%EC%86%8C%EA%B0%9C%EC%84%9C-%EC%9D%B4%EA%B2%8C-%EB%A7%9E%EB%8A%94%EC%A7%80%EB%8A%94-%EB%AA%A8%EB%A5%B4%EA%B2%A0%EC%9D%8C#entry46comment</comments>
      <pubDate>Fri, 18 Sep 2026 10:48:33 +0900</pubDate>
    </item>
    <item>
      <title>Java 문법 공부</title>
      <link>https://codingrecorder.tistory.com/entry/Java-%EB%AC%B8%EB%B2%95-%EA%B3%B5%EB%B6%80</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 파일 하나에 public 타입은 하나만 둘 수 있습니다. 그&amp;nbsp;public&amp;nbsp;타입&amp;nbsp;이름과&amp;nbsp;파일&amp;nbsp;이름이&amp;nbsp;같아야&amp;nbsp;합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 상속을 막는 방법: 클래스에 final을 붙이면 아무도 extends BaseClass를 할 수 없습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. Java Type은 2가지로 나뉜다. (1) 원시 타입(Primitive) 변수에는 값 자체가 담김. == 값을 비교 (2) 참조 타입(Reference) 변수에는 주소가 담김. == 저장된 주소가 같으면 같은 객체로 판단. String, Array, 직접 만든 클래는 모두 참조 타입이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. Objects 사용법&lt;/p&gt;
&lt;pre id=&quot;code_1787065384081&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 사용법 1.
if (value == null) throw new NullPointerException(&quot;value must not be null&quot;);
this.value = value;


// 사용법 2.
this.value = Objects.requireNonNull(value, &quot;value must not be null&quot;);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5. Java의 모든 객체는 'Object'를 자동으로 상속함. Object는 equals, hashCode, toString을 이미 가지고 있음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;equals(): 주소가 같은지 비교 -&amp;gt; 값으로 비교하고 싶다면(값이 같으면 같은 객체라면) equals를 @Override 해야한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;hashCode(): 객체마다 다른 정수값&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;6. Annotation(@): 코드에 붙이는 메모인데 컴파일러나 프레임워크가 읽는다&lt;/p&gt;
&lt;pre id=&quot;code_1787065676022&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Override
public boolean equals(Object other) {
    return this == other || other instanceof SomeClass that &amp;amp;&amp;amp; value.equals(that.value);
}

// || other instanceof ProjectId that   // ② 타입이 맞나? 맞으면 that에 담아라
// &amp;amp;&amp;amp; value.equals(that.value)          // ③ 안에 든 문자열이 같나?&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 때 that 문법의 장점이 드러나는데&lt;/p&gt;
&lt;pre id=&quot;code_1787065867417&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// Java 15 버전 이하에서는 원래
@Override
public boolean equals(Object other) {
    if (other instanceof SomeClass) {
        SomeClass that = (SomeClass) other;
        return value.equals(that.value);
    }
    return false;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;7. toString()&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(1) 암시적 호출 System.out.println(객체), 문자열 연결 연산시 toString()이 호출됨 ex) System.out.println(&quot;&amp;gt;&amp;gt; &quot; + someObject);&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(2) 명시적 호출 someClass.toString()을 직접 불러서 호출하기&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;8. enum ~ 정해진 값만 들어올 수 있는 타입&lt;/p&gt;
&lt;pre id=&quot;code_1787066269276&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public enum AppErrorCode {
    BAD_REQUSET,
    UNAUTHORIZED,
    NOT_FOUND,
    CONFLICT,
    RATE_LIMIT
}


// 이렇게 선언한 후 활용법
AppErrorCode.values(); // 모든 값을 배열로, 반복 돌 때 사용한다

code.name(); // 해당 enum 변수가 갖고 있는 값을 문자열로 return

AppErrorCode.valueOf(&quot;...&quot;); // 문자열을 enum으로, 없는 이름이면 예외&lt;/code&gt;&lt;/pre&gt;</description>
      <category>Java</category>
      <author>개발코딩기록</author>
      <guid isPermaLink="true">https://codingrecorder.tistory.com/44</guid>
      <comments>https://codingrecorder.tistory.com/entry/Java-%EB%AC%B8%EB%B2%95-%EA%B3%B5%EB%B6%80#entry44comment</comments>
      <pubDate>Wed, 19 Aug 2026 00:17:58 +0900</pubDate>
    </item>
    <item>
      <title>인스턴스(Instance) 뜻, 의미 IT 용어</title>
      <link>https://codingrecorder.tistory.com/entry/%EC%9D%B8%EC%8A%A4%ED%84%B4%EC%8A%A4Instance-%EB%9C%BB-%EC%9D%98%EB%AF%B8-IT-%EC%9A%A9%EC%96%B4</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;사전적으로 인스턴스는 '실제 예', '사례' 라는 뜻을 가지고 있습니다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;객체는 클래스의 인스턴스다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인스턴스는 추상적인 설계도를 바탕으로 &lt;b&gt;컴퓨터 메모리에 실제로 만들어진&lt;/b&gt; '구체적인 실체'를 뜻한다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;설계도(Class)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;객체(Object) 소프트웨어에서 표현할 수 있는 모든 실체를 통틀어 부르는 말&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인스턴스(Instance) 특정 클래스의 실제 구현체&lt;/p&gt;</description>
      <category>단어, 용어 정리</category>
      <category>Instance</category>
      <category>IT용어</category>
      <category>인스턴스</category>
      <author>개발코딩기록</author>
      <guid isPermaLink="true">https://codingrecorder.tistory.com/43</guid>
      <comments>https://codingrecorder.tistory.com/entry/%EC%9D%B8%EC%8A%A4%ED%84%B4%EC%8A%A4Instance-%EB%9C%BB-%EC%9D%98%EB%AF%B8-IT-%EC%9A%A9%EC%96%B4#entry43comment</comments>
      <pubDate>Tue, 18 Aug 2026 23:46:16 +0900</pubDate>
    </item>
    <item>
      <title>꾸준함은 모든것을 이긴다 20일차 260818(화)</title>
      <link>https://codingrecorder.tistory.com/entry/%EA%BE%B8%EC%A4%80%ED%95%A8%EC%9D%80-%EB%AA%A8%EB%93%A0%EA%B2%83%EC%9D%84-%EC%9D%B4%EA%B8%B4%EB%8B%A4-20%EC%9D%BC%EC%B0%A8-260818%ED%99%94</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;664&quot; data-origin-height=&quot;428&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bwdrjJ/dJMcabFgjzl/Tmw29wJrzAgDLok2xEIN01/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bwdrjJ/dJMcabFgjzl/Tmw29wJrzAgDLok2xEIN01/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bwdrjJ/dJMcabFgjzl/Tmw29wJrzAgDLok2xEIN01/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbwdrjJ%2FdJMcabFgjzl%2FTmw29wJrzAgDLok2xEIN01%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;664&quot; height=&quot;428&quot; data-origin-width=&quot;664&quot; data-origin-height=&quot;428&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1.&lt;a href=&quot;https://codingrecorder.tistory.com/entry/React-%EB%82%B4%EB%B6%80-%EC%9B%90%EB%A6%AC-%EA%B3%B5%EB%B6%80-02&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt; 리액트 내부 원리 짧 공부&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1787063773888&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;React 내부 원리 공부 02&quot; data-og-description=&quot;React는 직접 DOM을 조작하는 것이 아니라 (명령형: document.querySelector('#alert-badge').textContent = 4) Virtual DOM(가상 DOM)을 통해 '상태의 변화'를 감지하여 변화된 부분의 DOM만 변경한다. 기존의 명령형(event&quot; data-og-host=&quot;codingrecorder.tistory.com&quot; data-og-source-url=&quot;https://codingrecorder.tistory.com/entry/React-%EB%82%B4%EB%B6%80-%EC%9B%90%EB%A6%AC-%EA%B3%B5%EB%B6%80-02&quot; data-og-url=&quot;https://codingrecorder.tistory.com/entry/React-%EB%82%B4%EB%B6%80-%EC%9B%90%EB%A6%AC-%EA%B3%B5%EB%B6%80-02&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/IOVzA/dJMb8Rki21W/GEAZtNhWrhD7XjsoII7Ai1/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/csx0tf/dJMb8XkwqmN/wBVqVr1bVPscJqk3fyRiLK/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/gyMkl/dJMb8SXOOWf/xjExBKnPssVDwKRkjlPhi0/img.jpg?width=678&amp;amp;height=452&amp;amp;face=0_0_678_452&quot;&gt;&lt;a href=&quot;https://codingrecorder.tistory.com/entry/React-%EB%82%B4%EB%B6%80-%EC%9B%90%EB%A6%AC-%EA%B3%B5%EB%B6%80-02&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://codingrecorder.tistory.com/entry/React-%EB%82%B4%EB%B6%80-%EC%9B%90%EB%A6%AC-%EA%B3%B5%EB%B6%80-02&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/IOVzA/dJMb8Rki21W/GEAZtNhWrhD7XjsoII7Ai1/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/csx0tf/dJMb8XkwqmN/wBVqVr1bVPscJqk3fyRiLK/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/gyMkl/dJMb8SXOOWf/xjExBKnPssVDwKRkjlPhi0/img.jpg?width=678&amp;amp;height=452&amp;amp;face=0_0_678_452');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;React 내부 원리 공부 02&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;React는 직접 DOM을 조작하는 것이 아니라 (명령형: document.querySelector('#alert-badge').textContent = 4) Virtual DOM(가상 DOM)을 통해 '상태의 변화'를 감지하여 변화된 부분의 DOM만 변경한다. 기존의 명령형(event&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;codingrecorder.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>당신은 꾸준한가요?</category>
      <author>개발코딩기록</author>
      <guid isPermaLink="true">https://codingrecorder.tistory.com/42</guid>
      <comments>https://codingrecorder.tistory.com/entry/%EA%BE%B8%EC%A4%80%ED%95%A8%EC%9D%80-%EB%AA%A8%EB%93%A0%EA%B2%83%EC%9D%84-%EC%9D%B4%EA%B8%B4%EB%8B%A4-20%EC%9D%BC%EC%B0%A8-260818%ED%99%94#entry42comment</comments>
      <pubDate>Tue, 18 Aug 2026 23:36:16 +0900</pubDate>
    </item>
    <item>
      <title>React 내부 원리 공부 02</title>
      <link>https://codingrecorder.tistory.com/entry/React-%EB%82%B4%EB%B6%80-%EC%9B%90%EB%A6%AC-%EA%B3%B5%EB%B6%80-02</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;React는 직접 DOM을 조작하는 것이 아니라 (명령형: document.querySelector('#alert-badge').textContent = 4) Virtual DOM(가상 DOM)을 통해 '상태의 변화'를 감지하여 변화된 부분의 DOM만 변경한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기존의 명령형(event 발생마다 직접 UI 값을 변경해주는) 웹 개발 패러다임에서 선언형 웹 개발 패러다임으로 넘어오게 된 1등 공신이 React다. 명령형 패러다임에서의 문제는 상태가 바뀌는 경로가 늘어날 때마다 갱신해야하는 DOM 조작이 곱절로 증가한다. React(선언형) 패러다임은 이렇게 정의한다. UI = function(state). 상태가 이럴때는 화면이 이렇게 생겨야한다는 선언.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실제로&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;React가 하는일 2가지는?&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 컴포넌트를 실행해서 &quot;화면에 대한 선언, 설명서&quot;를 만든다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;lt;App /&amp;gt;, function App() { ... } 은 실행되었을 때 DOM을 직접 만들지 않는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;{ type: &quot;h1&quot;, props: { ... }, children: [ { type: &quot;p&quot;, props: { ... } } ] } 같은 평범한 JS 객체 Tree를 만든다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 재조정(Reconciliation) ~ 이전 설명서와 비교해서 바뀐것만 찾아서 DOM에 반영 (=diffing)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이게 React의 Core Value다.&amp;nbsp; 상태가 바뀌면 App()을 통째로 다시 실행하지만, DOM이 실제로 달라진 부분만 Re-Paint 하는 것. DOM 조작은 느리고, 비가역적이라 한번 변경되면 변경을 추적하기 어렵다. JS 객체 비교가 훨씬 빠르고 저렴하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(1) 선언서(.jsx)는 개발자가 만들지만 (2) 재조정은 React 라이브러리가 내부적으로 실행한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;canvas는 DOM의 Node다. canvas 자체가 변화하면 diff가 생긴다. React는 DOM Node 단위로 Diff를 찾는다. 하지만, Canvas의 내부는 Node(DOM)이 아닌 Bitmap이라 bitmap이 바뀐 것은 React가 감지하는 변화 대상이 아니기에 추적이 불가능하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;UI = f(state)에서 모순이 있다.&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;UI = f(state)에서 모순이 있다. function은 순수한 함수여야 한다. 하지만, 순수 함수는 정의상 메모리(기억하고 있는 것)이 없어야한다. 지역 변수를 함수를 실행시키고 모두 날려버려야 하는데, 실제로 UI에서는 '기억력'이 필요하다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;excalidraw-clone 하면서 봤던 코드에서는 &quot;지금 Drag하고 있는 도형이 무엇인지 기억해야하고&quot;, &quot;Canvas DOM Node도 붙잡고 있어야 한다&quot;. 순수함수인데 기억해야한다는 모순이 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;React는 이 문제에 대한 해법을 함수 밖에 기억할것을 따로 두는 형태로 해결한다. Fiber(Reconciliation Engine)에 '기억할 상자 배열'을 따로 들고 있음. 컴포넌트 함수는 여전히 순수하게 실행되지만 훅을 통해 '기억 상자 배열'을 훅을 통해 들여다볼 수 있음.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[리액트 렌더링] App() 실행 -&amp;gt; 선언 설명서 Tree Build -&amp;gt; Virtual DOM이 Diff(변화) 목록을 작성한다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[Commit] (1) DOM 삽입/삭제/수정 -&amp;gt; (2) ref에 실제 node 채워넣기 -&amp;gt; (3) useLayoutEffect() 실행&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[Browser Paint] 사용자 눈에 보이기 시작&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Browser Paint 이후에 useEffect가 실행&lt;/p&gt;</description>
      <category>Web/React 원리</category>
      <author>개발코딩기록</author>
      <guid isPermaLink="true">https://codingrecorder.tistory.com/41</guid>
      <comments>https://codingrecorder.tistory.com/entry/React-%EB%82%B4%EB%B6%80-%EC%9B%90%EB%A6%AC-%EA%B3%B5%EB%B6%80-02#entry41comment</comments>
      <pubDate>Tue, 18 Aug 2026 23:23:29 +0900</pubDate>
    </item>
    <item>
      <title>꾸준함은 모든것을 이긴다 19일차 260817(월)</title>
      <link>https://codingrecorder.tistory.com/entry/%EA%BE%B8%EC%A4%80%ED%95%A8%EC%9D%80-%EB%AA%A8%EB%93%A0%EA%B2%83%EC%9D%84-%EC%9D%B4%EA%B8%B4%EB%8B%A4-19%EC%9D%BC%EC%B0%A8-260817%EC%9B%94</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;348&quot; data-origin-height=&quot;240&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/5n8uG/dJMcaiYCAJC/KnWY1ae9KRJ2KHR14BSThk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/5n8uG/dJMcaiYCAJC/KnWY1ae9KRJ2KHR14BSThk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/5n8uG/dJMcaiYCAJC/KnWY1ae9KRJ2KHR14BSThk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F5n8uG%2FdJMcaiYCAJC%2FKnWY1ae9KRJ2KHR14BSThk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;348&quot; height=&quot;240&quot; data-origin-width=&quot;348&quot; data-origin-height=&quot;240&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사소한 한 걸음, 벽돌 하나 쌓는게 중요하다&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;천천히, 꾸준하게&lt;/p&gt;</description>
      <category>당신은 꾸준한가요?</category>
      <author>개발코딩기록</author>
      <guid isPermaLink="true">https://codingrecorder.tistory.com/40</guid>
      <comments>https://codingrecorder.tistory.com/entry/%EA%BE%B8%EC%A4%80%ED%95%A8%EC%9D%80-%EB%AA%A8%EB%93%A0%EA%B2%83%EC%9D%84-%EC%9D%B4%EA%B8%B4%EB%8B%A4-19%EC%9D%BC%EC%B0%A8-260817%EC%9B%94#entry40comment</comments>
      <pubDate>Mon, 17 Aug 2026 23:04:48 +0900</pubDate>
    </item>
    <item>
      <title>꾸준함은 모든것을 이긴다 18일차 260816(일)</title>
      <link>https://codingrecorder.tistory.com/entry/%EA%BE%B8%EC%A4%80%ED%95%A8%EC%9D%80-%EB%AA%A8%EB%93%A0%EA%B2%83%EC%9D%84-%EC%9D%B4%EA%B8%B4%EB%8B%A4-18%EC%9D%BC%EC%B0%A8-260816%EC%9D%BC</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;284&quot; data-origin-height=&quot;219&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/8tInT/dJMcahyLaSP/j5XDdOnJUCI0KTcYDVMKkk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/8tInT/dJMcahyLaSP/j5XDdOnJUCI0KTcYDVMKkk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/8tInT/dJMcahyLaSP/j5XDdOnJUCI0KTcYDVMKkk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F8tInT%2FdJMcahyLaSP%2Fj5XDdOnJUCI0KTcYDVMKkk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;284&quot; height=&quot;219&quot; data-origin-width=&quot;284&quot; data-origin-height=&quot;219&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사소한 한 걸음, 벽돌 하나 쌓는게 중요하다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;천천히, 꾸준하게&lt;/p&gt;</description>
      <category>당신은 꾸준한가요?</category>
      <author>개발코딩기록</author>
      <guid isPermaLink="true">https://codingrecorder.tistory.com/39</guid>
      <comments>https://codingrecorder.tistory.com/entry/%EA%BE%B8%EC%A4%80%ED%95%A8%EC%9D%80-%EB%AA%A8%EB%93%A0%EA%B2%83%EC%9D%84-%EC%9D%B4%EA%B8%B4%EB%8B%A4-18%EC%9D%BC%EC%B0%A8-260816%EC%9D%BC#entry39comment</comments>
      <pubDate>Mon, 17 Aug 2026 23:02:44 +0900</pubDate>
    </item>
    <item>
      <title>Main.java가 실행되기까지 필요한 과정 - JDK, javac, java, JVM</title>
      <link>https://codingrecorder.tistory.com/entry/Mainjava%EA%B0%80-%EC%8B%A4%ED%96%89%EB%90%98%EA%B8%B0%EA%B9%8C%EC%A7%80-%ED%95%84%EC%9A%94%ED%95%9C-%EA%B3%BC%EC%A0%95-JDK-javac-java-JVM</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;Main.java 파일을 생성해서 실행하기까지의 과정을 순서대로 따라가기 위해서 이해해야하는 개념&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Main.java(소스코드) -&amp;gt; javac -&amp;gt; Main.class(바이트코드) -&amp;gt; java -&amp;gt; JVM이 실행&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;javac: 컴파일러 (Java Compiler)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;.java 소스를 바이트코드(.class)로 컴파일하는 역할. 결과물이 기계어는 아님. 특정 CPU가 아닌, JVM이 읽을 수 있는 중간언어. 문법적 오류가 발생하면 컴파일이 실패하여 문법 오류를 잡을 수 있게 해줌.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JVM: 자바 가상 머신(Java Virtual Machine)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;바이트코드를 실제로 실행하는 가상의 컴퓨터. 바이트 코드를 그 컴퓨터의 기계어로 바꿔서 작동시키고, 메모리 관리 및 GC(Garbage Collector) 역할도 담당한다. JVM은&amp;nbsp; Window용 Mac용 Linux용이 각각 따로 있지만, 읽는 바이트코드 자체는 운영체제와 상관없이 모두 똑같다. 한 번 컴파일한 .class는 어디서든 다시 돌릴 수 있음. &quot;Write Once, Run Anywhere&quot;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Java: 실행 명령어&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JVM을 띄우고 지정한 클래스의 public static main 함수를 실행시키는 런처. java Main을 치면 JVM이 켜지고 바이트코드가 올라간다. JVM 자체가 아닌, JVM을 켜주는 역할.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JDK: 개발자용 전체 패키지 (Java Development Kit)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 javac, java, JVM에 표준 라이브러리와 각종 도구(jar, 디버거 등등)까지 묶은 꾸러미.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;맥에서 brew install openjdk로 설치했었음.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Java</category>
      <author>개발코딩기록</author>
      <guid isPermaLink="true">https://codingrecorder.tistory.com/38</guid>
      <comments>https://codingrecorder.tistory.com/entry/Mainjava%EA%B0%80-%EC%8B%A4%ED%96%89%EB%90%98%EA%B8%B0%EA%B9%8C%EC%A7%80-%ED%95%84%EC%9A%94%ED%95%9C-%EA%B3%BC%EC%A0%95-JDK-javac-java-JVM#entry38comment</comments>
      <pubDate>Mon, 17 Aug 2026 22:59:55 +0900</pubDate>
    </item>
  </channel>
</rss>