<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>A seeker after truth</title>
    <link>https://thewayaboutme.tistory.com/</link>
    <description>전공 공부 trace + tracing용 블로그. 저작권 문제가 되는 사진이 포함돼 있는 경우 글이  '보호'처리 되어 있습니다.</description>
    <language>ko</language>
    <pubDate>Thu, 7 May 2026 09:16:26 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>dr.meteor</managingEditor>
    <image>
      <title>A seeker after truth</title>
      <url>https://tistory1.daumcdn.net/tistory/3167469/attach/67c13f49de6a4cfe85f33f0f1fee0af7</url>
      <link>https://thewayaboutme.tistory.com</link>
    </image>
    <item>
      <title>PostgreSQL Index 생성 'CONCURRENTLY' 옵션, Auto Vacuum, 기타</title>
      <link>https://thewayaboutme.tistory.com/777</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. CREATE INDEX &lt;b&gt;CONCURRENTLY&lt;/b&gt; 에 대하여&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PostgreSQL에서 CONCURRENTLY 옵션은 인덱스를 생성하거나 제거할 때 &lt;b&gt;테이블에 대한 락(lock) 방식을 다르게 하는 옵션&lt;/b&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;1) 일반적인 인덱스 생성&lt;/h3&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;CREATE&lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt; INDEX idx_name &lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;ON&lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt; table_name(column_name);&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;351&quot; data-start=&quot;195&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;297&quot; data-start=&quot;195&quot;&gt;이 방식은 &lt;b&gt;테이블에 대한 공유 락(share lock)&lt;/b&gt;을 걸기 때문에, 인덱스를 생성하는 동안 테이블에 쓰기(INSERT/UPDATE/DELETE)가 잠깐 멈춘다&lt;/li&gt;
