🤖

본 콘텐츠의 이미지 및 내용은 AI로 생성되었습니다.

⚠️

본 콘텐츠의 이미지 및 내용을 무단으로 복제, 배포, 수정하여 사용할 경우 저작권법에 의해 법적 제재를 받을 수 있습니다.

이미지 로딩 중...

EC2 인스턴스의 이해와 생성 실습 완벽 가이드 - 슬라이드 1/7
A

AI Generated

2025. 12. 23. · 3 Views

EC2 인스턴스의 이해와 생성 실습 완벽 가이드

AWS EC2의 기본 개념부터 인스턴스 생성, 접속, 관리까지 베스트셀러 입문서 스타일로 쉽게 배웁니다. 클라우드 컴퓨팅의 핵심인 EC2를 실무 중심 스토리텔링으로 술술 읽으며 이해할 수 있습니다.


목차

  1. EC2 인스턴스란 무엇인가
  2. 인스턴스 타입 선택 가이드
  3. AMI(Amazon Machine Image) 이해하기
  4. 첫 번째 EC2 인스턴스 생성 실습
  5. SSH로 인스턴스 접속하기
  6. 인스턴스 시작/중지/종료 관리

1. EC2 인스턴스란 무엇인가

어느 날 김개발 씨가 회사에서 새로운 프로젝트를 맡게 되었습니다. 팀장님이 말씀하셨습니다.

"이번 서비스는 EC2에 배포할 거예요." 김개발 씨는 고개를 끄덕였지만, 사실 EC2가 정확히 무엇인지 잘 몰랐습니다.

**EC2(Elastic Compute Cloud)**는 아마존 웹 서비스에서 제공하는 클라우드 컴퓨팅 서비스입니다. 마치 컴퓨터를 빌려 쓰는 것처럼, 필요한 만큼의 서버를 클릭 몇 번으로 생성하고 사용할 수 있습니다.

물리적인 서버를 구매하거나 관리할 필요 없이, 인터넷을 통해 가상의 서버를 즉시 사용할 수 있는 것이 가장 큰 장점입니다.

다음 코드를 살펴봅시다.

// AWS SDK를 사용한 EC2 인스턴스 정보 조회 예제
const { EC2Client, DescribeInstancesCommand } = require('@aws-sdk/client-ec2');

// EC2 클라이언트 생성
const client = new EC2Client({ region: 'ap-northeast-2' });

async function getInstanceInfo() {
  try {
    // 실행 중인 인스턴스 조회
    const command = new DescribeInstancesCommand({});
    const response = await client.send(command);

    // 각 인스턴스의 정보 출력
    response.Reservations.forEach(reservation => {
      reservation.Instances.forEach(instance => {
        console.log(`인스턴스 ID: ${instance.InstanceId}`);
        console.log(`상태: ${instance.State.Name}`);
        console.log(`타입: ${instance.InstanceType}`);
        console.log(`IP 주소: ${instance.PublicIpAddress}`);
      });
    });
  } catch (error) {
    console.error('인스턴스 조회 실패:', error);
  }
}

getInstanceInfo();

김개발 씨는 점심시간에 선배 박시니어 씨에게 조심스럽게 물어봤습니다. "선배님, EC2가 정확히 뭔가요?" 박시니어 씨는 커피를 한 모금 마시고 친절하게 설명을 시작했습니다.

"좋은 질문이에요. EC2를 이해하려면 먼저 예전 방식을 알아야 해요." 과거에는 웹 서비스를 시작하려면 직접 서버를 구매해야 했습니다.

비싼 돈을 주고 서버 컴퓨터를 사고, IDC 센터에 입주시키고, 관리 인력을 고용해야 했습니다. 문제는 서비스가 잘될지 안 될지도 모르는 상황에서 이런 큰 투자를 해야 한다는 점이었습니다.

더 큰 문제는 확장성이었습니다. 갑자기 사용자가 몰리면 서버가 다운되고, 새 서버를 추가하려면 몇 주가 걸렸습니다.

반대로 사용자가 줄어들면 비싼 서버가 놀고 있어도 어쩔 수 없었습니다. 바로 이런 문제를 해결하기 위해 클라우드 컴퓨팅이 등장했습니다.

EC2는 쉽게 말하면 아마존이 운영하는 거대한 컴퓨터 대여점입니다. 마치 렌터카를 빌리듯이, 필요한 사양의 서버를 클릭 몇 번으로 빌릴 수 있습니다.

소형차가 필요하면 소형 인스턴스를, 트럭이 필요하면 대형 인스턴스를 선택하면 됩니다. 김개발 씨가 고개를 끄덕이자 박시니어 씨가 계속 설명합니다.

"EC2의 가장 큰 장점은 **탄력성(Elastic)**이에요. 사용자가 늘어나면 서버를 추가하고, 줄어들면 서버를 줄일 수 있죠.

몇 분이면 됩니다." 실제로 많은 스타트업이 EC2로 시작합니다. 처음에는 가장 작은 인스턴스 하나로 시작해서, 서비스가 성장하면 점진적으로 서버를 늘려갑니다.

투자 리스크를 최소화하면서도 빠르게 시작할 수 있는 것입니다. EC2 인스턴스는 기본적으로 가상 서버입니다.

하나의 물리적 서버 안에 여러 개의 가상 서버가 돌아가는 구조입니다. 마치 아파트 한 동에 여러 세대가 사는 것처럼, 각 인스턴스는 독립적인 공간을 가지고 있습니다.

위의 코드를 살펴보면, AWS SDK를 사용해서 현재 실행 중인 EC2 인스턴스의 정보를 조회하는 것을 볼 수 있습니다. 이렇게 프로그래밍 방식으로도 EC2를 제어할 수 있다는 점이 매우 강력합니다.

실무에서는 어떻게 활용할까요? 대표적인 예가 쇼핑몰 서비스입니다.

평소에는 작은 인스턴스로 운영하다가, 블랙프라이데이 같은 특별 행사 기간에는 자동으로 인스턴스를 늘려서 트래픽을 감당합니다. 행사가 끝나면 다시 줄이면 됩니다.

