<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>veloggggg</title>
        <link>https://velog.io/</link>
        <description></description>
        <lastBuildDate>Sat, 22 May 2021 15:16:08 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <copyright>Copyright (C) 2019. veloggggg. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/keep_going" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[미니 프로젝트]]></title>
            <link>https://velog.io/@keep_going/%EB%AF%B8%EB%8B%88-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8</link>
            <guid>https://velog.io/@keep_going/%EB%AF%B8%EB%8B%88-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8</guid>
            <pubDate>Sat, 22 May 2021 15:16:08 GMT</pubDate>
            <description><![CDATA[<p>spring-boot, mysql, thymeleaf 개발 환경 셋팅. </p>
<p>ide intellij 사용</p>
<p>하루 공부시간과 일정을 기록하고 관리해주는 프로그램</p>
<p>셋팅 : java 8, spring boot 2.5.0, gradle </p>
<p>gradle : spring we,b mysql driver, thymeleaf, spring boot devtools, lombok</p>
<p>기능 1) 로그인, 회원가입.</p>
<p>   version
   java 8 spring boot 2.5.0, gradle</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[불친절한 SQL 프로그래밍]]></title>
            <link>https://velog.io/@keep_going/%EB%B6%88%EC%B9%9C%EC%A0%88%ED%95%9C-SQL-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D</link>
            <guid>https://velog.io/@keep_going/%EB%B6%88%EC%B9%9C%EC%A0%88%ED%95%9C-SQL-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D</guid>
            <pubDate>Thu, 14 Jan 2021 13:43:20 GMT</pubDate>
            <description><![CDATA[<p><img src="https://images.velog.io/images/keep_going/post/82db70a3-2e8a-442a-a438-b007bf9367de/4.PNG" alt=""></p>
<h3 id="목차">목차</h3>
<h4 id="1부-기본-개념">1부 기본 개념</h4>
<ul>
<li>데이터, 데이터 모델링 오라클 데이터베이스, SQL에 대한 내용 수록.<h4 id="2부-기본-쿼리">2부 기본 쿼리</h4>
</li>
<li>SELECT문, 단일 행 함수, WHERE 절, ORDER BY절 집계 함수, GROUP BY절과 HAVING절<h4 id="3부-중급-쿼리">3부 중급 쿼리</h4>
</li>
<li>조인, 서브쿼리, 집합 연산자, 분석 함수, Top-N 쿼리, 계층 쿼리, PRIVOT 절과 UNPIVOT절<h4 id="4부-관리-구문">4부 관리 구문</h4>
</li>
<li>DML문, TCS문, DDL문, SCS 문</li>
<li>SCS 문은 애플리케이션 개발과 관련된 구문으로 데이터, 트랜잭션, 세션을 관리한다.<h4 id="5부-고급-쿼리">5부 고급 쿼리</h4>
</li>
<li>시간대 지원, 정규 표현식, 근사 쿼리, MODEL절, MATCH_RECOGNIZE 절, 사용자 정의 타입, XML개발, JSON개발, Flashback 기술, 제공 패키지에 대한 내용 수록. </li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[아마존 웹 서비스 부하 테스트 입문]]></title>
            <link>https://velog.io/@keep_going/%EC%95%84%EB%A7%88%EC%A1%B4-%EC%9B%B9-%EC%84%9C%EB%B9%84%EC%8A%A4-%EB%B6%80%ED%95%98-%ED%85%8C%EC%8A%A4%ED%8A%B8-%EC%9E%85%EB%AC%B8</link>
            <guid>https://velog.io/@keep_going/%EC%95%84%EB%A7%88%EC%A1%B4-%EC%9B%B9-%EC%84%9C%EB%B9%84%EC%8A%A4-%EB%B6%80%ED%95%98-%ED%85%8C%EC%8A%A4%ED%8A%B8-%EC%9E%85%EB%AC%B8</guid>
            <pubDate>Thu, 14 Jan 2021 12:21:38 GMT</pubDate>
            <description><![CDATA[<p><img src="https://images.velog.io/images/keep_going/post/2549d55d-c75e-45ba-89bd-350b8ab85f43/Test.PNG" alt=""></p>
<blockquote>
<p>적절한 부하 테스트를 할 수 있다면 우리의 서비스에 맞는 인프라 구조와 규모를 산정해 운영하면 비용을 절감할 수 있다.<br>    확장성을 가지며 가용성이 높은 시스템을 만들어야 하는 시스템 담당자를 위해 필요한 내용을 &quot;클라우드를 이용한 설계&quot;와 &quot;부하 테스트&quot; 그리고 그에 필요한 사전 지식, 구체적인 방법, 사례 등을 통해 설명하고 있다. </p>
</blockquote>
<hr>
<h2 id="목차">목차</h2>
<h4 id="1장-부하-테스트의-문제와-웹-시스템의-실패-사례">1장 부하 테스트의 문제와 웹 시스템의 실패 사례</h4>
<h4 id="2장-웹-시스템-설계-방법">2장 웹 시스템 설계 방법.</h4>
<h4 id="3장-부하-테스트-기본-지식">3장 부하 테스트 기본 지식</h4>
<h4 id="4장-부하-테스트-도구">4장 부하 테스트 도구</h4>
<h4 id="5장-부하-테스트-계획">5장 부하 테스트 계획</h4>
<h4 id="6장-부하-테스트-준비">6장 부하 테스트 준비</h4>
<h4 id="7장-부하-테스트-실행1-테스트-실행과-병목-현상-확인">7장 부하 테스트 실행1 (테스트 실행과 병목 현상 확인)</h4>
<h4 id="8장-부하-테스트-실행2-원인-분석과-시스템-개선-작업">8장 부하 테스트 실행2 (원인 분석과 시스템 개선 작업)</h4>
<h4 id="9장-부하-테스트-보고서-작성">9장 부하 테스트 보고서 작성</h4>
<h4 id="10장-부하-테스트에-대한-실제-사례">10장 부하 테스트에 대한 실제 사례</h4>
<h4 id="11장-용어-설명">11장 용어 설명</h4>
<h4 id="12장-aws-로드-테스팅">12장 AWS 로드 테스팅</h4>
<p><br/><br/></p>
<hr>
<h3 id="부하-테스트와-pdca-사이클">부하 테스트와 PDCA 사이클</h3>
<p>PDCA 사이클이라는 것은 Plan- Do - Check - Action을 반복하는 것을 말한다. </p>
<ul>
<li>Plan : 부하 테스트 계획 수립. </li>
<li>Do : 부하 테스트 준비와 실행</li>
<li>Check : 계획한 목표값과 전제 조건을 만족했는지, 의미 있는 숫자가 나왔는지 확인. </li>
<li>Action : 부하 테스트 보고서 작성과 시스템 개선, 목표값과 전제 조건을 검토한 다음 PDCA와 연결. </li>
</ul>
<p>PDCA를 한 번에 전체적으로 진행하는 것은 많은 작업이 발생하므로 시간과 리소스 낭비가 많아지고 위험성이 높아질 것이다.</p>
<hr>
<h3 id="대상-독자">대상 독자</h3>
<ul>
<li>안정적인 웹 시스템을 운용해야 하는 분. </li>
<li>현재 웹 시스템 부하로 인해 고민하는 분. </li>
<li>부하 테스트를 처음 시작하려고 하는 분.</li>
<li>부하 테스트를 과거에 몇 번이고 해봤지만, 결과에 자신이 없는 분. </li>
<li>시스템 설계에서 구축까지 한 번 더 공부하고 싶은 분. </li>
</ul>
<hr>
<h3 id="🔥-부하-테스트의-문제와-웹-시스템의-실패-사례">🔥 부하 테스트의 문제와 웹 시스템의 실패 사례.</h3>
<ul>
<li>잘못된 개발 일정. </li>
<li>잘못된 테스트 전제 조건. 
(결정된 사항과 시나리오) </li>
<li>잘못된 테스트 준비.</li>
<li>잘못된 테스트 실행. </li>
<li>잘못된 테스트 보고서</li>
</ul>
<p>&quot; 현재 세상에는 대규모 웹 시스템이 운용되고 있지만, 그 뒤에는 부하 대책에 실패한 시스템이 많이 존재한다. 겉으로는 안정적으로 운용되고 있는 것처럼 보이지만, 사용자 수가 없어서 문제없는 것이지 실제 예상했던 많은 사용자가 요청하게 되면 버티지 못하는 웹 시스템도 있다.&quot;</p>
<p><BR/><BR/></p>
<hr>
<h3 id="🔥-웹-시스템-설계-방법">🔥 웹 시스템 설계 방법.</h3>
<h4 id="1--높은-가용성을-가진-시스템-설계-방법">1.  높은 가용성을 가진 시스템 설계 방법.</h4>
<ul>
<li><p>시스템을 이중화한다.</p>
<ul>
<li>시스템 이중화라는 것은 시스템의 일부분을 사용할 수 없게 되어도 다른 시스템을 이용하여 서비스를 계속하는 것을 의미한다.</li>
<li>여기서 대체 시스템이 독립된 별도의 시스템이어야 한다는 것이다.</li>
<li>백업한 데이터는 같은 시스템에 저장되어 있어 서버에 장애가 발생하면 원본 데이터도 백업 데이터도 사용할 수 없게 된다. </li>
</ul>
</li>
<li><p>시스템을 확장한다.</p>
</li>
</ul>
<blockquote>
<p><strong>DB 이중화는 기본적으로 어렵다.</strong> 
*<em>DB 이중화를 한 경우 하드웨어뿐만 아니라 데이터베이스 안에 저장된 데이터도 이중화해야만 한다. *</em></p>
</blockquote>
<ol>
<li>여러 대의 DB에 같은 데이터를 저장하고 참고한다.</li>
<li>한쪽의 데이터를 저장하고 자동으로 반대쪽 데이터를 동기화한다. 다운이 발생했을 때 다른 한쪽의 DB를 이용한다.<blockquote>
<blockquote>
<p><strong>1의 경우에는 쓰기, 읽기 모두 응답 속도의 저하를 막을 수 없다. 데이터가 맞지 않을 때는 어떻게 복구할지에 대한 문제도 발생한다.</strong></p>
</blockquote>
</blockquote>
</li>
</ol>
<p><strong>2의 경우에는 다운이 발생했을 때 한쪽을 사용할 수 있게 하는 페일오버(Fail Over) 작업이 어렵진 않지만, 자동으로 데이터 동기화가 어렵다 .Sync 방식은 동기화 중에 처리 지연에 따른 성능 저하가 발생할 수 있으며, Async의 경우에는 DB 간의 데이터 무결성 문제가 발생할 수 있다 .</strong></p>
<h4 id="2-시스템-확장-">*<em>2. 시스템 확장. *</em></h4>
<p>( 요구되는 시스템 성능에 따라 동적으로 서버 구성이 변경되고 시스템의 처리 능력을 최적화할 수 있는 시스템을 확장 가능한 시스템이라고 한다 .)</p>
<h4 id="확장가능한-시스템을-구축하는-3가지-방법">확장가능한 시스템을 구축하는 3가지 방법.</h4>
<p><strong>1) 스케일 업/ 스케일 다운 한다.</strong></p>
<ul>
<li>시스템의 성능을 높이기 위해 병목이 되는 부분의 시스템 리소스를 보다 높은 성능으로 변경하는 것을 스케일 업. </li>
<li>반대로 낮은 성능으로 변경하는 것을 슼일 다운
ex) AWS의 EC2 인스턴스나 RDS 인스턴스의 경우 인스턴스 타입을 변경하는 것이 이에 속한다.</li>
</ul>
<p><strong>2) 스케일 아웃/ 스케일 인 한다.</strong></p>
<ul>
<li>AWS에서 웹 서비스를 구축할 때 AWS에서 제공하는 로드 밸런서 서비스인 ELB(Elastic Load Balancing)을 이용하여 애플리케이션 서버 대수를 동적으로 늘리고 줄이는 것이 가능하다.</li>
</ul>
<p>*<em>3) 클라우드 사업자가 확장성을 보증하는 서비스를 사용한다. *</em></p>
<ul>
<li>Route 53(DNS 제공 서비스), CloudFront(CDN 제공 서비스), Elastic Load Balancing(로드 밸런서 제공 서비스), S3(스토리지 제공 서비스) </li>
</ul>
<p><BR/><BR/></p>
<h4 id="-3-클라우드에서의-시스템-구축-">** 3. 클라우드에서의 시스템 구축. **</h4>
<p>&quot; 클라우드는 가장 큰 장점은 서버 리소스 추가가 아주 빠르고 서버 리소스 추가 자동화가 가능하다는 것이다. 온프레미스에서는 몇 주에서 몇 개월이 걸렸던 작업이 클라우드에서는 단 몇 분 만에 사용 중인 서버를 복제하여 새로운 서버를 구축할 수 있다. </p>
<BR/>