&lt;li data-end=&quot;351&quot; data-start=&quot;298&quot;&gt;큰 테이블에서는 시간이 오래 걸릴 수 있고, 서비스 중인 테이블이라면 문제가 될 수 있다&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-end=&quot;386&quot; data-start=&quot;358&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;2) CONCURRENTLY 옵션 사용&lt;/h3&gt;
&lt;div&gt;
&lt;div&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;CREATE&lt;/span&gt;&lt;/span&gt;&lt;span&gt; INDEX CONCURRENTLY idx_name &lt;/span&gt;&lt;span&gt;&lt;span&gt;ON&lt;/span&gt;&lt;/span&gt;&lt;span&gt; table_name(column_name); &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;702&quot; data-start=&quot;461&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;501&quot; data-start=&quot;461&quot;&gt;이 방식은 테이블을 락하지 않고도 인덱스를 생성할 수 있다 (인덱스를 생성하는 동안에도 SELECT, INSERT, UPDATE, DELETE 모두 가능)&lt;/li&gt;
&lt;li data-end=&quot;702&quot; data-start=&quot;567&quot;&gt;단점
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;702&quot; data-start=&quot;575&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;607&quot; data-start=&quot;575&quot;&gt;일반 인덱스 생성보다 시간이 더 오래 걸릴 수 있음&lt;/li&gt;
&lt;li data-end=&quot;702&quot; data-start=&quot;610&quot;&gt;만약 생성 도중 실패하면, &lt;b&gt;부분적으로 만들어진 인덱스가 남아 있는 경우가 있다.&lt;/b&gt; 이때는 DROP INDEX CONCURRENTLY로 제거해야 한다&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-end=&quot;722&quot; data-start=&quot;709&quot; data-ke-size=&quot;size23&quot;&gt;3)&amp;nbsp; 주의할 점&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;896&quot; data-start=&quot;723&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;877&quot; data-start=&quot;723&quot;&gt;CONCURRENTLY를 쓰면 트랜잭션 안에서 사용할 수 없다.&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;`BEGIN&lt;/span&gt;&lt;/span&gt;&lt;span&gt;; &lt;/span&gt;&lt;span&gt;&lt;span&gt;CREATE&lt;/span&gt;&lt;/span&gt;&lt;span&gt; INDEX CONCURRENTLY idx_name &lt;/span&gt;&lt;span&gt;&lt;span&gt;ON&lt;/span&gt;&lt;/span&gt;&lt;span&gt; table_name(column_name); &lt;/span&gt;&lt;span&gt;&lt;span&gt;--&amp;nbsp; 오류&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;COMMIT&lt;/span&gt;&lt;/span&gt;&lt;span&gt;;`&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li data-end=&quot;896&quot; data-start=&quot;878&quot;&gt;그래서 단독으로 실행해야 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr class=&quot;custom-cursor-on-hover&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2. Auto Vacuum이 동작하는 이유, 그리고 빅데이터 적재 시 이의 동작 시간이 늘어나는 이유&lt;/h2&gt;
&lt;h3 data-end=&quot;178&quot; data-start=&quot;152&quot; data-ke-size=&quot;size23&quot;&gt;1) Auto Vacuum이 필요한 이유&lt;/h3&gt;
&lt;p data-end=&quot;227&quot; data-start=&quot;179&quot; data-ke-size=&quot;size16&quot;&gt;PostgreSQL은 &lt;b&gt;레코드를 지우지 않고, 버전을 관리&lt;/b&gt;하는 구조를 쓴다 (MVCC(Multi-Version Concurrency Control) 기반 DB니까)&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;355&quot; data-start=&quot;228&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;284&quot; data-start=&quot;228&quot;&gt;UPDATE &amp;rarr; 기존 튜플을 &quot;dead tuple(죽은 행)&quot;으로 표시하고 새 튜플을 생성&lt;/li&gt;
&lt;li data-end=&quot;329&quot; data-start=&quot;285&quot;&gt;DELETE &amp;rarr; 튜플은 그대로 남아 있지만 &quot;dead&quot; 상태로만 표시&lt;/li&gt;
&lt;li data-end=&quot;355&quot; data-start=&quot;330&quot;&gt;즉, 물리적으로는 공간이 줄어들지 않음&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;375&quot; data-start=&quot;357&quot; data-ke-size=&quot;size16&quot;&gt;이 dead tuple이 쌓이면:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;498&quot; data-start=&quot;376&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;415&quot; data-start=&quot;376&quot;&gt;&lt;b&gt;디스크 공간 낭비&lt;/b&gt; &amp;rarr; 테이블이 실제 데이터보다 훨씬 커짐&lt;/li&gt;
&lt;li data-end=&quot;458&quot; data-start=&quot;416&quot;&gt;&lt;b&gt;쿼리 성능 저하&lt;/b&gt; &amp;rarr; 스캔 시 dead tuple까지 읽어야 함&lt;/li&gt;
&lt;li data-end=&quot;498&quot; data-start=&quot;459&quot;&gt;&lt;b&gt;통계 부정확&lt;/b&gt; &amp;rarr; 옵티마이저가 잘못된 실행 계획 선택 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;524&quot; data-start=&quot;500&quot; data-ke-size=&quot;size16&quot;&gt;그래서 autovacuum이 돌면서,&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;631&quot; data-start=&quot;525&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;550&quot; data-start=&quot;525&quot;&gt;dead tuple 정리 (공간 회수)&lt;/li&gt;
&lt;li data-end=&quot;577&quot; data-start=&quot;551&quot;&gt;ANALYZE 실행 (통계 업데이트)&lt;/li&gt;
&lt;li data-end=&quot;631&quot; data-start=&quot;578&quot;&gt;transaction wraparound 방지 (옛 트랜잭션 ID가 오버플로 되지 않게)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-end=&quot;670&quot; data-start=&quot;638&quot; data-ke-size=&quot;size23&quot;&gt;2) 대량 데이터가 많아질수록 시간이 늘어나는 이유&lt;/h3&gt;
&lt;p data-end=&quot;752&quot; data-start=&quot;671&quot; data-ke-size=&quot;size16&quot;&gt;autovacuum의 작업량은 단순히 &quot;변경된 행 개수&quot;에 비례하지 않고, &lt;b&gt;테이블 크기 전체와 dead tuple 분포&lt;/b&gt;에도 영향을 받는다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-end=&quot;1237&quot; data-start=&quot;754&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li data-end=&quot;859&quot; data-start=&quot;754&quot;&gt;&lt;b&gt;스캔 범위 증가&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;859&quot; data-start=&quot;775&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;822&quot; data-start=&quot;775&quot;&gt;autovacuum은 dead tuple을 찾으려고 테이블 페이지를 훑어야 함&lt;/li&gt;
&lt;li data-end=&quot;859&quot; data-start=&quot;826&quot;&gt;테이블이 커질수록 I/O 비용이 기하급수적으로 늘어남&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;966&quot; data-start=&quot;861&quot;&gt;&lt;b&gt;인덱스 정리 비용&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;966&quot; data-start=&quot;883&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;924&quot; data-start=&quot;883&quot;&gt;dead tuple이 삭제되면 인덱스에서도 해당 엔트리를 지워야 함&lt;/li&gt;
&lt;li data-end=&quot;966&quot; data-start=&quot;928&quot;&gt;인덱스 크기도 데이터에 비례해서 커지므로, 정리 시간이 길어짐&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;1030&quot; data-start=&quot;968&quot;&gt;&lt;b&gt;ANALYZE 비용&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1030&quot; data-start=&quot;991&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1030&quot; data-start=&quot;991&quot;&gt;통계를 샘플링하려 해도 테이블이 크면 I/O 자체가 더 많이 듦&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;1150&quot; data-start=&quot;1032&quot;&gt;&lt;b&gt;병렬성 제한&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1150&quot; data-start=&quot;1051&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1150&quot; data-start=&quot;1051&quot;&gt;autovacuum은 기본적으로 백그라운드에서 여러 워커(worker)가 돌아가지만, 전체 DB의 리소스를 무한히 쓰지는 않음 &amp;rarr; 큰 테이블이면 한 워커가 오래 잡고 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;1237&quot; data-start=&quot;1152&quot;&gt;&lt;b&gt;Cache 효과 감소&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1237&quot; data-start=&quot;1176&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1237&quot; data-start=&quot;1176&quot;&gt;작은 테이블은 메모리에 다 올라오지만, 대규모 테이블은 디스크 I/O를 계속 발생시킴 &amp;rarr; 시간이 늘어남&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-end=&quot;1253&quot; data-start=&quot;1244&quot; data-ke-size=&quot;size23&quot;&gt;3) 요약&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1394&quot; data-start=&quot;1254&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1288&quot; data-start=&quot;1254&quot;&gt;&lt;b&gt;autovacuum은 MVCC 구조 때문에 필수&lt;/b&gt;&lt;/li&gt;
&lt;li data-end=&quot;1394&quot; data-start=&quot;1289&quot;&gt;&lt;b&gt;데이터가 커질수록&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1394&quot; data-start=&quot;1310&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1333&quot; data-start=&quot;1310&quot;&gt;스캔해야 하는 페이지 수가 많아지고&lt;/li&gt;
&lt;li data-end=&quot;1371&quot; data-start=&quot;1336&quot;&gt;dead tuple 정리 및 인덱스 재정리 비용이 커져서&lt;/li&gt;
&lt;li data-end=&quot;1394&quot; data-start=&quot;1374&quot;&gt;시간이 오래 걸릴 수밖에 없음&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4) 나는 insert 쿼리만 쓰던 상황인데, 왜 auto vacuum이 오래 돌았을까?&lt;/h3&gt;
&lt;h4 data-end=&quot;559&quot; data-start=&quot;522&quot; data-ke-size=&quot;size20&quot;&gt;(1) autovacuum (ANALYZE)의 실행&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;774&quot; data-start=&quot;560&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;634&quot; data-start=&quot;560&quot;&gt;INSERT로 새로운 행이 많이 추가되면, PostgreSQL은 통계가 낡았다고 판단하고 ANALYZE를 자동 실행함&lt;/li&gt;
&lt;li data-end=&quot;738&quot; data-start=&quot;635&quot;&gt;autovacuum_analyze_scale_factor 기본값이 0.1 (10%)이라,&amp;nbsp;행 수가 1천만이라면 백만 건 추가될 때마다 ANALYZE가 돌음&lt;/li&gt;
&lt;li data-end=&quot;774&quot; data-start=&quot;739&quot;&gt;대용량 테이블일수록 샘플링 비용이 커져서 시간이 오래 걸림&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;848&quot; data-start=&quot;776&quot; data-ke-size=&quot;size16&quot;&gt;즉, UPDATE/DELETE가 없어도 &quot;INSERT가 많으면&quot; ANALYZE 때문에 autovacuum이 계속 돈다.&lt;/p&gt;
&lt;h4 data-end=&quot;886&quot; data-start=&quot;855&quot; data-ke-size=&quot;size20&quot;&gt;(2) 인덱스 팽창 (Index bloat)&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1003&quot; data-start=&quot;887&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;915&quot; data-start=&quot;887&quot;&gt;INSERT가 계속되면 인덱스도 계속 커짐.&lt;/li&gt;
&lt;li data-end=&quot;967&quot; data-start=&quot;916&quot;&gt;페이지 분할(splitting)이 반복되며 인덱스 구조가 비효율적으로 커질 수 있음.&lt;/li&gt;
&lt;li data-end=&quot;1003&quot; data-start=&quot;968&quot;&gt;autovacuum이 이 인덱스를 스캔하느라 시간이 늘어남.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;1089&quot; data-start=&quot;1005&quot; data-ke-size=&quot;size16&quot;&gt;특히 대량 INSERT &amp;rarr; autovacuum (analyze) 시 인덱스 페이지도 같이 스캔하게 되므로 시간이 점점 길어지는 현상 발생 가능.&lt;/p&gt;
&lt;h4 data-end=&quot;1119&quot; data-start=&quot;1096&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;(3) TOAST 테이블 증가&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1226&quot; data-start=&quot;1120&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1170&quot; data-start=&quot;1120&quot;&gt;&lt;b&gt;큰 텍스트나 JSON 같은 컬럼을 많이 INSERT하면 TOAST 테이블도 같이 커짐.&lt;/b&gt;&lt;/li&gt;
&lt;li data-end=&quot;1226&quot; data-start=&quot;1171&quot;&gt;&lt;b&gt;autovacuum은 메인 테이블 외에도 TOAST 테이블도 같이 관리함 &amp;rarr; 부하 증가.&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-end=&quot;1281&quot; data-start=&quot;1233&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;(4) Dead tuple이 없더라도 visibility map 스캔 비용&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1420&quot; data-start=&quot;1282&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1370&quot; data-start=&quot;1282&quot;&gt;VACUUM이 dead tuple을 정리하지 않더라도, &quot;페이지에 dead tuple이 있는지&quot; 확인하기 위해 visibility map을 스캔함.&lt;/li&gt;
&lt;li data-end=&quot;1420&quot; data-start=&quot;1371&quot;&gt;테이블 크기가 커지면, 이 확인 작업 자체가 느려짐. (즉, I/O 기반 비용 증가)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;5) TOAST 테이블이란?&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;TOAST(Table Of Attributes Stored Externally)는 테이블의 너무 큰 컬럼 데이터를 본 테이블 바깥에 따로 저장하는 내부 메커니즘&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-end=&quot;231&quot; data-start=&quot;207&quot; data-ke-size=&quot;size20&quot;&gt;(1) 왜 TOAST가 필요한가?&lt;/h4&gt;
&lt;p data-end=&quot;314&quot; data-start=&quot;233&quot; data-ke-size=&quot;size16&quot;&gt;PostgreSQL의 한 행(row)은 기본적으로 한 페이지(8KB) 안에 저장돼. 그런데 만약 하나의 컬럼이 너무 크면 어떻게 될까?&lt;/p&gt;
&lt;p data-end=&quot;324&quot; data-start=&quot;316&quot; data-ke-size=&quot;size16&quot;&gt;예를 들어&lt;/p&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1759921700977&quot; class=&quot;sql custom-cursor-default-hover&quot; data-ke-language=&quot;sql&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;CREATE TABLE files ( id serial primary key, filename text, content bytea );&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p data-end=&quot;475&quot; data-start=&quot;418&quot; data-ke-size=&quot;size16&quot;&gt;여기서 content가 20MB짜리 바이너리 데이터라면, 이걸 한 행 안에 다 넣을 수 없겠지?&amp;nbsp;그래서 PostgreSQL은 이 큰 데이터를 &lt;b&gt;자동으로 &lt;/b&gt;잘라서 다른 테이블에 따로 저장해버려. 이때 만들어지는 게 바로 TOAST 테이블이야.&lt;/p&gt;
&lt;h4 data-end=&quot;599&quot; data-start=&quot;576&quot; data-ke-size=&quot;size20&quot;&gt;(2) TOAST 테이블의 구조&lt;/h4&gt;
&lt;p data-end=&quot;697&quot; data-start=&quot;601&quot; data-ke-size=&quot;size16&quot;&gt;PostgreSQL은 테이블 생성 시, 만약 &amp;ldquo;큰 컬럼이 들어올 가능성이 있다면&amp;rdquo;,&lt;br /&gt;자동으로 _toast_&amp;lt;oid&amp;gt; 형태의 &lt;b&gt;숨겨진 보조 테이블&lt;/b&gt;을 같이 만든다.&lt;/p&gt;
&lt;p data-end=&quot;704&quot; data-start=&quot;699&quot; data-ke-size=&quot;size16&quot;&gt;예시:&lt;/p&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;pre id=&quot;code_1759921789832&quot; class=&quot;sql custom-cursor-default-hover&quot; data-ke-language=&quot;sql&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;SELECT relname, reltoastrelid::regclass FROM pg_class WHERE relname = 'files';&lt;/code&gt;&lt;/pre&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;564&quot; data-origin-height=&quot;162&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bBMnRH/btsQ5zprx1l/SQteixR50bKsdO8YpTcF2K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bBMnRH/btsQ5zprx1l/SQteixR50bKsdO8YpTcF2K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bBMnRH/btsQ5zprx1l/SQteixR50bKsdO8YpTcF2K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbBMnRH%2FbtsQ5zprx1l%2FSQteixR50bKsdO8YpTcF2K%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;359&quot; height=&quot;103&quot; data-origin-width=&quot;564&quot; data-origin-height=&quot;162&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1000&quot; data-start=&quot;907&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;937&quot; data-start=&quot;907&quot;&gt;files 테이블에는 작은 메타 정보만 남고&lt;/li&gt;
&lt;li data-end=&quot;1000&quot; data-start=&quot;938&quot;&gt;실제 큰 내용(content)은 pg_toast.pg_toast_12345 테이블에 저장돼 있음.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-end=&quot;1029&quot; data-start=&quot;1007&quot; data-ke-size=&quot;size20&quot;&gt;3) TOAST의 작동 방식&lt;/h4&gt;
&lt;p data-end=&quot;1074&quot; data-start=&quot;1031&quot; data-ke-size=&quot;size16&quot;&gt;PostgreSQL은 큰 컬럼을 저장할 때 자동으로 3단계 압축 과정을 거쳐:&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-end=&quot;1227&quot; data-start=&quot;1075&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li data-end=&quot;1108&quot; data-start=&quot;1075&quot;&gt;Compress &amp;rarr; 먼저 zlib으로 압축 시도&lt;/li&gt;
&lt;li data-end=&quot;1180&quot; data-start=&quot;1109&quot;&gt;Out-of-line storage &amp;rarr; 그래도 크면 chunk 단위(기본 2KB)로 잘라서 TOAST 테이블에 저장&lt;/li&gt;
&lt;li data-end=&quot;1227&quot; data-start=&quot;1181&quot;&gt;In-line fallback &amp;rarr; 크기가 작으면 그냥 본 테이블에 저장&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-end=&quot;1252&quot; data-start=&quot;1229&quot; data-ke-size=&quot;size16&quot;&gt;즉, 실제 본 테이블에는 다음처럼 저장됨&lt;/p&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1759921844746&quot; class=&quot;sql custom-cursor-default-hover&quot; data-ke-language=&quot;sql&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;main_table.row &amp;rarr; {toast_pointer} -- 실제 데이터는 다른 테이블(pg_toast)에 있음&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h4 data-end=&quot;1364&quot; data-start=&quot;1333&quot; data-ke-size=&quot;size20&quot;&gt;(4) autovacuum과 TOAST의 관계&lt;/h4&gt;
&lt;p data-end=&quot;1458&quot; data-start=&quot;1366&quot; data-ke-size=&quot;size16&quot;&gt;이게 핵심이야. PostgreSQL의 autovacuum은 메인 테이블만 관리하지 않아. 그 테이블에 딸린 TOAST 테이블도 같이 관리해. 즉,&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1564&quot; data-start=&quot;1465&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1523&quot; data-start=&quot;1465&quot;&gt;INSERT/UPDATE/DELETE가 많으면 &amp;rarr; main + toast 둘 다 vacuum 대상&lt;/li&gt;
&lt;li data-end=&quot;1564&quot; data-start=&quot;1524&quot;&gt;TOAST 테이블이 커질수록 &amp;rarr; autovacuum 시간이 늘어남&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;1685&quot; data-start=&quot;1566&quot; data-ke-size=&quot;size16&quot;&gt;특히 큰 TEXT, JSONB, BYTEA 컬럼이 자주 바뀌거나 계속 추가되는 환경이면, TOAST 테이블에 dead tuple이 쌓이고, 이걸 정리하느라 autovacuum이 점점 오래 걸릴 수 있어.&lt;/p&gt;
&lt;h4 data-end=&quot;1718&quot; data-start=&quot;1692&quot; data-ke-size=&quot;size20&quot;&gt;(5) TOAST 관련 성능 관리 팁&lt;/h4&gt;
&lt;div&gt;상황 조치
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 82px;&quot; border=&quot;1&quot; data-end=&quot;2021&quot; data-start=&quot;1720&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody data-end=&quot;2021&quot; data-start=&quot;1748&quot;&gt;
&lt;tr style=&quot;height: 18px;&quot; data-end=&quot;1806&quot; data-start=&quot;1748&quot;&gt;
&lt;td style=&quot;height: 18px;&quot; data-col-size=&quot;sm&quot; data-end=&quot;1770&quot; data-start=&quot;1748&quot;&gt;큰 텍스트/바이너리 컬럼 자주 삽입&lt;/td&gt;
&lt;td style=&quot;height: 18px;&quot; data-col-size=&quot;md&quot; data-end=&quot;1806&quot; data-start=&quot;1770&quot;&gt;TOAST 테이블도 같이 autovacuum 관리 필요&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 18px;&quot; data-end=&quot;1867&quot; data-start=&quot;1807&quot;&gt;
&lt;td style=&quot;height: 18px;&quot; data-col-size=&quot;sm&quot; data-end=&quot;1829&quot; data-start=&quot;1807&quot;&gt;UPDATE로 큰 데이터 교체 잦음&lt;/td&gt;
&lt;td style=&quot;height: 18px;&quot; data-col-size=&quot;md&quot; data-end=&quot;1867&quot; data-start=&quot;1829&quot;&gt;dead tuple 폭증 &amp;rarr; 수동 VACUUM 주기적 실행&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 18px;&quot; data-end=&quot;1953&quot; data-start=&quot;1868&quot;&gt;
&lt;td style=&quot;height: 18px;&quot; data-col-size=&quot;sm&quot; data-end=&quot;1888&quot; data-start=&quot;1868&quot;&gt;대용량 JSONB/TEXT 많음&lt;/td&gt;
&lt;td style=&quot;height: 18px;&quot; data-col-size=&quot;md&quot; data-end=&quot;1953&quot; data-start=&quot;1888&quot;&gt;ALTER TABLE ... SET STORAGE EXTERNAL or MAIN 등으로 정책 조정 가능&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 18px;&quot; data-end=&quot;2021&quot; data-start=&quot;1954&quot;&gt;
&lt;td style=&quot;height: 18px;&quot; data-col-size=&quot;sm&quot; data-end=&quot;1961&quot; data-start=&quot;1954&quot;&gt;모니터링&lt;/td&gt;
&lt;td style=&quot;height: 18px;&quot; data-col-size=&quot;md&quot; data-end=&quot;2021&quot; data-start=&quot;1961&quot;&gt;pg_class.reltoastrelid 로 어떤 테이블이 TOAST 테이블을 가지는지 확인 가능&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p data-end=&quot;2026&quot; data-start=&quot;2023&quot; data-ke-size=&quot;size16&quot;&gt;예시:&lt;/p&gt;
&lt;p data-end=&quot;2026&quot; data-start=&quot;2023&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;-- TOAST 테이블 이름 확인&lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt; relname &lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;AS&lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt; table_name, reltoastrelid::regclass &lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;AS&lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt; toast_table &lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;FROM&lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt; pg_class &lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;WHERE&lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt; reltoastrelid &lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;!=&lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;; &lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;-- TOAST 테이블의 dead tuple 수 확인&lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt; relname, n_dead_tup &lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;FROM&lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt; pg_stat_user_tables &lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;WHERE&lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt; relname &lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;LIKE&lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;'pg_toast%'&lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;;&lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;2026&quot; data-start=&quot;2023&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;2026&quot; data-start=&quot;2023&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;2026&quot; data-start=&quot;2023&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;.... 그럼 auto vacuum을 수동 실행하는 옵션으로 삽입만 계속 하면, 삽입이 느려질 가능성은 더이상 없는 건가 정말?&lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;2026&quot; data-start=&quot;2023&quot; 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;h2 data-ke-size=&quot;size26&quot;&gt;3. 기타 자잘한 것&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1) 2025-09-26 11:23:23 =&amp;gt; 이런 식으로 돼있는 데이터는 타입을 timestamp without time zone(단순히 날짜와 시간만 저장. 타임존 정보 없음) 또는 timestamptz(UTC 기준으로 내부 저장 후, 세션 타임존에 맞춰 변환해서 보여줌)로 저장한다.&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) 위와 같은 값을 삽입할 땐 INSERT INTO example (created_at) VALUES ('2025-09-26 11:23:23'); 같은 식으로 작은 따옴표로 감싸서 넣으면 된다.&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) INSERT INTO my_table (&quot;name&quot;) VALUES (hello); =&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;&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;&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;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Computer Science/Database</category>
      <author>dr.meteor</author>
      <guid isPermaLink="true">https://thewayaboutme.tistory.com/777</guid>
      <comments>https://thewayaboutme.tistory.com/777#entry777comment</comments>
      <pubDate>Wed, 8 Oct 2025 20:11:55 +0900</pubDate>
    </item>
    <item>
      <title>네트워크, DB 업무 용어1</title>
      <link>https://thewayaboutme.tistory.com/776</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;- 공인 IP: 인터넷 이용자로서 발급받은 공유기 IP. 한국인터넷진흥원에서 관리함.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 사설IP: 해당 공유기를 통한 네트워크를 사용하는 기기들이 가진 IP. 내 컴퓨터 IP, 엔진엑스 IP, 로컬호스트 IP 등등이 이에 해당.&lt;br /&gt;&lt;a href=&quot;https://inpa.tistory.com/entry/WEB-%F0%9F%8C%90-IP-%EA%B8%B0%EC%B4%88-%EC%82%AC%EC%84%A4IP-%EA%B3%B5%EC%9D%B8IP-NAT-%EA%B0%9C%EB%85%90-%EC%A0%95%EB%A7%90-%EC%89%BD%EA%B2%8C-%EC%A0%95%EB%A6%AC#%EA%B3%B5%EC%9D%B8_ip&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://inpa.tistory.com/entry/WEB-%F0%9F%8C%90-IP-%EA%B8%B0%EC%B4%88-%EC%82%AC%EC%84%A4IP-%EA%B3%B5%EC%9D%B8IP-NAT-%EA%B0%9C%EB%85%90-%EC%A0%95%EB%A7%90-%EC%89%BD%EA%B2%8C-%EC%A0%95%EB%A6%AC#%EA%B3%B5%EC%9D%B8_ip&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 터널링: 한 네트워크에서 다른 네트워크로 ... &lt;span style=&quot;background-color: #ffffff; color: #001d35; text-align: start;&quot;&gt;다른 프로토콜이나 물리적 장벽을 '터널'처럼 가로지르도록 데이터를 캡슐화하여, 마치 중간에 장애물이 없는 것처럼 통과시키는 기술 및 현상.&amp;nbsp; VPN, SSH, DNS 가 대표적.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- DB 클라이언트: 테이블플러스, dbeaver, 데이터그립 같은&amp;nbsp; 접속 GUI 프로그램&lt;/p&gt;</description>
      <category>Computer Science/컴퓨터 네트워크</category>
      <author>dr.meteor</author>
      <guid isPermaLink="true">https://thewayaboutme.tistory.com/776</guid>
      <comments>https://thewayaboutme.tistory.com/776#entry776comment</comments>
      <pubDate>Sun, 7 Sep 2025 23:41:24 +0900</pubDate>
    </item>
    <item>
      <title>Discord Stage 채널의 기술 아키텍처와 통신 기반 분석</title>
      <link>https://thewayaboutme.tistory.com/774</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Discord의 Stage 채널은 기존 음성 채팅 채널을 확장한 일종의 실시간 음성 방송 플랫폼입니다. 청중과 발표자를 분리하고, 요청 기반의 발언 시스템을 도입하여 공개 토론, 세미나, 팟캐스트 등 다양한 용도에 활용되고 있습니다. 하지만 90명 이상 참여하는 대규모 채널에서는 발표자의 음성이 중간에 끊기거나, 심각한 오디오 왜곡(잡음) 현상이 발생하는 등의 문제가 종종 보고되고 있습니다. 이 글에서는 Stage 채널의 통신 방식, 트래픽 처리 구조, 소프트웨어 아키텍처 및 사용자 경험에서 관찰된 주요 기술적 문제에 대해 다루겠습니다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;통신 방식: WebRTC + SFU 기반의 일방향 최적화 모델&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Stage 채널은 음성 데이터 전송을 위해 WebRTC 기술을 채택하고 있습니다. 이는 기본적으로 브라우저 간 실시간 음성/영상 전송을 위한 오픈소스 기술로, 낮은 지연을 보장하며 UDP를 기반으로 빠른 전송을 제공합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Stage 채널의 경우, 발표자에서 청중으로 향하는 단방향 음성 스트리밍이 핵심이므로, Peer-to-Peer 연결이 아닌 &lt;/span&gt;&lt;span&gt;&lt;b&gt;SFU(Selective Forwarding Unit)&lt;/b&gt;&lt;/span&gt;&lt;span&gt; 방식을 사용합니다. SFU는 각 발표자의 오디오 스트림을 받아 다수의 청중에게 중계하는 역할을 하며, 이를 통해 서버는 전송 병목을 줄이고 보다 효율적인 스트리밍을 지원합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;이와 같은 구조는 발표자 수보다 청중 수가 많을 때 유리하며, 각 클라이언트가 SFU로부터 스트림만 수신하므로 클라이언트 리소스 소비도 적습니다. 그러나 이 구조는 오디오 품질 저하 시 문제 원인을 정확히 추적하기 어렵다는 단점도 내포하고 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;트래픽 처리 및 분산 구조&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Stage 채널은 Discord의 글로벌 인프라 내에서 동작합니다. Discord는 지역 기반으로 배치된 음성 서버(Voice Regions)와, 전 세계에 분산된 백엔드 인프라를 활용하여 사용자의 접속 위치에 따라 최적의 서버를 연결해줍니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;이러한 구조는 일반적인 대화형 음성 채널에서는 잘 작동하지만, Stage 채널처럼 수십 명 이상의 청중이 동시에 접속할 경우 다음과 같은 트래픽 처리 이슈가 발생할 수 있습니다:&lt;/span&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-spread=&quot;true&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;SFU의 부하 집중&lt;/b&gt;&lt;/span&gt;&lt;span&gt;: 하나의 발표자의 오디오 스트림이 수십 또는 수백 명에게 중계되는 경우, 특정 SFU 노드에 부하가 집중됩니다. 부하 분산이 적절히 되지 않으면 스트림 지연이나 끊김 현상이 발생할 수 있습니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;패킷 손실과 Jitter&lt;/b&gt;&lt;/span&gt;&lt;span&gt;: UDP 기반 통신 특성상 네트워크 환경이 불안정한 사용자에게서 패킷 손실이 빈번하게 발생할 수 있으며, 이를 보정하기 위한 Jitter Buffer가 제 역할을 못하면 잡음, 끊김 등으로 이어집니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;브라우저/앱 환경 다양성&lt;/b&gt;&lt;/span&gt;&lt;span&gt;: 청중 중 일부는 브라우저로, 일부는 모바일 앱으로 접속하게 되는데, 서로 다른 환경에서 WebRTC 구현 방식이 달라져 호환성 문제로 음성 깨짐이나 싱크 밀림 현상이 일어날 수 있습니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;소프트웨어 아키텍처: 이벤트 기반 비동기 모델&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Discord는 클라이언트-서버 구조의 이벤트 기반 아키텍처를 사용합니다. 클라이언트의 모든 요청(예: 발언 요청, 발표자 전환, 음소거 처리 등)은 비동기 메시지로 서버에 전달되며, 서버는 이 이벤트를 구독 중인 참여자에게 브로드캐스트합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Stage 채널은 사용자 상태를 &quot;청중 &amp;rarr; 발언 요청 중 &amp;rarr; 발표자&quot; 등의 상태로 전이시키는 상태 머신 구조를 따릅니다. 이 구조는 이벤트 전파에 의존하기 때문에 네트워크 지연이나 서버 처리 병목이 있으면 발표자 전환이 지연되거나, 청중에게 잘못된 상태가 전달될 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;사용자 경험 기반 주요 이슈 및 기술적 원인&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Stage 채널을 실제로 운영하면서 가장 빈번히 경험되는 문제는 다음과 같습니다:&lt;/span&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-spread=&quot;true&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;발표자 음성이 중간에 끊기거나 무음 처리됨&lt;/b&gt;&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;SFU 노드의 부하로 인해 오디오 프레임이 유실되거나, 클라이언트의 Jitter Buffer가 정상 작동하지 않아 발생합니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;발표자 디바이스에서의 CPU 과부하나 Discord 앱의 비정상적인 WebRTC 세션 재시도 로직이 원인이 되기도 합니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;발표자 음성이 로봇 소리/기계음으로 들림&lt;/b&gt;&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;패킷 손실 보정을 위한 오디오 코덱(예: Opus)의 오류 복원 기능이 과도하게 작동할 경우, 음성 왜곡이 발생합니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;네트워크 품질이 낮은 상태에서 SFU가 재전송을 시도하지 못하거나, 오디오 재구성이 불완전할 경우에도 유사한 증상이 발생합니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;발언 요청/전환 지연&lt;/b&gt;&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;이벤트 기반 아키텍처에서 메시지 전파가 지연되거나, 발표자 상태 변경 이벤트가 일부 청중에게만 반영될 경우 발생합니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;일부 클라이언트의 Discord 앱 또는 브라우저에서 WebSocket 연결이 일시적으로 끊긴 후 재연결되는 경우, 상태 불일치가 발생할 수 있습니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;전체적인 지연 증가 (Latency Drift)&lt;/b&gt;&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;장시간 연결 시 클라이언트와 서버 간의 지연이 누적되며, 실시간성과 동기화 문제가 발생합니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;특히 모바일 네트워크나 Wi-Fi 환경에서 네트워크 핸드오버가 발생하면 이런 문제가 심해집니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;결론&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Discord Stage 채널은 실시간 음성 방송 플랫폼으로서 WebRTC와 SFU를 활용해 다수 청중에게 고품질 음성을 전달하는 구조로 설계되었습니다. 하지만 대규모 사용자 수, 네트워크 환경의 다양성, WebRTC의 구현 복잡성 등으로 인해 실제 사용에서는 다양한 품질 저하 현상이 보고되고 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;특히 90명 이상이 참여하는 상황에서는 발표자의 음성이 끊기거나 변형되는 등 기술적 한계가 분명히 드러나며, 이는 서버 부하, 네트워크 상태, 클라이언트 환경 등 여러 복합 요소에 기인합니다. 향후 이러한 문제를 해결하기 위해서는 더욱 정교한 트래픽 분산, 클라이언트 네트워크 적응 알고리즘 개선, 상태 동기화 메커니즘의 안정화가 필요합니다.&lt;/span&gt;&lt;/p&gt;</description>
      <category>Computer Science/호기심 해결</category>
      <author>dr.meteor</author>
      <guid isPermaLink="true">https://thewayaboutme.tistory.com/774</guid>
      <comments>https://thewayaboutme.tistory.com/774#entry774comment</comments>
      <pubDate>Mon, 16 Jun 2025 22:18:53 +0900</pubDate>
    </item>
    <item>
      <title>게임 개발은 유니티 하나로 끝? 게임 개발의 기술 스택과 구조 이해하기 (feat.MMORPG, 퍼즐)</title>
      <link>https://thewayaboutme.tistory.com/773</link>
      <description>&lt;p&gt;저는 웹, 앱, 데이터 분야 개발에는 익숙하지만, 게임 개발은 유니티와 언리얼만 알 뿐 구조나 기술 스택은 생소하여 이 글을 쓰게 되었습니다. 간단하게 공부해본 결과, 게임은 클라이언트-서버 아키텍처는 물론 실시간 통신, 인프라, 운영 툴까지 웹/앱 이상으로 복잡한 구조를 갖추고 있었습니다. 이 글에서는 게임 개발의 전체적인 아키텍처와 사용 기술, 엔진의 역할까지 정리했습니다.&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;/p&gt;