비용은 사용한 만큼만 지불하면 됩니다. 하지만 주의할 점도 있습니다.

인스턴스를 생성하고 나서 **종료(Terminate)**하지 않고 **중지(Stop)**만 하면, 저장 공간에 대한 비용은 계속 청구됩니다. 마치 렌터카를 반납하지 않고 주차만 해놓은 것과 같습니다.

김개발 씨는 이제 EC2가 무엇인지 확실히 이해했습니다. "아, 그러니까 우리가 직접 서버를 사지 않아도 되는 거네요!" 박시니어 씨가 웃으며 말했습니다.

"정확해요. 이제 인스턴스를 직접 만들어볼까요?"

실전 팁

💡 - EC2는 초 단위로 과금됩니다. 사용하지 않는 인스턴스는 반드시 종료하세요.

  • 처음에는 **프리 티어(무료 사용량)**를 활용해서 연습하면 좋습니다.
  • 인스턴스 타입은 언제든지 변경할 수 있으니, 처음부터 큰 사양을 선택할 필요는 없습니다.

2. 인스턴스 타입 선택 가이드

EC2 콘솔에 처음 들어간 김개발 씨는 당황했습니다. t2.micro, m5.large, c5.xlarge...

알 수 없는 이름들이 가득했습니다. "도대체 뭘 선택해야 하는 거지?" 선배에게 또다시 SOS를 요청할 시간입니다.

인스턴스 타입은 EC2 서버의 사양을 정의하는 것입니다. CPU, 메모리, 네트워크 성능 등이 타입마다 다르며, 각각의 알파벳은 특정 용도를 의미합니다.

마치 자동차를 고를 때 경차, 세단, SUV를 선택하는 것처럼, 서비스의 특성에 맞는 인스턴스 타입을 선택하는 것이 중요합니다.

다음 코드를 살펴봅시다.

// 인스턴스 타입별 특성을 코드로 표현
const instanceTypes = {
  // T 시리즈: 범용, 버스트 가능 (일반적인 웹 서버)
  't2.micro': {
    vCPU: 1,
    memory: '1GB',
    network: '낮음-보통',
    use: '개발/테스트, 소규모 웹사이트',
    price: '매우 저렴'
  },
  't3.medium': {
    vCPU: 2,
    memory: '4GB',
    network: '최대 5Gbps',
    use: '중소규모 웹 애플리케이션',
    price: '저렴'
  },
  // M 시리즈: 균형 잡힌 컴퓨팅, 메모리, 네트워크
  'm5.large': {
    vCPU: 2,
    memory: '8GB',
    network: '최대 10Gbps',
    use: '데이터베이스, 백엔드 서버',
    price: '보통'
  },
  // C 시리즈: CPU 집약적 작업
  'c5.xlarge': {
    vCPU: 4,
    memory: '8GB',
    network: '최대 10Gbps',
    use: '게임 서버, 과학 계산, 동영상 인코딩',
    price: '높음'
  },
  // R 시리즈: 메모리 집약적 작업
  'r5.large': {
    vCPU: 2,
    memory: '16GB',
    network: '최대 10Gbps',
    use: '대용량 캐시, 인메모리 DB',
    price: '높음'
  }
};

// 용도에 맞는 인스턴스 추천 함수
function recommendInstance(workload) {
  const recommendations = {
    '웹서버': ['t3.micro', 't3.small', 't3.medium'],
    '데이터베이스': ['m5.large', 'r5.large'],
    '게임서버': ['c5.large', 'c5.xlarge'],
    '캐시서버': ['r5.large', 'r5.xlarge']
  };

  return recommendations[workload] || ['t3.micro'];
}

console.log('웹 서버 추천:', recommendInstance('웹서버'));

박시니어 씨가 화이트보드에 그림을 그리기 시작했습니다. "인스턴스 타입은 생각보다 간단해요.

알파벳만 이해하면 돼요." AWS는 인스턴스 타입을 체계적으로 분류해 놓았습니다. 마치 자동차 제조사가 차량을 세단, SUV, 트럭으로 분류하는 것처럼, EC2도 용도별로 타입을 나눠놨습니다.

첫 번째 알파벳이 가장 중요합니다. T 시리즈는 범용 인스턴스입니다.

대부분의 웹 서비스는 T 시리즈로 충분합니다. 특히 T 시리즈의 특징은 크레딧 시스템입니다.

평소에는 CPU를 조금만 쓰다가, 갑자기 부하가 몰리면 크레딧을 써서 성능을 높일 수 있습니다. 마치 평소에 연비 좋게 운전하다가 필요할 때 가속 페달을 밟는 것과 같습니다.

김개발 씨가 물었습니다. "그럼 처음 시작할 때는 T 시리즈를 쓰면 되나요?" "맞아요.

특히 t3.microt3.small이 좋습니다. 프리 티어로 t2.micro를 1년간 무료로 쓸 수도 있고요." M 시리즈는 균형 잡힌 성능이 필요할 때 사용합니다.

CPU, 메모리, 네트워크가 골고루 좋은 타입입니다. 데이터베이스 서버나 중규모 이상의 백엔드 애플리케이션에 적합합니다.

마치 세단이 일상 생활에 두루 쓰이는 것처럼, M 시리즈는 범용적으로 활용됩니다. C 시리즈는 CPU 파워가 중요할 때 선택합니다.

같은 가격이면 메모리는 좀 적지만 CPU 코어 수와 성능이 높습니다. 게임 서버, 동영상 인코딩, 과학 계산처럼 CPU를 많이 쓰는 작업에 최적화되어 있습니다.

R 시리즈는 메모리가 많이 필요한 작업용입니다. 같은 CPU 코어 수 대비 메모리가 2배 이상 많습니다.

Redis 같은 인메모리 캐시나 대용량 데이터를 다루는 작업에 사용합니다. 박시니어 씨가 실제 사례를 들려줬습니다.

"우리 회사 초기에는 t2.micro 하나로 시작했어요. 사용자가 100명도 안 됐거든요.

