<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>jam 블로그</title>
    <link>https://kid1412.tistory.com/</link>
    <description>다양한 것을 공부해보고파 하는 개발자입니다.</description>
    <language>ko</language>
    <pubDate>Wed, 15 Apr 2026 03:34:56 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>jmkim87</managingEditor>
    <image>
      <title>jam 블로그</title>
      <url>https://tistory1.daumcdn.net/tistory/285654/attach/9cd1d2b83f8f4cd39188bfdc52e752d3</url>
      <link>https://kid1412.tistory.com</link>
    </image>
    <item>
      <title>LLM 추론 엔진 최적화: 효율성과 성능 향상을 위한 심층 분석</title>
      <link>https://kid1412.tistory.com/296</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure data-ke-type=&quot;video&quot; data-ke-style=&quot;alignCenter&quot; data-video-host=&quot;kakaotv&quot; data-video-url=&quot;https://tv.kakao.com/v/454954723&quot; data-video-thumbnail=&quot;https://scrap.kakaocdn.net/dn/4lAKv/hyYM4J12zH/CPENZehufYLJsgOGG2a4gk/img.jpg?width=1024&amp;amp;height=1024&amp;amp;face=0_0_1024_1024,https://scrap.kakaocdn.net/dn/THwTC/hyYM3K8PcA/9v6AcmiSikGcYWlGGsXpd0/img.jpg?width=1024&amp;amp;height=1024&amp;amp;face=0_0_1024_1024&quot; data-video-width=&quot;400&quot; data-video-height=&quot;400&quot; data-video-origin-width=&quot;860&quot; data-video-origin-height=&quot;860&quot; data-ke-mobilestyle=&quot;widthContent&quot; data-video-title=&quot;'jam 블로그'에서 업로드한 동영상&quot; data-video-play-service=&quot;daum_tistory&quot; data-original-url=&quot;&quot;&gt;&lt;iframe src=&quot;https://play-tv.kakao.com/embed/player/cliplink/454954723?service=daum_tistory&quot; width=&quot;400&quot; height=&quot;400&quot; frameborder=&quot;0&quot; allowfullscreen=&quot;true&quot;&gt;&lt;/iframe&gt;
&lt;figcaption&gt;논문 내용을 팟캐스트처럼 ai로 만들었습니다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div id=&quot;SE-cf7d9634-42d3-4b03-8a9f-7b6a0271ac2b&quot; data-a11y-title=&quot;본문&quot; data-compid=&quot;SE-cf7d9634-42d3-4b03-8a9f-7b6a0271ac2b&quot;&gt;
&lt;div&gt;
&lt;div data-direction=&quot;top&quot; data-compid=&quot;SE-cf7d9634-42d3-4b03-8a9f-7b6a0271ac2b&quot; data-unitid=&quot;&quot;&gt;
&lt;div&gt;
&lt;div id=&quot;SE-218a7541-6a1b-476f-a017-ff982dca82ce&quot;&gt;
&lt;p id=&quot;SE-01c7cde2-226c-4301-97ee-8178e79c4f84&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;대규모 언어 모델(LLMs)은 이제 챗봇, 코드 생성, 검색 엔진 등 다양한 분야에서 광범위하게 활용되고 있습니다. 하지만 LLM 추론(Inference) 과정은 모델 크기가 커짐에 따라 막대한 계산 비용과 높은 지연 시간(Latency)을 수반하는 핵심적인 과제입니다. 특히 &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Chain-of-Thought, 복잡한 추론, 에이전트 서비스와 같은 작업 부하는 모델&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;을 반복적으로 호출하면서 추론 비용을 크게 증가시킵니다.&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-421b0012-87c4-43f8-879a-b7e0054325f5&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p id=&quot;SE-d16859c0-6bde-4f92-b5fd-4d2b62d4e61a&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;논문 &lt;/span&gt;&lt;span style=&quot;color: #ba0000;&quot;&gt;&lt;b&gt;A Survey on Inference Engines for Large Language Models: Perspectives on Optimization and Efficiency&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;는 이러한 문제를 해결하기 위해 등장한 LLM 추론 엔진들에 대한 포괄적인 조사를 제공합니다. 다양한 추론 엔진의 최적화 전략과 효율성 관점을 중심으로 현재의 기술 동향과 미래 연구 방향을 제시하고 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-ee822e57-3d2a-4526-9925-cc44eb39c0c6&quot; data-a11y-title=&quot;구분선&quot; data-compid=&quot;SE-ee822e57-3d2a-4526-9925-cc44eb39c0c6&quot;&gt;
&lt;div&gt;
&lt;div data-direction=&quot;top&quot; data-compid=&quot;SE-ee822e57-3d2a-4526-9925-cc44eb39c0c6&quot; data-unitid=&quot;&quot;&gt;
&lt;div&gt;
&lt;div&gt;&lt;hr data-ke-style=&quot;style1&quot; /&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-96e505de-cad8-4de1-a976-87333c468c65&quot; data-a11y-title=&quot;소제목&quot; data-compid=&quot;SE-96e505de-cad8-4de1-a976-87333c468c65&quot;&gt;
&lt;div&gt;
&lt;div data-direction=&quot;top&quot; data-compid=&quot;SE-96e505de-cad8-4de1-a976-87333c468c65&quot; data-unitid=&quot;&quot;&gt;
&lt;div&gt;
&lt;div id=&quot;SE-627776d4-cf11-4e5a-9fe2-9a8642e7f868&quot;&gt;
&lt;p id=&quot;SE-a484d3e3-e4d3-4dfd-8e55-fcbffd41ff3a&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;LLM 추론 과정과 주요 성능 지표&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-25746dde-797a-44dd-b9b8-027afa9f53e1&quot; data-a11y-title=&quot;본문&quot; data-compid=&quot;SE-25746dde-797a-44dd-b9b8-027afa9f53e1&quot;&gt;
&lt;div&gt;
&lt;div data-direction=&quot;top&quot; data-compid=&quot;SE-25746dde-797a-44dd-b9b8-027afa9f53e1&quot; data-unitid=&quot;&quot;&gt;
&lt;div&gt;
&lt;div id=&quot;SE-42bb3471-c517-4edc-aa5b-1d7743ab084f&quot;&gt;
&lt;p id=&quot;SE-79f37b70-bbcf-4344-9596-9b0deff6fd01&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;논문은 주로 디코더 전용 Transformer 아키텍처에 기반한 LLM 추론 과정(Prefill 단계와 Decode 단계)을 설명하며, 추론 성능의 핵심 지표로 &lt;/span&gt;&lt;span style=&quot;color: #ba0000;&quot;&gt;&lt;b&gt;Latency&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; (특히 &lt;/span&gt;&lt;span style=&quot;color: #ba0000;&quot;&gt;첫 토큰 생성 시간인 &lt;/span&gt;&lt;span style=&quot;color: #ba0000;&quot;&gt;&lt;b&gt;TTFT&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;와 &lt;/span&gt;&lt;span style=&quot;color: #ba0000;&quot;&gt;토큰 간 시간인 &lt;/span&gt;&lt;span style=&quot;color: #ba0000;&quot;&gt;&lt;b&gt;TBT&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;)와 &lt;/span&gt;&lt;span style=&quot;color: #ba0000;&quot;&gt;&lt;b&gt;Throughput&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: #ba0000;&quot;&gt;을 강조&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;합니다. &lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-4db53dae-ff0f-4875-9b13-7dc20ccc213f&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p id=&quot;SE-9fd2e997-17d0-49da-aa0f-4ba1e8abf5b0&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이러한 지표들은 사용자의 응답 속도 체감 및 시스템의 전체 처리 용량과 직결되기 때문입니다.&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-3278a330-189a-47a1-a82d-ead01a107342&quot; data-a11y-title=&quot;구분선&quot; data-compid=&quot;SE-3278a330-189a-47a1-a82d-ead01a107342&quot;&gt;
&lt;div&gt;
&lt;div data-direction=&quot;top&quot; data-compid=&quot;SE-3278a330-189a-47a1-a82d-ead01a107342&quot; data-unitid=&quot;&quot;&gt;
&lt;div&gt;
&lt;div&gt;&lt;hr data-ke-style=&quot;style1&quot; /&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-2e89176b-67b2-4c41-8452-5599aba371ca&quot; data-a11y-title=&quot;소제목&quot; data-compid=&quot;SE-2e89176b-67b2-4c41-8452-5599aba371ca&quot;&gt;
&lt;div&gt;
&lt;div data-direction=&quot;top&quot; data-compid=&quot;SE-2e89176b-67b2-4c41-8452-5599aba371ca&quot; data-unitid=&quot;&quot;&gt;
&lt;div&gt;
&lt;div id=&quot;SE-22e14612-5472-4838-b032-f12fcafcd8ed&quot;&gt;
&lt;p id=&quot;SE-6c51160b-3aa5-46e6-a401-3dde011a5277&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;LLM 추론 효율화를 위한 주요 최적화 기법&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-f22e3f35-c62b-4b56-9aa2-0d8ebf74af10&quot; data-a11y-title=&quot;본문&quot; data-compid=&quot;SE-f22e3f35-c62b-4b56-9aa2-0d8ebf74af10&quot;&gt;
&lt;div&gt;
&lt;div data-direction=&quot;top&quot; data-compid=&quot;SE-f22e3f35-c62b-4b56-9aa2-0d8ebf74af10&quot; data-unitid=&quot;&quot;&gt;
&lt;div&gt;
&lt;div id=&quot;SE-fd9976a9-169b-43c8-8061-10f22f2c9a69&quot;&gt;
&lt;p id=&quot;SE-4493fabb-653a-49e8-b03c-a36271e96d94&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;다양한 최적화 전략이 논문에서 다음과 같이 정리되어 있습니다:&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;배치 최적화 (Batch Optimization)&lt;/b&gt;&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 style=&quot;color: #000000;&quot;&gt;여러 요청을 묶어 동시에 처리하여 하드웨어 활용도를 높입니다. &lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #ba0000;&quot;&gt;&lt;b&gt;Dynamic Batching, Continuous Batching, Chunked-prefills&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; 등이 포함됩니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;모델 압축 (Model Compression)&lt;/b&gt;&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 style=&quot;color: #000000;&quot;&gt;모델의 크기와 계산량을 줄입니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;양자화(Quantization)&lt;/b&gt;&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 style=&quot;color: #000000;&quot;&gt;모델 가중치나 활성값을 INT8, INT4 등의 낮은 정밀도로 표현&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;가지치기(Pruning)&lt;/b&gt;&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 style=&quot;color: #000000;&quot;&gt;중요도가 낮은 연결 제거&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;스파스성 최적화 (Sparsity Optimization)&lt;/b&gt;&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 style=&quot;color: #000000;&quot;&gt;모델 또는 계산의 희소성을 활용합니다. &lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #ba0000;&quot;&gt;&lt;b&gt;MoE(Mixture-of-Experts) 모델이나 동적 토큰 스파스성 기법&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이 여기에 포함됩니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;PEFT (Parameter-Efficient Fine-Tuning)&lt;/b&gt;&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 style=&quot;color: #000000;&quot;&gt;전체 모델이 아닌 일부 파라미터만 조정하여 효율성을 높입니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #ba0000;&quot;&gt;&lt;b&gt;LoRA, QLoRA&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; 등이 이에 해당합니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;캐싱 (Caching)&lt;/b&gt;&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 style=&quot;color: #000000;&quot;&gt;이전 계산 결과를 저장하여 재사용합니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;KV 캐싱(Key and Value Caching)&lt;/b&gt;&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 style=&quot;color: #000000;&quot;&gt;이전 Key/Value 벡터를 저장하여 반복 계산 최소화&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #ba0000;&quot;&gt;&lt;b&gt;PagedAttention, RadixAttention, Prompt Caching, Prefix Caching&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;어텐션 최적화 (Attention Optimization)&lt;/b&gt;&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 style=&quot;color: #000000;&quot;&gt;어텐션 메커니즘의 계산 비용을 줄입니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #ba0000;&quot;&gt;&lt;b&gt;FlashAttention&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #ba0000;&quot;&gt;&lt;b&gt;Multi-Query Attention (MQA)&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #ba0000;&quot;&gt;&lt;b&gt;Grouped-Query Attention (GQA)&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #ba0000;&quot;&gt;&lt;b&gt;Multi-Head Latent Attention (MLA)&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; 등&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;샘플링 최적화 (Sampling Optimization)&lt;/b&gt;&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 style=&quot;color: #000000;&quot;&gt;다음 토큰 생성 과정을 가속화합니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;투기적 디코딩(Speculative Decoding)&lt;/b&gt;&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 style=&quot;color: #000000;&quot;&gt;작은 Draft 모델로 여러 토큰을 예측 후 Target 모델이 검증&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;구조화된 출력 (Structured Outputs)&lt;/b&gt;&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 style=&quot;color: #000000;&quot;&gt;JSON Schema나 문법 기반 출력 제어를 통해 응답 형식을 통제합니다. &lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #ba0000;&quot;&gt;&lt;b&gt;Constrained Decoding&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이 이에 해당됩니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-335e48d7-c939-4685-8533-a9cbc903adf3&quot; data-a11y-title=&quot;구분선&quot; data-compid=&quot;SE-335e48d7-c939-4685-8533-a9cbc903adf3&quot;&gt;
&lt;div&gt;
&lt;div data-direction=&quot;top&quot; data-compid=&quot;SE-335e48d7-c939-4685-8533-a9cbc903adf3&quot; data-unitid=&quot;&quot;&gt;
&lt;div&gt;
&lt;div&gt;&lt;hr data-ke-style=&quot;style1&quot; /&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-98dd917a-e1e0-464b-a166-9b10db41c21d&quot; data-a11y-title=&quot;소제목&quot; data-compid=&quot;SE-98dd917a-e1e0-464b-a166-9b10db41c21d&quot;&gt;
&lt;div&gt;
&lt;div data-direction=&quot;top&quot; data-compid=&quot;SE-98dd917a-e1e0-464b-a166-9b10db41c21d&quot; data-unitid=&quot;&quot;&gt;
&lt;div&gt;
&lt;div id=&quot;SE-f2d92fc8-893a-4124-ae76-ed74f20bb4c3&quot;&gt;
&lt;p id=&quot;SE-24108160-6aac-410e-9195-9cf8508411d4&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;주요 LLM 추론 엔진 비교&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-fc1a2b89-96ed-41b5-8901-4dc4ac113358&quot; data-a11y-title=&quot;본문&quot; data-compid=&quot;SE-fc1a2b89-96ed-41b5-8901-4dc4ac113358&quot;&gt;
&lt;div&gt;
&lt;div data-direction=&quot;top&quot; data-compid=&quot;SE-fc1a2b89-96ed-41b5-8901-4dc4ac113358&quot; data-unitid=&quot;&quot;&gt;
&lt;div&gt;
&lt;div id=&quot;SE-8dd05282-95a6-4068-9c91-f69e22705f1c&quot;&gt;
&lt;p id=&quot;SE-912e14a5-4a9f-49c4-a30b-b13da9cf16bb&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;논문은 다음과 같은 오픈 소스 및 상용 추론 엔진들의 특징과 성능을 비교 분석합니다:&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Ollama&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;llama.cpp&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;vLLM&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;DeepSpeed-FastGen&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;TensorRT-LLM&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;TGI&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;PowerInfer&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;LMDeploy&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;LightLLM&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;SGLang&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p id=&quot;SE-1cf30e51-7c95-4d50-8124-8736b90926fd&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이들은 각기 다른 최적화 기법, 하드웨어 호환성, 추론 성능을 제공하고 있어 실제 시스템 구축 시 유용한 비교 자료로 활용될 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-2e78b9e1-e17d-48e7-878b-01e93cc48f2b&quot; data-a11y-title=&quot;구분선&quot; data-compid=&quot;SE-2e78b9e1-e17d-48e7-878b-01e93cc48f2b&quot;&gt;
&lt;div&gt;
&lt;div data-direction=&quot;top&quot; data-compid=&quot;SE-2e78b9e1-e17d-48e7-878b-01e93cc48f2b&quot; data-unitid=&quot;&quot;&gt;
&lt;div&gt;
&lt;div&gt;&lt;hr data-ke-style=&quot;style1&quot; /&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-2b7e6031-b3a4-4bf7-9066-f44d2e5af427&quot; data-a11y-title=&quot;소제목&quot; data-compid=&quot;SE-2b7e6031-b3a4-4bf7-9066-f44d2e5af427&quot;&gt;
&lt;div&gt;
&lt;div data-direction=&quot;top&quot; data-compid=&quot;SE-2b7e6031-b3a4-4bf7-9066-f44d2e5af427&quot; data-unitid=&quot;&quot;&gt;
&lt;div&gt;
&lt;div id=&quot;SE-98aff303-6bec-4914-8534-f8e02c31c202&quot;&gt;
&lt;p id=&quot;SE-e497908b-1566-4235-811d-7ad1dd2b2c95&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;결론&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-038ef085-7d68-43bf-83d5-0827e4843c91&quot; data-a11y-title=&quot;본문&quot; data-compid=&quot;SE-038ef085-7d68-43bf-83d5-0827e4843c91&quot;&gt;
&lt;div&gt;
&lt;div data-direction=&quot;top&quot; data-compid=&quot;SE-038ef085-7d68-43bf-83d5-0827e4843c91&quot; data-unitid=&quot;&quot;&gt;
&lt;div&gt;
&lt;div id=&quot;SE-7bff9661-5dac-4193-93fa-9f20890d48a3&quot;&gt;
&lt;p id=&quot;SE-2ebd43c8-10d6-4dee-be67-c06a142c262b&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이 논문은 LLM 추론의 효율성과 성능 향상을 위한 핵심 과제와 다양한 최적화 기법들을 체계적으로 정리하고 있습니다. 또한 현재 활용되는 주요 추론 엔진들의 기술적 역량을 분석함으로써, LLM 서비스를 개발하거나 운영하는 연구자와 개발자에게 매우 실질적인 가이드라인을 제공합니다.&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-66b27ed4-c9ef-4c55-ac8b-49dc1501dd00&quot; data-a11y-title=&quot;구분선&quot; data-compid=&quot;SE-66b27ed4-c9ef-4c55-ac8b-49dc1501dd00&quot;&gt;
&lt;div&gt;
&lt;div data-direction=&quot;top&quot; data-compid=&quot;SE-66b27ed4-c9ef-4c55-ac8b-49dc1501dd00&quot; data-unitid=&quot;&quot;&gt;
&lt;div&gt;
&lt;div&gt;&lt;hr data-ke-style=&quot;style1&quot; /&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-8e43f130-11f7-46c2-bdd6-0c7e0018d29d&quot; data-a11y-title=&quot;본문&quot; data-compid=&quot;SE-8e43f130-11f7-46c2-bdd6-0c7e0018d29d&quot;&gt;
&lt;div&gt;
&lt;div data-direction=&quot;top&quot; data-compid=&quot;SE-8e43f130-11f7-46c2-bdd6-0c7e0018d29d&quot; data-unitid=&quot;&quot;&gt;
&lt;div&gt;
&lt;div id=&quot;SE-c57ed578-a032-4a22-943a-36ebbf9e411a&quot;&gt;
&lt;p id=&quot;SE-352bd3ce-8751-43e8-b114-bb84345ffdaf&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;논문 주소 : &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot; data-href=&quot;https://arxiv.org/abs/2505.01658&quot;&gt;&lt;a href=&quot;https://arxiv.org/abs/2505.01658&quot;&gt;https://arxiv.org/abs/2505.01658&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-9cc7fe4d-e9f2-4966-a361-b47a3e9a7400&quot; data-a11y-title=&quot;본문&quot; data-compid=&quot;SE-9cc7fe4d-e9f2-4966-a361-b47a3e9a7400&quot;&gt;
&lt;div&gt;
&lt;div data-direction=&quot;top&quot; data-compid=&quot;SE-9cc7fe4d-e9f2-4966-a361-b47a3e9a7400&quot; data-unitid=&quot;&quot;&gt;
&lt;div&gt;
&lt;div id=&quot;SE-d83173be-f300-49a2-af57-ec121182d00b&quot;&gt;
&lt;p id=&quot;SE-cad0ce69-8cdd-4238-a649-ac46182f804f&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p id=&quot;SE-ad09da82-a652-40a2-a7af-6fb378c0e067&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;#LLM #거대언어모델 #추론 #인퍼런스 #LLM추론&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-fb8202c6-3cfa-47aa-be7f-531338a8eb0c&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;#LLM인퍼런스 #추론엔진 #인퍼런스엔진 #LLMOptimization #LLM최적화&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-e41bebfb-8025-44cb-b414-7d6de985d7d2&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;#LLM효율성 #AI반도체 #GPU최적화 #TTFT #TBT&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-5271bc90-d73c-44cc-8e7b-13fcaba42e8d&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;#Latency #Throughput #KV캐시 #KV캐싱 #PagedAttention&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-29a19065-0b94-47a0-a11c-8ccecb64176d&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;#FlashAttention #양자화 #Pruning #가지치기 #투기적디코딩&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-f3bee33a-e64b-415c-9175-c69968f3dc1f&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;#SpeculativeDecoding #구조화된출력 #ConstrainedDecoding #vLLM #llama_cpp&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>인공지능</category>
      <category>GPU</category>
      <category>LLM</category>
      <category>vllm</category>
      <category>거대언어모델</category>
      <category>딥러닝</category>
      <category>양자화</category>
      <category>인퍼런스</category>
      <category>최적화</category>
      <category>추론</category>
      <category>효율성</category>
      <author>jmkim87</author>
      <guid isPermaLink="true">https://kid1412.tistory.com/296</guid>
      <comments>https://kid1412.tistory.com/296#entry296comment</comments>
      <pubDate>Thu, 8 May 2025 09:30:14 +0900</pubDate>
    </item>
    <item>
      <title>초보 개발자를 위한 MCP(Model Context Protocol) 가이드: Claude 플랫폼 활용 예제</title>
      <link>https://kid1412.tistory.com/295</link>
      <description>&lt;div id=&quot;SE-df29a016-6085-4751-9a1c-a77686444004&quot; style=&quot;background-color: #ffffff; color: #7b6d6d; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;773&quot; data-origin-height=&quot;773&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ckr1vy/btsMX0M8Ko2/uhCrVymdskvEdPNA0oM7f0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ckr1vy/btsMX0M8Ko2/uhCrVymdskvEdPNA0oM7f0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ckr1vy/btsMX0M8Ko2/uhCrVymdskvEdPNA0oM7f0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fckr1vy%2FbtsMX0M8Ko2%2FuhCrVymdskvEdPNA0oM7f0%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;773&quot; height=&quot;773&quot; data-origin-width=&quot;773&quot; data-origin-height=&quot;773&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-06b5ca51-f158-401a-996f-902986896ace&quot; style=&quot;background-color: #ffffff; color: #7b6d6d; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p id=&quot;SE-2dd0b608-bacd-4899-a243-05163b3fc4a1&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-0fd26cb3-1e6a-4f65-96c1-c7bed22dd71b&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;최근 생성형 AI 기술이 발전하면서, AI 모델이 실시간으로 외부 데이터와 효율적으로 상호작용하는 방법이 중요해졌습니다. &lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-21fe21cb-e6ce-46d7-b454-6c838bc79a53&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이런 환경에서 주목받는 것이 바로 &lt;/span&gt;&lt;span style=&quot;color: #ff0010;&quot;&gt;&lt;b&gt;MCP(Model Context Protocol)&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;입니다. &lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-5c6f12cc-6ac1-45aa-b6f6-d00c75fe58d6&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이번 글에서는 MCP의 개념과 필요성을 쉽게 이해하고 Claude 플랫폼과 함께 실습해 볼 수 있도록 안내합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-b7a4d8ba-7e46-4525-b973-07de68cc1920&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-c54a2237-aac4-4e8b-9ff1-ca377ce6cc80&quot; style=&quot;background-color: #ffffff; color: #7b6d6d; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;h3 id=&quot;SE-d1ab7823-4195-4f98-a34f-ee8ce7f04540&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;MCP(Model Context Protocol)란 무엇인가?&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-674195ba-01ce-4386-a7a4-4d87d3234530&quot; style=&quot;background-color: #ffffff; color: #7b6d6d; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;773&quot; data-origin-height=&quot;773&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/opT39/btsM0qpwdb9/KSeu37fCQE0p6Ug83ZLS0k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/opT39/btsM0qpwdb9/KSeu37fCQE0p6Ug83ZLS0k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/opT39/btsM0qpwdb9/KSeu37fCQE0p6Ug83ZLS0k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FopT39%2FbtsM0qpwdb9%2FKSeu37fCQE0p6Ug83ZLS0k%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;773&quot; height=&quot;773&quot; data-origin-width=&quot;773&quot; data-origin-height=&quot;773&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-7cf243cd-4ce2-477b-a623-f20d3fc1902f&quot; style=&quot;background-color: #ffffff; color: #7b6d6d; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p id=&quot;SE-5b841ae5-d485-4c0a-a2e2-7e0f5930da3e&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;MCP는 간단히 말해 AI 모델과 외부 데이터 및 도구 간의 원활한 통신을 위한 개방형 표준 프로토콜입니다. &lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-66eb5389-6f9d-4c31-b010-0b55701b236d&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;USB-C가 다양한 장치를 하나로 통합하는 것처럼, MCP는 AI가 여러 데이터 소스에 간편하게 접근할 수 있도록 &lt;/span&gt;&lt;span style=&quot;color: #ff0010;&quot;&gt;&lt;b&gt;표준화된 인터페이스&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;를 제공합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-62b85324-f5c3-4a3f-8672-d55721637cba&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;예컨대&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt; 회사 내부 데이터베이스나 웹 API 등을 AI 챗봇에 쉽게 연결하여 실시간 데이터를 제공하거나 &lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff0010;&quot;&gt;&lt;b&gt;AI의 기능을 더욱 확장&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff0010;&quot;&gt;​&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;할 때 MCP를 활용할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-b5c9f4e3-28db-4e5e-aae4-b40a574d83b3&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-f2be371d-d26c-480a-8eb1-140e19e33d09&quot; style=&quot;background-color: #ffffff; color: #7b6d6d; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;h3 id=&quot;SE-115bb1f8-7b01-4232-b729-edadfe374b90&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;MCP가 필요한 이유&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-1e7db40c-f5a5-4695-85d2-1c50e51138bd&quot; style=&quot;background-color: #ffffff; color: #7b6d6d; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;773&quot; data-origin-height=&quot;773&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dqdGJC/btsMZOxCcIZ/jB4mBTNSMhdq7ciHHYmax1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dqdGJC/btsMZOxCcIZ/jB4mBTNSMhdq7ciHHYmax1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dqdGJC/btsMZOxCcIZ/jB4mBTNSMhdq7ciHHYmax1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdqdGJC%2FbtsMZOxCcIZ%2FjB4mBTNSMhdq7ciHHYmax1%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;773&quot; height=&quot;773&quot; data-origin-width=&quot;773&quot; data-origin-height=&quot;773&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-5ae3f8c6-7618-44b1-9c1d-2dcb84b4aac0&quot; style=&quot;background-color: #ffffff; color: #7b6d6d; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;773&quot; data-origin-height=&quot;773&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bra8HO/btsMX1yzvnE/VLaguhapn9vjb2k4FkzFd1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bra8HO/btsMX1yzvnE/VLaguhapn9vjb2k4FkzFd1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bra8HO/btsMX1yzvnE/VLaguhapn9vjb2k4FkzFd1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbra8HO%2FbtsMX1yzvnE%2FVLaguhapn9vjb2k4FkzFd1%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;773&quot; height=&quot;773&quot; data-origin-width=&quot;773&quot; data-origin-height=&quot;773&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-c8388d20-cc77-4182-b7e7-188180450afe&quot; style=&quot;background-color: #ffffff; color: #7b6d6d; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p id=&quot;SE-43fb06d8-3a56-499d-bb6f-a965f1cd7f49&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;기존 방식에서는 AI 모델이 외부 데이터에 접근하려면 매번 개별적인 코드를 작성해야 했습니다. &lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-fc373fb9-0b20-4471-bc6d-42f8123ab3e2&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이는 &lt;/span&gt;&lt;span style=&quot;color: #ff0010;&quot;&gt;&lt;b&gt;유지보수와 확장에 큰 부담&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이 되었습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-c60e9c22-1df6-4f72-8a65-ab6a9c0a4c9d&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;MCP를 도입하면 이 문제가 해결됩니다. 개발자는 데이터를 제공하는 &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;MCP 서버만 한 번 구축하면, 다양한 AI 모델과 애플리케이션에서 손쉽게 이를 &lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff0010;&quot;&gt;&lt;b&gt;재사용&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;할 수 있습니다. &lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-db70afed-ca03-4656-bfbe-17af625d987a&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-23a3c774-db09-4824-b33d-8123e94ac4cf&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;결과적으로 개발 생산성과 유지보수성이 크게 향상됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-3dbd7660-57f6-4c57-8ec5-19e23fced910&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-d1f8e57e-65a8-4e3b-b0ba-bff261cd673f&quot; style=&quot;background-color: #ffffff; color: #7b6d6d; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;h3 id=&quot;SE-906b24dc-ea01-4ac0-b8de-7e48a981a4f2&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;MCP의 기본 작동 방식&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-2ffb579d-8acd-4b3c-ba95-5dfb53c82efe&quot; style=&quot;background-color: #ffffff; color: #7b6d6d; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p id=&quot;SE-a98696e8-1e99-4c7d-937e-9dca5f3fa322&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;MCP는 클라이언트(AI 애플리케이션)와 서버(외부 데이터를 제공하는 프로그램)로 구성되며, JSON-RPC 프로토콜을 이용해 요청과 응답을 교환합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-b9b09522-02a5-4ffb-b357-70e7b55abfd3&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;클라이언트가 특정 데이터를 요청하거나 작업 수행을 요청하면, MCP 서버가 이를 처리한 후 결과를 반환하는 형태로 동작합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-1a6dfa05-7823-420f-862c-a92fae630575&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-2607884d-d335-4a2f-b29f-df44f9c06114&quot; style=&quot;background-color: #ffffff; color: #7b6d6d; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;h3 id=&quot;SE-7f900352-ab73-462d-8aef-4a9d8e579c2d&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;MCP 실습 예제: Claude 플랫폼 활용하기&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-c49516b1-0a62-4169-9734-f6b1ceaa91ff&quot; style=&quot;background-color: #ffffff; color: #7b6d6d; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p id=&quot;SE-353dd6fb-a545-4682-bfcc-817350d61d4a&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;다음 예제는 MCP를 실제로 구현해보고 이해하는 데 도움을 줍니다. &lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-140bae82-11e8-402d-9e5e-a7a0c7aba7a6&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;클라이언트는 TypeScript, 서버는 Python을 사용해 간단히 구현합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-9dc0684d-7621-4215-b40b-d344579ee07a&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-e94d55da-3514-4ffd-ab3c-3827af1c9062&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Python 기반의 MCP 서버 구축&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1743069488588&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;from mcp.server.fastmcp import FastMCP

app = FastMCP(&quot;DemoServer&quot;)

@app.tool()
def add(a: int, b: int) -&amp;gt; int:
    return a + b

@app.resource(&quot;greeting://{name}&quot;)
def greet(name: str) -&amp;gt; str:
    return f&quot;안녕하세요, {name}님!&quot;

if __name__ == &quot;__main__&quot;:
    app.run()&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-3646f2dd-7fbf-4f49-b1da-b2f365b22f3b&quot; style=&quot;background-color: #ffffff; color: #7b6d6d; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p id=&quot;SE-4f9d4b17-dc95-4a3c-9b9f-0f2166fb8f58&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이 서버는 간단한 덧셈과 인사 메시지를 제공하는 두 가지 기능을 MCP 표준으로 노출합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-4fb40251-f250-47e9-9256-00fa8616780e&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-e0462677-00ca-4a4d-a9e1-df1bdadb53b2&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;TypeScript 기반의 MCP 클라이언트 구축&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1743069501896&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import { Client } from &quot;@modelcontextprotocol/sdk/client&quot;;
import { StdioClientTransport } from &quot;@modelcontextprotocol/sdk/client/stdio&quot;;

const client = new Client();
const transport = new StdioClientTransport({ command: &quot;python3&quot;, args: [&quot;server.py&quot;] });

await client.connect(transport);

const result = await client.request({ method: &quot;add&quot;, params: { a: 5, b: 3 } });
console.log(&quot;덧셈 결과:&quot;, result);

const greeting = await client.request({ method: &quot;getResource&quot;, params: { uri: &quot;greeting://민수&quot; } });
console.log(greeting);&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-774bbdc2-9b7a-4055-bf80-4e91fc771d60&quot; style=&quot;background-color: #ffffff; color: #7b6d6d; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p id=&quot;SE-d58672f2-d544-4ccf-9afd-34af644c4174&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;실행 결과:&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1743069521376&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;덧셈 결과: 8
안녕하세요, 민수님!&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-722938bc-7e8b-485f-8314-16c95cd35968&quot; style=&quot;background-color: #ffffff; color: #7b6d6d; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p id=&quot;SE-ed21af6d-7789-44e5-8520-5f744254e749&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이 과정을 통해 MCP가 AI 애플리케이션과 데이터 간의 소통을 얼마나 간단하게 만들어주는지 확인할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-9238e68a-4adc-4ad7-90b0-3033833d8987&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-36072580-d4bb-40f2-959a-918d45224f72&quot; style=&quot;background-color: #ffffff; color: #7b6d6d; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;h3 id=&quot;SE-977eaa54-c8f5-4817-b736-5b7dfba161f7&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Claude 플랫폼에서의 MCP 활용법&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-2d547f56-bf40-4b47-8e1b-08cc9f4d627e&quot; style=&quot;background-color: #ffffff; color: #7b6d6d; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p id=&quot;SE-70c65f46-5c21-43ef-b4b4-7e33908c87a4&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Claude 플랫폼에서 MCP를 활용하면 사용자의 자연스러운 질문에 따라 자동으로 관련 데이터를 가져와 응답할 수 있습니다. &lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-d8c7cd51-a6f2-4c03-8252-df7bbb6ee4f0&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;예를 들어, Claude에게 &quot;최근 분기 보고서를 보여줘&quot;라고 요청하면, MCP 서버와 연동하여 최신 보고서를 즉시 제공받는 방식입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-28b732da-0a71-4e5b-90a4-6cdb613994a8&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Claude Desktop에서는 개발자가 구축한 MCP 서버를 등록하기만 하면, 사용자는 별도의 설정 없이 자연스럽게 MCP의 기능을 활용할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-b26f954b-01bb-4e29-bfef-2e5d9bfc771d&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-eb897be2-28eb-46f1-9d71-d2c25391ddee&quot; style=&quot;background-color: #ffffff; color: #7b6d6d; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;h3 id=&quot;SE-2a54ff6a-732d-4886-ba7c-b58e44c6096f&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;마치며&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-73267b1c-1947-4e9c-8b27-d92a96031fae&quot; style=&quot;background-color: #ffffff; color: #7b6d6d; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p id=&quot;SE-517aebe0-ea83-4552-b003-53d9766f78c4&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;MCP는 AI 개발의 효율성과 확장성을 획기적으로 향상시켜주는 중요한 프로토콜입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-589cfdbc-273a-40df-9906-e433cbb7678e&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt; 앞으로의 AI 애플리케이션 개발에서 MCP 활용이 더욱 확대&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;될 것으로 기대됩니다. &lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-d0f08e76-b546-4052-ad6c-76480dc96700&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이 글을 통해 MCP에 대한 이해를 넓히고 직접 활용해보는 기회를 가지시길 바랍니다.&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;</description>
      <category>인공지능</category>
      <category>AI개발</category>
      <category>ai표준</category>
      <category>AI플랫폼</category>
      <category>Claude</category>
      <category>MCP</category>
      <category>modelcontextprotocol</category>
      <category>Python</category>
      <category>바이브코딩</category>
      <category>인공지능</category>
      <category>코딩</category>
      <author>jmkim87</author>
      <guid isPermaLink="true">https://kid1412.tistory.com/295</guid>
      <comments>https://kid1412.tistory.com/295#entry295comment</comments>
      <pubDate>Thu, 27 Mar 2025 19:00:27 +0900</pubDate>
    </item>
    <item>
      <title>[내돈내산] 똑똑한 사람은 어떻게 생각하고 질문하는가 &amp;ndash; 사고력 실종의 시대, 앞서가는 사람의 생존 전략</title>
      <link>https://kid1412.tistory.com/294</link>
      <description>&lt;div id=&quot;SE-76c66711-5ccb-442f-bee9-98e12aa6bb1f&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;966&quot; data-origin-height=&quot;1051&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/pV78m/btsMUwxULxA/E9i4bwuxBdWo3YYYoTkiuk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/pV78m/btsMUwxULxA/E9i4bwuxBdWo3YYYoTkiuk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/pV78m/btsMUwxULxA/E9i4bwuxBdWo3YYYoTkiuk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FpV78m%2FbtsMUwxULxA%2FE9i4bwuxBdWo3YYYoTkiuk%2Fimg.jpg&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;966&quot; height=&quot;1051&quot; data-origin-width=&quot;966&quot; data-origin-height=&quot;1051&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;p id=&quot;SE-0507e5de-9c8b-490a-8d4d-b4a85aff9fed&quot; style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #555555;&quot;&gt;똑똑한 사람은 어떻게 생각하고 질문하는가&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-f421cd02-6be0-44e8-877f-234a4539c826&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p id=&quot;SE-096a8a0d-862d-43f1-b997-5fa09ef394be&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-83fc91c1-2b59-4930-a928-14e29737c9b5&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;질문을 잘하면 세상이 다르게 보인다고 합니다. &lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-91813a1a-0286-4832-be2c-b83c7da322b8&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;특히 ChatGPT 같은 &lt;/span&gt;&lt;span style=&quot;color: #ff0010;&quot;&gt;&lt;b&gt;인공지능과 협업하는 시대&lt;/b&gt;&lt;/span&gt;&lt;span&gt;에는 &amp;lsquo;좋은 질문&amp;rsquo;이야말로 경쟁력입니다. &lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-382ad0d7-6dbe-45ee-9253-cd09be4710d3&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;그런 의미에서 이시한 작가의 『똑똑한 사람은 어떻게 생각하고 질문하는가』는 지금 시대에 꼭 필요한 책이었습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-025d9c7b-ddda-44fc-b301-9e434924de43&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-447a9817-8978-4414-b177-7bfa610113e3&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;  저자: 이시한 | 출판사: 북플레저 | 출판년도: 2024.01.24 | 페이지: 328쪽&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-93262ddf-8d80-45a4-96dc-cf0ffeb0d2cd&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;div id=&quot;SE-457b82a6-c880-494e-b786-2787dacfc64c&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;h3 id=&quot;SE-f390afad-fbfc-4f95-b19e-911df1df773a&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;  책을 선택한 이유&lt;/span&gt;&lt;/h3&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-1a56c06c-0b90-42e6-bd21-c7f61883fa3e&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p id=&quot;SE-1df29014-81a4-4322-bbe0-48e897727e17&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-ce0731d0-7f06-4fe7-b2ac-cd4a16c9f40c&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;요즘 ChatGPT나 Claude 같은 대화형 인공지능을 활용하면서 &amp;lsquo;&lt;/span&gt;&lt;span style=&quot;color: #ff0010;&quot;&gt;&lt;b&gt;질문을 잘 던지는 능력&lt;/b&gt;&lt;/span&gt;&lt;span&gt;&amp;rsquo;이 정말 중요하다는 걸 느꼈습니다. &lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-e2fffab5-07b4-4dee-ace5-53ccc33c725a&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;답변의 퀄리티도 결국 질문의 퀄리티에서 나옵니다. &lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-c057f4d9-35f6-4a18-b853-03f8b97ef1d2&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;그러다 보니 자연스럽게 &amp;lsquo;&lt;/span&gt;&lt;span style=&quot;color: #ff0010;&quot;&gt;&lt;b&gt;질문을 잘하는 사람들은 어떻게 사고할까?&lt;/b&gt;&lt;/span&gt;&lt;span&gt;&amp;rsquo;에 대해 궁금해졌고, 이 책 제목이 딱 마음에 들어 선택하게 됐습니다.&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-9be3b7fa-b0af-4ee6-b148-5321db40d72e&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;966&quot; data-origin-height=&quot;1037&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bD2LXh/btsMVztNeR3/ts1sSfTxezvpgFMbXD65sK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bD2LXh/btsMVztNeR3/ts1sSfTxezvpgFMbXD65sK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bD2LXh/btsMVztNeR3/ts1sSfTxezvpgFMbXD65sK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbD2LXh%2FbtsMVztNeR3%2Fts1sSfTxezvpgFMbXD65sK%2Fimg.jpg&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;966&quot; height=&quot;1037&quot; data-origin-width=&quot;966&quot; data-origin-height=&quot;1037&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;p id=&quot;SE-bee2d934-4acc-424e-ba5b-2df4f6643526&quot; style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #555555;&quot;&gt;똑똑한 사람은 어떻게 생각하고 질문하는가&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-2c4aa3df-4446-42aa-b84b-53da1f012dbf&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;h3 id=&quot;SE-c4b32cd4-2f1a-45e5-916a-be6b60aac430&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;  추천 대상&lt;/span&gt;&lt;/h3&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-e20249db-6fa7-4050-a922-6fa400845f3d&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p id=&quot;SE-aa5c27c7-352b-41c0-9de0-2f8c8736f4b9&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-f8db57cb-651f-4947-be12-d22c18e1487e&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;이런 분들에게 추천드려요:&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-d4b898d0-974f-4689-b4c2-0c0c91720a20&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-be45d18b-8143-47b9-a4d0-89f0bd0ba499&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;✅ 원하는 답을 이끌어내는 &lt;/span&gt;&lt;span style=&quot;color: #ff0010;&quot;&gt;&lt;b&gt;질문법&lt;/b&gt;&lt;/span&gt;&lt;span&gt;이 궁금한 사람&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-8c40f031-9eed-47be-9148-da08a4101c55&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;✅ ChatGPT 같은 AI와 제대로 일하고 싶은 사람&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-9f1688f9-08b9-41c8-8383-4706720df2e8&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;✅ 암기 중심의 학습에서 벗어나, &amp;lsquo;&lt;/span&gt;&lt;span style=&quot;color: #ff0010;&quot;&gt;&lt;b&gt;생각하는 뇌&lt;/b&gt;&lt;/span&gt;&lt;span&gt;&amp;rsquo;를 만들고 싶은 사람&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-386245bf-7e4f-41ad-8699-28b8ddef74db&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;✅ 사람들과의 &lt;/span&gt;&lt;span style=&quot;color: #ff0010;&quot;&gt;&lt;b&gt;대화 주도권&lt;/b&gt;&lt;/span&gt;&lt;span&gt;을 잡고 싶은 사람&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div id=&quot;SE-aaad86c5-ae06-44e6-b43d-dd62c70527bb&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 id=&quot;SE-e1645407-0817-4f6a-b3e7-97b7f2dedb1e&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;  책 소개&lt;/span&gt;&lt;/h3&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #555555; font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;div id=&quot;SE-71e71a96-0f72-4244-8e30-3fbb3190c593&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;p id=&quot;SE-5956635a-2b26-46d5-8bd3-4d45047d7dad&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;이 책은 단순히 질문의 스킬을 넘어서, &lt;/span&gt;&lt;span style=&quot;color: #ff0010;&quot;&gt;&lt;b&gt;질문하는 뇌로 전환&lt;/b&gt;&lt;/span&gt;&lt;span&gt;하는 방법을 알려줍니다.&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-830802fc-a329-4922-ae36-14e34aef1a2a&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;bull; 왜 질문하는 능력이 중요한지&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-b7ca7217-9070-44b0-9b3f-bd8821a42469&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;bull; &lt;/span&gt;&lt;span style=&quot;color: #ff0010;&quot;&gt;&lt;b&gt;질문하는 사고방식&lt;/b&gt;&lt;/span&gt;&lt;span&gt;을 어떻게 뇌에 장착할 수 있을지&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-5445055a-661d-424c-a067-50e45200d412&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;bull; 사람들과의 대화에서 어떤 식으로 질문해야 원하는 답을 얻는지&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-9c1e71b8-d393-4e58-9d0a-f5d5e8bb6fe1&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;bull; 혼자 공부할 때 &lt;/span&gt;&lt;span style=&quot;color: #ff0010;&quot;&gt;&lt;b&gt;스스로 질문&lt;/b&gt;&lt;/span&gt;&lt;span&gt;을 던지는 법&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-d1b46aa2-1583-4f1c-80f9-3a6f98498302&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;bull; ChatGPT 같은 AI에게 &lt;/span&gt;&lt;span style=&quot;color: #ff0010;&quot;&gt;&lt;b&gt;효율적인 프롬프트&lt;/b&gt;&lt;/span&gt;&lt;span&gt;를 작성하는 팁까지&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-0be6e3b6-8b1e-424c-befa-82d6f328a229&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-4bb502a1-ba46-47f2-a7d9-4545868db237&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;질문은 단지 정보를 얻기 위한 도구가 아니라, 생각의 도약을 만드는 핵심 도구라는 걸 강조합니다. &lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-707ee132-38a8-4e18-a5b7-04612c23c059&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;특히 &lt;/span&gt;&lt;span style=&quot;color: #ff0010;&quot;&gt;&lt;b&gt;5Why 기법&lt;/b&gt;&lt;/span&gt;&lt;span&gt;&lt;b&gt;, &lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff0010;&quot;&gt;&lt;b&gt;질문하는 뇌 구조 바꾸기(뭐야? &amp;rarr; 진짜? &amp;rarr; 좀더? &amp;rarr; 왜?)&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff0010;&quot;&gt;​&lt;/span&gt;&lt;span&gt; 등 실전에서 바로 써먹을 수 있는 도구들을 제공해 줍니다.&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-c3bfd335-e2f6-4b70-8be5-640a189db276&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;div id=&quot;SE-de044e21-489a-45c2-918f-accc3f461faa&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;h3 id=&quot;SE-e5c2a075-ddd5-4571-8398-558af0a554eb&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;  주요 문구&lt;/span&gt;&lt;/h3&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-831b4c66-fd19-4b29-bf27-a5a29f7c9913&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p id=&quot;SE-9db83526-68fa-4378-9d3b-9b368d3bc0f4&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-52639c3e-e9b9-4e1a-92f1-977a394e9650&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;div&gt;
&lt;p id=&quot;SE-be01ff7c-a376-4bb2-9f98-62da8217bea1&quot; style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #0e0e0e;&quot;&gt;&amp;ldquo;5 Why 기법: 문제의 원인을 파악하려면 최소 5번 &amp;lsquo;왜?&amp;rsquo;를 던져라.&amp;rdquo;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/blockquote&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-c0436497-05ab-48c6-bbd7-25439c6bda7a&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p id=&quot;SE-2eed3fd3-a647-4352-81a9-ae0a49f42b43&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-389b2b37-7001-424c-bd71-ce7c9e884cc7&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;div&gt;
&lt;p id=&quot;SE-8eb4852b-c283-42ea-aee2-23089afb0c7b&quot; style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #0e0e0e;&quot;&gt;&amp;ldquo;질문하는 뇌를 만들기 위해선 평소에도 &amp;lsquo;뭐야?&amp;rsquo;, &amp;lsquo;진짜?&amp;rsquo;, &amp;lsquo;좀더?&amp;rsquo;, &amp;lsquo;왜?&amp;rsquo;라는 질문 습관을 갖는 것이 중요하다.&amp;rdquo;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/blockquote&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-3a96978e-590e-41db-b740-d04bf096fae6&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p id=&quot;SE-1ccf9320-2fd0-42ed-aa65-1bc3ec9f720c&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-641bc477-628a-43f6-8bab-48bfb972fadf&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;질문은 단순한 기술이 아니라 &lt;/span&gt;&lt;span style=&quot;color: #ff0010;&quot;&gt;&lt;b&gt;사고방식&lt;/b&gt;&lt;/span&gt;&lt;span&gt;이며, 스스로의 생각을 깊이 있게 확장시켜주는 엔진이 된다는 메시지가 마음에 와닿았습니다.&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-b7c9eb9e-de05-4843-964e-ef608e703c2c&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;div id=&quot;SE-b4537d16-a223-4a73-ac16-02a48769d565&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;h3 id=&quot;SE-77cad670-84a8-4183-ba65-e8176c5974f6&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;  감상 및 느낀 점&lt;/span&gt;&lt;/h3&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-5c9e7633-fcfa-43ed-a855-e44a7aeff9dd&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p id=&quot;SE-664ea72e-0145-4a2b-8071-8322de2f3dfe&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-8e5c0ae6-a1da-4860-bd83-630649a6a972&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;✔ 회의나 소통 자리에서 질문을 정리 못해 스트레스를 받았는데, 이 책을 통해 &lt;/span&gt;&lt;span style=&quot;color: #ff0010;&quot;&gt;&lt;b&gt;질문 정리하는 틀&lt;/b&gt;&lt;/span&gt;&lt;span&gt;을 배워서 실제로 도움이 되고 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-b3659692-6d9a-4d0b-b713-4a846d430540&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;✔ ChatGPT처럼 AI를 쓸 때도 점점 &lt;/span&gt;&lt;span style=&quot;color: #ff0010;&quot;&gt;&lt;b&gt;더 정교한 질문&lt;/b&gt;&lt;/span&gt;&lt;span&gt;을 던지게 되었고, 그만큼 더 좋은 답을 받을 수 있었습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-8d76d763-16a2-4f13-8160-a479311875cd&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;✔ 무엇보다 이 책을 읽고 나니, 사람과의 대화뿐만 아니라 &lt;/span&gt;&lt;span style=&quot;color: #ff0010;&quot;&gt;&lt;b&gt;자기 자신에게 던지는 질문&lt;/b&gt;&lt;/span&gt;&lt;span&gt;도 굉장히 중요하다는 걸 느꼈습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-bcbb7d90-8b01-458c-a86b-33f348b386da&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;✔ 개인적인 목표로는 &lt;/span&gt;&lt;span style=&quot;color: #ff0010;&quot;&gt;&lt;b&gt;소개팅 자리&lt;/b&gt;&lt;/span&gt;&lt;span&gt;에서 좋은 질문을 던지는 걸 연습해보고 싶다는 생각까지 들었습니다  &lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-d59d77bb-dc7a-45f6-ad62-141c52420300&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;div id=&quot;SE-50930479-9965-423d-bfa1-f3bc0af8b267&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;h3 id=&quot;SE-e80ed6d8-243d-4d42-8cb3-c8a3be8b244b&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;  총평 &amp;ndash; 질문은 최고의 사고 훈련이자 AI 시대의 필수 역량!&lt;/span&gt;&lt;/h3&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-76c6d97a-f551-4b5f-ab81-56cba6517dbe&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p id=&quot;SE-e4030ce0-a8c6-430e-af1c-556286bbdca7&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-344d1dcc-c9cd-4e8f-a42d-a264eb0034fa&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;질문이 단순한 대화 기술이 아니라 &lt;/span&gt;&lt;span style=&quot;color: #ff0010;&quot;&gt;&lt;b&gt;지성과 창의성의 출발점&lt;/b&gt;&lt;/span&gt;&lt;span&gt;이라는 사실을 깨닫게 해주는 책이었습니다. &lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-bbb52a52-11e2-49a9-abb7-d92d01b2a7cb&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ff0010;&quot;&gt;&lt;b&gt;질문하는 사람&lt;/b&gt;&lt;/span&gt;&lt;span&gt;이 앞으로의 시대를 이끌어간다는 말, 이제는 정말 실감이 납니다.&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-265aa0ac-c2a8-4d05-8e41-10fceaf3c8d5&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-c9b71e2c-e520-44ff-9155-3c488199c099&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;✔ AI를 더 잘 활용하고 싶은 분&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-ebbf2b29-82d2-48ed-a5d9-99739a54d2f8&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;✔ 업무 커뮤니케이션에서 질문으로 주도권을 잡고 싶은 분&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-480a2ce0-436e-4e3f-84e0-9a36d6d3438b&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;✔ 생각을 정리하고 깊이 있게 사고하는 연습이 필요한 분&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-8970250e-2b70-484f-92b4-d94d34fd4772&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-fa76e817-efdf-4d4a-83f8-48a3a1ccf0ab&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;b&gt;  이 책으로 질문 근육을 키워보세요!&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-91137b18-84f7-41de-ae4e-6b9da9eeda34&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;h3 id=&quot;SE-8b1a83a5-7e39-4293-8996-400ac33a4479&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;  구매한 곳&lt;/span&gt;&lt;/h3&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;a href=&quot;https://www.yes24.com/Product/Goods/124574383&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.yes24.com/Product/Goods/124574383&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;</description>
      <category>Book Review</category>
      <category>5Why</category>
      <category>내돈내산</category>
      <category>대화주도권</category>
      <category>사고력</category>
      <category>생각하는뇌</category>
      <category>인공지능</category>
      <category>질문</category>
      <category>질문하는뇌</category>
      <category>창의성</category>
      <category>책리뷰</category>
      <author>jmkim87</author>
      <guid isPermaLink="true">https://kid1412.tistory.com/294</guid>
      <comments>https://kid1412.tistory.com/294#entry294comment</comments>
      <pubDate>Mon, 24 Mar 2025 21:27:40 +0900</pubDate>
    </item>
    <item>
      <title>[내돈내산] 초역 부처의 말</title>
      <link>https://kid1412.tistory.com/293</link>
      <description>&lt;div id=&quot;SE-b63ae4a0-2526-4fc5-8c92-65c52901229a&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;966&quot; data-origin-height=&quot;1079&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kDJQD/btsMLMgWGMX/kxf62x8drh3MyG3YVpx4tk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kDJQD/btsMLMgWGMX/kxf62x8drh3MyG3YVpx4tk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kDJQD/btsMLMgWGMX/kxf62x8drh3MyG3YVpx4tk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkDJQD%2FbtsMLMgWGMX%2Fkxf62x8drh3MyG3YVpx4tk%2Fimg.jpg&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;966&quot; height=&quot;1079&quot; data-origin-width=&quot;966&quot; data-origin-height=&quot;1079&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;p id=&quot;SE-26e8ebb0-2646-4714-a349-751fd72ab933&quot; style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #555555;&quot;&gt;초역 부처의 말&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-4fef8298-32b3-40df-91b6-e1d661952638&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p id=&quot;SE-af6bd6b3-fe66-4ba0-957e-ee8a17bd3027&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;요즘 회사생활을 하다 보면 스트레스를 받는 순간이 많아 마음을 다스릴 방법을 찾게 됩니다. &lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-b45c04d1-312e-4412-acc5-dcac74b8744a&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;그러던 중 유퀴즈에서 아이브 장원영님이 힘들 때마다 읽는다는 책으로 소개한 &lt;/span&gt;&lt;span style=&quot;color: #ff0010;&quot;&gt;&lt;b&gt;『초역 부처의 말』&lt;/b&gt;&lt;/span&gt;&lt;span&gt;을 접하게 되었습니다. &lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-d5331914-c1b6-4fe1-b38e-b7674359fe60&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;이 책에는 불교 경전에서 발췌한 190개의 구절이 수록되어 있으며, 이를 현대적으로 해석한 초역(超譯) 방식으로 소개하고 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-e1b75b75-721d-4703-9bd6-78cffbd1c6eb&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-9fda5254-b301-45d5-bb70-8bd0bdc60837&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;  저자: 코이케 류노스케 | 역자: 박재현 | 출판사: 포레스트북스 | 출판년도: 2024.05.30 | 페이지: 256쪽&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div id=&quot;SE-54a8319d-3361-43f6-a0cb-24009324c641&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 id=&quot;SE-74b693d1-4d4d-427e-a1bb-0bd4e1babaf1&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;&lt;b&gt;  책을 선택한 이유&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-bc869112-de17-419e-93bc-d07a666bf649&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p id=&quot;SE-a2e96be0-0be0-4ad5-9beb-2b4f3ef75a79&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;bull; 유퀴즈에서 &lt;/span&gt;&lt;span style=&quot;color: #ff008c;&quot;&gt;&lt;b&gt;아이브의 장원영&lt;/b&gt;&lt;/span&gt;&lt;span&gt;님이 힘들 때마다 꺼내본다고 해서 관심이 생겼습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-78e74c09-b8e7-4f74-8c87-63c8f0bfc6fc&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;bull; 회사 생활을 하며 마음이 힘들 때가 많아 위로가 될 책이 필요했습니다.&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-f44f2c8c-fb22-4676-b0c5-6f413ddd7777&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;966&quot; data-origin-height=&quot;1085&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bxp7s1/btsMM50BIlt/kqBiwveVbNxqwqJLY9HBZ1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bxp7s1/btsMM50BIlt/kqBiwveVbNxqwqJLY9HBZ1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bxp7s1/btsMM50BIlt/kqBiwveVbNxqwqJLY9HBZ1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbxp7s1%2FbtsMM50BIlt%2FkqBiwveVbNxqwqJLY9HBZ1%2Fimg.jpg&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;966&quot; height=&quot;1085&quot; data-origin-width=&quot;966&quot; data-origin-height=&quot;1085&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;p id=&quot;SE-2e73c52f-726a-4041-8f6c-8279a454d9a1&quot; style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #555555;&quot;&gt;초역 부처의 말&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div id=&quot;SE-6a1612fc-b8ca-448a-80e1-d4c4f3552123&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 id=&quot;SE-fe060322-7068-465b-b563-a99d73150581&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;&lt;b&gt;  추천 대상&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-c7c375ab-78c3-4597-a50f-90ded31e1d5e&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p id=&quot;SE-f6a24865-01d5-4d29-b455-db2892373824&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-f99288fb-02d1-416e-a7ea-039710617eb0&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;b&gt;✔ 주변 사람들로 인해 &lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff0010;&quot;&gt;&lt;b&gt;스트레스를 많이 받는 분&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-f31dd089-f96c-4c76-a0d7-acac298ac2ec&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;b&gt;✔ &lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff0010;&quot;&gt;&lt;b&gt;마음의 안정을 찾고 싶은 분&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-904340b6-8700-4b0a-8815-32e4354cbaa4&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;b&gt;✔ &lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff0010;&quot;&gt;&lt;b&gt;불교 경전의 가르침&lt;/b&gt;&lt;/span&gt;&lt;span&gt;&lt;b&gt;을 쉽게 접하고 싶은 분&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-ffc297fa-815c-4d35-a060-2fef96ebd0e4&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;b&gt;✔&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff008c;&quot;&gt;&lt;b&gt; 아이브 장원영&lt;/b&gt;&lt;/span&gt;&lt;span&gt;님을 좋아하는 팬이라면 한 번쯤 읽어볼 만한 책&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-6fa3a33b-e438-45c8-addc-3b4f528945ed&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;div id=&quot;SE-7d3d9600-c3a5-4c7c-93b1-1a0cd07e2aaf&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;h3 id=&quot;SE-0c652d75-ce2e-4c81-bf6b-f7e11809a5a2&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;&lt;b&gt;  책 소개&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-6f176413-391f-4497-a966-49c659eb3201&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p id=&quot;SE-5cc56760-ed61-4729-a73d-512940e208dc&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-e46abec7-4c78-4ff8-b6d8-1dfec157c5d1&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ff0010;&quot;&gt;&lt;b&gt;『초역 부처의 말』&lt;/b&gt;&lt;/span&gt;&lt;span&gt;은 불교 경전 속 문구들을 현대적 해석을 더해 쉽게 풀어낸 책입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-12e6faab-035d-4730-8302-161fa3079da6&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-c54ad5ad-524e-4499-9351-cef4ea5a5285&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;bull; &lt;/span&gt;&lt;span&gt;&lt;b&gt;초역(超譯)이란?&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-c87ccf37-5a2b-4591-b631-e5befea5325e&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;저자는 원문의 의미를 최대한 보존하면서도 &lt;/span&gt;&lt;span style=&quot;color: #ff0010;&quot;&gt;&lt;b&gt;현대인이 이해하기 쉽게 번역하는 방식&lt;/b&gt;&lt;/span&gt;&lt;span&gt;을 사용했습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-34ea3aa9-b1ba-43f6-a54e-10eac74ddf59&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-da46151f-909b-432e-ac99-f5439a1e4ba5&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;bull; &lt;/span&gt;&lt;span&gt;&lt;b&gt;책의 구성&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-aeeda758-9a3a-4856-98ce-63ebaa1aefc5&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;190개의 구절을 12가지 주제로 나누어 구성하였으며, 처음에는 &lt;/span&gt;&lt;span style=&quot;color: #ff0010;&quot;&gt;&lt;b&gt;감정을 다스릴 수 있는 문장&lt;/b&gt;&lt;/span&gt;&lt;span&gt;부터 시작하여 점차 &lt;/span&gt;&lt;span style=&quot;color: #ff0010;&quot;&gt;&lt;b&gt;깨달음&lt;/b&gt;&lt;/span&gt;&lt;span&gt;으로 나아가는 방식입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-c6081d65-9cab-4050-8b19-ebc2376469a0&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-8a17245c-07fd-4d2a-a982-b644bbdf3897&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;b&gt;&amp;bull; 주요 주제&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-fa918eaf-9922-447c-a8c9-ed8e42634e70&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;화(분노), 비교, 갈망, 선(善), 친구, 행복, 자신, 신체, 자유, 자비, 깨달음, 죽음&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-deb239d5-5034-4995-99b7-5eb850f42806&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-5c66486e-d46b-4e88-ac67-87b13504af8b&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;bull; &lt;/span&gt;&lt;span&gt;&lt;b&gt;부록&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-202423e4-5944-45da-90a1-d352cbd98011&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;책의 마지막에는 부처의 일생을 간략히 정리하여 그의 삶과 가르침을 이해할 수 있도록 돕습니다.&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-ab0cccb5-810d-4e3d-a165-e7330952e1af&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;div id=&quot;SE-eee44389-485d-402d-a12e-899c16f0f393&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;h3 id=&quot;SE-769a49f8-a175-4d56-9fbb-7765be504726&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;&lt;b&gt;  주요 문구&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-4fa85af0-8b1f-4d10-8918-418acf0c0c47&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p id=&quot;SE-d890cc54-9ebe-42d4-a3ca-44e9cdf6ecb2&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-6836c500-a631-4f5e-b793-75512024621b&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;책을 읽으며 특히 인상 깊었던 문장을 몇 가지 소개합니다.&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-dad2b874-43d2-47d2-957d-97ef7ecbd696&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;div&gt;
&lt;p id=&quot;SE-2b6d1481-f170-431e-b316-96839c923b4c&quot; style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;마음의 예절이라는 것은 &lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-c684843b-f4f5-4465-a138-082a6945f481&quot; style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;단시간에 몸에 배는 게 아닙니다.&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-2f17231e-5594-411b-aa8c-4b50a0d2a9fe&quot; style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-1deadf2a-1998-4907-a126-8e696f8880e8&quot; style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;오랜 시간에 걸쳐 &lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-cd947ec5-3b15-42d8-b1df-7f7fa977a779&quot; style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;차분히 마음의 예절을 몸에 익히고&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-ec913297-b937-4e22-8daf-52f56372af49&quot; style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;그로 인해 험담이나&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-93ac2697-e6f8-4c1d-8fca-166487e01f30&quot; style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;자랑이나 난잡한 행동을 하지 않을 때&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-42592e8a-4336-41bf-a24d-775f9c3335ab&quot; style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;자연스럽게 당신 주변에는 기품이 감돕니다. &lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;p id=&quot;SE-eb2c22b9-ce17-47fc-bb59-312b2af67d91&quot; style=&quot;color: #777777; text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;경집&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/blockquote&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-9cdb3fa8-8bb8-4011-8fda-59d2a2a9e37e&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;div&gt;
&lt;p id=&quot;SE-2cbde459-bc04-4f43-a3de-ffcae9893de2&quot; style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;자주 불같이 화내는 사람.&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-93c2abcc-dcbe-4d96-bbbd-c24c71861ae2&quot; style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;언제까지고 원망을 잊지 않는 사람.&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-cd85ec21-5e97-4c5a-8ed5-1207be0197aa&quot; style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;자신의 결점을 감추려고 하는 사람.&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-60db663b-94ad-4bc9-9833-4b9585ab574c&quot; style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;자신을 실제보다 좋게 보이려고&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-171d7aa4-08d7-4b13-8832-8515f80f3557&quot; style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;친절을 가장하는 위선자.&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-777c7a6d-e909-4225-8604-b2d4e5044889&quot; style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-4849bec4-33b5-476c-99de-2aa33e988483&quot; style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;이런 사람들은 저속하다는 걸 알고,&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-420b10d9-8c7b-4585-8fe3-419cd430511e&quot; style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;그들과 어울리지 않도록 하세요.&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;p id=&quot;SE-e63f51be-f31e-4318-951c-2d65a94db17f&quot; style=&quot;color: #777777; text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;경집&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/blockquote&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-74fe98a6-15b0-4b11-98d6-ba7ea884d25d&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;div&gt;
&lt;p id=&quot;SE-5b0d9855-0ac0-43a6-8649-5cc72349153c&quot; style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;저 사람이 나를 비판했다.&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-fd13047e-8200-4648-bf25-651eaea69584&quot; style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;저사람이 내 마음을 짓밟았다.&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-293478e4-6e11-49e1-9cdb-9d0f37ceb973&quot; style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;저 사람이 나를 호되게 깎아내렸다.&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-0ec6e951-1305-45ac-9adb-c6e7596bbc54&quot; style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;저사람이 내 아이디어를 훔쳤다.&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-0c0481f5-c3ec-4eb5-adb0-f3b1133ab32c&quot; style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-46e6b09d-5c93-4c06-98f9-813b9d6015a9&quot; style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;이런식으로 화를 지피는걸 멈추고,&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-78a3eee8-c4d9-4836-9355-10a6511c6e5e&quot; style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;반복되는 감정에서 벗어나면,&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-f14b2007-d7ea-41b4-a3fc-313cd4b3d992&quot; style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;그 원망은 고요히 잔잔해지고&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-eae68c67-973a-43ae-8d55-7b45c70746a5&quot; style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;당신의 마음을 마침내 편안해집니다.&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;p id=&quot;SE-1ec6ae97-cb4b-4e1d-9b86-b27b0b4b6210&quot; style=&quot;color: #777777; text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;법구경&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/blockquote&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-40b9185e-d6ef-4808-8193-a25f0dcba88d&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;div&gt;
&lt;p id=&quot;SE-5ad0fec6-5c8c-40ba-8a4a-ebd0137d956a&quot; style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;lsquo;자, 보아라. 나는 대단하다.&amp;rsquo;&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-74ca81a8-7444-4df0-bcba-b4d6d82e12c2&quot; style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-a2c1442e-b424-4b4a-8595-9984c9280755&quot; style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;이렇게 자만하는 사람이 되지 마세요.&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-d9bcbd13-41ad-4d9c-97c0-5a0512651877&quot; style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;입 밖으로 노골적인 자랑을 꺼내지 않아도&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-c749385b-f4b2-4444-8836-7bba05e26c2f&quot; style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;태도나 행동에서 자만심이 묻어 나옵니다.&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-61410370-8da5-42bd-8f4c-9ba5a7ab6de2&quot; style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-ae0b89af-b1ec-4854-90f5-06554fdecb35&quot; style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;lsquo;나는 좀 알아줘&amp;rsquo;&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-c6ca33c6-5953-49e1-a3be-810574ae7f94&quot; style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;라는 마음을 내보이듯&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-b1615645-c68c-4aa5-828b-0b20320302cb&quot; style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;지나치게 자신을 자랑하지 마세요.&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-2daa5076-a277-4e55-8a49-e90ed8a3db57&quot; style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-9ae21fe6-e497-4125-ab8b-f69d87467faf&quot; style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;마음이 조금 성장했다고 해서&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-cee1a203-bd52-437c-a98c-13c71d9cf092&quot; style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;잘난 듯 굴지 마세요.&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-b705f428-7518-4c3a-b10f-348bfd25c8b6&quot; style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-5ba36f10-aec4-42ce-bc97-9fe90aa621ed&quot; style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;부디 자신도 모르는 사이에&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-b467b3ff-6024-4c9c-8ead-a0f6593ea815&quot; style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;잘난 척하고 타인에게 상처 주는 말을 내뱉지 않기를&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;p id=&quot;SE-c2024005-fed8-42ba-966e-a4f43a8d3d97&quot; style=&quot;color: #777777; text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;경집&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/blockquote&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-d45e521b-fd6f-470a-bcae-585f81ec25f7&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;div&gt;
&lt;p id=&quot;SE-573e3633-084c-46bf-8c5b-a87000d257cd&quot; style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;lsquo;역시 하지 말았어야 했다&amp;rsquo;&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-443235bb-12c7-4f52-b05b-3b86ce22806f&quot; style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;며 나중에 후회하고 고통받을 일을 저질렀다면, &lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-daffb482-db62-4033-9ebc-b3a2a3d4b4b5&quot; style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;그 일은 악업으로써 마음에 쌓입니다. &lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-4a5b7700-33b5-438a-9b22-a04108ef3451&quot; style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-0d6851f8-50f4-4651-9aa6-2393b31159fa&quot; style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;그 악업의 부정적인 에너지가 &lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-9095fdc2-4c63-4215-af98-e7af4d4f16fb&quot; style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;마음속에서 무르익어 이윽고 울면서 &lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-4fc4151c-391c-41fa-a666-c93f127f6626&quot; style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;고통의 인과응보를 받게 됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;p id=&quot;SE-13963c53-5732-4fa2-bbde-db6c3461aef5&quot; style=&quot;color: #777777; text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;법구경&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/blockquote&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-635d6612-377d-42f9-a1ce-10ea8b8e9b68&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;div id=&quot;SE-0393508a-ae61-4758-803f-f42307bb11ae&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;h3 id=&quot;SE-4564146d-3059-408d-965a-1fc5fbb5aeb7&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;&lt;b&gt;  감상 및 느낀 점&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-32007bd3-1ddb-4fd5-bd3f-e9bb3155e839&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p id=&quot;SE-778eb683-0d2d-4400-9eb9-0f28f5d1b871&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-87e065bd-640f-48ef-8410-f21a97a3e373&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;✔ &lt;/span&gt;&lt;span&gt;&lt;b&gt;단순히 종교적인 책이 아니라, &lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff0010;&quot;&gt;&lt;b&gt;누구나 쉽게 읽고 적용할 수 있는 문장들&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-1bdf98d6-3068-4115-8fb1-fe7f14ee580a&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;✔ &lt;/span&gt;&lt;span&gt;&lt;b&gt;현대인의 고민과 맞닿아 있어 &lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff0010;&quot;&gt;&lt;b&gt;위로&lt;/b&gt;&lt;/span&gt;&lt;span&gt;&lt;b&gt;가 됨&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-fdc34173-0ff5-4785-856c-ef12fb1862de&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;✔ &lt;/span&gt;&lt;span&gt;&lt;b&gt;스트레스가 쌓였을 때 &lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff0010;&quot;&gt;&lt;b&gt;마음을 다스리는 방법&lt;/b&gt;&lt;/span&gt;&lt;span&gt;&lt;b&gt;을 배울 수 있음&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-865f23d6-b6d4-4d4b-a716-d5e44669c919&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;✔ &lt;/span&gt;&lt;span&gt;&lt;b&gt;부처의 삶을 간략하게 정리한 부록도 흥미로움&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-e6077d41-d30f-49fb-ac31-644e705887ba&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-7f653991-931a-4efc-9264-19580f5ffca5&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;종교를 따로 믿지 않더라도 이 책에서 전하는 메시지는 삶을 돌아보는 데 많은 도움이 됩니다. &lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-724cea66-7df9-45ac-83a6-82a4b4aeb8a6&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;책을 읽으며 감정적으로 휩쓸리지 않고 차분히 마음을 다스리는 법을 배울 수 있었습니다.&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div id=&quot;SE-2409cd09-848e-4960-bcbf-5b0469062d4d&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 id=&quot;SE-2710fe0b-1b99-4973-b96d-29ecbcc597a7&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;&lt;b&gt;  총평 &amp;ndash; 마음을 다스리는 데 도움을 주는 책!&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-54a7eea2-573a-479b-b7f8-8685fe7702b0&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p id=&quot;SE-73adb493-fb5d-4b8f-b3a8-b47381e90c5e&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-be50bee5-66f5-4214-a1ea-faec3c7dfcba&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;✔ 마음이 힘들고 스트레스받을 때 위로가 필요하다면?&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-1c29a898-47e3-45bf-94c2-26824d394f1b&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;✔ 감정을 다스리고 삶의 균형을 찾고 싶다면?&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-3a2ce910-2973-47ec-8e56-2aa5e067b1f2&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;✔ 깊은 철학적 사유 없이도 쉽게 읽을 수 있는 책을 원한다면?&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-2067c5db-e524-49de-a416-fcc0da2e18dc&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-4017a2d0-56ba-4e5d-9494-0e3e1d66f564&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;&lt;b&gt;『초역 부처의 말』을 추천합니다!&lt;/b&gt;&lt;/span&gt;&lt;span&gt;  ✨&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-5cfa2c25-3000-469f-8d44-9ed6ea5aea41&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;div id=&quot;SE-9686195a-cc77-4791-8c3a-1a64c9aac670&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;h3 id=&quot;SE-bafc2801-3709-4539-bd65-961db9322368&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;&lt;b&gt;  구매한 곳&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-16e3de02-5cd4-4bee-961b-1697a3605f6e&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p id=&quot;SE-4eb8496e-2ef1-4b58-9c61-7875a05f4312&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;a href=&quot;https://www.yes24.com/Product/Goods/126590468&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.yes24.com/Product/Goods/126590468&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Book Review</category>
      <category>내돈내산</category>
      <category>마음</category>
      <category>부처의말</category>
      <category>스트레스</category>
      <category>아이브</category>
      <category>안정</category>
      <category>위로</category>
      <category>장원영</category>
      <category>책리뷰</category>
      <category>초역</category>
      <author>jmkim87</author>
      <guid isPermaLink="true">https://kid1412.tistory.com/293</guid>
      <comments>https://kid1412.tistory.com/293#entry293comment</comments>
      <pubDate>Sun, 16 Mar 2025 11:07:38 +0900</pubDate>
    </item>
    <item>
      <title>[내돈내산] 주식 투자 책: 비기너 편</title>
      <link>https://kid1412.tistory.com/292</link>
      <description>&lt;div id=&quot;SE-878c452b-881c-4ef9-9219-831fbd41312f&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;690&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/0p370/btsMErjNQ8Y/NEvC5EWWEvKSqOgzHWojT1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/0p370/btsMErjNQ8Y/NEvC5EWWEvKSqOgzHWojT1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/0p370/btsMErjNQ8Y/NEvC5EWWEvKSqOgzHWojT1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F0p370%2FbtsMErjNQ8Y%2FNEvC5EWWEvKSqOgzHWojT1%2Fimg.jpg&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;600&quot; height=&quot;690&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;690&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;p id=&quot;SE-34ce3205-20ae-4130-96a6-853cda67d1bd&quot; style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #555555;&quot;&gt;주식 투자 책&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-e7d13508-1825-4f02-9b23-0a112d9989bf&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;h4 id=&quot;SE-34e6e254-a4bf-4cb9-995c-0cb69545e0a2&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;&lt;b&gt;부제 : 더 이상 미룰 수 없어서 시작했지만 뭐부터 해야 할지 몰라 고른 첫 번째 머니북&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-9442047f-c81e-4004-aeeb-a65b1b47c36b&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p id=&quot;SE-e9ef0f52-be7e-4428-bee0-d6a191d129e3&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;  저자: 최광자 | 출판사: 경이로움 | 출판년도: 2024.11.15 | 페이지: 360&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div id=&quot;SE-2d658a23-a0e9-40c9-8086-6ba040240e21&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div id=&quot;SE-bece3bd5-d6ad-4737-8ab1-055842d64615&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;h3 id=&quot;SE-deaccf6f-2c2e-46a3-bff0-042085199e6d&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;&lt;b&gt;  책을 선택한 이유&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-7d818d53-cc9d-4816-9727-554d6c804a39&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p id=&quot;SE-d3bf79de-c6b6-4832-95ce-ede778c19bd3&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;주식을 시작했지만, 기초 지식 없이 투자하다 보니 어려움을 많이 겪었습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-efc667de-5add-4628-a766-bc9a5dc59c02&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;✔ 좋은 회사인지 판단하는 기준이 모호하고&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-b09e9c97-1697-4a86-938e-5d2cbf28784a&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;✔ 주식 용어가 익숙하지 않아 관련 대화에서도 어려움을 느꼈습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-2dd5657f-7054-4c91-a9c8-2a4885bd029b&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-ea454957-edeb-47d6-abb5-03fae5ba4f05&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;그래서 기초부터 다시 다지고 싶어 이 책을 선택했습니다.&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div id=&quot;SE-0ac0d7aa-754b-4d3b-b923-36b25a33c906&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 id=&quot;SE-790d395d-7805-4110-84e9-40d78fec97da&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;&lt;b&gt;  추천 대상&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-162a2d2b-28a8-48c6-9ad5-49abaad298f1&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p id=&quot;SE-fde32467-3aee-46af-9f21-8ae726ab7680&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;✅ &lt;/span&gt;&lt;span&gt;&lt;b&gt;주식 투자 초보자&lt;/b&gt;&lt;/span&gt;&lt;span&gt; &amp;ndash; 주식을 처음 시작하는 사람&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-8e88e305-b7a0-416b-9ae9-8c72c7c31412&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;✅ &lt;/span&gt;&lt;span&gt;&lt;b&gt;기본 개념이 부족한 투자자&lt;/b&gt;&lt;/span&gt;&lt;span&gt; &amp;ndash; 주식 용어와 개념을 제대로 알고 싶은 사람&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-98767ae3-b481-40f2-a31d-f7e670812c62&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;✅ &lt;/span&gt;&lt;span&gt;&lt;b&gt;기초를 다시 다지고 싶은 사람&lt;/b&gt;&lt;/span&gt;&lt;span&gt; &amp;ndash; 주식에 대해 어느 정도 알지만, 다시 정리하고 싶은 사람&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div id=&quot;SE-376d0830-5a7a-4ce2-923f-1c30f41f5e73&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 id=&quot;SE-ab7fdc08-a0fe-4e82-84ec-2f40d91ae172&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;&lt;b&gt;  책 소개&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-596ad673-c5e1-4989-9d3a-e3f6b32ed134&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p id=&quot;SE-df86f1aa-b028-4312-b7f9-0326b48a0a93&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;주식 시장에 들어선 순간, 우리는 이미 실전에 투입된 것입니다. 하지만 기본 개념을 모르고 투자하면 손실을 볼 가능성이 높죠.&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-0e30623a-dcab-4410-a367-b61def2b9b67&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;이 책은 &lt;/span&gt;&lt;span style=&quot;color: #ff0010;&quot;&gt;&lt;b&gt;투자 전 반드시 알아야 할 필수 개념&lt;/b&gt;&lt;/span&gt;&lt;span&gt;을 정리해 줍니다.&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-991a1653-75f0-4852-9604-488d67c7b6f1&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-6e91fd7e-1fd0-4f5f-bdef-8c87ae338816&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;&lt;b&gt;주식이란 무엇인가?&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-c527937a-e550-43a5-96bb-58562e69ed2e&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;&lt;b&gt;주식은 어떻게 사고파는가?&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-8d1f735c-deff-429f-9b06-6daf906966e2&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;&lt;b&gt;재무제표의 핵심 용어와 의미&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-759830de-735c-4785-b6d7-ca22da6c1c3a&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;&lt;b&gt;배당주, 공모주, ETF 투자 이해하기&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-f3cb4d87-f588-4dcf-b1cc-0e5f30f9e597&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-fc7ad788-cc22-4c59-8401-1774a4f5a1b5&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;무엇보다 &lt;/span&gt;&lt;span&gt;&lt;b&gt;실제 주식 데이터를 기반으로 설명&lt;/b&gt;&lt;/span&gt;&lt;span&gt;해 주기 때문에, 직접 주식 창을 보면서 따라 하기 좋습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-216fa9cd-66ea-4c69-a45f-0ac54b2eb6db&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-f662ca8e-0cf0-45a0-854d-21bef731b54c&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;✔ &lt;/span&gt;&lt;span&gt;&lt;b&gt;완전 초보자&lt;/b&gt;&lt;/span&gt;&lt;span&gt;라면 처음부터 차근차근&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-45ee0845-3dd9-4439-9ed9-496cca123932&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;✔ &lt;/span&gt;&lt;span&gt;&lt;b&gt;기본 개념이 있는 사람&lt;/b&gt;&lt;/span&gt;&lt;span&gt;이라면 필요한 부분만 읽어도 OK!&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-d18e206e-2909-4d14-a7a8-e25514b1ca5a&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-24d95604-c942-4221-b225-70768800152b&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 id=&quot;SE-650e19b8-abb7-44cb-be91-903a3ccfbc5f&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;&lt;b&gt;  주요 문구&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-6d985f32-c4bc-4a6f-88ba-e8198b2e3433&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p id=&quot;SE-377979b9-9c7d-4445-8b89-ffd574353847&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;책의 뒷표지 문구를 대신 정리합니다.&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-0272ff7d-dbc7-44a2-8e4f-51fd51595965&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;666&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mbGuP/btsMEYHZWb7/7ZpHuR2kH1C92X04OYMpVk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mbGuP/btsMEYHZWb7/7ZpHuR2kH1C92X04OYMpVk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mbGuP/btsMEYHZWb7/7ZpHuR2kH1C92X04OYMpVk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmbGuP%2FbtsMEYHZWb7%2F7ZpHuR2kH1C92X04OYMpVk%2Fimg.jpg&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;600&quot; height=&quot;666&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;666&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;p id=&quot;SE-42510397-0ea8-4efc-be52-9967a0ec7b47&quot; style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #555555;&quot;&gt;주식 투자 책&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-806e8ba5-9a1d-433e-b7c0-db2241e980e0&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;div&gt;
&lt;p id=&quot;SE-86fd3a7c-ddb3-45f1-bce7-bab834647218&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;이 책은 투자가 처음인 사람들을 위한 가장 기초적인 주식 책입니다. &lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-3ea4f166-a89b-476a-aa29-effbd5384c7d&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;막상 공부하려니 어디서부터 어떻게 해야 할지 모르겠다면 이 책을 읽어 보세요.&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/blockquote&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-f60502af-8e91-4a56-bd42-388d79fbe7b2&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;div&gt;
&lt;p id=&quot;SE-eecbd414-9d01-47fb-96c4-0b9cbe105bb2&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;읽는 순서는 없습니다. &lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-c4a78bf0-06f1-4f44-a1f6-63302f93093b&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;책의 처음부터 순서대로 읽어도 되고, 목차를 보며 필요한 페이지를 먼저 읽어도 됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/blockquote&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-702ad8c8-aeea-4df2-ae6b-2d39f551852c&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;div&gt;
&lt;p id=&quot;SE-7dd7982f-2c61-4f12-863f-36f15cfb2e0d&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;한번에 다 읽을 필요도 없습니다. 조금씩 필요에 따라 읽으세요. 투자를 하다 궁금한 내용이 생기면 해당 내용을 찾아 읽으면 됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/blockquote&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-7cd9d444-db2a-47f0-bd26-74f9ab34bf7d&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;div&gt;
&lt;p id=&quot;SE-238b7c9f-182d-4941-9be3-1198b9dc12da&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;1부를 읽고 나서 그 즉시 주식 한 주를 매수하세요. &lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-8e20624e-1a36-4d30-8476-ce0e65fa23c2&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;내 계좌에 주식이 있는 것만으로도 공부 의욕이 달라집니다.&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/blockquote&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-774d9cb8-3a62-46dc-b1af-0947ee0b255b&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;div&gt;
&lt;p id=&quot;SE-c003331e-72d8-4cb9-89ee-ae488bc20535&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;시간이 걸리더라도 처음부터 끝까지 완독하세요.&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-e360a47c-6484-40ff-a79e-bd3be0a10247&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;대충이라도 아는 것과 아예 모르는 것은 천지 차이니까요.&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/blockquote&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-86c1b20b-cd86-4ddd-965e-15b0663eadab&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;div&gt;
&lt;p id=&quot;SE-aa051562-3a29-458a-9e7d-de09eea803c5&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;단단한 기본기를 갖췄다면 이제 활용하고 응용할 차례입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-cf4430ec-140d-497e-849d-6515fc650fe2&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;자신감을 가지고 투자를 시작하세요.&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/blockquote&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-b45f2356-c9d2-48e5-9493-db159ac94e18&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-89ebebc7-02f9-4508-996f-b6b3990bb32e&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 id=&quot;SE-9fb12740-42fb-4f08-af3a-f50f29fe773d&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;&lt;b&gt;  감상 및 느낀 점&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-d48bb3f8-07ee-4042-a639-10ac87d2405f&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p id=&quot;SE-55437906-b1a5-43db-96c5-e13288be8408&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;✔ 주식 용어를 명확하게 이해할 수 있게 되었다.&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-c695f043-e814-490a-b5b2-17aafe439194&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;✔ ETF, 채권 등에 대한 관심이 생겼다.&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-cc65645c-d65f-4b8b-9d68-bc68fc890612&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;✔ 단순한 감이 아닌, &lt;/span&gt;&lt;span style=&quot;color: #ff0010;&quot;&gt;&lt;b&gt;지식 기반 투자&lt;/b&gt;&lt;/span&gt;&lt;span&gt;로 발전할 수 있는 계기가 되었다.&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-e693e36b-240e-4e01-8254-020830e73745&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;✔ 노후 대비 및 자산 운용에 대해 더 깊이 고민할 기회가 되었다.&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-f4eeb6b7-033b-4730-9725-c0c315d7729b&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-46c50309-be1c-48b0-8942-14995ce012ac&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;이제는 막연한 투자에서 벗어나, 보다 안정적으로 돈을 관리할 수 있을 것 같아요.&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-e795e8c1-aa0c-439a-8269-b1001462d3cf&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-1ac17cc4-cbd6-4f98-aef1-5d55e7ad2e3b&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 id=&quot;SE-4f5be53d-270f-4fbb-8cb4-2b1b29d0b602&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;&lt;b&gt;  총평 &amp;ndash; 주식 초보라면 꼭 읽어야 할 첫 번째 책!&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-1f2c3088-d267-453f-8ef6-d54334b96ebd&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p id=&quot;SE-f02c9cab-1671-43a8-8610-340c6dd717d3&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;이 책은 주식 초보자가 반드시 알아야 할 &lt;/span&gt;&lt;span style=&quot;color: #ff0010;&quot;&gt;&lt;b&gt;기본 개념을 쉽게 정리&lt;/b&gt;&lt;/span&gt;&lt;span&gt;해 줍니다.&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-48d9e55f-8c58-4daa-8b63-877108b27dda&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;✔ 주식 용어가 어렵게 느껴진다면?&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-8a029b30-ba5a-4e43-9854-3680d5bdabab&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;✔ 차트를 보며 투자하는 법을 알고 싶다면?&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-ad717fbc-0138-445a-b156-f040a0efd346&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;✔ ETF, 채권 등 다양한 투자 방식이 궁금하다면?&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-e77364a1-e1ab-4fa6-b247-28b972211bb8&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-5d7e6bd1-5cf3-4a20-9117-0f63b58b193d&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;&lt;b&gt;이 책이 당신의 &lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff0010;&quot;&gt;&lt;b&gt;첫 번째 투자 가이드&lt;/b&gt;&lt;/span&gt;&lt;span&gt;&lt;b&gt;가 되어 줄 것입니다!&lt;/b&gt;&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-a86efb20-571d-46f7-ba8e-4e9483c3f0b4&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-0d1fed2c-ea6e-41e8-87c3-30e91b638b57&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p id=&quot;SE-9c2b056d-12a6-453b-91ad-3d25aa8a10cf&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;&lt;b&gt;구매한 곳&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-b4aa597b-865d-430d-b909-1a3ade50a7f4&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p id=&quot;SE-7050f09a-56b6-48c4-b0a8-f4ffc24276a2&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;a href=&quot;https://search.shopping.naver.com/book/catalog/51209459632?query=%EC%A3%BC%EC%8B%9D%20%ED%88%AC%EC%9E%90%EC%B1%85%20%EB%B9%84%EA%B8%B0%EB%84%88%ED%8E%B8&amp;amp;NaPm=ct%3Dm811umxs%7Cci%3D8049a7d2127120ae2325be05204e6f8b32d1978f%7Ctr%3Dboksl%7Csn%3D95694%7Chk%3D88aee71e615cc06bf0bc9089d939622f99c3b800&quot;&gt;https://search.shopping.naver.com/book/catalog/51209459632?query=%EC%A3%BC%EC%8B%9D%20%ED%88%AC%EC%9E%90%EC%B1%85%20%EB%B9%84%EA%B8%B0%EB%84%88%ED%8E%B8&amp;amp;NaPm=ct%3Dm811umxs%7Cci%3D8049a7d2127120ae2325be05204e6f8b32d1978f%7Ctr%3Dboksl%7Csn%3D95694%7Chk%3D88aee71e615cc06bf0bc9089d939622f99c3b800&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-1bd04567-8e16-4c49-8ad8-344f7f1c47d2&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div style=&quot;background-color: #ffffff;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;</description>
      <category>Book Review</category>
      <category>etf</category>
      <category>IRP</category>
      <category>ISA</category>
      <category>국장</category>
      <category>배당</category>
      <category>주식</category>
      <category>주식공부</category>
      <category>주식투자</category>
      <category>코스닥</category>
      <category>코스피</category>
      <author>jmkim87</author>
      <guid isPermaLink="true">https://kid1412.tistory.com/292</guid>
      <comments>https://kid1412.tistory.com/292#entry292comment</comments>
      <pubDate>Sun, 9 Mar 2025 12:16:42 +0900</pubDate>
    </item>
    <item>
      <title>[내돈내산] 트럼프 2.0 시대 &amp;ndash; 트럼프의 재선과 세계 질서의 변화</title>
      <link>https://kid1412.tistory.com/291</link>
      <description>&lt;div id=&quot;SE-48fa8e5b-6720-46cf-8c8d-a93facd4ae62&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;966&quot; data-origin-height=&quot;1106&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rQo7E/btsMzfpCGwe/ssF37bV5yhRnC39mQio74k/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rQo7E/btsMzfpCGwe/ssF37bV5yhRnC39mQio74k/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rQo7E/btsMzfpCGwe/ssF37bV5yhRnC39mQio74k/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FrQo7E%2FbtsMzfpCGwe%2FssF37bV5yhRnC39mQio74k%2Fimg.jpg&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;966&quot; height=&quot;1106&quot; data-origin-width=&quot;966&quot; data-origin-height=&quot;1106&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-0d147677-9654-4141-9b0f-58f535139ebf&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p id=&quot;SE-98dd21ce-c327-4b98-9eeb-7786e2472a86&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-2e4991e9-7f4f-489b-afa7-631645ea819a&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;미국 역사상 가장 논란이 많았던 대통령 중 한 명, &lt;/span&gt;&lt;span style=&quot;color: #ff0010;&quot;&gt;&lt;b&gt;도널드 트럼프&lt;/b&gt;&lt;/span&gt;&lt;span&gt;&lt;b&gt;가 다시 백악관에 돌아왔다&lt;/b&gt;&lt;/span&gt;&lt;span&gt;. 그의 재선이 글로벌 경제와 국제 관계에 미치는 영향은 과연 무엇일까? &lt;/span&gt;&lt;span style=&quot;color: #ff0010;&quot;&gt;&lt;b&gt;『트럼프 2.0 시대』&lt;/b&gt;&lt;/span&gt;&lt;span&gt;는 트럼프의 정치 철학과 앞으로의 세계 전략을 분석한 책이다.&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-e1b63a67-b96a-4222-a78e-a3d2749b263a&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-4cf942cc-8a3c-4888-84a8-50cef727d7f3&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;h3 id=&quot;SE-48bd5350-cd9d-454e-b073-ffd27e2056dc&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;&lt;b&gt;  책을 선택한 이유&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-94edbfb1-fcee-4726-b87c-9403f051d85d&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;966&quot; data-origin-height=&quot;1194&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/NlV2U/btsMzga31pD/fOVvL0p4A89d3gfVqNN0A1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/NlV2U/btsMzga31pD/fOVvL0p4A89d3gfVqNN0A1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/NlV2U/btsMzga31pD/fOVvL0p4A89d3gfVqNN0A1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FNlV2U%2FbtsMzga31pD%2FfOVvL0p4A89d3gfVqNN0A1%2Fimg.jpg&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;966&quot; height=&quot;1194&quot; data-origin-width=&quot;966&quot; data-origin-height=&quot;1194&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-f8eef4ec-9ef9-423e-be32-b171bc2b7925&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p id=&quot;SE-aeea74d2-c8dc-4d13-8078-5dcc8f83b61b&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;2024년 11월 5일, 도널드 트럼프가 재선에 성공하면서 그의 정책 방향과 세계에 미칠 영향을 파악하고 싶었다. &lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-7bcfd9b0-bb96-4e1a-a441-9fa35446ee03&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;특히 미국 주식시장과 국제 정세가 어떻게 변화할지 궁금하여 이 책을 읽게 되었다.&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-e9620cbf-2109-4f5b-8497-e48149361a6b&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-d491f0b0-687f-4540-899a-fd880ceae40d&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;h3 id=&quot;SE-a13050ee-ceaf-456e-98c4-78b58b71adbd&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;&lt;b&gt;  추천 대상&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-b0956b0c-de3e-4d14-9242-69b9c0ca538a&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p id=&quot;SE-326225e2-d365-4605-8a32-b408007e4e09&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;✅ &lt;/span&gt;&lt;span style=&quot;color: #ba0000;&quot;&gt;&lt;b&gt;미국 주식 투자자&lt;/b&gt;&lt;/span&gt;&lt;span&gt; &amp;ndash; 트럼프의 정책 변화가 시장에 어떤 영향을 미칠지 알고 싶은 분&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-4288092f-673a-4d58-8820-b21afc727025&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;✅ &lt;/span&gt;&lt;span style=&quot;color: #ba0000;&quot;&gt;&lt;b&gt;국제 정세에 관심 있는 사람&lt;/b&gt;&lt;/span&gt;&lt;span&gt; &amp;ndash; 미&amp;middot;중 관계, AI 패권 경쟁, 글로벌 무역 흐름을 알고 싶은 분&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-77e86fe9-69ee-4c88-816e-e64d6a63d00e&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;✅ &lt;/span&gt;&lt;span style=&quot;color: #ba0000;&quot;&gt;&lt;b&gt;트럼프의 정치 철학을 이해하고 싶은 사람&lt;/b&gt;&lt;/span&gt;&lt;span&gt; &amp;ndash; 트럼프 1기와 2기의 차이점을 분석하고 싶은 분&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-9e5dd9df-7dff-4b44-bb86-8b21a6e4a9ca&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-a6ab3a68-5d54-4320-96c8-7c3d177d91f7&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;h3 id=&quot;SE-2f0e6ba9-6122-463f-aaee-6500a7f384fa&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;&lt;b&gt;  책 소개&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-15c27887-4549-40f6-8aae-56c4f767fe8b&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p id=&quot;SE-8f354934-f24f-48e0-89d1-604e97446a8c&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;이 책은 도널드 트럼프가 재선에 성공한 이후, 그의 정책 방향과 세계 질서에 미치는 영향을 분석한다.&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-78cd2d74-0378-4254-8811-805f2055a363&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-cdc60cf0-d3be-4132-b5bc-599b9b501407&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;h3 id=&quot;SE-7bd6aa65-4565-474c-aa8b-a47fd4fe9576&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;&lt;b&gt;왜 미국인들은 다시 트럼프를 선택했을까?&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-16838f19-0590-41ae-9539-5b235c7369b4&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p id=&quot;SE-7ebd551f-28f7-4d08-84ce-25a56067c91c&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;트럼프 1기에서 그는 &lt;/span&gt;&lt;span style=&quot;color: #ba0000;&quot;&gt;&lt;b&gt;미국 우선주의(America First)&lt;/b&gt;&lt;/span&gt;&lt;span&gt;를 내세우며 보호무역 정책을 강화했다. &lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;하지만 2기에서는 더욱 강경한 입장을 취하고 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-6cf2485b-8bf4-43ce-9b32-beed744a2595&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-3bb2fe25-3b3c-415e-87b8-110928932077&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;h3 id=&quot;SE-f7633544-9a4f-41ae-a314-b7467859285f&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;&lt;b&gt;트럼프 2기의 핵심 키워드&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-a831f867-18aa-4857-9735-2677131b3833&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p id=&quot;SE-21619215-5d35-4826-843f-6721bf0fe5c6&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;bull; 역사상 최강의 &lt;/span&gt;&lt;span style=&quot;color: #ba0000;&quot;&gt;&lt;b&gt;미국 우선주의&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-01f94d1a-e366-43a2-80fa-2b8709a54cc9&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;bull; 중국과의 &lt;/span&gt;&lt;span style=&quot;color: #ba0000;&quot;&gt;&lt;b&gt;AI 패권 전쟁&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-83a6db5f-8466-411d-86c0-236bf09b211b&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;bull; 글로벌 &lt;/span&gt;&lt;span style=&quot;color: #ba0000;&quot;&gt;&lt;b&gt;관세 정책 변화&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-2fe9b205-c7b0-459e-bd17-9af61c90bfa0&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;bull; &lt;/span&gt;&lt;span style=&quot;color: #ba0000;&quot;&gt;&lt;b&gt;해상 패권&lt;/b&gt;&lt;/span&gt;&lt;span&gt;을 둘러싼 미국과 중국의 대립&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-1b38a22c-16a1-4c8d-9520-e01d217b7ae3&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;bull; 대만 문제와 미국의 &lt;/span&gt;&lt;span style=&quot;color: #ba0000;&quot;&gt;&lt;b&gt;국제 전략 변화&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-4bde6253-5b59-423d-a732-9c4fc4caf77a&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-68dbbd1a-3f67-4b2a-9bac-45caeb91dc66&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;트럼프 2기에서는 중국과의 경쟁이 더욱 치열해지고, 대만 문제에 대한 미국의 개입이 가시화될 가능성이 크다. 이 책은 트럼프 정부가 추진할 경제, 외교, 군사 정책을 예측하며 앞으로의 세계 정세를 분석한다.&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-e20cfa20-af96-45c5-83f5-6f7bc8d7c658&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-5fb2306b-052c-46db-9c59-3db527c225a7&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;h3 id=&quot;SE-c405d465-62a6-420c-831d-a54370545296&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;&lt;b&gt;  주요 소제목&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-5b641576-e33a-437f-9d51-1e16decb7442&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;div&gt;
&lt;p id=&quot;SE-25a63a4e-e467-4d9d-bc40-95bdbd1bdaf6&quot; style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;b&gt;더 강력해진 트럼프가 온다&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/blockquote&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-c80f0c5e-1290-4b7f-96bb-745b976e2c2e&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;div&gt;
&lt;p id=&quot;SE-023e9632-a9fd-498e-8610-681d173e9207&quot; style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;b&gt;역사상 최강의 미국 우선주의&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/blockquote&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-c0ef28c3-15da-4b72-bf37-0e75f0e833af&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;div&gt;
&lt;p id=&quot;SE-8118d2ae-8467-405e-bd54-38b52f1e590f&quot; style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;b&gt;누가 해상 패권을 차지할 것인가?&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/blockquote&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-66d7ffec-77bc-45a7-8864-1a7458a349dc&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p id=&quot;SE-c8f43ae1-55fa-4ae3-a75b-c0c0000c75d9&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-d5bd4dcc-c5e7-43cf-9f14-6b8419fc695f&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;이 소제목만 봐도 트럼프 2기의 정책 기조가 1기보다 더 강력해질 것임을 예측할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-a060d4f9-709f-4798-9e8a-058b6baa62cb&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-3682e9af-48de-4b89-ab0a-31a79e4d6f92&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;h3 id=&quot;SE-6290eaff-27f7-4346-950c-0137b6179567&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;&lt;b&gt;  감상 및 느낀 점&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-e448e961-ac4f-4eb2-a57f-649b6c8bf990&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p id=&quot;SE-31e4045d-7dc2-458c-8cf3-bee544683379&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-ccdd1594-747e-4045-8bf6-d04140f27845&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;✔&lt;/span&gt;&lt;span style=&quot;color: #ba0000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #ba0000;&quot;&gt;&lt;b&gt;트럼프 1기와 2기의 차이점&lt;/b&gt;&lt;/span&gt;&lt;span&gt;&lt;b&gt;을 명확하게 비교&lt;/b&gt;&lt;/span&gt;&lt;span&gt; &amp;ndash; 단순한 연임이 아니라 완전히 새로운 국면으로 들어섰음을 실감할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-2a6e1379-9a3d-44d4-bda6-6b7834a10c44&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;✔ &lt;/span&gt;&lt;span&gt;&lt;b&gt;정책이 실현될 경우, &lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: #ba0000;&quot;&gt;&lt;b&gt;글로벌 시장과 한국 경제에 미치는 영향 분석&lt;/b&gt;&lt;/span&gt;&lt;span&gt;&lt;b&gt;이 인상적&lt;/b&gt;&lt;/span&gt;&lt;span&gt; &amp;ndash; 특히 한국이 직면할 문제와 해결 방안을 제시한다.&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-1bb60ac9-3ff2-49f9-b1be-e3a3bd15f532&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;✔ &lt;/span&gt;&lt;span style=&quot;color: #ba0000;&quot;&gt;&lt;b&gt;AI 패권 경쟁, 해상 패권 등 미국과 중국의 갈등&lt;/b&gt;&lt;/span&gt;&lt;span&gt;&lt;b&gt;을 구체적으로 다룸&lt;/b&gt;&lt;/span&gt;&lt;span&gt; &amp;ndash; 국제 정세에 관심 있는 사람이라면 반드시 읽어야 할 책.&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-8b302a6c-c32f-4702-96ac-87688b31b835&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-12ee67d1-291b-481a-96fb-09547c38f485&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;h3 id=&quot;SE-6196c204-4bb4-4597-a53d-aca8763fd447&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;&lt;b&gt;  총평 &amp;ndash; 트럼프 시대의 변화를 알고 싶다면 꼭 읽어야 할 책!&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-1182fe1c-3b41-4851-be79-d4112644f912&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p id=&quot;SE-e78c60e6-dbd6-4438-85d1-df088ebdfb6c&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-49e83c57-e7d2-44b2-9b75-ce4ac33b2ced&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;이 책은 트럼프 2기의 정책 기조를 분석하고, 글로벌 경제와 국제 관계에 미치는 영향을 다룬다. &lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-14f1fcc0-062e-4836-9eed-b03c07483f76&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;특히 미&amp;middot;중 경쟁, 대만 문제, 해상 패권 등을 중심으로 향후 미국의 행보를 예측한다.&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-fbf42fcd-ebf0-4af1-90d3-bca6eb252864&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-a8ac876f-f23f-432b-adc2-8cf8028fa6c8&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;✔ &lt;/span&gt;&lt;span&gt;&lt;b&gt;트럼프의 정책 변화가 시장과 국제 관계에 미칠 영향을 알고 싶은 사람&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-8444254b-9e3b-480d-ae1d-8b875326f872&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;✔ &lt;/span&gt;&lt;span&gt;&lt;b&gt;미국 우선주의가 더욱 강해지는 시대, 한국의 대응 전략을 고민하는 사람&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-12efdef3-a840-4f22-a152-3d00bdb9a204&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;✔ &lt;/span&gt;&lt;span&gt;&lt;b&gt;미&amp;middot;중 패권 전쟁과 AI 경쟁의 향방을 알고 싶은 사람&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-da9f3013-fe25-4b92-bb9d-b88da20e9df6&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-28399501-aa0f-4c4a-a719-d405872a1ec4&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;  트럼프 2.0 시대를 제대로 이해하고 싶다면, 꼭 읽어봐야 할 책!&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-69439d10-5a95-4db0-9f5c-1351bfa4e183&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-bc8ddf06-82ab-4113-8466-73603956323c&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;h3 id=&quot;SE-b92dc2bf-d6df-4af2-b433-40d146c5aebb&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;&lt;b&gt;구매한 곳&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-db341814-1009-46d7-a323-e9d9b605e9fd&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p id=&quot;SE-5965f487-3134-430a-aafb-9d3c0695f483&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;a href=&quot;https://www.yes24.com/Product/Goods/136734901&quot;&gt;https://www.yes24.com/Product/Goods/136734901&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;</description>
      <category>Book Review</category>
      <category>경제</category>
      <category>러시아</category>
      <category>미국</category>
      <category>미국우선주의</category>
      <category>우크라이나</category>
      <category>중국</category>
      <category>트럼프</category>
      <category>트럼프2기</category>
      <category>패권</category>
      <category>한국</category>
      <author>jmkim87</author>
      <guid isPermaLink="true">https://kid1412.tistory.com/291</guid>
      <comments>https://kid1412.tistory.com/291#entry291comment</comments>
      <pubDate>Sat, 1 Mar 2025 15:32:10 +0900</pubDate>
    </item>
    <item>
      <title>[내돈내산] 디자인 구구단 &amp;ndash; 디자인이 필요한 순간, &amp;lsquo;툭&amp;rsquo; 튀어나오는 디자인 공식</title>
      <link>https://kid1412.tistory.com/290</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;edited_IMG_5998.jpeg&quot; data-origin-width=&quot;400&quot; data-origin-height=&quot;468&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Uchj3/btsMlmBzheT/ox1P4skU22v1fB7tZHZhnK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Uchj3/btsMlmBzheT/ox1P4skU22v1fB7tZHZhnK/img.png&quot; data-alt=&quot;디자인 구구단&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Uchj3/btsMlmBzheT/ox1P4skU22v1fB7tZHZhnK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FUchj3%2FbtsMlmBzheT%2Fox1P4skU22v1fB7tZHZhnK%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;400&quot; height=&quot;468&quot; data-filename=&quot;edited_IMG_5998.jpeg&quot; data-origin-width=&quot;400&quot; data-origin-height=&quot;468&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;디자인 구구단&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;div id=&quot;SE-db63b171-4c13-4222-82c9-466e1ecbd449&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p id=&quot;SE-8e915ef3-e881-4012-921a-924ed05eefb5&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ff0010;&quot;&gt;&lt;b&gt;디자인을 배우고 싶지만&lt;/b&gt;&lt;/span&gt;&lt;span&gt; 어렵게만 느껴지는 분들에게, 또는 &lt;/span&gt;&lt;span style=&quot;color: #ff0010;&quot;&gt;&lt;b&gt;디자인이 필요한 순간 쉽게 활용&lt;/b&gt;&lt;/span&gt;&lt;span&gt;할 수 있는 공식이 있다면 얼마나 좋을까요? &lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-38f9b1e7-b820-4976-89c2-848b5935dab6&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;b&gt;에이핫 작가의 『디자인 구구단』&lt;/b&gt;&lt;/span&gt;&lt;span&gt;은 디자인을 &lt;/span&gt;&lt;span style=&quot;color: #ff0010;&quot;&gt;​&lt;/span&gt;&lt;span style=&quot;color: #ff0010;&quot;&gt;&lt;b&gt;&amp;lsquo;구구단&amp;rsquo;&lt;/b&gt;&lt;/span&gt;&lt;span&gt;처럼 쉽게 익힐 수 있도록 도와주는 책입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-69364a6f-196f-44de-9c14-583c0013f0a7&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;b&gt;​&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-430bc4a4-a014-414d-93d5-559a16f974f3&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;h3 id=&quot;SE-2f9ee6cd-cfc6-444a-b080-3f816ade52c9&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;&lt;b&gt;  책을 선택한 이유&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-2a72b9fe-0caf-4f45-8373-8cdb72d5cab5&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p id=&quot;SE-af2fa8a4-51c9-40ae-8646-9917942a0917&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;b&gt;이 책은 회사 팀장님의 추천으로 접하게 되었고, 개인적으로도 디자인에 대한 관심이 있어서 읽게 되었습니다. 웹 개발을 하면서 디자인 감각이 중요하다고 느꼈고, 좀 더 체계적으로 배우고 싶던 차에 딱 맞는 책이었어요.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-e80a646c-20b1-4f72-9f5c-6fad0a73acfa&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-9e509b1a-26ad-4898-b761-b0c04d7b3203&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;h3 id=&quot;SE-e1cf4527-2838-4072-9332-22c1edfa86db&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;&lt;b&gt;  추천 대상&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-213b3a08-3f41-452d-8c0e-471e12c891da&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p id=&quot;SE-af9b9a07-6a65-4548-8666-8fe57cf23726&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;이 책은 특정 직군만을 위한 것이 아닙니다!&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-2234a65e-ba28-4570-9560-756f8a53339f&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;✅ &lt;/span&gt;&lt;span&gt;&lt;b&gt;웹 개발자&lt;/b&gt;&lt;/span&gt;&lt;span&gt; &amp;ndash; UI/UX 감각을 키우고 싶은 분&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-f0f2d7bb-dece-4466-adb8-5338515655b7&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;✅ &lt;/span&gt;&lt;span&gt;&lt;b&gt;웹 디자이너&lt;/b&gt;&lt;/span&gt;&lt;span&gt; &amp;ndash; 디자인 이론을 쉽게 정리하고 싶은 분&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-9429b034-6e4c-44a5-9962-4123a82c455a&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;✅ &lt;/span&gt;&lt;span&gt;&lt;b&gt;사진작가&lt;/b&gt;&lt;/span&gt;&lt;span&gt; &amp;ndash; 색감과 구도를 더 잘 이해하고 싶은 분&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-07bb9b20-c612-402b-a3f3-a6634319fe40&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;✅ &lt;/span&gt;&lt;span&gt;&lt;b&gt;PPT 작업이 많은 직장인&lt;/b&gt;&lt;/span&gt;&lt;span&gt; &amp;ndash; 자료를 더 효과적으로 표현하고 싶은 분&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-573bc45a-f69d-475a-a0c2-e5448212b8c1&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;✅ &lt;/span&gt;&lt;span&gt;&lt;b&gt;인테리어&amp;middot;광고&amp;middot;포스터 제작에 관심 있는 모든 분&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-4d52d59d-a3e7-43a1-949a-79fac1d75a43&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-ca41db44-dbc9-48cc-a920-79b3c526d625&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;  디자인을 전문적으로 배우지 않은 분들도 &lt;/span&gt;&lt;span style=&quot;color: #ff0010;&quot;&gt;&lt;b&gt;쉽게 이해할 수 있도록 구성&lt;/b&gt;&lt;/span&gt;&lt;span&gt;되어 있어 누구나 부담 없이 읽을 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-a374845a-708f-4e12-92ca-4d7d28d7dd64&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-ed7c27f7-d5f5-4590-9b68-96e11c8f4f51&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;h3 id=&quot;SE-8199f8d7-5d39-4a85-9032-e8d7b07df6c4&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;&lt;b&gt;  책 소개&lt;/b&gt;&lt;/span&gt;&lt;b&gt;​&lt;/b&gt;&lt;/h3&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-be1f5a6e-c8c8-4f6c-8e4e-f95ef7708f91&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;p id=&quot;SE-1d691ffa-5a7b-4b7b-8c0a-fe6c47859ec7&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;b&gt;디자인, 어렵게만 느껴지시나요?&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-1961a832-d396-4bbc-abc3-d88fce55e628&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;이 책은 &lt;/span&gt;&lt;span&gt;&lt;b&gt;디자인을 처음 접하는 사람&lt;/b&gt;&lt;/span&gt;&lt;span&gt;들도 부담 없이 배울 수 있도록 설명합니다. 디자인을 &lt;/span&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;&amp;lsquo;메시지를 전달하는 다리&amp;rsquo;&lt;/b&gt;&lt;/span&gt;&lt;span&gt;라고 정의하며, 이를 &lt;/span&gt;&lt;span&gt;&lt;b&gt;9가지 공식(구구단)&lt;/b&gt;&lt;/span&gt;&lt;span&gt;로 쉽게 풀어줍니다.&lt;/span&gt;&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;IMG_6001.JPG&quot; data-origin-width=&quot;1616&quot; data-origin-height=&quot;2573&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cDpUH4/btsMkJjFKt0/FUKPVEoFqGkGFMXdQ7IKz1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cDpUH4/btsMkJjFKt0/FUKPVEoFqGkGFMXdQ7IKz1/img.jpg&quot; data-alt=&quot;9단 이론&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cDpUH4/btsMkJjFKt0/FUKPVEoFqGkGFMXdQ7IKz1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcDpUH4%2FbtsMkJjFKt0%2FFUKPVEoFqGkGFMXdQ7IKz1%2Fimg.jpg&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;400&quot; height=&quot;637&quot; data-filename=&quot;IMG_6001.JPG&quot; data-origin-width=&quot;1616&quot; data-origin-height=&quot;2573&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;9단 이론&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;div&gt;
&lt;p id=&quot;SE-d05fa97a-168e-4888-9a6f-5c2bed0103df&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;  무엇보다 이 책의 큰 장점은 &lt;/span&gt;&lt;span style=&quot;color: #ff0010;&quot;&gt;&lt;b&gt;만화 형식&lt;/b&gt;&lt;/span&gt;&lt;span&gt;으로 구성되어 있다는 점!&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-160b0ed7-653c-4589-a0cf-1360e79da32d&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;  딱딱한 이론서가 아니라 &lt;/span&gt;&lt;span style=&quot;color: #ff0010;&quot;&gt;&lt;b&gt;실제 예시와 그림으로 쉽게 설명&lt;/b&gt;&lt;/span&gt;&lt;span&gt;하기 때문에 읽는 내내 지루하지 않습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-d0a8a9db-ee5f-408e-9ab2-f3017909f360&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;  이 책에서 익힌 디자인 감각은 &lt;/span&gt;&lt;span style=&quot;color: #ff0010;&quot;&gt;&lt;b&gt;웹 디자인뿐만 아니라 사진, PPT, 인테리어, 광고 등 다양한 분야&lt;/b&gt;&lt;/span&gt;&lt;span&gt;에 적용할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;div id=&quot;SE-e976dea8-b184-439a-826b-75d34ab7df09&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;h3 id=&quot;SE-bfa85fc8-0ccc-4617-ba2d-6258a2497d25&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;&lt;b&gt;  주요 문구&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;/div&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;b&gt;제 목표는 디자인의 힘을 디자이너뿐만 아니라&lt;/b&gt;&lt;br /&gt;&lt;b&gt;모든 사람이 쓸 수 있도록 만드는 것입니다.​&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;디자인이 가진 힘은 여러분이 생각하는 것보다 훨씬 강력합니다.&lt;/b&gt;&lt;br /&gt;&lt;b&gt;여러분의 잠재력과 디자인이 만나면가능성이 무한대로 펼쳐질 것입니다.​&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;사람들에게 메시지를 던지고 있다면당신은 이미 크리에이터다.&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;디자인 구구단 프롤로그 - 에이핫 -&lt;/blockquote&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-972a960d-97a3-4bb4-944d-618b0384b8a8&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p id=&quot;SE-9d8a2d4d-4f7e-4c8f-ba99-e2341c6f5be8&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;이 문장들에서 알 수 있듯이, 저자는 디자인을 단순한 미적 요소가 아니라 &lt;/span&gt;&lt;span style=&quot;color: #ff0010;&quot;&gt;&lt;b&gt;강력한 커뮤니케이션 도구&lt;/b&gt;&lt;/span&gt;&lt;span&gt;로 바라봅니다. 그리고 이 도구를 누구나 활용할 수 있도록 돕고 싶어 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-7a3cce0c-918a-4c68-adb5-e43a2ee8a8f4&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-977c84a7-b635-40ca-acd6-9bc879f634ef&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;h3 id=&quot;SE-8b32a899-8967-4667-bb6b-07988b88ab8e&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;&lt;b&gt;  감상 및 느낀 점&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-8a185234-6d8d-4520-a6a5-03f27c13cd5b&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p id=&quot;SE-903a49f3-35a9-4514-8fc1-b6de4f3447ba&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;✔ &lt;/span&gt;&lt;span&gt;&lt;b&gt;쉽고 재미있게 읽힘&lt;/b&gt;&lt;/span&gt;&lt;span&gt; &amp;ndash; 만화 형식이라 부담 없이 술술 읽을 수 있음.&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-81ea6db6-593c-4019-a1a7-2b772e5ac5e6&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;✔ &lt;/span&gt;&lt;span&gt;&lt;b&gt;실제 사례와 그림이 많아 이해가 빠름&lt;/b&gt;&lt;/span&gt;&lt;span&gt; &amp;ndash; 디자인 이론이 아니라, 실제 적용할 수 있도록 설명.&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-1010d703-a0e3-4099-97e5-9ffeed782788&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;✔ &lt;/span&gt;&lt;span&gt;&lt;b&gt;웹디자인뿐만 아니라 사진, 광고, 포스터 등에도 활용 가능&lt;/b&gt;&lt;/span&gt;&lt;span&gt; &amp;ndash; 단순히 &amp;lsquo;디자인 공부&amp;rsquo;가 아니라, 다양한 분야에서 응용할 수 있음.&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-16df73bc-f2a9-4160-b86c-3c42102fb9ea&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;✔ &lt;/span&gt;&lt;span&gt;&lt;b&gt;업무와 취미생활에도 도움이 됨&lt;/b&gt;&lt;/span&gt;&lt;span&gt; &amp;ndash; 디자인 감각을 키우고 싶다면 누구에게나 추천하고 싶은 책.&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-184031bc-128b-4e3d-870c-00524db26ccf&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-1aa937da-85d3-4971-afce-45338fd205c6&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;이 책을 읽고 나니, 단순히 웹디자인뿐만 아니라 &lt;/span&gt;&lt;span&gt;&lt;b&gt;사진을 찍을 때, 광고나 포스터를 볼 때, PPT를 만들 때도&lt;/b&gt;&lt;/span&gt;&lt;span&gt; &amp;lsquo;이 디자인이 어떤 메시지를 전달하려고 하는지&amp;rsquo; 생각하게 되었습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-43d667c0-0e69-4d07-82bf-68dc236c401e&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-d2c72608-8157-4840-979e-e228e02969d8&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;h3 id=&quot;SE-a60621d2-7b1a-4240-a5e8-481fda0aee56&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;&lt;b&gt;  총평 &amp;ndash; 누구에게나 추천하고 싶은 디자인 입문서!&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-075cb556-d018-41bf-b452-8bd9c0ad9581&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p id=&quot;SE-44ca255c-3d65-4d3e-8238-1f0aed5a912f&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;이 책은 디자인을 전공하지 않았어도 누구나 쉽게 이해하고 활용할 수 있도록 구성되어 있습니다. 회사에서 웹 디자인이 필요해서 읽기 시작했지만, 읽다 보니 &lt;/span&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;디자인이 단순한 &amp;lsquo;예쁜 꾸밈&amp;rsquo;이 아니라 강력한 메시지 전달 수단&lt;/b&gt;&lt;/span&gt;&lt;span&gt;이라는 걸 깨달았습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-c7d9fe3e-bb51-42a2-9146-9790b44c98af&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-3f1f792e-78b9-4e9b-9c87-9f845224d645&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;✔ &lt;/span&gt;&lt;span&gt;&lt;b&gt;디자인이 어렵게만 느껴졌다면?&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-65a2e90b-7f5d-4785-887e-71fb058a4dd4&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;✔ &lt;/span&gt;&lt;span&gt;&lt;b&gt;색감과 구도를 어떻게 활용해야 할지 모르겠다면?&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-a5a71a88-4e38-421a-b725-68063ad455fe&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;✔ &lt;/span&gt;&lt;span&gt;&lt;b&gt;PPT, 사진, 광고 등에서 감각을 키우고 싶다면?&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-c3013dfb-d2a5-45eb-a572-4edd547299ba&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-78d70748-80ef-4dc7-8fc1-06e2bc0579ba&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;  이 책이 &lt;/span&gt;&lt;span&gt;&lt;b&gt;디자인 감각을 키우는 최고의 입문서&lt;/b&gt;&lt;/span&gt;&lt;span&gt;가 될 것입니다!  ✨&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-d6aaf0eb-3fcd-4520-ac92-22722bda8fc8&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-e46721a8-bc7d-4093-ac92-02e71cd85851&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;h3 id=&quot;SE-fb67c90d-b5a4-49ec-a12b-3004f6043908&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;  구매한 곳&lt;/span&gt;&lt;/h3&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-1d980c1f-9835-4621-b0e9-eebcdfface40&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p id=&quot;SE-2dcd2850-77be-4e42-bf21-d6b896361541&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;a href=&quot;https://www.yes24.com/Product/Goods/129392318&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://www.yes24.com/Product/Goods/129392318&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;</description>
      <category>Book Review</category>
      <category>디자이너</category>
      <category>디자인구구단</category>
      <category>사진</category>
      <category>사진작가</category>
      <category>에이핫</category>
      <category>웹디자인</category>
      <category>책리뷰</category>
      <category>책리뷰블로그</category>
      <category>책추천</category>
      <category>포스터</category>
      <author>jmkim87</author>
      <guid isPermaLink="true">https://kid1412.tistory.com/290</guid>
      <comments>https://kid1412.tistory.com/290#entry290comment</comments>
      <pubDate>Sun, 16 Feb 2025 12:20:03 +0900</pubDate>
    </item>
    <item>
      <title>HTTP/3 (HTTP Protocol 발전 과정)</title>
      <link>https://kid1412.tistory.com/247</link>
      <description>&lt;h1&gt;HTTP/3&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2019년 9월 정도에 새로운 웹 표준인 HTTP/3에 대한 지원을 발표하였습니다.&lt;br /&gt;파트 내에서 웹 로딩 및 접근 속도를 위해서 조사를 하였습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;HTTP Protocol 발전 과정&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;요약&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;380&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ca8HTD/btqNNikNQXj/2fJdPVNLx24Sic4uxTQwA1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ca8HTD/btqNNikNQXj/2fJdPVNLx24Sic4uxTQwA1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ca8HTD/btqNNikNQXj/2fJdPVNLx24Sic4uxTQwA1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fca8HTD%2FbtqNNikNQXj%2F2fJdPVNLx24Sic4uxTQwA1%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;1024&quot; height=&quot;380&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;380&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;HTTP/0.9&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;HTTP 초기 버전에는 버전 번호가 없지만 추후 버전과 구별을 위해 붙여졌습니다.&lt;/p&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: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;GET 메소드만 존재&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;HTTP 헤더가 존재하지 않음&lt;/b&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;HTTP/1.0&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;0.9버전에서 브라우저와 서버 모두 융통성을 가지도록 확장되었습니다.&lt;/p&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: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;버전 정보가 각 요청 사이내로 전송되기 시작 (HTTP/1.0 GET &lt;del&gt;~&lt;/del&gt;)&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;HTTP Status code가 라인 또는 시작 부분에 붙어 전송&lt;/b&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;브라우저의 요청에 대한 성공 실패 여부 확인 및 그에 따른 동작&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;HTTP 헤더 개념이 요청, 응답 모두에 도입&lt;/b&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;메타 데이터 전송을 허용&lt;/li&gt;
&lt;li&gt;프로토콜을 극도로 유연하고 확장 가능&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;HTML 파일들 외에 다른 문서들을 전송하는 기능 추가 (Content-Type)&lt;/b&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;HTTP/1.1&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1.0이 나온지 몇달 안되고 나서 발표 되었으며, 많은 개선 사항을 도입되었습니다.&lt;/p&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: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;커넥션 재사용&lt;/b&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;탐색된 단일 원본 문서 내로 임베드된 리소스들을 디스플레이하기 위해 사용된 커넥션을 다시 열어 시간 절약&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;파이프라이닝 추가&lt;/b&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;커뮤니케이션 레이턴시를 낮춤
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;첫번째 요청에 대한 응답이 완전히 전송되지 전에 두번째 요청 전송을 가능케 함&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;청크된 응답 지원&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;캐시 제어 메커니즘 도입&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;언어, 인코딩 혹은 타입을 포함한 컨텐츠 협상 도입&lt;/b&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;클라이언트와 서버로 하여금 교환하려는 가장 적합한 컨텐츠에 대한 동의를 가능케 함&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Host 헤더 추가&lt;/b&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;동일 IP 주소에 다른 도메인을 호스트 하는 기능&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;기타
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;HTTPS&lt;/b&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;SSL(Secure Sockets Layer, 보안 소켓 계층) : 웹사이트와 브라우저 사이에 전송된 데이터를 암호화하여 보안을 유지하는 표준 기술&lt;/li&gt;
&lt;li&gt;TLS(Transport Layer Security, 전송 계층 보안) : SSL의 상위 기술, SSL 3.0버전에서 취약점을 고친 버전으로 버전이 올라갈 때마다 암호화 알고리즘을 강력한 것으로 변경합니다. (현재는 1.3버전 진행 중)&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;REST&lt;/b&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;API에 의해 유도되는 액션들은 새로운 HTTP 메소드 뿐만 아니라, 기초적인 HTTP/1.1 메소드를 이용&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Same-Origin 정책&lt;/b&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;웹 보안을 위해 &lt;a href=&quot;https://developer.mozilla.org/ko/docs/Web/HTTP/CORS&quot;&gt;CORS(Cross-Origin Resources Share)&lt;/a&gt; or &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP&quot;&gt;CSP(Contents Security Policy)&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;HTTP/2&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Google에서 응답 속도를 개선을 위해서 SPDY 프로토콜을 구현하였으며, 속도 개선의 가능성과 데이터 중복에 관한 문제를 해결하면서 HTTP/2로 거듭 납니다.&lt;/p&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: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;바이너리 프레이밍 계층&lt;/b&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;1.1버전은 줄바꿈으로 구분되는 일반 텍스트로 인코딩&lt;/li&gt;
&lt;li&gt;2.0은 더 작은 메시지와 프레임으로 분할되며, 각각은 바이너리 형식으로 인코딩&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/0CziC/btqNMNyAX3Y/tW8xOno9MNDntQxvzEcfJ0/tfile.svg&quot; width=&quot;100%&quot; /&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;스트림, 메시지 및 프레임 교환 방식&lt;/b&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;스트림&lt;/b&gt; : 구성된 연결 내에서 전달되는 바이트의 양방향 흐름
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;모든 통신은 단일 TCP을 통해 수행&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;b&gt;메시지&lt;/b&gt; : 논리적 요청, 응답 메시지에 매핑되는 프레임의 전체 시퀀스
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;각 메시지는 하나의 논리적 HTTP 메시지 이며, 하나 이상의 프레임으로 구성&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;프레임&lt;/b&gt; : HTTP/2에서 통신의 최소 단위이며, 하나의 프레임 헤더가 포함
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;특정 유형의 데이터(HTTP 헤더, 메시지 페이로드 등)를 전달&lt;/li&gt;
&lt;li&gt;다름 스트림들의 프레임을 interleaving 한 다음, 각 프레임의 헤더에 삽입된 스트리 식별자를 통해 재조립 가능&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/oGihs/btqNNhGcCZM/n86xeMSmoFsawTaL3CZNx1/tfile.svg&quot; width=&quot;100%&quot; /&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;요청 및 응답 다중화&lt;/b&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;HTTP 메시지 프레임 세분화 및 재조립&lt;/b&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;1.1에서 병렬 요청 시 여러 TCP 연결 사용에 대한 동작 해결&lt;/li&gt;
&lt;li&gt;HOL(Head-of-Line) 차단, 기본 TCP 연결의 비효율 사용 해결&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Interleaving&lt;/b&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;여러 요청을 하나도 차단하지 않고 병렬로 interleaving할 수 있음&lt;/li&gt;
&lt;li&gt;여러 응답을 하나도 차단하지 않고 병렬로 interleaving할 수 있음&lt;/li&gt;
&lt;li&gt;단일 연결을 사용하여 여러 요청과 응답을 병렬로 전달할 수 있음&lt;/li&gt;
&lt;li&gt;연결된 파일, 이미지 스프라이트, 도메인 분할과 같은 불필요한 HTTP/1.x 임시 방편을 제거합니다.&lt;/li&gt;
&lt;li&gt;불필요한 지연 시간을 제거하고 가용 네트워크 용량의 활용도를 개선하여 페이지 로드 시간을 줄입니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dakcs0/btqNHqd5oGy/lVRlEDnzCvK4xKbA99VZK0/tfile.svg&quot; width=&quot;100%&quot; /&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;스트림 우선순위 지정&lt;/b&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;각 스트림에 가중치와 종속성 할당
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;스트림의 종속성 및 가중치 조합을 이용하여 클라이언트가 우선순위 지정 트리를 구성&lt;/li&gt;
&lt;li&gt;트리는 서버에서 CPU, 메모리 및 기타 리소스의 할당하거나 대역폭을 할당&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;출처당 하나의 연결&lt;/b&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;동일한 연결에 대해서 재사용 하기에 전반적인 프로토콜 오버헤드를 대폭 감소&lt;/li&gt;
&lt;li&gt;또한 더 적은 연결을 하기 때문에 메모리와 처리량이 감소&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;흐름 제어&lt;/b&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;송신기의 데이터가 불필요하거나 처리가 불가능하여 수신기에 부담을 주는 것을 막음
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;흐름 제어는 양방향&lt;/li&gt;
&lt;li&gt;흐름 제어는 크레딧 기반&lt;/li&gt;
&lt;li&gt;흐름 제어는 비활성화 할 수 없음&lt;/li&gt;
&lt;li&gt;흐름 제어는 종단간(End-to-End) 방식이 아닌 홉(Hop-by-Hop)방식&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;서버 푸시&lt;/b&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;서버가 단일 클라이언트 요청에 대해 여러 응답이 가능
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;클라이언트가 명시적으로 요청하지 않아도 서버가 추가적인 리소스를 푸시할 수 있음&lt;/li&gt;
&lt;li&gt;서비스 워커를 사용하여 캐시된 자원을 리턴 받아서 불필요한 네트워크 트래픽을 줄입니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/P5bxE/btqNLRaoJKm/xdpgf9F9ebXaakhGY5s0F0/tfile.svg&quot; width=&quot;100%&quot; /&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;헤더 압축&lt;/b&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;HPACK 압축 형식을 사용
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;전송되는 헤더 필드를 정적 huffman 코드로 인코딩&lt;/li&gt;
&lt;li&gt;공유 압축 컨텍스트를 구성
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;정적/동적 테이블로 구성
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;정적 테이블 : 사양에 정의되며, 모든 연결에 사용될 가능성이 있는 공용 HTTP 헤더 필드를 제공&lt;/li&gt;
&lt;li&gt;동적 테이블 : 처음에는 비어있으며, 특정 연결에서 교환되는 값에 따라 업데이트&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Hq7lW/btqNNg8mkGK/drWYqrL58X9IJw7ZLiSdx1/tfile.svg&quot; width=&quot;100%&quot; /&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;HTTP/3&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;HTTP/3는 QUIC이라는 프로토콜 위에서 돌아가는 HTTP입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;QUIC란?&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Quick UDP Internet Connection의 약자로 UDP를 사용하여 인터넷 연결을 하는 프로토콜&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;TCP 단점&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;TCP vs UDP&lt;/b&gt;위 그림처럼 TCP는 신뢰성이 높고 느리고, UDP는 신뢰성이 낮고 빠릅니다.&lt;br /&gt;현재 TCP를 사용하고 있는 HTTP/2 보다 빠르게 사용하기 위해서는 TCP를 버리고 UDP를 사용하는 것을 목적으로 하였습니다.&lt;/li&gt;
&lt;li&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bfRBq7/btqNLQJjSiT/E8qUnrPEWLqiwF5Fwh9CAk/img.png&quot; width=&quot;100%&quot; /&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;TCP가 느린 이유는 다음과 같습니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;3 Way Handshake&lt;/b&gt; 간략히 설명하면 #1~3의 통신을 통해서 정상적으로 연결이 되면 신뢰성이 생겨 이후에 데이터를 주고 받습니다.HTTP/1.1에서는 하나의 TCP 연결에 하나의 요청만 처리하게 되어 있어서 매 요청마다 3 Way handshake를 해줘야 하며, HTTP/2에서는 최소화를 하기 위해 단일 TCP 연결을 유지하면서 여러개의 요청을 처리할 수 있도록 변경되었습니다.&lt;/li&gt;
&lt;li&gt;하지만, TCP를 버리기 전에는 적어도 1번 이상 3 Way handshake를 해줘야 하기 때문에 속도가 느립니다.&lt;/li&gt;
&lt;li&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/beU8Td/btqNJwEAkJm/RiWOaj4GrgkpWc6uQ9XEWk/img.png&quot; width=&quot;100%&quot; /&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;HOLB(Head of line Blocking)&lt;/b&gt;이럴 경우 병목이 발생하는데 이러한 현상을 HOLB라 부릅니다. 이 현상은 HTTP/1, HTTP/2까지 발생하는 문제입니다.&lt;/li&gt;
&lt;li&gt;TCP를 사용한 통신에서는 패킷은 패킷 재조립을 위해서 무조건 정확한 순서대로 처리되어야 합니다. (위에서 시퀀스 번호가 그 예)&lt;br /&gt;그래서 통신 중간에 패킷이 손실되면 완전한 데이터로 다시 조립할 수 없어서 다음 패킷을 처리할 수 없습니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서, UDP를 사용하여 위 2가지 문제를 해결하여 프로토콜을 개발한 것 입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;UDP 사용 이유&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;연결 설정 레이턴시 감소&lt;/b&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nWxT2/btqNLPXUWyG/xD9LBC9QyeJ6zGgyG6M7uk/img.png&quot; width=&quot;100%&quot; /&gt;&lt;/li&gt;
&lt;li&gt;TCP + TLS 같은 경우 신뢰성있는 연결과 암호화에 필요한 모든 정보를 교환하고 유효성 검사를 한 후에 데이터 교환&lt;br /&gt;QUIC은 데이터를 바로 전달. 단, 클라이언트가 서버로 첫 요청을 보낼 때는 서버의 세션 키를 모르는 상태이기 때문에 서버의 Connection ID를 사용하여 생성한 특벽한 키를 사용하여 통신을 암호화 합니다.&lt;/li&gt;
&lt;li&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/GOP5g/btqNMNL597Q/1GCzIs7KfN0zRSPPMk4E30/img.png&quot; width=&quot;100%&quot; /&gt;&lt;/li&gt;
&lt;li&gt;TCP의 3 way handshake 때문에 연결 시에 레이턴시를 줄이기가 어렵습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;패킷 손실 감지에 걸리는 시간 단축&lt;/b&gt;
&lt;pre class=&quot;yaml&quot;&gt;&lt;code&gt; 1. Separate Packet Number Spaces
 2. Monotonically Increasing Packet Numbers
 3. Clearer Loss Epoch
 4. No Reneging
 5. More ACK Ranges
 6. Explicit Correction For Delayed Acknowledgements
 7. Probe Timeout Replaces RTO and TLP
 8. The Minimum Congestion Window is Two Packets&lt;/code&gt;&lt;/pre&gt;
참고 : &lt;a href=&quot;https://www.ietf.org/id/draft-ietf-quic-recovery-29.html#name-relevant-differences-betwee&quot;&gt;https://www.ietf.org/id/draft-ietf-quic-recovery-29.html#name-relevant-differences-betwee&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;아래는 QUIC에서 속도 향상을 위해서 작업한 방식들입니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;멀티플렉싱 지원&lt;/b&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ZIBV8/btqNNg8lSfM/Fa0lSpKgl64RqiOIgZDjl0/img.png&quot; width=&quot;100%&quot; /&gt;&lt;/li&gt;
&lt;li&gt;위 그림처럼 HTTP/1.1은 하나의 TCP 연결에 하나의 스트림만 사용하기 때문에 HOLB 문제에서 벗어날 수 없습니다.&lt;br /&gt;HTTP/2 같은 경우 하나의 TCP 연결 안에서 여러 개의 스트림을 처리하는 멀티플레싱 기법 도입으로 성능을 끌어올렸습니다.&lt;br /&gt;HTTP/3 또한 HTTP/2와 동일하게 지원합니다.&lt;/li&gt;
&lt;li&gt;멀티플렉싱은 HOLB를 방지하기 위한 기술입니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;클라이언트의 IP가 바뀌어도 연결이 유지됨&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;TCP의 경우 소스의 IP 주소와 포트, 연결 대상의 IP 주소와 포트로 연결을 식별하기 때문에 IP가 바뀌면 연결이 끊깁니다.&lt;br /&gt;QUIC은 Connection ID를 사용하여 서버와 연결을 생성합니다. 클라이언트의 IP와는 전혀 무관한 데이터이기 때문에 기존의 연결을 계속 유지할 수 있습니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;테스트 및 구축 방법&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아직 Nginx에서는 preview 상태이며, nginx 1.16.1 소스과 quiche를 받아서 patch 후 compile하여 사용해야합니다.&lt;/p&gt;
&lt;pre class=&quot;crystal&quot;&gt;&lt;code&gt;% curl -O https://nginx.org/download/nginx-1.16.1.tar.gz % tar xvzf nginx-1.16.1.tar.gz % git clone &amp;ndash;recursive https://github.com/cloudflare/quiche % cd nginx-1.16.1 % patch -p01 &amp;lt; ../quiche/extras/nginx/nginx-1.16.patch
% ./configure
&amp;ndash;prefix=$PWD
&amp;ndash;with-http_ssl_module
&amp;ndash;with-http_v2_module
&amp;ndash;with-http_v3_module
&amp;ndash;with-openssl=../quiche/deps/boringssl
&amp;ndash;with-quiche=../quiche % make &lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;events {
    worker_connections  1024;
}

http {
    server {
        # Enable QUIC and HTTP/3.
        listen 443 quic reuseport;

        # Enable HTTP/2 (optional).
        listen 443 ssl http2;

        ssl_certificate      cert.crt;
        ssl_certificate_key  cert.key;

        # Enable all TLS versions (TLSv1.3 is required for QUIC).
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;

        # Add Alt-Svc header to negotiate HTTP/3.
        add_header alt-svc 'h3-23=&quot;:443&quot;; ma=86400';
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위와 같이 설정 후 설정한 사이트에 크롬으로 접속하면 protocol에 h3-q050이 보여야 합니다.&lt;br /&gt;아래 이미지는 cloudflare에 접속하여 확인한 화면입니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1202&quot; data-origin-height=&quot;548&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bwWlxs/btqNIGm9wvY/RQnaWEvRsROKzOruhAFqaK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bwWlxs/btqNIGm9wvY/RQnaWEvRsROKzOruhAFqaK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bwWlxs/btqNIGm9wvY/RQnaWEvRsROKzOruhAFqaK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbwWlxs%2FbtqNIGm9wvY%2FRQnaWEvRsROKzOruhAFqaK%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;1202&quot; height=&quot;548&quot; data-origin-width=&quot;1202&quot; data-origin-height=&quot;548&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>개발 및 관련 자료/WEB</category>
      <category>3way-handshake</category>
      <category>HTTP</category>
      <category>http2</category>
      <category>http3</category>
      <category>HTTPS</category>
      <category>multiplexing</category>
      <category>Nginx</category>
      <category>QUIC</category>
      <category>tcp</category>
      <category>udp</category>
      <author>jmkim87</author>
      <guid isPermaLink="true">https://kid1412.tistory.com/247</guid>
      <comments>https://kid1412.tistory.com/247#entry247comment</comments>
      <pubDate>Sun, 10 Dec 2023 11:34:49 +0900</pubDate>
    </item>
    <item>
      <title>[괌] 여행 준비</title>
      <link>https://kid1412.tistory.com/274</link>
      <description>&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;b&gt;여권&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;6개월 이상 남은 여권&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;신분증&lt;/b&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;b&gt;볼펜&lt;/b&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;b&gt;전자세관신고서 (도착하기 72시간 이내에 할 것)&lt;/b&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://blog.naver.com/alfk7807/222982178995&quot;&gt;괌 입국 서류 총정리 (여행 필수 준비물), .. : 네이버블로그 (naver.com)&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;li&gt;먼저 읽어보고 작성&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://traveller.guamedf.landing.cards/&quot;&gt;괌 필수 세관 신고서 (landing.cards)&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;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;2차 영문접종확인서 (아래 전부 필요)&lt;/b&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://nip.kdca.go.kr/irhp/index.jsp?msg=IRGD&quot;&gt;예방접종도우미 (kdca.go.kr)&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;li&gt;제출은 항공사에서 표 받을 때 제출하면 됨.&lt;/li&gt;
&lt;li&gt;전자예방접종증명서(COOV APP(쿠브앱) 설치)
&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;b&gt;괌 비자 면제 서류 (괌 비자면제신청서 )&lt;/b&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;이스타는 몇 개월 이내에 또 괌에 방문할 사람들이 미리 돈 내고 빠르게 수속 밟기 위한 비자 (인당 21$)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;만약 하나투어에서 작성하라고 하면 비용 물어보고, 만약 작성 했다면 입국 심사받는 곳에 ESTA(이스타) 수속하는 줄이 따로 있으니 빠르게 입국이 가능&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;a href=&quot;https://blog.naver.com/alfk7807/222982178995&quot;&gt;괌 입국 서류 총정리 (여행 필수 준비물), .. : 네이버블로그 (naver.com)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;CDC 서약서&lt;/b&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;b&gt;괌 입국심사&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;괌입국서류 준비만틈 떨렸던 입국심사. 괌 입국심사는 아주 간단했는데 마스크 잠깐 벗고 얼굴 확인 후에 손가락 오른손 엄지, 나머지 손가락, 왼손 엄지, 나머지 손가락 찍고 간단하게 질문 몇 가지 하고 도장 쾅쾅 찍고 끝! 질문의 수는 3~4가지 됐는데 간단한 영어라 걱정할 필요는 없음.&lt;/li&gt;
&lt;li&gt;입국심사질문으로는 왜 왔는지, 얼마나 머무는지, 어느 호텔에 묵는지, 몇 번 와봤는지 정도였는데 허니문이라고 말하니깐 잘 지내라는 이야기까지 해줬다. 영어 못해도 눈치코치로 알아들을 수 있는 정도의 질문&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://cafe.naver.com/guamfree/2482229?art=ZXh0ZXJuYWwtc2VydmljZS1uYXZlci1zZWFyY2gtaW50ZW50LXZpZXc%3D.eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJjYWZlVHlwZSI6IkNBRkVfVVJMIiwiY2FmZVVybCI6Imd1YW1mcmVlIiwiYXJ0aWNsZUlkIjoyNDgyMjI5LCJpc3N1ZWRBdCI6MTY3NzYzMTUzNDc4OX0=.MMlr6UzBYpnm1agSf5DZoYvLpoJhyNhy679moUZhLnM=&quot;&gt;괌여행후기 [준비물꿀팁편] 필수 준비물 총정리 : 네이버 카페 (naver.com)&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;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;여행자 보험&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;공항에서 4박 5일 들면 됨.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;환전&lt;/b&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;b&gt;신용카드&lt;/b&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;b&gt;여러 가지&lt;/b&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;선크림 (SPF50 이상)
&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;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;a href=&quot;https://blog.naver.com/saladin324/223012758828&quot;&gt;https://blog.naver.com/saladin324/223012758828&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;110V 어댑터&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;우리나라에서 11자 어댑터라고 하면 알아듣는 그 변환잭&lt;/li&gt;
&lt;li&gt;가져갈 기기들이 대부분 프리폴트이겠지만 혹시나 하면 볼트 적혀 있는 곳 보면 100v-220v 이런 식으로 쓰여있으면 대부분 사용 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;충전 케이블&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;핸드폰 로밍 또는 포켓와이파이&lt;/b&gt;
&lt;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;a href=&quot;https://www.skyscanner.co.kr/news/tips/how-to-save-money-on-mobile-data-charges-when-you-travel&quot;&gt;해외 데이터 요금 폭탄을 막는 방법 4가지 - 스카이스캐너-항공권, 호텔, 렌터카 최저가 비교예약 (skyscanner.co.kr)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;보조배터리&lt;/b&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;b&gt;마스크&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;우산&lt;/b&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;b&gt;셀카봉&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;블루투스 이어폰 (숙소에서 쉴 때)&lt;/b&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;주의사항&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;팁문화&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://blog.naver.com/mellow47/222830991259&quot;&gt;https://blog.naver.com/mellow47/222830991259&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;b&gt;식당&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;식당에서 밥 먹을 시 계산지에 Service Charge 나 Included Gratuity라고 10~15% 적혀 있으면 따로 팁은 안내도 됨.&lt;/li&gt;
&lt;li&gt;만약 붙어 있지 않으면 음식 값의 10~20% 팁으로 생각할 것&lt;/li&gt;
&lt;li&gt;만약 카드라면 계산지에 additional Tip에 팁 금액 쓰고 Total 금액에 다 더해서 사인하면 됨&lt;/li&gt;
&lt;li&gt;밥 다 먹고 계산하기 전에 Check Please라고 하면 계산지 가져다줌&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;호텔&lt;/b&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;b&gt;투어&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;특별한 별도로 투어가 있다면 인당 $1~2 달러 생각하면 됨.&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;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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://blog.naver.com/neti96/222984977345&quot;&gt;https://blog.naver.com/neti96/222984977345&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;호텔 프런트에서 시간표를 받을 수 있고 아래 사진 참고 (23년 1월 기준)&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;편도 : $4&lt;/li&gt;
&lt;li&gt;1일: $10&lt;/li&gt;
&lt;li&gt;2일 : $14&lt;/li&gt;
&lt;li&gt;3일 : $18&lt;/li&gt;
&lt;li&gt;5일 : $24&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;20221125_141213_1.jpg&quot; data-origin-width=&quot;2944&quot; data-origin-height=&quot;1335&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/DyK0r/btr3offtvVJ/5WQQgMw2lzp48GQvPj5oAk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/DyK0r/btr3offtvVJ/5WQQgMw2lzp48GQvPj5oAk/img.jpg&quot; data-alt=&quot;티롤리 노선도&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/DyK0r/btr3offtvVJ/5WQQgMw2lzp48GQvPj5oAk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FDyK0r%2Fbtr3offtvVJ%2F5WQQgMw2lzp48GQvPj5oAk%2Fimg.jpg&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;2944&quot; height=&quot;1335&quot; data-filename=&quot;20221125_141213_1.jpg&quot; data-origin-width=&quot;2944&quot; data-origin-height=&quot;1335&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;티롤리 노선도&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;20221124_210618_1.jpg&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;2365&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dnQDbW/btr3vOhvQz6/CJIdGfkwFOH4KmK3Uncgp0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dnQDbW/btr3vOhvQz6/CJIdGfkwFOH4KmK3Uncgp0/img.jpg&quot; data-alt=&quot;티롤리 시간표&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dnQDbW/btr3vOhvQz6/CJIdGfkwFOH4KmK3Uncgp0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdnQDbW%2Fbtr3vOhvQz6%2FCJIdGfkwFOH4KmK3Uncgp0%2Fimg.jpg&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;3024&quot; height=&quot;2365&quot; data-filename=&quot;20221124_210618_1.jpg&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;2365&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;티롤리 시간표&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&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;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;a href=&quot;https://guambada.tistory.com/117&quot;&gt;https://guambada.tistory.com/117&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://blog.naver.com/minek23/221510753892&quot;&gt;https://blog.naver.com/minek23/221510753892&lt;/a&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;a href=&quot;https://blog.naver.com/iheendung/223001186909&quot;&gt;https://blog.naver.com/iheendung/223001186909&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: none;&quot;&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: none;&quot;&gt;&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>여행</category>
      <category>괌</category>
      <category>대중교통</category>
      <category>세관</category>
      <category>여행</category>
      <category>여행준비</category>
      <author>jmkim87</author>
      <guid isPermaLink="true">https://kid1412.tistory.com/274</guid>
      <comments>https://kid1412.tistory.com/274#entry274comment</comments>
      <pubDate>Mon, 13 Mar 2023 09:24:52 +0900</pubDate>
    </item>
    <item>
      <title>[강화 학습] 1990년 이후 강화학습 관련 모델이나 기법</title>
      <link>https://kid1412.tistory.com/257</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Q-Learning (1992)&lt;/b&gt;: 이후 강화학습 분야의 대표적인 알고리즘 중 하나인 Q-Learning이 Watkins와 Dayan에 의해 제안됨. [논문: &quot;Q-Learning&quot;, 1992]&lt;/p&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;TD-Gammon (1995)&lt;/b&gt;: 텐니스 게임에서의 자가 학습을 통해 세계 챔피언을 이긴 최초의 강화학습 모델인 TD-Gammon이 제안됨. [논문: &quot;Temporal Difference Learning of Backgammon Strategy&quot;, 1995]&lt;/p&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;DQN (2013)&lt;/b&gt;: DeepMind에서 개발된 Deep Q-Network(DQN)은 딥러닝을 강화학습에 적용한 첫번째 모델로, Atari 게임에서 인간 수준의 성능을 보임. [논문: &quot;Playing Atari with Deep Reinforcement Learning&quot;, 2013]&lt;/p&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;Actor-Critic (2016)&lt;/b&gt;: 대표적인 강화학습 알고리즘 중 하나인 Actor-Critic은 신경망 모델을 사용하여 정책(policy)과 가치함수(value function)를 동시에 학습하는 방식으로 구현됨. [논문: &quot;Asynchronous Methods for Deep Reinforcement Learning&quot;, 2016]&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;AlphaGo (2016)&lt;/b&gt;: 구글 딥마인드 팀에서 개발한 인공지능 기반의 바둑 프로그램으로, 강화학습, 신경망, 몬테카를로 트리 탐색 등의 기술을 사용하여 이세돌 9단과 대국을 했을 때 4승 1패의 기록을 달성하는 등 바둑 역사상 최초로 프로 수준의 기량을 보여주었다. AlphaGo의 성공은 인공지능의 발전에 큰 기여를 하였으며, 이후 알파고 제로와 알파제로 등 다양한 알파고 시리즈가 개발되어 대표적인 강화학습 모델로 자리 잡았다. [논문: &quot;Mastering the Game of Go with Deep Neural Networks and Tree Search&quot;, 2016]&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Dueling DQN (2016)&lt;/b&gt;: 강화학습 분야에서 딥러닝 모델을 사용하여 Atari 게임에서 인간 수준의 성능을 보인 첫 모델 중 하나인 Dueling DQN이 소개됨. [논문: &quot;Dueling Network Architectures for Deep Reinforcement Learning&quot;, 2016]&lt;/p&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;Rainbow (2017)&lt;/b&gt;: 다양한 강화학습 모델의 장점을 합친 Rainbow가 발표되어 Atari 게임에서 최고 성능을 달성함. [논문: &quot;Rainbow: Combining Improvements in Deep Reinforcement Learning&quot;, 2017]&lt;/p&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;Proximal Policy Optimization&lt;b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;(PPO)&lt;/b&gt;&lt;/b&gt;&amp;nbsp;(2017)&lt;/b&gt;: OpenAI에서 제안한 Proximal Policy Optimization(PPO)은 안정적인 정책 최적화 알고리즘으로, Atari 게임과 로봇 제어 문제에서 우수한 성능을 보임. [논문: &quot;Proximal Policy Optimization Algorithms&quot;, 2017]&lt;/p&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;Soft Actor-Critic (SAC) (2018)&lt;/b&gt;: 연속적인 행동 공간(Continuous Action Space)에서 안정적인 학습을 위해 제안된 SAC는 안정적이면서도 높은 성능을 보이는 대표적인 알고리즘 중 하나임. [논문: &quot;Soft Actor-Critic Algorithms and Applications&quot;, 2018]&lt;/p&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;AlphaZero (2018)&lt;/b&gt;: 딥러닝을 이용한 강화학습 알고리즘의 한계를 극복한 AlphaZero는, 오로지 게임 규칙만을 입력으로 받아 최적의 전략을 스스로 학습하고, 세계 최고 수준의 바둑, 장기, 체스 선수들을 이길 정도의 실력을 보임. [논문: &quot;Mastering Chess and Shogi by Self-Play with a General Reinforcement Learning Algorithm&quot;, 2018]&lt;/p&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;RL^2 (2018)&lt;/b&gt;: 강화학습을 위한 메타-러닝 방법인 RL^2는, 새로운 태스크를 빠르게 학습할 수 있는 강화학습 모델을 학습하는 모델로, 최신 연구 주제 중 하나임. [논문: &quot;Meta-Learning with Reinforcement Learning&quot;, 2018]&lt;/p&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;A3C (2018)&lt;/b&gt;: Asynchronous Advantage Actor-Critic(A3C)은 비동기적으로 여러 환경에서 학습하는 방식으로, 실시간으로 대규모 데이터를 학습할 수 있음. [논문: &quot;Asynchronous Methods for Deep Reinforcement Learning&quot;, 2018]&lt;/p&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;RAINBOW (2018)&lt;/b&gt;: Google DeepMind에서 제안한 RAINBOW는 다양한 강화학습 알고리즘들을 융합하여 개발한 모델로, Atari 게임에서 DQN보다 더욱 높은 성능을 보임. [논문: &quot;Rainbow: Combining Improvements in Deep Reinforcement Learning&quot;, 2018]&lt;/p&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;World Models (2019)&lt;/b&gt;: 강화학습 모델에 베이지안 네트워크와 생성모델을 결합하여 게임에서 좋은 성능을 보이는 World Models가 소개됨. [논문: &quot;World Models&quot;, 2019]&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;PlaNet (2019)&lt;/b&gt;: Model-based 강화학습 알고리즘인 PlaNet은 모델 학습에 Variational Auto-Encoder(VAE)를 사용하여 높은 성능을 보이며, 예측 정확도가 높아서 몇몇 문제에서는 Model-Free 알고리즘과 견줄만한 성능을 보인다. 또한, 비교적 적은 수의 환경 탐색으로도 높은 성능을 얻을 수 있는 장점이 있다. [논문: &quot;Stabilizing Off-Policy Q-Learning via Bootstrapping Error Reduction&quot;, 2019]&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;MuZero (2019)&lt;/b&gt;: 일반 게임과 바둑, 체스 등의 게임에서 뛰어난 성능을 보이는 모델로, 강화학습, 자가 대국, 신경망 등의 기술을 활용하여 구현되었다. MuZero는 특히 게임에 대한 사전 지식 없이도 학습 가능하며, 게임 상태의 내부 모델을 학습하여 미래의 게임 상태를 예측하여 최적의 행동을 결정한다. [논문: &quot;Mastering Atari, Go, Chess and Shogi by Planning with a Learned Model&quot;, 2019]&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;D4RL (2020)&lt;/b&gt;: 데이터셋 구축 및 평가를 위한 강화학습 벤치마크인 D4RL(Dataset for Deep Data-Driven Reinforcement Learning)이 소개됩니다. [논문: &quot;D4RL: Datasets for Deep Data-Driven Reinforcement Learning&quot;, 2020]&lt;br /&gt;&lt;br /&gt;&lt;b&gt;DreamerV2&amp;nbsp;(2021)&lt;/b&gt;:&amp;nbsp;자기&amp;nbsp;대국과&amp;nbsp;같은&amp;nbsp;높은&amp;nbsp;차원의&amp;nbsp;문제를&amp;nbsp;해결하기&amp;nbsp;위한&amp;nbsp;강화학습&amp;nbsp;알고리즘인&amp;nbsp;DreamerV2가&amp;nbsp;소개됩니다.&amp;nbsp;[논문:&amp;nbsp;&quot;DreamerV2:&amp;nbsp;Deep&amp;nbsp;Reinforcement&amp;nbsp;Learning&amp;nbsp;for&amp;nbsp;Vision-Based&amp;nbsp;Robotic&amp;nbsp;Manipulation&amp;nbsp;with&amp;nbsp;Latent&amp;nbsp;Imagination&quot;,&amp;nbsp;2021]&lt;br /&gt;&lt;br /&gt;&lt;b&gt;MOReL (2021)&lt;/b&gt;: 도메인 어댑티브 강화학습을 위한 모델 기반 강화학습 알고리즘인 MOReL(Model-Based Offline Reinforcement Learning)이 소개됩니다. [논문: &quot;MOReL: Model-Based Offline Reinforcement Learning for Non-Stationary Environments&quot;, 2021]&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;Muzero General (2021)&lt;/b&gt;: MuZero 모델을 보완한 Muzero General이 발표되었다. Muzero General은 MuZero와 같이 게임에서 높은 성능을 보이지만, 훨씬 더 광범위한 문제에 적용할 수 있다. [논문: &quot;Muzero General: A Generalized Framework for Offline Planning&quot;, 2021]&lt;br /&gt;&lt;br /&gt;&lt;b&gt;R2D2&amp;nbsp;(2022)&lt;/b&gt;:&amp;nbsp;대규모&amp;nbsp;분산&amp;nbsp;강화학습&amp;nbsp;시스템인&amp;nbsp;R2D2(Rollout2Distibuted&amp;nbsp;Deep&amp;nbsp;Reinforcement&amp;nbsp;Learning)이&amp;nbsp;소개됩니다.&amp;nbsp;[논문:&amp;nbsp;&quot;R2D2:&amp;nbsp;Rollout2Distibuted&amp;nbsp;Deep&amp;nbsp;Reinforcement&amp;nbsp;Learning&amp;nbsp;for&amp;nbsp;Large-Scale&amp;nbsp;Multi-Agent&amp;nbsp;Environments&quot;,&amp;nbsp;2022]&lt;/span&gt;&lt;/p&gt;</description>
      <category>인공지능</category>
      <category>강화학습</category>
      <category>딥러닝</category>
      <category>알파고</category>
      <category>알파제로</category>
      <category>인공지능</category>
      <author>jmkim87</author>
      <guid isPermaLink="true">https://kid1412.tistory.com/257</guid>
      <comments>https://kid1412.tistory.com/257#entry257comment</comments>
      <pubDate>Mon, 27 Feb 2023 21:07:15 +0900</pubDate>
    </item>
    <item>
      <title>[이미지 처리] 1990년 이후 이미지 관련 모델이나 기법</title>
      <link>https://kid1412.tistory.com/256</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;LeNet-5 (1998)&lt;/b&gt;: 이미지 분류를 위한 최초의 합성곱 신경망 모델로, 손글씨 숫자 인식에 성공함. [논문: &quot;Gradient-based learning applied to document recognition&quot;, 1998]&lt;/p&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;SIFT (1999)&lt;/b&gt;: 이미지에서 특징점을 검출하고, 이를 기초로 이미지를 비교하는 방법으로, 이미지 인식 분야에서 큰 역할을 함. [논문: &quot;Distinctive Image Features from Scale-Invariant Keypoints&quot;, 1999]&lt;/p&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;Bag-of-features (2004)&lt;/b&gt;: 이미지의 전체적인 특징만을 고려하여 이미지를 분류하는 방법으로, 이미지 분류 분야에서 활용되었음. [논문: &quot;An Introduction to the Bag-of-Features Framework for Image Classification and Retrieval&quot;, 2004]&lt;/p&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;HOG (2005)&lt;/b&gt;: 이미지 내의 에지 방향을 히스토그램으로 표현한 후, 이를 분석하는 방법으로, 사물 검출 분야에서 활용됨. [논문: &quot;Histograms of Oriented Gradients for Human Detection&quot;, 2005]&lt;/p&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;Deformable Part-based Model (DPM) (2008)&lt;/b&gt;: 객체의 각 부분을 검출하고, 이들을 조합하여 객체를 검출하는 방법으로, 사물 검출 분야에서 활용되었음. [논문: &quot;Beyond PASCAL: A benchmark for 3D object detection in the wild&quot;, 2008]&lt;/p&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;Deep Convolutional Neural Network (DCNN) (2012)&lt;/b&gt;: 다층 합성곱 신경망 모델로, 이미지 인식 분야에서 혁신적인 성과를 냈고, 이후 많은 딥러닝 모델들의 기반 기술이 되었음. [논문: &quot;Imagenet classification with deep convolutional neural networks&quot;, 2012]&lt;/p&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;Spatial Pyramid Pooling (SPP) (2014)&lt;/b&gt;: 이미지 내의 특징들을 고정된 크기의 블록으로 분할하여 히스토그램으로 만들어, 크기가 다른 이미지에서도 동일한 크기의 특징 벡터를 추출할 수 있도록 한 방법으로, 이미지 인식 분야에서 활용되었음. [논문: &quot;Spatial Pyramid Pooling in Deep Convolutional Networks for Visual Recognition&quot;, 2014]&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;ResNet (2015)&lt;/b&gt;: 이미지 인식 분야에서 혁신적인 딥러닝 모델 중 하나인 ResNet은 네트워크의 깊이가 증가함에 따라 발생하는 gradient vanishing 문제를 해결하였습니다. ResNet은 residual connection이라는 새로운 구조를 도입하여, 이전 레이어의 출력을 다음 레이어의 입력으로 사용함으로써, 딥러닝 모델을 더욱 깊게 학습시킬 수 있게 되었습니다. [논문: &quot;Deep Residual Learning for Image Recognition&quot;, 2015]&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;b&gt;GQN (2018)&lt;/b&gt;: 다양한 위치와 방향에서 입력된 2D 이미지들을 3D 공간에 배치하고 이를 연속적으로 조합하여 새로운 관찰 가능한 이미지를 생성하는 Generative Query Network (GQN)가 제안됨. [논문: &quot;Neural Scene Representation and Rendering&quot;, 2018]&lt;/p&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;BigGAN (2018)&lt;/b&gt;: 기존의 GAN 모델에서 발전시켜 고해상도, 다양한 카테고리의 이미지 생성에 뛰어난 성능을 보이는 BigGAN 모델이 발표됨. [논문: &quot;Large Scale GAN Training for High Fidelity Natural Image Synthesis&quot;, 2018]&lt;/p&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;StyleGAN (2019)&lt;/b&gt;: GAN 기반 모델 중 하나인 StyleGAN은 기존의 GAN 모델들과는 다르게 생성된 이미지의 품질 뿐 아니라 이미지의 특정 스타일을 조정할 수 있는 기능을 갖추고 있음. [논문: &quot;A Style-Based Generator Architecture for Generative Adversarial Networks&quot;, 2019]&lt;/p&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;ViT (2020)&lt;/b&gt;: 기존의 CNN 모델에 비해 더욱 간결한 구조를 갖추고 있으며, 전이학습에 용이한 Vision Transformer (ViT)가 발표됨. [논문: &quot;An Image is Worth 16x16 Words: Transformers for Image Recognition at Scale&quot;, 2020]&lt;/p&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;CLIP (2021)&lt;/b&gt;: 이미지와 텍스트를 함께 이용하여 모델 학습을 진행하는 Contrastive Language-Image Pre-Training (CLIP) 모델이 발표됨. 이 모델은 이미지 검색, 이미지 분류 등 다양한 응용 분야에서 높은 성능을 보임. [논문: &quot;Learning Transferable Visual Models From Natural Language Supervision&quot;, 2021]&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Stable Diffusion (2021)&lt;/b&gt;:&lt;span style=&quot;color: #333333;&quot;&gt; 이미지 생성 분야에서 최신 기술 중 하나인 Stable Diffusion이 발표되었습니다. 이 모델은 CLIP, UNet, VAE(Variational Auto Encoder, 자기부호화기)이라는 세 가지 인공신경망으로 이루어져 있다. 유저가 텍스트를 입력하면 텍스트 인코더(CLIP)가 유저의 텍스트를 토큰(Token)이라는 UNet이 알아들을 수 있는 언어로 변환하고, UNet은 토큰을 기반으로 무작위로 생성된 노이즈를 디노이징하는 방식이다. 디노이징을 반복하다 보면 제대로 된 이미지가 생성되며, 이 이미지를 픽셀로 변환하는 것이 VAE의 역할이다. 해상도가 높아질수록 리소스를 기하급수적으로 사용하게 되는 종전의 확산 확률 이미지 생성 모델과 달리, 앞뒤에 오토인코더를 도입하여 이미지 전체가 아닌 훨씬 작은 차원의 잠재공간(latent space)에서 노이즈를 삽입/제거하므로, 비교적 큰 해상도의 이미지를 생성하는데도 리소스 사용량을 대폭 줄여 일반 가정의 그래픽카드 정도로도 이용이 가능해진 것이 특징입니다. [논문: &quot;High-Resolution Image Synthesis with Latent Diffusion Models&quot;, 2021]&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;</description>
      <category>인공지능</category>
      <category>stable diffusion</category>
      <category>WEBUI</category>
      <category>딥러닝</category>
      <category>이미지</category>
      <category>인공지능</category>
      <author>jmkim87</author>
      <guid isPermaLink="true">https://kid1412.tistory.com/256</guid>
      <comments>https://kid1412.tistory.com/256#entry256comment</comments>
      <pubDate>Sun, 26 Feb 2023 21:22:27 +0900</pubDate>
    </item>
    <item>
      <title>[자연어처리] 1990년 이후 자연어처리에 쓰인 모델이나 기법들</title>
      <link>https://kid1412.tistory.com/255</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;LSTM (1997)&lt;/b&gt;: 반복 신경망을 장기 기억을 유지할 수 있도록 확장한 LSTM(Long Short-Term Memory) 모델이 제안됨. [논문: &quot;Long Short-Term Memory&quot;, 1997]&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;Conditional Random Field (2001)&lt;/b&gt;: 레이블된 시퀀스 데이터를 모델링하는데 사용되는 조건부 랜덤 필드(Conditional Random Field) 모델이 제안됨. [논문: &quot;Conditional Random Fields: Probabilistic Models for Segmenting and Labeling Sequence Data&quot;, 2001]&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;Word2Vec (2013)&lt;/b&gt;: 단어를 밀집 벡터(dense vector)로 표현하는 기법인 Word2Vec이 제안됨. [논문: &quot;Efficient Estimation of Word Representations in Vector Space&quot;, 2013]&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;Sequence to Sequence (Seq2Seq) (2014)&lt;/b&gt;: 인코더-디코더(encoder-decoder) 구조를 사용하여 시퀀스를 다른 시퀀스로 변환하는 모델인 Seq2Seq가 제안됨. [논문: &quot;Sequence to Sequence Learning with Neural Networks&quot;, 2014]&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;Attention Mechanism (2014)&lt;/b&gt;: 입력 시퀀스의 각 단어가 출력 시퀀스의 각 단어에 직접 매핑되는 대신, 입력 시퀀스의 모든 단어가 출력의 각 단어에 영향을 주는 방식으로 작동하는 어텐션(attention) 메커니즘이 제안됨. [논문: &quot;Neural Machine Translation by Jointly Learning to Align and Translate&quot;, 2014]&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;Pointer Network (2015)&lt;/b&gt;: 일반적인 시퀀스-시퀀스(Seq2Seq) 모델의 한계를 극복하기 위해, 출력 시퀀스를 생성할 때 입력 시퀀스의 요소를 가리키는 방식으로 작동하는 포인터(Pointer) 네트워크가 제안됨. [논문: &quot;Pointer Networks&quot;, 2015]&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;Character-level Convolutional Network (2016)&lt;/b&gt;: 단어 대신 문자 단위의 컨볼루션(Convolution) 신경망을 사용하여 단어나 문장을 분류하는 모델이 제안됨. [논문: &quot;Character-level Convolutional Networks for Text Classification&quot;, 2016]&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;Transformer (2017)&lt;/b&gt;: 자연어 처리 분야에서 가장 유명한 모델 중 하나인 Transformer가 소개됨. self-attention 기반 신경망 구조인 Transformer는 번역, 요약, 질의응답 등 다양한 자연어 처리 문제에서 좋은 성능을 보이며, 이전 모델들과는 달리 순차적인 계산을 하지 않고 전체 문장을 동시에 처리하는 방식을 채택하여 학습 속도가 빠르고 효과적이다. [논문: &quot;Attention Is All You Need&quot;, 2017]&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;ELMo (2018)&lt;/b&gt;: 사전 훈련된 언어 모델을 활용해 단어의 다의어성(disambiguation)과 문맥 파악 등을 수행하는 모델로, 이후 BERT와 같은 모델의 발전에 영향을 끼쳤다. [논문: &quot;Deep contextualized word representations&quot;, 2018]&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;BERT (2018)&lt;/b&gt;: 사전 훈련된 언어 모델 중 가장 대표적인 모델 중 하나로, Transformer 구조를 활용해 사전 학습된 언어 모델을 기반으로 문장 분류, 질의 응답, 개체명 인식 등 다양한 자연어 처리 태스크에서 우수한 성능을 보여주었다. [논문: &quot;BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding&quot;, 2018]&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;GPT (2018)&lt;/b&gt;: OpenAI에서 발표한 Transformer 기반 언어 생성 모델로, 문장을 생성하는 과정에서 이전 단어와 다음 단어의 관계를 고려해 다양한 문장을 생성할 수 있다. [논문: &quot;Improving Language Understanding by Generative Pre-Training&quot;, 2018]&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;XLNet (2019)&lt;/b&gt;: 자기회귀(autoregressive) 모델의 한계를 극복하기 위해 자기회귀 언어 모델과 오토인코더(autoencoder)를 결합한 모델로, 다양한 자연어 처리 태스크에서 우수한 성능을 보여주며, BERT와 같은 모델의 한계를 극복하고자하는 연구들에 큰 영향을 끼쳤다. [논문: &quot;XLNet: Generalized Autoregressive Pretraining for Language Understanding&quot;, 2019]&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;RoBERTa (2019)&lt;/b&gt;: BERT와 유사한 구조를 가지고 있으나, 더 많은 데이터를 이용하여 학습시켰습니다. [논문: &quot;RoBERTa: A Robustly Optimized BERT Pretraining Approach&quot;, 2019]&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;ALBERT (2019)&lt;/b&gt;: BERT와 유사한 구조를 가지고 있으나, 파라미터를 줄여 더 경량화시켰습니다. [논문: &quot;ALBERT: A Lite BERT for Self-supervised Learning of Language Representations&quot;, 2019]&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;ELECTRA (2020)&lt;/b&gt;: BERT와 유사한 구조를 가지고 있으나, 마스킹된 단어를 진짜 단어인 것처럼 학습시켜 더 효과적인 학습을 이루었습니다. [논문: &quot;ELECTRA: Pre-training Text Encoders as Discriminators Rather Than Generators&quot;, 2020]&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;DistilBERT (2019)&lt;/b&gt;: BERT와 유사한 구조를 가지고 있으나, 더 작은 모델 크기로 학습시켜 더 빠르게 추론할 수 있습니다. [논문: &quot;DistilBERT, a distilled version of BERT: smaller, faster, cheaper and lighter&quot;, 2019]&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;CamemBERT (2019)&lt;/b&gt;: 프랑스어 자연어 처리를 위해 BERT를 수정하고 학습시켰습니다. [논문: &quot;CamemBERT: a Tasty French Language Model&quot;, 2019]&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;XLM (2019)&lt;/b&gt;: 다국어 자연어 처리를 위해 BERT를 수정하고 학습시켰습니다. [논문: &quot;Cross-lingual Language Model Pretraining&quot;, 2019]&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;RoBERTa (2019)&lt;/b&gt;: BERT 모델의 사전 훈련을 개선하고 성능을 향상시킨 RoBERTa가 소개됨. [논문: &quot;RoBERTa: A Robustly Optimized BERT Pretraining Approach&quot;, 2019]&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;T5 (2020)&lt;/b&gt;: Transformer를 기반으로 하는 다목적 언어 모델로, 텍스트 생성, 번역, 요약, 질의 응답 등 다양한 태스크를 하나의 모델로 수행할 수 있다. [논문: &quot;Exploring the Limits of Transfer Learning with a Unified Text-to-Text Transformer&quot;, 2020]&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;GPT-3 (2020)&lt;/b&gt;: 대규모 transformer 모델을 사용한 언어 생성 모델로 GPT-3가 소개됨. [논문: &quot;Language Models are Few-Shot Learners&quot;, 2020]&lt;/span&gt;&lt;/p&gt;</description>
      <category>인공지능</category>
      <category>Bert</category>
      <category>ChatGPT</category>
      <category>GPT</category>
      <category>GPT3</category>
      <category>transformer</category>
      <category>논문</category>
      <category>모델</category>
      <category>역사</category>
      <category>자연어처리</category>
      <category>챗GPT</category>
      <author>jmkim87</author>
      <guid isPermaLink="true">https://kid1412.tistory.com/255</guid>
      <comments>https://kid1412.tistory.com/255#entry255comment</comments>
      <pubDate>Sat, 25 Feb 2023 21:17:10 +0900</pubDate>
    </item>
    <item>
      <title>[React] React 18</title>
      <link>https://kid1412.tistory.com/261</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;React 18은 React 프레임워크의 새로운 버전입니다. 이번 버전에서는 기존의 React와 비교하여 많은 기능 개선 및 업그레이드가 이루어졌습니다. 예를 들어, 성능을 개선하고 안정성을 확보하기 위해 다양한 업그레이드가 이루어졌습니다.&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;b&gt;서버 사이드 렌더링 개선:&lt;/b&gt; 이번 버전에서는 기존에 있었던 서버 사이드 렌더링의 성능 이슈가 해결되었습니다. 이로 인해 더욱 빠르고 안정적인 서버 사이드 렌더링이 가능해졌습니다. 이 기능의 개선으로 인해, 사용자들은 더욱 빠른 웹 페이지 로딩 시간을 경험할 수 있게 되었습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;새로운 이벤트 모델:&lt;/b&gt; 기존의 이벤트 모델에서 발생하던 문제점들을 개선하였습니다. 예를 들어, 이제 이벤트 처리가 더욱 직관적이고 유연해졌습니다. 이로 인해, 사용자 경험과 개발자 경험 모두가 향상될 것입니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;빠른 초기 로딩:&lt;/b&gt; 이번 버전에서는 초기 로딩 속도가 매우 빨라졌습니다. 이는 사용자 경험을 높이고 검색 엔진 최적화(SEO)에도 도움이 됩니다. 이 기능의 개선으로 인해, 사용자들은 더욱 빠른 페이지 로딩 속도를 경험할 수 있게 되었습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;자동 배치(Concurrent Mode):&lt;/b&gt; React 18에서는 자동 배치 기능이 추가되어 UI 업데이트가 더욱 빠르고 부드러워졌습니다. 이 기능의 개선으로 인해, 사용자들은 더욱 더 빠르고 부드러운 UI를 경험할 수 있게 되었습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;React Suspense:&lt;/b&gt; React 18에서는 새로운 기능으로 React Suspense가 추가되었습니다. 이를 통해 데이터 로딩이 완료될 때까지 UI를 로딩 상태로 유지하거나, 로딩 중인 데이터에 대한 fallback UI를 보여줄 수 있습니다. 이 기능의 개선으로 인해, 사용자들은 더욱 더 부드러운 UI 및 더욱 높은 유저 경험을 경험할 수 있게 되었습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;결론&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;React 18은 기존의 React에서 발생하던 성능 이슈와 문제점들을 개선하여 더욱 빠르고 안정적인 웹 개발을 가능케 합니다. 이를 통해 사용자 경험을 향상시키고 검색 엔진 최적화를 위한 노력도 더욱 더 효과적으로 이루어질 것입니다. 이번 버전에서의 업그레이드와 개선 사항은 React 프레임워크의 기능적인 발전만큼이나, 웹 개발자들에게 편리함과 향상된 개발 경험을 제공합니다. 또한, 이번 버전에서는 더욱 많은 개발자들이 React를 사용할 수 있게 되었습니다.&lt;/p&gt;</description>
      <category>개발 및 관련 자료/WEB</category>
      <category>Automatic Batching</category>
      <category>Improved Developer Experience</category>
      <category>Javascript</category>
      <category>New Start Transition</category>
      <category>react</category>
      <category>React18</category>
      <category>Server Components</category>
      <category>Web</category>
      <author>jmkim87</author>
      <guid isPermaLink="true">https://kid1412.tistory.com/261</guid>
      <comments>https://kid1412.tistory.com/261#entry261comment</comments>
      <pubDate>Fri, 24 Feb 2023 23:16:51 +0900</pubDate>
    </item>
    <item>
      <title>#3.&amp;nbsp;Longest Substring Without Repeating Characters [Medium] [Javascript]</title>
      <link>https://kid1412.tistory.com/250</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;문제&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Given a string &lt;code&gt;s&lt;/code&gt;, find the length of the &lt;b&gt;longest substring&lt;/b&gt; without repeating characters.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Example 1:&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;applescript&quot;&gt;&lt;code&gt;Input: s = &quot;abcabcbb&quot;
Output: 3
Explanation: The answer is &quot;abc&quot;, with the length of 3.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Example 2:&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;applescript&quot;&gt;&lt;code&gt;Input: s = &quot;bbbbb&quot;
Output: 1
Explanation: The answer is &quot;b&quot;, with the length of 1.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Example 3:&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;livecodeserver&quot;&gt;&lt;code&gt;Input: s = &quot;pwwkew&quot;
Output: 3
Explanation: The answer is &quot;wke&quot;, with the length of 3.
Notice that the answer must be a substring, &quot;pwke&quot; is a subsequence and not a substring.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Constraints:&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;code&gt;0 &amp;lt;= s.length &amp;lt;= 5 * 104&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;s&lt;/code&gt; consists of English letters, digits, symbols and spaces.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;.&lt;br /&gt;.&lt;br /&gt;.&lt;br /&gt;.&lt;br /&gt;.&lt;br /&gt;.&lt;br /&gt;.&lt;br /&gt;.&lt;br /&gt;.&lt;br /&gt;.&lt;br /&gt;.&lt;br /&gt;.&lt;br /&gt;.&lt;br /&gt;.&lt;br /&gt;.&lt;br /&gt;.&lt;br /&gt;.&lt;br /&gt;.&lt;br /&gt;.&lt;br /&gt;.&lt;br /&gt;.&lt;br /&gt;.&lt;br /&gt;.&lt;br /&gt;.&lt;/p&gt;
&lt;pre class=&quot;swift&quot;&gt;&lt;code&gt;var lengthOfLongestSubstring = function(s) {
    const map = {};
    var left = 0;

    return s.split('').reduce((max, v, i) =&amp;gt; {
        left = map[v] &amp;gt;= left ? map[v] + 1 : left;
        map[v] = i;
        return Math.max(max, i - left + 1);
    }, 0);
};&lt;/code&gt;&lt;/pre&gt;</description>
      <category>개발 및 관련 자료/LeetCode</category>
      <category>Javascript</category>
      <category>LeetCode</category>
      <category>Medium</category>
      <category>Reduce</category>
      <author>jmkim87</author>
      <guid isPermaLink="true">https://kid1412.tistory.com/250</guid>
      <comments>https://kid1412.tistory.com/250#entry250comment</comments>
      <pubDate>Thu, 14 Apr 2022 21:39:35 +0900</pubDate>
    </item>
    <item>
      <title>#2.&amp;nbsp;Add Two Numbers [Medium][Javascript]</title>
      <link>https://kid1412.tistory.com/249</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;문제&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;You are given two &lt;b&gt;non-empty&lt;/b&gt; linked lists representing two non-negative integers. The digits are stored in &lt;b&gt;reverse order&lt;/b&gt;, and each of their nodes contains a single digit. Add the two numbers and return the sum as a linked list.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;You may assume the two numbers do not contain any leading zero, except the number 0 itself.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Example 1:&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://assets.leetcode.com/uploads/2020/10/02/addtwonumber1.jpg&quot; alt=&quot;https://assets.leetcode.com/uploads/2020/10/02/addtwonumber1.jpg&quot; /&gt;&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;Input: l1 = [2,4,3], l2 = [5,6,4]
Output: [7,0,8]
Explanation: 342 + 465 = 807.&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Example 2:&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;Input: l1 = [0], l2 = [0]
Output: [0]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Example 3:&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;Input: l1 = [9,9,9,9,9,9,9], l2 = [9,9,9,9]
Output: [8,9,9,9,0,0,0,1]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Constraints:&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;The number of nodes in each linked list is in the range &lt;code&gt;[1, 100]&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;0 &amp;lt;= Node.val &amp;lt;= 9&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;It is guaranteed that the list represents a number that does not have leading zeros.&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;.&lt;br /&gt;.&lt;br /&gt;.&lt;br /&gt;.&lt;br /&gt;.&lt;br /&gt;.&lt;br /&gt;.&lt;br /&gt;.&lt;br /&gt;.&lt;br /&gt;.&lt;br /&gt;.&lt;br /&gt;.&lt;br /&gt;.&lt;br /&gt;.&lt;br /&gt;.&lt;br /&gt;.&lt;br /&gt;.&lt;br /&gt;.&lt;br /&gt;.&lt;br /&gt;.&lt;br /&gt;.&lt;/p&gt;
&lt;pre class=&quot;monkey&quot;&gt;&lt;code&gt;var addTwoNumbers = function(l1, l2) {
    let upNumber = 0;
    const head = new ListNode(0, null);
    let pr = head;

    while(l1 !== null || l2 !== null) { 
        const sum = (l1 ? l1.val : 0) + (l2 ? l2.val: 0);
        const current = new ListNode((sum + upNumber) % 10, null);
        upNumber = Math.floor((sum + upNumber) / 10);
        l1 = l1 ? l1.next : null;
        l2 = l2 ? l2.next : null;
        pr.next = current;
        pr = pr.next;
    }

    if(upNumber &amp;gt; 0) {
        pr.next = new ListNode(upNumber, null)
    }


    return head.next;
};&lt;/code&gt;&lt;/pre&gt;</description>
      <category>개발 및 관련 자료/LeetCode</category>
      <category>Javascript</category>
      <category>LeetCode</category>
      <category>문제풀이</category>
      <category>알고리즘</category>
      <category>코딩 테스트</category>
      <category>코테</category>
      <author>jmkim87</author>
      <guid isPermaLink="true">https://kid1412.tistory.com/249</guid>
      <comments>https://kid1412.tistory.com/249#entry249comment</comments>
      <pubDate>Sun, 3 Apr 2022 14:36:55 +0900</pubDate>
    </item>
    <item>
      <title>#1.  Two Sum [Easy] [javascript]</title>
      <link>https://kid1412.tistory.com/248</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;문제&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Given an array of integers &lt;code&gt;nums&lt;/code&gt; and an integer &lt;code&gt;target&lt;/code&gt;, return &lt;i&gt;indices of the two numbers such that they add up to &lt;code&gt;target&lt;/code&gt;&lt;/i&gt;.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;You may assume that each input would have &lt;b&gt;&lt;i&gt;exactly&lt;/i&gt; one solution&lt;/b&gt;, and you may not use the &lt;i&gt;same&lt;/i&gt; element twice.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;You can return the answer in any order.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Example 1:&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;Input: nums = [2,7,11,15], target = 9
Output: [0,1]
Explanation: Because nums[0] + nums[1] == 9, we return [0, 1].&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Example 2:&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;Input: nums = [3,2,4], target = 6
Output: [1,2]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Example 3:&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;Input: nums = [3,3], target = 6
Output: [0,1]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Constraints:&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;code&gt;2 &amp;lt;= nums.length &amp;lt;= 10^4&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-10^9 &amp;lt;= nums[i] &amp;lt;= 10^9&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-10^9 &amp;lt;= target &amp;lt;= 10^9&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Only one valid answer exists.&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Follow-up:&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Can you come up with an algorithm that is less than&lt;/p&gt;
&lt;pre class=&quot;stylus&quot;&gt;&lt;code&gt;O(n2)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;time complexity?&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;풀이&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;.&lt;br /&gt;.&lt;br /&gt;.&lt;br /&gt;.&lt;br /&gt;.&lt;br /&gt;.&lt;br /&gt;.&lt;br /&gt;.&lt;br /&gt;.&lt;br /&gt;.&lt;br /&gt;.&lt;br /&gt;.&lt;br /&gt;.&lt;br /&gt;.&lt;br /&gt;.&lt;/p&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;var twoSum = function(nums, target) {
    const results = [];
    let index = 0;
    while(nums.length) {
        const first = nums.shift();
        index++;
        const result = nums.findIndex((num) =&amp;gt; (target - (num + first) === 0));
        if(result &amp;gt; -1) {
            results.push(index - 1);
            results.push(result + index);
            break;
        }
    }
    return results;
};&lt;/code&gt;&lt;/pre&gt;</description>
      <category>개발 및 관련 자료/LeetCode</category>
      <category>Javascript</category>
      <category>LeetCode</category>
      <category>Two Sum</category>
      <category>알고리즘</category>
      <category>코딩테스트</category>
      <category>코테</category>
      <category>풀이</category>
      <author>jmkim87</author>
      <guid isPermaLink="true">https://kid1412.tistory.com/248</guid>
      <comments>https://kid1412.tistory.com/248#entry248comment</comments>
      <pubDate>Thu, 31 Mar 2022 19:35:22 +0900</pubDate>
    </item>
    <item>
      <title>기술 블로그 모음 입니다.</title>
      <link>https://kid1412.tistory.com/228</link>
      <description>&lt;p&gt;이래저래 모아둔 기술 블로그 링크 모듬입니다. 보이거나 링크 변경될 때 수정할 예정입니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;카카오 &lt;a href=&quot;http://tech.kakao.com&quot;&gt;http://tech.kakao.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;네이버 &lt;a href=&quot;http://d2.naver.com&quot;&gt;http://d2.naver.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;VCNC &lt;a href=&quot;http://engineering.vcnc.co.kr&quot;&gt;http://engineering.vcnc.co.kr&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;우아한형제들 기술 블로그 &lt;a href=&quot;https://woowabros.github.io&quot;&gt;https://woowabros.github.io&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;SK플래닛 &lt;a href=&quot;http://feeds.feedburner.com&quot;&gt;http://feeds.feedburner.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Amazon Web Services 한국 블로그 &lt;a href=&quot;https://aws.amazon.com/ko/blogs/korea/&quot;&gt;https://aws.amazon.com/ko/blogs/korea/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;스타일쉐어 &lt;a href=&quot;https://styleshare.github.io&quot;&gt;https://styleshare.github.io&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Spoqa &lt;a href=&quot;https://spoqa.github.io&quot;&gt;https://spoqa.github.io&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;이음소시어스 &lt;a href=&quot;http://bigmatch.i-um.net&quot;&gt;http://bigmatch.i-um.net&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;토스랩(잔디) &lt;a href=&quot;https://tosslab.github.io&quot;&gt;https://tosslab.github.io&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;굿닥 엔지니어링 블로그 &lt;a href=&quot;http://dev.goodoc.co.kr&quot;&gt;http://dev.goodoc.co.kr&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;티몬 &lt;a href=&quot;http://tmondev.blog.me&quot;&gt;http://tmondev.blog.me&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;엠비안 &lt;a href=&quot;http://blog.embian.com&quot;&gt;http://blog.embian.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;데일리호텔 &lt;a href=&quot;https://dailyhotel.io&quot;&gt;https://dailyhotel.io&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Mozilla 웹 기술 블로그 &lt;a href=&quot;http://hacks.mozilla.or.kr/&quot;&gt;http://hacks.mozilla.or.kr/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Google Developers Korea 블로그 &lt;a href=&quot;http://googledevkr.blogspot.in&quot;&gt;http://googledevkr.blogspot.in&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;달리웍스 &lt;a href=&quot;http://techblog.daliworks.net&quot;&gt;http://techblog.daliworks.net&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;조이코퍼레이션 &lt;a href=&quot;https://medium.com&quot;&gt;https://medium.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;후이서울 &lt;a href=&quot;https://engineering.huiseoul.com&quot;&gt;https://engineering.huiseoul.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;드라마앤컴퍼니 &lt;a href=&quot;http://blog.dramancompany.com&quot;&gt;http://blog.dramancompany.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;꿈많은청년들 &lt;a href=&quot;https://blog.dreamyoungs.com&quot;&gt;https://blog.dreamyoungs.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Realm &lt;a href=&quot;https://realm.io&quot;&gt;https://realm.io&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;하이퍼커넥트 &lt;a href=&quot;https://hyperconnect.github.io/&quot;&gt;https://hyperconnect.github.io/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;네이버 클라우드 플랫폼 블로그 &lt;a href=&quot;https://blog.naver.com/n_cloudplatform&quot;&gt;https://blog.naver.com/n_cloudplatform&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;당근마켓 팀블로그 &lt;a href=&quot;https://medium.com/n42-corp&quot;&gt;https://medium.com/n42-corp&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;RemoteMonster &lt;a href=&quot;https://blog.remotemonster.com&quot;&gt;https://blog.remotemonster.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;컬리 기술 블로그 &lt;a href=&quot;https://helloworld.kurly.com/&quot;&gt;https://helloworld.kurly.com/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;핑퐁 기술 블로그 &lt;a href=&quot;https://blog.pingpong.us&quot;&gt;https://blog.pingpong.us&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;쿠팡 기술 블로그 &lt;a href=&quot;https://medium.com/coupang-tech&quot;&gt;https://medium.com/coupang-tech&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Line &lt;a href=&quot;https://engineering.linecorp.com/ko/blog/&quot;&gt;https://engineering.linecorp.com/ko/blog/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Airbnb &lt;a href=&quot;https://medium.com/airbnb-engineering&quot;&gt;https://medium.com/airbnb-engineering&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;페이스북 개발자 블로그 &lt;a href=&quot;https://developers.facebook.com/blog/&quot;&gt;https://developers.facebook.com/blog/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Netfilx &lt;a href=&quot;https://netflixtechblog.com&quot;&gt;https://netflixtechblog.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;twitter &lt;a href=&quot;https://blog.twitter.com/engineering/en_us.html&quot;&gt;https://blog.twitter.com/engineering/en_us.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;microsoft &lt;a href=&quot;https://techcommunity.microsoft.com/t5/custom/page/page-id/Blogs&quot;&gt;https://techcommunity.microsoft.com/t5/custom/page/page-id/Blogs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;dropbox &lt;a href=&quot;https://dropbox.tech&quot;&gt;https://dropbox.tech&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;instagram &lt;a href=&quot;https://instagram-engineering.com&quot;&gt;https://instagram-engineering.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;toast &lt;a href=&quot;https://meetup.toast.com&quot;&gt;https://meetup.toast.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;레진코믹스 &lt;a href=&quot;https://tech.lezhin.com&quot;&gt;https://tech.lezhin.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;야놀자 &lt;a href=&quot;https://yanolja.github.io&quot;&gt;https://yanolja.github.io&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;zigzag &lt;a href=&quot;https://devblog.croquis.com/ko/&quot;&gt;https://devblog.croquis.com/ko/&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;무신사 &lt;a href=&quot;https://medium.com/musinsa-tech&quot;&gt;https://medium.com/musinsa-tech&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>개발 및 관련 자료</category>
      <category>airbnb</category>
      <category>AWS</category>
      <category>facebook</category>
      <category>Google</category>
      <category>KAKAO</category>
      <category>naver</category>
      <category>기술블로그</category>
      <category>네이버</category>
      <category>우아한형재들</category>
      <category>카카오</category>
      <author>jmkim87</author>
      <guid isPermaLink="true">https://kid1412.tistory.com/228</guid>
      <comments>https://kid1412.tistory.com/228#entry228comment</comments>
      <pubDate>Mon, 17 May 2021 18:12:32 +0900</pubDate>
    </item>
    <item>
      <title>1장 빅테이터 기술 기초 다지기</title>
      <link>https://kid1412.tistory.com/246</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;1035&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/RteL0/btqJ1LERhOi/KPTxeh3VuIjmX0TKPK5jaK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/RteL0/btqJ1LERhOi/KPTxeh3VuIjmX0TKPK5jaK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/RteL0/btqJ1LERhOi/KPTxeh3VuIjmX0TKPK5jaK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FRteL0%2FbtqJ1LERhOi%2FKPTxeh3VuIjmX0TKPK5jaK%2Fimg.jpg&quot; width=&quot;100%&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;1035&quot; data-ke-mobilestyle=&quot;widthContent&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;h2&gt;1. 빅데이터 기술 기초 다지기&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;아파치 하둡(Apache Hadoop)&lt;/code&gt;&lt;/strong&gt; : 높은 확장성과 신뢰성을 보유한 분산 스토리지와 분산 처리 기능을 제공하기 위해 다양한 소프트웨어를 밀접하게 통합한 에코시스템. 대표적으로 분산 파일 시스템 &lt;strong&gt;&lt;code&gt;HDFS(Hadoop Distributed File System)&lt;/code&gt;&lt;/strong&gt;과 분산 서버 클러스터 환경에서 프로세스를 실행하는 &lt;strong&gt;&lt;code&gt;YARN(Yet Another Resource Negotiator)&lt;/code&gt;&lt;/strong&gt;가 있다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;클러스터(Cluster)&lt;/code&gt;&lt;/strong&gt;란?&lt;ul&gt;
&lt;li&gt;저장이나 연산 등 하나 이상의 기능을 제공하기 위해 협력하는 서버의 조합.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;마스터(Master)&lt;/code&gt;&lt;/strong&gt;와 &lt;strong&gt;&lt;code&gt;워커(Worker)&lt;/code&gt;&lt;/strong&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;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;1-1. 하둡 에코시스템 둘러보기&lt;/h3&gt;
&lt;p&gt;하둡 에코시스템은 하둡을 중심으로 만들어진 데이터 엔지니어링 프로젝트와 프레임워크 전부를 의미.&lt;/p&gt;
&lt;p&gt;여기서는 프로젝트의 의존 관계를 &lt;strong&gt;&lt;code&gt;데이터&lt;/code&gt;&lt;/strong&gt;와 &lt;strong&gt;&lt;code&gt;제어&lt;/code&gt;&lt;/strong&gt; 두가지로 구분함.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;4032&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bbfZeQ/btqJWsNj9ES/N0q1Z9XE4oGJ3qKm4P3rr1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bbfZeQ/btqJWsNj9ES/N0q1Z9XE4oGJ3qKm4P3rr1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bbfZeQ/btqJWsNj9ES/N0q1Z9XE4oGJ3qKm4P3rr1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbbfZeQ%2FbtqJWsNj9ES%2FN0q1Z9XE4oGJ3qKm4P3rr1%2Fimg.jpg&quot; width=&quot;100%&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;4032&quot; data-ke-mobilestyle=&quot;widthContent&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;h3&gt;핵심 컴포넌트&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;**HDFS**&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;**하둡 분산 파일 시스템(Hadoop Distributed File System)**&lt;/code&gt;은 확장성과 장애 허용성을 가진 분산 파일 시스템&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;상당히 긴 순차 접근(Sequential access) 방식을 통해 디스크에 불변 데이터를 저장하는데 최적화돼 있음&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;데이터를 설정 가능한 크기의 block으로 나눠 저장.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;기본은 128MB이며, 데이터 회복성 및 데이터 병렬 처리를 위해 여러대의 서버에 각 블록의 복제본을 저장&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;클러스터에 있는 워커 노드는 &lt;strong&gt;&lt;code&gt;데이터 노드(Data node)&lt;/code&gt;&lt;/strong&gt; 데몬을 실행 새 블록을 전달받아서 로컬디스크에 저장&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;데이터의 저장 및 제공을 담당&lt;/li&gt;
&lt;li&gt;블록과 블록의 ID만 알고 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;마스터 서버에서 실행되고 있는 &lt;code&gt;**네임 노드(Name node)**&lt;/code&gt;는 파일 자체의 메타 데이터를 관리&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;파일이 어느 복제본에 속하는지에 대한 정보&lt;/li&gt;
&lt;li&gt;파일과 블록 사이의 매핑 정보&lt;/li&gt;
&lt;li&gt;파일 이름, 권한, 속성, 복제 계수(Replication factor)등에 대한 정보&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;불변성을 위해 파일의 일부분 수정을 지원하지 않음.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot; data-origin-width=&quot;813&quot; data-origin-height=&quot;509&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/olpio/btqJ0nEd6hp/CAj4YrsMmtZiGu492awbzK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/olpio/btqJ0nEd6hp/CAj4YrsMmtZiGu492awbzK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/olpio/btqJ0nEd6hp/CAj4YrsMmtZiGu492awbzK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Folpio%2FbtqJ0nEd6hp%2FCAj4YrsMmtZiGu492awbzK%2Fimg.jpg&quot; width=&quot;100%&quot; data-origin-width=&quot;813&quot; data-origin-height=&quot;509&quot; data-ke-mobilestyle=&quot;widthContent&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;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;YARN(Yet Another Resource Negotiator)&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;작업 스케줄링, 클러스터 리소스 관리를 위한 프레임 워크&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;워커 노드 안에 &lt;strong&gt;&lt;code&gt;노드 매니저(Node Manager)&lt;/code&gt;&lt;/strong&gt;가 &lt;strong&gt;&lt;code&gt;리소스 매니저(Resource Manager)&lt;/code&gt;&lt;/strong&gt;에 다양한 정보 전달&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;가상 코어(vcore)의 단위로 얼마나 많은 연산 자원을 사용할 수 있는지&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;해당 노드에 메모리가 얼마나 남아 있는지&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot; data-origin-width=&quot;1400&quot; data-origin-height=&quot;1049&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/yBZ2I/btqJWS51iJy/BETKIUGwDRwRwOk0kqZcGk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/yBZ2I/btqJWS51iJy/BETKIUGwDRwRwOk0kqZcGk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/yBZ2I/btqJWS51iJy/BETKIUGwDRwRwOk0kqZcGk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FyBZ2I%2FbtqJWS51iJy%2FBETKIUGwDRwRwOk0kqZcGk%2Fimg.jpg&quot; width=&quot;100%&quot; data-origin-width=&quot;1400&quot; data-origin-height=&quot;1049&quot; data-ke-mobilestyle=&quot;widthContent&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;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;ZooKeeper&lt;/code&gt;&lt;/strong&gt;&lt;/p&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;운영(active) 서버에서 문제가 발생하여 서비스 제공할 수 없는 경우 다른 대기중인 서버를 운영서버로 변경하여 중지없이 제공&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;strong&gt;&lt;code&gt;지노드(znode)&lt;/code&gt;&lt;/strong&gt; : 데이터를 가지고 있으며, 0개 이상의 자식 노드를 가질수 있음&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;앙상블(ensemble)&lt;/code&gt;&lt;/strong&gt; : 회복성을 확보하기 위해 인스턴스를 각기 서로 다른 서버에 배포&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;쿼럼(quorum)&lt;/code&gt;&lt;/strong&gt; : 다수결 원칙에 따라 합의(consensus)를 이끌어 내므로 홀수의 서버에 배포하고 이때 과반수의 서버로 이루어진 그룹&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot; data-origin-width=&quot;728&quot; data-origin-height=&quot;270&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bSJ2IC/btqJV7ijSww/aCfjzJk2AkqnywmqvrvQ2k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bSJ2IC/btqJV7ijSww/aCfjzJk2AkqnywmqvrvQ2k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bSJ2IC/btqJV7ijSww/aCfjzJk2AkqnywmqvrvQ2k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbSJ2IC%2FbtqJV7ijSww%2FaCfjzJk2AkqnywmqvrvQ2k%2Fimg.png&quot; width=&quot;100%&quot; data-origin-width=&quot;728&quot; data-origin-height=&quot;270&quot; data-ke-mobilestyle=&quot;widthContent&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;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;프로젝트&lt;/th&gt;
&lt;th&gt;주키퍼 사용 목적&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;HDFS&lt;/td&gt;
&lt;td&gt;고가용성 조율&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HBase&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;/tr&gt;
&lt;tr&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;/tr&gt;
&lt;tr&gt;
&lt;td&gt;하이브&lt;/td&gt;
&lt;td&gt;테이블 및 파티션 잠금 및 고가용성&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;아파치 하이브(Hive) 메타스토어&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;하둡 내에 존재하는 &lt;strong&gt;&lt;code&gt;비정형 바이너리 데이터(unstructured binary data)&lt;/code&gt;&lt;/strong&gt;가 아닌 &lt;strong&gt;&lt;code&gt;정형 데이터셋(structured dataset)&lt;/code&gt;&lt;/strong&gt;에 대한 정보를 데이터 셋, 테이블, 뷰 같은 논리적인 위계 구조로 구성해서 관리&lt;/li&gt;
&lt;li&gt;HDFS에서는 하이브 테이블이 디렉토리와 같다.&lt;/li&gt;
&lt;li&gt;파티셔닝을 지원하며, 파티션된 테이블은 HDFS 상에서 하위 디렉토리를 가지게 된다.&lt;/li&gt;
&lt;li&gt;하나의 테이블 안에서의 모든 파일은 동일한 포맷으로 저장돼야 한다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;관리형 테이블(managed table)&lt;/code&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;code&gt;외부 테이블(external table)&lt;/code&gt;&lt;/strong&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;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;연산 프레임워크&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;하둡 맵리듀스(MapReduce)&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;대용량 데이터를 분산 처리하기 위한 프로그래밍 모델 프레임워크&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;MapReduce Framework를 이용하면 대규모 분산 컴퓨팅 환경에서, 대량의 데이터를 병렬로 분석 가능&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;연산을 &lt;strong&gt;&lt;code&gt;맵(Map),&lt;/code&gt;&lt;/strong&gt; &lt;strong&gt;&lt;code&gt;셔플(Shuffle)&lt;/code&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;code&gt;리듀스(Reduce)&lt;/code&gt;&lt;/strong&gt; 3 단계로 나눠서 처리&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot; data-origin-width=&quot;576&quot; data-origin-height=&quot;211&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qHnBy/btqJV5LBabZ/gKCki9mosURtfQRe9oAg1K/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qHnBy/btqJV5LBabZ/gKCki9mosURtfQRe9oAg1K/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qHnBy/btqJV5LBabZ/gKCki9mosURtfQRe9oAg1K/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqHnBy%2FbtqJV5LBabZ%2FgKCki9mosURtfQRe9oAg1K%2Fimg.jpg&quot; width=&quot;100%&quot; data-origin-width=&quot;576&quot; data-origin-height=&quot;211&quot; data-ke-mobilestyle=&quot;widthContent&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;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;아파치 스파크(Spark)&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;효율성과 사용성에 중점을 둔 분산 연산 프레임워크&lt;/li&gt;
&lt;li&gt;다수의 저사양 장비로 이루어지는 워크 노드에 있는 메모리를 최대한 활용하는 것&lt;/li&gt;
&lt;li&gt;배치 연산과 스트리밍 연산을 모두 지원&lt;/li&gt;
&lt;li&gt;데이터셋에 직접 적용할 수 있는 풍부한 API를 제공&lt;/li&gt;
&lt;li&gt;프로세싱 그래프가 표준 쿼리 옵티마이저를 거친 후에 실행&lt;/li&gt;
&lt;li&gt;스파크 표준 쿼리 옵티마이저 : 관계형 데이터베이스 혹은 대규모 병렬 쿼리 엔진의 쿼리 옵티마이저와 비슷&lt;ul&gt;
&lt;li&gt;파이프라인 실행의 효율성을 극대화 하기 위해 프로세싱 그래프를 &lt;strong&gt;&lt;code&gt;재배치(rearrange)&lt;/code&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;code&gt;결합(combine)&lt;/code&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;code&gt;가지치기(prune)&lt;/code&gt;&lt;/strong&gt; 사용&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;분석용 SQL 엔진&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;아파치 하이브(Hive)&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;하둡에 사용되는 원조 데이터 웨어하우징 기술&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;HDFS에 저장된 정형 데이터를 SQL과 비슷한 문법(하이브QL)으로 쿼리할 수있게 만든 기술&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;ETL(추출(Extract), 변환(Transform), 적재(Load)), 보고서 데이터 생성, 벌크 데이터 처리 등 오프라인 배치 작업에 적합&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot; data-origin-width=&quot;805&quot; data-origin-height=&quot;876&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bODa1y/btqJ0ob5hPR/EJ2NEmRkTOKad1KHbc2d4k/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bODa1y/btqJ0ob5hPR/EJ2NEmRkTOKad1KHbc2d4k/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bODa1y/btqJ0ob5hPR/EJ2NEmRkTOKad1KHbc2d4k/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbODa1y%2FbtqJ0ob5hPR%2FEJ2NEmRkTOKad1KHbc2d4k%2Fimg.jpg&quot; width=&quot;100%&quot; data-origin-width=&quot;805&quot; data-origin-height=&quot;876&quot; data-ke-mobilestyle=&quot;widthContent&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;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;아파치 임팔라(Impala)&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;대규모 병렬 처리(Massive Parallel Processing) 엔진&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;MapReduce를 사용하지 않고 C++로 개발한 인메모리 엔진을 사용하여 빠른 성능을 보여줌&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;하둡이나 클라우드 스토리지에 저장된 대용량 데이터셋에 대한 고속, 대화형 SQL 쿼리를 목적으로 설계&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;테라바이트 단위의 데이터에 대해 다수의 동시 실행 애드혹 쿼리, 보고서 스타일의 쿼리를 수초내에 처리하는 것이 목표&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;452&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/btxEPp/btqJ0oiPS3V/8cy8IYNSvt42MmlsT1i7u0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/btxEPp/btqJ0oiPS3V/8cy8IYNSvt42MmlsT1i7u0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/btxEPp/btqJ0oiPS3V/8cy8IYNSvt42MmlsT1i7u0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbtxEPp%2FbtqJ0oiPS3V%2F8cy8IYNSvt42MmlsT1i7u0%2Fimg.png&quot; width=&quot;100%&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;452&quot; data-ke-mobilestyle=&quot;widthContent&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;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;스토리지 엔지&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;아파치 HBase&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;HDFS의 컬럼(열) 기반 데이터베이스&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;분산 테이블에 cell이라고 불리는 키-값 쌍의 반정형 데이터 형식으로 HDFS에 저장&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;실시간 랜덤 조회 및 업데이트 가능&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;각각의 프로세스들은 개인의 데이터를 비동기적(동시성 X)으로 업데이트 할 수 있음. 단 MapReduce는 일괄처리 방식으로 수행!&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Hadoop 및 HDFS위에 Bigtable과 같은 기능을 제공&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Cell key를 위계 구조(hierarchy)를 가지도록 세분화&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;로우 키&lt;/code&gt;&lt;/strong&gt; : Cell의 논리적인 그룹인 로우row를 정의함&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;컬럼 패밀리&lt;/code&gt;&lt;/strong&gt; : 메모리와 디스크에 분리되어 저장되고, 컬럼 한정자로 세분화되는데 하나의 로우에 수백만 개의 컬럼 한정자가 있을 수 있음.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot; data-origin-width=&quot;770&quot; data-origin-height=&quot;324&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/yxXqF/btqJWSZiULg/g1kUxUCmzVFxKeO5VcKE81/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/yxXqF/btqJWSZiULg/g1kUxUCmzVFxKeO5VcKE81/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/yxXqF/btqJWSZiULg/g1kUxUCmzVFxKeO5VcKE81/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FyxXqF%2FbtqJWSZiULg%2Fg1kUxUCmzVFxKeO5VcKE81%2Fimg.png&quot; width=&quot;100%&quot; data-origin-width=&quot;770&quot; data-origin-height=&quot;324&quot; data-ke-mobilestyle=&quot;widthContent&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;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;버전&lt;/code&gt;&lt;/strong&gt; : 타임스탬프로 되어 있음.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;리전(region)&lt;/code&gt;&lt;/strong&gt; : HBase에서 수평확장의 기본단위이며, 함께 저장되는 테이블의 부분집합&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot; data-origin-width=&quot;1148&quot; data-origin-height=&quot;768&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dqzLoq/btqJ6caCDlO/yaWjNYDqvyIt9R7b2jv62K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dqzLoq/btqJ6caCDlO/yaWjNYDqvyIt9R7b2jv62K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dqzLoq/btqJ6caCDlO/yaWjNYDqvyIt9R7b2jv62K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdqzLoq%2FbtqJ6caCDlO%2FyaWjNYDqvyIt9R7b2jv62K%2Fimg.png&quot; width=&quot;100%&quot; data-origin-width=&quot;1148&quot; data-origin-height=&quot;768&quot; data-ke-mobilestyle=&quot;widthContent&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;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;아파치 쿠두(Kudu)&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;미리 정의된 스키마를 따르는 테이블에 타입을 가진 컬럼으로 구성된 레코드를 저장하는 정형 데이터 스토어&lt;/li&gt;
&lt;li&gt;컴럼의 일부는 테이블의 기본 키로 사용되며, 인덱스가 생성됨&lt;/li&gt;
&lt;li&gt;파티셔닝 매커니즘&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;범위 파티셔닝(Range Partitioning)&lt;/code&gt;&lt;/strong&gt; : 각 태블릿은 상한과 하한으로 이뤄진 범위를 갖고 있으며, 범위 내에 들어가는 파티션 키를 가진 모든 레코드는 해당 태블릿에 저장&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;해시 파티셔닝(Hash Partitioning)&lt;/code&gt;&lt;/strong&gt; : 사용자는 테이블 파티셔닝의 기준이 되는 고정된 수의 해시 버킷을 지정할 수 있고 각 행에서 선택된 컬럼의 해시 값을 해시 커빗 수로 나눈 나머지를 기준으로 태블릿에 저장&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;아파치 솔라(Solr)&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;정보검색 라이브러리인 루씬의 엔터프라이즈 버전&lt;/li&gt;
&lt;li&gt;텍스트 검색, 다면적 검색, 실시간 인덱싱, 클러스터링, 데이터베이스 통합, 다양한 문서처리 및 솔라 분산 인덱싱 등 기능을 지원&lt;/li&gt;
&lt;li&gt;루씬에서 나온 개념인 역방향 인덱스(inverted index)를 사용&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;아파치 카프카(Kafka)&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;실시간으로 기록 스트림을 게시, 구독, 저장 및 처리할 수 있는 분산 데이터 스트리밍 플랫품&lt;/li&gt;
&lt;li&gt;입수되는 메시지를 분산 저장되는 순차적인 로그로 저장하고, 클라이언트나 크라이언트의 그룹은 간단한 숫자 형태의 오프셋을 이용해 특정 지점으로부터의 데이터를 가져옴&lt;/li&gt;
&lt;li&gt;다양한 업스트림 소스와 다운스트림 싱크를 통합하고 회복성있는 고가용성 입수 버퍼를 제공&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;토픽(topic)&lt;/code&gt;&lt;/strong&gt; : 기초가 되는 데이터 구조&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;브로커(broker)&lt;/code&gt;&lt;/strong&gt; : 여러대의 서버&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;프로듀서(producer)&lt;/code&gt;&lt;/strong&gt; : 카프카 토픽의 파티션으로 메시지를 발행&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;컨슈머(consumer)&lt;/code&gt;&lt;/strong&gt; : 토픽에 있는 데이터를 읽음&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;컨슈머 그룹(consumer group)&lt;/code&gt;&lt;/strong&gt; : 확장성을 위해 여러 컨슈머로 묶을 수 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;데이터 입수&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;아파치 플룸(Flume)&lt;/p&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;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot; data-origin-width=&quot;1200&quot; data-origin-height=&quot;489&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bn5XmX/btqJZmS5Hl9/TaomaqUW7dIMbpxbnlBU81/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bn5XmX/btqJZmS5Hl9/TaomaqUW7dIMbpxbnlBU81/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bn5XmX/btqJZmS5Hl9/TaomaqUW7dIMbpxbnlBU81/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbn5XmX%2FbtqJZmS5Hl9%2FTaomaqUW7dIMbpxbnlBU81%2Fimg.jpg&quot; width=&quot;100%&quot; data-origin-width=&quot;1200&quot; data-origin-height=&quot;489&quot; data-ke-mobilestyle=&quot;widthContent&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;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;아파치 스쿱(Sqoop)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;관계형 데이터베이스와 하둡 사이에서 데이터 이관을 지원하는 툴&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot; data-origin-width=&quot;708&quot; data-origin-height=&quot;375&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/1DPGd/btqJ1LrkgWr/nniHJdPRyjfaCGnMqraa10/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/1DPGd/btqJ1LrkgWr/nniHJdPRyjfaCGnMqraa10/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/1DPGd/btqJ1LrkgWr/nniHJdPRyjfaCGnMqraa10/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F1DPGd%2FbtqJ1LrkgWr%2FnniHJdPRyjfaCGnMqraa10%2Fimg.png&quot; width=&quot;100%&quot; data-origin-width=&quot;708&quot; data-origin-height=&quot;375&quot; data-ke-mobilestyle=&quot;widthContent&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&gt;&lt;strong&gt;데이터 임포트&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot; data-origin-width=&quot;1383&quot; data-origin-height=&quot;769&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/beFTpQ/btqJV5Sh6ec/0djnz4Vm52RkWqDuO4r6yk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/beFTpQ/btqJV5Sh6ec/0djnz4Vm52RkWqDuO4r6yk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/beFTpQ/btqJV5Sh6ec/0djnz4Vm52RkWqDuO4r6yk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbeFTpQ%2FbtqJV5Sh6ec%2F0djnz4Vm52RkWqDuO4r6yk%2Fimg.png&quot; width=&quot;100%&quot; data-origin-width=&quot;1383&quot; data-origin-height=&quot;769&quot; data-ke-mobilestyle=&quot;widthContent&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&gt;&lt;strong&gt;데이터 익스포트&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;컴포넌트 요약&lt;/h3&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;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;ZooKeeper&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;HDFS&lt;/td&gt;
&lt;td&gt;분산 파일 스토리지&lt;/td&gt;
&lt;td&gt;불변 데이터를 위한 확장성 있는 스토리지&lt;/td&gt;
&lt;td&gt;ZooKeeper&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Yarn&lt;/td&gt;
&lt;td&gt;분산 리소스 스케줄링 및 실행 프레임워크&lt;/td&gt;
&lt;td&gt;확장성 있는 분산 컴퓨팅 자원을 필요로 하는 프레임워크&lt;/td&gt;
&lt;td&gt;ZooKeeper, HDFS&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MapReduce&lt;/td&gt;
&lt;td&gt;범용 분산 연산 프레임워크&lt;/td&gt;
&lt;td&gt;배치 연산 작업&lt;/td&gt;
&lt;td&gt;Yarn, HDFS&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Spark&lt;/td&gt;
&lt;td&gt;범용 분산 연산 프레임워크&lt;/td&gt;
&lt;td&gt;배치, 분석 SQL, 스트리밍 작업&lt;/td&gt;
&lt;td&gt;자원 스케줄러(Yarn, Mesos) 및 데이터 소스(HDFS, Kudu 등)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hive&lt;/td&gt;
&lt;td&gt;SQL 기반 분석 쿼리 프레임워크&lt;/td&gt;
&lt;td&gt;분산 SQL 작업&lt;/td&gt;
&lt;td&gt;Yarn, 데이터 소스(HDFS, Kudu)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Impala&lt;/td&gt;
&lt;td&gt;SQL 기반 대규모 병렬 처리 분산 엔진&lt;/td&gt;
&lt;td&gt;분석 및 대화형 SQL 작업&lt;/td&gt;
&lt;td&gt;데이터 소스(HDFS, Kudu, HBase)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HBase&lt;/td&gt;
&lt;td&gt;위계 구조를 가진 키-값 데이터 분산/정렬 스토어&lt;/td&gt;
&lt;td&gt;정형 키를 가진 로우 기반 데이터에 대한 고속 랜덤 읽기/쓰기&lt;/td&gt;
&lt;td&gt;HDFS, ZooKeeper&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Kudu&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;Solr&lt;/td&gt;
&lt;td&gt;엔터프라이즈 검색 프레임 워크&lt;/td&gt;
&lt;td&gt;확장성 있는 도큐먼트 인덱싱 및 임의 필트 쿼리&lt;/td&gt;
&lt;td&gt;HDFS, ZooKeeper&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Kafka&lt;/td&gt;
&lt;td&gt;분산 발행/구독 메시징 프레임워크&lt;/td&gt;
&lt;td&gt;데이터 프로세싱 파이프라인의 주기적 또는 실시간 실행&lt;/td&gt;
&lt;td&gt;ZooKeeper&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;</description>
      <category>IT Book Study/엔터프라이즈 데이터 플랫폼 구축</category>
      <category>Hadoop</category>
      <category>hbase</category>
      <category>HDFS</category>
      <category>HIVE</category>
      <category>kafka</category>
      <category>SPARK</category>
      <category>yarn</category>
      <category>zookeeper</category>
      <category>엔터프라이즈 데이터 플랫폼 구축</category>
      <category>하둡 에코시스템</category>
      <author>jmkim87</author>
      <guid isPermaLink="true">https://kid1412.tistory.com/246</guid>
      <comments>https://kid1412.tistory.com/246#entry246comment</comments>
      <pubDate>Fri, 2 Oct 2020 23:35:30 +0900</pubDate>
    </item>
    <item>
      <title>러닝스칼라 10장 - 고급 타입 특징</title>
      <link>https://kid1412.tistory.com/245</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dwOi4l/btqJPBJxmpP/ntw5dkyDD8U2ZuDAZWL7d0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dwOi4l/btqJPBJxmpP/ntw5dkyDD8U2ZuDAZWL7d0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dwOi4l/btqJPBJxmpP/ntw5dkyDD8U2ZuDAZWL7d0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdwOi4l%2FbtqJPBJxmpP%2Fntw5dkyDD8U2ZuDAZWL7d0%2Fimg.jpg&quot; width=&quot;100%&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&gt;스칼라 데이터 타입 특징을 깊게 알아보자.&lt;br&gt;이 장을 이해함으로써 스칼라 API, 라이브러리 동작 방식을 이해할 수 있다.&lt;/p&gt;
&lt;h2&gt;튜플과 함숫값 클래스&lt;/h2&gt;
&lt;p&gt;튜플은 &lt;code&gt;TupleX[Y]&lt;/code&gt; 케이스 클래스의 인스턴스로 구현&lt;/p&gt;
&lt;p&gt;&lt;code&gt;X&lt;/code&gt;: 1 &amp;lt;= X &amp;lt;= 22, 튜플의 입력 매개변수 개수&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Y&lt;/code&gt;: 타입 매개변수&lt;/p&gt;
&lt;p&gt;&lt;code&gt;productArity&lt;/code&gt;: 튜플의 매개변수 개수를 반환하는 함수, 튜플이 상속받는 ProductX 트레이트에 정의됨&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;scala&amp;gt; val x = (10, 20)
x: (Int, Int) = (10,20)

scala&amp;gt; val x: (Int, Int) = Tuple2(10, 20)
x: (Int, Int) = (10,20)

scala&amp;gt; println(&amp;quot;Does the arity = 2? &amp;quot; + (x.productArity == 2))
Does the arity = 2? true&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;함수값은 &lt;code&gt;FunctionX[Y]&lt;/code&gt; 트레이트를 확장한 익명 클래스의 인스턴스로 구현된다.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;X&lt;/code&gt;: 매개변수 개수&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Y&lt;/code&gt;: 타입 매개변수, 첫 번째는 반환값 타입, 두 번째부터는 매개변수의 타입&lt;br&gt;스칼라 컴파일러가 함수 리터럴을 FunctionX를 확장하는 새로운 클래스의 apply() 메소드의 body로 전환한다.&lt;br&gt;이는 모든 함수가 클래스 메소드로 구현되도록 제한하는 JVM과 호환되도록 해준다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;scala&amp;gt; val hello1 = (n: String) =&amp;gt; s&amp;quot;Hello, $n&amp;quot;
hello1: String =&amp;gt; String = $$Lambda$839/0x000000080104a040@3820cfe

scala&amp;gt; val h1 = hello1(&amp;quot;Function Literals&amp;quot;)
h1: String = Hello, Function Literals

scala&amp;gt; val hello2 = new Function1[String, String] {
     |   def apply(n: String) = s&amp;quot;Hello, $n&amp;quot;
     | }
hello2: String =&amp;gt; String = &amp;lt;function1&amp;gt;

scala&amp;gt; val h2 = hello2(&amp;quot;Functional Instances&amp;quot;)
h2: String = Hello, Functional Instances

scala&amp;gt; println(s&amp;quot;hello1 = $hello1, hello2 = $hello2&amp;quot;)
hello1 = $line6.$read$$iw$$iw$$$Lambda$839/0x000000080104a040@3820cfe, hello2 = &amp;lt;function1&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Function1 트레이트는 FunctionX (X != 1)에는 없는 2개의 메소드를 가지고 있다.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;andThen&lt;/code&gt;: 두 함수값으로부터 새로운 함수값을 생성, 왼쪽 인스턴스에서 오른쪽에 있는 인스턴스를 실행&lt;/p&gt;
&lt;p&gt;&lt;code&gt;compose&lt;/code&gt;: 반대 방향으로 동작&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;scala&amp;gt; val doubler = (i: Int) =&amp;gt; i*2
doubler: Int =&amp;gt; Int = $$Lambda$970/0x00000008010c3040@22b10124

scala&amp;gt; val plus3 = (i: Int) =&amp;gt; i+3
plus3: Int =&amp;gt; Int = $$Lambda$971/0x00000008010c3840@79ae3fb1

scala&amp;gt; val append = (doubler andThen plus3)(1)
append: Int = 5

scala&amp;gt; val prepend = (doubler compose plus3)(1)
prepend: Int = 8&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;묵시적 매개변수 (implicit parameter)&lt;/h2&gt;
&lt;p&gt;nonimplicit 매개변수와 별개로 implicit한 매개변수 그룹을 정의한다.&lt;br&gt;implicit 매개변수에 명시적으로 값을 넣어도 동작한다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;scala&amp;gt; object Doubly {
     |   def print(num: Double)(implicit fmt: String) = {
     |     println(fmt format num)
     |   }
     | }
defined object Doubly

scala&amp;gt; case class USD(amount: Double) {
     |   implicit val printFmt = &amp;quot;%.2f&amp;quot;
     |   def print = Doubly.print(amount)
     | }
defined class USD

scala&amp;gt; new USD(81.924).print
81.92

scala&amp;gt; Doubly.print(3.724)(&amp;quot;%.1f&amp;quot;)
3.7&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;묵시적 클래스 (implicit class)&lt;/h2&gt;
&lt;p&gt;묵시적 클래스는 특정 클래스의 자동 전환을 제공&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;// Int를 Fishes 클래스로 자동 전환
scala&amp;gt; object IntUtils {
     |   implicit class Fishies(val x: Int) {
     |     def fishes = &amp;quot;Fish&amp;quot; * x
     |   }
     | }
defined object IntUtils

scala&amp;gt; import IntUtils._
import IntUtils._

scala&amp;gt; println(3.fishes)
FishFishFish&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt; 묵시적 클래스 제약 사항&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;다른 객체, 클래스, 트레이트 안에 정의되어야 한다. &lt;/li&gt;
&lt;li&gt;하나의 nonimplicit 클래스 인수를 받아야 한다. &lt;/li&gt;
&lt;li&gt;현재 네임스페이스의 다른 객체, 클래스, 트레이트와 클래스명이 겹치면 안된다. &lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;케이스 클래스는 자동으로 생성된 동반 객체와 이름이 겹치기 때문에 묵시적 클래스로 사용할 수 없다. &lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;객체 내에 구현하는 것이 가장 좋다. 객체 내에 정의할 경우 쉽게 임포트할 수 있다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;여러가지 묵시적 클래스를 가진 &lt;code&gt;scala.Predef&lt;/code&gt; 객체는 자동으로 네임스페이스에 추가된다. &lt;/p&gt;
&lt;p&gt;예를 들어서 x -&amp;gt; y 연산자는 아래와 같이 정의되어 자동으로 적용된다. &lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;// 간략하게 적음
// 1 -&amp;gt; &amp;quot;a&amp;quot; Tuple2(1,&amp;quot;a&amp;quot;)
implicit class ArrowAssoc[A](x: A) {
  def -&amp;gt;[B](y: B) = Tuple2(x, y)
}&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;타입&lt;/h2&gt;
&lt;p&gt;클래스, 트레이트 타입은 사용가능하지만 객체는 타입으로 간주하지 않는다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;scala&amp;gt; class A
defined class A

scala&amp;gt; trait B
defined trait B

scala&amp;gt; val a:A = new A
a: A = A@4860627a

scala&amp;gt; val b:B = new B{}
b: B = $anon$1@79486f38&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;타입 별칭 (type alias)&lt;/h3&gt;
&lt;p&gt;기존 타입을 새롭게 명명하는 것 &lt;/p&gt;
&lt;p&gt;타입 별칭은 객체, 클래스, 트레이트 내부에서만 정의가능&lt;/p&gt;
&lt;p&gt;객체는 타입 별칭을 생성하는 데 사용할 수 없음&lt;/p&gt;
&lt;p&gt;&lt;code&gt;type &amp;lt;식별자&amp;gt;[타입 매개변수] = &amp;lt;타입명&amp;gt;[타입 매개변수]&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;scala&amp;gt; object TypeFun {
     |   type Whole = Int
     |   val x: Whole = 5
     |
     |   type UserInfo = Tuple2[Int, String]
     |   val u: UserInfo = new UserInfo(123, &amp;quot;George&amp;quot;)
     |
     |   type T3[A,B,C] = Tuple3[A,B,C]
     |   val things = new T3(1, &amp;#39;a&amp;#39;, true)
     | }
defined object TypeFun

scala&amp;gt; val x = TypeFun.x
x: TypeFun.Whole = 5

scala&amp;gt; val u = TypeFun.u
u: TypeFun.UserInfo = (123,George)

scala&amp;gt; val things = TypeFun.things
things: (Int, Char, Boolean) = (1,a,true)&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;추상 타입 (abstract type)&lt;/h2&gt;
&lt;p&gt;추상 클래스, 트레이트를 mixin한 서브클래스가 구현해야만 하는 타입을 선언하기 위해 사용&lt;br&gt;허용 가능한 타입의 범위를 지정하기 위해 타입 매개변수로 사용된다.&lt;br&gt;인스턴스를 생성하는데 사용할 수 없다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;scala&amp;gt; class User(val name: String)
defined class User

scala&amp;gt; trait Factory { type A; def create: A }
defined trait Factory

scala&amp;gt; trait UserFactory extends Factory {
     |   type A = User
     |   def create = new User(&amp;quot;&amp;quot;)
     | }
defined trait UserFactory
//위의 코드와 동일하기 동작하지만 더 간결함
scala&amp;gt; trait Factory[A] { def create: A }
defined trait Factory

scala&amp;gt; trait UserFactory extends Factory[User] { def create = new User(&amp;quot;&amp;quot;) }
defined trait UserFactory&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;경계가 있는 타입 (bounded type)&lt;/h2&gt;
&lt;h3&gt;상한 경계&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;&amp;lt;식별자&amp;gt; &amp;lt;: &amp;lt;상한 경계 타입&amp;gt;&lt;/code&gt; &lt;/p&gt;
&lt;p&gt;해당 타입 또는 서브타입으로 제한&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;scala&amp;gt; class BaseUser (val name: String)
defined class BaseUser

scala&amp;gt; class Admin(name: String, val level: String) extends BaseUser(name)
defined class Admin

scala&amp;gt; class Customer(name: String) extends BaseUser(name)
defined class Customer

scala&amp;gt; class PreferredCustomer(name: String) extends Customer(name)
defined class PreferredCustomer&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;check: [A &amp;lt;: BaseUser](u: A)Unit

scala&amp;gt; check(new Customer(&amp;quot;Fred&amp;quot;))

scala&amp;gt; check(new Admin(&amp;quot;&amp;quot;, &amp;quot;strict&amp;quot;))
Fail!&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;하한 경계&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;&amp;lt;식별자&amp;gt; &amp;gt;: &amp;lt;하한 경계 타입&amp;gt;&lt;/code&gt; &lt;/p&gt;
&lt;p&gt;해당 타입 또는 그 타입이 확장한 타입으로 제한&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;scala&amp;gt; def recruit[A &amp;gt;: Customer](u: Customer): A = u match {
     |   case p: PreferredCustomer =&amp;gt; new PreferredCustomer(u.name)
     |   case u: Customer =&amp;gt; new Customer(u.name)
     | }
recruit: [A &amp;gt;: Customer](u: Customer)A

scala&amp;gt; val customer = recruit(new Customer(&amp;quot;Fred&amp;quot;))
customer: Customer = Customer@52d7889a

scala&amp;gt; val preferred = recruit(new PreferredCustomer(&amp;quot;George&amp;quot;))
preferred: Customer = PreferredCustomer@32dd05af/&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;scala&amp;gt; abstract class Card {
     |   type UserType &amp;lt;: BaseUser
     |   def verify(u: UserType): Boolean
     | }
defined class Card

scala&amp;gt; class SecurityCard extends Card {
     |   type UserType = Admin
     |   def verify(u: Admin) = true
     | }
defined class SecurityCard

scala&amp;gt; val v1 = new SecurityCard().verify(new Admin(&amp;quot;George&amp;quot;, &amp;quot;high&amp;quot;))
v1: Boolean = true&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;타입 가변성 (type variance)&lt;/h2&gt;
&lt;p&gt;타입 가변성을 사용하면 타입 매개변수를 더 유연하게 사용할 수 있다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;scala&amp;gt; class Car { override def toString = &amp;quot;Car()&amp;quot; }
defined class Car

scala&amp;gt; class Volvo extends Car { override def toString = &amp;quot;Volvo()&amp;quot; }
defined class Volvo&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;// Volvo 인스턴스가 타입 Car의 값으로 할당될 수 있음
scala&amp;gt; val c: Car = new Volvo()
c: Car = Volvo()

// Item[Volvo] 인스턴스는 Item[Car]의 값으로 할당될 수 없다.
scala&amp;gt; val c: Item[Car] = new Item[Volvo](new Volvo)
                          ^
       error: type mismatch;
        found   : Item[Volvo]
        required: Item[Car]
       Note: Volvo &amp;lt;: Car, but class Item is invariant in type A.
       You may wish to define A as +A instead. (SLS 4.5)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;타입 매개변수 앞에 &lt;code&gt;+&lt;/code&gt;를 붙이면 공변(covariant)하게 만들 수 있다.&lt;/p&gt;
&lt;p&gt;공변성은 타입 매개변수가 그 타입이 확장한 타입으로 변할 수 있는 성질&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;scala&amp;gt; case class Item[+A](a: A) { def get: A = a }
defined class Item

scala&amp;gt; val c: Item[Car] = new Item[Volvo](new Volvo)
c: Item[Car] = Item(Volvo())

scala&amp;gt; val auto = c.get
auto: Car = Volvo()&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;타입 매개변수 앞에 &lt;code&gt;-&lt;/code&gt;를 붙이면 반공변(contravariant)하게 만들 수 있다.&lt;/p&gt;
&lt;p&gt;반공변성은 타입 매개변수가 서브타입으로 변할 수 있는 성질&lt;/p&gt;
&lt;p&gt;메소드 매개변수에 사용된 타입 매개변수는 반공변성을 가진다. &lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;scala&amp;gt; class Check[+A] { def check(a: A) = {} }
                                   ^
       error: covariant type A occurs in contravariant position in type A of value a

scala&amp;gt; class Check[-A] { def check(a: A) = {} }
defined class Check&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;scala&amp;gt; class Car; class Volvo extends Car; class VolvoWagon extends Volvo
defined class Car
defined class Volvo
defined class VolvoWagon

scala&amp;gt; class Item[+A](a: A) { def get: A = a }
defined class Item

scala&amp;gt; class Check[-A] { def check(a: A) = {} }
defined class Check

scala&amp;gt; def item(v: Item[Volvo]) { val c: Car = v.get }
item: (v: Item[Volvo])Unit

scala&amp;gt; def check(v: Check[Volvo]) { v.check(new VolvoWagon()) }
check: (v: Check[Volvo])Unit&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;모든 타입 매개변수를 불변의 상태로 유지하는 것이 더 안전하다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;패키지 객체 (package object)&lt;/h2&gt;
&lt;p&gt;패키지 객체는 해당 패키지에 위치한 파일 package.scala에 정의되어 네임스페이스에 자동 임포드된다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;// 위치: com/oreilly/package.scala
package object oreilly {
  type Mappy[A, B] = collection.mutable.HashMap[A, B]
}&lt;/code&gt;&lt;/pre&gt;</description>
      <category>IT Book Study/러닝 스칼라</category>
      <category>abstract type</category>
      <category>bounded type</category>
      <category>implicit class</category>
      <category>implicit parameter</category>
      <category>Scala</category>
      <category>tuple</category>
      <category>variance</category>
      <category>가변성</category>
      <category>러닝스칼라</category>
      <author>jmkim87</author>
      <guid isPermaLink="true">https://kid1412.tistory.com/245</guid>
      <comments>https://kid1412.tistory.com/245#entry245comment</comments>
      <pubDate>Mon, 28 Sep 2020 23:43:59 +0900</pubDate>
    </item>
    <item>
      <title>러닝스칼라 9장 - 객체, 케이스 클래스, 트레이트</title>
      <link>https://kid1412.tistory.com/244</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/crcG1A/btqJSbb1mUb/qDcNxi9JjrjuffkTYDUKWk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/crcG1A/btqJSbb1mUb/qDcNxi9JjrjuffkTYDUKWk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/crcG1A/btqJSbb1mUb/qDcNxi9JjrjuffkTYDUKWk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcrcG1A%2FbtqJSbb1mUb%2FqDcNxi9JjrjuffkTYDUKWk%2Fimg.jpg&quot; width=&quot;100%&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;h2&gt;객체(object)&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;하나 이상의 인스턴스를 가질 수 없는 형태의 클래스, 싱글턴(Singletom)&lt;/li&gt;
&lt;li&gt;클래스 이름으로 객체에 접근&lt;/li&gt;
&lt;li&gt;JVM에서 최초로 접근될 때 인스턴스화&lt;/li&gt;
&lt;li&gt;자바에서는 클래스의 특정 필드와 메소드를 정적(static)으로 지정.(인스턴스 기반 필드/메소드와 섞여있음) 스칼라는 전역 필드/메소드와 인스턴스 기반 필드/메소드를 분리&lt;/li&gt;
&lt;li&gt;class 대신 object 키워드 사용, 클래스 매개변수를 취할 수 없음&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;object &amp;lt;identifier&amp;gt; [extends &amp;lt;identifier&amp;gt;] [{ fields, methods, and classes }]&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;scala&amp;gt; object Hello { println(&amp;quot;in Hello&amp;quot;); def hi = &amp;quot;hi&amp;quot; }
defined object Hello

scala&amp;gt; println(Hello.hi)
in Hello
hi

scala&amp;gt; println(Hello.hi)
hi&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;순수 함수와 외부 입출력을 이용하는 함수&lt;/strong&gt;에 어울림, 해당 함수들은 클래스의 필드와 거의 상관이 없기 때문에 클래스 메소드로 적합하지 않음&lt;/p&gt;
&lt;h3&gt;Apply 메소드와 동반 객체&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;동반 객체&lt;/strong&gt; : 클래스와 동일한 이름을 가지고, 동일 파일 내에 정의되는 객체. 서로의 private/protected 멤버에 접근 가능.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;객체의 apply 메소드&lt;/strong&gt; : 객체의 이름으로 호출하는 메소드, 팩토리(factory)패턴을 위해 주로 사용. // List(1, 2, 3), Option(1)&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;scala&amp;gt; :paste
// Entering paste mode (ctrl-D to finish)

class Multiplier(val x: Int) { def product(y: Int) = x * y }

object Multiplier { def apply(x: Int) = new Multiplier(x) }

// Exiting paste mode, now interpreting.

defined class Multiplier
defined object Multiplier

scala&amp;gt; val tripler = Multiplier(3)
tripler: Multiplier = Multiplier@5af28b27

scala&amp;gt; val result = tripler.product(13)
result: Int = 39&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;scala&amp;gt; :paste
// Entering paste mode (ctrl-D to finish)

object DBConnection {
  private val db_url = &amp;quot;jdbc://localhost&amp;quot;
  private val db_user = &amp;quot;franken&amp;quot;
  private val db_pass = &amp;quot;berry&amp;quot;

  def apply() = new DBConnection
}

class DBConnection {
  private val props = Map(
    &amp;quot;url&amp;quot; -&amp;gt; DBConnection.db_url,
    &amp;quot;user&amp;quot; -&amp;gt; DBConnection.db_user,
    &amp;quot;pass&amp;quot; -&amp;gt; DBConnection.db_pass
  )
  println(s&amp;quot;Created new connection for &amp;quot; + props(&amp;quot;url&amp;quot;))
}

// Exiting paste mode, now interpreting.

defined object DBConnection
defined class DBConnection

scala&amp;gt; val conn = DBConnection()
Created new connection for jdbc://localhost
conn: DBConnection = DBConnection@4d27d9d&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;객체를 가지는 명령줄 어플리케이션&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;자바의 public static void main ~, 프로그램 진입점&lt;/li&gt;
&lt;li&gt;파라미터로 문자열(Array[String]로 유일한 파라미터 받고 Unit을 반환하는)을 가진 main 메소드를 포함한 객체 필요. 컴파일 후 해당 객체 파일에 대하여 scala 명령어로 실행.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;$ cat &amp;gt; Cat.scala
object Cat {
  def main(args: Array[String]) {
    for (arg &amp;lt;- args) {
      println( io.Source.fromFile(arg).mkString )
    }
  }
}

$ scalac Cat.scala

$ scala Cat Date.scala
object Date {
  def main(args: Array[String]) {
    println(new java.util.Date)
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;App trait를 상속해서 만들 수 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;object HelloWorld {
   def main(args: Array[String]) {
     println(&amp;quot;Hello, world!&amp;quot;)
   }
 }

object HelloWorld extends App {
  println(&amp;quot;Hello, world!&amp;quot;)
}&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;케이스 클래스(case class)&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;자동으로 생성되는 메소드를 포함하는 클래스, 또한 자동으로 동반객체가 생성되는데 해당 객체도 자동으로 생성된 메소드를 가짐&lt;/li&gt;
&lt;li&gt;자동으로 생성되는 모든 메소드들은 케이스 클래스의 매개변수 목록을 기반으로 생성&lt;/li&gt;
&lt;/ul&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Name&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;apply&lt;/td&gt;
&lt;td&gt;객체&lt;/td&gt;
&lt;td&gt;케이스 클래스를 인스턴스화하는 팩토리 메소드&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;unapply&lt;/td&gt;
&lt;td&gt;객체&lt;/td&gt;
&lt;td&gt;인스턴스를 그 인스턴스의 필드들의 튜플로 추출하여 패턴 매칭에 케이스 클래스 인스턴스를 사용하 수 있도록 함&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;copy&lt;/td&gt;
&lt;td&gt;클래스&lt;/td&gt;
&lt;td&gt;요청받은 변경사항이 반영된 인스턴스의 사본을 반환함. 매개변수느 현재 필드 값으로 설정된 기본값을 갖는 클래스의 필드임&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;equals&lt;/td&gt;
&lt;td&gt;클래스&lt;/td&gt;
&lt;td&gt;다른 인스턴스의 모든 필드가 이 인스턴스의 모든 필드와 일치하면 true 반환. 연산자 ==로도 호출 가능&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;hashCode&lt;/td&gt;
&lt;td&gt;클래스&lt;/td&gt;
&lt;td&gt;인스턴스의 필드들의 해시 코드를 반환함. 해시 기반의 컬렉션에 유용함&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;toString&lt;/td&gt;
&lt;td&gt;클래스&lt;/td&gt;
&lt;td&gt;클래스명과 필드들을 String으로 전환함&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;ul&gt;
&lt;li&gt;클래스 정의 앞에 case 키워드 추가&lt;/li&gt;
&lt;li&gt;클래스 매개변수를 값 필드로 자동으로 전환하여 사용(val 직접 붙일 필요 없음)&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;**case class &amp;lt;identifier&amp;gt; ([var] &amp;lt;identifier&amp;gt;: &amp;lt;type&amp;gt;[, ... ])
                        [extends &amp;lt;identifier&amp;gt;(&amp;lt;input parameters&amp;gt;)]
                        [{ fields and methods }]**&lt;/code&gt;&lt;/pre&gt;&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;scala&amp;gt; case class Character(name: String, isThief: Boolean)
defined class Character

scala&amp;gt; val h = Character(&amp;quot;Hadrian&amp;quot;, true)                    
h: Character = Character(Hadrian,true)                       

scala&amp;gt; val r = h.copy(name = &amp;quot;Royce&amp;quot;)                        
r: Character = Character(Royce,true)

scala&amp;gt; h == r                                                
res0: Boolean = false

scala&amp;gt; h match {
     |   case Character(x, true) =&amp;gt; s&amp;quot;$x is a thief&amp;quot;         
     |   case Character(x, false) =&amp;gt; s&amp;quot;$x is not a thief&amp;quot;
     | }
res1: String = Hadrian is a thief&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;데이터 전송 객체&lt;/strong&gt;를 표현할 때 사용. (필요한 메소드들 자동으로 생성해줘서 편의 제공)&lt;/p&gt;
&lt;h2&gt;트레이트(trait)&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;다중 상속을 가능케 하는 클래스 유형 중 하나, 여러 개의 trait를 확장(mixin)할 수 있음&lt;/li&gt;
&lt;li&gt;인스턴스화 할 수 없고, 클래스 매개변수를 취할 수 없음 (타입 매개변수 사용은 가능)&lt;/li&gt;
&lt;li&gt;trait 키워드를 사용해서 정의함, with 키워드를 사용하여 두 개 이상의 trait을 확장할 수 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;trait &amp;lt;identifier&amp;gt; [extends &amp;lt;identifier&amp;gt;] [{ fields, methods, and classes }]&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;scala&amp;gt; trait HtmlUtils {
     |   def removeMarkup(input: String) = {
     |     input
     |       .replaceAll(&amp;quot;&amp;quot;&amp;quot;&amp;lt;/?\w[^&amp;gt;]*&amp;gt;&amp;quot;&amp;quot;&amp;quot;,&amp;quot;&amp;quot;)
     |       .replaceAll(&amp;quot;&amp;lt;.*&amp;gt;&amp;quot;,&amp;quot;&amp;quot;)
     |   }
     | }
defined trait HtmlUtils

scala&amp;gt; trait SafeStringUtils {
     |
     |   // Returns a trimmed version of the string wrapped in an Option,
     |   // or None if the trimmed string is empty.
     |   def trimToNone(s: String): Option[String] = {
     |     Option(s) map(_.trim) filterNot(_.isEmpty)
     |   }
     | }
defined trait SafeStringUtils

scala&amp;gt; class Page(val s: String) extends SafeStringUtils with HtmlUtils {
     |   def asPlainText: String = {
     |     trimToNone(s) map removeMarkup getOrElse &amp;quot;n/a&amp;quot;
     |   }
     | }
defined class Page

scala&amp;gt; new Page(&amp;quot;&amp;lt;html&amp;gt;&amp;lt;body&amp;gt;&amp;lt;h1&amp;gt;Introduction&amp;lt;/h1&amp;gt;&amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;&amp;quot;).asPlainText
res3: String = Introduction

scala&amp;gt; new Page(&amp;quot;  &amp;quot;).asPlainText
res4: String = n/a

scala&amp;gt; new Page(null).asPlainText
res5: String = n/a&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;여러 개의 trait을 확장한 경우, 상속될 클래스와 트레이트의 수평적인 리스트를 받아서 한 클래스가 다른 클래스를 확장하는 수직적 체인으로 재구성(선형화)&lt;/li&gt;
&lt;li&gt;오른쪽에서 왼쪽 순으로 가장 가까운 부모부터 높은 부모로 배치된다. (class D extends A with B with C =&amp;gt; class D extends C extends B extends A)&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;scala&amp;gt; trait Base { override def toString = &amp;quot;Base&amp;quot; }
defined trait Base

scala&amp;gt; class A extends Base { override def toString = &amp;quot;A-&amp;gt;&amp;quot; + super.toString }
defined class A

scala&amp;gt; trait B extends Base { override def toString = &amp;quot;B-&amp;gt;&amp;quot; + super.toString }
defined trait B

scala&amp;gt; trait C extends Base { override def toString = &amp;quot;C-&amp;gt;&amp;quot; + super.toString }
defined trait C

scala&amp;gt; class D extends A with B with C { override def toString = &amp;quot;D-&amp;gt;&amp;quot; +
  super.toString }
defined class D

scala&amp;gt; new D()
res50: D = D-&amp;gt;C-&amp;gt;B-&amp;gt;A-&amp;gt;Base&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;부모 클래스의 행위를 재정의, 부가적 기능을 추가 (부모 클래스와 기능을 추가한 trait)&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;scala&amp;gt; class RGBColor(val color: Int) { def hex = f&amp;quot;$color%06X&amp;quot; }
defined class RGBColor

scala&amp;gt; val green = new RGBColor(255 &amp;lt;&amp;lt; 8).hex
green: String = 00FF00

scala&amp;gt; trait Opaque extends RGBColor { override def hex = s&amp;quot;${super.hex}FF&amp;quot; }
defined trait Opaque

scala&amp;gt; trait Sheer extends RGBColor { override def hex = s&amp;quot;${super.hex}33&amp;quot; }
defined trait Sheer

scala&amp;gt; class Paint(color: Int) extends RGBColor(color) with Opaque
defined class Paint

scala&amp;gt; class Overlay(color: Int) extends RGBColor(color) with Sheer
defined class Overlay

scala&amp;gt; val red = new Paint(128 &amp;lt;&amp;lt; 16).hex
red: String = 800000FF

scala&amp;gt; val blue = new Overlay(192).hex
blue: String = 0000C033&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;셀프 타입&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;트레이트가 클래스에 추가될 때 특정 타입 또는 그 서브타입과 함께 사용되어야 함을 강제&lt;/li&gt;
&lt;li&gt;트레이트 정의의 중괄호를 연 다음 식별자, 요청받은 타입, =&amp;gt;를 포함한다&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;scala&amp;gt; class A { def hi = &amp;quot;hi&amp;quot; }
defined class A

scala&amp;gt; trait B { self: A =&amp;gt;                                             
     |   override def toString = &amp;quot;B: &amp;quot; + hi
     | }
defined trait B

scala&amp;gt; class C extends B
&amp;lt;console&amp;gt;:9: error: illegal inheritance;                                
 self-type C does not conform to B&amp;#39;s selftype B with A
       class C extends B
                       ^

scala&amp;gt; class C extends A with B                                         
defined class C

scala&amp;gt; new C()
res1: C = B: hi&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;입력 매개변수가 필요한 클래스에 트레이트로 기능을 추가하는데 사용, 트레이트는 입력 매개변수를 지정하지 않고도 클래스를 확장할 수 있음&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;scala&amp;gt; class TestSuite(suiteName: String) { def start() {} }      
defined class TestSuite

scala&amp;gt; trait RandomSeeded { self: TestSuite =&amp;gt;                        
     |   def randomStart() {
     |     util.Random.setSeed(System.currentTimeMillis)
     |     self.start()
     |   }
     | }
defined trait RandomSeeded

scala&amp;gt; class IdSpec extends TestSuite(&amp;quot;ID Tests&amp;quot;) with RandomSeeded {     
     |   def testId() { println(util.Random.nextInt != 1) }
     |   override def start() { testId() }
     |
     |   println(&amp;quot;Starting...&amp;quot;)
     |   randomStart()
     | }
defined class IdSpec&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;트레이트를 이용하여 인스턴스화&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;클래스가 인스턴스화될 때 클래스에 트레이트를 추가, 클래스가 의존하는 기능이 클래스 정의 시점에 추가되지 않다가 클래스가 인스턴스화 될 때 주입됨(종속성 주입)&lt;/li&gt;
&lt;li&gt;트레이트가 클래스를 확장하는 식, 왼쪽부터 오른쪽으로의 선형화&lt;/li&gt;
&lt;li&gt;하나 이상의 트레이트를 with 키워드를 사용해서 클래스에 추가(extends는 사용 불가, 트레이트를 확장하는 것이 아닌 트레이트의 의한 확장)&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;scala&amp;gt; class User(val name: String) {
     |   def suffix = &amp;quot;&amp;quot;
     |   override def toString = s&amp;quot;$name$suffix&amp;quot;
     | }
defined class User

scala&amp;gt; trait Attorney { self: User =&amp;gt; override def suffix = &amp;quot;, esq.&amp;quot; }
defined trait Attorney

scala&amp;gt; trait Wizard { self: User =&amp;gt; override def suffix = &amp;quot;, Wizard&amp;quot; }
defined trait Wizard

scala&amp;gt; trait Reverser { override def toString = super.toString.reverse }
defined trait Reverser

scala&amp;gt; val h = new User(&amp;quot;Harry P&amp;quot;) with Wizard
h: User with Wizard = Harry P, Wizard

scala&amp;gt; val g = new User(&amp;quot;Ginny W&amp;quot;) with Attorney
g: User with Attorney = Ginny W, esq.

scala&amp;gt; val l = new User(&amp;quot;Luna L&amp;quot;) with Wizard with Reverser
l: User with Wizard with Reverser = draziW ,L anuL&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;trait 사용처(Programming in Scala)&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;간결한 인터페이스를 확장해 풍부한 인터페이스 만들기&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;trait에 간결한 인터페이스 역할을 하는 추상 메소드를 정의하고 풍부한 인터페이스 역할을 할 여러 메소드를 추상메소드를 이용하는 방식으로 구현(메소드 구현 넣을 수 있음)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;해당 trait을 mix in한 클래스에서 추상 메소드로 지정한 간결한 인터페이스만 구현해주면 풍부한 인터페이스까지 포함한 클래스 완성&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;trait Rectangular {
 def topLeft :Point
 def bottomRight :Point  // 2개의 추상 메소드만 mix in한 클래스에서 구현해주면 아래 모든 메소드 이용 가능

 def left = topLeft.x
 def right = bottomRight.x
 def width = right - left
 // 여러 기하 관련 메소드..
}
// Rectangle, Component 클래스 등에서 Rectangular trait를 mix in해 직사각형 객체를 편리하게 쓸 수 있게 만들 수 있다(기하학적 속성을 조회하는 모든 메소드를 갖출 수 있음)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;// Orderd trait : 하나의 비교 연산자만 작성하면 모든 비교 연산자 구현을 대신할 수 있음
class Rational(n :Int, d :Int) extends Ordered[Rational] {  // 타입 파라미터 명시해야
 // ...

 // 두 객체가 동일하면 0, 자신이 인자보다 작으면 음수, 크면 양수 반환
 // 아래 메소드 구현만 채워주면, 해당 클래스는 &amp;lt;, &amp;gt;, &amp;lt;=, &amp;gt;= 연산 모두 제공할 수 있게 된다
 def compare(that: Rational) = (this.number * that.denom) - (that.number * this.denom)

 // equals는 정의하지 않음. Ordered를 상속하더라도 직접 정의해야 함.
}&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;쌓을 수 있는 변경 정의&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;super 호출을 동적으로 바인딩한다. (클래스에서는 super 호출을 정적으로 바인딩한다) trait을 이용해 원하는 기능을 스택처럼 쌓아 올릴 수 있다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;abstract class IntQueue {
 def get() :Int
 def put(x: Int)
}

// (슈퍼클래스를 지정 함으로써) IntQueue를 상속한 클래스에만 mix in할 수 있음
trait Doubling extends IntQueue {
 abstract override def put(x : Int) = super.put(2 * x)  // 큐에 있는 모든 정수를 두 배 만들기
}
// 컴파일러에게 의도적으로 super의 메소드를 호출했다는 사실을 알리기 위해 abstract override로 표시해야 함
// 즉 어떤 trait에 abstract override메소드가 있다면, 그 trait는 반드시 해당 메소드에 대한 구체적 구현을 제공하는 클래스에 mix in 해야함

trait Incrementing extends IntQueue {
 abstract override def put(x : Int) = super.put(x + 1) // 큐에 모든 정수에 1을 더한다
}

trait Filtering extends IntQueue {
 abstract override def put(x : Int) = if (x &amp;gt;= 0) super.put(x) // 큐에 있는 음수를 걸러낸다
}

import scala.collection.mutable.ArrayBuffer
class BasicIntQueue extends IntQueue {
 private val buf = new ArrayBuffer[Int]
 def get() = buf.remove(0)
 def put(x:Int) = buf += x
 override def toString() = buf.toString
}

val queue = new BasicIntQueue with Incrementing with Filtering
queue.put(-1); queue.put(0); queue.put(1)  // -&amp;gt; 1, 2

val queue2 = new BasicIntQueue with Filtering with Incrementing
queue2.put(-1); queue2.put(0); queue2.put(1)  // -&amp;gt; 0, 1, 2&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;</description>
      <category>IT Book Study/러닝 스칼라</category>
      <category>case class</category>
      <category>object</category>
      <category>Scala</category>
      <category>trait</category>
      <category>러닝스칼라</category>
      <author>jmkim87</author>
      <guid isPermaLink="true">https://kid1412.tistory.com/244</guid>
      <comments>https://kid1412.tistory.com/244#entry244comment</comments>
      <pubDate>Mon, 28 Sep 2020 23:41:47 +0900</pubDate>
    </item>
    <item>
      <title>러닝스칼라 8장 - 클래스</title>
      <link>https://kid1412.tistory.com/243</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bScqrp/btqJG9HylfL/MxwhDbKAk93khDg9xrUCdK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bScqrp/btqJG9HylfL/MxwhDbKAk93khDg9xrUCdK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bScqrp/btqJG9HylfL/MxwhDbKAk93khDg9xrUCdK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbScqrp%2FbtqJG9HylfL%2FMxwhDbKAk93khDg9xrUCdK%2Fimg.jpg&quot; width=&quot;100%&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;h2&gt;클래스란?&lt;/h2&gt;
&lt;p&gt;데이터 구조와 함수의 조합으로, 객체지향 언어의 핵심 구성 요소&lt;/p&gt;
&lt;h3&gt;특징&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;상속(inheritance)&lt;/code&gt;&lt;/strong&gt; : 다른 클래스로 확장할 수 있어서 서브 클래스와 슈퍼 클래스의 계층 구조 생성 가능&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;다형성(polymorphism)&lt;/code&gt;&lt;/strong&gt; : 서브 클래스가 부모 클래스를 대신하여 작업하는 것이 가능&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;캡슐화(encapsulation)&lt;/code&gt;&lt;/strong&gt; : 클래스의 외관을 관리하는 프라이버시 제어를 제공&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;class User
val u = new User
val u1 = new User
val isAnyRef = u.isInstanceOf[AnyRef]

/*
    defined class User
    u: User = User@4c478184
    u1: User = User@2e6ef924
    isAnyRef: Boolean = true
*/&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;AnyRef는 classes의 부모 타입입니다.&lt;/p&gt;
&lt;h3&gt;클래스 기본&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;**// 1번 예제**
class User {
  val name: String = &amp;quot;jmkim&amp;quot;
  def greet: String = s&amp;quot;Hello from $name&amp;quot;
  override def toString = s&amp;quot;User($name)&amp;quot;
}

val u = new User
println(u.greet)
/*
    defined class User
    u: User = User(jmkim)
    Hello from jmkim
*/&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;toString을 override 함으로써 기존에 User@4c478184 처럼 보여지는 것을&lt;br&gt;u: User = User(jmkim)처럼 변경 됩니다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;**// 2번 예제**
class User(val name: String) {
  def greet: String = s&amp;quot;Hello from $name&amp;quot;
  override def toString = s&amp;quot;User($name)&amp;quot;
}

val u = new User(&amp;quot;jmkim&amp;quot;)
println(u.greet)
/*
    defined class User
    u: User = User(jmkim)
    Hello from jmkim
*/&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;1번 예제와 다르게 name을 매개 변수로 받으면서 바로 클래스 필드로 사용하는 방법입니다.&lt;/p&gt;
&lt;p&gt;다음은 리스트를 사용하여 다양한 것을 해봅니다. &lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;val users = List(new User(&amp;quot;jam&amp;quot;), new User(&amp;quot;karl&amp;quot;), new User(&amp;quot;jason&amp;quot;), new User(&amp;quot;sophie&amp;quot;), new User(&amp;quot;kai&amp;quot;), new User(&amp;quot;lucas&amp;quot;), new User(&amp;quot;jeff&amp;quot;))
val usersSize = users.size
val userNameSize = users map (_.name.length)
val sorted = users sortBy (_.name)
val jason = users find (_.name contains &amp;quot;jason&amp;quot;)
val greet = jason map (_.greet) getOrElse &amp;quot;Hi&amp;quot;

val test = users find (_.name contains &amp;quot;test&amp;quot;)
val greet1 = test map (_.greet) getOrElse &amp;quot;Hi&amp;quot;

/*
    users: List[User] = List(User(jam), User(karl), User(jason), User(sophie), User(kai), User(lucas), User(jeff))
    usersSize: Int = 7
    userNameSize: List[Int] = List(3, 4, 5, 6, 3, 5, 4)
    sorted: List[User] = List(User(jam), User(jason), User(jeff), User(kai), User(karl), User(lucas), User(sophie))
    jason: Option[User] = Some(User(jason))
    greet: String = Hello from jason
    test: Option[User] = None
    greet1: String = Hi
*/&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;클래스 상속, 다형성&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;상속&lt;/code&gt;&lt;/strong&gt; : 서브 클래스가 부모 클래스로부터 필드와 메소드를 extends 키워드로 확장된 것이며, override로&lt;br&gt;상속받은 메소드를 재정의 할 수 있습니다. &lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;class A {
  def hi = &amp;quot;Hello from A&amp;quot;
  override def toString = getClass.getName
}

class B extends A
class C extends B {
  override def hi = &amp;quot;hi C -&amp;gt; &amp;quot; + super.hi
}

val hiA = new A().hi
val hiB = new B().hi
val hiC = new C().hi
/*
    defined class A
    defined class B
    defined class C
    hiA: String = Hello from A
    hiB: String = Hello from A
    hiC: String = hi C -&amp;gt; Hello from A
*/&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;다형성&lt;/code&gt;&lt;/strong&gt; : 서브 클래스는 자신의 부모 클래스를 확장하므로 부모의 필드와 메소드를 100% 지원하지만 그 역은 성립하지 않을 수 도 있습니다. &lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;class A {
  def hi = &amp;quot;Hello from A&amp;quot;
  override def toString = getClass.getName
}

class B extends A
class C extends B {
  override def hi = &amp;quot;hi C -&amp;gt; &amp;quot; + super.hi
}

val a: A = new A
val a: A = new B
val b: B = new B
val b: B = new A

/*
    defined class A
    defined class B
    defined class C
    a: A = A
    a: A = B
    b: B = B
    Error:(14, 12) type mismatch;
        found   : A
        required: B
        val b: B = new A
*/&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;클래스 정의하기&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;입력 매개변수로 클래스 정의하기&lt;/strong&gt; &lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;class Car(val make: String, var reserved: Boolean) {
  def reserve(r: Boolean):Unit = {reserved = r}
}

val t = new Car(&amp;quot;Tesla&amp;quot;, false)
t.reserve(true)
println(s&amp;quot;My ${t.make} is now reserved? ${t.reserved}&amp;quot;)
/*
    defined class Car
    t: Car = Car@2c4c333a
    My Tesla is now reserved? true
*/

val t2 = new Car(reserved = false, make = &amp;quot;Toyota&amp;quot;)
println(t2)
/*
    t2: Car = Car@20a0dd40
    My Toyota is now reserved? false
*/

class Lotus(val color: String, reserved: Boolean) extends Car(&amp;quot;Lotus&amp;quot;, reserved)
val l = new Lotus(&amp;quot;sliver&amp;quot;, false)
println(s&amp;quot;Requested a ${l.color} ${l.make}&amp;quot;)
/*
    defined class Lotus
    l: Lotus = Lotus@6067b0f0
    Requested a sliver Lotus
*/&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;입력 매개변수와 기본값으로 클래스 정의하기&lt;/strong&gt; &lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;class Car(val make: String, var reserved : Boolean = true, val year: Int = 2005) {
  override def toString = s&amp;quot;$year $make, reserved = $reserved&amp;quot;
}

val a = new Car(&amp;quot;Acura&amp;quot;)
val l = new Car(&amp;quot;Lexus&amp;quot;, year = 2010)
val p = new Car(reserved = false, make = &amp;quot;Porsche&amp;quot;)
/*
    a: Car = 2005 Acura, reserved = true
    l: Car = 2010 Lexus, reserved = true
    p: Car = 2005 Porsche, reserved = false
*/&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;그 외의 클래스 유형&lt;/h2&gt;
&lt;h3&gt;추상 클래스&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;추상 클래스&lt;/code&gt;&lt;/strong&gt;는 다른 클래스들에 의해 확장되도록 설계되었으나 인스턴스를 생성하지 않는 클래스&lt;br&gt;서브클래스들이 필요로 하는 핵심적인 필드와 메소드를 실제 구현물을 제공하지 않으면서 정의하는 데에 사용 &lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;abstract class Car {
  val year: Int
  val automatic: Boolean = true
  def color: String
}

class Mini(val year: Int, val color: String) extends Car

val redMini: Car = new Mini(2005, &amp;quot;Red&amp;quot;)
println(s&amp;quot;Got a ${redMini.color} Mini&amp;quot;)
/*
    defined class Car
    defined class Mini
    redMini: Car = Mini@19fce221
    Got a Red Mini
*/&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;익명 클래스&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;익명클래스&lt;/code&gt;&lt;/strong&gt;는 서브 클래스가 한번만 필요한 상황일 때 코드를 단순화 해주는 데에 도움을 줍니다.&lt;br&gt;추상 클래스를 따로 extends로 상속 받는 class를 만들지 않고 notification.register에 있는 것처럼&lt;br&gt;new Listener로 정의하여 익명 클래스를 만들어 넣습니다. &lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;abstract class Listener {def trigger}
class Listening {
  var listener: Listener = null
  def register(l: Listener) {listener = l}
  def sendNotification() {listener.trigger}
}

val notification = new Listening()

notification.register(new Listener {
  def trigger {println(s&amp;quot;Trigger at ${new java.util.Date}&amp;quot;)}
})

notification.sendNotification()
/*
    defined class Listener
    defined class Listening
    notification: Listening = Listening@1db58f45
    Trigger at Sat Jun 20 14:17:07 KST 2020
*/&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;그외의 필드와 메소드 유형&lt;/h2&gt;
&lt;h3&gt;중복 정의된 메소드&lt;/h3&gt;
&lt;p&gt;동일한 이름과 반환값을 갖지만, 다른 입력 매개변수를 갖는 둘 또는 그 이상의 메소드를 가질 수 있습니다. &lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;class Printer(msg: String) {
  def print(s:String):Unit = println(s&amp;quot;$msg: $s&amp;quot;)
  def print(l:Seq[String]):Unit = print(l.mkString(&amp;quot;, &amp;quot;))
}

new Printer(&amp;quot;Today&amp;#39;s Report&amp;quot;).print(&amp;quot;Foggy&amp;quot;::&amp;quot;Rainy&amp;quot;:: &amp;quot;Hot&amp;quot; :: Nil)
/*
    defined class Printer
    Today&amp;#39;s Report: Foggy, Rainy, Hot
*/&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;apply 메소드&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;apply&lt;/code&gt;&lt;/strong&gt; 메소드는 기본 메소드 또는 인젝터 메소드로 불리며 메소드 이름 없이 호출 될 수 있습니다. &lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;class Multiplier(factor: Int) {
  def apply(input: Int) = input * factor
}

val tripleMe = new Multiplier(3)
val tripled = tripleMe.apply(10)
val tripled2 = tripleMe(10)
/*
    defined class Multiplier
    tripleMe: Multiplier = Multiplier@43e42b0b
    tripled: Int = 30
    tripled2: Int = 30
*/&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;지연값&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;지연값&lt;/code&gt;&lt;/strong&gt;은 자신이 처음 인스턴스화될 때에만 생성되며 &lt;strong&gt;&lt;code&gt;val 키워드 앞에 lazy&lt;/code&gt;&lt;/strong&gt;를 씁니다.&lt;br&gt;클래스 수명 내에 실행 시간과 성능에 민감한 연산이 한 번만 실행 될 수 있음을 보장하며,&lt;br&gt;보통 파일 기반의 속성, 데이터 베이스 커넥션 열기, 그 외 정말 필요한 경우 단 한번만 초기화 되어야 하는&lt;br&gt;불변의 데이터와 같은 정보를 저장하는데 사용합니다. &lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;class RandomPoint {
  val x = {println(&amp;quot;creating x&amp;quot;); util.Random.nextInt}
  lazy val y = {println(&amp;quot;now y&amp;quot;); util.Random.nextInt}
}

val p = new RandomPoint()
println(s&amp;quot;Location is ${p.x}, ${p.y}&amp;quot;)
println(s&amp;quot;Location is ${p.x}, ${p.y}&amp;quot;)
/*
    defined class RandomPoint
    creating x
    p: RandomPoint = RandomPoint@6ecd22fd
    now y
    Location is 389314740, -1884004327
    Location is 389314740, -1884004327
*/&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;패키징&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;패키지&lt;/code&gt;&lt;/strong&gt;는 스칼라 코드를 점으로 구분된 경로를 사용하여 디렉토리별로 정리할 수 있게 해줍니다. &lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;mkdir -p src/com/oreilly
cat &amp;gt; src/com/oreilly/Config.scala
# class Config(val baseUrl:String = &amp;quot;http://localhost&amp;quot;)
scalac src/com/oreilly/Config.scala
ls com/oreilly/Config.class
# com/oreilly/Config.class&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;패키징된 클래스에 접근하기&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;import java.util.Date
val d = new Date

import scala.collection.mutable._
// import scala.collection.mutable.{ArrayBuffer =&amp;gt; ArrBuf, Queue}

val b = new ArrayBuffer[String]

b += &amp;quot;Hello&amp;quot;

val q = new Queue[Int]

q.enqueue(3,4,5)

val pop = q.dequeue
println(q)

/*
    import scala.collection.mutable._
    b: scala.collection.mutable.ArrayBuffer[String] = ArrayBuffer()
    res0: b.type = ArrayBuffer(Hello)
    q: scala.collection.mutable.Queue[Int] = Queue()
    res1: q.type = Queue(3, 4, 5)
    pop: Int = 3
    Queue(4, 5)
*/&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;패키징 구문&lt;/h3&gt;
&lt;p&gt;아래와 같이 package를 사용하여 만들 수 있습니다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;package com {
  package oreilly {
    class Config(val baseUrl: String = &amp;quot;http://localhost&amp;quot;)
  }
}

val url = new com.oreilly.Config().baseUrl&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;프라이버시 제어&lt;/h3&gt;
&lt;p&gt;기본은 pubilc이며 상황에 따라서 protected, private를 사용하여 제어를 할 수 있습니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;protected&lt;/code&gt;&lt;/strong&gt; : 정의한 클래스와 서브 클래스의 코드에서만 접근이 가능합니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;private&lt;/code&gt;&lt;/strong&gt; : 정의한 클래스에서만 접근이 가능합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;class User(private var password: String) {
  def update(p: String): Unit = {
    println(&amp;quot;Modifying the password!&amp;quot;)
    password = p
  }
  def validate(p: String) = p == password
} 

val u = new User(&amp;quot;1234&amp;quot;)
val isValid = u.validate(&amp;quot;4567&amp;quot;)

u.update(&amp;quot;4567&amp;quot;)
val isValid = u.validate(&amp;quot;4567&amp;quot;)
/*
    defined class User

    u: User = User@2030ce87
    isValid: Boolean = false

    Modifying the password!
    isValid: Boolean = true
*/&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;프라이버시 접근 변경자&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;package com.oreilly {
  // []로 접근 블록을 지정해 줄 수 있습니다. 
  private[oreilly] class Config {
    val url = &amp;quot;http://localhsot&amp;quot;
  }

  class Authentication {
    private[this] val password = &amp;quot;jason&amp;quot;
    def validate = password.nonEmpty
  }

  class Test {
    println(s&amp;quot;url = ${new Config().url}&amp;quot;)
  }
}

object Example extends App {
  val valid = new com.oreilly.Authentication().validate
  println(valid)

  new com.oreilly.Test
/*
    true
    url = http://localhsot
*/
}&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;종단 클래스와 봉인 클래스&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;종단 클래스(final class)&lt;/code&gt;&lt;/strong&gt;는 더이상 상속을 받지 못하게 만들며, 변수에 final을 쓸 경우 override가 방지 됩니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/DxEq0/btqJG9U6kPV/IsityU2LcQFz1dj34cEkZk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/DxEq0/btqJG9U6kPV/IsityU2LcQFz1dj34cEkZk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/DxEq0/btqJG9U6kPV/IsityU2LcQFz1dj34cEkZk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FDxEq0%2FbtqJG9U6kPV%2FIsityU2LcQFz1dj34cEkZk%2Fimg.png&quot; width=&quot;100%&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ndDuq/btqJPCBEf3K/9D6tm3nh85oFwrRVjuhwMk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ndDuq/btqJPCBEf3K/9D6tm3nh85oFwrRVjuhwMk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ndDuq/btqJPCBEf3K/9D6tm3nh85oFwrRVjuhwMk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FndDuq%2FbtqJPCBEf3K%2F9D6tm3nh85oFwrRVjuhwMk%2Fimg.png&quot; width=&quot;100%&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&gt;&lt;strong&gt;&lt;code&gt;봉인 클래스(sealed class)&lt;/code&gt;&lt;/strong&gt;는 클래스의 서브클래스가 부모 클래스와 동일한 파일에 위치하도록 제한 합니다.&lt;br&gt;또한, 클래스의 계층 구조에 대해 안전하게 가정하는 코드를 작성 할 수 있습니다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;// 같은 파일 안에 class를 상속 할 경우
sealed class Fruit(color: String) {
  def printColor = println(color)
}

class Apple extends Fruit(&amp;quot;Red&amp;quot;) {
  def print = &amp;quot;Apple&amp;quot;
}

// 다른 파일에서 상속 할 경우
class Banana extends Fruit(&amp;quot;Yellow&amp;quot;) {

}
// illegal inheritance from sealed class Fruit&lt;/code&gt;&lt;/pre&gt;</description>
      <category>IT Book Study/러닝 스칼라</category>
      <category>Abstract</category>
      <category>apply</category>
      <category>Class</category>
      <category>final class</category>
      <category>Scala</category>
      <category>seal class</category>
      <category>다형성</category>
      <category>러닝스칼라</category>
      <category>익명 클래스</category>
      <category>클래스</category>
      <author>jmkim87</author>
      <guid isPermaLink="true">https://kid1412.tistory.com/243</guid>
      <comments>https://kid1412.tistory.com/243#entry243comment</comments>
      <pubDate>Mon, 28 Sep 2020 23:38:50 +0900</pubDate>
    </item>
    <item>
      <title>러닝스칼라 7장 - 그 외의 컬렉션</title>
      <link>https://kid1412.tistory.com/242</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/d2nx9S/btqJP6icIfi/KwhXmgKQe6kjYsyQYGmgC0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/d2nx9S/btqJP6icIfi/KwhXmgKQe6kjYsyQYGmgC0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/d2nx9S/btqJP6icIfi/KwhXmgKQe6kjYsyQYGmgC0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fd2nx9S%2FbtqJP6icIfi%2FKwhXmgKQe6kjYsyQYGmgC0%2Fimg.jpg&quot; width=&quot;100%&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&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;h2&gt;불변의 컬렉션&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;List, Set, Map 은 불변의 컬렉션&lt;/li&gt;
&lt;li&gt;코드의 안정성을 높이고 버그를 방지하기 위해 데이터와 데이터 구조는 변경되거나 자신의 상태를 바꿀 수 없다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;가변 컬렉션 생성하기&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;collection.mutable은 자동으로 추가되지 않아서 반드시 포함해야한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;stylus&quot;&gt;&lt;code&gt;//불변
collection.immutable.Buffer
collection.immutable.Set
collection.immutable.Map

//가변
collection.mutable.Buffer
collection.mutable.Set
collection.mutable.Map&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;가변 컬렉션을 이용하면 추가나 변경을 할 수 있다.&lt;/li&gt;
&lt;li&gt;toList , toSet, toMap 메소드를 이용해서 가변 컬렉션을 불변의 컬랙션으로 만들 수 있다.&lt;/li&gt;
&lt;li&gt;toBuffer 메소드를 이용해서 불변의 컬렉션을 가변적인 컬렉션으로 변경할 수 있다.&lt;/li&gt;
&lt;li&gt;버퍼의 단점이 너무 광범위하다는 것인데 이것을 빌더(builder)로 해&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;컬렉션 빌더 사용하기&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Builder는 Buffer를 단순화한 형태로, 할당된 컬렉션 타입을 생성하고 추가연산만 지원&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;stylus&quot;&gt;&lt;code&gt;scala&amp;gt; val b = Set.newBuilder[Char]
b = scala.collection.mutable.SetBuilder@3789ad3d

scala&amp;gt; b += 'h'
scala.collection.mutable.SetBuilder@3789ad3d

scala&amp;gt; b ++= List('e', 'l', 'l', 'o')
scala.collection.mutable.SetBuilder@3789ad3d

scala&amp;gt; val helloSet = b.result
helloSet: scala.collection.immutable.Set[Char] = Set(h, e, l, o)&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;불변의 컬렉션을 전환하기 위해 단지 가변적인 컬렉션을 반복적으로 생성한다면 Builder&lt;/li&gt;
&lt;li&gt;빌더는 자신의 타입에 대응하는 불변의 타입이 무엇인지 알고 있음&lt;/li&gt;
&lt;li&gt;빌더의 장점?&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;배열&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Array는 고정된 크기를 가지며, 내용을 변경할 수 있으며, 인덱스를 가지고 있다.&lt;/li&gt;
&lt;li&gt;자바 배열은 toString() 메소드를 재정의 하지 않기 때문에 타입 매개변수와 참조를 출력, 스칼라는 재정의&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;processing&quot;&gt;&lt;code&gt;scala&amp;gt; val colors = Array(&quot;red&quot; ,&quot;green&quot;, &quot;blue&quot;)

scala&amp;gt; colors(0) = &quot;purple&quot;
Array[String] = Array(purple, green, blue)

scala&amp;gt; println(&quot;vert purple : &quot; + colors)
vert purple : [Ljava.lang.String;@6f76b33e

val files = new java.io.File(&quot;.&quot;).listFiles
Array(./.jupyter, ./Untitled.ipynb, ./.ipynb_checkpoints, ./Untitled1.ipynb, ./Untitled2.ipynb)

val scala = files map (_.getName) filter(_ endsWith &quot;ipynb&quot;)
Array(Untitled.ipynb, Untitled1.ipynb, Untitled2.ipynb)&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;JVM 코드를 위해 필요한 경우가 아니라면 이 타입을 사용하는 것은 권하지 않는다 왜?&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Seq와 시퀀스&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Seq는 오든 시퀀스의 루트 타입으로 List , Vector도 포함&lt;/li&gt;
&lt;li&gt;Seq는 인스턴스화 할 수 없지만 List를 생성하는 방법으로 Seq를 호출 할 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;lisp&quot;&gt;&lt;code&gt;scala&amp;gt; val inks = Seq('C','M','Y','K')
inks = List(C, M, Y, K)&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;Vector : 색인된 접근을 위해 Array에 의해 지원받는 리스트&lt;/li&gt;
&lt;li&gt;List : n번쨰 항목에 접근하려면 헤드부터 탐색&lt;/li&gt;
&lt;li&gt;String : Char 구성 요소를 가지는 시쿼스&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;스트림&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Stream 타입은 하나 또는 그 이상의 시작 요소들과 재귀함수로 생성되는 지연(lazy) 컬랙션&lt;/li&gt;
&lt;li&gt;스트림의 구성 요소들은 나중에 추출될 떄를 대비하여 캐시에 저장되어 각 요소가 한번만 생성됨을 보장&lt;/li&gt;
&lt;li&gt;Stream.Empty로 종료될 수 있고 무한히 커질수 있다.&lt;/li&gt;
&lt;li&gt;List 와 마찬가지로 헤드와 테일로 구성된 재귀적인 데이터 구조&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;zephir&quot;&gt;&lt;code&gt;scala&amp;gt; def inc(i: Int) : Stream[Int] = Stream.cons(i,inc(i+1))
scala&amp;gt; def inc(head: Int): Stream[Int] = head #:: inc(head+1)
inc: (i : Int)Stream[Int]

scala&amp;gt; val s = inc(1)
s: Stream[Int] = Stream(1,?)

scala&amp;gt; val l = s.take(5).toList
List(1,2,3,4,5)

scala&amp;gt; s
Stream(1,2,3,4,5,?)

scala&amp;gt; def to(head:Char, end:Char):Stream[Char] = (head &amp;gt; end) match {
    case true =&amp;gt; Stream.empty
    case false =&amp;gt; head #:: to((head+1).toChar , end)
}
to: (head: Char, end: Char)Stream[Char]

scala&amp;gt; val hexChars = to('A','F').take(20).toList
hexChars = List(A, B, C, D, E, F)&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;모나딕&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Iterable 연산 같은 변형 연산을 지원하지만 하나 이상의 요소는 포함할 수 없다.&lt;/li&gt;
&lt;li&gt;잠재적 값을 나타내며 추가 연산을 연결하거나 값을 추출하는 안전한 연산 제&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Option 컬렉션&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;크기가 1이 넘지 않는 컬렉션으로 단일값의존재 또는 부재를 나타냄&lt;/li&gt;
&lt;li&gt;널(null) 값의 안전한 대체제, NullPointException을 일으킬 가능성이 즐어듬&lt;/li&gt;
&lt;li&gt;타입-매개변수화된 컬랙션인 Some 과 빈 컬렉션인 None&lt;/li&gt;
&lt;li&gt;함수 결과를 처리하는데 type-safe 방식을 제공&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;scala&amp;gt; def divid(amt: Double, divisor:Double): Option[Double] = {
           if(divisor == 0) None
           else Option(amt/divisor)
}
divid: (amt: Double, divisor: Double)Option[Double]

scala&amp;gt; val legit = divid(5,2)
legit = Some(2.5)

scala&amp;gt; val illegit = divid(3,0)
illegit = None&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;headOption 과 find 연산&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;scala&amp;gt; val odds = List(1,3,5)

scala&amp;gt; val events = odds filter (_ % 2 ==0)
events = List()

scala&amp;gt; val firstEven = events.headOption
firstEven = None

scala&amp;gt; val words = List(&quot;risible&quot;, &quot;scavenger&quot;, &quot;gist&quot;)

scala&amp;gt; val uppercase = words find (w =&amp;gt; w == w.toUpperCase)
Option[String] = None

scala&amp;gt; val lowercase = words find ( w =&amp;gt; w == w.toLowerCase)
Option[String] = Some(risible)&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Option으로부터 값 추출하기&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;get() 메소드도 있지만 안전하지 않다, None에 get 을 한다면 no such element 에러가 발생하기 때문이다.&lt;/li&gt;
&lt;li&gt;누란된 갑슬 처리하는 대체값이 있는 fold나 getorElse를 사용하자&lt;/li&gt;
&lt;/ul&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Name&lt;/th&gt;
&lt;th&gt;Example&lt;/th&gt;
&lt;th&gt;설명&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;fold&lt;/td&gt;
&lt;td&gt;nextOption.fold(-1)(x =&amp;gt; x)&lt;/td&gt;
&lt;td&gt;Some인 경우 주어진 함수로부터 추출한 값을 None인 경우 시작값을 반환함, 그외 다른 fold나 reduce도 마찬가지&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;getOrElse&lt;/td&gt;
&lt;td&gt;nextOption getOrElse 5&lt;/td&gt;
&lt;td&gt;Some의 값을 반환하거나 아니면 이름 매개변수의 결과를 반환&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;orElse&lt;/td&gt;
&lt;td&gt;nextOption orElse nextOption&lt;/td&gt;
&lt;td&gt;실제로 값을 추출하지는 않지만 None 인 경우 값을 채우려함&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;매치 표현식&lt;/td&gt;
&lt;td&gt;nextOption match { case Some(x) =&amp;gt; x ; case None =&amp;gt; -1&lt;/td&gt;
&lt;td&gt;값이 있는 경우 매치표현식으로 그 값을 처리함&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;ul&gt;
&lt;li&gt;null 을 쓰는 것보다 더 안전한 방법, 그 이유는 모든 널 포인트 에러를 방지 못하기 때문&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Try 컬렉션&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;util.Try 컬렉션은 에러 처리를 컬랙션 관리로 바꿔 놓는다.&lt;/li&gt;
&lt;li&gt;스칼라에서는 예외(Exception)을 발생시켜 에러를 일으킬 수 있다.&lt;/li&gt;
&lt;li&gt;예외를 발생시키기 위해서는 Exception 키워드와 함께 throw를 사용&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;scala&amp;gt; def loopAndFail (end:Int , failAt: Int ) : Int = {
        for ( i &amp;lt;- 1 to end ) {
           println(s&quot;$i) &quot; )
           if (i == failAt ) throw new Exception(&quot;Too many iterations&quot;)
        }
        end
      }&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;catch 보단 util.Try 만 사용하는 것을 추천, 그 이유는 에러를 처리하기에 더 안전하고 완전한 모나딕 접근법&lt;/li&gt;
&lt;li&gt;util.Try 는 Success 와 Failure 을 가지고 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;scala&amp;gt; val t1 = util.Try( loadAndFail(2,3))
1)
2)
Success(2)

scala&amp;gt; val t2 = util.Try ( loadAndFail(4,2))
1)
2)
Failure(java.lang.Exception: Too many iterations)&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;Try 에러 처리 메소드&lt;/li&gt;
&lt;/ul&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Name&lt;/th&gt;
&lt;th&gt;Example&lt;/th&gt;
&lt;th&gt;설명&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;flatMap&lt;/td&gt;
&lt;td&gt;nextError flatMap { _ =&amp;gt; nextError }&lt;/td&gt;
&lt;td&gt;Success인 경우 util.Try를 반환하는 함수를 호출함으로써 현재의 반환값을 새로운 내장된 반환값(또는 예외에 매핀함, 우리의 &amp;lsquo;nextError&amp;rsquo; 데모함수는 입력값을 취하지 않기 때문에 우리는 현재 Success로 부터 사용하지 않는 입력값을 나타내는 언더스코어를 사용&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;foreach&lt;/td&gt;
&lt;td&gt;nextError foreach(x =&amp;gt; println(&amp;ldquo;success!&amp;rdquo; + x))&lt;/td&gt;
&lt;td&gt;Success인 경우 주어진 함수를 한 번 실행하고, Failure 일 때는 실행하지 않&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;getOrElse&lt;/td&gt;
&lt;td&gt;nextError getOrElse 0&lt;/td&gt;
&lt;td&gt;Success에 내장된 값을 반환하거나,Failure인 경우 이름에 의한 매개변수의 결과를 반환함&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;orElse&lt;/td&gt;
&lt;td&gt;nextError orElse nextError&lt;/td&gt;
&lt;td&gt;flatMap의 반대되는 메소드, Failure인 경우 그 역시Try를 반환하는 함수를 호출함.orElse로 어쩌면 Failure를 Success로 전환 할 수 있음&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;toOption&lt;/td&gt;
&lt;td&gt;nextError.toOption&lt;/td&gt;
&lt;td&gt;Try를 Option으로 전환하여 Success는 Some으로 Failure는 None이 됨. 내장된 Exception을 잃게 된다는 단점이 있음&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;map&lt;/td&gt;
&lt;td&gt;nextError map (_ * 2)&lt;/td&gt;
&lt;td&gt;Success인 경우 새로운 값에 내장된 값을 매핑하는 함수를 호출함&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;매치표현식&lt;/td&gt;
&lt;td&gt;nextError match { case util.Success(x) =&amp;gt; x; case util.Failure(error) =&amp;gt; -1 }&lt;/td&gt;
&lt;td&gt;Success를 (&amp;rsquo;x&amp;rsquo;에 저장된) 반환값으로 또는 Failure를 (&amp;rsquo;error&amp;rsquo;에 저장된) 예외로 처리하기 위해 매치 표현식을 사용함.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;아무일도 하지않음&lt;/td&gt;
&lt;td&gt;nextError&lt;/td&gt;
&lt;td&gt;가장 쉬운 에러 처리 방식으로, 내가 개인적으로 선호하는 방식임. 이 방식으로 단순히 예외가 잡히거나,현재의 애플리케이션을 종료시킬 때까지 호출 스택을 타고 전파되도록 그대로 둠. 이 방식은 민감한 경우에 사용하면 문제가 크겠짐나, 발새한 예왼느 결코 무시되지 않음&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;scala&amp;gt; val input = &quot; 123 &quot;
input = &quot; 123 &quot;

scala&amp;gt; val result = util.Try(input.toInt) orElse util.Try(input.trim.toInt)
result = Success(123)

scala&amp;gt; result foreach { r =&amp;gt; println(s&quot;Parsed '$input' to $r!&quot; )}
Parsed ' 123 ' to 123!

scala&amp;gt; val x = result match {
           case util.Success(x) =&amp;gt; Some(x)
           case  util.Failure(ex) =&amp;gt; {
               println(s&quot;$input&quot;)
               None
           }
       }

x = Some(123)&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;퓨처 컬렉션&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;백그라운드 작업을 개시하는 concurrent.Future&lt;/li&gt;
&lt;li&gt;Option과 Try 와는 달리 즉시 사용하지 못할수 있다.&lt;/li&gt;
&lt;li&gt;퓨처를 함수로 호출하면 현행 스레드와는 별개의 스레드에서 그 함수를 실행시킨다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;fortran&quot;&gt;&lt;code&gt;scala&amp;gt; import concurrent.ExecutionConscala 3.Implicits.global
scala&amp;gt; val f = concurrent.Future{println(&quot;hi&quot;)}
Message: &amp;lt;console&amp;gt;:25: error: Cannot find an implicit ExecutionConscala 3.

scala&amp;gt;  val f = concurrent.Future{Thread.sleep(5000);println(&quot;hi&quot;)}
scala&amp;gt; println(&quot;waiting&quot;)
waiting
hi&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;퓨처의 작업이 완료될때 실행할 콜백 함수를 설정 가능&lt;/li&gt;
&lt;li&gt;백그라운드 작업이 끝날때까지 main 스레드를 차단하고 기다리는 기능&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;비동기식 퓨처 연산&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Name&lt;/th&gt;
&lt;th&gt;Example&lt;/th&gt;
&lt;th&gt;설명&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;failbackTo&lt;/td&gt;
&lt;td&gt;nextFtr(1) failbackTo nextFtr(2)&lt;/td&gt;
&lt;td&gt;두번째 퓨쳐를 첫번째 연결하고 새로운 종합적인 퓨처를 반환함. 첫 번째 퓨처가 성공적이지 않다면 두 번째 퓨처가 호출&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;flatMap&lt;/td&gt;
&lt;td&gt;nextFtr(1).flatMap(int =&amp;gt; nextFtr())&lt;/td&gt;
&lt;td&gt;두번째 퓨처를 첫 번째에 연결하고 새로운 종합적인 퓨처를 반환함. 첫 번째가 성공적이라면 그 반환 값이 두 번째를 호출하는데 사용됨&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;map&lt;/td&gt;
&lt;td&gt;nextFtr(1) map (_ * 2)&lt;/td&gt;
&lt;td&gt;주어진 함수를 퓨처에 연결하고 새로운 종합적인 퓨처를 반환함. 퓨처가 성공적이라면 그 반환 값이 해당 함수를 호출할 때 사용됨&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;onComplete&lt;/td&gt;
&lt;td&gt;nextFtr() onComplete { _ getOrElse 0 }&lt;/td&gt;
&lt;td&gt;퓨처의 작업이 완료된 후 주어진 함수가 값 또는 예외를 포함한 Try를 이용하여 호출됨&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;onFailure&lt;/td&gt;
&lt;td&gt;nextFtr() onFailure { case _ =&amp;gt; &amp;ldquo;Error!&amp;rdquo; }&lt;/td&gt;
&lt;td&gt;퓨처의 작업이 예외를 발생시키면 주어진 함수는 그 예외를 가지고 호출됨&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;onSuccess&lt;/td&gt;
&lt;td&gt;nextFtr() onSuccess { case _ =&amp;gt; s&amp;ldquo;Got $x&amp;rdquo; }&lt;/td&gt;
&lt;td&gt;퓨처의 작업이 성공적으로 완료되었으면 주어진 함수는 그 반환값을 가지고 호출&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Future.sequence&lt;/td&gt;
&lt;td&gt;concurrent.Future sequence List(nextFtre(1),nextFtr(5))&lt;/td&gt;
&lt;td&gt;주어진 시퀀스에서 퓨처를 벙행으로 실행하여 새로운 퓨처를 반환함. 시퀀스 내의 모든 퓨처가 성공하면 이들의 반환값의 리스트가 반환됨. 그렇지 않으면 그 시퀀스내에서 처음으로 발생한 예외가 반환됨&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;pre class=&quot;julia&quot;&gt;&lt;code&gt;import concurrent.ExecutionConscala 3.Implicits.global
import concurrent.Future
import scala.io.Source
def cityTemp(name:String): Double = {
    val url = &quot;http://api.openweathermap.org/data/2.5/weather&quot;
    val cityUrl = s&quot;$url?&amp;amp;APPID=72bf27b20bf867de6236aca3a257e0d1&amp;amp;q=$name&quot;
    val json = io.Source.fromURL(cityUrl).mkString.trim
    val pattern = &quot;&quot;&quot;.*&quot;temp&quot;:([\d.]+).*&quot;&quot;&quot;.r
    val pattern(temp) = json
    temp.toDouble
}

val cityTemps = Future sequence Seq(
    Future(cityTemp(&quot;Seoul&quot;)), Future(cityTemp(&quot;Jeju&quot;))
)

cityTemps onSuccess {
  case Seq(x,y) if (x&amp;gt;y) =&amp;gt; println(s&quot;Seoul is warmer: $x K&quot;)
  case Seq(x,y) if (y&amp;gt;x) =&amp;gt; println(s&quot;Jeju is warmer: $x K&quot;)
}&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;동기식 퓨처 처리&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;백그라운드 스레드가 완료되기를 기다리는 동안 메인 스레드를 차단&lt;/li&gt;
&lt;li&gt;concurrent.Await.result() 사용&lt;/li&gt;
&lt;li&gt;주어진 시간보다 빠르게 처리되면 결과가 반환되지만 아니라면 java.util.concurrent.TimeoutException 발생&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;scala&amp;gt; def nextFtr( i: Int = 0 ) = Future {
    def rand(x:Int) = util.Random.nextInt(x)
    Thread.sleep(rand(5000))
    if(rand(3)&amp;gt;0) (i +1) else throw new Exception
}
nextFtr: (i: Int)scala.concurrent.Future[Int]

scala&amp;gt; import concurrent.duration._

scala&amp;gt; val amount = concurrent.Await.result(nextFtr(5), maxtime)
amount: Int = 6

scala&amp;gt; val amount = concurrent.Await.result(nextFtr(5), maxtime)
java.lang.Exception&lt;/code&gt;&lt;/pre&gt;</description>
      <category>IT Book Study/러닝 스칼라</category>
      <category>futrue</category>
      <category>Option</category>
      <category>Scala</category>
      <category>seq</category>
      <category>Stream</category>
      <category>try</category>
      <category>그 외의 컬렉션</category>
      <category>러닝 스칼라</category>
      <category>러닝스칼라</category>
      <category>시퀀스</category>
      <author>jmkim87</author>
      <guid isPermaLink="true">https://kid1412.tistory.com/242</guid>
      <comments>https://kid1412.tistory.com/242#entry242comment</comments>
      <pubDate>Mon, 28 Sep 2020 23:35:33 +0900</pubDate>
    </item>
    <item>
      <title>러닝스칼라 6장 - 보편적인 컬렉션</title>
      <link>https://kid1412.tistory.com/241</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/6dvL3/btqJRlMIJZW/CHODQJIaeuZrK2vSQav801/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/6dvL3/btqJRlMIJZW/CHODQJIaeuZrK2vSQav801/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/6dvL3/btqJRlMIJZW/CHODQJIaeuZrK2vSQav801/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F6dvL3%2FbtqJRlMIJZW%2FCHODQJIaeuZrK2vSQav801%2Fimg.jpg&quot; width=&quot;100%&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&gt;&lt;code&gt;컬렉션(collection)&lt;/code&gt; 프레임워크는 배열, 리스트, 맵, 집합, 트리와 같이 주어진 타입을 가지는 하나 또는 그 이상의 값을 수집하는 데이터 구조를 제공한다. 1. 성능이 좋고, 객체지향적, 타입-매개변수화 - 자바 컬렉션 라이브러리 1. jvm이기 때문에 자바 컬렉션을 스칼라에서 활용 가능&lt;/p&gt;
&lt;p&gt;스칼라는 여러 이유로 컬렉션을 재정의함 1. 고차함수 이용 (map, filter, reduce) 1. mutable/immutable 타입의 계층 구조&lt;/p&gt;
&lt;h2&gt;리스트, 집합, 그리고 맵&lt;/h2&gt;
&lt;h3&gt;&lt;code&gt;List 타입&lt;/code&gt;: immutable 단반향 연결 리스트&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;scala&amp;gt; val numbers = List(32, 95, 24, 21, 17)
numbers: List[Int] = List(32, 95, 24, 21, 17)

scala&amp;gt; val colors = List(&amp;quot;red&amp;quot;, &amp;quot;green&amp;quot;, &amp;quot;blue&amp;quot;)
numbers: List[String] = List(red, green, blue)

scala&amp;gt; println(s&amp;quot;I have ${colors.size} colors: $colors&amp;quot;)
I have 3 colors: List(red, greem, blue)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;모든 컬렉션은 &lt;code&gt;size&lt;/code&gt; 메소드롤 통해서 포함된 데이터의 개수를 반환 가능하다.&lt;/p&gt;
&lt;p&gt;컬렉션은 초기화때 사용했던 데이터의 타입을 기억하여 타입-매개변수화 될 수 있다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;scala&amp;gt; val colors = List(&amp;quot;red&amp;quot;, &amp;quot;green&amp;quot;, &amp;quot;blue&amp;quot;)
numbers: List[String] = List(red, green, blue)

scala&amp;gt; colors.head
res0: String = red

scala&amp;gt; colors.tail
res1: List[String] = List(green, blue)

scala&amp;gt; colors(1)
res2: String = green

scala&amp;gt; colors(2)
res2: String = blue&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;head와 tail메소드를 이용하여 리스트의 첫번쨰 요소와 나머지 요소를 반환할 수 있다.&lt;code&gt;&amp;lt;collect&amp;gt;(index)&lt;/code&gt;를 통하여 0번째부터 컬렉션의 인덱스의 요소를 반환할 수 있다.&lt;/p&gt;
&lt;p&gt;for 루프를 이용하여 컬렉션안의 요소를 순회 할 수 있다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;scala&amp;gt; val numbers = List(32, 95, 24, 21, 17)
numbers: List[Int] = List(32, 95, 24, 21, 17)

scala&amp;gt; val total=0; for(i &amp;lt;- numbers) {total += i}
total: Int = 189&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;고차함수 이용&lt;/h3&gt;
&lt;p&gt;스칼라의 컬렉션은 반복하고(iterate), 매핑하고(map,) 축소하기(reduce, fold)위하여 고차함수를 이용&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;scala&amp;gt; val colors = List(&amp;quot;red&amp;quot;, &amp;quot;green&amp;quot;, &amp;quot;blue&amp;quot;)
numbers: List[String] = List(red, green, blue)

scala&amp;gt; colors.foreach( (c: String) =&amp;gt; println(c) )
red
green
blue

scala&amp;gt; val sizes = colors.map( (c: String) =&amp;gt; c.size )
List[Int] = List(3, 5, 4)

scala&amp;gt; val numbers = List(32, 95, 24, 21, 17)
numbers: List[Int] = List(32, 95, 24, 21, 17)

scala&amp;gt; val total = numbers.reduce( (a: Int, b:Int) =&amp;gt; a + b )
total: Int = 189&lt;/code&gt;&lt;/pre&gt;
&lt;ol&gt;
&lt;li&gt;foreach는 프로시져를 취하고, 해당 프로시져에 리스트의 요소를 주압&lt;/li&gt;
&lt;li&gt;map은 리스트의 요소를 다른 값이나 타입으로 전환하는 함수를 취함&lt;/li&gt;
&lt;li&gt;reduce는 리스트의 ㅇㅛ소를 단일 항목으로 결합하는 함수를 취함&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;&lt;code&gt;Set 타입&lt;/code&gt;: immutable, 순서 없음, List와 동일연산 지원&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;scala&amp;gt; val unique = Set(10, 20, 30, 20, 20, 10)
unique: scala.collection.immutable.Set[Int] = Set(10, 20, 30)

scala&amp;gt; val sum = unique.reduce( (a: String, b: Int) =&amp;gt; a + b )
sum: Int = 60&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;&lt;code&gt;Map 타입&lt;/code&gt;: immutable, key-value, 해시맵, 딕셔너리, 연관배열등으로 알려짐&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;key는 유일키로 value와 연결된다.&lt;/li&gt;
&lt;li&gt;Map을 생성 할때 kv쌍을 튜플로 기술하면 된다.&lt;/li&gt;
&lt;li&gt;키와 값의 관계는 -&amp;gt; 연산자로 정의된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;scala&amp;gt; val colorMap = Map(&amp;quot;red&amp;quot; -&amp;gt; 0xFF0000, &amp;quot;green&amp;quot; -&amp;gt; OxFF00, &amp;quot;blue&amp;quot; -&amp;gt; 0xFF)
    colorMap: scala.collection.immutable.Map[String, Int] = Map(red -&amp;gt; 16711680, green -&amp;gt; 65280, blue -&amp;gt; 255)
}

scala&amp;gt; val redRGB = colorMap(&amp;quot;red&amp;quot;)
redRGB: Int = 16711680

scala&amp;gt; val hasWhite = colorMap.contains(&amp;quot;white&amp;quot;)
hasWhite: Boolean = false

scala&amp;gt; for (pairs &amp;lt;- colorMap) { println(pairs) }
(red, 16711680)
(green, 65280)
(blue, 255)&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;리스트의 종류&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;일반적인 리스트 - &lt;code&gt;List(1,2,3)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;중첩된 리스트 - &lt;code&gt;List(List(1,2), List(3), List(4,5))&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;tuple 리스트 - &lt;code&gt;List((&amp;#39;A&amp;#39;,1), (&amp;#39;B&amp;#39;, 2))&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;등 등 일관성 있는 매개변수 추론이 되는 요소의 리스트르 생성가능&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;code&gt;isEmpty&lt;/code&gt; 메서드를 이용하여 리스트의 값 소유여부를 측정 가능하다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;scala&amp;gt; val primes = List(2, 3, 5, 7, 11, 13)
primes: List[Int] = List(2, 3, 5, 7, 11, 13)

scala&amp;gt; var i = primes
i: List[Int] = List(2, 3, 5, 7, 11, 13)

scala&amp;gt; while(! i.isEmpty) { print(i.head + &amp;quot;, &amp;quot;); i = i.tail}
2, 3, 7, 11, 13&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;리스트의 마지막을 검출하기 위해 isEmpty를 사용할 수 있지만 다른 방법으로 Nil인스턴스를 활용할 수 있다.&lt;br&gt;모든 리스트는 그 종점으로 Nil으로 종료된다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;scala&amp;gt; val primes = List(2, 3, 5, 7, 11, 13)
primes: List[Int] = List(2, 3, 5, 7, 11, 13)

scala&amp;gt; var i = primes
i: List[Int] = List(2, 3, 5, 7, 11, 13)

scala&amp;gt; while(i != Nil) { print(i.head + &amp;quot;, &amp;quot;); i = i.tail}
2, 3, 7&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Nil은 List[Nothing]의 싱글턴 인스턴스, Nothing은 모든 스칼라 리스트에 호환되기 때문에 종점으로 안전히 사용가능하다.&lt;br&gt;새로운 빈 리스트를 생성하면 새로 생긴 인스턴스 대신 Nil을 반ㄹ환한다.&lt;br&gt;Nil은 immutable 데이터 구조기때문에 근본적으로 빈 리스트 인스턴스와 차이가 없다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;scala&amp;gt; val l = List[Int] = List()
l: List[Int] = List()

scala&amp;gt; l == Nil
res0: Boolean = true&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;생성 연산자&lt;/h3&gt;
&lt;p&gt;Nil의 속성을 이용하여 생성 연산자를 이용한 리스트를 생성 할 수 있다.&lt;br&gt;오른쪽-결합형(right-associative)인 :: 연산자를 이용하여 리스트를 생성 가능하다.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;오른쪽-결합형(right-associative) 표기법&lt;/code&gt; - 스칼라에서 연산자가 :로 끝나면 오른쪽 결합형으로 그 연산자의 오른쪽의 객체에서 호출 된다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;scala&amp;gt; val first = Nil.::(1)
first: List[Int] = List(1)

scala&amp;gt; first.tail == Nil
res3: Boolean = true&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;리스트 산술 연산&lt;/h2&gt;
&lt;p&gt;산술은 추가하고, 제거하고, 나누고, 결합하고, 구성 요소를 변경하는 등의 작업을 의미한다.&lt;br&gt;immutable형이기 때문에 실제로는 변경 사항을 반영한 새로운 리스트를 반환한다.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Name&lt;/th&gt;
&lt;th&gt;Example&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;1 :: 2:: Nil&lt;/td&gt;
&lt;td&gt;리스트에 개별 요소를 덧붙임&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;:::&lt;/td&gt;
&lt;td&gt;List(1 2) ::: List(2, 3)&lt;/td&gt;
&lt;td&gt;이 리스트 앞에 다른 리스트를 추가함&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;++&lt;/td&gt;
&lt;td&gt;List(1, 2) ++ Set(3, 4, 3)&lt;/td&gt;
&lt;td&gt;이 리스트에 다른 컬렉션을 덧붙임&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;==&lt;/td&gt;
&lt;td&gt;List(1, 2) == List(1, 2)&lt;/td&gt;
&lt;td&gt;두 컬렉션의 요소를 비교&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;distinct&lt;/td&gt;
&lt;td&gt;List(3, 5, 4, 3, 4).distinct&lt;/td&gt;
&lt;td&gt;중복 요소가 없는 리스트를 반환&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;drop&lt;/td&gt;
&lt;td&gt;List(1 ,2 , 3 ,4) drop 2&lt;/td&gt;
&lt;td&gt;주어진 n개의 요소를 앞에서 부터 제거&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;filter&lt;/td&gt;
&lt;td&gt;List(23, 8, 14, 21) filter (_ &amp;gt; 18)&lt;/td&gt;
&lt;td&gt;참/거짓 함수를 참으로 만족한 요소를 반환&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;flatten&lt;/td&gt;
&lt;td&gt;List(List(1,2), List(3,4)).flatten&lt;/td&gt;
&lt;td&gt;중첩된 리스트의 요소를 단일 리스트로 전환함&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;partition&lt;/td&gt;
&lt;td&gt;List(1, 2, 3, 4, 5) partition (_ &amp;lt; 3)&lt;/td&gt;
&lt;td&gt;참/거짓 기준으로 리스트를 2개로 나눔&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;reverse&lt;/td&gt;
&lt;td&gt;List(1,2,3).reverse&lt;/td&gt;
&lt;td&gt;요소의 순서가 거꾸로인 리스트 반환&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;slice&lt;/td&gt;
&lt;td&gt;List(2,3,5,7) slice (1, 3)&lt;/td&gt;
&lt;td&gt;첫번째, 두번째-1 사이의 요소의 리스트를 반환&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;sortBy&lt;/td&gt;
&lt;td&gt;List(“apple”, “to”) sortBy (_.size)&lt;/td&gt;
&lt;td&gt;주어진 함수의 값을 이용하여 요소를 정렬함&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;sorted&lt;/td&gt;
&lt;td&gt;List(“apple”, “to”).sorted&lt;/td&gt;
&lt;td&gt;자연값 기준 정렬&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;splitAt&lt;/td&gt;
&lt;td&gt;List(2, 3, 5, 7) splitAt 2&lt;/td&gt;
&lt;td&gt;주어진 인덱스 기준으로 리스트를 2개로 나눔&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;take&lt;/td&gt;
&lt;td&gt;List(2, 3, 5, 7, 11, 13) take 3&lt;/td&gt;
&lt;td&gt;리스트에서 첫번쨰 n개의 요소를 추출&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;zip&lt;/td&gt;
&lt;td&gt;List(1, 2) zip List(“a”, “b”)&lt;/td&gt;
&lt;td&gt;두 리스트의 요소들을 튜플 결합한 리스트를 반한&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;&lt;code&gt;연산자 vs 점 표기법&lt;/code&gt; - 매개변수가 없어 . 표기법이 요구되는 경우를 제외하면 개인의 선택문제이다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;::도 연산자이기 떄문에 순서가 역순이 되나 다음과 같은 수행도 가능하다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;scala&amp;gt; val numbers = 1 :: 2 :: 3 :: Nil
numbers: List[Int] = List(1, 2, 3)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;리스트는 단일 연결리스트로 앞에서 연산하는 것이 이익이다.&lt;br&gt;::, drop, take는 앞에서 부터 연산되지만 간혹 전체 순회가 필요한 동반연산(corollary operation)이 필요할 수 있다.&lt;br&gt;:+(왼쪽 결합형 연산자, 책오타), dropRight, takeRight&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;scala&amp;gt; val appended = List(1, 2, 3, 4) :+ 5
appended: List[Int] = List(1, 2, 3, 4, 5)

scala&amp;gt; val suffix = appended takeRight 3
suffix: List[Int] = List(3, 4, 5)

scala&amp;gt; val middle = suffix dropRight 2
middle: List[Int] = List(3)&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;리스트 매핑&lt;/h2&gt;
&lt;p&gt;Map 메서드는 함수를 취하여 요소에 적용하고, 그 결과를 새로운 리스트에 수집한다.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Name&lt;/th&gt;
&lt;th&gt;Example&lt;/th&gt;
&lt;th&gt;설명&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;collect&lt;/td&gt;
&lt;td&gt;List(0, 1, 0) collect { case =&amp;gt; “ok” }&lt;/td&gt;
&lt;td&gt;각 요소에 case 적용 뒤 적용된 요소를 반환&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;flatMap&lt;/td&gt;
&lt;td&gt;List(“milk,tea”) flatMap (_.split(“,”))&lt;/td&gt;
&lt;td&gt;주어진 함수를 이용하여 요소에 적용한 뒤 flatten함&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;map&lt;/td&gt;
&lt;td&gt;List(“milk,tea”) map (_.toUooerCase)&lt;/td&gt;
&lt;td&gt;주어진 함수를 이용하여 각 요소를 변환함&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h2&gt;리스트 축소&lt;/h2&gt;
&lt;p&gt;리스트를 단일 값으로 축소한다. 스칼라 컬렉션은 수학적 축소 연산과 부울 축소 연산을 지원한다.&lt;br&gt;또한 스칼라는 fold로 알려진 일반적인 고차 연산을 지원하는데, 이를 사용하여 임의의 다른 형태의 리스트 축소 알고리즘을 생성할 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;수학적 축소 연산&lt;/code&gt;&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Name&lt;/th&gt;
&lt;th&gt;Example&lt;/th&gt;
&lt;th&gt;설명&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;max&lt;/td&gt;
&lt;td&gt;List(41, 59, 26).max&lt;/td&gt;
&lt;td&gt;리스트의 최댓값 추출&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;min&lt;/td&gt;
&lt;td&gt;List(10.9, 32.5, 4.23, 5.67).min&lt;/td&gt;
&lt;td&gt;리스트의 최솟값 추출&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;product&lt;/td&gt;
&lt;td&gt;List(5, 6, 7).product&lt;/td&gt;
&lt;td&gt;원소들의 곱을 반환&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;sum&lt;/td&gt;
&lt;td&gt;List(11.3, 23.5, 7.2).sum&lt;/td&gt;
&lt;td&gt;원소들의 합을 반환&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;&lt;code&gt;부울 축소 연산&lt;/code&gt;&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Name&lt;/th&gt;
&lt;th&gt;Example&lt;/th&gt;
&lt;th&gt;설명&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;contains&lt;/td&gt;
&lt;td&gt;List(34, 29, 18) contains 29&lt;/td&gt;
&lt;td&gt;리스트가 해당 요소를 포함하는지 검사&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;endsWith&lt;/td&gt;
&lt;td&gt;List(0, 4, 3) endsWith List(4, 3)&lt;/td&gt;
&lt;td&gt;리스트가 주어진 리스트로 끝나는지 검사&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;exists&lt;/td&gt;
&lt;td&gt;List(24, 17, 32 exists (_ &amp;lt; 18)&lt;/td&gt;
&lt;td&gt;최소 하나의 요소가 주어진 조건 함수를 만족하는지 검사&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;forall&lt;/td&gt;
&lt;td&gt;List(24, 17, 32 forall (_ &amp;lt; 18)&lt;/td&gt;
&lt;td&gt;모든 요소가 주어진 조건 함수를 만족하는지 검사&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;startsWith&lt;/td&gt;
&lt;td&gt;List(0, 4, 3) startsWith List(0)&lt;/td&gt;
&lt;td&gt;리스트가 주어진 리스트로 시작하는지 검사&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h3&gt;커링 활용&lt;/h3&gt;
&lt;p&gt;contains를 직접 구현한다고 가정해보자.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;scala&amp;gt; def contains(x: Int, l: List[Int]): Boolean = {
  | var a: Boolean = false
  | for (i &amp;lt;- l) { if (!a) a = (i == x) }
  | a
}
contains: (x:Int, l: List[Int])Boolean

scala&amp;gt; val included = contains(19, List(46, 19, 92))
included: Boolean = true&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;요소 순회와 조건 함수를 다음과 같이 분리하여 개선 할 수 있다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;scala&amp;gt; def boolReduce(l: List[Int], start: Boolean)(f: (Boolean, Int) =&amp;gt; Boolean): Boolean = {
  | var a = start
  | for (i &amp;lt;- l) a = f(a, i)
  | a
}
boolReduce: (l: List[Int], start: Boolean)(f: (Boolean, Int) =&amp;gt; Boolean)Boolean

scala&amp;gt; val included = boolReduce(List(46, 19, 92), false) { (a, i) =&amp;gt; if (a) a else (i == 19)}
included: Boolean = true&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;같은 방식으로 boolean 함수 뿐만이 아닌 reduce 연산에 일반화 시킬 수 있다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;scala&amp;gt; def reduceOp[A,B](l: List[A], start: B)(f: (B, A) =&amp;gt; B): B = {
  | var a = start
  | for (i &amp;lt;- l) a = f(a, i)
  | a
}
reduceOp: [A, B](l: List[A], start: B)(f: (B, A) =&amp;gt; B)B

scala&amp;gt; val included = reduceOp(List(46, 19, 92), false) { (a, i) =&amp;gt; if (a) a else (i == 19)}
included: Boolean = true

scala&amp;gt; val answer = reduceOp(List(11.3, 23.5, 7.2), 0.0)(_ + _)
answer: Double = 42.0&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;list-folding (fold 함수)&lt;/h3&gt;
&lt;p&gt;스칼라 컬렉션은 이미 다음과 같은 내장 연산을 제공하고 있다. 내장 연산들은 왼쪽에서 오른쪽, 오른쪽에서 왼쪽, 순서와 무관한 버전을 모두 제공할 만큼 유연하다.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Name&lt;/th&gt;
&lt;th&gt;Example&lt;/th&gt;
&lt;th&gt;설명&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;fold&lt;/td&gt;
&lt;td&gt;List(4, 5, 6).fold(0)(_ + _)&lt;/td&gt;
&lt;td&gt;초기값을 기준으로 리스트 축소&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;foldLeft&lt;/td&gt;
&lt;td&gt;List(4, 5, 6).foldLeft(0)(_ + _)&lt;/td&gt;
&lt;td&gt;초기값을 기준으로 왼쪽에서 오른쪽으로 리스트 축소&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;foldRight&lt;/td&gt;
&lt;td&gt;List(4, 5, 6).foldRight(0)(_ + _)&lt;/td&gt;
&lt;td&gt;초기값을 기준으로 오른쪽에서 왼쪽으로 리스트 축소&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;reduce&lt;/td&gt;
&lt;td&gt;List(4, 5, 6).reduce(_ + _)&lt;/td&gt;
&lt;td&gt;페어요소 별 리스트 축소&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;reduceLeft&lt;/td&gt;
&lt;td&gt;List(4, 5, 6).reduceLeft(_ + _)&lt;/td&gt;
&lt;td&gt;첫번째 요소 기준으로 왼쪽에서 오른쪽으로 리스트 축소&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;reduceRight&lt;/td&gt;
&lt;td&gt;List(4, 5, 6).reduceRight(_ + _)&lt;/td&gt;
&lt;td&gt;마지막 요소 기준으로 오른쪽에서 왼쪽으로 리스트 축소&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;scan&lt;/td&gt;
&lt;td&gt;List(4, 5, 6).scan(0)(_ + _)&lt;/td&gt;
&lt;td&gt;초기값 기준으로 축소 함수를 취하여 각각의 누적 리스트를 반환&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;scanLeft&lt;/td&gt;
&lt;td&gt;List(4, 5, 6).scanLeft(0)(_ + _)&lt;/td&gt;
&lt;td&gt;초기값 기준으로 축소 함수를 취하여 왼쪽 부터 오른쪽으로 수행 후 각각의 누적 리스트를 반환&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;scanRight&lt;/td&gt;
&lt;td&gt;List(4, 5, 6).scanRight(0)(_ + _)&lt;/td&gt;
&lt;td&gt;초기값 기준으로 축소 함수를 취하여 오른쪽 부터 왼쪽으로 수행 후 각각의 누적 리스트를 반환&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h2&gt;컬렉션 전환&lt;/h2&gt;
&lt;p&gt;컬렉션들은 서로 다른 타입의 컬렉션으로 전환 될 수 있다.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Name&lt;/th&gt;
&lt;th&gt;Example&lt;/th&gt;
&lt;th&gt;설명&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;mkString&lt;/td&gt;
&lt;td&gt;List(24, 99, 104).mkString(“,”)&lt;/td&gt;
&lt;td&gt;주어진 구분자로 컬렉션을 String으로 전환&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;toBuffer&lt;/td&gt;
&lt;td&gt;List(‘f’, ‘t’).toBuffer&lt;/td&gt;
&lt;td&gt;immutable을 mutable로 전환&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;toList&lt;/td&gt;
&lt;td&gt;Map(“a” -&amp;gt; 1, “b” -&amp;gt; 2).toList&lt;/td&gt;
&lt;td&gt;컬렉션을 List로 전환&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;toMap&lt;/td&gt;
&lt;td&gt;Set(1 -&amp;gt; true, 3 -&amp;gt; true).toMap&lt;/td&gt;
&lt;td&gt;두 요소 튜블로 구성된 컬렉션을 Map으로 전환&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;toSet&lt;/td&gt;
&lt;td&gt;List(2, 5, 3, 2).toSet&lt;/td&gt;
&lt;td&gt;컬렉션을 Set으로 전환&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;toString&lt;/td&gt;
&lt;td&gt;List(2, 5, 5, 3, 2).toString&lt;/td&gt;
&lt;td&gt;컬렉션 타입을 포함하여 콜렉션을 문자열로 전환&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h2&gt;자바와 스칼라 컬렉션 호환성&lt;/h2&gt;
&lt;p&gt;스칼라는 jvm으로 컴파일되고 그 위에서 동작한다.&lt;br&gt;즉 jdk와 상호작용뿐 아니라 어떤 자바 라이브러리도 추가 할 수 있어야한다는 것이 보편적인 요구사항이다.&lt;br&gt;그러나 자바 컬렉션과 스칼라 컬렉션의 타입은 기본적으로 호환 되지 않는다.&lt;/p&gt;
&lt;p&gt;자바와 스칼라 컬렉션 사이의 전환을 하려면 다음 명령어를 추가해야한다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;import collection.JavaConverters._&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;collection.JavaConverters&lt;/code&gt;의 메서드가 추가 되면 자바와 스칼라 컬렉션에 다음 연산을 사용할 수 있다.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Name&lt;/th&gt;
&lt;th&gt;Example&lt;/th&gt;
&lt;th&gt;설명&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;asJava&lt;/td&gt;
&lt;td&gt;List(12, 29).asJava&lt;/td&gt;
&lt;td&gt;스칼라 컬렉션을 대응되는 자바 컬렉션으로 전환&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;asScala&lt;/td&gt;
&lt;td&gt;new java.util.ArrayList(5).asScala&lt;/td&gt;
&lt;td&gt;자바 컬렉션을 대응되는 스칼라 컬렉션으로 전환&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h2&gt;컬렉션으로 패턴 매칭하기&lt;/h2&gt;
&lt;p&gt;이전에 배웠던 단일값 패턴 매칭은 다음과 같다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;scala&amp;gt; val statuses = List(500, 404)
statuses: List[Int] = List(500, 404)

scala&amp;gt; msg = statuses.head match {
  | case x if x &amp;lt; 500 =&amp;gt; &amp;quot;okay&amp;quot;
  | case _ =&amp;gt; &amp;quot;whoah, an error&amp;quot;
}
msg: String = whoah, an error&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;하지만 컬렉션의 값 중 하나의 값밖에 검사할 수 없다. 다음은 개선 버전이다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;scala&amp;gt; msg = statuses match {
  | case x if x contains(500) =&amp;gt; &amp;quot;has error&amp;quot;
  | case _ =&amp;gt; &amp;quot;okay&amp;quot;
}
msg: String = has error&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;이와 다르게 값 바인딩을 통하여 패턴 가드에서 컬렉션의 일부 또는 모든 요소에 값 바인딩이 가능하다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;scala&amp;gt; msg = statuses match {
  | case List(500, x) =&amp;gt; s&amp;quot;Error followed by $x&amp;quot;
  | case List(e, x) =&amp;gt; s&amp;quot;$e was followed by $x&amp;quot;
}
msg: String = Error followed by 404&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;리스트는 head와 tail로 분해 가능하기 떄문에 다음과 같은 매칭도 가능하다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;scala&amp;gt; val head = List(&amp;#39;r&amp;#39;, &amp;#39;g&amp;#39;, &amp;#39;b&amp;#39;) match {
  | case x :: xs =&amp;gt; x
  | case Nil =&amp;gt; &amp;#39; &amp;#39;
}
head: Char = r&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;튜플도 값 바인딩을 이용한 패턴 매칭을 지원한다. 패턴 매칭은 스칼라 표준 컬렉션 라이브러리의 평범한 연산이 아니라 함수형 언어의 핵심적 특징이다.&lt;/p&gt;</description>
      <category>IT Book Study/러닝 스칼라</category>
      <category>asJava</category>
      <category>Collection</category>
      <category>Fold</category>
      <category>List</category>
      <category>Map</category>
      <category>Reduce</category>
      <category>Scala</category>
      <category>러닝 스칼라</category>
      <category>러닝스칼라</category>
      <category>보편적인 컬렉션</category>
      <author>jmkim87</author>
      <guid isPermaLink="true">https://kid1412.tistory.com/241</guid>
      <comments>https://kid1412.tistory.com/241#entry241comment</comments>
      <pubDate>Mon, 28 Sep 2020 23:31:57 +0900</pubDate>
    </item>
    <item>
      <title>러닝스칼라 5장 - 일급 함수</title>
      <link>https://kid1412.tistory.com/240</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bdhNNM/btqJOx8qhMs/hk09KaxQJX4Z1oJ8vpMmck/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bdhNNM/btqJOx8qhMs/hk09KaxQJX4Z1oJ8vpMmck/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bdhNNM/btqJOx8qhMs/hk09KaxQJX4Z1oJ8vpMmck/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbdhNNM%2FbtqJOx8qhMs%2Fhk09KaxQJX4Z1oJ8vpMmck%2Fimg.jpg&quot; width=&quot;100%&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&gt;스칼라는 일급 함수, 선언형 프로그래밍을 지원한다.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;**일급 함수(first-class function)**&lt;/code&gt; : 함수형 프로그래밍에서 함수는 일급(first-class) 객체&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;다른 데이터 타입처럼 리터럴 형태로 생성될 수 있다. &lt;/li&gt;
&lt;li&gt;val, var로 저장될 수 있다. &lt;/li&gt;
&lt;li&gt;다른 함수의 매개변수나 반환값으로 사용될 수 있다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;code&gt;**선언형 프로그래밍(declarative programming)**&lt;/code&gt; : 고차함수(또는 다른 함수를 사용하는 로직)는 단순히 이루어져야 할 작업을 선언하고 그 작업을 직접 수행하지 않음&lt;/p&gt;
&lt;h2&gt;함수 타입과 값&lt;/h2&gt;
&lt;p&gt;함수 타입은 입력 타입과 반환값 타입의 그룹으로 표현된다.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;([&amp;lt;타입&amp;gt;, ...]) =&amp;gt; &amp;lt;타입&amp;gt;&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;def double(x: Int): Int = x * 2
val myDouble: Int =&amp;gt; Int = double
myDouble(5)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;와일드 카드 연산자로 함수를 할당하면 함수 타입을 쓰지 않아도 된다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;val &amp;lt;식별자&amp;gt; = &amp;lt;함수명&amp;gt; _&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;val myDouble = double _&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;고차함수(higher-order function)&lt;/h2&gt;
&lt;p&gt;입력 매개변수나 반환값으로 함수 타입의 값을 가지는 함수&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;// safeStringOp: (s: String, f: String =&amp;gt; String): String
def safeStringOp(s: String, f: String =&amp;gt; String) = {
  if (s != null) f(s) else s
}

def reverser(s: String) = s.reverse

safeStringOp(null, reverser) // null
safeStringOp(&amp;quot;Ready&amp;quot;, reverser) // &amp;quot;ydaeR&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;함수 리터럴(function literal)&lt;/h2&gt;
&lt;p&gt;함수명이 없는 함수&lt;br&gt;익명 함수(Anonymous function), 람다 표현식(Lambda expression), 람다(Lambda), (function0, function1, function2…) 으로도 불린다.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;([식별자: &amp;lt;타입&amp;gt;, ...]) =&amp;gt; &amp;lt;표현식&amp;gt;&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;val doubler = (x: Int) =&amp;gt; x * 2
// val doubler = x =&amp;gt; x * 2 안됨
val doubled = doubler(22) // 44&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;함수 리터럴은 고차 함수 호출 내부에서 정의 가능&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;def safeStringOp(s: String, f: String =&amp;gt; String) = {
  if (s != null) f(s) else s
}
safeStringOp(&amp;quot;Ready&amp;quot;, (s: String) =&amp;gt; s.reverse)
// safeStringOp(&amp;quot;Ready&amp;quot;, s =&amp;gt; s.reverse) 가능&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;자리표시자 구문(placeholder syntax)&lt;/h2&gt;
&lt;p&gt;매개변수를 와일드카드 연산자( _ )로 대체&lt;/p&gt;
&lt;p&gt;1) 함수의 명시적 타입이 정의되어 있고, 2) 매개변수가 한 번 사용되거나 사용되지 않을 때 사용가능&lt;br&gt;placeholder의 개수는 입력 인수 개수와 동일&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;val doubler: Int =&amp;gt; Int = _ * 2

def safeStringOp(s: String, f: String =&amp;gt; String) = {
  if (s != null) f(s) else s
}
safeStringOp(&amp;quot;Ready&amp;quot;, _.reverse)

def combination(x: Int, y: Int, f: (Int, Int) =&amp;gt; Int) = f(x,y)
combination(23, 12, _ * _) // 23*12&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;타입 매개변수 사용하기&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;def tripleOp1[A, B](a: A, b: A, c: A, f: (A, A, A) =&amp;gt; B) = f(a,b,c)
tripleOp1[Int, Double](23, 92, 14, _ * _ + _)
// tripleOp1(23, 92, 14, _ * _ + _) 불가능

def tripleOp2[A, B](a: A, b: A, c: A)(f: (A, A, A) =&amp;gt; B) = f(a,b,c)
tripleOp2(23, 92, 14)( _ * _ + _)&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;부분 적용 함수(Partially Applied Function)와 커링(currying)&lt;/h2&gt;
&lt;p&gt;부분 적용 함수: 와일드 카드 연산자를 이용해서 어떤 함수를 부분적으로 적용한 함수&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;def factorOf(x: Int, y: Int) = y % x == 0
val multipleOf3 = factorOf(3, _: Int)
val y = multipleOf3(78)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;커링: 한 매개변수 그룹은 적용하고 다른 그룹은 적용하지 않는 기법 &lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;def factorOf(x: Int)(y: Int) = y % x == 0
val isEven = factorOf(2) _
val z = isEven(32) // true&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;다중 매개변수 그룹을 가지는 함수를 함수 체인(chain) 형태로 간주한다.&lt;br&gt;예를 들어 &lt;code&gt;def factorOf(x: Int, y: Int)&lt;/code&gt;의 함수 타입은 &lt;code&gt;(Int, Int) =&amp;gt; Boolean&lt;/code&gt;이다.&lt;br&gt;하지만 &lt;code&gt;def factorOf(x: Int)(y: Int)&lt;/code&gt;의 함수 타입은 &lt;code&gt;Int =&amp;gt; Int =&amp;gt; Boolean&lt;/code&gt; (체인 형식)이다.&lt;br&gt;이 함수를 커링하면 &lt;code&gt;Int =&amp;gt; Boolean&lt;/code&gt;이 된다.&lt;/p&gt;
&lt;h2&gt;이름에 의한(by-name) 호출 매개변수&lt;/h2&gt;
&lt;p&gt;값 또는 값을 반환하는 함수 모두를 취할 수 있는 매개변수, 함수 유연성을 높일 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&amp;lt;식별자&amp;gt;: =&amp;gt; &amp;lt;타입&amp;gt;&lt;/code&gt; &lt;/p&gt;
&lt;p&gt;만약 함수를 매개변수로 받는 경우, 함수를 사용할 때 마다 함수를 호출한다.&lt;br&gt;함수에 반복하여 접근할 때 발생할 수 있는 문제들에 대해 생각하고 사용해야된다.&lt;br&gt;예를 들어, 데이터베이스에 고정값을 검색하고 그 값을 반환하는 표현식을 by-name 호출 매개변수로 사용한다면 함수 내에서 사용될 때마다 데이터베이스에 접근하게 된다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;def doubles(x: =&amp;gt; Int) = {
  println(&amp;quot;Now doubling &amp;quot; + x)
  x * 2
}

doubles(5)
// Now doubling 5
// res18: Int = 10

def f(i: Int) = { println(s&amp;quot;Hello from f($i)&amp;quot;); i }

doubles( f(18) )
// Hello from f(8)
// Now doubling 8
// Hello from f(8)
// res19: Int = 16&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;부분 함수(partial function)&lt;/h2&gt;
&lt;p&gt;입력타입을 만족하는 값을 모두 처리하지 못하는 함수&lt;br&gt;컬렉션과 패턴 매칭으로 작업할 때 유용하다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;val statusHandler: Int =&amp;gt; String = {
  case 200 =&amp;gt; &amp;quot;Okay&amp;quot;
  case 400 =&amp;gt; &amp;quot;Your Error&amp;quot;
  case 500 =&amp;gt; &amp;quot;Our Error&amp;quot;
}

statusHandler(401) // scala.MatchError 발생&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;함수 리터럴 블록으로 고차 함수 호출하기&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;def safeStringOp(s: String)(f: String =&amp;gt; String) = {
  if ( s != null ) f(s) else s
}

val uuid = java.util.UUID.randomUUID.toString
val timedUUID = safeStringOp(uuid) { s =&amp;gt;
  val now = System.currentTimeMillis
  val timed = s.take(24) + now
  timed.toUpperCase
}&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;데이터베이스 트랜젝션 관리에서 고차 함수는 세션을 열고, 함수 매개변수를 호출하고, 커밋또는 롤백을 하여 트랜젝션 종료&lt;/li&gt;
&lt;li&gt;오류를 내지 않을 때까지 함수 매개변수를 여러번 재시도&lt;/li&gt;
&lt;li&gt;지역, 전역, 외부값(환경변수)에 기반하여 조건부로 함수 매개변수 호출&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;함수 내용에 관계 없이 일반화해서 처리할 수 있는 부분를 고차 함수로 정의&lt;/p&gt;
&lt;/blockquote&gt;</description>
      <category>IT Book Study/러닝 스칼라</category>
      <category>Scala</category>
      <category>고차 함수</category>
      <category>러닝 스칼라</category>
      <category>러닝스칼라</category>
      <category>일급함수</category>
      <category>함수 리터럴</category>
      <author>jmkim87</author>
      <guid isPermaLink="true">https://kid1412.tistory.com/240</guid>
      <comments>https://kid1412.tistory.com/240#entry240comment</comments>
      <pubDate>Mon, 28 Sep 2020 23:14:41 +0900</pubDate>
    </item>
    <item>
      <title>러닝스칼라 4장 - 함수</title>
      <link>https://kid1412.tistory.com/239</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bVmOhM/btqJKvJ5Lxw/meZa5pZ5F4ffnFZH3eeWkk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bVmOhM/btqJKvJ5Lxw/meZa5pZ5F4ffnFZH3eeWkk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bVmOhM/btqJKvJ5Lxw/meZa5pZ5F4ffnFZH3eeWkk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbVmOhM%2FbtqJKvJ5Lxw%2FmeZa5pZ5F4ffnFZH3eeWkk%2Fimg.jpg&quot; width=&quot;100%&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;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;/ul&gt;
&lt;p&gt;주어진 입력으로 계산하는 것 이외에 프로그램의 실행에 영향을 미치지 않아야 한다, 즉 &lt;strong&gt;부수 효과(side effect)&lt;/strong&gt; 가 없다&lt;/p&gt;
&lt;h2&gt;함수 정의&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;def multiplier(x:Int, y:Int):Int = {x * y}&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;def로 시작하며 이름이 따라온다 - 그 뒤 괄호 안에는 매개변수 목록이 온다 (매개변수 타입은 추론하지 않으므로 지정해야 한다) - 그 뒤 : 뒤에 결과 타입을 지정한다 (결과 타입은 추론이 가능하므로 생략할 수 있다, 재귀 함수면 생략 불가능) - 함수 본문은 표현식 또는 표현식 블록으로 구성되어 있으며, 마지막 줄이 함수의 반환값이 된다&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;프로시저&lt;/h2&gt;
&lt;p&gt;반환값을 가지지 않는 함수. 문장(println()호출 등)으로 끝나는 함수. Unit 타입으로 추론된다.&lt;/p&gt;
&lt;p&gt;부수 효과(메소드 밖에 있는 상태(var 변수) 변경, I/O 수행 등)를 위해 실행 &lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;def log(d: Double) = println(f&amp;quot;Got value $d%.2f&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;매개변수가 없는 함수&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;def hi() = &amp;quot;hi&amp;quot;
hi()
// hi&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;함수 호출 시 빈괄호를 붙이거나 안 붙일 수 있다.&lt;/p&gt;
&lt;p&gt;관례 상 메소드에 부수 효과가 있다면 괄호를 넣고, 없다면 괄호를 사용하지 않는다. &lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;def hi = &amp;quot;hi&amp;quot;
hi() // compile error
hi // hi&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;함수를 매개변수 괄호 없이 정의할 수 있다. 해당 경우에는 빈괄호를 붙여서 호출할 수 없다.&lt;/p&gt;
&lt;h2&gt;표현식 블록 매개변수&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;def formatEuro(amt: Double) = f&amp;quot;$amt%.2f euro&amp;quot;
formatEuro {
  val rate = 1.32
  0.235 + 0.7123 + rate * 5.32
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;단일 매개변수일 때 괄호를 중괄호로 바꾸고 표현식 블록을 매개변수로 사용할 수 있다. 함수 호출 시 표현식을 평가한 후, 반환값을 함수 매개변수로 사용한다.&lt;/p&gt;
&lt;p&gt;계산된 값을 함수로 전달해야 할 때 지역 변수에 저장할 필요 없이 넘길 수 있다.&lt;/p&gt;
&lt;h2&gt;재귀 함수&lt;/h2&gt;
&lt;h3&gt;꼬리 재귀&lt;/h3&gt;
&lt;p&gt;재귀적 호출이 새로운 스택 공간을 생성하지 않는 대신 현행 함수의 스택 공간을 사용하도록 최적화됨. 마지막 문장이 재귀적 호출이여야 한다&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;@tailrec annotation&lt;/code&gt;&lt;/strong&gt; : 표시된 함수가 꼬리 재귀로 최적화 될 수 없다면 컴파일 에러 발생시킨다. &lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;def boom(x:Int) : Int = 
    if (x == 0) 1
    else bool(x - 1)

@annotation.tailrec
def boom(x:Int) : Int = 
    if (x == 0) 1
    else bool(x - 1) + 1 
// 마지막 문장이 재귀적 호출만 있지 않다. + 1을 추가로 하고 있어 compile error

@annotation.tailrec
val funValue = nestedFum _
def nestedFum(x :Int) : Unit = 
    if (x != 0) {println(x); funValue(x - 1)}  
// 함수 값을 통하는 중간 경로가 있어 재귀적 호출이라고 볼 수 없다. compile error&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;중첩 함수&lt;/h2&gt;
&lt;p&gt;함수(외부) 내에 다른 함수(내부) 정의. 내부 함수는 외부 함수 scope에서만 사용할 수 있다.&lt;/p&gt;
&lt;p&gt;메소드로 생각하면 scope을 class 내 -&amp;gt; 해당 method 내로 옮기는 효과가 있다. &lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;def max(a: Int, b: Int, c: Int) = {
  def max(x: Int, y: Int) = if (x &amp;gt; y) x else y
  max(a, max(b, c))
}&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;이름 붙인 매개변수&lt;/h2&gt;
&lt;p&gt;매개변수 목록에 정해진 순서와 다른 순서로 함수에 인자 전달 가능 &lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;def speed(distance:Float, time:Float) = distance / time
speed(time = 10, distance = 100)&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;default 매개변수 값&lt;/h2&gt;
&lt;p&gt;default 값을 지정해 놓으면 함수 호출 시 해당 인자 생략 가능, 이름 붙인 인자와 같이 쓰면 유용함&lt;/p&gt;
&lt;p&gt;기본값을 갖는 매개변수가 필수 매개변수 다음에 오도록 함수 매개변수를 구조화해야 &lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;def printTime(out: java.io.PrintStream = Console.out, divisor:Int = 1) = out.println(&amp;quot;time = &amp;quot; + System.CurrentTimeMillis() / divisor)
printTime(out = Console.err)
printTime(divisor = 1000)

def greet(name: String, prefix: String = &amp;quot;&amp;quot;) = s&amp;quot;$prefix$name&amp;quot;
greet(&amp;quot;Ola&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;가변 매개변수&lt;/h2&gt;
&lt;p&gt;정해지지 않은 개수의 입력 인수들로 함수를 정의&lt;/p&gt;
&lt;p&gt;함수의 마지막 파라미터만 지정 가능, 함수 내에서 해당 타입의 배열로 취급됨 &lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;def echo(args: String *) = for(arg &amp;lt;- args) println(arg)
echo(&amp;quot;AA&amp;quot;)
echo(&amp;quot;AA&amp;quot;, &amp;quot;BB&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;커링&lt;/h2&gt;
&lt;h2&gt;타입 매개변수&lt;/h2&gt;
&lt;p&gt;매개 변수 또는 반환 값 등에 사용될 타입을 지시한다 (타입을 매개변수화) &lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;def identity[A](a: A) : A = a
val s: String = identity[String](&amp;quot;Hello&amp;quot;)
val s: String = identity(&amp;quot;Hello&amp;quot;) // 함수에 전달하는 리터럴 값이나 함수의 반환 값을 할당한 값의 타입을 통해 타입 추론 가능, 타입 매개변수 생략 가능&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;메소드&lt;/h2&gt;
&lt;p&gt;클래스에서 정의된 함수로 그 객체의 데이터에 동작. &amp;lt;인스턴스&amp;gt;.&amp;lt;메소드&amp;gt;로 호출&lt;/p&gt;
&lt;p&gt;스칼라에서는 모든 것이 객체(int, double 등도)이므로 산술 연산자도 해당 객체 내의 메소드로 정의되어 있다.&lt;/p&gt;
&lt;p&gt;객체와 메소드, 그리고 매개변수를 공백으로 구분하는 연산자 호출법으로 메소드 호출이 가능하므로 연산자 메소드들을 연산자처럼 보이게 할 수 있다. &lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;2 + 3  // compiler가 아래 모양으로 변경
2.+(3)

d compare 18.0 // 모든 메소드에 사용 가능
&amp;quot;abcde&amp;quot; substring (1, 2) // 매개 변수가 여러 개면 괄호 이용&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;연산자 우선순위는 method 첫 글자를 보고 우선순위 결정. a +++ b &lt;strong&gt;* c(+++, *&lt;/strong&gt; 는 메소드 이름)일 경우 a +++ (b &lt;strong&gt;***&lt;/strong&gt; c)로 취급(*가 +보다 우선순위 높음)&lt;/p&gt;
&lt;p&gt;한가지 예외, =로 끝나는 메소드는 =(할당 연산자)와 동급으로 취급해 우선순위 제일 낮게 취급. x &lt;em&gt;= y + 1일 경우 x&lt;/em&gt; = (y + 1)로 취급(&lt;em&gt;가 +보다 우선순위 높지만.&lt;/em&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;함수 내에 세부사항과 맥락에 대한 설명, 잠재적인 문제점, TODO등을 주석으로 표현하기.&lt;/li&gt;
&lt;li&gt;ScalaDoc 헤더 추가&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>IT Book Study/러닝 스칼라</category>
      <category>curring</category>
      <category>function</category>
      <category>Scala</category>
      <category>러닝 스칼라</category>
      <category>러닝스칼라</category>
      <category>매개변수</category>
      <category>재귀함수</category>
      <category>커링</category>
      <category>프로시저</category>
      <author>jmkim87</author>
      <guid isPermaLink="true">https://kid1412.tistory.com/239</guid>
      <comments>https://kid1412.tistory.com/239#entry239comment</comments>
      <pubDate>Mon, 28 Sep 2020 23:13:16 +0900</pubDate>
    </item>
    <item>
      <title>러닝스칼라 3장 - 표현식과 조건문</title>
      <link>https://kid1412.tistory.com/238</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dnoo9U/btqJKwCccU8/axLfAMGMPkx84pYK1SXkf1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dnoo9U/btqJKwCccU8/axLfAMGMPkx84pYK1SXkf1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dnoo9U/btqJKwCccU8/axLfAMGMPkx84pYK1SXkf1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdnoo9U%2FbtqJKwCccU8%2FaxLfAMGMPkx84pYK1SXkf1%2Fimg.jpg&quot; width=&quot;100%&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;h2&gt;표현식&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;표현식(expression)&lt;/strong&gt; 은 값을 반환하는 코드의 단위입니다. &lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;// String 리터럴
&amp;quot;hello&amp;quot;
&amp;quot;hel&amp;quot;+&amp;#39;l&amp;#39;+&amp;#39;o&amp;#39;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;표현식으로 값과 변수 정의하기&lt;/h3&gt;
&lt;p&gt;아래와 같이 표현식의 반환값을 값 또는 변수에 할당하는 식으로 나타낼 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;val &amp;lt;식별자&amp;gt;[: &amp;lt;타입&amp;gt;] = &amp;lt;표현식&amp;gt;&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;표현식 블록&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;표현식 블록&lt;/strong&gt; 은 중괄호({,})를 사용하여 하나로 묶어서 사용합니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;두 표현식&lt;/strong&gt; &lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;val x = 5 * 20; val amount = x + 10&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;표현식 블록&lt;/strong&gt; &lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;val amount = { val x = 5 * 20; x + 10}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;여러 줄로 표현&lt;/strong&gt; &lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;val amount = {
  val x = 5 * 20
  x + 10
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;삼중 구조&lt;/strong&gt; 후반부에 제어 구조를 다룰 때 다룹니다. &lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;{ val a = 1; { val b = a * 2; { val c = b + 4; c}}}&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;문장(statement)&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;문장(statement)&lt;/strong&gt; : 값을 반환하지 않는 표현식&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;문장 블록(Statement block)&lt;/strong&gt; : 표현식 블록과 다르게 값을 반환하지 않습니다. * 결과 값이 없기 때문에 보편적으로 기존 데이터를 수정하거나 애플리케이션 범위 밖을 변경하는데 사용 합니다.&lt;/p&gt;
&lt;h2&gt;If .. Else 표현식 블록&lt;/h2&gt;
&lt;h3&gt;If 표현식&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;if (&amp;lt;부울식&amp;gt;) &amp;lt;표현식&amp;gt;&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;if ( 47 % 3 &amp;gt; 0 )  println(&amp;quot;Not a multiple of 3&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;If-Else 표현식&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;if (&amp;lt;부울식&amp;gt;) &amp;lt;표현식&amp;gt; else &amp;lt;표현식&amp;gt;&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;val x = 10 
val y = 20 
val max = if (x &amp;gt; y) x else y // 20&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;다른 언어에서 지원하는 삼항 표현식을 사용하지 않는 이유는 간결하게 표현할 수 있기 때문&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;매치 표현식&lt;/h2&gt;
&lt;p&gt;switch문과 유사합니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;&amp;lt;표현식&amp;gt; match {
    case &amp;lt;패턴 매치&amp;gt; =&amp;gt; &amp;lt;표현식&amp;gt;
    [case ...]
}&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;If .. else와 같은 방식의 match&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;val x = 10 
val y = 20 
val max = x &amp;gt; y match { 
    case true =&amp;gt; x 
    case false =&amp;gt; y 
} //max = 20s&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Request Status Code&lt;/strong&gt; &lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;val status = 500
val message = status match { 
    case 200 =&amp;gt; “ok” 
    case 400 =&amp;gt; { 
        println(&amp;quot;ERROR - we called the service incorrectly.&amp;quot;) 
        &amp;quot;error&amp;quot;
    } 
    case 500 =&amp;gt; { 
        println(&amp;quot;ERROR - the service encountered an error.&amp;quot;) 
        &amp;quot;error&amp;quot; 
    } 
} 
// ERROR - the service encountered an error 
// message : error&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;여러 패턴을 동일한 case 블록 사용하기&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;val day = &amp;quot;MON&amp;quot; 
val kind = day match { 
    case &amp;quot;MON&amp;quot; | &amp;quot;TUE&amp;quot; | &amp;quot;WED&amp;quot; | &amp;quot;THU&amp;quot; | &amp;quot;FRI&amp;quot; =&amp;gt; { 
        &amp;quot;weekday&amp;quot; 
    } 
    case &amp;quot;SAT&amp;quot; | &amp;quot;SUN&amp;quot; =&amp;gt; { 
        &amp;quot;weekend&amp;quot; 
    } 
} 
//kind = &amp;quot;weekday&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Error&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;&amp;quot;match me&amp;quot; match {
    case &amp;quot;nope&amp;quot; =&amp;gt; &amp;quot;sorry&amp;quot;
} 
// scala.MatchError&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt; 위처럼 에러를 방지하기 위해 와일드 카드로 매칭하여 예외처리 합니다.&lt;/p&gt;
&lt;h3&gt;와일드카드로 매칭하기&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;값 바인딩(value binding)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;case 블록이 유지되는 동안만 정의됩니다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;val message = &amp;quot;FAIL&amp;quot;
val status = message match {
case &amp;quot;OK&amp;quot; =&amp;gt; 200
case other =&amp;gt; {
  println(other) // &amp;quot;FAIL&amp;quot;
  -1
}
}&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;와일드 카드(_, underscore)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;_를 사용하며 값 바인딩과 다르게 해당 값에 대해서 접근할 수 없습니다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;val status = message match {
case &amp;quot;OK&amp;quot; =&amp;gt; 200
case _ =&amp;gt; {
  -1
}
}&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;패턴 가드를 이용한 매칭&lt;/h3&gt;
&lt;p&gt;기존의 if문과 다르게 둘러싸고 있는 ()가 필요 없습니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;case &amp;lt;패턴&amp;gt; if &amp;lt;부울식&amp;gt; =&amp;gt; &amp;lt;하나 이상의 표현식&amp;gt;&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;val response: String = null
response match {
  case s if s != null =&amp;gt; println(s&amp;quot;Received &amp;#39;$s&amp;#39;&amp;quot;)
  case s =&amp;gt; println(&amp;quot;Error!&amp;quot;)
}
// &amp;quot;Error!&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;패턴 변수를 이용한 타입 매칭&lt;/h3&gt;
&lt;p&gt;패턴 변수는 다른 타입의 값으로 전환할 수 있습니다. 패턴 변수에서의 제한은 반드시 소문자로 시작해야합니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;case &amp;lt;identifier&amp;gt;: &amp;lt;type&amp;gt; =&amp;gt; &amp;lt;one or more expressions&amp;gt;&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;패턴 변수 사용법&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;val y:Any = 12345

y match {
  case x: String =&amp;gt; s&amp;quot;&amp;#39;$x&amp;#39;&amp;quot;
  case x: Double =&amp;gt; f&amp;quot;$x%.2f&amp;quot;
  case x: Float =&amp;gt; f&amp;quot;$x%.2f&amp;quot;
  case x: Long =&amp;gt; s&amp;quot;${x}l&amp;quot;
  case x: Int =&amp;gt; s&amp;quot;${x}i&amp;quot;
}
//12345i&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;루프&lt;/h2&gt;
&lt;p&gt;숫자 범위 정의하기&lt;br&gt;&lt;strong&gt;&lt;code&gt;&amp;lt;시작 정수값&amp;gt; [to|until] &amp;lt;끝 정수값&amp;gt; [by increment]&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;기본 for 루프로 반복하기&lt;br&gt;&lt;strong&gt;&lt;code&gt;for (&amp;lt;식별자&amp;gt; &amp;lt;- &amp;lt;반복자&amp;gt;)[yield] [&amp;lt;표현식&amp;gt;]&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;for (x &amp;lt;- 1 to 7) {println(s&amp;quot;Day $x:&amp;quot;)}
/*
    Day 1:
    Day 2:
    Day 3:
    Day 4:
    Day 5:
    Day 6:
    Day 7:
*/&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;만약 for loop시에 하나의 컬렉션에 넣어서 반환하려면 yield를 사용합니다. &lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;for (x &amp;lt;- 1 to 7) yield { s&amp;quot;Day $x:&amp;quot;}
// res0: IndexedSeq[String] = Vector(Day 1:, Day 2:, Day 3:, Day 4:, Day 5:, Day 6:, Day 7:)&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;반복자 가드&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;for (&amp;lt;identifier&amp;gt; &amp;lt;- &amp;lt;iterator&amp;gt; if &amp;lt;Boolean expression&amp;gt;) ...&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;아래는 3의 배수로 이루어진 컬렉션을 만드는 예제입니다. &lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;val threes = for (i &amp;lt;- 1 to 20 if i % 3 == 0) yield i 

val threes_multi_line = for {
  i &amp;lt;- 1 to 20
  if i % 3 == 0
} yield i
// threes_multi_line: IndexedSeq[Int] = Vector(3, 6, 9, 12, 15, 18)&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;중첩된 반복자&lt;/h3&gt;
&lt;p&gt;for 루프에 추가된 부가적인 반복자로, 전체 반복 횟수를 자신의 반복 횟수만큼 반복합니다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;val two_dimension = for {
  x &amp;lt;- 1 to 2
  y &amp;lt;- 1 to 3  
} {print(s&amp;quot;($x, $y)&amp;quot;)}
// (1, 1)(1, 2)(1, 3)(2, 1)(2, 2)(2, 3)two_dimension: Unit = ()&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;값 바인딩&lt;/h3&gt;
&lt;p&gt;for 루프 정의에서 값 바인딩을 사용하여 좀 더 깔끔한 코드를 만들 수 있습니다.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;for (&amp;lt;식별자&amp;gt; &amp;lt;- &amp;lt;반복자&amp;gt; ; &amp;lt;식별자&amp;gt; = &amp;lt;표현식&amp;gt;) ...&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;예시로 아래에 0에서 8까지 2의 거듭 제곱 값을 계산하는 for 루프 입니다. 값 바인딩을 사용하지 않았을 경우 코드가 좀 길어집니다. &lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;val powersOf2 = for (i &amp;lt;- 0 to 8) yield {
  val pow = 1 &amp;lt;&amp;lt; i
  pow
}
// powersOf2: IndexedSeq[Int] = Vector(1, 2, 4, 8, 16, 32, 64, 128, 256)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;값 바인딩을 사용하면 아래와 같이 깔끔하게 정의할 수 있습니다. &lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;val powerOf2 = for (i &amp;lt;- 0 to 8; pow = 1 &amp;lt;&amp;lt; i) yield pow
// powersOf2: IndexedSeq[Int] = Vector(1, 2, 4, 8, 16, 32, 64, 128, 256)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;위에서 사용한 &amp;lt;&amp;lt;(shift 연산자)는 비트를 옮기는 역할을 합니다.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;대략적인 ...
1 : 0b000000001
2 : 0b000000010
4 : 0b000000100
8 : 0b000001000
...
256 : 0b100000000
&lt;/code&gt;&lt;/pre&gt;&lt;h3&gt;While과 Do/While 루프&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;while (&amp;lt;부울식&amp;gt;) 표현식&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;var x = 10
while (x &amp;gt; 0) x -= 1

var x = 10
do x -= 1 while ( x &amp;gt; 0 )&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;FAQ&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;yield 사용 시 동작 방법&lt;ol&gt;
&lt;li&gt;for loop에서는 map function처럼 동작 합니다.&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.scala-lang.org/tutorials/FAQ/yield.html&quot;&gt;https://docs.scala-lang.org/tutorials/FAQ/yield.html&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;yield 앞에 사용법에 따라서 동작 방식이 달라질 듯 합니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;</description>
      <category>IT Book Study/러닝 스칼라</category>
      <category>match</category>
      <category>Scala</category>
      <category>러닝 스칼라</category>
      <category>러닝스칼라</category>
      <category>반복문</category>
      <category>조건문</category>
      <category>표현식</category>
      <author>jmkim87</author>
      <guid isPermaLink="true">https://kid1412.tistory.com/238</guid>
      <comments>https://kid1412.tistory.com/238#entry238comment</comments>
      <pubDate>Mon, 28 Sep 2020 23:11:23 +0900</pubDate>
    </item>
    <item>
      <title>러닝스칼라 2장 - 데이터로 작업하기: 리터럴, 값, 변수, 타입</title>
      <link>https://kid1412.tistory.com/237</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;L.jpg&quot; data-origin-width=&quot;307&quot; data-origin-height=&quot;400&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cYfMRV/btqJIOb3BPC/HArztidRqHLF4sD0CrZiO1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cYfMRV/btqJIOb3BPC/HArztidRqHLF4sD0CrZiO1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cYfMRV/btqJIOb3BPC/HArztidRqHLF4sD0CrZiO1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcYfMRV%2FbtqJIOb3BPC%2FHArztidRqHLF4sD0CrZiO1%2Fimg.jpg&quot; data-filename=&quot;L.jpg&quot; data-origin-width=&quot;307&quot; data-origin-height=&quot;400&quot; data-ke-mobilestyle=&quot;widthContent&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&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;스칼라에서 값과 변수에 저장된 데이터를 더 이상 사용하지 않으면 자바 가상 머신의 가비지 컬렉션이 자동으로 할당을 취소한다. 직접 할당 취소할 필요도 능력도 없다.&lt;/p&gt;
&lt;h2&gt;리터럴(literal)&lt;/h2&gt;
&lt;p&gt;숫자 5, 문자 A, 텍스트 &amp;rsquo;Hello, World&amp;rsquo;처럼 소스 코드에 바로 등장하는 데이터&lt;/p&gt;
&lt;h2&gt;값 (value)&lt;/h2&gt;
&lt;p&gt;불변의 타입을 갖는 스토리지 단위이며, 데이터를 저장 - 명시적인 타입이 있어야 하는 것은 아니다, 스칼라 컴파일러가 할당된 데이터를 기반으로 추론한다. =&amp;gt; 타입 추론 (type inference) - 코드를 작성하는데 타입 추론은 편하지만 가독성을 떨어뜨리지 않는 범위에서 사용&lt;/p&gt;
&lt;pre class=&quot;xml&quot;&gt;&lt;code&gt;val &amp;lt;식별자&amp;gt;[: 타입] = &amp;lt;데이터&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;변수 (variable)&lt;/h2&gt;
&lt;p&gt;값을 저장하고 그 값을 가져올 수 있도록 할당되거나 예약된 메모리 공간에 대응하는 유일한 식별자 - 메모리 공간에 예약되어 있는 동안에는 새로운 값을 계속 할당할 수 있다. - 메로리 간의 내용은 동적이며 가변적이다. - 스칼라에서는 관례상 변수보다 값을 선호하는 이유는 값을 사용하면 소스 코드가 안정적이며 예측할 수 있기 때문 - 디버깅이 쉽고 멀티 스레드 코드에서 가변 데이터보다 더 안정적이며 에러 발생 확률이 적어진다.&lt;/p&gt;
&lt;pre class=&quot;xml&quot;&gt;&lt;code&gt;var &amp;lt;식별자&amp;gt;[: 타입] = &amp;lt;데이터&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;타입 추론은 가능하지만 지정된 타입은 바꿀수 없다. (예외로 Double 변수에 Int를 할당하면 Double로 바꿔준다)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;명명&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;이름은 숫자로 시작할수 없다&lt;/li&gt;
&lt;li&gt;val a.b = 4 는 불가능 하지만 val &amp;lsquo;a.b&amp;rsquo; = 4 는 가능하다.&lt;/li&gt;
&lt;li&gt;관례상 camel case 를 쓴다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;타입&lt;/h2&gt;
&lt;h3&gt;숫자형 타입&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&quot;center&quot;&gt;이름&lt;/th&gt;
&lt;th align=&quot;center&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;Byte&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;1byte&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;center&quot;&gt;Short&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;2byte&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;center&quot;&gt;Int&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;4byte&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;5, 0x0f&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;center&quot;&gt;Long&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;8byte&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;5l&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;center&quot;&gt;Float&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;4byte&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;5f&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;center&quot;&gt;Double&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;8byte&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;5d, 5.0&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;ul&gt;
&lt;li&gt;스칼라는 타입 순위에 기반하여 한 타입의 순자를 자동으로 다른 타입으로 전환해준다 =&amp;gt; 상향전환&lt;/li&gt;
&lt;li&gt;표는 자동 전환 순위대로 정렬한것이다. Byte 타입이 최하위여서 모든 타입으로 전환 가능&lt;/li&gt;
&lt;li&gt;높은 순위의 데이터 타입이 더 낮은 순위의 타입으로 자동 전환을 허용하지 않는다.&lt;/li&gt;
&lt;li&gt;to 으로 수동 전환은 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;문자열&lt;/h3&gt;
&lt;p&gt;텍스트의 문자열, 스칼라늬 String은 자바의 String을 기반으로 하며, 여러줄 리터럴(multiline literal) 과 문자열 보간(interpolation)을 추가 - 숫자타입과 마찬가지로 수학 연산자 사용 지원 - 여러줄 String은 입력할때 &quot;&quot;&quot; &quot;&quot;&quot; 를 사용한다 (이때는 인지 못함) - 문자열 보간&lt;/p&gt;
&lt;pre class=&quot;kotlin&quot;&gt;&lt;code&gt;val approx = 355/113f
println(s&quot;PI, using 255/113 is about $approx.&quot;)
PI, using 255/113 is about 3.141593

val pepper = &quot;pepper &quot;
println(s&quot;${pepper *3} salt&quot;)
pepper pepper pepper  salt

// printf
val item = &quot;apple&quot;
f&quot;I wrote a new $item%.3s today&quot;
I wrote a new app today&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;정규 표현식&lt;/h3&gt;
&lt;p&gt;검색 패턴을 나타내는 문자와 구두점으로 이루어진 문자열이다. - java.util.regex.Pattern에 기반 - matches, replaceAll, replaceFrist&lt;/p&gt;
&lt;h3&gt;정규 표현식으로 값 캡처하기&lt;/h3&gt;
&lt;p&gt;정규 표현식의 고급 처리 기법을 위해서 r 연산자를 호출하여 문자열을 정규표현식 타입으로 전환하면 된다.&lt;/p&gt;
&lt;pre class=&quot;pony&quot;&gt;&lt;code&gt;scala&amp;gt; val input = &quot;Enjoying this apple 3.14159 times today&quot;
input: String = Enjoying this apple 3.14159 times today

scala&amp;gt; val pattern= &quot;&quot;&quot;.* apple ([\d.]+) times .*&quot;&quot;&quot;.r
pattern: scala.util.matching.Regex = .* apple ([\d.]+) times .*

scala&amp;gt; val pattern(amountText) = input
amountText: String = 3.14159

scala&amp;gt; val amount = amountText.toDouble
amount: Double = 3.14159&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;참고: &lt;a href=&quot;https://programmingnote.tistory.com/36&quot;&gt;https://programmingnote.tistory.com/36&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;스칼라 타입의 개요&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Any는 절대 루트로 다은 모든 타입들은 이 루트의 두 자식 노으인 AnyVal, AnyRef의 자식이다.&lt;/li&gt;
&lt;li&gt;Anyval는 값 타입 (value type)이라 하며 숫자형 타입과 Char, Boolean, Unit 포함
&lt;ul&gt;
&lt;li&gt;객체로 힙메모리에 할당되거나 JVM 기본값으로 스택에 지역적으로 할당된다&lt;/li&gt;
&lt;li&gt;AnyVal 이외에는 AnyRef 이며 오직 객체로 힙 메모리에만 할당&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;최하위 Nothing, Null 타입
&lt;ul&gt;
&lt;li&gt;Nothing은 프로그램 흐름에 영향을 줄 수 있는 연산에서 호환성 있는 반환값을 제공&lt;/li&gt;
&lt;li&gt;return 키워드는 Nothing 이며 타입으로만 사용하며 인스터스화 할 수 없다.&lt;/li&gt;
&lt;li&gt;Null은 AnyRef의 서브타입으로 키워드 Null 타입을 제공&lt;/li&gt;
&lt;li&gt;String변수는 언제라도 null 타입이 될수있고 그 변수는 메모리의 어떤 문자열 인스턴스도 가리키지 않는다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;char는 String 타입의 기본이 되는 타입으로 단일 문자
&lt;ul&gt;
&lt;li&gt;다르 숫자와 양방향 전환이 가능하다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Boolean 타입은 true와 false
&lt;ul&gt;
&lt;li&gt;스칼라는 다른 타입을 부울 타입으로 자동 전환해주지 않는다.&lt;/li&gt;
&lt;li&gt;null이 아닌 문자열을 true 라고 하지 않고, 숫자 0은 false 와 다르다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Unit은 데티어 타입을 나타내는 대신 데이터가 없음을 나타낸다.
&lt;ul&gt;
&lt;li&gt;void 와 유사하고 () 로 표현&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;타입 연산&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&quot;center&quot;&gt;Name&lt;/th&gt;
&lt;th align=&quot;center&quot;&gt;Example&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;asInstanceOf[타입&amp;gt;]&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;5.asInstanceOf[Long]&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;해당값을 원하는 타입의 값으로 전환, 그 값이 새로운 타입과 호환되지 않으면 에러&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;center&quot;&gt;getClass&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;(7.0/5).getClass&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;해당값의 타입 반환&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;center&quot;&gt;isInstanceOf&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;(5.0).isInstanceOf[Float]&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;해당 값이 주어진 타입을 가지면 true 반환&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;center&quot;&gt;hashCode&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;&quot;A&quot;.hashCode&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;해당 값의 해시값 반환&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;center&quot;&gt;to&amp;lt;타입&amp;gt;&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;20.toByte&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;하나의 값을 호환되는 값으로 반환&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;center&quot;&gt;toString&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;(3.0/ 4.0).toString&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;해당 값을 String으로 전환&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;ul&gt;
&lt;li&gt;asInstanceOf는 요청받은 타입으로 전환될 수 없으면 에러가 발생한다.
&lt;ul&gt;
&lt;li&gt;런타입 에러가 발생하는 것을 피하기 위해서는 가능하다면 타입 지정된 전환 연산인 to을 사용하는 것이 좋다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;튜플&lt;/h3&gt;
&lt;p&gt;둘 이상의 값을 가지는 순서가 있는 컨테이너, 각각의 값은 서로 다른 타입을 가질 수 있다. - 항목은 1부터 시작하는 인덱스를 이용하여 접근가능 , 화살표 연산자로 사용하는 방법&lt;/p&gt;
&lt;h2&gt;appendix. 그외 이슈&lt;/h2&gt;
&lt;h3&gt;tuple은 왜 loop 순회 할 수 없는가?&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/IWvOS/btqJOzrEkx6/t7itp0EnMJq20VGAC1BiX1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/IWvOS/btqJOzrEkx6/t7itp0EnMJq20VGAC1BiX1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/IWvOS/btqJOzrEkx6/t7itp0EnMJq20VGAC1BiX1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FIWvOS%2FbtqJOzrEkx6%2Ft7itp0EnMJq20VGAC1BiX1%2Fimg.png&quot; width=&quot;100%&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&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;ul&gt;
&lt;li&gt;튜플은 Tuple case클래스와 product trait으로 구성&lt;/li&gt;
&lt;li&gt;tuple/product는 item개수에 따라 직접 구현됨&lt;/li&gt;
&lt;li&gt;product는 내부에 item에 매핑되는 member를 가지고 있음 &lt;a href=&quot;https://www.scala-lang.org/api/current/scala/Product.html&quot;&gt;product구성&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;각 member는 productElement(n: Int)로 조회될 수 있음&lt;/li&gt;
&lt;li&gt;product는 productElement를 loop 호출하는 productIterator를 가지고 있음&lt;/li&gt;
&lt;li&gt;이것을 사용하여 loop 순회 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c6RuXf/btqJPBJvsIN/lAgZodcM4kokP7qBwYtUo0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c6RuXf/btqJPBJvsIN/lAgZodcM4kokP7qBwYtUo0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c6RuXf/btqJPBJvsIN/lAgZodcM4kokP7qBwYtUo0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc6RuXf%2FbtqJPBJvsIN%2FlAgZodcM4kokP7qBwYtUo0%2Fimg.png&quot; width=&quot;100%&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&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;h3&gt;python의 속도&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/GliVe/btqJKvcdFiA/lEINgDOIKzcjqymrqIbiFK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/GliVe/btqJKvcdFiA/lEINgDOIKzcjqymrqIbiFK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/GliVe/btqJKvcdFiA/lEINgDOIKzcjqymrqIbiFK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FGliVe%2FbtqJKvcdFiA%2FlEINgDOIKzcjqymrqIbiFK%2Fimg.png&quot; width=&quot;100%&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&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;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://brunch.co.kr/@abrahamsong/43&quot;&gt;스칼라와 파이썬&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>IT Book Study/러닝 스칼라</category>
      <category>Scala</category>
      <category>tuple</category>
      <category>값</category>
      <category>러닝 스칼라</category>
      <category>러닝스칼라</category>
      <category>리터럴</category>
      <category>변수</category>
      <category>타입</category>
      <author>jmkim87</author>
      <guid isPermaLink="true">https://kid1412.tistory.com/237</guid>
      <comments>https://kid1412.tistory.com/237#entry237comment</comments>
      <pubDate>Mon, 28 Sep 2020 23:06:30 +0900</pubDate>
    </item>
    <item>
      <title>러닝스칼라 1장 - 스칼라 시작하기</title>
      <link>https://kid1412.tistory.com/236</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;L.jpg&quot; data-origin-width=&quot;307&quot; data-origin-height=&quot;400&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rFUH0/btqJG9HxjBO/WQUKvXLcymtvRn6Bfc0Kd1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rFUH0/btqJG9HxjBO/WQUKvXLcymtvRn6Bfc0Kd1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rFUH0/btqJG9HxjBO/WQUKvXLcymtvRn6Bfc0Kd1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FrFUH0%2FbtqJG9HxjBO%2FWQUKvXLcymtvRn6Bfc0Kd1%2Fimg.jpg&quot; data-filename=&quot;L.jpg&quot; data-origin-width=&quot;307&quot; data-origin-height=&quot;400&quot; data-ke-mobilestyle=&quot;widthContent&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&gt;해당 챕터는 책과 좀 다르게 intellij로 환경 설정 하는 방법으로 적겠습니다.&lt;/p&gt;
&lt;h2&gt;1.1. 설치하기&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Intellij를 처음 설치 후 첫 실행 시 아래와 같은 화면에서 설치 할 수 있습니다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignLeft&quot; width=&quot;50%&quot; data-origin-width=&quot;1628&quot; data-origin-height=&quot;1354&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bagN3J/btqJOzyog0w/Zksb2zwV6CZWTLoQcZKzZK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bagN3J/btqJOzyog0w/Zksb2zwV6CZWTLoQcZKzZK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bagN3J/btqJOzyog0w/Zksb2zwV6CZWTLoQcZKzZK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbagN3J%2FbtqJOzyog0w%2FZksb2zwV6CZWTLoQcZKzZK%2Fimg.png&quot; width=&quot;50%&quot; data-origin-width=&quot;1628&quot; data-origin-height=&quot;1354&quot; data-ke-mobilestyle=&quot;widthContent&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;/li&gt;
&lt;li&gt;
&lt;p&gt;새 프로젝트를 만들 시 다음과 같이 선택 할 수 있습니다. Use library에 버전이 없을 경우 Create를 누릅니다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;이미 Scala를 따로 깔으셨다면 자동으로 잡힐꺼라 생각됩니다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignLeft&quot; width=&quot;50%&quot; data-origin-width=&quot;1722&quot; data-origin-height=&quot;1066&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bflRBX/btqJPDgfaVz/xAQjbqfY8PTlPrGxKuaAW0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bflRBX/btqJPDgfaVz/xAQjbqfY8PTlPrGxKuaAW0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bflRBX/btqJPDgfaVz/xAQjbqfY8PTlPrGxKuaAW0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbflRBX%2FbtqJPDgfaVz%2FxAQjbqfY8PTlPrGxKuaAW0%2Fimg.png&quot; width=&quot;50%&quot; data-origin-width=&quot;1722&quot; data-origin-height=&quot;1066&quot; data-ke-mobilestyle=&quot;widthContent&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;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Use library에 버전이 없을 때 Create 버튼을 누르면 아래와 같이 나옵니다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignLeft&quot; width=&quot;50%&quot; data-origin-width=&quot;970&quot; data-origin-height=&quot;1058&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/byN8sW/btqJP6JdxDY/XMdxDqhMlEkMhWvZJqXRT1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/byN8sW/btqJP6JdxDY/XMdxDqhMlEkMhWvZJqXRT1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/byN8sW/btqJP6JdxDY/XMdxDqhMlEkMhWvZJqXRT1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbyN8sW%2FbtqJP6JdxDY%2FXMdxDqhMlEkMhWvZJqXRT1%2Fimg.png&quot; width=&quot;50%&quot; data-origin-width=&quot;970&quot; data-origin-height=&quot;1058&quot; data-ke-mobilestyle=&quot;widthContent&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;/li&gt;
&lt;li&gt;
&lt;p&gt;다운 받을 버전 선택&lt;/p&gt;
&lt;figure class=&quot;imageblock alignLeft&quot; width=&quot;50%&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;1090&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bn31ud/btqJRlFUT7J/eErc6ZE0pDbSK0pg6Khw80/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bn31ud/btqJRlFUT7J/eErc6ZE0pDbSK0pg6Khw80/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bn31ud/btqJRlFUT7J/eErc6ZE0pDbSK0pg6Khw80/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbn31ud%2FbtqJRlFUT7J%2FeErc6ZE0pDbSK0pg6Khw80%2Fimg.png&quot; width=&quot;50%&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;1090&quot; data-ke-mobilestyle=&quot;widthContent&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;/li&gt;
&lt;li&gt;
&lt;p&gt;설치가 완료 되면 Use library에 버전이 들어가서 보여집니다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignLeft&quot; width=&quot;50%&quot; data-origin-width=&quot;1726&quot; data-origin-height=&quot;1066&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b4BLTW/btqJPCBCBSg/HvZKzcMuUqIFca2k9bISK1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b4BLTW/btqJPCBCBSg/HvZKzcMuUqIFca2k9bISK1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b4BLTW/btqJPCBCBSg/HvZKzcMuUqIFca2k9bISK1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb4BLTW%2FbtqJPCBCBSg%2FHvZKzcMuUqIFca2k9bISK1%2Fimg.png&quot; width=&quot;50%&quot; data-origin-width=&quot;1726&quot; data-origin-height=&quot;1066&quot; data-ke-mobilestyle=&quot;widthContent&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;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;참조 : &lt;a href=&quot;https://wingnim.tistory.com/71&quot;&gt;https://wingnim.tistory.com/71&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;1.1.1. 번외&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Intellij 첫 실행 시에 scala를 깔지 않았다면 2가지 방법이 있습니다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Scala를 별도로 설치하여 사용하기&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;이 방식은 별도로 해보지 않았지만 될 듯 합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Intellij plugin에서 scala를 검색하여 설치하기&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;프로젝트 생성 전 화면에서 아래 화면처럼 plugin을 선택합니다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignLeft&quot; width=&quot;50%&quot; data-origin-width=&quot;2234&quot; data-origin-height=&quot;1674&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Bcaof/btqJP63zQli/Q5NXrY1DsDkwYHzxESrPbK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Bcaof/btqJP63zQli/Q5NXrY1DsDkwYHzxESrPbK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Bcaof/btqJP63zQli/Q5NXrY1DsDkwYHzxESrPbK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FBcaof%2FbtqJP63zQli%2FQ5NXrY1DsDkwYHzxESrPbK%2Fimg.png&quot; width=&quot;50%&quot; data-origin-width=&quot;2234&quot; data-origin-height=&quot;1674&quot; data-ke-mobilestyle=&quot;widthContent&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;/li&gt;
&lt;li&gt;
&lt;p&gt;plugin -&amp;gt; Marketplace에서 scala 검색 후 설치하고 Intellij를 재시작 합니다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignLeft&quot; width=&quot;50%&quot; data-origin-width=&quot;1998&quot; data-origin-height=&quot;1756&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/moYyT/btqJKwIWM5k/eT29pfmHTzjN42LRnSKQF0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/moYyT/btqJKwIWM5k/eT29pfmHTzjN42LRnSKQF0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/moYyT/btqJKwIWM5k/eT29pfmHTzjN42LRnSKQF0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmoYyT%2FbtqJKwIWM5k%2FeT29pfmHTzjN42LRnSKQF0%2Fimg.png&quot; width=&quot;50%&quot; data-origin-width=&quot;1998&quot; data-origin-height=&quot;1756&quot; data-ke-mobilestyle=&quot;widthContent&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;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;1.2. 실행 해 보기&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;기본 적인 실행은 아래와 같이 object를 만들고 extends app을 사용하여 실행합니다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;sbt를 사용하기 원하시면 젤 하단에 sbt shell에서 test나 run을 실행 시키실 수 있습니다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignLeft&quot; width=&quot;50%&quot; data-origin-width=&quot;2946&quot; data-origin-height=&quot;2076&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/myN4H/btqJP6P1t3n/qSgQp2ZZ8cxHl9F96ncjU1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/myN4H/btqJP6P1t3n/qSgQp2ZZ8cxHl9F96ncjU1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/myN4H/btqJP6P1t3n/qSgQp2ZZ8cxHl9F96ncjU1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmyN4H%2FbtqJP6P1t3n%2FqSgQp2ZZ8cxHl9F96ncjU1%2Fimg.png&quot; width=&quot;50%&quot; data-origin-width=&quot;2946&quot; data-origin-height=&quot;2076&quot; data-ke-mobilestyle=&quot;widthContent&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;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;</description>
      <category>IT Book Study/러닝 스칼라</category>
      <category>IntelliJ</category>
      <category>Scala</category>
      <category>러닝 스칼라</category>
      <category>러닝스칼라</category>
      <category>스칼라</category>
      <author>jmkim87</author>
      <guid isPermaLink="true">https://kid1412.tistory.com/236</guid>
      <comments>https://kid1412.tistory.com/236#entry236comment</comments>
      <pubDate>Mon, 28 Sep 2020 22:51:02 +0900</pubDate>
    </item>
    <item>
      <title>깔끔한 파이썬 탄탄한 백엔드 -8-</title>
      <link>https://kid1412.tistory.com/235</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/t6CLX/btqH0piUbkn/7N6NgbuwZeoLpfU0HCVQl1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/t6CLX/btqH0piUbkn/7N6NgbuwZeoLpfU0HCVQl1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/t6CLX/btqH0piUbkn/7N6NgbuwZeoLpfU0HCVQl1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Ft6CLX%2FbtqH0piUbkn%2F7N6NgbuwZeoLpfU0HCVQl1%2Fimg.jpg&quot; width=&quot;100%&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;h2&gt;8. Unit Test&lt;/h2&gt;
&lt;p&gt;기능을 개발하고 나서 제대로 돌아가는지 매번 수동으로 API를 쏠수 없으니 Unit Test를 하여 각 기능들이 제대로 돌아가는지 테스트를 해야합니다.&lt;/p&gt;
&lt;h3&gt;UI test / End-to-End Test&lt;/h3&gt;
&lt;p&gt;웹브라우저를 통해서 웹사이트를 실제로 접속하고 UI에 직접 입력하고 클릭하는 등을 통해서 기능을 정상적으로 작동하고 화면이 정상적으로 작동하는지 테스트 해보는 방식&lt;/p&gt;
&lt;p&gt;아래는 웹 UI test하는 툴입니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Selenium&lt;/li&gt;
&lt;li&gt;Katalon&lt;/li&gt;
&lt;li&gt;Protractor&lt;/li&gt;
&lt;li&gt;CasperJS&lt;/li&gt;
&lt;li&gt;PhantomJS&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Integration test(통합 테스트)&lt;/h3&gt;
&lt;p&gt;각 기능(모듈)을 통합하는 과정에서 모듈간 호환성의 문제를 찾아내기 위해 수행되는 테스트&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;빅뱅 통합 : 전체 모듈을 모두 통합한 이후 통합 테스트를 수행하는 방식. (서비스 전체를 한번에 유저 시나리오로 테스트 하는 방식)&lt;/li&gt;
&lt;li&gt;점진적 통합 : 한번에 모듈을 통합하지 않고 하향식/상향식 기법으로 점진적으로 통합하면서 테스트 하는 방식 (시나리오 하나씩 붙이면서 테스트를 하는 방식)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Unit Test&lt;/h3&gt;
&lt;p&gt;각각 기능 하나에 대해서 코드 테스트를 합니다.&lt;/p&gt;
&lt;p&gt;python3에서 uniittest라는 모듈이 탑재되어 있지만 좀더 쓰기 편한 pytest를 사용합니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;테스트를 할 파일명은 test_ 를 붙여야 합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;# test_minitter.py
import pytest
import bcrypt
import json
import config
import sys
from sqlalchemy import create_engine, text
sys.path.append(&amp;#39;../&amp;#39;)
from app import create_app

database = create_engine(config.test_config[&amp;#39;DB_URL&amp;#39;], encoding=&amp;#39;utf-8&amp;#39;, max_overflow=0)

@pytest.fixture
def api():
    app = create_app(config.test_config)
    app.config[&amp;#39;TESTING&amp;#39;] = True
    api = app.test_client()

    return api

def setup_function():
    hashed_password = bcrypt.hashpw(b&amp;quot;test password&amp;quot;, bcrypt.gensalt())
    new_users = [
        {
            &amp;quot;id&amp;quot;: 1,
            &amp;quot;name&amp;quot;: &amp;quot;test1&amp;quot;,
            &amp;quot;email&amp;quot;: &amp;quot;test1@test.com&amp;quot;,
            &amp;quot;profile&amp;quot;: &amp;quot;test1 profile&amp;quot;,
            &amp;quot;hashed_password&amp;quot;: hashed_password
        },
        {
            &amp;quot;id&amp;quot;: 2,
            &amp;quot;name&amp;quot;: &amp;quot;test2&amp;quot;,
            &amp;quot;email&amp;quot;: &amp;quot;test2@test.com&amp;quot;,
            &amp;quot;profile&amp;quot;: &amp;quot;test2 profile&amp;quot;,
            &amp;quot;hashed_password&amp;quot;: hashed_password
        }
    ]

    database.execute(text(&amp;quot;&amp;quot;&amp;quot;
        INSERT INTO users (
            id,
            name,
            email,
            profile,
            hashed_password
        ) VALUES (
            :id,
            :name,
            :email,
            :profile,
            :hashed_password
        )
    &amp;quot;&amp;quot;&amp;quot;), new_users)

    database.execute(text(&amp;quot;&amp;quot;&amp;quot;
        INSERT INTO tweets (
            user_id,
            tweet
        ) VALUES (
            2,
            &amp;quot;Hello World!&amp;quot;
        )
    &amp;quot;&amp;quot;&amp;quot;))

def teardown_function():
    database.execute(text(&amp;quot;SET FOREIGN_KEY_CHECKS=0&amp;quot;))
    database.execute(text(&amp;quot;TRUNCATE users&amp;quot;))
    database.execute(text(&amp;quot;TRUNCATE tweets&amp;quot;))
    database.execute(text(&amp;quot;TRUNCATE users_follow_list&amp;quot;))
    database.execute(text(&amp;quot;SET FOREIGN_KEY_CHECKS=1&amp;quot;))

def test_ping(api):
    resp = api.get(&amp;#39;/ping&amp;#39;)
    assert b&amp;#39;pong&amp;#39; in resp.data

def test_login(api):
    resp = api.post(
        &amp;#39;/login&amp;#39;,
        data = json.dumps({&amp;#39;email&amp;#39;: &amp;#39;test1@test.com&amp;#39;, &amp;#39;password&amp;#39;: &amp;#39;test password&amp;#39;}),
        content_type = &amp;#39;application/json&amp;#39;
    )
    assert b&amp;quot;access_token&amp;quot; in resp.data

def test_unauthorized(api):
    resp = api.post(
        &amp;#39;/tweet&amp;#39;,
        data = json.dumps({&amp;#39;tweet&amp;#39;: &amp;#39;Hello World!&amp;#39;}),
        content_type = &amp;#39;application/json&amp;#39;
    )
    assert resp.status_code == 401

    resp = api.post(
        &amp;#39;/follow&amp;#39;,
        data = json.dumps({&amp;#39;follow&amp;#39;: 2}),
        content_type = &amp;#39;application/json&amp;#39;
    )
    assert resp.status_code == 401

    resp = api.post(
        &amp;#39;/unfollow&amp;#39;,
        data = json.dumps({&amp;#39;unfollow&amp;#39;: 2}),
        content_type = &amp;#39;application/json&amp;#39;
    )
    assert resp.status_code == 401

def test_tweet(api):
    resp = api.post(
            &amp;#39;/login&amp;#39;,
            data = json.dumps({&amp;#39;email&amp;#39;: &amp;#39;test1@test.com&amp;#39;, &amp;#39;password&amp;#39;: &amp;#39;test password&amp;#39;}),
            content_type = &amp;#39;application/json&amp;#39;
            )
    resp_json = json.loads(resp.data.decode(&amp;#39;utf-8&amp;#39;))
    access_token = resp_json[&amp;#39;access_token&amp;#39;]

    resp = api.post(
        &amp;#39;/tweet&amp;#39;,
        data = json.dumps({&amp;#39;tweet&amp;#39;: &amp;quot;Hello World!&amp;quot;}),
        content_type = &amp;#39;application/json&amp;#39;,
        headers = {&amp;#39;Authorization&amp;#39;: access_token}
    )
    assert resp.status_code == 200

    resp = api.get(f&amp;#39;/timeline/1&amp;#39;)
    tweets = json.loads(resp.data.decode(&amp;#39;utf-8&amp;#39;))

    assert resp.status_code == 200
    assert tweets == {
        &amp;quot;user_id&amp;quot;: 1,
        &amp;quot;timeline&amp;quot;: [
            {
                &amp;quot;user_id&amp;quot;: 1,
                &amp;quot;tweet&amp;quot;: &amp;quot;Hello World!&amp;quot;
            }
        ]
    }

def test_follow(api):
    resp = api.post(
        &amp;#39;/login&amp;#39;,
        data = json.dumps({&amp;#39;email&amp;#39;: &amp;#39;test1@test.com&amp;#39;, &amp;#39;password&amp;#39;: &amp;#39;test password&amp;#39;}),
        content_type = &amp;#39;application/json&amp;#39;
    )
    resp_json = json.loads(resp.data.decode(&amp;#39;utf-8&amp;#39;))
    access_token = resp_json[&amp;#39;access_token&amp;#39;]

    resp = api.get(f&amp;#39;/timeline/1&amp;#39;)
    tweets = json.loads(resp.data.decode(&amp;#39;utf-8&amp;#39;))

    assert resp.status_code ==200
    assert tweets == {
        &amp;#39;user_id&amp;#39;: 1,
        &amp;#39;timeline&amp;#39;: []
    }

    resp = api.post(
        &amp;#39;/follow&amp;#39;,
        data = json.dumps({&amp;#39;id&amp;#39;: 1, &amp;#39;follow&amp;#39;: 2}),
        content_type = &amp;#39;application/json&amp;#39;,
        headers = {&amp;#39;Authorization&amp;#39;: access_token}
    )

    assert resp.status_code == 200

    resp = api.get(f&amp;#39;/timeline/1&amp;#39;)
    tweets = json.loads(resp.data.decode(&amp;#39;utf-8&amp;#39;))

    assert resp.status_code == 200
    assert tweets == {
        &amp;#39;user_id&amp;#39;: 1,
        &amp;#39;timeline&amp;#39; : [
            {
                &amp;#39;user_id&amp;#39;: 2,
                &amp;#39;tweet&amp;#39;: &amp;#39;Hello World!&amp;#39;
            }
        ]
    }

def test_unfollow(api):
    resp = api.post(
        &amp;#39;/login&amp;#39;,
        data = json.dumps({&amp;#39;email&amp;#39;: &amp;#39;test1@test.com&amp;#39;, &amp;#39;password&amp;#39;: &amp;#39;test password&amp;#39;}),
        content_type = &amp;#39;application/json&amp;#39;
    )
    resp_json = json.loads(resp.data.decode(&amp;#39;utf-8&amp;#39;))
    access_token = resp_json[&amp;#39;access_token&amp;#39;]

    resp = api.post(
        &amp;#39;/follow&amp;#39;,
        data = json.dumps({&amp;#39;id&amp;#39;: 1, &amp;#39;follow&amp;#39;: 2}),
        content_type = &amp;#39;application/json&amp;#39;,
        headers = {&amp;#39;Authorization&amp;#39;: access_token}
    )
    assert resp.status_code == 200

    resp = api.get(f&amp;#39;/timeline/1&amp;#39;)
    tweets = json.loads(resp.data.decode(&amp;#39;utf-8&amp;#39;))

    assert resp.status_code == 200
    assert tweets == {
        &amp;quot;user_id&amp;quot; : 1,
        &amp;quot;timeline&amp;quot;: [
            {
                &amp;quot;user_id&amp;quot;: 2,
                &amp;quot;tweet&amp;quot;: &amp;quot;Hello World!&amp;quot;
            }
        ]
    }

    resp = api.post(
        &amp;#39;/unfollow&amp;#39;,
        data = json.dumps({&amp;#39;id&amp;#39;: 1, &amp;#39;unfollow&amp;#39;: 2}),
        content_type = &amp;#39;application/json&amp;#39;,
        headers = {&amp;#39;Authorization&amp;#39;: access_token}
    )

    assert resp.status_code == 200

    resp = api.get(f&amp;#39;/timeline/1&amp;#39;)
    tweets = json.loads(resp.data.decode(&amp;#39;utf-8&amp;#39;))

    assert resp.status_code == 200
    assert tweets == {
        &amp;quot;user_id&amp;quot;: 1,
        &amp;quot;timeline&amp;quot;: []
    }&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;위와 같이 작성합니다.&lt;/li&gt;
&lt;li&gt;assert로 값 비교하여 true이면 pass 입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;$&amp;gt; pytest -p no:warnings -vv -s
================================================= test session starts ==================================================
platform linux -- Python 3.6.5, pytest-5.4.1, py-1.8.1, pluggy-0.13.1 -- /project/huggingfaceAPI/venv/bin/python
cachedir: .pytest_cache
rootdir: /project/huggingfaceAPI/test
collected 6 items

test_minitter.py::test_ping PASSED
test_minitter.py::test_login PASSED
test_minitter.py::test_unauthorized PASSED
test_minitter.py::test_tweet PASSED
test_minitter.py::test_follow PASSED
test_minitter.py::test_unfollow PASSED

================================================== 6 passed in 11.87s ==================================================&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;위와 같이 깔끔하게 나오면 됩니다.&lt;/li&gt;
&lt;li&gt;teardown_function 함수로 test시작 전/후에 실행시킵니다. 내용은 DB 초기화 입니다.&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>IT Book Study/깔끔한 파이썬 탄탄한 백엔드</category>
      <category>backend</category>
      <category>flask</category>
      <category>Integration test</category>
      <category>Python</category>
      <category>Unit Test</category>
      <category>백엔드</category>
      <category>파이썬</category>
      <author>jmkim87</author>
      <guid isPermaLink="true">https://kid1412.tistory.com/235</guid>
      <comments>https://kid1412.tistory.com/235#entry235comment</comments>
      <pubDate>Thu, 3 Sep 2020 22:48:47 +0900</pubDate>
    </item>
    <item>
      <title>깔끔한 파이썬 탄탄한 백엔드 -7-</title>
      <link>https://kid1412.tistory.com/234</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/KigfU/btqH0pXvSri/RSdFJ7j4nuQOgDPCCSnUq0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/KigfU/btqH0pXvSri/RSdFJ7j4nuQOgDPCCSnUq0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/KigfU/btqH0pXvSri/RSdFJ7j4nuQOgDPCCSnUq0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FKigfU%2FbtqH0pXvSri%2FRSdFJ7j4nuQOgDPCCSnUq0%2Fimg.jpg&quot; width=&quot;100%&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;h2&gt;7. 인증&lt;/h2&gt;
&lt;p&gt;인증은 private api와 같은 사용자를 제한해야하는 api에서 필요하며, public api와 같은 경우 사용 횟수 제한이나 남용 방지등을 위해 쓰입니다. &lt;/p&gt;
&lt;h3&gt;인증 흐름&lt;/h3&gt;
&lt;p&gt;인증을 생성 및 사용 방법은 대략적으로 아래와 같습니다. &lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;회원 가입을 진행할때 api에 id/pw를 api에 보냅니다.&lt;/li&gt;
&lt;li&gt;회원 가입 api에서 id/pw를 체크하고 별 문제 없으면 DB에 저장합니다. 이때 id는 그대로 저장하며 pw는 암호화해서 저장합니다. &lt;/li&gt;
&lt;li&gt;회원 가입이 완료 되면 로그인 합니다. 이때 들어온 id와 pw를 DB에 저장된 값과 비교합니다. (pw는 암호화한 후 암호화로 저장된 DB와 비교합니다.)&lt;/li&gt;
&lt;li&gt;로그인이 OK가 되면 이때 access token을 만들어서 front-end에 전송합니다. &lt;/li&gt;
&lt;li&gt;Front-end에서는 이제 API를 사용할 때 access-token을 같이 보내어 사용 가능한 사용자라는 것을 확인 시켜줍니다. access-token이 만료되지만 않으면 재로그인을 하지 않고 계속 token으로 통신이 가능합니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;비밀번호 암호화&lt;/h3&gt;
&lt;p&gt;암호화에는 두가지 방식이 있습니다. &lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://images.velog.io/images/jmkim87/post/d9db50bc-2967-4c19-98e2-e20820ddbb37/img1.daumcdn.jpg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;일반적으로 비밀번호를 암호화 할때는 단방향 암호화  방식을 사용합니다. 다만 md5나 sha1 같은 경우 rainbow table과 같은 hash table로 깨지기 쉽기 때문에 깨기 어렵게 하는 hash 알고리즘을 사용합니다. &lt;/p&gt;
&lt;p&gt;여기서 사용할 것은 &lt;strong&gt;bcrypt&lt;/strong&gt; 알고리즘입니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;salting&lt;/strong&gt; : 비밀번호에 랜덤 값을 더해서 해시화 (다만 salt에 쓰는 키값은 서버나 conf 파일 같은 곳에 저장되는 경우가 많기 때문에 서버 자체의 보안에 조심해야합니다.)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;키 스트레칭(Key stretching)&lt;/strong&gt; : 단방향 해시 값을 계산후 그 해시값을 또 해시하는 방법으로 여러번 반복 합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;참고 : &lt;a href=&quot;https://namu.wiki/w/%EC%95%94%ED%98%B8%20%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98&quot;&gt;https://namu.wiki/w/암호 알고리즘&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;JWT&lt;/h3&gt;
&lt;p&gt;access token을 만드는 방법은 다양하지만 여기서는 많이 쓰이는 JWT를 사용합니다. &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;구조&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;header : 토큰 타입과 사용되는 해시 알고리즘을 지정합니다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;payload : 실제로 서버 간에 전송하고자 하는 데이터 부분. 다만 base64로 암호화하는거라 민감한 데이터는 넣지 말아야 합니다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;signature : BASE64URL 코드화된 header와 payload 그리고 JWT secret를 헤더에 지정된 암호 알고리즘으로 암호화하여 전송&lt;/p&gt;
&lt;p&gt;참고 : &lt;a href=&quot;https://medium.com/sjk5766/jwt-json-web-token-%EC%86%8C%EA%B0%9C-49e211c65b45&quot;&gt;https://medium.com/sjk5766/jwt-json-web-token-소개-49e211c65b45&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;decorator 함수&lt;/h3&gt;
&lt;p&gt;우리는 http header에 access token이 있는지 특정 api에서 검사를 할 decorator를 만들어야 합니다. 다른 파일들처럼 decorator를 따로 작성합니다. &lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;# decorator.py
import jwt
from api import *
from functools import wraps
from flask import request, Response, current_app, g

def login_required(f):
    @wraps(f)
    def decorated_function(*args, **kwargs):
        access_token = request.headers.get(&amp;#39;Authorization&amp;#39;)
        if access_token is not None:
            try:
                payload = jwt.decode(access_token, current_app.config[&amp;#39;JWT_SECRET_KEY&amp;#39;], &amp;#39;HS256&amp;#39;)
            except jwt.InvalidTokenError:
                payload = None

            if payload is None: return Response(status = 401)

            user_id = payload[&amp;#39;user_id&amp;#39;]
            g.user_id = user_id
            g.user = get_user(user_id) if user_id else None
        else:
            return Response(status=401)
        return f(*args, **kwargs)
    return decorated_function&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;Http header에 Authorization에 access token이 있는지 확인합니다.&lt;/li&gt;
&lt;li&gt;없으면 401을 반환 합니다.&lt;/li&gt;
&lt;li&gt;있으면 JWT로 decode하여 user_id값을 global로 설정합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Authorization이 필요한 API에 decorator를 설정 합니다. &lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;# app.py
@app.route(&amp;#39;/tweet&amp;#39;, methods=[&amp;#39;POST&amp;#39;])
@login_required
def tweet():
    user_tweet = request.json
    user_tweet[&amp;#39;id&amp;#39;] = g.user_id
    tweet = user_tweet[&amp;#39;tweet&amp;#39;]

    if len(tweet) &amp;gt; 300:
        return &amp;#39;300자를 초과했습니다.&amp;#39;, 400

    insert_tweet(user_tweet)

    return &amp;#39;&amp;#39;, 200

@app.route(&amp;#39;/follow&amp;#39;, methods=[&amp;#39;POST&amp;#39;])
@login_required
def follow():
    payload = request.json
    payload[&amp;#39;id&amp;#39;] = g.user_id

    insert_follow(payload)

    return &amp;#39;&amp;#39;, 200

@app.route(&amp;#39;/unfollow&amp;#39;, methods=[&amp;#39;POST&amp;#39;])
@login_required
def unfollow():
    payload = request.json
    payload[&amp;#39;id&amp;#39;] = g.user_id

    insert_unfollow(payload)

    return &amp;#39;&amp;#39;, 200&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;tweet, follow, unfollow에는 auth가 필요하기에 decorator를 설정합니다.&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>IT Book Study/깔끔한 파이썬 탄탄한 백엔드</category>
      <category>backend</category>
      <category>flask</category>
      <category>Python</category>
      <category>백엔드</category>
      <category>파이썬</category>
      <author>jmkim87</author>
      <guid isPermaLink="true">https://kid1412.tistory.com/234</guid>
      <comments>https://kid1412.tistory.com/234#entry234comment</comments>
      <pubDate>Thu, 3 Sep 2020 22:47:39 +0900</pubDate>
    </item>
  </channel>
</rss>