&lt;h3&gt;  게임 개발의 전체 구조&lt;/h3&gt;
&lt;p&gt;게임 개발도 웹 서비스처럼 &lt;strong&gt;기획 → 개발 → 테스트 → 출시 → 운영&lt;/strong&gt;이라는 사이클을 따릅니다. 하지만 내부 구조와 요구되는 기술은 꽤 다릅니다.&lt;br&gt;게임은 무엇보다 &lt;strong&gt;실시간성&lt;/strong&gt;과 &lt;strong&gt;높은 사용자 경험(UX)&lt;/strong&gt;을 요구하기 때문에, 아키텍처도 여기에 맞춰 구성됩니다.&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;/p&gt;
&lt;h3&gt; ️ 기본 아키텍처: 클라이언트 - 서버 - DB&lt;/h3&gt;
&lt;p&gt;게임도 기본적으로는 클라이언트와 서버, 그리고 데이터 저장소로 구성됩니다.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[클라이언트(Unity/Unreal)]  &amp;lt;--&amp;gt;  [게임 서버]  &amp;lt;--&amp;gt;  [DB, 캐시 등]
                                        │
                                        └── [운영툴 서버, API 게이트웨이 등]&lt;/code&gt;&lt;/pre&gt;&lt;h4&gt;  클라이언트&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Unity (C#), Unreal Engine (C++) 등 게임 엔진을 사용&lt;/li&gt;
&lt;li&gt;그래픽, 물리 엔진, UI, 애니메이션, 사운드, 입력 처리 등 포함&lt;/li&gt;
&lt;li&gt;WebSocket이나 TCP/UDP 통신 기능 내장 또는 확장 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;  게임 서버&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;실시간 멀티플레이, 전투 로직, 유저 세션, 매치메이킹 등 처리&lt;/li&gt;
&lt;li&gt;Java, Node.js, Go, C#, C++ 등 다양한 언어로 커스텀 구현&lt;/li&gt;
&lt;li&gt;Redis, MySQL, MongoDB, Cassandra 등 다양한 DB 사용&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;  게임 서버 구조는 어떻게 생겼을까?&lt;/h3&gt;
&lt;p&gt;게임의 장르에 따라 서버 구조도 달라집니다.&lt;/p&gt;
&lt;p&gt;예를 들어 MMORPG처럼 대규모 유저가 동시에 접속하는 게임은 다음과 같은 &lt;strong&gt;마이크로서비스 아키텍처&lt;/strong&gt; 형태를 가질 수 있습니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Zone 서버 (맵/지역 단위로 분리)&lt;/li&gt;
&lt;li&gt;매치메이킹 서버&lt;/li&gt;
&lt;li&gt;채팅 서버&lt;/li&gt;
&lt;li&gt;AI 서버&lt;/li&gt;
&lt;li&gt;인증 및 과금 서버&lt;/li&gt;
&lt;li&gt;운영툴 서버&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;실시간 처리를 위해 TCP/UDP 기반 통신을 주로 사용하고, 일부 시스템은 REST API나 gRPC로도 구성합니다.&lt;br&gt;&lt;br&gt;&lt;/p&gt;
&lt;p&gt;그렇다면 퍼즐 게임은 어떨까요? 경우에 따라 다르지만, 여기선 MMORPG에 비하면 비교적 단순한 &lt;strong&gt;클라이언트-서버&lt;/strong&gt; 구조를 갖는 예시로 캐주얼 퍼즐 게임을 들어보겠습니다.&lt;/p&gt;
&lt;p&gt;캔디크러쉬사가, 애니팡 같은 캐주얼 퍼즐 게임의 특징은 다음과 같습니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;싱글 플레이 중심&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;p&gt;따라서 클라이언트가 대부분의 게임 로직을 처리하고, 서버는 기록과 검증만 맡는 구조가 일반적입니다. 이 경우 서버는 주로 다음과 같은 기능을 수행합니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;유저 계정 관리 (게스트, 소셜 로그인 등)&lt;/li&gt;
&lt;li&gt;스테이지 클리어 기록 저장&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;p&gt;이 경우 DB에는 유저 상태, 인벤토리 등이 저장될 것이고, 광고, 결제, 랭킹, 푸시 등의 기능은 내외부 API가 수행할 것입니다.&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;/p&gt;
&lt;h3&gt;  유니티/언리얼의 주요 역할&lt;/h3&gt;
&lt;p&gt;유니티와 언리얼은 주로 &lt;strong&gt;클라이언트 개발&lt;/strong&gt;에 집중된 엔진입니다.&lt;/p&gt;
&lt;h4&gt;주요 역할:&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;3D/2D 렌더링&lt;/li&gt;
&lt;li&gt;물리 엔진 처리&lt;/li&gt;
&lt;li&gt;UI 구성&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;p&gt;그렇기 때문에 유니티, 언리얼이 기획자에게 프로토타이핑 툴로도 쓰일 수 있는 것입니다. 반면, 주 역할이 아닌 것은 다음과 같습니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;게임 서버 로직 개발 (멀티플레이 동기화, 매치메이킹 등)&lt;/li&gt;
&lt;li&gt;데이터베이스 저장/조회&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;p&gt;그렇지만 앞서 나왔던 캐주얼 퍼즐 장르처럼 비교적 단순한 게임의 경우, 클라이언트가 게임의 주요 로직을 처리하기도 합니다.&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;/p&gt;
&lt;h3&gt;  주요 기술 스택&lt;/h3&gt;
&lt;p&gt;게임 클라이언트, 서버, 인프라/DevOps 분야의 주요 기술 스택을 정리하면 다음과 같습니다.&lt;/p&gt;
&lt;h4&gt;  클라이언트&lt;/h4&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;기능&lt;/th&gt;
&lt;th&gt;기술 스택&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;그래픽/물리/애니메이션&lt;/td&gt;
&lt;td&gt;Unity, Unreal Engine&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;UI&lt;/td&gt;
&lt;td&gt;엔진 내 UI 시스템, TextMeshPro 등&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;오디오&lt;/td&gt;
&lt;td&gt;FMOD, Wwise 등&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;네트워크&lt;/td&gt;
&lt;td&gt;WebSocket, TCP/UDP, Photon, Mirror 등&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h4&gt;  서버&lt;/h4&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;기능&lt;/th&gt;
&lt;th&gt;기술 스택&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;게임 로직&lt;/td&gt;
&lt;td&gt;Java, Node.js, C#, C++ 등&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;데이터 저장&lt;/td&gt;
&lt;td&gt;MySQL, MongoDB, Redis, Cassandra 등&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;세션/매치메이킹&lt;/td&gt;
&lt;td&gt;자체 구현 또는 BaaS (PlayFab, Nakama 등)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;인증/결제&lt;/td&gt;
&lt;td&gt;OAuth, Firebase Auth, AWS Cognito 등&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h4&gt;  인프라 및 DevOps&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;인프라&lt;/strong&gt;: Docker, Kubernetes, AWS/GCP&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;배포/CI&lt;/strong&gt;: GitHub Actions, Jenkins, ArgoCD&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;모니터링/로깅&lt;/strong&gt;: Prometheus, Grafana, ELK, Sentry&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;콘텐츠 배포&lt;/strong&gt;: CDN 기반 패치 시스템&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;✅ 마무리&lt;/h3&gt;
&lt;p&gt;게임 개발은 처음 접하면 유니티, 언리얼로 모든 걸 다 할 수 있을 것 같지만, 실제로는 복잡한 분산 시스템과 다양한 기술 스택이 함께 움직이는 종합 개발입니다. &lt;/p&gt;
&lt;p&gt;웹이나 앱 개발에 익숙한 사람이라면, &lt;strong&gt;서버 아키텍처, 통신 구조, DevOps 등 익숙한 개념들이 게임에서도 적용되지만&lt;/strong&gt;, &lt;strong&gt;실시간성과 사용자 경험에 훨씬 민감한 환경&lt;/strong&gt;이라는 점이 차이점입니다.&lt;/p&gt;
&lt;p&gt;처음 게임 개발을 알아보시는 다른 분들에게도 이 글이 도움되었길 바라며 마치겠습니다.&lt;/p&gt;</description>
      <category>게임 개발</category>
      <author>dr.meteor</author>
      <guid isPermaLink="true">https://thewayaboutme.tistory.com/773</guid>
      <comments>https://thewayaboutme.tistory.com/773#entry773comment</comments>
      <pubDate>Tue, 22 Apr 2025 22:20:40 +0900</pubDate>
    </item>
    <item>
      <title>OS에서 프로그램과 패키지가 설치 및 삭제되는 과정을 설명해보자.</title>
      <link>https://thewayaboutme.tistory.com/772</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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1450&quot; data-origin-height=&quot;1056&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/o2HDL/btsNslpakdv/Wt8rJ8lIKZQXMlNuKV02c1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/o2HDL/btsNslpakdv/Wt8rJ8lIKZQXMlNuKV02c1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/o2HDL/btsNslpakdv/Wt8rJ8lIKZQXMlNuKV02c1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fo2HDL%2FbtsNslpakdv%2FWt8rJ8lIKZQXMlNuKV02c1%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;1450&quot; height=&quot;1056&quot; data-origin-width=&quot;1450&quot; data-origin-height=&quot;1056&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. 설치 파일 실행 - 첫 단계&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Windows에서 .exe 파일을, Mac에서 .dmg 파일을 더블 클릭하면 어떤 일이 벌어질까요?&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;avrasm custom-cursor-default-hover&quot; style=&quot;color: #383a42; text-align: left;&quot;&gt;&lt;code&gt;User: 크롬 설치 파일 더블클릭
OS: &quot;오, 실행 가능한 프로그램이네! 이걸 메모리에 올려서 실행해야겠다.&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 순간 운영체제는 해당 파일이 실행 가능한 형식인지 확인하고, 설치 프로그램을 메모리에 로드합니다. 이것은 하드 디스크에서 RAM으로 데이터를 복사하는 과정입니다. 설치 프로그램이 메모리에 로드되면, CPU는 해당 프로그램의 명령어를 실행하기 시작합니다.&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;2. 사용자 권한 확인 - 보안의 첫 관문&lt;/h3&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;avrasm custom-cursor-default-hover&quot; style=&quot;color: #383a42; text-align: left;&quot;&gt;&lt;code&gt;OS: &quot;이 프로그램이 시스템을 변경하려고 하는데, 허용할까요?&quot;
User: &quot;예&quot; 버튼 클릭&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 단계에서 운영체제는 사용자 계정 제어(UAC)를 통해 관리자 권한이 필요한 작업을 허용할지 확인합니다. 이는 권한 상승(privilege escalation)이라는 보안 메커니즘의 일부로, 모든 프로그램이 기본적으로 제한된 권한으로 실행되다가 필요할 때만 더 높은 권한을 요청하게 됩니다.&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;3. 시스템 환경 확인 - 호환성 체크&lt;/h3&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;1c custom-cursor-default-hover&quot; style=&quot;color: #383a42; text-align: left;&quot;&gt;&lt;code&gt;설치 프로그램: &quot;이 컴퓨터가 내가 필요로 하는 조건을 갖추고 있는지 확인해야겠다.&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;설치 프로그램은 다음과 같은 항목을 확인합니다:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;OS 버전과 호환성&lt;/li&gt;
&lt;li&gt;필요한 최소 하드웨어 사양&lt;/li&gt;
&lt;li&gt;필수 종속성(dependencies) 존재 여부&lt;/li&gt;
&lt;li&gt;디스크 공간 확인&lt;/li&gt;
&lt;/ul&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;4. 파일 추출 및 복사 - 짐 풀기&lt;/h3&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;1c custom-cursor-default-hover&quot; style=&quot;color: #383a42; text-align: left;&quot;&gt;&lt;code&gt;설치 프로그램: &quot;모든 필요한 파일을 지정된 위치에 풀어놓자.&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대부분의 설치 파일은 실제로는 압축 파일입니다. 이 단계에서는:&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;압축 해제 알고리즘이 작동하여 파일을 풉니다.&lt;/li&gt;
&lt;li&gt;파일 시스템 API를 사용하여 파일을 지정된 디렉토리에 복사합니다.&lt;/li&gt;
&lt;li&gt;파일 시스템 트리가 업데이트됩니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Windows에서는 주로 C:\Program Files\ 디렉토리에, Mac에서는 /Applications/ 폴더에 파일이 복사됩니다. 이 과정에서 파일 시스템의 디렉토리 구조에 새로운 노드(폴더와 파일)가 추가됩니다.&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;5. 시스템 레지스트리 업데이트 - 주소록 갱신&lt;/h3&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;1c custom-cursor-default-hover&quot; style=&quot;color: #383a42; text-align: left;&quot;&gt;&lt;code&gt;설치 프로그램: &quot;OS에게 내가 여기 있다고 알려주자.&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특히 Windows 시스템에서 중요한 단계입니다:&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;레지스트리는 키-값 쌍으로 구성된 계층적 데이터베이스입니다.&lt;/li&gt;
&lt;li&gt;설치 프로그램은 HKEY_LOCAL_MACHINE\SOFTWARE\ 또는 HKEY_CURRENT_USER\SOFTWARE\ 아래에 프로그램 정보를 기록합니다.&lt;/li&gt;
&lt;li&gt;이 정보에는 설치 경로, 버전, 구성 설정 등이 포함됩니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Mac과 Linux에서는 레지스트리 대신 구성 파일(.plist, .conf 등)을 사용하여 비슷한 정보를 저장합니다.&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;6. 환경 변수 설정 - 길 표시하기&lt;/h3&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;1c custom-cursor-default-hover&quot; style=&quot;color: #383a42; text-align: left;&quot;&gt;&lt;code&gt;설치 프로그램: &quot;다른 프로그램들이 나를 쉽게 찾을 수 있도록 지도에 표시해놓자.&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;많은 프로그램이 시스템 환경 변수를 수정합니다:&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;PATH 변수에 실행 파일 경로 추가 (명령줄에서 프로그램을 쉽게 실행할 수 있게 함)&lt;/li&gt;
&lt;li&gt;특정 프로그램용 환경 변수 설정 (예: JAVA_HOME)&lt;/li&gt;
&lt;li&gt;이 변경사항은 메모리와 구성 파일 모두에 반영됩니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 환경 변수는 일종의 전역 해시맵(hashmap)으로 생각할 수 있습니다.&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;7. 바로가기 생성 - 접근성 향상&lt;/h3&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;1c custom-cursor-default-hover&quot; style=&quot;color: #383a42; text-align: left;&quot;&gt;&lt;code&gt;설치 프로그램: &quot;사용자가 나를 쉽게 찾을 수 있게 바로가기를 만들자.&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 단계에서는:&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;바탕화면, 시작 메뉴 또는 독(Dock)에 바로가기 파일이 생성됩니다.&lt;/li&gt;
&lt;li&gt;이 바로가기는 실제로 작은 포인터 파일로, 실제 프로그램 경로를 가리킵니다.&lt;/li&gt;
&lt;li&gt;파일 연결(file associations)이 설정되어 특정 확장자를 가진 파일을 이 프로그램으로 열 수 있게 합니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;8. 서비스 등록 - 백그라운드 작업자 배치&lt;/h3&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;1c custom-cursor-default-hover&quot; style=&quot;color: #383a42; text-align: left;&quot;&gt;&lt;code&gt;설치 프로그램: &quot;부팅할 때마다 자동으로 실행되도록 설정하자.&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일부 프로그램은 시스템 서비스나 데몬으로 등록됩니다:&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;Windows의 서비스 관리자 또는 Linux/Mac의 systemd/launchd에 서비스가 등록됩니다.&lt;/li&gt;
&lt;li&gt;부팅 시퀀스에 이 서비스를 시작하는 단계가 추가됩니다.&lt;/li&gt;
&lt;li&gt;이는 프로세스 관리 시스템의 작업 대기열에 새로운 항목을 추가하는 것과 같습니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;9. 종속성 설치 - 필요한 재료 모으기&lt;/h3&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;1c custom-cursor-default-hover&quot; style=&quot;color: #383a42; text-align: left;&quot;&gt;&lt;code&gt;설치 프로그램: &quot;내가 제대로 작동하려면 이것들도 필요해.&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;많은 프로그램이 다른 소프트웨어 구성 요소에 의존합니다:&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;공유 라이브러리 (.dll, .so, .dylib 파일)&lt;/li&gt;
&lt;li&gt;런타임 환경 (예: .NET, Java Runtime)&lt;/li&gt;
&lt;li&gt;이런 종속성이 없으면 설치 프로그램이 자동으로 다운로드하고 설치합니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이것은 일종의 의존성 그래프(dependency graph)를 따라 필요한 모든 노드를 확보하는 과정입니다.&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;10. 설치 완료 및 정리 - 마무리 작업&lt;/h3&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;1c custom-cursor-default-hover&quot; style=&quot;color: #383a42; text-align: left;&quot;&gt;&lt;code&gt;설치 프로그램: &quot;모든 작업이 완료되었으니 임시 파일을 정리하고 마무리하자.&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마지막으로&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;임시 파일이 삭제됩니다.&lt;/li&gt;
&lt;li&gt;설치 로그가 생성됩니다.&lt;/li&gt;
&lt;li&gt;필요하다면 시스템 재시작을 요청합니다.&lt;/li&gt;
&lt;li&gt;설치 프로그램 자신이 종료됩니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;CLI 패키지 관리자로 설치하게 되면?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CLI 패키지 관리자(apt, yum, brew, npm 등) 역시 명령어 한 줄로 위의 모든 단계를 자동화합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;avrasm custom-cursor-default-hover&quot; style=&quot;color: #383a42; text-align: left;&quot;&gt;&lt;code&gt;User: apt install firefox
패키지 관리자: &quot;알겠습니다. 필요한 모든 것을 알아서 처리할게요.&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 간단한 명령어 뒤에서 패키지 관리자는&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;중앙 저장소에서 패키지 정보를 검색합니다.&lt;/li&gt;
&lt;li&gt;종속성을 해결합니다 (의존성 그래프 생성).&lt;/li&gt;
&lt;li&gt;필요한 모든 파일을 다운로드합니다.&lt;/li&gt;
&lt;li&gt;파일을 적절한 위치에 설치합니다.&lt;/li&gt;
&lt;li&gt;시스템 구성을 업데이트합니다.&lt;/li&gt;
&lt;/ol&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;h2 data-ke-size=&quot;size26&quot;&gt;프로그램 삭제 시&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로그램을 삭제할 때는 설치의 역순으로 진행됩니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;avrasm custom-cursor-default-hover&quot; style=&quot;color: #383a42; text-align: left;&quot;&gt;&lt;code&gt;User: &quot;프로그램 삭제&quot; 클릭
OS: &quot;이 프로그램과 관련된 모든 것을 찾아서 제거할게요.&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;자료 구조로 본 삭제 프로세스&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;그래프 순회(Graph Traversal)&lt;/b&gt;: 설치 중 생성된 파일 및 레지스트리 항목의 그래프를 역방향으로 순회합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;해시맵 조회(HashMap Lookup)&lt;/b&gt;: 빠른 파일 및 레지스트리 항목 조회를 위해 해시맵을 사용합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;큐(Queue)&lt;/b&gt;: 삭제할 항목을 순서대로 처리하기 위한 작업 대기열이 생성됩니다.&lt;/li&gt;
&lt;/ol&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;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;언인스톨러(제거 프로그램) 실행: 대부분의 프로그램은 자체 제거 프로그램을 포함합니다.&lt;/li&gt;
&lt;li&gt;파일 시스템 정리: 프로그램 파일이 삭제됩니다 (파일 시스템 트리에서 노드 제거).&lt;/li&gt;
&lt;li&gt;레지스트리 정리: 프로그램 관련 레지스트리 키가 삭제됩니다.&lt;/li&gt;
&lt;li&gt;환경 변수 롤백: 변경된 환경 변수가 원래 상태로 복원됩니다.&lt;/li&gt;
&lt;li&gt;바로가기 및 파일 연결 제거: 생성된 바로가기와 파일 연결이 제거됩니다.&lt;/li&gt;
&lt;li&gt;서비스 등록 해제: 등록된 서비스가 중지되고 시스템에서 제거됩니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;이 과정에 사용된 아키텍처와 기술은?&lt;/h2&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;1556&quot; data-origin-height=&quot;900&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cY8KxP/btsNslbAzca/tNFogbSveK25bbHplSjp71/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cY8KxP/btsNslbAzca/tNFogbSveK25bbHplSjp71/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cY8KxP/btsNslbAzca/tNFogbSveK25bbHplSjp71/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcY8KxP%2FbtsNslbAzca%2FtNFogbSveK25bbHplSjp71%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;1556&quot; height=&quot;900&quot; data-origin-width=&quot;1556&quot; data-origin-height=&quot;900&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1356&quot; data-origin-height=&quot;982&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bw9jFq/btsNspkzVe8/4LYPdKccJerIDFkz73Ko71/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bw9jFq/btsNspkzVe8/4LYPdKccJerIDFkz73Ko71/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bw9jFq/btsNspkzVe8/4LYPdKccJerIDFkz73Ko71/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbw9jFq%2FbtsNspkzVe8%2F4LYPdKccJerIDFkz73Ko71%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;1356&quot; height=&quot;982&quot; data-origin-width=&quot;1356&quot; data-origin-height=&quot;982&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. 계층적 파일 시스템&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;파일 시스템은 트리 구조로 설계되어 있어 프로그램 파일을 체계적으로 저장하고 찾을 수 있게 해줍니다:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;fortran custom-cursor-default-hover&quot; style=&quot;color: #383a42; text-align: left;&quot;&gt;&lt;code&gt;/ (루트)
└── Program Files/
    └── Chrome/
        ├── chrome.exe
        ├── resources/
        └── libs/&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 트리 구조는 깊이 우선 탐색(DFS)이나 너비 우선 탐색(BFS) 알고리즘으로 효율적으로 탐색할 수 있습니다.&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;2. 계층적인 키-값 저장소 형태의 레지스트리/설정 데이터베이스&lt;/h3&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;nix custom-cursor-default-hover&quot; style=&quot;color: #383a42; text-align: left;&quot;&gt;&lt;code&gt;HKEY_LOCAL_MACHINE/
└── SOFTWARE/
    └── Google/
        └── Chrome/
            ├── Version = &quot;123.0.0&quot;
            └── InstallPath = &quot;C:\Program Files\Chrome&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 구조는 B-트리나 그 변형을 사용하여 빠른 검색, 삽입, 삭제를 지원합니다.&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;3. 패키지 관리 시스템&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;패키지 관리자는 다음과 같은 핵심 구성 요소를 가집니다:&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;의존성 해결기(Dependency Resolver)&lt;/b&gt;: 방향성 비순환 그래프(DAG)를 사용하여 패키지 간 관계를 모델링합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;중앙 저장소(Repository)&lt;/b&gt;: 패키지 메타데이터의 분산 데이터베이스입니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;트랜잭션 엔진&lt;/b&gt;: ACID(원자성, 일관성, 고립성, 지속성) 속성을 보장하여 설치 과정이 중단되어도 시스템이 일관된 상태를 유지하게 합니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4. 디지털 서명과 해시 함수를 활용한 무결성 검증&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;패키지 파일의 해시값 계산 (SHA-256 등)&lt;/li&gt;
&lt;li&gt;공개 키 암호화를 사용한 서명 검증&lt;/li&gt;
&lt;li&gt;인증서 체인 검증&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;OS는 암호화 기술을 통해 설치 과정의 안전성을 보장합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;마치며&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단순해 보이는 설치/삭제 작업 뒤에는 이처럼 복잡한 과정과 정교한 알고리즘이 작동하고 있습니다. 이같은 복잡성은 사용자에게는 보이지 않지만, 시스템의 안정성과 효율성을 보장하는 필수적인 요소입니다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현대 패키지 관리자들은 다음과 같은 문제를 해결하기 위해 계속 발전하고 있습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;의존성 지옥 방지&lt;/b&gt;: 정교한 버전 관리와 충돌 해결 메커니즘&lt;/li&gt;
&lt;li&gt;&lt;b&gt;안전한 롤백&lt;/b&gt;: 설치 실패 시 시스템을 이전 상태로 복원&lt;/li&gt;
&lt;li&gt;&lt;b&gt;성능 최적화&lt;/b&gt;: 병렬 다운로드, 증분 업데이트 등으로 속도 향상&lt;/li&gt;
&lt;li&gt;&lt;b&gt;보안 강화&lt;/b&gt;: 서명 검증, 체크섬, 샌드박싱 기술 적용&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음에 프로그램을 설치하거나 삭제할 때, 단순한 클릭 또는 명령어 하나로 이루어지는 것처럼 보이지만, 그 이면에는 수십 년간 발전해온 컴퓨터 과학의 정수가 응축되어 있다는 점을 기억하시면 좋겠습니다.&lt;br /&gt;&lt;br /&gt;그럼 이 글이 독자분의 CS 이해도와 응용력을 높이는 데 도움이 되었기를 바라며 글을 마치겠습니다.&lt;/p&gt;</description>
      <category>Computer Science/호기심 해결</category>
      <category>운영체제</category>
      <category>컴퓨터 과학</category>
      <category>패키지 매니저</category>
      <category>프로그램 설치</category>
      <author>dr.meteor</author>
      <guid isPermaLink="true">https://thewayaboutme.tistory.com/772</guid>
      <comments>https://thewayaboutme.tistory.com/772#entry772comment</comments>
      <pubDate>Sun, 20 Apr 2025 17:30:38 +0900</pubDate>
    </item>
    <item>
      <title>개념, 논리 모델링</title>
      <link>https://thewayaboutme.tistory.com/745</link>
      <description>&lt;div data-pm-slice=&quot;1 2 []&quot;&gt;모델링의 정의&lt;/div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-id=&quot;pHfGqnV2NLKr5YHfEuZqgXs_0&quot;&gt;모델링의 정의는 영속성을 갖는 데이터에 대한 시스템 구조를 사람이 이해할 수 있도록 형상화하는 과정임&lt;/li&gt;
&lt;li data-id=&quot;pHfGqnV2NLKr5YHfEuZqgXs_1&quot;&gt;개념적 모델링을 거쳐 식별한 것을 기호 등을 통해 추상화하여 표현, 논리적 모델링을 하고 정보 시스템의 데이터베이스로 구축하기 위해 추상화된 모델을 구체화된 형태로 변환하는 것을 물리적 모델링이라고 함&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div data-pm-slice=&quot;1 2 []&quot;&gt;식별자 상속&lt;/div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-id=&quot;hFxPQtzYd4STYNufUmikuHs_0&quot;&gt;집합 간의 베타 관계를 해소하고 두 집합을 통합 테이블 형태로 설계한 경우 개인 개발 생산성이 증대되고 성능 향상 효과도 기대할 수 있음&lt;/li&gt;
&lt;li data-id=&quot;hFxPQtzYd4STYNufUmikuHs_1&quot;&gt;개인 고객 속성과 법인 고객 속성이 같은 테이블에 혼합되어 존재함으로 속성의 의미가 불분명해지고, not null 제약 조건을 반영할 수 없어 데이터 무결성 문제가 발생할 수 있음&lt;/li&gt;
&lt;li data-id=&quot;hFxPQtzYd4STYNufUmikuHs_2&quot;&gt;데이터 정합성 문제가 발생하지 않도록 응용 프로그램에서 업무 규칙을 추가로 설계하고 반영해야 함&lt;/li&gt;
&lt;li data-id=&quot;hFxPQtzYd4STYNufUmikuHs_3&quot;&gt;식별자 상속은 식별 관계와 비식별 관계로 구분할 수 있음&lt;/li&gt;
&lt;li data-id=&quot;hFxPQtzYd4STYNufUmikuHs_4&quot;&gt;&lt;b&gt;식별 관계는 참조되는 상위 엔티티, 식별자가 참조하는 하위엔티티 비식별자로 상속되는 경우를 말하고, 비식별 관계는 식별자가 아닌 일반 속성으로 상속되는 관계를 말함&lt;/b&gt;&lt;/li&gt;
&lt;/ul&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;div data-pm-slice=&quot;1 2 []&quot;&gt;데이터 모델링의 정규형&lt;/div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-id=&quot;VAcG7PbrdgAGGbGo9i8JdLs_0&quot;&gt;유형을 만족하지 못하는 모델은 개념이 명확하지 않거나 다수의 개념을 하나의 엔티티에 포함한 것이므로 개념을 분리하여 모델링을 하면 대부분 정규형을 만족하는 결과를 얻게 됨&lt;/li&gt;
&lt;li data-id=&quot;VAcG7PbrdgAGGbGo9i8JdLs_1&quot;&gt;별도 정규화 과정을 거치지 않았다 해도 데이터 모델링 완전성을 확인해 본다는 측면에서 정규형을 만족하고 있는지 검토할 수 있음&lt;/li&gt;
&lt;li data-id=&quot;VAcG7PbrdgAGGbGo9i8JdLs_2&quot;&gt;정규화를 너무 심하게 할 경우 응용 프로그램에서 조인이 빈번하게 발생해 성능이 저하되지 않을까 걱정할 수 있음&lt;/li&gt;
&lt;/ul&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;div data-pm-slice=&quot;1 2 []&quot;&gt;정규화의 개념&lt;/div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-id=&quot;U9ymg52Fz7EaGMFrDwAowPs_0&quot;&gt;정교화는 물리모델링이 아닌 논리모델링 과정에서 ER 모델과 함께 적용하는 것이 일반적임&lt;/li&gt;
&lt;li data-id=&quot;U9ymg52Fz7EaGMFrDwAowPs_1&quot;&gt;부채꼴 함정은 제3정규형에서 발생하는 문제임&lt;/li&gt;
&lt;li data-id=&quot;U9ymg52Fz7EaGMFrDwAowPs_2&quot;&gt;부채꼴&amp;nbsp;함정은 엔티티 사이의 관계가 정의되어 있지만 관계가 모호한 경우 m:n 관계를 해결하기 위해 교차 엔티티를 도입하면서 1대 1 관계를 만들 때 일어날 수 있음&lt;/li&gt;
&lt;li data-id=&quot;U9ymg52Fz7EaGMFrDwAowPs_3&quot;&gt;엔티티&amp;nbsp;간 관계를 잘못 설계하여 연계된 정보를 추적하지 못해 발생함으로 이들 간 관계를 명확히 하여 해결할 수 있음&lt;/li&gt;
&lt;/ul&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;div data-pm-slice=&quot;1 2 []&quot;&gt;데이터 모델링의 개념&lt;/div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-id=&quot;uLHAyVegqYVbGxmnbqabTTs_0&quot;&gt;데이터 모델링은 데이터 아키텍처의 핵심 구성 요소임&lt;/li&gt;
&lt;li data-id=&quot;uLHAyVegqYVbGxmnbqabTTs_1&quot;&gt;데이터 모델링은 프로젝트 상황에 따라 하향식 접근 방식과 상향식 접근 방식 두 가지가 있음&lt;/li&gt;
&lt;/ul&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;div data-pm-slice=&quot;1 2 []&quot;&gt;리버스 모델링의 개념&lt;/div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-id=&quot;qCJtgY7byJzHycRUaLF6oCs_0&quot;&gt;직무 면접을 갔을 때 소통 성향이라든지 외향적인 성향이라든지 이런 것들이 중요하게 여겨질 수 있음&lt;/li&gt;
&lt;li data-id=&quot;qCJtgY7byJzHycRUaLF6oCs_1&quot;&gt;리버스 모델 활용이라는 개념이 새로워서 알면 좋을 것 같음&lt;/li&gt;
&lt;li data-id=&quot;qCJtgY7byJzHycRUaLF6oCs_2&quot;&gt;리버스 모델링은 &lt;u&gt;데이터 모델을 현행화&lt;/u&gt;하는 과정을 말함&lt;/li&gt;
&lt;li data-id=&quot;qCJtgY7byJzHycRUaLF6oCs_3&quot;&gt;보충 설명: DB 메타 정보로 기초 데이터 모델을 생성, 즉 엔티티를 생성하고 컬럼에 대한 코멘트 정보를 이용하거나 시스템 운영자의 지원을 받아 한글명으로 속성을 수정하는데 FK 제약 조건이 없는 경우가 대부분이므로 현행 시스템 산출물을 최대한 활용하고 업무나 시스템을 잘 아는 시스템 운영자에게 도움을 요청할 수 있다&lt;/li&gt;
&lt;/ul&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;div data-pm-slice=&quot;1 2 []&quot;&gt;데이터 분산 전략&lt;/div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-id=&quot;DupCKdex9js9rvoiamLdoHs_0&quot;&gt;할당된 it 자원을 파악할 수 있어 정보 시스템 구축에 따른 중복 투자를 방지할 수 있고 이미 투입된 자원을 효율적으로 재분배할 수 있음&lt;/li&gt;
&lt;li data-id=&quot;DupCKdex9js9rvoiamLdoHs_1&quot;&gt;데이터 관리 차원에서는 데이터에 대한 &lt;u&gt;통합, 연계, 중복 등에 대한 방안&lt;/u&gt;을 수립하는 데 기초 자료로 활용할 수 있음&lt;/li&gt;
&lt;li data-id=&quot;DupCKdex9js9rvoiamLdoHs_2&quot;&gt;데이터 분산 전략 수립 시 &lt;b&gt;데이터 주제 영역별로 분산 아키텍, 주제 영역 단위로 담당자를 지정&lt;/b&gt;하여 &lt;b&gt;데이터 모델링 작업을 수행&lt;/b&gt;하고 각각의 데이터 모델을 통합할 수 있는 근간을 제공하여 시스템 개발 및 유지보수 활동을 효율적으로 수행할 수 있음&lt;/li&gt;
&lt;/ul&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;div data-pm-slice=&quot;1 2 []&quot;&gt;개념 모델의 속성 정의&lt;/div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-id=&quot;MDUDvd3z3HCgwoQLsyw7AYs_0&quot;&gt;데이터를 바라보는 관점에 따라 완전히 다른 주제 영역으로 분류될 수 있으므로 &lt;b&gt;&lt;u&gt;데이터 관점으로 접근할지, 업무나 기능 중심으로 분류할지&lt;/u&gt;&lt;/b&gt; 고객을 포함한 이해관계자와 충분히 협의하여 진행하는 것이 좋음&lt;/li&gt;
&lt;li data-id=&quot;MDUDvd3z3HCgwoQLsyw7AYs_1&quot;&gt;식별자 및 속성 정의에 대한 이야기&lt;/li&gt;
&lt;li data-id=&quot;MDUDvd3z3HCgwoQLsyw7AYs_2&quot;&gt;개념 모델링을 하다 보면 모델러에 따라 &lt;b&gt;속성 전체를 노출해야 한다&lt;/b&gt;는 사람도 있고, &lt;b&gt;식별자와 일부 속성 정도로 극히 일부만 노출&lt;/b&gt;하면 된다는 사람도 있음&lt;/li&gt;
&lt;li data-id=&quot;MDUDvd3z3HCgwoQLsyw7AYs_3&quot;&gt;개념 모델을 &lt;u&gt;&lt;b&gt;누가 어떤 용도로 사용할지를 생각한다면 답은 대충 나오는 것 같음&lt;/b&gt;&lt;/u&gt;&lt;/li&gt;
&lt;/ul&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;div data-pm-slice=&quot;1 2 []&quot;&gt;논리 데이터 모델링&lt;/div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-id=&quot;W8QQN6LVQ54hFaJYRCXPqes_0&quot;&gt;논리 데이터 모델링은 &lt;u&gt;모든 업무 영역에 필요한 데이터 모델을 설계&lt;/u&gt;하고 시스템 관점에서 필요한 데이터 항목은 반영하지 않음&lt;/li&gt;
&lt;li data-id=&quot;W8QQN6LVQ54hFaJYRCXPqes_1&quot;&gt;데이터에 대한 &lt;u&gt;이력 관리 대상은 업무 측면에서 꼭 관리할 필요가 있는 부분은 반영해야 함&lt;/u&gt;&lt;/li&gt;
&lt;li data-id=&quot;W8QQN6LVQ54hFaJYRCXPqes_2&quot;&gt;&lt;b&gt;논리모델링은 개념 데이터 모델과 지속해서 구조적 일관성을 유지하면서 진행함&lt;/b&gt;&lt;/li&gt;
&lt;/ul&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;div data-pm-slice=&quot;1 2 []&quot;&gt;엔티티&amp;nbsp;통합의 개념&lt;/div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-id=&quot;eFy35Q6VtBySC9Bx988Y2Ts_0&quot;&gt;데이터를 수집할 수 있는 대상이 고객이 될 수도 있고, 동의 절차를 통과해야 비로소 고객 집합에 포함될 수도 있어서 까다로움&lt;/li&gt;
&lt;li data-id=&quot;eFy35Q6VtBySC9Bx988Y2Ts_1&quot;&gt;엔티티는 업무 행위에 대한 상세 배역 및 업무 결과에 대한 상태를 나타내는 엔티티이며, 중요 엔티티에 종속되거나 다른 행위 엔티티에 종속됨&lt;/li&gt;
&lt;li data-id=&quot;eFy35Q6VtBySC9Bx988Y2Ts_2&quot;&gt;엔티티&amp;nbsp;통합은 엔티티 일반화를 통해 구조적인 측면에서 하나의 엔티티로 설계하는 경우도 있고, 여러 시스템이나 업무에서 개별적으로 관리하던 데이터를 모아 관리하는 데이터 통합도 있음&lt;/li&gt;
&lt;li data-id=&quot;eFy35Q6VtBySC9Bx988Y2Ts_3&quot;&gt;투비 데이터 모델의 설계 방향을 수립할 때 데이터 및 엔티티 통합이 핵심 개선 요소로 많이 언급됨&lt;/li&gt;
&lt;/ul&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;div data-pm-slice=&quot;1 2 []&quot;&gt;식별자 상속 관계와 비식별자 상속 관계&lt;/div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-id=&quot;Yd7d4NpB2DTsC3LwEQ4UhFs_0&quot;&gt;식별자 상속 관계와 비식별자 상속 관계의 차이는 FK가 어디에 위치하느냐임&lt;/li&gt;
&lt;li data-id=&quot;Yd7d4NpB2DTsC3LwEQ4UhFs_1&quot;&gt;&lt;b&gt;식별자 상속 관계&lt;/b&gt;는&lt;b&gt; FK가 곧 PK키를 갖는 엔티티를 구별하는 역할&lt;/b&gt;까지 동시에 수행하는 것임&lt;/li&gt;
&lt;li data-id=&quot;Yd7d4NpB2DTsC3LwEQ4UhFs_2&quot;&gt;&lt;b&gt;비식별적 상속 관계인 경우&lt;/b&gt;에는 &lt;b&gt;관계를 통해서 FK를 받긴 하지만 그게 곧 FK이 갖고 있는 엔티티의 PK까진 아닌 거임&lt;/b&gt;&lt;/li&gt;
&lt;/ul&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;M:N 관계&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;고객과 상품, 주문과 배송처럼 핵심 엔티티나 중요한 엔티티&amp;nbsp;간 관계를 개념적으로 표현할 때 나타난다.&lt;/li&gt;
&lt;li&gt;&lt;span data-pm-slice=&quot;1 1 []&quot;&gt;논리&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;모델에서는&lt;/span&gt;&lt;span&gt; 엔티티&lt;/span&gt;&lt;span&gt;를&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;상세화하거나&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;교차하는&lt;/span&gt;&lt;span&gt; 엔티티&lt;/span&gt;&lt;span&gt;를&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;설계하여&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;m:n&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;관계를&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1대&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;관계로&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;표현한다.&lt;/span&gt;&lt;br /&gt;&lt;span&gt;M:N 관계가&amp;nbsp;&lt;/span&gt;&lt;u&gt;&lt;b&gt;&lt;span&gt;완전히&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;해소될&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;때까지&lt;/span&gt;&lt;/b&gt;&lt;/u&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1대&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;m&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;관계를&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;분해해야&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;한다.&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&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;span&gt;속성&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;데이터 표준 도메인과 매우 깊은 관계가 있으며, 번호, 코드, 명칭, 설명, 금액, 날짜, 비율 등 &lt;u&gt;도메인을 중심으로 데이터 성격을 식별&lt;/u&gt;할 수도 있다.&lt;/li&gt;
&lt;li&gt;&lt;u&gt;&lt;span data-pm-slice=&quot;1 1 []&quot;&gt;데이터&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;발생&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/u&gt;&lt;span&gt;&lt;u&gt;규칙&lt;/u&gt;을&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;기술하기도&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;한다.&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;유일하게 식별 가능하고 최소 속성으로 구성하고 변하지 않으면서 반드시 존재하는 값&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;span data-pm-slice=&quot;1 1 []&quot;&gt;자세한&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;얘기는&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;SQLD&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;요약본에. &lt;/span&gt;&lt;/span&gt;&lt;span data-pm-slice=&quot;1 1 []&quot;&gt;모든&lt;/span&gt;&lt;span&gt; 엔티티&lt;/span&gt;&lt;span&gt;는&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;식별자가&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;있어야&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;되는데&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;u&gt;&lt;b&gt;&lt;span&gt;없는&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;경우는&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;로그&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;성격&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;데이터거나&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;데이터로서&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;가치를&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;갖지&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;않는&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;임시&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;저장&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;성격의&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;데이터&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;가능성이&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;높다.&lt;/span&gt;&lt;/b&gt;&lt;/u&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;span data-pm-slice=&quot;1 1 []&quot;&gt;그래서&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;b&gt;&lt;span&gt;데이터&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;간&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;특성의&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;구분이&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;식별자로&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;이루어질&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;수도&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/b&gt;&lt;span&gt;&lt;b&gt;있다&lt;/b&gt;는&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;걸&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;배우게&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;됐고,&lt;/span&gt;&lt;span&gt; 엔티티&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;개체가&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;처음부터&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;유일하게&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;존재하는&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;것이&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;아니라&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;b&gt;&lt;span&gt;업무&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;처리나&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;이벤트&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;성격의&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;데이터인&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;경우&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;회원&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;아이디,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;계좌번호처럼&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;아이디나&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;일련번호&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;등을&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;부여하여&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;식별하는&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;경우도&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/b&gt;&lt;span&gt;&lt;b&gt;흔하다&lt;/b&gt;. &lt;span data-pm-slice=&quot;1 1 []&quot;&gt;이&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;경우라&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;하더라도&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;b&gt;일련&lt;/b&gt;&lt;/span&gt;&lt;b&gt;&lt;span&gt;번호&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;등을&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;부여하는&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;기준이&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;뭔지&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;반드시&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;식별해야&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;한다.&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span data-pm-slice=&quot;1 1 []&quot;&gt;인조&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;식별자는&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;결제&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;번호처럼&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;결제를&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;상실할&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;때&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;본질&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;식별자인&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;사원번호 등&lt;/span&gt;&lt;span&gt;을&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;대신하여&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;인위적으로&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;부여한&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;일련번호&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;형식의&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;식별자를&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;말한다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;u&gt;&lt;span data-pm-slice=&quot;1 1 []&quot;&gt;본질&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;식별자를&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;주&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;식별자로&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;하는&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;경우&lt;/span&gt;&lt;/u&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;주민등록번호보다는&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;사원번호처럼&lt;/span&gt;&lt;b&gt;&lt;span&gt; 엔티티&lt;/span&gt;&lt;span&gt;를&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;대표하거나&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;변하지&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;않는&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;혹은&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;식별자&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;특성에&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;더&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;적합한&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;속성을&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;우선하는&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;것이&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/b&gt;&lt;span&gt;&lt;b&gt;좋다&lt;/b&gt;. &lt;/span&gt;&lt;u&gt;&lt;span&gt;사원번호가&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;주식별자가&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;되는&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;경우&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;주민등록번호는&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;자연스럽게&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;대체&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;식별자가&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;된다.&lt;/span&gt;&lt;/u&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span data-pm-slice=&quot;1 1 []&quot;&gt;인조&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;식별자를&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;주&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;식별자로&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;사용하면서&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;본질&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;식별자를&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;식별하지&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;않은&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;경우를&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;종종&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;볼&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;수&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;있다.&lt;/span&gt;&lt;br /&gt;&lt;span&gt;결제에&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;상실할&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;때&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;상신자가&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;상신했을&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;때&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;본질&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;식별자는&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;데이터를&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;발생하는&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;규칙을&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;제공하며&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;유일하게&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;데이터를&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;식별할&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;수&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;있는&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;기준을&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;제공한다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span data-pm-slice=&quot;1 1 []&quot;&gt;본질&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;식별자를&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;정확하게&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;정의하지&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;않았다면 &lt;span data-pm-slice=&quot;1 1 []&quot;&gt;핵심적인&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;정의가&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;누락되었다고&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;볼&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;수&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;있으며,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;개발자가&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;데이터&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;집합을&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;자의적으로&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;해석하여&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;중복&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;데이터를&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;발생시킬&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;수&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;있는&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;여지를&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;주게&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;된다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;u&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span data-pm-slice=&quot;1 1 []&quot;&gt;결제번호처럼&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;인조&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;식별자를&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;주&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;식별자로&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;정의한&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;경우&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;문제&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;식별자인&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;상신자,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;사원번호,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;플러스&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;결제&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;일시를&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;대체&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;식별자로&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;지정할&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;수&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;있다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/u&gt;&lt;/li&gt;
&lt;li&gt;&lt;span data-pm-slice=&quot;1 1 []&quot;&gt;본질&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;식별자&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;또는&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;인조&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;식별자가&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;주식별자&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;역할이라든지&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;대체&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;식별자&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;역할이라든지&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;b&gt;&lt;span&gt;데이터&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;발생&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;규칙을&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;정의하고&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;실체의&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;무결성,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;제약&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;조건을&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;설계해야&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/b&gt;&lt;span&gt;&lt;b&gt;한다&lt;/b&gt;.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;span data-pm-slice=&quot;1 1 []&quot;&gt;논리&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;데이터&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;모델은&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;업무&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;변경에&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;유연하게&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;대응할&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;수&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;있어야&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;하고&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;확장성을&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;가져야&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;한다.&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;span&gt;&lt;span data-pm-slice=&quot;1 1 []&quot;&gt;향후&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;식별자를&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;변경하게&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;된다면&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;해당&lt;/span&gt;&lt;span&gt; 엔티티&lt;/span&gt;&lt;span&gt;와&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;관계를&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;갖는&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;다른&lt;/span&gt;&lt;span&gt; 엔티티&lt;/span&gt;&lt;span&gt;도&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;영향을&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;받게&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;된다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;&lt;u&gt;본질 식별자를 사용하는 것보다 인조 식별자를 사용한다면 식별자를 변경할 가능성이 낮아지고 이로 인한 설계 변경을 최소화할 수 있다.&lt;/u&gt;&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span data-pm-slice=&quot;1 1 []&quot;&gt;이처럼&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;본질&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;식별자&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;대신&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;인조&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;식별자를&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;사용하여&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;유연하고&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;확장&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;가능한&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;논리&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;모델을&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;설계할&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;수&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;있는&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;경우가&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;있다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span data-pm-slice=&quot;1 1 []&quot;&gt;업무적으로&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;중요성은&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;덜하지만&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;본질&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;식별자에&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;발주&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;번호&lt;/span&gt;&lt;span&gt; + &lt;/span&gt;&lt;span&gt;입찰&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;마감일자)&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;대신&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;인조&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;식별자인&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;입찰&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;번호를&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;부여하여&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;관리할&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;수도&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;있다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;u&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;하위&lt;/span&gt;&lt;span&gt; 엔티티&lt;/span&gt;&lt;span&gt;에&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;대한&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;하위&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;엔티티가&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;존재할&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;때&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;식별자를&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;계속&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;상속받게&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;되므로&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;하위&lt;/span&gt;&lt;span&gt; 엔티티&lt;/span&gt;&lt;span&gt;로&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;내려갈수록&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;식별자&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;속성&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;개수가&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;많아지게&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;되며&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;모델이&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;복잡해진다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/u&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;데이터&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;모델을&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;단순화하고&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;물리 모델로 변환했을 때 개발 편의성 및 성능적인 이점을 제공하기 위해 인조 식별자를 추가하여 주 식별자로 &lt;/b&gt;&lt;/span&gt;&lt;span&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;사용&lt;/b&gt;&lt;/span&gt;한다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;u&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;또&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;개인정보&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;암호화&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;대상에&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;해당하여&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;본질&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;식별자를&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;주식별자로&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;사용하지&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;못하는&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;경우도&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;있고,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;본질&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;식별자에&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;대한&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;데이터가&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;들어오지&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;않은&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;상태에서&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;업무&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;처리를&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;위해&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;인조&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;식별자를&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;추가하는&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;경우도&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;있다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/u&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;도메인을&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;지정하거나&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;데이터&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;타입을&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;지정할&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;때&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;가장&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;중요한&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;원칙은&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;속성이&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;관리할&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;때&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;데이터에&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;맞는 &lt;/span&gt;&lt;span&gt;데이터&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;타입을&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;지정하는&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;것이다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;데이터 유형을 고려하여 문자형, 숫자, 날짜형 데이터 타입을 지정해야 한다. 식별자 속성은 좀 애매하다. 업무적으로 부어 코드, 연도, 일련번호와 같은 식별 체제 체계를 갖는다면 문자형을 지정해야 하고, 의미없이 시스템에서 순차적으로 부여한다면 숫자형으로 지정한다.&lt;/li&gt;
&lt;li&gt;자식 엔티티에서 식별자로 상속받으려면 무조건 not null로 지정되고, 비식별자, 즉 일반 속성으로 상속받으면 옵셔널리티 지정에 따라 not null 여부가 결정된다.&lt;/li&gt;
&lt;/ul&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Projects/자린고비</category>
      <author>dr.meteor</author>
      <guid isPermaLink="true">https://thewayaboutme.tistory.com/745</guid>
      <comments>https://thewayaboutme.tistory.com/745#entry745comment</comments>
      <pubDate>Mon, 22 Apr 2024 17:37:02 +0900</pubDate>
    </item>
    <item>
      <title>CI, github actions에 대해 알게 된 것 총정리 ing</title>
      <link>https://thewayaboutme.tistory.com/738</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;CI는  리눅스 등 로컬 OS 환경에서 뭘 할 수 없을 때, 검사하고 싶은 타 OS 에서 뭘 하고 싶은지 CLI 명령어 기반으로 정의 내리고 시키는 일이라고 생각한다.&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;대표적 툴인 github actions 의 문법이 공식 문서에 정리돼있다: &lt;a href=&quot;https://docs.github.com/en/actions/using-workflows&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://docs.github.com/en/actions/using-workflows&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;검사 속도를 빠르게 하는 캐싱에 관한 건 여기 정리돼있고 &lt;a href=&quot;https://docs.github.com/en/actions/using-workflows/caching-dependencies-to-speed-up-workflows&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://docs.github.com/en/actions/using-workflows/caching-dependencies-to-speed-up-workflows&lt;/a&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;a href=&quot;https://github.com/actions/cache&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://github.com/actions/cache&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또 feature/** 브랜치에 push가 생길 때마다, develop 브랜치에 PR 생길 때마다 CI 트리거를 하고 싶어 문법을 찾아봤는데, 아래와 같이 하면 끝난다... 출처는 &lt;a href=&quot;https://github.com/actions/cache&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://github.com/actions/cache&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-04-01 오전 10.00.11.png&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;576&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dKyFQT/btsGew5woiZ/RhEPKk5Bz5JKKBUpiLUHTk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dKyFQT/btsGew5woiZ/RhEPKk5Bz5JKKBUpiLUHTk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dKyFQT/btsGew5woiZ/RhEPKk5Bz5JKKBUpiLUHTk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdKyFQT%2FbtsGew5woiZ%2FRhEPKk5Bz5JKKBUpiLUHTk%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;596&quot; height=&quot;238&quot; data-filename=&quot;스크린샷 2024-04-01 오전 10.00.11.png&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;576&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;또 주의사항으로, 처음 workflow 구동 시 루트 폴더에 대해 동일한 하위폴더 명으로 들어가 실행 경로를 잡아 버린다. 보통 장고에서 레포 네이밍을 이런 식으로 많이 하기 때문이겠지&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1336&quot; data-origin-height=&quot;200&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/sZXtY/btsGhlBH9ga/mniNKBfcmZAA8gZK9x0IKk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/sZXtY/btsGhlBH9ga/mniNKBfcmZAA8gZK9x0IKk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/sZXtY/btsGhlBH9ga/mniNKBfcmZAA8gZK9x0IKk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FsZXtY%2FbtsGhlBH9ga%2FmniNKBfcmZAA8gZK9x0IKk%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;1336&quot; height=&quot;200&quot; data-origin-width=&quot;1336&quot; data-origin-height=&quot;200&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;그래서 이름을 서로 다르게 잡아놨다면, python manage.py test 명령 전에 폴더를옮기는 작업 먼저 해주어야 한다. yml 파일에 반영한 모습은 아래와 같다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;416&quot; data-origin-height=&quot;168&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/03Hgb/btsGfgHRYXZ/GzCkKCvVrKwvY9eJzXYpCk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/03Hgb/btsGfgHRYXZ/GzCkKCvVrKwvY9eJzXYpCk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/03Hgb/btsGfgHRYXZ/GzCkKCvVrKwvY9eJzXYpCk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F03Hgb%2FbtsGfgHRYXZ%2FGzCkKCvVrKwvY9eJzXYpCk%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;416&quot; height=&quot;168&quot; data-origin-width=&quot;416&quot; data-origin-height=&quot;168&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;a href=&quot;https://velog.io/@excellent/Github-Action-Context&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://velog.io/@excellent/Github-Action-Context&lt;/a&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;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;&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;</description>
      <category>Computer Science/호기심 해결</category>
      <author>dr.meteor</author>
      <guid isPermaLink="true">https://thewayaboutme.tistory.com/738</guid>
      <comments>https://thewayaboutme.tistory.com/738#entry738comment</comments>
      <pubDate>Sun, 31 Mar 2024 08:41:33 +0900</pubDate>
    </item>
    <item>
      <title>21년도에 스파크 실시간 처리 영상 남겨둔 것</title>
      <link>https://thewayaboutme.tistory.com/732</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure data-ke-type=&quot;video&quot; data-ke-style=&quot;alignCenter&quot; data-video-host=&quot;kakaotv&quot; data-video-url=&quot;https://tv.kakao.com/v/445171913&quot; data-video-thumbnail=&quot;https://scrap.kakaocdn.net/dn/RK4TN/hyVxAqsapt/zYnfxzCgeRNFwnPsJa6I80/img.jpg?width=1298&amp;amp;height=694&amp;amp;face=0_0_1298_694,https://scrap.kakaocdn.net/dn/kTZvT/hyVxAxdpln/6kjPh9cvljVNwCVSsi3rH1/img.jpg?width=1298&amp;amp;height=694&amp;amp;face=0_0_1298_694&quot; data-video-width=&quot;860&quot; data-video-height=&quot;460&quot; data-video-origin-width=&quot;860&quot; data-video-origin-height=&quot;460&quot; data-ke-mobilestyle=&quot;widthContent&quot; data-video-title=&quot;'A seeker after truth'에서 업로드한 동영상&quot; data-video-play-service=&quot;daum_tistory&quot; data-original-url=&quot;&quot;&gt;&lt;iframe src=&quot;https://play-tv.kakao.com/embed/player/cliplink/445171913?service=daum_tistory&quot; width=&quot;860&quot; height=&quot;460&quot; frameborder=&quot;0&quot; allowfullscreen=&quot;true&quot;&gt;&lt;/iframe&gt;