그러다 서비스가 커지면서 t3.medium으로 업그레이드했고, 지금은 웹 서버는 t3.large, 데이터베이스는 m5.xlarge를 쓰고 있어요." 숫자와 세대도 중요합니다. t2, t3, t4...

숫자가 클수록 최신 세대입니다. 같은 가격이면 최신 세대가 성능이 더 좋고 효율적입니다.

마치 같은 가격의 2020년 모델과 2024년 모델 중 당연히 최신 모델을 선택하는 것과 같습니다. 뒤의 크기 표시도 체계적입니다.

nano < micro < small < medium < large < xlarge < 2xlarge... 순서로 커집니다.

각 단계마다 대략 2배씩 성능이 올라갑니다. 실무 팁 하나를 알려드리자면, 처음에는 작은 인스턴스로 시작해서 모니터링 결과를 보고 결정하는 것이 좋습니다.

CloudWatch를 보면 CPU 사용률, 메모리 사용률을 알 수 있습니다. CPU가 항상 80퍼센트 이상이면 C 시리즈나 상위 타입으로, 메모리가 부족하면 M이나 R 시리즈를 고려하면 됩니다.

주의할 점은 과도한 사양 선택입니다. 초보자들은 혹시 모를 부하를 대비해서 처음부터 큰 인스턴스를 선택하는 경우가 많습니다.

하지만 클라우드의 장점은 필요할 때 늘리고 줄일 수 있다는 점입니다. 작게 시작해서 필요할 때 키우는 것이 비용 효율적입니다.

김개발 씨가 정리하듯 말했습니다. "T는 일반 웹, M은 균형형, C는 CPU, R은 메모리...

생각보다 간단하네요!" 박시니어 씨가 웃으며 대답했습니다. "맞아요.

처음에는 t3.micro로 시작하면 됩니다."

실전 팁

💡 - 대부분의 웹 서비스는 T3 시리즈로 충분합니다.

  • 인스턴스 타입은 중지 후 변경 가능하니 작게 시작하세요.
  • 모니터링을 통해 실제 사용량을 확인한 후 최적의 타입을 선택하세요.

3. AMI(Amazon Machine Image) 이해하기

인스턴스 타입을 선택한 김개발 씨는 다음 화면에서 또 막혔습니다. "AMI를 선택하세요"라는 메시지가 떴는데, Amazon Linux, Ubuntu, Windows Server 등 수십 개의 선택지가 나타났습니다.

"이건 또 뭐지?" 김개발 씨의 한숨 소리가 들렸습니다.

**AMI(Amazon Machine Image)**는 EC2 인스턴스의 기본 소프트웨어 구성을 담은 템플릿입니다. 마치 스마트폰을 살 때 안드로이드와 iOS 중 선택하는 것처럼, 서버에 어떤 운영체제와 기본 소프트웨어가 설치될지를 정하는 것입니다.

한 번 선택하면 해당 설정이 적용된 서버가 생성됩니다.

다음 코드를 살펴봅시다.

// AMI를 사용한 EC2 인스턴스 생성 예제
const { EC2Client, RunInstancesCommand, DescribeImagesCommand } = require('@aws-sdk/client-ec2');

const client = new EC2Client({ region: 'ap-northeast-2' });

// 가장 최신 Amazon Linux 2 AMI 찾기
async function getLatestAmazonLinuxAMI() {
  const command = new DescribeImagesCommand({
    Filters: [
      {
        Name: 'name',
        Values: ['amzn2-ami-hvm-*-x86_64-gp2']
      },
      {
        Name: 'state',
        Values: ['available']
      }
    ],
    Owners: ['amazon']
  });

  const response = await client.send(command);
  // 가장 최신 이미지 선택
  const sortedImages = response.Images.sort((a, b) =>
    new Date(b.CreationDate) - new Date(a.CreationDate)
  );

  return sortedImages[0].ImageId;
}

// AMI를 사용하여 인스턴스 생성
async function createInstance() {
  const amiId = await getLatestAmazonLinuxAMI();

  const command = new RunInstancesCommand({
    ImageId: amiId, // AMI ID 지정
    InstanceType: 't3.micro',
    MinCount: 1,
    MaxCount: 1,
    KeyName: 'my-key-pair', // SSH 키 페어
    TagSpecifications: [{
      ResourceType: 'instance',
      Tags: [{ Key: 'Name', Value: 'MyFirstInstance' }]
    }]
  });

  const response = await client.send(command);
  console.log('인스턴스 생성됨:', response.Instances[0].InstanceId);
}

createInstance();

박시니어 씨가 김개발 씨의 화면을 보고 미소를 지었습니다. "AMI는 어렵지 않아요.

컴퓨터에 윈도우를 깔지 맥OS를 깔지 선택하는 것과 같아요." AMI를 이해하려면 먼저 서버 구축 과정을 떠올려봐야 합니다. 예전에는 새 서버를 받으면 운영체제부터 설치해야 했습니다.

CD를 넣고 몇 시간 기다리면서 Windows Server나 Linux를 설치했습니다. 그다음에는 웹 서버 소프트웨어, 데이터베이스, 각종 라이브러리를 하나하나 설치했습니다.

하루 종일 걸리는 일이었습니다. 더 큰 문제는 서버를 여러 대 만들 때였습니다.

똑같은 설정을 10대, 100대의 서버에 반복해야 했습니다. 실수도 잦았고, 서버마다 미묘하게 설정이 달라지는 일도 빈번했습니다.

바로 이 문제를 해결하는 것이 AMI입니다. AMI는 쉽게 말해 서버의 스냅샷입니다.

마치 게임에서 세이브 파일처럼, 특정 시점의 서버 상태를 그대로 저장해둔 것입니다. 운영체제, 설치된 프로그램, 설정 파일, 심지어 데이터까지 모두 포함됩니다.

박시니어 씨가 예를 들어 설명했습니다. "우리 회사 웹 서버를 예로 들어볼게요.

Node.js, Nginx, PM2가 모두 설치되고 설정된 상태의 서버를 AMI로 만들어뒀어요. 새로운 서버가 필요하면 이 AMI로 인스턴스를 만들면 몇 분 만에 똑같은 서버가 생성됩니다." AMI는 크게 세 종류로 나눌 수 있습니다.