<h4 id="✔--클라우드-디자인-패턴을-사용한-고가용성높은-확장성의-시스템-구축">✔  클라우드 디자인 패턴을 사용한 고가용성/높은 확장성의 시스템 구축.</h4>
<p>-** AWS에서 사용 가능한 대표적인 클라우드 디자인 패턴**</p>
<ul>
<li><p>EC3 인스턴스를 이용한 동적 콘텐츠 배포.</p>
</li>
<li><p>S3를 이용한 정적 콘텐츠 배포.</p>
</li>
<li><p>동적 콘텐츠와 정적 콘텐츠.</p>
</li>
<li><p>서버리스 아키텍처를 이용한 동적 웹 서비스 구축. </p>
</li>
<li><p>RDS를 이용한 RDB 구축.</p>
</li>
</ul>
<blockquote>
<ul>
<li>부하테스트는 가용성과 확장성이 높은 시스템을 구축하기 위한 방법이다.</li>
<li>온프레미스에서 가용성과 확장성이 높은 시스템을 구축하긴 어렵다.</li>
<li>클라우드 디자인 패턴을 활용하면 가용성과 확장성이 높은 시스템을 쉽게 구축할 수 있다. </li>
</ul>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[1장 클라우드와 아마존 웹 서비스]]></title>
            <link>https://velog.io/@keep_going/1%EC%9E%A5-%ED%81%B4%EB%9D%BC%EC%9A%B0%EB%93%9C%EC%99%80-%EC%95%84%EB%A7%88%EC%A1%B4-%EC%9B%B9-%EC%84%9C%EB%B9%84%EC%8A%A4</link>
            <guid>https://velog.io/@keep_going/1%EC%9E%A5-%ED%81%B4%EB%9D%BC%EC%9A%B0%EB%93%9C%EC%99%80-%EC%95%84%EB%A7%88%EC%A1%B4-%EC%9B%B9-%EC%84%9C%EB%B9%84%EC%8A%A4</guid>
            <pubDate>Thu, 14 Jan 2021 11:28:58 GMT</pubDate>
            <description><![CDATA[<h3 id="클라우드-컴퓨터란">클라우드 컴퓨터란?</h3>
<p>: 개인용 컴퓨터보다 성능이 뛰어난 컴퓨터나 저장장치 등의 컴퓨터 자원을 다른 곳에서 빌려 사용할 수 있도록 처리해주는 IT 기술이다. </p>
<p><BR/><bR/></p>
<h3 id="클라이드-서비스-이용-방식">클라이드 서비스 이용 방식.</h3>
<p><img src="https://images.velog.io/images/keep_going/post/a1c67bd2-7a68-4c51-aed9-59417fbf30ed/cloud.png" alt=""></p>
<ul>
<li><p>IaaS ( Infrastructure-as-a-service) : 물리적 서버(CPU, Memory 및 OS), 네트워크, 스토리지를 가상화하여 다수의 고객을 대상으로 유연하게 제공하는 인프라 서비스</p>
</li>
<li><p>PaaS(Platform-as-a-service) : Web 기반의 서비스 또는 애플리케이션 등의 개발 및 실행을 위한 표준 플랫폼 환경을 서비스 형태로 제공하는 서비스</p>
</li>
<li><p>SaaS(Software-as-a-service) : 구글의 Gmail이나 MS Office 365 등과 같이 응용 프로그램 및 인터넷 및 웹 브라우저를 통해 제공하는 서비스</p>
</li>
</ul>
<p><br/><br/></p>
<h3 id="클라이드-컴퓨팅의-장점-및-혜택">클라이드 컴퓨팅의 장점 및 혜택</h3>
<ul>
<li>초기 투자 비용이 발생하지 않으며, 사용한 만큼 지불하면 된다.</li>
<li>규모의 경제를 통해 지속적인 인하를 실형한다.</li>
<li>미래에 필요한 인프라의 용량을 추정할 필요가 없다.</li>
<li>속도 및 민첩성이 향상된다.</li>
<li>데이터 센터 운영 및 유지 관리에 비용 투자가 필요하지 않는다.</li>
<li>몇 분 만에 전세계에 서비스를 런칭하거나 배포할 수 있다. </li>
</ul>
<p><br/><br></p>
<h3 id="aws-의-주요-서비스">AWS 의 주요 서비스</h3>
<ul>
<li><h4 id="컴퓨팅-서비스">컴퓨팅 서비스</h4>
</li>
<li><em>1) Amazon EC2(Elastic Compute Cloud)*</em> : 다양한 형태의 타입과 서비스에 따라 적합한 사양을 선택할 수 있으며, 사용량만큼 비용을 지불하는 컴퓨팅 서비스이다.)</li>
<li><em>2) Amazon Auto Scaling*</em> : 서버의 특정 조건에 따라 서버를 추가/삭제할 수 있게 해주는 서비스로 서버 사용량이 많은 경우 추가로 생성하고, 사용하지 않는 경우 서버를 자동으로 삭제할 수 있게 해주는 서비스이다.</li>
<li><em>3) Amazon Lightsail*</em> : 간단한 가상화 프라이빗 서버(Virtual Private Server, 이하 VPS)가 필요한 개발자에게 웹 사이트와 웹 애플리케이션을 배포하고 관리하는 기능과 컴퓨팅, 스토리지, 네트워크를 빠르고, 손쉽게 저렴한 비용으로 제공</li>
<li><em>4) Amazon Workspace *</em> : 데스크톱 가상화 서비스로 사내 pc를 가상화로 구성하여, 문서 및 데이터를 개인 pc에 보관하지 않고 서버에서 보관 관리할 수 있도록 해주는 서비스이다.</li>
</ul>
<ul>
<li><h4 id="네트워킹-서비스">네트워킹 서비스</h4>
</li>
<li><ul>
<li>1) Amazon Route 53** : 가용성과 확장성이 우수한 클라우드 기반의 Domain Name System(DNS) 웹 서비스로, 사용자의 요청을 AWS에서 실행되는 다양한 인프라에 효과적으로 연결할 수 있다. 또한 사용자를 AWS외부의 인프라로 전달하는 서비스도 Route 53를 사용할 수 있다. </li>
</ul>
</li>
<li><ul>
<li>2) Amazon VPC(Virtual Private Cloud) ** : 가상 사설 네트워크 인프라를 클라우드 내에 생성/구성하고, 네트워크를 이용한 접근 제어(Security Group, NACL), DHCP 및 VPN 연결, 인터넷 게이트웨이 등의 서비스 제공과 타 VPC와 다른 리전 간 VPC Peering 구성을 통해 보안성 및 안정성이 높은 네트워킹 서비스를 제공한다.</li>
</ul>
</li>
<li><ul>
<li>3) AWS Direct Connect** : 기존 On-Premise의 인프라와 AWS를 연결하는 전용선을 구성하여, 낮은 지연 시간으로 데이터 및 정보를 공유할 수 있게 하는 서비스를 제공한다. AWS-On-Premise를 연결하는 전용선 서비스이다.</li>
</ul>
</li>
<li><ul>
<li>4) Amazon ELB(Elastic Load Balancer) ** : Load Balance 서비스라고 생각하면 이해하기 쉽다. 웹 서버 및 각종 서버에 사용량과 접속자가 많은 경우 트래픽에 대한 부하 분산을 통해 네트워크 트래픽을 인스턴스로 전달한다.</li>
</ul>
</li>
</ul>
<ul>
<li><h4 id="스토리지-서비스">스토리지 서비스</h4>
</li>
<li><ul>
<li>1) Amazon S3 ** : 여러 가지 용도로 사용할 수 있는 범용적인 스토리지 서비스로 데이터 보관 이외에도 정적 웹 사이트 호스팅 및 다양한 형태의 서비스로 활용 가능한 만능 스토리지 서비스이다.</li>
</ul>
</li>
<li><ul>
<li>2) Amazon Glacier ** : 사용 빈도가 높지 않는 데이터를 저렴한 비용으로 장기 보관할 수 있게 해주는 서비스로 가격이 저렴하고 무제한으로 데이터를 보관할 수 있는 장점을 가지고 있는 스토리지 서비스이다.</li>
</ul>
</li>
<li><ul>
<li>3) Amazon EBS(Elastic Block Storage) ** : 빠른 속도로 데이터를 저장 보관할 수 있는 서비스로 주로 서버에 디스크로 추가하여 데이터를 보관 제공할 수 있으며, 기본으로 SSD를 사용하여 데이터 입출력 속도가 매우 빠르고, 고성능의 서비스를 필요로 하는 스토리지 서비스에 적합한 서비스이다.</li>
</ul>
</li>
<li><p><em>4) AWS Snowball *</em> : Import/Export 서비스를 통해 대량의 데이터를 AWS로 이전할 때 네트워크로 전송하지 않고 디스크나 스토리지에 저장하여 물리적으로 전달하고 이를 업로드하여 주는 서비스로 대량의 데이터를 AWS로 업로드할 때 유용한 서비스이다.</p>
</li>
<li><h3 id="데이터베이스-서비스">데이터베이스 서비스</h3>
</li>
<li><ul>
<li>1) Amazon RDS ** : 관계형 데이터베이스 서비스인 MSSQL, Oracle, MySQL, MarinaDB, PostreSQL 등 RDBMS 서비스를 사용자가 직접 관리하지 않고, Amazon에서 제공하는 서비스를 이용하여 데이터베이스를 이용할 수 있도록 해준다. </li>
</ul>
</li>
<li><ul>
<li>2) Amazon DynamoDB ** : NoSQL 용 서비스로 대량의 데이터를 손쉽게 저장할 수 있고, 이렇게 저장된 데이터를 추가 분석 서비스와 연계 활용할 수 있도록 확장할 수 있는 서비스이다.</li>
</ul>
</li>
<li><ul>
<li>3) Amazon ElastiCache ** : In-Memory 기반의 Cache 서비스로 빠른 속도를 필요로 하는 서비스와 연계하여 높은 응답속도와 신뢰성을 필요로 하는 서비스에 적합한 서비스이다.</li>
</ul>
</li>
<li><h3 id="분석-플랫폼">분석 플랫폼.</h3>
</li>
<li><ul>
<li>1) Amazon Kinesis** : 대량의 데이터를 저장 분류할 수 있는 서비스이다. 다양한 규모의 스트리밍 데이터를 비용 효율적으로 처리할 수 있는 기능과 애플리케이션 요구사항에 따라 가장 적합한 도구를 선택할 수 있는 유연성을 제공한다. 또는 기계학습, 분석 및 기타 애플리케이션을 위해 비디오, 오디오, 애플리케이션 로그, 웹 사이트 클릭스트림 및 IoT 텔레메트리 데이터와 같은 실시간 데이터를 수집할 수 있다.</li>
</ul>
</li>
<li><ul>
<li>2) Amazon Redshift ** : 데이터 웨어하우스와 데이터 레이크 전체에 걸쳐 간단하며, 효율적으로 비용 모든 데이터를 분석할 수 있는 빠르고 확장 가능한 데이터 웨어하우스이다. RedShift는 기계학습, 대량 병령 쿼리 실행, 고성능 디스크의 열 기반 스토리지를 사용하여 다른 데이터 웨어하우스보다 10배 빠른 성능을 제공한다.</li>
</ul>
</li>
<li><p><em>3) Amazon EMR *</em> : 저장된 대량의 데이터를 분류하고 분석하여 필요한 정보를 뽑아낼 수 있도록 다양한 서비스를 제공한다.</p>
</li>
<li><h3 id="애플리케이션-서비스">애플리케이션 서비스</h3>
</li>
<li><ul>
<li>1) Amazon CloudSearch ** : 검색 서비스이며, SWF는 워크플로우 서비스, SQS는 큐서비스를 활용한 대량의 데이터를 할 수 있도록 해주는 서비스로, 손쉽게 중요 정보를 모바일로 전달할 수 있는 서비스이다.</li>
</ul>
</li>
<li><ul>
<li>2) Amazon SES ** : 외부로 대량의 메일을 발송하는 서비스이다.</li>
</ul>
</li>
<li><ul>
<li>3) Amazon Elastic Transcoder ** : 동영상을 인코딩할 수 있는 서비스이다.</li>
</ul>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Apache2 설치 중 에러 발생.]]></title>
            <link>https://velog.io/@keep_going/Apache2-%EC%84%A4%EC%B9%98-%EC%A4%91-%EC%97%90%EB%9F%AC-%EB%B0%9C%EC%83%9D</link>
            <guid>https://velog.io/@keep_going/Apache2-%EC%84%A4%EC%B9%98-%EC%A4%91-%EC%97%90%EB%9F%AC-%EB%B0%9C%EC%83%9D</guid>
            <pubDate>Tue, 12 Jan 2021 02:06:55 GMT</pubDate>
            <description><![CDATA[<h2 id="apache2-설치-에러">apache2 설치 에러</h2>
<pre><code>sudo apt-get install apache2
sudo apt-get remove apache2</code></pre><p><img src="https://images.velog.io/images/keep_going/post/f9b8d690-81d7-410a-ae70-fa19f4adbb14/image.png" alt=""></p>
<h4 id="🙈문제">🙈문제</h4>
<ul>
<li>apache2 설치 중 에러 발생.  </li>
</ul>
<h4 id="log-message">Log Message</h4>
<ul>
<li>apache2 설치 중 에러 메시지 출력  <span style="color:red">Failed to start The apache HTTP Server. </li>
</ul>
<h4 id="추론">추론</h4>
<ul>
<li>웹 서버 설치 시 순서가 꼬였을 가능성. </li>
</ul>
<h4 id="해결방안">해결방안</h4>
<ul>
<li><p>☒ apache2 삭제 후 재 설치 -&gt; 같은 원인 발생. </p>
<pre><code>sudo apt-get remove apache2
sudo apt-get remove --purge apache2 apache2-utils</code></pre></li>
<li><p>☑ 설치 후 아래 명령어 추가 -&gt; *<em>문제 해결 *</em></p>
<pre><code>sudo apt install --reinstall apache-bin
sudo service apache2 start</code></pre></li>
</ul>
<ul>
<li><strong>tomcat -&gt; apache2 -&gt; mod-jk 순으로 파일을 설치해야 한다.</strong> </li>
</ul>
<h4 id="원인">원인</h4>
<ul>
<li>서버에서 apache2 파일을 사용할 수 없다. /usr/sbin/apache2는 apache2-bin에서 제공되기 때문에 apache2-bin은 apache2 패키지의 종속성이므로 apache2가 없으면 제대로 작동하지않는다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Ubuntu 서버 셋팅]]></title>
            <link>https://velog.io/@keep_going/Ubuntu-%EC%84%9C%EB%B2%84-%EC%85%8B%ED%8C%85</link>
            <guid>https://velog.io/@keep_going/Ubuntu-%EC%84%9C%EB%B2%84-%EC%85%8B%ED%8C%85</guid>
            <pubDate>Mon, 11 Jan 2021 13:37:09 GMT</pubDate>
            <description><![CDATA[<br/>

<blockquote>
<p>** 🙋🏻‍♂️ Ubuntu에서 Java, apache, tomcat, mysql 환경 구축을 해보자.**</p>
</blockquote>
<br/>



<h3 id="작업하기-전에-알아야-할-4가지">작업하기 전에 알아야 할 4가지.</h3>
<p>☑ <strong>기본적인 Linux 명령어와 Vi 명령어 알고 있는지?</strong>
☐ <strong>apache/tomcat directory 구조를 알고 있는지?</strong>
☐ <strong>수정할 설정 파일의 위치 접근방법 알고 있는지?</strong>
☐ <strong>vhost에 대해 알고 있는지?</strong></p>
<p><br/><br/><Br/></p>
<hr>
<h3 id="목차"><strong>목차.</strong></h3>
<h4 id="-1-java-8-설치-환경-변수-설정">** 1. Java 8 설치/ 환경 변수 설정.**</h4>
<h4 id="-2-apache-tomcat-설치-연동-모듈_mod-jk">** 2. apache, tomcat 설치.(+ 연동 모듈_mod-jk)**</h4>
<h4 id="-3-workerproperties-000-defaultconf-serverxml-설정-변경-">** 3. worker.properties, 000-default.conf, server.xml 설정 변경 **</h4>
<h4 id="-4-mysql-설치-">** 4. mysql 설치 **</h4>
<h4 id="-5-mysql-설치-후-외부-접근-가능하도록">** 5. mysql 설치 후 외부 접근 가능하도록**</h4>
<h4 id="-6-apache-가상-호스트-설치하기-">** 6. apache 가상 호스트 설치하기 **</h4>
<br/>

<hr>
<h3 id="수정해야할-파일-위치">수정해야할 파일 위치</h3>
<p> ** <span style="color:blue">✔ mod-jk 설정</span>  :  workers.properties  **</p>
<ul>
<li>파일 위치 : /etc/libapache2-mod-jk/workers.properties</li>
</ul>
<ul>
<li>확인 내용 : tomcat_home 경로, java_home 경로 맞는지 확인.</li>
</ul>
<p>**<span style="color:blue">✔ tomcat 설정</span> : server.xml ** </p>
<ul>
<li>etc/tomcat9/server.xml <br/>

</li>
</ul>
<p>✔ **<span style="color:blue">apache 설정</span> : 000-default.conf **  (가상호스트 기본 설정값 파일)</p>
<ul>
<li>/etc/apache2/sites-available/000-default.conf</li>
</ul>
<br/>

<hr>
<h3 id="port-정보">port 정보</h3>
<ul>
<li>8080 포트는 기본적으로 설정되어 있는 포트</li>
<li>8005 포트는 http 프로토콜을 처리하기 위한 내부포트</li>
<li>8009 포트는 mod-jk를 통해 apache 서비스와 통신하기 위한 포트.</li>
</ul>
<hr>
<p><br/><Br/></p>
<blockquote>
<h3 id="1-java-8-설치-환경-변수-설정">1. Java 8 설치/ 환경 변수 설정</h3>
</blockquote>
<pre><code>sudo apt-get update
sudo apt-get install openjdk-8-jdk
java -version
vi ~/.bashrc

# path  설정
export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64
export PATH=&quot;$PATH:$JAVA_HOME/bin&quot;

#적용 확인
source ~/.bashrc
echo $JAVA_HOME
( /usr/lib/jvm/java-8-openjdk-amd64 가 출력 확인.)</code></pre><br/>




<blockquote>
<h3 id="2-apache-tomcat-설치--연동-모듈_mod-jk">2. apache tomcat 설치 (+ 연동 모듈_mod-jk)</h3>
</blockquote>
<h4 id="🔥-웹-서버-설치-시-순서가-중요하다--순서가-바뀌면-에러가-발생할-수-있음">🔥 웹 서버 설치 시 순서가 중요하다. ( 순서가 바뀌면 에러가 발생할 수 있음)</h4>
<p>** Step1) tomcat 설치 **</p>
<pre><code>sudo apt-get install tomcat9 </code></pre><p><strong>Step2) apache2 설치</strong></p>
<pre><code>sudo apt-get update
sudo apt-get install apache2
apache2 -v</code></pre><p><strong>Step3) 아파치 톰캣 연동 모듈 설치</strong></p>
<pre><code>sudo apt-get install libapache2-mod-jk</code></pre><br/>


<blockquote>
<h3 id="3-workerproperties-000-defaultconf-serverxml-설정">3. worker.properties, 000-default.conf, server.xml 설정</h3>
</blockquote>
<pre><code>sudo nano /etc/libapache2-mod-jk/workers.properties</code></pre><ul>
<li><strong>worker.properties</strong>
  ❯ 현재 Java, tomcat 경로. 
<img src="https://images.velog.io/images/keep_going/post/e2418e59-a5e4-4c64-acd2-4b853f1438e2/image.png" alt=""><img src="https://images.velog.io/images/keep_going/post/61bc2869-d3e9-4b58-a27e-dba54a5e0775/image.png" alt="">❯ Java, tomcat 실제 경로 확인 후 -&gt; 경로 수정<img src="https://images.velog.io/images/keep_going/post/7cd06dfc-da70-4e67-a055-56ecca760140/image.png" alt=""><img src="https://images.velog.io/images/keep_going/post/849f053d-b605-4b6f-94e7-34e1b8fca283/image.png" alt=""></li>
</ul>
<br/>

<pre><code>sudo nano /etc/tomcat9/server.xml
</code></pre><ul>
<li><strong>server.xml</strong>
❯ 세가지 확인
<img src="https://images.velog.io/images/keep_going/post/2aff7185-a44e-4924-9e01-39edfe2e07e1/image.png" alt="">: connector 포트 기입. 방화벽도 열어주어야 한다.
<img src="https://images.velog.io/images/keep_going/post/bdd3a5ed-e6d1-4d85-ade5-b29b80707509/image.png" alt=""><img src="https://images.velog.io/images/keep_going/post/d07b1ec3-3aa5-4944-a737-015852dfbf33/image.png" alt=""> : path는 프로젝트의 경로이다.(대부분 빈칸) docBase는 소스의 경로이다.<img src="https://images.velog.io/images/keep_going/post/6ad3c505-0675-47f7-9dfa-43686fda6a04/image.png" alt=""></li>
</ul>
<br/>


<pre><code>sudo nano /etc/apache2/sites-available/000-default.conf</code></pre><ul>
<li><strong>000-default.conf</strong>
  ❯ </li>