&lt;figcaption style=&quot;display: none;&quot;&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Data/hadoop ecosystem</category>
      <author>dr.meteor</author>
      <guid isPermaLink="true">https://thewayaboutme.tistory.com/732</guid>
      <comments>https://thewayaboutme.tistory.com/732#entry732comment</comments>
      <pubDate>Sat, 9 Mar 2024 20:46:06 +0900</pubDate>
    </item>
    <item>
      <title>데이터 재전처리 과정에서 발견한 것들</title>
      <link>https://thewayaboutme.tistory.com/731</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;- 면수는 그냥 물이랑 마찬가진데 미리 전처리할걸 후회됨...&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 한 컵을 1C 로 표현한 것도 발견. 국자'란 단위도 있음. 또 밥 한 '공기' 도. tb란 단위도. ea/EA 도 있음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 파프리카 &quot;각각 1/2개씩&quot; 이런거 표현 어케하나 싶음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &quot;야채 절임물&quot; 이것도 판매하는 재료 아닌데 어쩌냐&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 당근 단위로 '덩이'도 있다.. 심지어 3/1 덩이라고 분수 잘못씀ㅎㅎ;;;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;- 아래와 같은 '혼합장' 재료로 인식하면.. 없는 재료라서...ㅠㅠㅠㅠ&lt;/p&gt;