첫째, AWS 공식 AMI입니다. Amazon Linux, Ubuntu, Windows Server 등 AWS가 직접 만들어서 제공하는 이미지입니다.

가장 안정적이고 보안 업데이트도 꾸준히 제공됩니다. 대부분의 경우 이것을 사용하면 됩니다.

둘째, Marketplace AMI입니다. 다른 회사나 개발자가 만들어서 판매하는 이미지입니다.

예를 들어 WordPress가 미리 설치된 AMI, 데이터 분석 도구가 설치된 AMI 등이 있습니다. 초기 설정을 건너뛸 수 있어서 편리하지만, 유료인 경우가 많습니다.

셋째, 커스텀 AMI입니다. 자신이 직접 만든 이미지입니다.

서버를 원하는 대로 설정한 후 AMI로 저장하면, 똑같은 서버를 계속 만들 수 있습니다. 위의 코드를 보면 프로그래밍 방식으로 최신 Amazon Linux AMI를 찾고 인스턴스를 생성하는 것을 볼 수 있습니다.

ImageId가 바로 AMI의 고유 ID입니다. 이 ID만 있으면 언제든지 똑같은 환경의 서버를 만들 수 있습니다.

실무에서는 어떻게 활용할까요? 대표적인 패턴이 골든 이미지 방식입니다.

개발팀이 서버를 완벽하게 설정하고 테스트한 후 AMI로 만듭니다. 이후 모든 서버는 이 골든 이미지로 생성합니다.

이렇게 하면 환경 차이로 인한 버그를 예방할 수 있습니다. 자동 확장(Auto Scaling)에서도 AMI가 핵심입니다.

트래픽이 늘어나면 자동으로 서버를 추가해야 하는데, 이때 어떤 서버를 만들지 AMI로 정의해둡니다. 수작업 없이 동일한 서버가 자동으로 생성됩니다.

주의할 점도 있습니다. AMI에는 리전 개념이 있습니다.

서울 리전에서 만든 AMI는 서울에서만 사용할 수 있습니다. 다른 리전에서 쓰려면 복사해야 합니다.

또한 AMI는 저장 공간을 차지합니다. 사용하지 않는 AMI는 삭제해서 비용을 절약해야 합니다.

마치 클라우드 스토리지에 파일이 쌓이는 것과 같습니다. 김개발 씨가 이해했다는 표정을 지었습니다.

"아, 그러니까 AMI는 서버 복사본 같은 거네요. 한 번 만들어두면 계속 똑같은 서버를 찍어낼 수 있고요." 박시니어 씨가 엄지를 치켜세웠습니다.

"완벽해요!"

실전 팁

💡 - 처음에는 Amazon Linux 2 또는 Ubuntu를 추천합니다.

  • 서버 설정을 완료한 후 커스텀 AMI를 만들어두면 나중에 시간을 절약할 수 있습니다.
  • AMI는 리전별로 관리되므로 필요한 리전에 복사해두세요.

4. 첫 번째 EC2 인스턴스 생성 실습

드디어 실전입니다. 김개발 씨는 손을 비비며 EC2 콘솔의 "인스턴스 시작" 버튼 앞에 섰습니다.

박시니어 씨가 옆에서 하나하나 가이드를 해주기로 했습니다. "긴장하지 마세요.

클릭 몇 번이면 끝나요."

EC2 인스턴스 생성은 AWS 콘솔에서 단계별로 진행됩니다. 이름 지정, AMI 선택, 인스턴스 타입 선택, 키 페어 생성, 보안 그룹 설정까지 각 단계를 거치면 몇 분 만에 서버가 생성됩니다.

마치 온라인 쇼핑몰에서 옵션을 선택하고 주문하는 것처럼 간단한 프로세스입니다.

다음 코드를 살펴봅시다.

// AWS SDK로 EC2 인스턴스 생성하는 완전한 예제
const { EC2Client, RunInstancesCommand, CreateKeyPairCommand } = require('@aws-sdk/client-ec2');
const fs = require('fs');

const client = new EC2Client({ region: 'ap-northeast-2' });

async function createFirstInstance() {
  try {
    // 1단계: SSH 키 페어 생성
    const keyPairCommand = new CreateKeyPairCommand({
      KeyName: 'my-first-key-pair'
    });
    const keyPairResponse = await client.send(keyPairCommand);

    // 키를 파일로 저장 (매우 중요!)
    fs.writeFileSync('my-first-key-pair.pem', keyPairResponse.KeyMaterial);
    console.log('키 페어 생성 완료: my-first-key-pair.pem');

    // 2단계: 인스턴스 생성
    const runCommand = new RunInstancesCommand({
      ImageId: 'ami-0c9c942bd7bf113a2', // Amazon Linux 2 (서울 리전)
      InstanceType: 't3.micro',
      MinCount: 1,
      MaxCount: 1,
      KeyName: 'my-first-key-pair',
      SecurityGroupIds: ['sg-xxxxxxxxx'], // 보안 그룹 ID
      TagSpecifications: [{
        ResourceType: 'instance',
        Tags: [
          { Key: 'Name', Value: '김개발의 첫 인스턴스' },
          { Key: 'Environment', Value: 'Development' }
        ]
      }],
      // 사용자 데이터: 인스턴스 시작 시 자동 실행될 스크립트
      UserData: Buffer.from(`#!/bin/bash
        yum update -y
        yum install -y nginx
        systemctl start nginx
        systemctl enable nginx
        echo "<h1>Hello from EC2!</h1>" > /usr/share/nginx/html/index.html
      `).toString('base64')
    });

    const response = await client.send(runCommand);
    const instance = response.Instances[0];

    console.log('인스턴스 생성 성공!');
    console.log('인스턴스 ID:', instance.InstanceId);
    console.log('상태:', instance.State.Name);
    console.log('몇 분 후 퍼블릭 IP로 접속 가능합니다.');

  } catch (error) {
    console.error('인스턴스 생성 실패:', error);
  }
}

