<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>sss_jinn.log</title>
        <link>https://velog.io/</link>
        <description></description>
        <lastBuildDate>Wed, 23 Apr 2025 01:31:57 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>sss_jinn.log</title>
            <url>https://velog.velcdn.com/images/sss_jinn/profile/8524197c-b08f-4e65-a891-b5981556a6f1/image.jpg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. sss_jinn.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/sss_jinn" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[PHP 버퍼 캐시 이슈]]></title>
            <link>https://velog.io/@sss_jinn/%EC%9B%B9-%EC%BA%90%EC%8B%9C-%EC%9D%B4%EC%8A%88</link>
            <guid>https://velog.io/@sss_jinn/%EC%9B%B9-%EC%BA%90%EC%8B%9C-%EC%9D%B4%EC%8A%88</guid>
            <pubDate>Wed, 23 Apr 2025 01:31:57 GMT</pubDate>
            <description><![CDATA[<h1 id="php-리다이렉트와-캐시-문제-분석">PHP 리다이렉트와 캐시 문제 분석</h1>
<h3 id="캐시에-의한-웹-동작-차이-분석">캐시에 의한 웹 동작 차이 분석</h3>
<p><img src="https://velog.velcdn.com/images/sss_jinn/post/546e2708-168f-4732-b34f-77472216d09b/image.png" alt=""></p>
<hr>
<h2 id="목차">목차</h2>
<ol>
<li>문제 상황 개요</li>
<li>정상 동작 프로세스 (최초 요청)</li>
<li>문제 발생 프로세스 (재요청)</li>
<li>원인 분석</li>
<li>핵심 개념 설명</li>
<li>해결 방안</li>
</ol>
<hr>
<h2 id="1-문제-상황-개요">1. 문제 상황 개요</h2>
<ul>
<li><strong>테스트서버</strong>: 리다이렉트가 정상 동작</li>
<li><strong>실서버</strong>: 최초 1회만 리다이렉트가 작동하고 이후 작동하지 않음</li>
<li><strong>현상</strong>: 같은 코드이지만 환경에 따라 다른 동작을 보임</li>
<li><strong>원인</strong>: 캐시 사용 여부에 따른 차이</li>
</ul>
<hr>
<h2 id="2-정상-동작-프로세스-최초-요청">2. 정상 동작 프로세스 (최초 요청)</h2>
<p><strong>메뉴의 다시보기 클릭 → &quot;tv_sub/552/2636&quot; 요청</strong></p>
<p><img src="/api/placeholder/800/500" alt="최초 요청 프로세스"></p>
<ol>
<li>캐시 파일이 없으므로 <code>ob_start()</code> 실행</li>
<li>응답 페이지 구성 시작 (헤더 + 바디)</li>
<li>헤더에 301 리다이렉트와 Location: &quot;tv/552/&quot; 포함</li>
<li>페이지 내용은 출력 버퍼에 저장됨</li>
<li>응답 시 헤더의 Location으로 리다이렉트 발생</li>
<li>동시에 출력 버퍼 내용은 캐시 파일로 저장됨</li>
</ol>
<hr>
<h2 id="3-문제-발생-프로세스-재요청">3. 문제 발생 프로세스 (재요청)</h2>
<p><strong>메뉴의 다시보기 클릭 → &quot;tv_sub/552/2636&quot; 재요청</strong></p>
<p><img src="/api/placeholder/800/500" alt="재요청 프로세스"></p>
<ol>
<li>캐시 파일이 존재함을 확인</li>
<li>캐시 파일을 <code>echo</code>로 즉시 출력</li>
<li><code>exit</code> 명령으로 이후 코드 실행 중단</li>
<li>이 과정에서 리다이렉트를 위한 헤더 설정 코드가 실행되지 않음</li>
<li>결과적으로 Location 헤더가 없어 리다이렉트 발생하지 않음</li>
<li>원래 요청한 &quot;tv_sub/552/2636&quot; 페이지가 그대로 표시됨</li>
</ol>
<hr>
<h2 id="4-원인-분석">4. 원인 분석</h2>
<h3 id="핵심-원인">핵심 원인:</h3>
<ul>
<li>캐시 사용 시 <code>echo</code>로 내용 출력 후 <code>exit</code>로 종료</li>
<li>이로 인해 리다이렉트 헤더가 설정되기 전에 응답이 완료됨</li>
</ul>
<pre><code class="language-php">// 캐시 처리 관련 코드 예시
if (file_exists($cache_file)) {
    echo file_get_contents($cache_file);
    exit; // 여기서 코드 실행이 중단됨
}

// 아래 코드는 캐시 파일이 있으면 실행되지 않음
ob_start();
// 페이지 콘텐츠 생성...
header(&quot;HTTP/1.1 301 Moved Permanently&quot;);
header(&quot;Location: tv/552/&quot;);
// 나머지 코드...</code></pre>
<hr>
<h2 id="5-핵심-개념-설명">5. 핵심 개념 설명</h2>
<h3 id="php의-출력-버퍼링-ob_start">PHP의 출력 버퍼링 (<code>ob_start()</code>)</h3>
<ul>
<li>출력을 바로 전송하지 않고 버퍼에 저장</li>
<li>버퍼 내용은 스크립트 종료 시 또는 명시적 호출 시 전송</li>
<li><strong>중요</strong>: 버퍼링은 출력 내용(body)만 제어하며 헤더는 제어하지 않음</li>
</ul>
<h3 id="헤더와-출력의-관계">헤더와 출력의 관계</h3>
<ul>
<li>PHP에서 <code>echo</code> 등으로 출력이 시작되면 헤더도 함께 전송됨</li>
<li>헤더는 항상 본문(body) 이전에 전송되어야 함</li>
<li>출력이 시작된 후에는 <code>header()</code> 함수가 작동하지 않음</li>
</ul>
<hr>
<h2 id="6-해결-방안">6. 해결 방안</h2>
<h3 id="가능한-해결책">가능한 해결책:</h3>
<ol>
<li><p><strong>캐시 파일에 헤더 정보도 포함시키기</strong></p>
<ul>
<li>캐시 데이터에 리다이렉트 정보도 저장</li>
</ul>
</li>
<li><p><strong>캐시 파일 출력 전에 헤더 설정하기</strong></p>
<pre><code class="language-php">if (file_exists($cache_file)) {
    header(&quot;HTTP/1.1 301 Moved Permanently&quot;);
    header(&quot;Location: tv/552/&quot;);
    echo file_get_contents($cache_file);
    exit;
}</code></pre>
</li>
<li><p><strong>조건부 캐시 사용</strong></p>
<ul>
<li>리다이렉트가 필요한 페이지는 캐시를 사용하지 않거나</li>
<li>리다이렉트 정보를 별도로 확인하여 처리</li>
</ul>
</li>
</ol>
<hr>
<h2 id="질문에-대한-답변">질문에 대한 답변</h2>
<h3 id="exit이-없으면-어떻게-되나요">&quot;exit이 없으면 어떻게 되나요?&quot;</h3>
<ul>
<li><code>exit</code>이 없어도 <code>echo</code>가 실행되면 헤더가 이미 전송됨</li>
<li>이후 <code>header()</code> 함수는 효과가 없음 (&quot;Headers already sent&quot; 오류)</li>
<li>단, 이후 코드는 계속 실행되어 추가 출력이나 로직이 동작함</li>
</ul>
<h3 id="ob_start는-header-값을-담을-수-없나요">&quot;ob_start()는 header 값을 담을 수 없나요?&quot;</h3>
<ul>
<li><code>ob_start()</code>는 출력 내용(body)만 버퍼링함</li>
<li>헤더 정보는 별도로 관리되며 버퍼링되지 않음</li>
<li>출력 버퍼는 본문 콘텐츠만 제어할 뿐임</li>
</ul>
<hr>
<h2 id="정리">정리</h2>
<ol>
<li><strong>문제 원인</strong>: 캐시 사용 시 리다이렉트 헤더를 설정하기 전에 출력과 종료가 발생</li>
<li><strong>PHP 특성</strong>: 출력 시작 시 헤더도 함께 전송됨</li>
<li><strong>해결 방향</strong>: 캐시 처리 전에 필요한 헤더 설정 또는 캐시에 헤더 정보 포함</li>
<li><strong>교훈</strong>: 출력 버퍼링과 헤더 관리는 별개의 메커니즘임을 이해해야 함</li>
</ol>
<h2 id="원본">원본</h2>
<p>[ 상황 정리 ]
테스트서버에서는 제대로 리다이렉트가 동작한다. 근데, 실서버에서는 리다이렉트가 최초 1회만 동작하고 제대로 동작하지않는다.
뭣도 모르고 됏다가 안됏다가 하는데 거의 안되네라고 생각했다. ㅎ.</p>
<p>1) 최초 요청 (캐시 동작 x, 실서버 기준)</p>
<ul>
<li>메뉴의 다시보기를 클릭 -&gt; &quot;tv_sub/552/2636&quot; 으로 요청이 된다.</li>
<li>&quot;tv_sub/552/2636&quot; 에 진입해서 캐시가 없으면 ob_start 시작된다. 
 그와 동시에 요청에 따른 응답 페이지(응답할 헤더와 바디)를 구성한다. (header에 리다이렉트 301 요청과 Location (&quot;tv/552/&quot;) 을 포함한다)
 그리고 ob_start에 body의 내용들이 쌓이게 된다. (이때 header의 정보는 쌓이지 못한다)</li>
<li>페이지를 모두 구성하면 브라우저(Reqest)에 Response 한다. Response 하면 header에 Location이 값이 담겨 있기 때문에 바로 &quot;tv/552/&quot;로 리다이렉트
이와 동시에 캐시파일에도 해당 페이지의 내용이 담겨 저장된다.</li>
</ul>
<p>2) 재 요청 (캐시 동작 o, 실서버 기준)</p>
<ul>
<li>메뉴의 다시보기를 클릭 -&gt; &quot;tv_sub/552/2636&quot; 으로 요청이 된다.</li>
<li>응답할 페이지를 구성하기 위해서 위에서부터 아래로 순차적으로 스캔하면서 상단에 캐시파일 로직을 지나는데 캐시파일이 존재하기 때문에 
그냥 캐시파일을 echo로 뿌려버리고 exit 한다. 이렇게 되면 Response body와 header를 그 순간 그 상태로 응답해버린다. 그렇기 때문에 header에 
리다이렉트를 해야할 Location 정보를 담지 못한다. </li>
<li>그래서 응답 페이지의 header에는 Location정보가 없어 리다이렉트 하지 않고, 그냥 요청한 &quot;tv_sub/552/2636&quot; 페이지가 캐시에 의해 응답된다.</li>
</ul>
<p>[ 궁금한 점 ]</p>
<ol>
<li>재요청 상황에서 echo로 뿌려버리고 exit 한다. 라고 작성 했는데 exit이 없으면? 어떻게?
-&gt; php는 echo출력과 동시에 header 정보도 함께 응답해버린다. 그리고  exit을 해야 뒤에 내용들이 동작을 안한다. exit이 없어도 echo가 있으면 header 정보도 바로 응답이 되기 때문에 이후의 header()는 무용지물!</li>
</ol>
<ol start="2">
<li>ob_start()는 header 값을 담을 수 없나?
-&gt; 출력 제어만 가능할 뿐이다. 원한다면 내용 출력이전에 header를 셋팅해라!</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[AWS - DB]]></title>
            <link>https://velog.io/@sss_jinn/AWS-DB</link>
            <guid>https://velog.io/@sss_jinn/AWS-DB</guid>
            <pubDate>Mon, 14 Oct 2024 14:11:59 GMT</pubDate>
            <description><![CDATA[<h2 id="aws-db">AWS DB</h2>
<p>AWS에는 EBS,EFS,EC2 Instance store,S3 등등 스토리지 서비스가 있지만 데이터를 구조에 맞게 저장하려면 결국 DB가 필요하다.</p>
<h2 id="aws-db-이점">AWS DB 이점</h2>
<p>EC2 인스턴스에 자체적으로 DB 기술을 실행할 수도 있으나, 그럴 경우에는 복원력, 백업, 패치작업, 고가용성, 내결함성, 스케일링 등과 관련된 모든 사항을 직접 처리해애 한다.</p>
<ol>
<li>퀵프로비저닝, 고가용성, 수직 및 수평 확장</li>
<li>자동 백업 및 저장, 설정, 업그레이드</li>
<li>모니터링 등등</li>
</ol>
<h2 id="rds">RDS</h2>
<blockquote>
<p>RDS란? -&gt; 관계형 DB를 의미한다. SQL을 쿼리언어로 사용하는 DB를 위한 서비스이다.</p>
</blockquote>
<ul>
<li>RDS를 통해 AWS에서 관리할 DB를 클라우드에 생성할 수 있다.</li>
<li>PostgreSQL, Mysql, Oracle, MariaDB, Aurora(AWS 독점 서비스) 등등</li>
</ul>
<h2 id="rds를-쓰는-이유는">RDS를 쓰는 이유는?</h2>
<ul>
<li>RDS는 RDBMS서비스로 DB 배정이 자동으로 이루어진다. AWS가 운영체제 패치를 진행, 지속적인 백업 및 복원 옵션을 제공, 또한 DB가 잘 작동하는지 모니터링 대시보드 제공.</li>
<li>읽기 복제본을 생성하여 읽기 규모를 확장하고 읽기 성능을 향상시킬 수 있다.</li>
<li>하나의 가용영역(AZ) 전체가 다운되는 경우를 대비한 재해복구 계획으로써 다중 AZ를 설정하는 방법을 갖게 된다.</li>
<li>수직, 수평 확장 지원<ul>
<li>스토리지는 EBS의 지원을 받는다.</li>
</ul>
</li>
</ul>
<blockquote>
<p>유일하게 RDS로 할 수 없는 것은 RDS에 SSH를 통해 인스턴스 연결이 불가하다. DB에서 무슨일이 일어나는 지 확인을 하지 못한다. AWS가 DB 전체를 관리한다.</p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/sss_jinn/post/b2647e54-83b6-4e94-a847-5d2b173981bc/image.png" alt=""></p>
<p>RDS를 활용한 기본적인 아키텍처 예시이다. ELB와 함께 ASG를 사용하고, DB는 RDS를 사용하고있다. 이 때 여러 EC2 인스턴스에서 RDS로 읽기와 쓰기 작업이 가능하다. 보통 이러한 아키텍처로 구성을 하는게 기본 중의 기본이다.</p>
<h2 id="aurora">Aurora</h2>
<blockquote>
<p>AWS에서 만든 DB 기술. 오픈소스가 아니다. RDS와 동일한 방식으로 동작한다.</p>
</blockquote>
<ul>
<li>PostgreSQL과 MYsql을 지원한다.</li>
<li>클라우드에 최적화된 서비스이다. 따라서 RDS 상의 Mysql 보다 5배 정도 성능이 좋고, PostgreSQL보다 약 3배 정도 성능이 좋다.</li>
<li>Storage 걱정 할 필요가 없다. 스토리지가 10gb단위로 최대 128TB까지  자동증가.</li>
<li>프리티어가 아니며, RDS는 프리티어이다.</li>
</ul>
<h2 id="aurora-serverless">Aurora Serverless</h2>
<ul>
<li>DB 인스턴스화가 자동, DB 실제 상황을 기반으로 한 자동확장 기능.</li>
<li>User가 서버를 관리하지 않아도 된다. 초당 비용 지불.</li>
</ul>
<p>관리 오버헤드가 없는 Aurora라는 표현은 Aurora Serverless를 뜻한다.</p>
<h2 id="rds-배포-옵션">RDS 배포 옵션</h2>
<h3 id="read-replicas">Read Replicas</h3>
<ul>
<li>읽기 전용 RDS 복제본은 사용하는 방식</li>
<li>쓰기는 오직 중앙의 메인 RDS를 통해서만 가능한 형태</li>
<li>읽기 작업 확장용 구조</li>
</ul>
<h3 id="multi-az">Multi-AZ</h3>
<ul>
<li>AZ 운영 정지와 같은 장애 조치가 발생했을 때 유용하게 쓰임</li>
<li>높은 가용성을 보장</li>
<li>다른 AZ에 장애 조치용 DB를 구성하는 형태</li>
</ul>
<p>(왼쪽이 Read Replicas , 오른쪽이 Multi-AZ)</p>
<p><img src="https://velog.velcdn.com/images/sss_jinn/post/ecd6b8b1-4408-4161-b5f9-d4db9a0dcaa3/image.png" alt=""></p>
<h3 id="multi-region">Multi-Region</h3>
<p><img src="https://velog.velcdn.com/images/sss_jinn/post/d0ce5cf9-d7a5-466e-b954-678e8ffe9479/image.png" alt=""></p>
<ul>
<li>한 리전에 문제가 생기는 것을 대비한 구조</li>
<li>하지만 리전 간, 복제된 데이터를 네트워크를 통해 전송하는 경우 비용이 발생한다.</li>
</ul>
<h2 id="elasticache">ElastiCache</h2>
<p>캐시를 활용한 높은 성능과 짧은 지연시간을 보장하는 인메모리 DB 서비스이다.
일부 데이터를 ElastiCache DB에 캐싱처리하는데 이 작업은 인메모리에서 이루어지므로 속도가 빠르다. 즉, RDS의 부하를 줄인다. </p>
<p><img src="https://velog.velcdn.com/images/sss_jinn/post/7c22e2fb-bcda-45ee-b54e-579c0f1a52f9/image.png" alt=""></p>
<p>읽기에 집중되는 부하를 DB로 부터 줄일 때 유용한 서비스이다.</p>
<h2 id="dynamodb">DynamoDB</h2>
<ul>
<li>DynamoDB는 완전 관리형 고가용성 DB로써, 3개의 가용영역에 걸쳐 복제본을 두고 운영된다.</li>
<li>NoSql의 DB로 비관계형이다. 모든 데이터를 하나의 디비에서 유연하게 관리한다.</li>
<li>AWS의 대표상품이며 Serverless 이다.</li>
<li>한 자릿수 밀리초의 지연시간과 같이 저지연 시간 (초고속)을 보장한다.</li>
</ul>
<h3 id="dynamodb---dax">DynamoDB - DAX</h3>
<ul>
<li>이는 DynamoDB를 위한 완전관리형 인 메모리 캐시 서비스. DAX는 DynamoDB 전용.</li>
</ul>
<h3 id="dynamodb---global-tables">DynamoDB - Global Tables</h3>
<ul>
<li>DynamoDB의 핵심은 짧은 지연 시간으로 DynamoDB 테이블에 액세스 할 수 있도록 하는 기능이며, 여러 리전에서 사용하는 점이 중요함.</li>
</ul>
<h2 id="나머지-db-서비스들">나머지 DB 서비스들</h2>
<h3 id="redshift">RedShift</h3>
<p>PostgreSQL 기반의 DB이다. 분석과 데이터 웨어하우스에 용이하다. (OLAP)</p>
<h3 id="emr">EMR</h3>
<p>실제 DB는 아니고 AWS에서 빅데이터를 작업하고자 할 때 사용하는 Hadoop 클러스터를 생성한다. 이때 Hadoop 클러스터란 방대한 양의 데이터를 분석하고 처리하는 것이다.</p>
<h3 id="athena">Athena</h3>
<p>AWS S3를 위한 서버리스 쿼리 서비스이다. AWS S3에 저장된 오브젝트에 대한 분석을 수행.</p>
<h3 id="quicksight">QuickSight</h3>
<p>서버리스 머신러닝 방식의 비즈니스 인텔리전스 서비스로 대화형 대시보드를 생성.</p>
<h3 id="documentdb">DocumentDB</h3>
<p>Aurora가 PostgreSQL,Mysql을 클라우드 네이티브 버전으로 사용하듯이 DocumentDB는 MongoDB의 Aurora 버전이라고 보면된다. NoSQL이다.</p>
<h3 id="neptune">Neptune</h3>
<p>Neptune은 완전 관리형 그래프 DB이다. 데이터셋은 소셜 네트워크를 생각하면 된다. 모든 것이 연결되어있다.</p>
<h3 id="timestream">TimeStream</h3>
<p>time series(시계열,시간에 따라 지속적으로 변화하는) 데이터를 저장하고, 완전한 관리를 받으며, 빠르고 규모 조정이 가능한 서버리스인 DB이다.</p>
<h3 id="qldb">QLDB</h3>
<p>금융거리를 기록하는 장부의 역할</p>
<h3 id="managed-blockchain">Managed BlockChain</h3>
<p>중앙 기관 없이도 신뢰할 수 있는 여러 당사자의 트랜잭션 실행이 가능한 애플리케이션을 구출할 수 있는 기술이다.
블록체인, hyperledger Fabric, Ethereum</p>
<h3 id="glue">Glue</h3>
<p>ETL 서비스라고 한다. ETL은 데이터셋에 대한 분석을 진행할 때에 그 형식이 올바르지 않거나 원하는 형식이 아닐때 유용하다.</p>
<h3 id="dms-db-migration-service">DMS (DB Migration Service)</h3>
<p>DB 간의 마이그레이션 방법이다. AWS의 마이그레이션.</p>
<h2 id="aws-db---summary">AWS DB - SUMMARY</h2>
<ol>
<li>RDBMS-OLTP: RDS 및 Aurora (SQL)</li>
<li>RDS 배포 옵션 별 차이: 읽기 복제본(Read Replicas), 다중 가용 영역(Multi-AZ), 다중 리전(Multi-Region)</li>
<li>인메모리 데이터베이스: ElastiCache</li>
<li>키-값 데이터베이스: DynamoDB (서버리스) 및 DAX (DynamoDB용 캐시)</li>
<li>데이터 웨어하우스-OLAP: RedShift (SQL)</li>
<li>하둡 클러스터: EMR (Elastic MapReduce)</li>
<li>Athena: AWS S3에서 데이터를 쿼리</li>
<li>QuickSight: 데이터 대시보드 (서버리스)</li>
<li>DocumentDB: MongoDB를 위한 Aurora (Json-NoSQL)</li>
<li>TimeStream: 시계열 데이터 저장</li>
<li>Neptune: 그래프 데이터베이스</li>
<li>AWS QLDB: 변경 불가능한 원장(Ledger)</li>
<li>AWS 블록체인: 관리형 Hyperledger Fabric 또는 이더리움 블록체인</li>
<li>Glue: 관리형 ETL 및 데이터 카탈로그 서비스</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[AWS - S3]]></title>
            <link>https://velog.io/@sss_jinn/AWS-S3</link>
            <guid>https://velog.io/@sss_jinn/AWS-S3</guid>
            <pubDate>Sun, 13 Oct 2024 14:08:38 GMT</pubDate>
            <description><![CDATA[<h2 id="s3-개요">S3 개요</h2>
<ol>
<li>S3는 AWS를 구성하는 핵심 요소 중 하나이다.</li>
<li>S3는 제한 없이 스케일을 할 수 있는 스토리지로 알려져있다.</li>
<li>많은 웹 사이트 들은 AWS S3를 백본(중요한 인프라, 기반)으로 사용하고 또 많은 AWS 서비스들도 AWS S3를 연동해서 활용한다.</li>
</ol>
<h2 id="s3-use-cases">S3 Use Cases</h2>
<ol>
<li>S3는 백업과 저장소로 활용된다. 파일을 정장할 수도 있고 디스크 역할도 해준다. </li>
<li>재해 복구 용도로 사용된다.</li>
<li>꽤 저렴한 비용.</li>
<li>하이브리드 클라우드 스토리지. 온프레미스 스토리지가 있는데 클라우드로 확장하고 싶다면 AWS S3를 이용하면 된다.</li>
<li>애플리케이션이나 미디어, 즉 비디오 파일이나 이미지 같은 걸 호스팅할 수 있다. 또한 빅데이터 분석을 위한 큰 용량의 데이터 저장.</li>
<li>소프트웨어 업데이트</li>
<li>정적 웹사이트 호스팅</li>
</ol>
<h2 id="s3-buckets">S3 Buckets</h2>
<ul>
<li><p>S3는 파일을 버킷에 저장한다. 버킷은 최상위 디렉토리 같은 거라고 보면 된다. 이 S3 버킷에 저장되는 파일을 &quot;오브젝트&quot; 라고 부른다.</p>
</li>
<li><p>버킷 이름은 전역적으로 고유한 이름이어야 한다. 즉, 가지고 있는 계정에 속한 모든 리전을 통틀어 고유해야 하면서 또 AWS에 있는 모든 계정을 대상으로도 고유해야 한다. --&gt; AWS (리전) 에서 전역적으로 고유해야 하는 유일한 항목이 바로 S3다. </p>
</li>
<li><p>버킷은 리전 단위로 정의가 된다. --&gt; 특정 리전 안에서 생성 되는 것이다. </p>
</li>
</ul>
<h2 id="s3-objects">S3 Objects</h2>
<ul>
<li>오브젝트는 파일을 뜻하며, 각각의 파일들은 키를 가진다. AWS S3에 저장되는 오브젝트의 키는 해당 파일의 전체 경로(Pull Path)이다.</li>
<li>S3에서는 디렉토리라는 개념은 없으며, 무엇이든지 간에 전부 키로 구성된다. 
키는 접두사랑 오브젝트 이름으로 구성된다.</li>
<li>모든 오브젝트는 S3의 버킷에 저장된다.</li>
<li>우리는 무엇이던지 S3에 올릴 수 있다. 최대 5TB 짜리 오브젝트를 올릴 수 있다. 이걸 초과하면 멀티파트로 업로드 해야한다. 여러조각으로 나눠서. </li>
<li>오브젝트는 메타데이터를 키-값 형태의 목록으로 가진다. 이것은 파일의 어떤 요소를 명시하기 위한 것.</li>
</ul>
<h2 id="s3-security">S3 Security</h2>
<blockquote>
<p>전체적으로 사용자 역할, 버킷 정책, 오브젝트 암호화 이렇게 3가지 있다고 보면 된다.</p>
</blockquote>
<ol>
<li>사용자 기준 </li>
</ol>
<ul>
<li>(IAM 정책) 사용자에겐 IAM 정책을 적용하는데, IAM 정책이 정의하는 건 어떤 API가 어떤 IAM 사용자에 의해 호출될 수 있는가이다.</li>
</ul>
<ol start="2">
<li>리소스 기준 <ul>
<li>(버킷 정책) 신규 기능, 여러 버킷에 적용되는 규칙을 S3 콘솔에서 바로 설정 가능하다. 이 규칙은 특정 사용자에게 이용을 허용하거나 또 다른 계정 사용자를 허용 가능하다. S3 버킷을 대상으로 교차 계정 액세스가 가능하다. 이걸 이용해서 S3 버킷을 공개 가능하다. 가장 일반적인 방식</li>
<li>(ACL : Object Access Control List) 세밀하게 보안을 관리하는 장치. 비활성화 시킬 수도 있다. </li>
<li>(ACL : Bucket Access Control List) 버킷 단위에서 관리하기 위해 버킷 ACL을 반들기도 한다. 흔한 방법 X</li>
</ul>
</li>
</ol>
<blockquote>
<h4 id="iam-정책으로-s3-오브젝트에-접근할-수-있는-건-언제인가">IAM 정책으로 S3 오브젝트에 접근할 수 있는 건 언제인가?</h4>
</blockquote>
<ul>
<li>IAM 권한이 허용으로 돼 있거나 리소스 정책이 허용으로 돼 있거나, 접근 거절 액션이 명시 돼 있지 않다면 API 호출 시 정책에 기반해 S3 오브젝트에 접근 가능하다. </li>
</ul>
<ol start="3">
<li>암호화 - 암호화 키를 이용해 오브젝트를 암호화 하는 방식</li>
</ol>
<p><img src="https://velog.velcdn.com/images/sss_jinn/post/bd8c28d2-bcd6-4963-a59f-5cd27da4c376/image.png" alt=""></p>
<p>S3의 Bucket에 public access가 허용되어있으면 www 웹사이트로 S3dp 접근 가능</p>
<p><img src="https://velog.velcdn.com/images/sss_jinn/post/3e482f8f-591a-40e6-8408-6c10ca7ab1fa/image.png" alt=""></p>
<p>IAM 사용자에게 권한 (S3 getObject 같은 권한)이 있으면 S3에 접근 가능</p>
<p><img src="https://velog.velcdn.com/images/sss_jinn/post/d6dbd284-8a04-44e2-bab7-6097854865fe/image.png" alt=""></p>
<p>EC2 인스턴스의 Role에 S3의 Bucket에 접근 가능한 권한이 있으면 S3에 접근가 능</p>
<p><img src="https://velog.velcdn.com/images/sss_jinn/post/bb18dfc8-8726-48ee-8306-20fea0148c89/image.png" alt=""></p>
<p>S3의 Bucket 정책을 사용자 별로 교차적으로로 접근 가능하게 할 수 있다. 특정 AWS계정에 대한 특정 사용자는 허용, 특정 사용자는 불가</p>
<h2 id="s3-versioning">S3 Versioning</h2>
<ul>
<li>S3에 업로드되는 오브젝트들의 버전을 관리하는 기능이다. 이 설정은 버킷 단위에서 설정해줘야한다.</li>
<li>사용자가 파일을 S3 Bucket에 업로드 하게 되면, 같은 파일의 경우 자동으로 v1,v2 이런식으로 업로드 된다. 이 기능을 활성화 해두는게 좋다. 이유는 의도치 않게 파일을 삭제하는 것을 잘 막아준다.</li>
</ul>
<h2 id="s3-replication-crr--srr">S3 Replication (CRR &amp; SRR)</h2>
<p>S3에는 2가지 복제 기능이 있다.</p>
<ol>
<li>CRR (Cross Region Replication) - 리전 간 복제</li>
<li>SRR (Same Region Replication) - 동일 리전 복제</li>
</ol>
<p>설정을 해주면, 각각의 기능에 따라 복제를 비동기 적으로 진행한다.</p>
<h2 id="s3-storage-classes">S3 Storage Classes</h2>
<h3 id="내구성과-가용성의-개념을-파악하자">내구성과 가용성의 개념을 파악하자</h3>
<p>내구성 (Durability) - S3로 인해 오브젝트가 손실될 수 있는 확률이다. 99.999999% 확률로 손상안됨.
가용성 - 얼마나 쉽게 서비스를 이용할 수 있느냐. 이것도 99.9% 이상의 확률이다. 클래스마다 약간다름.</p>
<h3 id="스토리지-종류와-목적">스토리지 종류와 목적</h3>
<ol>
<li><p>Amazon S3 Standard - General Purpose</p>
<ul>
<li>내구성 : 99.99% , 자주 액세스 하는 데이터용 , 기본값으로 사용하는 스토리지 유형, 지연 시간이 짧고 처리량이 많다.</li>
<li>두 곳에서 발생하느 동시 기능 장애를 감달 할 수 있어서 빅데이터 분석과 모바일 및 게임 애플리케이션 콘텐츠 배포의 사용 사례에 적합하다.</li>
</ul>
</li>
<li><p>Amazon S3 Standard-Infrequent Aeccess (IA)</p>
<ul>
<li>자주 액세스하지 않지만, 필요할 때 빠르게 액세스 가능. Standard보다는 요금이 저렴하지만, 검색 요금이 추가로 발생한다.</li>
<li>재해 복구와 백업에 이상적이다. </li>
</ul>
</li>
<li><p>Amazon S3 One Zone-Infrequent Access</p>
<ul>
<li>단일 AZ(가용영역)에서 내구성이 높지만(99.999999%), 가용영역이 파괴되면 데이터가 손실될 수 있다.  가용성 (99.5%)</li>
<li>온프레미스 데이터나 다시 생성 가능한 데이터의 보조 백업 복사본 저장에 적합하다.</li>
</ul>
</li>
<li><p>Amazon S3 Glacier Instant Retrieval</p>
<ul>
<li>밀리초 단위의 검색 가능, 분기에 한 번 데이터에 액세스할 때 적합하다.</li>
<li>밀리초 내에 액세스가 필요한 백업에 이상적이다.</li>
<li>최소 스토리지 기간은 90일</li>
</ul>
</li>
<li><p>Amazon S3 Glacier Flexible Retrieval</p>
<ul>
<li>유연한 무료 검색 기능을 제공한다.<ul>
<li>1<del>5분의 빠른 검색과 3</del>5시간의 표준 검색, 5~12시간의 무료 대량 검색 중 선택 가능하다.</li>
<li>최소 스토리지 기간은 90일</li>
</ul>
</li>
</ul>
</li>
<li><p>Amazon S3 Glacier Deep Archive</p>
<ul>
<li>2가지 옵션 -&gt; 12시간의 표준 옵션과 48시간 대량 옵션</li>
<li>검색 시간이 아주 많이 들지만 가장 저렴하게 이용 가능하다.</li>
<li>최소 스토리지 기간은 180일</li>
</ul>
</li>
<li><p>Amazon S3 Intelligent Tiering</p>
<ul>
<li>사용 패턴을 기반으로 액세스 계층 간에 오브젝트를 이동시킨다.</li>
<li>매월 모니터링과 자동화 요금이 발생한다.</li>
<li>검색 요금은 발생하지 않는다.</li>
<li>Frequent Access 계층에 오브젝트를 자동 저장하고, 30일 동안 액세스하지 않은 오브젝트는 Infrequent Access 계층에 이동된다. 90일 동안 액세스 하지 않으면 Archivce Instant Access 계층으로 이동된다.  (여기는 자동)</li>
<li>90<del>700++일 동안 액세스하지 않은 오브젝트는 Archive Access 계층으로 이동 설정 가능하다. 180</del>700일 동안 액세스하지 않은 오브젝트는 Deep Archive Access 계층으로 이동하게 설정 가능하다.  (여기는 옵션)</li>
</ul>
</li>
</ol>
<p>( Glacier 클래스 ) : 아카이브와 백업에 적합한 저비용 오브젝트 스토리지이다. 스토리지 비용에 검색 비용이 포함되어있다.</p>
<p>AWS S3에서 오브젝트를 선택할때 클래스를 선택할 수 있다. 스토리지 설정을 수동으로 구성할 수 있고, S3 수명 주기 구성을 이용해서 모든 스토리지 클래스 간에 오브젝트를 자동으로 이동시킬 수 도 있다.</p>
<h2 id="s3-encryption">S3 Encryption</h2>
<ol>
<li><p>서버측 암호화 (Server Side Encryption) - 기본적으로 버킷을 생성하거나 오브젝트를 올릴 때마다 암호화는 적용된다. 사용자가 파일을 S3에 업로드하면 보안을 위해 S3가 암호화시킨 상태로 저장된다. 암호화를 서버가 수행하기 떄문에 서버측 암호화라고 한다.</p>
</li>
<li><p>클라이언트측 암호화 (Client Side Encryption) - 사용자가 파일을 업로드 하기 전에 직접 암호화 하는 것이다.</p>
</li>
</ol>
<p><img src="https://velog.velcdn.com/images/sss_jinn/post/5877d8c5-7c77-473b-83ab-a070539ff82a/image.png" alt=""></p>
<blockquote>
<p>이 2가지 방식은 AWS에 존재하지만, 서버측 암호화는 항상 기본적으로 활성화 되어있다.</p>
</blockquote>
<h2 id="s3-iam-access-analyzer">S3 IAM Access Analyzer</h2>
<ul>
<li>S3 버킷을 모니터링하는 기능. </li>
<li>의도된 대로 접근을 허용한 사람만 S3 버킷에 접근할 수 있나를 본다.</li>
<li>버킷 규칙이랑 S3 ACL이랑 S3 액세스포인트 규칙이랑 분석을 한다. 그리고 어떤 버킷이 퍼블릭 액세스가 가능한지 또 어느 버킷이 다른 AWS 계정과 공유가 됐는지 등을 본다. 이걸 통해 User 가 판단.</li>
</ul>
<h2 id="s3-공동-책임-모델">S3 공동 책임 모델</h2>
<h4 id="aws">AWS</h4>
<ul>
<li>인프라에 대한 모든 책임</li>
<li>S3 -&gt; 내구성, 가용성<h4 id="user">User</h4>
<ul>
<li>S3 버전 관리를 잘하고 올바른 S3 버킷정책을 설정함으로써 데이터 손실 방지</li>
<li>복제 잡업이 필요하면 직접</li>
<li>로깅,모니터링은 선택사항이니 User가 자첵저긍로 활성화해야함</li>
<li>스토리지 클래스를 사용하는 것도 사용자 본인의 책임</li>
<li>어떤 암호화 할건지</li>
</ul>
</li>
</ul>
<h2 id="aws-snow-family">AWS Snow Family</h2>
<p>이는 AWS 내에서 &quot;두 가지 사용 사례&quot; 를 가진 매우 안전한 휴대용 장치이다.
엣지에서 데이터를 수집 및 처리하거나 AWS 내부 및 외부로 데이터를 마이그레이션하는 데 사용된다.</p>
<h4 id="첫번째-데이터-마이그레이션">첫번째, 데이터 마이그레이션</h4>
<ol>
<li><p>Snowcone</p>
<ul>
<li>거대한 박스 이며, 테라바이트 또는 페타바이트의 데이터를 AWS 안팎으로 이동시키는 데 사용될 것이다. 네트워크를 통해 데이터를 이동하는 것의 대안이 될 것이다. 페타바이트 규모의 데이터를 이동하는데 적합. PB 데이터</li>
</ul>
<ol start="2">
<li>Snowball Edge</li>
</ol>
<ul>
<li>매우 작은 휴대용 장치이며 견고하다. 안전하고 열악한 환경을 견딜 수 있으며 데이터 양이 적은 환경에 적합하다. 가볍고 2.1kg정도된다. 원하면 드론에도 장착가능</li>
</ul>
<ol start="3">
<li>Snowmobile</li>
</ol>
<ul>
<li>실제 트럭이다. 엑사바이트 규모의 데이터를 전송 가능하다. 1엑사바이트는 1,000PB이고1,000,000TB 이다. 각 스노우모빌의 용량은 100PB이다.</li>
</ul>
</li>
</ol>
<h4 id="두번째-엣지-컴퓨팅">두번째, 엣지 컴퓨팅</h4>
<ul>
<li><p>엣지 컴퓨팅이란? -&gt; 엣지 로케이션에서 데이터가 생성되는 동안 데이터를 처리하는 것이다.
엣지 로케이션이란? -&gt; 실제로 인터넷이 없거나 클라우드에서 멀리 떨어진 곳을 의미한다.</p>
</li>
<li><p>따라서 연결이 제한되고 인터넷에 액세스할 수 없거나 컴퓨팅 성능에 액세스 할 수 없다는 것을 뜻함. 이러한 위치에서 데이터 처리를 계속 실행하고 싶을 수도 있다. 이를 위해서는 엣지 컴퓨팅이 필요하다.</p>
</li>
<li><p>엣지 컴퓨팅을 수행하려면 스노우볼 엣지 장치나 스노우콘을 주문하고 이를 엣지 로케이션에 내장하고 엣지 컴퓨팅을 시작할 수 있다. 엣지 컴퓨팅의 사용 사례는 데이터를 전처리하고 엣지에서 기계 학습을 수행하는 것이다.</p>
</li>
<li><p>따라서 클라우드로 돌아가지 않고도 주요 스트림을 미리 트랜스코딩하고, 필요에 따라 데이터를 다시 AWS로 전송해야 하는 경우 스노우콘 또는 스노우볼 엣지용 장치를 다시 배송할 수 있습니다.</p>
</li>
</ul>
<p>Snowball Edge Pricing
-&gt; 해당서비스를 사용함녀 비용은 발생한다. 다만, AWS로 데이터 이관 시엔 무료, 기가 바이트당 $0</p>
<h2 id="storage-gateway---hybrid-cloud">Storage Gateway - Hybrid Cloud</h2>
<blockquote>
<p>지금 까지의 AWS는 독립 실행형 서비스 였으나, 하이브리드 클라우드 유형의 설정에서도 사용이 가능하다.  AWS는 사용자의 온프레미스 환경과 AWS 간의 교두보를 제공하는데 바로 이를 하이브리드 클라우드라고 한다. 사용자의 인프라 중 일부는 온프레미스에 두고, 나머지는 클라우드에 존재하게 된다. 이 때 필요한 것은 &quot;Storage Gateway&quot; 이다.</p>
</blockquote>
<p>AWS는 독점 스토리지 기술로 이전에 봤던 EFS 서비스나 NFS 프로토콜과는 다르다. 이 2가지 서비스는 클라우드 환경에서 운영되었다. 온프레미스에서 S3 데이터를 보려면 Storage Gateway를 사용해야 한다.</p>
<p><img src="https://velog.velcdn.com/images/sss_jinn/post/18857151-8cfe-4680-b1ae-1fbdce702a0b/image.png" alt=""></p>
<p>즉, AWS의 스토리지를 정리해보면</p>
<ol>
<li>EBS, 또는 EC2 인스턴스 스토어는 블록 스토리지</li>
<li>EFS는 파일 스토리지</li>
<li>S3 또는 Glacier는 오브젝트 스토리지</li>
</ol>
<p><img src="https://velog.velcdn.com/images/sss_jinn/post/a79dfcb6-3a67-46c8-b617-b0c94373f1de/image.png" alt=""></p>
<p>Storage Gateway의 역할은 무엇일까?  </p>
<ul>
<li>AWS 내 사용자의 온프레미스 데이터와 클라우드 데이터를 연결해 준다. 즉 하이브리드 스토리지를 사용하여 온프레미스 시스템에서도 문제 없이 클라우드를 이용할 수 있도록 스토리지 기능을 확장하는 것이다. 이것은 재해복구나 백업,복원 혹은 스토리지 계층에 대해 활용하능하다.</li>
</ul>
<h2 id="s3-summary">S3 SUMMARY</h2>
<ol>
<li>Buckets vs Objects : 버킷의 이름은 전역적으로 고유해야함, 또한 특정 리전에 위치한다. 오브젝트들은 버킷 안에 존재한다.</li>
<li>S3 Security : 이를 위해선 사용자나 역할에 IAM 규칙을 적용할 수 있다. S3 버킷 규칙을 이용하는 방법(퍼블릭액세스, 암호화 등)도 있다. </li>
<li>S3 Websites : 정적 웹사이트 호스팅 제공</li>
<li>S3 Versioning : 파일을 버전 단위로 관리해서 실수로 작제하는 걸 방지, 필요에 따라 이전 버전으로 롤백 가능</li>
<li>S3 Replication : 1. 동일 리전 복제 , 2. 리전 간 복제 - 뭘 하던지 버전 관리 기능을 활성화 시켜야 한다.</li>
<li>S3 Storage Classes : S3의 스토리지 클래스들</li>
<li>Snow Family : S3로 데이터를 임포트할 수 있는 물리적인 기기</li>
<li>OpsHub : 데스크톱애플리케이션, Snow 패밀리 기기를 관리하고 데이터를 기기에 옮겨 준다.</li>
<li>Storage Gateway : 온프레미스 스토리지를 S3로 확장하는 방법</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[AWS - ELB 및 ASG]]></title>
            <link>https://velog.io/@sss_jinn/AWS-ELB-%EB%B0%8F-ASG</link>
            <guid>https://velog.io/@sss_jinn/AWS-ELB-%EB%B0%8F-ASG</guid>
            <pubDate>Sat, 12 Oct 2024 14:25:09 GMT</pubDate>
            <description><![CDATA[<h2 id="클라우드의-확장성-탄력성-고가용성-이란">클라우드의 확장성, 탄력성, 고가용성 이란?</h2>
<h3 id="확장성">확장성</h3>
<p> 애플리케이션을 스케일(확장)한다는 것은 큰 부하(트래픽)에 적응하여 그것을 처리 가능하다는 뜻.</p>
<h4 id="클라우드-확장성-2가지">클라우드 확장성 2가지</h4>
<ol>
<li>수직 확장<ul>
<li>AWS에서 수직 확장이 가능하다는 것은 EC2 인스턴스의 크기를 증가할 수 있다는 뜻. DB와 같은 분산되지 않는 시스템에서 사용하는 방식.</li>
<li>이러한 하드웨어 확장 방식에는 한계가 존재한다.</li>
</ul>
</li>
<li>수평 확장 <ul>
<li>EC2 인스턴스의 사이즈를 늘리는 대신, 인스턴스 또는 시스템의 숫자를 늘리는 것이다.</li>
</ul>
</li>
</ol>
<blockquote>
<p>현대적인 애플리케이션이라면, 수평확장성을 염두에 두고 설계 및 개발을 진행해야한다. AWS에서는 이것이 매우 쉽게 가능하다. AWS EC2와 ASG 덕분이다. </p>
</blockquote>
<h3 id="고가용성">고가용성</h3>
<ul>
<li>수평확장과 잘 어울린다.</li>
<li>애플리케이션을 최소 두 군데에서 실행하는 것을 의미한다.</li>
<li>목적 : 데이터 센터의 손실과 같은 재앙 상황에서 살아남는 것이다.</li>
</ul>
<h3 id="탄력성">탄력성</h3>
<ul>
<li>수요 ( 수신하는 로드 ) 에 따라 시스템을 확장 및 축소하는 클라우드의 특성.</li>
</ul>
<h2 id="확장성-vs-탄력성--vs-민첩성-">확장성 vs 탄력성 ( vs 민첩성 )</h2>
<blockquote>
<p>이 단어들의 차이를 명확히 파악하자.</p>
</blockquote>
<ul>
<li>확장성 : 시스템에 더 큰 부하를 수용하게 하는 것.</li>
<li>탄력성 : 수요에 따라 시스템이 자동으로 확장 및 축소 되는 것.</li>
<li>민첩성 : 리소스를 매우 빠르게 생성 및 삭제하는 것.</li>
</ul>
<h2 id="elb---elastic-load-balancing">ELB - Elastic Load Balancing</h2>
<blockquote>
<p>ELB는 Elastic Load Balancing의 약자로, 로드 밸런서를 포함한다.
로드 밸런서란? -&gt; 인터넷 트래픽을 다운 스트림의 여러 서버로 전달하는 서버를 뜻한다. 부하 분산 기능이다.</p>
</blockquote>
<h3 id="elb-특징">ELB 특징</h3>
<ol>
<li>AWS에서 관리하며 여기에 로드 밸런서가 존재한다. 로드 밸런서 뒤에는 여러 개의 EC2 인스턴스가 존재한다.</li>
<li>애플리케이션에 대한 DNS 호스트 이름인 단일 액세스 지점을 노출한다.</li>
<li>정기적으로 인스턴스 상태를 확인하고 문제가 있는 곳으로는 트래픽을 보내지 않는다.</li>
<li>HTTPS를 제공한다.</li>
<li>AWS가 ELB의 모든 것을 책임진다. (ELB 업그레이드, 유지보수, 고가용성 등등)</li>
<li>개발자가 해야할 건 유일하게 ELB 동작에 관한 몇가지 구성하는 것 뿐이다.</li>
</ol>
<p><img src="https://velog.velcdn.com/images/sss_jinn/post/7bc71353-d651-4343-a4f2-7da203cfa5b5/image.png" alt=""></p>
<p>해당 이미지는 ELB 서비스를 활용한 아키텍처이다. User는 ELB에 의해 노출되는 경로로 요청을 진행하게 되고, 이때 ELB에 의해 각각의 연결되어있는 EC2 인스턴스에 부하가 분산된다.</p>
<h3 id="elb-종류">ELB 종류</h3>
<blockquote>
<p>ELB에는 4가지 종류가 존재하며, 각각의 종류를 상황에 맞게 ELB를 선택하면 좋다.</p>
</blockquote>
<ol>
<li>ALB (Application Load Balancer)<ul>
<li>HTTP,HTTPS 전용 ELB, 계층 7 유형의 로드밸런서이다. 정적 DNS(URL)를 제공한다.</li>
</ul>
</li>
<li>NLB (Network Load Balancer)<ul>
<li>계층 4 유형의 로드밸런서이다. TCP,UDP를 포함, 초고속 성능을 가진다. 정적 IP를 제공한다. 낮은 지연시간으로 초당 수백만개의 요청을 처리한다.</li>
</ul>
</li>
<li>GLB (Gateway Load Balancer)<ul>
<li>계층 3 유형의 로드밸런서이다. 트래픽을 EC2 인스턴스에서 과니하는 방화벽으로 라우팅하여 침입감지, 심층 패킷 검사 등을 실행한다.</li>
</ul>
</li>
<li>CLB (Classic Load Balancer)<ul>
<li>2023년에 폐기된 서비스이다.</li>
</ul>
</li>
</ol>
<p><img src="https://velog.velcdn.com/images/sss_jinn/post/c1b2ff2f-1422-4259-bd49-1936715cd97b/image.png" alt=""></p>
<p>해당 이미지의 ELB 서비스 종류에 대한 각각의 아키텍처를 참고하면 이해가 잘된다.</p>
<h2 id="asg---auto-scaling-group">ASG - Auto Scaling Group</h2>
<blockquote>
<p>우리는 로드밸런서를 통해 트래픽을 여러 EC2 인스턴스로 분산시키는 과정을 알아보았다. 그럼 이 여러 EC2 인스턴스는 어떻게 자동으로 만들 수 있을까???? 
정답 : ASG</p>
</blockquote>
<ul>
<li>AWS의 ASG를 사용하면 된다.</li>
<li>스케일 업,다운(수직확장) 또는 아웃,인(수평확장)의 역할을 해내어 각 상황에 맞게 EC2 인스턴스를 최소, 최대로 보장한다.</li>
<li>그래서 ELB와 ASG는 보통 함께 작용하여 대규모 트래픽에 대한 시너지를 낸다.</li>
<li>ASG는 항상 최적의 용량에서 실행된다. 엄청난 탄력성을 지닌다. 이것은 클라우드의 기본 원칙과도 같다.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/sss_jinn/post/2321637e-e025-4b27-83b5-9c2c2bfbc679/image.png" alt=""></p>
<p>ASG는 EC2 인스턴스의 최소 개수와 평균 개수, 최대 개수를 세팅하여 EC2 인스턴스를 운영한다. </p>
<p><img src="https://velog.velcdn.com/images/sss_jinn/post/c9de203f-d254-4582-bac7-dcfc74bae6b3/image.png" alt=""></p>
<p>ELB 서비스와의 시너지를 알아보자. 트래픽이 발생하면 트래픽의 규모에 따라 EC2 인스턴스를 ASG가 자동으로 스케일 아웃 했다가 스케일 인 했다가 하는 등 탄력적으로 관리하게 된다.</p>
<h2 id="asg---전략">ASG - 전략</h2>
<p>ASG 전략에는 총 4가지가 존재한다.</p>
<ol>
<li><p>단순,단계 스케일링</p>
<ul>
<li>예를 들어, CPU사용량이 5분 동안 70%를 넘으면 ASG 용량에 유닛(EC2) 2개를 추가 or 10분 동안 30% 미만이라면 ASG에서 유닛(EC2) 1개를 제거.</li>
</ul>
</li>
<li><p>대상 추적 스케일링</p>
<ul>
<li>ASG의 모든 EC2 인스턴스의 평균 CPU 사용율을 40%로 유지하고자 한다면 이를 위해 자동으로 조정하는 것.</li>
</ul>
</li>
<li><p>예약 스케일링</p>
<ul>
<li>변경 사항을 미리 아는 것, 사용자 패턴을 기반으로 확장을 예약하는 전략이다.
예를 들어, 사람들이 금요일 5pn에 축구경기 베팅을 한다고 하면 금요일 5pm에 맞춰서 EC2 인스턴스 최소 용량을 10까지 높이는 방식.</li>
</ul>
</li>
<li><p>예측 스케일링</p>
<ul>
<li>머신 러닝을 활용하여 트래픽을 미리 예측하는 방식. 과거 트래픽을 확인하는 알고리즘이 있고 과거의 패턴을 기반으로 트래픽을 예측한다.</li>
<li>그래서 예측을 기반으로 올바른 수의 EC2 인스턴스를 자동으로 세팅한다.
따라서, 시간에 따른 패턴이 존재하고, 스케일링 유형 별 전략을 신경 쓰고 싶지 않다면 예측 스케일링이 정답이다. 매우 유용하다!</li>
</ul>
</li>
</ol>
<h2 id="elb-및-asg---요약">ELB 및 ASG - 요약</h2>
<ol>
<li>각 단어의 뜻과 차이
고가용성 : 여러 가용영역에 걸쳐서 애플리케이션을 보유
확장성 : 수직 - 인스턴스 크기 조절, 수평 - 인스턴스 개수 조절
탄력성 : 수용에 따라 확장 및 축소할 수 있는 기능
민첩성 : 리소스를 미우 빠르게 생성 및 삭제하는 기능</li>
</ol>
<ol start="2">
<li><p>ELB
로드밸런서는 ELB서비스에 있고, 이를 통해 EC2 인스턴스에 트래픽 분산이 가능하다. 여러 가용영역에 분산되어 운영도 가능하다.
EC2 상태를 확인한다.
4가지 타입이 존재한다.</p>
</li>
<li><p>ASG
애플리케이션을 구성하는 EC2 인스턴스의 탄력성을 구현할 수 있어서 부하를 여러 A~Z에 걸쳐 분산하고 적절히 스케일링 할 수 있다.
따라서, 시스템 수요에 따라 이러한 EC2 인스턴스를 스케일링하고 비정상 인스턴스를 교체할 수 있다.</p>
</li>
</ol>
<blockquote>
<p>ASG와 ELB는 긴밀하게 통합되어 있다.</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[AWS - EC2 Instance Storage]]></title>
            <link>https://velog.io/@sss_jinn/AWS-EC2-Instance-Storage</link>
            <guid>https://velog.io/@sss_jinn/AWS-EC2-Instance-Storage</guid>
            <pubDate>Sat, 12 Oct 2024 05:17:38 GMT</pubDate>
            <description><![CDATA[<h2 id="ebs">EBS</h2>
<blockquote>
<p>EBS란? -&gt; Elastic Block Store의 약자로써, 인스턴스가 실행중인 동안 연결 가능한 네트워크 드라이브를 뜻한다.</p>
</blockquote>
<ul>
<li>EC2 인스턴스를 종료 후 새로 생성 했을 때, EBS를 통해 새로운 EC2 인스턴스에 기존 데이터를 전달 가능하다.</li>
<li>EBS는 특정 가용역역에서만 사용 가능하다.<ul>
<li>예를 들어, us-east-1a 영역에 생성되었다면, us-east-1b에서는 사용이 불가하다. 하지만, 스냅샷을 이용하면 다른 가용영역으로 옮기는 것이 가능하다.</li>
</ul>
</li>
<li>매달 30GB 까지 무료이며, gp2와 gp3를 범용으로 사용한다.</li>
<li>EC2 인스턴스 생성 시 EC2 인스턴스를 종료할 때 EBS를 삭제하는 옵션이 있다. 활성화, 비활성화를 통해서 통제 가능하다.</li>
</ul>
<h3 id="ebs-예시">EBS 예시</h3>
<p> <img src="https://velog.velcdn.com/images/sss_jinn/post/82b1bdb7-905b-4196-9a2b-3d60a5648925/image.png" alt=""></p>
<p>해당 이미지는 EBS Volume의 예시이다.</p>
<ol>
<li>US-EAST-1A 영역을 살펴보면 2개의 EC2 인스턴스와 3개의 EBS를 확인 할 수 있다. 1개의 EBS는 1개의 EC2 인스턴스에만 연결이 가능하며, 1개의 EC2 인스턴스에는 여러개의 EBS 설정이 가능하다.</li>
<li>US-EAST-1B 영역을 살펴보면 EC2 인스턴스에 EBS 가 1대 1로 잘 연결되어있고, 나머지 1개의 EBS는 unattached 상태로 남아있음을 볼 수 있다. unattached 상태로 존재 가능하다.</li>
</ol>
<h2 id="ebs-스냅샷">EBS 스냅샷</h2>
<blockquote>
<p>스냅샷이란? </p>
</blockquote>
<ol>
<li><p>내가 원하는 시점에 대한 백업이라고 보면된다.</p>
</li>
<li><p>추후 EBS가 삭제되어도 이걸로 복구 가능하다.</p>
</li>
<li><p>여러 가용영역과 리전 간 복제에도 쓸 수 있다.</p>
<h3 id="ebs-스냅샷의-2가지-특성">EBS 스냅샷의 2가지 특성</h3>
</li>
<li><p>EBS Snapshot Archive</p>
<ul>
<li>스냅샷을 또 다른 스토리지 티어인 &quot;아카이브 티어&quot;로 옮길 수 있다. 이는 기존 스토리지보다 75% 정도 저렴하다. 하지만 이 아카이브를 이용하면 해당 아카이브로 부터 스냅샷을 다시 복구하는데 약 24h~72h 정도로 오래 걸린다.</li>
</ul>
<ol start="2">
<li>Recycle Bin for EBS Snapshot</li>
</ol>
<ul>
<li>이걸 사용하면 삭제된 EBS를 휴지통에서 보관하게 된다. 나중에 복구가 가능하다.</li>
</ul>
</li>
</ol>
<h3 id="ebs-스냅샷-예시">EBS 스냅샷 예시</h3>
<p><img src="https://velog.velcdn.com/images/sss_jinn/post/9b81e4fa-10f8-4f62-a12d-a1179458d86b/image.png" alt=""></p>
<p>해당 이미지는 US-EAST-1A의 가용역역에서 EBS 스토리지를 스냅샷을 통해 US-EAST-1B 가용영역으로 옮기는 과정을 나타내고 있다. 스냅샷을 이용한다면, EBS의 가용영역에 제한되는 특성을 극복 가능하다.</p>
<h2 id="ami">AMI</h2>
<blockquote>
<p>AMI 란? -&gt; Amazon Machine Image의 약자로써, 사용자 지정 EC2 인스턴스라고 보면 된다.</p>
</blockquote>
<ul>
<li>공통으로 제공되는 AMI.</li>
<li>본인이 직접 AMI를 설계해서 만들 수 있다.</li>
<li>딴 사람이 만들어서 판매하는 AMI도 있다.</li>
</ul>
<h3 id="ami-예시">AMI 예시</h3>
<p><img src="https://velog.velcdn.com/images/sss_jinn/post/57dad53c-6b31-4224-ab48-8591a060fa7d/image.png" alt=""></p>
<p>AMI를 직접 커스텀하는 과정을 나타내는 예시이다.</p>
<ol>
<li>US-EAST-1A 영역에서 EC2 인스턴스를 생성하여 커스텀 AMI를 만든다.</li>
<li>US-EAST-1B 영역에서 만들어진 AMI를 이용하여 EC2 인스턴스를 생성한다.</li>
</ol>
<h2 id="ec2-image-builder">EC2 Image Builder</h2>
<blockquote>
<p>기본적으로 커스텀 AMI를 만들 때 이 서비스를 이용하면 커스텀 AMI 셋팅이 가능하다.</p>
</blockquote>
<ul>
<li>가상 머신이나 컨테이너 이미지 생성을 자돟화 하는 데 사용된다.</li>
<li>이를 이용하여, EC2 인스턴스에 대한 AMI의 생성, 유지, 검증 및 테스트를 자동화 할 수 있다.</li>
</ul>
<h2 id="ec2-instance-store">EC2 Instance Store</h2>
<blockquote>
<p>기본적으로 EBS는 &quot;제한된&quot; 네트워크 드라이브이다. 그렇기 떄문에 고성능 하드웨어 디스크가 필요한 경우 EC2 Instance Store를 이용한다.</p>
</blockquote>
<ul>
<li>EC2 인스턴스와 연결된 매우 고성능의 하드웨어를 얻는 방법이다.</li>
<li>하지만 인스턴스 종료 시 소멸 된다.</li>
</ul>
<h2 id="efs">EFS</h2>
<blockquote>
<p>EFS 란? -&gt; Elastic File System의 약자로, 관리형 네트워크 파일 시스템을 뜻한다. EBS가 1개의 EC2 인스턴스에 대한 저장소라고 한다면, EFS는 네트워크에 대한 공유 저장소 같은 느낌이다.</p>
</blockquote>
<ul>
<li>이 시스템을 한번에 수백 개의 EC2 인스턴스에 마운트 할 수 있다.</li>
<li>오직, Linux EC2 인스턴스에서만 사용이 가능하다.</li>
<li>여러 가용 영역에서 사용이 가능하다.</li>
<li>gp2 EBS 볼륨에 비하면 3배 가량 비싸다.</li>
</ul>
<h3 id="efs-예시">EFS 예시</h3>
<p><img src="https://velog.velcdn.com/images/sss_jinn/post/2aa197bd-c2c0-474d-842e-1bc5105bfc2e/image.png" alt=""></p>
<p>해당 이미지는 EFS 서비스를 나타낸 것이다. 여러 가용영역에서 여러 개의 EC2 인스턴스와 연결되어서 파일을 관리하고 있음을 확인 가능하다.</p>
<h2 id="ebs-vs-efs">EBS vs EFS</h2>
<p><img src="https://velog.velcdn.com/images/sss_jinn/post/e549490b-2a81-4679-b51b-5b849423e7c9/image.png" alt=""></p>
<p>EBS와 EFS 스토리지의 비교를 나타내는 자료이다. EBS를 활용한 스토리지는 스냅샷을 통해서 가용영역에서의 데이터를 전송하고 보관한다. EFS는 여러개의 가용영역에 있는 EC2 인스턴스를 관리함으로써 EBS보다는 데이터 파일 관리 및 전송에 용이하다고 볼 수 있다. 하지만 EBS보다 비싸긴하다.</p>
<h2 id="efs의-스토리지-클래스-efs-ia">EFS의 스토리지 클래스 (EFS-IA)</h2>
<blockquote>
<p>EFS의 스토리지 클래스는 파일 액세스 빈도에 따라 비용 최적화 과정을 진행한다.</p>
</blockquote>
<ul>
<li>EFS-IA 스토리지 클래스는 EFS 표준 스토리지 클래스보다 데이터를 저장함에 있어서 92% 더 저렴하다.</li>
<li>EFS-IA 스토리지 클래스를 활성화 시키면 EFS가 자동으로 수명 주기 정책에 따라서 마지막 액세스 시점을 기반으로 User의 파일을 EFS 표준 스토리지에서 EFS-IA 스토리지로 이동시킨다.</li>
</ul>
<h3 id="efs-스토리지-클래스-예시">EFS 스토리지 클래스 예시</h3>
<p> <img src="https://velog.velcdn.com/images/sss_jinn/post/8112c675-e480-47ff-8504-6fa754e25c4c/image.png" alt=""></p>
<p>해당 이미지는 EFS 스토리지의 라이프사이클 정책을 나타내고 있다.
파일의 액세스 시점을 기반으로 관리 정책에 의하여 오랜 기간동안 액세스 되지 않은 파일은 EFS-IA 스토리지 클래스로 파일을 이동시켜 최적화를 진행한다.</p>
<h2 id="ec2-스토리지-공동-책임-모델">EC2 스토리지 공동 책임 모델</h2>
<p>AWS - EBS,EFS 등의 서비스에서의 책임, 시스템 장애의 책임을 가진다.
User - EBS,EFS 서비스를 활용한 백업, 스냅샷 등을 활용한 데이터 전송 절차에 대한 데이터 손실 등의 책임을 가진다.</p>
<h2 id="amazon-fsx">Amazon FSx</h2>
<blockquote>
<p>FSx 란? -&gt; AWS에서 타사의 고성능 파일 시스템을 얻는 관리형 서비스이다.</p>
</blockquote>
<h3 id="1-windows-파일-서버용-amazon-fsx">1. Windows 파일 서버용 Amazon FSx</h3>
<ul>
<li>Windows 인스턴스 용. </li>
<li>특정 데이터센터의 windows pc에서 SMB프로토콜을 사용하여 FSx 파일 서버에 액세스하는 방식이다.</li>
<li>Amazon FSx는 SMB 프로토콜, Windows NTFS로 window 파일 서버를 배포하는 방식이다.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/sss_jinn/post/a33e6393-3918-476a-9ea6-8f424db49ead/image.png" alt=""></p>
<h3 id="2-lustre-파일-서버용-amazon-fsx">2. Lustre 파일 서버용 Amazon FSx</h3>
<ul>
<li>Linux 인스턴스 용.</li>
<li>특정 데이터 센터의 서버에서 FSx 파일 서버에 직접 액세스 하는 방식이다.</li>
<li>그리고 FSx는 해당 파일 데이터를 S3에 저장한다.</li>
</ul>
<p><img src="blob:https://velog.io/755efb5c-4f9c-4560-ba7e-33ba7f8a9f39" alt="업로드중.."></p>
<h2 id="ec2-storage---summary">EC2 Storage - SUMMARY</h2>
<ol>
<li>EBS - 한번에 1개의 EC2 인스턴스에 연결된 네트워크 드라이브, 특정 가용영역에 매핑되며, 스냅샷을 통해 데이터를 백업하거나 다른 가용영역으로 데이터 이동이 가능하다.</li>
<li>AMI - 원하는 대로 사용자가 지정해 바로 사용가능한 EC2 인스턴스 데이터.</li>
<li>EC2 Image Builder : AMI 생성 처리를 자동화하는 서비스이다.</li>
<li>EC2 Instance Store : EC2 인스턴스와 연결된 매우 고성능의 하드웨어를 얻는 방법이다. 하지만 인스턴스 종료 시 소멸된다.</li>
<li>EFS : 네트워크 파일 공유 시스템. (NFS)</li>
<li>EFS-IA : 자주 사용하지 않는 파일을 비용이 낮은 티어로 이동하는 서비스.</li>
<li>FSx for windows : windows 용 NFS</li>
<li>FSx for Lustre : 고성능 컴퓨팅 수행을 위한 파일 서버. Linux 파일 시스템의 HPC.</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[AWS - EC2]]></title>
            <link>https://velog.io/@sss_jinn/AWS-EC2</link>
            <guid>https://velog.io/@sss_jinn/AWS-EC2</guid>
            <pubDate>Wed, 09 Oct 2024 15:23:19 GMT</pubDate>
            <description><![CDATA[<h2 id="ec2-기초">EC2 기초</h2>
<blockquote>
<p>EC2란? -&gt; Elastic Compute Cloud의 약자로, Infrastructure as a Service라고 볼 수 있다. 또한 AWS에서 가장 인기 있는 서비스이다. </p>
</blockquote>
<ul>
<li>EC2는 하나의 서비스가 아닌 많은 서비스를 포함하는 서비스이다.<ul>
<li>가상 머신을 EC2 서비스를 통해 임대하는 것을 EC2 인스턴스라고 한다.</li>
</ul>
</li>
<li>(EBS) 데이터를 가상 드라이브 또는 EBS볼륨에 저장 가능하다.</li>
<li>(ELB) Elastic 로드 밸런서로 로드를 분산시킬 수 있다.</li>
<li>(ASG) 오토 스케일링 그룹을 통해 서비스를 확장시킬 수 있다.</li>
</ul>
<h3 id="핵심">핵심</h3>
<ol>
<li>EC2의 사용법을 아는 것은 클라우드의 작동 방식을 이해할 때 필수적이다.</li>
<li>클라우드는 필요할 때 언제든지 컴퓨팅을 대여할 수 있고 EC2가 그 예시이다.</li>
</ol>
<h2 id="ec2-옵션">EC2 옵션</h2>
<ol>
<li>OS : Linux, Windows, Mac 등</li>
<li>CPU : 해당 가상 머신에서 사용할 컴퓨팅 성능과 코어의 양 선택 가능</li>
<li>RAM : 랜덤 액세스 메모리 선택 가능</li>
<li>EBS,EFS : 용량, 스토리지 선택 가능</li>
<li>EC2 Instance store : 하드웨어 연결 가능 (스토리지)</li>
<li>Network : EC2 인스턴스에 연결할 네트워크 종류 (속도,IP 등등)</li>
<li>Fire wall : 방화벽 규칙, 보안그룹</li>
<li>Bootstrap script : EC2 User Date</li>
</ol>
<h3 id="ec2-user-data">EC2 User Data</h3>
<ul>
<li>EC2 사용자 데이터 스크립트를 사용해 인스턴스를 부트스트래핑(머신이 시작될 때 명령을 시작하는 것) 이 가능하다.</li>
<li>부팅작업 자동화</li>
<li>모든 작업은 root계정에서 발생한다. 그러니 명령은 sudo로 작업해야한다.</li>
</ul>
<h2 id="ec2-종류">EC2 종류</h2>
<p><img src="https://velog.velcdn.com/images/sss_jinn/post/3e717125-ff65-436f-8641-f05c6b248d3b/image.png" alt=""></p>
<p>해당 그림을 보면 종류 별로 EC2의 옵션을  파악할 수 있다.</p>
<h2 id="ec2-종류별-의미">EC2 종류별 의미</h2>
<p><img src="https://velog.velcdn.com/images/sss_jinn/post/08303e30-611f-40f2-8e9f-de12b8a6671a/image.png" alt=""></p>
<ul>
<li>t로 시작하는 인스턴스는 그냥 범용(균형적인) 인스턴스라고 생각하면 된다.</li>
<li>c로 시작하는 인스턴스는 고성능을 요구하는 작업에 유용한 인스턴스이다. (Compute Optimized)</li>
<li>r로 시작하는 인스턴스는 대용량 메모리 처리에 적합한 인스턴스이다. (Memory Optimized)</li>
<li>I,G,H 등으로 시작하는 인스턴스는 로컬 스토리지에서 대규모 데이터셋에 액세스 할 때 적합하다. (Storage Optimized)</li>
</ul>
<h2 id="ec2-보안-그룹">EC2 보안 그룹</h2>
<h3 id="보안-그룹의-역할">보안 그룹의 역할</h3>
<ol>
<li>방확벽, 포트에 대한 액세스를 규제한다.</li>
<li>승인된 IP 범위가 표시된다. (Ipv4, Ipv6)</li>
<li>인바운드 네트워크 제어 (외부에서 들어오는 트래픽)</li>
<li>아웃바운드 네트워크 제어 (내부에서 나가는 트래픽)</li>
<li>보안 그룹은 여러 EC2 인스턴스에 연동 가능하다. 또한 하나의 EC2 인스턴스에 여러 보안 그룹이 적용 가능하다.</li>
<li>보안 그룹은 특정 지역과 VPC 조합에만 제한된다.
6-1. 지역이 바뀌면 새 보안 그룹을 생성해야한다.
6-2. 다른 VPC를 생성한 경우 보안 그룹을 새로 해야한다.</li>
<li>보안 그룹은 EC2 외부에서 존재한다. -&gt; EC2 내부에서는 트래픽을 알 수 없다.</li>
<li>SSH 접근을 위한 별도의 보안 그룹 하나를 유지하는 것이 좋은 방식이다.</li>
<li>기본적으로 모든 인바운드 트래픽은 차단되고, 모든 아웃바운드 트래픽은 승인된다.</li>
<li>로드 밸런서를 사용하면 다른 보안그룹의 보안그룹을 참조가능하다.</li>
</ol>
<p><img src="https://velog.velcdn.com/images/sss_jinn/post/70a13554-c660-4eb3-bfb4-20b94c78a4d7/image.png" alt=""></p>
<p>이런 식으로 셋팅 가능하다.</p>
<p><img src="https://velog.velcdn.com/images/sss_jinn/post/7ab95fe9-911d-488c-863e-7cb401831e23/image.png" alt=""></p>
<p>해당 그림을 보자. 만약에 보안 그룹 설정에서 나의 컴퓨터 IP에 대한 22번 SSH 포트를 허용 해두었다면 보안그룹을 통과해서 EC2 인스턴스에 접근가능하고 Any Ip - Any Port로 아웃바운드 보안그룹이 설정되어 있으면 어떠한 상황에서도 아웃바운드는 허용된다. 하지만 다른 PC에서 22번 포트로 접근하려고하면 보안그룹에 걸려서 타임아웃이 발생하고 EC2 인스턴스에 접근이 불가할 것이다.</p>
<p><img src="https://velog.velcdn.com/images/sss_jinn/post/a6f9da1f-9fec-420f-9176-10f8c993ad75/image.png" alt=""></p>
<p>해당 이미지를 보면, Security Group 1은 인바운드 규칙에서 Security Group 1과 Security Group 2로부터의 트래픽을 허용하고 있다. 그렇기 때문에 Security Group 1과 2 보안 그룹에 허용되는 방식으로 접근하면 접근이 가능하다. 하지만 Security Group 1이 Security Group 3으로부터의 트래픽을 허용하지 않기 때문에 해당 방식으로는 접근이 차단된다.</p>
<h3 id="ec2-포트">EC2 포트</h3>
<p><img src="https://velog.velcdn.com/images/sss_jinn/post/7ab493e7-44fb-42a9-a504-d1fea5579b7c/image.png" alt=""></p>
<blockquote>
<p>EC2 인스턴스에 접근하는데 &quot;타임아웃&quot;이 발생하면 100%에 가까운 확률로 보안 그룹에서 접근이 차단된 것이다.</p>
</blockquote>
<h2 id="ec2-ssh">EC2 SSH</h2>
<ul>
<li>Linux, Windows 10 이상, Mac 에서 SSH 사용이 가능하다. (.pem)</li>
<li>Windows 10 미만이면 Putty를 사용해야한다. (.ppk)</li>
<li>모든 OS에서 EC2 Instance Connect를 통해 EC2 인스턴스에 접근이 가능하다.</li>
</ul>
<h3 id="os에-따른-ssh-사용법">OS에 따른 SSH 사용법</h3>
<ol>
<li>Linux or Mac -&gt; ssh -i <del>~</del>.pem <a href="mailto:ec2-user@xxx.xxx.xxx.xxx">ec2-user@xxx.xxx.xxx.xxx</a> (퍼블릭 ip주소)</li>
<li>Windows 10이상 -&gt; ssh -i .~<del>~</del>.pem <a href="mailto:ec2-user@xxx.xxx.xxx.xxx">ec2-user@xxx.xxx.xxx.xxx</a> (퍼블릭 ip주소)</li>
</ol>
<blockquote>
<p>만약 접근 과정에서 보안 에러가 발생한다면 .pem key의 권한을 바꿔줘야 한다.</p>
</blockquote>
<h2 id="ec2를-위한-iam-역할-사용">EC2를 위한 IAM 역할 사용</h2>
<ul>
<li>EC2 인스턴스에 접근하여 aws --version을 입력하면 aws cli를 포함하고 있을 것임!</li>
<li>그리고 aws configure를 통해서 사용자 정보를 입력하려고 한다면 절대 xxxxx 안됨. 이유는 다른 사람이 정보를 획득할 수 있다.</li>
<li>IAM에서 등록된 Roles를 EC2 IAM Role에 등록해주면 된다.</li>
</ul>
<h2 id="ec2-구매옵션">EC2 구매옵션</h2>
<ol>
<li>on-demand : 언제 어디서나, 내 맘대로.</li>
<li>reserved : 1~3년 동안 미리 예약. 할인 up.</li>
<li>savings-plans : 일점 금액을 지불하기로 하고, 그 기간동안 서비스도 변경하면서 마음대로 사용.</li>
<li>spot instances : 마감 할인 개념. 파격적인 할인을 받는다. 하지만 비용 초과하면 언제든지 서비스 종료.</li>
<li>dedicated Hosts : 서비스 전체를 예약, 나만의 것을 대여.</li>
<li>capacity reservations : 언제 쓸지는 모르지만 미리 예약 해놓고 기간 내에는 언제든지 사용.</li>
</ol>
<h2 id="ec2-summary">EC2 SUMMARY</h2>
<blockquote>
<p>EC2 = AMI(OS) + Instance Size (CPU,RAM) + Storage + Security Groups + EC2 User Data 이다.</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[AWS - IAM ID 및 액세스 관리]]></title>
            <link>https://velog.io/@sss_jinn/AWS-IAM-ID-%EB%B0%8F-%EC%95%A1%EC%84%B8%EC%8A%A4-%EA%B4%80%EB%A6%AC</link>
            <guid>https://velog.io/@sss_jinn/AWS-IAM-ID-%EB%B0%8F-%EC%95%A1%EC%84%B8%EC%8A%A4-%EA%B4%80%EB%A6%AC</guid>
            <pubDate>Mon, 07 Oct 2024 14:33:24 GMT</pubDate>
            <description><![CDATA[<h2 id="iam-사용자-및-그룹">IAM 사용자 및 그룹</h2>
<p><img src="https://velog.velcdn.com/images/sss_jinn/post/ab6d8e51-9713-4b6b-8900-664bdc7202d9/image.png" alt=""></p>
<p>IAM 이란? - 계정 접근 관리 서비스를 뜻한다.
Root account - 말 그대로 루드 계정, 절대 공유하면 안 된다.
Users - 같은 조직 내 사람들을 뜻하며, 그룹에 속 할 수 있다. 
Groups - 사용자만 포함할 수 있으며 다른 그룹은 포함할 수 없다.</p>
<blockquote>
<p>그림과 같이 사용자는 여러 그룹에 속할 수 있으며, 그룹은 여러 명의 사용자를 포함시킬 수 있다.</p>
</blockquote>
<h2 id="iam-정책">IAM 정책</h2>
<p><img src="https://velog.velcdn.com/images/sss_jinn/post/4788037b-e720-4af8-a838-b3a23c1a120b/image.png" alt=""></p>
<p>사용자 또는 그룹에 할당되는 정책 JSON 문서이다.</p>
<ul>
<li>Version -&gt; 정책 버전</li>
<li>Statement -&gt; 정책 요소</li>
<li>sid -&gt; 정책 식별 값</li>
<li>effect -&gt; 특정 API에 대한 권한 (허용,거부)</li>
<li>principal -&gt; 정책이 적용될 사용자,계정, 혹은 역할</li>
<li>Action -&gt; effet에 기반해 허용, 거부되는 API 목록</li>
<li>resource -&gt; 작업이 적용될 action의 리소스 목록</li>
<li>condition -&gt; statement가 적용되는 조건</li>
</ul>
<h2 id="iam---비밀번호-정책">IAM - 비밀번호 정책</h2>
<p> 1.강력한 비밀번호 타입 지원
 2.MFA</p>
<ul>
<li>Multi Factor Authentication (비밀번호 + 보안장치의 조합)</li>
<li>구글 인증기 등등  </li>
</ul>
<p>이 외에 다른 여러가지 방식과 인증 장치 들이 있다.</p>
<h2 id="iam-access">IAM Access</h2>
<ol>
<li>Console URL</li>
<li>CLI (명령줄 인터페이스)</li>
<li>SDK (AWS 소프트웨어 개발 키트)</li>
</ol>
<h2 id="iam-cli-사용법-windows">IAM CLI 사용법 (windows)</h2>
<ol>
<li>AWS cli install 구글링 </li>
<li>windows관련 aws cli msi 설치, 실행</li>
<li>터미널로 접근 후 aws configure 입력 후 엑세스 키값을 입력하면 끝.</li>
</ol>
<h3 id="iam-cloudshell">IAM CloudShell</h3>
<ul>
<li>AWS에서 제공하는 CLI랑 비슷한 터미널이라고 보면된다.</li>
</ul>
<h2 id="iam-역할-role">IAM 역할 (Role)</h2>
<ul>
<li>AWS의 특정 서비스에 대한 IAM 역할을 생성해줘야 할 수도 있다.</li>
<li>Role -&gt; AWS의 실체(ec2 등)들에게 aws에서 작업을 수행할 수 있는 권한을 부여하는 것.</li>
</ul>
<h2 id="iam-모범사례">IAM 모범사례</h2>
<ol>
<li>AWS 계정 설정 이외에는 루트계정을 사용하지 않는다.</li>
<li>한명의 AWS 사용자는 한명의 물리적 사용자와 동일하다.</li>
<li>사용자를 그룹에 할당하고 그룹에 권한을 할당하여 보안그룹 수준에서 관리를 해야한다.</li>
<li>강력한 비밀번호 정책을 따른다.</li>
<li>다중 인증 방식을 적용한다.</li>
<li>AWS 서베스에 대한 권한을 부여할 때 Role을 생성하고 사용하는 것이 좋다.</li>
<li>CLI,SDK 사용 시 사용자 엑세스 키 생성한다.</li>
<li>계정의 권한을 감시하려면 IAM 자격 증명 보고서 확인한다.</li>
<li>절대 IAM 사용자와 액세스 키를 공유하지 않는다.</li>
</ol>
<h2 id="iam-공통-책임-모델">IAM 공통 책임 모델</h2>
<h3 id="aws">AWS</h3>
<ul>
<li><p>AWS 는 제공하는 모든 것에 책임을 가진다</p>
<h3 id="me">ME</h3>
</li>
<li><p>AWS가 제공하지 않는 많은 것의 책임을 진다.</p>
</li>
<li><p>자체 사용자, 그룹 , 역할, 정책, 그 정책을 관리하고 모니터링 하는 모든 것이 전부 &quot;나&quot;의 책임이다. 모든 계정에서 MFA를 활성화하고 시행하는 것도 &quot;나&quot;의 책임이다. 또한 키를 자주 교체하는 것도 내 책임이며, IAM 도구를 사용해서 적합한 권한을 적용하는 것과, 액세스 패턴과, 계정 권한 검토 등등 모든 것이 &quot;나&quot;의 책임.</p>
<blockquote>
<p>AWS는 모든 인프라에 대한 책임을 지며, &quot;나&quot;는 모든 인프라 사용에 대한 책임을 진다.</p>
</blockquote>
</li>
</ul>
<h2 id="iam-최종-요약">IAM 최종 요약</h2>
<p>User - 사용자는 반드시 기업(팀) 내 사용자여야한다. 그리고 사용자는 AWS콘솔의 아이디,비밀번호를 가진다.
Groups - 이러한 사용자를 사용자 그룹으로 그룹화 가능하다.
Policies - 사용자 또는 그룹의 권한을 설정하는 정책 연결 or Json 문서 공유. 또한, 역할을 생성하고 이것을 EC2 인스턴스나 다른 AWS 서비스를 위한 자격 증명이 가능하다.
Security - MFA, Passowrd Policy
AWS CLI - CLI 명령을 통해 서비스를 관리 가능하다.
AWS SDK - SDK로 프로그래밍 언어를 통해 서비스 관리가 가능하다.
Access key - CLI, SDK 사용하기 위함이다.
Audit - IAM 자격증명보고서 생성가능, IAM 접근 감시 서비스로 IAM 사용량 감시 가능하다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[AWS - 클라우드 컴퓨팅이란?]]></title>
            <link>https://velog.io/@sss_jinn/AWS-%ED%81%B4%EB%9D%BC%EC%9A%B0%EB%93%9C-%EC%BB%B4%ED%93%A8%ED%8C%85%EC%9D%B4%EB%9E%80</link>
            <guid>https://velog.io/@sss_jinn/AWS-%ED%81%B4%EB%9D%BC%EC%9A%B0%EB%93%9C-%EC%BB%B4%ED%93%A8%ED%8C%85%EC%9D%B4%EB%9E%80</guid>
            <pubDate>Sun, 06 Oct 2024 12:50:24 GMT</pubDate>
            <description><![CDATA[<h2 id="클라우드-종류">클라우드 종류</h2>
<h3 id="private-cloud">private cloud</h3>
<ul>
<li>외부 노출 x</li>
<li>자체 사설 클라우드와 데이터센터를 가진다. (특정 조직을 위해 전용으로 구성된 클라우드 인프라)</li>
<li>맞춤형 보안, 통제</li>
<li>확장성, 유연성을 가지지만 퍼블릭보단 떨어짐</li>
<li>Rackspace 등등</li>
</ul>
<h3 id="public-cloud">public cloud</h3>
<ul>
<li>공통된 데이터센터를 공유.</li>
<li>확장성, 유연성</li>
<li>온디맨드 -&gt; 언제나 리소스 확장, 감소 가능</li>
<li>MS Azure, Google Cloud, AWS 등등</li>
</ul>
<h3 id="hybrid-cloud">hybrid cloud</h3>
<ul>
<li>private + public</li>
<li>일부 서비스는 온프레미스 혹은 프라이빗 클라우드 (자체 인프라) + 클라우드 하이브리드</li>
<li>유연함, 효율성</li>
</ul>
<h2 id="클라우드-특징">클라우드 특징</h2>
<ol>
<li>온디맨드 -&gt; 필요할 때 원하는 대로 바로바로 사용가능<blockquote>
<p>기존 물리 서버에서 운영하던 방식과 매우 비교되는 핵심 특징.
물리 서버는 확장하기 위해서 용량에 맞는 장치를 주문해서 <del>~ 설치 ~</del> 구축 이런식임.</p>
</blockquote>
</li>
<li>광역 네트워크 접근 가능</li>
<li>보안, 프라이버시 우수</li>
<li>빠른 탄력성, 확장성</li>
<li>측정 가능한 서비스</li>
</ol>
<h2 id="클라우드-장점">클라우드 장점</h2>
<ol>
<li>하드웨서 소유 x</li>
<li>규모가 클수록 좋다.</li>
<li>용량을 예측할 필요가 없다.</li>
<li>확장성</li>
<li>유지보수 비용 x (운영비용,인력비 등등)</li>
</ol>
<blockquote>
<p>물리 서버와 비교해보면 된다.</p>
</blockquote>
<h2 id="클라우드의-유형">클라우드의 유형</h2>
<h3 id="iaas-infrastructure-서비스형-인프라">IaaS (Infrastructure, 서비스형 인프라)</h3>
<ul>
<li>클라우드 IT의 구성요소를 제공한다.</li>
<li>네트워킹,컴퓨팅,스토리지 등을 원시적인 형태로 제공한다.</li>
<li>높은 유연성을 가진다.</li>
<li>AWS EC2 등등</li>
</ul>
<h3 id="paas-platform-서비스형-플랫폼">PaaS (Platform, 서비스형 플랫폼)</h3>
<ul>
<li>기본 인프라 관리가 필요없다. 다 제공한다.</li>
<li>배포와 애플리케이션 관리에만 집중 가능하다.</li>
<li>Elastic Beanstalk, Heroku 등등</li>
</ul>
<h3 id="saas-software-서비스형-소프트웨어">SaaS (Software, 서비스형 소프트웨어)</h3>
<ul>
<li>서비스 제공 업체가 완전히 운영하고 관리하는것</li>
<li>Gmail, Dropbox, Zoom 등등</li>
</ul>
<p><img src="https://velog.velcdn.com/images/sss_jinn/post/5bb55696-e8e1-4ad1-bdd9-df910fbf5cdf/image.png" alt=""></p>
<p>해당 그림을 보면 각 클라우드 서비스 유형 별로 관리자가 어떤 부분을 운영해야 하는지 알 수 있다.</p>
<h2 id="클라우드의-가격">클라우드의 가격</h2>
<blockquote>
<p>클라우드에는 3가지의 기본가격이 있고 모두 종량 과금제(종량제)를 따르고 있다.</p>
</blockquote>
<ul>
<li>컴퓨팅 관련 서비스 -&gt; 시간에 따라 지불</li>
<li>스토리지 -&gt; 저장한 양 만큼 지불</li>
<li>네트워킹 (데이터전송) -&gt; 클라우드에서 데이터가 나갈 때만 지불, 들어올 때는 무료</li>
</ul>
<h2 id="aws의-regions">AWS의 Regions</h2>
<h3 id="regions란">Regions란?</h3>
<ul>
<li>데이터 센터의 집합.</li>
</ul>
<h3 id="리전-선택방법">리전 선택방법</h3>
<ul>
<li>상황에 따라 다르지만, 나라의 정책도 따져봐야 한다.</li>
<li>지연시간 (사용자와 거리가 가까워야함. 멀면 딜레이 생길수도.)</li>
<li>모든 리전이 모든 서비스를 지원하지는 않는다.</li>
<li>리전마다 요금이 다르다.</li>
</ul>
<h2 id="aws-regions의-가용영역">AWS Regions의 가용영역</h2>
<p><img src="https://velog.velcdn.com/images/sss_jinn/post/8463f460-fd8b-4061-ab87-aa9589469f7d/image.png" alt=""></p>
<ul>
<li>리전 별로 가용영역을 가진다. (min:2, avg:3, max:6)</li>
<li>예를 들어, 시드니 리전이 있다고 가정해보자.
실제로 각 영역에서 데이터센터가 어떻게 구성되어있는 지 우리는 알수없지만, 이 가용영역들은 서로 독립적인 형태로 서로 하나의 네트워킹을 구성하고 있다. 이는 재난 등의 상황을 대비하기 위해 이렇게 구성되어있는 것.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[예산 - 2512]]></title>
            <link>https://velog.io/@sss_jinn/%EC%98%88%EC%82%B0-2512</link>
            <guid>https://velog.io/@sss_jinn/%EC%98%88%EC%82%B0-2512</guid>
            <pubDate>Wed, 01 Nov 2023 02:06:38 GMT</pubDate>
            <description><![CDATA[<h2 id="문제">문제</h2>
<p><img src="https://velog.velcdn.com/images/sss_jinn/post/e0016618-7069-4dc0-9344-fdc0c2001991/image.png" alt=""></p>
<h2 id="풀이">풀이</h2>
<pre><code>import java.util.*;

// 예산
public class ex2512 {

    static int n;
    static int[] arr;
    static int total;

    public static long solution(int sum){
        int answer=0;
        Arrays.sort(arr);

        // 총 예산 = total
        long lt = 0;
        long rt = arr[n-1];
        while (lt&lt;=rt){
            long mid = (lt + rt) / 2;
            long budget = 0;

            for(int i=0; i&lt;n; i++){
                if(mid &gt;= arr[i]){
                    budget += arr[i];
                }
                else if(mid &lt; arr[i]){
                    budget += mid;
                }
            }

            if(budget &lt;= total) lt = mid + 1;
            else rt = mid - 1;
        }

        return rt;
    }
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        n = sc.nextInt();
        arr = new int[n];

        int sum=0;
        int max =Integer.MIN_VALUE;
        for(int i=0; i&lt;n; i++){
            arr[i] = sc.nextInt();
            sum+=arr[i];
            max = Math.max(max,arr[i]);
        }
        total = sc.nextInt();

        if(sum &lt;= total) System.out.println(max);
        else System.out.println(solution(sum));
    }
}
</code></pre><p>이분 탐색은 풀 때마다 헷갈린다. 그냥 문제 보고 종이에 쓱쓱 쓰다 보니까 이분탐색 문제인거를 바로 알았다.</p>
<h3 id="이분탐색-필수조건">이분탐색 필수조건</h3>
<ol>
<li>좌표의 정렬</li>
<li>mid 값 구하기 -&gt; mid 값을 기준으로 로직 실행.</li>
<li>만약 mid값 기준으로 더 작은 값이 필요하다면 rt = mid - 1; 그 반대라면 lt = mid + 1;</li>
<li>무한 반복 (효율좋음)</li>
</ol>
<p>이분탐색 문제 개인적으로 어렵게 느껴지는데 간단한 문제는 위 필수조건 적용해서 꼭 풀자.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[최소 회의실 개수]]></title>
            <link>https://velog.io/@sss_jinn/%EC%B5%9C%EC%86%8C-%ED%9A%8C%EC%9D%98%EC%8B%A4-%EA%B0%9C%EC%88%98</link>
            <guid>https://velog.io/@sss_jinn/%EC%B5%9C%EC%86%8C-%ED%9A%8C%EC%9D%98%EC%8B%A4-%EA%B0%9C%EC%88%98</guid>
            <pubDate>Fri, 29 Sep 2023 06:21:07 GMT</pubDate>
            <description><![CDATA[<h3 id="문제">문제</h3>
<p><img src="https://velog.velcdn.com/images/sss_jinn/post/035b6404-0918-4bc8-9713-9c8bec2f29fd/image.png" alt=""></p>
<h3 id="풀이">풀이</h3>
<pre><code>import java.util.*;

// 최소 회의실 개수
public class ex7 {

    static int n;
    static int[][] meetings;
    static int answer=1;

    public static void solution(){
        Arrays.sort(meetings, (a,b) -&gt; a[0]==b[0] ? a[0]-b[0] : a[1]-b[1]);

        // 회의시간이 가장 빠르게 끝나는 순으로 정렬
        // 2 5
        // 0 10
        // 5 15
        // 12 25
        PriorityQueue&lt;Integer&gt; pq = new PriorityQueue&lt;&gt;();
        pq.offer(meetings[0][1]);

        // pq : 5
        for(int i=1; i&lt;meetings.length; i++){
            if(!pq.isEmpty() &amp;&amp; pq.peek()&lt;=meetings[i][0]){
                pq.poll();
            }
            pq.offer(meetings[i][1]);
            answer = Math.max(answer,pq.size());
        }

    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        n = sc.nextInt();
        meetings = new int[n][2];
        for(int i=0; i&lt;n; i++){
            meetings[i][0] = sc.nextInt();
            meetings[i][1] = sc.nextInt();
        }
        solution();
        System.out.println(answer);
    }
}
</code></pre><p>시작 시간 , 종료 시간 기준으로 최소로 사용되는 회의실 개수를 구할 때는 무조건 해야하는 것들이 있다.</p>
<ul>
<li><ol>
<li>무조건 종료시간 기준으로 오름차순 정렬.</li>
</ol>
</li>
<li><ol start="2">
<li>PriorityQueue를 이용해서 최소회의실 개수를 구해야한다.</li>
</ol>
<pre><code>PriorityQueue&lt;Integer&gt; pq = new PriorityQueue&lt;&gt;();
pq.offer(meetings[0][1]);

for(int i=1; i&lt;meetings.length; i++){
         if(!pq.isEmpty() &amp;&amp; pq.peek()&lt;=meetings[i][0]){
             pq.poll();
         }
         pq.offer(meetings[i][1]);
         answer = Math.max(answer,pq.size());
}</code></pre></li>
</ul>
<p>암기 필수.
미팅의 시작시간보다 작은 회의실이 있으면 빼주고, 아니면 계속 pq에 미팅의 종료시간을 접어 넣어준다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[진법 변환]]></title>
            <link>https://velog.io/@sss_jinn/%EC%A7%84%EB%B2%95-%EB%B3%80%ED%99%98</link>
            <guid>https://velog.io/@sss_jinn/%EC%A7%84%EB%B2%95-%EB%B3%80%ED%99%98</guid>
            <pubDate>Wed, 13 Sep 2023 00:32:22 GMT</pubDate>
            <description><![CDATA[<h3 id="목적">목적</h3>
<p>진법 변환하는 거에 있어서 헷갈리지 않기 위함.
확실하게 암기하자.</p>
<pre><code>int i = 127;

String binaryString = Integer.toBinaryString(i); //2진수
String octalString = Integer.toOctalString(i);   //8진수
String hexString = Integer.toHexString(i);       //16진수

System.out.println(binaryString); //1111111
System.out.println(octalString);  //177
System.out.println(hexString);    //7f


int binaryToDecimal = Integer.parseInt(binaryString, 2);
int binaryToOctal = Integer.parseInt(octalString, 8);
int binaryToHex = Integer.parseInt(hexString, 16);

System.out.println(binaryToDecimal); //127
System.out.println(binaryToOctal);   //127
System.out.println(binaryToHex);     //127</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[숫자 카드 나누기]]></title>
            <link>https://velog.io/@sss_jinn/%EC%88%AB%EC%9E%90-%EC%B9%B4%EB%93%9C-%EB%82%98%EB%88%84%EA%B8%B0-toljyjzy</link>
            <guid>https://velog.io/@sss_jinn/%EC%88%AB%EC%9E%90-%EC%B9%B4%EB%93%9C-%EB%82%98%EB%88%84%EA%B8%B0-toljyjzy</guid>
            <pubDate>Wed, 30 Aug 2023 15:22:01 GMT</pubDate>
            <description><![CDATA[<h3 id="문제">문제</h3>
<p><img src="https://velog.velcdn.com/images/sss_jinn/post/24938992-c325-46e3-8152-611a8bfa9f8a/image.png" alt=""></p>
<h3 id="풀이">풀이</h3>
<pre><code>//최대공약수가 다른 배열의 약수가되는지 아닌지 확인한다.
class Solution {
    //최대공약수
    static int gcd(int a, int b) {
        if(b == 0) return a;
        return gcd(b, a%b);
    }

    public int solution(int[] arrayA, int[] arrayB) {
        int answer = 0;
        int a = 0;
        int b = 0;

        //최대 공약수를 구하고.
        for(int i = 0; i &lt; arrayA.length; i++) {
            int max = Math.max(arrayA[i], a);
            int min = Math.min(arrayA[i], a);
            a = gcd(max, min);
         }
        for(int i = 0; i &lt; arrayB.length; i++) {
            int max = Math.max(arrayB[i], b);
            int min = Math.min(arrayB[i], b);
            b = gcd(max, min);
        }

        // 각자의 최대공약수로 다른 배열에 나눠 떨어지면 최대공약수 0으로 만들고 스톱.
        for(int i : arrayB) {
            if(i % a == 0) {
                a = 0;
                break;
            }
        }
        for(int i : arrayA) {
            if(i % b == 0) {
                b = 0;
                break;
            }
        }

        answer = Math.max(a,b);

        return answer;
    }
}</code></pre><p>이 문제 핵심은 자신의 배열은 서로 나누어져야하고, 다른 배열은 그러지 않아야 한다.
A배열에서 가진 최대공약수로 B배열에서 아무요소도 나누어지지않아야한다. 또는 B배열에서 가진 최대공약수로 A배열에서 아무요소도 나누어지지않아야한다는 것이다.
즉 최대공약수를 가진다는 것은 자신의 배열은 서로 나누어 진다는 것.</p>
<p>그래서</p>
<ol>
<li><p>각 배열의 최대공약수를 구한다. </p>
<blockquote>
<p>만약에 최대공약수가 0이면, 그 배열은 서로 나누어지지 않은 배열의 경우라고 할 수 있다. 반대편에서 최대공약수를 가지면 문제 조건 성립</p>
</blockquote>
</li>
<li><p>각 배열의 최대공약수로 다른 배열에 나누어 떨어지는지 확인한다. 만약에 나누어 떨어지면 최대 공약수를 0으로 만들어버린다. 그 최대공약수는 정답이될수없다.</p>
</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[아기 상어 2 - 17086]]></title>
            <link>https://velog.io/@sss_jinn/%EC%95%84%EA%B8%B0-%EC%83%81%EC%96%B4-2-17086</link>
            <guid>https://velog.io/@sss_jinn/%EC%95%84%EA%B8%B0-%EC%83%81%EC%96%B4-2-17086</guid>
            <pubDate>Mon, 28 Aug 2023 12:02:51 GMT</pubDate>
            <description><![CDATA[<h3 id="문제">문제</h3>
<p><img src="https://velog.velcdn.com/images/sss_jinn/post/c96c790c-54e0-4ccc-831f-042e047cc78b/image.png" alt=""></p>
<h3 id="풀이">풀이</h3>
<pre><code>import java.util.*;

// 아기상어2 - BFS
class Point5{
    int x;
    int y;
    public Point5(int x,int y) {
        this.x = x;
        this.y = y;
    }
}
public class ex17086 {
    static int n,m,answer=Integer.MIN_VALUE;
    static int[][] board;
    static int[] dx={0,1,1,1,0,-1,-1,-1};
    static int[] dy={1,1,0,-1,-1,-1,0,1};
    static int[][] dis;
    static boolean[][] ch;
    public static void BFS(int x,int y,int[][] dis,boolean[][] ch){
        Queue&lt;Point5&gt; Q = new LinkedList&lt;&gt;();
        Q.offer(new Point5(x,y));
        ch[x][y]=true;

        while(!Q.isEmpty()){
            Point5 poll = Q.poll();

            if(board[poll.x][poll.y]==1){
                answer = Math.max(answer,dis[poll.x][poll.y]); //핵심
                break;
            }

            for(int i=0; i&lt;8; i++){
                int nx = poll.x + dx[i];
                int ny = poll.y + dy[i];
                if(nx&gt;=0 &amp;&amp; nx&lt;n &amp;&amp; ny&gt;=0 &amp;&amp; ny&lt;m &amp;&amp; !ch[nx][ny]){
                    ch[nx][ny]=true;
                    Q.offer(new Point5(nx,ny));
                    dis[nx][ny] = dis[poll.x][poll.y] + 1;
                }
            }
        }
    }
    public static void solution(){
        for(int i=0; i&lt;n; i++){
            for(int j=0; j&lt;m; j++){
                if(board[i][j]==0){
                    dis = new int[n][m];
                    ch = new boolean[n][m];
                    BFS(i,j,dis,ch);
                }
            }
        }
    }
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        n = sc.nextInt();
        m = sc.nextInt();
        board = new int[n][m];
        for(int i=0; i&lt;n; i++){
            for(int j=0; j&lt;m; j++){
                board[i][j] = sc.nextInt();
            }
        }
        solution();
        System.out.println(answer);
    }
}
</code></pre><blockquote>
<p>글 목적
이 문제는 한번에 맞췄다! 
근데 이 글을 쓰는 목적은 기본적인 문제라 나중에 복습을 하기 위함.</p>
</blockquote>
<p>우선 기본적인 BFS 템플릿 구조를 가진다. 하지만 주의할점은 8방향으로 대각선 포함 이동이 가능해야하며, 각 위치(좌표)에서의 상어까지의 최소거리를 구해서, 모든 좌표에서 가장 긴 상어까지의 길이 answer를 출력하는게 핵심이다.</p>
<p>우선 각 좌표를 구해서 BFS()를 돌릴 solution()를 구현해준다. 이 때 주의할 점은 dis[][] 거리 좌표배열과 ch[][] 체크 불리언 배열을 초기화 시켜서 BFS()에 같이 보내줘야한다.</p>
<p>그 후 메인 BFS()에서 기본적인 BFS()템플릿 구조대로 구현을 하돼,</p>
<pre><code>    if(board[poll.x][poll.y]==1){
        answer = Math.max(answer,dis[poll.x][poll.y]); //핵심
        break;
    }</code></pre><p>이 구문을 이용해서 각 좌표의 상어까지의 최소거리들 중에서 가장 긴 최대거리를 구한다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[너구리 구구 - 18126]]></title>
            <link>https://velog.io/@sss_jinn/%EB%84%88%EA%B5%AC%EB%A6%AC-%EA%B5%AC%EA%B5%AC-18126</link>
            <guid>https://velog.io/@sss_jinn/%EB%84%88%EA%B5%AC%EB%A6%AC-%EA%B5%AC%EA%B5%AC-18126</guid>
            <pubDate>Thu, 17 Aug 2023 14:40:30 GMT</pubDate>
            <description><![CDATA[<h3 id="문제">문제</h3>
<p><img src="https://velog.velcdn.com/images/sss_jinn/post/08eaf752-e4ab-46d7-88f0-52504dd786f2/image.png" alt=""></p>
<h3 id="풀이">풀이</h3>
<pre><code>package Baekjoon;


import java.util.ArrayList;
import java.util.Scanner;

// 너구리 구구 - DFS
// 그냥 끝으로 가면된다.
// 인접리스트를 이용한 경로 탐색 문제. 기본이면서 매우 중요한 문제.
class Edge{
    int y;
    int dis;
    public Edge(int y,int dis){
        this.y = y;
        this.dis = dis;
    }
}
public class ex18126 {
    static ArrayList&lt;ArrayList&lt;Edge&gt;&gt; graph;
    static boolean[] ch;
    static int n;
    static long answer=0;

    public static void DFS(int now,long dis){
        if(answer&lt;dis){
            answer = dis;
        }

        for(Edge edge : graph.get(now)){
            if(ch[edge.y]) continue;
            else{
                ch[edge.y] = true;
                DFS(edge.y, dis+ edge.dis);
            }
        }
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        n = sc.nextInt();
        ch = new boolean[n+1];
        graph=new ArrayList&lt;ArrayList&lt;Edge&gt;&gt;();
        for(int i=0; i&lt;=n; i++){
            graph.add(new ArrayList&lt;Edge&gt;());
        }

        for(int i=1; i&lt;=n-1; i++){
            int x = sc.nextInt();
            int y = sc.nextInt();
            int dis = sc.nextInt();

            //양방향 그래프.
            graph.get(x).add(new Edge(y,dis));
            graph.get(y).add(new Edge(x,dis));
        }

        ch[1] = true;
        DFS(1,0);
        System.out.println(answer);
    }

}
</code></pre><p>인접리스트를 이용한 경로를 탐색하고 끝으로가는 거리를 구하면된다. 단순한 문제이면서, 인접리스트 DFS의 기본이자 핵심 문제이다. 이 유형을 문제를 오랜만에 풀었는데, 헷갈렸다. 연습하자. ........ </p>
<p>DFS은 크게 기본 미로탐색같은 템플릿구조를 띄는 문제와 인접리스트 인접행렬을 이용한 그래프 형태의 DFS문제 2가지로 나뉜다.</p>
<p>그래프 형태에 소홀해졌다. 연습을 하자. 무방향,양방향그래프도 신경쓰자.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[양 - 3184]]></title>
            <link>https://velog.io/@sss_jinn/%EC%96%91-3184</link>
            <guid>https://velog.io/@sss_jinn/%EC%96%91-3184</guid>
            <pubDate>Wed, 16 Aug 2023 07:08:20 GMT</pubDate>
            <description><![CDATA[<h2 id="문제">문제</h2>
<p><img src="https://velog.velcdn.com/images/sss_jinn/post/090a4938-66d7-42f6-a5f6-08aef474b2bb/image.png" alt=""></p>
<h2 id="풀이">풀이</h2>
<pre><code>package Baekjoon;

import java.util.Scanner;

// 양 - DFS
public class ex3184 {
    static int n,m;
    static char[][] map;
    static int[] dx={0,1,0,-1};
    static int[] dy={1,0,-1,0};
    static int answerO = 0 , answerV=0;
    static int nowO=0;
    static int nowV=0;

    public static void DFS(int x,int y){
        if(map[x][y]==&#39;o&#39;) nowO++;
        else if(map[x][y]==&#39;v&#39;) nowV++;

        map[x][y]=&#39;#&#39;;
        for(int i=0; i&lt;4; i++){
            int nx = x + dx[i];
            int ny = y + dy[i];
            if(nx&gt;=0 &amp;&amp; nx&lt;n &amp;&amp; ny&gt;=0 &amp;&amp; ny&lt;m &amp;&amp; map[nx][ny]!=&#39;#&#39;){
                DFS(nx,ny);
            }
        }
    }
    public static void solution(){
        for(int i=0; i&lt;n; i++){
            for(int j=0; j&lt;m; j++){
                if(map[i][j]==&#39;.&#39; || map[i][j]==&#39;v&#39; || map[i][j]==&#39;o&#39;){
                    DFS(i,j);
                    if(nowO &gt; nowV){
                        answerO += nowO;
                    }
                    else answerV += nowV;
                }
                nowO=0;
                nowV=0;
            }
        }
    }
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        n = sc.nextInt();
        m = sc.nextInt();

        map = new char[n][m];
        for(int i=0; i&lt;n; i++){
            char[] str = sc.next().toCharArray();
            for(int j=0; j&lt;m; j++){
                map[i][j] = str[j];
            }
        }

        solution();
        System.out.println(answerO + &quot; &quot; + answerV);
    }
}
</code></pre><p>오랜만에 DFS 기본이 되는 문제! 원샷원킬!
DFS의 핵심. 기본 DFS 템플릿 구조를 이해해야하며, DFS() 호출 전에 탐색하는 solution() 함수를 잘 작성해야한다.</p>
<p>이 문제의 경우 한 곳의 울타리를 찾아서 그곳에서의 살아남는 양과 늑대의 현황을 종합해서 출력하는 문제이다. </p>
<p>처음에 &#39;.&#39; 나왔을 때만 DFS()를 호출했는데, 자세히 보니까 그냥 울타리 안에 늑대나 양만 있는 경우도 있을 수 있더라. 그래서 고쳐주고 정답 돌렸는데 바로 클리어!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[점 찍기 ]]></title>
            <link>https://velog.io/@sss_jinn/%EC%A0%90-%EC%B0%8D%EA%B8%B0</link>
            <guid>https://velog.io/@sss_jinn/%EC%A0%90-%EC%B0%8D%EA%B8%B0</guid>
            <pubDate>Tue, 08 Aug 2023 09:21:34 GMT</pubDate>
            <description><![CDATA[<h2 id="문제">문제</h2>
<p><img src="https://velog.velcdn.com/images/sss_jinn/post/5101ccc7-e741-48c9-b897-94415c21404f/image.png" alt=""></p>
<h2 id="풀이">풀이</h2>
<pre><code>import java.util.*;

class Point{
    long x,y;
    public Point(long x,long y){
        this.x = x;
        this.y = y;
    }

    //중복제거 메소드 오버라이딩 ㅋㅋ;;
    public boolean equals(Object obj){
        if(obj instanceof Point){
            Point tmp = (Point)obj;
            return x==tmp.x &amp;&amp; y==tmp.y; 
        }
        return false;
    }

    public int hashCode(){
        return Objects.hash(x,y);
    }

    public String toString(){
        return x + &quot;:&quot; + y;
    }
}

class Solution {
    static Set&lt;Point&gt; set = new HashSet&lt;&gt;();
    public long solution(int k, int d) {
        long answer = 0;
        // x제곱 + y제곱 = 대각선제곱 의 식을 이용해서 -&gt; 대각선 제곱 &gt; d 이면 포함 x
        // else set.add();

        long x=0,y=0;

        // y값 먼저 올리면서 x도 올리고
        while(y&gt;=0){
            if( (Math.pow(x,2) + Math.pow(y*k,2)) &lt;= Math.pow(d,2)){
                set.add(new Point(x,y*k));
            }
            else break;
            y++;

            while(y % k ==0){
                if( (Math.pow(x,2) + Math.pow(y,2)) &lt;= Math.pow(d,2)){
                    set.add(new Point(x,y));
                }
                else break;
                x+=k;
            }
            x=0;
        }

        y=0; x=0;
        // x값 후에 올리고
        while(x&gt;=0){
            if( (Math.pow(x*k,2) + Math.pow(y,2)) &lt;= Math.pow(d,2)){
                set.add(new Point(x*k,y));
            }
            else break;
            x++;
        }


        return set.size();
    }
}</code></pre><p>피타고라스 방식으로 풀어야겠다고 생각했는데 , 구현 방법이 틀린것같아서 정답 코드를 참고했다.........</p>
<h4 id="정답-코드">정답 코드</h4>
<pre><code>class Solution {
    public long solution(int k, int d) {
        long answer = 0;

        // 피타고라스 -&gt; y제곱 = d제곱 - x제곱
        for(int i=0; i&lt;=d; i+=k){
            int maxY = yDis(i,d);
            answer += maxY/k + 1; // 여기서 1은 해당 (x,0)
        }
        return answer;
    }

    public static int yDis(int x,int d){
        long powX = (long) Math.pow(x,2);
        long powD = (long) Math.pow(d,2);

        int result = (int)(Math.sqrt(powD-powX));
        return result;
    }

}</code></pre><p>간단 하게 , x좌표를 k의 배수만큼 올려주면서 각 x좌표에서의 가능한 y의 크기를 구해서 거기에 해당되는 y의 개수를 추가해줌으로써 답을 구한다.,,,,,,,,,,,,,,,,,,,,,</p>
<p>분명히 피타고라스인건 알았는데, 구현 방법이 잘못되도 너무 잘못됐다. 쉽게 생각을 해보자.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[마법의 엘리베이터]]></title>
            <link>https://velog.io/@sss_jinn/%EB%A7%88%EB%B2%95%EC%9D%98-%EC%97%98%EB%A6%AC%EB%B2%A0%EC%9D%B4%ED%84%B0</link>
            <guid>https://velog.io/@sss_jinn/%EB%A7%88%EB%B2%95%EC%9D%98-%EC%97%98%EB%A6%AC%EB%B2%A0%EC%9D%B4%ED%84%B0</guid>
            <pubDate>Sat, 05 Aug 2023 07:17:44 GMT</pubDate>
            <description><![CDATA[<h3 id="문제">문제</h3>
<p><img src="https://velog.velcdn.com/images/sss_jinn/post/6c002e70-e95d-4248-afd5-b3d95548d8e9/image.png" alt=""></p>
<h3 id="풀이">풀이</h3>
<pre><code>import java.util.*;
class Solution {
    public int solution(int storey) {
        int answer = 0;
        boolean flag = false;
        char[] ctr = Integer.toString(storey).toCharArray(); //2 5 5 4

        for(int i=ctr.length-1; i&gt;=0; i--){
            if(flag){
                ctr[i] = (char) (Integer.valueOf(ctr[i]) + 1); 
                flag=false;
            }

            if(Integer.valueOf(ctr[i]-&#39;0&#39;) &lt; 5){
                answer += Integer.valueOf(ctr[i]-&#39;0&#39;);
            }
            else if(Integer.valueOf(ctr[i]-&#39;0&#39;) &gt; 5){
                if(i==0) answer+=1;
                answer += (10 - Integer.valueOf(ctr[i]-&#39;0&#39;));
                flag = true;
            }

            // 이 문제의 핵심 : 5인 경우에 앞자리 수가 4이하면 그냥 내리는게 더 최솟값이된다.
            else if(Integer.valueOf(ctr[i]-&#39;0&#39;) == 5){
                if(i&gt;0 &amp;&amp; Integer.valueOf(ctr[i-1]-&#39;0&#39;) &lt;= 4){
                    answer += Integer.valueOf(ctr[i]-&#39;0&#39;);
                }
                else {
                    answer += (10 - Integer.valueOf(ctr[i]-&#39;0&#39;));
                    flag = true;
                }
            }
        }


        return answer;
    }
}</code></pre><p>문제 보자마자 어떻게 풀지 조금 생각하는데 5분도 안걸리는 쉬운? 문제였다.
코드 구현은 생각보다 복잡해서 20분 정도 걸렸다고 생각한다. 근데 몇몇 테스트 케이스에 대해서 통과를 받지 못했다. </p>
<p>왤까 생각을 해봤는데 , 현재 자리수가 5인 경우에 앞자리가 4면 내려주는게 더 효율적인데 그냥 싹다 5 밑이면 내리고 5이상이면 올리는 식으로 코드를 짜서 문제의 함정에 걸린게 아닌가싶다.</p>
<p>일단 몇몇 테스트케이스가 통과되지 않을 경우에는 내 코드가 통과되지 못하는 경우를 생각해봐야한다. 여기서 오래걸리면 이 문제는 못푸는거다.
좀 걸렸지만 다행히 찾아서 잘 해결했다.</p>
<p>그리고 </p>
<pre><code>1. intToChar
ctr[i] = (char) (Integer.valueOf(ctr[i]) + 1); 

2. charToInt
int ~~ = Integer.valueOf(ctr[i]-&#39;0&#39;);</code></pre><p>이런거는 이제 바로바로 자동으로 생각없이 나와야한다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[2개 이하로 다른 비트]]></title>
            <link>https://velog.io/@sss_jinn/2%EA%B0%9C-%EC%9D%B4%ED%95%98%EB%A1%9C-%EB%8B%A4%EB%A5%B8-%EB%B9%84%ED%8A%B8</link>
            <guid>https://velog.io/@sss_jinn/2%EA%B0%9C-%EC%9D%B4%ED%95%98%EB%A1%9C-%EB%8B%A4%EB%A5%B8-%EB%B9%84%ED%8A%B8</guid>
            <pubDate>Tue, 01 Aug 2023 10:05:34 GMT</pubDate>
            <description><![CDATA[<h3 id="문제">문제</h3>
<p><img src="https://velog.velcdn.com/images/sss_jinn/post/a63e8223-6a89-4469-9664-7be0b2adb3af/image.png" alt=""></p>
<h3 id="풀이">풀이</h3>
<pre><code>import java.util.*;
class Solution {

    public ArrayList&lt;Long&gt; solution(long[] numbers) {
        ArrayList&lt;Long&gt; answer = new ArrayList&lt;&gt;();

        for(long x : numbers){
            if(x % 2 == 0){
                String binaryString = Long.toString(x,2); // 2진수 변환
                String str = binaryString.replaceFirst(&quot;0$&quot;, &quot;1&quot;);  
                answer.add(Long.parseLong(str, 2));
            }
            else{
                String n = Long.toString(x,2);
                if(!n.contains(&quot;0&quot;)){
                    String temp = &quot;10&quot; + n.substring(1,n.length());
                    answer.add(Long.parseLong(temp,2));
                }
                // 홀수이면서 1과 0이 포함되어있으면 -&gt; 마지막 0을 1로 바꾸고 그 뒤에 1을 0으로 바꿔주면 된다.
                else{
                    // 1 0 0 1
                    // 1 0 1 0
                    char[] temp = n.toCharArray();
                    int idx = n.lastIndexOf(&quot;0&quot;);
                    temp[idx] = &#39;1&#39;;
                    temp[idx + 1] = &#39;0&#39;;

                    long aa = Long.parseLong(String.valueOf(temp), 2);
                    answer.add(aa);
                }
            }
        }

        return answer;
    }

}</code></pre><p>0$ -&gt; 문자열 끝($)의 0을 의미</p>
<ol>
<li><p>짝수
짝수인 경우에는 무조건 1의 자리가 0이다. 1의 자리 수를 1로 바꿔주면 문제에 해당되는 수를 찾을 수 있다
ex) 2 -&gt; 10 -&gt; 11 -&gt; output data : 3
ex) 4 -&gt; 100 -&gt; 101 -&gt;output data : 5
ex) 6 -&gt; 110 -&gt; 111 -&gt; output data : 7</p>
</li>
<li><p>홀수
홀수인 경우에는 2가지의 경우로 나뉜다. 첫번째로는 0이 포함되지 않는 홀수와 두번째로는 0이 포함되는 홀수의 경우이다. 
첫번째 경우에는 그냥 젤 앞의 1을 0으로 바꿔주고 앞에 1을 붙여주면된다.
두번째 경우에는 마지막 0을 1로 바꾸고 , 그 뒤에있는 1을 0으로 바꿔주면 된다.
ex) 5 -&gt; 6
ex) 3 -&gt; 5
ex) 7 -&gt; 11
ex) 9  -&gt; 12</p>
</li>
</ol>
<p>두번째 경우의 홀수인 경우에 바꾸는 부분이 헷갈려서 너무 어려웠다.
그냥 문자열 조절하는게 어려우면 char 단위로 쪼개서 하나하나 씩 수정하는 방식으로 잘 해보자.</p>
<p>[ 알아야 할 것들 ]</p>
<pre><code>replaceFirst(&quot;0$&quot;,&quot;1&quot;); -&gt; 처음 나오는 문자를 &quot;1&quot;로 변경
Long.toString(x,2); -&gt; 2진수 문자 형태로
Long.parseLong(temp,2) -&gt; 2진수를 숫자로</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[모음사전]]></title>
            <link>https://velog.io/@sss_jinn/%EB%AA%A8%EC%9D%8C%EC%82%AC%EC%A0%84</link>
            <guid>https://velog.io/@sss_jinn/%EB%AA%A8%EC%9D%8C%EC%82%AC%EC%A0%84</guid>
            <pubDate>Mon, 31 Jul 2023 05:54:49 GMT</pubDate>
            <description><![CDATA[<h3 id="문제">문제</h3>
<p><img src="https://velog.velcdn.com/images/sss_jinn/post/d92e7404-05da-45ae-927a-584c7b9b4ba4/image.png" alt=""></p>
<h3 id="풀이">풀이</h3>
<pre><code>import java.util.*;

class Solution {
    static String[] str = {&quot;A&quot;,&quot;E&quot;,&quot;I&quot;,&quot;O&quot;,&quot;U&quot;};
    static int answer = 0; 
    static int cnt=0;

    public static void DFS(String tmp,String word){
        if(tmp.equals(word)){
            answer = cnt;
            return;
        }
        if(tmp.length() == 5){
            return;
        } 

        for(int i=0; i&lt;5; i++){
            cnt++;
            DFS(tmp+str[i], word);
        }
    }

    public int solution(String word) {
        // A , E , I , O , U
        DFS(&quot;&quot;,word);
        return answer;
    }
}</code></pre><p>기본적인 완전탐색의 템플릿 형태를 띈다. 빽트래킹을 설정해주고 for문을 돌려준다.
단 , tmp.equals(word) 형태의 빽트래킹이 최우선이 되어야한다. 왜냐하면 tmp.length() == 5 일 경우 빽트래킹을 해버리면 정답을 지나쳐버릴 수도 있기때문이다.
이런 문제를 항상 풀다보면 거의 빽트래킹 설정하는 부분에서 잘못된 부분이 발생한다.
이런 유형의 문제를 만나면 그러한 부분들을 신경쓰자.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[둘만의 암호]]></title>
            <link>https://velog.io/@sss_jinn/%EB%91%98%EB%A7%8C%EC%9D%98-%EC%95%94%ED%98%B8</link>
            <guid>https://velog.io/@sss_jinn/%EB%91%98%EB%A7%8C%EC%9D%98-%EC%95%94%ED%98%B8</guid>
            <pubDate>Thu, 27 Jul 2023 06:21:54 GMT</pubDate>
            <description><![CDATA[<h3 id="문제">문제</h3>
<p><img src="https://velog.velcdn.com/images/sss_jinn/post/ce7e8fa8-611c-4fd9-806d-6b6c0edc4ebf/image.png" alt=""></p>
<h3 id="풀이">풀이</h3>
<pre><code>import java.util.*;
class Solution {
    static ArrayList&lt;Character&gt; list = new ArrayList&lt;&gt;();
    public String solution(String s, String skip, int index) {
        String answer = &quot;&quot;;

        for(char c : skip.toCharArray()){
            list.add(c);
        }

        for(int i=0; i&lt;s.length(); i++){     
            char c = s.charAt(i);
            for(int j=1; j&lt;=index; j++){
                c++;
                if(c&gt;&#39;z&#39;) c-=26;
                if(list.contains(c)) j--; //한번 더 돌게
            }
            answer+=c;
        }

        return answer;
    }
}</code></pre><ol>
<li>2중 for문으로 s.charAt()을 파헤쳐나가면 된다.</li>
<li>만약에 해당 s.charAt()인 c가 알파벳 범위를 넘어가면 c-=26;을 해줘야 하는 부분이 핵심부분이다.</li>
<li>그리고 만약에 건너뛰어야하는 리스트에 해당되는 c면 j--를 해줘서 for문이 한번 더 돌아가게 해주면된다. </li>
</ol>
]]></description>
        </item>
    </channel>
</rss>