<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>Stack by Stack</title>
    <link>https://itdar.tistory.com/</link>
    <description></description>
    <language>ko</language>
    <pubDate>Wed, 19 Aug 2026 13:40:28 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>Ginjoe</managingEditor>
    <image>
      <title>Stack by Stack</title>
      <url>https://tistory1.daumcdn.net/tistory/2941879/attach/89e7fd5892954f779c65c9222fba77d4</url>
      <link>https://itdar.tistory.com</link>
    </image>
    <item>
      <title>태국에도 사주가 있다 &amp;mdash; 요일부터 시작하는 태국 점성술 탁사</title>
      <link>https://itdar.tistory.com/439</link>
      <description>&lt;div style=&quot;max-width:720px;margin:0 auto;line-height:1.8;font-size:16px&quot;&gt;

&lt;div style=&quot;display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:6px 16px;margin:18px 0;padding:10px 14px;background:#eef2ff;border:1px solid #c9d4f5;border-radius:12px;font-size:14px&quot;&gt;
&lt;span style=&quot;color:#666&quot;&gt;결과 이미지로 저장해서 공유할 수 있어요:&lt;/span&gt;
&lt;a href=&quot;https://utils.im/ko/thai-astrology&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; style=&quot;color:#3b63e0;font-weight:600;text-decoration:none;white-space:nowrap&quot;&gt;태국 점성술 (탁사) 계산기 →&lt;/a&gt;
&lt;/div&gt;
  

&lt;p&gt;태국에서 점을 보러 가면 생년월일보다 먼저 묻는 게 있어요.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;무슨 요일에 태어났어요?&lt;/b&gt;&lt;br&gt;
한국에서 태어난 시각을 묻는 자리에, 태국은 요일을 묻습니다.&lt;br&gt;
모른다고 하면 그 자리에서 달력을 꺼내 찾아 줘요. 요일을 모르면 아무것도 시작되지 않거든요.&lt;/p&gt;

&lt;blockquote style=&quot;border-left:4px solid #3b63e0;margin:16px 0;padding:8px 16px;background:#f5f7ff&quot;&gt;
&lt;b&gt;요약&lt;/b&gt;&lt;br&gt;
· 태국 점성술은 별자리가 아니라 &lt;b&gt;태어난 요일&lt;/b&gt;에서 시작해요&lt;br&gt;
· 요일마다 주성이 있고, 거기서 &lt;b&gt;탁사 8궁&lt;/b&gt;이 돌면서 색·방위·이름의 글자를 정합니다&lt;br&gt;
· 하루가 자정이 아니라 &lt;b&gt;새벽 6시&lt;/b&gt;에 바뀌고, 수요일만 낮·밤이 다른 날이에요&lt;br&gt;
· 사주와 계보가 달라요 — 사주는 중국·간지·오행, 태국은 인도·행성·요일신&lt;br&gt;
· 널리 도는 「요일별 금기색」 표는 따로 전해진 목록이 아니라 &lt;b&gt;탁사 배치의 결과&lt;/b&gt;예요
&lt;/blockquote&gt;

&lt;h3 style=&quot;margin-top:32px&quot;&gt;요일이 사람을 가른다&lt;/h3&gt;

&lt;p&gt;이건 점집 안에서 끝나는 이야기가 아니에요. 절에 가면 여덟 개의 불상이 나란히 서 있고,
사람들은 자기 요일 앞에서만 초를 켭니다. 병원과 관공서에는 요일마다 정해진 색의 유니폼이 있고,
국왕의 탄생 요일 색이 국가 행사의 색이 돼요. 태국 사람에게 요일은 달력의 눈금이 아니라
&lt;b&gt;자기가 속한 칸&lt;/b&gt;이에요.&lt;/p&gt;

&lt;p&gt;그 칸을 규칙으로 만든 체계가 &lt;b&gt;탁사(ทักษา)&lt;/b&gt;입니다.
사주가 태어난 순간을 여덟 글자로 옮기는 기술이라면,
탁사는 태어난 요일에서 여덟 영역을 배치하는 기술이에요.&lt;/p&gt;

&lt;h3 style=&quot;margin-top:32px&quot;&gt;인도에서 와서 태국에서 굳었다&lt;/h3&gt;

&lt;p&gt;뼈대는 인도의 조티샤예요. 크메르 제국을 거쳐 들어오면서 항성황도 방식, 열두 라시,
스물일곱 낙샤트라가 그대로 따라왔어요. 지금도 태국 달력의 별자리는 서양 별자리보다
약 &lt;b&gt;24일 늦게&lt;/b&gt; 시작합니다. 세차운동을 보정하지 않기 때문이에요.&lt;/p&gt;

&lt;p&gt;여기에 태국 현지의 요일 신앙과 상좌부 불교가 얹혔어요. 요일마다 불상 자세가 배정되고
(토요일은 나가가 덮어 주는 나크쁘록, 목요일은 좌선하는 사마티), 요일마다 외우는 경의 횟수도
달라졌습니다. 조티샤에는 없던 층이에요.&lt;/p&gt;

&lt;p&gt;연도 표기도 갈렸어요. 태국은 지금도 &lt;b&gt;불기(พ.ศ.)&lt;/b&gt;를 씁니다. 서기에 543을 더한 숫자예요.
해가 바뀌는 시점도 1월 1일이 아니라 송끄란 무렵인 4월 중순이라, 1월에 태어난 사람의 띠가
서기 기준과 한 칸 어긋나요. 입춘 전에 태어나면 작년 띠가 되는 사주의 사정과 같은 종류의 차이입니다.&lt;/p&gt;

&lt;h3 style=&quot;margin-top:32px&quot;&gt;탁사 — 여덟 행성, 여덟 영역&lt;/h3&gt;

&lt;p&gt;탁사는 여덟 행성을 삶의 여덟 영역에 앉히는 장치예요. 영역 이름이 곧 내용입니다.&lt;/p&gt;

&lt;table style=&quot;width:100%;border-collapse:collapse;margin:14px 0;font-size:14.5px&quot;&gt;
&lt;tr style=&quot;background:#f5f7ff&quot;&gt;
&lt;td style=&quot;border:1px solid #e3e6ef;padding:8px 10px&quot;&gt;&lt;b&gt;บริวาร&lt;/b&gt; 보리완&lt;/td&gt;
&lt;td style=&quot;border:1px solid #e3e6ef;padding:8px 10px&quot;&gt;따르는 사람·측근&lt;/td&gt;
&lt;td style=&quot;border:1px solid #e3e6ef;padding:8px 10px&quot;&gt;&lt;b&gt;มูละ&lt;/b&gt; 물라&lt;/td&gt;
&lt;td style=&quot;border:1px solid #e3e6ef;padding:8px 10px&quot;&gt;재산·기반&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;border:1px solid #e3e6ef;padding:8px 10px&quot;&gt;&lt;b&gt;อายุ&lt;/b&gt; 아유&lt;/td&gt;
&lt;td style=&quot;border:1px solid #e3e6ef;padding:8px 10px&quot;&gt;수명·건강&lt;/td&gt;
&lt;td style=&quot;border:1px solid #e3e6ef;padding:8px 10px&quot;&gt;&lt;b&gt;อุตสาหะ&lt;/b&gt; 웃사하&lt;/td&gt;
&lt;td style=&quot;border:1px solid #e3e6ef;padding:8px 10px&quot;&gt;노력·추진력&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background:#f5f7ff&quot;&gt;
&lt;td style=&quot;border:1px solid #e3e6ef;padding:8px 10px&quot;&gt;&lt;b&gt;เดช&lt;/b&gt; 뎃&lt;/td&gt;
&lt;td style=&quot;border:1px solid #e3e6ef;padding:8px 10px&quot;&gt;권위·명성&lt;/td&gt;
&lt;td style=&quot;border:1px solid #e3e6ef;padding:8px 10px&quot;&gt;&lt;b&gt;มนตรี&lt;/b&gt; 몬뜨리&lt;/td&gt;
&lt;td style=&quot;border:1px solid #e3e6ef;padding:8px 10px&quot;&gt;귀인·후원자&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;border:1px solid #e3e6ef;padding:8px 10px&quot;&gt;&lt;b&gt;ศรี&lt;/b&gt; 시&lt;/td&gt;
&lt;td style=&quot;border:1px solid #e3e6ef;padding:8px 10px&quot;&gt;재복·행운&lt;/td&gt;
&lt;td style=&quot;border:1px solid #e3e6ef;padding:8px 10px;color:#d64545&quot;&gt;&lt;b&gt;กาลกิณี&lt;/b&gt; 가라끼니&lt;/td&gt;
&lt;td style=&quot;border:1px solid #e3e6ef;padding:8px 10px;color:#d64545&quot;&gt;흉 — 피하는 자리&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;

&lt;p&gt;요일은 일곱인데 자리는 여덟이에요. 이 어긋남을 태국은 &lt;b&gt;라후(ราหู)&lt;/b&gt;로 메웁니다.
달의 교점이자 일식을 일으킨다고 여겨진 그림자 행성이에요. 라후에게는 &lt;b&gt;수요일 밤&lt;/b&gt;이 배당됐어요.
그래서 수요일에 태어난 사람만 낮과 밤에 따라 완전히 다른 사람이 됩니다 — 주성도, 색도,
이름에 쓰면 안 되는 글자도 갈려요.&lt;/p&gt;

&lt;p&gt;배치는 단순해요. 자기 요일의 주성 자리에 보리완을 놓고, 정해진 수레바퀴 순서대로
시계 방향으로 나머지를 채우면 끝입니다. 아래는 금요일생의 배치예요.&lt;/p&gt;

&lt;figure style=&quot;margin:16px 0;padding:16px 12px 10px;border:1px solid #e3e6ef;border-radius:12px;background:#fafbff&quot;&gt;
&lt;svg viewBox=&quot;0 0 640 330&quot; role=&quot;img&quot; aria-label=&quot;금요일생의 탁사 배치. 금성 자리에 보리완이 놓이고 시계 방향으로 태양은 아유, 달은 뎃, 화성은 시, 수성은 물라, 토성은 웃사하, 목성은 몬뜨리, 라후는 가라끼니가 된다.&quot; style=&quot;display:block;width:100%;height:auto&quot;&gt;
  &lt;circle cx=&quot;320&quot; cy=&quot;165&quot; r=&quot;95&quot; fill=&quot;none&quot; stroke=&quot;#ccd2e3&quot; stroke-width=&quot;1.5&quot;/&gt;
  &lt;text x=&quot;320&quot; y=&quot;160&quot; fill=&quot;#3b63e0&quot; font-size=&quot;16&quot; font-weight=&quot;700&quot; text-anchor=&quot;middle&quot;&gt;금요일생&lt;/text&gt;
  &lt;text x=&quot;320&quot; y=&quot;182&quot; fill=&quot;#8a90a3&quot; font-size=&quot;13&quot; text-anchor=&quot;middle&quot;&gt;주성 금성&lt;/text&gt;
  &lt;circle cx=&quot;320&quot; cy=&quot;70&quot; r=&quot;7&quot; fill=&quot;#e2453c&quot;/&gt;
  &lt;text x=&quot;320&quot; y=&quot;34&quot; fill=&quot;#4a4f5e&quot; font-size=&quot;13&quot; text-anchor=&quot;middle&quot;&gt;태양 · 아유&lt;/text&gt;
  &lt;circle cx=&quot;387&quot; cy=&quot;98&quot; r=&quot;7&quot; fill=&quot;#f2c744&quot;/&gt;
  &lt;text x=&quot;432&quot; y=&quot;66&quot; fill=&quot;#4a4f5e&quot; font-size=&quot;13&quot;&gt;달 · 뎃&lt;/text&gt;
  &lt;circle cx=&quot;415&quot; cy=&quot;165&quot; r=&quot;9&quot; fill=&quot;#ef7ea6&quot;/&gt;
  &lt;text x=&quot;432&quot; y=&quot;163&quot; fill=&quot;#3b63e0&quot; font-size=&quot;13&quot; font-weight=&quot;700&quot;&gt;화성 · 시&lt;/text&gt;
  &lt;text x=&quot;432&quot; y=&quot;181&quot; fill=&quot;#8a90a3&quot; font-size=&quot;12&quot;&gt;행운색 분홍&lt;/text&gt;
  &lt;circle cx=&quot;387&quot; cy=&quot;232&quot; r=&quot;7&quot; fill=&quot;#2fa35b&quot;/&gt;
  &lt;text x=&quot;432&quot; y=&quot;277&quot; fill=&quot;#4a4f5e&quot; font-size=&quot;13&quot;&gt;수성 · 물라&lt;/text&gt;
  &lt;circle cx=&quot;320&quot; cy=&quot;260&quot; r=&quot;7&quot; fill=&quot;#7d5bbe&quot;/&gt;
  &lt;text x=&quot;320&quot; y=&quot;315&quot; fill=&quot;#4a4f5e&quot; font-size=&quot;13&quot; text-anchor=&quot;middle&quot;&gt;토성 · 웃사하&lt;/text&gt;
  &lt;circle cx=&quot;253&quot; cy=&quot;232&quot; r=&quot;7&quot; fill=&quot;#f4801a&quot;/&gt;
  &lt;text x=&quot;208&quot; y=&quot;277&quot; fill=&quot;#4a4f5e&quot; font-size=&quot;13&quot; text-anchor=&quot;end&quot;&gt;목성 · 몬뜨리&lt;/text&gt;
  &lt;circle cx=&quot;225&quot; cy=&quot;165&quot; r=&quot;9&quot; fill=&quot;#6f7480&quot;/&gt;
  &lt;text x=&quot;208&quot; y=&quot;163&quot; fill=&quot;#d64545&quot; font-size=&quot;13&quot; font-weight=&quot;700&quot; text-anchor=&quot;end&quot;&gt;라후 · 가라끼니&lt;/text&gt;
  &lt;text x=&quot;208&quot; y=&quot;181&quot; fill=&quot;#8a90a3&quot; font-size=&quot;12&quot; text-anchor=&quot;end&quot;&gt;금기색 회색&lt;/text&gt;
  &lt;circle cx=&quot;253&quot; cy=&quot;98&quot; r=&quot;7&quot; fill=&quot;#3d8bd6&quot;/&gt;
  &lt;text x=&quot;208&quot; y=&quot;66&quot; fill=&quot;#4a4f5e&quot; font-size=&quot;13&quot; text-anchor=&quot;end&quot;&gt;금성 · 보리완&lt;/text&gt;
&lt;/svg&gt;
&lt;figcaption style=&quot;margin:10px 4px 2px;color:#8a90a3;font-size:12.5px&quot;&gt;수레바퀴 순서는 태양·달·화성·수성·토성·목성·라후·금성. 시작점만 요일마다 달라서, 같은 여덟 자리가 사람마다 다른 행성에 얹혀요.&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;여기서 색이 나옵니다. 행성마다 색이 있으니, &lt;b&gt;시(ศรี) 자리에 온 행성의 색이 행운색&lt;/b&gt;이고
&lt;b&gt;가라끼니에 온 행성의 색이 금기색&lt;/b&gt;이에요. 일요일생은 가라끼니가 금성이라 파랑을 피하고,
목요일생은 토성이라 검정과 보라를 피합니다. 태국에서 흔히 도는 요일별 금기색 표는
따로 전해 내려온 목록이 아니라, 이 배치를 읽은 결과예요.&lt;/p&gt;

&lt;div style=&quot;display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:6px 16px;margin:0 0 18px;padding:10px 14px;background:#eef2ff;border:1px solid #c9d4f5;border-radius:12px;font-size:14px&quot;&gt;
&lt;span style=&quot;color:#666&quot;&gt;내 요일과 배치부터 확인:&lt;/span&gt;
&lt;a href=&quot;https://utils.im/ko/thai-astrology&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; style=&quot;color:#3b63e0;font-weight:600;text-decoration:none;white-space:nowrap&quot;&gt;태국 점성술 (탁사) 계산기 →&lt;/a&gt;
&lt;/div&gt;

&lt;h3 style=&quot;margin-top:32px&quot;&gt;하루가 새벽 여섯 시에 바뀐다&lt;/h3&gt;

&lt;p&gt;요일이 첫 축이다 보니, 요일을 &lt;b&gt;언제 가르느냐&lt;/b&gt;가 이 체계에서 가장 예민한 지점이에요.
태국 전통에서 하루는 자정이 아니라 해뜰녘에 바뀝니다. 실무에서는 대략 06시로 잡아요.
화요일 새벽 3시에 태어난 사람은 화요일생이 아니라 &lt;b&gt;월요일생&lt;/b&gt;입니다.&lt;/p&gt;

&lt;p&gt;수요일에는 두 번째 경계가 하나 더 붙어요. 18시가 지나면 라후의 시간이에요.&lt;/p&gt;

&lt;figure style=&quot;margin:16px 0;padding:16px 12px 10px;border:1px solid #e3e6ef;border-radius:12px;background:#fafbff&quot;&gt;
&lt;svg viewBox=&quot;0 0 640 210&quot; role=&quot;img&quot; aria-label=&quot;달력상 하루는 자정부터 자정까지지만, 태국식 하루는 새벽 6시에 시작해 다음 날 새벽 6시에 끝난다. 수요일은 18시부터 라후의 시간으로 다시 갈린다.&quot; style=&quot;display:block;width:100%;height:auto&quot;&gt;
  &lt;text x=&quot;30&quot; y=&quot;30&quot; fill=&quot;#8a90a3&quot; font-size=&quot;13&quot;&gt;달력상 하루&lt;/text&gt;
  &lt;rect x=&quot;30&quot; y=&quot;40&quot; width=&quot;580&quot; height=&quot;28&quot; rx=&quot;6&quot; fill=&quot;#e8ecf7&quot; stroke=&quot;#ccd2e3&quot;/&gt;
  &lt;text x=&quot;320&quot; y=&quot;59&quot; fill=&quot;#4a4f5e&quot; font-size=&quot;14&quot; text-anchor=&quot;middle&quot;&gt;화요일&lt;/text&gt;
  &lt;text x=&quot;30&quot; y=&quot;102&quot; fill=&quot;#8a90a3&quot; font-size=&quot;13&quot;&gt;태국식 하루&lt;/text&gt;
  &lt;rect x=&quot;30&quot; y=&quot;112&quot; width=&quot;145&quot; height=&quot;28&quot; rx=&quot;6&quot; fill=&quot;#e8ecf7&quot; stroke=&quot;#ccd2e3&quot;/&gt;
  &lt;text x=&quot;102&quot; y=&quot;131&quot; fill=&quot;#8a90a3&quot; font-size=&quot;13&quot; text-anchor=&quot;middle&quot;&gt;월요일&lt;/text&gt;
  &lt;rect x=&quot;175&quot; y=&quot;112&quot; width=&quot;435&quot; height=&quot;28&quot; rx=&quot;6&quot; fill=&quot;#3b63e0&quot;/&gt;
  &lt;text x=&quot;392&quot; y=&quot;131&quot; fill=&quot;#ffffff&quot; font-size=&quot;14&quot; text-anchor=&quot;middle&quot;&gt;화요일&lt;/text&gt;
  &lt;text x=&quot;30&quot; y=&quot;174&quot; fill=&quot;#8a90a3&quot; font-size=&quot;13&quot;&gt;수요일이라면&lt;/text&gt;
  &lt;rect x=&quot;175&quot; y=&quot;182&quot; width=&quot;290&quot; height=&quot;22&quot; rx=&quot;5&quot; fill=&quot;#dff0e4&quot; stroke=&quot;#a8d5b6&quot;/&gt;
  &lt;text x=&quot;320&quot; y=&quot;198&quot; fill=&quot;#2f7a4a&quot; font-size=&quot;12.5&quot; text-anchor=&quot;middle&quot;&gt;수요일 낮 · 수성&lt;/text&gt;
  &lt;rect x=&quot;465&quot; y=&quot;182&quot; width=&quot;145&quot; height=&quot;22&quot; rx=&quot;5&quot; fill=&quot;#e6e8ec&quot; stroke=&quot;#b9bec8&quot;/&gt;
  &lt;text x=&quot;537&quot; y=&quot;198&quot; fill=&quot;#55596a&quot; font-size=&quot;12.5&quot; text-anchor=&quot;middle&quot;&gt;라후&lt;/text&gt;
  &lt;line x1=&quot;175&quot; y1=&quot;34&quot; x2=&quot;175&quot; y2=&quot;206&quot; stroke=&quot;#d64545&quot; stroke-width=&quot;1&quot; stroke-dasharray=&quot;3 3&quot;/&gt;
  &lt;text x=&quot;175&quot; y=&quot;20&quot; fill=&quot;#d64545&quot; font-size=&quot;12.5&quot; text-anchor=&quot;middle&quot;&gt;06:00&lt;/text&gt;
  &lt;line x1=&quot;465&quot; y1=&quot;176&quot; x2=&quot;465&quot; y2=&quot;206&quot; stroke=&quot;#d64545&quot; stroke-width=&quot;1&quot; stroke-dasharray=&quot;3 3&quot;/&gt;
  &lt;text x=&quot;465&quot; y=&quot;170&quot; fill=&quot;#d64545&quot; font-size=&quot;12.5&quot; text-anchor=&quot;middle&quot;&gt;18:00&lt;/text&gt;
&lt;/svg&gt;
&lt;figcaption style=&quot;margin:10px 4px 2px;color:#8a90a3;font-size:12.5px&quot;&gt;새벽 6시 이전 출생은 앞 요일로 넘어가요. 수요일만 18시에 한 번 더 갈려서 여덟 번째 날인 라후가 생깁니다.&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;사주에도 같은 성격의 경계가 있죠. 자시를 어디서 끊을지, 야자시를 인정할지로 학파가 갈리고,
해의 경계는 1월 1일이 아니라 입춘이에요. 두 체계 모두 달력이 말하는 날짜와 명리가 말하는 날짜가
다르고, 계산기끼리 결과가 갈리는 자리도 대개 여기입니다.&lt;/p&gt;

&lt;h3 style=&quot;margin-top:32px&quot;&gt;이름의 글자가 규칙이 되는 순간&lt;/h3&gt;

&lt;p&gt;탁사가 태국 사회에 남긴 가장 실용적인 흔적은 색이 아니라 &lt;b&gt;이름&lt;/b&gt;이에요.
태국 자음 42자와 모음 기호는 여덟 개의 자음군으로 나뉘고, 각 군이 행성 하나에 붙어 있어요.
그러니 배치가 끝나면 그 사람에게는 「이름에 쓰면 안 되는 글자 목록」이 생깁니다.
가라끼니 자리에 온 행성의 자음군이에요.&lt;/p&gt;

&lt;table style=&quot;width:100%;border-collapse:collapse;margin:14px 0;font-size:14.5px&quot;&gt;
&lt;tr style=&quot;background:#f5f7ff&quot;&gt;
&lt;th style=&quot;border:1px solid #e3e6ef;padding:8px 10px;text-align:left&quot;&gt;요일&lt;/th&gt;
&lt;th style=&quot;border:1px solid #e3e6ef;padding:8px 10px;text-align:left&quot;&gt;가라끼니 행성&lt;/th&gt;
&lt;th style=&quot;border:1px solid #e3e6ef;padding:8px 10px;text-align:left&quot;&gt;피하는 색&lt;/th&gt;
&lt;th style=&quot;border:1px solid #e3e6ef;padding:8px 10px;text-align:left&quot;&gt;피하는 글자&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;border:1px solid #e3e6ef;padding:8px 10px&quot;&gt;일요일&lt;/td&gt;&lt;td style=&quot;border:1px solid #e3e6ef;padding:8px 10px&quot;&gt;금성&lt;/td&gt;&lt;td style=&quot;border:1px solid #e3e6ef;padding:8px 10px&quot;&gt;하늘색·파랑&lt;/td&gt;&lt;td style=&quot;border:1px solid #e3e6ef;padding:8px 10px&quot;&gt;ศ ษ ส ห ฬ ฮ&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;border:1px solid #e3e6ef;padding:8px 10px&quot;&gt;월요일&lt;/td&gt;&lt;td style=&quot;border:1px solid #e3e6ef;padding:8px 10px&quot;&gt;태양&lt;/td&gt;&lt;td style=&quot;border:1px solid #e3e6ef;padding:8px 10px&quot;&gt;빨강&lt;/td&gt;&lt;td style=&quot;border:1px solid #e3e6ef;padding:8px 10px&quot;&gt;อ + &lt;b&gt;모든 모음 기호&lt;/b&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;border:1px solid #e3e6ef;padding:8px 10px&quot;&gt;화요일&lt;/td&gt;&lt;td style=&quot;border:1px solid #e3e6ef;padding:8px 10px&quot;&gt;달&lt;/td&gt;&lt;td style=&quot;border:1px solid #e3e6ef;padding:8px 10px&quot;&gt;노랑·크림&lt;/td&gt;&lt;td style=&quot;border:1px solid #e3e6ef;padding:8px 10px&quot;&gt;ก ข ค ฆ ง&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;border:1px solid #e3e6ef;padding:8px 10px&quot;&gt;수요일 낮&lt;/td&gt;&lt;td style=&quot;border:1px solid #e3e6ef;padding:8px 10px&quot;&gt;화성&lt;/td&gt;&lt;td style=&quot;border:1px solid #e3e6ef;padding:8px 10px&quot;&gt;분홍&lt;/td&gt;&lt;td style=&quot;border:1px solid #e3e6ef;padding:8px 10px&quot;&gt;จ ฉ ช ซ ฌ ญ&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;border:1px solid #e3e6ef;padding:8px 10px&quot;&gt;수요일 밤&lt;/td&gt;&lt;td style=&quot;border:1px solid #e3e6ef;padding:8px 10px&quot;&gt;목성&lt;/td&gt;&lt;td style=&quot;border:1px solid #e3e6ef;padding:8px 10px&quot;&gt;주황&lt;/td&gt;&lt;td style=&quot;border:1px solid #e3e6ef;padding:8px 10px&quot;&gt;บ ป ผ ฝ พ ฟ ภ ม&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;border:1px solid #e3e6ef;padding:8px 10px&quot;&gt;목요일&lt;/td&gt;&lt;td style=&quot;border:1px solid #e3e6ef;padding:8px 10px&quot;&gt;토성&lt;/td&gt;&lt;td style=&quot;border:1px solid #e3e6ef;padding:8px 10px&quot;&gt;검정·보라&lt;/td&gt;&lt;td style=&quot;border:1px solid #e3e6ef;padding:8px 10px&quot;&gt;ด ต ถ ท ธ น&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;border:1px solid #e3e6ef;padding:8px 10px&quot;&gt;금요일&lt;/td&gt;&lt;td style=&quot;border:1px solid #e3e6ef;padding:8px 10px&quot;&gt;라후&lt;/td&gt;&lt;td style=&quot;border:1px solid #e3e6ef;padding:8px 10px&quot;&gt;회색·연기색&lt;/td&gt;&lt;td style=&quot;border:1px solid #e3e6ef;padding:8px 10px&quot;&gt;ย ร ล ว&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;border:1px solid #e3e6ef;padding:8px 10px&quot;&gt;토요일&lt;/td&gt;&lt;td style=&quot;border:1px solid #e3e6ef;padding:8px 10px&quot;&gt;수성&lt;/td&gt;&lt;td style=&quot;border:1px solid #e3e6ef;padding:8px 10px&quot;&gt;초록&lt;/td&gt;&lt;td style=&quot;border:1px solid #e3e6ef;padding:8px 10px&quot;&gt;ฎ ฏ ฐ ฑ ฒ ณ&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;

&lt;p&gt;금요일생은 ย·ร·ล·ว 를 피해요. 태국어에서 이 넷은 흔하디흔한 글자라 이름 후보 절반이 걸러집니다.
더 극단적인 건 &lt;b&gt;월요일생&lt;/b&gt;이에요. 월요일생의 가라끼니는 태양인데, 태양군에는 자음 อ 와 함께
&lt;b&gt;모든 모음 기호&lt;/b&gt;가 들어 있어요. 그래서 월요일에 태어난 아이의 이름은 모음 기호 없이
자음만으로 짓는 관습이 있습니다. 태국 이름 중에 모음 표기가 하나도 없는 이름들이 그래서 생겨요.&lt;/p&gt;

&lt;p&gt;반대 방향도 있어요. 시(재복)와 몬뜨리(귀인) 군의 글자는 이름에 넣으면 좋다고 봅니다.
태국에서 개명이 흔하고 절차가 무겁지 않은 배경에 이 규칙이 있어요 — 일이 안 풀리면
이름을 바꾸는 게 납득 가능한 선택지인 셈입니다.&lt;/p&gt;

&lt;h3 style=&quot;margin-top:32px&quot;&gt;사주와 어디서 갈라지나&lt;/h3&gt;

&lt;table style=&quot;width:100%;border-collapse:collapse;margin:14px 0;font-size:14.5px&quot;&gt;
&lt;tr style=&quot;background:#f5f7ff&quot;&gt;
&lt;th style=&quot;border:1px solid #e3e6ef;padding:8px 10px;text-align:left&quot;&gt;&lt;/th&gt;
&lt;th style=&quot;border:1px solid #e3e6ef;padding:8px 10px;text-align:left&quot;&gt;사주&lt;/th&gt;
&lt;th style=&quot;border:1px solid #e3e6ef;padding:8px 10px;text-align:left&quot;&gt;태국식 탁사&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;border:1px solid #e3e6ef;padding:8px 10px&quot;&gt;&lt;b&gt;계보&lt;/b&gt;&lt;/td&gt;&lt;td style=&quot;border:1px solid #e3e6ef;padding:8px 10px&quot;&gt;중국&lt;/td&gt;&lt;td style=&quot;border:1px solid #e3e6ef;padding:8px 10px&quot;&gt;인도 조티샤 → 크메르 → 태국&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;border:1px solid #e3e6ef;padding:8px 10px&quot;&gt;&lt;b&gt;재료&lt;/b&gt;&lt;/td&gt;&lt;td style=&quot;border:1px solid #e3e6ef;padding:8px 10px&quot;&gt;천간·지지 여덟 글자&lt;/td&gt;&lt;td style=&quot;border:1px solid #e3e6ef;padding:8px 10px&quot;&gt;여덟 행성과 요일신&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;border:1px solid #e3e6ef;padding:8px 10px&quot;&gt;&lt;b&gt;이론&lt;/b&gt;&lt;/td&gt;&lt;td style=&quot;border:1px solid #e3e6ef;padding:8px 10px&quot;&gt;음양오행 상생상극·십신&lt;/td&gt;&lt;td style=&quot;border:1px solid #e3e6ef;padding:8px 10px&quot;&gt;행성의 성격과 여덟 궁&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;border:1px solid #e3e6ef;padding:8px 10px&quot;&gt;&lt;b&gt;해의 경계&lt;/b&gt;&lt;/td&gt;&lt;td style=&quot;border:1px solid #e3e6ef;padding:8px 10px&quot;&gt;입춘&lt;/td&gt;&lt;td style=&quot;border:1px solid #e3e6ef;padding:8px 10px&quot;&gt;송끄란(4월 중순)&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;border:1px solid #e3e6ef;padding:8px 10px&quot;&gt;&lt;b&gt;하루의 경계&lt;/b&gt;&lt;/td&gt;&lt;td style=&quot;border:1px solid #e3e6ef;padding:8px 10px&quot;&gt;자시(23시 전후, 학파별)&lt;/td&gt;&lt;td style=&quot;border:1px solid #e3e6ef;padding:8px 10px&quot;&gt;해뜰녘(06시)&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;border:1px solid #e3e6ef;padding:8px 10px&quot;&gt;&lt;b&gt;주 용도&lt;/b&gt;&lt;/td&gt;&lt;td style=&quot;border:1px solid #e3e6ef;padding:8px 10px&quot;&gt;궁합·대운 — 시간의 흐름&lt;/td&gt;&lt;td style=&quot;border:1px solid #e3e6ef;padding:8px 10px&quot;&gt;작명·색·택일 — 오늘의 선택&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;

&lt;p&gt;계산의 단위부터 달라요. 사주는 연·월·일·시를 각각 간지 한 쌍으로 옮겨 여덟 글자를 만들고
그 사이의 상생상극을 읽습니다. 탁사는 글자를 만들지 않아요. 요일 하나로 시작점을 정하고
여덟 자리를 배치할 뿐이에요. 대신 그 배치가 색·방위·숫자·글자처럼 &lt;b&gt;일상에서 바로 쓰는 항목&lt;/b&gt;으로
떨어집니다.&lt;/p&gt;

&lt;p&gt;하나는 인생의 곡선을 그리고, 하나는 오늘의 체크리스트를 줘요.
덧붙이면 태국에도 본격 명식이 있어요. 정사각형 열두 칸에 행성을 숫자로 적어 넣는 두앙(ดวง)인데,
이건 항성황도 천체력이 있어야 그릴 수 있습니다. 요일과 탁사는 그 앞에 놓인,
달력과 규칙만으로 닫히는 층이에요.&lt;/p&gt;

&lt;div style=&quot;display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:6px 16px;margin:18px 0;padding:10px 14px;background:#eef2ff;border:1px solid #c9d4f5;border-radius:12px;font-size:14px&quot;&gt;
&lt;span style=&quot;color:#666&quot;&gt;사주 쪽 계산도 나란히 보고 싶다면:&lt;/span&gt;
&lt;a href=&quot;https://utils.im/ko/saju&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; style=&quot;color:#3b63e0;font-weight:600;text-decoration:none;white-space:nowrap&quot;&gt;사주 명식 계산기 →&lt;/a&gt;
&lt;/div&gt;

&lt;h3 style=&quot;margin-top:32px&quot;&gt;계산기로 확인하는 순서&lt;/h3&gt;

&lt;p&gt;탁사는 손으로도 돌릴 수 있지만, 새벽 출생과 수요일 밤이 겹치면 사람이 잘 틀려요.
계산기는 그 두 경계를 먼저 처리하고 나머지를 파생시킵니다. 쓰는 순서는 셋이면 충분해요.&lt;/p&gt;

&lt;p&gt;① 생년월일과 시각을 넣어요. 시각을 모르면 체크 한 번으로 낮 12시로 계산합니다.&lt;br&gt;
② 새벽에 태어났다면 해뜰녘 규칙을 껐다 켜 보세요. 요일이 통째로 움직이는 게 보여요.&lt;br&gt;
③ 이름 칸에 태국 문자를 넣으면 글자마다 어느 자리에 걸리는지 색으로 표시되고,
가라끼니 글자 수와 점수가 나옵니다.&lt;/p&gt;

&lt;p&gt;도구가 일부러 하지 않는 것도 있어요. &lt;b&gt;로마자로 적은 이름은 판정하지 않습니다.&lt;/b&gt;
로마자 s 하나가 ส·ศ·ษ 중 무엇인지 되돌릴 방법이 없고, 이 셋은 같은 군이지만 모음 기호는
아예 다른 군이라, 철자를 찍는 순간 결과가 거짓이 돼요. 그리고 색 표를 따로 저장하지 않고
배치에서 파생시킵니다 — 표를 두 벌 두면 언젠가는 어긋나니까요.&lt;/p&gt;

&lt;div style=&quot;display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:6px 16px;margin:18px 0;padding:10px 14px;background:#eef2ff;border:1px solid #c9d4f5;border-radius:12px;font-size:14px&quot;&gt;
&lt;span style=&quot;color:#666&quot;&gt;결과 이미지로 저장해서 공유할 수 있어요:&lt;/span&gt;
&lt;a href=&quot;https://utils.im/ko/thai-astrology&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; style=&quot;color:#3b63e0;font-weight:600;text-decoration:none;white-space:nowrap&quot;&gt;태국 점성술 (탁사) 계산기 →&lt;/a&gt;
&lt;/div&gt;

&lt;p style=&quot;color:#8a90a3;font-size:14px;margin-top:24px&quot;&gt;전통 규칙을 그대로 계산한 결과예요.
어느 색이 운을 바꾼다는 근거도, 이름의 글자가 재산을 정한다는 근거도 없습니다.
다만 태국에서는 이 규칙이 사람들의 옷장과 이름과 달력을 실제로 움직여 왔고,
그 규칙이 어떻게 생겼는지는 알아 둘 만해요.&lt;/p&gt;

&lt;/div&gt;</description>
      <category>Life</category>
      <category>가라끼니</category>
      <category>탁사</category>
      <category>태국 사주</category>
      <category>태국 요일 색</category>
      <category>태국 이름 짓기</category>
      <category>태국 점성술</category>
      <author>Ginjoe</author>
      <guid isPermaLink="true">https://itdar.tistory.com/439</guid>
      <comments>https://itdar.tistory.com/439#entry439comment</comments>
      <pubDate>Tue, 18 Aug 2026 22:49:28 +0900</pubDate>
    </item>
    <item>
      <title>연봉 실수령액 계산기 &amp;mdash; 5,000만원이 통장에 352만원으로 찍히는 과정</title>
      <link>https://itdar.tistory.com/438</link>
      <description>&lt;div style=&quot;max-width:720px;margin:0 auto;line-height:1.8;font-size:16px&quot;&gt;

&lt;p&gt;연봉 5,000만원이면 12로 나눠서 &lt;b&gt;416만원&lt;/b&gt;.&lt;/p&gt;

&lt;p&gt;첫 월급날 통장에 찍히는 건 &lt;b&gt;352만원&lt;/b&gt;입니다.&lt;br&gt;
사라진 &lt;b&gt;64만원&lt;/b&gt;은 급여명세서에 항목이 여섯 개로 쪼개져 있어서 한눈에 안 들어와요.&lt;br&gt;
이 글은 그 64만원을 하나씩 뜯어봅니다.&lt;/p&gt;

&lt;blockquote style=&quot;border-left:4px solid #3b63e0;margin:16px 0;padding:8px 16px;background:#f5f7ff&quot;&gt;
&lt;b&gt;요약&lt;/b&gt;&lt;br&gt;
· 공제는 &lt;b&gt;4대 보험&lt;/b&gt;(38만 5,430원)과 &lt;b&gt;세금&lt;/b&gt;(25만 9,990원) 두 덩어리 — 합쳐 월 &lt;b&gt;64만 5,420원&lt;/b&gt;&lt;br&gt;
· 4대 보험은 요율 한 번 곱하면 끝, 소득세는 &lt;b&gt;여섯 단계&lt;/b&gt;를 거치는 계산이에요&lt;br&gt;
· 2026년은 &lt;b&gt;국민연금 요율이 오른 해&lt;/b&gt;(9% → 9.5%)라 작년과 같은 연봉이어도 실수령이 줄어듭니다&lt;br&gt;
· 계산기와 실제 명세서가 몇 만원 어긋나는 건 정상 — 매달은 &lt;b&gt;간이세액표&lt;/b&gt;로 대충 떼고 연말정산에서 확정해요
&lt;/blockquote&gt;

&lt;h3 style=&quot;margin-top:32px&quot;&gt;416만원이 352만원이 되기까지&lt;/h3&gt;

&lt;figure style=&quot;margin:16px 0;padding:16px 12px 10px;border:1px solid #e3e6ef;border-radius:12px;background:#fafbff&quot;&gt;
&lt;svg viewBox=&quot;0 0 640 210&quot; role=&quot;img&quot; aria-label=&quot;연봉 5,000만원의 세전 월급 4,166,667원과 실수령액 3,521,247원 비교. 차액인 공제 합계는 645,420원으로 세전의 15.5%.&quot; style=&quot;display:block;width:100%;height:auto&quot;&gt;
  &lt;rect x=&quot;30&quot; y=&quot;34&quot; width=&quot;580&quot; height=&quot;46&quot; rx=&quot;6&quot; fill=&quot;#e8ecf7&quot; stroke=&quot;#ccd2e3&quot;/&gt;
  &lt;text x=&quot;44&quot; y=&quot;63&quot; fill=&quot;#4a4f5e&quot; font-size=&quot;15&quot;&gt;세전 월급&lt;/text&gt;
  &lt;text x=&quot;596&quot; y=&quot;63&quot; fill=&quot;#333&quot; font-size=&quot;15&quot; text-anchor=&quot;end&quot; font-weight=&quot;600&quot;&gt;4,166,667원&lt;/text&gt;
  &lt;rect x=&quot;30&quot; y=&quot;106&quot; width=&quot;490&quot; height=&quot;46&quot; rx=&quot;6&quot; fill=&quot;#3b63e0&quot;/&gt;
  &lt;text x=&quot;44&quot; y=&quot;135&quot; fill=&quot;#ffffff&quot; font-size=&quot;15&quot;&gt;실수령액&lt;/text&gt;
  &lt;text x=&quot;506&quot; y=&quot;135&quot; fill=&quot;#ffffff&quot; font-size=&quot;15&quot; text-anchor=&quot;end&quot; font-weight=&quot;600&quot;&gt;3,521,247원&lt;/text&gt;
  &lt;line x1=&quot;520&quot; y1=&quot;106&quot; x2=&quot;520&quot; y2=&quot;180&quot; stroke=&quot;#d64545&quot; stroke-width=&quot;1&quot; stroke-dasharray=&quot;3 3&quot;/&gt;
  &lt;line x1=&quot;610&quot; y1=&quot;152&quot; x2=&quot;610&quot; y2=&quot;180&quot; stroke=&quot;#d64545&quot; stroke-width=&quot;1&quot; stroke-dasharray=&quot;3 3&quot;/&gt;
  &lt;line x1=&quot;520&quot; y1=&quot;172&quot; x2=&quot;610&quot; y2=&quot;172&quot; stroke=&quot;#d64545&quot; stroke-width=&quot;1.5&quot;/&gt;
  &lt;text x=&quot;565&quot; y=&quot;166&quot; fill=&quot;#d64545&quot; font-size=&quot;13&quot; text-anchor=&quot;middle&quot; font-weight=&quot;600&quot;&gt;645,420원&lt;/text&gt;
  &lt;text x=&quot;565&quot; y=&quot;196&quot; fill=&quot;#d64545&quot; font-size=&quot;13&quot; text-anchor=&quot;middle&quot;&gt;세전의 15.5%&lt;/text&gt;
&lt;/svg&gt;
&lt;figcaption style=&quot;margin:10px 4px 2px;color:#8a90a3;font-size:12.5px&quot;&gt;연봉 5,000만원 · 부양가족 본인 1명 · 비과세 식대 월 20만원 · 2026년 요율 기준.&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;div style=&quot;display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:6px 16px;margin:0 0 18px;padding:10px 14px;background:#eef2ff;border:1px solid #c9d4f5;border-radius:12px;font-size:14px&quot;&gt;
&lt;span style=&quot;color:#666&quot;&gt;내 연봉·부양가족·비과세액으로 바로 확인:&lt;/span&gt;
&lt;a href=&quot;https://utils.im/ko/salary&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; style=&quot;color:#3b63e0;font-weight:600;text-decoration:none;white-space:nowrap&quot;&gt;연봉 실수령액 계산기 →&lt;/a&gt;
&lt;/div&gt;

&lt;p&gt;연 기준으로는 세전 5,000만원 중 &lt;b&gt;4,225만 4,960원&lt;/b&gt;이 손에 남습니다.
공제가 연 774만 5,040원이니, 대략 &lt;b&gt;두 달치 월급&lt;/b&gt;이 통장을 스치지 않고 빠져나가는 셈이에요.&lt;/p&gt;

&lt;h3 style=&quot;margin-top:32px&quot;&gt;64만원의 정체 — 항목별로&lt;/h3&gt;

&lt;figure style=&quot;margin:16px 0;padding:16px 12px 10px;border:1px solid #e3e6ef;border-radius:12px;background:#fafbff&quot;&gt;
&lt;svg viewBox=&quot;0 0 640 272&quot; role=&quot;img&quot; aria-label=&quot;월 공제 항목별 금액: 소득세 236,360원, 국민연금 188,410원, 건강보험 142,600원, 고용보험 35,690원, 지방소득세 23,630원, 장기요양보험 18,730원.&quot; style=&quot;display:block;width:100%;height:auto&quot;&gt;
  &lt;text x=&quot;110&quot; y=&quot;39&quot; fill=&quot;#4a4f5e&quot; font-size=&quot;14&quot; text-anchor=&quot;end&quot;&gt;소득세&lt;/text&gt;
  &lt;rect x=&quot;120&quot; y=&quot;20&quot; width=&quot;400&quot; height=&quot;28&quot; rx=&quot;3&quot; fill=&quot;#d64545&quot;/&gt;
  &lt;text x=&quot;528&quot; y=&quot;39&quot; fill=&quot;#333&quot; font-size=&quot;13&quot;&gt;236,360원&lt;/text&gt;

  &lt;text x=&quot;110&quot; y=&quot;81&quot; fill=&quot;#4a4f5e&quot; font-size=&quot;14&quot; text-anchor=&quot;end&quot;&gt;국민연금&lt;/text&gt;
  &lt;rect x=&quot;120&quot; y=&quot;62&quot; width=&quot;319&quot; height=&quot;28&quot; rx=&quot;3&quot; fill=&quot;#3b63e0&quot;/&gt;
  &lt;text x=&quot;447&quot; y=&quot;81&quot; fill=&quot;#333&quot; font-size=&quot;13&quot;&gt;188,410원&lt;/text&gt;

  &lt;text x=&quot;110&quot; y=&quot;123&quot; fill=&quot;#4a4f5e&quot; font-size=&quot;14&quot; text-anchor=&quot;end&quot;&gt;건강보험&lt;/text&gt;
  &lt;rect x=&quot;120&quot; y=&quot;104&quot; width=&quot;241&quot; height=&quot;28&quot; rx=&quot;3&quot; fill=&quot;#3b63e0&quot;/&gt;
  &lt;text x=&quot;369&quot; y=&quot;123&quot; fill=&quot;#333&quot; font-size=&quot;13&quot;&gt;142,600원&lt;/text&gt;

  &lt;text x=&quot;110&quot; y=&quot;165&quot; fill=&quot;#4a4f5e&quot; font-size=&quot;14&quot; text-anchor=&quot;end&quot;&gt;고용보험&lt;/text&gt;
  &lt;rect x=&quot;120&quot; y=&quot;146&quot; width=&quot;60&quot; height=&quot;28&quot; rx=&quot;3&quot; fill=&quot;#3b63e0&quot;/&gt;
  &lt;text x=&quot;188&quot; y=&quot;165&quot; fill=&quot;#333&quot; font-size=&quot;13&quot;&gt;35,690원&lt;/text&gt;

  &lt;text x=&quot;110&quot; y=&quot;207&quot; fill=&quot;#4a4f5e&quot; font-size=&quot;14&quot; text-anchor=&quot;end&quot;&gt;지방소득세&lt;/text&gt;
  &lt;rect x=&quot;120&quot; y=&quot;188&quot; width=&quot;40&quot; height=&quot;28&quot; rx=&quot;3&quot; fill=&quot;#d64545&quot;/&gt;
  &lt;text x=&quot;168&quot; y=&quot;207&quot; fill=&quot;#333&quot; font-size=&quot;13&quot;&gt;23,630원&lt;/text&gt;

  &lt;text x=&quot;110&quot; y=&quot;249&quot; fill=&quot;#4a4f5e&quot; font-size=&quot;14&quot; text-anchor=&quot;end&quot;&gt;장기요양보험&lt;/text&gt;
  &lt;rect x=&quot;120&quot; y=&quot;230&quot; width=&quot;32&quot; height=&quot;28&quot; rx=&quot;3&quot; fill=&quot;#3b63e0&quot;/&gt;
  &lt;text x=&quot;160&quot; y=&quot;249&quot; fill=&quot;#333&quot; font-size=&quot;13&quot;&gt;18,730원&lt;/text&gt;
&lt;/svg&gt;
&lt;figcaption style=&quot;margin:10px 4px 2px;color:#8a90a3;font-size:12.5px&quot;&gt;파랑은 4대 보험(38만 5,430원), 빨강은 세금(25만 9,990원). 가장 큰 한 덩어리는 소득세지만, 4대 보험을 합치면 세금보다 큽니다.&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;덩치 순으로 보면 &lt;b&gt;소득세 → 국민연금 → 건강보험&lt;/b&gt; 이 셋이 공제의 &lt;b&gt;88%&lt;/b&gt;를 차지합니다.
나머지 셋(고용보험·지방소득세·장기요양)은 다 합쳐도 7만 8천원 남짓이에요.
그러니 실수령액이 왜 이런지 이해하려면 앞의 세 항목만 알면 됩니다.&lt;/p&gt;

&lt;h3 style=&quot;margin-top:32px&quot;&gt;4대 보험은 요율 한 번 곱하면 끝&lt;/h3&gt;

&lt;p&gt;계산이 단순합니다. 과세 대상 소득(세전 월급 − 비과세액)에 정해진 요율을 곱하고,
회사가 절반을 부담해요. 명세서에 찍히는 건 &lt;b&gt;본인부담분&lt;/b&gt;입니다.&lt;/p&gt;

&lt;table style=&quot;width:100%;border-collapse:collapse;margin:14px 0;font-size:14.5px&quot;&gt;
&lt;thead&gt;
&lt;tr style=&quot;background:#f5f7ff&quot;&gt;
&lt;th style=&quot;padding:9px 10px;border:1px solid #e3e6ef;text-align:left&quot;&gt;항목&lt;/th&gt;
&lt;th style=&quot;padding:9px 10px;border:1px solid #e3e6ef;text-align:left&quot;&gt;2026년 요율&lt;/th&gt;
&lt;th style=&quot;padding:9px 10px;border:1px solid #e3e6ef;text-align:left&quot;&gt;기준&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;padding:9px 10px;border:1px solid #e3e6ef&quot;&gt;국민연금&lt;/td&gt;&lt;td style=&quot;padding:9px 10px;border:1px solid #e3e6ef&quot;&gt;본인 &lt;b&gt;4.75%&lt;/b&gt; (총 9.5%)&lt;/td&gt;&lt;td style=&quot;padding:9px 10px;border:1px solid #e3e6ef&quot;&gt;기준소득월액, 상한 659만원&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;padding:9px 10px;border:1px solid #e3e6ef&quot;&gt;건강보험&lt;/td&gt;&lt;td style=&quot;padding:9px 10px;border:1px solid #e3e6ef&quot;&gt;본인 &lt;b&gt;3.595%&lt;/b&gt; (총 7.19%)&lt;/td&gt;&lt;td style=&quot;padding:9px 10px;border:1px solid #e3e6ef&quot;&gt;보수월액, 상한 없음&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;padding:9px 10px;border:1px solid #e3e6ef&quot;&gt;장기요양보험&lt;/td&gt;&lt;td style=&quot;padding:9px 10px;border:1px solid #e3e6ef&quot;&gt;&lt;b&gt;13.14%&lt;/b&gt;&lt;/td&gt;&lt;td style=&quot;padding:9px 10px;border:1px solid #e3e6ef&quot;&gt;소득이 아니라 &lt;b&gt;건강보험료&lt;/b&gt;에 곱해요&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;padding:9px 10px;border:1px solid #e3e6ef&quot;&gt;고용보험&lt;/td&gt;&lt;td style=&quot;padding:9px 10px;border:1px solid #e3e6ef&quot;&gt;본인 &lt;b&gt;0.9%&lt;/b&gt;&lt;/td&gt;&lt;td style=&quot;padding:9px 10px;border:1px solid #e3e6ef&quot;&gt;보수월액 (실업급여분)&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;세 가지만 기억하면 이 표를 다 외운 것과 같습니다.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;① 2026년은 국민연금이 오른 첫 해예요.&lt;/b&gt; 2025년 연금개혁으로 보험료율이
9% → 13% 까지 매년 0.5%p 씩 오르기 시작했습니다. 2026년은 총 9.5%, 본인부담 4.75%.
월급이 작년과 똑같아도 연금 공제액은 늘어납니다.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;② 국민연금에는 상한이 있습니다.&lt;/b&gt; 기준소득월액 상한이 &lt;b&gt;659만원&lt;/b&gt;이라,
월 소득이 그보다 높아도 보험료는 659만원까지만 매겨요. 본인부담 상한은
659만 × 4.75% = &lt;b&gt;월 313,020원&lt;/b&gt;. 연봉이 8,000만원이든 2억이든 국민연금 공제액은 여기서 멈춥니다.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;③ 장기요양보험은 소득이 아니라 건강보험료를 따라갑니다.&lt;/b&gt; 위 예시에서
건강보험료 142,600원의 13.14% 가 18,730원이에요. 건보료가 오르면 장기요양도 자동으로
같이 오르는 구조라 두 항목은 늘 함께 움직입니다.&lt;/p&gt;

&lt;h3 style=&quot;margin-top:32px&quot;&gt;소득세는 요율 곱하기가 아닙니다&lt;/h3&gt;

&lt;p&gt;세금은 구조가 다릅니다. 연봉에 세율을 곧바로 곱하는 게 아니라 여섯 단계를 거쳐요.
실수령액 계산에서 사람들이 틀리는 지점은 거의 전부 여기입니다.&lt;/p&gt;

&lt;pre style=&quot;margin:14px 0;padding:14px 16px;background:#f7f8fb;border:1px solid #e3e6ef;border-radius:10px;overflow-x:auto;font-size:13.5px;line-height:1.7&quot;&gt;&lt;code&gt;연봉
 → (−) 비과세액           식대 월 20만원 = 연 240만원
 = 총급여
 → (−) 근로소득공제        총급여 구간별, 소득 낮을수록 공제율 높음
 → (−) 인적공제            부양가족 1인당 150만원
 → (−) 연금보험료공제      국민연금 본인부담 전액
 = 과세표준
 → (×) 누진세율            6% ~ 45%
 = 산출세액
 → (−) 근로소득세액공제    130만원 이하 55%, 초과분 30% (구간별 한도)
 → (−) 자녀세액공제        8~20세 자녀 1명 25만원, 2명 55만원
 = 소득세
 → (+) 지방소득세          소득세의 10%&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;세율표는 이렇습니다.&lt;/p&gt;

&lt;table style=&quot;width:100%;border-collapse:collapse;margin:14px 0;font-size:14.5px&quot;&gt;
&lt;thead&gt;
&lt;tr style=&quot;background:#f5f7ff&quot;&gt;
&lt;th style=&quot;padding:9px 10px;border:1px solid #e3e6ef;text-align:left&quot;&gt;과세표준&lt;/th&gt;
&lt;th style=&quot;padding:9px 10px;border:1px solid #e3e6ef;text-align:right&quot;&gt;세율&lt;/th&gt;
&lt;th style=&quot;padding:9px 10px;border:1px solid #e3e6ef;text-align:right&quot;&gt;누진공제&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;padding:9px 10px;border:1px solid #e3e6ef&quot;&gt;~ 1,400만원&lt;/td&gt;&lt;td style=&quot;padding:9px 10px;border:1px solid #e3e6ef;text-align:right&quot;&gt;6%&lt;/td&gt;&lt;td style=&quot;padding:9px 10px;border:1px solid #e3e6ef;text-align:right&quot;&gt;—&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;padding:9px 10px;border:1px solid #e3e6ef&quot;&gt;~ 5,000만원&lt;/td&gt;&lt;td style=&quot;padding:9px 10px;border:1px solid #e3e6ef;text-align:right&quot;&gt;15%&lt;/td&gt;&lt;td style=&quot;padding:9px 10px;border:1px solid #e3e6ef;text-align:right&quot;&gt;126만원&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;padding:9px 10px;border:1px solid #e3e6ef&quot;&gt;~ 8,800만원&lt;/td&gt;&lt;td style=&quot;padding:9px 10px;border:1px solid #e3e6ef;text-align:right&quot;&gt;24%&lt;/td&gt;&lt;td style=&quot;padding:9px 10px;border:1px solid #e3e6ef;text-align:right&quot;&gt;576만원&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;padding:9px 10px;border:1px solid #e3e6ef&quot;&gt;~ 1억 5,000만원&lt;/td&gt;&lt;td style=&quot;padding:9px 10px;border:1px solid #e3e6ef;text-align:right&quot;&gt;35%&lt;/td&gt;&lt;td style=&quot;padding:9px 10px;border:1px solid #e3e6ef;text-align:right&quot;&gt;1,544만원&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;blockquote style=&quot;border-left:4px solid #d64545;margin:16px 0;padding:8px 16px;background:#fff5f5&quot;&gt;
&lt;b&gt;흔한 오해&lt;/b&gt;&lt;br&gt;
&quot;연봉이 5,000만원을 넘으면 &lt;b&gt;전체에&lt;/b&gt; 15%가 붙는다&quot; — 아닙니다.
넘어간 &lt;b&gt;부분에만&lt;/b&gt; 높은 세율이 붙어요. 누진공제액이 붙어 있는 이유가 그겁니다.
연봉이 한 구간을 넘겨서 실수령이 오히려 줄어드는 일은 생기지 않습니다.
&lt;/blockquote&gt;

&lt;p&gt;그리고 세율이 걸리는 대상은 연봉이 아니라 &lt;b&gt;과세표준&lt;/b&gt;이에요. 연봉 5,000만원에서
비과세 240만원, 근로소득공제 1,213만원, 인적공제 150만원, 국민연금 226만원을 차례로 빼면
과세표준은 &lt;b&gt;약 3,170만원&lt;/b&gt;. 여기에 15%를 곱하고 누진공제 126만원과 근로소득세액공제를
또 빼야 소득세가 나옵니다. &quot;연봉 × 세율&quot; 로 어림한 금액이 실제와 크게 어긋나는 이유예요.&lt;/p&gt;

&lt;p&gt;지방소득세는 그렇게 확정된 소득세의 &lt;b&gt;10%&lt;/b&gt;. 소득세 236,360원이면 지방소득세
23,630원입니다. 별도 계산이 아니라 그냥 따라붙는 항목이에요.&lt;/p&gt;

&lt;h3 style=&quot;margin-top:32px&quot;&gt;연봉이 오르면 공제율은 어떻게 되나&lt;/h3&gt;

&lt;figure style=&quot;margin:16px 0;padding:16px 12px 10px;border:1px solid #e3e6ef;border-radius:12px;background:#fafbff&quot;&gt;
&lt;svg viewBox=&quot;0 0 640 344&quot; role=&quot;img&quot; aria-label=&quot;연봉별 실효 공제율: 3,000만원 10.7%, 4,000만원 13.4%, 5,000만원 15.5%, 6,000만원 17.0%, 8,000만원 20.2%, 1억원 22.2%.&quot; style=&quot;display:block;width:100%;height:auto&quot;&gt;
  &lt;line x1=&quot;60&quot; y1=&quot;300&quot; x2=&quot;610&quot; y2=&quot;300&quot; stroke=&quot;#d5d9e4&quot; stroke-width=&quot;1.5&quot;/&gt;
  &lt;line x1=&quot;60&quot; y1=&quot;50&quot; x2=&quot;60&quot; y2=&quot;300&quot; stroke=&quot;#d5d9e4&quot; stroke-width=&quot;1.5&quot;/&gt;
  &lt;line x1=&quot;60&quot; y1=&quot;214&quot; x2=&quot;610&quot; y2=&quot;214&quot; stroke=&quot;#eef0f6&quot; stroke-width=&quot;1&quot;/&gt;
  &lt;line x1=&quot;60&quot; y1=&quot;129&quot; x2=&quot;610&quot; y2=&quot;129&quot; stroke=&quot;#eef0f6&quot; stroke-width=&quot;1&quot;/&gt;
  &lt;text x=&quot;52&quot; y=&quot;304&quot; fill=&quot;#8a90a3&quot; font-size=&quot;12&quot; text-anchor=&quot;end&quot;&gt;10%&lt;/text&gt;
  &lt;text x=&quot;52&quot; y=&quot;218&quot; fill=&quot;#8a90a3&quot; font-size=&quot;12&quot; text-anchor=&quot;end&quot;&gt;15%&lt;/text&gt;
  &lt;text x=&quot;52&quot; y=&quot;133&quot; fill=&quot;#8a90a3&quot; font-size=&quot;12&quot; text-anchor=&quot;end&quot;&gt;20%&lt;/text&gt;
  &lt;polyline points=&quot;60,288 137,242 214,206 291,180 446,125 600,91&quot; fill=&quot;none&quot; stroke=&quot;#3b63e0&quot; stroke-width=&quot;3&quot; stroke-linejoin=&quot;round&quot; stroke-linecap=&quot;round&quot;/&gt;
  &lt;circle cx=&quot;60&quot; cy=&quot;288&quot; r=&quot;4&quot; fill=&quot;#3b63e0&quot;/&gt;
  &lt;circle cx=&quot;137&quot; cy=&quot;242&quot; r=&quot;4&quot; fill=&quot;#3b63e0&quot;/&gt;
  &lt;circle cx=&quot;214&quot; cy=&quot;206&quot; r=&quot;4&quot; fill=&quot;#3b63e0&quot;/&gt;
  &lt;circle cx=&quot;291&quot; cy=&quot;180&quot; r=&quot;4&quot; fill=&quot;#3b63e0&quot;/&gt;
  &lt;circle cx=&quot;446&quot; cy=&quot;125&quot; r=&quot;4&quot; fill=&quot;#3b63e0&quot;/&gt;
  &lt;circle cx=&quot;600&quot; cy=&quot;91&quot; r=&quot;4&quot; fill=&quot;#3b63e0&quot;/&gt;
  &lt;text x=&quot;66&quot; y=&quot;278&quot; fill=&quot;#3b63e0&quot; font-size=&quot;13&quot;&gt;10.7%&lt;/text&gt;
  &lt;text x=&quot;137&quot; y=&quot;232&quot; fill=&quot;#3b63e0&quot; font-size=&quot;13&quot; text-anchor=&quot;middle&quot;&gt;13.4%&lt;/text&gt;
  &lt;text x=&quot;214&quot; y=&quot;196&quot; fill=&quot;#3b63e0&quot; font-size=&quot;13&quot; text-anchor=&quot;middle&quot;&gt;15.5%&lt;/text&gt;
  &lt;text x=&quot;291&quot; y=&quot;170&quot; fill=&quot;#3b63e0&quot; font-size=&quot;13&quot; text-anchor=&quot;middle&quot;&gt;17.0%&lt;/text&gt;
  &lt;text x=&quot;446&quot; y=&quot;115&quot; fill=&quot;#3b63e0&quot; font-size=&quot;13&quot; text-anchor=&quot;middle&quot;&gt;20.2%&lt;/text&gt;
  &lt;text x=&quot;600&quot; y=&quot;81&quot; fill=&quot;#3b63e0&quot; font-size=&quot;13&quot; text-anchor=&quot;end&quot;&gt;22.2%&lt;/text&gt;
  &lt;text x=&quot;60&quot; y=&quot;322&quot; fill=&quot;#8a90a3&quot; font-size=&quot;12&quot; text-anchor=&quot;middle&quot;&gt;3,000만&lt;/text&gt;
  &lt;text x=&quot;137&quot; y=&quot;322&quot; fill=&quot;#8a90a3&quot; font-size=&quot;12&quot; text-anchor=&quot;middle&quot;&gt;4,000만&lt;/text&gt;
  &lt;text x=&quot;214&quot; y=&quot;322&quot; fill=&quot;#8a90a3&quot; font-size=&quot;12&quot; text-anchor=&quot;middle&quot;&gt;5,000만&lt;/text&gt;
  &lt;text x=&quot;291&quot; y=&quot;322&quot; fill=&quot;#8a90a3&quot; font-size=&quot;12&quot; text-anchor=&quot;middle&quot;&gt;6,000만&lt;/text&gt;
  &lt;text x=&quot;446&quot; y=&quot;322&quot; fill=&quot;#8a90a3&quot; font-size=&quot;12&quot; text-anchor=&quot;middle&quot;&gt;8,000만&lt;/text&gt;
  &lt;text x=&quot;600&quot; y=&quot;322&quot; fill=&quot;#8a90a3&quot; font-size=&quot;12&quot; text-anchor=&quot;middle&quot;&gt;1억&lt;/text&gt;
&lt;/svg&gt;
&lt;figcaption style=&quot;margin:10px 4px 2px;color:#8a90a3;font-size:12.5px&quot;&gt;세로축은 연봉 대비 실효 공제율. 같은 조건(부양가족 1명, 비과세 월 20만원)에서 연봉만 바꿔 계산했어요.&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;table style=&quot;width:100%;border-collapse:collapse;margin:14px 0;font-size:14.5px&quot;&gt;
&lt;thead&gt;
&lt;tr style=&quot;background:#f5f7ff&quot;&gt;
&lt;th style=&quot;padding:9px 10px;border:1px solid #e3e6ef;text-align:left&quot;&gt;연봉&lt;/th&gt;
&lt;th style=&quot;padding:9px 10px;border:1px solid #e3e6ef;text-align:right&quot;&gt;월 실수령액&lt;/th&gt;
&lt;th style=&quot;padding:9px 10px;border:1px solid #e3e6ef;text-align:right&quot;&gt;연 실수령액&lt;/th&gt;
&lt;th style=&quot;padding:9px 10px;border:1px solid #e3e6ef;text-align:right&quot;&gt;실효 공제율&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;padding:9px 10px;border:1px solid #e3e6ef&quot;&gt;3,000만원&lt;/td&gt;&lt;td style=&quot;padding:9px 10px;border:1px solid #e3e6ef;text-align:right&quot;&gt;2,233,220원&lt;/td&gt;&lt;td style=&quot;padding:9px 10px;border:1px solid #e3e6ef;text-align:right&quot;&gt;2,679만원&lt;/td&gt;&lt;td style=&quot;padding:9px 10px;border:1px solid #e3e6ef;text-align:right&quot;&gt;10.7%&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;padding:9px 10px;border:1px solid #e3e6ef&quot;&gt;4,000만원&lt;/td&gt;&lt;td style=&quot;padding:9px 10px;border:1px solid #e3e6ef;text-align:right&quot;&gt;2,886,743원&lt;/td&gt;&lt;td style=&quot;padding:9px 10px;border:1px solid #e3e6ef;text-align:right&quot;&gt;3,464만원&lt;/td&gt;&lt;td style=&quot;padding:9px 10px;border:1px solid #e3e6ef;text-align:right&quot;&gt;13.4%&lt;/td&gt;&lt;/tr&gt;
&lt;tr style=&quot;background:#f5f7ff&quot;&gt;&lt;td style=&quot;padding:9px 10px;border:1px solid #e3e6ef&quot;&gt;&lt;b&gt;5,000만원&lt;/b&gt;&lt;/td&gt;&lt;td style=&quot;padding:9px 10px;border:1px solid #e3e6ef;text-align:right&quot;&gt;&lt;b&gt;3,521,247원&lt;/b&gt;&lt;/td&gt;&lt;td style=&quot;padding:9px 10px;border:1px solid #e3e6ef;text-align:right&quot;&gt;&lt;b&gt;4,225만원&lt;/b&gt;&lt;/td&gt;&lt;td style=&quot;padding:9px 10px;border:1px solid #e3e6ef;text-align:right&quot;&gt;&lt;b&gt;15.5%&lt;/b&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;padding:9px 10px;border:1px solid #e3e6ef&quot;&gt;6,000만원&lt;/td&gt;&lt;td style=&quot;padding:9px 10px;border:1px solid #e3e6ef;text-align:right&quot;&gt;4,149,490원&lt;/td&gt;&lt;td style=&quot;padding:9px 10px;border:1px solid #e3e6ef;text-align:right&quot;&gt;4,979만원&lt;/td&gt;&lt;td style=&quot;padding:9px 10px;border:1px solid #e3e6ef;text-align:right&quot;&gt;17.0%&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;padding:9px 10px;border:1px solid #e3e6ef&quot;&gt;8,000만원&lt;/td&gt;&lt;td style=&quot;padding:9px 10px;border:1px solid #e3e6ef;text-align:right&quot;&gt;5,318,887원&lt;/td&gt;&lt;td style=&quot;padding:9px 10px;border:1px solid #e3e6ef;text-align:right&quot;&gt;6,383만원&lt;/td&gt;&lt;td style=&quot;padding:9px 10px;border:1px solid #e3e6ef;text-align:right&quot;&gt;20.2%&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;padding:9px 10px;border:1px solid #e3e6ef&quot;&gt;1억원&lt;/td&gt;&lt;td style=&quot;padding:9px 10px;border:1px solid #e3e6ef;text-align:right&quot;&gt;6,480,453원&lt;/td&gt;&lt;td style=&quot;padding:9px 10px;border:1px solid #e3e6ef;text-align:right&quot;&gt;7,777만원&lt;/td&gt;&lt;td style=&quot;padding:9px 10px;border:1px solid #e3e6ef;text-align:right&quot;&gt;22.2%&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;div style=&quot;display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:6px 16px;margin:0 0 18px;padding:10px 14px;background:#eef2ff;border:1px solid #c9d4f5;border-radius:12px;font-size:14px&quot;&gt;
&lt;span style=&quot;color:#666&quot;&gt;표에 없는 연봉이면 직접 넣어 보세요:&lt;/span&gt;
&lt;a href=&quot;https://utils.im/ko/salary&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; style=&quot;color:#3b63e0;font-weight:600;text-decoration:none;white-space:nowrap&quot;&gt;연봉 실수령액 계산기 →&lt;/a&gt;
&lt;/div&gt;

&lt;p&gt;연봉이 &lt;b&gt;3배&lt;/b&gt;가 되는 동안 공제율은 10.7% → 22.2% 로 &lt;b&gt;두 배&lt;/b&gt;가 됩니다. 누진세율 때문이에요.
그래서 연봉 협상에서 인상분의 체감은 늘 기대보다 작습니다.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;5,000만원 → 6,000만원&lt;/b&gt; 인상을 예로 들면 — 월 실수령 &lt;b&gt;+62만 8,243원&lt;/b&gt;,
연 실수령 &lt;b&gt;+753만 8,920원&lt;/b&gt;. 세전 인상분 1,000만원 중 손에 남는 건 &lt;b&gt;약 75%&lt;/b&gt; 예요.&lt;/p&gt;

&lt;h3 style=&quot;margin-top:32px&quot;&gt;계산기와 실제 명세서가 다를 수 있는 이유&lt;/h3&gt;

&lt;p&gt;몇 만원 어긋나는 건 정상입니다. 원인이 넷이에요.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;① 매달 떼는 소득세는 정확한 세액이 아닙니다.&lt;/b&gt; 회사가 떼는 건
&lt;b&gt;근로소득 간이세액표&lt;/b&gt;에 따른 개략적인 금액이에요. 의료비·신용카드·연금저축·월세 공제는
간이세액표가 반영하지 못합니다. 그래서 매달은 대충 떼고 &lt;b&gt;연말정산에서 확정&lt;/b&gt;하는 구조예요.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;② 비과세 항목이 회사마다 다릅니다.&lt;/b&gt; 식대 20만원은 기본이지만 자가운전보조금
20만원, 출산·보육수당 같은 항목이 붙으면 총급여가 더 줄어 실수령이 올라가요.
명세서에서 비과세로 표시된 금액을 확인해 계산기에 넣으면 훨씬 정확해집니다.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;③ 성과급·상여금이 있는 달은 튑니다.&lt;/b&gt; 그 달 소득이 뛰면서 세금도 같이 뛰어요.
연봉을 12로 나눈 평균과 실제 월별 금액은 다를 수 있습니다.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;④ 4대 보험료는 나중에 정산됩니다.&lt;/b&gt; 작년 소득 기준으로 부과하다가 뒤에 맞춰요.
연봉이 오른 해에는 한동안 덜 내다가 정산 때 한꺼번에 빠져나갑니다. 건강보험 정산은 보통
&lt;b&gt;4월 급여&lt;/b&gt;에 반영돼요.&lt;/p&gt;

&lt;h3 style=&quot;margin-top:32px&quot;&gt;내 숫자로 돌려보기&lt;/h3&gt;

&lt;p&gt;연봉만 넣어도 되지만, 부양가족 수와 8~20세 자녀 수까지 넣으면 세액공제가 반영된
값이 나옵니다. 명세서와 맞춰 보려면 비과세액을 실제 금액으로 바꾸세요.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://utils.im/ko/salary&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;연봉 실수령액 계산기&lt;/a&gt; — 2026년 요율 기준, 항목별 공제 내역까지. 입력한 연봉은 서버로 전송되지 않아요.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://utils.im/ko/percent&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;퍼센트 계산기&lt;/a&gt; — 인상률과 실질 인상 폭을 따져 볼 때.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://utils.im/ko/severance&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;퇴직금 계산기&lt;/a&gt; — 퇴직금은 통상임금이 아니라 평균임금으로 계산해요.&lt;/li&gt;
&lt;/ul&gt;

&lt;p style=&quot;color:#8a90a3;font-size:13px;margin-top:24px&quot;&gt;계산 도구는 utils.im — 가입·설치 없이 브라우저에서 바로 돌아갑니다.&lt;/p&gt;

&lt;/div&gt;</description>
      <category>Life</category>
      <category>4대보험 계산기</category>
      <category>세후 월급 계산</category>
      <category>연봉 실수령액</category>
      <category>연봉 실수령액표</category>
      <category>월급 실수령액 계산</category>
      <author>Ginjoe</author>
      <guid isPermaLink="true">https://itdar.tistory.com/438</guid>
      <comments>https://itdar.tistory.com/438#entry438comment</comments>
      <pubDate>Mon, 17 Aug 2026 21:36:52 +0900</pubDate>
    </item>
    <item>
      <title>10년 일찍 시작한 사람을 더 많이 저축해도 못 이기는 이유 - 복리 계산</title>
      <link>https://itdar.tistory.com/437</link>
      <description>&lt;div style=&quot;max-width:720px;margin:0 auto;line-height:1.8;font-size:16px&quot;&gt;

&lt;p&gt;두 사람이 적립식으로 돈을 모읍니다.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Ana&lt;/b&gt; 는 25살부터 매달 &lt;b&gt;20만원&lt;/b&gt;씩, 연 6%(월복리) 계좌에 넣습니다.&lt;br&gt;
&lt;b&gt;Ben&lt;/b&gt; 은 35살부터 시작하는 대신, 늦은 만큼 매달 &lt;b&gt;30만원&lt;/b&gt;씩 넣습니다.&lt;br&gt;
둘 다 55살에 멈춥니다. 내 돈으로 넣은 원금은 둘 다 정확히 &lt;b&gt;7,200만원&lt;/b&gt;으로 같아요.&lt;/p&gt;

&lt;blockquote style=&quot;border-left:4px solid #3b63e0;margin:16px 0;padding:8px 16px;background:#f5f7ff&quot;&gt;
&lt;b&gt;요약&lt;/b&gt;&lt;br&gt;
· 55살에 Ana 는 약 &lt;b&gt;2억 90만원&lt;/b&gt;, Ben 은 약 &lt;b&gt;1억 3,860만원&lt;/b&gt; — 같은 원금인데 &lt;b&gt;약 6,200만원&lt;/b&gt; 차이&lt;br&gt;
· 이유는 수익률도 저축액도 아니고, 돈이 자랄 &lt;b&gt;시간이 10년 더 있었다&lt;/b&gt;는 것 하나&lt;br&gt;
· 연 7%면 돈은 약 10년마다 2배 (72의 법칙) — 늦게 시작할수록 &lt;b&gt;가장 큰 마지막 2배&lt;/b&gt;를 잃습니다
&lt;/blockquote&gt;

&lt;h3 style=&quot;margin-top:32px&quot;&gt;같은 7,200만원, 왜 6,200만원이 벌어지나&lt;/h3&gt;

&lt;figure style=&quot;margin:16px 0;padding:16px 12px 10px;border:1px solid #e3e6ef;border-radius:12px;background:#fafbff&quot;&gt;
&lt;svg viewBox=&quot;0 0 640 360&quot; role=&quot;img&quot; aria-label=&quot;나이별 잔액: 25살부터 월 20만원 넣은 Ana 는 55살에 약 2억 90만원, 35살부터 월 30만원 넣은 Ben 은 약 1억 3,860만원.&quot; style=&quot;display:block;width:100%;height:auto&quot;&gt;
  &lt;line x1=&quot;60&quot; y1=&quot;320&quot; x2=&quot;600&quot; y2=&quot;320&quot; stroke=&quot;#d5d9e4&quot; stroke-width=&quot;1.5&quot;/&gt;
  &lt;line x1=&quot;60&quot; y1=&quot;40&quot; x2=&quot;60&quot; y2=&quot;320&quot; stroke=&quot;#d5d9e4&quot; stroke-width=&quot;1.5&quot;/&gt;
  &lt;text x=&quot;60&quot; y=&quot;342&quot; fill=&quot;#8a90a3&quot; font-size=&quot;12&quot; text-anchor=&quot;middle&quot;&gt;25살&lt;/text&gt;
  &lt;text x=&quot;240&quot; y=&quot;342&quot; fill=&quot;#8a90a3&quot; font-size=&quot;12&quot; text-anchor=&quot;middle&quot;&gt;35살&lt;/text&gt;
  &lt;text x=&quot;420&quot; y=&quot;342&quot; fill=&quot;#8a90a3&quot; font-size=&quot;12&quot; text-anchor=&quot;middle&quot;&gt;45살&lt;/text&gt;
  &lt;text x=&quot;600&quot; y=&quot;342&quot; fill=&quot;#8a90a3&quot; font-size=&quot;12&quot; text-anchor=&quot;middle&quot;&gt;55살&lt;/text&gt;
  &lt;text x=&quot;52&quot; y=&quot;324&quot; fill=&quot;#8a90a3&quot; font-size=&quot;12&quot; text-anchor=&quot;end&quot;&gt;0&lt;/text&gt;
  &lt;text x=&quot;52&quot; y=&quot;190&quot; fill=&quot;#8a90a3&quot; font-size=&quot;12&quot; text-anchor=&quot;end&quot;&gt;1억&lt;/text&gt;
  &lt;text x=&quot;52&quot; y=&quot;56&quot; fill=&quot;#8a90a3&quot; font-size=&quot;12&quot; text-anchor=&quot;end&quot;&gt;2억&lt;/text&gt;
  &lt;polyline points=&quot;60,320 150,301 240,276 330,242 420,197 510,135 600,52&quot; fill=&quot;none&quot; stroke=&quot;#3b63e0&quot; stroke-width=&quot;3&quot; stroke-linejoin=&quot;round&quot; stroke-linecap=&quot;round&quot;/&gt;
  &lt;polyline points=&quot;240,320 330,292 420,254 510,204 600,135&quot; fill=&quot;none&quot; stroke=&quot;#d64545&quot; stroke-width=&quot;3&quot; stroke-linejoin=&quot;round&quot; stroke-linecap=&quot;round&quot;/&gt;
  &lt;circle cx=&quot;600&quot; cy=&quot;52&quot; r=&quot;4&quot; fill=&quot;#3b63e0&quot;/&gt;
  &lt;circle cx=&quot;600&quot; cy=&quot;135&quot; r=&quot;4&quot; fill=&quot;#d64545&quot;/&gt;
  &lt;text x=&quot;592&quot; y=&quot;44&quot; fill=&quot;#3b63e0&quot; font-size=&quot;14&quot; text-anchor=&quot;end&quot;&gt;Ana · 약 2억 90만원&lt;/text&gt;
  &lt;text x=&quot;592&quot; y=&quot;127&quot; fill=&quot;#d64545&quot; font-size=&quot;14&quot; text-anchor=&quot;end&quot;&gt;Ben · 약 1억 3,860만원&lt;/text&gt;
  &lt;text x=&quot;150&quot; y=&quot;266&quot; fill=&quot;#3b63e0&quot; font-size=&quot;14&quot;&gt;25살부터 월 20만원&lt;/text&gt;
  &lt;text x=&quot;330&quot; y=&quot;316&quot; fill=&quot;#d64545&quot; font-size=&quot;14&quot;&gt;35살부터 월 30만원&lt;/text&gt;
&lt;/svg&gt;
&lt;figcaption style=&quot;margin:10px 4px 2px;color:#8a90a3;font-size:12.5px&quot;&gt;넣은 원금은 똑같이 7,200만원 — 10년 빠른 출발의 값이 약 6,200만원. 두 곡선 모두 연 6%·월복리 가정.&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;div style=&quot;display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:6px 16px;margin:0 0 18px;padding:10px 14px;background:#eef2ff;border:1px solid #c9d4f5;border-radius:12px;font-size:14px&quot;&gt;
&lt;span style=&quot;color:#666&quot;&gt;내 금액·수익률·기간으로 바꿔서 직접 확인:&lt;/span&gt;
&lt;a href=&quot;https://utils.im/ko/compound&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; style=&quot;color:#3b63e0;font-weight:600;text-decoration:none;white-space:nowrap&quot;&gt;복리 계산기 →&lt;/a&gt;
&lt;/div&gt;

&lt;p&gt;복리는 매 기간의 증가분을 &lt;b&gt;원금이 아니라 지금까지 쌓인 잔액 전체&lt;/b&gt;에 대해 계산합니다.
1년 차에는 넣은 돈에 이자가 붙지만, 10년 차에는 넣은 돈 + 9년치 이자에 이자가 붙어요.
불어난 것 자체가 불어나기 시작하는 거죠.&lt;/p&gt;

&lt;p&gt;이 되먹임은 처음엔 느립니다. 그래서 다들 과소평가해요. 곡선은 처음 10년이 거의 평평하고
마지막 10년이 가장 가파른데 — 늦게 시작한다는 건 &lt;b&gt;가장 가파른 구간을 잘라내는 것&lt;/b&gt;이지,
평평한 구간을 자르는 게 아닙니다.&lt;/p&gt;

&lt;h3 style=&quot;margin-top:32px&quot;&gt;손으로 검산할 수 있는 식&lt;/h3&gt;

&lt;p&gt;원금 P 를 연 수익률 r 로 n 년 굴리면 P × (1 + r)ⁿ 이 됩니다. 예를 들어 1,000만원을
연 7%로 40년 굴리면 1,000만 × 1.07⁴⁰ ≈ &lt;b&gt;1억 4,970만원&lt;/b&gt;. 같은 1,000만원을 30년이면
1,000만 × 1.07³⁰ ≈ &lt;b&gt;7,610만원&lt;/b&gt;이에요.&lt;/p&gt;

&lt;p&gt;이 두 숫자를 다시 보세요. 40년 차 잔액이 30년 차의 거의 2배 — 추가 입금 없는 &lt;b&gt;마지막
10년 하나&lt;/b&gt;가 앞의 30년 합계에 맞먹는 금액을 보태 줍니다. 연 7%에서 돈은 약 10년마다
2배가 되므로(72의 법칙: 72 ÷ 수익률 = 대략의 2배 소요 연수), 시작을 10년 미룰 때마다
&lt;b&gt;마지막이자 가장 큰 2배&lt;/b&gt;를 잃는 셈이에요.&lt;/p&gt;

&lt;figure style=&quot;margin:16px 0;padding:16px 12px 10px;border:1px solid #e3e6ef;border-radius:12px;background:#fafbff&quot;&gt;
&lt;svg viewBox=&quot;0 0 640 300&quot; role=&quot;img&quot; aria-label=&quot;1,000만원을 연 7%로: 10년 후 약 1,970만원, 20년 후 3,870만원, 30년 후 7,610만원, 40년 후 1억 4,970만원 — 10년마다 대략 2배.&quot; style=&quot;display:block;width:100%;height:auto&quot;&gt;
  &lt;line x1=&quot;30&quot; y1=&quot;250&quot; x2=&quot;620&quot; y2=&quot;250&quot; stroke=&quot;#d5d9e4&quot; stroke-width=&quot;1.5&quot;/&gt;
  &lt;rect x=&quot;55&quot; y=&quot;237&quot; width=&quot;70&quot; height=&quot;13&quot; fill=&quot;#e8ecf7&quot; stroke=&quot;#ccd2e3&quot;/&gt;
  &lt;rect x=&quot;175&quot; y=&quot;224&quot; width=&quot;70&quot; height=&quot;26&quot; fill=&quot;#e8ecf7&quot; stroke=&quot;#ccd2e3&quot;/&gt;
  &lt;rect x=&quot;295&quot; y=&quot;198&quot; width=&quot;70&quot; height=&quot;52&quot; fill=&quot;#e8ecf7&quot; stroke=&quot;#ccd2e3&quot;/&gt;
  &lt;rect x=&quot;415&quot; y=&quot;149&quot; width=&quot;70&quot; height=&quot;101&quot; fill=&quot;#e8ecf7&quot; stroke=&quot;#ccd2e3&quot;/&gt;
  &lt;rect x=&quot;535&quot; y=&quot;50&quot; width=&quot;70&quot; height=&quot;200&quot; fill=&quot;#3b63e0&quot;/&gt;
  &lt;text x=&quot;90&quot; y=&quot;229&quot; fill=&quot;#333&quot; font-size=&quot;14&quot; text-anchor=&quot;middle&quot;&gt;1,000만&lt;/text&gt;
  &lt;text x=&quot;210&quot; y=&quot;216&quot; fill=&quot;#333&quot; font-size=&quot;14&quot; text-anchor=&quot;middle&quot;&gt;1,970만&lt;/text&gt;
  &lt;text x=&quot;330&quot; y=&quot;190&quot; fill=&quot;#333&quot; font-size=&quot;14&quot; text-anchor=&quot;middle&quot;&gt;3,870만&lt;/text&gt;
  &lt;text x=&quot;450&quot; y=&quot;141&quot; fill=&quot;#333&quot; font-size=&quot;14&quot; text-anchor=&quot;middle&quot;&gt;7,610만&lt;/text&gt;
  &lt;text x=&quot;570&quot; y=&quot;42&quot; fill=&quot;#3b63e0&quot; font-size=&quot;14&quot; text-anchor=&quot;middle&quot;&gt;1억 4,970만&lt;/text&gt;
  &lt;text x=&quot;90&quot; y=&quot;272&quot; fill=&quot;#8a90a3&quot; font-size=&quot;12&quot; text-anchor=&quot;middle&quot;&gt;지금&lt;/text&gt;
  &lt;text x=&quot;210&quot; y=&quot;272&quot; fill=&quot;#8a90a3&quot; font-size=&quot;12&quot; text-anchor=&quot;middle&quot;&gt;10년 후&lt;/text&gt;
  &lt;text x=&quot;330&quot; y=&quot;272&quot; fill=&quot;#8a90a3&quot; font-size=&quot;12&quot; text-anchor=&quot;middle&quot;&gt;20년 후&lt;/text&gt;
  &lt;text x=&quot;450&quot; y=&quot;272&quot; fill=&quot;#8a90a3&quot; font-size=&quot;12&quot; text-anchor=&quot;middle&quot;&gt;30년 후&lt;/text&gt;
  &lt;text x=&quot;570&quot; y=&quot;272&quot; fill=&quot;#8a90a3&quot; font-size=&quot;12&quot; text-anchor=&quot;middle&quot;&gt;40년 후&lt;/text&gt;
&lt;/svg&gt;
&lt;figcaption style=&quot;margin:10px 4px 2px;color:#8a90a3;font-size:12.5px&quot;&gt;1,000만원을 연 7%로 그냥 놔둔 경우. 10년마다 대략 2배 — 그래서 건너뛰는 마지막 10년이 제일 비쌉니다.&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;div style=&quot;display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:6px 16px;margin:0 0 18px;padding:10px 14px;background:#eef2ff;border:1px solid #c9d4f5;border-radius:12px;font-size:14px&quot;&gt;
&lt;span style=&quot;color:#666&quot;&gt;내 수익률로 2배 속도 확인:&lt;/span&gt;
&lt;a href=&quot;https://utils.im/ko/compound&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; style=&quot;color:#3b63e0;font-weight:600;text-decoration:none;white-space:nowrap&quot;&gt;복리 계산기 →&lt;/a&gt;
&lt;/div&gt;

&lt;h3 style=&quot;margin-top:32px&quot;&gt;매달 넣는 적립식도 같은 법칙&lt;/h3&gt;

&lt;p&gt;대부분은 목돈이 아니라 매달 적립합니다. 월 수익률 i 로 n 개월, 매달 PMT 씩 넣는 식은
PMT × ((1 + i)ⁿ − 1) ÷ i. 위 Ana·Ben 의 숫자가 여기서 나옵니다:
20만 × (1.005³⁶⁰ − 1) ÷ 0.005 ≈ 2억 90만원, 30만 × (1.005²⁴⁰ − 1) ÷ 0.005 ≈ 1억 3,860만원.&lt;/p&gt;

&lt;p&gt;Ben 이 매달 10만원 더 넣고 얻은 걸 보세요 — 별로 없습니다. 55살에 Ana 를 정말로
따라잡으려면 20년 내내 매달 &lt;b&gt;약 43만 5천원&lt;/b&gt;, 즉 Ana 의 2배 넘게 넣어야 해요.
돈으로 시간을 따라잡는 건 비쌉니다.&lt;/p&gt;

&lt;h3 style=&quot;margin-top:32px&quot;&gt;수익률은 생각만큼 안 중요하다&lt;/h3&gt;

&lt;p&gt;0.5%p 수익률 차이를 고민하느라 시작을 미루는 경우가 많은데, 저축 초반에는 그 우선순위가
거꾸로입니다. 1년 차에 잔액 1,000만원에서 5%를 6%로 올리면 늘어나는 건 10만원. 반면 1년
일찍 시작하면 첫해 성장 전체에 더해, 그 1년이 씨앗이 되는 이후의 모든 2배를 얻어요.&lt;/p&gt;

&lt;p&gt;수익률이 효과를 내기 시작하는 건 잔액이 커진 뒤입니다. 바꿔 말하면 — 초반의 레버는
&lt;b&gt;저축액과 시작 시점&lt;/b&gt;, 후반의 레버가 수익률. 최적화는 이 순서로 하세요.&lt;/p&gt;

&lt;h3 style=&quot;margin-top:32px&quot;&gt;복리가 해결해 주지 않는 것&lt;/h3&gt;

&lt;p&gt;정직한 주의점 세 가지. 첫째, &lt;b&gt;인플레이션도 복리로 굴러갑니다&lt;/b&gt; — 물가상승 3% 시대의
명목 6% 성장은 실질 약 3%라, 위의 미래 잔액은 표기된 숫자보다 구매력이 작아요. 둘째, 실제
수익률은 매끈한 고정값이 아닙니다. 예시가 고정 수익률인 건 시간의 효과만 떼어 보여주기
위해서지 포트폴리오 예측이 아니에요. 셋째, 복리는 &lt;b&gt;빚에서는 같은 힘으로 반대로&lt;/b&gt;
작동합니다 — 연 20% 카드 잔액은 같은 72의 법칙으로 약 3년 반마다 2배가 됩니다.&lt;/p&gt;

&lt;h3 style=&quot;margin-top:32px&quot;&gt;내 숫자로 돌려보기&lt;/h3&gt;

&lt;p&gt;제일 빨리 체감하는 방법은 내 숫자를 넣고 곡선을 보는 겁니다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://utils.im/ko/compound&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;복리 계산기&lt;/a&gt; — 원금·수익률·기간을 넣으면 연도별 잔액. 같은 입력에서 기간만 10년 바꿔 비교해 보세요.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://utils.im/ko/loan&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;대출 이자 계산기&lt;/a&gt; — 같은 힘이 반대로 작동하는 모습. 매달 갚는 돈에서 이자가 얼마나 가져가는지.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://utils.im/ko/percent&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;퍼센트 계산기&lt;/a&gt; — 어디서 읽은 수익률 주장, 검산이 필요할 때 제일 빠른 길.&lt;/li&gt;
&lt;/ul&gt;

&lt;p style=&quot;color:#8a90a3;font-size:13px;margin-top:24px&quot;&gt;계산 도구는 utils.im — 가입·설치 없이 브라우저에서 바로 돌아갑니다.&lt;/p&gt;

&lt;/div&gt;</description>
      <category>Life</category>
      <category>72의 법칙</category>
      <category>복리 계산기</category>
      <category>복리 이자 계산</category>
      <category>복리 효과</category>
      <category>적립식 투자 계산</category>
      <author>Ginjoe</author>
      <guid isPermaLink="true">https://itdar.tistory.com/437</guid>
      <comments>https://itdar.tistory.com/437#entry437comment</comments>
      <pubDate>Sat, 15 Aug 2026 20:38:00 +0900</pubDate>
    </item>
    <item>
      <title>대출 이자 계산기 &amp;mdash; 원리금균등과 원금균등, 3억 빌리면 총이자가 3,500만원 갈립니다</title>
      <link>https://itdar.tistory.com/436</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;대출 상담을 받으면 상환 방식을 고르라고 합니다. 원리금균등, 원금균등, 만기일시.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다만 같은 금액을 같은 금리로 빌려도 방식에 따라 총이자가 &lt;b&gt;3,500만원&lt;/b&gt; 차이 납니다.&lt;br /&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;middot;금리&amp;middot;기간을 넣으면 세 방식이 각각 얼마인지 바로 나옵니다.&lt;/p&gt;
&lt;p&gt;&lt;iframe src=&quot;https://utils.im/ko/embed/loan&quot; width=&quot;100%&quot; height=&quot;720&quot;&gt;&lt;/iframe&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;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;b&gt;요약&lt;/b&gt;&lt;/blockquote&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이자는 항상&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;남은 원금&lt;/b&gt;에 붙습니다. 세 방식의 차이는 전부 여기서 나와요&lt;/li&gt;
&lt;li&gt;3억&amp;middot;4.0%&amp;middot;30년 기준 총이자 &amp;mdash; 원금균등&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;1.81억&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;/ 원리금균등&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;2.16억&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;/ 만기일시&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;3.6억&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;거치기간은 이자를&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;깎는 게 아니라 미루는&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;겁니다 (3년 거치 = 총이자 +1,145만원)&lt;/li&gt;
&lt;li&gt;금리 0.5%p 는 총이자&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;3,000만원&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;남짓입니다&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. 세 방식은 원금을 언제 갚느냐가 다릅니다&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이자는 항상 &lt;b&gt;남은 원금&lt;/b&gt;에 붙습니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 문장 하나가 세 방식의 차이를 전부 설명해요.&lt;br /&gt;원금을 빨리 줄이면 이자가 적고, 늦게 줄이면 많습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;원리금균등&lt;/b&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;/li&gt;
&lt;li&gt;갈수록 이자가 줄면서 원금 비중이 커집니다&lt;/li&gt;
&lt;li&gt;매달 같은 돈이 나가니 가계 관리가 쉬워요&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;원금균등&lt;/b&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;/li&gt;
&lt;li&gt;첫 달이 가장 부담스럽고 갈수록 가벼워집니다&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;만기일시&lt;/b&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;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2. 3억, 연 4.0%, 30년으로 비교하면&lt;/h2&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&quot;left&quot;&gt;방식&lt;/th&gt;
&lt;th align=&quot;right&quot;&gt;첫 회차&lt;/th&gt;
&lt;th align=&quot;right&quot;&gt;마지막 회차&lt;/th&gt;
&lt;th align=&quot;right&quot;&gt;총이자&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&quot;left&quot;&gt;원리금균등&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;1,432,246원&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;1,432,246원&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;215,608,519원&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;left&quot;&gt;&lt;b&gt;원금균등&lt;/b&gt;&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;1,833,333원&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;836,111원&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;&lt;b&gt;180,500,000원&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;left&quot;&gt;만기일시&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;1,000,000원&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;301,000,000원&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;360,000,000원&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;원금균등 vs 원리금균등&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;총이자 &lt;b&gt;3,510만원&lt;/b&gt; 적음&lt;/li&gt;
&lt;li&gt;대신 첫 회차 부담 &lt;b&gt;40만원&lt;/b&gt; 더 큼&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 40만원을 30년 초반에 감당할 수 있느냐가 갈림길입니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;감당 가능하다 &amp;rarr; &lt;b&gt;원금균등&lt;/b&gt;이 유리&lt;/li&gt;
&lt;li&gt;초반 현금흐름이 빡빡하다 &amp;rarr; &lt;b&gt;원리금균등&lt;/b&gt;이 안전&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;만기일시는 언제 쓰나&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;총이자 3억 6천만원은 &lt;b&gt;원금보다 큽니다&lt;/b&gt;. 3억을 빌려서 6억 6천만원을 갚는 구조예요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만기 전에 자산을 팔거나 다른 자금으로 갚을 계획이 확실할 때만 의미가 있습니다.&lt;br /&gt;전세자금대출처럼 만기에 보증금이 돌아오는 경우가 그런 사례예요.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3. 거치기간은 공짜가 아닙니다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;거치기간은 원금을 갚지 않고 &lt;b&gt;이자만&lt;/b&gt; 내는 구간입니다. 당장 부담이 줄어서 매력적으로 보여요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3억을 4.0% 로 빌리면 거치 중에는 월 &lt;b&gt;100만원&lt;/b&gt;만 나갑니다.&lt;br /&gt;원리금균등 143만원보다 43만원 가벼워요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제는 그 3년 동안 &lt;b&gt;원금이 3억 그대로&lt;/b&gt;라는 점입니다. 이자는 남은 원금에 붙으니까요.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3년 거치를 넣으면 무슨 일이 생기나&lt;/h3&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&quot;left&quot;&gt;&amp;nbsp;&lt;/th&gt;
&lt;th align=&quot;right&quot;&gt;거치 없음&lt;/th&gt;
&lt;th align=&quot;right&quot;&gt;3년 거치&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&quot;left&quot;&gt;거치 중 월 납입액&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;&amp;mdash;&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;1,000,000원&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;left&quot;&gt;거치 후 월 납입액&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;1,432,246원&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;&lt;b&gt;1,515,625원&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;left&quot;&gt;총이자&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;215,608,519원&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;&lt;b&gt;227,062,355원&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;거치가 끝나면 월 납입액이 100만원 &amp;rarr; 152만원으로 &lt;b&gt;한 번에 52만원&lt;/b&gt; 오릅니다&lt;/li&gt;
&lt;li&gt;총이자는 &lt;b&gt;1,145만원&lt;/b&gt; 늘어납니다. 3년간 매달 43만원씩 미룬 대가예요&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;거치기간이 나쁘다는 얘기가 아닙니다. &lt;b&gt;미루는 것이지 깎는 게 아니라는&lt;/b&gt; 뜻이에요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;신혼부부가 초기 정착 비용을 감당하는 동안, 사업 초기 현금흐름을 버티는 용도라면 합리적입니다.&lt;br /&gt;다만 거치 종료 시점의 납입액을 미리 보고 결정하세요.&lt;br /&gt;그 시점에 소득이 얼마나 늘어 있을지도 계산에 넣어야 합니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;4. 금리 0.5%p 가 얼마인지&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;금리 비교는 대개 소수점 차이라 체감이 안 됩니다. 총이자로 환산하면 달라져요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3억 / 30년 / 원리금균등&lt;/b&gt; 기준입니다.&lt;/p&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&quot;center&quot;&gt;금리&lt;/th&gt;
&lt;th align=&quot;right&quot;&gt;월 납입액&lt;/th&gt;
&lt;th align=&quot;right&quot;&gt;총이자&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&quot;center&quot;&gt;3.5%&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;1,347,134원&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;184,968,263원&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;center&quot;&gt;4.0%&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;1,432,246원&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;215,608,519원&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;center&quot;&gt;4.5%&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;1,520,056원&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;247,220,135원&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;center&quot;&gt;5.0%&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;1,610,465원&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;279,767,353원&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;0.5%p 마다 총이자가 &lt;b&gt;3,000만원 남짓&lt;/b&gt; 움직입니다&lt;/li&gt;
&lt;li&gt;3.5% 와 5.0% 의 차이는 &lt;b&gt;9,480만원&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;금리 협상이나 대출 갈아타기에 드는 수고가 왜 값어치가 있는지 여기서 보입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;중도상환수수료가 있어도 계산해 볼 만합니다&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;보통 3년 이내 상환에 남은 기간 비례로 &lt;b&gt;1% 안팎&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;3억이면 &lt;b&gt;300만원&lt;/b&gt; 수준&lt;/li&gt;
&lt;li&gt;금리를 0.5%p 낮출 수 있다면 수수료를 내고도 남는 경우가 많아요&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;5. 실제 한도는 DSR 이 정합니다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;계산기가 알려주는 건 &quot;이 조건이면 매달 얼마&quot; 입니다.&lt;br /&gt;은행이 실제로 빌려주는 금액은 &lt;b&gt;DSR(총부채원리금상환비율)&lt;/b&gt; 규제가 따로 정해요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DSR 은 &lt;b&gt;연 소득 대비 모든 대출의 연간 원리금 상환액 비율&lt;/b&gt;입니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재 은행권 기준 &lt;b&gt;40%&lt;/b&gt;.&lt;br /&gt;연 소득 6,000만원이면 모든 대출의 연간 원리금 합계가 2,400만원(월 200만원)을 넘을 수 없습니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 주의할 점 두 가지예요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;기존 대출이 한도를 깎습니다&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;신용대출이나 카드론이 있으면 그만큼 주택담보대출 한도가 줄어듭니다.&lt;br /&gt;마이너스통장은 &lt;b&gt;쓰지 않아도 한도 전액이 잡히는&lt;/b&gt; 경우가 있어요.&lt;br /&gt;대출 신청 전에 안 쓰는 마이너스통장을 정리하라는 조언이 여기서 나옵니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;스트레스 DSR 이 또 있습니다&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;변동금리 대출은 미래 금리 상승분을 얹어서 심사해요.&lt;br /&gt;지금 금리가 4% 여도 심사는 더 높은 금리로 돌리기 때문에 실제 한도는 계산기보다 낮게 나옵니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&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://utils.im/ko/loan&quot;&gt;utils.im 의 대출 이자 계산기&lt;/a&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;여윳돈을 굴리는 쪽과 비교하려면 &amp;rarr; &lt;a href=&quot;https://utils.im/ko/savings&quot;&gt;적금 계산기&lt;/a&gt; &amp;middot; &lt;a href=&quot;https://utils.im/ko/compound&quot;&gt;복리 계산기&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;전세를 월세로 돌릴지 고민 중이면 &amp;rarr; &lt;a href=&quot;https://utils.im/ko/jeonse&quot;&gt;전월세 전환 계산기&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Life</category>
      <category>거치기간 이자</category>
      <category>대출 상환 스케줄</category>
      <category>대출 이자 계산기</category>
      <category>원리금균등 원금균등 차이</category>
      <category>주택담보대출 월 상환액</category>
      <author>Ginjoe</author>
      <guid isPermaLink="true">https://itdar.tistory.com/436</guid>
      <comments>https://itdar.tistory.com/436#entry436comment</comments>
      <pubDate>Sat, 15 Aug 2026 14:16:12 +0900</pubDate>
    </item>
    <item>
      <title>전월세 전환율 계산기 &amp;mdash; 전세 3억을 월세로 돌리면 월 얼마가 맞는 걸까</title>
      <link>https://itdar.tistory.com/435</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;집주인이 전세를 반전세로 돌리자고 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;보증금 1억에 월세 100만원이면 어떻겠냐&quot; 는 제안.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이게 적정한 금액인지 판단하려면 &lt;b&gt;전월세 전환율&lt;/b&gt;이라는 숫자를 알아야 합니다.&lt;br /&gt;그리고 지금 상황이 &lt;b&gt;계약 기간 중 전환&lt;/b&gt;인지 &lt;b&gt;새 계약&lt;/b&gt;인지에 따라 법이 개입하는 정도가&lt;br /&gt;완전히 달라져요. 이 구분을 모르면 협상 카드를 하나 놓칩니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;요약&lt;/b&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;연 4.75%&lt;/b&gt; (기준금리 2.75% + 2%p)&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;/blockquote&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;rarr; 월세, 월세 &amp;rarr; 전세 양방향으로 계산됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;iframe src=&quot;https://utils.im/ko/embed/jeonse&quot; width=&quot;100%&quot; height=&quot;720&quot;&gt;&lt;/iframe&gt;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. 계산식은 두 줄입니다&lt;/h2&gt;
&lt;pre class=&quot;ada&quot;&gt;&lt;code&gt;전세 &amp;rarr; 월세 : 월세 = (전세보증금 &amp;minus; 남길 보증금) &amp;times; 전환율 &amp;divide; 12
월세 &amp;rarr; 전세 : 전세보증금 = 보증금 + 월세 &amp;times; 12 &amp;divide; 전환율&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두 식은 서로의 역입니다. 같은 전환율로 왕복하면 원래 금액으로 돌아와요.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;앞의 제안을 계산해 봅시다&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;전세 3억을 보증금 1억짜리 월세로 돌리는 경우입니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;월세로 바뀌는 목돈 = 3억 &amp;minus; 1억 = &lt;b&gt;2억&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;전환율 4.75% &amp;rarr; 2억 &amp;times; 0.0475 &amp;divide; 12 = &lt;b&gt;월 791,667원&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;집주인 제안은 월 100만원이었죠. 역산하면 이렇게 됩니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;2억 &amp;times; 0.06 &amp;divide; 12 = 100만원 &amp;rarr; &lt;b&gt;전환율 6.0%&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&quot;center&quot;&gt;전환율&lt;/th&gt;
&lt;th align=&quot;right&quot;&gt;월세&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&quot;center&quot;&gt;4.75% (법정 상한)&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;791,667원&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;center&quot;&gt;6.0% (집주인 제안)&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;1,000,000원&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;차이는 월 &lt;b&gt;208,333원&lt;/b&gt;. 2년이면 &lt;b&gt;500만원&lt;/b&gt;입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2. 법정 상한이 있지만, 모든 경우에 걸리진 않습니다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;주택임대차보호법 제7조의2 가 전환율 상한을 정해 두고 있어요.&lt;br /&gt;시행령 제9조가 두 가지 값을 주고 그중 &lt;b&gt;낮은 쪽&lt;/b&gt;이 상한입니다.&lt;/p&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&quot;left&quot;&gt;근거&lt;/th&gt;
&lt;th align=&quot;right&quot;&gt;값&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&quot;left&quot;&gt;시행령 제9조 제1항 &amp;mdash; 고정 상한&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;연 10%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;left&quot;&gt;시행령 제9조 제2항 &amp;mdash; 기준금리 + 2%p&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;연 &lt;b&gt;4.75%&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기준금리가 2.75% 인 지금은 4.75% 가 낮으니 &lt;b&gt;현재 법정 상한은 연 4.75%&lt;/b&gt; 입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;문제는 이 상한이 걸리는 범위가 좁다는 점입니다&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;✅ 상한이 적용되는 경우 &amp;mdash; 계약 기간 중 전환&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;임대인이 계약 도중에 &quot;전세를 월세로 돌리자&quot; 고 요구하는 상황입니다.&lt;br /&gt;이때 6.0% 를 요구하면 법정 상한 초과예요. &lt;b&gt;초과분은 무효라 반환을 청구할 수 있습니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;❌ 상한이 적용되지 않는 경우 &amp;mdash; 새로 맺는 계약&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이사를 가서 처음 계약하는 경우, 계약 기간이 끝나고 새 조건으로 갱신하는 경우입니다.&lt;br /&gt;보증금과 월세 조합은 당사자가 정할 문제로 봐요.&lt;br /&gt;시장 전환율은 지역&amp;middot;시기에 따라 &lt;b&gt;5~7% 대&lt;/b&gt;에서 움직이고, 법정 상한보다 높은 게 보통입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;⚠️ 애매한 경우 &amp;mdash; 계약갱신요구권으로 갱신&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;갱신 시 임대인이 전세를 월세로 바꾸려면 임차인 동의가 필요하고,&lt;br /&gt;동의해서 전환한다면 법정 전환율이 적용된다는 게 국토교통부의 해석이에요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다만 분쟁이 잦은 지점입니다.&lt;br /&gt;확정적으로 다투려면 &lt;b&gt;대한법률구조공단&lt;/b&gt;이나 &lt;b&gt;주택임대차분쟁조정위원회&lt;/b&gt;를 통하는 게 안전해요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3. 전세와 월세, 어느 쪽이 이득인가&lt;/h2&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;대출로 마련했다면 &amp;rarr; 매달 &lt;b&gt;이자&lt;/b&gt;가 나갑니다&lt;/li&gt;
&lt;li&gt;내 돈이라면 &amp;rarr; 그 돈으로 벌 수 있었던 &lt;b&gt;이자 수익을 포기&lt;/b&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;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;전환율이 내 자금의 기회비용보다 높으면 월세가 손해입니다.&lt;/b&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;숫자로 보면&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;전세 3억 중 &lt;b&gt;2억&lt;/b&gt;이 전환 대상이고, 전세자금대출 금리가 &lt;b&gt;4.0%&lt;/b&gt; 인 경우입니다.&lt;/p&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&quot;left&quot;&gt;선택&lt;/th&gt;
&lt;th align=&quot;right&quot;&gt;월 부담&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&quot;left&quot;&gt;전세 유지 (2억 &amp;times; 4.0% &amp;divide; 12)&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;666,667원&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;left&quot;&gt;월세 전환 (2억 &amp;times; 4.75% &amp;divide; 12)&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;791,667원&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;left&quot;&gt;&lt;b&gt;차이&lt;/b&gt;&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;&lt;b&gt;전세가 월 125,000원 유리&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;손익분기는 &lt;b&gt;전환율 = 대출 금리&lt;/b&gt;인 지점이에요.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;대출 금리가 4.75% 로 오르면 &amp;rarr; 두 선택이 같아집니다&lt;/li&gt;
&lt;li&gt;그보다 높아지면 &amp;rarr; 월세가 유리해집니다&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2022년처럼 금리가 급등한 시기에 월세 선호가 늘어난 게 이 계산의 결과예요.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;숫자에 안 잡히는 것들&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;전세 쪽 위험&lt;/b&gt; &amp;mdash; 보증금 전액을 떼일 수 있습니다.&lt;br /&gt;전세사기와 역전세가 이어진 뒤로는 이 위험을 할인율로 반영하는 게 합리적이에요.&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;월세 쪽 혜택&lt;/b&gt; &amp;mdash; 세액공제 대상입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&quot;left&quot;&gt;총급여&lt;/th&gt;
&lt;th align=&quot;right&quot;&gt;공제율&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&quot;left&quot;&gt;5,500만원 이하&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;17%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;left&quot;&gt;8,000만원 이하&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;15%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;무주택 세대주 기준이고 한도는 &lt;b&gt;연 1,000만원&lt;/b&gt;이에요.&lt;br /&gt;월 791,667원이면 연 950만원이라 거의 전액이 공제 대상에 들어갑니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;4. 반전세 조건을 스스로 설계하는 법&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;집주인이 제시한 조건을 받아들이거나 거절하는 것만이 선택지는 아닙니다.&lt;br /&gt;계산식을 알면 역으로 조건을 제안할 수 있어요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;전세 3억 / 전환율 4.75% 고정&lt;/b&gt;, 보증금만 바꿔 본 표입니다.&lt;/p&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&quot;left&quot;&gt;남길 보증금&lt;/th&gt;
&lt;th align=&quot;right&quot;&gt;전환 대상&lt;/th&gt;
&lt;th align=&quot;right&quot;&gt;월세&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&quot;left&quot;&gt;5,000만원&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;2억 5,000만원&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;989,583원&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;left&quot;&gt;1억원&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;2억원&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;791,667원&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;left&quot;&gt;1억 5,000만원&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;1억 5,000만원&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;593,750원&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;월세 부담을 낮추고 싶다 &amp;rarr; &lt;b&gt;보증금을 올린다&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;목돈을 다른 데 쓰고 싶다 &amp;rarr; &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;집주인과 협상할 때 &lt;b&gt;&quot;전환율 몇 % 로 계산하신 건가요&quot;&lt;/b&gt; 라고 묻는 것만으로도 대화의 층위가 달라져요.&lt;br /&gt;근거 없이 부른 금액인지, 시장 전환율을 반영한 금액인지 여기서 드러납니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;보증금을 낮출 때 같이 확인할 것&lt;/h3&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; &amp;mdash; 보증금이 기준 이하면 대상이 됩니다. 기준은 지역별로 달라요&lt;/li&gt;
&lt;li&gt;&lt;b&gt;확정일자 + 전입신고&lt;/b&gt; &amp;mdash; 어느 조건이든 &lt;b&gt;계약 당일&lt;/b&gt;에 해 두는 게 원칙입니다&lt;/li&gt;
&lt;li&gt;&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;계산기는 &lt;a href=&quot;https://utils.im/ko/jeonse&quot;&gt;utils.im 의 전월세 전환 계산기&lt;/a&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;/li&gt;
&lt;li&gt;전세자금대출 상환 계획을 같이 보려면 &amp;rarr; &lt;a href=&quot;https://utils.im/ko/loan&quot;&gt;대출 이자 계산기&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Life</category>
      <category>계산기</category>
      <category>반전세</category>
      <category>월세</category>
      <category>전세</category>
      <category>전월세 전환률</category>
      <category>전환률</category>
      <author>Ginjoe</author>
      <guid isPermaLink="true">https://itdar.tistory.com/435</guid>
      <comments>https://itdar.tistory.com/435#entry435comment</comments>
      <pubDate>Thu, 13 Aug 2026 11:07:24 +0900</pubDate>
    </item>
    <item>
      <title>BMI 계산기 &amp;mdash; 같은 몸무게가 기준에 따라 정상도 되고 비만도 되는 이유</title>
      <link>https://itdar.tistory.com/434</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;BMI 를 검색하면 계산기마다 결과 해석이 다릅니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;똑같이 &lt;b&gt;25.5&lt;/b&gt; 가 나왔는데 어떤 곳은 &quot;과체중&quot;, 어떤 곳은 &quot;1단계 비만&quot; 이라고 해요.&lt;br /&gt;계산이 틀린 게 아니라 &lt;b&gt;분류 기준이 다른&lt;/b&gt; 겁니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;요약&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;BMI 계산식은 어디서나 같지만, 그 숫자를 부르는 이름은 국내 기준과 국제 기준이 다릅니다&lt;/li&gt;
&lt;li&gt;국내 기준은 &lt;b&gt;25 부터 비만&lt;/b&gt;, WHO 기준은 &lt;b&gt;30 부터 비만&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;23~25 구간이 가장 헷갈립니다. 국제 기준으로는 정상, 국내 기준으로는 &quot;비만 전단계&quot;&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&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;키&amp;middot;몸무게만 &amp;rarr; BMI 와 적정 체중 범위&lt;/li&gt;
&lt;li&gt;성별&amp;middot;나이&amp;middot;활동량까지 &amp;rarr; 기초대사량과 하루 유지 칼로리&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;iframe src=&quot;https://utils.im/ko/embed/bmi&quot; width=&quot;100%&quot; height=&quot;720&quot;&gt;&lt;/iframe&gt;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. 계산 자체는 나눗셈 한 번&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;BMI 는 체중을 키의 제곱으로 나눈 값입니다. 키는 미터로 환산해요.&lt;/p&gt;
&lt;pre class=&quot;gcode&quot;&gt;&lt;code&gt;BMI = 체중(kg) &amp;divide; 키(m)&amp;sup2;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;키 175cm, 몸무게 78kg 이라면&lt;/p&gt;
&lt;pre class=&quot;basic&quot;&gt;&lt;code&gt;78 &amp;divide; (1.75 &amp;times; 1.75) = 25.5&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;손으로 해도 30초면 끝납니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어려운 건 계산이 아니라, 이 &lt;b&gt;25.5 를 뭐라고 부를 것인가&lt;/b&gt;예요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2. 25.5 는 과체중인가, 비만인가&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;세계보건기구(WHO) 기준으로 25.5 는 &lt;b&gt;과체중&lt;/b&gt;입니다. 비만은 30 부터예요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데 대한비만학회의 아시아&amp;middot;태평양 기준으로 보면 25 부터가 이미 &lt;b&gt;1단계 비만&lt;/b&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;같은 BMI 에서 동아시아인은 서구인보다 &lt;b&gt;체지방률이 높습니다&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;당뇨&amp;middot;고혈압 같은 대사질환이 &lt;b&gt;더 낮은 BMI 에서 시작되는&lt;/b&gt; 경향이 관찰됐어요&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;두 기준 비교표&lt;/h3&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&quot;center&quot;&gt;BMI&lt;/th&gt;
&lt;th align=&quot;left&quot;&gt;대한비만학회 (국내)&lt;/th&gt;
&lt;th align=&quot;left&quot;&gt;WHO (국제)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&quot;center&quot;&gt;18.5 미만&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;저체중&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;저체중&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;center&quot;&gt;18.5 ~ 22.9&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;정상&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;정상&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;center&quot;&gt;&lt;b&gt;23 ~ 24.9&lt;/b&gt;&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;&lt;b&gt;비만 전단계&lt;/b&gt;&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;&lt;b&gt;정상&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;center&quot;&gt;&lt;b&gt;25 ~ 29.9&lt;/b&gt;&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;&lt;b&gt;1단계 비만&lt;/b&gt;&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;&lt;b&gt;과체중&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;center&quot;&gt;30 ~ 34.9&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;2단계 비만&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;비만&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;center&quot;&gt;35 이상&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;3단계 비만&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;고도비만&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;굵게 표시한 두 줄이 갈리는 구간입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;국제 기준으로는 아직 정상인데 국내 기준으로는 &quot;비만 전단계&quot; 경고가 붙어요.&lt;br /&gt;건강검진에서 갑자기 관리 대상으로 분류돼 당황하는 구간이 대개 여기입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 계산기는 &lt;b&gt;국내 기준&lt;/b&gt;을 씁니다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3. 적정 체중은 숫자 하나가 아니라 범위&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;표준체중&quot; 을 검색하면 딱 떨어지는 숫자 하나를 알려주는 곳이 많습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;BMI 로 역산하면 원래 &lt;b&gt;범위&lt;/b&gt;가 나와요. 정상 구간인 18.5 ~ 22.9 를 몸무게로 돌려놓는 겁니다.&lt;/p&gt;
&lt;pre class=&quot;armasm&quot;&gt;&lt;code&gt;적정 체중 = BMI &amp;times; 키(m)&amp;sup2;&lt;/code&gt;&lt;/pre&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&quot;center&quot;&gt;키&lt;/th&gt;
&lt;th align=&quot;left&quot;&gt;적정 체중 범위&lt;/th&gt;
&lt;th align=&quot;center&quot;&gt;폭&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&quot;center&quot;&gt;160cm&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;47.4 ~ 58.6kg&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;11.2kg&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;center&quot;&gt;175cm&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;56.7 ~ 70.1kg&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;13.4kg&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 범위 안이면 어느 쪽에 있든 정상입니다.&lt;br /&gt;굳이 한가운데를 목표로 삼을 이유는 없어요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;4. BMI 가 못 보는 것&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;BMI 에는 몸무게가 &lt;b&gt;근육인지 지방인지 구분하는 능력이 없습니다&lt;/b&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; &amp;mdash; 체지방이 적어도 비만으로 분류됩니다. 운동을 꾸준히 한 사람이 BMI 27 을 받고 억울해하는 경우가 흔해요&lt;/li&gt;
&lt;li&gt;&lt;b&gt;마른 비만&lt;/b&gt; &amp;mdash; 체중은 정상인데 근육이 적고 지방이 많은 경우. BMI 는 통과시키지만 대사 위험은 남습니다&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;허리둘레를 같이 보세요&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;허리둘레는 내장지방을 반영해서 BMI 가 놓치는 부분을 메워 줍니다.&lt;/p&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&quot;center&quot;&gt;구분&lt;/th&gt;
&lt;th align=&quot;left&quot;&gt;복부비만 기준 (국내)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&quot;center&quot;&gt;남성&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;90cm 이상&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;center&quot;&gt;여성&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;85cm 이상&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;줄자 하나면 재니까 BMI 와 같이 확인해 두면 좋아요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;BMI 를 아예 쓰지 말자는 얘기가 아닙니다.&lt;br /&gt;집단 지표로는 여전히 유용하고, 개인에게도 &quot;지금 어디쯤인지&quot; 를 30초에 알려주는 값싼 신호예요.&lt;br /&gt;다만 &lt;b&gt;이 하나로 건강을 판정하지는 말자&lt;/b&gt;는 겁니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;5. 감량 계획으로 넘어가려면 칼로리가 필요합니다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;BMI 가 관리 구간에 들어왔다면 다음 질문은 &quot;그래서 얼마나 먹어야 하나&quot; 입니다.&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;BMR (기초대사량)&lt;/b&gt; &amp;mdash; 아무것도 안 하고 누워만 있어도 쓰는 에너지&lt;/li&gt;
&lt;li&gt;&lt;b&gt;TDEE (하루 총 소비 칼로리)&lt;/b&gt; &amp;mdash; BMR &amp;times; 활동량 계수&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 계산기는 Mifflin-St Jeor 공식을 씁니다. 현재 가장 널리 검증된 추정식이에요.&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;남성: BMR = 10 &amp;times; 체중(kg) + 6.25 &amp;times; 키(cm) &amp;minus; 5 &amp;times; 나이 + 5
여성: BMR = 10 &amp;times; 체중(kg) + 6.25 &amp;times; 키(cm) &amp;minus; 5 &amp;times; 나이 &amp;minus; 161&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;35세 남성, 175cm, 78kg&lt;/b&gt; 으로 계산하면&lt;/p&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&quot;left&quot;&gt;항목&lt;/th&gt;
&lt;th align=&quot;right&quot;&gt;값&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&quot;left&quot;&gt;기초대사량(BMR)&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;1,704kcal&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;left&quot;&gt;하루 유지 칼로리(TDEE, 주 3~5회 운동)&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;2,641kcal&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;left&quot;&gt;감량 목표 섭취량&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;2,141kcal&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;왜 500kcal 을 빼나&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;체지방 1kg 은 대략 &lt;b&gt;7,700kcal&lt;/b&gt; 입니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;하루 500kcal &amp;rarr; 일주일 3,500kcal&lt;/li&gt;
&lt;li&gt;한 달이면 &lt;b&gt;약 2kg&lt;/b&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;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;6. 자주 나오는 질문&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Q. 아침저녁으로 몸무게가 다른데 언제 재나요?&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아침에 화장실 다녀온 직후, 같은 옷차림이 제일 흔들림이 적습니다.&lt;br /&gt;하루 안에서 1~2kg 은 수분으로 오르내려요.&lt;br /&gt;매일의 숫자보다 &lt;b&gt;일주일 평균의 방향&lt;/b&gt;을 보세요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Q. BMI 는 정상인데 배만 나왔어요.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앞서 말한 허리둘레를 재 보세요. BMI 가 통과시켜도 복부비만은 따로 잡힙니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Q. 임신 중에도 BMI 를 쓰나요?&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;쓰지 않습니다.&lt;br /&gt;임신 전 BMI 를 기준으로 권장 체중 증가량이 따로 있고, 담당 의사와 상의할 영역이에요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Q. 아이도 같은 기준인가요?&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아닙니다.&lt;br /&gt;만 18세 미만은 성인 기준선 대신 &lt;b&gt;연령&amp;middot;성별 백분위 성장곡선&lt;/b&gt;을 봅니다.&lt;br /&gt;성인용 계산기 결과를 그대로 적용하면 안 돼요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;계산기는 &lt;a href=&quot;https://utils.im/ko/bmi&quot;&gt;utils.im 의 BMI 계산기&lt;/a&gt; 를 임베드했습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;설치&amp;middot;가입 없이 브라우저 안에서 계산됩니다&lt;/li&gt;
&lt;li&gt;입력한 키&amp;middot;몸무게는 서버로 전송되지 않아요&lt;/li&gt;
&lt;li&gt;하루 유지 칼로리만 따로 보려면 &amp;rarr; &lt;a href=&quot;https://utils.im/ko/tdee&quot;&gt;TDEE 계산기&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Life/Health care</category>
      <category>BMI</category>
      <category>tdee</category>
      <category>다이어트</category>
      <category>비만도</category>
      <category>운동</category>
      <category>표준 체중</category>
      <category>피트니스</category>
      <author>Ginjoe</author>
      <guid isPermaLink="true">https://itdar.tistory.com/434</guid>
      <comments>https://itdar.tistory.com/434#entry434comment</comments>
      <pubDate>Thu, 13 Aug 2026 11:03:47 +0900</pubDate>
    </item>
    <item>
      <title>젠킨스, Jenkins, 도커, Docker, 컨테이너, CICD</title>
      <link>https://itdar.tistory.com/432</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Jenkins Docker&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;docker images&lt;/li&gt;
&lt;li&gt;docker container ls&lt;/li&gt;
&lt;li&gt;docker pull jenkins/jenkins:lts-jdk11&lt;/li&gt;
&lt;li&gt;docker run -d -p 8080:8080 -p 50000:50000 --name jenkins-server --restart=on-failure -v jenkins_home:${jekinks-home-path} jenkins/jenkins:lts-jdk11&lt;/li&gt;
&lt;li&gt;Docker 컨테이너 프로세스 확인&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;## docker 최초 비밀번호 확인을 위해서 로그 확인&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;docker logs jenkins-server&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;## Docker 컨테이너에 터널링으로 접속&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;docker exec -it jenkins-server bash&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Programming</category>
      <category>CICD</category>
      <category>docker</category>
      <category>Jenkins</category>
      <category>도커</category>
      <category>젠킨스</category>
      <category>컨테이너</category>
      <author>Ginjoe</author>
      <guid isPermaLink="true">https://itdar.tistory.com/432</guid>
      <comments>https://itdar.tistory.com/432#entry432comment</comments>
      <pubDate>Fri, 21 Jun 2024 19:34:04 +0900</pubDate>
    </item>
    <item>
      <title>맥북 개발용 최초 세팅 (MACBOOK development environment initial setting)</title>
      <link>https://itdar.tistory.com/431</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;필수적인 것들, 개인적으로 좋았던 것들을 메모겸 적어둔다.&lt;/b&gt;&lt;/p&gt;
&lt;table style=&quot;width: 461px;&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style12&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&quot;width: 289px;&quot;&gt;&amp;nbsp;&lt;/th&gt;
&lt;th style=&quot;width: 172px;&quot;&gt;&amp;nbsp;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 289px;&quot;&gt;이름&lt;/td&gt;
&lt;td style=&quot;width: 172px;&quot;&gt;용도&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 289px;&quot;&gt;intellij&lt;/td&gt;
&lt;td style=&quot;width: 172px;&quot;&gt;통합개발환경툴&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 289px;&quot;&gt;fork&lt;/td&gt;
&lt;td style=&quot;width: 172px;&quot;&gt;깃 gui&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 289px;&quot;&gt;chrome&lt;/td&gt;
&lt;td style=&quot;width: 172px;&quot;&gt;웹브라우저&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 289px;&quot;&gt;&lt;a href=&quot;https://hbase.tistory.com/427&quot;&gt;iterm2 + (&lt;/a&gt;&lt;a href=&quot;https://hbase.tistory.com/427)&quot;&gt;https://hbase.tistory.com/427)&lt;/a&gt;&lt;/td&gt;
&lt;td style=&quot;width: 172px;&quot;&gt;커맨드&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 289px;&quot;&gt;goland&lt;/td&gt;
&lt;td style=&quot;width: 172px;&quot;&gt;통합개발환경툴&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 289px;&quot;&gt;workbench&lt;/td&gt;
&lt;td style=&quot;width: 172px;&quot;&gt;DB gui&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 289px;&quot;&gt;3tstudio&lt;/td&gt;
&lt;td style=&quot;width: 172px;&quot;&gt;mongo db gui&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 289px;&quot;&gt;postman&lt;/td&gt;
&lt;td style=&quot;width: 172px;&quot;&gt;http gui&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 289px;&quot;&gt;openlens&lt;/td&gt;
&lt;td style=&quot;width: 172px;&quot;&gt;k8s gui&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 289px;&quot;&gt;rancher desktop&lt;/td&gt;
&lt;td style=&quot;width: 172px;&quot;&gt;docker&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 289px;&quot;&gt;drawio&lt;/td&gt;
&lt;td style=&quot;width: 172px;&quot;&gt;diagram tool&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 289px;&quot;&gt;visual studio code&lt;/td&gt;
&lt;td style=&quot;width: 172px;&quot;&gt;editor&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 289px;&quot;&gt;microsoft edge&lt;/td&gt;
&lt;td style=&quot;width: 172px;&quot;&gt;web browser&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 289px;&quot;&gt;microsoft pp, excel, word, etc..&lt;/td&gt;
&lt;td style=&quot;width: 172px;&quot;&gt;~&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 289px;&quot;&gt;amphetamine&lt;/td&gt;
&lt;td style=&quot;width: 172px;&quot;&gt;화면 꺼지지 않도록&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;</description>
      <category>Programming</category>
      <category>mac 세팅</category>
      <category>개발자 세팅</category>
      <category>개발환경</category>
      <category>맥북 세팅</category>
      <category>최초 세팅</category>
      <author>Ginjoe</author>
      <guid isPermaLink="true">https://itdar.tistory.com/431</guid>
      <comments>https://itdar.tistory.com/431#entry431comment</comments>
      <pubDate>Tue, 11 Jun 2024 17:21:19 +0900</pubDate>
    </item>
    <item>
      <title>캐싱을 한다면 고려할 점 (Spring, @Cachable, @CacheEvict)</title>
      <link>https://itdar.tistory.com/429</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;서버에서 어떤 요청에 대해서 캐싱을 하려면 고려해야 할 것들이..&lt;br /&gt;1.&amp;nbsp;정상&amp;nbsp;반환에&amp;nbsp;대해서만&amp;nbsp;캐싱&lt;br /&gt;2.&amp;nbsp;유효한&amp;nbsp;캐싱&amp;nbsp;시간을&amp;nbsp;설정하고&amp;nbsp;지나면&amp;nbsp;삭제&amp;nbsp;후&amp;nbsp;다시&amp;nbsp;로딩/계산&amp;nbsp;후&amp;nbsp;캐싱&amp;nbsp;(왜냐면&amp;nbsp;그&amp;nbsp;사이에&amp;nbsp;내용이&amp;nbsp;변화할&amp;nbsp;수&amp;nbsp;있으니까)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;스프링 프레임워크를 놓고 본다면...&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1676814986685&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Cachable(value = &quot;캐시이름&quot;, key = &quot;#캐싱키이름(파라미터)&quot;, unless = &quot;#result == null&quot;)
public Object methodForCache(Object 캐싱키이름(파라미터)) {
    무언가 작업을 하고;
    return 결과물;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;이 때, 스프링 캐시의 구현체로 설정하는 ehcache, redis 등의 cache manager 에서 ttl (time to live) 설정을 하는 것도 가능하겠지만..&lt;/p&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;pre id=&quot;code_1676814959895&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@CacheEvict(cacheNames=&quot;캐시이름&quot;, allEntries=true)
@Scheduled(fixedRate=시간)
public void evictCache() { }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;으로 시간을 설정해서 초기화 가능하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;@EnableScheduled ? 였나 선언 안하면 스케줄 안먹는거 까먹지 말장&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;api 호출로 특정 이름과 키값의 캐싱을 삭제 할 수 있도록 백도어?를 만들어두기도 했던 것 같다.&lt;/p&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;</description>
      <category>Programming</category>
      <category>@Cachable</category>
      <category>@CacheEvict</category>
      <category>cache</category>
      <category>Spring</category>
      <category>캐시</category>
      <category>캐시 삭제</category>
      <author>Ginjoe</author>
      <guid isPermaLink="true">https://itdar.tistory.com/429</guid>
      <comments>https://itdar.tistory.com/429#entry429comment</comments>
      <pubDate>Sun, 19 Feb 2023 22:59:29 +0900</pubDate>
    </item>
    <item>
      <title>Java collection 교집합 retainsAll() 에 대하여 (List, Set, 시간복잡도, 최적화)</title>
      <link>https://itdar.tistory.com/428</link>
      <description>&lt;h1&gt;List vs Set, Time complexity&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;보통 2개의 다른 콜렉션 등에서 같은 것들을 찾는 등의 동작은 List 의 경우는 n^2 시간복잡도이다 (빅오)&lt;ul&gt;
&lt;li&gt;그래서 중복이 없다면 기준이 되는 콜렉션을 Set 으로 사용하면 n 시간복잡도로 해결 할 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;UUID 교집합을 골라내는 작업 중 최적화가 필요한 부분이 있었는데, List 두개를 retainAll() 을 사용해서 구하고 있었다.&lt;ul&gt;
&lt;li&gt;n^2 의 경우에 약 50만^2 정도의 연산횟수가 필요했는데 &lt;/li&gt;
&lt;li&gt;retainAll() 을 사용할 필요없이 기준을 Set 으로 해서 O(n) 으로 마칠 수 있을 것 같다는 의견을 전달했다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;최초 내 생각은 Set 을 사용하되 retainAll 에 해당하는 메서드를 만들면 된다는 말이었지만&lt;ul&gt;
&lt;li&gt;Set, List 로 기존 콜렉션 메서드 retainAll 을 사용해도 이미 최적화된 결과가 나왔다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;@Test
void testest() {
    List&amp;lt;String&amp;gt; a = new ArrayList&amp;lt;&amp;gt;();
    List&amp;lt;String&amp;gt; b = new ArrayList&amp;lt;&amp;gt;();

    // setUp
    for (int i = 0; i &amp;lt; 500000; i++) {
        a.add(UUID.randomUUID().toString());
    }

    for (int i = 0; i &amp;lt; 10000; i++) {
        b.add(a.get(i+10000));
    }

    // List
    long start = System.currentTimeMillis();

    a.retainAll(b);

    long finish = System.currentTimeMillis();
    long timeElapsed = finish - start;

    System.out.println(&amp;quot; List retainAll() &amp;gt;&amp;gt; &amp;quot; + timeElapsed / 1000 + &amp;quot; sec&amp;quot;);

    // Set
    Set&amp;lt;String&amp;gt; set = new HashSet&amp;lt;&amp;gt;(a);

    start = System.currentTimeMillis();

    set.retainAll(b);

    finish = System.currentTimeMillis();
    timeElapsed = finish - start;

    System.out.println(&amp;quot; Set retainAll() &amp;gt;&amp;gt; &amp;quot; + timeElapsed / 1000 + &amp;quot; sec&amp;quot;);
}&lt;/code&gt;&lt;/pre&gt;</description>
      <category>Programming</category>
      <category>Collection</category>
      <category>Java</category>
      <category>list</category>
      <category>retainAll</category>
      <category>set</category>
      <category>time complexity</category>
      <category>시간복잡도</category>
      <author>Ginjoe</author>
      <guid isPermaLink="true">https://itdar.tistory.com/428</guid>
      <comments>https://itdar.tistory.com/428#entry428comment</comments>
      <pubDate>Sun, 23 Oct 2022 22:43:05 +0900</pubDate>
    </item>
    <item>
      <title>HTTP 메시지에 관하여.. (HTTP/1.1 기준)</title>
      <link>https://itdar.tistory.com/427</link>
      <description>&lt;h1&gt;HTTP 메시지에 관하여.. (HTTP/1.1 기준)&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;기본적인 HTTP 메시지의 구조는  &lt;ul&gt;
&lt;li&gt;&lt;code&gt;메시지 헤더&lt;/code&gt;, &lt;code&gt;개행문자&lt;/code&gt;, &lt;code&gt;메시지 바디&lt;/code&gt; 로 만들어진다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;크게 Request, Response 메시지로 나눌 수 있다.&lt;/li&gt;
&lt;li&gt;요청과 응답 시 헤더의 차이가 나는데,&lt;ul&gt;
&lt;li&gt;요청 시: 리퀘스트 라인, 리퀘스트 헤더필드, 일반 헤더필드, 엔티티 헤더필드&lt;/li&gt;
&lt;li&gt;응답 시: 상태 라인, 리스폰스 헤더필드, 일반 헤더필드, 엔티티 헤더필드&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h4&gt;메시지 바디와 엔티티 바디의 차이점은?&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;기본적으로 HTTP 메시지 바디의 역할은 리퀘스트와 리스폰스에 관한 엔티티 바디를 운반하는 일이다.&lt;/li&gt;
&lt;li&gt;따라서 기본적으로 메시지 바디와 엔티티 바디는 같지만, 전송 코딩이 적용되는 경우에 엔티티 바디의 내용이 변화하기 때문에 메시지 바디와 달라지게 된다.&lt;ul&gt;
&lt;li&gt;메시지 바디 안에 엔티티 바디가 있다고 이해하면 될 듯 하다.&lt;/li&gt;
&lt;li&gt;인코딩된 엔티티는 클라 쪽에서 디코딩해서 사용함&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h4&gt;메시지 바디의 엔티티를 콘텐츠 코딩하는 콘텐츠 압축의 종류는?&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;gzip(GNU zip)&lt;/li&gt;
&lt;li&gt;compress(UNIX의 표준 압축)&lt;/li&gt;
&lt;li&gt;deflate(zlib)&lt;/li&gt;
&lt;li&gt;identity(인코딩 없음)&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h4&gt;최적의 콘텐츠를 내려주기 위한 콘텐츠 네고시에이션이란? (Content Negotiation)&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;같은 콘텐츠 이지만 여러 개의 페이지를 지닌 웹페이지 등의 경우, 예를 들면 같은 내용에 영어판, 한국어판 처럼 같이 표시되는 언어가 다른 경우&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;주로 사용하는 브라우저가 같은 URI 에 액세스 할 때 적절하게 웹페이지를 표시한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;제공 기준으로는, 제공하는 리소스를 언어와 문자셋, 인코딩 방식 등 으로 한다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Accept&lt;/li&gt;
&lt;li&gt;Accept-Charset&lt;/li&gt;
&lt;li&gt;Accept-Encoding&lt;/li&gt;
&lt;li&gt;Accept-Language&lt;/li&gt;
&lt;li&gt;Content-Language&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Server-driven Negotiation&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;서버 측에서 요청 헤더필드를 참고해서 처리 (브라우저가 보낸 정보 기반이라서 유저에게 정말 적절한지 모름) &lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Agent-driven Negotiation&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;클라이언트에서 브라우저에 표시된 선택지 중에서 유저가 수동으로 선택&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Transparent Negotiation&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;서버와 에이전트 구동형을 각각 혼합&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&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;th&gt;설명&lt;/th&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;1xx&lt;/td&gt;
&lt;td&gt;Informational&lt;/td&gt;
&lt;td&gt;요청을 받아들여 처리 중&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2xx&lt;/td&gt;
&lt;td&gt;Success&lt;/td&gt;
&lt;td&gt;요청을 정상적으로 처리했음&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;200&lt;/td&gt;
&lt;td&gt;OK&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;204&lt;/td&gt;
&lt;td&gt;No Content&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;206&lt;/td&gt;
&lt;td&gt;Partial Content&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3xx&lt;/td&gt;
&lt;td&gt;Redirection&lt;/td&gt;
&lt;td&gt;요청을 완료하기 위해 추가 동작이 필요함&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;301&lt;/td&gt;
&lt;td&gt;Moved Permanently&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;302&lt;/td&gt;
&lt;td&gt;Found&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;303&lt;/td&gt;
&lt;td&gt;See Other&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;304&lt;/td&gt;
&lt;td&gt;Not Modified&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;307&lt;/td&gt;
&lt;td&gt;Temporary Redirect&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4xx&lt;/td&gt;
&lt;td&gt;Client Error&lt;/td&gt;
&lt;td&gt;서버는 리퀘스트를 이해 불가능함&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;400&lt;/td&gt;
&lt;td&gt;Client Error&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;401&lt;/td&gt;
&lt;td&gt;Unauthorized&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;403&lt;/td&gt;
&lt;td&gt;Forbidden&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;404&lt;/td&gt;
&lt;td&gt;Not Found&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5xx&lt;/td&gt;
&lt;td&gt;Server Error&lt;/td&gt;
&lt;td&gt;서버는 리퀘스트 처리 실패함&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;500&lt;/td&gt;
&lt;td&gt;Internal Server Error&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;503&lt;/td&gt;
&lt;td&gt;Service Unavailable&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;ul&gt;
&lt;li&gt;에러가 발생한 경우에도 에러메시지를 포함한 200 OK 가 오는 경우도 많음...  &lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h4&gt;웹서버에 관하여?&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;HTTP 를 이용 할 때 도메인명이 달라도 DNS 에 의해서 IP 로 변환되어 액세스 하기 때문에 서버에 도착한 시점에 서버에 여러 도메인 서버가 있을 경우 어떤 도메인에 대한 액세스인지 알 수 없음&lt;ul&gt;
&lt;li&gt;같은 IP 주소에 다른 호스트명과 도메인 명을 가진 여러 웹서버가 실행되는 가상 호스트 시스템이 있음&lt;/li&gt;
&lt;li&gt;HTTP 리퀘스트 보낼 경우 호스트명과 도메인 명을 완전하게 포함한 URI 를 지정하거나, 반드시 Host 헤더필드에 지정을 해야함&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;통신을 중계하는 것으로는&lt;ul&gt;
&lt;li&gt;프록시, 게이트웨이, 터널 이 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&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;th&gt;상세&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Cache-Control&lt;/td&gt;
&lt;td&gt;캐싱 동작 지정&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Connection&lt;/td&gt;
&lt;td&gt;커넥션 관리, Hop-by-hop 헤더&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Date&lt;/td&gt;
&lt;td&gt;메시지 생성 날짜&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pragma&lt;/td&gt;
&lt;td&gt;메시지 제어&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Trailer&lt;/td&gt;
&lt;td&gt;메시지 끝에 있는 헤더의 일람&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Transfer-Encoding&lt;/td&gt;
&lt;td&gt;메시지 바디의 전송 코딩 형식 지정&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Upgrade&lt;/td&gt;
&lt;td&gt;다른 프로토콜에 업그레이드&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Via&lt;/td&gt;
&lt;td&gt;프록시 서버에 관한 정보&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Warning&lt;/td&gt;
&lt;td&gt;에러 통지&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;br&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&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;th&gt;상세&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Accept&lt;/td&gt;
&lt;td&gt;유저 에이전트가 처리 가능한 미디어 타입&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Accept-Charset&lt;/td&gt;
&lt;td&gt;문자셋 우선순위&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Accept-Encoding&lt;/td&gt;
&lt;td&gt;콘텐츠 인코딩 우선순위&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Accept-Language&lt;/td&gt;
&lt;td&gt;언어(자연어) 우선순위&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Authorization&lt;/td&gt;
&lt;td&gt;웹 인증을 위한 정보&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Expect&lt;/td&gt;
&lt;td&gt;서버에 대한 특정 동작의 기대&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;From&lt;/td&gt;
&lt;td&gt;유저의 메일 주소&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Host&lt;/td&gt;
&lt;td&gt;요구된 리소스 호스트&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;If-Match&lt;/td&gt;
&lt;td&gt;리소스 태그의 비교&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;If-Modified-Since&lt;/td&gt;
&lt;td&gt;리소스 갱신 시간 비교&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;If-None-Match&lt;/td&gt;
&lt;td&gt;엔티티 태그의 비교 (If-Match 의 반대)&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;If-Range&lt;/td&gt;
&lt;td&gt;리소스가 갱신되지 않은 경우에 엔티티의 바이트 범위의 요구를 송신&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;If-Unmodified-Since&lt;/td&gt;
&lt;td&gt;리소스의 갱신 시간 비교 (If-Modified-Since 의 반대)&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Max-Forwards&lt;/td&gt;
&lt;td&gt;최대 전송 홉 수&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Proxy-Authorization&lt;/td&gt;
&lt;td&gt;프록시 서버의 클라이언트 인증을 위한 정보&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Range&lt;/td&gt;
&lt;td&gt;엔티티 바이트 범위 요구 (청크 전송 등)&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Referer&lt;/td&gt;
&lt;td&gt;리퀘스트 중의 URI 를 취득하는 곳&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;TE&lt;/td&gt;
&lt;td&gt;전송 인코딩의 우선순위&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;User-Agent&lt;/td&gt;
&lt;td&gt;HTTP 클라이언트 정보&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br&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;th&gt;상세&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Accept-Ranges&lt;/td&gt;
&lt;td&gt;바이트 단위의 요구를 수신할 수 있는지 없는지 여부&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Age&lt;/td&gt;
&lt;td&gt;리소스의 지정 경과 시간&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Etag&lt;/td&gt;
&lt;td&gt;리소스 특정하기 위한 정보&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Location&lt;/td&gt;
&lt;td&gt;클라이언트를 지정한 URI 에 리다이렉트&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Proxy-Authenticate&lt;/td&gt;
&lt;td&gt;프록시 서버의 클아이언트 인증을 위한 정보&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Retry-After&lt;/td&gt;
&lt;td&gt;리퀘스트 재시행의 타이밍 요구&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Server&lt;/td&gt;
&lt;td&gt;HTTP 서버 정보&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Vary&lt;/td&gt;
&lt;td&gt;프록시 서버에 대한 캐시 관리 정보&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;WWW-Authenticate&lt;/td&gt;
&lt;td&gt;서버의 클라이언트 인증을 위한 정보&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br&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;th&gt;상세&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Allow&lt;/td&gt;
&lt;td&gt;리소스가 제공하는 HTTP 메소드&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Content-Encoding&lt;/td&gt;
&lt;td&gt;엔티티 바디에 적용되는 콘텐츠 인코딩&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Content-Language&lt;/td&gt;
&lt;td&gt;엔티티의 자연어&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Content-Length&lt;/td&gt;
&lt;td&gt;엔티티 바디의 사이즈(단위:바이트)&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Content-Location&lt;/td&gt;
&lt;td&gt;리소스에 대응하는 대체 URI&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Content-MD5&lt;/td&gt;
&lt;td&gt;엔티티 바디의 메시지 다이제스트&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Content-Range&lt;/td&gt;
&lt;td&gt;엔티티 바디의 범위 위치(청크 전송 시)&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Content-Type&lt;/td&gt;
&lt;td&gt;엔티티 바디의 미디어 타입&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Expires&lt;/td&gt;
&lt;td&gt;엔티티 바디의 유효기한 날짜&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Last-Modified&lt;/td&gt;
&lt;td&gt;리소스의 최종 갱신 날짜&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;hr&gt;
&lt;h3&gt;HTTPS 란?&lt;/h3&gt;
&lt;p&gt; IP 위에 TCP 위에 HTTP 를 사용하는데 SSL(TLS) 로 암호화를 해서 보안성을 높였다.&lt;br&gt;대칭키를 사용하는데, 이 대칭키를 교환하기 위해서 인증기관과 서버의 비대칭키를 사용한다.&lt;/p&gt;
&lt;hr&gt;
&lt;h4&gt;Reference&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;그림으로 배우는 Http Network Basic&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/ko/docs/Web/HTTP/Messages&quot;&gt;https://developer.mozilla.org/ko/docs/Web/HTTP/Messages&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Programming</category>
      <category>HTTP</category>
      <category>HTTP 1.1</category>
      <category>http message</category>
      <category>Network</category>
      <category>Request</category>
      <category>response</category>
      <author>Ginjoe</author>
      <guid isPermaLink="true">https://itdar.tistory.com/427</guid>
      <comments>https://itdar.tistory.com/427#entry427comment</comments>
      <pubDate>Fri, 19 Aug 2022 00:54:19 +0900</pubDate>
    </item>
    <item>
      <title>MySQL vs Cubrid, 차이에 관하여...</title>
      <link>https://itdar.tistory.com/426</link>
      <description>&lt;h1&gt;MySQL vs Cubrid, 차이에 관하여...&lt;/h1&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;/li&gt;
&lt;li&gt;쿼리&lt;/li&gt;
&lt;li&gt;함수&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;그냥 이러이런게 다르다더라 정도로 보면 될 듯 하다. 전체 차이점도 아니다.&lt;/h4&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;일반 기능&lt;/h2&gt;
&lt;table style=&quot;height: 352px; width: 757px;&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;th style=&quot;height: 20px; width: 202.391px;&quot;&gt;범주&lt;/th&gt;
&lt;th style=&quot;height: 20px; width: 248.188px;&quot;&gt;MySQL&lt;/th&gt;
&lt;th style=&quot;height: 20px; width: 292.422px;&quot;&gt;Cubrid&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;height: 20px; width: 188.391px;&quot;&gt;테이블 내의 속성 수&lt;/td&gt;
&lt;td style=&quot;height: 20px; width: 234.188px;&quot;&gt;~3398&lt;/td&gt;
&lt;td style=&quot;height: 20px; width: 278.422px;&quot;&gt;제한 없음&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 38px;&quot;&gt;
&lt;td style=&quot;height: 38px; width: 188.391px;&quot;&gt;레코드 크기&lt;/td&gt;
&lt;td style=&quot;height: 38px; width: 234.188px;&quot;&gt;~65534 &lt;br /&gt;(BLOB, TEXT 별도)&lt;/td&gt;
&lt;td style=&quot;height: 38px; width: 278.422px;&quot;&gt;제한 없음&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;height: 20px; width: 188.391px;&quot;&gt;명명 규칙 (테이블, 뷰, 인덱스)&lt;/td&gt;
&lt;td style=&quot;height: 20px; width: 234.188px;&quot;&gt;대상_이름&lt;/td&gt;
&lt;td style=&quot;height: 20px; width: 278.422px;&quot;&gt;[소유자].대상_이름&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;height: 20px; width: 188.391px;&quot;&gt;데이터베이스 이름&lt;/td&gt;
&lt;td style=&quot;height: 20px; width: 234.188px;&quot;&gt;도메인 내 고유&lt;/td&gt;
&lt;td style=&quot;height: 20px; width: 278.422px;&quot;&gt;도메인 내 고유&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;height: 20px; width: 188.391px;&quot;&gt;데이터베이스 이름 길이&lt;/td&gt;
&lt;td style=&quot;height: 20px; width: 234.188px;&quot;&gt;64바이트&lt;/td&gt;
&lt;td style=&quot;height: 20px; width: 278.422px;&quot;&gt;최대 17바이트&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;height: 20px; width: 188.391px;&quot;&gt;테이블 이름&lt;/td&gt;
&lt;td style=&quot;height: 20px; width: 234.188px;&quot;&gt;데이터베이스 사용자 계정 안에서 고유&lt;/td&gt;
&lt;td style=&quot;height: 20px; width: 278.422px;&quot;&gt;데이터베이스 안에서 고유, 대소문자 구분 없음&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;데이터 타입&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;대체적으로 비슷하지만, 다른 부분들이 있음
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;MySQL 에서 타입이 더 세분화하여 나뉘어져 있다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Cubrid 는 BIT 가 BIT, BOOLEAN 을 커버&lt;/li&gt;
&lt;li&gt;Cubrid 는 SMALLINT 가 TYNYINT, SMALLINT 를 커버&lt;/li&gt;
&lt;li&gt;Cubrid 는 INTEGER 가 MEDIUMINT, INTEGER 를 커버&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;MySQL 은 BLOB 이 용량별로 4종류 이지만 Cubrid 는 2종류&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;table style=&quot;width: 842px; height: 716px;&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;th style=&quot;width: 266.469px; height: 20px;&quot;&gt;MySQL&lt;/th&gt;
&lt;th style=&quot;width: 247.641px; height: 20px;&quot;&gt;Cubrid&lt;/th&gt;
&lt;th style=&quot;width: 313.891px; height: 20px;&quot;&gt;비고&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 18px;&quot;&gt;
&lt;td style=&quot;width: 252.469px; height: 18px;&quot;&gt;BIT&lt;/td&gt;
&lt;td style=&quot;width: 233.641px; height: 18px;&quot;&gt;BIT&lt;/td&gt;
&lt;td style=&quot;width: 299.891px; height: 18px;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 18px;&quot;&gt;
&lt;td style=&quot;width: 252.469px; height: 18px;&quot;&gt;BOOLEAN&lt;/td&gt;
&lt;td style=&quot;width: 233.641px; height: 18px;&quot;&gt;BIT&lt;/td&gt;
&lt;td style=&quot;width: 299.891px; height: 18px;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 36px;&quot;&gt;
&lt;td style=&quot;width: 252.469px; height: 36px;&quot;&gt;TYNYINT&lt;/td&gt;
&lt;td style=&quot;width: 233.641px; height: 36px;&quot;&gt;SMALLINT&lt;/td&gt;
&lt;td style=&quot;width: 299.891px; height: 36px;&quot;&gt;tinyint -&amp;gt; 1byte, &lt;br /&gt;smallint -&amp;gt; 2byte&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 18px;&quot;&gt;
&lt;td style=&quot;width: 252.469px; height: 18px;&quot;&gt;SMALLINT&lt;/td&gt;
&lt;td style=&quot;width: 233.641px; height: 18px;&quot;&gt;SMALLINT&lt;/td&gt;
&lt;td style=&quot;width: 299.891px; height: 18px;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 36px;&quot;&gt;
&lt;td style=&quot;width: 252.469px; height: 36px;&quot;&gt;MEDIUMINT&lt;/td&gt;
&lt;td style=&quot;width: 233.641px; height: 36px;&quot;&gt;INTEGER&lt;/td&gt;
&lt;td style=&quot;width: 299.891px; height: 36px;&quot;&gt;midiumint -&amp;gt; 3byte, &lt;br /&gt;integer -&amp;gt; 4byte&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 18px;&quot;&gt;
&lt;td style=&quot;width: 252.469px; height: 18px;&quot;&gt;INTEGER&lt;/td&gt;
&lt;td style=&quot;width: 233.641px; height: 18px;&quot;&gt;INTEGER&lt;/td&gt;
&lt;td style=&quot;width: 299.891px; height: 18px;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 18px;&quot;&gt;
&lt;td style=&quot;width: 252.469px; height: 18px;&quot;&gt;BIGINT&lt;/td&gt;
&lt;td style=&quot;width: 233.641px; height: 18px;&quot;&gt;BIGINT&lt;/td&gt;
&lt;td style=&quot;width: 299.891px; height: 18px;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 18px;&quot;&gt;
&lt;td style=&quot;width: 252.469px; height: 18px;&quot;&gt;REAL&lt;/td&gt;
&lt;td style=&quot;width: 233.641px; height: 18px;&quot;&gt;REAL&lt;/td&gt;
&lt;td style=&quot;width: 299.891px; height: 18px;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 18px;&quot;&gt;
&lt;td style=&quot;width: 252.469px; height: 18px;&quot;&gt;DOUBLE&lt;/td&gt;
&lt;td style=&quot;width: 233.641px; height: 18px;&quot;&gt;DOUBLE&lt;/td&gt;
&lt;td style=&quot;width: 299.891px; height: 18px;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 36px;&quot;&gt;
&lt;td style=&quot;width: 252.469px; height: 36px;&quot;&gt;DOUBLE PRECISION&lt;/td&gt;
&lt;td style=&quot;width: 233.641px; height: 36px;&quot;&gt;DOUBLE PRECISION&lt;/td&gt;
&lt;td style=&quot;width: 299.891px; height: 36px;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 18px;&quot;&gt;
&lt;td style=&quot;width: 252.469px; height: 18px;&quot;&gt;FLOAT(n)&lt;/td&gt;
&lt;td style=&quot;width: 233.641px; height: 18px;&quot;&gt;FLOAT(n)&lt;/td&gt;
&lt;td style=&quot;width: 299.891px; height: 18px;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 36px;&quot;&gt;
&lt;td style=&quot;width: 252.469px; height: 36px;&quot;&gt;DECIMAL(p,s), &lt;br /&gt;NUMERIC(p,s)&lt;/td&gt;
&lt;td style=&quot;width: 233.641px; height: 36px;&quot;&gt;DECIMAL(p,s), &lt;br /&gt;NUMERIC(p,s)&lt;/td&gt;
&lt;td style=&quot;width: 299.891px; height: 36px;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 60px;&quot;&gt;
&lt;td style=&quot;width: 252.469px; height: 60px;&quot;&gt;TINYBLOB &amp;lt;= 256&lt;/td&gt;
&lt;td style=&quot;width: 233.641px; height: 60px;&quot;&gt;BIT VARYING(n) &lt;br /&gt;or &lt;br /&gt;Large Object(GLO)&lt;/td&gt;
&lt;td style=&quot;width: 299.891px; height: 60px;&quot;&gt;Cubrid 에서, &lt;br /&gt;1G 이하는 BIT VARYING, &lt;br /&gt;1G 이상은 GLO 대체 권장&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 60px;&quot;&gt;
&lt;td style=&quot;width: 252.469px; height: 60px;&quot;&gt;BLOB &amp;lt;= 65K&lt;/td&gt;
&lt;td style=&quot;width: 233.641px; height: 60px;&quot;&gt;BIT VARYING(n) &lt;br /&gt;or &lt;br /&gt;Large Object(GLO)&lt;/td&gt;
&lt;td style=&quot;width: 299.891px; height: 60px;&quot;&gt;Cubrid 에서, &lt;br /&gt;1G 이하는 BIT VARYING, &lt;br /&gt;1G 이상은 GLO 대체 권장&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 60px;&quot;&gt;
&lt;td style=&quot;width: 252.469px; height: 60px;&quot;&gt;MEDIUMBLOB &amp;lt;= 16M&lt;/td&gt;
&lt;td style=&quot;width: 233.641px; height: 60px;&quot;&gt;BIT VARYING(n) &lt;br /&gt;or &lt;br /&gt;Large Object(GLO)&lt;/td&gt;
&lt;td style=&quot;width: 299.891px; height: 60px;&quot;&gt;Cubrid 에서, &lt;br /&gt;1G 이하는 BIT VARYING, &lt;br /&gt;1G 이상은 GLO 대체 권장&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 60px;&quot;&gt;
&lt;td style=&quot;width: 252.469px; height: 60px;&quot;&gt;LONGBLOB &amp;lt;= 4G&lt;/td&gt;
&lt;td style=&quot;width: 233.641px; height: 60px;&quot;&gt;BIT VARYING(n) &lt;br /&gt;or &lt;br /&gt;Large Object(GLO)&lt;/td&gt;
&lt;td style=&quot;width: 299.891px; height: 60px;&quot;&gt;Cubrid 에서, &lt;br /&gt;1G 이하는 BIT VARYING, &lt;br /&gt;1G 이상은 GLO 대체 권장&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 36px;&quot;&gt;
&lt;td style=&quot;width: 252.469px; height: 36px;&quot;&gt;DATE&lt;/td&gt;
&lt;td style=&quot;width: 233.641px; height: 36px;&quot;&gt;DATE&lt;/td&gt;
&lt;td style=&quot;width: 299.891px; height: 36px;&quot;&gt;MySQL: date -&amp;gt; 3byte &lt;br /&gt;Cubrid: date -&amp;gt; 4byte&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 18px;&quot;&gt;
&lt;td style=&quot;width: 252.469px; height: 18px;&quot;&gt;DATETIME&lt;/td&gt;
&lt;td style=&quot;width: 233.641px; height: 18px;&quot;&gt;DATETIME&lt;/td&gt;
&lt;td style=&quot;width: 299.891px; height: 18px;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 36px;&quot;&gt;
&lt;td style=&quot;width: 252.469px; height: 36px;&quot;&gt;TIME&lt;/td&gt;
&lt;td style=&quot;width: 233.641px; height: 36px;&quot;&gt;TIME&lt;/td&gt;
&lt;td style=&quot;width: 299.891px; height: 36px;&quot;&gt;MySQL: time -&amp;gt; 3byte &lt;br /&gt;Cubrid: time -&amp;gt; 4byte&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 252.469px; height: 20px;&quot;&gt;TIMESTAMP&lt;/td&gt;
&lt;td style=&quot;width: 233.641px; height: 20px;&quot;&gt;TIMESTAMP&lt;/td&gt;
&lt;td style=&quot;width: 299.891px; height: 20px;&quot;&gt;Cubrid: 초단위 연산만 지원&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 40px;&quot;&gt;
&lt;td style=&quot;width: 252.469px; height: 40px;&quot;&gt;YEAR&lt;/td&gt;
&lt;td style=&quot;width: 233.641px; height: 40px;&quot;&gt;-&lt;/td&gt;
&lt;td style=&quot;width: 299.891px; height: 40px;&quot;&gt;Cubrid: VARCHAR(4) 로 대체&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&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;919&quot; data-origin-height=&quot;543&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cx7A41/btrIVg66rQH/MH883d2lL1QGnfHVPSPKd0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cx7A41/btrIVg66rQH/MH883d2lL1QGnfHVPSPKd0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cx7A41/btrIVg66rQH/MH883d2lL1QGnfHVPSPKd0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcx7A41%2FbtrIVg66rQH%2FMH883d2lL1QGnfHVPSPKd0%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;919&quot; height=&quot;543&quot; data-origin-width=&quot;919&quot; data-origin-height=&quot;543&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;함수&lt;/h2&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;/ul&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;MySQL&lt;/th&gt;
&lt;th&gt;Cubrid&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;NOW&lt;/td&gt;
&lt;td&gt;SYSTIMESTAMP&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CURRENT_DATE&lt;/td&gt;
&lt;td&gt;CURRENT_DATE or SYSDATE or SYS_DATE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CURRENT_TIME&lt;/td&gt;
&lt;td&gt;CURRENT_TIME or SYSTIME or SYS_TIME&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;IFNULL&lt;/td&gt;
&lt;td&gt;NVL&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;LOCATE&lt;/td&gt;
&lt;td&gt;POSITION&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;LEFT&lt;/td&gt;
&lt;td&gt;SUBSTR&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;!= 또는 &amp;lt;&amp;gt;&lt;/td&gt;
&lt;td&gt;&amp;lt;&amp;gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CONCAT 또는 +&lt;/td&gt;
&lt;td&gt;+ 또는 or문자&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;쿼리&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;가장 차이가 느껴졌던 것만 추린다면,
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;MySQL 은 묵시적인 타입변환이 지원되지만, Cubrid 는 데이터타입의 명시적인 변환이 필요하다.&lt;/li&gt;
&lt;li&gt;Cubrid 는 subquery 에서 구문 외부의 alias 등을 참조할 수 있으나, MySQL 에서는 같은 쿼리를 사용하면 참조할 수 없다는 에러가 나서 수정했음
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;찾아보니.. mysql 은 2 depth 이상 차이의 외부 alias 는 참조 불가하다고 함&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;GROUP BY 관련 사용 불가한 경우가 있었음 (mysql 에서)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;정리&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;921&quot; data-origin-height=&quot;603&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/tyaob/btrIXARpOB3/AmzG5PnSIpPEz6rO0xiJ60/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/tyaob/btrIXARpOB3/AmzG5PnSIpPEz6rO0xiJ60/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/tyaob/btrIXARpOB3/AmzG5PnSIpPEz6rO0xiJ60/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Ftyaob%2FbtrIXARpOB3%2FAmzG5PnSIpPEz6rO0xiJ60%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;921&quot; height=&quot;603&quot; data-origin-width=&quot;921&quot; data-origin-height=&quot;603&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Reference&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://www.cubrid.com/education_materials&quot;&gt;https://www.cubrid.com/education_materials&lt;/a&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;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Programming</category>
      <category>cubrid</category>
      <category>MySQL</category>
      <author>Ginjoe</author>
      <guid isPermaLink="true">https://itdar.tistory.com/426</guid>
      <comments>https://itdar.tistory.com/426#entry426comment</comments>
      <pubDate>Thu, 4 Aug 2022 19:57:56 +0900</pubDate>
    </item>
    <item>
      <title>HTTP 2.0 에 관하여...</title>
      <link>https://itdar.tistory.com/425</link>
      <description>&lt;h1&gt;HTTP 2.0 에 대하여...&lt;/h1&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;HTTP 2.0 등장배경&lt;/li&gt;
&lt;li&gt;HTTP 2.0 특징&lt;/li&gt;
&lt;li&gt;정리&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/itdar/TIL/commit/533167fb17d0c7d0a25ec6dcc9f905778a5b93fd&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://github.com/itdar/TIL/commit/533167fb17d0c7d0a25ec6dcc9f905778a5b93fd&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1659460703767&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;chore: HTTP 2.0 에 관하여... &amp;middot; itdar/TIL@533167f&quot; data-og-description=&quot;+ HTTP Message&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/itdar/TIL/commit/533167fb17d0c7d0a25ec6dcc9f905778a5b93fd&quot; data-og-url=&quot;https://github.com/itdar/TIL/commit/533167fb17d0c7d0a25ec6dcc9f905778a5b93fd&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/kpRGH/hyPhrA3PXx/YVyRpLueBnOllIaw94xO1K/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/itdar/TIL/commit/533167fb17d0c7d0a25ec6dcc9f905778a5b93fd&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/itdar/TIL/commit/533167fb17d0c7d0a25ec6dcc9f905778a5b93fd&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/kpRGH/hyPhrA3PXx/YVyRpLueBnOllIaw94xO1K/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;chore: HTTP 2.0 에 관하여... &amp;middot; itdar/TIL@533167f&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;+ HTTP Message&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. HTTP 2.0 등장배경 (2015)&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;과거의 웹 요청 및 전송속도에 쓰던 전송기술이 현대와 맞지 않음
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;HTTP 1.1 이 1999년도에 나온 후 웹 전송기술의 표준이 게속 유지되었음&lt;/li&gt;
&lt;li&gt;옛날의 웹 요청과 다르게 최근에는 요청의 횟수와 요청 리소스 용량도 많아짐&lt;/li&gt;
&lt;li&gt;전송속도도 옛날에 비해 100배 이상 빨라지게 됨&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2. HTTP 2.0 특징&lt;/h2&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;바이너리 프로토콜
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;텍스트가 아닌 Binary 프레임으로 구성
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;파싱이 더 빠르고 오류 발생 가능성이 낮음&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;HEADERS frame(헤더), DATA frame(바디) 으로 구성됨&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;멀티플렉싱
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;하나의 TCP Connection 내에서 다수의 Stream 생성&lt;/li&gt;
&lt;li&gt;하나의 요청이 지연되면 나머지 응답도 늦어지는(HOL) HTTP Pipelining 과 다르게 각각의 요청/응답을 독립적으로 처리
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;다수의 요청/응답을 동시에 처리 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;프레임마다 관련된 요청 순서번호 (Stream #) 을 기재해서 요청 순서에 상관없이 데이터 전송 가능 (하나의 TCP 세션 사용)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;헤더 압축
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;반복적으로 사용되는 헤더를 헤더 테이블 내의 인덱스로 표기
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;헤더 크기를 80% 정도 줄임&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;이전 헤더 내용을 테이블에 저장, 다음 요청에서 동일 헤더 사용 시 테이블 인덱스 번호만 사용함&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;우선순위 설정
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Stream 별로 우선 순위를 지정
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;중요한 리소스의 처리 지연을 방지&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&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;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3. 정리&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;변화된 웹서비스 및 네트워크 환경에 맞게 15년여만에&lt;br /&gt;HTTP 표준 개정&lt;/li&gt;
&lt;li&gt;HTTP 2.0을 통해 웹서비스 성능 향상을 기대
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;다만, 환경에 따라서는 오히려 성능 저하가 올 수 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;웹서비스 최적화 기법의 재검토가 필요&lt;/li&gt;
&lt;li&gt;주요 브라우저의 h2(https) only 정책으로 인해 기존 웹서비스에 대한 수정/보완 작업이 필요&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Reference&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://www3.ntu.edu.sg/home/ehchua/programming/webprogramming/HTTP_Basics.html&quot;&gt;https://www3.ntu.edu.sg/home/ehchua/programming/webprogramming/HTTP_Basics.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://krnet.gagabox.com/board/data/dprogram/1929/C1-1-%C7%E3%C5%C2%BC%BA.pdf&quot;&gt;http://krnet.gagabox.com/board/data/dprogram/1929/C1-1-%C7%E3%C5%C2%BC%BA.pdf&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Programming</category>
      <category>HTTP</category>
      <category>HTTP 2.0</category>
      <category>SPDY</category>
      <author>Ginjoe</author>
      <guid isPermaLink="true">https://itdar.tistory.com/425</guid>
      <comments>https://itdar.tistory.com/425#entry425comment</comments>
      <pubDate>Wed, 3 Aug 2022 02:16:48 +0900</pubDate>
    </item>
    <item>
      <title>DispatcherServlet 에 관하여... (스프링 디스패처서블릿)</title>
      <link>https://itdar.tistory.com/424</link>
      <description>&lt;h1&gt;Dispatcher Servlet 에 관하여..&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;WAS -&amp;gt; Servlet Container (Servlet Context) -&amp;gt; Front Controller (Dispatcher Servlet) -&amp;gt; Servlet 으로 보면 될 것 같다.&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;스프링 뿐만 아니라 대부분의 web MVC 프레임워크들은, 요청을 웹어플리케이션의 다른 컨트롤러나 기능제공 부분에 전달(dispatch) 해주는 센터 서블릿을 두고 디자인 되어있다.&lt;/li&gt;
&lt;li&gt;스프링의 DispatcherServlet 은 Spring IoC Container 와 완벽히 통합되는 등 스프링이 제공하는 아주 많은 기능들을 사용할 수 있게 해준다.&lt;/li&gt;
&lt;li&gt;프론트컨트롤러 패턴으로 부를 수도 있고, 다른 많은 MVC 프레임워크들이 영향 받았다.&lt;/li&gt;
&lt;li&gt;아래는 스프링공식문서에서의 워크플로우이고, 이 중 프론트컨트롤러가 DispatcherServlet.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;513&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b3FBeD/btrH0tF7NT3/MiRwXFwtnRvCfct8jXGN6K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b3FBeD/btrH0tF7NT3/MiRwXFwtnRvCfct8jXGN6K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b3FBeD/btrH0tF7NT3/MiRwXFwtnRvCfct8jXGN6K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb3FBeD%2FbtrH0tF7NT3%2FMiRwXFwtnRvCfct8jXGN6K%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;800&quot; height=&quot;513&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;513&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;좀 더 상세하게 동작 방식을 본다면,&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1196&quot; data-origin-height=&quot;798&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/uIQfk/btrHZ7J4BUH/8wGd2Ku5KbZ8pGmv3KrbA0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/uIQfk/btrHZ7J4BUH/8wGd2Ku5KbZ8pGmv3KrbA0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/uIQfk/btrHZ7J4BUH/8wGd2Ku5KbZ8pGmv3KrbA0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FuIQfk%2FbtrHZ7J4BUH%2F8wGd2Ku5KbZ8pGmv3KrbA0%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;1196&quot; height=&quot;798&quot; data-origin-width=&quot;1196&quot; data-origin-height=&quot;798&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;DispatcherServlet receives the request.
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;code&gt;디스패처서블릿&lt;/code&gt;이 &lt;code&gt;요청&lt;/code&gt;을 받는다.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;DispatcherServlet dispatches the task of selecting an appropriate controller to HandlerMapping. HandlerMapping selects the controller which is mapped to the incoming request URL and returns the (selected Handler) and Controller to DispatcherServlet.
&lt;ol style=&quot;list-style-type: disc;&quot; start=&quot;2&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;디스패처서블릿은 적절한 &lt;code&gt;컨트롤러&lt;/code&gt;를 고르는 작업을 &lt;code&gt;핸들러매핑&lt;/code&gt;에게 넘긴다. 핸들러매핑은 요청 URL 과 매핑되는 컨트롤러를 찾고 핸들러와 컨트롤러를 디스패처서블릿에 넘겨준다.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;DispatcherServlet dispatches the task of executing of business logic of Controller to HandlerAdapter.
&lt;ol style=&quot;list-style-type: disc;&quot; start=&quot;3&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;디스패처서블릿은 컨트롤러의 비지니스로직의 실행 작업을 &lt;code&gt;핸들러어댑터&lt;/code&gt;에게 넘겨준다.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;HandlerAdapter calls the business logic process of Controller.
&lt;ol style=&quot;list-style-type: disc;&quot; start=&quot;4&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;핸들러어댑터는 컨트롤러의 비지니스 로직 과정을 호출한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;Controller executes the business logic, sets the processing result in Model and returns the logical name of view to HandlerAdapter.
&lt;ol style=&quot;list-style-type: disc;&quot; start=&quot;5&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;컨트롤러는 비지니스 로직을 실행하고, 결과를 모델에 저장하고, &lt;code&gt;뷰&lt;/code&gt;의 이름을 핸들러어댑터에게 전달한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;DispatcherServlet dispatches the task of resolving the View corresponding to the View name to ViewResolver. ViewResolver returns the View mapped to View name.
&lt;ol style=&quot;list-style-type: disc;&quot; start=&quot;6&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;디스패처서블릿은 뷰 네임에 맞는 뷰를 찾는 작업을 &lt;code&gt;뷰리졸버&lt;/code&gt;에 전달한다. 뷰리졸버는 뷰 이름에 매핑되는 뷰를 반환한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;DispatcherServlet dispatches the rendering process to returned View.
&lt;ol style=&quot;list-style-type: disc;&quot; start=&quot;7&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;디스패처서블릿은 반환될 뷰에 대한 &lt;code&gt;렌더링&lt;/code&gt; 프로세스를 진행한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;View renders Model data and returns the response.
&lt;ol style=&quot;list-style-type: disc;&quot; start=&quot;8&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;뷰는 모델데이터를 렌더링하고, &lt;code&gt;응답&lt;/code&gt;을 반환한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Reference&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.spring.io/spring-framework/docs/4.1.7.RELEASE/spring-framework-reference/html/mvc.html&quot;&gt;https://docs.spring.io/spring-framework/docs/4.1.7.RELEASE/spring-framework-reference/html/mvc.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://terasolunaorg.github.io/guideline/5.0.1.RELEASE/en/Overview/SpringMVCOverview.html#overview-of-spring-mvc-processing-sequence&quot;&gt;https://terasolunaorg.github.io/guideline/5.0.1.RELEASE/en/Overview/SpringMVCOverview.html#overview-of-spring-mvc-processing-sequence&lt;/a&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;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://itdar.tistory.com/418&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;2022.04.01 - [Programming] - DI 와 IoC 에 대한 개념과 스프링&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://itdar.tistory.com/413&quot;&gt;2022.02.17 - [Programming/Database] - Head First SQL (헤드퍼스트 SQL) 요약정리&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Programming</category>
      <category>Dispatcher Servlet</category>
      <category>Servlet</category>
      <category>Servlet Container</category>
      <category>Spring</category>
      <category>WAS</category>
      <category>디스패처서블릿</category>
      <category>스프링</category>
      <author>Ginjoe</author>
      <guid isPermaLink="true">https://itdar.tistory.com/424</guid>
      <comments>https://itdar.tistory.com/424#entry424comment</comments>
      <pubDate>Fri, 22 Jul 2022 23:57:55 +0900</pubDate>
    </item>
    <item>
      <title>GRASP 책임할당패턴에 대하여...</title>
      <link>https://itdar.tistory.com/423</link>
      <description>&lt;h1&gt;GRASP (General Responsibility Assignment Software Pattern) 에 관하여..&lt;/h1&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;책임 기반 객체지향 관점에서 객체에 책임을 할당하기 위한 패턴을 정리한 것&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;책임과 역할 이라는 말을 많이 쓰는데, 이 때 책임의 종류를 나열하고 어떻게 할당할 것인지에 대한 기준 패턴으로 보면 될 것 같다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Information Expert&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;역할을 수행할 수 있는 정보를 가지고 있는 객체에 역할을 부여한다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Problem: What is a basic principle by which to assign responsibilities to objects?&lt;/li&gt;
&lt;li&gt;Solution: Assign a responsibility to the class that has the information needed to fulfill it.&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;h4 data-ke-size=&quot;size20&quot;&gt;Creator&lt;/h4&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Problem: Who creates object A?&lt;/li&gt;
&lt;li&gt;Solution: Assign class B the responsibility to create object A if one of these is true (more is better)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;B contains or compositely aggregates A&lt;/li&gt;
&lt;li&gt;B records A&lt;/li&gt;
&lt;li&gt;B closely uses A&lt;/li&gt;
&lt;li&gt;B has the initializing data for A&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Controller&lt;/h4&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;돌고 있는 SW, 혹은 주요한 서브시스템의 전체 시스템이나 루트 객체를 표현한다. (퍼사드 컨트롤러의 범주)&lt;/li&gt;
&lt;li&gt;유즈케이스 시나리오에서 시스템 동작이 발생하는 것을 표현하도록 한다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Problem: What first object beyond the UI layer receives and coordinates &amp;ldquo;controls&amp;rdquo; a system operation?&lt;/li&gt;
&lt;li&gt;Solution: Assign the responsibility to an object representing one of these choices:
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Represents the overall &amp;ldquo;system&amp;rdquo;, &amp;ldquo;root object&amp;rdquo;, device that the software is running within, or a major subsystem (these are all variations of a facade controller)&lt;/li&gt;
&lt;li&gt;Represents a use case scenario within which the system operation occurs (a use case or session controller)&lt;/li&gt;
&lt;/ul&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;h4 data-ke-size=&quot;size20&quot;&gt;Low Coupling&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;객체들간, 서브 시스템들간의 상호의존도가 낮게 역할을 부여한다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Problem: How to reduce the impact of change? How to support low dependency and increased reuse?&lt;/li&gt;
&lt;li&gt;Solution: Assign responsibilities so that (unnecessary) coupling remains low. Use this principle to evaluate alternatives.&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;h4 data-ke-size=&quot;size20&quot;&gt;High Cohesion&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;각 객체가 밀접하게 연관된 역할들만 가지도록 역할을 부여한다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Problem: How to keep objects focused, understandable, manageable and as a side effect support Low Coupling?&lt;/li&gt;
&lt;li&gt;Solution: Assign a responsibility so that cohesion remains high. Use this to evaluate alternatives.&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;h4 data-ke-size=&quot;size20&quot;&gt;Indirection&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;두 객체 사이의 직접적인 Coupling 을 피하고 싶으면, 그 사이에 다른 객체를 사용한다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Problem: Where to assign a responsibility to avoid direct coupling between two or more things?&lt;/li&gt;
&lt;li&gt;Solution: Assign the responsibility to an intermediate object to mediate between other components or services so that they are not directly coupled.&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;h4 data-ke-size=&quot;size20&quot;&gt;Polymorphism&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;객체의 종류에 따라 행동양식이 바뀌면, Polymorphism 을 사용한다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Problem: How handle alternatives based on type?&lt;/li&gt;
&lt;li&gt;Solution: When related alternatives or behaviors vary by type (class), assign responsibility for the behavior (using polymorphic operations) to the types for which the behavior varies.&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;h4 data-ke-size=&quot;size20&quot;&gt;Pure Fabrication&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Information Expert 등의 다른 패턴을 적용 시 Low Coupling 과 High Cohesion 원칙이 깨진다면, 기능적인 역할을 별도의 한 곳으로 모은다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Problem: What object should have the responsibility, when you do not want to viloate High Cohesion and Low Coupling but solutions offered by other principles are not appopriate?&amp;gt;&lt;/li&gt;
&lt;li&gt;Solution: Assign a highly cohesive set of responsibilites to an artifical or convenience class that does not represent a problem domain conecept.&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;h4 data-ke-size=&quot;size20&quot;&gt;Protected Variations&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;변경될 여지가 있는 곳에 안정된 인터페이스를 정의해서 책임을 부여한다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Problem: How to design objects, subsystems and systems so that the variations or instability in these elements does not have an undesirable impact on other elements?&lt;/li&gt;
&lt;li&gt;Solution: Identify points of predicted variation or instability, assign responsibilities to create a stable interface around them.&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;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Reference&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;http://www.kamilgrzybek.com/design/grasp-explained/&quot;&gt;http://www.kamilgrzybek.com/design/grasp-explained/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://edu.nextstep.camp/&quot;&gt;https://edu.nextstep.camp/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Programming</category>
      <category>General Responsibility Assgnment Software Pattern</category>
      <category>grasp</category>
      <category>객체 책임 할당 소프트웨어 패턴</category>
      <category>책임할당패턴</category>
      <author>Ginjoe</author>
      <guid isPermaLink="true">https://itdar.tistory.com/423</guid>
      <comments>https://itdar.tistory.com/423#entry423comment</comments>
      <pubDate>Tue, 19 Jul 2022 02:00:38 +0900</pubDate>
    </item>
    <item>
      <title>HTTPS 에 관하여..</title>
      <link>https://itdar.tistory.com/422</link>
      <description>&lt;h1&gt;HTTPS 에 관하여..&lt;/h1&gt;
&lt;h3&gt;HTTPS 란?&lt;/h3&gt;
&lt;p&gt;IP(3계층) 위에 TCP(4계층) 위에 SSL/TSL(5계층) 위에 HTTP(6계층) 를 사용하는데 SSL 로 암호화를 해서 보안성을 높였다.&lt;br&gt;대칭키를 사용하는데, 이 대칭키를 교환하기 위해서 비대칭키를 사용하여 보안을 유지한다.  &lt;/p&gt;
&lt;h4&gt;과정&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;RSA 등의 비대칭 암호화 방법을 이용해서 서버에서 개인키(private)/공용키(public) 을 만들어둔다.  &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;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h4&gt;Cipher suite&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;SSL/TLS 통신 시, 키 교환 방식/암호화 방식 등의 상세 스펙을 정의해둔다.  &lt;/li&gt;
&lt;li&gt;클라이언트에서 지원 가능한 내용을 최초에 보내는 내용&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h4&gt;Cipher spec&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Change Cipher Spec 프로토콜은 Handshake 과정에서 데이터 암호화용 대칭키 생성이 완료되고 나면 이후부터 데이터를 암호화하라는 신호  &lt;/li&gt;
&lt;li&gt;서버에서 보내는 내용&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h4&gt;Reference&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.ibm.com/docs/ko/ibm-mq/9.1?topic=tls-cipherspecs-ciphersuites&quot;&gt;https://www.ibm.com/docs/ko/ibm-mq/9.1?topic=tls-cipherspecs-ciphersuites&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://kthan.tistory.com/entry/TLS-%ED%95%B8%EB%93%9C%EC%89%90%EC%9D%B4%ED%81%AC-Handshake-%ED%94%84%EB%A1%9C%ED%86%A0%EC%BD%9C-%EB%B6%84%EC%84%9D&quot;&gt;https://kthan.tistory.com/entry/TLS-%ED%95%B8%EB%93%9C%EC%89%90%EC%9D%B4%ED%81%AC-Handshake-%ED%94%84%EB%A1%9C%ED%86%A0%EC%BD%9C-%EB%B6%84%EC%84%9D&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Programming</category>
      <category>https</category>
      <category>ssl/tls</category>
      <category>TCP/IP</category>
      <category>네트워크</category>
      <author>Ginjoe</author>
      <guid isPermaLink="true">https://itdar.tistory.com/422</guid>
      <comments>https://itdar.tistory.com/422#entry422comment</comments>
      <pubDate>Wed, 13 Jul 2022 01:37:44 +0900</pubDate>
    </item>
    <item>
      <title>기계학습 개념 정리</title>
      <link>https://itdar.tistory.com/421</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;기계학습&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;데이터 정규화 (Normalization)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;값의 범위가 크게 다른 특징들을 입력 변수로 사용할 경우 -&amp;gt; 적절한 학습 안될 수 있음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각각의 특징들이 갖는 값들의 범위를 적당한 규모로 변경하는 작업&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;데이터 표준화 (Standardization)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데이터를 정제할 때 평균과 분산을 이용해서 데이터 분포를 0으로 맞춤&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&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;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;k-nn(Classification, 지도)&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;k-means(Clustering, 비지도)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;k-NN 알고리즘&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기존 라벨링된 데이터를 기준으로 근접 k 개 확인 후 다수결로 결정&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;동률의 경우에는 거리로 확정&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;장점: 단순하고 직관적임, 준비 시간이 필요없음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단점: 모든 데이터에 대한 정보 필요, 많은 메모리와 계산시간 필요함&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;표집편향 (Sampling bias)&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&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;gt; 양성으로 판단한 것 / 실제 양성 의 비율&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;재현율: 진짜 양성비율 -&amp;gt; 올바르게 양성판단 / (모델이)양성 판단 의 비율&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;재현율은 가로축, 정밀도는 세로축&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;TN FP&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;FN TP&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;F1 점수&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;정밀도와 재현율의 조화평균을 구한 점수&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;쇠렌센-다이스 계수&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;혼동행렬을 만들어서 확인함&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&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;여러 분류기가 각자 분류 결과를 내놓아 투표하듯 다수결&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다양성을 확보하는 방법으로 -&amp;gt; 각각 다른 모델의 분류기 만듦, 서로 다른 학습데이터 학습&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&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;gt; 페이스팅&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;배깅 기법을 개선한 방법이 부스팅&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&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;분류기를 순차적으로 학습시키면서 이전 분류기가 제대로 처리하지 못한 데이터의 가중치를 올리고, 다음 예측기는 높은 가중치에 더 집중해서 학습&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&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;/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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;k-means 알고리즘&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;k 개의 그룹으로 나누는 알고리즘&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;군집개수 k 를 알아야함&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&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;다항회귀는 더 좋은 예측성능을 가진 회귀함수를 찾을 수 있게 함&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다항회귀 차수를 높이면 -&amp;gt; 오버피팅 문제, 계산복잡도 증가 문제&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&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;학습모델 차수 등 복잡도를 높인다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&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;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데이터 특징을 줄인다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;학습모델 차수 등 복잡도를 낮춘다. -&amp;gt; 일반화 능력을 높인다. (정칙화 regularization)&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&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;어떤 질문(속성)을 선택해야 정보이득이 높은, 트리가 넓게 퍼지고 깊게 안가는 것을 고르는가&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정보이득 :&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;-&amp;gt; 특정한 속성에 따라 데이터를 나누었을 때 줄어든 엔트로피&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;-&amp;gt; 데이터 속성 중 어느 것이 중요한 것인지 판단하는 기준&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ID3, CART 두개 많이 쓰임&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&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;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정보량을 측정하기 위함&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;0.5가 가장 높고, 0 과 1 이 가장 낮음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;ID3 알고리즘&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;엔트로피 (정보이득) 을 사용&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;CART 알고리즘&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;SVM 서포트벡터머신&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;gt; 마진이 가장 넓은 것을 구함 (빡쎄면 하드마진, 섞이는거 허용하면 소프트마진)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어쨌든 마진을 최대화 하기 때문에 데이터들이 하나씩은 닿아있는데 그게 서포트벡터&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;소프트마진 사용 시 마진 내 가능 데이터 수 제어하는 변수가 슬랙&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;커널트릭 (kernel trick)&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;효율적인 비선형 분류를 위해 커널트릭 사용함 (최적화 문제의 쌍대성)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;쌍대문제을 통해서 특징 데이터 차원이 증가해도 내적 계산 시간이 증가하지 않는 커널 트릭 존재&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다항 특징변환이 지나치게 차원 높이는 문제를 해결하려고 커널트릭 사용함&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;커널은: 변환된 두 벡터의 내적을 변환 없이 원래 벡터로 구하는 것&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&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;높은 차원 데이터를 다룰 때 중요하지 않은 차원 생략하는 차원축소 가 필요함&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정보 손실을 최소화 하면서 특징의 수를 줄이는 방법이 필요함&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;차원이 높아지면 데이터들 사이 거리가 멀어지면서 데이터 밀도가 낮아짐 -&amp;gt; 데이터 사이의 관계를 파악하기가 힘들어짐 &amp;mdash;&amp;gt; 차원의 저주&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&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;/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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;투영&lt;/span&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;gt; 특징 투영&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;축을 하나 제외해서 가장 간단한 직교투영 가능&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;주성분 분석 (PCA, Principle Component Analysis)&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;데이터의 분산을 (최대화) 가장 잘 유지하는 축들: 주성분&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;평균과 분산을 구해서 분산을 최대화&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;훈련집합의 공분산행렬을 구하고, 그 고유벡터를 구함 -&amp;gt; 고유값 클수록 중요도 큼&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;주성분분석 -&amp;gt; 특이값 분해&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;특이값분해 (SVD, Singular Value Decomposition)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특이값분해는 행렬M의 변환을: 회전 -&amp;gt; 크기변경 -&amp;gt; 다시 회전 으로 표현&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;행렬을 공간의 가중합으로 표현해서, 가중치는 특이값인데 특이값이 클수록 중요한 정보담은 공간&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;차원축소: 중요한 차원만큼 중요한 정보를 담고있는 공간을 선택하는 것&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;PCA 왜 하는가?&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데이터과적을&lt;span&gt; &lt;/span&gt;막기&lt;span&gt; &lt;/span&gt;위해&lt;span&gt; -&amp;gt; &lt;/span&gt;차원을&lt;span&gt; &lt;/span&gt;축소&lt;span&gt; -&amp;gt; &lt;/span&gt;최대분산&lt;span&gt; &lt;/span&gt;축을&lt;span&gt; &lt;/span&gt;유지하게&lt;span&gt; &lt;/span&gt;끔&lt;span&gt; &lt;/span&gt;줄인다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;</description>
      <category>Programming/Artificial Intelligence (AI)</category>
      <category>Artificial Intelligence</category>
      <category>machine learning</category>
      <category>기계학습</category>
      <category>인공지능</category>
      <author>Ginjoe</author>
      <guid isPermaLink="true">https://itdar.tistory.com/421</guid>
      <comments>https://itdar.tistory.com/421#entry421comment</comments>
      <pubDate>Tue, 21 Jun 2022 02:43:30 +0900</pubDate>
    </item>
    <item>
      <title>[LeetCode] 1. TwoSum + 테스트케이스</title>
      <link>https://itdar.tistory.com/420</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;630&quot; data-origin-height=&quot;136&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bt6idy/btrz34IonvK/kYXVkcnJ5Owj5F1USZJ200/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bt6idy/btrz34IonvK/kYXVkcnJ5Owj5F1USZJ200/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bt6idy/btrz34IonvK/kYXVkcnJ5Owj5F1USZJ200/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbt6idy%2Fbtrz34IonvK%2FkYXVkcnJ5Owj5F1USZJ200%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;630&quot; height=&quot;136&quot; data-origin-width=&quot;630&quot; data-origin-height=&quot;136&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;간만에 재미로 다시 푸니까 새롭기도 하고 배우는 것도 있고 좋았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단 테스트케이스&lt;/p&gt;
&lt;pre id=&quot;code_1650556003385&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import static org.assertj.core.api.Assertions.assertThat;

import org.junit.jupiter.api.Test;

class LC_00001_TwoSumTest {

    @Test
    void twoSumTest1() {
        LC_00001_TwoSum ts = new LC_00001_TwoSum();

        int[] result = ts.twoSum(new int[]{2,7,11,15}, 9);

        assertThat(result).containsExactly(0,1);
    }

    @Test
    void twoSumTest2() {
        LC_00001_TwoSum ts = new LC_00001_TwoSum();

        int[] result = ts.twoSum(new int[]{3,2,4}, 6);

        assertThat(result).containsExactly(1,2);
    }

    @Test
    void twoSumTest3() {
        LC_00001_TwoSum ts = new LC_00001_TwoSum();

        int[] result = ts.twoSum(new int[]{3,3}, 6);

        assertThat(result).containsExactly(0,1);
    }

    @Test
    void twoSumTest4() {
        LC_00001_TwoSum ts = new LC_00001_TwoSum();

        int[] result = ts.twoSum(new int[]{0,4,3,0}, 0);

        assertThat(result).containsExactly(0,3);
    }

    @Test
    void twoSumTest5() {
        LC_00001_TwoSum ts = new LC_00001_TwoSum();

        int[] result = ts.twoSum(new int[]{-3,4,3,90}, 0);

        assertThat(result).containsExactly(0,2);
    }

}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;풀이는 퍼포먼스 확인하면서 개선&lt;/p&gt;
&lt;pre id=&quot;code_1650556102089&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class LC_00001_TwoSum {

    public int[] twoSum(int[] nums, int target) {
        Map&amp;lt;Integer, Integer&amp;gt; map = new HashMap&amp;lt;&amp;gt;();

        int numI;
        for (int i = 0; i &amp;lt; nums.length; ++i) {
            numI = nums[i];

            if (map.containsKey(target - numI)) {
                return new int[] {map.get(target-numI), i};
            }

            map.put(numI, i);
        }

        return null;
    }

    public int[] twoSum1(int[] nums, int target) {
        for (int i = 0; i &amp;lt; nums.length-1; ++i) {
            for (int j = i+1; j &amp;lt; nums.length; ++j) {
                if (nums[i] + nums[j] == target) {
                    return new int[]{i,j};
                }
            }
        }

        return null;
    }

    public int[] twoSum2(int[] nums, int target) {
        class Num {
            private final int index;
            private final int num;

            public Num(int index, int num) {
                this.index = index;
                this.num = num;
            }
        }

        List&amp;lt;Num&amp;gt; numList = new ArrayList&amp;lt;&amp;gt;();
        for (int i = 0; i &amp;lt; nums.length; ++i) {
            numList.add(new Num(i, nums[i]));
        }

        Collections.sort(numList, Comparator.comparingInt(v -&amp;gt; v.num));

        Num numI;
        Num numJ;
        int temp;
        for (int i = numList.size()-1; i &amp;gt;= 0; --i) {
            numI = numList.get(i);
            temp = target - numI.num;
            for (int j = 0; j &amp;lt; i; ++j) {
                numJ = numList.get(j);
                if (temp &amp;gt; numJ.num) continue;

                if (numJ.num == (target - numI.num)) {
                    return new int[] {numJ.index, numI.index};
                }
            }
        }

        return null;
    }

}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://itdar.tistory.com/418&quot;&gt;2022.04.01 - [Programming] - DI 와 IoC 에 대한 개념과 스프링&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1650556159458&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;DI 와 IoC 에 대한 개념과 스프링&quot; data-og-description=&quot;https://github.com/itdar/TIL/blob/main/books/Toby_Spring3.1_vol.1.md &amp;nbsp;책의 2회독째 3ch 부근에서 확 와닿게 정리되는 문장을 보아서 그냥 줄줄 써본다. &amp;nbsp;전체 정리를 먼저 해본다면, IoC 는 Inversion of C..&quot; data-og-host=&quot;itdar.tistory.com&quot; data-og-source-url=&quot;https://itdar.tistory.com/418&quot; data-og-url=&quot;https://itdar.tistory.com/418&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/rBlta/hyN8whuc9D/mVxycDi3XtiXjeAl1olp9k/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/S2yVh/hyN64AbfvH/UCIxjtLwjK3KiUn3VHHWKk/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/4FAd2/hyN8Ac7iYk/ZWihZQ4dpSzh5XlB5JJnB0/img.png?width=264&amp;amp;height=200&amp;amp;face=0_0_264_200&quot;&gt;&lt;a href=&quot;https://itdar.tistory.com/418&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://itdar.tistory.com/418&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/rBlta/hyN8whuc9D/mVxycDi3XtiXjeAl1olp9k/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/S2yVh/hyN64AbfvH/UCIxjtLwjK3KiUn3VHHWKk/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/4FAd2/hyN8Ac7iYk/ZWihZQ4dpSzh5XlB5JJnB0/img.png?width=264&amp;amp;height=200&amp;amp;face=0_0_264_200');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;DI 와 IoC 에 대한 개념과 스프링&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;https://github.com/itdar/TIL/blob/main/books/Toby_Spring3.1_vol.1.md &amp;nbsp;책의 2회독째 3ch 부근에서 확 와닿게 정리되는 문장을 보아서 그냥 줄줄 써본다. &amp;nbsp;전체 정리를 먼저 해본다면, IoC 는 Inversion of C..&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;itdar.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Algorithm/Leet Code</category>
      <category>coding test</category>
      <category>leetcode</category>
      <category>leetcode 1</category>
      <category>tech interview</category>
      <category>TwoSum</category>
      <category>코딩테스트</category>
      <category>코테</category>
      <author>Ginjoe</author>
      <guid isPermaLink="true">https://itdar.tistory.com/420</guid>
      <comments>https://itdar.tistory.com/420#entry420comment</comments>
      <pubDate>Fri, 22 Apr 2022 00:49:26 +0900</pubDate>
    </item>
    <item>
      <title>[Codility] Chapter 9. Maximum slice problem, 최대 구간 문제</title>
      <link>https://itdar.tistory.com/419</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;Reference: &lt;a href=&quot;https://codility.com/media/train/7-MaxSlice.pdf&quot;&gt;https://codility.com/media/train/7-MaxSlice.pdf&lt;/a&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;코딜리티 알고리즘 학습 pdf 중에서 나중에 써먹을 만한 것&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최대 슬라이싱과 관련된 문제를 정의해 본다. n 개의 정수 배열이 주어지고, 가장 큰 합을 갖는 구간을 찾는 일이다. 더 정확히는, 두개의 인덱스 p, q 를 찾는데, [p]~ [q] 까지의 합이 최대값인 것이다. 예를 들어, p = 2, q = 5 가 최대 슬라이스 구간의 합을 찾은 것이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;174&quot; data-origin-height=&quot;53&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c8RmCU/btryfZ1M4hC/5aRQZByaIUK7kVIKwWvDIk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c8RmCU/btryfZ1M4hC/5aRQZByaIUK7kVIKwWvDIk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c8RmCU/btryfZ1M4hC/5aRQZByaIUK7kVIKwWvDIk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc8RmCU%2FbtryfZ1M4hC%2F5aRQZByaIUK7kVIKwWvDIk%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;174&quot; height=&quot;53&quot; data-origin-width=&quot;174&quot; data-origin-height=&quot;53&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단순하게 O(n^3) 시간복잡도를 갖는 풀이를 생각 해볼 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. n개의 정수 배열 입력받는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 앞쪽 인덱스 p 는 0~ n 반복한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;2.1. 뒤쪽 인덱스 q 는 p~ n 반복한다.&amp;nbsp; -&amp;gt;&amp;nbsp; 여기까지의 반복이 모든 경우의 슬라이싱 구간을 만들어낸다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; 2.1.1. 이제 p~ q 슬라이싱의 합을 구한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; 2.1.2. 기존 최대값과 비교 갱신 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 최대값 반환한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;gt; 이건 뭐.. 그냥 대충 머리로 구현을..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;O(n^2) 시간복잡도를 갖는 풀이로 최적화 해볼 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. n개의 정수 배열 입력받는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 앞쪽 인덱스 p 는 0~ n 반복한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;2.1. 슬라이싱 합 초기화 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;2.2. 뒤쪽 인덱스 q 는 p~ n 반복한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; 2.2.1. 기존 슬라이싱 합에 [q] 값을 더한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; 2.2.2. 기존 최대값과 비교 갱신한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 최대값 반환한다.&lt;/p&gt;
&lt;pre id=&quot;code_1648875496522&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;    public int maxSliceQuadratic(int[] a) {
        int n = a.length;
        int result = 0;
        int sum;

        for (int i = 0; i &amp;lt; n; ++i) {
            sum = 0;
            for (int j = i; j &amp;lt; n; ++j) {
                sum += a[j];
                result = Math.max(result, sum);
            }
        }

        return result;
    }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;O(n) 시간복잡도를 갖는 풀이로 최적화 해볼 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. n개의 정수 배열 입력받는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 정수 배열 전체 반복한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;2.1. 이전 누적 합 중 최대 값 (직전의 값까지의 누적 최대합에 이번 차례 값을 더함)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;2.2. 최대 슬라이싱 합은 기존 최대합과 이전 누적합을 비교 갱신한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 최대값 반환한다.&lt;/p&gt;
&lt;pre id=&quot;code_1648875348767&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;    public int maxSlice(int[] a) {
        int maxEnding = 0;
        int maxSlice = 0;

        for (int i = 0; i &amp;lt; a.length; ++i) {
            maxEnding = Math.max(0, maxEnding + a[i]);
            maxSlice = Math.max(maxSlice, maxEnding);
        }

        return maxSlice;
    }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Programming</category>
      <category>Codility</category>
      <category>maximum slice problem</category>
      <category>최대 슬라이싱 구간 문제</category>
      <author>Ginjoe</author>
      <guid isPermaLink="true">https://itdar.tistory.com/419</guid>
      <comments>https://itdar.tistory.com/419#entry419comment</comments>
      <pubDate>Sat, 2 Apr 2022 13:59:15 +0900</pubDate>
    </item>
    <item>
      <title>DI 와 IoC 에 대한 개념과 스프링</title>
      <link>https://itdar.tistory.com/418</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/itdar/TIL/blob/main/books/Toby_Spring3.1_vol.1.md&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://github.com/itdar/TIL/blob/main/books/Toby_Spring3.1_vol.1.md&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;책의 2회독째 3ch 부근에서 확 와닿게 정리되는 문장을 보아서 그냥 줄줄 써본다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;전체 정리를 먼저 해본다면,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;IoC 는 Inversion of Control, 제어의 역전 이라는 뜻을 갖는다. IoC 컨테이너는 그 기능을 하는 것이고,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이는 객체지향적인 코딩을 하는데에 불편한? 필요한? 것들을 없애주고 제공해준다. 이 때, IoC 의 기반이 되는 것이 DI 이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DI 는 Dependency Injection, 의존관계 주입인데 이를 통해서 IoC 가 구현 될 수 있는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;- IoC 가 뭘 제어한다는 것인가?&lt;/h4&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;h4 data-ke-size=&quot;size20&quot;&gt;- 그럼 뭐가 역전되었다는 것인가?&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단순히 클라이언트가 필요에 따라 사용할 객체들을 생성하고 의존관계 설정해서 사용을 할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클라이언트는 생성과 의존관계 설정에 관심을 두지 않고 필요한 객체만 제 3자에게 받아서 사용한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;- 여기서 제 3자에게 제어권이 역전되어 넘어갔다는 것인데, 제 3자는 누구인가?&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단순하게는 팩토리가 될 수도 있을테고, 대표적인 프레임워크로 본다면 스프링프레임워크의 빈팩토리 (스프링컨테이너, IoC 컨테이너 ...) 가 될 수 있겠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;- 왜 제어권을 IoC 컨테이너 같은 제 3자에게 넘겨야 하는가?&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;객체지향의 원리를 고민하는, 즉 유지보수가 용이한, 미래를 고려한, 설계와 구현을 고민하면서 나오는 문제를 해결하는 일종의 방법이 될 수도 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;관심사의 분리 (생성, 관계설정, 기능동작 등) 가 될 수도 있겠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;- 그렇다면 DI 는 뭔데 스프링 얘기 할 때 항상 세트로 언급되는가?&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;IoC 를 구현하려면, DI 가 필요하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;- 그럼 DI 는 무엇인가?&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DI 는 Dependency Injection, 의존 주입, 의존관계 주입, 의존객체 주입 의 뜻을 갖는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;객체와 객체의 관계를 설정하는데, 생성자(Constructor)/수정자(Setter) 등을 통해 객체 레퍼런스를 입력받아서 설정한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;- DI 는 왜 쓰는건가?&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;객체끼리 어떻게 연결해서 사용할 지 정해줘야하니까.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;근데 객체와 객체를 정적인 컴파일타임에 설정하는 것이 아니라, 동적인 런타임에 설정 할 여지를 남겨둔다. (고정된 것이 아니고 주입을 받으니까)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;- 그래서 그게 IoC 랑 DI 랑 무슨 관련인가?&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;IoC 컨테이너에서 관리하는 객체들이 관계를 맺으려면, 컴파일 타임에서 관계가 없으니 어쩔 수 없이라도 런타임에 주입을 받아야지!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DI 할 코드 (생성자, 수정자) 가 없으면 관계를 못 맺으니까.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;예전 회사에서 일하면서 요구사항 바뀌는 것이 잦아서 외부 xml 로 내부 인터페이스 구현체를 바꾸도록 해서&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;장비 사용 시나리오나 알고리즘의 설정을 변경 할 수 있게 했던 적이 있는데, 그게 IoC 컨테이너 개념이었던 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Programming</category>
      <category>DI</category>
      <category>IOC</category>
      <category>Spring Framework</category>
      <category>객체지향</category>
      <author>Ginjoe</author>
      <guid isPermaLink="true">https://itdar.tistory.com/418</guid>
      <comments>https://itdar.tistory.com/418#entry418comment</comments>
      <pubDate>Fri, 1 Apr 2022 02:42:07 +0900</pubDate>
    </item>
    <item>
      <title>Docker 이용해서 MySQL 설치 후 접속 예제</title>
      <link>https://itdar.tistory.com/417</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;스프링부트랑 마이바티스 연결해서 테스트 할 일이 있어서 docker compose + mysql 연결해봄&lt;/p&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;m1 실리콘칩 맥북 기준 도커에서 mysql:latest 버전 이미지 다운로드&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;vala&quot;&gt;&lt;code&gt;docker pull --platform linux/amd64 mysql

## 보통 피씨에서는
# docker pull mysql
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;docker-compose 파일 구성
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;파일명: docker-compose-mysql-8.yml (?)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;http&quot;&gt;&lt;code&gt;version: '3.1'

services:

  db:
    image: mysql
    container_name: testmysql
    ports:
      - &quot;3306:3306&quot;
    command:
      # 인증 플러그인 암호화방식 변경
      - --default-authentication-plugin=mysql_native_password
      # 문자열 인코딩 이모지 포함
      - --character-set-server=utf8mb4
      # 문자열 정렬순서 collation
      - --collation-server=utf8mb4_unicode_ci
    environment:
      MYSQL_ROOT_PASSWORD: &quot;password&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;docker-compose 통해서 이미지 실행&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;docker-compose -f docker-compose-mysql-8.yml up -d
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;docker 의 mysql 컨테이너 접속&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;armasm&quot;&gt;&lt;code&gt;docker exec -it testmysql bash
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;도커 컨테이너 내에서 mysql 접속 (위 yml 에서 root 패스워드로 설정해두었던 것으로 접속)&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;ebnf&quot;&gt;&lt;code&gt;mysql -u root -p
&lt;/code&gt;&lt;/pre&gt;</description>
      <category>Programming</category>
      <category>docker</category>
      <category>docker-compose</category>
      <category>MySQL</category>
      <author>Ginjoe</author>
      <guid isPermaLink="true">https://itdar.tistory.com/417</guid>
      <comments>https://itdar.tistory.com/417#entry417comment</comments>
      <pubDate>Mon, 28 Mar 2022 02:38:34 +0900</pubDate>
    </item>
    <item>
      <title>RabbitMQ 정리와 실행 예제</title>
      <link>https://itdar.tistory.com/416</link>
      <description>&lt;h1&gt;RabbitMQ 간단 정리&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/itdar/TIL/blob/main/infra/rabbitmq.md&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://github.com/itdar/TIL/blob/main/infra/rabbitmq.md&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;AMQP 란?
&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;/li&gt;
&lt;li&gt;특징&lt;/li&gt;
&lt;li&gt;구성&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;그래서 Rabbit MQ 란?&lt;/li&gt;
&lt;li&gt;RabbitMQ vs Kafka
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;RabbitMQ&lt;/li&gt;
&lt;li&gt;Kafka&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;RabbitMQ 실행 샘플&lt;/li&gt;
&lt;li&gt;Reference&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;AMQP 란?&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Advanced Message Queuing Protocol.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;위키에 따르면, 메시지 지향 미들웨어를 위한 개방형 표준 응용계층&lt;span&gt;&amp;nbsp;&lt;/span&gt;프로토콜&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;배경
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;기존 MQ 프로토콜들은 서로 다른 플랫폼 간의 메시지 교환을 위해서는 별도 작업 추가 (속도 저하), 또는 플랫폼 통일 등이 필요했음&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;목적
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;AMQP 는 서로 다른 시스템간에 (비용/기술/시간적인 측면에서) 최대한 효율적인 방법으로 메시지를 교환하기 위해 나온 MQ&lt;span&gt;&amp;nbsp;&lt;/span&gt;프로토콜&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;특징
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;모든&lt;span&gt;&amp;nbsp;&lt;/span&gt;Broker&lt;span&gt;&amp;nbsp;&lt;/span&gt;들은 똑같은 방식으로 동작할 것&lt;/li&gt;
&lt;li&gt;모든&lt;span&gt;&amp;nbsp;&lt;/span&gt;Client&lt;span&gt;&amp;nbsp;&lt;/span&gt;들은 똑같은 방식으로 동작할 것&lt;/li&gt;
&lt;li&gt;네트웍상으로 전송되는 명령어들의 표준화&lt;/li&gt;
&lt;li&gt;프로그래밍 언어 중립적&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;구성
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;아래 그림에서, 큰 상관은 없을 것 같지만 Publisher 는&lt;span&gt;&amp;nbsp;&lt;/span&gt;Producer&lt;span&gt;&amp;nbsp;&lt;/span&gt;로 바꾸는게 나을 것 같고.. Server 는&lt;span&gt;&amp;nbsp;&lt;/span&gt;Broker로 보면 될 것 같다.&lt;/li&gt;
&lt;li&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;482&quot; data-origin-height=&quot;317&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cSkYKn/btrwJvhnQ4X/QTVRCxTtUislkQ5um3fqpk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cSkYKn/btrwJvhnQ4X/QTVRCxTtUislkQ5um3fqpk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cSkYKn/btrwJvhnQ4X/QTVRCxTtUislkQ5um3fqpk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcSkYKn%2FbtrwJvhnQ4X%2FQTVRCxTtUislkQ5um3fqpk%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;482&quot; height=&quot;317&quot; data-origin-width=&quot;482&quot; data-origin-height=&quot;317&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/li&gt;
&lt;li&gt;Exchange:&lt;span&gt;&amp;nbsp;&lt;/span&gt;Producer&lt;span&gt;&amp;nbsp;&lt;/span&gt;에서 수신한 메시지를 적절한&lt;span&gt;&amp;nbsp;&lt;/span&gt;Queue&lt;span&gt;&amp;nbsp;&lt;/span&gt;또는 다른&lt;span&gt;&amp;nbsp;&lt;/span&gt;Exchange&lt;span&gt;&amp;nbsp;&lt;/span&gt;로 분배하는 라우터의 기능을 한다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;각&lt;span&gt;&amp;nbsp;&lt;/span&gt;Queue&lt;span&gt;&amp;nbsp;&lt;/span&gt;나&lt;span&gt;&amp;nbsp;&lt;/span&gt;Exchange&lt;span&gt;&amp;nbsp;&lt;/span&gt;는&lt;span&gt;&amp;nbsp;&lt;/span&gt;Binding을 사용해서&lt;span&gt;&amp;nbsp;&lt;/span&gt;Exchange&lt;span&gt;&amp;nbsp;&lt;/span&gt;에 바인드 되어 있고, 따라서&lt;span&gt;&amp;nbsp;&lt;/span&gt;Exchange&lt;span&gt;&amp;nbsp;&lt;/span&gt;는 수신한 메시지를 이&lt;span&gt;&amp;nbsp;&lt;/span&gt;Binding&lt;span&gt;&amp;nbsp;&lt;/span&gt;에 따라 적당한&lt;span&gt;&amp;nbsp;&lt;/span&gt;Queue나&lt;span&gt;&amp;nbsp;&lt;/span&gt;Exchange로 라우팅한다.&lt;/li&gt;
&lt;li&gt;Binding&lt;span&gt;&amp;nbsp;&lt;/span&gt;과 메시지를 매칭시키기 위한 라우팅 알고리즘을 정의한것을&lt;span&gt;&amp;nbsp;&lt;/span&gt;Exchange type이라고 하고,&lt;span&gt;&amp;nbsp;&lt;/span&gt;Exchange type은 라우팅 알고리즘의 클래스이다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;Broker는 여러개의 exchange type 인스턴스를 가질 수 있다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;Binding과&lt;span&gt;&amp;nbsp;&lt;/span&gt;Exchange type이 혼동될 수 있는데,
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Exchange type은 메시지를 어떤 방법으로 라우팅 시킬지를 결정하는 것이고,&lt;span&gt;&amp;nbsp;&lt;/span&gt;Binding은 이러한 방법을 이용해 실제로 어떤 메시지를 어떤 큐에 보낼지를 결정하는 라우팅 테이블이라고 할 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;ex) 명함정보가 들어오면 그것을 특정&lt;span&gt;&amp;nbsp;&lt;/span&gt;Queue로 보내는&lt;span&gt;&amp;nbsp;&lt;/span&gt;Broker가 존재한다면, 명함의 사람 이름 성씨를 보고&lt;span&gt;&amp;nbsp;&lt;/span&gt;Queue를 결정하겠다는 것은&lt;span&gt;&amp;nbsp;&lt;/span&gt;Exchange type이고, 김씨는 1번큐, 박씨는 2번큐, 이씨는 3번큐로 보내겠다는 것은&lt;span&gt;&amp;nbsp;&lt;/span&gt;Binding이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Queue: 일반적으로 알고있는 큐이다. 메모리나 디스크에 메시지를 저장하고, 그것을&lt;span&gt;&amp;nbsp;&lt;/span&gt;Consumer에게 전달
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Queue&lt;span&gt;&amp;nbsp;&lt;/span&gt;는 스스로가 관심있는 메시지 타입을 지정한&lt;span&gt;&amp;nbsp;&lt;/span&gt;Binding&lt;span&gt;&amp;nbsp;&lt;/span&gt;을 통해&lt;span&gt;&amp;nbsp;&lt;/span&gt;Exchange&lt;span&gt;&amp;nbsp;&lt;/span&gt;에 말그대로 bind 된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Binding:&lt;span&gt;&amp;nbsp;&lt;/span&gt;Exchange&lt;span&gt;&amp;nbsp;&lt;/span&gt;와&lt;span&gt;&amp;nbsp;&lt;/span&gt;Queue와의 관계를 정의한 일종의 라우팅 테이블이다. 하나의&lt;span&gt;&amp;nbsp;&lt;/span&gt;Queue가 여러개의&lt;span&gt;&amp;nbsp;&lt;/span&gt;Exchange에 bind 될 수도 있고, 하나의&lt;span&gt;&amp;nbsp;&lt;/span&gt;Exchange에 여러개의&lt;span&gt;&amp;nbsp;&lt;/span&gt;Queue가 bind 될 수도 있다.&lt;/li&gt;
&lt;li&gt;Routing Key:&lt;span&gt;&amp;nbsp;&lt;/span&gt;Producer&lt;span&gt;&amp;nbsp;&lt;/span&gt;에서 송신한 메시지 헤더에 포함되는 것으로 일종의&lt;span&gt;&amp;nbsp;&lt;/span&gt;가상주소라고 보면 된다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;Exchange는 이것을 이용해서 어떤&lt;span&gt;&amp;nbsp;&lt;/span&gt;Queue로 메시지를 라우팅할지 결정할 수 있다. (이것을 사용하지 않고 다른 룰을 이용할 수도 있음)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;AMQP의 표준&lt;span&gt;&amp;nbsp;&lt;/span&gt;Exchange type은 이 라우팅 키를 이용하도록 되어있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Standard Exchange Type: 대부분의 MQ 에서 가능한 여러가지 상황에 대하여 AMQP 에서 정의한&lt;span&gt;&amp;nbsp;&lt;/span&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;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;772&quot; data-origin-height=&quot;1138&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bZV4M6/btrwKFKy1p6/TabSKF4I3YdKUZKIKKOLk1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bZV4M6/btrwKFKy1p6/TabSKF4I3YdKUZKIKKOLk1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bZV4M6/btrwKFKy1p6/TabSKF4I3YdKUZKIKKOLk1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbZV4M6%2FbtrwKFKy1p6%2FTabSKF4I3YdKUZKIKKOLk1%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;827&quot; height=&quot;1219&quot; data-origin-width=&quot;772&quot; data-origin-height=&quot;1138&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/li&gt;
&lt;/ul&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;h2 data-ke-size=&quot;size26&quot;&gt;그래서 RabbitMQ 란?&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Erlang 과 Java 로 AMQP 를 맞추어 구현한 메시지 큐 (MQ)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;여기서 메시지 큐란?
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;위키에 메시지큐를 찾으면, OS 에서 Input device 등의 입력 메시지를 저장해두는 대기열로 쓰는 큐 설명같은 것이 나오는데..&lt;/li&gt;
&lt;li&gt;그보다는 시스템 간의 메시지 교환을 위해 중간에 있는 큐 자료형의 메시지 대기열 로 보면 될 것 같다.&lt;/li&gt;
&lt;/ul&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;h2 data-ke-size=&quot;size26&quot;&gt;RabbitMQ vs Kafka (일단, 둘 다 나온지 오래되어 (2007 vs 2011) 안정적임)&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;RabbitMQ
&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;/li&gt;
&lt;li&gt;Scale-up 을 고려한 설계&lt;/li&gt;
&lt;li&gt;Message broker&lt;span&gt;&amp;nbsp;&lt;/span&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;&amp;nbsp;&lt;/span&gt;Producer&lt;span&gt;&amp;nbsp;&lt;/span&gt;이 메시지를 받는&lt;span&gt;&amp;nbsp;&lt;/span&gt;Consumer&lt;span&gt;&amp;nbsp;&lt;/span&gt;의 개수, 활성여부 등 정보를 몰라도 메시지 보낼 수 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;520&quot; data-origin-height=&quot;570&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/7zSB6/btrwDNJVupk/1hfZ5yJUsrDkPiQLgUefz0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/7zSB6/btrwDNJVupk/1hfZ5yJUsrDkPiQLgUefz0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/7zSB6/btrwDNJVupk/1hfZ5yJUsrDkPiQLgUefz0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F7zSB6%2FbtrwDNJVupk%2F1hfZ5yJUsrDkPiQLgUefz0%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;520&quot; height=&quot;570&quot; data-origin-width=&quot;520&quot; data-origin-height=&quot;570&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Kafka 는 pub/sub 방식
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;메시지를&lt;span&gt;&amp;nbsp;&lt;/span&gt;Record&lt;span&gt;&amp;nbsp;&lt;/span&gt;라고 부르기도 함&lt;/li&gt;
&lt;li&gt;처리량이 많은 데이터 스트림 처리 및 재생 등의 실시간 처리 동작에 적합&lt;/li&gt;
&lt;li&gt;많은 양의 데이터 보관 및 배하도록 설계 됨&lt;/li&gt;
&lt;li&gt;Scale-out 을 고려한 설계&lt;/li&gt;
&lt;li&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;850&quot; data-origin-height=&quot;455&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mnyec/btrwMFJ4qtB/eRNsGXliO7U0FU6c7ICP9K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mnyec/btrwMFJ4qtB/eRNsGXliO7U0FU6c7ICP9K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mnyec/btrwMFJ4qtB/eRNsGXliO7U0FU6c7ICP9K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fmnyec%2FbtrwMFJ4qtB%2FeRNsGXliO7U0FU6c7ICP9K%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;850&quot; height=&quot;455&quot; data-origin-width=&quot;850&quot; data-origin-height=&quot;455&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;대략 아래를 고려해서 선택하면 된다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;701&quot; data-origin-height=&quot;237&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/7Ygdi/btrwDPud7Uk/oBdCpsjYP0Jp8mHyTbSht0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/7Ygdi/btrwDPud7Uk/oBdCpsjYP0Jp8mHyTbSht0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/7Ygdi/btrwDPud7Uk/oBdCpsjYP0Jp8mHyTbSht0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F7Ygdi%2FbtrwDPud7Uk%2FoBdCpsjYP0Jp8mHyTbSht0%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;701&quot; height=&quot;237&quot; data-origin-width=&quot;701&quot; data-origin-height=&quot;237&quot;/&gt;&lt;/span&gt;&lt;/figure&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;h2 data-ke-size=&quot;size26&quot;&gt;RabbitMQ 실행 샘플&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;0.1.&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a href=&quot;https://github.com/itdar/TIL/tree/main/java/rabbitmq-consumer&quot;&gt;https://github.com/itdar/TIL/tree/main/java/rabbitmq-consumer&lt;/a&gt;&lt;span&gt;&amp;nbsp;&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;&amp;nbsp;&lt;/span&gt;&lt;span&gt;IDE&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;로드&lt;/span&gt;&lt;br /&gt;&lt;span&gt;0.2.&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a href=&quot;https://github.com/itdar/TIL/tree/main/java/rabbitmq-producer&quot;&gt;https://github.com/itdar/TIL/tree/main/java/rabbitmq-producer&lt;/a&gt;&lt;span&gt;&amp;nbsp;&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;&amp;nbsp;&lt;/span&gt;&lt;span&gt;IDE&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;로드&lt;/span&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;docker 설치 (OS 에 맞게)&lt;/li&gt;
&lt;li&gt;docker 에서 rabbitmq:management 이미지 다운로드&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class=&quot;css&quot;&gt;&lt;code&gt;docker pull rabbitmq:management
&lt;/code&gt;&lt;/pre&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;docker 에서 다운받은 이미지 실행&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;docker run -d --name rabbitmq -p 5672:5672 -p 5673:5673 -p 15672:15672 rabbitmq:management
&lt;/code&gt;&lt;/pre&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;RabbitMQ gui 접속&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class=&quot;dts&quot;&gt;&lt;code&gt;http://localhost:15672

// id: guest
// pw: guest
&lt;/code&gt;&lt;/pre&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;RabbitMQ 에서&lt;span&gt;&amp;nbsp;&lt;/span&gt;Queue&lt;span&gt;&amp;nbsp;&lt;/span&gt;생성 (이름은 testQueue, 아래 그림 참조)&lt;br /&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;821&quot; data-origin-height=&quot;566&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/KfbLD/btrwLgDNf4R/Yq6JMpVG2YtZfp8a7dHrfk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/KfbLD/btrwLgDNf4R/Yq6JMpVG2YtZfp8a7dHrfk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/KfbLD/btrwLgDNf4R/Yq6JMpVG2YtZfp8a7dHrfk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FKfbLD%2FbtrwLgDNf4R%2FYq6JMpVG2YtZfp8a7dHrfk%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;821&quot; height=&quot;566&quot; data-origin-width=&quot;821&quot; data-origin-height=&quot;566&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/li&gt;
&lt;li&gt;IDE 에서 Consumer App 실행&lt;/li&gt;
&lt;li&gt;IDE 에서 Producer 의 RabbitMQHelperTest 클래스 테스트메서드 실행해서 메시지 보내기&lt;/li&gt;
&lt;li&gt;consumer 에서 출력되는 메시지 확인&lt;br /&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;271&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lEv1f/btrwLg4PhSn/eiAoIS8TSw2sED0o5InK6k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lEv1f/btrwLg4PhSn/eiAoIS8TSw2sED0o5InK6k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lEv1f/btrwLg4PhSn/eiAoIS8TSw2sED0o5InK6k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlEv1f%2FbtrwLg4PhSn%2FeiAoIS8TSw2sED0o5InK6k%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;1280&quot; height=&quot;271&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;271&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Reference&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://ko.wikipedia.org/wiki/AMQP&quot;&gt;https://ko.wikipedia.org/wiki/AMQP&lt;/a&gt;&lt;br /&gt;&lt;a href=&quot;http://egloos.zum.com/killins/v/3025514&quot;&gt;http://egloos.zum.com/killins/v/3025514&lt;/a&gt;&lt;br /&gt;&lt;a href=&quot;https://coding-nyan.tistory.com/129&quot;&gt;https://coding-nyan.tistory.com/129&lt;/a&gt;&lt;br /&gt;&lt;a href=&quot;https://www.cloudamqp.com/blog/when-to-use-rabbitmq-or-apache-kafka.html&quot;&gt;https://www.cloudamqp.com/blog/when-to-use-rabbitmq-or-apache-kafka.html&lt;/a&gt;&lt;br /&gt;&lt;a href=&quot;https://stackoverflow.com/questions/42151544/when-to-use-rabbitmq-over-kafka/42154452#42154452&quot;&gt;https://stackoverflow.com/questions/42151544/when-to-use-rabbitmq-over-kafka/42154452#42154452&lt;/a&gt;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&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;&amp;nbsp;&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;&amp;nbsp;&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;&amp;nbsp;&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;&amp;nbsp;&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;&amp;nbsp;&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;&amp;nbsp;&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;&amp;nbsp;&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;&amp;nbsp;&lt;/span&gt;&lt;span&gt;와닿지는&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;않는다.&lt;/span&gt;&lt;/p&gt;</description>
      <category>Programming</category>
      <category>amqp</category>
      <category>kafka</category>
      <category>Message Queue</category>
      <category>rabbitmq</category>
      <category>rabbitmq vs kafka</category>
      <category>래빗 큐</category>
      <category>메시지 큐</category>
      <author>Ginjoe</author>
      <guid isPermaLink="true">https://itdar.tistory.com/416</guid>
      <comments>https://itdar.tistory.com/416#entry416comment</comments>
      <pubDate>Tue, 22 Mar 2022 00:57:07 +0900</pubDate>
    </item>
    <item>
      <title>Linux tar 압축, 압축 풀기</title>
      <link>https://itdar.tistory.com/415</link>
      <description>&lt;ul&gt;
&lt;li&gt;용량 압축보다는 그냥 디렉토리와 파일을 하나로 묶고 싶다.&lt;h2&gt;1. tar로 압축 하기&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;tar -cvf ${압축할 파일이름}.tar ${압축할 폴더이름} --exclude=${제외할 파일이름}&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;압축할 파일 이름을 제외해준다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;e.g.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;tar -cvf ./temp.tar /etc --exclude=./temp.tar&lt;/code&gt;&lt;/pre&gt;&lt;h2&gt;2. tar 압축 풀기&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;tar -xvf ${압축해제 할 파일이름}.tar -C ${압축해제 할 경로}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;e.g.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;tar -xvf ./temp.tar -C /home/user&lt;/code&gt;&lt;/pre&gt;&lt;br&gt;

&lt;ul&gt;
&lt;li&gt;묶으면서 용량까지 압축하고 싶다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;1. tar.gz 로 압축 하기&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;tar -zcvf ${압축할 파일이름}.tar ${압축할 폴더이름} --exclude=${제외할 파일이름}&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;
&lt;li&gt;압축할 파일 이름을 제외해준다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;e.g.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;tar -zcvf ./temp.tar /etc --exclude=./temp.tar&lt;/code&gt;&lt;/pre&gt;&lt;h2&gt;4. tar.gz 압축 풀기&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;tar -zxvf ${압축해제 할 파일이름}.tar -C ${압축해제 할 경로}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;e.g.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;tar -zxvf ./temp.tar -C /home/user&lt;/code&gt;&lt;/pre&gt;</description>
      <category>Programming</category>
      <category>COMPRESS</category>
      <category>decompress</category>
      <category>Linux</category>
      <category>tar</category>
      <category>압축</category>
      <category>압축해제</category>
      <author>Ginjoe</author>
      <guid isPermaLink="true">https://itdar.tistory.com/415</guid>
      <comments>https://itdar.tistory.com/415#entry415comment</comments>
      <pubDate>Thu, 3 Mar 2022 01:07:25 +0900</pubDate>
    </item>
    <item>
      <title>Java TreeMap 을 이용하여 삽입 시 정렬되도록 예제</title>
      <link>https://itdar.tistory.com/414</link>
      <description>&lt;h1&gt;Java TreeMap 을 이용하여 삽입 시 정렬되도록 예제&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;TreeMap 의 경우, 생성 시 Comparator를 구현해서 넣어주어 사용한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;// Order
Comparator&amp;lt;String&amp;gt; comparator = (o1, o2) -&amp;gt; o1.compareTo(o2);

// ReverseOrder
Comparator&amp;lt;String&amp;gt; comparator = (o1, o2) -&amp;gt; o2.compareTo(o1);&lt;/code&gt;&lt;/pre&gt;&lt;h4&gt;코드&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;import java.util.Comparator;
import java.util.Map;
import java.util.TreeMap;

public static void main(String[] args) {
        Comparator&amp;lt;Integer&amp;gt; comparator = Integer::compareTo;
        Map&amp;lt;Integer, String&amp;gt; map = new TreeMap&amp;lt;&amp;gt;(comparator);
        map.put(2, &amp;quot;Two&amp;quot;);
        map.put(0, &amp;quot;Zero&amp;quot;);
        map.put(-3, &amp;quot;Minus Three&amp;quot;);
        map.put(13, &amp;quot;Thirteen&amp;quot;);
        map.put(5, &amp;quot;Five&amp;quot;);

        for (Map.Entry&amp;lt;Integer, String&amp;gt; entry : map.entrySet()) {
            System.out.println(&amp;quot;Key: &amp;quot; + entry.getKey() + &amp;quot;\t\t&amp;quot; + &amp;quot;Value: &amp;quot; + entry.getValue());
        }
}&lt;/code&gt;&lt;/pre&gt;&lt;h4&gt;결과&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;Key: -3        Value: Minus Three
Key: 0        Value: Zero
Key: 2        Value: Two
Key: 5        Value: Five
Key: 13        Value: Thirteen&lt;/code&gt;&lt;/pre&gt;</description>
      <category>Programming</category>
      <category>Java</category>
      <category>sort</category>
      <category>TreeMap</category>
      <author>Ginjoe</author>
      <guid isPermaLink="true">https://itdar.tistory.com/414</guid>
      <comments>https://itdar.tistory.com/414#entry414comment</comments>
      <pubDate>Thu, 17 Feb 2022 21:35:46 +0900</pubDate>
    </item>
    <item>
      <title>Head First SQL (헤드퍼스트 SQL) 요약정리</title>
      <link>https://itdar.tistory.com/413</link>
      <description>&lt;h1&gt;Head First SQL (헤드퍼스트 SQL)&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;markdown 포맷 잘 맞는 것 링크 (github)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/itdar/TIL/blob/main/books/headfirst_sql.md&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://github.com/itdar/TIL/blob/main/books/headfirst_sql.md&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1646920939022&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;GitHub - itdar/TIL: Today I Learned&quot; data-og-description=&quot;Today I Learned. Contribute to itdar/TIL development by creating an account on GitHub.&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/itdar/TIL/blob/main/books/headfirst_sql.md&quot; data-og-url=&quot;https://github.com/itdar/TIL&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/b8tZmG/hyNFBxofst/ziVknxuBiTzf7Biw75rd40/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/itdar/TIL/blob/main/books/headfirst_sql.md&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/itdar/TIL/blob/main/books/headfirst_sql.md&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/b8tZmG/hyNFBxofst/ziVknxuBiTzf7Biw75rd40/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;GitHub - itdar/TIL: Today I Learned&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Today I Learned. Contribute to itdar/TIL development by creating an account on GitHub.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#1.-%EB%8D%B0%EC%9D%B4%ED%84%B0%EC%99%80-%ED%85%8C%EC%9D%B4%EB%B8%94&quot;&gt;데이터와 테이블&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#2.-SELECT-%EB%AC%B8&quot;&gt;SELECT 문&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#3.-DELETE-%EC%99%80-UPDATE&quot;&gt;DELETE 와 UPDATE&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#4.-%EC%A2%8B%EC%9D%80-%ED%85%8C%EC%9D%B4%EB%B8%94-%EC%84%A4%EA%B3%84:-%EC%A0%95%EA%B7%9C%ED%99%94%EB%8A%94-%EC%99%9C-%ED%95%98%EC%A3%A0?&quot;&gt;좋은 테이블 설계: 정규화는 왜 하죠?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#5.-ALTER:-%EA%B3%BC%EA%B1%B0-%EB%8B%A4%EC%8B%9C-%EC%93%B0%EA%B8%B0&quot;&gt;ALTER: 과거 다시 쓰기&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#6.-%EA%B3%A0%EA%B8%89-SELECT&quot;&gt;고급 SELECT&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#7.-%ED%85%8C%EC%9D%B4%EB%B8%94%EC%9D%B4-%EC%97%AC%EB%9F%AC%EA%B0%9C%EC%9D%B8-%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%B2%A0%EC%9D%B4%EC%8A%A4-%EC%84%A4%EA%B3%84&quot;&gt;테이블이 여러개인 데이터베이스 설계&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#8.-%EC%A1%B0%EC%9D%B8%EA%B3%BC-%EB%8B%A4%EC%A4%91-%ED%85%8C%EC%9D%B4%EB%B8%94-%EC%97%B0%EC%82%B0&quot;&gt;조인과 다중 테이블 연산&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#9.-%EC%84%9C%EB%B8%8C-%EC%BF%BC%EB%A6%AC:-%EC%BF%BC%EB%A6%AC-%EC%95%88%EC%9D%98-%EC%BF%BC%EB%A6%AC&quot;&gt;서브 쿼리: 쿼리 안의 쿼리&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#10.-%EC%99%B8%EB%B6%80-%EC%A1%B0%EC%9D%B8,-%EC%85%80%ED%94%84-%EC%A1%B0%EC%9D%B8,-%EC%9C%A0%EB%8B%88%EC%98%A8&quot;&gt;외부 조인, 셀프 조인, 유니온&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#11.-%EC%A0%9C%EC%95%BD%EC%82%AC%ED%95%AD,-%EB%B7%B0,-%ED%8A%B8%EB%9E%9C%EC%9E%AD%EC%85%98&quot;&gt;제약사항, 뷰, 트랜잭션&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#12.-%EB%B3%B4%EC%95%88&quot;&gt;보안&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. 데이터와 테이블&lt;/h2&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;CREATE DATABASE database_1 

USE database_1;

CREATE TABLE table_1
(
  value1 CHAR(1) NOT NULL,
  value2 INT     NOT NULL
);

DROP TABLE table_1;

-- 테이블 구조 확인 (Describe)
DESC table_1;

INSERT INTO table_1 (value1, value2) VALUES ('1', 2);

SELECT * FROM table_1;&lt;/code&gt;&lt;/pre&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;테이블 구조 확인은 DESC 사용&lt;/li&gt;
&lt;li&gt;DROP TABLE 은 주의해서 사용 (테이블 삭제)&lt;/li&gt;
&lt;li&gt;테이블에 데이터 넣는 것은 INSERT&lt;/li&gt;
&lt;li&gt;INSERT 문에서 값이 할당되지 않은 열은 디폴트로 NULL 이 된다.&lt;/li&gt;
&lt;li&gt;테이블을 만들 때 NOT NULL 키워드를 사용해서 NULL 값이 올 수 없도록 할 수 있다.&lt;/li&gt;
&lt;li&gt;테이블을 만들 때 열에 대해서 DEFAULT 값을 사용하면 레코드 삽입 시 그 열에 대해 값을 주지 않을 경우 디폴트 값으로 열을 채운다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2. SELECT 문&lt;/h2&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;-- table_1 이라는 테이블에서 모든 데이터를 가져온다.
SELECT * FROM table_1;
-- table_1 이라는 테이블에서 first_name 컬럼이 Anne 인 데이터를 가져온다. 
SELECT * FROM table_1 WHERE first_name = 'Anne';&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;문자열 'words' 와 &quot;words&quot; 는 쿼리에서 동작하지만, 작은따옴표가 관습적&lt;/li&gt;
&lt;li&gt;숫자를 따옴표 안에 넣은 쿼리도 동작함&lt;/li&gt;
&lt;/ul&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&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;CHAR&lt;/td&gt;
&lt;td&gt;DEC&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;VARCHAR&lt;/td&gt;
&lt;td&gt;INT&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DATE&lt;/td&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DATETIME, TIME, TIMESTAMP&lt;/td&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;BLOB&lt;/td&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;문자열 내에 작은 따옴표가 있으면, (문자열의 일부임을 표기한다)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;앞에 백슬래시 ( ' ) 를 붙이거나 -&amp;gt; 더 관습적임&lt;/li&gt;
&lt;li&gt;작은따옴표를 하나 더 붙인다 ( '' )&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;SELECT * 보다는 특정 열들을 SELECT 해서 결과를 제한한다.
&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;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;쿼리를 외부에서 복붙하여 사용할 때, 문법이 맞는 것 같은데 에러가 나면 편집기를 거쳐서 온다.&lt;/li&gt;
&lt;li&gt;비교연산자 ( &amp;lt;&amp;gt; 와 != 는 같다.)&lt;/li&gt;
&lt;li&gt;비교연산자로 문자열 처리도 가능하다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;제일 앞글자가 a 보다 뒤의 문자인 문자열 등..&lt;br /&gt;```sql&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;첫번째 문자가 'L' 이상인 문자를 찾는다.&lt;br /&gt;SELECT drink_name FROM drink_info WHERE drink_name &amp;gt;= 'L';&lt;br /&gt;```&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;NULL 을 찾기 위해서는 IS NULL 을 사용한다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;SELECT drink_name FROM drink_info WHERE calories IS NULL;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;LIKE 는 와일드카드 문자와 사용 가능하다
&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;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;SELECT first_name FROM my_contacts WHERE first_name LIKE '%im';
SELECT first_name FROM my_contacts WHERE first_name LIKE '_im';&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;BETWEEN 키워드로 범위를 사용한다. (&amp;gt;=, &amp;lt;=)&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;-- 30 &amp;lt;= x &amp;lt;= 60
-- 항상 작은값이 앞에 와야한다.  
SELECT drink\_name FROM drink\_info WHERE calories BETWEEN 30 AND 60;  &lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;IN 키워드로 OR 여러 개를 짧게 할 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;-- 동일한 쿼리. 개수가 많을수록 더 보기 좋다.  
SELECT date_name FROM black_book WHERE rating = 'innovative' OR rating = 'fabulous';  
SELECT data_name FROM black_book WHERE rating IN ('innovative', 'fabulous');

-- NOT 을 붙여서 포함하지 않는 것을 찾는다.  
SELECT data_name FROM black_book WHERE rating NOT IN ('innovative', 'fabulous');&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;NOT 은 WHERE / AND / OR 등 바로 뒤에도 쓰인다.&lt;/li&gt;
&lt;/ul&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&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;SELECT&lt;/td&gt;
&lt;td&gt;조회&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;IS NULL&lt;/td&gt;
&lt;td&gt;null check&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;BETWEEN&lt;/td&gt;
&lt;td&gt;이상/이하 사이값&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;%&lt;/td&gt;
&lt;td&gt;LIKE와 쓰는 와일드카드 문자 (다수)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;_&lt;/td&gt;
&lt;td&gt;LIKE와 쓰는 와일드카드 문자 (단일)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&amp;lt;&amp;gt;&lt;/td&gt;
&lt;td&gt;!=&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3. DELETE 와 UPDATE&lt;/h2&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;-- 테이블에서 해당 조건에 맞는 모든 레코드(행)를 삭제한다.
DELETE FROM table_1 WHERE column_1 = 'value1';&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;n1ql&quot;&gt;&lt;code&gt;INSERT INTO table_1 VALUES (column1, column2);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;테이블에서 행의 순서가 시간 순이라고 할 수 없음&lt;/b&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;어느 회사 데이터베이스 인지, 열에 인덱스가 있는지 등&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;DELETE&lt;/b&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;WHERE 절에 따라서 한 행이나 여러 행들을 지울 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;WHERE 절은 SELECT 문에서 썼던 WHERE 절과 같아서 LIKE, IN, BETWEEN 등 조건 사용 가능하다.&lt;/li&gt;
&lt;li&gt;조건을 안넣어서 전체 테이블 날리는 것 주의&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;WHERE 절을 사용하는 쿼리문은 SELECT 를 먼저 해보고 조건이 맞는지 확인해 볼 수 있다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;UPDATE 문은: 조건 SELECT(확인) -&amp;gt; 새로운 내용 INSERT(삽입) -&amp;gt; 기존 내용 DELETE(삭제)&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;UPDATE table_1 SET column_name = 'newValue'
WHERE column_name = 'oldValue';&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;WHERE 절을 뺴고 업데이트 하면, 모든 행에 대해 SET 절에 명시된 각 열의 값이 새 값으로 업데이트 된다..&lt;/li&gt;
&lt;li&gt;내가 원하는 행만 변경하는지 어떻게 확인? -&amp;gt; SELECT 문을 먼저 해본다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;UPDATE 문은: 아래처럼 기본적인 수학 연산도 수행 가능&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;UPDATE drink_info
SET cost = cost + 1
WHERE drink_name = 'Blue Moon'
OR drink_name = 'Oh My Gosh';&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;수학연산 뿐 아니라 문자 변수도 연산이 있음
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;UPPER(), LOWER() -&amp;gt; 대문자 / 소문자 변경 등&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;4. 좋은 테이블 설계: 정규화는 왜 하죠?&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;데이터가 많아지면 원하는 데이터를 찾기 위한 WHERE 절이 점점 복잡해짐 -&amp;gt; 테이블을 정규화하여 문제 해결 가능&lt;/li&gt;
&lt;li&gt;테이블은 사용자가 원하는 데이터에 따라서 형태가 달라진다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;사용용도와 테이블의 데이터 형태가 맞지 않는 경우, LIKE 등을 사용하고 쿼리가 길어지게 된다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;LIKE 키워드를 사용할 경우, 쓰는 것이 문제는 아니지만 사용이 쉽지 않고 열의 정보가 복잡하면 원하는 특정 데이터를 뽑기 쉽지 않다.&lt;/li&gt;
&lt;li&gt;쿼리는 간단할수록(짧을수록) 좋은데, 데이터베이스가 증가하고 테이블이 추가됨에 따라 쿼리는 점점 더 복잡해진다. 처음부터 최대한 간단하게 만들면 도움이 된다.&lt;/li&gt;
&lt;li&gt;무조건 잘게 쪼개는 것은 아니고, 데이터를 어떻게 사용하는 지에 따라서 정해진다.RDBMS 에서 테이블은 관계에 관한 것: 테이블을 잘 설계하려면 정보를 나타낼 때 여러 테이블 사이의 열들이 서로 어떤 관계인지 고려해야 한다는 것&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;i&gt;데이터를 어떻게 사용할 것인가에 대한 결정이 테이블을 어떻게 만들지에 영향을 준다*&lt;/i&gt;&lt;/li&gt;
&lt;li&gt;테이블을 생성하는 과정
&lt;ol 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;/li&gt;
&lt;li&gt;리스트를 이용하여 테이블을 만들 정보들의 조각으로 나눔 (가장 쉽게 쿼리를 보낼 방법)&lt;/li&gt;
&lt;li&gt;예를들어, 테이블로 음식점의 평점과 간판메뉴를 알고 싶다면 테이블로 표현하려는 것: 식당들의 평점과 간판메뉴 정보 테이블을 사용하여 얻어야 하는 정보들의 리스트: 식당이름, 주소, 전화번호, 평점, 간판메뉴(들) 테이블을 만들 정보들의 조각: 식당이름, 지역, 상세주소, 전화번호, 평점, 간판메뉴(들)&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 주소는 지역/상세주소 로 원자화 했지만&lt;br /&gt;간판메뉴는 여러개이지만 목록으로 가져오면 된다고 생각해서 쪼개지 않음 (별도 테이블로?)&lt;br /&gt;-&amp;gt; 충분히 원자적(atomic) 이다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&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;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;i&gt;원자적 데이터를 사용하면 쿼리 작성이 더 쉽고, 수행 시간이 더 빨라진다. (저장 데이터가 대용량일 경우 더 효율적)*&lt;/i&gt;&lt;/li&gt;
&lt;li&gt;테이블에 무엇을 넣을지 도움되는 질문
&lt;ol 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;/li&gt;
&lt;li&gt;열들은 쿼리를 짧게 명료하게 하기 위해 원자적 데이터를 갖는가?&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;원자적 데이터 규칙&lt;/b&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;원자적 데이터로 구성된 열은 그 열에 같은 타입의 데이터를 여러 개 가질 수 없다.&lt;/li&gt;
&lt;/ol&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;food_name&lt;/th&gt;
&lt;th&gt;ingredients&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;bread&lt;/td&gt;
&lt;td&gt;flour, milk, egg, yeast, oil&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;salad&lt;/td&gt;
&lt;td&gt;lettuce, tomato, cucumber&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2. 원자적 데이터로 구성된 테이블은 같은 타입의 데이터를 여러 열에 가질 수 없다.&lt;/td&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;teacher&lt;/th&gt;
&lt;th&gt;student1&lt;/th&gt;
&lt;th&gt;student2&lt;/th&gt;
&lt;th&gt;studnet3&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Ms. Martini&lt;/td&gt;
&lt;td&gt;Joe&lt;/td&gt;
&lt;td&gt;Ron&lt;/td&gt;
&lt;td&gt;Kelly&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mr. Howard&lt;/td&gt;
&lt;td&gt;Sanjaya&lt;/td&gt;
&lt;td&gt;Tim&lt;/td&gt;
&lt;td&gt;Julie&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;정규화의 이유&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;테이블이 표준 규칙을 따르게 한다 -&amp;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;h4 data-ke-size=&quot;size20&quot;&gt;제 1정규화 (1NF)&lt;/h4&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;각 행의 데이터들은 원자적 값을 가져야 한다.&lt;/li&gt;
&lt;li&gt;각 행은 유일무이한 식별자인 기본키(primary key)를 가지고 있어야 한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;기본키 규칙
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;NULL 불가&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;/li&gt;
&lt;li&gt;기본키를 주민번호 등 기존 존재하는 열 데이터로 만드는 것 (natural key)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;개인정보 유출 등을 고려해서 조심&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;새로 만들어 내는 기본키 사용 (synthetic key)&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;DESCRIBE table_name; 
-- 위 경우는 테이블 필드 정보

SHOW CREATE TABLE table_name; 
-- 위 경우는 테이블 작성문 반환&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;SHOW 를 통해서 테이블 작성문을 반환해보면 백틱문자(`) 가 있음 (복붙에는 상관 없음)&lt;/li&gt;
&lt;li&gt;SHOW 키워드&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;-- 테이블 모든 열을 표시하고 열의 데이터 타입과 열의 세부사항 표시
SHOW COLUMNS FROM table_name;

-- 테이블을 생성하는 명령을 얻음  
SHOW CREATE TABLE table_name;

-- 데이터베이스를 생성하는 명령을 얻음  
SHOW CREATE DATABASE database_name;

-- 인덱싱이 되어 있는 열과 무슨 타입의 인덱스를 갖는지 표시  
SHOW INDEX FROM table_name;

-- 수행한 SQL문이 경고 메시지를 표시하면 이것으로 실제 경고 메시지 확인 가능  
SHOW WARNINGS;&lt;/code&gt;&lt;/pre&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;b&gt;AUTO_INCREMENT&lt;/b&gt; 키워드를 사용해서 자동으로 최대값 이 후 값을 넣어주는 기능을 넣을 수 있다.&lt;/li&gt;
&lt;li&gt;기본키 값을 포함해서 INSERT 가능하지만, 중복은 안되고 없는 값은 넣을 수 있다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;NULL 의 경우는 무시되고 알아서 AUTO_INCREMENT 된 값이 들어간다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;-- 기존 테이블에 기본키 추가하는 방법 (ALTER)
ALTER TABLE table_name
ADD COLUMN id INT NOT NULL AUTO_INCREMENT FIRST,
ADD PRIMARY KEY (id);

-- 위 코드의 경우 기존에 있던 레코드들에 id 값을 자동으로 넣어준다.&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;마무리 정리&lt;/h3&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;AUTO_INCREMENT: primary key 또는 unique 키 에서 사용 가능함. 해당 열의 최대값보다 큰 값으로 더해서 겹치지 않게 넣어줌.&lt;/li&gt;
&lt;li&gt;SHOW CREATE TABLE: 테이블 생성 명령어를 보여줌&lt;/li&gt;
&lt;li&gt;제 1정규형(1NF):
&lt;ol 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;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;기본키(Primary Key): 중복되지 않고 null 이 될 수 없는 식별자 역할의 키. 레코드 삽입 시 필수!&lt;/li&gt;
&lt;li&gt;원자적데이터 규칙
&lt;ol 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;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;5. ALTER: 과거 다시 쓰기&lt;/h2&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;-- 예시
-- 테이블에 전화번호 컬럼을 추가하는데, 위치는 이름 컬럼 바로 뒤에 넣는다.
-- FIRST, SECOND, THIRD, FOURTH... , AFTER, LAST, FIRST 위치 지정도 가능하다.
ALTER TABLE table_name
ADD COLUMN phone VARCHAR(20) AFTER name;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;-- 예시
-- 연락처테이블에 아이디컬럼을 추가하는데, 자동증가 키값으로 가장 앞 열에 추가한다.
ALTER TABLE contacts
ADD COLUMN contact_id INT NOT NULL AUTO_INCREMENT FIRST,
ADD PRIMARY KEY (contact_id);&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;데이터 변경 (데이터 손실에 유의한다.)&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;CHANGE: 기존 열의 &lt;code&gt;이름&lt;/code&gt;과 &lt;code&gt;데이터타입&lt;/code&gt;을 바꾼다.&lt;/li&gt;
&lt;li&gt;MODIFY: 기존 열의 &lt;code&gt;데이터타입&lt;/code&gt;이나 &lt;code&gt;위치&lt;/code&gt;를 바꾼다.&lt;/li&gt;
&lt;li&gt;ADD: 테이블에 열을 추가한다. (데이터타입 설정 가능)&lt;/li&gt;
&lt;li&gt;DROP: 열을 제거한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;--예시
ALTER TABLE projekts  
RENAME TO project\_list;

ALTER TABLE project\_list  
CHANGE COLUMN number proj\_id INT NOT NULL AUTO\_INCREMENT,  
ADD PRIMARY KEY (proj\_id);

ALTER TABLE project\_list  
CHANGE COLUMN descriptionofproj proj\_desc VARCHAR(100),  
CHANGE COLUMN contractoronjob con\_name VARCHAR(30);&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데이터 타입을 새롭게 바꾸면 데이터를 잃을 수 있다.&lt;/p&gt;
&lt;/blockquote&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;b&gt;테이블 당 1개의 필드만 AUTO INCREMENT 가 있을 수 있고, 정수 타입이고 NULL 이 아니어야 한다.&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;문자 함수들: 실제 값을 변화시키지 않고, 쿼리 결과로 반환된 문자열을 변환&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;SUBSTRING: SUBSTRING(your_string, start_position, length)&lt;/li&gt;
&lt;li&gt;SUBSTRING_INDEX: 찾는 문자의 해당 숫자번째로 찾아진 문자까지 출력한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;stylus&quot;&gt;&lt;code&gt;SUBSTRING_INDEX('Hello, world, bye,', ',', 2)
-- 'Hello, world'&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;RIGHT: RIGHT('Hello, 2) -&amp;gt; 'lo'&lt;/li&gt;
&lt;li&gt;LEFT: LEFT('Hello', 4) -&amp;gt; 'Hell'&lt;/li&gt;
&lt;li&gt;UPPER: 문자열 대문자로 변환&lt;/li&gt;
&lt;li&gt;LOWER: 문자열 소문자로 변환&lt;/li&gt;
&lt;li&gt;REVERSE: 문자열 역순으로 만듦&lt;/li&gt;
&lt;li&gt;LTRIM: 왼쪽 공백 제거&lt;/li&gt;
&lt;li&gt;RTRIM: 오른쪽 공백 제거&lt;/li&gt;
&lt;li&gt;LENGTH: 문자열 길이 반환&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;6. 고급 SELECT&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;lt;&amp;gt;&lt;/b&gt; -&amp;gt; &lt;b&gt;!=&lt;/b&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;CASE&lt;/h4&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;-- 예시
-- 무비테이블에서 카테고리를 업데이트하는데,
-- 드라마가 트루이면 'drama' 로,
-- 코메디가 트루이면 'comedy' 로,
-- 조건에 없으면 'misc' 로 업데이트 한다.
UPDATE movie_table
SET category =
    CASE
        WHEN drama = 'T' THEN 'drama'
        WHEN comedy = 'T' THEN 'comedy'
        -- ...
        ELSE 'misc'
    END;&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;CASE 문이 동작 할 때, 윗줄의 조건에 해당하는 것이 있으면 아랫줄로 내려오지 않는다.&lt;/li&gt;
&lt;li&gt;ELSE 문은 뺄 수 있지만, 조건이 없는 경우 NULL 외에 다른 값이 좋다. (ELSE 도 없고 조건에도 없으면 CRUD 동작하지 않는다.)&lt;/li&gt;
&lt;li&gt;END 뒤에 WHERE 절을 붙여서 해당 조건의 행에서만 CASE 문을 실행하도록 할 수 있다.&lt;/li&gt;
&lt;li&gt;CASE 문은 SELECT, INSERT, DELETE, UPDATE 모두 사용 가능하다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;ORDER BY&lt;/h4&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;-- 예시
-- 타이틀, 카테고리, 구매날짜를 무비테이블에서 조회하는데
-- 카테고리가 Family 인 것들을 조회하고,
-- 카테고리는 오름차순 정렬하고, 카테고리 내부에서는 구매날짜의 내림차순으로 정렬한다.
SELECT title, category, purchased
FROM movie_table
WHERE category = 'Family'
ORDER BY category ASC, purchased DESC;&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;결과를 정해둔 기준으로 정렬한다. (오름차순(ASC), 내림차순(DESC))&lt;/li&gt;
&lt;li&gt;SQL 순서 규칙
&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;/li&gt;
&lt;li&gt;NULL 은 숫자 앞에 온다.&lt;/li&gt;
&lt;li&gt;NULL 은 알파벳 앞에 온다.&lt;/li&gt;
&lt;li&gt;대문자는 소문자 앞에 온다.&lt;/li&gt;
&lt;li&gt;&quot;A 1&quot; 은 &quot;A1&quot; 앞에 온다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;SQL 순서 규칙 (기호)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;! &quot; &amp;amp; ' * + = ? @ ~SUM, AVG, MIN, MAX, COUNT (함수) + GROUP BY, DISTINCT (키워드)```mysql&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&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;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;sales 를 조회해서 합산한 값을 보여주는데,&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&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;/ul&gt;
&lt;/li&gt;
&lt;li&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;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;sales 합산 값의 내림차순으로 보여주는데,&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;0부터 2개 (0,1) 까지만 보여준다. (또는 그냥 LIMIT 2)&lt;br /&gt;SELECT SUM(sales)&lt;br /&gt;FROM cookie_sales&lt;br /&gt;GROUP BY name&lt;br /&gt;ORDER BY SUM(sales) DESC&lt;br /&gt;LIMIT 0, 2;&lt;br /&gt;mysql&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&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;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;n1ql&quot;&gt;&lt;code&gt;SELECT DISTINCT COUNT(sale_date)  
FROM cookie_sales  
ORDER BY sale_date;  &lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;GROUP BY
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;공통된 열 값으로 행들을 집계한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;DISTINCT
&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;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;LIMIT
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;몇개의 행을 반환할지, 어디부터 몇개 행을 반환할지 정한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;NULL 은 MIN, MAX, COUNT 에 영향받지 않음&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;7. 테이블이 여러개인 데이터베이스 설계&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;테이블을 잘 설계해서 일을 해결해야 한다. 설계에 문제가 있는 테이블을 해결하려고 복잡한 쿼리를 작성하면 안된다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;테이블에서 원자적이지 않은 열을 새로운 테이블로 옮긴다.&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;gcode&quot;&gt;&lt;code&gt; 주소록(contacts)테이블에서 관심사(interests) 와 같이, 검색하기 어려운 경우&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;스키마: 데이터베이스 내의 데이터(열들과 테이블들), 그리고 데이터들 사이의 연결 방식에 대한 표현&lt;/h3&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;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;테이블을 그림으로 만들면 테이블 설계와 데이터를 분리하여 생각 할 수 있다.&lt;/b&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;하나의 테이블을 두개로 만드는 법 (ex. 관심사(interests))&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;관심사 열을 없애고 관심사만의 테이블에 넣는다.&lt;/li&gt;
&lt;li&gt;관심사가 기존 테이블(contacts)의 어떤 레코드와 관련 있는지를 알 수 있게 하는 열을 추가한다.
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이 때, 관련있는 열이 유일하지 않으면, 연결이 잘못 될 수 있다. (기본키를 쓰는데, 다른 테이블에서는 참조키(Foreign Key)라 한다)&lt;/li&gt;
&lt;li&gt;참조키(외래키, FK)를 통해서, 어느 관심사가 어느 사람연락처에 속하는지 알 수 있다.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;참조키&lt;/h3&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;참조키에서 참조하는 기본키는 부모키(parent key), 부모키가 있는 테이블은 부모테이블(parent table) 이라 한다.&lt;/li&gt;
&lt;li&gt;한 테이블의 열들이 다른 테이블의 열과 연결되도록 하는데 사용할 수 있다.&lt;/li&gt;
&lt;li&gt;기본키는 not null 이지만, 참조키 값은 null 일 수 있다.&lt;/li&gt;
&lt;li&gt;참조키는 유일할 필요가 없다. (not unique)&lt;/li&gt;
&lt;li&gt;참조키는 부모테이블에 존재하는 키의 값만을 넣을 수 있다. (참조 무결성, referential integrity)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;자식테이블의 참조키로는 부모 테이블에 존재하는 값만 넣을 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;제약조건 (constraint): 테이블이 준수해야 하는 규칙&lt;/h4&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;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;참조키가 있는 테이블 생성&lt;/h3&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;-- 기존에 my_contacts 테이블에서 분리된다고 가정
CREATE TABLE interests (
    int_id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
    interest VARCHAR(50) NOT NULL,
    contact_id INT NOT NULL,
    CONSTRAINT my_contacts_contact_id_fk    -- 제약조건은 어느테이블 어느키를 참조하는지, 제약조간이 fk 라고 명명 (이름 수정 가능)
    FOREIGN KEY (contact_id)                -- 괄호 안의 열 이름이 참조키
    REFERENCES my_contacts (contact_id)     -- REFERENCES 어느 테이블의 (어느 열) 인지 표시한다.
);

-- DESC interests 를 터미널에서 쳐서 정보를 확인 할 때,
-- Key 열에서 MUL (같은 값이 여러번 나올 수 있다) 을 확인하면 참조키 확인 가능&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;참조키를 제약조건 없이, 그냥 다른 테이블 참조하여 사용할 수 있지만, 연결을 강제하기 위해 제약조건을 사용한다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&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;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;테이블 간의 관계 (일대일, 일대다, 다대다)&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;일대일 (부모테이블 하나의 행은 자식 테이블 하나의 행과 관련되어 있다)&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;ex) 보안을 위해서 분리: 사원 테이블 - 급여 테이블(+SSN)&lt;/li&gt;
&lt;li&gt;자주 이용은 안됨&lt;/li&gt;
&lt;li&gt;열을 분리하면 데이터 조회 속도가 향상될 수 있음&lt;/li&gt;
&lt;li&gt;아직 모르는 값을 포함하는 열이 있어도, 주 테이블에서는 null 값을 피할 수 있음&lt;/li&gt;
&lt;li&gt;데이터의 일부를 접근하기 힘들게 할 수 있다.&lt;/li&gt;
&lt;li&gt;BLOB 타입처럼 양이 큰 데이터가 있어서 큰 데이터는 따로 저장 하고 싶을 경우.일대다&lt;/li&gt;
&lt;li&gt;ex) 직업 테이블의 레코드는 사람들 테이블에서 여러번 나올 수 있지만, 사람들 테이블은 1개의 직업ID 만 가지고 연결된다.&lt;/li&gt;
&lt;li&gt;테이블 A 의 한 레코드가 테이블 B 의 여러 레코드와 연결되지만, 테이블 B 의 레코드는 테이블 A 의 레코드 한개에만 연결될 수 있다.다대다&lt;/li&gt;
&lt;li&gt;ex) 여러 명의 여자는 여러 켤레의 신발을 갖는다.&lt;/li&gt;
&lt;li&gt;2개의 일대다 관계로 이루어지고 사이에 연결테이블이 있다.&lt;/li&gt;
&lt;li&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;중간테이블(연결테이블, junction table)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;양 측의 id 값 쌍들을 보관한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;두 테이블 사이에 연결테이블이 없으면, 중복데이터가 생겨서 제1정규형을 위반한다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;위반 시, 중복 데이터 때문에 쿼리의 시간이 길어진다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;테이블을 분리하고 연결테이블을 쓰면, 조인을 사용한 쿼리를 사용 가능하다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;테이블 조인을 사용하면 데이터의 무결성(integrity)을 유지하는데 도움이 된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;제 1 정규형 (1NF)&lt;/h4&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;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;합성키: 두 개 이상의 열로 이루어진 키&lt;/h3&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;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;한 테이블 내의 열들이 서로 어떻게 연결되는지 이해하는 것: 제2정규형, 제3정규형 이해의 핵심&lt;/h3&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;함수적 종속&lt;/h2&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;ex) 영웅이름 -&amp;gt; 영응이름의 이니셜 (T.x -&amp;gt; T.y, T 라는 테이블에서 열 y는 열 x에 함수적으로 종속된다)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이니셜은 이름에 종속, 약점은 이름에 종속, 도시는 나라에 종속 등...&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;T.x -&amp;gt; T.y (shorthand notation, 줄임 표기법)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;부분적 함수 종속&lt;/h3&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;ex) name, power 가 함께 합성키인 경우
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이니셜은 name에 종속되지만 power에 종속되지 않음 (부분적 함수종속)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;이행적 함수 종속 (transitive dependency)&lt;/h3&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;/li&gt;
&lt;li&gt;ex) heroes table 에서, arch_enemy 를 변경하면 arch_enemy, arch_enemy_city 도 변할 수 있다.&lt;/li&gt;
&lt;li&gt;부분적 함수 종속을 피하는 방법
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;id 열을 만들어서 필드로 사용한다. (새 키는 테이블 인덱스 용으로만 사용되기 때문에 새 키에 종속되는 것이 없다)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;natural key(자연키) - 기존 있는 것 또는 합성 키, synthetic key(인위적 키) - 키를 위한 키
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;선택 사항&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;테이블에 기본키 열을 추가하면 2NF 를 만드는 데 도움이 됨&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;왜냐면, 제2정규형은 테이블의 기본키가 데이터와 어떤 관계에 있는지에 초점을 맞춤&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;제 2 정규형 (2NF)&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;1NF 여야 한다.&lt;/li&gt;
&lt;li&gt;부분적 함수 의존이 없다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;간단한 방법으로는..
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;1NF 이면서 하나의 열로 된 기본키를 갖거나 (인위적으로 만든 기본키가 있고, 합성키가 없으면 2NF),&lt;/li&gt;
&lt;li&gt;1NF 모든 열이 기본키(합성키)의 일부이거나,&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;제 3 정규형 (3NF)&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;2NF 여야 한다.&lt;/li&gt;
&lt;li&gt;이행적 종속이 없다. (키가 아닌 다른 열이 키가 아닌 다른 열과 관련되어 있지 않다)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;3NF 를 고려할 때는 기본키는 무시할 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;제 1, 2, 3 정규화를 통해서..&lt;br /&gt;테이블을 정돈&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;정리&lt;/h4&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;/li&gt;
&lt;li&gt;일대다 관계: 한 테이블의 한 행이 두 번째 테이블의 여러 행과 연결되지만 두 번째 테이블은 첫번째 테이블의 한 행과 연결되는 관계&lt;/li&gt;
&lt;li&gt;다대다 관계: 두 테이블이 연결 테이블로 연결되어 첫번째 테이블의 여러 행이 두번째 테이블의 여러 행과 연결, 두번째 테이블의 여러 행도 첫번째 테이블의 여러 행과 연결되는 관계&lt;/li&gt;
&lt;li&gt;제1정규형: 열이 원자적 값만을 포함하고, 열에 데이터가 반복되지 않는 형태&lt;/li&gt;
&lt;li&gt;제2정규형: 테이블이 1NF 여야 하고, 부분적 함수 종속이 없음&lt;/li&gt;
&lt;li&gt;제3정규형: 테이블이 2NF 여야 하고, 이행적 종속 관계가 없음&lt;/li&gt;
&lt;li&gt;이행적 함수 종속: 키가 아닌 열이 키가 아닌 다른 열과 관련있다는 의미&lt;/li&gt;
&lt;li&gt;참조키: 테이블에서 다른 테이블의 기본키를 참조하는 열&lt;/li&gt;
&lt;li&gt;합성키: 여러열로 구성된 기본키로 유일무이 한 값&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;8. 조인과 다중 테이블 연산&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;정규화 되지 않은 테이블 설계 때문에 쿼리를 만들기가 어려움.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;ex) my_contacts 테이블에서, interests 는 원자화 되어있지 않음
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;컬럼을 추가해서 나눈다 (아직 같은 데이터 열들이 반복되긴 함)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;interest1 = SUBSTRING_INDEX(interests, ',', 1);&lt;/li&gt;
&lt;li&gt;SUBSTR(interests, LENGTH(interest1) + 2);&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;SELECT 문을 이용하여 새로운 테이블을 채우는 법
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;여러 방법을 알면 상황에 가장 맞는 방법을 선택 할 수 있고, 같은 일을 여러 방법으로 수행 할 수 있으면 최적화에 도움이 된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;-- 1. CREATE table 그리고 SELECT 를 이용한 INSERT  
    CREATE TABLE profession  
    (  
    id INT(11) NOT NULL AUTO\_INCREMENT PRIMARY KEY,  
    profession VARCHAR(20)  
    );

INSERT INTO profession (profession)  
SELECT profession FROM my\_contacts  
GROUP BY profession  
ORDER BY profession;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;-- 2. SELECT 를 이용해서 테이블을 만들고 ALTER 를 사용해서 기본키 추가  
CREATE TABLE profession AS  
SELECT profession FROM my\_contacts  
GROUP BY profession  
ORDER BY profession;

ALTER TABLE profession  
ADD COLUMN id INT NOT NULL AUTO\_INCREMENT FIRST,  
ADD PRIMARY KEY (id);&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;-- 3. 기본키와 SELECT 문의 데이터를 포함한 테이블을 한 문장으로 생성
CREATE TABLE profession
(
    id INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
    profession VARCHAR(20)
) AS 
SELECT profession FROM my_contacts
GROUP BY profession
ORDER BY profession;

-- 3번과 같이 새 테이블이 새로운 이름의 2개 열을 갖는다고 표시하지 않았다면,
-- AS 는 한 열을 SELECT 의 결과와 같은 이름, 타입을 만듦 (2번처럼)&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;별명(alias) 만드는 방법: 처음 나오는 열 이름 뒤에 AS 와 함께 별명을 붙인다.&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;AS 는 생략 가능&lt;/li&gt;
&lt;li&gt;별명은 원래 열의 이름은 변하지 않고, 잠깐 사용된다.&lt;/li&gt;
&lt;li&gt;테이블 별명은 연결이름(correlation name) 이라고 부른다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;CREATE TABLE profession 
( 
    id INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY, 
    profession VARCHAR(20) 
) AS 
SELECT profession AS mc_prof 
FROM my_contacts 
GROUP BY mc_prof 
ORDER BY mc_prof;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Join&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Inner Join (내부조인)&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;code&gt;내부조인&lt;/code&gt;은 쿼리의 조건에 따라 일부 결과열이 제거된 크로스 조인&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;1. 카티젼 조인 (Cartesian join, Cartesian product, Cross product, Cross join...)&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&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;/ul&gt;
&lt;/li&gt;
&lt;li&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;DB 시스템과 환경의 성능 확인에 사용된다.&lt;/li&gt;
&lt;li&gt;슬로 쿼리 사용 시 걸리는 시간을 더 쉽게 비교, 확인 가능하다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;너무 큰 테이블을 크로스 조인하면 다운 될 위험&lt;/li&gt;
&lt;li&gt;&lt;code&gt;SELECT t.toy, b.boy FROM toys AS t CROSS JOIN boys AS b;&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;-- cross join 없애고 콤마로 대체 가능  
SELECT toys.toy, boys.boy  
FROM toys, boys;&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;2. 내부 조인 ( 동등조인(=), 비동등조인(&amp;lt;&amp;gt;) )&lt;/h4&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;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;n1ql&quot;&gt;&lt;code&gt;SELECT someColumns
FROM table1
INNER JOIN table2
    ON table1.something = table2.something  -- ON 대신 WHERE 가능
OR table1.something &amp;lt;&amp;gt; table2.something;&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;3. 내부 조인 (자연조인)&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;일치하는 열 이름을 사용하는 &lt;code&gt;내부조인&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;두 테이블에 같은 이름의 열이 있을 때 동작&lt;/li&gt;
&lt;li&gt;동등조인과 유사
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;SELECT boys.boy, toys.toy 
FROM boys 
NATURAL JOIN toys;&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;외부조인&lt;/code&gt;의 경우에는 테이블을 조인하는 순서가 중요함 (10장)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;정리&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;내부조인(INNER JOIN): 조건을 사용해서 두 테이블의 레코드를 결합하는 모든 조인
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;동등조인(EQUI JOIN): 같은 행들 반환&lt;/li&gt;
&lt;li&gt;비동등조인(NON-EQUI JOIN): 같지 않은 행들 반환&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;자연조인(NATURAL JOIN): ON 절이 없는 내부조인. 같은 열 이름을 가진 두 테이블을 조인할 때만 동작한다.&lt;/li&gt;
&lt;li&gt;크로스조인(CROSS JOIN, Comma JOIN): 한 테이블의 모든 행과 다른 테이블의 모든 행이 연결되는 모든 경우를 반환 (=&lt;code&gt;카티젼조인&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;9. 서브 쿼리: 쿼리 안의 쿼리&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;서브쿼리: 다른 쿼리에 싸여진 쿼리 = 내부쿼리&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;연산자를 사용해서 하나의 값, 혹은 한 열의 한 행을 (셀, 스칼라) 반환하며, 반환된 값은 WHERE 절의 열들과 비교된다. (대부분은 하나의 결과)&lt;/li&gt;
&lt;li&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;/ul&gt;
&lt;/li&gt;
&lt;li&gt;조인으로도 처리 가능함&lt;/li&gt;
&lt;li&gt;WHERE 절 같은 역할을 함&lt;/li&gt;
&lt;li&gt;서브쿼리는 언제나 SELECT 문 한개&lt;/li&gt;
&lt;li&gt;SELECT, INSERT, UPDATE, DELETE 와 함께 사용 가능함&lt;/li&gt;
&lt;li&gt;쿼리할 질문을 나누어 각 부분에 작은 쿼리를 만드는 방법이 좋음
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;ex) 연봉이 가장 많은 웹 디자이너와 같은 연봉을 버는 사람을 찾으려 한다면,
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;가장 연봉이 많은 웹 디자이너를 찾는다&lt;/li&gt;
&lt;li&gt;연봉이 X 인 사람을 찾는다&lt;/li&gt;
&lt;/ol&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;첫번째 쿼리의 답을 X 에다가 넣어서 돌린다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ex) 아래 동일한 쿼리&lt;/p&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;-- 쿼리 2회
SELECT mc.first_name, mc.last_name, mc.phone, jc.title
FROM job_current AS jc NATURAL JOIN my_contacts AS mc
WHERE
    jc.title IN ('Cook', 'Hairdresser', 'Waiter', 'Web Designer', 'Web Developer');

-- 서브쿼리 사용 (IN 을 사용하는 것은 예외적인 경우이긴 함, 보통 1개 결과를 반환하게 사용함)
SELECT mc.first_name, mc.last_name, mc.phone, jc.title
FROM job_current AS jc NATURAL JOIN my_contacts AS mc
WHERE
    jc.title IN (SELCT title FROM job_listings);&lt;/code&gt;&lt;/pre&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;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;열 별명 (AS 사용)&lt;/h4&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;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;서브 쿼리 생성의 예&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;ex) 가장 연봉이 높은 사람의 이름과 연봉을 찾는다. (my_contacts, job_currents)&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;-- 1  
SELECT MAX(salary) FROM job_current;

-- 2  
SELECT mc.first_name, mc.last_name  
FROM my_contacts AS mc;

-- 3  
SELECT mc.first_name, mc.last_name, jc.salary  
FROM my_contacts AS mc  
NATURAL JOIN job_currents AS jc;

-- 4  
SELECT mc.first_name, mc.last_name, jc.salary  
FROM my_contacts AS mc  
NATURAL JOIN job_currents AS jc  
WHERE jc.salary = (SELECT MAX(jc.salary) FROM job_current jc);&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;서브 쿼리를 SELECT &lt;code&gt;열&lt;/code&gt;에서 사용&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;서브 쿼리는 SELECT 문의 열 중 하나로 사용될 수 있음&lt;/li&gt;
&lt;li&gt;서브쿼리가 열의 표현식으로 사용되었다면, 한 열에서 하나의 값만을 반환할 수 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;pf&quot;&gt;&lt;code&gt;SELECT mc.first_name, mc.last_name,
(SELECT state 
FROM zip_code
WHERE mc.zip_code = zip_code) AS state
FROM my_contacts AS mc;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;자연 조인을 포함한 서브 쿼리의 예&lt;/h3&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;-- 1
SELECT jc.salary
FROM my_contacts mc NATURAL JOIN job_current AS jc
WHERE email = 'andy@weatherorama.com';

-- 2
SELECT mc.first_name, mc.last_name, jc.salary
FROM my_contacts AS mc
NATURAL JOIN job_current AS jc
WHERE jc.salary &amp;gt; 
    (SELECT jc.salary 
    FROM my_contacts AS mc
    NATURAL JOIN job_current AS jc
    WHERE email = 'andy@weatherorama.com');&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;비상관 서브쿼리 (non-correlated)&lt;/h3&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;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;상관 서브쿼리 (correlated)&lt;/h3&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;/li&gt;
&lt;li&gt;외부 쿼리에서 만들어진 테이블과 같은 별명 (상관 이름) 을 사용함&lt;/li&gt;
&lt;li&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;ex) my_contacts 의 사람들 중 job_current 테이블에 없는 모든 사람을 찾는다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;n1ql&quot;&gt;&lt;code&gt;SELECT mc.first_name, mc.last_name, mc.email 
FROM my_contacts mc 
WHERE NOT EXISTS 
(
    SELECT * FROM job_current jc 
    WHERE mc.contact_id = jc.contact_id
);&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;서브쿼리 예제(Join, Noncorrelated subquery)&lt;/h3&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;-- 1. job_listings 테이블에서 가장 연봉이 높은 직업들의 이름을 나열 (my_contacts, job_listings)
SELECT jl.title FROM job_listings AS jl
WHERE jl.salary = (SELECT MAX(jl.salary) FROM job_listings AS jl);

-- 2. 평균 연봉보다 많은 연봉인 사람의 이름을 나열 (my_contacts, job_current) 
SELECT mc.name FROM my_contacts AS mc
INNER JOIN job_current AS jc
    ON mc.contact_id = jc.contact_id
WHERE jc.salary &amp;gt; (SELECT AVG(salary) FROM job_current);

-- 3. job_listings 테이블에서 웹디자이너에 대한 우편번호와 같은 우편번호를 갖는 웹 디자이너를 찾아라 (my_contacts, job_current, job_listings)
SELECT zip FROM job_listings WHERE title = 'Web Developer';

SELECT mc.name FROM my_contacts AS mc
INNER JOIN job_current AS jc
    ON mc.contact_id = jc.contact_id
WHERE jc.title = 'Web Developer'
    AND mc.zip_code IN (
        SELECT zip_code FROM job_listings WHERE title = 'Web Developer'
);

-- 4. 현재의 연봉이 가장 많은 사람과 같은 우편번호에 사는 모든 사람을 나열 (my_contacts, job_current)
-- 쪼개서 순서대로 구현
-- 연봉 가장 많은 사람
SELECT MAX(salary) FROM job_current;
-- 연봉 가장 많은 사람의 우편번호
SELECT mc.zip_code FROM my_contacts AS mc
INNER JOIN job_current AS jc
    ON mc.contact_id = jc.contact_id
WHERE jc.salary = (SELECT MAX(salary) FROM job_current);
-- 연봉 가장 많은 사람의 우편번호와 같은 사람들
SELECT mc.name FROM my_contacts AS mc
WHERE mc.zip_code = (SELECT mc.zip_code FROM my_contacts AS mc
    INNER JOIN job_current AS jc
        ON mc.contact_id = jc.contact_id
    WHERE jc.salary = (SELECT MAX(salary) FROM job_current)
);&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;정리&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&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;/ul&gt;
&lt;/li&gt;
&lt;li&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;/ul&gt;
&lt;/li&gt;
&lt;li&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;/ul&gt;
&lt;/li&gt;
&lt;li&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;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;10. 외부 조인, 셀프 조인, 유니온&lt;/h2&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;code&gt;조인이 서브쿼리보다는 훨씬 빠르다.&lt;/code&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;자신을 참조하는 참조키 (SELF REFERENCE KEY)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;같은 테이블 내의 기본키를 가리키는 참조키로, 특정 목적에 이용됨&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;셀프 조인 (INNER JOIN)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;셀프 조인을 사용하여 하나의 테이블을 같은 정보의 테이블이 두 개 인 것처럼 쿼리를 실행 가능함&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;왼쪽 외부 조인 (LEFT OUTER JOIN)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;왼쪽 외부 조인은 왼쪽 테이블의 모든 행들을 가져다 오른쪽 테이블의 행에 대응시킴&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;오른쪽 외부 조인 (RIGHT OUTUER JOIN)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;오른쪽 외부 조인은 오른쪽 테이블의 모든 행을 가져다 왼쪽 테이블의 행에 대응시킴&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;UNION, UNION ALL
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;UNION 은 SELECT 의 열 리스트를 기반으로 두 개 이상 쿼리의 결과를 합해 하나의 테이블에 나타냄&lt;/li&gt;
&lt;li&gt;UNION 은 중복된 값들은 하나만 표시하고, UNION ALL 은 중복값을 모두 표시함&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;CREATE TABLE AS
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;SELECT 문의 결과로 테이블을 만들 때 사용함&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;INTERSECT
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;첫번째 쿼리의 결과와 두번째 쿼리의 결과 모두에서 나오는 값들을 구할 때 사용&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;EXCEPT
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;첫번째 쿼리의 결과이면서 두번째 쿼리의 결과는 아닌 값들만을 구할 때 이 키워드 사용&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;LEFT OUTER JOIN (왼쪽 외부 조인)&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;왼쪽 테이블의 &lt;code&gt;모든 행&lt;/code&gt;을 가져다 오른쪽 테이블의 행과 비교한다.&lt;/li&gt;
&lt;li&gt;왼쪽 테이블과 오른쪽 테이블이 일대다 관계에 있을 때 유용함&lt;/li&gt;
&lt;li&gt;왼쪽 외부 조인에서는 FROM 뒤에 그리고 조인 전에 나오는 테이블이 왼쪽 테이블이고, 조인 뒤에 나오는 테이블이 오른쪽 테이블&lt;/li&gt;
&lt;li&gt;외부조인 (OUTER JOIN)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;다른 테이블과 일치하는 것이 있는가에 상관없이 행을 반환함
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;일치하는 것이 없으면 NULL 값으로 표시함&lt;/li&gt;
&lt;li&gt;소녀와 장난감의 경우, 결과가 NULL 값이면 특정 장난감이 어느 소녀한테도 속하지 않는다는 의미&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;왼쪽 외부 조인의 결과가 NULL 값이면,
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;오른쪽에 왼쪽 테이블에 상응하는 값이 없다는 의미&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;RIGHT OUTER JOIN&lt;/h3&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;/li&gt;
&lt;li&gt;그럼에도 오른쪽/왼쪽 외부 조인을 사용하는 이유는?
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;쿼리에서 테이블의 순서를 변경하는 것보다 LEFT/RIGHT 바꾸는 것이 쉬움&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;ex)&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;girls&lt;/b&gt; (left table)&lt;/p&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;girl_id&lt;/th&gt;
&lt;th&gt;girl&lt;/th&gt;
&lt;th&gt;toy_id&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Jane&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;Sally&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;Cindy&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;toys&lt;/b&gt; (right table)&lt;/p&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;toy_id&lt;/th&gt;
&lt;th&gt;toy&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;hula hoop&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;balsa glider&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;toy soldiers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;harmonica&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;baseball cards&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;tinker toys&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;etch-a-sketch&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;slinky&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;result&lt;/b&gt; of &lt;code&gt;LEFT OUTER JOIN&lt;/code&gt;&lt;/p&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;girl&lt;/th&gt;
&lt;th&gt;toy&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Cindy&lt;/td&gt;
&lt;td&gt;hula hoop&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Jane&lt;/td&gt;
&lt;td&gt;toy soldiers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sally&lt;/td&gt;
&lt;td&gt;harmonica&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;result&lt;/b&gt; of &lt;code&gt;RIGHT OUTER JOIN&lt;/code&gt;&lt;/p&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;girl&lt;/th&gt;
&lt;th&gt;toy&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Cindy&lt;/td&gt;
&lt;td&gt;hula hoop&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;null&lt;/td&gt;
&lt;td&gt;balsa glider&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Jane&lt;/td&gt;
&lt;td&gt;toy soldiers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sally&lt;/td&gt;
&lt;td&gt;harmonica&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;null&lt;/td&gt;
&lt;td&gt;baseball cards&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;null&lt;/td&gt;
&lt;td&gt;tinker toys&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;null&lt;/td&gt;
&lt;td&gt;etch-a-sketch&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;null&lt;/td&gt;
&lt;td&gt;slinky&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;pre class=&quot;n1ql&quot;&gt;&lt;code&gt;SELECT g.girl, t.toy FROM girls g 
LEFT OUTER JOIN toys t 
    ON g.toy_id = t.toy_id;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;자신을 참조하는 참조키 (OUTER, INNER, ...)&lt;/h3&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;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;셀프 조인 (SELF JOIN)&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&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;/ul&gt;
&lt;/li&gt;
&lt;li&gt;SELF JOIN 을 통해서 하나의 테이블로 같은 정보를 가진 테이블이 두 개 있는 것처럼 쿼리를 보낼 수 있다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;SELECT c1.name, c2.name AS boss FROM clown_info c1 INNER JOIN clown_info c2 ON c1.boss_id = c2.id;&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;UNION&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;두 개 이상의 테이블을 묶는 방법으로 유니온을 쓴다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;유니온은 SELECT 의 열 리스트를 바탕으로 두 개 이상 쿼리의 결과를 하나의 테이블로 합침&lt;/li&gt;
&lt;li&gt;유니온의 결과를 각 SELECT 의 값들이 &lt;code&gt;겹쳐진&lt;/code&gt; 결과라고 보면 됨 (&lt;code&gt;합쳐진&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;ORDER BY 는 마지막에 1개만 받을 수 있음 (여러 셀렉문의 결과를 합친 후 결과를 만들어 내기 때문에)&lt;/li&gt;
&lt;li&gt;각 SELECT 문의 열 수는 같아야 함&lt;/li&gt;
&lt;li&gt;각 SELECT 문에 표현식과 집계 함수도 같아야 함&lt;/li&gt;
&lt;li&gt;순서는 무관함&lt;/li&gt;
&lt;li&gt;유니온 결과에서 중복값은 하나로 나오는 것이 디폴트&lt;/li&gt;
&lt;li&gt;열의 데이터 타입은 &lt;code&gt;같거나&lt;/code&gt; 서로 &lt;code&gt;변환 가능한 값&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;특별한 이유로 중복을 보고 싶으면 &lt;code&gt;UNION ALL&lt;/code&gt; 을 사용하면 됨&lt;/li&gt;
&lt;li&gt;&lt;code&gt;SELECT title FROM job_current UNION SELECT title FROM job_desired UNION SELECT title FROM job_listings ORDER BY title;&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;UNION 으로 테이블 만들기 (CREATE TABLE AS)&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;유니온으로 반환되는 데이터 타입이 무엇인지 알기 쉽지 않음,
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;CREATE TABLE AS 문으로 유니온 결과를 테이블로 만들고 살펴본다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;CREATE TABLE my_union AS SELECT title FROM job_current UNION SELECT title FROM job_desired UNION SELECT title FROM job_listings ORDER BY title;&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;INTERSECT 와 EXCEPT&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&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;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;n1ql&quot;&gt;&lt;code&gt;-- 앞 뒤 테이블 모두에 있는 직업이름들만 나옴  
SELECT title FROM job_current  
INTERSECT  
SELECT title FROM job_desired;

-- 먼저 나온 테이블의 직업이름 중, 뒤의 테이블에 없는 직업이름들만 나옴  
SELECT title FROM job_current  
EXCEPT  
SELECT title FROM job_desired;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;서브쿼리를 조인으로 바꾼다.&lt;/h3&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;/li&gt;
&lt;li&gt;조인은 SELECT 에 only, 서브쿼리는 CRUD 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;n1ql&quot;&gt;&lt;code&gt;-- subquery
SELECT mc.first_name 
     , mc.last_name 
     , mc.phone
     , jc.title
  FROM job_current AS jc
NATURAL JOIN my_contacts AS mc
WHERE jc.title IN (SELECT title FROM job_listings);

-- join (subquery 를 포함한 WHERE 절은 내부조인으로 대체 가능함)
SELECT mc.first_name, mc.last_name, mc.phone, jc.title
FROM job_current AS jc
INNER JOIN my_contacts AS mc
    ON jc.contact_id = mc.contact_id
INNER JOIN job_listings AS jl
    ON jc.title = jl.title;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;셀프조인을 서브쿼리로 바꾼다. (ex)&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&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;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;-- inner join  
SELECT c1.name, c2.name AS boss  
FROM clown_info c1  
INNER JOIN clown_info c2  
ON c1.boss_id = c2.id;

-- subquery  
SELECT c1.name,  
(SELECT name FROM clown_info WHERE c1.boss_id = id) AS boss  
FROM clown_info AS c1;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;11. 제약사항, 뷰, 트랜잭션&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사람들이 잘못된 데이터를 입력하지 못하도록, 유저에 따라 일부만을 볼 수 있게, 사람들이 데이터를 동시에 입력할 때 엉키지 않도록 할 방법이 필요함&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;트랜잭션: 하나의 단위로 함께 수행되는 쿼리의 집합, 방해없이 모두 수행될 수 없으면 아무것도 수행될 수 없음
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;START TRANSACTION; COMMIT; ROLLBACK;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;VIEW 뷰: 쿼리의 결과를 테이블로 다룰 때, 뷰를 사용. 복잡한 쿼리를 간단한 쿼리로 바꿀 떄 좋음
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;업데이트 가능한 뷰: 뷰와 관련 테이블의 데이터를 변경할 수 있는 뷰. 관련 테이블들의 NOT NULL 인 열들만을 포함할 때 가능&lt;/li&gt;
&lt;li&gt;업데이트 불가능한 뷰: 뷰와 관련된 테이블에 데이터를 INSERT 하거나 UPDATE 하는 데 이용할 수 없는 뷰&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;CHECK 제약조건: 특정 값들만이 테이블에 추가되고 변경되게 한다.&lt;/li&gt;
&lt;li&gt;CHECK OPTION: 업데이트 가능한 뷰에 대한 INSERT 와 UPDATE 가 뷰의 WHERE 절을 만족하게 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;제약조건 (CONSTRAINT)&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;NOT NULL, PRIMARY KEY, FOREIGN KEY, UNIQUE&lt;/li&gt;
&lt;li&gt;+CHECK (넣으려는 값이 체크 조건에 맞지 않으면 에러가 발생함)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;MySQL 에서는 체크가 데이터의 무결성을 강제하지 않음: 호환성을 위해 체크 제약조건을 사용해서 테이블을 만들 수 있지만 효과가 없음
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;8.0.16 부터 지원됨&lt;/li&gt;
&lt;li&gt;VIEW 를 만들어서 WITH CHECK OPTION 으로 제약조건 흉내낼 수 있음&lt;/li&gt;
&lt;li&gt;BEFORE INSERT, BEFORE UPDATE 의 trigger 를 만들 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;체크 조건으로는 WHERE 절에 사용되는 조건들(AND,OR,IN,NOT,BETWEEN 등) 사용 가능함. 단, 서브쿼리는 사용할 수 없음.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;-- 신규 제작 테이블
CREATE TABLE piggy_bank
(
    id INT AUTO_INCREMENT NOT NULL PRIMARY KEY,
    coin CHAR(1) CHECK (coin IN ('P', 'N', 'D', 'Q'))
);

-- 기존 테이블 수정
ALTER TABLE my_contacts
ADD CONSTRAINT CHECK gender IN ('M', 'F');&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;뷰 (VIEW)&lt;/h3&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;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;-- VIEW 만들기  
CREATE VIEW web_designers AS  
SELECT mc.first_name, mc.last_name, mc.phone, mc.email  
FROM my_contacts AS mc  
NATURAL JOIN job_desired jd  
WHERE jd.title = 'Web Designer';

-- VIEW 확인 (뷰를 테이블처럼 다룸)  
SELECT * FROM web_designers;

-- 동작 방식  
SELECT * FROM  
(  
    SELECT mc.first_name, mc.last_name, mc.phone, mc.email  
    FROM my_contacts mc  
    NATURAL JOIN job_desired jd  
    WHERE jd.title = 'Web Designer'  
) AS web_designers;&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;FROM 절에는 테이블이 나와야 함 (AS web_designers 가 있는 이유)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;SELECT 문이 가상테이블을 반환하기는 하지만, alias(별명) 없이는 SQL 이 접근할 방법이 없음&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;뷰 란 무엇인가?&lt;/h4&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;가상테이블: 테이블처럼 행동하고, 테이블에서 할 수 있는 조작을 똑같이 수행 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;데이터베이스 내에 존재하지 않음 (VIEW 사용 시 생성 후 지워짐)&lt;/li&gt;
&lt;li&gt;이름 있는 뷰는 지속되는 가상테이블&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;뷰가 데이터베이스에서 유용한 이유&lt;/h4&gt;
&lt;ol 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;/li&gt;
&lt;li&gt;사용자에게 필요없는 정보를 숨기는 뷰를 만들 수 있음 (민감한 정보를 숨기면서 필요한 정보만을 볼 수 있게 함)&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;뷰에 INSERT, UPDATE, DELETE 하기 (변경 가능한/불가능한 VIEW)&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;뷰에 SELECT 뿐 아니라 UPDATE, INSERT, DELETE 도 가능함
&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 이어야 함 (뷰를 사용해서 INSERT 할 때, 값이 있어야 하는 모든 열에 값이 있는 것을 확신함)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;변경 불가능한 뷰 (업데이트가 불가능한 뷰) 는 뷰가 NOT NULL 이 아닌 열을 포함하는 경우
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;업데이트가 불가능한 뷰에는 생성과 삭제 말고 SELECT 만 할 수 있음&lt;/li&gt;
&lt;li&gt;집계연산자(SUM, COUNT, AVG 등), 연산자(BETWEEN, HAVING, IN, NOT IN 등) 이 포함된 뷰는 업데이트 불가함&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;뷰가 집계값(SUM, COUNT, AVG 등)을 사용하면 데이터 변경에 뷰를 사용할 수 없음&lt;/li&gt;
&lt;li&gt;뷰에 GROUP BY, DISTINCT, HAVING 이 포함되어 있으면 데이터를 변경 할 수 없음&lt;/li&gt;
&lt;li&gt;MySQL 에서 데이터 무결성을 강제하는 등의 유용한 사용례가 있긴 하지만, 일반적으로 INSERT/UPDATE/DELETE 는 테이블을 직접 이용하는 것이 더 쉬움
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;뷰에 INSERT 하는 것이 편한 경우로, 뷰가 열 하나를 나타내고 그 외의 열들이 NULL 이나 기본값이 할당되어야 하는 경우&lt;/li&gt;
&lt;li&gt;뷰에 WHERE 절을 추가하여 INSERT 데이터를 제한할 수 있음 (CHECK 제약조건 흉내)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;WITH CHECK OPTION 을 사용한 뷰(VIEW)&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;CHECK OPTION 이 있는 뷰는 데이터베이스 시스템에 INSERT/UPDATE 를 사용하는 문장을 확인해서 뷰의 WHERE 절에 허용되는지 확인한다.&lt;/li&gt;
&lt;li&gt;MySQL 에서 CHECK OPTION 으로 CHECK 제약조건을 흉내낼 수 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;CREATE VIEW pb_quarters AS SELECT * FROM piggy_bank WHERE coin = 'Q';
CREATE VIEW pb_dimes AS SELECT * FROM piggy_bank WHERE coin = 'D' WITH CHECK OPTION;

-- 조건에 맞지 않지만 들어감
INSERT INTO pb_quarters VALUES ('','D', 1942);

-- 조건에 맞지 않아서 들어가지 않음
INSERT INTO pb_dimes VALUES ('','Q', 1942);&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;-- 성별 란에 'M' or 'F' 입력을 강제하는 my_contacts VIEW
CREATE VIEW my_contacts AS
(
    SELECT * FROM my_contacts
    WHERE gender = 'M' OR gender = 'F'
);&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;VIEW 삭제&lt;/h4&gt;
&lt;pre class=&quot;n1ql&quot;&gt;&lt;code&gt;DROP VIEW pb_dimes;&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CHECK 제약조건과 VIEW 는, 여러 사람이 데이터베이스를 이용할 때 관리, 통제하는데 도움이 됨&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;트랜젝션&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;한 단위의 일을 수행하는 일련의 SQL 문&lt;/li&gt;
&lt;li&gt;트랜젝션 동안 모든 단계가 방해없이 완료될 수 없다면 어떤 것도 완료되지 않는다.&lt;/li&gt;
&lt;li&gt;MySQL 의 경우, InnoDB 와 BDB 저장엔진(Storage Engine)들이 트랜잭션이 가능한 두가지 방법임ACID (트랜젝션의 특징)&lt;/li&gt;
&lt;/ul&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Atomic 원자성: 트랜젝션을 구성하는 모든 명령이 실행되거나 어떠한 명령도 실행되지 않아야 함 (일부만 수행 X)&lt;/li&gt;
&lt;li&gt;Consistency 일관성: 트랜젝션이 끝난 후 데이터베이스는 일관성을 유지해야 함 (시작과 끝이 맞아야 함)&lt;/li&gt;
&lt;li&gt;Isolation 독립성: 모든 트랜젝션은 동시에 일어나는 다른 트랜잭션과 상관없이 일관된 뷰를 갖는다.&lt;/li&gt;
&lt;li&gt;Durability 지속성: 트랜잭션이 끝난 후, 데이터베이스는 데이터를 정확히 저장하고 이상 상황으로부터 데이터를 보호한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;START TRANSACTION;
SELECT * FROM piggy_bank;
UPDATE piggy_bank SET coin = 'Q' where coin = 'P';
SELECT * FROM piggy_bank;

ROLLBACK; -- COMMIT;
-- 변경 된 것 원 상태로 복구 (COMMIT; 의 경우는 변경된 내용 그대로 볼 수 있음)
SELECT * FROM piggy_bank;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;12. 보안&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;데이터베이스 사용자들에게 &lt;code&gt;사용자 계정&lt;/code&gt;을 주어서, 데이터베이스에 할 수 있는 일과 할 수 없는 일을 제어한다.&lt;/li&gt;
&lt;li&gt;루트 계정 보호는 꼭 필요함&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;단어정리&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;CREATE USER: 데이터베이스 시스템에 사용자 계정을 만들고 암호를 부여함&lt;/li&gt;
&lt;li&gt;GRANT: 사용자에게 권한을 부여하여, 사용자가 테이블과 열에 무엇을 할 수 있는지 통제 가능함&lt;/li&gt;
&lt;li&gt;REVOKE: 사용자로부터 권한을 없앰&lt;/li&gt;
&lt;li&gt;WITH GRANT OPTION: 사용자가 자신이 가진 권한과 같은 권한을 다른 사람에게 줄 수 있음&lt;/li&gt;
&lt;li&gt;ROLE: 역할을 가진 유저가 자신의 역할을 다른 사람에게 부여할 수 있음&lt;/li&gt;
&lt;li&gt;WITH ADMIN OPTION: 권한의 집합, 역할이 있어 특정 권한들을 묶어 여러사람에게 할당할 수 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;root 사용자에게 암호를 부여&lt;/h3&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;SET PASSWORD FOR 'root'@'localhost' = PASSWORD('password');

-- localhost: 사용하는 컴퓨터가 데이터베이스가 설치된 컴퓨터와 같은 컴퓨터
-- 원격접속의 경우는, localhost 대신 hostname 을 사용할 수 있음
SET PASSWORD FOR 'root'@'kumquats.oreilly.com' = PASSWORD('password');&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;사용자 추가&lt;/h3&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;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;GRANT SELECT ON tableName TO elsie;&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;code&gt;CREATE USER elsie IDENTIFIED BY 'password';&lt;/code&gt;&lt;/li&gt;
&lt;li&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;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;GRANT&lt;/h3&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;GRANT INSERT ON tableName TO userName;
GRANT DELETE ON tableName TO userName;

-- 삭제 권한을 주는데, 다른 사람에게 해당 권한을 줄 권한도 부여한다.  
GRANT DELETE ON tableName TO userName WITH GRANT OPTION;

-- 해당 테이블의 해당 열만을 SELECT 할 권한을 부여한다.  
GRANT SELECT(columName) ON tableName TO userName;

GRANT SELECT, INSERT ON tableName TO userName;

-- CRUD 전체 권한 부여  
GRANT ALL ON tableName TO userName;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;REVOKE&lt;/h3&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;/ul&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;REVOKE SELECT ON tableName FROM userName;

-- 해당 유저의 권한은 그대로이고, 권한을 부여할 수 있는 권한만 제거한다.  
REVOKE GRANT OPTION ON DELETE  
ON table_name  
FROM userName;&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;CASCADE (종속, 작은폭포) / RESTRICT (제한하다)&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;CASCADE: 권한 삭제 시에, 권한을 줄 수 있는 권한이 있는 유저가 주었던 권한까지 싹 다 제거하는 방법&lt;/li&gt;
&lt;li&gt;RESTRICT: 권한 삭제 시에, 원하는 유저의 권한만 없애고 다른 유저에는 영향을 주지 않는 방법 (에러남)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;REVOKE DELETE ON tableName FROM userName CASCADE; REVOKE DELETE ON tableName FROM userName RESTRICT;&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;열의 이름을 지정하는 GRANT 문의 경우에 INSERT 권한만 부여했다면?
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;의미있는 행을 추가 못하므로 쓸데없음 (테이블에 열이 1개면 가능)&lt;/li&gt;
&lt;li&gt;열에 대해 권한을 주는 것은 SELECT 문과 관련 없다면 보통 쓸모없음&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;모든 데이터베이스의 모든 테이블에 SELECT 권한을 준다면?&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GRANT SELECT ON _._ TO userName;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;REVOKE 의 기본은? - CASCADE&lt;/li&gt;
&lt;li&gt;사용자에게 없는 권한을 REVOKE 하면? - 권한 없다는 에러남&lt;/li&gt;
&lt;li&gt;테이블, 열 외에 GRANT 나 REVOKE 를 사용 가능한 것은? - VIEW 가 업데이트 가능하면, 테이블에서 사용하는 것과 같은 방식을 뷰에도 사용 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;ROLE&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&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;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;역할을 만든다.&lt;/li&gt;
&lt;li&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;mysql 에는 역할 기능이 없음?!&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;8.0 부터 추가된 것으로 보임&lt;br /&gt;CREATE ROLE roleName;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;만든 역할에 권한을 부여한다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GRANT SELECT, INSERT ON tableName TO roleName;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;권한을 부여한 역할을 사용자에게 부여한다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GRANT roleName TO userName;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;역할을 취소한다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;REVOKE roleName FROM userName;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;역할을 버린다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;DROP ROLE roleName;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;데이터베이스의 모든 테이블에 권한을 부여하려면?&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GRANT SELECT, INSERT ON databaseName.* TO userName;&lt;/code&gt;&lt;/li&gt;
&lt;li&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;/ul&gt;
&lt;/li&gt;
&lt;li&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;/li&gt;
&lt;li&gt;&lt;b&gt;거절하는 권한과 허용하는 권한이 충돌하면, 거절하는 권한이 우선임&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;WITH ADMIN OPTION&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;위의 WITH GRANT OPTION 처럼, 역할도 해당 역할을 가진 사용자가 다른 사용자에게 역할의 권한을 줄 수 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;-- 역할 권한을 줄 권한까지 부여한다.  
GRANT roleName TO userName WITH ADMIN OPTION;  &lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;역할의 REVOKE 또한 동일하게 CASCADE / RESTRICT 키워드를 갖고 있음
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;CASCADE: 연결된 모든 사용자까지 권한 제거&lt;/li&gt;
&lt;li&gt;RESTRICT: 연결된 사용자가 있으면 에러&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;한 문장에서 유저를 만들고 권한을 주는 방법&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GRANT SELECT ON tableName TO userName IDENTIFIED BY 'password';&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Programming/Database</category>
      <category>HeadFirst</category>
      <category>headfirst sql</category>
      <category>개발 책</category>
      <category>헤드퍼스트</category>
      <category>헤드퍼스트 SQL</category>
      <author>Ginjoe</author>
      <guid isPermaLink="true">https://itdar.tistory.com/413</guid>
      <comments>https://itdar.tistory.com/413#entry413comment</comments>
      <pubDate>Thu, 17 Feb 2022 20:49:48 +0900</pubDate>
    </item>
    <item>
      <title>Mock 객체 사용 개념과 예제</title>
      <link>https://itdar.tistory.com/411</link>
      <description>&lt;h1&gt;Java, Mockito, Mock... example.&lt;/h1&gt;
&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

class TestExample {

    class Foo {
        Bar bar;

        public Foo(Bar bar) {
            this.bar = bar;
        }

        String execute() {
            return bar.execute() + &amp;quot;Foo:&amp;quot;;
        }
    }

    class Bar {
        String execute() {
            return &amp;quot;Bar:&amp;quot;;
        }
    }

    @Test
    void MockTest() {
        // 1. 둘다 실제
        Foo realFoo = new Foo(new Bar());
        System.out.println(&amp;quot;realFoo.execute() = &amp;quot; + realFoo.execute());

        // 2. Foo mock
        Foo mockFoo = mock(Foo.class);
        when(mockFoo.execute()).thenReturn(&amp;quot;Bar:&amp;quot; + &amp;quot;Foo:&amp;quot;);

        // 3. Foo 실제, &amp;lt;- Bar mock
        Bar mockBar = mock(Bar.class);
        when(mockBar.execute()).thenReturn(&amp;quot;Bar:&amp;quot;);
        Foo innerMockFoo = new Foo(mockBar);

        assertThat(realFoo.execute()).isEqualTo(mockFoo.execute());
        assertThat(realFoo.execute()).isEqualTo(innerMockFoo.execute());
    }

}
&lt;/code&gt;&lt;/pre&gt;</description>
      <category>Programming</category>
      <category>mock</category>
      <category>mockito</category>
      <author>Ginjoe</author>
      <guid isPermaLink="true">https://itdar.tistory.com/411</guid>
      <comments>https://itdar.tistory.com/411#entry411comment</comments>
      <pubDate>Wed, 26 Jan 2022 01:10:17 +0900</pubDate>
    </item>
    <item>
      <title>[LeetCode] 130. Surrounded Regions (BFS, DFS, TDD, 코테, 릿코드, tech interview)</title>
      <link>https://itdar.tistory.com/407</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;682&quot; data-origin-height=&quot;125&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/AE4mq/btrpJQet9uc/FxqWloRUEEzcu7xGZWxeNk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/AE4mq/btrpJQet9uc/FxqWloRUEEzcu7xGZWxeNk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/AE4mq/btrpJQet9uc/FxqWloRUEEzcu7xGZWxeNk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FAE4mq%2FbtrpJQet9uc%2FFxqWloRUEEzcu7xGZWxeNk%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;682&quot; height=&quot;125&quot; data-origin-width=&quot;682&quot; data-origin-height=&quot;125&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;간만에 미디움 풀었더니 빡셌음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;퍼포먼스는 딱히.. 리팩토링 하느라 테스트코드만 매우 꼼꼼하게 작성하게 됨&lt;/p&gt;
&lt;p 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;테스트코드&lt;/h2&gt;
&lt;pre id=&quot;code_1641217940795&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import static org.assertj.core.api.Assertions.assertThat;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

class LeetCode_0130_SurroundedRegionsTest {

    @DisplayName(&quot;BFS, leetcode 130. Surrounded Regions Test 1.&quot;)
    @Test
    void surroundedRegionsTest_1() {
        LeetCode_0130_SurroundedRegions test = new LeetCode_0130_SurroundedRegions();

        char[][] board = new char[][]
            {{'X','X','X','X'},
                {'X','O','O','X'},
                {'X','X','O','X'},
                {'X','O','X','X'}};

        test.solve(board);

        char[][] target = new char[][]
            {{'X','X','X','X'},
                {'X','X','X','X'},
                {'X','X','X','X'},
                {'X','O','X','X'}};

        Assertions.assertArrayEquals(board, target);
    }

    @DisplayName(&quot;BFS, leetcode 130. Surrounded Regions Test 2.&quot;)
    @Test
    void surroundedRegionsTest_2() {
        LeetCode_0130_SurroundedRegions test = new LeetCode_0130_SurroundedRegions();

        char[][] board = new char[][]
            {{'X'}};

        test.solve(board);

        char[][] target = new char[][]
            {{'X'}};

        for (int i = 0; i &amp;lt; target.length; ++i) {
            for (int j = 0; j &amp;lt; target[0].length; ++j) {
                assertThat(target[i][j]).isEqualTo(board[i][j]);
            }
        }
    }

    @DisplayName(&quot;BFS, leetcode 130. Surrounded Regions Test 3.&quot;)
    @Test
    void surroundedRegionsTest_3() {
        LeetCode_0130_SurroundedRegions test = new LeetCode_0130_SurroundedRegions();

        char[][] board = new char[][]
            {   {'O','O','X','X'},
                {'X','X','O','X'},
                {'O','O','X','X'},
                {'X','O','X','O'}};

        test.solve(board);

        char[][] target = new char[][]
            {   {'O','O','X','X'},
                {'X','X','X','X'},
                {'O','O','X','X'},
                {'X','O','X','O'}};

        Assertions.assertArrayEquals(board, target);
    }

    @DisplayName(&quot;BFS, leetcode 130. Surrounded Regions Test 4.&quot;)
    @Test
    void surroundedRegionsTest_4() {
        LeetCode_0130_SurroundedRegions test = new LeetCode_0130_SurroundedRegions();

        char[][] board = new char[][]
            {   {'O','X','X','O','X'},
                {'X','O','O','X','O'},
                {'X','O','X','O','X'},
                {'O','X','O','O','O'},
                {'X','X','O','X','O'}};

        test.solve(board);

        char[][] target = new char[][]
            {   {'O','X','X','O','X'},
                {'X','X','X','X','O'},
                {'X','X','X','O','X'},
                {'O','X','O','O','O'},
                {'X','X','O','X','O'}};

        Assertions.assertArrayEquals(board, target);
    }

    @DisplayName(&quot;BFS, leetcode 130. Surrounded Regions Test 5.&quot;)
    @Test
    void surroundedRegionsTest_5() {
        LeetCode_0130_SurroundedRegions test = new LeetCode_0130_SurroundedRegions();

        char[][] board = new char[][]
            {   {'O','X','O','O','O','O','O','O','O'},
                {'O','O','O','X','O','O','O','O','X'},
                {'O','X','O','X','O','O','O','O','X'},
                {'O','O','O','O','X','O','O','O','O'},
                {'X','O','O','O','O','O','O','O','X'},
                {'X','X','O','O','X','O','X','O','X'},
                {'O','O','O','X','O','O','O','O','O'},
                {'O','O','O','X','O','O','O','O','O'},
                {'O','O','O','O','O','X','X','O','O'}};

        test.solve(board);

        char[][] target = new char[][]
            {   {'O','X','O','O','O','O','O','O','O'},
                {'O','O','O','X','O','O','O','O','X'},
                {'O','X','O','X','O','O','O','O','X'},
                {'O','O','O','O','X','O','O','O','O'},
                {'X','O','O','O','O','O','O','O','X'},
                {'X','X','O','O','X','O','X','O','X'},
                {'O','O','O','X','O','O','O','O','O'},
                {'O','O','O','X','O','O','O','O','O'},
                {'O','O','O','O','O','X','X','O','O'}};

        Assertions.assertArrayEquals(board, target);
    }

}&lt;/code&gt;&lt;/pre&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;pre id=&quot;code_1641217959437&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;

public class LeetCode_0130_SurroundedRegions {
    boolean[][] visited;

    int[] rotateX = {1,-1,0,0};
    int[] rotateY = {0,0,1,-1};

    Queue&amp;lt;Coords130&amp;gt; queue = new LinkedList&amp;lt;&amp;gt;();
    List&amp;lt;Coords130&amp;gt; coordsBuffer = new ArrayList&amp;lt;&amp;gt;();

    int height;
    int width;

    public void solve(char[][] board) {
        if (board.length &amp;lt; 2 || board[0].length &amp;lt; 2) {
            return;
        }

        height = board.length;
        width = board[0].length;
        visited = new boolean[height][width];

        bfsAllExceptOutside(board);

//        printForDebugging(board);
    }

    private void bfsAllExceptOutside(char[][] board) {
        for (int i = 1; i &amp;lt; height-1; ++i) {
            for (int j = 1; j &amp;lt; width-1; ++j) {
                if (board[i][j] != 'O') {
                    continue;
                }
                queue.add(new Coords130(i,j));
                bfs(board);
                clear();
            }
        }
    }

    private void bfs(char[][] board) {
        int x;
        int y;

        while (!queue.isEmpty()) {
            Coords130 block = queue.poll();
            x = block.x;
            y = block.y;

            if (isOutBound(x, y)) {
                break;
            }

            if (isDirtyConnection(x, y, board)) {
                rollback(board);
                break;
            }

            if (isInvalidBlock(x, y, board)) {
                continue;
            }

            coordsBuffer.add(new Coords130(x, y));

            board[x][y] = 'X';
            visited[x][y] = true;

            for (int i = 0; i &amp;lt; 4; ++i) {
                x = rotateX[i] + block.x;
                y = rotateY[i] + block.y;

                queue.add(new Coords130(x, y));
            }
        }
    }

    private boolean isInvalidBlock(int x, int y, char[][] board) {
        return visited[x][y]
            || board[x][y] == 'X'
            || x &amp;lt; 1
            || y &amp;lt; 1
            || x &amp;gt; height-2
            || y &amp;gt; width-2;
    }

    private boolean isDirtyConnection(int x, int y, char[][] board) {
        return (x &amp;lt; 1 || y &amp;lt; 1 || x &amp;gt; height-2 || y &amp;gt; width-2)
            &amp;amp;&amp;amp; board[x][y] == 'O';
    }

    private boolean isOutBound(int x, int y) {
        return x &amp;lt; 0 || y &amp;lt; 0 || x &amp;gt; height-1 || y &amp;gt; width-1;
    }

    private void rollback(char[][] board) {
        for (Coords130 coords130 : coordsBuffer) {
            board[coords130.x][coords130.y] = 'O';
            visited[coords130.x][coords130.y] = false;
        }
        queue.clear();
        coordsBuffer.clear();
    }

    private void clear() {
        queue.clear();
        coordsBuffer.clear();
    }

    static class Coords130 {
        int x;
        int y;

        public Coords130(int x, int y) {
            this.x = x;
            this.y = y;
        }
    }

    private void printForDebugging(char[][] board) {
        for (char[] chars : board) {
            for (char aChar : chars) {
                System.out.print(aChar + &quot; &quot;);
            }
            System.out.println(&quot;&quot;);
        }
        System.out.println(&quot;\n&quot;);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Algorithm/Leet Code</category>
      <category>Algorithm</category>
      <category>BFS</category>
      <category>dfs</category>
      <category>leetcode</category>
      <category>TDD</category>
      <category>깊이우선탐색</category>
      <category>너비우선탐색</category>
      <category>릿코드</category>
      <category>문제풀이</category>
      <author>Ginjoe</author>
      <guid isPermaLink="true">https://itdar.tistory.com/407</guid>
      <comments>https://itdar.tistory.com/407#entry407comment</comments>
      <pubDate>Mon, 3 Jan 2022 22:53:55 +0900</pubDate>
    </item>
    <item>
      <title>[LeetCode] 202. Happy Number (TDD, 코테, 릿코드, tech interview)</title>
      <link>https://itdar.tistory.com/406</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;653&quot; data-origin-height=&quot;126&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dHSkyi/btrpiHvrUkw/f6GVOvLyKlZ7hIv9txl2k1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dHSkyi/btrpiHvrUkw/f6GVOvLyKlZ7hIv9txl2k1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dHSkyi/btrpiHvrUkw/f6GVOvLyKlZ7hIv9txl2k1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdHSkyi%2FbtrpiHvrUkw%2Ff6GVOvLyKlZ7hIv9txl2k1%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;653&quot; height=&quot;126&quot; data-origin-width=&quot;653&quot; data-origin-height=&quot;126&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; letter-spacing: 0px;&quot;&gt;간만에 문제풀이&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 테스트코드&lt;/p&gt;
&lt;pre id=&quot;code_1640788266263&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import static org.assertj.core.api.Assertions.assertThat;

import org.junit.jupiter.api.Test;

public class LeetCode_0202_HappyNumberTest {

    @Test
    public void isHappyTest() {
        LeetCode_0202_HappyNumber test = new LeetCode_0202_HappyNumber();

        assertThat(test.isHappy(19)).isEqualTo(true);
        assertThat(test.isHappy(2)).isEqualTo(false);
    }

}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 풀이코드&lt;/p&gt;
&lt;pre id=&quot;code_1640788279191&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import java.util.HashSet;
import java.util.Set;

public class LeetCode_0202_HappyNumber {

    boolean isHappy(int n) {
        int sumOfSquaresOfDigits = n;

        Set&amp;lt;Integer&amp;gt; set = new HashSet&amp;lt;&amp;gt;();

        while (sumOfSquaresOfDigits != 1 &amp;amp;&amp;amp; !set.contains(sumOfSquaresOfDigits)) {
            set.add(sumOfSquaresOfDigits);

            sumOfSquaresOfDigits = getSumOfSquaresOfDigits(sumOfSquaresOfDigits);
        }

        return (sumOfSquaresOfDigits == 1);
    }

    private int getSumOfSquaresOfDigits(int number) {
        int sum = 0;

        while (number &amp;gt; 0) {
            sum += Math.pow((number % 10), 2);
            number /= 10;
        }

        return sum;
    }

}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://itdar.tistory.com/404&quot;&gt;2021.12.28 - [Programming] - Effective Java 2/E, 이펙티브 자바 책 핵심요약&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1640788335140&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;Effective Java 2/E, 이펙티브 자바 책 핵심요약&quot; data-og-description=&quot;전체 목차 Github https://github.com/itdar/TIL/blob/main/books/effective_java/effective_java.md GitHub - itdar/TIL: Today I Learned Today I Learned. Contribute to itdar/TIL development by creating an..&quot; data-og-host=&quot;itdar.tistory.com&quot; data-og-source-url=&quot;https://itdar.tistory.com/404&quot; data-og-url=&quot;https://itdar.tistory.com/404&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/zsx6x/hyMS0sourZ/5KSB69muoAvUdccikyVkv1/img.png?width=495&amp;amp;height=649&amp;amp;face=0_0_495_649,https://scrap.kakaocdn.net/dn/bwUOMQ/hyMTCXJwhg/yeKLMZxk3mP7V7bqO7OoN0/img.png?width=495&amp;amp;height=649&amp;amp;face=0_0_495_649,https://scrap.kakaocdn.net/dn/zQeKG/hyMTIXWiCp/hWbRfaQGCUAfAZ5u5s6Fok/img.png?width=495&amp;amp;height=649&amp;amp;face=0_0_495_649&quot;&gt;&lt;a href=&quot;https://itdar.tistory.com/404&quot; data-source-url=&quot;https://itdar.tistory.com/404&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/zsx6x/hyMS0sourZ/5KSB69muoAvUdccikyVkv1/img.png?width=495&amp;amp;height=649&amp;amp;face=0_0_495_649,https://scrap.kakaocdn.net/dn/bwUOMQ/hyMTCXJwhg/yeKLMZxk3mP7V7bqO7OoN0/img.png?width=495&amp;amp;height=649&amp;amp;face=0_0_495_649,https://scrap.kakaocdn.net/dn/zQeKG/hyMTIXWiCp/hWbRfaQGCUAfAZ5u5s6Fok/img.png?width=495&amp;amp;height=649&amp;amp;face=0_0_495_649');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Effective Java 2/E, 이펙티브 자바 책 핵심요약&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;전체 목차 Github https://github.com/itdar/TIL/blob/main/books/effective_java/effective_java.md GitHub - itdar/TIL: Today I Learned Today I Learned. Contribute to itdar/TIL development by creating an..&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;itdar.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;</description>
      <category>Algorithm/Leet Code</category>
      <category>happy number</category>
      <category>leetcode</category>
      <category>TDD</category>
      <category>릿코드</category>
      <category>문제풀이</category>
      <category>알고리즘</category>
      <author>Ginjoe</author>
      <guid isPermaLink="true">https://itdar.tistory.com/406</guid>
      <comments>https://itdar.tistory.com/406#entry406comment</comments>
      <pubDate>Wed, 29 Dec 2021 23:32:21 +0900</pubDate>
    </item>
    <item>
      <title>규칙9. equals를 재정의할 때는 반드시 hashCode도 재정의하라 / Effective Java 2/E, 이펙티브 자바</title>
      <link>https://itdar.tistory.com/405</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;책 전체의 내용은 아래 링크&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://itdar.tistory.com/404&quot;&gt;https://itdar.tistory.com/404&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1640697427395&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;Effective Java 2/E, 이펙티브 자바 책 전체&quot; data-og-description=&quot;Effective Java 2/E 서론 객체의 생성과 삭제 모든 객체의 공통 메서드 규칙9. equals를 재정의할 때는 반드시 hashCode도 재정의하라 클래스와 인터페이스 규칙13. 클래스와 멤버의 접근 권한은 최소화하&quot; data-og-host=&quot;itdar.tistory.com&quot; data-og-source-url=&quot;https://itdar.tistory.com/404&quot; data-og-url=&quot;https://itdar.tistory.com/404&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bSVgZ5/hyMSUEwDVX/ti0mJvyXuD5mi0dLkipnk0/img.png?width=495&amp;amp;height=649&amp;amp;face=0_0_495_649,https://scrap.kakaocdn.net/dn/ldrn9/hyMS1DD6hb/Zxb8XBQStX1Y93BtWDufek/img.png?width=495&amp;amp;height=649&amp;amp;face=0_0_495_649,https://scrap.kakaocdn.net/dn/bHaOUs/hyMS2igxjO/Ga106PIRlfWYoTqMG2L2jk/img.png?width=495&amp;amp;height=649&amp;amp;face=0_0_495_649&quot;&gt;&lt;a href=&quot;https://itdar.tistory.com/404&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://itdar.tistory.com/404&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bSVgZ5/hyMSUEwDVX/ti0mJvyXuD5mi0dLkipnk0/img.png?width=495&amp;amp;height=649&amp;amp;face=0_0_495_649,https://scrap.kakaocdn.net/dn/ldrn9/hyMS1DD6hb/Zxb8XBQStX1Y93BtWDufek/img.png?width=495&amp;amp;height=649&amp;amp;face=0_0_495_649,https://scrap.kakaocdn.net/dn/bHaOUs/hyMS2igxjO/Ga106PIRlfWYoTqMG2L2jk/img.png?width=495&amp;amp;height=649&amp;amp;face=0_0_495_649');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Effective Java 2/E, 이펙티브 자바 책 전체&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Effective Java 2/E 서론 객체의 생성과 삭제 모든 객체의 공통 메서드 규칙9. equals를 재정의할 때는 반드시 hashCode도 재정의하라 클래스와 인터페이스 규칙13. 클래스와 멤버의 접근 권한은 최소화하&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;itdar.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;규칙9. equals를 재정의할 때는 반드시 hashCode도 재정의하라&lt;/h4&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;equals(Object) 메서드가 같다고 판정한 두 객체의 hashCode 값은 같아야 한다.&lt;/li&gt;
&lt;li&gt;equals(Object) 메서드가 다르다고 판정한 두 객체의 hashCode 값은 꼭 다를 필요는 없다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;그러나 서로 다른 hashCode 값이 나오면 해시테이블 성능이 향상될 수 있다.&lt;/li&gt;
&lt;li&gt;같은 값의 다른 객체의 경우, 다른 해시값을 가지면 성능이 향상 되는 경우.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;해시 함수는 다른 객체에는 다른 해시 코드를 반환하도록 해야 한다.&lt;/li&gt;
&lt;li&gt;hashCode 구현이 끝나면, 동치 관계의 객체 해시코드 값이 똑같이 계산되는지 확인한다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;객체의 동치 관계: (객체 == 객체)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;equals 계산에 쓰이지 않는 필드는 &lt;b&gt;반드시&lt;/b&gt; 제외해서 해시 함수를 만든다.&lt;/li&gt;
&lt;li&gt;해시코드 계산 비용이 높은 변경 불가능 클래스는 객체 안에 캐시해 둘 수 있다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;최초 호출까지 해시코드 초기화를 늦출 수도 있다. (lazy initialization)&amp;nbsp;&lt;/li&gt;
&lt;li class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;// lazy initialization
private volatile int hashCode;

@Override public int hashCode() {
    int result = hashCode;
    if (result == 0) {
        result = 17;
        result = 31 * result + field1;
        result = 31 * result + field2;
        hashCode = result;
    }
    return result;
}&lt;/code&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;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;/ul&gt;</description>
      <category>Programming</category>
      <category>Effective Java rule 9</category>
      <category>equals and hashCode</category>
      <category>Java</category>
      <category>이펙티브자바 규칙 9</category>
      <author>Ginjoe</author>
      <guid isPermaLink="true">https://itdar.tistory.com/405</guid>
      <comments>https://itdar.tistory.com/405#entry405comment</comments>
      <pubDate>Tue, 28 Dec 2021 22:20:59 +0900</pubDate>
    </item>
    <item>
      <title>Effective Java 2/E, 이펙티브 자바 책 핵심요약</title>
      <link>https://itdar.tistory.com/404</link>
      <description>&lt;p data-ke-size=&quot;size18&quot;&gt;전체 목차 Github&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/itdar/TIL/blob/main/books/effective_java/effective_java.md&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://github.com/itdar/TIL/blob/main/books/effective_java/effective_java.md&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1640698990373&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;GitHub - itdar/TIL: Today I Learned&quot; data-og-description=&quot;Today I Learned. Contribute to itdar/TIL development by creating an account on GitHub.&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/itdar/TIL/blob/main/books/effective_java/effective_java.md&quot; data-og-url=&quot;https://github.com/itdar/TIL&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/fKvYX/hyMSY1f5ZJ/Y2bckkaqF8YJjsuPTAHO31/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/itdar/TIL/blob/main/books/effective_java/effective_java.md&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/itdar/TIL/blob/main/books/effective_java/effective_java.md&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/fKvYX/hyMSY1f5ZJ/Y2bckkaqF8YJjsuPTAHO31/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;GitHub - itdar/TIL: Today I Learned&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Today I Learned. Contribute to itdar/TIL development by creating an account on GitHub.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;h1&gt;Effective Java 2/E&lt;/h1&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#1%EC%9E%A5.-%EC%84%9C%EB%A1%A0&quot;&gt;서론&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#2%EC%9E%A5.-%EA%B0%9D%EC%B2%B4%EC%9D%98-%EC%83%9D%EC%84%B1%EA%B3%BC-%EC%82%AD%EC%A0%9C&quot;&gt;객체의 생성과 삭제&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#3%EC%9E%A5.-%EB%AA%A8%EB%93%A0-%EA%B0%9D%EC%B2%B4%EC%9D%98-%EA%B3%B5%ED%86%B5-%EB%A9%94%EC%84%9C%EB%93%9C&quot;&gt;모든 객체의 공통 메서드&lt;/a&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#%EA%B7%9C%EC%B9%999.-equals%EB%A5%BC-%EC%9E%AC%EC%A0%95%EC%9D%98%ED%95%A0-%EB%95%8C%EB%8A%94-%EB%B0%98%EB%93%9C%EC%8B%9C-hashCode%EB%8F%84-%EC%9E%AC%EC%A0%95%EC%9D%98%ED%95%98%EB%9D%BC&quot;&gt;규칙9. equals를 재정의할 때는 반드시 hashCode도 재정의하라&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#4%EC%9E%A5.-%ED%81%B4%EB%9E%98%EC%8A%A4%EC%99%80-%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4&quot;&gt;클래스와 인터페이스&lt;/a&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#%EA%B7%9C%EC%B9%9913.-%ED%81%B4%EB%9E%98%EC%8A%A4%EC%99%80-%EB%A9%A4%EB%B2%84%EC%9D%98-%EC%A0%91%EA%B7%BC-%EA%B6%8C%ED%95%9C%EC%9D%80-%EC%B5%9C%EC%86%8C%ED%99%94%ED%95%98%EB%9D%BC&quot;&gt;규칙13. 클래스와 멤버의 접근 권한은 최소화하라&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#%EA%B7%9C%EC%B9%9914.-public-%ED%81%B4%EB%9E%98%EC%8A%A4-%EC%95%88%EC%97%90%EB%8A%94-public-%ED%95%84%EB%93%9C%EB%A5%BC-%EB%91%90%EC%A7%80-%EB%A7%90%EA%B3%A0-%EC%A0%91%EA%B7%BC%EC%9E%90-%EB%A9%94%EC%84%9C%EB%93%9C%EB%A5%BC-%EC%82%AC%EC%9A%A9%ED%95%98%EB%9D%BC&quot;&gt;규칙14. public 클래스 안에는 public 필드를 두지 말고 접근자 메서드를 사용하라&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#5%EC%9E%A5.-%EC%A0%9C%EB%84%A4%EB%A6%AD&quot;&gt;제네릭&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#6%EC%9E%A5.-%EC%97%B4%EA%B1%B0%ED%98%95(enum)%EA%B3%BC-%EC%96%B4%EB%85%B8%ED%85%8C%EC%9D%B4%EC%85%98&quot;&gt;열거형(enum)과 어노테이션&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#7%EC%9E%A5.-%EB%A9%94%EC%84%9C%EB%93%9C&quot;&gt;메서드&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#8%EC%9E%A5.-%EC%9D%BC%EB%B0%98%EC%A0%81%EC%9D%B8-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D-%EC%9B%90%EC%B9%99%EB%93%A4&quot;&gt;일반적인 프로그래밍 원칙들&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#9%EC%9E%A5.-%EC%98%88%EC%99%B8&quot;&gt;예외&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#10%EC%9E%A5.-%EB%B3%91%ED%96%89%EC%84%B1&quot;&gt;병행성&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#11%EC%9E%A5.-%EC%A7%81%EB%A0%AC%ED%99%94&quot;&gt;직렬화&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1장. 서론&lt;/h2&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2장. 객체의 생성과 삭제&lt;/h2&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3장. 모든 객체의 공통 메서드&lt;/h2&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;a href=&quot;https://itdar.tistory.com/405&quot;&gt;규칙9. equals를 재정의할 때는 반드시 hashCode도 재정의하라&lt;/a&gt;&lt;/h4&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;4장. 클래스와 인터페이스&lt;/h2&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;규칙13. 클래스와 멤버의 접근 권한은 최소화하라&lt;/h4&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;규칙14. public 클래스 안에는 public 필드를 두지 말고 접근자 메서드를 사용하라&lt;/h4&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;5장. 제네릭&lt;/h2&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;6장. 열거형(enum)과 어노테이션&lt;/h2&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;7장. 메서드&lt;/h2&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;8장. 일반적인 프로그래밍 원칙들&lt;/h2&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;9장. 예외&lt;/h2&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;10장. 병행성&lt;/h2&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;11장. 직렬화&lt;/h2&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Reference&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Effective Java 2/E (Joshua Bloch)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;495&quot; data-origin-height=&quot;649&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/oUWve/btro6aFuN5E/O3WWdZNh5FK47XmmEvp8ik/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/oUWve/btro6aFuN5E/O3WWdZNh5FK47XmmEvp8ik/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/oUWve/btro6aFuN5E/O3WWdZNh5FK47XmmEvp8ik/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FoUWve%2Fbtro6aFuN5E%2FO3WWdZNh5FK47XmmEvp8ik%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;495&quot; height=&quot;649&quot; data-origin-width=&quot;495&quot; data-origin-height=&quot;649&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>Programming</category>
      <category>Effective Java</category>
      <category>effective java 2/e</category>
      <category>Java</category>
      <category>이펙티브 자바</category>
      <author>Ginjoe</author>
      <guid isPermaLink="true">https://itdar.tistory.com/404</guid>
      <comments>https://itdar.tistory.com/404#entry404comment</comments>
      <pubDate>Tue, 28 Dec 2021 22:13:52 +0900</pubDate>
    </item>
    <item>
      <title>Linux 명령어: find</title>
      <link>https://itdar.tistory.com/403</link>
      <description>&lt;h1&gt;Linux 명령어: find&lt;/h1&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;52&quot; data-origin-height=&quot;32&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cw3cdd/btrul3NKzOU/72GGNeSV0Og3e5eRSn73B0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cw3cdd/btrul3NKzOU/72GGNeSV0Og3e5eRSn73B0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cw3cdd/btrul3NKzOU/72GGNeSV0Og3e5eRSn73B0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcw3cdd%2Fbtrul3NKzOU%2F72GGNeSV0Og3e5eRSn73B0%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;52&quot; height=&quot;32&quot; data-origin-width=&quot;52&quot; data-origin-height=&quot;32&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;find&lt;/h3&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;-exec 옵션으로 찾아낸 파일에 대해 특정 명령을 실행 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;검색 옵션&lt;/h3&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&quot;center&quot;&gt;옵션의 종류&lt;/th&gt;
&lt;th&gt;내용&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&quot;center&quot;&gt;-name&lt;/td&gt;
&lt;td&gt;원하는 이름의 파일을 찾아주며, 와일드카드(*,?,[])를 사용 가능&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;center&quot;&gt;-type&lt;/td&gt;
&lt;td&gt;찾고자 하는 것이 파일(f)인지, 디렉터리(d)인지, 링크(i)인지 등을 정한다&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;center&quot;&gt;-user&lt;/td&gt;
&lt;td&gt;지정한 사용자가 소유한 파일을 찾는다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;center&quot;&gt;-size&lt;/td&gt;
&lt;td&gt;크기가 n인 파일을 찾는다. (-n, n, +n)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;center&quot;&gt;-newer&lt;/td&gt;
&lt;td&gt;지정한 파일보다 나중에 생성된 파일을 찾아준다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;center&quot;&gt;-empty&lt;/td&gt;
&lt;td&gt;비어있는 파일을 찾는다.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;동작 옵션&lt;/h3&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&quot;center&quot;&gt;옵션의 종류&lt;/th&gt;
&lt;th&gt;내용&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&quot;center&quot;&gt;-exec&lt;/td&gt;
&lt;td&gt;찾아낸 파일을 인수로 지정한 명령을 수행한다&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;center&quot;&gt;-print&lt;/td&gt;
&lt;td&gt;찾아낸 파일의 전체 경로를 표시해 보여준다. 이 옵션은 find 명령 기본옵션&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;center&quot;&gt;-ok&lt;/td&gt;
&lt;td&gt;-exec 옵션과 동일하나, 명령 수행 이전에 사용자에게 수행 여부를 확인한다&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예시 #1&lt;/p&gt;
&lt;pre class=&quot;clean&quot;&gt;&lt;code&gt;### ex)
### 파일을 찾는데, 이름은 '*.log'
### 찾아서 grep 으로 2021-12-25 찾는 것을 실행하는데
### 인자는 앞에 찾은 파일들 경로가 {} 에 들어가고
### 결과는 현재 경로의 tmp.txt 에 저장한다.

find / -type f -name '*.log' -exec grep 2021-12-25 &amp;gt; tmp.txt {} \;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예시 #2&lt;/p&gt;
&lt;pre id=&quot;code_1645754959871&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# httpd.conf 라는 이름의
# 타입이 파일인 것을 찾는데,
# 허가 거부 등의 아닌 결과는 버린다.

find / -type f -name 'httpd.conf' 2&amp;gt;/dev/null&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예시 #3&lt;/p&gt;
&lt;pre id=&quot;code_1646022949168&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# / 부터 전체를 탐색하는데
# server.xml 의 이름 파일을 찾아서
# 해당 파일에 8080 문자열이 있는지 확인하고
# 해당 파일의 이름을 출력한다.
# 이 때, 불필요 로그는 버린다.

find / -type f -name 'server.xml' -exec grep -l 8080 2&amp;gt;/dev/null {} \;&lt;/code&gt;&lt;/pre&gt;</description>
      <category>Programming</category>
      <category>find</category>
      <category>grep</category>
      <category>Linux</category>
      <author>Ginjoe</author>
      <guid isPermaLink="true">https://itdar.tistory.com/403</guid>
      <comments>https://itdar.tistory.com/403#entry403comment</comments>
      <pubDate>Wed, 22 Dec 2021 00:03:37 +0900</pubDate>
    </item>
    <item>
      <title>[LeetCode] 94. Maximum Number of Balls in a Box (TDD, 코테, 릿코드, tech interview)</title>
      <link>https://itdar.tistory.com/402</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;512&quot; data-origin-height=&quot;171&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dpvkc3/btrodTksw99/NHHUjFG4ha3nkkRKkcw8QK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dpvkc3/btrodTksw99/NHHUjFG4ha3nkkRKkcw8QK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dpvkc3/btrodTksw99/NHHUjFG4ha3nkkRKkcw8QK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdpvkc3%2FbtrodTksw99%2FNHHUjFG4ha3nkkRKkcw8QK%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;512&quot; height=&quot;171&quot; data-origin-width=&quot;512&quot; data-origin-height=&quot;171&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;풀이 코드&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1639924139240&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import java.util.ArrayList;
import java.util.List;

public class LeetCode_0094_BinaryTreeInorderTraversal {

    private List&amp;lt;Integer&amp;gt; result = new ArrayList&amp;lt;&amp;gt;();

    public List&amp;lt;Integer&amp;gt; inorderTraversal(TreeNode94 root) {
        if (root == null) {
            return result;
        }

        recursiveInorderTraversal(root);

        return result;
    }

    private void recursiveInorderTraversal(TreeNode94 node) {
        if (node.left != null) {
            recursiveInorderTraversal(node.left);
        }

        result.add(node.val);

        if (node.right != null) {
            recursiveInorderTraversal(node.right);
        }
    }

}

class TreeNode94 {
    int val;
    TreeNode94 left;
    TreeNode94 right;
    TreeNode94() {}
    TreeNode94(int val) { this.val = val; }
    TreeNode94(int val, TreeNode94 left, TreeNode94 right) {
        this.val = val;
        this.left = left;
        this.right = right;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;테스트코드&lt;/p&gt;
&lt;pre id=&quot;code_1639924166873&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import static org.assertj.core.api.Assertions.assertThat;

import org.junit.jupiter.api.Test;

public class LeetCode_0094_BinaryTreeInorderTraversalTest {

    @Test
    public void inorderTraversalTest_1() {
        LeetCode_0094_BinaryTreeInorderTraversal test = new LeetCode_0094_BinaryTreeInorderTraversal();

        TreeNode94 root = new TreeNode94(1);
        TreeNode94 node2 = new TreeNode94(2);
        TreeNode94 node3 = new TreeNode94(3);

        root.right = node2;
        node2.left = node3;

        assertThat(test.inorderTraversal(root)).containsExactly(1,3,2);
    }

    @Test
    public void inorderTraversalTest_2() {
        LeetCode_0094_BinaryTreeInorderTraversal test = new LeetCode_0094_BinaryTreeInorderTraversal();

        TreeNode94 root = new TreeNode94();

        assertThat(test.inorderTraversal(root)).containsExactly(0);
    }

    @Test
    public void inorderTraversalTest_3() {
        LeetCode_0094_BinaryTreeInorderTraversal test = new LeetCode_0094_BinaryTreeInorderTraversal();

        TreeNode94 root = new TreeNode94(1);

        assertThat(test.inorderTraversal(root)).containsExactly(1);
    }

}&lt;/code&gt;&lt;/pre&gt;</description>
      <category>Algorithm/Leet Code</category>
      <category>binary tree inorder traversal</category>
      <category>dfs</category>
      <category>leetcode</category>
      <category>TDD</category>
      <category>중위순회</category>
      <author>Ginjoe</author>
      <guid isPermaLink="true">https://itdar.tistory.com/402</guid>
      <comments>https://itdar.tistory.com/402#entry402comment</comments>
      <pubDate>Sun, 19 Dec 2021 23:29:44 +0900</pubDate>
    </item>
    <item>
      <title>프로세스의 메모리 주소 공간 (Memory address space of Process)</title>
      <link>https://itdar.tistory.com/401</link>
      <description>&lt;h1&gt;프로세스의 메모리 주소 공간&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;코드&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;데이터&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;힙&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;스택&lt;/p&gt;
&lt;h2&gt;현대의 모든 운영체제는 가상 메모리 기반으로 동작함&lt;/h2&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;각 프로세스는 독립적인 가상 메모리의 주소 공간을 갖는다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;프로세스는 자신만 메모리를 독점하고 있다고 생각&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h3&gt;코드&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;실행할 프로그램의 코드가 저장&lt;/li&gt;
&lt;li&gt;프로그램 시작부터 끝까지 메모리에 남아있음&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h3&gt;데이터&lt;/h3&gt;
&lt;h4&gt;초기화 된 데이터&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;전역변수, 정적(static)변수, 소스코드 상의 문자열&lt;/li&gt;
&lt;li&gt;실행파일에 데이터를 기록해야함&lt;/li&gt;
&lt;li&gt;실행 파일의 크기가 크다.&lt;h4&gt;초기화 되지 않은 데이터 (BSS-Block Started by Symbol)&lt;/h4&gt;
&lt;/li&gt;
&lt;li&gt;초기화 없이 해당 데이터의 사이즈만 기억함&lt;/li&gt;
&lt;li&gt;해당 부분을 실행 할 때 할당 받으면서 0으로 초기화함&lt;/li&gt;
&lt;li&gt;실행 파일의 크기가 작다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h3&gt;힙 (Heap)&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;동적으로 할당한 메모리를 저장&lt;/li&gt;
&lt;li&gt;개발자가 관리하는 메모리 영역 (할당 해제 안하면 memory leak)&lt;/li&gt;
&lt;li&gt;런타임에 크기가 정해짐&lt;/li&gt;
&lt;li&gt;위에서부터 채워짐&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h3&gt;스택 (Stack)&lt;/h3&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;</description>
      <category>Programming</category>
      <category>memory</category>
      <category>Memory address space</category>
      <category>Process</category>
      <category>메모리 주소공간</category>
      <category>스택영역</category>
      <category>힙영역</category>
      <author>Ginjoe</author>
      <guid isPermaLink="true">https://itdar.tistory.com/401</guid>
      <comments>https://itdar.tistory.com/401#entry401comment</comments>
      <pubDate>Sun, 19 Dec 2021 20:49:52 +0900</pubDate>
    </item>
    <item>
      <title>Spring Security 5 OAuth 정리 (클라에서 서버까지)</title>
      <link>https://itdar.tistory.com/400</link>
      <description>&lt;h1&gt;Spring Security 5 OAuth 정리 (클라에서 서버까지)&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;SpringSecurity5 OAuth&lt;/li&gt;
&lt;li&gt;SpringSecurity5 이전의 AOuth&lt;/li&gt;
&lt;li&gt;OAuth Client 최소설정 및 주의할 점&lt;/li&gt;
&lt;li&gt;OAuth Server 최소설정 및 주의할 점&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;SpringSecurity 란&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;스프링프레임워크 기반 인증(Authn), 인가(Authz) 프레임워크&lt;/li&gt;
&lt;li&gt;스프링 기반 애플리케이션에서는 사실상 표준 (de-facto standard)&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Spring Security 5&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;스프링부터 2.0부터&lt;/li&gt;
&lt;li&gt;스프링프레임워크 5.0 기반&lt;/li&gt;
&lt;li&gt;새로운 기능: OAuth 2.0 Login 등&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Spring Security 5 OAuth&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;http.oauth2.Login() (대표적)&lt;ul&gt;
&lt;li&gt;한방 사용이 가능해짐 (편리해짐)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Spring Security 5 이전의 OAuth&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Spring Security 4 까지 - Spring Security OAuth 별도 모듈 존재&lt;/li&gt;
&lt;li&gt;OAuth 1.0, OAuth 2.0&lt;/li&gt;
&lt;li&gt;OAuth Client, Resource Source, Authorization Server 지원&lt;ul&gt;
&lt;li&gt;다 필요 시 각각 구현해 주어야했음&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;OAuth 2.0 Roles&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;- Resource Owner
- Resource Server
- Client
- Authorization Server&lt;/code&gt;&lt;/pre&gt;&lt;h4&gt;Spring Security OAuth 불편한점&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;기존 form login 이나 지금의 oath login 과는 코딩스타일이 다르고 확장포인트가 불명확함&lt;/li&gt;
&lt;li&gt;명시적으로 OAuth 기능을 제공하지 않음&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Spring Boot OAuth Client 최소설정&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Common OAuth2 Provider: google, GitHub, Facebook, okta&lt;ul&gt;
&lt;li&gt;Application.properties 에서 id 와 secret 설정으로 구현 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Uncommon provider&lt;ul&gt;
&lt;li&gt;Client registration 코드 작성 등록&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;최소설정 사용 시, OAuth2AuthorizedClientService bean 기본 구현이 in memory.&lt;ul&gt;
&lt;li&gt;실제 환경은 별도 구현 필요함 (서버 여러 대 이거나 하면 문제)&lt;/li&gt;
&lt;li&gt;Jdbc 등으로&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;OAuth Client 주요 확장 포인트&lt;ul&gt;
&lt;li&gt;authorizationEndpoint, redirectionEndpoint, userInfoEndpoint&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Spring Boot OAuth Server 최소설정&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;SpringSecurity5 + Spring-authorization-server 라이브러리 추가 사용&lt;/li&gt;
&lt;li&gt;아직 userEndpoint 구현 안됨. (곧 릴리즈 될 예정임)&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h4&gt;Reference&lt;/h4&gt;
&lt;p&gt;&lt;a href=&quot;https://youtu.be/-YbqW-pqt3w&quot;&gt;https://youtu.be/-YbqW-pqt3w&lt;/a&gt;&lt;/p&gt;</description>
      <category>Programming</category>
      <category>Oauth 2.0</category>
      <category>spring security</category>
      <author>Ginjoe</author>
      <guid isPermaLink="true">https://itdar.tistory.com/400</guid>
      <comments>https://itdar.tistory.com/400#entry400comment</comments>
      <pubDate>Fri, 17 Dec 2021 00:33:43 +0900</pubDate>
    </item>
    <item>
      <title>Oracle to MySQL 변환 시 고려사항 (RDBMS)</title>
      <link>https://itdar.tistory.com/399</link>
      <description>&lt;h1&gt;Oracle 에서 MySQL 로 변환..&lt;/h1&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;/li&gt;
&lt;li&gt;RDBMS 변환 시 전체적인 계획&lt;/li&gt;
&lt;/ul&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;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;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;고려사항&lt;/h2&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;Subquery alias (mysql 에서는 subquery에 alias 없으면 쿼리에러 발생)&lt;/li&gt;
&lt;li&gt;Mysql 은 대소문자를 구분함 (설치 시 구분여부 설정 가능)&lt;/li&gt;
&lt;li&gt;함수 명칭 (IFNULL, NOW, CASE, CAST, DATE_ADD 등)&lt;/li&gt;
&lt;li&gt;Oracle 에서만 지원하는 구문/함수 들 (sequence, rownum, join, pivot 등)&lt;/li&gt;
&lt;li&gt;계층형 쿼리&lt;/li&gt;
&lt;li&gt;|| (pipe_as_concat -&amp;gt; cancat_ws)&lt;/li&gt;
&lt;li&gt;공백문자를 null로 취급하는 것의 차이&lt;/li&gt;
&lt;li&gt;Dynamic where 차이&lt;/li&gt;
&lt;li&gt;Byte 입력 및 byte 연산 차이 (함수 만들어서 해결)&lt;/li&gt;
&lt;li&gt;대용량 처리 시 성능 저하 (oracle -&amp;gt; mysql)
&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;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Isolation level&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;RDBMS 변환 시 계획&lt;/h2&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;/li&gt;
&lt;li&gt;복구 가능한 형태로 데이터 보관&lt;/li&gt;
&lt;li&gt;QA 지속적으로.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Reference&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=jMHOJQczrnI&quot;&gt;https://www.youtube.com/watch?v=jMHOJQczrnI&lt;/a&gt;&lt;/p&gt;</description>
      <category>Programming</category>
      <category>Oracle to MySQL</category>
      <category>RDBMS</category>
      <author>Ginjoe</author>
      <guid isPermaLink="true">https://itdar.tistory.com/399</guid>
      <comments>https://itdar.tistory.com/399#entry399comment</comments>
      <pubDate>Wed, 15 Dec 2021 22:53:03 +0900</pubDate>
    </item>
    <item>
      <title>[LeetCode] 1742. Maximum Number of Balls in a Box (TDD, 코테, 릿코드, tech interview)</title>
      <link>https://itdar.tistory.com/398</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;TDD로 알고리즘 풀이 후 리팩토링&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리팩토링해서 함수만들고 하면 성능이 좀 떨어짐&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;테스트코드&lt;/p&gt;
&lt;pre id=&quot;code_1639212465397&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package algorithm_sites.leetcode;

import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.Test;

public class LeetCode_1742_MaximumNumberOfBallsInABoxTest {

    private LeetCode_1742_MaximumNumberOfBallsInABox test = new LeetCode_1742_MaximumNumberOfBallsInABox();

    @Test
    public void countBallsTest() {
        Assertions.assertThat(test.countBalls(1, 10)).isEqualTo(2);
        Assertions.assertThat(test.countBalls(5, 15)).isEqualTo(2);
        Assertions.assertThat(test.countBalls(19, 28)).isEqualTo(2);
    }

    @Test
    public void digitSumTest() {
        Assertions.assertThat(test.digitSum(12)).isEqualTo(3);
        Assertions.assertThat(test.digitSum(312)).isEqualTo(6);
        Assertions.assertThat(test.digitSum(4572)).isEqualTo(18);
        Assertions.assertThat(test.digitSum(9380)).isEqualTo(20);
        Assertions.assertThat(test.digitSum(0)).isEqualTo(0);
        Assertions.assertThat(test.digitSum(1)).isEqualTo(1);
        Assertions.assertThat(test.digitSum(990)).isEqualTo(18);
    }

}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;풀이코드&lt;/p&gt;
&lt;pre id=&quot;code_1639212494494&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package algorithm_sites.leetcode;

/**
 * Written by Gin (thesockerr@gmail.com) on 2021/12/11.
 */
public class LeetCode_1742_MaximumNumberOfBallsInABox {
    int[] boxes = new int[10 * 100000];

    // Process
    // 1. Input low high limits
    // 2. Iterate low to high (num)
    //  2.1. Get digitSum of num
    //  2.2. Put digitSum in boxNumber
    // 3. Get maxBoxNumber
    // 4. Return
    public int countBalls(int lowLimit, int highLimit) {
        // 2.
        fillTheBoxes(lowLimit, highLimit);

        // 3. / 4.
        return findMaxNumberOfMaxCountBox();
    }

    private void fillTheBoxes(int lowLimit, int highLimit) {
        for (int i = lowLimit; i &amp;lt;= highLimit; ++i) {
            ++boxes[digitSum(i)];
        }
    }

    private int findMaxNumberOfMaxCountBox() {
        int max = 0;
        for (int i = 0; i &amp;lt; boxes.length; ++i) {
            if (max &amp;lt; boxes[i]) {
                max = boxes[i];
            }
        }

        return max;
    }

    protected int digitSum(int number) {
        int sum = 0;

        while (number &amp;gt; 0) {
            sum += (number % 10);
            number /= 10;
        }

        return sum;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;문제 영어 독해가 빡쎘음..&lt;/p&gt;</description>
      <category>Programming</category>
      <category>1742</category>
      <category>Algorithm</category>
      <category>leetcode</category>
      <category>Maximum Number of Balls in a Box</category>
      <category>TDD</category>
      <author>Ginjoe</author>
      <guid isPermaLink="true">https://itdar.tistory.com/398</guid>
      <comments>https://itdar.tistory.com/398#entry398comment</comments>
      <pubDate>Sat, 11 Dec 2021 17:49:48 +0900</pubDate>
    </item>
    <item>
      <title>[LeetCode] 2085. Count common words with one occurrence (코딩테스트, 테스트케이스 포함, 릿코드, tech interview)</title>
      <link>https://itdar.tistory.com/397</link>
      <description>&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;/li&gt;
&lt;/ul&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;696&quot; data-origin-height=&quot;176&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bu3jz0/btrmYcSQW2O/28ZRd06U8C3y9gtcZDOATk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bu3jz0/btrmYcSQW2O/28ZRd06U8C3y9gtcZDOATk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bu3jz0/btrmYcSQW2O/28ZRd06U8C3y9gtcZDOATk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbu3jz0%2FbtrmYcSQW2O%2F28ZRd06U8C3y9gtcZDOATk%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;696&quot; height=&quot;176&quot; data-origin-width=&quot;696&quot; data-origin-height=&quot;176&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;pre class=&quot;arduino&quot;&gt;&lt;code&gt;    // Process
    // 1. Input 2 string arrays
    // 2. 한개 배열씩 반복한다.
    //  2.1. 중복안되는 것들의 배열을 각각 만든다.
    // 3. 중복안되는 것들의 배열 2개에서 서로 중복되는 개수를 센다.
    // 4. 개수 반환한다.
    public int countWords(String[] words1, String[] words2) {
        int result = 0;

        Set&amp;lt;String&amp;gt; repeated = new HashSet&amp;lt;&amp;gt;();
        Set&amp;lt;String&amp;gt; set1 = new HashSet&amp;lt;&amp;gt;();
        Set&amp;lt;String&amp;gt; set2 = new HashSet&amp;lt;&amp;gt;();

        // 2.
        for (String word : words1) {
            if (repeated.contains(word)) {
                continue;
            }

            if (set1.contains(word)) {
                set1.remove(word);
                repeated.add(word);
                continue;
            }

            set1.add(word);
        }

        for (String word : words2) {
            if (repeated.contains(word)) {
                continue;
            }

            if (set2.contains(word)) {
                set2.remove(word);
                repeated.add(word);
                continue;
            }

            set2.add(word);
        }

        // 3.
        for (String string : set1) {
            if (set2.contains(string)) {
                ++result;
            }
        }

        return result;
    }&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;테스트코드는 assertj 라이브러리를 씀&lt;/h4&gt;
&lt;pre class=&quot;haxe&quot;&gt;&lt;code&gt;import static org.assertj.core.api.Assertions.assertThat;

import org.junit.jupiter.api.Test;

public class LeetCode_2085_CountCommonWordsWithOneOccurrenceTest {

    @Test
    public void 두개의_배열에서_각각_1회씩만_나오면서_겹치는_숫자의_개수() {
        LeetCode_2085_CountCommonWordsWithOneOccurrence test = new LeetCode_2085_CountCommonWordsWithOneOccurrence();

        assertThat(test.countWords(new String[] {&quot;leetcode&quot;, &quot;is&quot;, &quot;amazing&quot;, &quot;as&quot;, &quot;is&quot;}, new String[] {&quot;amazing&quot;, &quot;leetcode&quot;, &quot;is&quot;})).isEqualTo(2);
        assertThat(test.countWords(new String[] {&quot;b&quot;,&quot;bb&quot;,&quot;bb&quot;}, new String[] {&quot;a&quot;,&quot;aa&quot;,&quot;aaa&quot;})).isEqualTo(0);
        assertThat(test.countWords(new String[] {&quot;a&quot;, &quot;ab&quot;}, new String[] {&quot;a&quot;,&quot;a&quot;, &quot;a&quot;, &quot;ab&quot;})).isEqualTo(1);
    }

}&lt;/code&gt;&lt;/pre&gt;</description>
      <category>Programming</category>
      <category>leetcode</category>
      <category>릿코드</category>
      <category>문제풀이</category>
      <category>알고리즘</category>
      <author>Ginjoe</author>
      <guid isPermaLink="true">https://itdar.tistory.com/397</guid>
      <comments>https://itdar.tistory.com/397#entry397comment</comments>
      <pubDate>Sat, 4 Dec 2021 17:57:37 +0900</pubDate>
    </item>
    <item>
      <title>Gradle 의존 키워드의 차이점 (compile vs implementation + api, Gradle dependency configurations diff)</title>
      <link>https://itdar.tistory.com/396</link>
      <description>&lt;h1&gt;&amp;nbsp;&lt;/h1&gt;
&lt;h1&gt;Gradle 의존 키워드의 차이점 (compile vs implementation + api, Gradle dependency configurations diff)&lt;/h1&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;/li&gt;
&lt;li&gt;Reference&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;배경&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;gradle 3.0 부터 compile 키워드가 deprecated 되었다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;각각의 특징 및 차이점&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;api 또는 compile
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;가장 상위의 의존을 시작하는 app 에서, 직접 의존하고 있는 것이 의존하고 있는 하위의 간접 의존에도 접근이 가능하다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;implementation
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;가장 상위의 의존을 시작하는 app 에서, 직접 의존하는 것만 가능하다.&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;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;추천 사용법&lt;/h2&gt;
&lt;pre class=&quot;ada&quot;&gt;&lt;code&gt;api : app 에서 직접의존+간접의존 하는 내용을 전부 보여주고 싶다면
implementation : app 에서 직접의존 하는 내용만 보여주고 싶다면&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;compile 은 implementation 또는 api 로 변경하여 사용한다.&lt;/li&gt;
&lt;li&gt;testCompile 은 testImplementation 으로,&lt;/li&gt;
&lt;li&gt;debugCompile 은 debugImplementation 으로,&lt;/li&gt;
&lt;li&gt;androidTestCompile 은 androidTestImplementation 으로,&lt;/li&gt;
&lt;li&gt;compileOnly 는 유효함&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Reference&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://stackoverflow.com/questions/44493378/whats-the-difference-between-implementation-api-and-compile-in-gradle&quot;&gt;https://stackoverflow.com/questions/44493378/whats-the-difference-between-implementation-api-and-compile-in-gradle&lt;/a&gt;&lt;/p&gt;</description>
      <category>Programming</category>
      <category>API</category>
      <category>Compile</category>
      <category>dependencies</category>
      <category>Gradle</category>
      <category>Implementation</category>
      <author>Ginjoe</author>
      <guid isPermaLink="true">https://itdar.tistory.com/396</guid>
      <comments>https://itdar.tistory.com/396#entry396comment</comments>
      <pubDate>Sun, 28 Nov 2021 21:08:49 +0900</pubDate>
    </item>
    <item>
      <title>RPC, 근데 이제 Json을 곁들인.. (Json-RPC)</title>
      <link>https://itdar.tistory.com/395</link>
      <description>&lt;h1&gt;RPC, 근데 이제 Json을 곁들인.. (Json-RPC)&lt;/h1&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;RPC 란 무엇인가?&lt;/li&gt;
&lt;li&gt;Json 이란 무엇인가?&lt;/li&gt;
&lt;li&gt;RPC 가 사용되는 이유&lt;/li&gt;
&lt;li&gt;RPC 동작 방식&lt;/li&gt;
&lt;li&gt;Json-RPC 특징&lt;/li&gt;
&lt;li&gt;추가: gRPC는?&lt;/li&gt;
&lt;li&gt;HTTP 위에 얹는 Json-RPC 스타일&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;RPC 란 무엇인가?&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Remote Procedure Call (원격 프로시져 호출)&lt;/h4&gt;
&lt;pre class=&quot;&quot;&gt;&lt;code&gt; 언어나 환경 등에 종속되지 않고 서비스 간 프로시저를 호출하도록 해주는 개념&lt;/code&gt;&lt;/pre&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;프로세스 간 통신 (Inter-Process Communication) 의 한 형태&lt;/li&gt;
&lt;li&gt;클라이언트-서버 관계로 요청-응답 시스템&lt;/li&gt;
&lt;li&gt;클라이언트에서 서버로 필요한 파라미터를 보내어 프로시저를 동작시킨다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Json 이란 무엇인가?&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;JavaScript Object Notation&lt;/h4&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;Key / Value 쌍으로 콜렉션 타입으로 구성됨&lt;/li&gt;
&lt;li&gt;예시 (below)
&lt;pre class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;{
  &quot;widget&quot;: {
    &quot;debug&quot;: &quot;on&quot;,
    &quot;window&quot;: {
      &quot;title&quot;: &quot;Sample Konfabulator Widget&quot;,
      &quot;name&quot;: &quot;main_window&quot;,
      &quot;width&quot;: 500,
      &quot;height&quot;: 500
    },
    &quot;image&quot;: {
      &quot;src&quot;: &quot;Images/Sun.png&quot;,
      &quot;name&quot;: &quot;sun1&quot;,
      &quot;hOffset&quot;: 250,
      &quot;vOffset&quot;: 250,
      &quot;alignment&quot;: &quot;center&quot;
    },
    &quot;text&quot;: {
      &quot;data&quot;: &quot;Click Here&quot;,
      &quot;size&quot;: 36,
      &quot;style&quot;: &quot;bold&quot;,
      &quot;name&quot;: &quot;text1&quot;,
      &quot;hOffset&quot;: 250,
      &quot;vOffset&quot;: 100,
      &quot;alignment&quot;: &quot;center&quot;,
      &quot;onMouseUp&quot;: &quot;sun1.opacity = (sun1.opacity / 100) * 90;&quot;
    }
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;RPC 가 사용되는 이유&lt;/h3&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;/li&gt;
&lt;li&gt;HTTP 는 어플리케이션 레이어 (7계층) 에서 동작하는 것과 다르게, RPC 는 TCP (4계층) 위에서 동작한다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;따라서 더 다양한 프로토콜 사용 가능하다 (TCP, Socket, HTTP 등..)&lt;/li&gt;
&lt;li&gt;CRUD 외에 다양한 동작 표현 (동일한 엔드포인트 호출로 메서드와 파라미터만 바꿔서)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;RPC 동작방식&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://github.com/itdar/TIL/blob/main/zdata/json-rpc.png?raw=true&quot; alt=&quot;img.png&quot; /&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;클라이언트는 클라이언트 Stub 을 호출한다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;스택에 매개변수를 푸시하는 로컬 프로시저 콜&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;클라이언트 Stub 은 메시지로 매개변수를 패킹하고 메시지를 전송하는 시스템 호출
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이 때, 매개변수 패킹하는 것을 마샬링(Marshalling)이라 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;클라이언트 로컬 OS 는 클라이언트에서 서버로 메시지 보낸다.&lt;/li&gt;
&lt;li&gt;서버 로컬 OS 는 들어오는 패킷을 서버 Stub 으로 보낸다.&lt;/li&gt;
&lt;li&gt;서버 Stub 은 메시지에서 매개변수 압축을 언패킹 한다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이 때, 매개변수 압축 푸는 것을 언마샬링(Unmarshalling) 이라 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;서버 Stub 은 서버 프로시저를 호출한다.&lt;/li&gt;
&lt;li&gt;응답과 반환패킷은 반대 방향으로 동일한 단계를 거친다.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Json-RPC 특징&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;RPC 를 Json 포맷으로 표현한 것&lt;/li&gt;
&lt;li&gt;2.0부터 Request-Response 뿐만 아니라 응답없는 Notification 지원한다.&lt;/li&gt;
&lt;li&gt;4계층 TCP 에서 동작하여 Http 프로토콜을 얹을 필요없이, Json 만 전달하여 동작 가능하다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;더 가볍고 빠르다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;+ gRPC&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;구글에서 만든 gRPC 를 많이들 쓰는 것으로 보임
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;protobuf 통해서 binary 로 마샬링 (더 빠름)&lt;/li&gt;
&lt;li&gt;IDL 통해서 여러 언어로 제너레이팅 가능&lt;/li&gt;
&lt;li&gt;HTTP 2.0 지원&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;HTTP 위에 얹는 Json-RPC 스타일&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;HTTP 프로토콜을 사용하되, 요청을 1개로 통일&lt;/li&gt;
&lt;li&gt;POST 의 Body 등으로 json 을 넘기는데, 이 때 JsonRPC 포맷을 따른다. (id, method, params)&lt;/li&gt;
&lt;li&gt;이렇게 하면..
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;컨트롤러 1개로 모든 요청을 받고, 메서드를 호출해서 응답을 할 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;간단한 구현은 편해서 좋은점도 있다고 하는데.. 흠?&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Reference&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Remote_procedure_call&quot;&gt;https://en.wikipedia.org/wiki/Remote_procedure_call&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/JSON-RPC&quot;&gt;https://en.wikipedia.org/wiki/JSON-RPC&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.jsonrpc.org/&quot;&gt;https://www.jsonrpc.org/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.json.org/json-en.html&quot;&gt;https://www.json.org/json-en.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.geeksforgeeks.org&quot;&gt;https://www.geeksforgeeks.org&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Programming</category>
      <category>JSON</category>
      <category>JSON-RPC</category>
      <category>Remote Procedure Call</category>
      <category>RPC</category>
      <author>Ginjoe</author>
      <guid isPermaLink="true">https://itdar.tistory.com/395</guid>
      <comments>https://itdar.tistory.com/395#entry395comment</comments>
      <pubDate>Wed, 17 Nov 2021 23:21:15 +0900</pubDate>
    </item>
    <item>
      <title>개발자의 글쓰기 - 책정리</title>
      <link>https://itdar.tistory.com/394</link>
      <description>&lt;h1&gt;개발자의 글쓰기&lt;/h1&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;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;7장. 기술 블로그 쉽게 쓰고 운영하기&lt;/h2&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;1. 기술 블로그를 쉽게 쓰는 방법 3가지&lt;/h4&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;1. 소재우선 글쓰기 (주제의식을 버리고 소재의식으로 글쓰기)
2. 자기 수준 글쓰기 (핵심 내용만 쓰고 나머지는 독자가 공부할 수 있게 길만 터둔다)
3. 재미있는 글쓰기 (글쓴이의 경험 등을 기교와 녹여낸다)&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;2. 글의 종류로 목차를 잡는 법 (저, 술, 편, 집)&lt;/h4&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;구분&lt;/th&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;직접 경험하고 실험한 과정이나 결과&lt;/td&gt;
&lt;td&gt;개발기, 도입기, 적용기&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;술&lt;/td&gt;
&lt;td&gt;어떤 것을 분석하여 의미를 풀이하고 해석한 것&lt;/td&gt;
&lt;td&gt;기술 소개, 용어 분석, 에러 해결 방법 등&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;편&lt;/td&gt;
&lt;td&gt;산만하고 복잡한 자료를 편집해 질서를 부여한 것&lt;/td&gt;
&lt;td&gt;프로그램 설치/설정 방법, 튜토리얼, 세미나 후기, 책 리뷰&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;집&lt;/td&gt;
&lt;td&gt;여러 사람의 견해나 흩어진 자료를 한데 모아 정리한 것&lt;/td&gt;
&lt;td&gt;명령어 모음, 팁, 00가지 규칙&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&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;/li&gt;
&lt;li&gt;편: 순서를 요약하여 쓴다.&lt;/li&gt;
&lt;li&gt;집: 글쓰기가 어려우면 자료를 모아 핵심을 엮는다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Programming</category>
      <category>개발자의 글쓰기</category>
      <category>기술블로그 쉽게 쓰고 운영하기</category>
      <category>저술편집</category>
      <category>책정리</category>
      <author>Ginjoe</author>
      <guid isPermaLink="true">https://itdar.tistory.com/394</guid>
      <comments>https://itdar.tistory.com/394#entry394comment</comments>
      <pubDate>Tue, 26 Oct 2021 17:16:55 +0900</pubDate>
    </item>
    <item>
      <title>객체지향의 사실과 오해 (The Essence of Object-Orientation) - 책정리</title>
      <link>https://itdar.tistory.com/393</link>
      <description>&lt;h1&gt;객체지향의 사실과 오해 (The Essence of Object-Orientation)&lt;/h1&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;역할, 책임, 협력 관점에서 본 객체지향&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Roles, Responsibilities, and Collaborations&lt;/h2&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. 협력하는 객체들의 공동체&lt;/h2&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;ol 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;/li&gt;
&lt;li&gt;책임을 수행하는 방법은 선택 가능 (동일 요청에 다른 방식 응답 - 다형성)&lt;/li&gt;
&lt;li&gt;하나가 여러 역할 수행 가능&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;객체의 덕목 2가지: 협력적, 자율적&lt;/li&gt;
&lt;li&gt;협력은 메시지를 통해 이루어진다.&lt;/li&gt;
&lt;li&gt;요청을 표현하는 메시지와, 요청을 처리하는 구체적 방법인 메서드를 분리하는 것은 자율성을 높이는데에 도움이 되고, 캡슐화(encapsulation)와 관련이 깊다.&lt;/li&gt;
&lt;li&gt;객체지향은 클래스들의 정적인 관계나 구조, 메서드가 아니라 객체의 역할, 책임, 협력 에 집중해야 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2. 이상한 나라의 객체&lt;/h2&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;객체는 상태(state), 행동(behavior), 식별자(identifier) 를 갖는다.&lt;/li&gt;
&lt;li&gt;객체의 정의: 식별 가능한 개체 또는 사물. 구체적인 사물일 수도 있고, 시간처럼 추상적잉ㄴ 개념일 수도 있다. 객체는 구별 가능한 식별자, 특징적인 행동, 변경 가능한 상태를 가진다. 소프트웨어 안에서 객체는 저장된 상태와 실행 가능한 코드를 통해 구현된다.&lt;/li&gt;
&lt;li&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;상태는 스스로의 행동에 의해서만 변경되는 것을 보장한다 -&amp;gt; 객체의 자율성을 유지한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&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;/li&gt;
&lt;li&gt;행동이란 외부의 요청 또는 수신 메시지에 응답하기 위해 동작하고 반응하는 활동.&lt;/li&gt;
&lt;li&gt;행동은 객체 자신의 상태를 변경하거나, 협력하는 다른 객체에 메시지를 전달할 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;객체의 행동을 유발하는 것은 외부에서 온 메시지이지만, 객체의 상태를 변경하는 여부는 객체 스스로 정한다. -&amp;gt; 객체의 자율성, 지능이 높아진다 -&amp;gt; 협력은 유연하고 간결해진다.&lt;/li&gt;
&lt;li&gt;식별자
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;불변한 값들은 동등성을 확인 (equality)&lt;/li&gt;
&lt;li&gt;가변의 값들은 동일성을 확인 (identical)&lt;/li&gt;
&lt;li&gt;객체는 어떤 상태에 있어라도 유일하게 식별되도록 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;객체를 기계로 바라보는 관점은 상태/행동/식별자 에 대한 이해를 높이고, 캡슐화와 메시지를 통한 협력 관계를 잘 설명한다.&lt;/li&gt;
&lt;li&gt;좋은 객체를 만들기 위해서는 상태보다는 행동에 우선 초점을 맞추어야 한다.&lt;br /&gt;-&amp;gt; 애플리케이션에 필요한 협력을 생각하고, 그에 필요한 행동을 생각하고, 행동 수행 객체를 선택한다.&lt;/li&gt;
&lt;li&gt;&amp;ldquo;행동이 상태를 결정한다.&amp;rdquo;&lt;/li&gt;
&lt;li&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;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;이상한 나라를 창조하라.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3. 타입과 추상화&lt;/h2&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;추상화: 어떠한 것을 더 명확하게 이해하기 위해서 부분을 의도적으로 생략하거나 감춤 -&amp;gt; 복잡도 극복
&lt;ol 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;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;객체는 특정 개념이 적용 가능한 구체적인 사물 -&amp;gt; 개념이 객체에 적용되면 객체를 개념의 인스턴스라 할 수 있다.&lt;/li&gt;
&lt;li&gt;객체 추상화 시에 객체 분류 방식으로 쓰이는 개념(concept)의 3가지 관점
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;심볼: 개념의 명칭이나 이름 (ex. 트럼프)&lt;/li&gt;
&lt;li&gt;내연: 개념의 완전한 정의 (ex. 몸이 납작, 두손 두발이 네모 귀퉁이에)&lt;/li&gt;
&lt;li&gt;외연: 개념에 속하는 모든 객체의 집합 set (ex. 정원사, 병사, 왕, 여왕 etc)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&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;/li&gt;
&lt;li&gt;타입은 데이터를 표현할 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&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;데이터 내부 표현방식과 무관하고 행동만이 고려대상이다. -&amp;gt; 외부에 데이터를 감춰야 한다. (캡슐화)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&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;/li&gt;
&lt;li&gt;데이터를 책임을 수행하는 데 필요한 외부 인터페이스 뒤로 캡슐화 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;타입과 타입 사이의 일반화/특수화 (Generalization/Specialization)
&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;/li&gt;
&lt;li&gt;중요한 것은 일반화/특수화 관계를 결정하는 것이 상태 데이터가 아니라 행동 이라는 것&lt;/li&gt;
&lt;li&gt;일반적인 타입은 특수한 타입에 비해 더 적은 수의 행동을 갖는다.&lt;/li&gt;
&lt;li&gt;일반적인 타입(supertype), 특수한 타입(subtype)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&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;/li&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;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;4. 역할, 책임, 협력&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;객체지향 설계의 품질을 결정하는 것은 역할, 책임, 협력 -&amp;gt; 객체들 사이의 협력의 품질이 가장 중요하다.&lt;/li&gt;
&lt;li&gt;객체와 책임을 설계하고, 그 다음에 구현을 한다.&lt;/li&gt;
&lt;li&gt;객체의 책임 분류
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&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;/li&gt;
&lt;li&gt;다른 객체의 활동을 제어하고 조절하는 것&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&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;/li&gt;
&lt;li&gt;자신이 유도하거나 계산할 수 있는 것에 관해 아는 것&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;책임은 즉 공용 인터페이스를 구성한다. -&amp;gt; 캡슐화로 연결된다.&lt;/li&gt;
&lt;li&gt;무엇을 할 수 있는지에 대한 나열: 책임&lt;/li&gt;
&lt;li&gt;협력에 참여하는 두 객체 사이의 관계: 메시지&lt;/li&gt;
&lt;li&gt;동일한 메시지에 동일한 책임을 수행할 수 있으면 -&amp;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;다양한 객체들이 동일한 협력에 참여 -&amp;gt; 재사용성 높아진다.&lt;/li&gt;
&lt;li&gt;역할은, 단순성, 유연성, 재사용성 을 뒷받침하는 핵심 개념&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;객체지향의 핵심은 객체가 협력 안에서 어떤 책임과 역할을 수행할 것인지를 결정하는 것&lt;/li&gt;
&lt;li&gt;협력이라는 문맥에서 책임(행동)을 결정한다. -&amp;gt; 그 다음 행동 수행을 위한 데이터를 고민한다.&lt;br /&gt;-&amp;gt; 그 다음에 클래스 구현 방법을 정한다.&lt;/li&gt;
&lt;li&gt;객체지향 설계 기법 3가지
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;책임주도개발 (Responsibility-Driven Development)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;시스템 책임을 객체 책임으로 변환, 객체의 책임과 상호작용에 집중 (역할, 책임, 협력)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&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;/ul&gt;
&lt;/li&gt;
&lt;li&gt;테스트주도개발 (Test-Driven Development)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;책임주도설계의 기본 개념, 다양한 원칙, 연습, 패턴을 종합적으로 이해해야함&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;5. 책임과 메시지&lt;/h2&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;어떻게(How)가 아니라 무엇(What)을&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&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;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&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;/ul&gt;
&lt;/li&gt;
&lt;li&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;/li&gt;
&lt;li&gt;역할, 책임, 협력 과 깊은 관련이 있음&lt;/li&gt;
&lt;li&gt;객체들의 대체 가능성을 이용해 설계를 유연하고 재사용 가능하게 한다.&lt;/li&gt;
&lt;li&gt;수신자의 종류를 캡슐화 하는 것.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&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;/li&gt;
&lt;li&gt;협력이 수행되는 방식 재사용 가능: 다양한 문맥에서 협력을 재사용 가능하다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;객체지향의 핵심: 메시지&lt;/li&gt;
&lt;li&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;/ul&gt;
&lt;/li&gt;
&lt;li&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;/ul&gt;
&lt;/li&gt;
&lt;li&gt;RDD (Responsibility-Driven Development)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;What/Who 사이클: 어떤 행위가 필요한지를 먼저 결정하고, 수행할 객체를 결정한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&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;/ul&gt;
&lt;/li&gt;
&lt;li&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;/li&gt;
&lt;li&gt;객체의 인터페이스는 객체가 수신 가능한 메시지 목록으로 채워짐&lt;/li&gt;
&lt;li&gt;메서드: 메시지 수신 시 책임을 수행하는 방법&lt;/li&gt;
&lt;li&gt;인터페이스: 객체가 책임을 수행하기 위해 외부로부터 메시지 받는 통로&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;인터페이스의 외부와 실제 내부 구현을 분리한다. (캡슐화, 정보은닉)&lt;/li&gt;
&lt;li&gt;캡슐화의 2가지 관점
&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;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;객체를 자율적으로 바라보는 것 -&amp;gt; 객체의 내부와 외부를 분리하는 것&lt;/li&gt;
&lt;li&gt;객체의 책임이 자율적이어야 하는 이유
&lt;ol 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;/li&gt;
&lt;li&gt;자율적인 책임은 내부가 변경되어도 외부에 영향이 없다. (캡슐화 -&amp;gt; 낮은 결합도)&lt;/li&gt;
&lt;li&gt;자율적인 책임은 협력의 대상이 다양해질 수 있는 유연성을 제공한다.&lt;/li&gt;
&lt;li&gt;자율적인 책임은 객체의 역할을 이해하기 쉽게 해준다.&lt;/li&gt;
&lt;/ol&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;/ul&gt;
&lt;/li&gt;
&lt;li&gt;메시지를 통해서 객체들의 책임을 자율적으로 만든다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;6. 객체 지도&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&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;/ul&gt;
&lt;/li&gt;
&lt;li&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;/li&gt;
&lt;li&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;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;유즈케이스 (Use-Case)
&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;/li&gt;
&lt;li&gt;단순한 피처 목록이 아니고, 이야기를 통해 연관된 기능들을 묶어서 보여준다.&lt;/li&gt;
&lt;li&gt;사용자 인터페이스와 관련된 세부 정보를 포함하지 않는다.&lt;/li&gt;
&lt;li&gt;내부 설계와 관련된 정보를 포함하지 않는다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;도메인 모델은 안정적인 구조를 개념화해주고, 유즈케이스는 불안정한 기능을 서술한다. (일반적으로 쓰이는 도구들)&lt;/li&gt;
&lt;li&gt;견고한 객체지향 애플리케이션 개발
&lt;ol 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;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&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;/ul&gt;
&lt;/li&gt;
&lt;li&gt;안정적인 도메인 모델을 기반으로 기스템의 기능을 구현&lt;/li&gt;
&lt;li&gt;도메인 모델과 코드를 밀접하게 연관하도록 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;gt; 유지보수하기 쉽고 유연한 객체지향 시스템&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;7. 함께 모으기&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;객체지향 설계 안의 3가지 상호 연관된 관점이 있다. 구현 클래스를 이러한 관점들로 바라보는 것을 이해한다.
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;개념 관점 (Conceptual Perspective): 도메인 안의 개념과 개념들 사이의 관계 표현&lt;/li&gt;
&lt;li&gt;명세 관점 (Specification Perspective): 도메인이 아니라 소프트웨어 안에 살아있는 객체들의 책임(객체의 인터페이스)에 초점&lt;/li&gt;
&lt;li&gt;구현 관점 (Implementation Perspective): 실제 작업 수행하는 코드, 객체들의 책임을 수행하는데 필요한 동작(속성, 메서드)하는 코드 작성에 초점&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;역할, 책임, 협력을 이용해 객체 인터페이스를 식별하는 방식
&lt;ol 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;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&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;/li&gt;
&lt;li&gt;인터페이스 정리 (메시지 정리)&lt;/li&gt;
&lt;li&gt;구현 (코드)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;구상한 설계는 코드로 구현하면서 변경됨 -&amp;gt; 코드를 빨리 구현해보고 피드백을 얻으면서 설계를 수정한다.&lt;/li&gt;
&lt;li&gt;객체가 어떤 책임을 수행해야 하는지 결정한 후에 책임을 수행하는데 필요한 객체 속성을 결정한다.&lt;br /&gt;-&amp;gt; 객체의 구현 세부사항을 객체 공용 인터페이스에 노출시키지 않고 구현과 분리하는 기본적인 방법&lt;/li&gt;
&lt;li&gt;UML 자유 수정 가능. UML은 의사소통을 위한 표기법이고, 꼭 지켜야하는 법칙은 아님.&lt;/li&gt;
&lt;li&gt;객체지향 코드에서 클래스 안에 3가지 관점을 모두 각 포함하면서 관점에 대응하는 요소들을 명확하고 깔끔하게 나타내야한다.
&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;/li&gt;
&lt;li&gt;구현관점: 클래스 내부 구현은 철저히 캡슐화 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;도메인 개념을 참조하고, 인터페이스와 구현을 분리하라.&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Programming</category>
      <category>객체지향의 사실과 오해</category>
      <category>역할 책임 책임 관점에서 본 객체지향</category>
      <category>책 정리</category>
      <author>Ginjoe</author>
      <guid isPermaLink="true">https://itdar.tistory.com/393</guid>
      <comments>https://itdar.tistory.com/393#entry393comment</comments>
      <pubDate>Mon, 11 Oct 2021 23:10:10 +0900</pubDate>
    </item>
    <item>
      <title>소프트웨어 장인 (프로페셔널리즘, 실용주의, 자부심) 책 정리</title>
      <link>https://itdar.tistory.com/392</link>
      <description>&lt;h1&gt;소프트웨어 장인 (The Software Craftsman)&lt;/h1&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;1. 21세기의 소프트웨어 개발&lt;/h2&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;소프트웨어 장인정신이 필요해졌다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2. 애자일 (Agile, 민첩)&lt;/h2&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;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;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;애자일 메니페스토(menifesto, 선언문) 원칙들&lt;/li&gt;
&lt;li&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;/li&gt;
&lt;li&gt;기업 차원에서 소웨 장인정신이 필요하다&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3. 소프트웨어 장인정신&lt;/h2&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;소프트웨어 장인정신 메니페스토 (menifesto, 선언문)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;스스로 끊임없이 기술연마, 다른 사람들의 기술연마를 도움&lt;br /&gt;-&amp;gt; 궁극적으로 Professional SW 개발 수준을 높인다.&lt;/li&gt;
&lt;/ul&gt;
&lt;ol 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;/li&gt;
&lt;li&gt;개별적으로 협력하는 것 뿐만 아니라, 프로페셔널 커뮤니티를 조성하는 것을,&lt;/li&gt;
&lt;li&gt;고객과 협업하는 것 뿐만 아니라, 생산적인 동반자 관계를,&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;4. 소프트웨어 장인의 태도&lt;/h2&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;ol 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;/li&gt;
&lt;li&gt;기술 웹사이트&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;끊임없는 훈련
&lt;ol 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;/li&gt;
&lt;li&gt;오픈소스&lt;/li&gt;
&lt;li&gt;페어 프로그래밍&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;사회활동 (다른 개발자와 어울림)&lt;/li&gt;
&lt;li&gt;워라밸 (집중과 삶의 균형)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;5. 영웅, 선의 그리고 프로페셔널리즘&lt;/h2&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;'아니오' 라고 말하는 방법 배우기 (예시, 마케팅 - PM - 개발팀 간의 실패 이야기)&lt;/li&gt;
&lt;li&gt;대안 제시: 아니오 라고 할 때는 대안을 준비해서 제시한다.&lt;/li&gt;
&lt;li&gt;깨어있는 관리자는 개발팀과 동고동락 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;6. 동작하는 소프트웨어&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;최근에는, 동작하는 소프트웨어 -&amp;gt; 고품질의 동작하는 소프트웨어 로 변화하고 있다.&lt;/li&gt;
&lt;li&gt;소프트웨어를 운영하는 것은 정원 돌보기와 유사함: 꾸준히 해야 일이 적음&lt;/li&gt;
&lt;li&gt;코드 품질과 기능구현 시간의 상관관계는 반비례 관계&lt;/li&gt;
&lt;li&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;/li&gt;
&lt;li&gt;단위테스트 작성은 별도로 스케줄 잡는 작업이 아니고, 코드 작성에 녹아있어야 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;레거시(legacy) 코드
&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;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;7. 기술적 실행 관례&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;관리자나 개발자 등이 TDD, XP 등의 기술적 실행 관례에 관심을 가져야 하는 이유
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;무슨 가치가 있는지, 동료를 설득하기 위함과 상통함&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;애자일은 빠르고 짧은 피드백 루프로 올바른 일(right things)을 하는 것을 확인.&lt;/li&gt;
&lt;li&gt;소프트웨어 장인정신은 기술적 실행 관례에 집중해서 올바른 실행을 하는 것을 확인.&lt;/li&gt;
&lt;li&gt;애자일의 기술적 실행 관례는 적용 전에 실상황 파악을 잘 해야한다.&lt;/li&gt;
&lt;li&gt;절차적 관례 &amp;gt; 실행적 관례 라고 애자일 코치나 컨설팅회사들이 주장하지만 아니다. 둘 다 중요하다.&lt;/li&gt;
&lt;li&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;/li&gt;
&lt;li&gt;지식 공유&lt;/li&gt;
&lt;li&gt;줄어드는 버그&lt;/li&gt;
&lt;li&gt;전체적으로 자동화되고 릴리즈가 빨라짐&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;실행관례 (XP 등) 예시 및 장점
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;자동화된 테스트: 피드백 루프 빠름, QA를 패스하여 비지니스 시간 단축&lt;/li&gt;
&lt;li&gt;테스트 먼저: 하나씩 집중, 잘 정리된 요구사항 역할, 오버엔지니어링 줄임&lt;/li&gt;
&lt;li&gt;TDD: 테스트가 코딩 방향을 주도하면 복잡한 코딩 불가함&lt;/li&gt;
&lt;li&gt;살아있는 문서역할을 함 설계, 단순성, 유지보수 용이성에 빠른 피드백&lt;/li&gt;
&lt;li&gt;지속가능한 통합: 코드 통합 시 전체 테스트 -&amp;gt; 버그가 쌓이지 않게, &quot;일단 멈추고 버그부터 수정&quot;&lt;/li&gt;
&lt;li&gt;페어프로그래밍: 코드리뷰는 피드백 루프 주기가 길다.&lt;br /&gt;즉각적인 피드백, 코딩 표준 정의/유지에 도움&lt;/li&gt;
&lt;li&gt;리팩토링: 자주 건드리는 곳의 작은 부분에서 시작 (꼭 필요한 부분)&lt;br /&gt;유지보수 쉬운 클린코드는 개발속도를 높이고, 버그 가능성을 낮춘다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&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;/li&gt;
&lt;li&gt;항상 무엇을 하고 있고, 왜 하고 있는지를 질문한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&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;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;8. 길고 긴 여정&lt;/h2&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;br /&gt;인생을 큰 장기 프로젝트 개념으로 생각한다.&lt;/li&gt;
&lt;li&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;/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;/ul&gt;
&lt;/li&gt;
&lt;li&gt;회사 등의 일도 커리어 투자의 개념으로 접근 (이기적 마음으로 커리어 활동 x)&lt;/li&gt;
&lt;li&gt;지식은 영원하고 돈과 안정은 영원 할 수 없다.&lt;/li&gt;
&lt;li&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;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;일(직장)을 신중히 선택하고 고객들을 만족시켜 나가면, SW장인으로서 좋은 커리어 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;9. 인재 채용&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&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;/ul&gt;
&lt;/li&gt;
&lt;li&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;/ul&gt;
&lt;/li&gt;
&lt;li&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;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;10. 소프트웨어 장인 면접하기&lt;/h2&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;회사/프로젝트 장단점을 다 설명해줄 필요가 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&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;좋은 면접은 자유토론과 같다. -&amp;gt; 이를 통해 실제 경험을 알아내기 좋다.&lt;/li&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;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;11. 잘못된 면접방식&lt;/h2&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;/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;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;12. 낮은 사기의 대가&lt;/h2&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;/li&gt;
&lt;li&gt;낮은 동기부여 -&amp;gt; 회사의 일하는 방식 개선이 불가하다.&lt;br /&gt;-&amp;gt; 소프트웨어 장인이 열정을 불어넣을 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;13. 배움의 문화&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&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;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;/li&gt;
&lt;li&gt;그룹 토론회&lt;/li&gt;
&lt;li&gt;업무 교환 (얼마의 기간동안)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&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;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;배움의 문화는 개발자 포함 모두가 해나가야 할 일&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;14. 기술적 변화의 실행&lt;/h2&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;무지, 대중(팔로워), 냉소주의, 트라우마, 너무 바쁜, 상사, 몰상식, 피해망상, 무능력 등등
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;바꾸려면 논쟁이 필요하고 -&amp;gt; 따라서 용기가 필요하다.&lt;/li&gt;
&lt;li&gt;논쟁의 방법: 상대의 언어로 말하기, 말할 내용에 대해 스스로 잘 이해하기, 상대방 존중, 경청하는 법 알기&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&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;/li&gt;
&lt;li&gt;모범을 보여라&lt;/li&gt;
&lt;li&gt;부분적으로 시작한다&lt;/li&gt;
&lt;li&gt;점진적 반복/관찰/수용&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;소프트웨어 장인으로서 기술적 변화 도입을 위해서.. 소통을 명확히 하고, 신뢰를 이끌어낸다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;15. 실용주의 장인정신&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;고품질은 고비용이다 -&amp;gt; 편견&lt;/li&gt;
&lt;li&gt;품질은 선택사항이 아니고, 최소한의 품질을 유지한다.&lt;/li&gt;
&lt;li&gt;소프트웨어 장인은 TDD 같은 실행 관례들을 마스터하고 있고, 시작부터 짧은 주기로 고객에게 전달하는 것을 목표로 한다.
&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;애플리케이션 크기가 커질수록 XP 실행관례를 체득한 소웨 장인이 훨씬 빠르다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;TDD는 항상 필요한 것은 아니다? (그렇다, 그렇지만 논의가 무의미하다)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;적응되고 체득하면 모든 부분에서 훨씬 좋다 (UI 제외)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;리팩토링 -&amp;gt; 레거시 수정 시 or 새로 추가 시 영향 받는 레거시&lt;br /&gt;위의 상황들에 대해 리팩토링 (불필요한 리팩토링 지양)&lt;/li&gt;
&lt;li&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;/ul&gt;
&lt;/li&gt;
&lt;li&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;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;단순한 설계를 위한 네가지 원칙 (켄트 벡)
&lt;ol 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;/li&gt;
&lt;li&gt;중복의 최소화 (동작이나 설정에 중복이 있어서는 안된다)&lt;/li&gt;
&lt;li&gt;구성요소의 최소화 (메서드, 클래스, 모듈의 수는 가능한 적어야 한다)&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&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;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;새로운 스킬, 실행 관례 등을 배우는 것은 병목점이 될 수 있지만,&lt;br /&gt;TDD 자체 (타이핑) 가 병목점이 되진 않는다.&lt;/li&gt;
&lt;li&gt;장인으로서의 역할은 특별히 이슈가 되지 않을 정도까지 품질 비용을 낮추는 것&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;16. 소프트웨어 장인으로서의 커리어&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;소프트웨어 장인: &quot;열정&quot;, &quot;겸손&quot;, &quot;정직과 용기&quot;&lt;/li&gt;
&lt;li&gt;장인에게 직장은 커리어를 위한 지속적인 투자 개념도 갖는다.&lt;/li&gt;
&lt;li&gt;커리어 관련해서 스스로에게 질문해본다.
&lt;ol 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;/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;/li&gt;
&lt;li&gt;나의 고용주와 생산적인 동반자 관계를 맺을 수 있나? 양측 모두 가치 얻고 행복할 수 있나?&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&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;/ul&gt;
&lt;/li&gt;
&lt;li&gt;본인에게 맞는 답들을 잘 모르겠다면 -&amp;gt; 사람들을 만나서 물어라&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;소프트웨어 장인은 사명을 갖는다.&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;더 나아지는데 집중하고, 계속 커리어에 투자하고, 배우고, 가르치고, 공유한다.&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;고객에게 항상 가치를 전달한다.&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;그러면서, 자부심을 갖는다.&lt;/h4&gt;</description>
      <category>Programming</category>
      <category>Software Craftsman</category>
      <category>기술서적 정리</category>
      <category>소프트웨어 장인</category>
      <category>책 정리</category>
      <author>Ginjoe</author>
      <guid isPermaLink="true">https://itdar.tistory.com/392</guid>
      <comments>https://itdar.tistory.com/392#entry392comment</comments>
      <pubDate>Tue, 5 Oct 2021 00:11:38 +0900</pubDate>
    </item>
    <item>
      <title>[LeetCode] 771. Jewels and Stones(코딩테스트, 릿코드, tech interview)</title>
      <link>https://itdar.tistory.com/391</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;657&quot; data-origin-height=&quot;127&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cdDT2h/btrfG2hxqk3/8FxVJbtHOqEkW02zKUhnq0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cdDT2h/btrfG2hxqk3/8FxVJbtHOqEkW02zKUhnq0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cdDT2h/btrfG2hxqk3/8FxVJbtHOqEkW02zKUhnq0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcdDT2h%2FbtrfG2hxqk3%2F8FxVJbtHOqEkW02zKUhnq0%2Fimg.png&quot; data-origin-width=&quot;657&quot; data-origin-height=&quot;127&quot; data-ke-mobilestyle=&quot;widthOrigin&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;/&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;Hash 쓰는 것 외에 뭐 딱히 퍼포먼스 향상시킬 것이 있나 싶다.&lt;/p&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;// Process&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;// 1. Input&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;// 2. jewels 로 해시셋 만든다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;// 3. stones 에서 jewel 이 있는지 확인해서&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;//&amp;nbsp; 3.1. jewel 이면 counting&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;// 4. Return count&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1632238221127&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import java.util.HashSet;
import java.util.Set;

public class LeetCode_0771_JewelsAndStones {

    public int numJewelsInStones(String jewels, String stones) {
        Set&amp;lt;Character&amp;gt; set = new HashSet&amp;lt;&amp;gt;();

        for (int i = 0; i &amp;lt; jewels.length(); ++i) {
            set.add(jewels.charAt(i));
        }

        int count = 0;
        for (int i = 0; i &amp;lt; stones.length(); ++i) {
            if (set.contains(stones.charAt(i))) {
                ++count;
            }
        }

        return count;
    }

}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://itdar.tistory.com/389&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;2021.08.31 - [Programming] - [Database] 트랜잭션 격리수준에 관하여.. (데이터베이스 Transaction isolation level)&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1632238298063&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[Database] 트랜잭션 격리수준에 관하여.. (데이터베이스 Transaction isolation level)&quot; data-og-description=&quot;[MySQL] 데이터베이스 트랜잭션의 격리수준에 관하여.. (Database transaction isolation level) 목차 트랜잭션 격리수준 이란 무엇인가? 격리수준에 따라 발생할 수 있는 문제점들은? 격리수준의 종류는? 격&quot; data-og-host=&quot;itdar.tistory.com&quot; data-og-source-url=&quot;https://itdar.tistory.com/389&quot; data-og-url=&quot;https://itdar.tistory.com/389&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/WXUh9/hyLFtoAn5f/cQkSlKxkv6kE4Tfn2vuLkK/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/baEjrU/hyLFGnVy02/ooewEkvCfN5FAGApyAmQ4K/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800&quot;&gt;&lt;a href=&quot;https://itdar.tistory.com/389&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://itdar.tistory.com/389&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/WXUh9/hyLFtoAn5f/cQkSlKxkv6kE4Tfn2vuLkK/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/baEjrU/hyLFGnVy02/ooewEkvCfN5FAGApyAmQ4K/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[Database] 트랜잭션 격리수준에 관하여.. (데이터베이스 Transaction isolation level)&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;[MySQL] 데이터베이스 트랜잭션의 격리수준에 관하여.. (Database transaction isolation level) 목차 트랜잭션 격리수준 이란 무엇인가? 격리수준에 따라 발생할 수 있는 문제점들은? 격리수준의 종류는? 격&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;itdar.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&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://itdar.tistory.com/381&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;2021.08.05 - [Algorithm/Programmers] - [프로그래머스] 전화번호 목록, 알고리즘 문제풀이, Hash, 해시&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1632238307965&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[프로그래머스] 전화번호 목록, 알고리즘 문제풀이, Hash, 해시&quot; data-og-description=&quot;이전에 파이썬으로 풀었던 방식은, 정렬 후에 두개의 for 문을 사용하되 해당 순서의 길이보다 긴 것들만 찾아보는 식으로 풀었었다. 21년 3월 효율성 테스트케이스 추가되면서 안되는 듯해서 연&quot; data-og-host=&quot;itdar.tistory.com&quot; data-og-source-url=&quot;https://itdar.tistory.com/381&quot; data-og-url=&quot;https://itdar.tistory.com/381&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/jy2DF/hyLHG0SoQu/fGAs5hfwyrXxoORU4VJWn1/img.png?width=297&amp;amp;height=41&amp;amp;face=0_0_297_41,https://scrap.kakaocdn.net/dn/PoiZT/hyLFEXV7RL/6siO9dCq9Jsctx6jTkQPB1/img.png?width=297&amp;amp;height=41&amp;amp;face=0_0_297_41,https://scrap.kakaocdn.net/dn/BfJqn/hyLHEaU2F9/0rW4azd8ZJJAmMRaagG1q0/img.png?width=264&amp;amp;height=200&amp;amp;face=0_0_264_200&quot;&gt;&lt;a href=&quot;https://itdar.tistory.com/381&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://itdar.tistory.com/381&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/jy2DF/hyLHG0SoQu/fGAs5hfwyrXxoORU4VJWn1/img.png?width=297&amp;amp;height=41&amp;amp;face=0_0_297_41,https://scrap.kakaocdn.net/dn/PoiZT/hyLFEXV7RL/6siO9dCq9Jsctx6jTkQPB1/img.png?width=297&amp;amp;height=41&amp;amp;face=0_0_297_41,https://scrap.kakaocdn.net/dn/BfJqn/hyLHEaU2F9/0rW4azd8ZJJAmMRaagG1q0/img.png?width=264&amp;amp;height=200&amp;amp;face=0_0_264_200');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[프로그래머스] 전화번호 목록, 알고리즘 문제풀이, Hash, 해시&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;이전에 파이썬으로 풀었던 방식은, 정렬 후에 두개의 for 문을 사용하되 해당 순서의 길이보다 긴 것들만 찾아보는 식으로 풀었었다. 21년 3월 효율성 테스트케이스 추가되면서 안되는 듯해서 연&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;itdar.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Algorithm/Leet Code</category>
      <category>Jewels and stones</category>
      <category>leetcode</category>
      <category>릿코드</category>
      <author>Ginjoe</author>
      <guid isPermaLink="true">https://itdar.tistory.com/391</guid>
      <comments>https://itdar.tistory.com/391#entry391comment</comments>
      <pubDate>Wed, 22 Sep 2021 00:32:06 +0900</pubDate>
    </item>
    <item>
      <title>[Database] Optimistic lock(낙관적 잠금), Pessimistic lock(비관적 잠금) 에 관하여..</title>
      <link>https://itdar.tistory.com/390</link>
      <description>&lt;h1&gt;Optimistic lock(낙관적 잠금), Pessimistic lock(비관적 잠금) 에 관하여..&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;우선 데이터베이스의 격리수준(Isolation level) 에 대하여 알아야 한다.&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://itdar.tistory.com/389&quot;&gt;트랜잭션 격리수준에 관하여(MySQL).. https://itdar.tistory.com/389&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;목차&lt;/p&gt;
&lt;/blockquote&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;Lock 을 하는 이유는?&lt;/li&gt;
&lt;li&gt;Optimistic lock (낙관적 잠금) 이란?&lt;/li&gt;
&lt;li&gt;Pessimistic lock (비관적 잠금) 이란?&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;각각 어느 상황에서 사용하는 것이 좋을지?&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Optimistic lock (낙관적 잠금)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;동시 레코드 업데이트가 드물거나, lock 오버헤드가 높은 것으로 예상될 때 사용한다.&lt;/li&gt;
&lt;li&gt;데이터베이스에 연결을 유지하고 있을 필요가 없는 대용량 시스템, 3계층 시스템 등 (클라이언트가 pool 에서 연결을 가져와서 lock 을 유지할 수 없음)&lt;/li&gt;
&lt;li&gt;낙관적으로 바라보는 곳에 사용한다 (Data 충돌이 거의 일어나지 않을 것이라는 가정을 한다)&lt;/li&gt;
&lt;li&gt;아예 데이터 충돌이 나서 dirty read 가 되더라도 무관한 곳에 사용한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Pessimistic lock (비관적 잠금)
&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;데이터베이스에 직접 연결하는 시스템, 2계층 시스템 등&lt;/li&gt;
&lt;li&gt;비관적으로 바라보는 곳에 사용한다 (Data 충돌이 분명 일어날 것이라는 가정을 한다)&lt;/li&gt;
&lt;li&gt;금융 관련 등 항상 정확해야 하는 곳에 사용한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Lock 을 하는 이유는?&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Database 가 Concurrency control (동시성 제어) 을 할 때,&lt;br /&gt;트랜잭션의 격리수준과 비지니스 로직에 맞추어 Lock 을 하여&lt;br /&gt;데이터 충돌이 나지 않도록 하고,&lt;br /&gt;충돌이 났다면 문제를 뒷처리를 하기 위함이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Optimistic lock (낙관적 잠금) 이란?&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;레코드(데이터) 잠금을 사용하지 않는 RDBMS 에서 사용되는 동시성 제어 방법이다.&lt;/li&gt;
&lt;li&gt;여러 트랜잭션이 동일한 데이터에 업데이트를 시도할 수 있고, 커밋할 때만 유효성이 검사된다.&lt;/li&gt;
&lt;li&gt;데이터베이스 수준의 Roll-back 이 없기에, 충돌 시 대처방안을 구현해야함&lt;/li&gt;
&lt;li&gt;Application level (JPA 등) 에서 동작한다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;version 등의 컬럼을 추가해서 여러 트랜잭션 내에서 하나의 데이터에 중복 업데이트를 확인한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Pessimistic lock (비관적 잠금) 이란?&lt;/h3&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;다음 사용자는 대기한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Database level 의 transaction 을 이용한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Reference&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://www.ibm.com/docs/en/rational-clearquest/7.1.0?topic=clearquest-optimistic-pessimistic-record-locking&quot;&gt;https://www.ibm.com/docs/en/rational-clearquest/7.1.0?topic=clearquest-optimistic-pessimistic-record-locking&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://stackoverflow.com/questions/129329/optimistic-vs-pessimistic-locking&quot;&gt;https://stackoverflow.com/questions/129329/optimistic-vs-pessimistic-locking&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://sabarada.tistory.com/175&quot;&gt;https://sabarada.tistory.com/175&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://velog.io/@lsb156/JPA-Optimistic-Lock-Pessimistic-Lock&quot;&gt;https://velog.io/@lsb156/JPA-Optimistic-Lock-Pessimistic-Lock&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나중에 &lt;a href=&quot;https://stackoverflow.com/questions/129329/optimistic-vs-pessimistic-locking&quot;&gt;https://stackoverflow.com/questions/129329/optimistic-vs-pessimistic-locking&lt;/a&gt;&lt;br /&gt;위 질답은 전체 번역해보고 싶다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Programming</category>
      <category>Database</category>
      <category>Lock</category>
      <category>locking</category>
      <category>optimistic lock</category>
      <category>pessimistic lock</category>
      <author>Ginjoe</author>
      <guid isPermaLink="true">https://itdar.tistory.com/390</guid>
      <comments>https://itdar.tistory.com/390#entry390comment</comments>
      <pubDate>Mon, 6 Sep 2021 23:27:54 +0900</pubDate>
    </item>
    <item>
      <title>[Database] 트랜잭션 격리수준에 관하여.. (데이터베이스 Transaction isolation level)</title>
      <link>https://itdar.tistory.com/389</link>
      <description>&lt;h1&gt;[MySQL] 데이터베이스 트랜잭션의 격리수준에 관하여.. (Database transaction isolation level)&lt;/h1&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;목차&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;트랜잭션 격리수준 이란 무엇인가?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;격리수준에 따라 발생할 수 있는 문제점들은?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;격리수준의 종류는?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;격리수준에 따른 문제 발생 표&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;트랜잭션 격리수준 이란 무엇인가? (Transaction isolation level)&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&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;/ul&gt;
&lt;/li&gt;
&lt;li&gt;비지니스 모델에 따라서, 어떤 결과가 나오는지에 맞춰서 격리수준을 결정한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;격리수준에 따라 발생할 수 있는 문제점들은? (부정합 문제 Problems)&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Dirty read
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;A 트랙잭션이 데이터를 핸들링하고 있는데, B 트랜잭션에서 해당 데이터를 읽을 수 있는 것을 칭한다.&lt;/li&gt;
&lt;li&gt;Commit / Roll-back 에 따라서 데이터의 부정합이 발생하기 쉽다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Non-repeatable read
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;하나의 트랜잭션에서 데이터를 읽는데, 때에 따라서 값이 달라질 수 있는 경우를 말한다. (update, delete)&lt;/li&gt;
&lt;li&gt;다른 트랜잭션과 겹쳤을 때 데이터가 Undo 영역 등에 있다가 Commit 되거나 하면 해당 문제가 생길 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Phantom read
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;하나의 트랜잭션에서 데이터를 읽을 때, 데이터가 없다가 생기는 경우를 말한다. (insert)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;격리수준의 종류는? (Sort of Isolation level)&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Read uncomitted
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;A 트랜잭션이 데이터를 핸들링하고 있을 때, B 트랜잭션에서 해당 데이터를 직접 접근해서 읽는 것을 칭한다.&lt;/li&gt;
&lt;li&gt;읽었는데 문제가 생겨서 rollback 을 하는 경우 등의 데이터의 부정합이 발생하기 쉽다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Read comitted
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;트랜잭션에서 변경된 데이터는 Commit 이 완료되어야만 읽을 수 있다.&lt;/li&gt;
&lt;li&gt;A 트랜잭션이 데이터를 핸들링하고 있을 때 B 트랜잭션에서 읽는다면, 해당 데이터의 commit 되기 전에는 undo 영역에서 데이터를 읽는다.&lt;/li&gt;
&lt;li&gt;A 트랜잭션에서 어떤 변화를 일으켜도, commit 전에는 B 트랜잭션에서 undo 영역의 기존 데이터를 읽으므로 Dirty read 문제가 없다.&lt;br /&gt;하지만, A 트랜잭션은 Commit 을 하고, B 트랜잭션은 그 이전부터 이후까지 지속한다면 시작과 끝의 값이 다른 문제 (Non-repeatable read) 가 생길 수 있다. (update, delete)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Repeatable read
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;트랜잭션에 순차적으로 고유의 트랜잭션 번호를 부여한다. 접근하는 데이터의 트랜잭션 번호와 비교해서, 진행 중인 트랜잭션의 번호보다 뒤에 있으면 백업되어있는 (Undo 영역) 데이터를 읽도록 한다.&lt;/li&gt;
&lt;li&gt;트랜잭션이 오래 지속되면 Undo 영역 사이즈가 커져서 성능 이슈가 생길 수 있다.&lt;/li&gt;
&lt;li&gt;Phantom read 문제는 발생 가능하다. (update, delete) 는 막지만, insert 를 막지는 않는다는 것)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Serializable
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;하나의 트랜잭션이 진행되고 있는 동안에는 다른 트랜잭션이 접근 할 수 없다.&lt;br /&gt;즉, Serialize 하게 진행된다는 것으로, 따라서 동시성(Parallel) 하게 진행되어야 하는 성능이 중요한 곳은 사용 불가하다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;격리수준에 따른 문제발생 표 (Comparison table)&lt;/h3&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&quot;center&quot;&gt;&amp;nbsp;&lt;/th&gt;
&lt;th align=&quot;center&quot;&gt;Dirty read&lt;/th&gt;
&lt;th align=&quot;center&quot;&gt;Non-Repeatable read&lt;/th&gt;
&lt;th align=&quot;center&quot;&gt;Phantom read&lt;/th&gt;
&lt;th&gt;&amp;nbsp;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&quot;center&quot;&gt;Read uncomitted&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;O&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;O&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;O&lt;/td&gt;
&lt;td&gt;거의 사용안함&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;center&quot;&gt;Read comitted&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;X&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;O&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;O&lt;/td&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;center&quot;&gt;Repeatable read&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;X&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;X&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;O (InnoDB는 X)&lt;/td&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;center&quot;&gt;Serializable&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;X&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;X&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;X&lt;/td&gt;
&lt;td&gt;동시성이 중요한 곳에선 사용 못함 (성능저하)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&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://itdar.tistory.com/390&quot;&gt;2021.09.06 - [Programming] - [Database] Optimistic lock(낙관적 잠금), Pessimistic lock(비관적 잠금) 에 관하여..&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1662038793276&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[Database] Optimistic lock(낙관적 잠금), Pessimistic lock(비관적 잠금) 에 관하여..&quot; data-og-description=&quot;Optimistic lock(낙관적 잠금), Pessimistic lock(비관적 잠금) 에 관하여.. 우선 데이터베이스의 격리수준(Isolation level) 에 대하여 알아야 한다. 트랜잭션 격리수준에 관하여(MySQL).. https://itdar.tistory..&quot; data-og-host=&quot;itdar.tistory.com&quot; data-og-source-url=&quot;https://itdar.tistory.com/390&quot; data-og-url=&quot;https://itdar.tistory.com/390&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/VPeXj/hyPEL54KL3/igtOFdJBPM19nehyaSNvfK/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/daWfg0/hyPEBPYJeY/WMmU7tiikahD0gajWxAqgK/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800&quot;&gt;&lt;a href=&quot;https://itdar.tistory.com/390&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://itdar.tistory.com/390&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/VPeXj/hyPEL54KL3/igtOFdJBPM19nehyaSNvfK/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/daWfg0/hyPEBPYJeY/WMmU7tiikahD0gajWxAqgK/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[Database] Optimistic lock(낙관적 잠금), Pessimistic lock(비관적 잠금) 에 관하여..&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Optimistic lock(낙관적 잠금), Pessimistic lock(비관적 잠금) 에 관하여.. 우선 데이터베이스의 격리수준(Isolation level) 에 대하여 알아야 한다. 트랜잭션 격리수준에 관하여(MySQL).. https://itdar.tistory..&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;itdar.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Programming</category>
      <category>isolation level</category>
      <category>MySQL</category>
      <category>Transaction</category>
      <category>격리수준</category>
      <category>데이터베이스</category>
      <category>트랜잭션</category>
      <author>Ginjoe</author>
      <guid isPermaLink="true">https://itdar.tistory.com/389</guid>
      <comments>https://itdar.tistory.com/389#entry389comment</comments>
      <pubDate>Tue, 31 Aug 2021 01:15:27 +0900</pubDate>
    </item>
    <item>
      <title>[네트워크] 세션과 토큰에 관하여.. (feat. 쿠키) / Session, Token, Cookie, Network</title>
      <link>https://itdar.tistory.com/388</link>
      <description>&lt;h1&gt;네트워크의 토큰과 세션에 관하여..&lt;/h1&gt;
&lt;p&gt;면접에서 나온 질문인데, 분명 기술 질문 관련해서 정리하면서 몇번 읽었던 내용이었지만,&lt;br&gt;실제로 접하며 느낀 적이 없어서 그런가 깔끔하게 대답을 못해서 다시 정리한다.&lt;/p&gt;
&lt;h3&gt;세션과 토큰이 나온 배경&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;HTTP 의 stateless 특성 때문에, 로그인 등의 상태를 유지해야 하는 경우를 보완하기 위해 나옴.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;세션이란?&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;통신을 하기 위해서 서로 연결된 순간부터 통신을 마칠 때 까지의 &lt;strong&gt;기간&lt;/strong&gt;  &lt;ul&gt;
&lt;li&gt;즉, HTTP 세션이란 클라이언트가 웹서버에 연결된 순간부터 통신 종료 까지의 &lt;strong&gt;기간&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;쿠키를 기반으로 동작한다. (여기서 쿠키는, 세션에 앞서 stateless 문제를 해결하기 위해 나왔다)  &lt;ul&gt;
&lt;li&gt;보안 문제 등으로 세션 아이디만 쿠키에 넣어 왔다갔다 할 수 있도록 세션을 만들었다.&lt;/li&gt;
&lt;li&gt;쿠키만 있을 때에는 쿠키 자체에 로그인 정보 자체를 넣어서 보내기 때문에 탈취 당하면 문제가 됨&lt;/li&gt;
&lt;li&gt;그나마 세션을 적용하면 쿠키 안에 세션ID 등만 들어있기에, 탈취 당해도 시간이 지나면 세션 expired 등으로 보호를 할 수 있음.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;인증 성공 후 세션 관련 정보를 DB에 저장하여, 많아지면 부하가 생길 수 있고 확장성이 좋지 않다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;세션이 사용되는 방법&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;클라이언트: 로그인한다 (request)&lt;/li&gt;
&lt;li&gt;서버: 로그인사용자를 검증, 유효하면 고유ID를 세션저장소에 저장 후 세션ID를 만들어서 반환 (response)&lt;/li&gt;
&lt;li&gt;클라이언트: 세션ID 저장 후, 이제 End point (인증 필요 요청) 접근 시에 쿠키에 세션ID를 넣어서 요청 (request)&lt;/li&gt;
&lt;li&gt;서버: 쿠키에서 세션ID를 확인하고 저장소(DB)에서 검증 후 요청에 대한 응답 반환 (response)&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;토큰이란?&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;인증을 수행하는 방법 중 하나이다.  &lt;/li&gt;
&lt;li&gt;세션기반은 서버의 메모리 또는 DB에 유지하여 서버에 부하가 발생할 수 있으나,&lt;br&gt;토큰은 서버에서 검증만 하면 되기 때문에 서버 부담이 적고 확장성을 높였다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;토큰이 사용되는 방법&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;클라이언트: 로그인한다 (request)&lt;/li&gt;
&lt;li&gt;서버: 로그인사용자를 검증, 유효하면 토큰을 발급한다 (response)&lt;/li&gt;
&lt;li&gt;클라이언트: 토큰을 저장하고, 이제 End point (인증 필요 요청) 접근 시에 토큰을 헤더에 담아서 요청 (request)&lt;/li&gt;
&lt;li&gt;서버: 토큰을 검증하고 요청에 응답 반환 (response)&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;세션과 토큰의 차이점은?&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;토큰은 클라이언트 측에 저장이 되고, 세션은 서버의 메모리나 데이터베이스에 저장된다.      &lt;ul&gt;
&lt;li&gt;위 이유 때문에 안정성은 -&amp;gt; 세션 &amp;gt; 토큰&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;토큰 사이즈 &amp;gt; 세션 ID 사이즈&lt;/li&gt;
&lt;li&gt;세션의 경우 클러스터 / 분산서버 환경에서 요청이 나뉘는 경우 요청이 들어가는 서버에 따라서 상태가 변할 수 있다.  &lt;ul&gt;
&lt;li&gt;따라서, 토큰을 사용하는 것이 일반적 (확장성이 좋다)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Programming</category>
      <category>Authentication</category>
      <category>cookie</category>
      <category>Network</category>
      <category>Session</category>
      <category>Token</category>
      <author>Ginjoe</author>
      <guid isPermaLink="true">https://itdar.tistory.com/388</guid>
      <comments>https://itdar.tistory.com/388#entry388comment</comments>
      <pubDate>Mon, 30 Aug 2021 22:55:22 +0900</pubDate>
    </item>
    <item>
      <title>Deadlock 데드락에 관하여.. 멀티쓰레드 사용 시,</title>
      <link>https://itdar.tistory.com/387</link>
      <description>&lt;h1&gt;멀티쓰레드 사용 시, 데드락에 관하여..&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;데드락의 발생 조건&lt;/li&gt;
&lt;li&gt;데드락을 해결을 위한 방법들&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;데드락의 발생 조건&lt;/h2&gt;
&lt;p&gt;아래 4가지 조건을 동시에 충족하면 데드락이 발생한다.&lt;/p&gt;
&lt;h3&gt;1. Mutual Exclusion(상호배제, mutex - 자원에 대한 동시접근 불가)&lt;/h3&gt;
&lt;p&gt;한번에 여러 프로세스(혹은 쓰레드)가 한 자원에 접근하지 못하도록 막음&lt;br&gt;(만약 동시에 자원 접근이 가능하다면 애초에 다른 프로세스가 다 쓰길 기다릴 필요가 없다)  &lt;/p&gt;
&lt;h3&gt;2. Hold and Wait(점유대기)&lt;/h3&gt;
&lt;p&gt;자원을 가지고 있는 상태에서 다른 프로세스가 쓰는 다른 자원을 기다리는 상태  &lt;/p&gt;
&lt;h3&gt;3. No Preemption(선점불가)&lt;/h3&gt;
&lt;p&gt;다른 프로세스가 이미 점유한 자원을 강제로 뺏어오지 못함&lt;br&gt;우선권이 우선한다는 뜻의 &amp;quot;선점&amp;quot;  &lt;/p&gt;
&lt;h3&gt;4. Circular Wait(환형대기, 순환 형태로 대기함)&lt;/h3&gt;
&lt;p&gt;내가 일을 하려면 내가 일을 끝내야 수행이 가능한 모순적인 상황 (돌고 돌아서 나에게 돌아옴)&lt;/p&gt;
&lt;h2&gt;그럼 이 데드락을 해결하려면?&lt;/h2&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;h3&gt;데드락의 예방(Prevention)&lt;/h3&gt;
&lt;p&gt;위 4가지 조건은 동시에 충족돼야 데드락이 발생한다. 그러므로 그 중 하나라도 발생하지 않도록 시스템 차원에서 막아버리면 해결된다.&lt;br&gt;근데 이 방법은 대부분 자원이 낭비되는 경향이 있다. 발생 가능성을 원천봉쇄하려면 성능이 나빠지거나 또 다른 문제를 발생시킬 수 있다.&lt;/p&gt;
&lt;h3&gt;데드락의 회피(Avoidance)&lt;/h3&gt;
&lt;p&gt;교착상태의 원칙적인 발생 가능성(조건)은 그냥 두고, 발생을 막는 알고리즘을 적용해서 해결한다.&lt;br&gt;은행원 알고리즘(프로세스가 자원을 요구하는 시점에 자원을 할당해도 안전한지를 검사하여 데드락을 막는 방법)&lt;br&gt;자원할당 그래프 알고리즘 등&lt;/p&gt;
&lt;h3&gt;데드락의 탐지(Detection)와 회복(Recovery)&lt;/h3&gt;
&lt;p&gt;교착상태가 발생하는 것을 아예 안막음. 발생하면 그때서야 해결.  &lt;/p&gt;
&lt;h3&gt;데드락 무시&lt;/h3&gt;
&lt;p&gt;무시해도 좋을 확률로 데드락이 발생한다고 판단되면 그냥 무시&lt;br&gt;왜냐면 데드락 문제는 해결하려면 성능상 손해를 봐야 하기 때문&lt;br&gt;안정성과 성능을 고려해서 데드락 문제를 해결할지 말지를 정한다.  &lt;/p&gt;</description>
      <category>Programming</category>
      <category>Deadlock</category>
      <category>데드락</category>
      <author>Ginjoe</author>
      <guid isPermaLink="true">https://itdar.tistory.com/387</guid>
      <comments>https://itdar.tistory.com/387#entry387comment</comments>
      <pubDate>Thu, 26 Aug 2021 22:38:42 +0900</pubDate>
    </item>
    <item>
      <title>Java 의 final keyword 에 관하여..</title>
      <link>https://itdar.tistory.com/386</link>
      <description>&lt;h1&gt;자바의 final 키워드에 관하여..&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;인터뷰에서 버벅대서 정리한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;자바에서 final 키워드를 사용할 수 있는 곳에는,&lt;br&gt;&lt;strong&gt;class&lt;/strong&gt;, &lt;strong&gt;method&lt;/strong&gt;, &lt;strong&gt;variable&lt;/strong&gt; 에 사용할 수 있다.&lt;/p&gt;
&lt;h3&gt;사용하는 이유는?&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Immutable (불변)&lt;br&gt;-&amp;gt; 따라서 쓰기가 불가하다. (read-only)&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;1. 클래스를 상속받을 수 없도록 만든다.&lt;/h4&gt;
&lt;h4&gt;2. 메서드를 override 가 불가하도록 만든다.&lt;/h4&gt;
&lt;h4&gt;3. 변수를 read-only 상수로 만든다.&lt;/h4&gt;
&lt;blockquote&gt;
&lt;p&gt;가독성을 해치지 않는 범위에서 써야한다고 하는데,&lt;br&gt;개인적으로는 불변해야 하는 엔티티를 정확히 지정해주고 명시해준다는 점에서 가독성이 더 좋아지는 경우가 있다고 본다.&lt;br&gt;그리고.. 상속해서 공통으로 사용하는 변수의 경우 등, 변하지 않아야 하는 내용에 붙여서 버그를 방지할 수 있다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4&gt;요새는 IDE 설정을 통해서 기본적으로 final 을 붙이는 것이 좋은 방향으로 보인다.&lt;/h4&gt;</description>
      <category>Programming</category>
      <category>final</category>
      <category>immutable</category>
      <category>Java</category>
      <category>keyword</category>
      <author>Ginjoe</author>
      <guid isPermaLink="true">https://itdar.tistory.com/386</guid>
      <comments>https://itdar.tistory.com/386#entry386comment</comments>
      <pubDate>Thu, 26 Aug 2021 22:35:21 +0900</pubDate>
    </item>
    <item>
      <title>[LeetCode] 7. Reverse Integer (코딩테스트, 릿코드, tech interview)</title>
      <link>https://itdar.tistory.com/385</link>
      <description>&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;프로그래밍 처음 시작할 때, 막 풀었던 것보다 코드도 깨끗해지고 퍼포먼스도 훨씬 올라가서 나름 좋았다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;646&quot; data-origin-height=&quot;139&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dx9hNw/btrdd4pnsQW/WkqM0OqRASlFXy5v3gZLV0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dx9hNw/btrdd4pnsQW/WkqM0OqRASlFXy5v3gZLV0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dx9hNw/btrdd4pnsQW/WkqM0OqRASlFXy5v3gZLV0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdx9hNw%2Fbtrdd4pnsQW%2FWkqM0OqRASlFXy5v3gZLV0%2Fimg.png&quot; data-origin-width=&quot;646&quot; data-origin-height=&quot;139&quot; data-ke-mobilestyle=&quot;widthOrigin&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;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;3번에 걸쳐서 리팩토링 했고, 최대 퍼포먼스 뽑아냄&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 개인적으로는 2번째 코드가 좀 더 정리하면 가장 읽기 편할 것으로 보여서 좋아보인다.&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;package algorithm_sites.leetcode;

public class LC_0007_ReverseInteger {

    public int reverse_3(int x) {
        if (x == 0) {
            return 0;
        }

        boolean isPositive = x &amp;gt; 0;

        int result = 0;
        int pop;

        try {
            while (x != 0) {
                pop = x % 10;
                x /= 10;

                if (isPositive &amp;amp;&amp;amp; result &amp;gt; (Integer.MAX_VALUE - pop) / 10) {
                    return 0;
                }
                if (!isPositive &amp;amp;&amp;amp; result &amp;lt; (Integer.MIN_VALUE - pop) / 10) {
                    return 0;
                }

                result = (result * 10 + pop);
            }
        } catch (NumberFormatException e) {
            return 0;
        }

        return result;
    }

    public int reverse_2(int x) {
        if (x == 0) {
            return 0;
        }

        boolean isPositive = x &amp;gt; 0;

        StringBuilder sb = new StringBuilder(Integer.toString(Math.abs(x))).reverse();

        int result;

        try {
            result = Integer.parseInt(sb.toString());

            if (!isPositive) {
                return result * -1;
            }

            return result;
        } catch (NumberFormatException e) {
            return 0;
        }

    }

    public int reverse_1(int x) {
        if (x == 0) {
            return 0;
        }

        boolean isPositive;
        if (x &amp;gt; 0) {
            isPositive = true;
        } else {
            isPositive = false;
        }

        StringBuilder sb = new StringBuilder();

        while (x != 0) {
            int temp = x % 10;

            sb.append(Math.abs(temp));

            x /= 10;
        }

        try {
            int result = Integer.parseInt(sb.toString());

            if (!isPositive) {
                return result * -1;
            }

            return result;
        } catch (NumberFormatException e) {
            return 0;
        }

    }

    public static void main(String args[]) {

        LC_0007_ReverseInteger leet = new LC_0007_ReverseInteger();

        int reverse = leet.reverse_3(-321);

        System.out.println(reverse);
    }

}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Algorithm/Leet Code</category>
      <category>Algorithm</category>
      <category>leetcode</category>
      <category>Reverse Integer</category>
      <category>릿코드</category>
      <author>Ginjoe</author>
      <guid isPermaLink="true">https://itdar.tistory.com/385</guid>
      <comments>https://itdar.tistory.com/385#entry385comment</comments>
      <pubDate>Thu, 26 Aug 2021 00:32:53 +0900</pubDate>
    </item>
    <item>
      <title>[LeetCode] 1. Two Sum (코딩테스트, 릿코드, tech interview)</title>
      <link>https://itdar.tistory.com/384</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;릿코드 하나씩 공부하면서 열심히 풀기로&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;575&quot; data-origin-height=&quot;132&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/vX00z/btrc4DshN1O/Qc7npoJVailJpuko7duEK0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/vX00z/btrc4DshN1O/Qc7npoJVailJpuko7duEK0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/vX00z/btrc4DshN1O/Qc7npoJVailJpuko7duEK0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FvX00z%2Fbtrc4DshN1O%2FQc7npoJVailJpuko7duEK0%2Fimg.png&quot; data-origin-width=&quot;575&quot; data-origin-height=&quot;132&quot; data-ke-mobilestyle=&quot;widthOrigin&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;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;1, 2, 3 세번에 걸쳐서 퍼포먼스를 올렸고, 거의 최대치로 나옴&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Process&lt;br /&gt;// 1. Input&lt;br /&gt;// 2. Iterate all with hashmap (i)&lt;br /&gt;// 2.1. Check target-nums[i]&lt;br /&gt;// 2.1.1. If so -&amp;gt; return answer&lt;br /&gt;// 3. Finish&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;processing&quot;&gt;&lt;code&gt;package algorithm_sites.leetcode;

import java.util.*;

public class LC_00001_TowSum {

    public int[] twoSum_1(int[] nums, int target) {
        if (nums.length == 2) {
            return new int[] {0,1};
        }

        for (int i = 0; i &amp;lt; nums.length-1; ++i) {
            for (int j = i+1; j &amp;lt; nums.length; ++j) {
                if (nums[i] + nums[j] == target) {
                    return new int[] {i, j};
                }
            }
        }

        return null;
    }

    public int[] twoSum_2(int[] nums, int target) {
        if (nums.length == 2) {
            return new int[] {0,1};
        }

        Map&amp;lt;Integer, Integer&amp;gt; map = new HashMap&amp;lt;&amp;gt;();
        for (int i = 0; i &amp;lt; nums.length; ++i) {
            map.put(nums[i], i);
        }

        for (int i = 0; i &amp;lt; nums.length; ++i) {
            if (map.containsKey(target-nums[i])) {
                if (map.get(target-nums[i]) != i) {
                    return new int[] {map.get(target-nums[i]), i};
                }
            }
        }

        return null;
    }

    public int[] twoSum_3(int[] nums, int target) {
        if (nums.length == 2) {
            return new int[] {0,1};
        }

        Map&amp;lt;Integer, Integer&amp;gt; map = new HashMap&amp;lt;&amp;gt;();
        for (int i = 0; i &amp;lt; nums.length; ++i) {
            if (map.containsKey(target-nums[i])) {
                return new int[] {map.get(target-nums[i]), i};
            }
            map.put(nums[i], i);
        }

        return null;
    }

    public static void main(String args[]) {
        LC_00001_TowSum lc = new LC_00001_TowSum();

        int[] result = lc.twoSum_3(new int[]{3, 2, 4}, 6);

        for (int i = 0; i &amp;lt; result.length; ++i) {
            System.out.print(result[i] + &quot; &quot;);
        }
    }

}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://itdar.tistory.com/382&quot;&gt;2021.08.06 - [Algorithm] - [Codility] MaxNonoverlappingSegments, 코딜리티 그리디 greedy&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1629823279267&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[Codility] MaxNonoverlappingSegments, 코딜리티 그리디 greedy&quot; data-og-description=&quot;문제는 다음과 같다. 풀이 방법으로 생각했던 것은 다음과 같다. 모든 세그먼트를 하나의 평면으로 통합시키면, 중복은 전부 연결이 된다. 이 때 떨어져있는 세그먼트들의 수를 세면 된다. 통과&quot; data-og-host=&quot;itdar.tistory.com&quot; data-og-source-url=&quot;https://itdar.tistory.com/382&quot; data-og-url=&quot;https://itdar.tistory.com/382&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bkZm1n/hyLmITHh1N/Y9dxLzh5xyFSFPkVa6R1F1/img.png?width=800&amp;amp;height=667&amp;amp;face=0_0_800_667,https://scrap.kakaocdn.net/dn/gNuW6/hyLmSPAdOk/osZkesgGQvgLRvOjfFQOr1/img.png?width=800&amp;amp;height=667&amp;amp;face=0_0_800_667,https://scrap.kakaocdn.net/dn/tLjlS/hyLmK42Tbs/AFNtesejMMkebWSe9Sgoq1/img.png?width=991&amp;amp;height=827&amp;amp;face=0_0_991_827&quot;&gt;&lt;a href=&quot;https://itdar.tistory.com/382&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://itdar.tistory.com/382&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bkZm1n/hyLmITHh1N/Y9dxLzh5xyFSFPkVa6R1F1/img.png?width=800&amp;amp;height=667&amp;amp;face=0_0_800_667,https://scrap.kakaocdn.net/dn/gNuW6/hyLmSPAdOk/osZkesgGQvgLRvOjfFQOr1/img.png?width=800&amp;amp;height=667&amp;amp;face=0_0_800_667,https://scrap.kakaocdn.net/dn/tLjlS/hyLmK42Tbs/AFNtesejMMkebWSe9Sgoq1/img.png?width=991&amp;amp;height=827&amp;amp;face=0_0_991_827');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[Codility] MaxNonoverlappingSegments, 코딜리티 그리디 greedy&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;문제는 다음과 같다. 풀이 방법으로 생각했던 것은 다음과 같다. 모든 세그먼트를 하나의 평면으로 통합시키면, 중복은 전부 연결이 된다. 이 때 떨어져있는 세그먼트들의 수를 세면 된다. 통과&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;itdar.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Algorithm/Leet Code</category>
      <category>Algorithm</category>
      <category>hash</category>
      <category>leetcode</category>
      <category>two sum</category>
      <author>Ginjoe</author>
      <guid isPermaLink="true">https://itdar.tistory.com/384</guid>
      <comments>https://itdar.tistory.com/384#entry384comment</comments>
      <pubDate>Wed, 25 Aug 2021 01:08:24 +0900</pubDate>
    </item>
  </channel>
</rss>