createFirstInstance();

박시니어 씨가 AWS 콘솔을 열고 설명을 시작했습니다. "자, 따라 해보세요.

어렵지 않아요." 먼저 EC2 대시보드에서 주황색 "인스턴스 시작" 버튼을 클릭합니다. 그러면 인스턴스 생성 마법사가 시작됩니다.

첫 번째 단계는 이름과 태그입니다. "인스턴스 이름은 뭐라고 할까요?" 김개발 씨가 물었습니다.

박시니어 씨가 답했습니다. "보통 용도와 환경을 표시해요.

예를 들어 'dev-web-server' 같은 식이죠." 이름은 나중에 여러 인스턴스를 관리할 때 매우 중요합니다. 마치 파일 이름을 잘 지어야 나중에 찾기 쉬운 것과 같습니다.

명확하고 일관된 명명 규칙을 정해두는 것이 좋습니다. 두 번째 단계는 AMI 선택입니다.

"처음이니까 Amazon Linux 2를 선택하세요. 프리 티어도 지원하고 AWS와 가장 잘 호환돼요." 김개발 씨는 목록에서 "Amazon Linux 2 AMI"를 찾아 클릭했습니다.

세 번째 단계는 인스턴스 타입입니다. 기본값으로 t2.micro가 선택되어 있었습니다.

"프리 티어 사용 가능"이라는 표시가 보였습니다. 박시니어 씨가 말했습니다.

"처음에는 이걸로 충분해요. 나중에 필요하면 언제든 변경할 수 있어요." **네 번째 단계가 중요합니다.

키 페어 생성**입니다. "키 페어는 뭔가요?" 김개발 씨가 물었습니다.

박시니어 씨가 설명했습니다. "서버에 접속하기 위한 열쇠예요.

비밀번호 대신 파일로 된 키를 사용합니다." "새 키 페어 생성"을 클릭하고 이름을 입력합니다. RSA 타입에 .pem 형식을 선택합니다.

"생성" 버튼을 누르면 .pem 파일이 자동으로 다운로드됩니다. 박시니어 씨가 강조했습니다.

"이 파일은 절대 잃어버리면 안 돼요. 이 파일이 없으면 인스턴스에 접속할 수 없어요.

USB에도 백업해두세요." 다섯 번째 단계는 네트워크 설정입니다. 보안 그룹은 방화벽과 같습니다.

어떤 트래픽을 허용할지 정합니다. 기본적으로 SSH(22번 포트)가 허용되어 있습니다.

웹 서버를 운영한다면 HTTP(80)와 HTTPS(443) 포트도 열어야 합니다. "내 IP에서만 SSH 접속 허용"을 선택하면 보안이 강화됩니다.

마치 집 현관문을 특정 사람에게만 열어주는 것과 같습니다. 여섯 번째는 스토리지 설정입니다.

기본값인 8GB로도 충분하지만, 필요하면 늘릴 수 있습니다. 프리 티어는 30GB까지 무료입니다.

위의 코드를 보면 UserData 부분이 흥미롭습니다. 이것은 인스턴스가 시작될 때 자동으로 실행되는 스크립트입니다.

예제에서는 Nginx 웹 서버를 자동으로 설치하고 실행합니다. 이렇게 하면 인스턴스가 생성되자마자 바로 웹 서버가 돌아가는 상태가 됩니다.

모든 설정을 마치고 "인스턴스 시작" 버튼을 클릭합니다. 잠시 후 "인스턴스가 시작 중입니다"라는 메시지가 나타납니다.

김개발 씨가 신기한 듯 화면을 바라봤습니다. "벌써요?" EC2 대시보드로 돌아가면 방금 만든 인스턴스가 보입니다.

상태가 "pending"에서 "running"으로 바뀌면 사용 가능합니다. 보통 1-2분 정도 걸립니다.

인스턴스를 클릭하면 상세 정보를 볼 수 있습니다. 퍼블릭 IPv4 주소가 중요합니다.

이 주소로 서버에 접속할 수 있습니다. 실무 팁을 알려드리자면, Elastic IP를 할당하는 것이 좋습니다.

일반 퍼블릭 IP는 인스턴스를 중지했다가 다시 시작하면 바뀝니다. Elastic IP는 고정 IP로, 한 번 할당하면 계속 유지됩니다.

주의할 점은 보안 그룹 설정입니다. 초보자들이 흔히 하는 실수가 모든 IP(0.0.0.0/0)에서 SSH 접속을 허용하는 것입니다.

이렇게 하면 전 세계 누구나 접속을 시도할 수 있어 위험합니다. 꼭 필요한 IP만 허용하세요.

김개발 씨의 첫 번째 인스턴스가 running 상태가 되었습니다. 박시니어 씨가 축하했습니다.

"성공이에요! 이제 여러분만의 클라우드 서버가 생겼어요."

실전 팁

💡 - 키 페어 파일(.pem)은 안전한 곳에 백업하세요. 분실하면 인스턴스 접속이 불가능합니다.

  • 보안 그룹은 최소 권한 원칙을 따르세요. 필요한 포트만 열고, 가능하면 IP 범위를 제한하세요.
  • 태그를 잘 활용하면 나중에 비용 관리와 리소스 관리가 쉬워집니다.

5. SSH로 인스턴스 접속하기

인스턴스가 running 상태가 된 김개발 씨는 들떠 있었습니다. "이제 뭐 하면 되나요?" 박시니어 씨가 답했습니다.

"이제 서버에 접속해봐야죠. SSH로 연결하는 방법을 알려드릴게요."

**SSH(Secure Shell)**는 암호화된 네트워크 프로토콜로 원격 서버에 안전하게 접속하는 방법입니다. EC2 인스턴스에 접속하려면 앞서 다운로드한 키 페어 파일을 사용합니다.

Windows에서는 PuTTY나 OpenSSH를, Mac/Linux에서는 터미널의 ssh 명령어를 사용합니다.

다음 코드를 살펴봅시다.

// Node.js에서 SSH 연결을 통해 EC2 명령 실행 예제
const { Client } = require('ssh2');
const fs = require('fs');