&lt;div style=&quot;background-color: #1f1f1f; color: #cccccc;&quot;&gt;
&lt;div&gt;&lt;span style=&quot;color: #4ec9b0;&quot;&gt;콩나물 300g 끓는물에 3분데쳐 냉장고에서 차게 식힌다.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #4ec9b0;&quot;&gt;혼합장 1/2T, 소금 1/2t, 깨소금 1T, 참기름 1T, 다진대파 2T넣고 무친다.&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #4ec9b0;&quot;&gt;시금치나물&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #4ec9b0;&quot;&gt;시금치 300g 데쳐 물기 꼭짜주고,&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #4ec9b0;&quot;&gt;*혼합장 1/2T, 소금 1/2t, 깨소금 1T, 참기름 1T넣고 무쳐준다.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #4ec9b0;&quot;&gt;*혼합장= 국간장:멸치액젓:참치액 1:1:1로 섞어서 써요.&lt;/span&gt;&lt;/div&gt;
&lt;/div&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;&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;&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;&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;&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;&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;&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;&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;&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;&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;&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;&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;&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;&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;&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;&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;&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;&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;&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;&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;&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;&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;&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;&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;&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;&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;&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;&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;&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;&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;&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;&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;&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;</description>
      <category>Projects/자린고비</category>
      <author>dr.meteor</author>
      <guid isPermaLink="true">https://thewayaboutme.tistory.com/731</guid>
      <comments>https://thewayaboutme.tistory.com/731#entry731comment</comments>
      <pubDate>Sun, 3 Mar 2024 14:18:42 +0900</pubDate>
    </item>
    <item>
      <title>&amp;lt;Apache Airflow 기반의 데이터 파이프라인&amp;gt; 6,8,14단원 메모</title>
      <link>https://thewayaboutme.tistory.com/715</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;8단원&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코드 자체가 좋음 이를테면 yield, 에러 및 예외처리 파트 등. 그리고 파이썬 패키지 만드는 방법 다루고 있는.. 챕터다.&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;a href=&quot;https://github.com/K9Ns/data-pipelines-with-apache-airflow/blob/main/chapter08/dags/custom/ranking.py&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://github.com/K9Ns/data-pipelines-with-apache-airflow/blob/main/chapter08/dags/custom/ranking.py&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이를테면 위 코드에서 pd.NamedAgg란 클래스는 처음봄!&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;logger&amp;nbsp;=&amp;nbsp;logging.getLogger(__name__)&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;&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;&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;&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;&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;&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;&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;&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;&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;&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;&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;&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;&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;&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;&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;&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;&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;&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;&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;&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;&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;&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;&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;&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;&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;&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;&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;&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;&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;&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;&amp;nbsp;&lt;/p&gt;</description>
      <category>Data/데엔 데브코스 TIL</category>
      <author>dr.meteor</author>
      <guid isPermaLink="true">https://thewayaboutme.tistory.com/715</guid>
      <comments>https://thewayaboutme.tistory.com/715#entry715comment</comments>
      <pubDate>Fri, 26 Jan 2024 20:38:33 +0900</pubDate>
    </item>
  </channel>
</rss>