<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>코딩 온보딩</title>
        <link>https://velog.io/</link>
        <description>똑똑해지고 싶은 공학도</description>
        <lastBuildDate>Fri, 16 May 2025 05:38:46 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>코딩 온보딩</title>
            <url>https://velog.velcdn.com/images/urban-jungle/profile/ada3df35-274b-4df5-bf14-1e6a04253977/image.png</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. 코딩 온보딩. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/urban-jungle" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[<프로그래머스 293260> 월별 잡은 물고기 수 구하기 (MySQL)]]></title>
            <link>https://velog.io/@urban-jungle/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-293260-%EC%9B%94%EB%B3%84-%EC%9E%A1%EC%9D%80-%EB%AC%BC%EA%B3%A0%EA%B8%B0-%EC%88%98-%EA%B5%AC%ED%95%98%EA%B8%B0-MySQL</link>
            <guid>https://velog.io/@urban-jungle/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-293260-%EC%9B%94%EB%B3%84-%EC%9E%A1%EC%9D%80-%EB%AC%BC%EA%B3%A0%EA%B8%B0-%EC%88%98-%EA%B5%AC%ED%95%98%EA%B8%B0-MySQL</guid>
            <pubDate>Fri, 16 May 2025 05:38:46 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/urban-jungle/post/96e13f75-f43c-41a5-98ea-f1919e21d363/image.png" alt=""></p>