// SSH 연결 설정
const conn = new Client();

conn.on('ready', () => {
  console.log('EC2 인스턴스에 연결되었습니다.');

  // 원격 명령 실행: 시스템 정보 조회
  conn.exec('uname -a && uptime && df -h', (err, stream) => {
    if (err) throw err;

    stream.on('close', (code, signal) => {
      console.log('명령 실행 완료');
      conn.end();
    }).on('data', (data) => {
      console.log('출력:', data.toString());
    }).stderr.on('data', (data) => {
      console.error('에러:', data.toString());
    });
  });
}).connect({
  host: '13.125.XXX.XXX', // EC2 퍼블릭 IP
  port: 22,
  username: 'ec2-user', // Amazon Linux는 'ec2-user', Ubuntu는 'ubuntu'
  privateKey: fs.readFileSync('/path/to/my-first-key-pair.pem')
});

// 파일 업로드 예제 (SFTP 사용)
const sftpConn = new Client();

sftpConn.on('ready', () => {
  sftpConn.sftp((err, sftp) => {
    if (err) throw err;

    // 로컬 파일을 EC2로 업로드
    const localFile = './app.js';
    const remoteFile = '/home/ec2-user/app.js';

    sftp.fastPut(localFile, remoteFile, (err) => {
      if (err) {
        console.error('업로드 실패:', err);
      } else {
        console.log('파일 업로드 성공!');
      }
      sftpConn.end();
    });
  });
}).connect({
  host: '13.125.XXX.XXX',
  port: 22,
  username: 'ec2-user',
  privateKey: fs.readFileSync('/path/to/my-first-key-pair.pem')
});

박시니어 씨가 터미널을 열었습니다. "SSH는 서버를 제어하는 가장 기본적인 방법이에요.

마치 다른 컴퓨터에 원격 접속하는 것과 같아요." 먼저 이해해야 할 것이 SSH의 보안 원리입니다. 예전에는 서버에 접속할 때 텔넷(Telnet)이라는 프로토콜을 사용했습니다.

문제는 비밀번호가 평문으로 전송된다는 점이었습니다. 네트워크를 감청하면 비밀번호가 그대로 노출되었습니다.

SSH는 이 문제를 해결하기 위해 만들어졌습니다. 모든 통신이 암호화되고, 비밀번호 대신 키 쌍을 사용합니다.

공개 키와 개인 키 한 쌍으로 이루어지는데, 개인 키는 사용자만 갖고 있고 공개 키는 서버에 등록됩니다. 김개발 씨가 Mac을 사용하고 있어서 박시니어 씨가 터미널 접속 방법을 알려줬습니다.

"먼저 키 파일의 권한을 바꿔야 해요. 보안을 위해 소유자만 읽을 수 있게 설정합니다." 터미널을 열고 다음 명령어를 입력합니다.

bash chmod 400 my-first-key-pair.pem 이 명령어는 키 파일을 읽기 전용으로 만듭니다. SSH는 키 파일 권한이 너무 느슨하면 보안상 위험하다고 판단해서 접속을 거부합니다.

다음으로 SSH 접속 명령어를 입력합니다. bash ssh -i my-first-key-pair.pem ec2-user@13.125.XXX.XXX 여기서 -i는 identity file, 즉 키 파일을 지정하는 옵션입니다.

ec2-user는 사용자 이름인데, Amazon Linux는 기본적으로 ec2-user입니다. Ubuntu AMI를 사용했다면 ubuntu를, Red Hat은 ec2-user를 사용합니다.

처음 접속하면 이런 메시지가 나타납니다. "The authenticity of host can't be established.

Are you sure you want to continue connecting?" 이것은 처음 접속하는 서버라는 의미입니다. "yes"를 입력하면 서버가 신뢰할 수 있는 호스트 목록에 추가됩니다.

잠시 후 프롬프트가 바뀌면서 접속에 성공합니다. [ec2-user@ip-172-31-XX-XX ~]$ 김개발 씨가 신기해하며 말했습니다.

"와, 정말 서버 안에 들어온 거예요?" 박시니어 씨가 웃으며 답했습니다. "맞아요.

이제 이 서버를 마음대로 제어할 수 있어요." 간단한 명령어를 실행해봅니다. bash whoami # 현재 사용자 확인 pwd # 현재 디렉토리 확인 ls -la # 파일 목록 보기 위의 Node.js 코드를 보면 프로그래밍 방식으로도 SSH 연결을 할 수 있습니다.

ssh2 라이브러리를 사용하면 자동화 스크립트를 작성할 수 있습니다. 예를 들어 여러 서버에 동시에 명령을 실행하거나, 파일을 배포하는 작업을 자동화할 수 있습니다.

실무에서는 SSH 접속을 더 편리하게 만드는 방법이 있습니다. 홈 디렉토리의 .ssh 폴더에 config 파일을 만듭니다.

Host my-ec2 HostName 13.125.XXX.XXX User ec2-user IdentityFile ~/.ssh/my-first-key-pair.pem 이렇게 설정하면 다음부터는 간단하게 접속할 수 있습니다. bash ssh my-ec2 IP 주소나 키 파일 경로를 매번 입력할 필요가 없어집니다.

Windows 사용자라면 PuTTY 또는 Windows Terminal을 사용할 수 있습니다. 최신 Windows 10/11은 OpenSSH가 기본 설치되어 있어서 Mac처럼 ssh 명령어를 바로 사용할 수 있습니다.

주의할 점은 SSH 키 관리입니다. 키 파일을 GitHub 같은 공개 저장소에 올리면 절대 안 됩니다.

누구나 여러분의 서버에 접속할 수 있게 됩니다. .gitignore에 반드시 추가하세요.

또한 보안 그룹 설정을 다시 한번 확인하세요. SSH 포트(22번)가 0.0.0.0/0으로 열려있다면, 전 세계에서 접속 시도를 할 수 있습니다.

가능하면 자신의 IP로 제한하거나, VPN을 통해서만 접속하도록 설정하는 것이 안전합니다. 김개발 씨가 여러 명령어를 실행해보며 즐거워했습니다.