</ul>
<blockquote>
<h3 id="4-mysql-설치">4. mysql 설치</h3>
</blockquote>
<pre><code>코드를 입력하세요</code></pre><blockquote>
<h3 id="5-mysql-설치-후-외부-접근-가능하도록">5. mysql 설치 후 외부 접근 가능하도록</h3>
</blockquote>
<pre><code>코드를 입력하세요</code></pre><blockquote>
<h3 id="6--apache-가상-호스트-설치하기">6.  apache 가상 호스트 설치하기</h3>
</blockquote>
<pre><code>코드를 입력하세요</code></pre><p><br/><br/><br/><br/><br/><br/></p>
<hr>
<h4 id="vi-명령어"><strong>VI 명령어</strong></h4>
<p>:norm i# - # 모양의 주석 들어감.</p>
<p>:norm 1x - 앞쪽 1개의 문자가 지워짐. </p>
<p><BR/><BR/></p>
<h3 id="apache-tomcat-apache-디렉토리-구조">Apache tomcat, Apache 디렉토리 구조.</h3>
<table>
<thead>
<tr>
<th align="left">apache</th>
<th align="center">apache tomcat</th>
</tr>
</thead>
<tbody><tr>
<td align="left"><strong>웹 ROOT 디렉토리 : /var/www/html</strong></td>
<td align="center">** HOME 디렉토리 : /usr/share/tomcat9/**</td>
</tr>
<tr>
<td align="left"><strong>conf 디렉토리 : /etc/apache2</strong></td>
<td align="center"><strong>CONF 디렉토리 : /etc/tomcat9/</strong></td>
</tr>
<tr>
<td align="left">** LOG 디렉토리 : /var/log/apache2**</td>
<td align="center">** LOG 디렉토리 /var/log/tomcat9/**</td>
</tr>
<tr>
<td align="left"></td>
<td align="center">** 웹ROOT 디렉토리 : /var/lib/tomcat9/**</td>
</tr>
</tbody></table>
<br/>

<h3 id="설정-디렉토리-구조">설정 디렉토리 구조</h3>
<ul>
<li>/etc/apache2 : 설정파일 루트 위치</li>
<li>/etc/apache2/apache2.conf : 기본 설정 파일로, 다른 배포판은 httpd.conf를 사용.<pre><code>                               (우분투에서는 apache2.conf사용)</code></pre></li>
<li>/etc/apache2/envvars : apache2ctl 환경 설정 파일</li>
<li>/etc/apache2/magic : 파일의 시작값(magic number) 데이터베이스, 이 값에 기반해 전송하는 파일의 MIME Type을 결정한다. </li>
<li>/etc/apache2/mods-available : 사용가능한 apache 모듈을 불러오는 곳. </li>
<li>/etc/apache2/mods-enabled : 위의 mods-available 모듈 중에 사용할 모듈을 심볼릭 링크로 추가하여 동작하게 만든다.</li>
<li>/etc/apache2/ports.conf : apache 서버의 서비스 포트설정으로 http의 기본 값 80과 https의 기본값 443, 가상호스트 포트들을 설정할 수 있다. </li>
<li>/etc/apache2/sites-available : 서버에서 운영할 사이트의 설정 파일</li>
<li>/etc/apache2/sited-enabled : 위의 sites-available에서 설정한 파일을 심볼릭 링크로 추가하여 실제 운영에 사용할 설정 파일들. </li>
</ul>
<br/>

]]></description>
        </item>
        <item>
            <title><![CDATA[AWS]]></title>
            <link>https://velog.io/@keep_going/AWS</link>
            <guid>https://velog.io/@keep_going/AWS</guid>
            <pubDate>Sun, 10 Jan 2021 15:20:04 GMT</pubDate>
            <description><![CDATA[<h3 id="아마존-웹-서비스-aws--amazon-discovery-book">아마존 웹 서비스 AWS ( Amazon Discovery Book)</h3>
<p><img src="https://images.velog.io/images/keep_going/post/9db04889-4fee-4d66-beb7-3ca2a92536cd/1.PNG" alt=""></p>
<p>위 책을 보고 정리한 내용입니다.</p>
<p><a href="https://blog.naver.com/saga111">https://blog.naver.com/saga111</a></p>
<p>참고 페이지 
<a href="https://aws.amazon.com/ko/what-is-cloud-computing/">https://aws.amazon.com/ko/what-is-cloud-computing/</a>
<a href="https://www.aws.training/">https://www.aws.training/</a>
<a href="https://aws.amazon.com/ko/developer/">https://aws.amazon.com/ko/developer/</a></p>
<h2 id="목차">목차</h2>
<h3 id="1장-클라우드와-아마존-웹-서비스">1장 클라우드와 아마존 웹 서비스</h3>
<h3 id="2장-확장성과-안정성-높은-서버-만들기">2장 확장성과 안정성 높은 서버 만들기</h3>
<h3 id="3장-무한대로-저장-가능한-스토리지-만들기">3장 무한대로 저장 가능한 스토리지 만들기</h3>
<h3 id="4장-독립적인-나만의-가상-네트워크-공간-만들기">4장 독립적인 나만의 가상 네트워크 공간 만들기</h3>
<h3 id="5장-확장-가능한-데이터베이스-서버-만들기">5장 확장 가능한 데이터베이스 서버 만들기</h3>
<h3 id="6장-dns를-손쉽게-연결하고-관리하기">6장 DNS를 손쉽게 연결하고 관리하기</h3>
<h3 id="7장-네트워크-트래픽을-분산시켜-주는-로드밸런싱">7장 네트워크 트래픽을 분산시켜 주는 로드밸런싱</h3>
<h3 id="8장-가용성-높고-빠르게-확장-가능한-인프라-구성하기">8장 가용성 높고 빠르게 확장 가능한 인프라 구성하기</h3>
<h3 id="9장-cdn-서비스로-웹-사이트의-속도를-더욱-빠르게-하기">9장 CDN 서비스로 웹 사이트의 속도를 더욱 빠르게 하기</h3>
<h3 id="10장-클라우드-자원과-리소스-관리하기">10장 클라우드 자원과 리소스 관리하기</h3>
<h3 id="11장-알뜰하고-저렴하게-나만의-서버-만들기">11장 알뜰하고 저렴하게 나만의 서버 만들기</h3>
<h3 id="12장-aws-자격증-취득에-도전해보기">12장 AWS 자격증 취득에 도전해보기</h3>
<h3 id="13장-aws-training-계정-생성-및-시험-신청-방법">13장 AWS Training 계정 생성 및 시험 신청 방법</h3>
]]></description>
        </item>
        <item>
            <title><![CDATA[Real MySQL]]></title>
            <link>https://velog.io/@keep_going/Real-MySQL</link>
            <guid>https://velog.io/@keep_going/Real-MySQL</guid>
            <pubDate>Sun, 10 Jan 2021 15:19:02 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[리포지터리와 모델 구현(JPA 중심)]]></title>
            <link>https://velog.io/@keep_going/%EB%A6%AC%ED%8F%AC%EC%A7%80%ED%84%B0%EB%A6%AC%EC%99%80-%EB%AA%A8%EB%8D%B8-%EA%B5%AC%ED%98%84JPA-%EC%A4%91%EC%8B%AC</link>
            <guid>https://velog.io/@keep_going/%EB%A6%AC%ED%8F%AC%EC%A7%80%ED%84%B0%EB%A6%AC%EC%99%80-%EB%AA%A8%EB%8D%B8-%EA%B5%AC%ED%98%84JPA-%EC%A4%91%EC%8B%AC</guid>
            <pubDate>Sun, 10 Jan 2021 02:53:30 GMT</pubDate>
            <description><![CDATA[<p>이 장의 주제는 리포지터리 구현이다.</p>
<h3 id="jpa를-이용한-리포지터리-구현">JPA를 이용한 리포지터리 구현</h3>
<ul>
<li><p>애그리거트를 이떤 저장소에 저장하느냐에 따라 리포지터리를 구현하는 방법이 다르기 때문에 모든 구현 기술에 대해 알 수는 없다. </p>
</li>
<li><p>도메인 모델과 리포지터리를 구현할 때 선호하는 기술을 꼽자면 JPA를 들 수 있다.</p>
</li>
<li><p>ORM 표준인 JPA를 이용해서 리포지터리와 애그리거트를 구현하는 방법에 대해 살펴보자.</p>
</li>
</ul>
<hr>
<h3 id="리포지터리-기본-기능-구현">리포지터리 기본 기능 구현.</h3>
<ul>
<li>아이디로 애그리거트 조회하기</li>
<li>애그리거트 저장하기</li>
</ul>
<pre><code>public interface OrderRepository{
    public Order findById(OrderNo no);
        public void save(Order order);
}</code></pre><p>: 주문 애그리거트는 Order 루트 엔티티를 비롯패 OrderLine, Orderer, ShippingInfo 등 다양한 객체를 포함하는데, 이 구성 요소 중에서 Order 루트 엔티티를 기준으로 리포지터리 인터페이스를 작성한다.</p>
<p>&quot;findById()는 아이디에 해당하는 애그리거트가 존재하면 Order를 리턴하고, 존재하지 않으면 null을 리턴한다.&quot;</p>
<pre><code>import org.springframework.stereotype.Repository;
import shop.order.domain.Order;
import shop.order.domain.OrderNo;
import shop.order.domain.OrderRepository;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

@Repository
public class JpaOrderRepository implements OrderRepository{
    @PersistenceContext
    private EntityManager entityManager; 

    @Override
    public Order findById(OrderNo id){
        return entityManager.find(Order.class, id);
    }

    @Override
    public void save(Order order){
        entityManager.persist(order);
    }

}</code></pre><p>애그리거트를 수정한 결과를 저장소에 반영하는 메서드를 추가할 필요는 없다.
JPA를 사용하면 트랜잭션 범위에서 변경한 데이터를 자동으로 반영하기 때문이다.</p>
<hr>
<h3 id="매핑-구현">매핑 구현</h3>
<h4 id="엔티티와-벨류-기본-매핑-구현">엔티티와 벨류 기본 매핑 구현</h4>
<ul>
<li>애그리거트 루트는 엔티티이므로 @Entity로 매핑 설정한다.</li>
<li>한 테이블에 엔티티와 밸류 데이터가 같이 있다면, 
( 밸류는 @Embeddable로 매핑 설정/ 밸류 타입 프로퍼티는 @Embedded 매핑 설정한다. ) </li>
</ul>
<p><strong>Order 애그리거트 루트 엔티티는 @Embedded를 이용해서 밸류 타입 프로퍼티를 설정한다.</strong></p>
<pre><code>@Entity
public class Order{
    @Embedded
        private Orderer orderer;

        @Embedded
        private ShippingInfo shippingInfo;

}
</code></pre><p>** JPA의 @Entity와 @Embeddable로 클래스를 매핑하려면 기본 생성자를 제공해야 한다. **</p>
<ul>
<li>하이버네이트와 같은 JPA 프로바이더는 DB에 데이터를 읽어와 매핑된 객체를 생성할 때 기본 생성자를 사용해서 객체를 생성한다. <pre><code>@Embeddable
public class Receiver{
  @Column(name = &quot;reveiver_name&quot;)
      private String name;
        @Column(name = &quot;receiver_phone&quot;)
      private String phone;

</code></pre></li>
</ul>
<pre><code>protected Receiver(){} // JPA를 적용하기 위해 기본 생성자 추가.

public Receiver(String name, String phone){
    this.name = name;
    this.phone = phone; 

}</code></pre><p>}</p>
<pre><code>
: 기본 생성자는 JPA 프로바이더가 객체를 생성할 때만 사용한다. 기본 생성자를 다른 코드에서 사용하면 값이 온전하지 못한 객체를 만들게 된다. 이런 이유로 다른 코드에서 기본 생성자를 사용하지 못하도록 protected를 선언한다.
&gt;  Hibernate는 클래스를 상속한 프록시 객체를 이용해서 지연 로딩을 구현한다. 이 경우 프록시 클래스에서 상위 클래스의 기본 생성자를 호출할 수 있어야 하므로 지연 로딩 대상이 되는 @Entity와 @Embeddable의 기본 생성자는 private이 아닌 protected로 지정해야 한다. </code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[애그리거트]]></title>
            <link>https://velog.io/@keep_going/%EC%95%A0%EA%B7%B8%EB%A6%AC%EA%B1%B0%ED%8A%B8</link>
            <guid>https://velog.io/@keep_going/%EC%95%A0%EA%B7%B8%EB%A6%AC%EA%B1%B0%ED%8A%B8</guid>
            <pubDate>Sat, 02 Jan 2021 08:35:10 GMT</pubDate>
            <description><![CDATA[<p><img src="https://images.velog.io/images/keep_going/post/2c8e62a9-fae7-4341-a15c-d6540a1c586f/image.png" alt=""></p>
<h4 id="주문은-상품-회원-결제와-관련이-있다는-것을-쉽게-파악할-수-있다">주문은 상품, 회원, 결제와 관련이 있다는 것을 쉽게 파악할 수 있다.</h4>
<p><br/><br/>
<img src="https://images.velog.io/images/keep_going/post/21bacb5b-7afd-49a9-b2dd-b20031b5f420/image.png" alt="">
위 그림처럼 개별 객체 수준에서 모델을 바라보면 상위 수준에서 관계를 파악하기 어렵다.
( 주요 도메인 개념 간의 관계를 파악하기 어렵다는 것은 곧 코드를 변경하고 확정하는 것이 어려워진다는 것을 의미한다.)</p>
<br/>

<p><img src="https://images.velog.io/images/keep_going/post/47942e0e-05c4-48cf-b2f8-6f38a3d29ba5/image.png" alt="">
동일한 모델이지만 애그리거트를 사용함으로써 모델 간의 관계를 개별 모델 수준뿐만 아니라 상위 수준에서도 이해할 수 있게 된다.</p>
<ul>
<li>모델을 보다 잘 이해할 수 있고 애그리커트 단위로 일관성을 관리하기 때문에 애그리거트는 복잡한 도메인을 단순한 구조로 만들어 준다.</li>
<li>복잡도가 낮아지는 만큼 도메인 기능을 확장하고 변경하는데 필요한 노력도 줄어든다.<br/>

</li>
</ul>
<blockquote>
<p>불필요한 중복을 피하고 애그리거트 루트를 통해서만 도메인 로직을 구현하게 만들려면 도메인 모델에 대해 다음의 두가지를 습관적으로 적용애야 한다. </p>
</blockquote>
<p>1) 단순히 필드를 변경하는 set 메서드를 공개(public) 범위로 만들지 않는다.
2) 밸류 타입은 불변으로 구현한다.</p>
<p><strong>도메인 모델의 엔티티나 밸류에 공개 set 메서드만 넣지 않아도 일관성이 깨질 가능성이 줄어든다.</strong></p>
<p>애그리거트 외부에서 내부 상태를 함부로 바꾸지 못하므로 애그리거트의 일관성이 깨질 가능성이 줄어든다. ( 즉, 다음과 같이 애그리거트 루트가 제공하는 메서드에 새로운 밸류 객체를 전달해서 값을 변경하는 방법밖에 없다.)</p>
<pre><code>public class Order{
    private ShippingInfo shippingInfo;
        public void changeShippingInfo(ShippingInfo newShippingInfo){
            verifyNotYetShipped();
                setShippingInfo(newShippingInfo);

        }
    // set 메서드의 접근 허용 범위는 private 이다.
        private void setShippingInfo(ShippingInfo newShippingInfo){
            // 벨류가 불변이면, 새로운 객체를 할당해서 값을 변경해야 한다.
                // 불변이므로 this.shippingInfo.setAddress(newShippingInfo.getAddress())와 같은
                // 코드를 사용할 수 없다.
                this.shippingInfo = newShippingInfo;

        }

}</code></pre><p>✔ 밸루 타입의 내부 상태를 변경하려면 애그리거트 루트를 통해서만 가능하다.</p>
<p><br/><br/><Br/></p>
<h3 id="애그리거트-루트의-기능-구현">애그리거트 루트의 기능 구현</h3>
<ul>
<li>애그리거트 루트는 애그리거트 내부의 다른 객체를 조합해서 기능을 완성한다.</li>
</ul>
<p><strong>방법1) Order는 총 주문 금액을 구하기 위해 OrderLine 목록을 사용한다.</strong></p>
<pre><code>public class Order{
    private Money totalAmounts;
        private List&lt;OrderLine&gt; orderLines;

        private void calculateTotalAmounts(){
            int sum = orderLines.stream()
                      .mapToInt(ol -&gt; ol.getPrice() * ol.quantity())
                             .sum();
                this.totalAmounts = new Money(sum);

        }

}</code></pre><pre><code>public class Member{
    private Password password;

        public void changedPassword(String currentPassword, String newPassword){
            if(!password.match(currentPassword)){
                    throw new PasswordNotMatchException();
            }
            this.password = new Password(newPassword);
        }

}</code></pre><p><Br/><Br/>
방법2) OrderLine 클래스를 별도 클래스로 분리했다고 가정. </p>
<pre><code>public class OrderLines{
    private List&lt;OrderLine&gt; lines; 

        public Money getTotalAmounts() {  };
        public void changeOrderLines(List&lt;OrderLine&gt; newLines){
            this.lines = newLines; 
        }

}</code></pre><pre><code>public class Order{
    private OrderLines orderLines; 

        public void changeOrderLines(List&lt;OrderLine&gt; newLines){
            orderLines.changeOrderLines(newLines);
                this.totalAmounts = orderLines.getTotalAmounts(); 

        }

}</code></pre><p>Order의 changeOrderLines() 메서드는 다음과 같이 내부의 orderLines 필드에 상태 변경을 위임하는 방식으로 기능을 구현. 
만약 Order가 getOrderLines()와 같이 OrderLines를 구현할 수 있는 메서드를 제공하면 애그리거트 외부에서 OrderLines의 기능을 실행할 수 있게 된다. </p>
<blockquote>
<p>팀 표준이나 구현 기술의 제약으로 OrderLines를 불변으로 구현할 수 없다면 Order-Lines의 변경 기능을 패키지나 protected 범위로 한정해서 외부에서 실행할 수 없도록 제한하는 방법이 있다. **보통 한 애그리거트에 속하는 모델은 한 패키지에 속하기 때문에 패키지나 protected 범위를 사용하면 애그리거트 외부에서 상태 변경 기능을 실행하는 것을 방지할 수 </p>
</blockquote>
<p><br/><Br/></p>
<h3 id="트랜잭션-범위">트랜잭션 범위</h3>
<p>: 트랜잭션의 범위는 작을수록 좋다. DB 테이블을 기준으로 한 트랜잭션이 한 개 테이블을 수정하는 것과 세 개의 테이블을 수정하는 것은 성능에 차이가 발생한다. 
(잠금 대상이 많아진다는 것은 그만큼 동시에 처리할 수 있는 트랜잭션 개수가 줄어든다는 것을 뜻하고 이는 전체적인 성능(처리량)을 떨어뜨린다. ) </p>
<p>✔ *<em>한 트랜잭션에서는 한 개의 애그리거트만 수정해야 한다. *</em>
한 트랜잭션에서 두 개 이상의 애그리거트를 수정하면 트랜잭션 충돌이 발생할 가능성이 더 높아지기 때문에 한번에 수정하는 애그리거트 개수가 많아질수록 전체 처리량이 떨어지게 된다.</p>
<br/>

<p><strong>1) 다른 애그리커트의 상태 변경의 잘못된 예</strong></p>
<pre><code>public class Order{
    private Orderer orderer;

        public void shipTo(ShippingInfo newShippingInfo, boolean useNewShippingAddrAsMemberAddr){
            verifyNotYetShipped();
               setShippingInfo(newShippingInfo);
                if(useNewShippingAddrAsMemberAddr){
                 //다른 애그리거트의 상태를 변경하면 안됨!
                    orderer.getCustomer().changeAddress(newShippingInfo.getAddress());
                }

        }
}</code></pre><p>애그리거트는 서로 최대한 독립적이어야 하는데 한 애그리거트가 다른 애그리거트의 기능에 의존하기 시작하면 애그리거트 간 결합도가 높아지게 된다.
(결합도가 높아지면 높아질수록 향후 수정 비용이 증가하므로 애그리거트에서 다른 애그리거트의 상태를 변경하지 말아야 한다.)</p>
<br/>

<pre><code>public class ChangeOrderService{
    // 두 개 이상의 애그리커트를 변경해야 하면,
        // 응용 서비스에서 각 애그리거트의 상태를 변경한다.
        @Transactional
        public void changedShippingInfo(OrderId id, ShippingInfo newShippingInfo, boolean useNewShippingAddrAsMemberAddr){
         Order order = orderRepository.findbyId(id);
            if(order == null) throw new OrderNotFoundException();
                order.shipTo(newShippingInfo);
                if(useNewshippingAddrAsMemberAddr){
                    order.getOrderer()
                        .getCustomer().changedAddress(newShippingInfo.getAddress());
                }


        }
}</code></pre><blockquote>
<p>다음의 경우는 한 트랜잭션에서 두 개 이상의 애그리거트를 변경하는 것을 고려할 수 있다.</p>
</blockquote>
<ul>
<li>팀 표준 : 팀이나 조직의 표준에 따라 사용자 유스케이스와 관련된 응용 서비스의 기능을 한 트랜잭션으로 실행해야 하는 경우가 있다. </li>
<li>기술 제약 : 한 트랜잭션에서 두 개 이상의 애그리거트를 수정하는 대신 도메인 이벤트와 비동기를 사용하는 방식을 사용하는데, 기술적으로 이벤트 방식을 도입할 수 없는 경우 한 트랜잭션에서 다수의 애그리거트를 수정해서 일관성을 처리해야 한다. </li>
<li>UI 구현의 편리 : 운영자의 편리함을 위해 주문 목록 화면에서 여러 주문의 상태를 한 번에 변경하고 싶을 것이다. 이 경우 한 트랜잭션에서 여러 주문 애그리거트의 상태를 변경할 수 있을 것이다.</li>
</ul>
<BR/>

<hr>
<BR/>

<h3 id="리포지터리와-애그리거트">리포지터리와 애그리거트</h3>
<p>Order와 OrderLine을 물리적으로 각각 별도의 DB 테이블에 저장한다고 해서 Order와 OrderLine을 위한 리포지터리를 각각 만들지 않는다. 
(Order가 애그리거트 루트이고 OrderLine인 애그리커트에 속하는 구성요소이므로 Order를 위한 리포지터리만 존재한다. ) </p>
<BR/>

<p>✔ 새로운 애그리거트를 만들면 2가지 메소드가 필요하다.</p>
<ul>
<li>save : 애그리거트 저장. </li>
<li>findById : ID로 애그리거트를 구함. </li>
</ul>
<br/>
애그리거트를 영속화할 저장소로 무엇을 사용하든지 간에 애그리거트의 상태가 변경되면 모든 변경을 원자적으로 저장소에 반영해야 한다. 
<BR/>
(애그리거트에서 두 개의 객체를 변경했는데 저장소에는 한 객체에 대한 변경만 반영되면 데이터 일관성이 깨지므로 문제가 된다.)
<BR/><bR/>

<hr>
<h3 id="id를-이용한-애그리거트-참조">ID를 이용한 애그리거트 참조</h3>
<p>JPA를 사용하면 @ManyToOne, @OneToOne과 같은 애노테이션을 이용해서 연관된 객체를 로딩하는 기능을 제공하고 있으므로 필드를 이용해서 다른 애그리거트를 쉽게 참조할 수 있다. 
(ORM 기술 덕에 애그리거트 루트에 대한 참조를 쉽게 구현할 수 있고, 필드를 이용한 애그리거트 참조를 사용하면 다른 애그리커트의 데이터를 객체 탐색을 통해 조회할 수 있다.)</p>
<p>✔ 애그리거트 참조의 문제점. </p>
<ul>
<li>편한 탐색 오용</li>
<li>성능에 대한 고민</li>
<li>확장 어려움. </li>
</ul>
<p><BR/><BR/>
🔥 <strong>편한 탐색 오용</strong>
&quot;애그리거트를 직접 참조할 때 발생할 수 있는 가장 큰 문제점은 편리함을 오용할 수 있다는 것이다. 한 애그리거트 내부에서 다른 애그리거트 객체에 접근할 수 있으면 다른 애그리거트의 상태를 쉽게 변경할 수 있게 된다. ( 트랜재견 범위에서 언급한 것처럼 한 애그리커트가 관리하는 범위는 자기 자신으로 한정해야 한다. 그런데, 애그리거트 내부에서 다른 애그리거트 객체에 접근할 수 있으면 다음 코드처럼 구현의 편리함 때문에 다른 애그리거트를 수정하고자 하는 유혹에 빠지기 쉽다. ) </p>
<p>-&gt; 한 애그리거트에서 다른 애그리거트의 상태를 변경하는 것은 애그리거트 간의 의존 결합도를 높여서 결과적으로 애그리거트의 변경을 어렵게 만든다.</p>
<br/>
<bR/>

<p>🔥 <strong>성능에 대한 고민</strong></p>
<p>JPA를 사용할 경우 참조한 객체를 지연(lazy) 로딩과 즉시(eager) 로딩의 두 가지 방식으로 로딩할 수 있다. 두 로딩 방식 중 무엇을 사용할지 여부는 애그리거트의 어떤 기능을 사용하느냐에 따라 달라진다. </p>
<p>단순히 연관된 객체의 데이터를 함께 화면에 보여주어야 하면 즉시 로딩이 조회 성능에 유리하지만, 애그리거트의 상태를 변경하는 기능을 실행하는 경우에는 불필요한 객체를 함께 로딩할 필요가 없으므로 지연 로딩이 유리하다.</p>
<br/>


<p>🔥 확장 어려움
사용자가 늘고 트래픽이 증가하면 자연스럽게 부하를 분산하기 위해 하위 도메인별로 시스템을 분리하기 시작한다. 
이 과정에서 후위 도메인마다 서로 다른 DBMS를 사용할 가능성이 높아진다. 심지어 하위 도메인마다 다른 종류의 데이터 저장소를 사용하기도 한다. </p>
<blockquote>
<p>이 세가지 문제를 완화할 때 사용할 수 있는 것이 ID를 이용해서 다른 애그리거트를 참조하는 것이다. </p>
</blockquote>
<br/>

<hr>
<br/>

<h3 id="id를-이용한-참조와-조회-성능">ID를 이용한 참조와 조회 성능.</h3>
<p>다른 애그리거트를 ID로 참조하는 여러 애그리거트를 읽어야 할 조회 속도가 문제될 수 있다. </p>
<p>애그리거트마다 서로 다른 저장소를 사용하는 경우에는 한 번의 쿼리로 관련 애그리거트를 조회할 수 없다. 이런 경우 조회 성능을 높이기 위해 캐시를 적용하거나 조회 전용 저장소를 따로 구성한다.
이 방법은 코드가 복잡해지는 단점이 있지만 시스템의 처리량을 높일 수 있다는 장점이 있다. 
한 대의 DB 장비로 대응할 수 없는 수준의 트래픽이 발생하는 경우 캐시나 조회 전용 저장소는 필수로 선택해야 하는 기법이다.</p>
<hr>
<h3 id="애그리거트-간-집합-연관">애그리거트 간 집합 연관</h3>
<p>이 절에서는 애그리거트 간 1:N과 M:N 연관에 대해 살펴보자. 이 두 연관은 컬렉션을 이용한 연관이다. 카테고리와 상품 간의 연관이 대표적이다. </p>
<p>애그리거트 간 1:N 관계는 Set과 같은 컬렉션을 이용해서 표현할 수 있다. </p>
<p>1) 1:N 연관 카테고리</p>
<pre><code>public class Category{
    private Set&lt;Product&gt; products;

        public List&lt;Product&gt; getProducts(int page, int size){
            List&lt;Product&gt; sortedProducts = sortById(products);
                return sortedProducts.subList((page - 1 )  * size, page * size);

        }


}</code></pre><p>이 코드를 실제 dbms와 연동해서 구현하면 Category에 속한 모든 Product를 조회하게 된다. Product 개수가 수백에서 수만개 정도로 많다면 이 코드를 실행할 때마다 실행 속도가 급격히 느려져 성능에 심각한 문제를 일으킬 것이다. 이런 성능상의 문제 때문에 애그리서트 간의 1:N 연관을 실제 구현에 반영하는 경우는 드물다. </p>
<br/>

<p>2) ProductRepository를 이용해서 목록 구현. </p>
<pre><code>public class ProductService{
    public Page&lt;Product&gt; getProductOfCategory(Long categoryId, int page, int size){
            Category category = categoryRepository.findById(categoryId);
                checkCategory(category);
                List&lt;Product&gt; products = productRepository.findByCategoryId(categoryId.getId(), page, size); 
                int totalCount = productRepository.countsByCategoryId(category.getId(); 
                return new Page(page, size, totalCount, products); 

        }

}</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[아키텍처]]></title>
            <link>https://velog.io/@keep_going/%EC%95%84%ED%82%A4%ED%85%8D%EC%B2%98</link>
            <guid>https://velog.io/@keep_going/%EC%95%84%ED%82%A4%ED%85%8D%EC%B2%98</guid>
            <pubDate>Thu, 31 Dec 2020 18:31:52 GMT</pubDate>
            <description><![CDATA[<h3 id="네개의-영역">네개의 영역</h3>
<blockquote>
<p>아키텍처는 &quot;표현&quot;, &quot;응용&quot;, &quot;도메인&quot;, &quot;인프라스트럭처&quot; 의 네 영역이다.</p>
</blockquote>
<h4 id="표현-영역">표현 영역</h4>
<ul>
<li>응용 서비스가 리턴한 결과를 JSON 형식으로 변환해서 HTTP 응답으로 웹 브라우저에 전송한다.</li>
</ul>
<h4 id="응용-영역">응용 영역</h4>
<ul>
<li>표현 영역을 통해 사용자의 요청을 전달받는 응용 영역은 시스템이 사용자에게 제공해야 할 기능을 구현한다. </li>
<li>&#39;주문 등록&#39;, &#39;주문 취소&#39;, &#39;상품 상세 조회&#39;와 같은 기능을 구현한다.</li>
<li>응용 영역은 기능을 구현하기 위해 도메인 영역의 도메인 모델을 사용한다.</li>
</ul>
<br/>
<Br/>

<ul>
<li>주문 취소 기능을 예로 들면 다음과 같이 주문 도메인 모델을 사용하여 기능을 구현한다.<pre><code>public class CancelOrderService {
  @Transactional
  public void cancelOrder(String orderId){
      Order order = findOrderById(orderId);
          if(order == null) throw new OrderNotFoundException(orderId);
              order.cancel();

</code></pre></li>
</ul>
<pre><code>    } </code></pre><p>}</p>
<pre><code>



&lt;br/&gt;

#### 도메인 영역
- 도메인 모델은 도메인의 핵심 로직을 구현한다.
- 주문 도메인의 경우 &#39;배송지 변경&#39;, &#39;결제 완료&#39;, &#39;주문 총액 계산&#39;과 같은 핵심 로직을 도메인 모델에서 구현한다.


&lt;br/&gt;

#### 인프라스트럭처
- 이 영역은 RDBMS 연동을 처리하고, 메시징 큐에 메시지를 전송하거나 수신하는 기능을 구현하고, 몽고 DB나 HBase를 사용해서 데이터베이스 연동처리 한다. 
- 이 영역은 SMTP를 이용한 메일 발송 기능을 구현하거나 HTTP 클라이언트를 이용해서 REST API를 호출하는 것도 처리한다. 
- 인프라스트럭처 영역은 논리적인 개념을 표현하기보다는 실제 구현을 다룬다.
&gt; 도메인 영역, 응용 영역, 표현 영역은 구현 기술을 사용한 코드를 직접 만들지 않는다. 대신 인프라스트럭처 영역에서 제공하는 기능을 사용해서 필요한 기능을 개발한다. 
예를 들어, 응용 영역에서 DB에 보관된 데이터가 필요하면 인프라스트럭처 영역의 DB 모듈을 사용해서 데이터를 읽어온다. 

---


&lt;BR/&gt;&lt;BR/&gt;
#### 계층 구조 아키텍처 
&gt;  응용 영역과 도메인 영역은 DB나 외부 시스템 연동을 위해 인프라스트럭처의 기능을 사용하므로 이런 계층 구조를 사용하는 것이 직관적으로 이해하기 쉽다. 하지만, 짚고 넘어가야 할 것이 있는데 바로 표현, 응용, 도메인 계층이 상세한 구현 기술을 다루는 **인프라스트럭처 계층**에 종속된다는 점이다.



🙏 도메인 가격 계산 규칙을 예로 들어보자. 할인 금액 계산 로직이 복잡해지면 객체 지향으로 구현하는 것 보다 &quot;룰 엔진&quot;을 사용하는 것이 알맞을 때가 있다.

&lt;BR/&gt;

#### Drools라는 룰 엔진 사용해서 로직 수행할 수 있는 인프라스트럭처 영역의 코드</code></pre><p>public class CalculateDiscountService{</p>
<pre><code>private DroolsRuleEngine ruleEngine;

    public CalculateDiscountService(){
        ruleEngine = new DroolsRuleEngine();
    }

    public Money calculateDiscount(List&lt;OrderLine&gt; orderLines, String customerId){
        Customer customer = findCustomer(customerId);


            MutableMoney money = new MutableMoney(0);
            List&lt;?&gt; facts = Arrays.asList(customer, money);
            facts.addAll(orderLines);
            ruleEngine.evalute(&quot;discountCalculation&quot;, facts);
            return money.toImmutableMoney();


}</code></pre><p>}</p>
<pre><code>CalculateDiscountService가 겉으로는 인프라스트럭처의 기술에 직접적인 의존을 하지 않는 것처럼 보여도 실제로는 Drools라는 인프라스트럭처 영역의 기술에 완전하게 의존하고 있다. 이런 상황에서 Drools가 아닌 다른 구현 기술을 사용하려면 코드의 많은 부분을 고쳐야 한다..

**&quot;테스트 어려움&quot;**과 **&quot;기능 확장의 어려움&quot;**이라는 문제가 발생한다. 
이 두가지 문제를 해소 할수 있는 방법은 **&quot;DIP&quot;**를 적용하는 것이다.


&lt;BR/&gt;

#### 🔥DIP
CalculateDiscountService는 고수준 모듈이다. 고수준 모듈의 기능을 구현하려면 여러 하위 기능이 필요하다.

고수준 모듈이 제대로 동작하려면 저수준 모듈을 사용해야 한다. 그런데, 고수준 모듈이 저수준 모듈을 사용하면 앞서 계층 구조 아키텍처에서 언급했던 두가지 문제(구현 변경과 테스트가 어려움)가 발생한다.

DIP는 이 문제를 해결하기 위해 저수준 모듈이 고수준 모듈에 의존하도록 바꾼다. ( 추상화 인터페이스를 사용하면 된다.)
</code></pre><p>public interface RuleDiscounter{
     public Money applyRules(Custome customer, List<OrderLine> orderLines);
}</p>
<pre><code>
CalculateDiscountService가 RuleDiscounter를 이용하도록 변경</code></pre><p>public class CalculateDiscountService{
    private RuleDiscounter ruleDiscounter; </p>
<pre><code>public CalculateDiscountService(RuleDiscounter ruleDiscounter){
    this.ruleDiscounter = ruleDiscounter;
}

public Money calculateDiscount(List&lt;OrderLine&gt; orderLines, String customerId){
    Customer customer = findCustomer(customerId);
    return ruleDiscounter.applyRules(customer, orderLines); 
}</code></pre><p>}</p>
<pre><code>
-&gt; CalculateDiscountService는 더 이상 구현 기술인 Drools에 의존하지 않는다.
룰을 이용한 할인 금액 계산을 추상화한 RuleDiscounter 인터페이스에 의존할 뿐이다. 
 &quot;룰을 이용한 할인 금액 계산&quot;은 고수준 모듈의 개념이므로 RuleDiscounter 인터페이스는 고수준 모듈에 속한다. DroolsRuleDiscounter는 고수준의 하위 기능인 RuleDiscounter를 구현한 것이므로 저수준 모듈에 속한다. 

&gt;  DIP를 적용하면 앞서 다른 영역이 인프라스트럭처 영역에 의존할 때 발생했던 두 가지 문제인 구현 교체가 어렵다는 문제와 테스트가 어려운 문제를 해소할 수 있다. 
</code></pre><p>//사용할 저수준 객체 생성
RuleDiscounter ruleDiscounter = new DroolsRuleDiscounter();</p>
<p>//생성자 방식으로 주입
CalculateDiscountService disService = new CalculateDiscountService(ruleDiscounter);</p>
<p>//사용할 저수준 구현 객체 변경
RuleDiscounter ruleDiscounter = new SimpleRuleDiscounter();</p>
<p>//사용할 저수준 모듈을 변경해도 고수준 모듈을 수정할 필요가 없다. 
CalculateDiscountService disService = new CalculateDiscountService(ruleDiscounter);</p>
<pre><code>


&lt;br/&gt;&lt;Br/&gt;&lt;br/&gt;
#### DIP와 아키텍처
인프라스트럭처 영역은 구현 기술을 다루는 저수준 모듈이고 응용 영역과 도메인 영역은 고수준 모듈이다.
![](https://images.velog.io/images/keep_going/post/86d6ffe7-7978-4936-b0d9-84b23b1eaab2/image.png)


---

#### 도메인 영역의 주요 구성 요소
- **엔티티** : 주문(Order), 회원(Member), 상품(Product)과 같이 도메인의 교유한 개념을 표현한다. 도메인 모델의 데이터를 포함하며 해당 데이터와 관련된 기능을 함께 제공한다.

- **벨류** : 고유의 식별자를 갖지 않는 객체로 주로 개념적으로 하나인 도메인 객체의 속성을 표현할 때 사용된다.

- **애그리거트** : 관련된 엔티티와 밸루 객체를 개념적으로 하나로 묶은 것이다. 예를 들어, 주문과 관련된 Order 엔티티, OrderLine밸류, Order 밸류 객체를 &#39;주문&#39; 애그리거트로 묶을 수 있다. 

- **리포지터리** : 도메인 모델의 영속성을 처리한다. 예를 들어, DBMS 테이블에서 엔티티 객체를 로딩하거나 저장하는 기능을 제공한다.

- **도메인 서비스** : 특정 엔티티에 속하지 않은 도메인 로직을 제공한다. &#39;할인 금액 계산&#39;은 상품, 쿠폰, 회원 등급, 구매 금액 등 다양한 조건을 이용해서 구현하게 되는데, 이렇게 도메인 로직이 여러 엔티티와 밸류를 필요로 할 경우 도메인 서비스에서 로직을 구현한다.

&gt; **애그리커드를 사용하면 개별 객체가 아닌 관련 객체를 묶어서 객체 군집 단위로 모델을 바라볼 수 있다.** 
(개별 객체 간의 관계가 아닌 애그리거트 간의 관계로 도메인 모델을 이해하고 구현할 수 있게 되며, 이를 통해 큰 틀에서 도메인 모델을 관리할 수 있게 된다. )

&lt;BR/&gt;&lt;BR/&gt;
#### &gt; 리포지터리
- 도메인 객체를 지속적으로 사용하려면 RDBMS, NoSQL, 로컬 파일과 같은 물리적인 저장소에 도메인 객체를 보관해야 한다. 이를 위한 도메인 모델이 리포지터리(repository)이다. 
(엔티티나 벨류가 요구사항에 도출되는 도메인 모델이라면 리포지터리는 구현을 위한 도메인 모델이다. )

&lt;br/&gt;

✔** 응용 서비스와 리포지터리
**
- 응용 서비스는 필요한 도메인 객체를 구하거나 저장할 때 리포지터리를 사용한다
- 응용 서비스는 트랜잭션을 관리하는데, 트랜잭션 처리는 리포지터리 구현 기술에 영향을 받는다.</code></pre><p>public class CancelOrderService{
    private OrderRepository orderRepository;</p>
<pre><code>    @Transaction //응용서비스는 트랜잭션을 관리한다.
public void cancel(OrderNumber number){
        Order order = orderRepository.findByNumber(number);
            if(order == null) throw new NoOrderException(number);
            order.cancel();
    }</code></pre><p>}</p>
<p>```</p>
<p>✔ ** 표현 영역 **</p>
<ul>
<li>사용자가 전송한 데이터 형식이 올바른지 검사하고 문제가 없다면 데이터를 이용해서 응용 서비스에 기능 실행을 위임한다.</li>
</ul>
<Br/>

<p>✔ <strong>인프라스트럭처</strong> </p>
<ul>
<li><p>표현 영역, 응용 영역, 도메인 영역을 지원한다. 도메인 객체의 영속성 처리, 트랜잭션, SMTP 클라이언트, REST 클라이언트 등 다른 영역에서 필요로 하는 프레임워크, 구현 기술, 보조 기능을 지원한다. </p>
</li>
<li><p>DIP에서 언급한 것처럼 도메인 영역과 응용 영역에서 인프라스트럭처의 기능을 직접 사용하는 것보다 이 두 영역에 정의한 인터페이스를 인프라스트럭처 영역에서 구현하는 것이 시스템을 더 유연하고 테스트하기 쉽게 만들어 준다.</p>
</li>
<li><p>하지만 무조건  인프라스트럭처에 대한 의존을 없애는 것이 좋은 것이 아니다. (스프링은 @Transactional  / JPA는 @Entity나 @Table과 같은 JPA 전용 애노테이션을 도메인 모델 클래스에 사용하는 것이 효율적이다.)</p>
</li>
<li><p>응용 영역과 도메인 영역이 인프라스트럭처에 대한 의존을 완전히 갖지 않도록 시도하는 것은 자칫 구현을 더 복잡하고 어렵게 만들 수 있다. </p>
</li>
</ul>
<p><br/><br/><br/>
<a href="https://www.slideshare.net/cc612/ddd-start-2">https://www.slideshare.net/cc612/ddd-start-2</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[객체 생성과 파괴]]></title>
            <link>https://velog.io/@keep_going/%EA%B0%9D%EC%B2%B4-%EC%83%9D%EC%84%B1%EA%B3%BC-%ED%8C%8C%EA%B4%B4</link>
            <guid>https://velog.io/@keep_going/%EA%B0%9D%EC%B2%B4-%EC%83%9D%EC%84%B1%EA%B3%BC-%ED%8C%8C%EA%B4%B4</guid>
            <pubDate>Tue, 29 Dec 2020 11:51:24 GMT</pubDate>
            <description><![CDATA[<p> 객체를 만들어야 하는 경우와 그렇지 않은 경우에 대해 알아보자.</p>
<h3 id="🔥-생성자-대신-정적-팩터리-메서드를-고려하라">🔥 생성자 대신 정적 팩터리 메서드를 고려하라.</h3>
<ul>
<li><p>클라이언트가 클래스의 인스턴스를 얻는 전통적인 수단은 public 생성자다.</p>
<p>( public 방법 말고도 정적 팩터리 메서드를 사용할 수 있다. )</p>
</li>
</ul>
<p><br/><br/></p>
<h3 id="✔-정적-팩터리-메서드-장점-다섯-가지">✔ 정적 팩터리 메서드 장점 다섯 가지.</h3>
<p><strong>1) 첫 번째, 이름을 가질 수 있다.</strong> </p>
<p><strong>2) 두 번째, 호출될 때마다 인스턴스를 새로 생성하지는 않아도 된다.</strong></p>
<ul>
<li><p>덕분에 불변 클래스는 인스턴스를 미리 만들어 놓거나 새로 생성한 인스턴스를 캐싱하여 재활용하는 식으로 불필요한 객체 생성을 피할 수 있다. </p>
</li>
<li><p>Boolean.valueOf(boolean) 메서드는 객체를 아예 생성하지 않는다. </p>
</li>
<li><p>플라이웨이트 패턴이 이와 유사하다.</p>
</li>
</ul>
<p><strong>3) 반환 타입의 하위 타입 객체를 반환할 수 있는 능력이 있다.</strong></p>
<ul>
<li><p>반환할 클래스를 자유롭게 선택할 수 있는 &#39;엄청난 유연성&#39;을 가진다.</p>
</li>
<li><p>API를 만들 때 이 유연성을 응용하면 구현 클래스를 공개하지 않고도 그 객체를 반환할 수 있어 API를 작게 유지할 수 있다. </p>
</li>
</ul>
<p>*<em>4) 입력 매개변수에 따라 매번 다른 클래스의 객체를 반환할 수 있다. *</em></p>
<p><strong>5) 정적 팩터리 메서드를 작성하는 시점에는 반환할 객체의 클래스가 존재하지 않아도 된다.</strong></p>
<ul>
<li><p>이러한 유연함은 서비스 제공자 프레임워크를 만드는 근간이 된다. 대표적인 서비스 제공자 프레임워크로는 JDBC가 있다. </p>
</li>
<li><p>서비스 제공자 프레임워크는 3개의 핵심 컴포넌트로 이뤄진다. 구현체의 동작을 정의하는 <strong>서비스 인터페이스</strong>, 제공자가 구현체를 등록할 때 사용하는 <strong>제공자 등록 API</strong>(provider registration API), 클라이언트가 서비스의 인스턴스를 얻을 때 사용하는 <strong>서비스 접근 API</strong>가 그 주인공이다.</p>
</li>
</ul>
<h2 id="brbr"><Br/><br/></h2>
<br/>

<h3 id="🔥-생성자에-매개변수가-많다면-빌더를-고려하라">🔥 생성자에 매개변수가 많다면 빌더를 고려하라.</h3>
<p>: 매개변수 개수가 많아지면 클라이언트 코드를 작성하거나 읽기 어렵다. </p>
<h3 id="-✔-프로그래머들이-자주-사용하는-3가지-pattern에-대해-알아보자">** ✔ 프로그래머들이 자주 사용하는 3가지 Pattern에 대해 알아보자.**</h3>
<ul>
<li>*<em>점층적 생성자 패턴 ( telescoping constructor pattern) *</em><ul>
<li>사용하고 싶은 변수를 정해 매개변수를  늘리거나 줄여준다.</li>
<li>단점 : 매개변수가 많아지면 클라이언트 코드를 작성하거나 읽기 어려워진다.</li>
</ul>
</li>
<li>** 자바빈즈 패턴 ( JavaBeans Pattern) **<ul>
<li>매개변수가 없는 생성자로 객체를 만든 후 세터(setter) 메서드를 호출해 원하는 매개변수의 값을 설정하는 방식이다. </li>
<li>단점 : 객체 하나를 만들려면 여러 개 호출해야 하고, 객체가 완전히 생성되기 전까지는 일관성이 무너진 상태에 놓이게 된다. 자바빈즈 패턴에서는 클래스를 불변으로 만들 수 없다. </li>
</ul>
</li>
</ul>
<ul>
<li>*<em>빌더 패턴 ( Builder Pattern ) *</em>
(점층적 생성자 패턴과 자바빈즈 패턴을 보완해 나온 내용이 빌더 패턴이다. )<ul>
<li>클라리언트는 필요한 객체를 직접 만드는 대신, 필수 매개변수만으로 생성자를 호출해 빌더 객체를 얻는다. 그 다음 빌더 객체가 제공하는 일종의 세터 메서드들로 원하는 선택 매개변수들을 설정한다. </li>
<li>빌더 패턴은 (파이썬과 스칼라에 있는) 명명된 선택적 매개변수를 흉내 낸 것이다.</li>
<li>빌더 패턴은 계층적으로 설계된 클래스와 함께 쓰기에 좋다.  </li>
</ul>
</li>
</ul>
<ul>
<li><p>단점 : 빌더 패턴은 객체를 만들려면, 그에 앞서 빌더부터 만들어야 한다. 빌더 생성 비용이 크지는 않지만 성능에 민감한 상황에서는 문제가 될 수 있다. 또한 점층적 생성자 패턴보다는 코드가 장황해서 매개변수가 4개 이상은 되어야 값어치를 한다. 하지만 API는 시간이 지날수록 매개변수가 많아지는 경향이 있다.</p>
<p>🔥 생성자나 정적 팩터리 방식으로 시작했다가 나중에 매개변수가 많아지면 빌더 패턴으로 전환할 수도 있지만, 이전에 만들어둔 생성자와 정적 팩터리가 아주 도드라져 보일 것이다. 그러니 애초에 빌더로 시작하는 편이 나을 때가 많다 .</p>
</li>
</ul>
<hr>
<blockquote>
<p><strong>생성자나 정적 팩터리가 처리해야 할 매개변수가 많다면 빌더 패턴을 선택하는게 더 낫다.
빌더는 점층적 생성자보다 클라이언트 코드를 읽고 쓰기가 훨씬 간결하고, 자바빈즈보다 휠씬 안전하다.</strong></p>
</blockquote>
<p><br/><br/><Br/><Br/></p>
<h3 id="🔥-private-생성자나-열거-타입으로-싱글턴임을-보증하라">🔥 private 생성자나 열거 타입으로 싱글턴임을 보증하라.</h3>
<p>싱글턴이란? 인스턴스를 오직 하나만 생성할 수 있는 클래스를 말한다.</p>
<pre><code>public class Elvis {
    public static final Elvis INSTANCE = new Elvis();
        private Elvis() { ... }
        private void leaveTheBuilding(){ ...}

}</code></pre><p>클래스를 싱글턴으로 만들면 이를 사용하는 클라이언트를 테스트하기가 어려워질 수 있다. </p>
<p><br/><br/></p>
<h3 id="싱글턴을-만드는-2가지"><strong>싱글턴을 만드는 2가지</strong></h3>
<p><strong>첫번째 private으로 감춰두고, 유일한 인스턴스에 접근할 수 있는 수단으로 public static 멤버를 하나 마련해둔다.</strong></p>
<pre><code>public class Elvis {
    public static final Elvis INSTANCE = new Elvis();
        private Elvis() { ...}

        public void leaveTheBuilding() {... }
}</code></pre><p>private 생성자는 public static final 필드인 Elvis.INSTANCE를 초기화할 때 딱 한번만 호출된다. 
public이나 protected 생성자가 없으므로 Elvis 클래스가 초기화될 때 만들어진 인스턴스가 전체 시스템에서 하나뿐임이 보장된다. 클라이언트는 리플렉션 API인 AccessibleObject.setAccessible을 사용해 private 생성자를 호출할 수 있다. </p>
<br/>
두번째 방법에서는 정적 팩터리 메서드를 public static 멤버로 제공한다.

<pre><code>public class Elvis { 
    private static final Elvis INSTANCE = new Elvis();
        private Elvis() { ... }
        public static Elvis getInstance(){ return INSTANCE; }

        public void leaveTheBuilding(){ ... }

}</code></pre><p>public  필드 방식의 큰 장점은 해당 클래스가 싱글턴임이 API에 명백히 드러난다는 것이다. 
public static 필드가 final 이니 절대로 다른 객체를 참조할 수 없다. 
<br/><br/></p>
<p>세번째 방법은 원소가 하나인 열거 타입을 선언하는 것이다.
private enum Elivis {        </p>
<pre><code>  INSTANCE;           
  public void leaveTheBuilding(){ ... }</code></pre><p>}</p>
<p>public 필드 방식과 비슷하지만, 더 간결하고, 추가 노력 없이 직렬화할 수 있고, 심지어 아주 복잡한 질렬화 상황이나 리플렉션 공격에서도 제2의 인스턴스가 생기는 일을 완벽히 막아준다. </p>
<p>대부분 상황에서는 원소가 하나뿐인 열거 타입이 싱글터을 만드는 가장 좋은 방법이다. 단, 만드려는 싱글턴이 Enum 외에 클래스를 상속해야 한다면 이 방법은 사용할 수 없다. </p>
<p><br/><br/></p>
<h3 id="🔥-인스턴스화를-막으려거든-private-생성자를-사용하라">🔥 인스턴스화를 막으려거든 private 생성자를 사용하라.</h3>
<ul>
<li>추상 클래스로 만드는 것으로는 인스턴스화를 막을 수 없다. private 생성자를 추가하면 클래스의 인스턴스화를 막을 수 있다.<pre><code>public class UtilityClass{
  //기본 생성자가 만들어지는 것을 막는다.(인스턴스화 방지용)
  private UtilityClass(){
      throw new AssertionError();
  }
</code></pre></li>
</ul>
<p>}</p>
<pre><code>
이 방식은 상속을 불가능하게 하는 효과도 있다. 모든 생성자는 명시적이든 묵시적이든 상위 클래스의 생성자를 호출하게 되는데, 이를 private으로 선언했으니 하위 클래스가 사우이 클래스의 생성자에 접근할 길이 막혀버린다.

&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;

### 🔥 자원을 직접 명시하지 말고 의존 객체 주입을 사용하라.

**1) 싱글턴을 잘못 사용한 예 - 유연하지 않고 테스트하기 어렵다. **
</code></pre><p>public class SpellChecker {
    private final Lexicon dictionary = ...;</p>
<pre><code>    private SpellChecker(...){}
    public static SpellChecker INSTANCE = new SpellChecker(...);

    public boolean isValid(String world){...}
    public List&lt;String&gt; suggestions(String type){...}</code></pre><p>}</p>
<pre><code>

사용하는 자원에 따라 동작이 달라지는 클래스에는 정적 유틸리티 클래스나 싱글턴 방식이 적합하지 않다. 

&lt;br/&gt;&lt;br/&gt;
**2) 의존 객체 주입은 유연성과 테스트 용이성을 높여준다.
**</code></pre><p>public class SpellChecker {
    private final Lexicon dictionary;</p>
<pre><code>    public SpellChecker(Lexicon dictionary){
        this.dictionary = Objects.requireNonNull(dictionary);
    }
public boolean isValid(String word){...}
    public List&lt;String&gt; suggestions(String typo){ ... }</code></pre><p>}</p>
<pre><code>
이 패턴의 쓸만한 변형으로는, 생성자에 자원 팩터리를 넘겨주는 방식이다. 팩터리란 호출할 때마다 특정 타입의 인스턴스를 반복해서 넘겨주는 방식이다.
&lt;br/&gt;&lt;Br/&gt;&lt;br/&gt;
### 🔥 불필요한 객체 생성을 피하라.
- Boolean(String) 생성자 대신 Boolean.valueOf(String) 팩터리 메서드를 사용하는 것이 좋다.
(생성자는 호출할 때마다 새로운 객체를 만들지만, 팩터리 메서드는 전혀 그렇지 않다.)
&lt;br/&gt;

**1) 정규 표현식을 잘 사용하면 성능을 훨씬 더 끌어올릴 수 있다.** 
</code></pre><p>static boolean isRomanNumeral(String s){
    return s.matches(&quot;^(?=.)M*(C[MD]|D?C{0,3})&quot;
            + &quot;(X[CL]|L?X{0,3})(I[XV][V?I{0,3})$&quot;);</p>
<p>}</p>
<pre><code>String.matches는 정규표현식으로 문자열 형태를 확인하는 가장 쉬운 방법이지만, 성능이 중요한 상황에서 반복해 사용하기엔 적합하지 않다. 이 메서드가 내부에서 만드는 정규표현식용 Pattern 인스턴스는, 한 번 쓰고 버려져서 곧바로 가비지 컬렉션 대상이 된다. Pattern은 입력받은 정규표현식에 해당하는 유한 상태 머신(finite state machine)을 만들기 때문에 인스턴스 생성 비용이 높다. 


**2) 값비싼 객체를 재사용해 성능을 개선한다.
**</code></pre><p>public class RomanNumerals {
    private static final Pattern ROMAN = Pattern.compile(
            &quot;^(?=.)M*(C[MD]|D?C{0,3})&quot;
                + &quot;(X[CL]|L?X{0,3})(I[XV]|V?I{0,3})$&quot;);
        );
        static boolean isRomanNumeral(String s){
            return ROMAN.matcher(s).matches();
        }</p>
<p>}</p>
<pre><code>
개선 전에는 존재조차 몰랐던 Pattern 인스턴스를 static final 필드로 끄집어내고 이름을 지어줘 코드의 이미가 훨씬 잘 드러난다.

개선된 isRomanNumeral 방식의 클래스가 초기화된 후 이 메서드를 한 번도 호출하지 않는다면 ROMAN 필드는 쓸데없이 초기화된 꼴이다. 


예컨대 Map 인터페이스의 keyset 메서드는 Map 객체 안의 키 전부를 담은 Set 뷰를 반환한다. 

불필요한 객체를 만들어내는 또 다른 예로 오토박싱(auto boxing)을 들 수 있다. 오토박싱은 프로그래머가 기본 타입과 박싱된 기본 타입을 섞어 쓸 때 자동으로 상호 변환해주는 기술이다.

아주 무거운 객체가 아닌 다음에야 단순히 객체 생성을 피하고자 여러분만의 객체 풀을 만들지는 말자. 물론 객체 풀을 만드는 게 나은 예가 있다. 데이터베이스 연결 같은 경우 생성 비용이 워낙 비싸니 재사용하는 편이 낫다.
( 요즘 JVM의 가비지 컬렉터는 상당히 잘 최적화되어서 가벼운 객체용을 다룰 때는 직접 만든 객체 풀보다 훨씬 더 빠르다.)
&lt;BR/&gt;&lt;BR/&gt;

### 🔥 다 쓴 객체 참조를 해제하라.
- 가비지 컬렉션 언어에서는 (의도치 않게 객체를 살려두는) 메모리 누수를 찾기가 아주 까다롭다. 객체 참조 하나를 살려두면 가비지 컬렉터는 그 객체뿐 아니라 그 객체가 참조하는 모든 객체(그리고 또 그 객체들이 참조하는 모든 객체..)를 회수해가지 못한다. 그래서 단 몇 개의 객체가 매우 많은 객체를 회수되지 못하게 할 수 있고 잠재적으로 성능에 악영향 미칠 수 있다.

- 해법은 간단하다. 해당 참조를 다 썼을 때 null 처리하면 된다.

- 그렇다면 null 처리는 언제 해야 할까? Stack 클래스는 왜 메모리 누수에 취약한 걸까? 바로 스택이 자기 메모리를 직접 관리하기 때문이다. 
- 자기 메모리를 직접 관리하는 클래스라면 프로그래머는 항상 메모리 누수에 주의해야 한다. 원소를 다 사용한 즉시 그 원소가 참조한 객체들을 다 NULL 처리해줘야 한다.
- 캐시 역시 메모리 누수를 일으키는 주범이다. 
(캐시를 만들 때 보통은 캐시 엔트리의 유효 기간을 정확히 정의하기 어렵기 때문에 시간이 지날수록 엔트리의 가치를 떨어뜨리는 방식을 혼히 사용한다. 이런 방식에서는 쓰지 않는 엔트리를 이따금 청소해줘야 한다.-&gt; LinkedHashMap은 removeEldestEntry 메서드를 써서 후자의 방식으로 처리한다.
- 메모리 누수의 세 번째 주범은 바로 리스너(listener) 혹은 콜백(callback)이라 부르는 것이다.
(클라이언트가 콜백을 등록만 하고 명확히 해지하지 않는다면, 뭔가 조치해주지 않는 한 콜백은 계속 쌓여갈 것이다.)
&lt;br/&gt;&lt;br/&gt;&lt;Br/&gt;
### 🔥 finalizer와 cleaner 사용을 피하라.
- 자바는 두 가지 객체 소멸자를 제공한다. 그 중 finailzer는 예측할 수 없고, 상황에 따라 위험할 수 있어 일반적으로 불필요하다. cleaner는 finalizer보다는 덜 위험하지만, 여전히 예측할 수 없고, 느리고, 일반적으로 불필요하다.


- finalizer나 cleaner를 얼마나 신속히 수행할지는 전적으로 가비지 컬렉터 알고리즘에 달렸으며, 이는 가비지 컬렉터 구현마다 천차만별이다. 

- 클래스에 finalizer를 달아두면 그 인스턴스의 자원 회수가 제멋대로 지연될 수 있다.

- 상태를 영구적으로 수정하는 작업에서는 절대 finalizer나 cleaner에 의존해서는 안된다. 


</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[서비스 디스커버리]]></title>
            <link>https://velog.io/@keep_going/%EC%84%9C%EB%B9%84%EC%8A%A4-%EB%94%94%EC%8A%A4%EC%BB%A4%EB%B2%84%EB%A6%AC</link>
            <guid>https://velog.io/@keep_going/%EC%84%9C%EB%B9%84%EC%8A%A4-%EB%94%94%EC%8A%A4%EC%BB%A4%EB%B2%84%EB%A6%AC</guid>
            <pubDate>Tue, 29 Dec 2020 10:02:27 GMT</pubDate>
            <description><![CDATA[<h3 id="서비스-디스커버리-등장-배경">서비스 디스커버리 등장 배경?</h3>
<p>분산 아키텍처에서는 시스템의 물리적 위치 주소를 찾아야 한다. 이 개념은 분산 컴퓨팅 초창기 때부터 존재했고 공식적으로 서비스 디스커버리라고 한다. </p>
<br/>

<h3 id="서비스-디스커버리-유형">서비스 디스커버리 유형</h3>
<ul>
<li>서비스 디스커버리는 애플리케이션에서 사용하는 모든 원격 서비스의 주소가 포함된 프로퍼티 파일을 관리하는 것처럼 단순한 경우.</li>
<li>UUID 저장소처럼 정형화되고 복잡한 것일 수 있다. </li>
</ul>
<p><BR/><BR/></p>
<h3 id="서비스-디스커버리-중요성">서비스 디스커버리 중요성</h3>
<p>*<em>첫 번째,  애플리케이션 팀은 서비스 디스커버리를 사용해 해당 환경에서 시행하는 서비스 인스턴스 개수를 신속하게 수평 확장하거나 축소할 수 있다. *</em></p>
<ul>
<li>서비스 디스커버리를 통해 서비스의 물리적 위치는 서비스 소비자에게는 드러나지 않는다.</li>
<li>서비스 소비자는 실제 서비스 인스턴스의 물리적 위치를 모르기 때문에 서비스 풀에서 새로운 서비스 인스턴스의 추가나 삭제가 자유롭다.</li>
</ul>
<ul>
<li><p>일반적으로 모놀리식 방식을 사용하면 개발 팀은 필요한 용량보다 초과 구매를 하게 된다. </p>
</li>
<li><p>용량이 대량 큰 폭으로 증가되므로 원만하게 진행되는 경우는 드물다. </p>
</li>
<li><p>마이크로서비스 방식을 사용하면 새로운 인스턴스만 확장 축소할 수 있다. </p>
</li>
</ul>
<br/>

<p>*<em>두 번째, 애플리케이션 회복성을 향상하는데 도움이 된다는 것이다. *</em></p>
<ul>
<li><p>마이크로 서비스 인스턴스가 비정상이거나 가용하지 않다면 대부분의 서비스 디스커버리 엔진은 내부의 가용 서비스 목록에서 해당 인스턴스를 제거한다. </p>
</li>
<li><p>서비스 디스커버리 엔진이 사용할 수 없는 서비스를 피해 라우팅하므로 다운된 서비스가 야기한 피해를 최소화 한다. </p>
</li>
</ul>
<p><br/><br/></p>
<h3 id="서비스-위치-찾기">서비스 위치 찾기.</h3>
<p> 애플리케이션에서 여러 서버로 분산된 자원을 호출할 때마다 해당 자원의 물리적 위치를 찾아야 한다. 클라우드가 아닌 환경에서 이 서비스의 위치 확인은 대개 DNS와 네트워크 로드 밸런서로 해결되었다. </p>
<p>이처럼 애플리케이션은 다른 조직에 있는 서비스를 호출해야 한다. 애플리케이션이 호출하려던 서비스를 대표하는 고유 경로와 함께 일반적인 DNS 이름을 사용해 서비스 호출을 시도한다. 
(서비스 소비자에게 요청을 받으면 로드 밸런서는 사용자가 엑세스하려는 경로를 기반으로 라우팅 테이블에서 물리적 주소 항목을 찾는다. ) </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[도메인 모델]]></title>
            <link>https://velog.io/@keep_going/%EB%8F%84%EB%A9%94%EC%9D%B8-%EB%AA%A8%EB%8D%B8</link>
            <guid>https://velog.io/@keep_going/%EB%8F%84%EB%A9%94%EC%9D%B8-%EB%AA%A8%EB%8D%B8</guid>
            <pubDate>Mon, 28 Dec 2020 14:49:15 GMT</pubDate>
            <description><![CDATA[<p><img src="https://images.velog.io/images/keep_going/post/c4b7d52e-f064-43d0-ab7a-010100785112/%EB%8F%84%EB%A9%94%EC%9D%B8_%ED%95%98%EC%9C%84%EB%8F%84%EB%A9%94%EC%9D%B8.PNG" alt=""></p>
<h3 id="도메인은-여러-하위-도메인으로-구성된다">도메인은 여러 하위 도메인으로 구성된다.</h3>
<p>카탈로그 하위 도메인은 고객에게 구매할 수 있는 상품 목록을 제공하고, 주문 하위 도메인은 고객의 주문을 처리한다. </p>
<p>혜택 하위 도메인은 쿠폰이나 특별 할인과 같은 서비스를 제공하고, 배송 하위 도메인은 고객에게 구매한 상품을 전달하는 일련의 과정을 처리한다.</p>
<h3 id="소프트웨어가-도메인의-모든-기능을-제공하지-않는다">소프트웨어가 도메인의 모든 기능을 제공하지 않는다.</h3>
<ul>
<li>하위 도메인을 어떻게 구성할지 여부는 상황에 따라 달라진다. 기업 고객을 대상으로 대형 장비를 판매하는 곳은 온라인으로 카탈로그를 제공하고 주문서를 받는 정도만 필요할 것이다. 
( 반면에 의류나 액세서리처럼 일반 고객을 대상으로 물건을 판매한다면 카탈로그, 리뷰, 주문, 결제, 배송, 회원 기능이 필요할 것이다. ) </li>
</ul>
<BR/>

<blockquote>
<p><strong>개념 모델과 구현 모델.</strong> 
개념 모델은 순수하게 문제를 분석한 결과물이다. 개념 모델은 데이터베이스, 트랜잭션 처리, 성능, 구현 기술과 같은 것들을 고려하고 있지 않기 때문에 실제 코드를 작성할 때 개념 모델을 있는 그대로 사용할 수 없다. 그래서 개념 모델을 구현 가능한 형태의 모델로 전환하는 과정을 거치게 된다. </p>
</blockquote>
<p><BR/><BR/><BR/></p>
<hr>
<h3 id="엔티티">엔티티</h3>
<p>: 엔티티의 가장 큰 특징은 식별자를 갖는다는 것이다. 식별자는 엔티티 객체마다 고유해서 각 엔티티는 서로 다른 식별자를 갖는다. 예를 들어, 주문 도메인에서 각 주문은 주문번호를 갖는데 이 주문번호는 각 주문마다 서로 다르다. </p>
<h3 id="엔티티의-식별자-생성">엔티티의 식별자 생성.</h3>
<p>: 엔티티티의 식별자를 생성하는 시점은 도메인의 특징과 사용하는 기술에 따라 달라진다. </p>
<ul>
<li>특정 규칙에 따라 생성</li>
<li>UUID 사용</li>
<li>값을 직접 입력</li>
<li>일련번호 사용 (시퀀스나 DB의 자동 증가 칼럼 사용)</li>
</ul>
<p><strong>&quot;UUID(universally unique identifier)&quot;를 사용해서 식별자를 생성할 수 있다.</strong> 
(다수의 개발 언어가 UUID 생성기를 제공하고 있으므로 마땅한 규칙이 없다면 UUID를 식별자로 사용해도 된다.)</p>
<pre><code>UUID uuid = UUID.randomUUID();

String strUuid = uuid.toString(); </code></pre><p><br/><br/><Br/></p>
<h3 id="도메인-모델에-set-메서드-넣지-않기">도메인 모델에 set 메서드 넣지 않기</h3>
<p>: 도메인 모델에 get/set 메서드를 무조건 추가하는 것은 좋지 않는 버릇이다. 특히 set 메서드는 도메인의 핵심 개념이나 의도를 코드에서 사라지게 한다. </p>
<pre><code>public class Order{
    public void setShippingInfo(ShippingInfo newShipping){ }
        public void setOrderState(OrderState state){ }

}</code></pre><p>-&gt; changeShippingInfo()가 배송지 정보를 새로 변경하다는 의미를 가졌다면 setShippingInfo() 메서드는 단순히 배송지 값을 설정한다는 것을 뜻한다. </p>
<p>   complete-Payment()는 결제를 완료했다는 의미를 갖는 반면에 setOrderState()는 단순히 주문 상태 값을 설정한다는 것을 뜻한다.</p>
<blockquote>
<p>** DTO의 get/set 메서드**
: Data Transfer Object의 약자로 프레젠테이션 계층과 도메인 계층이 데이터를 서로 주고받을 때 사용하는 일종의 구조체이다. <code>코드를 입력하세요
 최근의 개발 프레임워크나 개발 도구는 set 메서드가 아닌 private 필드에 직접 값을 할당할 수 있는 기능을 제공하고 있다. 따라서 set 메서드를 제공하지 않아도 프레임워크를 이용해서 데이터를 전달받을 수 있다.</code></p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[스프링 클라우드 컨피그 서버로 구성 관리]]></title>
            <link>https://velog.io/@keep_going/%EC%8A%A4%ED%94%84%EB%A7%81-%ED%81%B4%EB%9D%BC%EC%9A%B0%EB%93%9C-%EC%BB%A8%ED%94%BC%EA%B7%B8-%EC%84%9C%EB%B2%84%EB%A1%9C-%EA%B5%AC%EC%84%B1-%EA%B4%80%EB%A6%AC</link>
            <guid>https://velog.io/@keep_going/%EC%8A%A4%ED%94%84%EB%A7%81-%ED%81%B4%EB%9D%BC%EC%9A%B0%EB%93%9C-%EC%BB%A8%ED%94%BC%EA%B7%B8-%EC%84%9C%EB%B2%84%EB%A1%9C-%EA%B5%AC%EC%84%B1-%EA%B4%80%EB%A6%AC</guid>
            <pubDate>Mon, 28 Dec 2020 13:39:28 GMT</pubDate>
            <description><![CDATA[<p>많은 개발자가 구성 정보를 저장하기 위해 저수준의 프로퍼티(property) 파일(yaml, json 또는 xml)로 전환할 것이다.</p>
<p>대개 이러한 프로퍼티 파일은 데이터베이스 및 미들웨어 접속 정보와 애플리케이션 행동 양식을 정하는 메타데이터가 존재하는 서버로 둔다. </p>
<p>애플리케이션을 프로퍼티 파일로 분리하는 것은 쉬우며, 대부분의 개발자는 구성 파일을 소스 관리 시스템에 넣거나 애플리케이션 일부로 배포하는 일 외에는 애플리케이션 구성을 위한 어떤 운영 작업도 하지 않는다.</p>
<p><br/><br/><br/></p>
<h3 id="클라우드-기반의-마이크로서비스-개발에서-중요한-3가지">클라우드 기반의 마이크로서비스 개발에서 중요한 3가지</h3>
<ol>
<li><p>배포되는 실제 코드에서 애플리케이션의 구성을 완전하게 분리한다.</p>
</li>
<li><p>서버 및 애플리케이션을 빌드하고 배포 환경에 따라 절대 바뀌지 않는 불변 이미지를 빌드한다.</p>
</li>
<li><p>서버를 시작할 때 환경 변수나 애플리케이션의 마이크로서비스가 읽어 올 수 있는 중앙 저장소를 이용해 애플리케이션 구성 정보를 주입한다.</p>
</li>
</ol>
<p><br/><br/><br/></p>
<h3 id="구성그리고-복잡성-관리">구성(그리고 복잡성) 관리</h3>
<p>마이크로서비스의 인스턴스는 사람이 최소한으로 개입해 신속하게 시작해야 하므로 클라우드에서 실행되는 마이크로서비스에 애플리케이션 구성 관리는 매우 중요하다. <BR/></p>
<ol>
<li><p>분리 : 실제 물리적인 서비스의 배포와 서비스 구성 정보를 완전히 분리해야 한다. </p>
</li>
<li><p>추상화 : 서비스 저장소에 직접 엑세스하는 코드를 작성하기(즉, JDBC를 사용해 데이터베이스에서 데이터 읽기)보다 애플리케이션이 REST 기반의 JSON 서비스를 사용해 구성 데이터를 조회하게 만들어야 한다.</p>
</li>
<li><p>중앙 집중화 : 클라우드 기반의 애플리케이션에는 말 그대로 수백 개의 서비스가 존재할 수 있으므로 구성 정보를 보관하는 저장소 개수를 최소로 줄이는 것이 매우 중요하다.</p>
</li>
<li><p>견고성 : 애플리케이션 구성 정보를 배포된 서비스와 완전히 분리하고 중앙 집중화하므로 어떤 솔루션을 사용하더라도 고가용성과 다중성을 구현할 수 있어야 한다. </p>
</li>
</ol>
<blockquote>
<p>애플리케이션의 구성을 제대로 관리하지 못하면 탐지하기 어려운 버그와 예상하지 못한 장애를 만드므로 애플리케이션의 구성 데이터를 추적하고 버전을 제어하는 것은 아무리 강조해도 지나치지 않다. </p>
</blockquote>
<p><br/><br/><Br/></p>
<h3 id="스프링-클라우드-컨피그-서버-구축">스프링 클라우드 컨피그 서버 구축.</h3>
<ul>
<li>스프링 클라우드 컨피그 서버는 스프링 부트로 만든 REST 기반의 애플리케이션이다. 
(<strong>독립형 서버로 제공되지 않아 기존 스프링 부트 애플리케이션에 내장하거나 새로운 스프링 부트 프로젝트를 만들어 내장하는 방법으로 시작할 수 있다.</strong>) </li>
</ul>
<ul>
<li>confsvr이라는 새로운 프로젝트 디렉터리를 만드는 일이다. confsvr 디렉터리 안에 스프링 클라우드 컨피그 서버를 시작하는데 JAR 파일을 내려받는 새로운 메이븐 파일을 생성한다.<BR/></li>
</ul>
<pre><code>&lt;dependencyManagement&gt;
    &lt;dependencies&gt;
            &lt;dependency&gt;
            &lt;groupId&gt;org.springframework.cloud&lt;/groupId&gt;    
            &lt;artifactId&gt;spring-cloud-dependencies&lt;/artifactId&gt; ---- 사용할 스프링 클라우드 버전
                    &lt;version&gt;Finchley.RELEASE&lt;/version&gt;
                        &lt;type&gt;pom&lt;/type&gt;
                        &lt;scope&gt;import&lt;/scope&gt;
        &lt;dependency&gt;
    &lt;/dependencies&gt;
&lt;/dependencyManagement&gt;


&lt;dependencies&gt;
    &lt;dependency&gt;
        &lt;groupId&gt;org.springframework.cloud&lt;/groupId&gt;
        &lt;artifactId&gt;spring-cloud-config-server&lt;/artifactId&gt;
    &lt;/dependency&gt;   └ 이 서비스에 사용할 스프링 클라우드 프로젝트들

    &lt;dependency&gt;
        &lt;groupdId&gt;org.springframework.cloud&lt;/groupId&gt;
        &lt;artifactId&gt;spring-cloud-starter-config&lt;/artifactId&gt; 
    &lt;/dependency&gt;             └이 서비스에 사용할 스프링 클라우드 프로젝트들
&lt;/dependencies&gt;



&lt;!--Docker build config--&gt;
&lt;properties&gt;
    &lt;project.build.sourceEncoding&gt;UTF-8&lt;/project.build.sourceEncoding&gt;
        &lt;start-class&gt;com.throughtmechanix.confsvr.ConfigServerApplication&lt;/start-class&gt;
        &lt;java.version&gt;1.8&lt;/java.version&gt;
        &lt;docker.image.name&gt;johncarnell/tmx-confsvr&lt;/docker.image.name&gt;
        &lt;docker.image.tag&gt;chapter3&lt;/docker.image.tag&gt;
&lt;/properties&gt;



&lt;/properties&gt;

</code></pre><p><br/><br/>
<strong>첫 번째 의존성은모든 스프링 클라우드 프로젝트에 사용되는 spring-cloud-starter-config다.</strong> <br/>
*<em>두 번째 의존성은 spring-cloud-config-server 스터터 프로젝트로 스프링 클라우드 컨피그 서버를 위한 핵심 라이브러리가 들어 있다. *</em></p>
<br/>

<p>컨피그 서버를 동작하게 하려면 여러 파일을 설정해야 한다. 우선 설명한 것은 application.yml 파일이며 confsvr/src/main/resources 디렉터리에 있다. 
application.yml 파일에는 스프링 클라우드 컨피그 서비스가 수신 대기할 포트, 구성 데이터를 제공하는 백엔드 위치 등 정보를 명시한다.</p>
<p><br/><br/><br/><br/></p>
<h3 id="스프링-클라우드-컨피그-부트스트랩-클래스-설정">스프링 클라우드 컨피그 부트스트랩 클래스 설정.</h3>
<pre><code>┌스프링 클라우드 컨피그 서비스는 스프링 부트 애플리케이션이므로 @SpringBootApplication 에너테이션을 붙인다.
@SpringBootApplication
@EnableConfigServer ----@EnableConfigServer 애너테이션은 서비스를 스프링 클라우드 컨피그 (Spring Cloud Config) 서비스```
코드를 입력하세요
```로 사용 가능하게 한다. 
public class ConfigServerApplication{
    public static void main(String[] args){
            SpringApplication.run(ConfigServerApplication.class, args);
    }
}</code></pre><br/>
<Br/>

<h3 id="파일-시스템과-스프링-클라우드-컨피그-서버-사용">파일 시스템과 스프링 클라우드 컨피그 서버 사용.</h3>
<p>스프링 클라우드 컨피그 서버는 confsvr/src/main/resources/application.yml 파일의 항목을 사용해 애플리케이션 구성 데이터를 보관할 저장소를 지정한다.</p>
<pre><code>server :
    port : 8888   --- 스프링 클라우드 컨피그 서버가 수신 대기하는 포트
spring : 
    profiles : 
            active: native --- 구성 정보를 저장할 백엔드 저장소 ( 파일 시스템)
       cloud : 
            config : 
                server :
                         native : 
                                 searchLocations : file://Users/johncarnell1/book/
                                    spmia_code/chapter3-code/confsvr/src/main/
                                        resources/config/licensingservice --- 구성 파일이 저장된 경로.

</code></pre><p><br/><br/><br/></p>
<h3 id="스프링-클라우드-컨피그-서버로-데이터-소스-연결">스프링 클라우드 컨피그 서버로 데이터 소스 연결.</h3>
<pre><code>import java.util.list;
import java.util.UUID;

@Service
public class LicenseService{

    @Autowired
        private LicenseRepository licenseRepository;

        @Autowired
        ServiceConfig config;

        public License getLicense(String organizationId, String licenseId){
            LicenseRepository.findByOrganizationIdAndLicenseId(organizationId, licenseId); 

                return license.withComment(config.getExampleProperty());
        }

        public List&lt;License&gt; getLicenseByOrg(String organizationId){
            return licenseRepository.findByOrganizationId(organizationId);

        }

        public void saveLicense(License license){
            license.withId(UUID.randomUUID().tostring());

                licenseRepository.save(license);
        }
}</code></pre><p><br/><br/><br/></p>
<h3 id="깃과-스프링-클라우드-컨피그-서버-사용">깃과 스프링 클라우드 컨피그 서버 사용.</h3>
<ul>
<li><p>스프링 클라우드 컨피그 서버의 백엔드 저장소로 파일 시스템이 적합하지 않은 이유는 개발 팀이 컨피그 서버의 모든 인스턴스에 마운트될 공유 파일 시스템을 설정하고 관리해야 되기 때문이다.</p>
</li>
<li><p>스프링 클라우드 컨피그 서버는 애플리케이션 구성 프로퍼티를 호스팅하는 다양한 백엔드 저장소와 통합될 수 있다. </p>
</li>
<li><p>깃을 사용하면 구성 관리 프로퍼티를 저장할 때 소스 관리의 모든 혜택을 누르고 빌드 및 배포 파이프라인에서 프로퍼티 구성 파일의 배포를 쉽게 통합할 수 있다. </p>
</li>
</ul>
<p>application.yml</p>
<pre><code>server : 
    port : 8888
spring : 
   cloud : 
      config : 
         server : 
            encrypt.enabled : false
            git :  ---- 스프링 클라우드 컨피그에 백엔드 저장소로 깃을 사용한다고 전달한다. 
                uri : https://github.com/klimtever/config-repo/ ---- 스프링 클라우드 컨피그에 깃 서버와 깃 repo의 URL을 전달한다.
                searchPaths : licensingservice, organizationservice ---- 스프링 클라우드 컨피그에 구성 파일을 찾을 깃 경로를 전달한다.
                username : native-cloud apps
                password : 0ffended
</code></pre><p><strong><em>세 가지 중요한 구성은 spring.cloud.config.server, spring.cloud.config.server.git.uri와 spring.cloud.config.server.git.searchPaths 프로퍼티다.</em></strong> </p>
<p>*<em>spring.cloud.config.server *</em>: 프로퍼티에서 스프링 클라우드 컨피그 서버에 파일 시스템 기반이 아닌 백엔드 저장소를 사용할 것이라고 알린다. </p>
<p><strong>spring.cloud.config.server.git.uri</strong> : 프로퍼티는 접속할 저장소의 URL를 제공한다.  </p>
<p>*<em>spring.cloud.config.server.git.searchPaths *</em>: 프로퍼티는 스프링 클라우드 컨피그 서버가 가동될 때 검색할 깃 저장소의 상대 경로를 전달한다. </p>
<p><br/><br/><br/></p>
<h3 id="스프링-클라우드-컨피그-서버에서-프로퍼티-갱신">스프링 클라우드 컨피그 서버에서 프로퍼티 갱신.</h3>
<p>: 스프링 부트 액추에이터는 @RefreshScope 애너테이션을 제공하므로 스프링 부트 애플리케이션을 제공하므로 스프링 부트 애플리케이션이 /refresh 엔드포인트를 사용해 애플리케이션 구성 정보를 다시 읽어올 수 있다. </p>
<pre><code>@SpringBootApplication
@RefreshScope
public class Application{
    public static void main(String[] args){
        SpringApplication.run(Application.class, args);
    }
}</code></pre><p>@RefreshScope 애너테이션에 대해 두가지 사항을 유의하자.</p>
<ol>
<li>이 애너테이션은 애플리케이션 구성에 있는 사용자 정의 스프링 프로퍼티만 다시 로드한다.
( 즉, 데이터베이스 구성 정보처럼 스프링 데이터에서 정의된 구성은 @RefreshScope 애너테이션으로 다시 로드하지 않는다.)</li>
</ol>
<ol start="2">
<li>둘째, 업데이트 를 수행하기 위해 http://<yourserver>:8080/actuator/refresh 엔드포인트를 호출한다.</li>
</ol>
<blockquote>
<p>  스프링 클라우드 컨피그 서비스는 이 서비스를 사용하는 모든 클라이언트에 변경이 일어났다고 알려 주는 스프링 클라우드 버스라는 푸시 기반의 매커니즘을 제공한다. 스프링 클라우드 컨피그는 RabbitMQ 같은 미들웨어를 추가해야 한다. 
  ( 변경을 감지하는 매우 유용한 방법이지만 모든 스프링 클라우드 컨피그 백엔드가 콘설 서버처럼 푸시 매커니즘을 지원하는 것은 아니다.</p>
</blockquote>
<p>  <BR/><BR/><BR/></p>
<h3 id="중요한-구성-정보-보호">중요한 구성 정보 보호</h3>
<ul>
<li><p>스프링 클라우드 컨피그는 중요한 프로퍼티를 쉽게 암호화할 수 있는 기능을 제공하며 대칭(공유 비밀 키 사용) 및 비대칭 암호화(공개 비공개 키 사용)를 모두 지원한다.</p>
</li>
<li><p><em>✔암화화 적용 단계 *</em></p>
</li>
<li><ul>
<li><ol>
<li>암호화에 필요한 오라클 JCE.jar 파일을 내려받고 설치한다.</li>
<li>암호화 키를 설정한다.</li>
<li>프로퍼티를 암호화 및 복호화 한다. **</li>
</ol>
<strong>4. 클라이언트 측에서 암호화하도록 마이크로서비스를 구성한다</strong>.</li>
</ul>
</li>
</ul>
  <br/>

<blockquote>
<p>실행 중인 애플리케이션과 서버가 불변하고 여러 환경에 배포되는 어떤 서버도 수작업으로 구성하지 않아야 한다. 하지만 이 모델은 JAR나 WAR 파일처럼 애플리케이션 산출물과 프로퍼티를 고정된 환경에 함께 배포하는 전통적인 배포 모델과는 상충된다.</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[Devops : 혹독한 런타임 구축.]]></title>
            <link>https://velog.io/@keep_going/Devops-%ED%98%B9%EB%8F%85%ED%95%9C-%EB%9F%B0%ED%83%80%EC%9E%84-%EA%B5%AC%EC%B6%95</link>
            <guid>https://velog.io/@keep_going/Devops-%ED%98%B9%EB%8F%85%ED%95%9C-%EB%9F%B0%ED%83%80%EC%9E%84-%EA%B5%AC%EC%B6%95</guid>
            <pubDate>Sun, 27 Dec 2020 07:59:10 GMT</pubDate>
            <description><![CDATA[<p>데브옵스 엔지니어에게 마이크로서비스 설계란 양산 이후의 서비스 관리에 관한 설계다. 
<br/><Br/></p>
<h2 id="데브옵스-마이크로-서비스-개발-원칙-4가지">데브옵스 마이크로 서비스 개발 원칙 4가지</h2>
<p>첫번째, 마이크로서비스는 단일 소프트웨어 산출물을 이용해 여러 서비스 인스턴스를 시작하거나 제거할 수 있도록 자체 완비형이며 독립적으로 배포 가능해야 한다. </p>
<ul>
<li>애플리케이션 환경변환에 대응해 마이크로서비스의 여러 인스턴스를 신속하게 배포할 수 있다는 것이다.</li>
<li>거의 모든 자바 마이크로서비스 프레임워크는 코드와 함께 패키징하고 배포할 수 있는 런타임 엔진을 포함한다.
<br/><br/></li>
</ul>
<p>두번째, 마이크로서비스는 구성 가능해야 한다. 서비스 인스턴스가 시작될 때 구성에 필요한 데이터를 중앙에서 읽어 들이거나 환경 변수로 전달된 구성 정보를 받아야 한다. 서비스를 구성하는데 사람의 개입은 필요하지 않다.</p>
<ul>
<li>일반적으로 이 작업은 애플리케이션과 함께 배포된 프로퍼티 파일에서 애플리케이션 구성 데이터를 읽거나 관계형 데이터베이스 같은 데이터 저장소에서 데이터를 읽어오는 작업이다.
<br/><br/></li>
</ul>
<p>세번째,  마이크로서비스 인스턴스는 클라이언트가 위치를 알지 못하도록 투명해야 한다. 클라이언트는 서비스의 정확한 위치를 알고 있어서는 안된다. 그 대신에 마이크로서비스 클라이언트는 마이크로서비스 인스턴스의 물리적 위치를 모르더라도 애플리케이션이 알 수 있도록 서비스 디스커버리 에이전트와 통신해야 한다.</p>
<ul>
<li>마이크로서비스 소비자 관점에서 마이크로서비스는 위치 투명성을 가져야 한다. </li>
<li>클라우드 기반 환경에서 서버는 일시적이기 때문이다. &#39;일시적&#39;이라는 말은 서비스를 호스팅하는 서버 수명이 기업 데이터센터에서 실행되는 서비스보다 더 짧아진다는 것을 의미한다. 
(클라우드 기반 서비스는 실행될 서버에 완전히 새로운 IP 주소를 할당받고 신속히 시작하고 제거할 수 있다.)</li>
<li>서비스를 일시적이고 폐기 가능한 객체로 취급해야 한다는 주장 덕분에 마이크로서비스 아키텍처는 많은 서비스 인스턴스를 실행하며 고수준의 확장성과 가용성을 얻을 수 있었다.
(일시적 서비스의 단점은 끊임없이 서비스의 시작과 종료를 반복하는 상황에서 일시적 서비스를 대량으로 수동 또는 직접 관리하면서 장애가 발생할 수 있다는 것이다.</li>
</ul>
<p><br/><Br/></p>
<p>네번째, 마이크로서비스는 자신의 상태를 전달해야 한다. 이는 클라우드 아키텍처에서 매우 중요한 부분이다. 마이크로서비스 인스턴스들은 고장 날 수 있으며 클라이언트는 잘못된 서비스 인스턴스를 피해 라우팅해야 한다.</p>
<ul>
<li>클라우드 기반 마이크로서비스 애플리케이션에서는 종종 어떤 서비스의 많은 인스턴스가 실행될 수 있고 언젠가 그 서비스 인스턴스 중 하나가 고장날 것이다. 서비스 디스커버리 에이전트는 등록된 각 서비스 상태를 모니터링한다. 
( 그리고 클라이언트가 고장 난 서비스를 호출하지 않도록 자신의 라우팅 테이블에서 문제가 된 서비스 인스턴스를 제거한다. ) </li>
<li>스프링 부트를 사용하면 엔드포인트를 노출하기 쉬운데, 메이븐 빌드 파일을 수정해 스프링 엑추에이터 모듈만 추가하면 된다.</li>
</ul>
<p><br/><br/></p>
<p><br/><br/><br/></p>
<h2 id="마이크로-서비스-수명주기">마이크로 서비스 수명주기</h2>
<p><img src="https://images.velog.io/images/keep_going/post/cca3eab1-7d3b-40f8-be0d-87722f36f62a/100.jpg" alt=""></p>
<p>*<em>Step1) 서비스 어셈블리 *</em>: 동일한 서비스 코드와 런타임을 정확히 같은 방식으로 배포하기 위해 반복성과 일관성을 보장하는 서비스 패키징과 배포 방식은 무엇인가?</p>
<p>*<em>Step2) 서비스 부트스트래핑 *</em>: 사람이 개입하지 않아도 모든 환경에 마이크로서비스 인스턴스를 신속하게 배포하기 위해 애플리케이션과 환경별 구성 코드를 런타임 코드와 분리하는 방법은 무엇인가?</p>
<p>*<em>Step3) 서비스 등록 및 디스커버리 *</em>: 새로운 마이크로서비스 인스턴스가 배포될 때 다른 애플리케이션 클라이언트가 발견할 수 있게 만드는 방법은 무엇인가?</p>
<p><strong>Step4) 서비스 모니터링</strong> : 마이크로서비스 환경에서 매우 높은 가용성을 요구하기 때문에 동일 서비스를 여러 인스턴스로 실행하는 것이 일반적이다. 데브옵스 관점에서 마이크로서비스 인스턴스를 모니터링하고 마이크로서비스 고장을 회피하는 라우팅과 비정상 인스턴스를 제거하는지 확인해야 한다.</p>
<p><br/><Br/><br/><br/></p>
<h4 id="twelve-factor-마이크로-서비스-애플리케이션-구축">Twelve-Factor 마이크로 서비스 애플리케이션 구축.</h4>
<p>[성공적인 마이크로 서비스 아키텍처를 위해 강력한 애플리케이션 개발과 데브옵스 실천이 필요함을 깨닫는다. 이러한 실천의 간결한 요약 중 하나가 <strong>Heroku&#39;s의 Twelve-Factor이다. (12개의 모범지침 제공)</strong>. ]</p>
<h2 id="herokus-의-twelve-factor">Heroku&#39;s 의 Twelve-Factor</h2>
<blockquote>
<p><strong>1. 코드베이스</strong> : 모든 애플리케이션 코드와 서버 프로비저닝(provisioning) 정보는 버전관리되어야 한다. 각 마이크로 서비스는 소스 제어 시스템 안에 독립적인 코드 저장소를 가져야 한다.
<br/>
<strong>2. 의존성</strong> : 애플리케이션이 사용하는 의존성을 메이븐 같은 빌드 도구를 이용해 명시적으로 선언해야 한다. 제3자의 JAR 의존성은 특정 버전 번호를 붙여 명시해 선언해야 한다. 따라서 동일 버전의 라이브러리를 사용해 항상 마이크로서비스를 빌드할 수 있다.
<BR/>
<strong>3. 구성</strong> : 애플리케이션 구성(특히 환경별 구성)을 코드와 독립적으로 저장하자. 애플리케이션 구성은 절대로 소스 코드와 동일한 저장소에 있으면 안된다. <Br/>
<strong>4. 백엔드 서비스</strong> : 마이크로서비스는 대개 네트워크를 거쳐 데이터베이스나 메시징 서비스와 통신한다. 그렇다면 언제든 데이터베이스 구현을 자체 관리형 서비스에서 외부업체 서비스로 교체할 수 있어야 한다. </br>
<strong>5. 빌드, 릴리스, 실행(build, release, run)</strong> : 배포할 애플리케이션의 빌드, 릴리스, 실행 부분을 철저히 분리하라. 코드가 빌드되면 개발자는 실행 중에 코드를 변경할 수 없다. 모든 변경 사항을 빌드 프로세스로 되돌려 재배포해야 한다. 빌드된 서비스는 불변적이므로 변경할 수 없다. <br/>
<strong>6. 프로세스</strong> : 마이크로서비스는 항상 무상태 방식을 사용해야 한다. 서비스 인스턴스 손실에 의해 데이터가 손실될 것이라는 우려 없이 언제든 서비스를 강제 종료하거나 교체할 수 있다. <BR/>
<strong>7. 포트 바인딩</strong> : 마이크로서비스는 서비스용 런타임 엔진을 포함한 완전히 자체 완비형이다. 별도의 웹 또는 애플리케이션 서버 없이도 서비스는 실행되어야 한다. 서비스는 명령행에서 단독으로 시작하고 노출한 HTTP 포트를 통해 즉시 엑세스 할 수 있어야 한다.<BR/>
  <strong>8. 동시성</strong>  : 확장해야 한다면 단일 서비스 안에서 스레드 모델에 의존하지 마라. 마이크로서비스 안에서 스레드 사용을 배제하지는 않지만 확장을 위한 유일한 매커니즘으로 믿지 말라. 수직 대신 수평 확장하라.<BR/>
  <strong>9. 폐기 기능</strong> : 마이크로서비스는 폐기 가능하므로 요구에 따라 시작 및 중지할 수 있다. 시작 시간은 최소화하고 운영 체제에서 강제 종료 신호를 받으면 프로세스는 적절히 종료해야 한다.<BR/>
  *<em>10. 개발 및 운영 환경 일치 *</em>: 서비스가 실행되는 모든 환경 사이의 차이를 최소화하라. 개발자는 서비스 개발을 위해 실제 서비스가 실행되는 동일한 인프라스트럭처를 로컬에 사용해야 한다. 이는 환경 간 서비스 배포가 수 주가 아닌 수 시간 안에 이루어져야 한다는 것을 의미한다. 코드가 커밋되자마자 테스트되고 가능한 신속하게 개발 환경에서 운영환경으로 전파되어야 한다. <BR/>
  *<em>11. 로그 *</em>: 로그는 이벤트 스트림이다. 로그가 기록될 때 스플렁크 같은 도구로 로그가 스트리밍되어야 한다. 이들 도구는 로그를 수집해 중앙에 기록한다. 마이크로서비스는 이러한 로깅 동작 방식에 신경쓰지 않아야 하며, 개발자는 표준 출력으로 출력된 로그를 시간적으로 확인할 수 있어야 한다. <BR/>
  *<em>12. 관리 프로세스 *</em>: 개발자는 종종 담당 서비스에 대해 데이터 마이그레이션이나 변환처럼 관리 작업을 수행해야 한다. 이러한 작업은 임의로 수행되면 안 되고 소스 코드 저장소에 유지 및 관리되는 스크립트에 의해 수행되어야 한다.</p>
</blockquote>
<BR/>


<BR/>
<BR/>
<BR/>

<h2 id="정리">정리</h2>
<ol>
<li><p>마이크로서비스의 성공을 위해 아키텍트, 소프트웨어 개발자, 데브옵스 관점을 통합해야 한다.<BR/></p>
</li>
<li><p>마이크로 서비스는 강력한 아키텍처 패러다임이지만, 혜택과 장단점이 있다. 모든 애플리케이션이 마이크로서비스 애플리케이션일 필요는 없다. </p>
<BR/></li>
<li><p>아키텍트 관점에서 마이크로서비스는 작고, 자체 완비형이며, 분산된 것이다. 마이크로서비스는 좁은 범위와 소규모 데이터를 관리한다.</p>
<BR/></li>
<li><p>개발자 관점에서 REST 설계 방식과 서비스의 데이터 송수신을 위한 JSON을 사용해 마이크로서비스를 구축한다.</p>
<BR/></li>
<li><p>데브옵스 관점에서 마이크로서비스를 패키징, 배포, 모니터링하는 방법은 매우 중요하다.</p>
<BR/></li>
<li><p>스프링 부트를 사용하면 서비스를 하나의 JAR 실행 파일로 전달할 수 있다. JAR 파일에 내장된 톰캣 서버가 서비스를 호스팅한다.</p>
<BR/></li>
<li><p>스프링 부트 프레임워크에 포함된 스프링 액추에이터는 서비스 런타임 정보와 함께 서비스의 운영 상태 정보도 제공한다.</p>
</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[REST와 JSON]]></title>
            <link>https://velog.io/@keep_going/REST%EC%99%80-JSON</link>
            <guid>https://velog.io/@keep_going/REST%EC%99%80-JSON</guid>
            <pubDate>Sun, 27 Dec 2020 06:45:21 GMT</pubDate>
            <description><![CDATA[<ul>
<li><p><strong>서비스 호출 프로토콜로 HTTP를 사용한다</strong> : 서비스는 HTTP 엔드포인트로 노출되고 HTTP 프로토콜을 사용해서 서비스와 데이터를 교환한다.</p>
</li>
<li><p><strong>서비스의 행동 양식을 표준 동사에 매핑한다</strong> : REST는 서비스의 행동 양식을 HTTP 동사인 POST, GET, PUT, DELETE에 매핑할 것을 강조한다. 그리고 이 동사의 대부분의 서비스에 있는 CRUD 함수에 매핑된다.</p>
</li>
<li><p><strong>서비스끼리 교환하는 모든 데이터의 직렬화 형식으로 JSON을 사용한다</strong> : JSON은 마이크로서비스에서 입출력 데이터의 직렬화를 위한 공용어가 되었다. XML을 사용할 수도 있지만 많은 REST 기반 애플리케이션은 자바스크립트와 JSON을 더 많이 사용한다. </p>
</li>
<li><p><strong>HTTP 상태 코드를 사용해 서비스 호출 상태를 전달한다</strong> : HTTP 프로토콜은 풍부한 상태 코드를 제공해 서비스의 성공과 상태를 나타낼 수 있다. REST 기반 서비스는 HTTP 상태 코드와 리버스 프록시(reverse proxy)나 캐시(cache)처럼 웹 기반 인프라스트럭처를 활용해 여러분의 마이크로 서비스와 비교적 쉽게 통합할 수 있다.</p>
</li>
</ul>
<blockquote>
<p>http는 웹 언어이며, 서비스 구축을 위한 철학적 프레임워크로 http를 사용하는 것은 클라우드에서 서비스를 구축하는 핵심이다.</p>
</blockquote>
<p><BR/><BR/><BR/></p>
<h4 id="restcontroller">RestController</h4>
<p>서비스에 JSON이나 XML로 전달된 데이터의 직렬화를 자동으로 처리한다. (기본적으로 @RestController 클래스는 반환할 데이터를 JSON으로 직렬화 한다.)</p>
<ul>
<li>RestController 애너테이션을 사용하면 Controller 클래스에서 ResponseBody클래스로 반환할 필요가 없다. 
(@ResponseBody)를 포함하는 @RestController 애너테이션에 의해 모두 처리되기 때문이다.</li>
</ul>
<p><BR/><BR/><BR/><br/><Br/></p>
<h4 id="마이크로서비스에-json이-선택된-이유">마이크로서비스에 JSON이 선택된 이유</h4>
<p>다양한 프로토콜을 사용해 HTTP 기반의 마이크로서비스 간에 데이터를 주고 받을 수 있다. JSON은 몇 가지 이유로 사실상 표준으로 등장했다.</p>
<p>첫째, XML 기반의 SOAP(Simple Object Access Protocal)과 같은 다른 프로토콜과 비교할 때 <strong>JSON은 적은 텍스트로 데이터 표현이 가능하다는 점에서 매우 가볍다</strong>.</p>
<p>둘째, <strong>JSON은 가독성이 높고 사용하기 쉽다</strong>. 이 특성은 직렬화 프로토콜을 선택하는 기준으로 과소평가되지만 문제가 발생하면 신속하게 JSON 내용을 살펴보고 문제를 시각적으로 처리하는 것이 중요하다. JSON은 프로토콜이 단순해 이러한 작업을 아주 쉽게 처리할 수 있다.</p>
<p>셋째, <strong>JSON은 자바스크립트에서 사용되는 기본 직렬화 프로토콜이다</strong>. 프로그래밍 언어로서 자바스크립트가 급격하게 성장하고 자바스크립트에 크게 의존하는 SPIA(Single Page Internet Application), 즉 단일 페이지 인터넷 애플리케이션이 급격하게 증가해서 JSON은 REST 기반 애플리케이션 적임자가 되었다. 프런트엔드 웹 클라이언트가 서비스를 호출하는데 JSON이 사용되기 때문이다.</p>
<blockquote>
</blockquote>
<p>서비스 간 통신을 위해 JSON보다 더 효율적인 매커니즘과 프로토콜도 존재한다. 아파치 쓰리프트 프레임워크를 이용하면 바이너리 프로토콜로 서로 통신할 수 있는 다중 언어 서비스를 구축할 수 있다. 
*아파치 아브로는 클라이언트와 서버 호출 간 데이터를 바이너리 포맷으로 상호 변환할 수 있는 데이터 직렬화 프로토콜이다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[아키텍처 설계, 마이크로서비스를 사용하지 않아야 할 때]]></title>
            <link>https://velog.io/@keep_going/%EC%95%84%ED%82%A4%ED%85%8D%EC%B2%98-%EC%84%A4%EA%B3%84</link>
            <guid>https://velog.io/@keep_going/%EC%95%84%ED%82%A4%ED%85%8D%EC%B2%98-%EC%84%A4%EA%B3%84</guid>
            <pubDate>Sun, 27 Dec 2020 05:06:59 GMT</pubDate>
            <description><![CDATA[<h3 id="마이크로-서비스-아키텍처를-구축할-때-프로젝트의-아키텍트가-하는-3가지-일">마이크로 서비스 아키텍처를 구축할 때 프로젝트의 아키텍트가 하는 3가지 일</h3>
<ol>
<li>비지니스 문제의 분해</li>
<li>서비스 세분화의 확정</li>
<li>서비스 인터페이스의 정의</li>
</ol>
<p><br/><br/>
&quot;마이크로 서비스 아키텍처는 비지니스 문제를 각 활동 영역을 대표하는 덩이들로 분해하고, 비즈니스 영역의 특징 부분과 연관된 비즈니스 규칙과 데이터 로직을 이 덩이들 안에 캡슐화 한다.&quot;</p>
<h3 id="비즈니스-문제를-익식하고-마이크로서비스-후보로-분해하는데-확인해야-할-지침-3가지">비즈니스 문제를 익식하고 마이크로서비스 후보로 분해하는데 확인해야 할 지침 3가지</h3>
<ol>
<li>비즈니스 문제를 기술하고 그 문제를 기술하는데 사용된 명사에 주목하라.</li>
<li>동사에 주목하라.</li>
<li>데이터 응집성을 찾아라.
: 비지니스 문제를 각 부분으로 분해할 때 서로 연관성이 높은 데이터 부분들을 찾는다. 마이크로 서비스는 자기 데이터를 완전히 소유해야 한다.</li>
</ol>
<p><br/><br/></p>
<h3 id="마이크로서비스-아키텍처를-구축할-때-고려해야-할-3가지">마이크로서비스 아키텍처를 구축할 때 고려해야 할 3가지</h3>
<ol>
<li><strong>큰 마이크로 서비스에서 시작해 작게 리팩토링하는 것이 더 낫다.</strong>
(문제 영역을 한 번에 작은 서비스들로 분해하는 것은 마이크로 서비스가 그저 단순한 데이터 서비스로 전략하기 때문에 너무 일찍 복잡함을 겪게 된다.)</li>
<li><strong>서비스 간 교류하는 방식에 먼저 집중한다.</strong>
(문제 영역에 대한 큰 단위의 인터페이스를 만드는데 도움이 된다.)</li>
<li>** 문제 영역에 대한 이해가 깊어짐에 따라 서비스 책임도 계속 변한다.**</li>
</ol>
<blockquote>
<p>마이크로 서비스는 처음부터 올바르게 설계하기 어렵기 때문에 진화론적 사고 과정으로 개발해야 한다. 
 끝으로 완벽한 설계를 위해 시간을 낭비하고 노력에 비해 보여 줄 것이 없는 것보다는 실용적인 접근 방식을 취하고 결과물을 전달하자.</p>
</blockquote>
<p><br/><Br/></p>
<h3 id="서비스-인터페이스-설계시-4가지-고려사항">서비스 인터페이스 설계시 4가지 고려사항.</h3>
<p><strong>1. REST 철학을 수용하라.</strong>
 : REST 방식은 서비스의 호출 프로토콜로 HTTP를 수용하고 표준 HTTP동사(GET, PUT, POST, DELETE)를 사용하는 것이 핵심이다.</p>
<p><strong>2. URL를 사용해 의도를 전달하라.</strong></p>
<p><strong>3. 요청(request)과 응답(response)에 JSON을 사용하라.</strong>
 : JSON은 초경량 데이터 직렬화 프로토콜이며 XML보다 훨씬 사용하기 쉽다.</p>
<p><strong>4. HTTP 상태 코드로 결과를 전달하라.</strong>
 : HTTP 프로토콜에는 서비스의 성공과 실패를 명시하는 풍부한 표준 응답 코드가 있다. 상태 코드를 익히고 모든 서비스에 일관되게 사용하는 것이 매우 중요하다.</p>
<p> <BR/><BR/><bR/><BR/><BR/></p>
<h3 id="마이크로-서비스를-사용하면-안되는-4가지-경우">마이크로 서비스를 사용하면 안되는 4가지 경우</h3>
<p>*<em>1. 분산 시스템 구축의 복잡성
2. 가상 서버/컨테이너의스프롤
3. 애플리케이션 유형
4. 데이터 변환과 일관성
*</em></p>
<blockquote>
<p>** 1. 분산 시스템 구축의 복잡성**
마이크로서비스는 잘게 나뉘고 분산되어 있어 모놀리식 애플리케이션에 없던 복잡성을 가져온다. 마이크로서비스 아키텍처에는 높은 수준의 운영 성숙도도 필요하다. 따라서 고도로 분산된 애플리케이션을 성공시키는 데 필요한 자동호와 운영 작업에 투자할 의사가 없는 조직이라면 마이크로서비스를 고려하지 않는 것이 좋다.</p>
</blockquote>
<blockquote>
<p>** 2. 서버 스프롤(Server sprawl)**
마이크로서비스의 가장 일반적인 배포 모델 중 하나는 한 서버에 하나의 마이크로서비스 인스턴스를 배포하는 것이다. 대규모 마이크로서비스 기반 애플리케이션의 운영 환경에서만 구축 및 관리가 필요한 서버나 컨테이너가(일반적으로 가상의) 50~100개 있을 수 있다. 클라우드에서 이들 서비스를 실행하는 데 드는 비용은 저렴하더라도 서버를 관리하고 모니터링하는 운영 작업은 엄청나게 복잡해질 수 있다. </p>
</blockquote>
<blockquote>
<p>** 3. 애플리케이션 유형 **
마이크로 서비스는 재사용성을 추구하며 높은 회복성과 확장성이 필요한 대규모 애플리케이션 구축에 매우 유용하다. 이 때문에 많은 클라우드 기반 기업에서 마이크로서비스를 채택한다. 소수 사용자를 위한 애플리케이션을 개발할 때 마이크로서비스와 같은 분산 모델로 구축한다면 구축에 따른 복잡성이 얻게 될 가치보다 더 클 수 있다.</p>
</blockquote>
<blockquote>
<p><strong>4. 데이터 변환과 일관성</strong>
 마이크로서비스를 검토할 때 여러분은 서비스의 데이터 사용 패턴과 서비스 소비자가 어떻게 서비스를 사용하는지 고민해야 한다. 마이크로서비스는 적은 수의 테이블을 둘러싸고 추상화하며 저장소에 단순한 질의 생성, 추가, 실행 등 &#39;운영상의&#39; 작업을 수행하는 매커니즘으로 잘 동작한다.
 애플리케이션이 여러 데이터 소스에서 복잡한 데이터를 취합하고 변환해야 할 경우 마이크로서비스의 분산된 특성 때문에 작업이 어려워진다. 마이크로서비스는 변함없이 과도한 책임을 떠안고 성능 문제에도 취약해질 것이다. 마이크로서비스 사이에 트랜잭션을 처리하는 표준이 없다는 사실도잊지말자. 트랜잭션 곤리자가 필요하다면 직접 만들어야 한다.</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[폭포수 개발 방법론, 마이크로 아키텍처 특징, 클라우드 서비스 특징 ]]></title>
            <link>https://velog.io/@keep_going/%ED%8F%AD%ED%8F%AC%EC%88%98-%EA%B0%9C%EB%B0%9C-%EB%B0%A9%EB%B2%95%EB%A1%A0-%EB%A7%88%EC%9D%B4%ED%81%AC%EB%A1%9C-%EC%95%84%ED%82%A4%ED%85%8D%EC%B2%98-%ED%8A%B9%EC%A7%95-%ED%81%B4%EB%9D%BC%EC%9A%B0%EB%93%9C-%EC%84%9C%EB%B9%84%EC%8A%A4-%ED%8A%B9%EC%A7%95</link>
            <guid>https://velog.io/@keep_going/%ED%8F%AD%ED%8F%AC%EC%88%98-%EA%B0%9C%EB%B0%9C-%EB%B0%A9%EB%B2%95%EB%A1%A0-%EB%A7%88%EC%9D%B4%ED%81%AC%EB%A1%9C-%EC%95%84%ED%82%A4%ED%85%8D%EC%B2%98-%ED%8A%B9%EC%A7%95-%ED%81%B4%EB%9D%BC%EC%9A%B0%EB%93%9C-%EC%84%9C%EB%B9%84%EC%8A%A4-%ED%8A%B9%EC%A7%95</guid>
            <pubDate>Sun, 27 Dec 2020 03:22:17 GMT</pubDate>
            <description><![CDATA[<h3 id="폭포수-개발-방법론의-단점">폭포수 개발 방법론의 단점</h3>
<ul>
<li><p><strong>강한 결합</strong> : 컴포넌트를 조금만 수정해도 그 애플리케이션의 다른 부분을 깨뜨리거나 새로운 거브를 생산할 가능성이 매우 높다..</p>
</li>
<li><p><strong>누설</strong> : 대규모 소프트웨어 애플리케이션의 대부분은 다양한 유형의 데이터를 취급한다. 예를 들어 고객 관계 관리(CRM) 애플리케이션은 고객, 판매, 제품 정보를 관리한다. 여기서 다른 영역의 데이터에 쉽게 접근하게 되면 보이지 않는 의존성이 생겨나고 컴포넌트의 내부 데이터 구조에 대한 세부 구현이 애플리케이션 전체에 유출될 수 있다. </p>
</li>
<li><p><strong>모놀리식</strong> : 전통적인 애플리케이션에서 대부분의 컴포넌트는 여러 팀에서 공유되는 단일 코드 베이스에 저장하므로 코드를 변경할 때마다 전체 테스팅 주기를 재수행하며 재배포한다. 애플리케이션 코드 베이스를 조금만 변경해도 비용이 많이 들며 오랜시간이 소요된다.</p>
</li>
</ul>
<p><BR/><BR/><BR/></p>
<h3 id="마이크로서비스-기반-아키텍처-특징">마이크로서비스 기반 아키텍처 특징</h3>
<ul>
<li><p><strong>제한</strong> : 마이크로서비스는 책임집합을 가지는 범위가 좁다. 마이크로 서비스는 애플리케이션이 한 가지 일을 하며, 정말 잘하는 서비스 집합에 불과하다는 유닉스 철학을 수용한다.</p>
</li>
<li><p><strong>느슨한 결합</strong> : HTTP와 REST처럼 비독점적 호출 프로토콜을 사용하는 구현 기술에 중립적인 인터페이스로 서로 소통한다. 
(서비스에 대한 인터페이스가 변하지 않는 한 마이크로서비스 소유자는 전통적인 애플리케이션 아키텍처보다서비스를 더 자유롭게 수정할 수 있다.)</p>
</li>
<li><p><strong>추상화</strong> : 마이크로서비스의 데이터를 보관하는 데이터베이스에서 해당 서비스만 접근할 수 있도록 통제할 수 있다.</p>
</li>
<li><p><strong>독립적</strong> : 마이크로서비스 애플리케이션 안의 모든 마이크로서비스는 서로 독립적으로 컴파일하고 배포할 수 있다. 
(상호 의존성이 높은 모놀리식 애플리케이션보다 변경 사항을 훨씬 쉽게 분리하고 테스트할 수 있다는 것을 의미한다.)</p>
</li>
</ul>
<p><BR/><BR/><BR/></p>
<h3 id="클라우드-기반-애플리케이션-특징">클라우드 기반 애플리케이션 특징.</h3>
<ul>
<li><p><strong>사용자층이 다양하며 대규모다</strong> : 고객마다 서로 다른 제품 기능을 원하며, 이 기능을 접하기까지 애플리케이션의 긴 릴리스 주기를 기다리고 싶어 하지 않는다. 마이크로서비스는 작은 범위를 담당하고, 명확히 정의된 인터페이스를 통해 접근하므로 기능을 신속하게 제공할 수 있다.</p>
</li>
<li><p><strong>상당한 작동 시간이 요구된다</strong> : 마이크로서비스 자체의 분산적 특성 때문에 마이크로서비스 기반 애플리케이션은 애플리케이션 전체를 중단하지 않고도 고장과 문제를 더 쉽게 격리할 수 있다. 이로 인해 전반적인 애플리케이션 작동 중지 시간은 줄어들고 결함 저항력은 높아진다.</p>
</li>
<li><p><strong>볼륨이 균일하지 않다</strong> : 기업 데이터센터에서 운용되는 전통적인 애플리케이션은 대개 일정한 사용 패턴을 가지므로, 애플리케이션의 용량 계획은 간단하다. 하지만 클라우드 기반 애플리케이션 환경에서는 포스팅 하나가 엄청한 수요를 불러올 수 있다.
(마이크로 서비스는 독립적인 배포가 가능한 작은 컴포넌트로 분리되어 있기 때문에 부하를 받는 컴포넌트를 조명하고 여러 서버에 수평 확장하기도 훨씬 쉽다.</p>
</li>
</ul>
<p><BR/><BR/><BR/></p>
<h4 id="성공적인-마이크로서비스-개발-토대는-다음-중요한-세-역할의-관점에서-시작한다">성공적인 마이크로서비스 개발 토대는 다음 중요한 세 역할의 관점에서 시작한다.</h4>
<ul>
<li><p><strong>아키텍트</strong> : 아키텍트의 역할은 솔루션을 제공하기 위해 큰 그림을 바라보고 애플리케이션을 개별 마이크로서비스로 분해하는 방법과 마이크로서비스의 상호 작용 방법을 이해하는 것이다.</p>
</li>
<li><p><strong>소프트웨어 개발자</strong>:  코드를 작성하고 마이크로서비스를 제공하기 위해 프로그래밍 언어와 해당 언어용 개발 프레임워크의 사용 방법을 자세히 이해해야 한다.</p>
</li>
<li><p><strong>데브옵스 엔지니어</strong> : 데브옵스 엔지니어는 운영 환경 및 비 운영 환경에서 서비스 배포와 관리 방법 정보를 제공한다. 데브옵스 엔지니어의 좌우명은 모든 환경에서의 일관성과 반복성이다.</p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[스프링, 클라우드와 만나다. ]]></title>
            <link>https://velog.io/@keep_going/%EC%8A%A4%ED%94%84%EB%A7%81-%ED%81%B4%EB%9D%BC%EC%9A%B0%EB%93%9C%EC%99%80-%EB%A7%8C%EB%82%98%EB%8B%A4</link>
            <guid>https://velog.io/@keep_going/%EC%8A%A4%ED%94%84%EB%A7%81-%ED%81%B4%EB%9D%BC%EC%9A%B0%EB%93%9C%EC%99%80-%EB%A7%8C%EB%82%98%EB%8B%A4</guid>
            <pubDate>Thu, 10 Dec 2020 11:30:04 GMT</pubDate>
            <description><![CDATA[<h3 id="마이크로-서비스-사용이유">마이크로 서비스 사용이유</h3>
<p>마이크로 서비스를 사용하면 대형 애플리케이션을 관리하기 쉽고, 제한된 책임을 담당하는 컴포넌트로 분해할 수 있다. 
마이크로서비스를 고려할 때 수용해야 할 핵심 개념은 애플리케이션 기능을 분해하고 분리해서 완전히 상호 독립적이어야 한다는 것이다.
<br><Br>
  <Br></p>
<h3 id="스프링과-마이크로-서비스의-관련성">스프링과 마이크로 서비스의 관련성</h3>
<p> 스프링은 의존성 주입 프레임워크를 사용하면 하드 코딩 하지 않고, 관례와 annotation으로 객체 간 관계를 외부화할 수 있어 대규모 자바프로젝트를 더 쉽게 관리할 수 있다. </p>
<p>  스프링 클라우드 프레임워크를 사용하면 private 및 public 공용 클라우드에 마이크로서비스를 쉽게 운영하고 배포할 수 있다. </p>
<br>
<br>


<h4 id="스프링-부트는-다음과-같이-요약-된다">스프링 부트는 다음과 같이 요약 된다.</h4>
<p>  작고(small) 단순하며(simple) 분리된(decoupled)서비스 = 확장 가능하고(scalable) 회복적이며(resilient) 유연한 애플리케이션</p>
<BR>
  <bR>


<h3 id="왜-클라우드는-마이크로서비스인가">왜 클라우드는 마이크로서비스인가?</h3>
<p> 마이크로 서비스를 작성하는 개발자는 서비스를 다음 중 어디에 배포할지 조만간 결정해야 한다.</p>
<ul>
<li><p>물리적 서버 : 용량을 빠르게 늘릴 수 없고 마이크로서비스를 수평 확장하는데 상당한 비용이 든다.</p>
</li>
<li><p>가상 머신 이미지 : 장점으로는 확장하고 실패 이벤트를 받을 때 신속하게 마이크로서비스 인스턴스를 시작하고 종료할 수 있다는 것이다.
(여러 인스턴스를 신속하게 IaaS형 사설 및 공용 클라우드에 배포하고 시작할 수 있다.)</p>
</li>
<li><p>가상 컨테이너 : 가상 머신 이미지 기반의 마이크로서비스 배포를 자연스럽게 확장한 것이다. 도커 컨테이너로 자기 서비스를 클라우드에 배포한다. 가상 컨테이너는 가상 머신 안에서 실행된다.</p>
</li>
</ul>
<pre><code>&quot; 클라우드 기반의 마이크로 서비스는 탄력성 개념을 중심으로 한다. 클라우드 서비스 공급자를 통해 몇 분 안에 새로운 가상 머신과 컨테이너를 빠르게 가동시킬 수 있다. 서비스 용량이 감소한다면 추가 비용을 들이지 않고도 가상 서버를 줄일 수 있다. 서버 탄력성은 애플리케이션 회복성이 높다는 것을 의미한다.</code></pre><h3 id="마이크로서비스-클라이언트-회복성-패턴">마이크로서비스 클라이언트 회복성 패턴</h3>
<pre><code>&quot; 마이크로 서비스 아키텍처는 고도로 분산되어 있어서 1개의 서비스 (또는 서비스 인스턴스) 문제가 서비스 소비자에게 연쇄적으로 발생하지 않도록 방지하는 데 매우 민감해져야 한다. 

1) 마이크로 서비스 보안 패턴
- 인증, 인가, 자격증명 관리와 전파 

2) 마이크로 서비스 로깅 및 추적 패턴. 
- 로그 상관관계, 로그 수집, 마이크로서비스 추적. 

3) 마이크로서비스 빌드 및 배포 패턴
- 빌드 및 배포 파이프라인, 코드형 인프라스트럭처, 불변 서버, 피닉스 서버</code></pre> <br>


<h3 id="스프링-클라우드로-마이크로서비스-구축">스프링 클라우드로 마이크로서비스 구축.</h3>
<p><img src="https://images.velog.io/images/keep_going/post/f58f4f89-7024-4ca6-975c-33be3ec7cc58/1.jpg" alt=""> </p>
<br>



<ul>
<li>스프링 부트 : REST 기반 마이크로 서비스를 구축하는 주요 작업을 단순화해 마이크로서비스를 상당히 쉽게 개발할 수 있다. HTTP 형식의 동사를 URL에 매핑하고 JSON 프로토콜을 자바 객체로 직렬화할 뿐만 아니라 자바 예외를 표준 HTTP 에러 코드에 매핑하는 작업도 간편해 졌다.<ul>
<li>스프링 클라우드 컨피그 : 중앙 집중식 서비스로 애플리케이션 구성 데이터 관리를 담당하고 애플리케이션 데이터를 마이크로서비스와 완전히 분리한다. (인스턴스가 아무리 많더라도 항상 동일한 구성을 유지할 수 있다.) 
ex)깃, 콘설, 유레카</li>
<li>스프링 클라우드 서비스 디스커버리 : 이것을 사용하면 클라이언트에 서버가 배포된 물리적 위치를 추상화할 수 있다. 소비자는 물리적 위치보다 논리적 이름을 사용해 서버의 비즈니스 로직을 호출한다.</li>
</ul>
</li>
</ul>
<pre><code>&quot;스프링 클라우드는 넷플릭스나 하시코프 같은 회사의 오픈 소스 기술을 집약 했다. 그들의 기술은 스프링 애너테이션에 &#39;포함&#39; 되어 서비스 설정과 구성을 크게 단순화 한다.&quot;</code></pre>]]></description>
        </item>
    </channel>
</rss>