<p><a href="https://school.programmers.co.kr/learn/courses/30/lessons/293260">https://school.programmers.co.kr/learn/courses/30/lessons/293260</a></p>
<p>Level: 2</p>
<hr>
<h4 id="문제-설명">문제 설명</h4>
<p>낚시앱에서 사용하는 <code>FISH_INFO</code> 테이블은 잡은 물고기들의 정보를 담고 있습니다. <code>FISH_INFO</code> 테이블의 구조는 다음과 같으며 <code>ID</code>, <code>FISH_TYPE</code>, <code>LENGTH</code>, <code>TIME</code>은 각각 잡은 물고기의 ID, 물고기의 종류(숫자), 잡은 물고기의 길이(cm), 물고기를 잡은 날짜를 나타냅니다.</p>
<p><img src="https://velog.velcdn.com/images/urban-jungle/post/b0234abc-8e72-444f-9a52-af51aae73f77/image.png" alt=""></p>
<p>단, 잡은 물고기의 길이가 10cm 이하일 경우에는 <code>LENGTH</code> 가 NULL 이며, <code>LENGTH</code> 에 NULL 만 있는 경우는 없습니다.</p>
<hr>
<h4 id="문제">문제</h4>
<p>월별 잡은 물고기의 수와 월을 출력하는 SQL문을 작성해주세요.</p>
<p>잡은 물고기 수 컬럼명은 <code>FISH_COUNT</code>, 월 컬럼명은 <code>MONTH</code>로 해주세요.
결과는 월을 기준으로 오름차순 정렬해주세요.
단, 월은 숫자형태 (1~12) 로 출력하며 9 이하의 숫자는 두 자리로 출력하지 않습니다. 잡은 물고기가 없는 월은 출력하지 않습니다.</p>
<hr>
<pre><code>SELECT COUNT(ID) AS FISH_COUNT, MONTH(TIME) AS MONTH
FROM FISH_INFO
GROUP BY MONTH(TIME)
ORDER BY MONTH ASC;</code></pre><hr>
<p><code>GROUP BY</code>와 <code>ORDER BY</code>를 사용하여 간단하게 풀 수 있는 문제.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[<프로그래머스 299308> 분기별 분화된 대장균의 개체 수 구하기 (MySQL)]]></title>
            <link>https://velog.io/@urban-jungle/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-299308-%EB%B6%84%EA%B8%B0%EB%B3%84-%EB%B6%84%ED%99%94%EB%90%9C-%EB%8C%80%EC%9E%A5%EA%B7%A0%EC%9D%98-%EA%B0%9C%EC%B2%B4-%EC%88%98-%EA%B5%AC%ED%95%98%EA%B8%B0-MySQL</link>
            <guid>https://velog.io/@urban-jungle/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-299308-%EB%B6%84%EA%B8%B0%EB%B3%84-%EB%B6%84%ED%99%94%EB%90%9C-%EB%8C%80%EC%9E%A5%EA%B7%A0%EC%9D%98-%EA%B0%9C%EC%B2%B4-%EC%88%98-%EA%B5%AC%ED%95%98%EA%B8%B0-MySQL</guid>
            <pubDate>Thu, 08 May 2025 12:51:44 GMT</pubDate>
            <description><![CDATA[<p><a href="https://school.programmers.co.kr/learn/courses/30/lessons/299308">https://school.programmers.co.kr/learn/courses/30/lessons/299308</a></p>
<p>Level: 2</p>
<hr>
<h4 id="문제-설명">문제 설명</h4>
<p>대장균들은 일정 주기로 분화하며, 분화를 시작한 개체를 부모 개체, 분화가 되어 나온 개체를 자식 개체라고 합니다.
다음은 실험실에서 배양한 대장균들의 정보를 담은 <code>ECOLI_DATA</code> 테이블입니다. <code>ECOLI_DATA</code> 테이블의 구조는 다음과 같으며, <code>ID</code>, <code>PARENT_ID</code>, <code>SIZE_OF_COLONY</code>, <code>DIFFERENTIATION_DATE</code>, <code>GENOTYPE</code> 은 각각 대장균 개체의 ID, 부모 개체의 ID, 개체의 크기, 분화되어 나온 날짜, 개체의 형질을 나타냅니다.</p>
<p><img src="https://velog.velcdn.com/images/urban-jungle/post/7f5e039b-8f4e-44d0-b46c-fe1d329b0d78/image.png" alt=""></p>
<p>최초의 대장균 개체의 <code>PARENT_ID</code> 는 NULL 값입니다.</p>
<hr>
<h4 id="문제">문제</h4>
<p>각 분기(<code>QUARTER</code>)별 분화된 대장균의 개체의 총 수(<code>ECOLI_COUNT</code>)를 출력하는 SQL 문을 작성해주세요. 이때 각 분기에는 &#39;Q&#39; 를 붙이고 분기에 대해 오름차순으로 정렬해주세요. 대장균 개체가 분화되지 않은 분기는 없습니다.</p>
<hr>
<pre><code>SELECT CONCAT(CEIL(MONTH(DIFFERENTIATION_DATE) / 3), &#39;Q&#39;) QUARTER, COUNT(ID) ECOLI_COUNT
FROM ECOLI_DATA
GROUP BY QUARTER
ORDER BY QUARTER</code></pre><p><code>MONTH</code> 함수를 이용해 &#39;월&#39;을 뽑아낸다.
그 후 3으로 나누고 올림(<code>CEIL</code>)해주면 분기를 구할 수 있다.
<code>QUARTER</code> 함수는 특정 날짜가 속한 연도의 분기를 1부터 4까지의 정수 값으로 반환한다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[CAB TA 4기 28일차의 기록]]></title>
            <link>https://velog.io/@urban-jungle/CAB-TA-4%EA%B8%B0-28%EC%9D%BC%EC%B0%A8%EC%9D%98-%EA%B8%B0%EB%A1%9D</link>
            <guid>https://velog.io/@urban-jungle/CAB-TA-4%EA%B8%B0-28%EC%9D%BC%EC%B0%A8%EC%9D%98-%EA%B8%B0%EB%A1%9D</guid>
            <pubDate>Wed, 23 Apr 2025 06:50:17 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/urban-jungle/post/99be08b6-bf05-42f7-a957-c85b341b8f34/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/urban-jungle/post/a2510e6c-399d-46c7-babd-5998fceb761b/image.png" alt=""></p>
<h1 id="dns란">DNS란</h1>
<h2 id="dns-서비스">DNS 서비스</h2>
<p>DNS는 Domain Name System의 약어로, 네트워크 통신으 위한 주소 체계를 문자 형태인 도메인으로 매핑하여 연결하는 서비스를 의미한다. 여기에서 네트워크 통신 주소는 일반적으로 IP 주소를 사용하는데, 한마디로 IP 주소를 문자 형태의P 주소를 사용하는데, 한마디로 IP 주소를 문자 형태의 도메인 주소로 매핑해서 사용하는 서비스를 의미한다.</p>
<p>예를 들어 구글 웹 페이지에 접속한다고 가정하면, 구글 웹 서버의 IP 주소로 접속해야 한다. 하지만 우리는 IP 주소가 아닌 google.com이라는 문자로 된 주소로 접속한다. DNS 서비스 덕분에 바로 이런 google.com이라는 도메인 주소로 구글 웹 페이지에 접근할 수 있다.</p>
<p>그렇다면 도메인 주소를 활용한 웹 서버 접근은 어떤 단계를 거치는가?</p>
<ol>
<li><p>웹 서버의 IP 주소를 도메인 주소로 사용하고자 ongja.com 도메인을 구매하고 등록한다. 그러면 DNS 서버는 ongja.com의 IP 주소가 무엇인지 알고 정보를 기록해둔다.</p>
</li>
<li><p>사용자는 ongja.com이라는 도메인 주소가 어떤 IP 주소인지 모르고 있으므로 해당 정보를 확인하는 작업이 필요하다.</p>
</li>
<li><p>사용자는 도메인 주소의 IP 주소를 확인하기 위해 DNS 서버에 ongja.com의 도메인 주소를 요청하고 응답받는다. 이때 UDP 53번 포트를 사용하는 DNS 프로토콜을 이용하여 통신한다. 그러면 사용자는 ongja.com에 대한 IP 주소가 무엇인지 알 수 있다.</p>
</li>
<li><p>사용자는 ongja.com의 IP 주소를 알아냈기 때문에 해당 IP 주소로 통신한다.</p>
</li>
</ol>
<p>물론 DNS 서버는 용도에 따라 종류가 다양하며 이들 사이에 복잡한 통신 과정이 있다.</p>
<h2 id="도메인-구조">도메인 구조</h2>
<p><img src="https://velog.velcdn.com/images/urban-jungle/post/dd7bfa75-bc03-4d1b-b260-c39eeb644568/image.png" alt=""></p>
<h3 id="루트-도메인">루트 도메인</h3>
<p>우리가 사용하는 모든 도메인 주소의 가장 마지막에는 온점이 있는데, 일반적으로 이 부분은 생략하고 사용한다. 여기에서 마지막에 위치하는 온점을 루트 도메인이라고 한다.</p>
<h3 id="탑-레벨-도메인">탑 레벨 도메인</h3>
<p>도메인 주소에서 가장 상위에 위치한 도메인을 탑 레벨 도메인이라고 하며, 줄여서 TLD(Top Level Domain)라고 한다.</p>
<h3 id="세컨드-레벨-도메인">세컨드 레벨 도메인</h3>
<p>TLD 다음에 위치한 두 번째 도메인 영역을 세컨드 레벨 도메인이라고 하며, 줄여서 SLD(Second Level Domain)라고 한다. 이런 SLD는 상위 TLD에서 유일하게 존재하고 식별하는 도메인 영역이다. 일반적으로 도메인 이름은 SLD와 TLD를 합친 형태로 표현한다.</p>
<h3 id="서브-도메인">서브 도메인</h3>
<p>도메인을 용도에 따라 앞에 명칭을 부여해서 분류할 수 있는데, 이를 서브 도메인이라고 한다.</p>
<h2 id="dns-서버-종류">DNS 서버 종류</h2>
<p>도메인 구조를 루트 도메인, 탑 레벨 도메인, 세컨드 레벨 도메인, 서브 도메인으로 구분하는 가장 큰 이유는 영역별 도메인을 관리하는 주체를 분리하기 위해서이다. 도메인은 DNS 네임 서버로 관리하는데, 이때 도메인 영역별로 DNS 네임 서버를 분류해서 관리한다.</p>
<h3 id="루트-네임-서버">루트 네임 서버</h3>
<p>루트 도메인을 관리하는 DNS 서버를 루트 네임 서버라고 한다. DNS 요청에 대해 TLD에 해당하는 네임 서버 정보를 응답한다. 루트 네임 서버는 전 세계에 13개만 존재한다.</p>
<h3 id="tld-네임-서버">TLD 네임 서버</h3>
<p>도메인 이름의 최상위 영역인 TLD를 관리하는 DNS 서버로, TLD 네임 서버라고 한다. TLD 영역에서 식별되는 모든 SLD를 관리하여 DNS 요청에 대해 SLD 네임 서버 정보를 응답한다. 예를 들어 .com이라는 TLD 네임 서버는 .com 내에 있는 google.com 도메인을 관리하는 SLD 네임 서버 정보를 알고 있다. 해당 도메인에 대한 DNS 요청이 있으면 SLD 네임 서버 주소를 알려준다.</p>
<h3 id="sld-네임-서버">SLD 네임 서버</h3>
<p>실질적인 도메인 이름을 관리하는 DNS 서버로, SLD 네임 서버(권한 있는 네임 서버)라고 한다. 이런 SLD 네임 서버는 실제 도메인의 최종 관리 서버로 권한이 있는 네임 서버라고 한다. 도메인 주소에 대한 IP 주소를 확인하는 가장 마지막 단계이다.</p>
<h3 id="dns-해석기">DNS 해석기</h3>
<p>사용자와 네임 서버 사이에서 중계자 역할을 수행하는 목적으로 DNS 해석기가 있다. 사용자가 DNS 해석기로 DNS 요청을 하면, DNS 해석기가 DNS 네임 서버와 정보를 주고받아 도메인 주소를 해석하여 최종적으로 IP 주소를 사용자에게 알려준다.</p>
<h2 id="dns-통신-흐름">DNS 통신 흐름</h2>
<ol>
<li><p>사용자 PC에서 blog.cloudneta.net이라는 도메인 주소의 IP 주소를 알기 위해 DNS 서버에 질의한다. 여기에서 DNS 서버는 DNS 해석기를 이용하여 다양한 네임 서버와 통신하는 중계자 역할을 수행한다.</p>
</li>
<li><p>기본적으로 DNS 해석기는 전 세계에 있는 루트 네임 서버의 주소를 알고 있다. 해당 루트 네임 서버에 blog.cloudneta.net 도메인 주소의 IP 주소를 물어본다. 여기에서 루트 네임 서버는 blog.cloudneta.net이라는 도메인 주소를 알지 못하지만 .net의 TLD 네임 서버는 알고 있기 때문에 해당 정보를 DNS 해석기에 전달한다.</p>
</li>
<li><p>그러면 DNS 해석기는 .net에 해당하는 TLD 네임 서버에 blog.cloudneta.net 도메인 주소의 IP 주소를 물어본다. 여기에서 TLD 네임 서버는 blog.cloudneta.net이라는 도메인 주소를 알지 못하지만 cloudneta.net의 SLD 네임 서버는 알고 있어 해당 정보를 DNS 해석기에 전달한다.</p>
</li>
<li><p>다시 DNS 해석기는 cloudneta.net에 해당하는 SLD 네임 서버에 blog.cloudneta.net 도메인 주소의 IP 주소를 물어본다. 이 SLD 네임 서버는 도메인 주소의 최종 정보가 있는 &#39;권한이 있는 네임 서버&#39;로, blog.cloudneta.net에 대한 IP 주소를 DNS 해석기에 전달한다.</p>
</li>
<li><p>DNS 해석기는 blog.cloudneta.net에 대해 최종적으로 해석한 IP 주소를 사용자 PC에 전달한다. 이것으로 사용자 PC는 blog.cloudneta.net 도메인 주소의 IP 주소를 알게 되어 해당 IP 주소로 통신한다.</p>
</li>
</ol>
<h2 id="dns-레코드-유형">DNS 레코드 유형</h2>
<p>DNS 레코드는 도메인에 대한 요청 처리 방법을 정의한 것으로, 용도에 따라 DNS 레코드 유형을 분류한다.</p>
<h3 id="a-레코드-유형">A 레코드 유형</h3>
<p>도메인 이름을 IPv4 주소로 매핑하는 가장 기본적인 DNS 레코드 유형이다. 
다음 형태로 표현한다.
<code>blog.cloudneta.net A 52.219.60.13</code>
blog.cloudneta.net이라는 도메인 주소로 질의하면 IPv4 주소인 52.219.60.13으로 응답한다.</p>
<h3 id="aaaa-레코드-유형">AAAA 레코드 유형</h3>
<p>도메인 이름을 IPv6 주소로 매핑하는 DNS 레코드 유형이다. A 레코드 유형의 IPv6 버전이라고 생각하면 된다. 다음 형태로 표현된다.
<code>blog.cloudneta.net AAAA 2001:A10::2001</code>
blog.cloudneta.net이라는 도메인 주소로 질의하면 IPv6 주소인 2001:A10::2001로 응답한다.</p>
<h3 id="ns-레코드-유형">NS 레코드 유형</h3>
<p>도메인 이름의 네임 서버 주소로 매핑하는 DNS 레코드 유형이다. 
다음 형태로 표현한다.
<code>net NS a.gtld-servers.net.</code>
blog.cloudneta.net이라는 도메인 주소로 질의하면 .net의 TLD 네임 서버 주소인 a.gtld-servers.net. 이라는 도메인 주소로 응답한다.</p>
<h3 id="cname-레코드-유형">CNAME 레코드 유형</h3>
<p>도메인 이름의 별칭을 지정하는 DNS 레코드 유형으로, 다른 도메인 이름을 정의한다. 다음 형태로 표현한다.
<code>www.cloudneta.net CNAME cloudneta.net</code>
<a href="http://www.cloudneta.net%EC%9D%B4%EB%9D%BC%EB%8A%94">www.cloudneta.net이라는</a> 도메인 주소로 질의하면 cloudneta.net의 도메인 주소로 응답한다.</p>
<p>이외에도 다양한 DNS 레코드 유형이 있으며, 이런 DNS 레코드 유형은 DNS 서버에서 다양하게 정의하고 동작한다.</p>
<h1 id="amazon-route-53-서비스">Amazon Route 53 서비스</h1>
<p>Amazon Route 53 서비스는 AWS에서 제공하는 관리형 DNS 서비스이다.</p>
<h2 id="amazon-route-53의-주요-기능">Amazon Route 53의 주요 기능</h2>
<p>Amazon Route 53은 다음 그림과 같은 형태의 아이콘으로 표현한다. Amazon Route 53은 주로 도메인 이름 등록과 호스팅 영역 생성, 레코드 작성 같은 기능을 제공한다.</p>
<h3 id="도메인-이름-등록">도메인 이름 등록</h3>
<p>도메인 이름을 사용하려면 도메인 이름을 등록하는 절차가 필요하다. 도메인을 등록하려면 전 세계에 위치한 네임 서버에 도메인 이름을 사용한다고 알려야 하는데, 이 작업은 개인이 아닌 등록대행소에서 관장한다. 즉, 사용자가 도메인 등록대행소에 도메인 이름 등록을 요청하면 도메인 등록 작업을 대행하는 것이다. 도메인 등록대행소로 국내외에 다양한 웹 사이트가 존재하는데 Amazon Route 53도 도메인 등록대행소 역할을 수행한다.</p>
<p>도메인 이름을 등록하는 작업을 살펴보기 전에 도메인 영역별 네임 서버를 관리하고 등록을 관장하는 단체들을 알아보자. 가장 상위에 ICANN이라는 비영리 단체가 루트 네임 서버를 관리하고 TLD 네임 서버를 등록하는 역할을 수행한다. 다음으로 &#39;등록소&#39;라고 하는 기관이나 기업들이 TLD 네임 서버를 관리하고 권한 있는 네임 서버를 등록하는 역할을 수행한다.</p>
<p>이런 구성에서 Amazon Route 53의 도메인 등록 대행소는 도메인 이름의 TLD에 해당하는 등록소로 도메인 등록 작업을 수행한다. 그래야 앞서 설명한 DNS 통신 흐름에 따라 최종적인 서비스가 가능하다.</p>
<h3 id="호스팅-영역-생성">호스팅 영역 생성</h3>
<p>Amazon Route 53으로 호스팅 영역을 생성하여 네임 서버를 관리할 수 있다. 이렇게 호스팅 영역을 생성해야 Amazon Route 53이 등록된 도메인 이름에 대한 권한 있는 네임 서버이자 SLD 네임 서버의 역할을 수행할 수 있다. 호스팅 영역의 네임 서버들은 고가용성을 위해 다수의 서버로 구성하는데, 마치 네임 서버들의 Zone을 구성하는 개념이다.</p>
<h3 id="레코드-작성">레코드 작성</h3>
<p>Amazon Route 53은 DNS 레코드를 정의하여 도메인에 대한 요청 처리 방법을 정의할 수 있는데, 이런 DNS 레코드는 다양한 형태의 라우팅 정책을 연결하여 도메인 요청에 대한 응답 방식을 정의할 수 있다.</p>
<h2 id="amazon-route-53의-라우팅-정책">Amazon Route 53의 라우팅 정책</h2>
<h3 id="단순-라우팅-정책">단순 라우팅 정책</h3>
<p>단순 라우팅 정책은 도메인에 대해 특정 대상을 지정하는 방식으로 여러 대상이 있으면 랜덤한 대상을 선택하고 응답한다. 예를 들어 ongja.com이라는 도메인의 A 레코드가 10.1.1.1과 10.1.1.2로, 단순 라우팅 정책으로 레코드를 구성하면 DNS 요청에 대해 둘 중 하나의 IP 주소로 랜덤하게 응답한다.</p>
<h3 id="가중치-기반-라우팅-정책">가중치 기반 라우팅 정책</h3>
<p>단순 라우팅 정책이 랜덤하게 대상을 지정했다면 가중치 기반 라우팅 정책은 대상의 가중치를 지정하여 비중에 따라 대상을 선택하고 응답한다. 참고로 가중치는 0~255 범위에서 설정하는데, 대상별 가중치 값을 합산한 전체 가중치를 대상별 가중치로 나누어 비중을 부여한다. 예를 들어 ongja.com이라는 도메인의 A 레코드가 10.1.1.1과 10.1.1.2로, 가중치 기반 라우팅 정책으로 레코드를 구성할 때 10.1.1.1의 가중치가 90이고 10.1.1.2의 가중치가 10이라고 하자. 그러면 DNS 요청에 대해 10.1.1.1로 응답하는 비중은 90/100이고 10.1.1.2로 응답하는 비중은 10/100이 된다.</p>
<h3 id="지연-시간-기반-라우팅-정책">지연 시간 기반 라우팅 정책</h3>
<p>지연 시간 기반 라우팅 정책은 다수의 리전에 대상 자원이 있으면 사용자와 인접한 리전을 기준으로 대상 자원의 리전까지 지연 시간을 파악해서 낮은 지연 시간의 대상을 선택하고 응답한다. 예를 들어 ongja.com이라는 도메인의 A 레코드가 10.1.1.1과 10.1.1.2로, 지연 시간 기반 라우팅 정책이라고 하자. 이때 10.1.1.1은 도쿄 리전에 위치하고 10.1.1.2는 런던 리전에 위치한다고 가정하면, 사용자 위치상 인접한 리전과 대상 자원의 리전까지 지연 시간을 파악한다. 이때 도쿄 리전은 50ms의 지연 시간을 갖고 런던 리전은 230ms의 지연 시간을 갖는다면 DNS 요청에 대해 도쿄 리전에 속한 대상으로 응답한다.</p>
<h3 id="장애-조치-라우팅-정책">장애 조치 라우팅 정책</h3>
<p>장애 조치 라우팅 정책은 다수의 대상 자원에 대해 액티브와 패시브로 분류하고 대상 상태를 주기적으로 검사하여 액티브 대상을 선택하고 응답한다. 액티브 대상이 통신 불가능할 때는 패시브 대상을 액티브로 승격하여 대상 경로로 라우팅한다.</p>
<p>그 밖에 사용자 PC가 지정하는 DNS 서버의 지리적으로 인접한 리전에 위치한 대상으로 경로를 선택하는 지리 위치 라우팅 정책, 지리 위치 라우팅과 형태가 동일하지만 영향도를 조정하는 바이어스(bias)라는 값을 사용하여 제어하는 지리 근접 라우팅 정책이 있다. 또한 DNS 요청에 대해 다수의 값을 반환할 수 있는 다중 값 응답 라우팅 정책도 있다.</p>
<p><img src="https://velog.velcdn.com/images/urban-jungle/post/c8bd4abf-3173-4d94-b3b3-2cc397077452/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[CAB TA 4기 27일차의 기록]]></title>
            <link>https://velog.io/@urban-jungle/CAB-TA-4%EA%B8%B0-27%EC%9D%BC%EC%B0%A8%EC%9D%98-%EA%B8%B0%EB%A1%9D</link>
            <guid>https://velog.io/@urban-jungle/CAB-TA-4%EA%B8%B0-27%EC%9D%BC%EC%B0%A8%EC%9D%98-%EA%B8%B0%EB%A1%9D</guid>
            <pubDate>Wed, 23 Apr 2025 05:10:10 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/urban-jungle/post/f195c6b5-e5fd-4288-9162-6bff1f69cdd8/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/urban-jungle/post/6aacd5f2-0769-4ab6-becb-c317c2131a76/image.png" alt=""></p>
<h1 id="데이터베이스와-dbms">데이터베이스와 DBMS</h1>
<h2 id="데이터와-데이터베이스">데이터와 데이터베이스</h2>
<p>데이터(data)는 어떤 이론을 세우는 데 기초가 되는 자료로, 문자와 숫자, 그림, 영상 등의 형태로 된 단위이다. 데이터는 원시적인 자료에 불가할 뿐 특정한 의미와 가치는 없다. 이런 데이터를 특정 목적에 따라 가공하고 이론을 세워 의미와 가치를 부여한 결과를 정보라고 한다.
데이터베이스는 데이터를 하나에 모아 두는 것을 의미한다. 데이터 베이스는 간단히 데이터를 모아 두는 집합이라고 정의할 수 있다. 또한 데이터 베이스를 관리하는 시스템을 DBMS(DataBase Management System)라고 하며, DBMS는 데이터에 대해 사용자의 논리적 명령을 해석하고 필요한 데이터를 찾아 주는 시스템이라고 정의할 수 있다.</p>
<p><img src="https://velog.velcdn.com/images/urban-jungle/post/1fb588c3-bec2-4655-a519-2fc017befd8a/image.png" alt=""></p>
<h2 id="데이터베이스-모델-유형">데이터베이스 모델 유형</h2>
<p>데이터베이스는 구조, 운영, 저장 방식에 따라 크게 계층형(hierarchical), 네트워크형, 관계형(relational), 객체 지향형(object-oriented) 모델 유형으로 구분할 수 있다.</p>
<h3 id="계층형-데이터베이스-모델">계층형 데이터베이스 모델</h3>
<p>계층형 데이터베이스 모델은 트리(tree) 구조를 기반으로 하며, 데이터는 1:N으로 상하 종속 관계 구조로 되어 있다. 데이터에 빠르게 접근이 가능하지만, 구조 변경에 대한 유연성이 부족하다는 단점이 있다.</p>
<h3 id="네트워크형-데이터베이스-모델">네트워크형 데이터베이스 모델</h3>
<p>네트워크형 데이터베이스 모델은 계층형 데이터베이스의 정형화된 구조를 해결하기 위해 1:N뿐 아니라 1:1, N:N 형태의 구조를 가질 수 있다. 하위 개체는 다수의 상위 개체를 가질 수 있어 형태가 좀 더 자유롭다. 다만 다양한 개체 간 연결에 따라 복잡성은 높아지기 때문에 데이터베이스 전반의 구조를 이해하는 데 어려움이 따를 수 있다.</p>
<h3 id="관계형-데이터베이스-모델">관계형 데이터베이스 모델</h3>
<p>관계형 데이터베이스 모델은 데이터의 논리적 관계를 초점으로 특정 개체 정보를 이용하여 열(column)과 행(row)으로 된 테이블(table)이라는 최소 단위로 구성된다. 앞서 계층형과 네트워크형 데이터베이스 모델은 데이터가 변화하면 상관관계에 따라 모든 데이터를 변경해야 하지만, 관계형 데이터베이스 모델은 데이터가 변화하면 쉽게 적용할 수 있다는 장점이 있다. 하지만 시스템 자원을 많이 차지해서 상대적으로 느리다는 단점이 있다. 물론 하드웨어가 발전하면서 느린 동작은 점점 해소되고 있는 편이다. 관계형 DBMS는 현재 가장 많이 사용하는 데이터베이스 모델이며, SQL(Structured Query Language)이라는 프로그래밍 언어를 사용하여 손쉽게 데이터베이스를 읽고 쓰고 해석한다.</p>
<h3 id="객체-지향형-데이터베이스-모델">객체 지향형 데이터베이스 모델</h3>
<p>객체 지향형 데이터베이스 모델은 모든 데이터를 테이블 형태로 구성하는 관계형 데이터베이스 모델과 다르게 객체(object)라는 형태의 최소 단위로 표현한다. 객체 집합을 정의하고 연결 구조를 확립하여 복잡한 객체 구조도 즉각적으로 표현할 수 있으며, 사용자 정의 데이터, 멀티미디어 등 비정형 데이터도 지원한다. 하지만 보편적으로 사용하는 관계형 데이터베이스의 호환성 문제와 복잡성에 따른 문제도 있다. 현재 객체 지향형 데이터베이스 모델은 특수한 전문 분야가 아니면 잘 쓰지 않는다.</p>
<p><img src="https://velog.velcdn.com/images/urban-jungle/post/916a46c7-792d-4480-bd77-ec6191d0cfbd/image.png" alt=""></p>
<h2 id="관계형-dbms의-sql-언어">관계형 DBMS의 SQL 언어</h2>
<h3 id="sql-데이터-정의">SQL 데이터 정의</h3>
<p>DBMS와 연계되는 다양한 응용 프로그램에서 요구하는 데이터의 형식과 구조를 정의하는 기능으로, 테이블이나 관계의 구조를 정의하는 목적에 따라 CREATE, ALTER, DROP 등의 명령어가 있다.</p>
<ul>
<li>CREATE: 테이블을 구성하고 속성에 대한 제약을 정의하는 명령어</li>
<li>ALTER: 생성된 테이블 속성을 정의하고 변경하는 명령어</li>
<li>DROP: 생성된 테이블을 삭제하는 명령어</li>
</ul>
<h3 id="sql-데이터-조작">SQL 데이터 조작</h3>
<p>데이터 검색, 삽입, 삭제 등을 처리하는 인터페이스를 제공하는 기능으로 SELECT, INSERT, UPDATE, DELETE 등의 명령어가 있다.</p>
<ul>
<li>SELECT: 테이블에 있는 정보를 가져오는 명령어</li>
<li>INSERT: 테이블에 새로운 데이터를 삽입하는 명령어</li>
<li>UPDATE: 테이블에 있는 데이터를 수정하는 명령어</li>
<li>DELETE: 테이블에 있는 기존 데이터를 삭제하는 명령어</li>
</ul>
<h3 id="sql-데이터-제어">SQL 데이터 제어</h3>
<p>데이터 무결성 유지와 접근 권한 및 다수의 사용자 데이터베이스에 정확하게 접근하는 기능으로 GRANT, DENY, REVOKE 등 명령어가 있다.</p>
<ul>
<li>GRANT: 테이블에 대한 권한을 허용하는 명령어</li>
<li>DENY: 테이블에 대한 권한을 차단하는 명령어</li>
<li>REVOKE: 테이블에 대한 권한을 회수하는 명령어</li>
</ul>
<h2 id="dbms-종류">DBMS 종류</h2>
<p>다양한 회사에서 만든 DBMS 제품들이 있는데, 대표적으로 Oracle, MySQL, MS-SQL, PostgreSQL 등이 있다.
인기도 확인: <a href="https://db-engines.com/en/ranking">https://db-engines.com/en/ranking</a></p>
<hr>
<h1 id="aws-데이터베이스-서비스">AWS 데이터베이스 서비스</h1>
<p>AWS 에서는 사용자 요구 사항에 따라 관계형 데이터베이스 서비스, 키-값 데이터베이스, 인-메모리 데이터베이스 등 다양한 데이터베이스 서비스를 제공한다.</p>
<h2 id="amazon-rds">Amazon RDS</h2>
<p>Amazon RDS(Relational Database Service)는 클라우드 환경에서 관계형 데이터베이스를 간편하게 설정하고 운영할 수 있는 서비스이다. 원하는 성능 요구에 따라 다양한 데이터베이스 인스턴스 유형을 선택할 수 있다. Amazon Aurora, PostgreSQL, MariaDB, Oracle Database, SQL Server 등 관계형 데이터베이스 엔진을 선택할 수 있다.</p>
<p>Amazon RDS는 관계형 데이터베이스 모델 유형으로, 테이블 구조에 행과 열로 구성된다. 또한 Amazon RDS는 관계형 데이터베이스 엔진을 사용하기 때문에 SQL 언어 기반으로 데이터베이스를 손쉽게 제어할 수 있다.</p>
<p>Amazon RDS는 사용 편의성이 높고, 모니터링 및 지표와 이벤트 알람을 이용하여 높은 관리 효율성을 보장하며, 비용도 상대적으로 매우 저렴하다. 또한 간편한 복제 기능을 이용하여 워크로드의 가용성과 확장성을 확보할 수 있다.</p>
<h2 id="amazon-rds의-데이터-복제">Amazon RDS의 데이터 복제</h2>
<h3 id="multi-az-복제-방식">Multi-AZ 복제 방식</h3>
<p>Multi-AZ 복제 방식은 기본적으로 액티브-스탠바이(active-standby) 형태로 동작한다. Primary DB가 액티브(활성) 상태이며, 보조의 Standby Replica가 스탠바이(대기) 상태이다. Primary DB에 문제가 발생하면 Standby Replica를 Primary DB로 승격하여 동적으로 유지한다.
이런 Multi-AZ 복제 방식은 데이터 정합성을 유지하는 것이 가장 중요하다. 데이터 정합성이란 데이터가 서로 일관되게 일치하는 것으로, 이를 위해 동기식 복제(synchronous replica)로 다른 가용 영역에 있는 데이터베이스와 데이터를 동기화한다. 여기에서 동기식 복제는 데이터에 변화가 일어나면 원본 데이터를 복제해서 전달하여 동기화하는 것을 의미한다.</p>
<p><img src="https://velog.velcdn.com/images/urban-jungle/post/79bba567-2222-4038-a91d-502fb1b3a7c1/image.png" alt=""></p>
<h3 id="read-replica-복제-방식">Read Replica 복제 방식</h3>
<p>Read Replica 복제 방식은 원본 데이터를 Primary DB에 두고, 읽기 전용의 복제 데이터를 Read-Replica 데이터베이스에 생성하여 유지한다. 읽기 전용 복제 데이터가 있는 Read Replica 데이터베이스는 확장이 가능하며, 데이터 읽기 처리 속도를 높일 수 있다. Amazon RDS는 최대 다섯 개의 Read Replica 데이터베이스를 복제할 수 있으며, 다른 리전까지 Read Replica 데이터베이스를 가질 수 있다.</p>
<p><img src="https://velog.velcdn.com/images/urban-jungle/post/bf8d47b1-d541-4611-9c62-6fcc393b345e/image.png" alt=""></p>
<h2 id="amazon-aurora">Amazon Aurora</h2>
<p>AWS 관계형 데이터베이스 서비스는 Amazon RDS를 이용하여 MySQL, PostgreSQL, Oracle 등 데이터베이스 엔진을 주로 사용하다 Amazon Aurora라는 AWS 자체의 클라우드 데이터베이스 엔진을 개발했다. Amazon Aurora는 엔터프라이즈 수준의 관계형 데이터베이스 엔진으로 안정적이고 고성능의 데이터베이스 처리가 가능하다. 또한 오픈 소스를 기반으로 다른 관계형 데이터베이스와 호환성이 우수하며, 비용 효율이 높다는 장점이 있다. 이런 Amazon Aurora 데이터베이스 엔진은 Amazon RDS에서 관리하며 프로비저닝, 패치, 백업, 복원, 장애 복구 등의 작업을 수행한다.</p>
<h3 id="amazon-aurora-복제-방식">Amazon Aurora 복제 방식</h3>
<p>Amazon Aurora 데이터베이스 엔진은 다른 관계형 데이터베이스 엔진보다 스토리지 내결함성이 우수하다. 예를 들어, MySQL 데이터베이스 엔진은 데이터베이스 인스턴스에 EBS 스토리지가 연결되어 서로 다른 가용 영역으로 동기식 복제가 된다. 반면 Amazon Aurora 데이터베이스 엔진은 공유 스토리지를 통해 최소 세 개의 가용 영역에서 두 개씩 총 여섯 개의 복제 데이터를 가지고 있어 더욱 안정적으로 서비스할 수 있다.</p>
<h2 id="amazon-dynamodb">Amazon DynamoDB</h2>
<p>Amazon DynamoDB는 비관계형 데이터베이스로, 키-값(key-value) 메소드를 사용하는 키-값 데이터베이스이다. 여기에서 비관계형 데이터베이스는 관계형 데이터베이스와 다르게 데이터가 서로 연결되지 않는 개별 형태로 저장하여 복잡하고 구조화되지 않은 데이터 유형에 적합한 데이터베이스이다. 앞서 관계형 데이터베이스가 SQL 언어를 사용했다면, Amazon DynamoDB는 비관계형 데이터베이스로 SQL 문을 사용하지 않는다. 이런 측면에서 NoSQL 데이터베이스라고도 한다.</p>
<p>Amazon DynamoDB의 데이터베이스 구조는 키와 값으로 된 비관계형 데이터베이스 유형이다. 키를 데이터의 고유한 식별자로 사용하고, 값은 유형의 제한이 없어 단순한 개체(entity)뿐 아니라 복잡한 집합체까지 무엇이든 가능한 비정형 데이터를 입력할 수 있다. 이런 키와 값을 쌍으로 집합해서 저장한다.</p>
<p>키-값 데이터베이스는 데이터베이스 구조가 단순하여 빠른 처리가 가능하다. 이런 특성에 따라 Amazon DynamoDB는 대규모 환경에서도 일관되게 10밀리초 미만의 처리 성능을 제공한다. 그리고 Amazon DynamoDB는 별도 서버를 구축하지 않고 운영되는 서버리스(serverless)로 동작하기 때문에 서버에 대한 프로비저닝, 패치, 소프트웨어 설치가 필요 없고 용량에 따라 테이블을 자동으로 확장 및 축소해서 관리 편의성이 높다.</p>
<h2 id="amazon-elasticache">Amazon ElastiCache</h2>
<p>Amazon ElastiCache는 인-메모리 데이터베이스로, 데이터를 메모리에 젖아하는 형태로 동작한다. 데이터가 메모리상에 위치하여 데이터를 빠르게 처리할 수 있다는 장점이 있지만, 데이터양이 많다면 데이터 처리가 느려질 수 있기 때문에 대용량 데이터에는 적합하지 않고 주로 데이터를 빠르게 자주 접근해야 할 때 사용한다. 이런 Amazon ElastiCache는 Memcached 방식과 Redis 방식 두 가지로 구분된다.</p>
<h3 id="amazon-elasticache-for-memcached">Amazon ElastiCache for Memcached</h3>
<p>Memcached는 보편적으로 사용하는 메모리 객체 캐싱 시스템으로, 인-메모리 데이터베이스 서비스이다. Amazon ElastiCache for Memcached는 Memcached와 호환하여 자주 접근할 데이터를 메모리에 놓고 빠르게 처리할 수 있다.</p>
<h3 id="amazon-elasticache-for-redis">Amazon ElastiCache for Redis</h3>
<p>Redis는 데이터베이스, 캐시, 메시지 브로커 및 대기열 용도로 사용되는 인-메모리 데이터베이스 서비스이다. Amazon ElastiCache for Redis는 오픈 소스인 Redis 기반으로 구축되고 Redis API와 호환하여 개방형 Redis 데이터 형식으로 저장한다. 실시간 애플리케이션을 지원할 수 있도록 1밀리초 미만의 지연으로 빠른 데이터를 처리할 수 있다.</p>
<hr>
<p><img src="https://velog.velcdn.com/images/urban-jungle/post/b6d97fca-8841-475a-8f8d-d6c2134b0ac3/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[<프로그래머스 293261> 물고기 종류 별 대어 찾기 (MySQL)]]></title>
            <link>https://velog.io/@urban-jungle/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-293261-%EB%AC%BC%EA%B3%A0%EA%B8%B0-%EC%A2%85%EB%A5%98-%EB%B3%84-%EB%8C%80%EC%96%B4-%EC%B0%BE%EA%B8%B0-MySQL</link>
            <guid>https://velog.io/@urban-jungle/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-293261-%EB%AC%BC%EA%B3%A0%EA%B8%B0-%EC%A2%85%EB%A5%98-%EB%B3%84-%EB%8C%80%EC%96%B4-%EC%B0%BE%EA%B8%B0-MySQL</guid>
            <pubDate>Tue, 22 Apr 2025 14:35:07 GMT</pubDate>
            <description><![CDATA[<p><a href="https://school.programmers.co.kr/learn/courses/30/lessons/293261">https://school.programmers.co.kr/learn/courses/30/lessons/293261</a></p>
<p>Level: 3</p>
<hr>
<h4 id="문제-설명">문제 설명</h4>
<p>낚시앱에서 사용하는 <code>FISH_INFO</code> 테이블은 잡은 물고기들의 정보를 담고 있습니다. FISH_INFO 테이블의 구조는 다음과 같으며 <code>ID</code>, <code>FISH_TYPE</code>, <code>LENGTH</code>, <code>TIME</code>은 각각 잡은 물고기의 ID, 물고기의 종류(숫자), 잡은 물고기의 길이(cm), 물고기를 잡은 날짜를 나타냅니다.</p>
<p><img src="https://velog.velcdn.com/images/urban-jungle/post/bb74f725-1ab4-45e1-b131-50234502e2b2/image.png" alt=""></p>
<p>단, 잡은 물고기의 길이가 10cm 이하일 경우에는 <code>LENGTH</code> 가 NULL 이며, <code>LENGTH</code> 에 NULL 만 있는 경우는 없습니다.</p>
<p><code>FISH_NAME_INFO</code> 테이블은 물고기의 이름에 대한 정보를 담고 있습니다. FISH_NAME_INFO 테이블의 구조는 다음과 같으며, <code>FISH_TYPE</code>, <code>FISH_NAME</code> 은 각각 물고기의 종류(숫자), 물고기의 이름(문자) 입니다.</p>
<p><img src="https://velog.velcdn.com/images/urban-jungle/post/fe98ee50-b12d-4fb7-a80e-54fffb5d015e/image.png" alt=""></p>
<h4 id="문제">문제</h4>
<p>물고기 종류 별로 가장 큰 물고기의 ID, 물고기 이름, 길이를 출력하는 SQL 문을 작성해주세요.</p>
<p>물고기의 ID 컬럼명은 <code>ID</code>, 이름 컬럼명은 <code>FISH_NAME</code>, 길이 컬럼명은 <code>LENGTH</code>로 해주세요.
결과는 물고기의 ID에 대해 오름차순 정렬해주세요.
단, 물고기 종류별 가장 큰 물고기는 1마리만 있으며 10cm 이하의 물고기가 가장 큰 경우는 없습니다.</p>
<hr>
<pre><code>SELECT A.ID, B.FISH_NAME, A.LENGTH
FROM FISH_INFO A
JOIN FISH_NAME_INFO B ON A.FISH_TYPE = B.FISH_TYPE
WHERE A.LENGTH = (
  SELECT MAX(LENGTH)
  FROM FISH_INFO
  WHERE FISH_TYPE = A.FISH_TYPE
)</code></pre><p>HAVING 또는 서브쿼리를 써야한다.</p>
<p>FISH_TYPE별로 가장 큰 LENGTH를 서브쿼리로 구해서 해당 LENGTH와 같은 값을 가진 행만 필터링한다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[<프로그래머스 301650> 특정 세대의 대장균 찾기 (MySQL)]]></title>
            <link>https://velog.io/@urban-jungle/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-301650-%ED%8A%B9%EC%A0%95-%EC%84%B8%EB%8C%80%EC%9D%98-%EB%8C%80%EC%9E%A5%EA%B7%A0-%EC%B0%BE%EA%B8%B0-MySQL</link>
            <guid>https://velog.io/@urban-jungle/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-301650-%ED%8A%B9%EC%A0%95-%EC%84%B8%EB%8C%80%EC%9D%98-%EB%8C%80%EC%9E%A5%EA%B7%A0-%EC%B0%BE%EA%B8%B0-MySQL</guid>
            <pubDate>Wed, 16 Apr 2025 17:24:34 GMT</pubDate>
            <description><![CDATA[<p><a href="https://school.programmers.co.kr/learn/courses/30/lessons/301650">https://school.programmers.co.kr/learn/courses/30/lessons/301650</a></p>
<p>Level: 4</p>
<hr>
<h4 id="문제-설명">문제 설명</h4>
<p>대장균들은 일정 주기로 분화하며, 분화를 시작한 개체를 부모 개체, 분화가 되어 나온 개체를 자식 개체라고 합니다.
다음은 실험실에서 배양한 대장균들의 정보를 담은 <code>ECOLI_DATA</code> 테이블입니다. <code>ECOLI_DATA</code> 테이블의 구조는 다음과 같으며, <code>ID</code>, <code>PARENT_ID</code>, <code>SIZE_OF_COLONY</code>, <code>DIFFERENTIATION_DATE</code>, <code>GENOTYPE</code> 은 각각 대장균 개체의 ID, 부모 개체의 ID, 개체의 크기, 분화되어 나온 날짜, 개체의 형질을 나타냅니다.</p>
<p><img src="https://velog.velcdn.com/images/urban-jungle/post/35f2524c-1108-4e56-b346-b65441e0f609/image.png" alt=""></p>
<p>최초의 대장균 개체의 <code>PARENT_ID</code> 는 NULL 값입니다.</p>
<h4 id="문제">문제</h4>
<p>3세대의 대장균의 ID(<code>ID</code>) 를 출력하는 SQL 문을 작성해주세요. 이때 결과는 대장균의 ID 에 대해 오름차순 정렬해주세요.</p>
<h4 id="예시">예시</h4>
<p>예를 들어 <code>ECOLI_DATA</code> 테이블이 다음과 같다면
<img src="https://velog.velcdn.com/images/urban-jungle/post/44280a77-260a-44e8-96cc-87b63590bb6b/image.png" alt=""></p>
<p>PARENT ID 가 NULL 인 ID 1, ID 2가 1 세대이며 ID 1에서 분화된 ID 3, ID 2에서 분화된 ID 4, ID 5 가 2 세대입니다. ID 4 에서 분화된 ID 6, ID 3에서 분화된 ID 7 이 3 세대이며 ID 6에서 분화된 ID 8은 4 세대입니다.</p>
<p>따라서 결과를 ID 에 대해 오름차순 정렬하면 다음과 같아야 합니다.</p>
<p><img src="https://velog.velcdn.com/images/urban-jungle/post/1389d506-7d15-4991-85f5-55c98887c81b/image.png" alt=""></p>
<hr>
<pre><code>SELECT A.ID
FROM ECOLI_DATA A, ECOLI_DATA B, ECOLI_DATA C
WHERE B.ID = A.PARENT_ID &amp;&amp; (B.PARENT_ID) = C.ID &amp;&amp; C.PARENT_ID IS NULL
ORDER BY ID ASC;</code></pre><p>이게 레벨 4가 맞나..? 싶을 정도로 쉽다.
테이블을 나누는게 어색하다면 낯설 수 있지만,
천천히 조건만 잘 읽고 대응하면 쉽게 풀 수 있다.
A.ID의 PARENT_ID를 가지는 B.ID를 고려한다.
B.ID의 PARENT_ID가 C.ID 값인 해당 C.ID의 PARENT_ID가 NULL값이면,
A.ID값을 출력해준다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[<프로그래머스 284531> 노선별 평균 역 사이 거리 조회하기 (MySQL)]]></title>
            <link>https://velog.io/@urban-jungle/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-284531-%EB%85%B8%EC%84%A0%EB%B3%84-%ED%8F%89%EA%B7%A0-%EC%97%AD-%EC%82%AC%EC%9D%B4-%EA%B1%B0%EB%A6%AC-%EC%A1%B0%ED%9A%8C%ED%95%98%EA%B8%B0-MySQL</link>
            <guid>https://velog.io/@urban-jungle/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-284531-%EB%85%B8%EC%84%A0%EB%B3%84-%ED%8F%89%EA%B7%A0-%EC%97%AD-%EC%82%AC%EC%9D%B4-%EA%B1%B0%EB%A6%AC-%EC%A1%B0%ED%9A%8C%ED%95%98%EA%B8%B0-MySQL</guid>
            <pubDate>Wed, 16 Apr 2025 17:04:23 GMT</pubDate>
            <description><![CDATA[<p><a href="https://school.programmers.co.kr/learn/courses/30/lessons/284531">https://school.programmers.co.kr/learn/courses/30/lessons/284531</a></p>
<p>Level: 2</p>
<hr>
<h4 id="문제-설명">문제 설명</h4>
<p><code>SUBWAY_DISTANCE</code> 테이블은 서울지하철 2호선의 역 간 거리 정보를 담은 테이블입니다. <code>SUBWAY_DISTANCE</code> 테이블의 구조는 다음과 같으며 <code>LINE</code>, <code>NO</code>, <code>ROUTE</code>, <code>STATION_NAME</code>, <code>D_BETWEEN_DIST</code>, <code>D_CUMULATIVE</code>는 각각 호선, 순번, 노선, 역 이름, 역 사이 거리, 노선별 누계 거리를 의미합니다.
<img src="https://velog.velcdn.com/images/urban-jungle/post/190d42c2-7e63-434f-9dcd-5a592a292eee/image.png" alt=""></p>
<h4 id="문제">문제</h4>
<p><code>SUBWAY_DISTANCE</code> 테이블에서 노선별로 노선, 총 누계 거리, 평균 역 사이 거리를 노선별로 조회하는 SQL문을 작성해주세요.</p>
<p>총 누계거리는 테이블 내 존재하는 역들의 <strong>역 사이 거리</strong>의 총 합을 뜻합니다. 총 누계 거리와 평균 역 사이 거리의 컬럼명은 각각 <code>TOTAL_DISTANCE</code>, <code>AVERAGE_DISTANCE</code>로 해주시고, 총 누계거리는 소수 둘째자리에서, 평균 역 사이 거리는 소수 셋째 자리에서 반올림 한 뒤 단위(km)를 함께 출력해주세요.
결과는 총 누계 거리를 기준으로 내림차순 정렬해주세요.</p>
<h4 id="예시">예시</h4>
<p><img src="https://velog.velcdn.com/images/urban-jungle/post/5b27488d-4fc9-4cc2-ab6a-5337f819c56e/image.png" alt=""></p>
<hr>
<pre><code>SELECT 
  ROUTE,
  CONCAT(ROUND(SUM(D_BETWEEN_DIST), 1), &#39;km&#39;) AS TOTAL_DISTANCE,
  CONCAT(ROUND(AVG(D_BETWEEN_DIST), 2), &#39;km&#39;) AS AVERAGE_DISTANCE
FROM 
  SUBWAY_DISTANCE
GROUP BY 
  ROUTE
ORDER BY 
  SUM(D_BETWEEN_DIST) DESC;</code></pre><p>MySQL은 &#39;km&#39;같은 문자열을 붙일때 CONCAT()을 사용해주어야 한다.
반올림 같은 조건은 ROUND로 잘 충족시켜줘야 한다.
그 이외에는 아주 쉬운 문제이다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[CAB TA 4기 26일차의 기록]]></title>
            <link>https://velog.io/@urban-jungle/CAB-TA-4%EA%B8%B0-26%EC%9D%BC%EC%B0%A8%EC%9D%98-%EA%B8%B0%EB%A1%9D</link>
            <guid>https://velog.io/@urban-jungle/CAB-TA-4%EA%B8%B0-26%EC%9D%BC%EC%B0%A8%EC%9D%98-%EA%B8%B0%EB%A1%9D</guid>
            <pubDate>Wed, 16 Apr 2025 16:22:20 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/urban-jungle/post/ee912900-8e3c-4af0-ba5f-1702e3d1b7d6/image.png" alt=""></p>
<hr>
<h1 id="스토리지-개요">스토리지 개요</h1>
<p>스토리지(Storage)란 데이터를 보관하는 장소로, 우리가 사용하는 모든 저장 장치를 스토리지라고 할 수 있다. 데이터 보관 방식과 데이터 사용 용도에 따라 여러 형태가 있다. 예를 들어 이동성 및 휴대성을 고려해서 간단한 데이터를 보관할 때 사용하는 USB(Universal Serial Bus), 대용량의 데이터를 보관하거나 백업할 때 사용하는 외장하드(SSD, HDD)가 있다.
IT가 발전하면서 스토리지도 변화했으며, 클라우드 환경에서 사용되는 스토리지 역시 그 목적에 따라 다양하게 변화했다.</p>
<hr>
<h1 id="스토리지-서비스-및-주요-기능">스토리지 서비스 및 주요 기능</h1>
<p>AWS에서 제공하는 스토리지 서비스 종류에는 블록(block) 스토리지, 파일(file) 스토리지, 객체(object) 스토리지가 있는데, 각 목적에 따라 사용하는 것이 좋다.</p>
<h2 id="블록-스토리지">블록 스토리지</h2>
<p>블록 스토리지는 단일 스토리지 볼륨을 &#39;블록&#39;이라는 개별 단위로 분할해서 저장한다. 각 블록은 저장된 위치에 고유한 주소가 있기 때문에 서버에서 파일을 요청하면 블록들을 재구성하여 하나의 데이터로 서버에 전달한다. 클라우드 환경에서 블록 스토리지의 각 블록은 가상 머신 인스턴스에 위치하며, 마치 일반 컴퓨터에 하드디스크를 추가하여 C 드라이브, D 드라이브처럼 논리적으로 구분해서 사용하는 것과 같다. 일반적으로 블록 스토리지는 SAN(Storage Area Network) 또는 가상 머신의 디스크로 사용된다.</p>
<h2 id="파일-스토리지">파일 스토리지</h2>
<p>파일 스토리지는 파일 수준 또는 파일 기반 스토리지라고 하며, 디렉터리 구조로 파일을 저장한다. 각 파일은 폴더에 종속되고 폴더 역시 다른 폴더에 종속되어 계층 구조를 이룬다. 따라서 파일을 찾으려면 어느 위치에 있는지 알아야 한다. 파일 스토리지는 개인용 컴퓨터와 서버에서 일상적인 작업을 공유하여 사용할 수 있지만, 파일이 늘어나면 분류하거나 정리(file system indexing)하는 데 시간이 점점 더 소요된다는 단점이 있다. 일반적으로 파일 스토리지는 NAS(Network Attached Storage)에 사용된다.</p>
<h2 id="객체-스토리지">객체 스토리지</h2>
<p>객체 스토리지는 각 데이터 조각을 가져와서 객체로 지정하고, 개별 단위로 저장한다. 파일 스토리지와 다르게 모든 객체는 중첩된 계층 구조 없이 단일한 평면적인 주소 공간에 저장된다. 이 평면 주소 공간에는 데이터 및 관련 메타데이터(metadata)로 구성된 객체에 고유 식별자가 있다. OS나 파일 시스템에 의존하지 않으면서 데이터를 저장하고 객체에 쉽게 접근할 수 있다. 객체 스토리지 시스템에서는 객체의 키(이름)만 알고 있으면 쉽고 빠르게 대상을 검색할 수 있다. 객체 스토리지 접근에는 HTTP 프로토콜 기반의 REST(Representational State Transfer) API(Application Programming Interface)를 사용한다.
객체 스토리지는 저장할 수 있는 데이터의 수와 파일 크기에 제한이 없으며 데이터 저장의 총용량 역시 무제한에 가깝다고 할 수 있다. </p>
<p><img src="https://velog.velcdn.com/images/urban-jungle/post/fa0c355d-b9e0-435d-a764-c2075b47d382/image.png" alt=""></p>
<h2 id="스토리지-선택-기준">스토리지 선택 기준</h2>
<p>클라우드 스토리지는 어디에서나 접근할 수 있는 편의성, 대량의 데이터를 수용할 수 있는 확장성을 갖추고 있다. 따라서 스토리지를 도입할 때는 클라우드 스토리지의 종류별 특징을 충분히 이해하고 목적과 상황에 맞게 선택해야 한다.</p>
<p>[스토리지를 선택할 때 고려 사항]</p>
<ul>
<li>내구성: 데이터 손실 가능성</li>
<li>가용성: 서비스 지속 시간</li>
<li>보안: 저장 및 전송 중 데이터 보안</li>
<li>비용: 스토리지 단위 가격</li>
<li>확장성: 스토리지 크기 및 사용자 수 변경</li>
<li>성능: 스토리지 크기 및 사용자 수 변경</li>
<li>통합: 다른 서비스와 호환성</li>
</ul>
<hr>
<h1 id="amazon-ebs">Amazon EBS</h1>
<h2 id="ebs란">EBS란</h2>
<p>Amazon EBS(Elastic Block Store)는 EC2 인스턴스에 사용할 수 있는 블록 스토리지 볼륨을 제공하는 서비스이다. 블록 스토리지 특성을 이용한 저장 방식이므로 데이터를 일정한 크기의 블록으로 나누어 분산 저장하는데, 볼륨 위에 파일 시스템을 생성하거나 하드디스크 드라이브 같은 블록 디바이스를 사용하는 것처럼 볼륨을 쓸 수 있다. 쉽게 운영 체제에 외장 하드디스크를 연결해서 데이터를 저장한다고 생각하면 됩니다. 또한 인스턴스에 연결된 EBS 볼륨의 구성을 동적으로 변경할 수 있다. 이처럼 EBS는 데이터베이스처럼 데이터 출입이 많은 서비스에 적합하다.</p>
<p>EBS 스토리지는 AWS 관리 콘솔에서 필요한 용량과 성능에 맞추어 볼륨을 생성한 후 EC2 인스턴스에 연결하고 파일 시스템을 포맷한 후 사용한다. 이때 파일 시스템 포맷은 운영 체제에 따라 다르게 사용된다. 리눅스는 xfs 또는 ext4 유형이 주로 사용되며, 윈도우는 NTFS 포맷이 주로 사용된다. 포맷이 완료되면 해당 볼륨을 서버에서 마운트한 후 데이터를 해당 디렉터리에 저장해서 사용한다.</p>
<p>EBS는 고속 네트워크로 연결되어 있으며, 데이터 수명 시간이 독립되어 있다. 독립된 데이터 수명 시간이란 &#39;서로 연결된 인스턴스와 볼륨을 사용하나 해당 인스턴스를 삭제해도 볼륨은 계속 사용할 수 있고 그 볼륨에 저장된 데이터도 다른 인스턴스와 연결하여 이어서 사용할 수 있다&#39;는 의미이다. 결론적으로 인스턴스와 EBS 볼륨은 서로 종속 관게에 있지 않으며, 인스턴스는 다수의 볼륨을 연결하여 사용할 수 있다. 하지만 하나의 EBS 볼륨은 한 번에 하나의 인스턴스에만 연결할 수 있고, 해당 인스턴스에서 지원하는 형태의 시스템으로 포맷해야만 사용할 수 있다.</p>
<p><img src="https://velog.velcdn.com/images/urban-jungle/post/a4831d77-9fe0-427e-ad61-60b5a36b4407/image.png" alt=""></p>
<h2 id="ebs-특징">EBS 특징</h2>
<ul>
<li>데이터 가용성: 단일 하드웨어 구성 요소의 장애 때문에 데이터가 손실되지 않도록 해당 가용 영역 내에서 자동으로 데이터를 복제한다.</li>
<li>데이터 지속성: EBS 볼륨은 인스턴스 수명과 관계없이 유지되는 비관계형 인스턴스 스토리지이다.</li>
<li>데이터 안정성: Amazon EBS 암호화(encryption) 기능으로 암호화된 EBS 볼륨을 생성할 수 있으며, 암호화 표준 알고리즘(AES-256)을 사용한다.</li>
<li>데이터 백업: 모든 EBS 볼륨의 스냅샷(백업)을 생성하고, 다중 가용 영역에 중복 저장이 가능한 Amazon S3(Simple Storage Service)에 볼륨 내 데이터 사본을 백업할 수 있다.</li>
<li>데이터 확장성: 서비스를 중단할 필요 없이 볼륨 유형, 볼륨 크기, IOPS(Input/Output operations Per Second) 용량을 수정할 수 있다.</li>
</ul>
<h2 id="ebs-볼륨-유형">EBS 볼륨 유형</h2>
<p>EBS 볼륨에는 크게 SSD와 HDD 유형이 있다. SSD는 메모리형 디스크를 사용하며, HDD는 플래터(platter) 디스크를 사용한다. 데이터를 빠르게 읽고 처리하는 능력이 좋은 SSD는 주로 서버의 운영 체제가 설치되는 OS 영역이나 일반 데이터베이스 보관용 스토리지 유형으로 사용된다. HDD는 속도와 상관없이 데이터 저장 용량이 많아 필요할 때 사용하므로 데이터 분석에 주로 활용된다.</p>
<h2 id="ebs-스냅샷">EBS 스냅샷</h2>
<p>EBS 스토리지의 대표적인 특징인 EBS 스냅샷 기능은 말 그대로 특정 시점에 포인트를 찍어서 그 시점으로 되돌아갈 수 있는 지점을 만드는 기능이다. 증분식 백업 방식을 이용하여 마지막 스냅샷 이후 변경되는 데이터 블록만 기록하고 복제하므로 저장 비용과 시간도 효과적으로 절감할 수 있다.</p>
<p>또한  매번 원본과 크기가  같지 않아도 변경된 부분만 증분되어 백업되기 때문에 특정 데이터를 삭제해도 어느 한 부분의 스냅샷만 가지고 있다면 복구할 수 있다. 스냅샷은 기본적으로 Amazon S3라는 스토리지 공간에 저장되어 여러 가용 영역에 자동으로 복제된다.</p>
<p><img src="https://velog.velcdn.com/images/urban-jungle/post/ac79722c-98ca-4446-81b1-8322a2313986/image.png" alt=""></p>
<h2 id="efs란">EFS란</h2>
<p>Amazon EFS(Elastic File System)는 클라우드 환경과 온프레미스 환경에서 사용할 수 있는 완전 관리형 네트워크 파일 시스템이다. 완전 관리형이란 클라우드에서 하드웨어 프로비저닝 유지 관리, 소프트웨어 구성, 모니터링, 복잡한 성능 조절 등 모든 것을 관리하기 때문에 사용자 입장에서는 별다른 관리가 필요 없다는 의미이다. 처음 파일 시스템을 생성한 후 서버에 연결하면 사용한 만큼 자동으로 스토리지 크기가 확장되고, 사용한 만큼만 비용을 지불하면 되기 때문에 사실상 용량 제한 없이 사용할 수 있다.</p>
<p><img src="https://velog.velcdn.com/images/urban-jungle/post/8b7cb74d-de0c-414b-9cf2-d5429b888867/image.png" alt=""></p>
<h2 id="efs-특징">EFS 특징</h2>
<p>EFS는 고성능 네트워크 파일 시스템으로, 여러 대의 컴퓨터가 네트워크상의 동일한 데이터에 접근해야 할 때 사용한다. NFS 표준 프로토콜 기반의 연결을 지원하고 있어 기존 다양한 애플리케이션과 유연하게 통합할 수 있고, 여러 컴퓨팅 인스턴스에서 동시에 사용할 수 있다. 또한 기존 NAS처럼 사용자 홈 디렉터리를 공유하여 애플리케이션을 개발하고, 테스트 환경의 다양한 웹 서비스와 콘텐츠 관리, 분석이나 미디어 업무에도 활용할 수 있다.</p>
<p>EFS 볼륨은 IOPS가 높고 용량이 매우 크기 때문에 처리량이 많고 대기 시간이 짧다. 또한 파일 시스템의 사용 증가에 따라 자동으로 용량 및 성능이 조정되는 탄력성을 제공하여 네트워크 스토리지의 용량 및 성능 부족을 걱정할 필요가 없다.</p>
<p>EFS는 EBS처럼 가용 영역 단위의 서비스가 아니라 가용 영역 전반에 걸쳐 사용할 수 있는 스토리지이므로, 가용 영역 장애를 고려한 디자인이 가능해서 전통적인 NAS보다 뛰어난 가용성을 가진다.</p>
<hr>
<h1 id="amazon-s3">Amazon S3</h1>
<h2 id="s3-소개">S3 소개</h2>
<p>Amazon S3는 AWS 서비스 중에서 EC2 서비스와 더불어 가장 오래되고, 기본이 되는 객체 스토리지 서비스이다. S3에 저장되는 데이터를 객체라고 하며, 이 객체 저장소를 버킷(bucket)이라고 한다. 그리고 객체에 대한 입출력은 HTTP 프로토콜로 하며, REST API를 이용하여 명령이 전달된다.</p>
<p>이 스토리지의 가장 큰 특징은 높은 내구성인데, 99.999%의 내구성으로 디자인되어 있어 데이터 손실을 최소화하도록 규정되어 있다. 또한 데이터 저장 공간이 거의 무제한에 가까워 특별한 용량 제한 없이 데이터를 저장할 수 있다. 필요한 경우 다양한 스토리지 계층으로 데이터를 분류하여 데이터 저장 비용을 절감할 수도 있다.</p>
<p>S3의 객체는 기본적으로 웹 접속이 가능하기 때문에 간단한 정적 웹 콘텐츠를 S3에 올려 웹 서버의 도움 없이 바로 웹 서비스가 가능하다. 그리고 S3는 보안 규정 준수 및 감시 기능을 제공하고 있어 데이터가 안전하게 저장되고 인증된 사용자만 접근할 수 있도록 구성한다. 필요한 경우 접근 권한 정책을 이용하여 해당 객체의 접근을 제어할 수 있다.</p>
<p><img src="https://velog.velcdn.com/images/urban-jungle/post/f283147f-0e79-4a9d-9a14-0350120ccacf/image.png" alt=""></p>
<h2 id="s3-구성-요소">S3 구성 요소</h2>
<ul>
<li>버킷: 데이터 스토리지를 위한 S3의 기본 컨테이너이다. 객체는 반드시 버킷에 저장되어야 하며, 하나의 리전에서 생성된 후에는 버킷 이름과 리전을 변경할 수 없다.</li>
<li>객체: S3에 저장되는 기본 매체로, 객체 데이터와 객체 메타데이터로 구성되어 있다. 메타데이터는 객체를 설명하는 이름-값에 대한 하나의 쌍으로 존재한다. 객체를 저장할 때 사용자 정의 메타데이터를 지정할 수 있으며, 객체는 키(이름) 및 버전 ID를 이용하여 버킷내에서 고유하게 식별된다.</li>
<li>키: 버킷 내에서 객체의 고유한 식별자이다. 버킷 내 모든 객체는 고유한 하나의 키를 갖게 되며, S3는 &#39;버킷 + 키 + 버전&#39;과 객체 사이의 기본 데이터 맵으로 생각할 수 있다.</li>
<li>S3 데이터 일관성: S3 버킷에 있는 객체에 대해 여러 서버로 데이터를 복제하여 고가용성 및 내구성을 구현하고 데이터 일관성 모델을 제공한다.</li>
</ul>
<h2 id="s3-특징">S3 특징</h2>
<p>Amazon S3는 객체에 대해 빠르고 내구성과 가용성이 높은 키 기반의 접근성을 제공하여 데이터의 저장 및 검색에 특화된 객체 스토리지이다.</p>
<p>S3는 하나의 리전 내 최소 세 개 이상의 물리적으로 분리된 가용 영역에 데이터를 복제해서 저장하므로 높은 내구성과 고가용성을 제공하며, 서버의 OS 도움 없이 객체별 접근이 가능하므로 데이터 저장 및 활용에 용이하다.</p>
<p>또한 Amazon S3는 동일 버킷 내 여러 개의 객체 변형을 보유하여 데이터 복구에 특화된 객체 스토리지이다. S3에 버전 관리 기능을 이용하면 버킷에 저장된 모든 버전의 객체를 보존하거나 검색 및 복원할 수 있으며, 의도하지 않은 사용자 작업 및 애플리케이션 장애에서 쉽게 복구될 수 있다.</p>
<h2 id="s3-스토리지-클래스">S3 스토리지 클래스</h2>
<p>S3는 여러 사용 사례에 맞게 설계된 다양한 스토리지 클래스를 제공한다. 여기에는 자주 접근하는 데이터를 저장하는 S3 standard와 알 수 없거나 변화하는 접근 패턴이 있는 데이터를 저장하는 S3 intelligent-tiering, 데이터 수명은 길지만 자주 접근하지 않는 데이터를 저장하는 S3 standard-IA 및 S3 one zone-IA, 데이터 수명이 제한되어 추후 삭제 예정인 데이터 및 백업을 위한 S3 glacier 등이 있다. 데이터 수명 주기에 따라 데이터를 관리할 수도 있다.</p>
<p>[AWS S3 스토리지 클래스의 종류 및 특징]</p>
<ul>
<li><p>standard: 가장 일반적인 스토리지 클래스이며, 데이터를 검색할 때 요금 및 최소 사용량에 제한 없이 사용한 만큼 비용을 지불하면 된다.</p>
</li>
<li><p>intelligent-tiering: 객체 접근 정보가 고정되어 있지 않을 때 자동으로 빈번한 접근 그룹과 간헐적 접근 그룹에 나누어서 저장한다.</p>
</li>
<li><p>infrequent access: 객체가 자주 사용되지는 않지만 조회가 필요할 때 사용되는 데이터를 저장하는 클래스이다. 두 개의 하위 클래스로 나뉜다.</p>
<ul>
<li>standard-infrequent access: 최소 세 개 이상의 가용 영역에 데이터가 저장되기 때문에 내구성이 높은 클래스이다.</li>
<li>one zone-infrequent access: 이름처럼 하나의 가용 영역에만 데이터가 저장되기 때문에 상대적으로 내구성이 낮고, 데이터가 삭제되어도 다시 생산할 수 있는 데이터를 위한 클래스이다.</li>
</ul>
</li>
<li><p>S3 glacier: 데이터 아카이브와 장기간 백업을 고려하여 만든 스토리지 클래스이다. 아카이빙 데이터는 오랫동안 데이터가 저장되어 있는 것을 의미하며, 이런 아카이빙 데이터에 접근하려면 많은 시간이 소요될 수 있다. 또한 데이터를 다른 클래스로 옮기려면 기가바이트당 비용이 발생하므로 주로 보관이 목적일 때 사용한다.</p>
</li>
<li><p>S3 glacier deep archive: 재사용이 거의 없는 데이터를 보관할 때 사용하는 클래스이다. 일정 기간이 지나면 삭제할 데이터를 주로 보관하며, 조회하는 데 수 시간에서 수일이 소요될 수 있다. 그 대신 데이터 보관 비용이 가장 저렴하므로 데이터 목적에 따라 매우 유용한 저장소가 될 수 있다.</p>
</li>
</ul>
<h2 id="s3-보안">S3 보안</h2>
<p>S3 버킷 접근은 일반적으로 버킷을 생성할 때 사용한 버킷 이름을 포함하여 생성된 유일한 식별자를 기반으로 언제, 어디에서든 접근이 가능하다. 그런 점에서 보안은 가장 중요한 부분이다. 그렇기 때문에 AWS의 자격 증명 서비스인 IAM(Identity and Access Management)과 밀접하게 연관되어 있고, IAM으로 접속 사용자나 데이터 접근을 관리할 수 있다. 특정 S3 버킷 접근에 대해 허용과 거부가 발생한다면 IAM에서 접근 권한을 통제하기 때문에 일어나는 상황이라고 이해하면 된다.</p>
<p>IAM으로 사용자 및 정책별 접근 권한을 제어할 수 있지만, 접근 권한이 있는 사용자가 개별 객체에 접근할 수 있게 하는 S3만의 버킷 정책으로 S3 버킷 내 모든 객체에 대한 권한을 조정할 수도 있다.</p>
<p>또한 쿼리를 요청할 때 쿼리 문자열을 인증하여 사용자 인증 정보도 함께 보낼 수 있는데, 해당 객체에 접근할 때 이 인증 정보로 일시적 허용 여부 권한을 이용할 수 있다. 대표적인 예가 임시 권한을 부여해서 접근하는 presign 기능이다.</p>
<p>다만 S3 객체는 기본적으로 외부 사용자가 접근할 수 없도록 설정되어 있다. 객체 소유자와 루트 사용자만 해당 객체에 접근할 수 있으며, 외부에서 접근하려면 별도의 정책을 이용하여 직접 설정해야 한다.</p>
<hr>
<p><img src="https://velog.velcdn.com/images/urban-jungle/post/f2eae9f6-0fe7-4510-b0fe-0fbd59102e3e/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[<프로그래머스 388352> 비밀 코드 해석 (C++)]]></title>
            <link>https://velog.io/@urban-jungle/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-388352-%EB%8C%80%EC%9E%A5%EA%B7%A0%EB%93%A4%EC%9D%98-%EC%9E%90%EC%8B%9D%EC%9D%98-%EC%88%98-%EA%B5%AC%ED%95%98%EA%B8%B0-C</link>
            <guid>https://velog.io/@urban-jungle/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-388352-%EB%8C%80%EC%9E%A5%EA%B7%A0%EB%93%A4%EC%9D%98-%EC%9E%90%EC%8B%9D%EC%9D%98-%EC%88%98-%EA%B5%AC%ED%95%98%EA%B8%B0-C</guid>
            <pubDate>Tue, 15 Apr 2025 14:33:25 GMT</pubDate>
            <description><![CDATA[<p><a href="https://school.programmers.co.kr/learn/courses/30/lessons/388352">https://school.programmers.co.kr/learn/courses/30/lessons/388352</a></p>
<p>Level:2</p>
<p>2025 프로그래머스 코드챌린지 1차 예선</p>
<hr>
<h4 id="문제-설명">문제 설명</h4>
<p>당신은 비밀 조직의 보안 시스템을 뚫고 중요한 정보를 해독해야 합니다. 시스템은 1부터 n까지의 서로 다른 정수 5개가 오름차순으로 정렬된 비밀 코드를 가지고 있으며, 당신은 이 비밀 코드를 맞혀야 합니다.</p>
<p>당신은 비밀 코드를 알아내기 위해 암호 분석 도구를 사용하며, m번의 시도를 할 수 있습니다. 각 시도마다 서로 다른 5개의 정수를 입력하면, 시스템은 그 중 몇 개가 비밀 코드에 포함되어 있는지 알려줍니다.</p>
<ul>
<li>만약 비밀 코드가 [3, 5, 7, 9, 10]이고, 입력한 정수가 [1, 2, 3, 4, 5]라면 비밀 코드에 포함된 정수는 3, 5 두 개이므로 시스템은 2를 응답합니다.</li>
</ul>
<p>당신은 m번의 시도 후, 비밀 코드로 가능한 정수 조합의 개수를 알고 싶습니다.</p>
<p>비밀 코드에 사용된 정수의 범위가 1~10일 때, 아래와 같이 5번의 시도를 했다고 가정해 보겠습니다.</p>
<p><img src="https://velog.velcdn.com/images/urban-jungle/post/667c3c87-2880-4c85-8215-2ed9cbb47ce6/image.png" alt=""></p>
<p>비밀 코드로 가능한 정수 조합은 아래와 같이 3개가 있습니다.</p>
<ul>
<li><p>[3, 4, 7, 9, 10]</p>
<ul>
<li>첫 번째 시도에서 비밀 코드에 포함된 정수가 3, 4로 2개 있습니다.</li>
<li>두 번째 시도에서 비밀 코드에 포함된 정수가 7, 9, 10으로 3개 있습니다.</li>
<li>세 번째 시도에서 비밀 코드에 포함된 정수가 3, 7, 9, 10으로 4개 있습니다.</li>
<li>네 번째 시도에서 비밀 코드에 포함된 정수가 7, 9, 10으로 3개 있습니다.</li>
<li>다섯 번째 시도에서 비밀 코드에 포함된 정수가 3, 4, 7로 3개 있습니다.</li>
</ul>
</li>
<li><p>[3, 5, 7, 8, 9]</p>
<ul>
<li>첫 번째 시도에서 비밀 코드에 포함된 정수가 3, 5로 2개 있습니다.</li>
<li>두 번째 시도에서 비밀 코드에 포함된 정수가 7, 8, 9로 3개 있습니다.</li>
<li>세 번째 시도에서 비밀 코드에 포함된 정수가 3, 7, 8, 9로 4개 있습니다.</li>
<li>네 번째 시도에서 비밀 코드에 포함된 정수가 5, 7, 9로 3개 있습니다.</li>
<li>다섯 번째 시도에서 비밀 코드에 포함된 정수가 3, 5, 7로 3개 있습니다.</li>
</ul>
</li>
<li><p>[3, 5, 7, 8, 10]</p>
<ul>
<li>첫 번째 시도에서 비밀 코드에 포함된 정수가 3, 5로 2개 있습니다.</li>
<li>두 번째 시도에서 비밀 코드에 포함된 정수가 7, 8, 10으로 3개 있습니다.</li>
<li>세 번째 시도에서 비밀 코드에 포함된 정수가 3, 7, 8, 10으로 4개 있습니다.</li>
<li>네 번째 시도에서 비밀 코드에 포함된 정수가 5, 7, 10으로 3개 있습니다.</li>
<li>다섯 번째 시도에서 비밀 코드에 포함된 정수가 3, 5, 7로 3개 있습니다.</li>
</ul>
</li>
</ul>
<p>정수 n, 입력한 정수를 담은 2차원 정수 배열 q와 시스템 응답을 담은 1차원 정수 배열 ans가 매개변수로 주어집니다. 이때, 비밀 코드로 가능한 정수 조합 개수를 return 하도록 solution 함수를 완성해 주세요.</p>
<hr>
<h4 id="제한사항">제한사항</h4>
<ul>
<li>10 ≤ n ≤ 30</li>
<li>1 ≤ (q의 길이 = m) ≤ 10<ul>
<li>q[i]의 길이 = 5</li>
<li>q[i]는 i+1번째 시도에서 입력한 5개의 서로 다른 정수를 담고 있으며, 오름차순으로 정렬되어 있습니다.</li>
<li>1 ≤ q[i][j] ≤ n</li>
</ul>
</li>
<li>ans의 길이 = m<ul>
<li>ans[i]는 i+1번째 시도에서 입력한 5개의 정수 중 비밀 코드에 포함된 정수의 개수를 나타냅니다.</li>
<li>0 ≤ ans[i] ≤ 5</li>
</ul>
</li>
<li>비밀 코드가 존재하지 않는(답이 0인) 경우는 주어지지 않습니다.</li>
</ul>
<hr>
<h4 id="입출력-예">입출력 예</h4>
<p><img src="https://velog.velcdn.com/images/urban-jungle/post/09fa59d3-0ed5-4674-b11a-66eb51a82c62/image.png" alt=""></p>
<hr>
<pre><code>#include &lt;string&gt;
#include &lt;vector&gt;
#include &lt;algorithm&gt;
#include &lt;bitset&gt;
#include &lt;numeric&gt;

using namespace std;

int solution(int n, vector&lt;vector&lt;int&gt;&gt; q, vector&lt;int&gt; ans){
    int answer = 0;

    vector&lt;bitset&lt;31&gt;&gt; qbit;
    for (auto&amp; v : q){
        bitset&lt;31&gt; b;
        for (int x : v){
            b.set(x);
        }
        qbit.push_back(b);
    }

    vector&lt;int&gt; nums(n);
    iota(nums.begin(), nums.end(), 1);

    vector&lt;int&gt; mask(n, 0);
    fill(mask.end() - 5, mask.end(), 1);

    do{
        bitset&lt;31&gt; cand;
        for (int i = 0; i &lt; n; ++i){
            if (mask[i]){
                cand.set(nums[i]);
            }
        }

        bool valid = true;
        for (int i = 0; i &lt; q.size(); ++i){
            int match = (cand &amp; qbit[i]).count();
            if (match != ans[i]){
                valid = false;
                break;
            }
        }

        if (valid){
            answer++;
        }

    }while (next_permutation(mask.begin(), mask.end()));

    return answer;
}</code></pre><hr>
<p>아아.. 알고리즘 문제를 너무 오랫동안 놓고 있어서 그런지 안풀려서 검색하면서 풀었다.
이 코드는 <code>bitset</code>, <code>next_permutation</code>, <code>iota</code>, <code>fill</code> 등의 함수를 사용하여 풀었다.</p>
<h4 id="qbit에-대한-설명">qbit에 대한 설명</h4>
<p><code>vector&lt;bitset&lt;31&gt;&gt; qbit;</code> → 비어 있는 bitset들이 들어갈 예정이고,
각 bitset은 1부터 30까지의 정수를 표현할 수 있도록 31비트로 설정했다.</p>
<h4 id="b의-구성">b의 구성</h4>
<p>for문을 돌면서 <code>b</code>는 31개의 0으로 채워지고, 이중 for문을 돌면서 <code>b</code>에 <code>q[i]</code>의 원소들이 set된다. 여기서 <code>set</code>은 <code>bitset</code>의 <code>.set()</code> 메서드이고, C++ STL의 <code>std::set</code>이 아니다. 
예를 들어 <code>q[i] = {3, 5, 9, 13, 25}</code> 라면, <code>b.set(3), b.set(5)</code> 등을 통해 해당 비트만 1이 된다.</p>
<h4 id="nums는-iota로-1부터-n까지">nums는 iota로 1부터 n까지</h4>
<p><code>iota</code>는 연속된 숫자로 채워주는 함수이다. 
<code>iota(nums.begin(), nums.end(), 1);</code> → <code>1, 2, ..., n</code></p>
<h4 id="mask는-끝-5개가-1">mask는 끝 5개가 1</h4>
<p><code>fill(mask.end() - 5, mask.end(), 1);</code> → 조합 5개를 고르는 마스크 역할이다.
<code>mask</code>의 끝 5개가 1로 채워진다. (나머지는 0)</p>
<h4 id="cand는-mask에-따라-채워짐">cand는 mask에 따라 채워짐</h4>
<p><code>mask[i] == 1</code> → <code>nums[i]를 선택</code> → <code>cand.set(nums[i]);</code></p>
<h4 id="cand--qbiti의-의미">cand &amp; qbit[i]의 의미</h4>
<p><code>bitset &amp; bitset</code> → 공통으로 1인 비트들만 남기고
<code>.count()</code> → 1의 개수를 세어줌 → 즉, <code>candidate</code>와 <code>q[i]</code>가 몇 개 겹치는지 알려주는 역할</p>
<h4 id="ans와-다르면-제외">ans와 다르면 제외</h4>
<p>이 조건을 m번의 시도 모두 통과한 조합만 정답으로 인정해서 <code>answer++</code> 해준다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[CAB TA 4기 25일차의 기록]]></title>
            <link>https://velog.io/@urban-jungle/CAB-TA-4%EA%B8%B0-25%EC%9D%BC%EC%B0%A8%EC%9D%98-%EA%B8%B0%EB%A1%9D</link>
            <guid>https://velog.io/@urban-jungle/CAB-TA-4%EA%B8%B0-25%EC%9D%BC%EC%B0%A8%EC%9D%98-%EA%B8%B0%EB%A1%9D</guid>
            <pubDate>Tue, 15 Apr 2025 07:37:18 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/urban-jungle/post/008332b2-78e1-4a71-a027-75ef7706af35/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/urban-jungle/post/596505cf-38c7-4087-898b-231f3be1d212/image.png" alt=""></p>
<hr>
<h1 id="네트워킹이란">네트워킹이란</h1>
<h2 id="네트워킹-정의">네트워킹 정의</h2>
<p>네트워킹은 &#39;서로 연결한다&#39;는 뜻으로, 서로 간에 의사소통을 하는 환경이다.</p>
<h2 id="네트워킹-요소">네트워킹 요소</h2>
<p><img src="https://velog.velcdn.com/images/urban-jungle/post/21bd12cd-1b6c-4e69-bdc1-5aee1252a1be/image.png" alt=""></p>
<p>국제표준화기구(ISO)에서 개발한 OSI 7계층 모델로, 네트워킹 통신 구조를 계층 일곱 개로 분류하는 방식이다.</p>
<h3 id="ip-주소와-서브넷">IP 주소와 서브넷</h3>
<h4 id="ip-주소">IP 주소</h4>
<p>IP(Internet Protocol) 주소는 인터넷상에서 IT 자원을 식별하는 고유한 주소이다. IP 버전에는 IPv4와 IPv6 두 가지가 있으며, 일반적으로 IPv4를 더 많이 사용한다.</p>
<h4 id="퍼블릭-ip-주소와-프라이빗-ip-주소">퍼블릭 IP 주소와 프라이빗 IP 주소</h4>
<p>퍼블릭 IP 주소는 실제 인터넷에서 사용하려고 인터넷 서비스 공급자(ISP)에서 제공하는 유일한 공인 IP 주소이다. 반면 프라이빗 IP 주소는 인터넷이 아닌 독립된 네트워크 내부에서만 사용하려고 네트워크 관리자가 제공하는 사설 IP 주소이다.</p>
<p>[프라이빗 IP 주소]</p>
<ul>
<li>클래스 A: 10.0.0.0 ~ 10.255.255.255</li>
<li>클래스 B: 172.16.0.0 ~ 172.31.255.255</li>
<li>클래스 C: 192.168.0.0 ~ 192.168.255.255</li>
</ul>
<h4 id="고정-ip-주소와-유동-ip-주소">고정 IP 주소와 유동 IP 주소</h4>
<p>IP 주소는 할당하는 방식에 따라 고정 IP 주소와 유동 IP 주소로 분류된다. 고정 IP 주소는 네트워크 관리자가 수동으로 할당하는 방식이며, 유동 IP 주소는 특정 서버가 IP 주소 범위에 따라 동적으로 할당하는 방식이다.</p>
<p>유동 IP 주소는 DHCP(Dynamic Host Configuration Protocol) 프로토콜을 통해 주소를 제공하는 서버와 주소를 할당받는 클라이언트로 구성되며, IP 주소를 임대(lease)하는 형태를 취한다.</p>
<p>[DHCP 프로토콜 메세지]</p>
<ul>
<li>DHCP Discover: DHCP 클라이언트에서 DHCP 서버를 찾는 메시지</li>
<li>DHCP Offer: DHCP 서버에서 할당할 IP 주소와 임대 시간을 알리는 메시지</li>
<li>DHCP Request: DHCP 클라이언트에서 DHCP 서버로 할당받을 IP 주소를 요청하는 메시지</li>
<li>DHCP Ack: DHCP 서버에서 최종적으로 할당할 IP 주소 승인을 알리는 메시지</li>
</ul>
<h4 id="서브넷과-서브넷-마스크">서브넷과 서브넷 마스크</h4>
<p>모든 네트워크는 하나의 네트워크로만 구성되어 있지 않다. 주체와 목적에 따라 부분 네트워크로 나뉘고, 서로 연결하여 거대한 네트워크 환경을 이루고 있다. 여기에서 서브넷(subnet)은 부분 네트워크를 의미하며, 다양한 서브넷이 연결되어 거대한 네트워크 환경을 이루고 있다고 이해하면된다. 서브넷을 구분하고 식별할 때 사용하는 것이 서브넷 마스크(subnet mask)이다.</p>
<h4 id="라우팅과-라우터">라우팅과 라우터</h4>
<p><img src="https://velog.velcdn.com/images/urban-jungle/post/70fa66cd-c981-423e-a52f-accb745fb612/image.png" alt=""></p>
<h4 id="tcp와-udp">TCP와 UDP</h4>
<p><strong>TCP</strong>
송수신 대상 간 연결을 맺고 데이터 전송 여부를 하나씩 확인하며 전송하는 연결형 프로토콜로, 신뢰성 있는 데이터 전송을 보장한다.</p>
<p><strong>UDP</strong>
TCP와 반대로 송수신 대상 간 연결 없이 전달하는 비연결형 프로토콜이다.</p>
<p><strong>포트 번호</strong>
TCP와 UDP를 사용하는 응용서비스는 서로 구분할 수 있도록 포트 번호를 사용한다. 이런 포트 번호는 IANA(Internet Assigned Numbers Authority)라는 인터넷 할당 번호 관리 기관에서 정의한다.</p>
<ul>
<li>잘 알려진 포트 번호(well-known port): 0~1023</li>
<li>등록된 포트 번호(registered port): 1024~49151</li>
<li>동적 포트(dynamic port): 49152~65535</li>
</ul>
<hr>
<h1 id="aws-네트워킹-소개">AWS 네트워킹 소개</h1>
<p>AWS 네트워킹 서비스는 AWS 글로벌 인프라에서 생성된 다양한 자원의 워크로드를 수행하는 네트워킹 서비스이다.</p>
<h2 id="aws-리전-네트워킹-디자인">AWS 리전 네트워킹 디자인</h2>
<p>리전은 전 세계 주요 도시의 데이터 센터를 군집화(clustering)하는 물리적인 위치를 의미한다. AWS 리전 내부에는 트랜짓 센터(transit center)와 가용 영역이 서로 연결되어 네트워크 환경을 이루고 있으며, 네트워킹 측면으로 어떤 대상과 연결되었는지에 따라 다음과 같이 분류할 수 있다.</p>
<h3 id="intra-az-연결">Intra-AZ 연결</h3>
<p>리전 내부에는 논리적인 데이터 센터의 집합인 가용 영역이 여럿 존재한다. 가용 영역에 존재하는 데이터 센터들은 고밀도 광섬유 케이블을 사용하여 100GE 또는 400GE(Gigabit Ethernet)로 상호 연결되어 네트워킹 환경을 구성한다. 이런 데이터 센터 간 연결을 Intra-AZ 연결(connection)이라고 한다.</p>
<h3 id="inter-az-연결">Inter-AZ 연결</h3>
<p>리전 내부에 위치하는 가용 영역은 실제 100km(서로 60마일 간격) 이내로 떨어져 있다. 이렇게 물리적으로 거리를 두는 이유는 정전이나 자연재해 같은 문제에 가용성을 유지하기 위함이다. 또한 AWS 클라우드 자원을 다수의 가용 영역에서 실행하도록 설계하여 내결함성을 강화할 수 있다. 지리적으로 떨어져 있는 가용 영역끼리 연결되어 네트워킹 환경을 구성하고 있으며, 이런 가용 영역 간 연결을 Inter-AZ 연결(connection)이라고 한다.</p>
<h3 id="트랜짓-센터">트랜짓 센터</h3>
<p>리전에서 외부 인터넷 구간과 통신이 필요할 때는 트랜짓 센터를 통해 통신한다. 내부에 있는 가용 영역들은 외부 인터넷 통신을 위해 트랜짓 센터와 연결되어 네트워킹 환경을 구성하며, 이런 가용 영역 간 연결을 트랜짓 센터 연결(transit center connection)이라고 한다.</p>
<h2 id="aws-글로벌-네트워크와-엣지-pop">AWS 글로벌 네트워크와 엣지 POP</h2>
<p>엣지 POP(edge Point Of Presence)는 AWS 글로벌 네트워크라는 전용망을 활용하여 안정적으로 고성능 서비스를 제공하는 센터이다. 엣지 POP을 통해 사용자에게 글로벌 서비스 콘텐츠를 빠르게 제공할 수 있다.
엣지 POP은 엣지 로케이션(edge location)과 리전별 엣지 캐시(regional edge cache)로 구성되며, 전 세계 300개 이상의 엣지 로케이션과 13개의 리전별 엣지 캐시가 서로 연결된 AWS 글로벌 네트워크를 구성하고 있다.</p>
<p><img src="https://velog.velcdn.com/images/urban-jungle/post/c425bdf9-f26b-4f43-8d9c-15fc29cb1692/image.png" alt=""></p>
<p>엣지 POP이 속해 있는 AWS 백본 네트워크는 AWS 글로벌 네트워크와 연결되어 있으며, 모든 리전(중국 리전 제외)은 백본 네트워크를 중심으로 서로 연결되어 있다.</p>
<h2 id="aws-네트워킹-서비스">AWS 네트워킹 서비스</h2>
<p>AWS의 다양한 자원이 서로 원활하게 통신할 수 있도록 도와주는 것이 바로 AWS 네트워킹 서비스이다.</p>
<p>대표적인 AWS 네트워킹 서비스를 정리해보면 다음과 같다.</p>
<ul>
<li>VPC: 사용자 전용 가상의 프라이빗 클라우드 네트워크로, 네트워크 자원을 탄력적으로 활용하는 서비스를 제공한다.</li>
<li>Transit Gateway: 중앙 허브 개념처럼 VPC와 온프레미스 네트워크를 연결하는 게이트웨이 역할의 서비스를 제공한다.</li>
<li>Route 53: AWS에서 제공하는 관리형 DNS 서비스로 도메인 등록, 라우팅, 상태 확인 등 서비스를 제공한다.</li>
<li>Global Accelerator: AWS 글로벌 네트워크를 통해 애플리케이션을 빠르고 안정적으로 사용할 수 있도록 가용성 및 성능을 보장하는 서비스를 제공한다.</li>
<li>Direct Connect: 온프레미스 환경에서 AWS의 전용 네트워크 연결 서비스를 제공한다.</li>
<li>Site-to-Site VPN: IPsec VPN 연결을 생성하여 암호화된 네트워크를 구성하는 서비스를 제공한다.</li>
</ul>
<hr>
<h1 id="amazon-vpc">Amazon VPC</h1>
<h2 id="amazon-vpc-기본-구성-요소">Amazon VPC 기본 구성 요소</h2>
<h3 id="리전과-vpc">리전과 VPC</h3>
<p>Amazon VPC는 리전마다 독립적으로 구성되어 있다. 예를 들어 서울 리전에 VPC를 생성했다면 생성한 VPC는 서울 리전에만 있으며, 다른 리전에는 없다. 또한 리전 내에는 다수의 VPC를 생성할 수 있으며, 각 VPC는 서로 독립적으로 분리된다. 이런 측면에서 사용자는 어느 리전에 VPC를 생성할지 미리 계획해야 한다.</p>
<h3 id="서브넷과-가용-영역">서브넷과 가용 영역</h3>
<p>Amazon VPC라는 하나의 독립된 클라우드 네트워크에도 서브넷을 이용하여 분리된 네트워크로 구성할 수 있다. 서브넷은 VPC 내 별도로 나누어진 네트워크라고 생각하면 된다. 또한, 서브넷은 반드시 하나의 가용 영역에 종속적으로 위치한다.</p>
<p>서브넷은 VPC 네트워크 환경 구성에 따라 <strong>퍼블릭 서브넷</strong>과 <strong>프라이빗 서브넷</strong>으로 분리할 수 있다. 퍼블릭 서브넷은 인터넷 구간과 연결되어 있어 외부 인터넷 통신이 가능한 네트워크 영역이고, 프라이빗 서브넷은 인터넷 구간과 연결되지 않은 폐쇄적인 네트워크 영역이다.</p>
<h3 id="ip-cidr">IP CIDR</h3>
<p>IP CIDR은 네트워크에 할당할 수 있는 IP 주소 범위를 표현하는 방법이다. Amazon VPC는 내부에 생성할 서브넷의 IP 주소 범위를 할당하기 위해 IP CIDR을 가지고 있으며, VPC 내 생성된 서브넷도 VPC의 IP CDIDR에서 분할된 IP CIDR을 가지고 있다. 즉, VPC라는 큰 네트워크의 IP CIDR에서 서브넷이라는 작은 네트워크의 IP CIDR이 분할되어 있다. 결론적으로, 서브넷에 생성되는 자원은 IP CIDR 범위 안에 있는 IP 주소를 할당받을 수 있다.</p>
<h3 id="가상-라우터와-라우팅-테이블">가상 라우터와 라우팅 테이블</h3>
<p><img src="https://velog.velcdn.com/images/urban-jungle/post/1f824f30-90bd-47dd-9068-799e725f859b/image.png" alt=""></p>
<p>Amazon VPC를 생성하면 기본적으로 네트워크 경로를 확인하여 트래픽을 전달하는 목적의 가상 라우터가 생성된다. 이렇게 생성된 가상 라우터는 기본 라우팅 테이블을 보유하고 있으며, 라우팅 테이블을 통해 네트워크 경로를 식별할 수 있다. 물론 기본 라우팅 테이블 외에 별도의 라우팅 테이블을 생성할 수 있고, 생성된 라우팅 테이블은 서브넷과 연결(attach)하여 서브넷마다 라우팅 테이블을 가질 수도 있다.</p>
<p>라우팅 테이블은 목적지 대상의 IP CIDR 블록과 타깃 대상으로 구성되어 있다. 참고로 타깃 대상에서 로컬은 VPC 내부 간 통신을 의미하며, 특수한 목적을 수행하는 인터넷 게이트웨이나 NAT 게이트웨이 등을 타깃 대상으로 지정할 수 있다.</p>
<h3 id="보안-그룹과-네트워크-acl">보안 그룹과 네트워크 ACL</h3>
<p>Amazon VPC는 보안 그룹(security group)과 네트워크 ACL(Access Control List) 같은 가상의 방화벽(firewall) 기능을 제공하여 서브넷과 생성된 자원에 대한 트래픽을 보호한다. 트래픽 접근을 통제하는 것이 주된 목적이며 IP CIDR 블록, 프로토콜, 포트 번호 등을 정의하여 허용(allow)과 거부(deny)를 결정하는 보안 규칙을 만든다. 가상의 방화벽을 기준으로 들어오는 인바운드(inbound) 규칙과 빠져나가는 아웃바운드(outbound) 규칙이 있기 때문에 트래픽 흐름을 고려한 보안 규칙을 세워야 한다.</p>
<p>보안 그룹과 네트워크 ACL은 송수신 트래픽의 접근을 통제한다는 점에서 서로 같지만, 차이점이 있다. 차이점은 크게 3가지로 나뉜다.</p>
<h4 id="트래픽-접근-제어-대상">트래픽 접근 제어 대상</h4>
<p>보안 그룹과 네트워크 ACL의 가장 큰 차이점은 접근 제어 대상이 서로 다르다는 것이다. 보안 그룹은 인스턴스와 같은 자원 접근을 제어하며, 네트워크 ACL은 서브넷 접근을 제어한다.</p>
<p><img src="https://velog.velcdn.com/images/urban-jungle/post/5fb6ac0a-a54b-4cab-be0c-a93be1f2fa58/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/urban-jungle/post/2df14af4-ee35-45ce-877d-b77b1e698fe3/image.png" alt=""></p>
<h4 id="스테이트풀과-스테이트리스">스테이트풀과 스테이트리스</h4>
<p>보안 그룹은 이전 상태 정보를 기억하고 다음에 그 상태를 활용하는 스테이트풀(stateful) 접근 통제를 수행하며, 네트워크 ACL은 이전 상태 정보를 기억하지 않아 다음에 그 상태를 활용하지 않는 스테이트리스(stateless) 접근 통제를 수행한다.</p>
<p><img src="https://velog.velcdn.com/images/urban-jungle/post/f45702f0-4818-4c9b-9c89-e9edc8dfcbc0/image.png" alt=""></p>
<p>보안 그룹의 스테이트풀 동작을 보면 인바운드 규칙에 따라 트래픽을 허용한 경우 정보를 기억하고 아웃바운드 규칙에 상관없이 자동으로 접근이 허용된다. 반대로 네트워크 ACL의 스테이트리스 동작을 보면 인바운드 규칙에 따라 트래픽을 허용했어도 아웃바운드 규칙으로 트래픽 허용 여부를 판단한다.</p>
<h4 id="허용-및-거부-정책">허용 및 거부 정책</h4>
<p>보안 그룹의 정책 테이블은 허용 규칙만 나열하며 허용 규칙에 해당하지 않으면 자동 거부된다. 반면 네트워크 ACL의 정책 테이블은 허용 규칙과 거부 규칙이 모두 존재하여 규칙을 순차적으로 확인하고 허용과 거부를 판단한다. 네트워크 ACL에도 모든 규칙이 매칭되지 않으면 거부하는 규칙이 기본적으로 있다.</p>
<hr>
<h2 id="amazon-vpc와-다른-네트워크-연결">Amazon VPC와 다른 네트워크 연결</h2>
<h3 id="인터넷-게이트웨이">인터넷 게이트웨이</h3>
<p>Amazon VPC는 프라이빗 클라우드 네트워크 환경으로, 외부 인터넷 구간과 연결되지 않은 독립적인 네트워크이다. 인터넷 게이트웨이는 VPC와 인터넷 구간의 논리적인 연결이자 인터넷으로 나가는 관문이 되는 네트워킹 자원이다.</p>
<p>퍼블릭 서브넷은 외부 인터넷 통신이 가능한 네트워크이다. 서브넷의 라우팅 테이블에서 외부 인터넷으로 나가는 타깃 대상을 인터넷 게이트웨이로 지정하여 퍼블릭 서브넷 환경을 만든다.</p>
<h3 id="nat-게이트웨이">NAT 게이트웨이</h3>
<p>NAT 게이트웨이(Network Address Translation gateway)는 프라이빗 서브넷에서 외부 인터넷으로 통신하는 관문 역할을 한다. NAT는 IP 주소를 변환하는 기능을 제공하며, 프라이빗 IP 주소를 퍼블릭 IP 주소로 변환하여 외부 인터넷 구간 통신 환경을 만든다.
프라이빗 서브넷은 외부 인터넷 구간과 단절된 독립된 네트워크이지만 외부 인터넷 구간과 통신이 필요할 때는 NAT 게이트웨이를 통해 프라이빗 IP 주소를 퍼블릭 IP 주소로 변환하여 외부 인터넷 구간과 통신할 수 있다.</p>
<h3 id="vpc-피어링">VPC 피어링</h3>
<p>VPC 피어링은 서로 다른 VPC를 연결하는 기능이다. 동일 리전뿐만 아니라 다른 리전에 위치한 VPC와 연결할 수도 있고, 다른 계정에 위치한 VPC까지 연결할 수 있다.
VPC 피어링으로 연결할 경우 IP CIDR 블록이 중복되면 연결이 불가능한 제약이 있어 VPC 피어링으로 클라우드 네트워크를 확장할 때는 IP 주소 대역을 반드시 점검해야 한다.</p>
<h3 id="전송-게이트웨이">전송 게이트웨이</h3>
<p>전송 게이트웨이(transit gateway)는 다수의 VPC나 온프레미스를 단일 지점으로 연결하는 중앙 집중형 라우터이다. 단일 지점 연결이라 네트워크 구성이 간소화되고 비용도 절감되는 효과가 있다.</p>
<h3 id="가상-프라이빗-게이트웨이">가상 프라이빗 게이트웨이</h3>
<p>가상 프라이빗 게이트웨이(virtual private gateway)는 관리형 AWS Site-to-Site VPN을 연결하거나 AWS Direct Connect로 온프레미스 환경을 연결한다.</p>
<h2 id="amazon-vpc-요금">Amazon VPC 요금</h2>
<p>기본적으로 Amazon VPC를 사용하면서 요금은 발생하지 않지만, VPC 기능 중 일부는 요금이 발생할 수 있다.
NAT 게이트웨이는 최초 프로비저닝한 후 시간에 따른 요금이 부과되며, 기가바이트 단위로 데이터 처리 요금도 부과된다. 실습을 진행할 때는 기가바이트 단위의 데이터가 발생하지 않아 문제가 되지는 않지만, 시간에 따른 요금이 발생하는 것은 불가피하다.</p>
<hr>
<h1 id="amazon-elb-기능">Amazon ELB 기능</h1>
<h2 id="부하분산이란">부하분산이란</h2>
<p>부하분산은 서버-클라이언트 환경에서 서버가 클라이언트 요청을 받아 처리하는 과정에서 발생하는 부하(연산 작업)에 대해 동일한 목적을 수행하는 다수의 서버에 분산 처리하는 기능이다. 이런 부하분산을 <strong>로드 밸런싱</strong>(load balancing)이라고 하며, 부하분산을 수행하는 대상을 <strong>로드 밸런서</strong>(load balancer)라고 한다.</p>
<p><img src="https://velog.velcdn.com/images/urban-jungle/post/43c54805-5f55-40f1-9579-e59c5ce9f511/image.png" alt=""></p>
<h2 id="amazon-elb-기능-1">Amazon ELB 기능</h2>
<p>AWS에서는 ELB(Elastic Load Balancing)라는 로드 밸런싱 기술을 제공한다. ELB는 Amazon EC2 인스턴스에서 운영 중인 애플리케이션, 마이크로서비스 또는 컨테이너 서비스로 유입되는 트래픽을 자동 분산처리하는 기술이다. EBLB는 애플리케이션 가용성을 향상시키고 HTTP, HTTPS, TCP, SSL 등 다양한 프로토콜을 지원하며 사용자가 같은 인스턴스에서 세션을 유지할 수 있도록 지원한다. 또한 AWS의 CloudWatch 기능을 이용하여 로그와 메트릭을 모니터링할 수 있으며, AWS의 오토 스케일링 기능과 결합해서 트래픽이 증가할 때 자동으로 인스턴스를 추가하거나 제거하면서 애플리케이션 가용성을 유지한다.</p>
<p><img src="https://velog.velcdn.com/images/urban-jungle/post/434d655d-1652-49b1-9a70-18cbf181f003/image.png" alt=""></p>
<h2 id="amazon-elb-구성-요소">Amazon ELB 구성 요소</h2>
<ul>
<li><p><strong>로드 밸런서</strong>: 여러 대의 EC2 인스턴스, IP 주소, 람다 등을 사용하여 트래픽을 대상 그룹에 있는 인스턴스로 분산시켜 애플리케이션의 가용성을 유지하는 역할을 한다. 로드 밸런서는 사용자 요청을 받아 애플리케이션 서버로 전달하고, 애플리케이션 서버의 응답을 사용자에게 반환한다.</p>
</li>
<li><p><strong>대상 그룹</strong>: 로드 밸런서에서 분산할 대상의 집합을 정의하는 구성요소이다. 대상 그룹의 인스턴스에 대해 정적 또는 동적으로 구성할 수 있으며, 라우팅 규칙에 따라 요청을 받아들일 대상 그룹을 선택한다. 로드 밸런서는 대상 그룹에 포함된 대상들의 상태를 정기적으로 확인하여 장애 발생 대상을 자동으로 제외하고, 정상적으로 동작하는 대상에만 요청을 전달한다.</p>
</li>
<li><p><strong>리스너</strong>: 로드 밸런서에서 사용할 포트와 프로토콜을 설정하는 구성 요소이다. 리스너는 로드 밸런서에서 클라이언트 요청을 수신하고, 해당 요청을 처리할 대상 그룹을 선택하는 역할을 한다. 리스너는 로드 밸런서에 연결된 프로토콜과 포트를 사용하여 클라이언트 요청을 수신하고, 해당 요청을 대상 그룹으로 라우팅한다.</p>
</li>
</ul>
<h2 id="amazon-elb-동작-방식">Amazon ELB 동작 방식</h2>
<p>Amazon ELB를 생성하면 설정한 가용 영역별로 로드 밸런서 노드가 생성되고 앞단에 리스너를 실행한다. 이런 리스너는 다양한 프로토콜을 지원하며, 요청에 대한 대상 그룹의 라우팅을 정의한다. 이에 따라 로드 밸런서는 가용 영역에 속한 대상 그룹의 인스턴스로 트래픽을 전달한다.</p>
<p><img src="https://velog.velcdn.com/images/urban-jungle/post/f64b1a86-6b81-426b-bb98-9ba427c8c751/image.png" alt=""></p>
<ol>
<li><p><strong>클라이언트 요청 수신</strong>: 로드 밸런서에서 클라이언트 요청을 수신한다. 로드 밸런서는 클라이언트와 연결을 유지하며, 요청을 수신하려고 리스너를 등록한다.</p>
</li>
<li><p><strong>대상 그룹 선택</strong>: 수신한 클라이언트 요청을 처리할 대상 그룹을 선택한다. 대상 그룹은 인스턴스, IP 주소, 람다 함수, ALB 등 여러 유형의 대상으로 구성된다.</p>
</li>
<li><p><strong>트래픽 분산</strong>: 선택된 대상 그룹에서 요청을 처리할 대상을 선택하고 해당 대상으로 요청을 분산한다. 이때 로드 밸런서는 각 대상의 가용성 상태를 모니터링하고 가용하지 않은 대상을 제외한다.</p>
</li>
<li><p><strong>응답 반환</strong>: 분산된 요청을 대상에서 처리하고 클라이언트에 응답을 반환한다. 이때 응답은 로드 밸런서에서 수신한 것으로 반환되므로, 클라이언트는 로드 밸런서가 대상 그룹에서 선택한 대상에게서 마치 응답을 받는 것처럼 느낄 수 있다.</p>
</li>
</ol>
<p>[ELB 생성 시 로드 밸런서와 통신하는 방식]</p>
<ul>
<li><p>인터넷 경계 로드 밸런서: 외부에서 직접 로드 밸런서에 접근하는 방식</p>
</li>
<li><p>내부 로드 밸런서: 외부의 접근이 차단된 격리된 네트워크(내부 서버 전용)에서 로드 밸런서를 사용하는 방식</p>
</li>
</ul>
<h2 id="amazon-elb-교차-영역-로드-밸런싱">Amazon ELB 교차 영역 로드 밸런싱</h2>
<p>Amazon ELB는 여러 가용 영역에서 로드 밸런서 노드를 실행하며, 각 노드는 가용 영역 내 대상 그룹으로 요청을 분산한다. 이때 대상 그룹에 등록된 대상이 여러 가용 영역에 걸쳐 있다면 기본적으로 로드 밸런서는 동일한 비중으로 가용 영역 내에 있는 대상으로 트래픽을 분산한다. 이는 대상 그룹의 가용성을 높이는 방법이라 유용하지만, 가용 영역 내 인스턴스 수량이 불균형할 때는 일부 인스턴스로 트래픽이 몰리고 다른 인스턴스는 유휴 상태가 되는 불균형 처리 문제가 발생할 수 있다.</p>
<h4 id="교차-영역-로드-밸런싱-비활성화">교차 영역 로드 밸런싱 비활성화</h4>
<p><img src="https://velog.velcdn.com/images/urban-jungle/post/45460c1d-2510-458d-9190-439c124d8a81/image.png" alt=""></p>
<p>그림에서 가용 영역별로 로드 밸런서가 배치되고 다수의 인스턴스가 구성되어 있다. 이때 대상 인스턴스 수량이 첫 번째 가용 영역은 두 대, 두 번째 가용 영역은 여덟 대로 영역별로 불균형하게 구성되어 있다. 사용자 PC에서 ELB 도메인 주소로 트래픽을 전송하면, 도메인을 해석하여 50:50 비중으로 각 가용 영역에 위치한 로드 밸런서로 전달할 것이다. 그러면 첫 번째 로드 밸런서는 총 50이라는 비중에서 두 대의 대상 인스턴스에 25의 비중으로 트래픽을 로드 밸런싱할 것이다. 따라서 첫 번째 가용 영역에 위치한 대상 인스턴스에 트래픽 부하도가 높아지게 되며, 전체적으로 로드 밸런싱이 불균형해지는 것을 확인할 수 있다.</p>
<p>이런 불균형 로드 밸런싱을 해결하는 데 Amazon ELB에서 제공하는 교차 영역 로드 밸런싱 기능을 사용할 수 있는데, ELB 교차 영역 로드 밸런싱(cross-zone load balancing)은 여러 가용 영역에 걸쳐 있는 EC2 인스턴스나 컨테이너 등 대상을 더 효과적으로 로드 밸런싱하는 기능이다. 이런 교차 영역 로드 밸런싱은 가용 영역별로 인스턴스 수량이 불균형하게 위치할 때 트래픽 비중을 보정할 수 있으며, 트래픽을 분산하는 기준이 가용 영역이 아닌 대상 그룹에 속한 자원을 기준으로 균일한 비중의 로드 밸런싱을 수행할 수 있다.</p>
<h4 id="교차-영역-로드-밸런싱-활성화">교차 영역 로드 밸런싱 활성화</h4>
<p><img src="https://velog.velcdn.com/images/urban-jungle/post/f2b000e1-aeab-4e85-954d-3eb5e9e28490/image.png" alt=""></p>
<p>앞의 상황과 동일하게 가용 영역별 인스턴스 수량이 불균형한 환경에서 가용 영역별로 50:50 비중으로 트래픽을 전달한다고 하자. 대상 자원의 비율에 따라 가용 영역을 교차하기 때문에 각 10의 비중을 맞추어 균일하게 열 대의 인스턴스 대상에 로드 밸런싱하는 것을 확인할 수 있다. 이렇게 교차 영역 로드 밸런싱을 활성화하면 가용 영역과 무관하게 대상 자원의 비율을 고려하여 가용 영역을 교차할 수 있어 좀 더 효율적으로 로드 밸런싱을 할 수 있다. 교차 영역 로드 밸런싱은 ALB를 사용할 때 기본적으로 활성화되어 있으나, NLB는 비활성화되어 있다. 또한 교차 영역 로드 밸런싱은 대상 그룹 수준에서 구성할 수 있으므로 필요에 따라 각 대상 그룹별로 별도로 구성할 수 있다. 단 사용할 때 가용 영역 간에 통신 비용이 발생할 수 있다.</p>
<h2 id="amazon-elb-종류">Amazon ELB 종류</h2>
<h3 id="clb">CLB</h3>
<p>CLB(Classic Load Balancer)는 Amazon ELB의 가장 초기에 출시된 로드 밸런서로, 4계층과 7계층 프로토콜을 모두 지원한다. HTTP/HTTPS 요청에 따른 최신 HTTPv1.2 프로토콜과 TCP의 SSL/TLS 암호화 프로토콜도 지원하며, SSL 인증서를 사용한다. 고정 IP 주소를 사용하여 로드 밸런서를 생성하고, 로드 밸런서에 대한 DNS 이름으로 액세스할 수 있다. 그러나 CLB는 서버의 기본 주소가 변경되면 로드 밸런서를 새로 생성해야 하며, 기능적인 한계 때문에 포트나 헤더 같은 데이터를 수정하거나 변경할 수 없는 등 제약 사항이 있다. 현재는 NLB와 ALB 같은 새로운 로드 밸런서 서비스가 출시되어 CLB를 대체해서 사용하는 추세이다.</p>
<h3 id="alb">ALB</h3>
<p>ALB(Application Load Balancer)는 AWS에서 제공하는 L7 로드 밸런서로, HTTP/HTTPS 같은 웹 애플리케이션 프로토콜을 지원한다. ALB는 대상 그룹 단위로 트래픽을 분산하며, 각 대상 그룹은 ALB가 요청을 전달할 EC2인스턴스, 람다 함수, 컨테이너 및 IP 주소로 라우팅하는 기능을 제공한다.</p>
<p>[ALB의 특징]</p>
<ul>
<li>HTTP 헤더를 확인하여 다양한 라우팅 기능을 제공<ul>
<li>경로 기반 라우팅: URL 경로를 기반으로 요청을 분산</li>
<li>호스트 기반 라우팅: 호스트 이름을 기반으로 요청을 분산</li>
<li>쿼리 문자열 기반 라우팅: URL 쿼리 문자열을 기반으로 요청을 분산</li>
</ul>
</li>
<li>오토 스케일링과 함께 사용하여 확장성 있는 애플리케이션 구성 가능</li>
<li>대상 그룹 내 인스턴스에 대해 상태 검사를 수행하고, 문제가 발생하면 자동으로 장애 조치를 취할 수 있음</li>
<li>Amazon CloudWatch Logs와 통합되어 로그 및 지표 데이터를 수집하고 모니터링 및 분석 가능</li>
</ul>
<p>따라서 ALB는 웹 애플리케이션에 특화된 세밀한 라우팅을 제어할 수 있어 웹 애플리케이션을 위한 로드 밸런서로 사용된다.</p>
<h3 id="nlb">NLB</h3>
<p>NLB(Network Load Balancer)는 AWS에서 제공하는 L4 로드 밸런서로, TCP/UDP/TLS 프로토콜을 지원한다. ALB와 달리, 클라이언트와 로드 밸런서 간 연결을 TCP 레벨에서 유지하므로 대규모 트래픽을 처리할 수 있다. 이를 위해 NLB는 높은 처리량, 초당 연결 수, 대역폭 등 기능을 제공하며 동일한 IP 주소에서 여러 대상 그룹을 지원할 수 있다.</p>
<p>[NLB의 특징]</p>
<ul>
<li>높은 처리량: 초당 수백만 개의 연결을 처리할 수 있음</li>
<li>빠른 응답 시간: 빠른 응답을 위해 최적화된 L4 로드 밸런싱 알고리즘을 사용</li>
<li>높은 가용성: 여러 가용 영역에서 인스턴스를 실행하고 매우 빠른 인스턴스 검색을 수행하여 신속하게 장애를 복구함</li>
<li>IP 주소 보존: 클라이언트 IP 주소를 원래 IP 주소로 보존할 수 있음. 이것은 클라이언트 IP 주소를 유지하면서 로드 밸런싱을 수행할 수 있다는 것을 의미함</li>
<li>모니터링: AWS CloudTrail, Amazon CloudWatch Logs 같은 모니터링 기능을 지원함</li>
</ul>
<p>따라서 NLB는 대규모 네트워크 트래픽을 처리하고 대상 그룹의 대상이 IP 주소로 식별될 때 유용하다. 또한 AWS에서 제공하는 다른 로드 밸런서보다 높은 처리량과 빠른 응답 시간을 보장하므로 게임 서버, VoIP 서비스, 미디어 스트리밍 등에서 사용된다.</p>
<h3 id="gwlb">GWLB</h3>
<p>GWLB(Gateway Load Balancer)는 네트워크 트래픽을 서드 파티의 방화벽/어플라이언스 장비로 부하분산 처리하는 로드밸런서이다. GWLB를 사용하면 서드 파티의 방화벽/어플라이언스 장비를 쉽게 배포하고 확장 및 관리할 수 있다. 요청에 따라 트래픽을 확장하거나 축소하면서 다수의 서드 파티 장비에 로드 밸런싱을 처리한다. GWLB는 VPC 내에서 실행되는 애플리케이션의 가용성과 확장성을 향상시키는 데 사용되며, TCP 및 UDP 프로토콜을 지원하여 다양한 유형의 애플리케이션에 유연하게 적용할 수 있다.</p>
<p>각 로드밸런서 종류는 고유한 기능을 제공하며, 사용자 요구 사항에 따라 적절한 로드 밸런서를 선택하는 것이 중요하다.</p>
<p><img src="https://velog.velcdn.com/images/urban-jungle/post/a8fbd46a-a684-4390-9611-be5e627bc3e9/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/urban-jungle/post/c8922477-9b1c-4aaf-a742-80104c02f3c9/image.png" alt=""></p>
<hr>
<p><img src="https://velog.velcdn.com/images/urban-jungle/post/3163bc21-64eb-4785-be69-55ae18f79df1/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[CAB TA 4기 24일차의 기록]]></title>
            <link>https://velog.io/@urban-jungle/CAB-TA-4%EA%B8%B0-24%EC%9D%BC%EC%B0%A8%EC%9D%98-%EA%B8%B0%EB%A1%9D</link>
            <guid>https://velog.io/@urban-jungle/CAB-TA-4%EA%B8%B0-24%EC%9D%BC%EC%B0%A8%EC%9D%98-%EA%B8%B0%EB%A1%9D</guid>
            <pubDate>Tue, 15 Apr 2025 01:56:49 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/urban-jungle/post/631dfe61-01c4-4d04-a402-c5fbfcce1b60/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/urban-jungle/post/414734ae-a327-4b4e-8d1d-71c53647668c/image.png" alt=""></p>
<h1 id="클라우드-컴퓨팅">클라우드 컴퓨팅</h1>
<h2 id="클라우드-컴퓨팅이란">클라우드 컴퓨팅이란</h2>
<p>IT 자원을 구축하는 전통적인 방법에 온프레미스 구축 방법이 있다.
프레미스(premise)는 기본, 건물, 토지라는 뜻이므로 온프레미스는 자체적인 공간과 자원을 이용하여 사용자가 직접 구축 및 운영하는 방식을 의미한다고 볼 수 있다.
사용자 입장에서 이런 구축 방식은 모든 것을 수행해야 하기 때문에 부담이 클 수 밖에 없으며, 비용 또한 만만치 않다.</p>
<p>이런 문제점을 고려하여 효율적으로 IT 자원을 구축하는 방법으로 <strong>클라우드 구축 방법</strong>이 떠오르고 있으며, 많은 비즈니스 환경에서 이 방식을 도입하자는 요구가 있다. 클라우드가 &#39;구름&#39;을 뜻한다는 것은 쉽게 알 수 있지만, 과연 IT 영역에서 클라우드는 어떤 의미일까?
일반적으로 IT 자원 구성도를 그릴 때, 인터넷에 있는 다양한 자원을 구름 형태로 표현하곤 한다. 이에 클라우드는 구름처럼 눈에 보이지 않는 형태로 집합되어 있는 IT 자원들이라고 생각할 수 있다.</p>
<p><strong>클라우드 컴퓨팅</strong>은 인터넷을 통해 요구가 있을 때 즉시(온디맨드) IT 자원을 제공하며, 사용한 만큼 비용을 지불하는 서비스이다. 좀 더 이해하기 쉽게 앞서 설명한 클라우드 단어 의미와 연결하여 생각하면, 인터넷 구간 어딘가에 구름 형태로 쌓여 실제 물리적인 자원은 보이지 않지만 IT 자원을 원하는 대로 가져다 사용할 수 있는 컴퓨팅 서비스를 의미한다. AWS와 같은 클라우드 공급자에게 필요에 따라 다양한 IT 자원을 공급받을 수 있다.</p>
<p><img src="https://velog.velcdn.com/images/urban-jungle/post/51f38e9a-bf68-4dde-b393-5366c388e004/image.png" alt=""></p>
<h3 id="온프레미스와-클라우드-정의">온프레미스와 클라우드 정의</h3>
<ul>
<li>온프레미스(on-premises): 사용자 입장에서 공간, 자원 등 모든 것을 자체적으로 구축 및 운영하는 방식</li>
<li>클라우드(cloud): 인터넷 구간 어딘가에 눈에 보이지 않는 형태로 구성된 IT 자원 집합</li>
<li>클라우드 컴퓨팅(cloud computing): 인터넷을 통해 IT 자원 요구에 따라 사용한 만큼 비용을 지불하는 서비스</li>
</ul>
<h2 id="클라우드-컴퓨팅-이점">클라우드 컴퓨팅 이점</h2>
<h3 id="민첩성">민첩성</h3>
<p>클라우드를 통해 광범위한 기술에 쉽게 접근할 수 있어 거의 모든 것을 빠르고 혁신적으로 구축할 수 있다.</p>
<h3 id="탄력성">탄력성</h3>
<p>클라우드 컴퓨팅을 사용하면 기존 온프레미스 환경처럼 향후 비즈니스 확장을 고려한 IT 자원을 사전에 과하게 구성할 필요가 없다.</p>
<h3 id="비용-절감">비용 절감</h3>
<p>클라우드 컴퓨팅은 Pay Per Use로, IT 자원을 사용한 만큼 비용을 지불하면 된다.</p>
<h2 id="클라우드-컴퓨팅-서비스-유형">클라우드 컴퓨팅 서비스 유형</h2>
<h3 id="iaasinfrastructure-as-a-service">IaaS(Infrastructure as a Service)</h3>
<p>말 그대로 인프라에 대한 클라우드 서비스 유형을 의미한다. 여기에서 인프라는 서버, 네트워크, 스토리지 등 하드웨어 영역과 가상화 기능이 해당된다. 클라우드 공급자는 해당 인프라 영역을 관리하고 서비스를 제공하며, 클라우드 사용자가 나머지 영역을 직접 고나리하는 구조이다.</p>
<p><img src="https://velog.velcdn.com/images/urban-jungle/post/2ee495b9-dad8-4608-a87e-ede5180646cb/image.png" alt=""></p>
<h3 id="paasplatform-as-a-service">PaaS(Platform as a Service)</h3>
<p>플랫폼 형태로 제공되는 클라우드 서비스 유형을 의미한다. 클라우드 공급자가 자체적으로 구축한 플랫폼을 제공하며, 클라우드 사용자는 별도의 플랫폼을 구축하지 않고 애플리케이션을 개발 및 관리만 하면 된다. 즉, 클라우드 사용자는 애플리케이션 영역만 담당하고 나머지는 클라우드 공급자가 관리 및 제공하는 구조이다.</p>
<p><img src="https://velog.velcdn.com/images/urban-jungle/post/a272736b-c07c-42cd-94c4-e9c8b8c777ba/image.png" alt=""></p>
<h3 id="saassoftware-as-a-service">SaaS(Software as a Service)</h3>
<p>SaaS는 소프트웨어 영역까지 클라우드 공급자가 관리 및 제공하는 유형을 의미한다. 클라우드 사용자는 별도의 애플리케이션을 설치하거나 운영할 필요 없이 클라우드 서비스를 제공받을 수 있다. 즉, 클라우드 공급자가 모든 것을 제공하고 클라우드 사용자는 서비스만 받는 구조이다.</p>
<p><img src="https://velog.velcdn.com/images/urban-jungle/post/b8a28cd1-9173-4cea-acc4-0be4cf8acf72/image.png" alt=""></p>
<h2 id="클라우드-구축-모델">클라우드 구축 모델</h2>
<h3 id="퍼블릭-클라우드-구축-모델">퍼블릭 클라우드 구축 모델</h3>
<p>일반적으로 사용자가 클라우드 자원을 소유하지 않으며, 자체적인 공간에 위치하지 않고 클라우드 공급자가 서비스를 제공하는 환경이다. 확장성이 우수하며, 글로벌 서비스 제공에도 유리하다.</p>
<h3 id="프라이빗-클라우드-구축-모델">프라이빗 클라우드 구축 모델</h3>
<p>사용자 전용 클라우드 환경으로, 자원 소유권은 사용자에게 있고 프라이빗 클라우드는 온프레미스 환경에 구축되어 서비스를 받는 환경이다. 즉, 서비스 주체가 &#39;사용자&#39;이다. 보안이 우수하지만, 퍼블릭 클라우드보다 서비스 확장성이 떨어진다.</p>
<h3 id="하이브리드-클라우드-구축-모델">하이브리드 클라우드 구축 모델</h3>
<p>퍼블릭 클라우드와 프라이빗 클라우드의 단점을 보완하려고 등장한 클라우드 모델이다. 다수의 클라우드 시스템이 혼합되어 있는 형태로, 클라우드 시스템이 서로 연결된 모델이다.</p>
<p><img src="https://velog.velcdn.com/images/urban-jungle/post/3be2dce3-c6c2-454d-bc1b-d41d46d2bef2/image.png" alt=""></p>
<h1 id="aws-서비스">AWS 서비스</h1>
<h2 id="aws-소개">AWS 소개</h2>
<p>AWS는 다양한 퍼블릭 클라우드 컴퓨팅 리소스를 제공하고 있으며 직접 장비를 구매하거나 임대하지 않고 인터넷 환경을 통해 필요한 만큼의 리소스를 제공하는 클라우드 서비스 제공자이다. 현재 aws는 200개 이상의 클라우드 서비를 제공하는 것으로 알려져 있다. AWS는 32개의 리전(클라우드 서비스를 위해 자원이 집적되어 있는 물리적 데이터 센터의 지리적 위치)과 102개의 가용 영역(리전 내 구성되는 하나 이상의 개별적 데이터 센터)을 운영하여 글로벌 클라우드 인프라를 제공하고 있다.</p>
<p><img src="https://velog.velcdn.com/images/urban-jungle/post/b4de3b47-921c-4768-964f-8e3ce838d7cc/image.png" alt=""></p>
<h3 id="리전과-가용-영역">리전과 가용 영역</h3>
<ul>
<li>리전(region): 데이터 센터가 집합된 물리적 위치(지역)</li>
<li>가용 영역(availability zone): 리전 내 구성된 하나 이상의 개별 데이터 센터</li>
</ul>
<h2 id="aws-서비스-라인업">AWS 서비스 라인업</h2>
<p><img src="https://velog.velcdn.com/images/urban-jungle/post/c1f0fa28-f1d4-480e-b859-d25fcd9e27d2/image.png" alt=""></p>
<p>각 분류별로 200개 이상의 세부 서비스가 있다.</p>
<h3 id="aws-컴퓨팅">AWS 컴퓨팅</h3>
<p>퍼블릭 클라우드의 서버 자원에 대해 가상 머신을 생성하고 비용 및 용량을 관리하는 서비스로 구성되어 있다.</p>
<h3 id="aws-네트워킹-및-콘텐츠-전송">AWS 네트워킹 및 콘텐츠 전송</h3>
<p>퍼블릭 클라우드에 생성한 다양한 자원으로 내/외부 통신을 하는 네트워크 서비스들로 구성되어 있다.</p>
<h3 id="aws-스토리지">AWS 스토리지</h3>
<p>퍼블릭 클라우드에 안정적이고 확장성이 높은 스토리지 서비스들로 구성되어 있다.</p>
<h3 id="aws-데이터베이스">AWS 데이터베이스</h3>
<p>데이터베이스 목적과 용도에 따라 퍼블릭 클라우드에 다양한 데이터베이스 엔진을 제공하여 완전 관리형 데이터베이스 서비스를 하고 있다.</p>
<h3 id="aws-보안-자격-증명-및-규격-준수">AWS 보안 자격 증명 및 규격 준수</h3>
<p>퍼블릭 클라우드 자원과 사용자 자격 증명 및 접근 관리, 데이터/네트워크/애플리케이션 보호와 위협 탐지 및 모니터링을 위한 다양한 서비스로 구성되어 있다.</p>
<h2 id="aws-과금-체계">AWS 과금 체계</h2>
<p>AWS는 Pay Per Use로, IT 자원을 사용한 만큼 비용을 지불하는 형태로 서비스를 제공한다. 물론 무료 서비스도 있지만, AWS 서비스 과금은 서비스마다 책정하는 방식과 기준이 다르다. 클라우드 서비스를 도입하기에 앞서 비용 검토가 선행되어야 하고 필요 자원을 산정해야 한다. 항상 과금은 시간과 사용량에 비례하여 사용한 만큼 부여한다는 점을 유의해야 한다.</p>
<h1 id="aws-컴퓨팅-서비스">AWS 컴퓨팅 서비스</h1>
<h2 id="컴퓨팅-정의">컴퓨팅 정의</h2>
<p>특정 부분을 계산해서 답을 구하고 추정하는 행위 자체를 Computing(컴퓨팅)이라고 정의하고 있다. 컴퓨팅을 전문적으로 수행하기 위해 인간이 아닌 컴퓨팅을 목적으로 하는 장비가 존재한다. 대표적으로 서버가 컴퓨팅을 위한 장비에 해당된다.</p>
<h2 id="aws-컴퓨팅-서비스-1">AWS 컴퓨팅 서비스</h2>
<p>AWS Computing Service는 퍼블릭 클라우드에서 컴퓨팅 자원을 활용해서 다양한 워크로드를 수행할 수있는 서비스를 의미한다.</p>
<ul>
<li>워크로드(Workload) :클라우드 환경에서 워크로드는 특정 작업이나 서비스를 수행하기 위해 클라우드 인프라에서 실행되는 애플리케이션, 프로세스, 또는 작업 집합을 의미한다. 이 워크로드는 웹 애플리케이션, 데이터베이스, 머신러닝 모델, 데이터 처리 작업 등 다양한 형태로 존재한다.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/urban-jungle/post/18c77eec-8e34-4b69-b3e2-195a2f95ff37/image.png" alt=""></p>
<p>컴퓨팅 리소스를 사용할 수 있는 만큼 비용을 지불하면 수분 내로 가상의 서버 자원을 생성하고 관리할 수 있다.</p>
<ul>
<li><p>EC2(Elastic Compute Cloud) : 클라우드 환경에서 서버 자원을 인스턴스라는 가상 머신의 형태로 제공하는 가장 기본적인 AWS Computing Service</p>
</li>
<li><p>Lambda : Serverless 컴퓨팅 서비스로, 별도의 서버 설정 없이 환경을 제공해서 코드만 실행해 주는 서비를 의미</p>
</li>
<li><p>Lightsail : 독립적인 환경을 제공한다. 최소한의 설정만으로도 바로 사용 가능한 컴퓨팅 서비스</p>
</li>
<li><p>ECS(Elastic Container Service) : EC2 기반 관리형 클러스터에서 실행되는 컨테이너 형태의 자원에 대해 배포, Scheduling, scaling 등을 관리하는 서비스</p>
</li>
</ul>
<h1 id="amazon-ec2-소개">Amazon EC2 소개</h1>
<p>Amazon EC2란 퍼블릭 클라우드 환경에서 확장 가능한 컴퓨팅 리소스를 제공하여 가상의 서버 인스턴스를 운영할 수 있도록 하는 서비스를 의미한다.
EC2 인스턴스는 가상 컴퓨팅 환경을 기반으로 하고 AMI(Amazon Machine Image)를 사용해서 인스턴스에서 필요한 소프트웨어 정보를 정의한다. </p>
<h2 id="amazon-ec2-인스턴스">Amazon EC2 인스턴스</h2>
<p>EC2 인스턴스는 가상의 컴퓨팅 환경으로 프로세서, 메모리, 스토리지, 네트워크 용량을 결정하는 다양한 인스턴스 유형을 제공한다. 인스턴스가 실행 중인 임의의 프로세스로 해석된다는 점과 클라우드 컴퓨팅이 가상의 환경에서 필요한 자원을 임대해서 사용하다는 점이 서로 일맥상통한 의미를 갖는다.EC2는 500개가 넘는 인스턴스 유형을 제공해서 사용자의 목적과 비즈니스 환경에 맞게 인스턴스를 선택할 수 있다.</p>
<h3 id="인스턴스-유형">인스턴스 유형</h3>
<p><img src="https://velog.velcdn.com/images/urban-jungle/post/d0387bd8-c3bf-4100-a4e0-32b3c8a77497/image.png" alt=""></p>
<h3 id="인스턴스-상태">인스턴스 상태</h3>
<p>인스턴스 상태는 일반적으로 7가지로 분류할 수 있으며, 어떤 행위에 최종적으로 도달하는 상태와 진행 과정에 따른 상태로 나눌 수 있다.</p>
<h4 id="인스턴스-수명-주기">인스턴스 수명 주기</h4>
<p><img src="https://velog.velcdn.com/images/urban-jungle/post/f38cc192-673c-48f0-94e1-90d3016ff0cf/image.png" alt=""></p>
<ul>
<li>최초 인스턴스를 시작하는 작업 : 대기 중 → 실행 중</li>
<li>실행 중인 인스턴스를 중지하는 작업 : 실행 중 → 중지 중  → 중지됨(인스턴스 종료 상태가 아님)</li>
<li>중지된 인스턴스를 종료 : 중지됨 → 종료 중 → 종료 됨</li>
<li>실행 중인 인스턴스의 종료 : 실행 중 → 종료 중 → 종료됨</li>
</ul>
<h3 id="amiamazon-machine-image">AMI(Amazon Machine Image)</h3>
<p>AMI는 인스턴스를 시작할 때 필요한 정보를 제공하는 것으로 운영 체제의 이미지 등 EC2 인스턴스에 대한 전반적인 메타데이터를 제공하는 템플릿을 의미한다.</p>
<p><img src="https://velog.velcdn.com/images/urban-jungle/post/7a37b5f8-5cf2-4e35-9fb2-954444bab3ba/image.png" alt=""></p>
<p>AWS에서 자체적으로 제공하는 기본 AMI를 활용해서 인스턴스를 생성하고 사용자 요구에 따라 변경하거나 구성하여 사용자 정의 AMI를 생성할 수 있다.
이렇게 만들어진 사용자 정의 AMI를 통해 다른 인스턴스를 생성할 수 있다.</p>
<h3 id="amazon-ec2-스토리지">Amazon EC2 스토리지</h3>
<p>AMI를 통해 인스턴스 환경을 설정했다면 다음으로 어떤 저장소를 사용할지 결정해야 한다. EC2는 유연하고 효율적인 스토리지 환경을 제공하고 아래와 같이 두 종류로 나뉜다.</p>
<p><img src="https://velog.velcdn.com/images/urban-jungle/post/66e655df-c151-40ca-aebe-7ca683ba054c/image.png" alt=""></p>
<p>EC2 인스턴스용 스토리지 유형은 인스턴스 스토어와 블록 스토리지인 Amazon EBS로 나뉜다.</p>
<h4 id="인스턴스-스토어">인스턴스 스토어</h4>
<p>인스턴스에 바로 붙어 있는 저장소로, Amazon EC2 인스턴스를 생성하면 기본적으로 존재하는 스토리지이다. 다만 일부 인스턴스 유형은 인스턴스 스토어를 지원하지 않는다.
아무래도 직접 붙어 있는 구조 덕분에 매우 빠른 I/O를 보장한다는 장점이 있지만, 인스턴스 스토어는 Amazon EC2 인스턴스를 중지하거나 종료하면 인스턴스 스토어에 저장된 데이터가 모두 손실된다는 단점이 있다. 따라서 임시적인 데이터 저장소로 생각할 수 있으며, 장기적으로 보존해야 하는 데이터는 인스턴스 스토어에 저장하지 않는 것이 좋다.</p>
<h4 id="amazon-ebs">Amazon EBS</h4>
<p>Amazon EBS는 AWS에서 제공하는 블록 스토리지 서비스로 EC2 인스턴스와 함께 사용되며 데이터의 지속성과 가용성을 보장한다. 디스크 형태로 작동하며 EC2 인스턴스에 네트워크로 연결하여 데이터를 저장하고 관리할 수 있다. 영구 보존이 가능하다.
EC2 인스턴스가 중지되거나 종료되어도 Amazon EBS에 보존하는 데이터는 그대로 유지할 수 있다. EBS는 관리 콘솔을 통해 스냅샷을 생성해 백업하거나 EBS 연결을 해제한 후 다른 인스턴스에 연결 가능하다는 특징이 있다.</p>
<h2 id="amazon-ec2-네트워킹">Amazon EC2 네트워킹</h2>
<p><img src="https://velog.velcdn.com/images/urban-jungle/post/19c97e65-6ab7-40ff-9447-6d9590441241/image.png" alt=""></p>
<p> Amazon EC2 인스턴스는 어떤 서비스를 수행하기 위해 특수한 목적으로 만들어진 가상 서버 머신이다. 서비스를 제공하기 위해 자연스럽게 통신이 가능한 환경으로 구성될 필요가 있다. 이때 EC2 네트워킹을 통해 통신이 가능한 환경을 구성할 수 있다. </p>
<h3 id="ec2-인스턴스-통신을-위한-네트워킹-요소">EC2 인스턴스 통신을 위한 네트워킹 요소</h3>
<h4 id="amazon-vpc">Amazon VPC</h4>
<p>Amazon VPC는 AWS 퍼블릭 클라우드 내부에서 논리적으로 격리된 가상의 클라우드 네트워크 환경이다. 생성된 EC2 인스턴스는 별도로 구성된 하나의 Amazon VPC 내부에 생성되어 네트워킹된다.</p>
<h4 id="네트워크-인터페이스">네트워크 인터페이스</h4>
<p>AWS에서는 ENI(Elastic Network Interface)라는 논리적 네트워크 인터페이스가 VPC 내 생성되며, ENI를 EC2 인스턴스에 연결해서 네트워킹을 수행한다.</p>
<h4 id="ip-주소">IP 주소</h4>
<p>네트워크 인터페이스에는 별도의 IP 주소가 존재하고 IP 주소로 각 인스턴스나 호스트를 구분하고 통신을 수행한다 이러한 IP 주소는 사설, 공인 IP 주소로 구분된다.</p>
<h2 id="amazon-ec2-보안">Amazon EC2 보안</h2>
<p>AWS에서도 클라우드 내부의 보안 요소들을 중요하게 인식하고 있으므로 EC2의 안정적인 운영을 위해 EC2 보안 기능을 제공하고 있다.</p>
<h3 id="보안-그룹">보안 그룹</h3>
<p>보안 그룹의 경우 EC2 인스턴스의 트래픽을 송수신 트래픽을 제어하기 위해 설계된 가상의 방화벽 환경이다. EC2 인스턴스를 기준으로 인바운드/아웃바운드 트래픽에 대한 규칙을 제어하게 된다. 트래픽 제어를 위해 IP 주소, 포트 번호, 프로토콜 등의 정보가 사용된다.</p>
<h3 id="키-페어">키 페어</h3>
<p>EC2 인스턴스에 연결할 때 사용자 자격을 증명하기 위한 보안 키다. 키 페어는 Public, Private로 구분되며 퍼블릭 키는 Amazon EC2 인스턴스에 저장되고 프라이빗 키는 사용자 로컬 환경에 저장된다. </p>
<h2 id="amazon-ec2-모니터링">Amazon EC2 모니터링</h2>
<p>EC2의 모니터링 기능은 서비스의 안정성, 가용성, 성능 유지에 반드시 필요한 기능이다. 불특정 다수에게 서비스되는 의미 있는 비즈니스 아키텍처의 경우 언제 어느 시점, 또는 특정 시점에 트래픽이 몰려서 서버가 다운될지 모른다. EC2의 리소스는 유한하기 때문에 자원에 대한 부하를 컨트롤하고 모니터링할 필요성이 있다.</p>
<p>아래와 같은 모니터링 계획을 정의해서 관리하는 것이 중요하다.</p>
<ul>
<li>모니터링 목표</li>
<li>모니터링 대상 자원</li>
<li>모니터링 빈도</li>
<li>모니터링 수행 도구</li>
<li>모니터링 작업을 수행할 사람</li>
<li>문제가 발생할 때 정보를 알려야 할 대상</li>
</ul>
<h3 id="수동-모니터링-도구">수동 모니터링 도구</h3>
<p>말 그대로 관리자가 직접 관리 콘솔을 이용하여 모니터링을 수행하는 것이다. Amazon EC2 대시보드에서 간단한 통계 정보를 확인하거나 Amazon CloudWatch라는 모니터링 전용 서비스를 이용하여 상세한 통계 정보를 모니터링할 수 있다.</p>
<h3 id="자동-모니터링-도구">자동 모니터링 도구</h3>
<p><img src="https://velog.velcdn.com/images/urban-jungle/post/71a00f05-27be-4a6b-ada2-111a5d38063a/image.png" alt=""></p>
<p>오토 모니터링의 경우 대상 리소스에 대해 임계값을 지정하고 임계값을 초과하게 되면 Alert Message를 관리자에게 보여주는 형식으로 동적인 모니터링을 진행하게 된다. 다양한 도구가 있지만 대표적으로 Amazon CloudWatch가 있다.</p>
<p>CloudWatch의 경보 시스템을 통해서 동적으로 단일 리소스를 모니터링하고 지정된 임계값을 초과하는 경고 메시지를 생성하는 등의 방법으로 모니터링이 가능하다. 경고 메시지 등의 경우 Amazon SNS(Simple Notificationi Service)를 통해 관리자 이메일로 메일을 보내거나 EC2 자원을 동적으로 컨트롤할 수 있게 된다.</p>
<h2 id="ec2-인스턴스-구입-옵션">EC2 인스턴스 구입 옵션</h2>
<ul>
<li>온디맨드 인스턴스: 시작하는 인스턴스에 대한 비용을 초 단위로 지불</li>
<li>Savings Plans: 1년 또는 3년 동안 시간당 비용을 약정하여 일관된 컴퓨팅 사용량을 제공</li>
<li>예약 인스턴스: 1년 또는 3년 동안 인스턴스 유형과 리전을 약정하여 일관된 인스턴스를 제공</li>
<li>스팟 인스턴스: 미사용 중인 인스턴스에 대해 경매 방식 형태로 할당</li>
</ul>
<p><img src="https://velog.velcdn.com/images/urban-jungle/post/da03ad6a-598a-494b-ab45-2b2bf480191f/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[CAB TA 4기 23일차의 기록]]></title>
            <link>https://velog.io/@urban-jungle/CAB-TA-4%EA%B8%B0-23%EC%9D%BC%EC%B0%A8%EC%9D%98-%EA%B8%B0%EB%A1%9D</link>
            <guid>https://velog.io/@urban-jungle/CAB-TA-4%EA%B8%B0-23%EC%9D%BC%EC%B0%A8%EC%9D%98-%EA%B8%B0%EB%A1%9D</guid>
            <pubDate>Tue, 15 Apr 2025 01:55:50 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/urban-jungle/post/6dc42c6b-3ab1-4269-8d45-c8b534f1e8dc/image.png" alt=""></p>
<h3 id="ssl-certificate-and-https-setup">SSL Certificate and HTTPS Setup</h3>
<p>본 프로젝트에서는 웹 서비스의 기본 보안을 강화하기 위해 Let&#39;s Encrypt 인증서와 Apache의 mod_ssl 모듈을 활용한 HTTPS 환경을 구축하였다.
초기에 mod_ssl 패키지를 설치하고 기본 SSL 설정 파일(/etc/httpd/conf.d/ssl.conf)을 검토하여 불필요하거나 충돌 가능성이 있는 설정을 제거한 후, WordPress 사이트에 적합한 별도 SSL 설정 파일(wordpress-ssl.conf)을 생성하였다.</p>
<p>Let&#39;s Encrypt를 활용한 인증서는 무료이면서도 브라우저와의 호환성이 높아 실무 환경에서도 널리 사용된다. 인증서를 수동 발급하기 위해 openssl 명령어를 사용해 자체 서명된 인증서(localhost.crt, localhost.key)를 /etc/pki/tls/경로에 생성하였고, Apache 설정에서 해당 경로를 명시했다.</p>
<p>설정 완료 후 apachectl configtest로 문법 오류를 검증하고 Apache를 재시작하여 HTTPS 접속이 가능함을 확인했다. 접속 시 브라우저에서 &quot;주의: 보안 연결이 완전하지 않을 수 있음&quot; 메시지가 출력되더라도, 자체 서명 인증서 기반의 HTTPS 연결이 정상적으로 동작하는 것은 실무에서도 초기에 테스트 및 내부 망에 유용하게 쓰일 수 있다.</p>
<p>특히, HTTPS 적용을 통해 WordPress 관리자 페이지와 사용자 로그인 정보 전송이 암호화되었으며, 이후 Wordfence 및 DISALLOW_FILE_EDIT, DISALLOW_FILE_MODS 설정과 함께 다중 보안 계층을 형성하여 외부 공격으로부터의 방어 체계를 마련하였다.</p>
<h4 id="httpslocalhost-접속"><a href="https://localhost">https://localhost</a> 접속</h4>
<p><img src="https://velog.velcdn.com/images/urban-jungle/post/56cacbd1-81b3-472d-9a29-671b60e1eebf/image.png" alt=""></p>
<p>&quot;Warning: Potential Security Risk Ahead&quot; → &quot;Advanced 
→ Accept the Risk and Continue&quot; </p>
<h4 id="ls--l-etcpkitlscertslocalhostcrt-파일-정상적으로-생성됨">ls -l /etc/pki/tls/certs/localhost.crt 파일 정상적으로 생성됨</h4>
<p><img src="https://velog.velcdn.com/images/urban-jungle/post/38afe72e-1104-4173-8c75-135d0021d80f/image.png" alt=""></p>
<h4 id="ls--l-etcpkitlsprivatelocalhostkey-파일-정상적으로-생성됨">ls -l /etc/pki/tls/private/localhost.key 파일 정상적으로 생성됨</h4>
<p><img src="https://velog.velcdn.com/images/urban-jungle/post/0f58897a-1eef-4ea6-a513-0029e1ce8f5b/image.png" alt=""></p>
<h4 id="apache-구문-오류-검사-통과">Apache 구문 오류 검사 통과</h4>
<p><img src="https://velog.velcdn.com/images/urban-jungle/post/b6e6b226-a02f-490f-8e6b-e687c0c9179f/image.png" alt=""></p>
<hr>
<h3 id="monitoring-with-prometheus-and-grafana">Monitoring with Prometheus and Grafana</h3>
<p>본 단계에서는 Prometheus와 Grafana를 활용하여 WordPress 서버의 시스템 상태를 실시간으로 수집, 시각화하는 모니터링 환경을 구축했다.
Prometheus는 Node Exporter로부터 수집한 메트릭 데이터를 주기적으로 스크래핑하며, Grafana는 해당 데이터를 기반으로 대시보드를 구성해 직관적인 시각 정보를 제공한다.</p>
<h4 id="구성-요소">구성 요소</h4>
<ul>
<li>Node Exporter: CPU, 메모리, 디스크, 네트워크 등의 시스템 메트릭 제공</li>
<li>Prometheus: /metrics 엔드포인트 수집 및 시계열 DB 저장</li>
<li>Grafana: Prometheus 데이터 시각화 및 대시보드 구성</li>
</ul>
<h4 id="구현한-주요-패널-구성">구현한 주요 패널 구성</h4>
<ol>
<li><p><strong>CPU Usage (%)</strong>
시각화 방식: Gauge
쿼리: 100 - (avg by (instance) (rate(node_cpu_seconds_total{mode=&quot;idle&quot;}[5m])) * 100)</p>
</li>
<li><p><strong>Memory Usage (%)</strong>
시각화 방식: Gauge
쿼리: (1 - (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes)) * 100</p>
</li>
</ol>
<ol start="3">
<li><p><strong>Disk Usage (%)</strong>
시각화 방식: Bar Gauge
쿼리: (node_filesystem_size_bytes - node_filesystem_free_bytes) / node_filesystem_size_bytes * 100</p>
</li>
<li><p><strong>CPU Load Average</strong>
시각화 방식: Stat
쿼리: node_load1</p>
</li>
<li><p><strong>Network Inbound</strong>
시각화 방식: Time Series
쿼리: rate(node_network_receive_bytes_total[5m])</p>
</li>
<li><p><strong>Network Outbound</strong>
시각화 방식: Time Series
쿼리: rate(node_network_transmit_bytes_total[5m])</p>
</li>
</ol>
<h4 id="prometheus-target-상태-확인">Prometheus Target 상태 확인</h4>
<p><img src="https://velog.velcdn.com/images/urban-jungle/post/7f46c372-7a03-441c-a576-5c340b30f36d/image.png" alt=""></p>
<p>Node_Exporter와 Prometheus가 모두 UP인 것을 확인</p>
<h4 id="grafana-data-sources-default는-prometheus">Grafana Data Sources default는 Prometheus</h4>
<p><img src="https://velog.velcdn.com/images/urban-jungle/post/e4cb1037-49c7-43c8-9959-36edd1a37c22/image.png" alt=""></p>
<p>Grafana - Data Source 설정에서 Prometheus 연결 확인</p>
<h4 id="grafana-대시보드-전체-뷰">Grafana 대시보드 전체 뷰</h4>
<p><img src="https://velog.velcdn.com/images/urban-jungle/post/8a469e98-5acc-4381-afe9-948767205bf3/image.png" alt=""></p>
<h4 id="network-inbound-설정-화면">Network Inbound 설정 화면</h4>
<p><img src="https://velog.velcdn.com/images/urban-jungle/post/4e12e523-9356-417c-9baf-aa7f41045873/image.png" alt=""></p>
<hr>
<h3 id="troubleshooting--real-world-challenges">Troubleshooting &amp; Real-world Challenges</h3>
<p>이번 프로젝트를 진행하며 여러 시스템 환경 변수와 충돌하는 문제를 직접 마주하고 해결해가는 과정을 통해 실무에서 발생 가능한 고급 이슈에 대한 감각을 키울 수 있었다.</p>
<p>가장 먼저 마주한 문제는 Apache + PHP-FPM 연동 과정에서의 500 Internal Server Error였다. 단순 설정 오류로 치부하지 않고 /var/log/httpd/error_log, PHP-FPM 서비스 로그까지 함께 확인하며 문제 원인을 추적했고, PHP를 proxy_fcgi 방식으로 처리하는 구조를 명확히 이해한 뒤 해결에 성공했다.</p>
<p>또한, 대부분 실습 환경에서는 비활성화하는 SELinux를  enforcing 모드로 유지한 채 작업을 진행했다. 이 과정에서 Apache와 PHP의 모듈 동작 권한, 인증서 파일 접근 권한이 충돌하는 부분을 restorecon, semanage, 로그 분석 등을 통해 해결해나갔다. SELinux 설정을 우회하지 않고 정책 안에서 문제를 풀어낸 점은, 보안을 고려한 시스템 운영 관점에서 특히 주목할 부분이다.</p>
<p>Grafana 설치에서도 yum 저장소가 닫힌 상황에서 포기하지 않고, 공식 .rpm 파일을 직접 다운로드하고 수동으로 설치하여 서비스 등록 및 실행까지 완료했으며, systemd 등록 후 상태 확인, 활성화까지 모든 과정이 자동화될 수 있게 구성했다.</p>
<p>마지막으로, Grafana 대시보드 구성에서도 단순 시각화가 아닌 실제 운영에 적합한 가로 3열 패널 구성, CPU 사용률, 메모리 사용률, 디스크 사용률, Load Average, 네트워크 트래픽까지 핵심 지표들을 시계열 + 게이지 방식으로 정리했다. 데이터 자체를 보여주는 것을 넘어서, 실시간 상황 판단이 가능한 구조로 시각화했다.</p>
<p>이러한 경험을 통해 단순히 설정을 따라 하기보다는, 문제가 발생했을 때 이를 분석하고 실무 환경에서도 적용 가능한 방식으로 직접 해결해보는 사고력과 기술 실천력을 갖추게 되었다고 느꼈다.</p>
<p>(자세한 트러블 슈팅 항목 -&gt; Troubleshooting Details)</p>
<hr>
<h3 id="system-architecture-diagram">System Architecture Diagram</h3>
<p><img src="https://velog.velcdn.com/images/urban-jungle/post/8856e0e6-fb85-49ef-a17f-f55653ff5f42/image.png" alt=""></p>
<hr>
<h3 id="strengths-of-the-system">Strengths of the System</h3>
<p>이번 프로젝트에서 구축한 시스템은 단순한 WordPress 설치를 넘어, 보안성, 확장성, 자동화, 가시성을 모두 고려한 종합적인 인프라 환경이다. 실무에 바로 적용 가능한 구조로 구성했으며, 다음과 같은 강점을 갖고 있다.</p>
<p><strong>1. 보안성 중심의 구성</strong>
SELinux를 Enforcing 모드로 유지한 채 모든 설정을 적용함으로써, 시스템 단에서의 정책 기반 보안을 실현했다. 또한, firewalld로 포트 접근 제어, ModSecurity(WAF)를 통한 웹 공격 차단 설정까지 적용하여 실제 서비스 수준의 보안 레벨을 구현했다. 이외에도, WordPress 내부 코드 수정을 막는 DISALLOW_FILE_EDIT, DISALLOW_FILE_MODS 설정으로 내부 보안 취약점도 방어했다.</p>
<p><strong>2. 운영 관점에서 강력한 가시성 확보</strong>
Prometheus + Node Exporter + Grafana 조합을 통해 실시간으로 CPU, 메모리, 디스크, 네트워크 사용량을 대시보드로 시각화했다. 이를 통해 시스템 과부하나 자원 병목 현상을 사전에 탐지하고 대응할 수 있는 운영 가시성을 갖추었다.</p>
<p><strong>3. 자동화 기반의 효율적 구성</strong>
Ansible을 활용하여 Apache, PHP, MariaDB, WordPress, 모니터링 도구 설치 및 설정을 자동화하여 반복적인 수동 작업을 줄이고 재현 가능하고 일관된 인프라 구축이 가능해졌다. 추후 백업/복구, 배포 자동화까지 확장할 수 있는 기반을 마련했다.</p>
<p><strong>4. 실무 환경과 유사한 구조</strong>
Rocky Linux, php-fpm, mod_ssl, systemctl, VirtualBox, Shell Script, logrotate 등 실제 현업에서 사용하는 기술들로만 구성했다. 단순 학습용이 아닌 실무자가 바로 이해하고 유지보수할 수 있는 구조와 표준 설정 방식을 따랐다.</p>
<p><strong>5. 문제 해결 경험 기반</strong>
SSL 인증서 오류, SELinux 충돌, 500/503 에러, php-fpm 연동 실패, Grafana 수동 설치 등 다양한 이슈를 직접 해결하며 실제 운영 상황에 대응할 수 있는 실무 역량을 체득했다.</p>
<hr>
<h3 id="troubleshooting-details">Troubleshooting Details</h3>
<h4 id="apache-초기-페이지에서-wordpress-화면이-출력되지-않음">Apache 초기 페이지에서 WordPress 화면이 출력되지 않음</h4>
<ul>
<li>원인: 기본 Apache 설정 상태로 /var/www/html/index.html만 표시됨</li>
<li>해결: index.html 제거 후 index.php가 로드되도록 설정</li>
</ul>
<h4 id="grafana-repository-접근-불가-404-오류">Grafana repository 접근 불가 (404 오류)</h4>
<ul>
<li>원인: <a href="https://rpm.grafana.com/oss/rpm/repodata/repomd.xml">https://rpm.grafana.com/oss/rpm/repodata/repomd.xml</a> 접근 실패</li>
<li>해결: dnf 저장소 설정을 통한 설치 대신, .rpm 파일을 수동으로 다운로드 후 dnf install로 설치하도록 플레이북 수정</li>
</ul>
<h4 id="php-fpm-및-wordpress-권한-오류-selinux">php-fpm 및 WordPress 권한 오류 (SELinux)</h4>
<ul>
<li>원인: SELinux enforcing 상태에서 /var/www/html/wordpress 디렉토리 접근 권한 부족</li>
<li>해결: audit.log에서 denied 메시지를 grep하여 문제 위치 확인 후, semanage fcontext 및 restorecon 명령어로 context 재설정</li>
</ul>
<h4 id="화면-ls--z-varwwwhtmlwordpress">화면: ls -Z /var/www/html/wordpress</h4>
<p><img src="https://velog.velcdn.com/images/urban-jungle/post/9f82c20e-3d27-4899-af36-14d15a0d9583/image.png" alt=""></p>
<h4 id="semanage-명령어가-작동하지-않음">semanage 명령어가 작동하지 않음</h4>
<ul>
<li>원인: policycoreutils-python-utils 패키지 미설치</li>
<li>해결: dnf install -y policycoreutils-python-utils로 설치 시도 (단, Grafana 저장소 오류로 이 역시 실패함 → 수동 설치 고려 필요)</li>
</ul>
<h4 id="getenforce로-selinux-상태-확인-시-enforcing-상태-유지">getenforce로 SELinux 상태 확인 시 enforcing 상태 유지</h4>
<ul>
<li>대응: 강제적으로 permissive 모드로 바꾸지 않고, SELinux 정책 수정을 통한 설정 유지 및 실무 친화적인 대응 방식으로 유지</li>
</ul>
<h4 id="wordpress-테마-편집플러그인-설치-불가-상태로-유지">WordPress 테마 편집/플러그인 설치 불가 상태로 유지</h4>
<ul>
<li>의도: wp-config.php 내 DISALLOW_FILE_EDIT 및 DISALLOW_FILE_MODS 설정 적용</li>
<li>결과: 보안 상 WordPress 관리자 UI에서 직접 코드/플러그인 수정 불가, 보안 강화를 위한 설정 완료</li>
</ul>
<h4 id="grafana-대시보드-레이아웃-불편">Grafana 대시보드 레이아웃 불편</h4>
<ul>
<li>문제: 모든 패널이 세로로만 정렬되어 시각적 불편함 발생</li>
<li>해결: 각 패널 편집 → Panel options → Width 비율 수동 조절을 통해 가로 3개 배치로 개선</li>
</ul>
<h4 id="prometheus-접속-시-ssl-오류-ssl_error_rx_record_too_long">Prometheus 접속 시 SSL 오류 (SSL_ERROR_RX_RECORD_TOO_LONG)</h4>
<ul>
<li>원인: https://로 접속했으나 Prometheus는 기본적으로 http:// 프로토콜 사용</li>
<li>해결: 브라우저 주소를 <a href="http://localhost:9090%EC%9C%BC%EB%A1%9C">http://localhost:9090으로</a> 변경하여 정상 접근</li>
</ul>
<h4 id="apache-설정-구문-오류-발생-여부-확인">Apache 설정 구문 오류 발생 여부 확인</h4>
<ul>
<li>조치: apachectl configtest 명령어로 구문 확인</li>
<li>출력: &quot;Syntax OK&quot; 메시지로 설정 정상 여부 확인</li>
</ul>
<h4 id="wordpress-내부-플러그인-관련-오류-처리">WordPress 내부 플러그인 관련 오류 처리</h4>
<ul>
<li>원인: Wordfence 설치 후 관리자 패널이 작동하지 않거나 로그인 차단 이슈 발생 가능성</li>
<li>조치: 2FA 설정 및 경고 이메일 확인, 로그인 제한 조건 재설정하여 정상 복구</li>
</ul>
<hr>
<h3 id="conclusion--what-i-learned">Conclusion &amp; What I Learned</h3>
<p>이번 SecureWP 프로젝트를 통해 시스템 인프라의 계획-구축-보안 강화-모니터링-문제 해결에 이르는 전 과정을 실습하며, 현업에서도 필요한 기술 역량을 종합적으로 익힐 수 있었다. 단순히 워드프레스를 설치하는 것을 넘어, 보안 강화를 위한 Wordfence 설정, 2FA 인증, SELinux 설정, 방화벽 규칙 구성 등 실무에서 반드시 필요한 절차들을 직접 수행했다.</p>
<p>특히 Ansible을 활용한 자동화 구성 관리는 서버 세팅의 일관성과 반복 가능성을 확보하는 데 큰 도움이 되었고, 문제가 발생했을 때 로그 분석, SELinux 트러블슈팅, 서비스 상태 확인, 포트 상태 점검 등 다양한 디버깅 스킬을 통해 실시간 문제 해결 경험을 쌓을 수 있었다. 또한 Prometheus + Node Exporter + Grafana 연동을 통해 시스템 자원(CPU, 메모리, 디스크, 네트워크)의 사용 현황을 시각화하여 시스템 상태를 한눈에 파악할 수 있는 모니터링 환경을 구현한 점은 큰 성과였다.</p>
<p>이 과정을 통해 단순한 기능 구현을 넘어 &quot;보안&quot;, &quot;운영&quot;, &quot;가시성&quot;, &quot;자동화&quot;, &quot;유지보수&quot;를 고려하는 인프라 마인드셋을 기를 수 있었고, 실무 환경에서 예기치 못한 이슈가 발생하더라도 원인을 빠르게 파악하고 대응할 수 있는 기반 지식과 경험을 확보할 수 있었다.</p>
<p>또한 기록 중심의 작업 방식으로, 모든 설정 및 트러블슈팅 과정을 문서화하고, 스크린샷 등 시각적 증거까지 확보함으로써 신뢰도 높은 기술 포트폴리오를 완성할 수 있었다. 이 프로젝트는 단지 기술 스택을 나열하는 것을 넘어서, 직접 경험하고 해결한 실전 중심의 프로젝트였기에 그 의미가 더욱 크다고 느껴진다.</p>
<p><img src="https://velog.velcdn.com/images/urban-jungle/post/54e24e75-ec7d-4764-9f70-7881401fa8cd/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[CAB TA 4기 22일차의 기록]]></title>
            <link>https://velog.io/@urban-jungle/CAB-TA-4%EA%B8%B0-22%EC%9D%BC%EC%B0%A8%EC%9D%98-%EA%B8%B0%EB%A1%9D</link>
            <guid>https://velog.io/@urban-jungle/CAB-TA-4%EA%B8%B0-22%EC%9D%BC%EC%B0%A8%EC%9D%98-%EA%B8%B0%EB%A1%9D</guid>
            <pubDate>Tue, 15 Apr 2025 01:32:46 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/urban-jungle/post/d63e4fe7-476b-4194-a139-37e9a4006b18/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/urban-jungle/post/1391fe91-1b5e-4488-b18b-88bc8ac1185e/image.png" alt=""></p>
<h3 id="securewp-infra-automated-wordpress-system">SecureWP Infra: Automated WordPress System</h3>
<h4 id="infrastructure-hardening-with-ansible-grafana-and-wordfence-on-rocky">Infrastructure Hardening with Ansible, Grafana, and Wordfence on Rocky</h4>
<hr>
<h2 id="project-overview">Project Overview</h2>
<p>이 프로젝트는 실무 환경 수준의 보안성과 운영 자동화를 목표로, Rocky Linux 기반의 WordPress 인프라를 직접 구축한 경험을 담고 있다.</p>
<p>단순 설치가 아닌, 보안 강화, 자동화 구성, 실시간 모니터링 체계 구축이라는 세 가지 핵심을 중심으로 설계했다.</p>
<p>Ansible을 활용해 Apache, PHP-FPM, MariaDB, WordPress, 방화벽, 로그 분석 도구까지 자동화 구성하였으며, SELinux는 enforcing 모드로 운영하여 보안 정책을 강제 적용했다. 또한, Wordfence 보안 플러그인을 통해 로그인 보호, 2단계 인증, 웹 방화벽을 설정하고, Prometheus + Grafana를 통해 시스템의 CPU, 메모리, 디스크, 네트워크 등의 상태를 시각화하여 실시간 운영 가시성을 확보했다.</p>
<p>진행 과정에서는 실제 장애 상황과 유사한 문제들(php-fpm 503 오류, SELinux 접근 차단, 인증서 발급 실패 등)을 직접 해결하며, 문제 분석 및 구조적인 운영 능력을 체득했다.</p>
<p>단순히 돌아가는 시스템이 아닌, 보안과 안정성을 모두 갖춘 실전형 인프라 환경을 자동화 방식으로 완성한 것이 이 프로젝트의 핵심이다.</p>
<hr>
<h2 id="technology-stack--justification">Technology Stack &amp; Justification</h2>
<h3 id="운영체제-및-가상환경">운영체제 및 가상환경</h3>
<h4 id="rocky-linux-95">Rocky Linux 9.5</h4>
<p>RHEL 계열의 오픈소스 OS로, 기업 실무 환경에서 CentOS 대체로 널리 사용되고 있다. SELinux, systemd, firewalld 등 실무에서 자주 접하는 구성 요소들이 탑재되어 있어 실제 서비스 환경과 유사한 조건을 제공한다.</p>
<h4 id="virtualbox">VirtualBox</h4>
<p>독립된 테스트 환경 구축을 위해 사용. 네트워크 설정, 스냅샷 복원 등을 통해 장애 테스트와 복구 실습이 가능하다.</p>
<h3 id="웹애플리케이션-및-데이터베이스">웹/애플리케이션 및 데이터베이스</h3>
<h4 id="apachehttpd">Apache(httpd)</h4>
<p>WordPress와의 호환성과 설정 유연성이 높아 선택했다.</p>
<h4 id="php-fpmfastcgi-process-manager">PHP-FPM(FastCGI Process Manager)</h4>
<p>성능 및 보안 향상을 위해 Apache와 연동하여 사용한다. socket 및 TCP 방식 모두 테스트하며 실무 연동 방식으로 학습했다.</p>
<h4 id="mariadb">MariaDB</h4>
<p>MySQL 호환 오픈소스 DBMS이다. mysqldump를 활용한 백업 및 복구 자동화가 가능하다.</p>
<h3 id="인프라-자동화-및-관리">인프라 자동화 및 관리</h3>
<h4 id="ansible">Ansible</h4>
<p>모든 구성 과정을 role 기반으로 자동화한다. . Apache, PHP, DB, WordPress 설치부터 보안 설정, 백업까지 반복 가능하고 관리가 쉬운 코드 형태로 관리할 수 있다.</p>
<h4 id="shell-script">Shell Script</h4>
<p>일부 로컬 설정 및 수동 작업을 위한 보조 자동화 수단으로 사용한다.</p>
<h4 id="powershell">PowerShell</h4>
<p>Windows 기반 서버 환경 연동 및 향후 확장성을 고려해 연습, 적용 예정이다.</p>
<h3 id="보안-및-방화벽">보안 및 방화벽</h3>
<h4 id="selinux-enforcing-모드">SELinux (Enforcing 모드)</h4>
<p>서비스 접근 제어 및 시스템 내부 권한을 관리한다. 운영 중 발생하는 차단 로그를 바탕으로 보안 예외 정책을 적용한다.</p>
<h4 id="firewalld">Firewalld</h4>
<p>포트 기반으로 접근을 제어한다. HTTPS 443, SSH 22 등 필요한 포트만 열어 실무 수준의 제어를 학습했다.</p>
<h4 id="modsecurity-waf">ModSecurity (WAF)</h4>
<p>웹 애플리케이션 방화벽이다. Apache와 연동하여, OWASP Core Rule Set을 적용, 테스트한다.</p>
<h4 id="wordfence">Wordfence</h4>
<p>WordPress 환경 전용 보안 플러그인이다. 관리자 로그인 제한, 이중 인증, 실시간 공격 탐지 기능으로 실무에서 가장 널리 사용된다.</p>
<h3 id="모니터링-및-시각화">모니터링 및 시각화</h3>
<h4 id="prometheus">Prometheus</h4>
<p>Node Exporter를 통해 시스템 지표를 수집한다. YAML 기반 설정으로 exporter을 연동한다.</p>
<h4 id="grafana">Grafana</h4>
<p>Prometheus에서 수집한 데이터를 시각화한다. CPU, 메모리, 디스크, 네트워크 트래픽 등을 Stat, Bar Gauge, Table 등의 시각 도구로 표현한다.</p>
<h4 id="logrotate-journalctl">logrotate, journalctl</h4>
<p>로그 순환 및 시스템 로그 분석을 담당한다. 주기적인 로그 정리를 통한 운영 안정성을 확보한다.</p>
<p>이 스택들은 실제 운영 환경에서 널리 사용되는 구성 요소들로, 단순한 구축이 아닌 실무 수준의 문제 해결 경험을 쌓기 위한 목적으로 선정했다.</p>
<hr>
<p>프로젝트는 VirtualBox 가상머신을 기반으로 진행되었으며, 테스트와 장애 복구 연습을 고려해 스냅샷 기능을 적극 활용했다.</p>
<p>기본 운영체제는 Rocky Linux 9.5 Minimal ISO를 사용하였고, 설치 시 GUI 없이 CLI 환경을 선택하여 리눅스 시스템 관리 능력 향상에 초점을 맞췄다.</p>
<hr>
<h2 id="environment-setup">Environment Setup</h2>
<h3 id="가상머신-구성">가상머신 구성</h3>
<h4 id="virtualbox-version">VirtualBox Version</h4>
<p>7.0.10</p>
<h4 id="설정-사양">설정 사양</h4>
<p>CPU 2코어, RAM 4GB, 저장공간 40GB</p>
<h4 id="네트워크-어댑터">네트워크 어댑터</h4>
<p>브리지 어댑터로 설정하여 외부 인터넷 접근 및 내부 IP 고정이 가능하게 구성했다.</p>
<h3 id="초기-설정-항목">초기 설정 항목</h3>
<ul>
<li>사용자 계정:    root, jm 일반 사용자 구성</li>
<li>Hostname:    securewp.local 설정</li>
<li>SELinux 설정:    설치 후 enforcing 상태 확인 및 정책 적용 준비</li>
<li>패키지 캐시 클리어:     dnf clean all 수행 후 dnf update로 최신화</li>
<li>EPEL 및 Remi 저장소 추가:    최신 PHP, MariaDB 패키지 설치를 위한 저장소 구성</li>
<li>timezone 설정:    Asia/Seoul 설정 및 시간 동기화 chronyd 구성</li>
<li>방화벽 초기 설정:    firewalld zone 확인 및 HTTP, HTTPS, SSH 포트 개방</li>
</ul>
<h3 id="getenforce-출력">getenforce 출력</h3>
<p><img src="https://velog.velcdn.com/images/urban-jungle/post/60c6f011-50d7-4ecc-a48c-fd8320d8b1b7/image.png" alt=""></p>
<h3 id="스냅샷-관리-전략">스냅샷 관리 전략</h3>
<ul>
<li>Snapshot 1 (Wordfence 설치 전): Apache, PHP, DB, WordPress 설치 완료</li>
<li>Snapshot 2 (PHP 보안 설정 완료 시점)</li>
<li>Snapshot 3 (Grafana 대시보드 구성 완료)</li>
</ul>
<p>실습 중 오류 발생 시 지점 복구 후 재진행 가능하도록 설계, 실무에서 시스템 복구/운영 경험까지 학습할 수 있도록 구성했다.</p>
<hr>
<h2 id="infrastructure-automation-with-ansible">Infrastructure Automation with Ansible</h2>
<p>WordPress 인프라 전체 구성은 수동 설정이 아닌, Ansible 역할 기반(Role-based) 자동화로 설계했습니다.
각 컴포넌트(Apache, PHP, MariaDB, WordPress 등)를 독립된 Role로 나누고, playbook 하나만 실행하면 시스템이 일관되게 설정되도록 구성하였습니다.</p>
<h3 id="디렉토리-구조">디렉토리 구조</h3>
<p><img src="https://velog.velcdn.com/images/urban-jungle/post/8595097e-20c9-49dd-b420-9d3cbe7769fa/image.png" alt=""></p>
<h3 id="주요-role-및-구성-목적">주요 Role 및 구성 목적</h3>
<ul>
<li>Apache: httpd 설치 및 가상호스트 설정(wordpress-ssl.conf)</li>
<li>PHP: PHP 8.1 설치 및 FPM 연동 (Remi repo 활용)</li>
<li>MariaDB: DB설치, root 계정 설정, WordPress용 DB/user 생성</li>
<li>Wordpress: Wordpress 압축 해제, wp-config.php 자동 구성</li>
<li>Firewall: firewalld 포트 개방 (80, 443, 22) 및 서비스 등록</li>
<li>SELinux: enforcing 유지, Wordpress 디렉토리 보안 context 설정</li>
<li>PHP_Hardening: php.ini 파일 보안 설정 적용 (expose.php, disable_functions 등)</li>
<li>Logwatch: 시스템 로그 리포트 자동화 (메일 발송도 구성 가능)</li>
</ul>
<h3 id="실행-방법">실행 방법</h3>
<p><img src="https://velog.velcdn.com/images/urban-jungle/post/c246f472-797a-499d-866e-0f834f6c56a3/image.png" alt=""></p>
<h3 id="systemctl-status-httpd-출력화면">systemctl status httpd 출력화면</h3>
<p><img src="https://velog.velcdn.com/images/urban-jungle/post/0a479382-ea49-42e1-af4c-bd82332c7793/image.png" alt=""></p>
<h3 id="자동화-구성-예시-apache-role-내-tasksmainyml">자동화 구성 예시 (apache role 내 tasks/main.yml)</h3>
<p><img src="https://velog.velcdn.com/images/urban-jungle/post/6da3ebf7-9b88-4559-a722-28085ed6fade/image.png" alt=""></p>
<ul>
<li>Role 분리: 각 서비스 단위로 역할이 구분되어 있어 유지보수, 재사용, 확장이 용이함</li>
<li>재현 가능성: 스냅샷 없이도 ansible-playbook 한 번으로 환경 구성 가능</li>
<li>실제 정책 반영: SELinux context, 파일 권한, php.ini 보안 설정 등 실제 운영환경에서 요구되는 설정 반영</li>
</ul>
<hr>
<h2 id="security-hardening--firewall-configuration">Security Hardening &amp; Firewall Configuration</h2>
<p>이 단계에서는 시스템 접근 제어, 파일 권한 보호, 웹 애플리케이션 공격 방어를 중심으로 기초 보안 설정을 강화했다.
보안 강화를 위한 핵심 요소는 SELinux, firewalld, ModSecurity, Wordfence 네 가지이다.</p>
<h3 id="selinux-정책-적용enforcing-유지">SELinux 정책 적용(enforcing 유지)</h3>
<h4 id="상태-확인">상태 확인</h4>
<p>getenforce 명령어로 SELinux 상태를 Enforcing으로 유지함으로써 비정상 접근을 정책 기반으로 차단한다.</p>
<h4 id="context-설정">Context 설정</h4>
<p>웹 서버 디렉토리(/var/www/html/wordpress)에 대해 httpd_sys_rw_content_t context를 부여했다.</p>
<p><img src="https://velog.velcdn.com/images/urban-jungle/post/78f4bc7d-92f9-4b5a-971b-0b4855b8ca1d/image.png" alt=""></p>
<h4 id="오류-해결-경험">오류 해결 경험</h4>
<p>php-fpm 연동 중 SELinux 차단 로그(avc: denied)를 journalctl -xe, ausearch -m avc로 분석해 해결</p>
<h3 id="방화벽-구성-firewalld">방화벽 구성 (firewalld)</h3>
<h4 id="firewalld-서비스-상태-확인-및-활성화">firewalld 서비스 상태 확인 및 활성화</h4>
<p><img src="https://velog.velcdn.com/images/urban-jungle/post/048cc81c-0832-4335-8fa5-2011f85191b0/image.png" alt=""></p>
<h4 id="http-https-ssh-포트-개방">HTTP, HTTPS, SSH 포트 개방</h4>
<p><img src="https://velog.velcdn.com/images/urban-jungle/post/525f619f-e74e-4c54-927c-9179d45b7340/image.png" alt=""></p>
<h4 id="zone-확인">zone 확인</h4>
<p><img src="https://velog.velcdn.com/images/urban-jungle/post/50f50bd9-251a-48ba-8161-72055883bf98/image.png" alt=""></p>
<h3 id="웹방화벽-구성-modsecurity">웹방화벽 구성 (ModSecurity)</h3>
<h4 id="설치-및-활성화">설치 및 활성화</h4>
<p><img src="https://velog.velcdn.com/images/urban-jungle/post/81018baf-246c-454e-8315-e679127927e8/image.png" alt=""></p>
<h4 id="기본-룰셋-확인-및-적용">기본 룰셋 확인 및 적용</h4>
<p>OWASP CRS 연동 가능하며, /etc/httpd/conf.d/mod_security.conf에서 설정을 변경한다.</p>
<h4 id="기능">기능</h4>
<p>SQL Injection, XSS, 파일 포함 공격 등을 탐지하고 차단한다.</p>
<h3 id="워드프레스-보안-플러그인-설정-wordfence">워드프레스 보안 플러그인 설정 (Wordfence)</h3>
<ul>
<li>2FA, 로그인 제한, 관리자 알림 이메일 활성화</li>
<li>Advanced Protection 모드: 모든 PHP 요청을 방화벽이 사전 처리</li>
<li>실시간 공격 탐지 대시보드 구성 완료</li>
</ul>
<h4 id="실무-관점에서의-강점">실무 관점에서의 강점</h4>
<ul>
<li><strong>SELinux</strong>: Enforcing 유지 -&gt; 시스템 내 비인가 접근 제어 정책</li>
<li><strong>Firewalld</strong>: 80/443/22 포트 제한 개방 -&gt; 외부 접근 최소화</li>
<li><strong>ModSecurity</strong>: 활성화 -&gt; 공격 유형 탐지 및 대응</li>
<li><strong>Wordfence</strong>: 로그인 보안 + 실시간 탐지 -&gt; WordPress 특화 보호 기능</li>
</ul>
<h3 id="wordpress-내부-메뉴-접근-제어">Wordpress 내부 메뉴 접근 제어</h3>
<p><img src="https://velog.velcdn.com/images/urban-jungle/post/f284c95c-b257-41e4-bfe3-5989a3822129/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/urban-jungle/post/ef9a90e4-e77f-40a2-a0e9-af2b1906abc0/image.png" alt=""></p>
<p>Appearance의 Theme Editor와 Plugin의 Add New Plugin이 차단된 모습을 볼 수 있다.</p>
<h3 id="wordfence-dashboard">Wordfence Dashboard</h3>
<p><img src="https://velog.velcdn.com/images/urban-jungle/post/73541be6-24ae-4d70-bc9c-9525d27c1774/image.png" alt=""></p>
<h3 id="wordfence-2fa2중-잠금-설정">Wordfence 2FA(2중 잠금) 설정</h3>
<p><img src="https://velog.velcdn.com/images/urban-jungle/post/74e72b0a-376d-44a8-b1d6-e261341ec35f/image.png" alt=""></p>
<hr>
<p>다음 날에 이어서..</p>
<p><img src="https://velog.velcdn.com/images/urban-jungle/post/8984bfc0-03ca-4dd4-8bd6-1cbade5a91da/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[<프로그래머스 299305> 대장균들의 자식의 수 구하기
 (MySQL)]]></title>
            <link>https://velog.io/@urban-jungle/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-299305-%EB%8C%80%EC%9E%A5%EA%B7%A0%EB%93%A4%EC%9D%98-%EC%9E%90%EC%8B%9D%EC%9D%98-%EC%88%98-%EA%B5%AC%ED%95%98%EA%B8%B0-MySQL</link>
            <guid>https://velog.io/@urban-jungle/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-299305-%EB%8C%80%EC%9E%A5%EA%B7%A0%EB%93%A4%EC%9D%98-%EC%9E%90%EC%8B%9D%EC%9D%98-%EC%88%98-%EA%B5%AC%ED%95%98%EA%B8%B0-MySQL</guid>
            <pubDate>Mon, 14 Apr 2025 08:14:10 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/urban-jungle/post/ce47dae5-c287-4f4a-aa86-f9d85156e355/image.png" alt=""></p>
<p><a href="https://school.programmers.co.kr/learn/courses/30/lessons/299305">https://school.programmers.co.kr/learn/courses/30/lessons/299305</a>
Level: 3</p>
<hr>
<p>[문제 설명]</p>
<p>대장균들은 일정 주기로 분화하며, 분화를 시작한 개체를 부모 개체, 분화가 되어 나온 개체를 자식 개체라고 한다.
다음은 실험실에서 배양한 대장균들의 정보를 담은 <code>ECOLI_DATA</code> 테이블이다. <code>ECOLI_DATA</code> 테이블의 구조는 다음과 같으며, <code>ID</code>, <code>PARENT_ID</code>, <code>SIZE_OF_COLONY</code>, <code>DIFFERENTIATION_DATE</code>, <code>GENOTYPE</code> 은 각각 대장균 개체의 <code>ID</code>, 부모 개체의 <code>ID</code>, 개체의 크기, 분화되어 나온 날짜, 개체의 형질을 나타낸다.</p>
<p><img src="https://velog.velcdn.com/images/urban-jungle/post/5fa846b7-96f6-49da-9f5d-5861a9af5487/image.png" alt=""></p>
<p>최초의 대장균 개체의 <code>PARENT_ID</code> 는 <code>NULL</code> 값이다.</p>
<p>[문제]</p>
<p>대장균 개체의 ID(<code>ID</code>)와 자식의 수(<code>CHILD_COUNT</code>)를 출력하는 SQL 문을 작성해주세요. 자식이 없다면 자식의 수는 0으로 출력해주세요. 이때 결과는 개체의 ID 에 대해 오름차순 정렬해주세요.</p>
<hr>
<pre><code>SELECT A.ID, COUNT(B.ID) AS CHILD_COUNT
FROM ECOLI_DATA A
LEFT JOIN ECOLI_DATA B
ON A.ID = B.PARENT_ID
GROUP BY A.ID
ORDER BY A.ID ASC;</code></pre><hr>
<p>테이블을 둘로 나눠 풀이하는 것에 점점 익숙해져가는 것 같다.</p>
<p>자식의 수가 0인 ID들도 출력해줘야 하기 때문에,
INNER JOIN이 아닌 LEFT JOIN을 써줘야만 한다.</p>
<p>그 외에 딱히 어려운 부분은 없다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[CAB TA 4기 21일차의 기록]]></title>
            <link>https://velog.io/@urban-jungle/CAB-TA-4%EA%B8%B0-21%EC%9D%BC%EC%B0%A8%EC%9D%98-%EA%B8%B0%EB%A1%9D</link>
            <guid>https://velog.io/@urban-jungle/CAB-TA-4%EA%B8%B0-21%EC%9D%BC%EC%B0%A8%EC%9D%98-%EA%B8%B0%EB%A1%9D</guid>
            <pubDate>Wed, 09 Apr 2025 05:18:44 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/urban-jungle/post/3114f25a-ca69-4b69-bd5e-d6f7814903e2/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/urban-jungle/post/2fdc46be-f90b-44c7-b1e4-6a704bed0364/image.png" alt=""></p>
<h2 id="dns-zone--zone-file-정리">DNS Zone &amp; Zone File 정리</h2>
<h3 id="dns-zone-이란">DNS Zone 이란?</h3>
<ul>
<li>DNS 정보를 관리하기 위한 논리적인 단위</li>
<li>계층적으로 구성 (root → TLD → subdomain)</li>
<li>Zone = 하나의 도메인에 대한 DNS 관리 범위</li>
<li>각 Zone은 다른 관리자가 관리 가능</li>
<li>하나의 도메인 안에서도 Zone을 나누어 관리 가능</li>
</ul>
<h3 id="zone-파일이란">Zone 파일이란?</h3>
<ul>
<li>텍스트 형식의 설정 파일</li>
<li>해당 Zone에 대한 <strong>DNS 레코드(RR)</strong>를 포함함</li>
<li>DNS 서버가 이를 데이터베이스처럼 참조</li>
</ul>
<h3 id="zone-파일-구성-요소">Zone 파일 구성 요소</h3>
<h4 id="시작-soa-start-of-authority-레코드">시작: SOA (Start of Authority) 레코드</h4>
<ul>
<li>Zone의 시작을 알림</li>
<li>마스터/슬레이브 서버 간 Zone Transfer 기준 정보 제공</li>
</ul>
<pre><code>@   IN  SOA ns1.example.com. admin.example.com. (
        2025042801 ; serial
        3600       ; refresh (1시간)
        1800       ; retry (30분)
        604800     ; expire (7일)
        86400 )    ; minimum TTL (1일)</code></pre><p><code>serial</code>:    변경 시마다 증가 (슬레이브는 이걸 기준으로 동기화 여부 판단)
<code>refresh</code>:    슬레이브가 마스터에게 변경 확인 주기
<code>retry</code>:    실패했을 경우 재시도 주기
<code>expire</code>:    마스터와의 연결이 끊긴 후 슬레이브가 데이터를 폐기할 시간
<code>minimum TTL</code>:    캐시 수명</p>
<h4 id="그-외-레코드들">그 외 레코드들</h4>
<p><code>NS(Name Server)</code>: 권한 있는 네임서버</p>
<p><code>A</code>: IPv4 주소</p>
<p><code>AAAA</code>: IPv6 주소</p>
<p><code>MX</code>: 메일 서버</p>
<p><code>CNAME</code>: 별칭</p>
<p><code>PTR</code>: 역방향 주소 매핑</p>
<p><code>TXT</code>: 인증 및 설명 정보 (ex. SPF, DKIM)</p>
<h3 id="zone-파일-취득-방법">Zone 파일 취득 방법</h3>
<h4 id="자체-운영-중인-dns-서버">자체 운영 중인 DNS 서버</h4>
<ul>
<li>경로: <code>/var/named/도메인명.zone</code></li>
</ul>
<h4 id="호스팅-제공-업체-이용-시">호스팅 제공 업체 이용 시</h4>
<ul>
<li>관리자 웹페이지에서 Zone File Export 기능 사용</li>
</ul>
<hr>
<h2 id="soa-레코드--실습-예시">SOA 레코드 &amp; 실습 예시</h2>
<h3 id="soa-레코드란">SOA 레코드란?</h3>
<ul>
<li>Start of Authority</li>
<li>DNS Zone의 시작점을 알리는 레코드</li>
<li>Zone 파일 내 가장 먼저 위치</li>
<li>Primary(마스터) DNS 서버의 정보와 슬레이브 DNS의 동기화 기준을 포함</li>
</ul>
<h3 id="soa-레코드-구조">SOA 레코드 구조</h3>
<pre><code>$TTL 3H
@  3600 IN  SOA  ns.icann.org. noc.dns.icann.org. (
           2020080302  ; Serial
           7200        ; Refresh
           3600        ; Retry
           1209600     ; Expire
           3600 )      ; Minimum TTL</code></pre><p><code>ns.icann.org.</code>:    Primary 네임서버
<code>noc.dns.icann.org.</code>:    관리자 이메일 → <code>noc@dns.icann.org</code>
<code>2020080302</code>:    시리얼 번호 (slave 서버가 최신 Zone 정보를 갖고 있는지 판단 기준)
<code>7200 (2시간)</code>:    Refresh – 슬레이브가 마스터에 변경사항 확인 주기
<code>3600 (1시간)</code>:    Retry – 마스터 응답 실패 시 재시도 시간
<code>1209600 (14일)</code>:    Expire – 슬레이브가 마스터로부터 응답 못 받을 경우 zone 폐기 시간
<code>3600 (1시간)</code>:    Minimum TTL – 레코드를 캐시하는 기본 시간</p>
<h3 id="실습-dig-명령으로-soa-조회">실습: dig 명령으로 SOA 조회</h3>
<p><strong><code>blog.naver.com</code> 의 SOA 레코드</strong></p>
<p><code>$ dig blog.naver.com SOA</code></p>
<p><strong>결과</strong></p>
<pre><code>;; AUTHORITY SECTION:
nheos.com. 180 IN SOA gns1.nheos.com. hostmaster.nheos.com. 2021081901 10800 3600 604800 180</code></pre><p><code>gns1.nheos.com.</code>:    Primary DNS
<code>hostmaster.nheos.com.</code>:    관리자 이메일 → <code>hostmaster@nheos.com</code>
<code>10800</code>:    Refresh → 3시간
<code>3600</code>:    Retry → 1시간
<code>604800</code>:    Expire → 7일
<code>180</code>:    TTL → 180초 (캐시 유지 시간)</p>
<p><strong><code>naver.com</code> 의 SOA 레코드</strong></p>
<p><code>$ dig naver.com SOA</code></p>
<p><strong>결과</strong></p>
<pre><code>;; ANSWER SECTION:
naver.com. 300 IN SOA ns1.naver.com. webmaster.naver.com. 2021082001 21600 1800 1209600 180</code></pre><p><code>ns1.naver.com.</code>:    Primary DNS
<code>webmaster.naver.com.</code>:    관리자 이메일 → <code>webmaster@naver.com</code>
<code>21600</code>:    Refresh → 6시간
<code>1800</code>:    Retry → 30분
<code>1209600</code>:    Expire → 14일
<code>180</code>:    TTL → 180초</p>
<hr>
<h2 id="dns-레코드-종류-및-설명">DNS 레코드 종류 및 설명</h2>
<p><code>A</code>    :IPv4 주소를 도메인에 매핑 (예: <code>example.com → 123.45.67.89</code>)
<code>AAAA</code>:    IPv6 주소를 도메인에 매핑 (예: <code>example.com → 2001:0db8::1</code>)
<code>CNAME</code>:    도메인의 별칭 설정 (예: <code>www.example.com → example.com</code>)
<code>MX</code>:    메일 서버 주소 지정 (<code>@example.com</code> 이메일을 어떤 서버로 전달할지 정의)
<code>PTR</code>:    IP → 도메인 역방향 질의용 (메일 수신 측에서 발신 서버의 신뢰 검증용)
<code>TXT</code>:    도메인 관련 정보 텍스트로 저장 (예: SPF, DKIM, DMARC 정책 등)
<code>NS</code>:    도메인을 관리하는 네임서버 지정 (<code>example.com → ns1.example.com</code>)
<code>URL</code>:    도메인을 특정 URL로 리디렉션 (HTTP 리디렉션 방식)
<code>Framed URL</code>:    URL 리디렉션 + 주소창에 원래 도메인 그대로 유지 (프레임 내 로딩)</p>
<hr>
<h2 id="dns-서버-구성-순서">DNS 서버 구성 순서</h2>
<h3 id="패키지-설치">패키지 설치</h3>
<p><code>yum -y install bind bind-utils</code></p>
<h3 id="네트워크-설정">네트워크 설정</h3>
<ul>
<li>고정 IP 주소 설정 (예: <code>192.168.56.100</code>)</li>
<li>DNS 서버 주소는 <code>/etc/resolv.conf</code> 또는 <code>nmcli</code>로 설정</li>
<li><code>hostnamectl set-hostname dns-server.cccr.org</code></li>
</ul>
<h3 id="설정-파일-편집">설정 파일 편집</h3>
<ul>
<li>메인 설정: <code>/etc/named.conf</code></li>
<li>Zone 파일 경로: <code>/var/named/도메인.zone</code></li>
</ul>
<h3 id="서비스-시작-및-활성화">서비스 시작 및 활성화</h3>
<p><code>systemctl start named</code>
<code>systemctl enable named</code></p>
<h3 id="방화벽-포트-오픈">방화벽 포트 오픈</h3>
<p><code>firewall-cmd --add-service=dns --permanent</code>
<code>firewall-cmd --reload</code></p>
<hr>
<h2 id="dns-도메인-확인-명령어">DNS 도메인 확인 명령어</h2>
<p><code>nslookup www.naver.com</code>:    도메인 이름 → IP 주소 확인
<code>nslookup</code> 후 <code>&gt; 10.0.2.100</code>:    IP 주소 → 도메인 확인
<code>host www.naver.com</code>:    도메인 정보 요약 출력
<code>host -t A www.naver.com</code>:    A 레코드 정보 조회
<code>host -t PTR 10.0.2.100</code>:    PTR 레코드 조회 (역방향 DNS)
<code>dig www.naver.com</code>:    상세 DNS 질의 결과 출력
<code>dig -x 10.0.2.100</code>:    역방향 질의</p>
<hr>
<h2 id="dns-서버-구성-실습">DNS 서버 구성 실습</h2>
<h3 id="초기-세팅">초기 세팅</h3>
<h4 id="패키지-설치-1">패키지 설치</h4>
<p><code>dnf -y install bind bind-utils</code></p>
<h4 id="방화벽-포트-오픈-1">방화벽 포트 오픈</h4>
<p><code>firewall-cmd --add-service=dns --permanent</code>
<code>firewall-cmd --reload</code></p>
<h4 id="네트워크-설정-1">네트워크 설정</h4>
<p><code>ip addr add 10.0.2.10/24 dev ethX</code>
<code>hostnamectl set-hostname dns.test.example.com</code></p>
<h3 id="namedconf-설정-정방향">named.conf 설정 (정방향)</h3>
<p><code>vi /etc/named.conf</code></p>
<pre><code>options {
    listen-on port 53 { any; };
    listen-on-v6 port 53 { none; };
    directory       &quot;/var/named&quot;;
    allow-query     { any; };
};

zone &quot;test.example.com&quot; IN {
    type master;
    file &quot;test.example.com.zone&quot;;
};</code></pre><h3 id="정방향-zone-파일-생성">정방향 zone 파일 생성</h3>
<p><code>cd /var/named</code>
<code>cp named.empty test.example.com.zone</code>
<code>vi test.example.com.zone</code></p>
<pre><code>$TTL 3H
@   IN  SOA test.example.com. root.test.example.com. (
            0       ; serial
            1D      ; refresh
            1H      ; retry
            1W      ; expire
            3H )    ; minimum

    NS      dns.test.example.com.
    A       10.0.2.2
dns     A   10.0.2.10
www     A   10.0.2.20
ftp     A   10.0.2.30
mail    A   10.0.2.40
blog    A   10.0.2.50</code></pre><p><code>chmod 660 test.example.com.zone</code>
<code>chown :named test.example.com.zone</code></p>
<h3 id="역방향-zone-구성">역방향 zone 구성</h3>
<p><code>vi /etc/named.conf</code></p>
<pre><code>zone &quot;2.0.10.in-addr.arpa&quot; IN {
    type master;
    file &quot;10.0.2.0.zone&quot;;
};</code></pre><p><code>cp test.example.com.zone 10.0.2.0.zone</code>
<code>vi 10.0.2.0.zone</code></p>
<pre><code>$TTL 3H
@   IN  SOA test.example.com. root.test.example.com. (
            0       ; serial
            1D      ; refresh
            1H      ; retry
            1W      ; expire
            3H )    ; minimum

    NS      dns.test.example.com.
    A       10.0.2.2

10  PTR dns.test.example.com.
20  PTR www.test.example.com.
30  PTR ftp.test.example.com.
40  PTR mail.test.example.com.
50  PTR blog.test.example.com.</code></pre><p><code>chmod 660 10.0.2.0.zone</code>
<code>chown :named 10.0.2.0.zone</code></p>
<h3 id="서비스-시작">서비스 시작</h3>
<p><code>systemctl enable named --now</code></p>
<hr>
<h2 id="master--slave-구성">Master / Slave 구성</h2>
<h3 id="마스터-dns-설정-변경">마스터 DNS 설정 변경</h3>
<p><code>vi /etc/named.conf</code></p>
<pre><code>zone &quot;test.example.com&quot; IN {
    type master;
    file &quot;test.example.com.zone&quot;;
    allow-transfer { 10.0.2.101; };
};

zone &quot;2.0.10.in-addr.arpa&quot; IN {
    type master;
    file &quot;10.0.2.0.zone&quot;;
    allow-transfer { 10.0.2.101; };
};</code></pre><h3 id="zone-파일-변경">zone 파일 변경</h3>
<p><code>vi /var/named/test.example.com.zone</code></p>
<pre><code>    NS  dns.test.example.com.
    NS  slave.test.example.com.
    ...
slave   A   10.0.2.101</code></pre><p><code>vi /var/named/10.0.2.0.zone</code></p>
<pre><code>    NS  dns.test.example.com.
    NS  slave.test.example.com.
    ...
101 PTR slave.test.example.com.</code></pre><hr>
<h2 id="slave-dns-서버-구성-실습">Slave DNS 서버 구성 실습</h2>
<h3 id="패키지-설치-2">패키지 설치</h3>
<p><code>dnf -y install bind bind-utils</code></p>
<h3 id="네트워크-및-호스트-설정">네트워크 및 호스트 설정</h3>
<p><code>nmcli con mod ethX ipv4.addresses 10.0.2.101/24</code>
<code>nmcli con mod ethX ipv4.method manual</code>
<code>nmcli con mod ethX ipv4.gateway &quot;&quot;</code>
<code>nmcli con mod ethX ipv4.dns 10.0.2.10</code>
<code>nmcli con up ethX</code></p>
<p><code>hostnamectl set-hostname slave.test.example.com</code></p>
<h3 id="namedconf-설정-slave-dns">named.conf 설정 (Slave DNS)</h3>
<p><code>vi /etc/named.conf</code></p>
<pre><code>options {
    listen-on port 53 { any; };
    listen-on-v6 port 53 { none; };
    directory       &quot;/var/named&quot;;
    dump-file       &quot;/var/named/data/cache_dump.db&quot;;
    statistics-file &quot;/var/named/data/named_stats.txt&quot;;
    memstatistics-file &quot;/var/named/data/named_mem_stats.txt&quot;;
    recursing-file  &quot;/var/named/data/named.recursing&quot;;
    secroots-file   &quot;/var/named/data/named.secroots&quot;;
    allow-query     { any; };
};

zone &quot;test.example.com&quot; IN {
    type slave;
    masters { 10.0.2.10; };
    file &quot;slaves/test.example.com.zone&quot;;
    notify no;
};

zone &quot;2.0.10.in-addr.arpa&quot; IN {
    type slave;
    masters { 10.0.2.10; };
    file &quot;slaves/10.0.2.0.zone&quot;;
    notify no;
};</code></pre><h3 id="서비스-실행-및-방화벽">서비스 실행 및 방화벽</h3>
<p><code>systemctl enable named --now</code></p>
<p><code>firewall-cmd --add-service=dns --permanent</code>
<code>firewall-cmd --reload</code></p>
<h3 id="슬레이브-zone-파일-복사-확인">슬레이브 zone 파일 복사 확인</h3>
<p><code>ls /var/named/slaves/</code></p>
<ul>
<li>마스터에서 allow-transfer 설정이 되어 있고 연결이 잘 되었으면 <code>test.example.com.zone</code>, <code>10.0.2.0.zone</code> 파일이 자동으로 생성됨</li>
</ul>
<h3 id="클라이언트-테스트">클라이언트 테스트</h3>
<p><code>nmcli con mod static +ipv4.dns 10.0.2.101</code></p>
<p><code>host dns.test.example.com 10.0.2.101</code></p>
<hr>
<p><img src="https://velog.velcdn.com/images/urban-jungle/post/007ee01e-ae18-4ea1-80c1-418234ad9b97/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[CAB TA 4기 20일차의 기록]]></title>
            <link>https://velog.io/@urban-jungle/CAB-TA-4%EA%B8%B0-20%EC%9D%BC%EC%B0%A8%EC%9D%98-%EA%B8%B0%EB%A1%9D</link>
            <guid>https://velog.io/@urban-jungle/CAB-TA-4%EA%B8%B0-20%EC%9D%BC%EC%B0%A8%EC%9D%98-%EA%B8%B0%EB%A1%9D</guid>
            <pubDate>Tue, 08 Apr 2025 01:52:22 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/urban-jungle/post/49e354fd-82a9-424a-a61f-75c22a3ae293/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/urban-jungle/post/79ddad59-303a-4f0e-b8b1-c374dbb1ec02/image.png" alt=""></p>
<h2 id="mysql-기본-실습">MySQL 기본 실습</h2>
<h3 id="mysql-접속">MySQL 접속</h3>
<p><code>mysql -u root -p</code></p>
<ul>
<li><code>-u root</code>: root 사용자로 접속</li>
<li><code>-p</code>: 비밀번호 입력을 위한 옵션</li>
</ul>
<h3 id="데이터베이스-목록-확인">데이터베이스 목록 확인</h3>
<p><code>SHOW DATABASES;</code></p>
<ul>
<li>현재 MySQL 서버에 존재하는 데이터베이스 목록을 출력함</li>
</ul>
<h3 id="특정-데이터베이스-사용">특정 데이터베이스 사용</h3>
<p><code>USE test;</code></p>
<ul>
<li><code>test</code>라는 데이터베이스를 사용하겠다는 의미</li>
<li>이후의 모든 쿼리는 이 데이터베이스에 적용됨</li>
</ul>
<h3 id="현재-사용-중인-데이터베이스-안의-테이블-목록-확인">현재 사용 중인 데이터베이스 안의 테이블 목록 확인</h3>
<p><code>SHOW TABLES;</code></p>
<ul>
<li>현재 선택한 데이터베이스(<code>USE</code> 명령어로 선택한 DB) 안에 존재하는 테이블을 보여줌</li>
</ul>
<h3 id="시스템-데이터베이스-접근">시스템 데이터베이스 접근</h3>
<p><code>USE mysql;</code></p>
<ul>
<li><code>mysql</code> 데이터베이스는 사용자 계정 및 권한 정보 등이 저장된 시스템 DB</li>
<li>사용자 관련 설정을 변경하거나 확인할 때 사용됨</li>
</ul>
<h3 id="시스템-테이블-목록-확인">시스템 테이블 목록 확인</h3>
<p><code>SHOW TABLES;</code></p>
<ul>
<li><code>mysql</code> 데이터베이스 내부의 모든 시스템 테이블을 나열함</li>
</ul>
<h3 id="사용자-정보-테이블-구조-확인">사용자 정보 테이블 구조 확인</h3>
<p><code>DESCRIBE user;</code></p>
<ul>
<li><code>user</code> 테이블의 컬럼(열) 정보 출력</li>
<li>각 필드의 이름, 타입, NULL 허용 여부, 기본값 등을 확인할 수 있음</li>
</ul>
<hr>
<h2 id="select--where-실습">SELECT / WHERE 실습</h2>
<h3 id="select-기본-구문">SELECT 기본 구문</h3>
<h4 id="기본-형식">기본 형식</h4>
<p><code>SELECT column1, column2, ... FROM table;</code></p>
<h4 id="예제">예제</h4>
<p><code>SELECT host FROM user;</code>
<code>SELECT host, user, password FROM user;</code></p>
<h3 id="where-조건절">WHERE 조건절</h3>
<h4 id="숫자-조건-검색">숫자 조건 검색</h4>
<h4 id="비교-연산자-사용">비교 연산자 사용</h4>
<p><code>SELECT host, user, password, max_updates FROM user WHERE max_updates = 0;</code>
<code>SELECT host, user, password, max_updates FROM user WHERE max_updates &gt; 0;</code>
<code>SELECT host, user, password, max_updates FROM user WHERE max_updates &gt;= 0;</code>
<code>SELECT host, user, password, max_updates FROM user WHERE max_updates != 1;</code>
<code>SELECT host, user, password, max_updates FROM user WHERE max_updates &lt;&gt; 1;</code></p>
<h4 id="범위-검색">범위 검색</h4>
<p><code>SELECT host, user, password, max_updates FROM user WHERE max_updates BETWEEN -1 AND 1;</code>
<code>SELECT host, user, password, max_updates FROM user WHERE max_updates BETWEEN 0 AND 1;</code>
<code>SELECT host, user, password, max_updates FROM user WHERE max_updates BETWEEN 1 AND 2;</code></p>
<h4 id="여러-값-중-하나">여러 값 중 하나</h4>
<p><code>SELECT host, user, password, max_updates FROM user WHERE max_updates IN (1, 2, 3, 4);</code>
<code>SELECT host, user, password, max_updates FROM user WHERE max_updates IN (1, 2, 3, 0);</code></p>
<h4 id="null-여부-검사">NULL 여부 검사</h4>
<p><code>SELECT host, user, password, max_updates FROM user WHERE max_updates IS NULL;</code>
<code>SELECT host, user, password, max_updates FROM user WHERE max_updates IS NOT NULL;</code></p>
<h3 id="문자열-조건-검색">문자열 조건 검색</h3>
<h4 id="같음-">같음 (=)</h4>
<p><code>SELECT host, user FROM user WHERE host = &#39;localhost&#39;;</code></p>
<h4 id="like-패턴-매칭">LIKE (패턴 매칭)</h4>
<h5 id="정확히-일치">정확히 일치</h5>
<p><code>SELECT host, user FROM user WHERE host LIKE &#39;localhost&#39;;</code></p>
<h5 id="local-뒤에-한-글자"><strong>local 뒤에 한 글자</strong></h5>
<p><code>SELECT host, user FROM user WHERE host LIKE &#39;local_&#39;;</code></p>
<h5 id="local로-시작하는-문자열"><strong>local로 시작하는 문자열</strong></h5>
<p><code>SELECT host, user FROM user WHERE host LIKE &#39;local_%&#39;;</code></p>
<h5 id="두-번째-글자가-o인-패턴"><strong>두 번째 글자가 o인 패턴</strong></h5>
<p><code>SELECT host, user FROM user WHERE host LIKE &#39;_ocal%&#39;;</code>      </p>
<h5 id="ocal로-시작"><strong>ocal로 시작</strong></h5>
<p><code>SELECT host, user FROM user WHERE host LIKE &#39;ocal%&#39;;</code> </p>
<h5 id="localhost로-시작"><strong>localhost로 시작</strong></h5>
<p><code>SELECT host, user FROM user WHERE host LIKE &#39;localhost%&#39;;</code></p>
<h5 id="앞에-글자-5개--host로-시작"><strong>앞에 글자 5개 + host로 시작</strong></h5>
<p><code>SELECT host, user FROM user WHERE host LIKE &#39;_____host%&#39;;</code>  </p>
<h5 id="특정-포맷-패턴"><strong>특정 포맷 패턴</strong></h5>
<p><code>SELECT host, user FROM user WHERE host LIKE &#39;_o___host%&#39;;</code> </p>
<h4 id="논리-연산자와-like">논리 연산자와 LIKE</h4>
<p><code>SELECT host, user FROM user WHERE host LIKE &#39;%local%&#39; AND user LIKE &#39;root&#39;;</code>
<code>SELECT host, user FROM user WHERE host LIKE &#39;%local%&#39; OR user LIKE &#39;root&#39;;</code></p>
<hr>
<h2 id="dml-실습-insert--update--delete">DML 실습: INSERT / UPDATE / DELETE</h2>
<h3 id="준비-작업-테이블-생성">준비 작업: 테이블 생성</h3>
<pre><code>USE test;

CREATE TABLE user (
  name VARCHAR(10),
  uid INT,
  locate VARCHAR(10),
  email VARCHAR(20)
);</code></pre><ul>
<li>VARCHAR(n) : 실제 입력된 글자 수만큼 저장.</li>
<li>CHAR(n) : 항상 고정된 길이(n)만큼 공간 차지.</li>
<li>INT : 정수 타입</li>
</ul>
<pre><code>DESCRIBE user;
SELECT * FROM user;</code></pre><h3 id="insert-구문">INSERT 구문</h3>
<h4 id="컬럼-순서를-지정하여-삽입">컬럼 순서를 지정하여 삽입</h4>
<pre><code>INSERT INTO user (name, uid, locate, email)
VALUES (&#39;Lee&#39;, 1, &#39;seoul&#39;, &#39;lee@test.example.com&#39;);
INSERT INTO user (uid, name, email, locate)
VALUES (2, &#39;KIM&#39;, &#39;kim@test.example.com&#39;, &#39;daegu&#39;);</code></pre><h4 id="컬럼-순서-생략-모든-컬럼-순서대로-입력">컬럼 순서 생략 (모든 컬럼 순서대로 입력)</h4>
<pre><code>INSERT INTO user
VALUES (&#39;Lim&#39;, 3, &#39;kyunggi&#39;, &#39;lim@test.example.com&#39;);</code></pre><h4 id="컬럼-순서-생략-시-순서가-다르면-오류-발생-가능">컬럼 순서 생략 시, 순서가 다르면 오류 발생 가능</h4>
<pre><code>INSERT INTO user
VALUES (4, &#39;kyunggi&#39;, &#39;park@test.example.com&#39;, &#39;Park&#39;);</code></pre><h4 id="입력-결과-확인">입력 결과 확인</h4>
<pre><code>SELECT * FROM user;</code></pre><h3 id="update-구문">UPDATE 구문</h3>
<h4 id="특정-조건의-행-데이터-변경">특정 조건의 행 데이터 변경</h4>
<pre><code>UPDATE user
SET name = &#39;Park&#39;
WHERE uid = 0;</code></pre><h3 id="delete-구문">DELETE 구문</h3>
<h4 id="특정-조건의-행-삭제">특정 조건의 행 삭제</h4>
<pre><code>DELETE FROM user
WHERE uid = 0;</code></pre><hr>
<h3 id="where-절-누락-주의">WHERE 절 누락 주의</h3>
<h4 id="update-구문--전체-레코드-변경됨">UPDATE 구문 – 전체 레코드 변경됨</h4>
<pre><code>UPDATE user
SET locate = &#39;busan&#39;;</code></pre><ul>
<li><code>WHERE</code> 조건이 없기 때문에 user 테이블의 모든 행의 locate 컬럼이 &#39;busan&#39;으로 변경됨</li>
</ul>
<h4 id="결과">결과</h4>
<pre><code>SELECT * FROM user;</code></pre><ul>
<li>모든 사용자 데이터의 <code>locate</code>가 &#39;busan&#39; 으로 동일하게 설정됨</li>
</ul>
<h3 id="delete-구문--전체-레코드-삭제됨">DELETE 구문 – 전체 레코드 삭제됨</h3>
<pre><code>DELETE FROM user;</code></pre><ul>
<li><code>WHERE</code> 조건이 없으면 user 테이블의 모든 행이 삭제됨</li>
</ul>
<h4 id="결과-1">결과</h4>
<pre><code>SELECT * FROM user;</code></pre><ul>
<li>결과 없음 (빈 테이블)</li>
</ul>
<h3 id="실무에서-반드시-기억해야-할-안전-수칙">실무에서 반드시 기억해야 할 안전 수칙</h3>
<ol>
<li><p>UPDATE / DELETE 사용 시 항상 <code>WHERE</code> 조건부터 작성하는 습관을 들이기</p>
</li>
<li><p>실수로 실행하지 않도록 SELECT로 먼저 조건 테스트하고, 조건이 맞는지 확인한 후에 UPDATE/DELETE 실행</p>
</li>
<li><p>트랜잭션 사용이 가능한 환경이라면 꼭 <code>BEGIN</code>, <code>ROLLBACK</code>, <code>COMMIT</code> 구조로 안전하게 작업</p>
</li>
</ol>
<hr>
<h2 id="트랜잭션transaction-설정-및-확인-실습">트랜잭션(Transaction) 설정 및 확인 실습</h2>
<h3 id="현재-트랜잭션-자동-커밋-설정-확인">현재 트랜잭션 자동 커밋 설정 확인</h3>
<pre><code>SHOW VARIABLES LIKE &#39;auto%&#39;;</code></pre><ul>
<li><code>autocommit = ON</code> 이면 각 SQL 실행 시 자동으로 커밋됨</li>
<li><code>autocommit = OFF</code> 이면 명시적인 COMMIT 없이는 반영되지 않음</li>
</ul>
<h3 id="트랜잭션-수동-커밋-모드-설정">트랜잭션 수동 커밋 모드 설정</h3>
<pre><code>SET autocommit = OFF;</code></pre><ul>
<li>이 설정은 현재 세션에만 적용됨</li>
<li>여러 쿼리를 하나의 트랜잭션처럼 묶어서 실행할 수 있음</li>
</ul>
<h3 id="insert-실습">INSERT 실습</h3>
<pre><code>INSERT INTO user
VALUES (&#39;Lim&#39;,3,&#39;kyunggi&#39;,&#39;lim@test.example.com&#39;);</code></pre><pre><code>SELECT * FROM user;</code></pre><ul>
<li>입력된 데이터 확인 가능</li>
<li>하지만 아직 <code>COMMIT</code> 하지 않았으므로 확정된 것은 아님</li>
</ul>
<h3 id="rollback-수행">ROLLBACK 수행</h3>
<pre><code>ROLLBACK;</code></pre><pre><code>SELECT * FROM user;</code></pre><ul>
<li>방금 넣은 데이터는 되돌려짐 (롤백됨)</li>
</ul>
<h3 id="세션-종료-및-재접속-후-확인">세션 종료 및 재접속 후 확인</h3>
<pre><code>exit</code></pre><p><code>mysql -u root -p</code></p>
<pre><code>SHOW VARIABLES LIKE &#39;autocommit&#39;;</code></pre><ul>
<li><code>autocommit = ON</code> (기본값으로 복귀됨)</li>
</ul>
<h3 id="tip">TIP</h3>
<h4 id="autocommit--off-상태에서-실수-없이-작업하려면-다음-흐름-추천">autocommit = OFF 상태에서 실수 없이 작업하려면 다음 흐름 추천</h4>
<pre><code>START TRANSACTION;
-- SQL 작업들 실행
COMMIT; -- 저장
-- 또는 ROLLBACK; -- 취소</code></pre><hr>
<h2 id="mysql-autocommit-영구-off-설정">MySQL autocommit 영구 OFF 설정</h2>
<h3 id="설정-파일-편집">설정 파일 편집</h3>
<p><code>vi /etc/my.cnf</code></p>
<pre><code>[mysqld]
autocommit = 0</code></pre><ul>
<li><code>[mysqld]</code> 섹션 아래에 <code>autocommit = 0</code> 추가</li>
<li>이는 MySQL 서버가 시작될 때 autocommit을 OFF 상태로 유지하게 만듦</li>
</ul>
<h3 id="mysql-서비스-재시작">MySQL 서비스 재시작</h3>
<p><code>systemctl restart mysql</code></p>
<ul>
<li>변경된 설정이 반영되도록 MySQL 서비스를 재시작함</li>
</ul>
<h3 id="mysql-접속-후-확인">MySQL 접속 후 확인</h3>
<p><code>mysql -u root -p</code></p>
<pre><code>SHOW VARIABLES LIKE &#39;autocommit&#39;;</code></pre><ul>
<li><code>Value</code>가 OFF로 표시되면 성공적으로 영구 설정 완료</li>
</ul>
<h3 id="참고">참고</h3>
<ul>
<li><code>SET autocommit = OFF;</code> 는 현재 세션에만 일시적 적용</li>
<li><code>my.cnf</code>의 <code>autocommit = 0</code> 설정은 모든 사용자의 기본값 변경</li>
</ul>
<hr>
<h2 id="mysql-테이블-수정-실습-정리">MySQL 테이블 수정 실습 정리</h2>
<h3 id="테이블에-컬럼-추가">테이블에 컬럼 추가</h3>
<h4 id="age-정수형-컬럼-추가">age 정수형 컬럼 추가</h4>
<pre><code>ALTER TABLE user ADD age INT;</code></pre><h4 id="level-숫자-자리수-제한표현-포함-컬럼-추가">level 숫자 자리수 제한(표현) 포함 컬럼 추가</h4>
<pre><code>ALTER TABLE user ADD level INT(5);</code></pre><h3 id="컬럼-삭제">컬럼 삭제</h3>
<pre><code>ALTER TABLE user DROP level;</code></pre><ul>
<li>level 컬럼 삭제</li>
</ul>
<h3 id="컬럼-타입-수정">컬럼 타입 수정</h3>
<pre><code>ALTER TABLE user MODIFY email INT;</code></pre><ul>
<li><code>email</code>을 INT로 수정 (기존 값이 문자열이라면 데이터 변환 주의)</li>
</ul>
<h3 id="기본-키-지정">기본 키 지정</h3>
<pre><code>ALTER TABLE user ADD PRIMARY KEY(uid);</code></pre><ul>
<li><code>uid</code>를 기본 키로 지정</li>
</ul>
<h3 id="not-null-제약-조건-추가">NOT NULL 제약 조건 추가</h3>
<pre><code>ALTER TABLE user MODIFY name VARCHAR(10) NOT NULL;</code></pre><ul>
<li><code>name</code>에 NOT NULL 제약조건 추가</li>
</ul>
<h3 id="unique-제약-조건-추가-시도">UNIQUE 제약 조건 추가 시도</h3>
<pre><code>ALTER TABLE user MODIFY locate VARCHAR(10) UNIQUE;</code></pre><ul>
<li>에러 발생: 기존 데이터에 중복된 값이 존재함</li>
</ul>
<h3 id="해결-팁">해결 팁</h3>
<ul>
<li>중복 데이터 제거 또는 정리 후 다시 시도해야 <code>UNIQUE</code> 제약 조건을 적용할 수 있음</li>
</ul>
<pre><code>SELECT locate, COUNT(*) FROM user GROUP BY locate HAVING COUNT(*) &gt; 1;</code></pre><ul>
<li>위 쿼리로 중복된 <code>locate</code> 확인 가능</li>
</ul>
<hr>
<h2 id="mysql-사용자-계정-및-권한-관리-실습">MySQL 사용자 계정 및 권한 관리 실습</h2>
<h3 id="mysql-시스템-db-사용">mysql 시스템 DB 사용</h3>
<pre><code>USE mysql;
SHOW TABLES;
DESCRIBE user;
SELECT host, user FROM user;</code></pre><ul>
<li><code>mysql.user</code> 테이블 구조 확인</li>
<li>현재 등록된 사용자 계정 리스트 확인</li>
</ul>
<h3 id="사용자-계정-생성">사용자 계정 생성</h3>
<pre><code>CREATE USER user01@localhost IDENTIFIED BY &#39;123&#39;;</code></pre><ul>
<li><code>user01</code> 이라는 사용자 계정 생성 (접속 호스트는 <code>localhost</code>)</li>
<li>호스트는 IP 형식, <code>%</code>, <code>127.0.0.1</code> 등으로도 지정 가능</li>
</ul>
<h3 id="권한-확인">권한 확인</h3>
<pre><code>DESCRIBE user;
SELECT Select_priv, user FROM user;</code></pre><ul>
<li>사용자의 권한 필드 확인 가능 (<code>Select_priv</code>, <code>Create_priv</code> 등)</li>
</ul>
<h3 id="사용자-권한-확인">사용자 권한 확인</h3>
<pre><code>SHOW GRANTS FOR user01@localhost;
SHOW GRANTS FOR root@localhost;</code></pre><ul>
<li>특정 사용자가 가진 권한 리스트 확인</li>
</ul>
<h3 id="권한-부여">권한 부여</h3>
<ul>
<li><code>test</code> DB의 <code>user</code> 테이블에 대해 <code>SELECT</code>, <code>CREATE</code>, <code>DROP</code> 권한 부여</li>
</ul>
<pre><code>GRANT SELECT, CREATE, DROP ON test.user TO user01@localhost;</code></pre><pre><code>SHOW GRANTS FOR user01@localhost;</code></pre><h3 id="권한-회수-revoke">권한 회수 (REVOKE)</h3>
<h4 id="지정한-권한만-회수-가능-전체-회수-아님">지정한 권한만 회수 가능 (전체 회수 아님)</h4>
<pre><code>REVOKE CREATE, DROP ON test.user FROM user01@localhost;</code></pre><h4 id="select-권한만-남았는지-확인"><code>SELECT</code> 권한만 남았는지 확인</h4>
<pre><code>SHOW GRANTS FOR user01@localhost;</code></pre><hr>
<h2 id="mysql-데이터베이스-백업--복원">MySQL 데이터베이스 백업 &amp; 복원</h2>
<h3 id="백업-dump">백업 (Dump)</h3>
<p><code>mysqldump -u root -p test &gt; test.dump</code></p>
<ul>
<li><p><code>test</code> 데이터베이스를 백업하여 <code>test.dump</code> 파일로 저장</p>
</li>
<li><p><code>-u root -p</code> : root 사용자로 비밀번호 입력 후 접속</p>
</li>
</ul>
<h3 id="테이블-삭제-테스트">테이블 삭제 테스트</h3>
<p><code>mysql -u root -p</code></p>
<pre><code>USE test;
SHOW TABLES;

DROP TABLE user;

SHOW TABLES;
exit;</code></pre><ul>
<li>백업 테스트를 위해 <code>user</code> 테이블 삭제</li>
</ul>
<h3 id="백업-파일로-복원">백업 파일로 복원</h3>
<p><code>mysql -u root -p test &lt; test.dump</code></p>
<ul>
<li><code>test.dump</code> 파일을 <code>test</code> 데이터베이스에 덮어쓰기</li>
<li>삭제되었던 <code>user</code> 테이블이 복구됨</li>
</ul>
<h3 id="복원-확인">복원 확인</h3>
<p><code>mysql -u root -p</code></p>
<pre><code>USE test;
SHOW TABLES;</code></pre><ul>
<li><code>user</code> 테이블이 다시 존재하는지 확인</li>
</ul>
<hr>
<p><img src="https://velog.velcdn.com/images/urban-jungle/post/37bd850c-ea32-4d54-8fa1-a28ced2d30f2/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[CAB TA 4기 19일차의 기록]]></title>
            <link>https://velog.io/@urban-jungle/CAB-TA-4%EA%B8%B0-19%EC%9D%BC%EC%B0%A8%EC%9D%98-%EA%B8%B0%EB%A1%9D</link>
            <guid>https://velog.io/@urban-jungle/CAB-TA-4%EA%B8%B0-19%EC%9D%BC%EC%B0%A8%EC%9D%98-%EA%B8%B0%EB%A1%9D</guid>
            <pubDate>Tue, 08 Apr 2025 00:57:10 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/urban-jungle/post/3f3b9f6c-b197-4649-9f14-d7da780e0e8b/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/urban-jungle/post/5ba31883-dfcf-4b6e-a0f7-ae03fa886c58/image.png" alt=""></p>
<h2 id="통합-시스템-설정-실습">통합 시스템 설정 실습</h2>
<p><strong>1. root 비밀번호 설정</strong></p>
<p><code>passwd root</code></p>
<ul>
<li>비밀번호로 cccr1234 입력</li>
</ul>
<p><strong>2. GRUB 타이머 10초 설정</strong></p>
<p><code>vim /etc/default/grub</code></p>
<ul>
<li><code>GRUB_TIMEOUT=10</code> 으로 수정</li>
</ul>
<p><code>grub2-mkconfig -o /boot/grub2/grub.cfg</code></p>
<p><strong>3. eth1 고정 IP 설정</strong></p>
<p><code>nmcli con add con-name static1 ifname eth1 type ethernet ip4 192.168.56.211/24</code>
<code>nmcli con up static1</code></p>
<p><strong>4. 인터넷 repo 설정</strong></p>
<p><code>cd /etc/yum.repos.d/</code>
<code>mkdir backup</code>
<code>mv *.repo backup/</code></p>
<p><code>vim net.repo</code></p>
<pre><code>[NET_BaseOS]
name=BaseOS
baseurl=http://dl.rockylinux.org/$contentdir/$releasever/BaseOS/$basearch/os/
enabled=1
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-Rocky-9

[NET_AppStream]
name=AppStream
baseurl=http://dl.rockylinux.org/$contentdir/$releasever/AppStream/$basearch/os/
enabled=1
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-Rocky-9</code></pre><p><code>dnf makecache</code></p>
<p><strong>5. /dev/sdb 파티션 (4,4,6,6)</strong></p>
<p><code>fdisk /dev/sdb</code></p>
<ul>
<li>n → primary → +4G, +4G, +6G, +6G</li>
<li>w로 저장</li>
</ul>
<p><code>partprobe</code>
<code>lsblk</code></p>
<p><strong>6. 포맷 및 마운트</strong></p>
<p><code>mkfs.xfs /dev/sdb1</code>
<code>mkdir /mnt1</code>
<code>mount /dev/sdb1 /mnt1</code>
<code>vim /etc/fstab</code>
<code>/dev/sdb1 /mnt1 xfs defaults 0 0</code></p>
<p><code>mkswap /dev/sdb2</code>
<code>swapon /dev/sdb2</code>
<code>echo &quot;/dev/sdb2 swap swap defaults 0 0&quot; &gt;&gt; /etc/fstab</code></p>
<p><strong>7. LVM 설정</strong></p>
<p><code>pvcreate /dev/sdb3 /dev/sdb4</code>
<code>vgcreate vg0 /dev/sdb3 /dev/sdb4</code>
<code>lvcreate -n lv01 -L 4G vg0</code>
<code>mkfs.xfs /dev/vg0/lv01</code>
<code>mkdir /home1</code>
<code>echo &quot;/dev/vg0/lv01 /home1 xfs defaults 0 0&quot; &gt;&gt; /etc/fstab</code>
<code>mount -a</code></p>
<p><strong>8. lv01 확장</strong></p>
<p><code>lvextend -L +2G /dev/vg0/lv01</code>
<code>xfs_growfs /home1</code></p>
<p><strong>9. 사용자 default home 디렉토리 변경</strong></p>
<p><code>vim /etc/default/useradd</code></p>
<ul>
<li><code>HOME=/home1</code> 으로 변경</li>
</ul>
<p><strong>10. user01 생성 + sudo 권한</strong></p>
<p><code>useradd user01</code>
<code>passwd user01</code>
<code>usermod -aG wheel user01</code></p>
<p><strong>11. 그룹 및 디렉토리 설정</strong></p>
<p><code>groupadd sggroup</code>
<code>mkdir -p /ptest/dir01 /ptest/dir02</code>
<code>chgrp sggroup /ptest/dir01</code>
<code>chmod 2775 /ptest/dir01</code></p>
<p><strong>12. cron 등록</strong></p>
<p><code>crontab -e -u user01</code>
<code>0 17 31 1 * date &gt;&gt; /ptest/dir02/datefile</code></p>
<p><strong>13. httpd 설치 및 활성화</strong></p>
<p><code>dnf install -y httpd</code>
<code>systemctl enable httpd --now</code></p>
<hr>
<h2 id="web-실습">web 실습</h2>
<h3 id="apache-가상-호스트-설정-http-기반">Apache 가상 호스트 설정 (HTTP 기반)</h3>
<h4 id="설정-파일-위치">설정 파일 위치</h4>
<p><code>/etc/httpd/conf.d/</code></p>
<h4 id="가상-호스트-vhost0">가상 호스트 vhost0</h4>
<p><code>vi /etc/httpd/conf.d/00-vhost.conf</code></p>
<pre><code>&lt;VirtualHost *:80&gt;
    DocumentRoot /var/www/html0
    ServerName vhost0.cccr1.org
    ServerAlias vhost0
&lt;/VirtualHost&gt;

&lt;Directory /var/www/html0&gt;
    AllowOverride None
    Require all granted
&lt;/Directory&gt;</code></pre><p><code>mkdir /var/www/html0</code>
<code>echo vhost0 &gt; /var/www/html0/index.html</code></p>
<h4 id="가상-호스트-vhost1">가상 호스트 vhost1</h4>
<p><code>vi /etc/httpd/conf.d/01-vhost.conf</code></p>
<pre><code>&lt;VirtualHost *:80&gt;
    DocumentRoot /var/www/html1
    ServerName vhost1.cccr1.org
    ServerAlias vhost1
&lt;/VirtualHost&gt;

&lt;Directory /var/www/html1&gt;
    AllowOverride None
    Require all granted
&lt;/Directory&gt;</code></pre><p><code>mkdir /var/www/html1</code>
<code>echo vhost1 &gt; /var/www/html1/index.html</code></p>
<h4 id="etchosts-에-가상호스트-도메인-매핑">/etc/hosts 에 가상호스트 도메인 매핑</h4>
<p><code>vi /etc/hosts</code></p>
<pre><code>192.168.56.100    server.cccr1.org  vhost0.cccr1.org  vhost0  vhost1.cccr1.org  vhost1</code></pre><h4 id="httpd-서비스-시작-및-방화벽-설정">httpd 서비스 시작 및 방화벽 설정</h4>
<p><code>systemctl start httpd</code></p>
<p><code>firewall-cmd --add-service=http --permanent</code>
<code>firewall-cmd --reload</code></p>
<h4 id="정상-동작-확인">정상 동작 확인</h4>
<p><code>curl server.cccr1.org</code>
<code>curl vhost0</code>
<code>curl vhost1</code></p>
<h3 id="https-리다이렉션-설정">HTTPS 리다이렉션 설정</h3>
<h4 id="방법-1-간단한-리다이렉트">방법 1: 간단한 리다이렉트</h4>
<p><code>RewriteEngine on</code>
<code>RewriteRule ^(.*)$ https://%{HTTP_HOST}$1 [R=301,L]</code></p>
<h4 id="방법-2-다양한-조건에-따른-리다이렉트">방법 2: 다양한 조건에 따른 리다이렉트</h4>
<p><code>RewriteEngine on</code>
<code>RewriteMap lowercase int:tolower</code></p>
<p><code>RewriteCond &quot;${lowercase:%{HTTPS}}&quot;             !on</code>
<code>RewriteCond &quot;${lowercase:%{REQUEST_SCHEME}}&quot;    !https</code>
<code>RewriteCond &quot;${lowercase:%{SERVER_PORT}}&quot;       !443</code></p>
<p><code>RewriteRule ^(.*)$ https://%{HTTP_HOST}$1 [R=301,L]</code></p>
<ul>
<li>위 조건이 하나라도 만족되면, HTTPS로 강제 리다이렉션이 수행됨</li>
</ul>
<hr>
<h2 id="https-실습">HTTPS 실습</h2>
<h3 id="ssl-관련-패키지-설치-및-인증서-생성">SSL 관련 패키지 설치 및 인증서 생성</h3>
<p><code>yum -y install mod_ssl</code></p>
<p><code>openssl genrsa -out private.key 2048</code>
<code>openssl req -new -key private.key -out cert.csr</code>
<code>openssl x509 -req -signkey private.key -in cert.csr -out cert.crt</code></p>
<p><code>chmod 600 private.key cert.crt</code>
<code>mv private.key /etc/pki/tls/private/</code>
<code>mv cert.* /etc/pki/tls/certs/</code></p>
<h3 id="apache-ssl-설정-수정-etchttpdconfdsslconf">Apache SSL 설정 수정 (/etc/httpd/conf.d/ssl.conf)</h3>
<p><code>vi /etc/httpd/conf.d/ssl.conf</code></p>
<h4 id="수정-포인트">수정 포인트</h4>
<ul>
<li><code>DocumentRoot &quot;/var/www/html&quot;</code> → 제거</li>
<li><code>ServerName server.cccr1.org:443</code> → 추가 또는 수정</li>
<li><code>SSLCertificateFile</code> → <code>/etc/pki/tls/certs/cert.crt</code></li>
<li><code>SSLCertificateKeyFile</code> → <code>/etc/pki/tls/private/private.key</code></li>
</ul>
<h3 id="http-→-https-리다이렉션-설정-가상호스트">HTTP → HTTPS 리다이렉션 설정 (가상호스트)</h3>
<p><code>/etc/httpd/conf.d/00-vhost.conf</code></p>
<pre><code>&lt;VirtualHost *:80&gt;
    DocumentRoot /var/www/html0
    ServerName vhost0.cccr1.org
    ServerAlias vhost0
    RewriteEngine On
    RewriteCond %{REQUEST_URI} !^/\.well\-known/acme\-challenge/
    RewriteRule ^(.*)$ https://%{HTTP_HOST}$1 [R=301,L]
&lt;/VirtualHost&gt;

&lt;Directory /var/www/html0&gt;
    AllowOverride None
    Require all granted
&lt;/Directory&gt;</code></pre><p><code>/etc/httpd/conf.d/01-vhost.conf</code></p>
<pre><code>&lt;VirtualHost *:80&gt;
    DocumentRoot /var/www/html1
    ServerName vhost1.cccr1.org
    ServerAlias vhost1
    RewriteEngine On
    RewriteCond %{REQUEST_URI} !^/\.well\-known/acme\-challenge/
    RewriteRule ^(.*)$ https://%{HTTP_HOST}$1 [R=301,L]
&lt;/VirtualHost&gt;

&lt;Directory /var/www/html1&gt;
    AllowOverride None
    Require all granted
&lt;/Directory&gt;</code></pre><h3 id="apache-서비스-재시작-및-방화벽-설정">Apache 서비스 재시작 및 방화벽 설정</h3>
<p><code>systemctl restart httpd</code></p>
<p><code>firewall-cmd --add-service=https --permanent</code>
<code>firewall-cmd --reload</code></p>
<hr>
<p><img src="https://velog.velcdn.com/images/urban-jungle/post/fd821777-2ede-4507-a5f9-4e1c4df9b097/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[25-01 네트워크관리사 2급 합격후기]]></title>
            <link>https://velog.io/@urban-jungle/25-01-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC%EA%B4%80%EB%A6%AC%EC%82%AC-2%EA%B8%89-%ED%95%A9%EA%B2%A9%ED%9B%84%EA%B8%B0</link>
            <guid>https://velog.io/@urban-jungle/25-01-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC%EA%B4%80%EB%A6%AC%EC%82%AC-2%EA%B8%89-%ED%95%A9%EA%B2%A9%ED%9B%84%EA%B8%B0</guid>
            <pubDate>Tue, 08 Apr 2025 00:43:07 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/urban-jungle/post/bf5fc2dc-50ae-4e05-a3cc-c4ad076a7b4a/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/urban-jungle/post/5cd44c8e-7689-4674-bee4-1c5f89c8a8a4/image.png" alt=""></p>
<p>안정적인 점수로 합격했다.</p>
<p>케이블은 귀찮아서 하지 않았다.</p>
<p>단답형의 경우, 85%정도 기존에 알고있었던 지식에서 나왔다.</p>
<p>라우터 문제는 show명령, telnet 관련 문제, ip add 관련 문제가 나와 쉽게 풀었다.</p>
<p>25-1회 윈도우 설정 문제에서는 세부 조건들이 많이 나왔기 때문에,
애뮬레이터로 연습할 때 꼼꼼하게 살펴보며 연습하면 좋을 것 같다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[CAB TA 4기 18일차의 기록]]></title>
            <link>https://velog.io/@urban-jungle/CAB-TA-4%EA%B8%B0-18%EC%9D%BC%EC%B0%A8%EC%9D%98-%EA%B8%B0%EB%A1%9D</link>
            <guid>https://velog.io/@urban-jungle/CAB-TA-4%EA%B8%B0-18%EC%9D%BC%EC%B0%A8%EC%9D%98-%EA%B8%B0%EB%A1%9D</guid>
            <pubDate>Fri, 04 Apr 2025 10:54:27 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/urban-jungle/post/a9c27005-12e1-4f7c-9302-8df8e5220e02/image.png" alt=""></p>
<h2 id="패키지-실습">패키지 실습</h2>
<h3 id="dvd-마운트-및-repo-설정">DVD 마운트 및 repo 설정</h3>
<p><code>umount /dev/cdrom</code>
<code>mkdir /media/cdrom</code>
<code>mount /dev/cdrom /media/cdrom</code></p>
<p><strong>기존 <code>.repo</code> 파일들 백업</strong></p>
<p><code>cd /etc/yum.repos.d/</code>
<code>mkdir backup</code>
<code>mv *.repo backup/</code></p>
<p><strong>DVD와 인터넷 repo 동시 사용을 위한 <code>test.repo</code> 구성 예시</strong></p>
<pre><code>[DVD_BaseOS]
name=dvd-baseos
baseurl=file:///media/cdrom/BaseOS/
enabled=1
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-Rocky-9

[DVD_AppStream]
name=dvd-appstream
baseurl=file:///media/cdrom/AppStream/
enabled=1
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-Rocky-9

[NET_BaseOS]
name=network-baseos
baseurl=http://dl.rockylinux.org/$contentdir/$releasever/BaseOS/$basearch/os/
enabled=1
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-Rocky-9</code></pre><p><code>dnf makecache</code>
<code>dnf repolist all</code></p>
<h3 id="패키지-설치삭제">패키지 설치/삭제</h3>
<p><strong>zsh 설치/삭제 (RPM 직접 설치)</strong></p>
<p><code>rpm -ivh /media/cdrom/BaseOS/Packages/z/zsh-5.8-9.el9.x86_64.rpm</code>
<code>rpm -e zsh</code></p>
<p><strong>ksh 설치/삭제 (YUM 사용)</strong></p>
<p><code>dnf install ksh -y</code>
<code>dnf remove ksh -y</code></p>
<p><strong>zsh 설치 (YUM + ISO rpm)</strong></p>
<p><code>dnf localinstall /media/cdrom/BaseOS/Packages/z/zsh-5.8-9.el9.x86_64.rpm</code></p>
<h3 id="security-tools--httpd">Security Tools &amp; httpd</h3>
<p><strong>그룹 패키지 확인/설치/삭제</strong></p>
<p><code>dnf group list</code>
<code>dnf group info &quot;Security Tools&quot;</code>
<code>dnf group install &quot;Security Tools&quot;</code>
<code>dnf group remove &quot;Security Tools&quot;</code></p>
<p><strong>/var/www 디렉토리 생성한 패키지 확인</strong></p>
<p><code>dnf provides /var/www</code></p>
<p><strong>httpd 관련 실습</strong></p>
<p><code>dnf install httpd -y</code>
<code>rpm -qc httpd</code>        # 설정 파일 확인
<code>rpm -qd httpd</code>         # 문서 파일 확인
<code>dnf info httpd</code>       # 패키지 정보 확인</p>
<p><strong>httpd 서비스 제어</strong></p>
<p><code>systemctl start httpd</code>
<code>systemctl enable httpd</code></p>
<p><code>systemctl stop httpd</code>
<code>systemctl disable httpd</code></p>
<p><strong>httpd 삭제 및 재설치 (무응답 설치)</strong></p>
<p><code>dnf remove httpd -y</code>
<code>dnf install httpd -y</code></p>
<hr>
<h2 id="네트워크-실습">네트워크 실습</h2>
<h3 id="초기-설정-및-ip-확인">초기 설정 및 IP 확인</h3>
<p><strong>모든 인터페이스 IP 확인</strong></p>
<p><code>ip addr</code>
<code>ifconfig</code></p>
<p><strong>특정 인터페이스만 확인 (예: <code>eth0</code> 또는 <code>enp0s3</code>)</strong></p>
<p><code>ip addr show eth0</code>
<code>ifconfig eth0</code></p>
<h3 id="연결-생성">연결 생성</h3>
<p><strong>유동 IP 연결 생성 (DHCP)</strong></p>
<p><code>nmcli con add con-name dhcp1 ifname eth0 type ethernet</code></p>
<p><strong>고정 IP 연결 생성 (STATIC)</strong></p>
<p><code>nmcli con add con-name static1 ifname eth0 type ethernet ip4 192.168.56.200/24 gw4 192.168.56.1 ipv4.method manual</code></p>
<ul>
<li><code>ipv4.method manual</code>을 꼭 추가해야 고정 IP로 설정됨</li>
</ul>
<h3 id="연결-수정">연결 수정</h3>
<p><strong>dhcp1 → static100 변경 + 고정 IP로 수정</strong></p>
<pre><code>nmcli con mod dhcp1 \
connection.id static100 \
ipv4.addresses 192.168.56.150/24 \
ipv4.gateway 192.168.56.1 \
ipv4.dns 8.8.8.8 \
connection.autoconnect no \
ipv4.method manual</code></pre><p><strong>static1 → dhcp2 변경 + 유동 IP로 수정</strong></p>
<pre><code>nmcli con mod static1 \
connection.id dhcp2 \
ipv4.method auto \
ipv4.addresses &quot;&quot; \
ipv4.gateway &quot;&quot;</code></pre><h3 id="호스트네임-변경">호스트네임 변경</h3>
<p><code>hostnamectl hostname servera.cccr.org</code></p>
<p><strong>변경 확인</strong></p>
<p><code>hostname</code></p>
<hr>
<h2 id="sshsecure-shell">SSH(Secure Shell)</h2>
<h3 id="ssh란">SSH란?</h3>
<ul>
<li>원격 서버에 암호화된 통신으로 접속할 수 있도록 해주는 보안 프로토콜</li>
<li><code>telnet</code>은 평문 전송 (보안 없음)</li>
<li><code>ssh</code>는 암호화 전송 (보안 있음)</li>
</ul>
<h3 id="암호화-방식">암호화 방식</h3>
<h4 id="대칭키-symmetric-key">대칭키 (Symmetric Key)</h4>
<ul>
<li>같은 키로 암호화/복호화</li>
<li>빠르지만, 키가 노출되면 위험</li>
</ul>
<h4 id="비대칭키-asymmetric-key">비대칭키 (Asymmetric Key)</h4>
<ul>
<li>공개키(암호화) + 개인키(복호화) 한 쌍</li>
<li>공개키는 누구나 공유 가능</li>
<li>개인키는 나만 보관</li>
</ul>
<h3 id="ssh-접속-원리">SSH 접속 원리</h3>
<ol>
<li>클라이언트가 서버에 접속 요청</li>
<li>서버가 공개키 전달</li>
<li>클라이언트가 대칭키(비밀키) 생성</li>
<li>클라이언트는 이 대칭키를 서버의 공개키로 암호화하여 전송</li>
<li>서버는 개인키로 복호화하여 대칭키 획득</li>
<li>이후 통신은 대칭키로 암호화된 채 전송됨</li>
</ol>
<ul>
<li>접속 후 통신은 대칭키 방식 → 빠르고 보안 유지 가능</li>
</ul>
<h3 id="ssh-인증-방식">SSH 인증 방식</h3>
<h4 id="일반-인증-id--pw-입력">일반 인증 (ID + PW 입력)</h4>
<ul>
<li>원격 접속 시 매번 패스워드 입력 필요</li>
</ul>
<h4 id="키-기반-인증-더-안전--자동화-가능">키 기반 인증 (더 안전 &amp; 자동화 가능)</h4>
<ul>
<li><p>클라이언트에서 해야 할 작업
<code>ssh-keygen</code></p>
</li>
<li><p>공개키 (<code>id_rsa.pub</code>) + 개인키 (<code>id_rsa</code>) 생성됨
<code>ssh-copy-id 사용자명@서버IP</code></p>
</li>
<li><p>서버에 공개키 등록 (<code>~/.ssh/authorized_keys</code>)</p>
</li>
</ul>
<p>-&gt; 이제 비밀번호 없이 SSH 접속 가능</p>
<h3 id="기억하면-좋은-명령어">기억하면 좋은 명령어</h3>
<h4 id="ssh-접속">ssh 접속</h4>
<p><code>ssh 사용자명@서버IP</code></p>
<h4 id="키-생성">키 생성</h4>
<p><code>ssh-keygen</code></p>
<h4 id="공개키-복사">공개키 복사</h4>
<p><code>ssh-copy-id 사용자명@서버IP</code></p>
<hr>
<h2 id="ssh-실습">SSH 실습</h2>
<h3 id="네트워크-설정">네트워크 설정</h3>
<h4 id="클라이언트-client">클라이언트 (Client)</h4>
<p><code>nmcli con add con-name static-client type ethernet ifname eth1 ip4 192.168.56.200/24 ipv4.method manual</code></p>
<h4 id="서버-server">서버 (Server)</h4>
<p><code>nmcli con add con-name static-server type ethernet ifname eth1 ip4 192.168.56.150/24 ipv4.method manual</code></p>
<h3 id="사용자-생성-및-활성화">사용자 생성 및 활성화</h3>
<h4 id="클라이언트">클라이언트</h4>
<p><code>useradd cuser</code>
<code>passwd cuser</code></p>
<h4 id="서버">서버</h4>
<p><code>useradd suser</code>
<code>passwd suser</code></p>
<h3 id="일반-ssh-접속-테스트">일반 SSH 접속 테스트</h3>
<h4 id="클라이언트cuser에서-서버suser로-ssh-접속">클라이언트(cuser)에서 서버(suser)로 SSH 접속</h4>
<p><code>ssh suser@192.168.56.150</code>
<code>exit</code></p>
<h3 id="공개키개인키-관련-확인">공개키/개인키 관련 확인</h3>
<h4 id="클라이언트-1">클라이언트</h4>
<p><code>vim ~/.ssh/known_hosts</code></p>
<h4 id="서버-1">서버</h4>
<p><code>vim /etc/ssh/ssh_host_rsa_key.pub</code></p>
<ul>
<li>두 파일의 fingerprint는 일치해야 정상 상태</li>
</ul>
<h3 id="서버-공개키-제거--재생성">서버 공개키 제거 &amp; 재생성</h3>
<p><code>rm -rf /etc/ssh/ssh_host*</code>
<code>systemctl restart sshd</code>
<code>ls /etc/ssh/</code></p>
<ul>
<li>공개키가 재생성되면서 클라이언트와 fingerprint가 불일치하게 됨</li>
</ul>
<h3 id="클라이언트에서-등록된-키-제거-후-재접속">클라이언트에서 등록된 키 제거 후 재접속</h3>
<p><code>rm -rf ~/.ssh/known_host*</code>
<code>ssh suser@192.168.56.150</code>
<code>exit</code></p>
<ul>
<li>새 서버 공개키를 다시 등록하게 됨</li>
</ul>
<h3 id="암호-없이-로그인-키-기반-인증-설정">암호 없이 로그인 (키 기반 인증 설정)</h3>
<h4 id="클라이언트-cuser">클라이언트 (cuser)</h4>
<p><code>ssh-keygen</code>
# 엔터 3번
<code>ssh-copy-id suser@192.168.56.150</code></p>
<ul>
<li>이제부터는 cuser → suser 접속 시 암호 없이 로그인 가능</li>
</ul>
<h3 id="root-계정-ssh-접속-차단">root 계정 SSH 접속 차단</h3>
<h4 id="서버-2">서버</h4>
<p><code>vim /etc/ssh/sshd_config</code></p>
<p><code>PermitRootLogin no</code> # 설정 확인 또는 추가</p>
<p><code>systemctl restart sshd</code></p>
<ul>
<li>이제 root는 SSH로 접속할 수 없음</li>
</ul>
<h3 id="요약">요약</h3>
<p>연결 상태 확인:    <code>nmcli con show</code>
IP 설정 확인:    <code>ip addr show eth1</code>
서버 공개키:    <code>cat /etc/ssh/ssh_host_rsa_key.pub</code>
클라 서버 키 등록:    <code>cat ~/.ssh/known_hosts</code>
암호 없이 로그인 테스트:    <code>ssh suser@192.168.56.150</code></p>
<hr>
<h2 id="firewalld">firewalld</h2>
<h3 id="firewalld-개요">firewalld 개요</h3>
<ul>
<li>리눅스 방화벽 서비스</li>
<li>동적(Dynamic) 구성 가능</li>
<li>iptables보다 현대적이며 유연함</li>
</ul>
<h4 id="구성-흐름">구성 흐름</h4>
<pre><code>Netfilter(Kernel)
  ↳ iptables → iptables.service
  ↳ firewalld → firewall-cmd / firewall-config (GUI)</code></pre><h3 id="구성-요소">구성 요소</h3>
<p>Zone:    네트워크 신뢰 수준
Service:    허용할 서비스 (ssh, http 등)
Port:    포트 기반 접근 허용
IP(Source):    접근 가능한 IP 제한
Interface:    네트워크 장치를 특정 Zone에 연결</p>
<h3 id="zone-종류-사전-정의됨">Zone 종류 (사전 정의됨)</h3>
<p><code>drop</code>:    모든 수신 DROP (ICMP 응답도 없음)
<code>block</code>:    모든 수신 REJECT (ICMP 거절)
<code>external</code>:    외부에서 SSH만 허용
<code>internal / home</code>:    내부망 접근 허용 (SSH, DHCP 등)
<code>public(기본)</code>:    SSH만 허용된 공개망
<code>trusted</code>:    모든 트래픽 허용
<code>work</code>:    제한적 허용 (SSH, DHCPv4 등)</p>
<h3 id="주요-명령어-firewall-cmd">주요 명령어 (firewall-cmd)</h3>
<p><code>--state    firewalld</code>: 상태 확인
<code>--get-default-zone</code>:    현재 기본 zone 확인
<code>--set-default-zone=ZONE</code>:    기본 zone 변경
<code>--get-zones</code>:    사용 가능한 zone 전체 보기
<code>--get-active-zones</code>:    활성화된 zone + 인터페이스 확인
<code>--get-services</code>:    등록된 서비스 목록 보기
<code>--list-all --zone=ZONE</code>:    zone에 구성된 모든 규칙 보기</p>
<h3 id="설정-예시">설정 예시</h3>
<h4 id="ip-소스-추가">IP 소스 추가</h4>
<p><code>firewall-cmd --zone=public --add-source=192.168.56.0/24</code></p>
<h4 id="인터페이스-추가">인터페이스 추가</h4>
<p><code>firewall-cmd --zone=internal --add-interface=eth1</code></p>
<h4 id="서비스-허용">서비스 허용</h4>
<p><code>firewall-cmd --zone=public --add-service=http</code></p>
<h4 id="포트-허용">포트 허용</h4>
<p><code>firewall-cmd --zone=public --add-port=8080/tcp</code></p>
<h4 id="영구-설정">영구 설정</h4>
<p><code>--permanent</code></p>
<h4 id="변경사항-적용">변경사항 적용</h4>
<p><code>firewall-cmd --reload</code></p>
<h4 id="런타임-설정을-영구-설정으로-저장">런타임 설정을 영구 설정으로 저장</h4>
<p><code>firewall-cmd --runtime-to-permanent</code></p>
<hr>
<h2 id="firewalld-실습-nfs--http-구성">Firewalld 실습 (NFS + HTTP 구성)</h2>
<h3 id="서버-초기화-후-필수-패키지-설치">서버 초기화 후 필수 패키지 설치</h3>
<p><code>dnf -y install nfs-utils</code>
<code>dnf -y install httpd</code></p>
<h3 id="서비스-시작--활성화">서비스 시작 &amp; 활성화</h3>
<p><code>systemctl enable nfs-server --now</code>
<code>systemctl enable httpd --now</code>
<code>systemctl status nfs-server</code></p>
<h3 id="홈-zone에-포트--프로토콜--서비스-추가-영구-설정">홈 zone에 포트 / 프로토콜 / 서비스 추가 (영구 설정)</h3>
<p><strong>포트 허용 (NFS, HTTP 관련)</strong>
<code>firewall-cmd --add-port=80/tcp --add-port=111/tcp --add-port=2049/udp --add-port=20048/tcp --permanent --zone=home</code></p>
<p><strong>프로토콜 허용 (ICMP 허용)</strong>
<code>firewall-cmd --add-protocol=icmp --permanent --zone=home</code></p>
<p>** 서비스 허용 (NFS)**
<code>firewall-cmd --add-service=nfs --permanent --zone=home</code></p>
<p><strong>변경사항 적용</strong>
<code>firewall-cmd --reload</code></p>
<h3 id="zone-확인-및-default-zone-변경">zone 확인 및 default zone 변경</h3>
<p><code>firewall-cmd --list-all --zone=home</code>
<code>firewall-cmd --set-default-zone=home</code></p>
<h3 id="웹서버-구성">웹서버 구성</h3>
<p><strong>고정 IP 설정</strong>
<code>nmcli con add con-name xxx ifname eth1 type ethernet ip4 &quot;192.168.56.100/24&quot;</code>
<code>nmcli con up xxx</code></p>
<p><strong>확인</strong>
<code>nmcli con show</code>
<code>nmcli con show xxx</code>
<code>ip addr show eth1</code></p>
<h3 id="테스트용-페이지-생성">테스트용 페이지 생성</h3>
<p><code>echo &quot;this is Rocky&quot; &gt; /var/www/html/index.html</code></p>
<h3 id="클라이언트-접속-테스트">클라이언트 접속 테스트</h3>
<p><strong>브라우저 or curl 사용</strong></p>
<p><code>http://192.168.56.100/index.html</code></p>
<p>→ &quot;this is Rocky&quot; 출력 확인</p>
<hr>
<p><img src="https://velog.velcdn.com/images/urban-jungle/post/417fe335-73dc-431b-a358-c8e2bff9439f/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[CAB TA 4기 17일차의 기록]]></title>
            <link>https://velog.io/@urban-jungle/CAB-TA-4%EA%B8%B0-17%EC%9D%BC%EC%B0%A8%EC%9D%98-%EA%B8%B0%EB%A1%9D</link>
            <guid>https://velog.io/@urban-jungle/CAB-TA-4%EA%B8%B0-17%EC%9D%BC%EC%B0%A8%EC%9D%98-%EA%B8%B0%EB%A1%9D</guid>
            <pubDate>Thu, 03 Apr 2025 06:11:50 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/urban-jungle/post/e5954729-006c-47d6-8453-7e5e786b0bdf/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/urban-jungle/post/660ed626-79eb-49cc-9506-b1598564d23b/image.png" alt=""></p>
<h2 id="systemd-실습sshd-서비스">systemd 실습(sshd 서비스)</h2>
<p><strong>1. sshd 서비스 상태 확인</strong></p>
<p><code>systemctl status sshd</code></p>
<ul>
<li>서비스 활성 상태 / 실행 상태 / PID / 로그 정보 확인</li>
</ul>
<p><strong>2. sshd 서비스 시작</strong></p>
<p><code>systemctl start sshd</code>
<code>systemctl status sshd</code></p>
<ul>
<li>실제 프로세스가 실행되는지 확인 (PID 발생)</li>
</ul>
<p><strong>3. sshd 서비스 부팅 시 자동 시작 설정 (활성화)</strong></p>
<p><code>systemctl enable sshd</code>
<code>systemctl list-unit-files | grep sshd</code></p>
<ul>
<li><code>enabled</code>로 바뀌었는지 확인</li>
</ul>
<p><strong>4. sshd 서비스 중지</strong></p>
<p><code>systemctl stop sshd</code>
<code>systemctl status sshd</code></p>
<ul>
<li><code>Active: inactive (dead)</code> 상태로 전환되는지 확인</li>
</ul>
<p><strong>5. sshd 서비스 비활성화 (부팅 시 자동 실행 해제)</strong></p>
<p><code>systemctl disable sshd</code>
<code>systemctl list-unit-files | grep sshd</code></p>
<ul>
<li>상태가 <code>disabled</code>로 바뀌는지 확인</li>
</ul>
<p><strong>6. sshd 서비스 잠금 (mask)</strong></p>
<p><code>systemctl mask sshd</code>
<code>systemctl status sshd</code></p>
<ul>
<li>상태: <code>masked</code></li>
<li>이제 <code>start</code> 명령어로도 실행 불가</li>
</ul>
<p><strong>7. sshd 서비스 잠금 해제 (unmask)</strong></p>
<p><code>systemctl unmask sshd</code>
<code>systemctl status sshd</code></p>
<ul>
<li>다시 <code>start</code> 가능</li>
</ul>
<p><strong>8. sshd 서비스 시작 후 PID 확인</strong></p>
<p><code>systemctl start sshd</code>
<code>systemctl status sshd</code></p>
<ul>
<li><code>Main PID: xxxx</code> → PID 기억해두기</li>
</ul>
<p><strong>9. sshd 서비스 리로드 후 PID 확인 (변화 없음)</strong></p>
<p><code>systemctl reload sshd</code>
<code>systemctl status sshd</code></p>
<ul>
<li>PID 변화 없어야 정상</li>
</ul>
<p><strong>10. sshd 서비스 재시작 후 PID 확인 (변화 있음)</strong></p>
<p><code>systemctl restart sshd</code>
<code>systemctl status sshd</code></p>
<ul>
<li>PID 변화해야 정상 (프로세스 재시작)</li>
</ul>
<p><strong>추가</strong></p>
<ul>
<li><code>reload</code>: 설정 파일만 다시 읽음 (프로세스 그대로 유지)</li>
<li><code>restart</code>: 완전 재시작 (PID 변경)</li>
<li><code>mask</code>: 완전 실행 금지 → <code>/dev/null</code>로 링크</li>
</ul>
<hr>
<h2 id="log-실습">log 실습</h2>
<p><strong>목표</strong></p>
<p><strong>1. <code>auth</code> 기능에서 <code>crit</code> 이상 로그만 <code>/var/log/securetest</code>에 기록
2. <code>logger</code>로 <code>auth.error</code>, <code>auth.crit</code> 메시지 테스트
3. <code>journalctl</code>에서 <code>notice</code> 이상 + <code>err</code> 이상 로그 보기</strong></p>
<p>*<em>1. rsyslog 설정 변경
*</em></p>
<p><code>vim /etc/rsyslog.conf</code></p>
<p><strong><code>#### RULES ####</code> 아래에 다음 한 줄 추가</strong></p>
<p><code>auth.crit    /var/log/securetest</code></p>
<p><strong>의미</strong></p>
<ul>
<li><code>auth facility</code>에서 <code>crit</code> 이상인 로그만 <code>/var/log/securetest</code>에 기록됨</li>
<li><code>auth.error</code>는 기록되지 않음, <code>auth.crit</code>은 기록됨</li>
</ul>
<p><strong>설정 적용</strong></p>
<p><code>systemctl restart rsyslog</code></p>
<p><strong>2. logger 명령어로 로그 발생 테스트</strong></p>
<p><code>logger -p auth.error &quot;auth.error 메시지입니다&quot;</code>
<code>logger -p auth.crit &quot;auth.critical 메시지입니다&quot;</code></p>
<p><strong>로그 확인</strong></p>
<p><code>tail -n 5 /var/log/secure</code>
→ 둘 다 기록됨 (<code>auth.error</code>, <code>auth.crit</code>)</p>
<p><code>tail -n 5 /var/log/securetest</code>
→ 오직 <code>auth.crit</code>만 기록됨</p>
<p><strong>3. journalctl 우선순위 필터링</strong></p>
<ul>
<li><p>notice(5) 이상 (즉, notice, warn, err, crit, alert, emerg)
<code>journalctl -p notice</code></p>
</li>
<li><p>err(3) 이상 (즉, err, crit, alert, emerg)
<code>journalctl -p err</code></p>
</li>
</ul>
<p><strong>실시간으로 모니터링하려면?</strong></p>
<p><code>journalctl -p err -f</code></p>
<hr>
<h2 id="rpm-패키지-관리">RPM 패키지 관리</h2>
<p><strong>1. 패키지 정보 확인</strong></p>
<p><code>rpm -q [옵션] [패키지명]</code></p>
<p><code>-a</code>:    시스템에 설치된 모든 패키지
<code>-i</code>:    패키지의 상세 정보 (설명, 버전, 설치일 등)
<code>-c</code>:    설정 파일 목록
<code>-d</code>:    문서 목록
<code>-l</code>:    설치된 파일 목록
<code>-f 파일명</code>: 해당 파일이 어떤 패키지에 속하는지</p>
<p><strong>2. 패키지 설치 / 업데이트 / 삭제</strong></p>
<ul>
<li><p>설치 또는 업그레이드
<code>rpm -Uvh 패키지파일.rpm</code></p>
</li>
<li><p>삭제
<code>rpm -e 패키지명</code></p>
</li>
<li><p><code>.rpm</code> 파일은 로컬에 있어야 함</p>
</li>
</ul>
<hr>
<h2 id="yum-또는-dnf--의존성-자동-처리">YUM (또는 DNF) – 의존성 자동 처리</h2>
<p><strong>1. 기본 명령어</strong></p>
<p><code>yum install 패키지명</code>
<code>yum remove 패키지명</code>
<code>yum update 패키지명</code>
<code>yum info 패키지명</code>
<code>yum list</code>
<code>yum provides /경로/파일명</code></p>
<p><code>yum repolist all</code> # 사용 가능한 저장소 목록 보기</p>
<p><strong>2. 그룹 패키지 관리</strong></p>
<p><code>yum group list</code>
<code>yum group install &quot;개발 도구&quot;</code>
<code>yum group remove &quot;서버 플랫폼 개발&quot;</code>
<code>yum group info &quot;보안 도구&quot;</code></p>
<p><strong>3. 로컬 패키지 설치 (의존성 포함)</strong></p>
<p><code>yum localinstall 패키지.rpm</code></p>
<h2 id="yum-repository-설정">YUM Repository 설정</h2>
<h1 id="예시-etcyumreposdbaserepo">예시 /etc/yum.repos.d/base.repo</h1>
<pre><code># 예시 /etc/yum.repos.d/base.repo

[BaseOS]
name=RockLinux BaseOS
baseurl=http://mirror.rocklinux.com/BaseOS/
enabled=1
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-RockLinux

metadata_expire=6h</code></pre><p><code>[ID명]</code>:    저장소 식별자
<code>name</code>:    저장소 설명
<code>baseurl</code>:    저장소 주소 (http, ftp, file://)
<code>enabled</code>:    1=활성화 / 0=비활성화
<code>gpgcheck</code>:    패키지 인증 여부
<code>gpgkey</code>:    인증 키 경로
<code>metadata_expire</code>:    메타데이터 만료시간</p>
<h2 id="appstream-vs-baseos">AppStream vs BaseOS</h2>
<p>BaseOS:    핵심 시스템 구성 (커널, 부트 등)
AppStream:    DB, 웹서버, 개발도구 등 자주 업데이트되는 앱들</p>
<h2 id="캐시-다시-만들기">캐시 다시 만들기</h2>
<p><code>dnf makecache</code></p>
<hr>
<h2 id="패키지-실습">패키지 실습</h2>
<p><strong>1. DVD 마운트 &amp; 준비</strong></p>
<p><code>umount /dev/cdrom</code>
<code>mkdir -p /media/cdrom</code>
<code>mount /dev/cdrom /media/cdrom</code>
<code>lsblk</code>        # 마운트 확인</p>
<p><strong>2. Repository 설정</strong></p>
<p><code>cd /etc/yum.repos.d/</code>
<code>mkdir backup</code>
<code>mv rocky* backup/</code></p>
<p><code>vim test.repo</code></p>
<pre><code>[NET_BaseOs]
name=network-baseos
baseurl=http://dl.rockylinux.org/$contentdir/$releasever/BaseOS/$basearch/os/`
enabled=1
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-Rocky-9

[NET_AppStream]
name=network-appstream
baseurl=http://dl.rockylinux.org/$contentdir/$releasever/AppStream/$basearch/os/
enabled=1
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-Rocky-9</code></pre><p><strong>3. 캐시 재생성 &amp; 저장소 확인</strong></p>
<p><code>dnf makecache</code>
<code>dnf repolist all</code></p>
<p><strong>4. NET_AppStream 비활성화</strong></p>
<p><code>vim test.repo</code></p>
<pre><code>[NET_AppStream]
...
enabled=0</code></pre><p><code>dnf repolist all</code>   # 비활성화 확인</p>
<p><strong>5. telnet 관련 패키지 검색</strong></p>
<p><code>dnf list | grep telnet</code></p>
<p><strong>6. telnet 패키지 설치 &amp; socket 활성화</strong></p>
<p><code>dnf install telnet*</code>
<code>systemctl enable telnet.socket --now</code></p>
<p><strong>텔넷이 다운되어있지 않다면?</strong>
<code>vim test.repo</code></p>
<pre><code>[NET_AppStream]
...
enabled=1</code></pre><p><code>dnf install telnet-server</code></p>
<pre><code>[NET_AppStream]
...
enabled=0</code></pre><p><strong>7. telnet 설정파일 &amp; 문서 확인</strong></p>
<p><code>rpm -qc telnet</code>     # config files
<code>rpm -qd telnet</code>     # doc files</p>
<p><strong>8. rsyslog.conf가 어떤 패키지에서 나왔는지 확인</strong></p>
<p><code>rpm -qf /etc/rsyslog.conf</code>
<code>dnf provides /etc/rsyslog.conf</code></p>
<p><strong>9. rsyslog 패키지 정보 확인</strong></p>
<p><code>rpm -qi rsyslog</code>
<code>dnf info rsyslog</code></p>
<p><strong>10. Security 관련 그룹 패키지 찾기</strong></p>
<p><code>dnf group list | grep -i security</code></p>
<p>→ 예시 결과: <code>Security Tools</code> or <code>보안 도구</code></p>
<p><strong>11. 해당 그룹의 상세 정보 확인</strong></p>
<p><code>dnf group info &quot;Security Tools&quot;</code></p>
<p><strong>12. zsh RPM 파일 yum으로 설치</strong></p>
<p><code>dnf localinstall /media/cdrom/BaseOS/Packages/z/zsh-5.8-9.el9.x86_64.rpm</code></p>
<hr>
<h2 id="네트워크-설정">네트워크 설정</h2>
<p><strong>네트워크 상태 확인</strong></p>
<p><code>ip addr</code><br><code>ip addr show 인터페이스명</code> 
<code>ifconfig</code><br><code>ifconfig 인터페이스명</code></p>
<h2 id="nmcli-명령어-정리"><strong>nmcli 명령어 정리</strong></h2>
<p><strong>기본 명령</strong></p>
<p><code>nmcli device</code>:    장치(device) 목록 확인
<code>nmcli con show</code>:    현재 연결 목록 확인
<code>nmcli con show 연결명</code>:    연결 상세 설정 보기
<code>nmcli con add ...</code>:    연결 생성
<code>nmcli con mod ...</code>:    연결 수정
<code>nmcli con delete ...</code>:    연결 삭제
<code>nmcli con up 연결명</code>:    연결 활성화
<code>nmcli con down 연결명</code>:    연결 비활성화
<code>nmcli con reload</code>:    연결 설정 재적용</p>
<h2 id="연결-생성-실습">연결 생성 실습</h2>
<p><strong>유동 IP 설정 (DHCP 방식)</strong></p>
<p><code>nmcli con add \</code>
<code>con-name dhcp7 \</code>
<code>ifname enp0s7 \</code>
<code>type ethernet \</code>
<code>autoconnect yes</code></p>
<ul>
<li><code>ipv4.method</code> 자동 설정 → <code>auto</code></li>
</ul>
<p><strong>고정 IP 설정 (Static 방식)</strong></p>
<p><code>nmcli con add \</code>
<code>con-name static7 \</code>
<code>ifname enp0s7 \</code>
<code>type ethernet \</code>
<code>autoconnect no \</code>
<code>ip4 10.100.5.100/24 \</code>
<code>gw4 10.100.5.2 \</code>
<code>ipv4.method manual</code></p>
<ul>
<li>주의: <code>ipv4.method manual</code> 반드시 포함</li>
</ul>
<p><strong>연결 상태 확인</strong></p>
<p><code>nmcli con show static7</code></p>
<ul>
<li>주요 항목 예시</li>
<li><code>connection.autoconnect</code>: yes / no</li>
<li><code>ipv4.method</code>: auto / manual</li>
<li><code>ipv4.addresses</code>, <code>ipv4.gateway</code></li>
</ul>
<h2 id="연결-수정-실습">연결 수정 실습</h2>
<p><strong>DHCP → 고정 IP 변경</strong></p>
<p><code>nmcli con mod dhcp7 \</code>
<code>connection.id static7-1 \</code>
<code>ipv4.method manual \</code>
<code>ipv4.addresses 10.100.5.200/24 \</code>
<code>ipv4.gateway 10.100.5.2 \</code>
<code>ipv4.dns 10.100.5.100</code></p>
<p><strong>고정 IP → DHCP 변경</strong></p>
<p><code>nmcli con mod static7 \</code>
<code>connection.id dhcp7-1 \</code>
<code>ipv4.method auto \</code>
<code>ipv4.addresses &quot;&quot; \</code>
<code>ipv4.gateway &quot;&quot; \</code>
<code>ipv4.dns &quot;8.8.8.8 10.100.5.100&quot; \</code>
<code>connection.autoconnect yes</code></p>
<h2 id="호스트명-설정">호스트명 설정</h2>
<p><code>hostname</code>:    현재 호스트명 확인
<code>cat /etc/hostname</code>:    설정된 호스트명 파일 확인
<code>hostnamectl set-hostname 새이름</code>:    호스트명 변경</p>
<p><strong>추가</strong></p>
<ul>
<li>연결 이름 바꿀 때는 <code>connection.id</code> 사용</li>
<li>연결 삭제는 <code>nmcli con delete 연결명</code></li>
<li>설정 후 <code>nmcli con up 연결명</code> 으로 적용</li>
</ul>
<p><strong>기억하면 좋은 포인트</strong></p>
<ul>
<li><code>ipv4.method manual</code> → 꼭 고정 IP 설정에 필요</li>
<li><code>ip4</code>, <code>gw4</code> → IP와 게이트웨이 주소 설정</li>
<li>연결 수정 시 DNS 추가는 <code>ipv4.dns</code></li>
<li>연결 비활성화 상태라도 수동 up 가능</li>
<li><code>nmcli con reload</code>로 설정 리로드</li>
</ul>
<hr>
<h2 id="네트워크-실습">네트워크 실습</h2>
<h3 id="현재-ip-주소-확인-2가지-방법">현재 IP 주소 확인 (2가지 방법)</h3>
<p><strong>전체 IP 확인</strong></p>
<p><code>ifconfig</code>
<code>ip addr</code></p>
<p><strong>특정 인터페이스(eth2) 확인</strong></p>
<p><code>ifconfig eth2</code>
<code>ip addr show eth2</code></p>
<h3 id="연결-생성-with-nmcli-con-add">연결 생성 with nmcli con add</h3>
<p><strong>1. 유동 IP 연결 생성 (DHCP 방식)</strong></p>
<p><code>nmcli con add con-name dhcp type ethernet ifname eth2</code></p>
<p><strong>2. 고정 IP 연결 생성 (Static 방식)</strong></p>
<p><code>nmcli con add \</code>
<code>con-name static2 \</code>
<code>type ethernet \</code>
<code>ifname eth2 \</code>
<code>ip4 192.168.56.200/24 \</code>
<code>gw4 192.168.56.1</code></p>
<h3 id="연결-수정-with-nmcli-con-mod">연결 수정 with nmcli con mod</h3>
<p><strong>기존 dhcp 연결을 다음과 같이 수정</strong></p>
<ul>
<li>이름: <code>static</code>으로 변경</li>
<li>IP: <code>192.168.56.120/24</code> 설정</li>
<li>추가 IP: <code>192.168.56.30/24</code></li>
<li>DNS: <code>8.8.8.8</code></li>
<li>자동 연결 해제</li>
<li>method: manual로 변경</li>
</ul>
<p><code>nmcli con mod dhcp \</code>
<code>connection.id static \</code>
<code>ipv4.addresses 192.168.56.120/24 \</code>
<code>ipv4.gateway 192.168.56.1 \</code>
<code>+ipv4.addresses 192.168.56.30/24 \</code>
<code>ipv4.dns 8.8.8.8 \</code>
<code>connection.autoconnect no \</code>
<code>ipv4.method manual</code></p>
<h3 id="특정-주소-제거-예-1921685612024">특정 주소 제거 (예: 192.168.56.120/24)</h3>
<p><code>nmcli con mod static -ipv4.addresses 192.168.56.120/24</code></p>
<h3 id="호스트명-변경">호스트명 변경</h3>
<p><code>hostnamectl hostname nobreak.com</code></p>
<p><strong>변경확인</strong></p>
<p><code>hostname</code></p>
<h3 id="요약">요약</h3>
<p>IP 전체 확인:    <code>ip addr / ifconfig</code>
eth2 확인:    <code>ip addr show eth2</code>
DHCP 연결 생성:    <code>nmcli con add con-name dhcp ...</code>
Static 연결 생성:    <code>nmcli con add con-name static2 ...</code>
연결 이름/속성 변경:    <code>nmcli con mod ...</code>
주소 제거:    <code>nmcli con mod static -ipv4.addresses 주소/넷마스크</code>
호스트명 설정:    <code>hostnamectl hostname 호스트명</code></p>
<hr>
<p><img src="https://velog.velcdn.com/images/urban-jungle/post/f7219410-cd97-4b34-95ca-c41aa73d794f/image.png" alt=""></p>
]]></description>
        </item>
    </channel>
</rss>