박시니어 씨가 말했습니다. "이제 진짜 클라우드 엔지니어가 된 기분이죠?"

실전 팁

💡 - 키 파일 권한을 400으로 설정하는 것을 잊지 마세요 (chmod 400).

  • SSH config 파일을 활용하면 접속이 훨씬 편리해집니다.
  • 키 파일은 절대 공개하지 말고 안전하게 보관하세요.

6. 인스턴스 시작/중지/종료 관리

실습을 마친 김개발 씨가 물었습니다. "선배님, 연습용 서버인데 계속 켜두면 요금이 나오지 않나요?" 박시니어 씨가 고개를 끄덕였습니다.

"좋은 질문이에요. 인스턴스 관리는 비용과 직결되니까 중요해요."

인스턴스 생명주기 관리는 클라우드 비용 최적화의 핵심입니다. 시작(Start), 중지(Stop), 재부팅(Reboot), 종료(Terminate)의 차이를 이해하고 상황에 맞게 사용해야 합니다.

중지는 일시 정지로 나중에 재시작할 수 있지만, 종료는 완전 삭제를 의미합니다.

다음 코드를 살펴봅시다.

// EC2 인스턴스 생명주기 관리 자동화 예제
const { EC2Client, StopInstancesCommand, StartInstancesCommand,
        TerminateInstancesCommand, RebootInstancesCommand,
        DescribeInstancesCommand } = require('@aws-sdk/client-ec2');

const client = new EC2Client({ region: 'ap-northeast-2' });

// 인스턴스 상태 확인
async function checkInstanceState(instanceId) {
  const command = new DescribeInstancesCommand({
    InstanceIds: [instanceId]
  });

  const response = await client.send(command);
  const instance = response.Reservations[0].Instances[0];

  return {
    state: instance.State.Name,
    type: instance.InstanceType,
    publicIp: instance.PublicIpAddress,
    privateIp: instance.PrivateIpAddress
  };
}

// 인스턴스 중지 (Stop) - 데이터 보존, 컴퓨팅 비용 중단
async function stopInstance(instanceId) {
  const command = new StopInstancesCommand({
    InstanceIds: [instanceId]
  });

  await client.send(command);
  console.log(`인스턴스 ${instanceId} 중지 중...`);
  console.log('스토리지 비용은 계속 청구됩니다.');
}

// 인스턴스 시작 (Start) - 중지된 인스턴스 재시작
async function startInstance(instanceId) {
  const command = new StartInstancesCommand({
    InstanceIds: [instanceId]
  });

  await client.send(command);
  console.log(`인스턴스 ${instanceId} 시작 중...`);
  console.log('퍼블릭 IP는 변경될 수 있습니다.');
}

// 인스턴스 재부팅 (Reboot) - OS 재시작, IP 유지
async function rebootInstance(instanceId) {
  const command = new RebootInstancesCommand({
    InstanceIds: [instanceId]
  });

  await client.send(command);
  console.log(`인스턴스 ${instanceId} 재부팅 중...`);
}

// 인스턴스 종료 (Terminate) - 영구 삭제, 복구 불가
async function terminateInstance(instanceId) {
  const command = new TerminateInstancesCommand({
    InstanceIds: [instanceId]
  });

  await client.send(command);
  console.log(`인스턴스 ${instanceId} 종료(삭제) 중...`);
  console.log('이 작업은 되돌릴 수 없습니다!');
}

// 야간 자동 중지 스케줄러 예제
async function nightlyShutdown(instanceIds) {
  console.log('야간 자동 중지 작업 시작...');

  for (const instanceId of instanceIds) {
    const state = await checkInstanceState(instanceId);

    if (state.state === 'running') {
      await stopInstance(instanceId);
      console.log(`${instanceId}: running → stopping`);
    } else {
      console.log(`${instanceId}: 이미 ${state.state} 상태`);
    }
  }
}

// 사용 예시
const myInstanceId = 'i-0123456789abcdef0';

// 인스턴스 중지
// await stopInstance(myInstanceId);

// 30분 후 자동 시작 예제 (실무에서는 Lambda + EventBridge 사용)
// setTimeout(() => startInstance(myInstanceId), 30 * 60 * 1000);

박시니어 씨가 화이트보드에 그림을 그리기 시작했습니다. "인스턴스에는 네 가지 주요 상태가 있어요." 첫째, Running(실행 중) 상태입니다.

서버가 켜져 있고 정상 작동하는 상태입니다. 이때 컴퓨팅 비용이 청구됩니다.

마치 자동차 엔진이 켜져 있어서 연료가 소모되는 것과 같습니다. 둘째, Stopped(중지됨) 상태입니다.

서버를 일시 정지한 상태로, 컴퓨팅 비용은 청구되지 않지만 스토리지 비용은 계속 청구됩니다. 자동차를 주차해둔 상태라고 생각하면 됩니다.

주차 공간 비용은 내야 하지만 연료는 소모되지 않습니다. 셋째, Terminated(종료됨) 상태입니다.

인스턴스를 완전히 삭제한 상태로, 복구할 수 없습니다. 자동차를 폐차한 것과 같습니다.

모든 데이터가 사라지고 비용도 청구되지 않습니다. 넷째, Rebooting(재부팅 중) 상태입니다.

운영체제를 재시작하는 상태로, IP 주소는 유지됩니다. 김개발 씨가 혼란스러워했습니다.

"중지와 종료의 차이가 뭔가요?" 박시니어 씨가 쉽게 설명했습니다. "중지는 노트북을 절전 모드로 만드는 거예요.

나중에 다시 켤 수 있죠. 종료는 노트북을 버리는 거고요." 실제 시나리오를 들어봅시다.

개발용 서버는 보통 업무 시간에만 사용합니다. 밤 10시부터 다음 날 아침 9시까지는 아무도 사용하지 않습니다.

이때 서버를 중지하면 약 11시간의 컴퓨팅 비용을 절약할 수 있습니다. 주말까지 포함하면 한 달에 70퍼센트 이상의 비용을 줄일 수 있습니다.

위의 코드를 보면 이런 작업을 자동화하는 예제가 있습니다. Lambda 함수와 EventBridge를 조합하면 매일 밤 10시에 자동으로 인스턴스를 중지하고, 아침 9시에 자동으로 시작하도록 설정할 수 있습니다.

주의할 점이 있습니다. 인스턴스를 중지했다가 다시 시작하면 퍼블릭 IP가 변경됩니다.

매번 새로운 IP가 할당되는 것입니다. 이것이 문제가 된다면 Elastic IP를 사용해야 합니다.

Elastic IP는 고정 IP 주소입니다. 한 번 할당받으면 인스턴스를 중지하고 시작해도 IP가 유지됩니다.

하지만 중요한 점이 있습니다. Elastic IP는 인스턴스와 연결되어 있지 않으면 비용이 청구됩니다.

마치 전화번호를 예약만 하고 사용하지 않으면 수수료를 내는 것과 같습니다. 재부팅은 언제 사용할까요?

소프트웨어 업데이트 후, 설정 변경 후, 또는 메모리 누수 같은 문제가 생겼을 때 재부팅합니다. 재부팅은 인스턴스 ID도 유지되고 IP 주소도 유지됩니다.

단순히 운영체제만 다시 시작하는 것입니다. 종료는 신중하게 사용해야 합니다.

AWS 콘솔에서 종료를 선택하면 경고 메시지가 나타납니다. "이 작업은 되돌릴 수 없습니다." 실수로 프로덕션 서버를 종료하는 사고를 방지하기 위해 **종료 보호(Termination Protection)**를 활성화할 수 있습니다.

실무 팁을 알려드리겠습니다. 태그를 활용해서 인스턴스를 분류하세요.

예를 들어 "AutoStop: true" 태그를 달아놓으면, 스크립트로 이 태그가 있는 인스턴스만 자동 중지할 수 있습니다. 프로덕션 서버는 태그를 달지 않아서 실수로 중지되는 것을 방지합니다.

또한 CloudWatch 알람을 설정하면 도움이 됩니다. CPU 사용률이 5퍼센트 이하로 1시간 이상 유지되면 알림을 받도록 설정합니다.

사용하지 않는 인스턴스를 빠르게 발견할 수 있습니다. 박시니어 씨가 김개발 씨에게 실습을 시켜봤습니다.

"자, 인스턴스를 중지해보세요." 김개발 씨가 콘솔에서 인스턴스를 선택하고 "인스턴스 상태 → 인스턴스 중지"를 클릭했습니다. 잠시 후 상태가 "stopping"으로 바뀌더니 곧 "stopped"가 되었습니다.

"SSH 접속이 끊어졌어요!" 김개발 씨가 말했습니다. 박시니어 씨가 웃었습니다.

"당연하죠. 서버가 꺼졌으니까요.

이제 다시 시작해보세요." "인스턴스 상태 → 인스턴스 시작"을 클릭하자 다시 "running" 상태가 되었습니다. 하지만 퍼블릭 IP 주소가 바뀌어 있었습니다.

"진짜 바뀌었네요!" 김개발 씨가 신기해했습니다. 박시니어 씨가 설명했습니다.

"이제 이해됐죠? 고정 IP가 필요하면 Elastic IP를 써야 해요." 마지막으로 비용 최적화 원칙을 정리하자면, 사용하지 않는 리소스는 즉시 정리하는 습관이 중요합니다.

테스트가 끝난 인스턴스는 중지하거나 종료하세요. 매달 청구서를 확인하며 예상치 못한 비용이 있는지 체크하세요.

실전 팁

💡 - 개발/테스트 서버는 야간과 주말에 자동 중지해서 비용을 70퍼센트 이상 절약하세요.

  • 중요한 프로덕션 서버는 종료 보호를 활성화하세요.
  • 고정 IP가 필요하면 Elastic IP를 사용하되, 미사용 시 비용이 청구된다는 점을 기억하세요.

이상으로 학습을 마칩니다. 위 내용을 직접 코드로 작성해보면서 익혀보세요!

#AWS#EC2#Cloud#Instance#SSH#AWS,EC2,Compute

댓글 (0)

댓글을 작성하려면 로그인이 필요합니다.

함께 보면 좋은 카드 뉴스

VPC 네트워크의 기초 - CIDR과 서브넷 설계 완벽 가이드

초급 개발자를 위한 VPC와 서브넷 설계 입문서입니다. 도서관 비유로 CIDR 개념을 쉽게 이해하고, 실무에서 자주 사용하는 서브넷 분할 전략을 단계별로 배워봅니다. 점프 투 자바 스타일로 술술 읽히는 네트워크 입문 가이드입니다.

AWS 리소스 정리와 비용 관리 완벽 가이드

AWS 사용 후 리소스를 안전하게 정리하고 예상치 못한 과금을 방지하는 방법을 배웁니다. 프리티어 관리부터 비용 모니터링까지 실무에서 꼭 필요한 내용을 다룹니다.

AWS Certificate Manager로 HTTPS 인증서 발급 완벽 가이드

AWS Certificate Manager를 사용하여 무료로 SSL/TLS 인증서를 발급받고, 로드 밸런서에 적용하여 안전한 HTTPS 웹 서비스를 구축하는 방법을 초급자도 쉽게 따라 할 수 있도록 단계별로 안내합니다.

Route 53으로 도메인 연결 완벽 가이드

AWS Route 53을 사용하여 도메인을 등록하고 실제 서비스에 연결하는 전 과정을 실무 스토리와 함께 쉽게 배워봅니다. DNS의 기본 개념부터 레코드 설정, ELB 연결까지 초급 개발자도 쉽게 따라할 수 있도록 구성했습니다.

AWS RDS 관리형 데이터베이스 완벽 가이드

직접 데이터베이스를 설치하고 관리하는 것이 부담스러운 초급 개발자를 위한 RDS 가이드입니다. 데이터베이스 엔진 선택부터 인스턴스 생성, 보안 설정, 백업까지 실무에 필요한 모든 내용을 다룹니다.