./modules/vpc/main.tf

resource "aws_vpc" "this" {
  cidr_block           = var.vpc_cidr
  enable_dns_support   = true
  enable_dns_hostnames = true
  tags = {
    Name = var.vpc_name
  }
}

resource "aws_internet_gateway" "this" {
  count = var.create_igw ? 1 : 0
  vpc_id = aws_vpc.this.id
  tags = {
    Name = "${var.vpc_name}-igw"
  }
}

resource "aws_subnet" "this" {
  for_each = var.subnets
  vpc_id            = aws_vpc.this.id
  cidr_block        = each.value.cidr
  availability_zone = each.value.az
  map_public_ip_on_launch = each.value.public
  tags = {
    Name = each.value.name
  }
}

resource "aws_route_table" "this" {
  for_each = var.route_tables
  vpc_id = aws_vpc.this.id
  tags = {
    Name = each.key
  }
}

# Elastic IP 생성
resource "aws_eip" "this" {
  for_each = var.nat_gateways
  vpc      = true
  tags = {
    Name = each.value.name
  }
}

# NAT Gateway 생성
resource "aws_nat_gateway" "this" {
  for_each       = var.nat_gateways
  subnet_id      = aws_subnet.this[each.value.subnet_id].id
  allocation_id  = aws_eip.this[each.key].id
  tags = {
    Name = each.value.name
  }
}

resource "aws_route" "this" {
  for_each = var.routes
  route_table_id         = aws_route_table.this[each.value.rt_name].id
  destination_cidr_block = each.value.cidr

  gateway_id = lookup(each.value, "gateway_id", null) != null ? each.value.gateway_id : null
  nat_gateway_id = lookup(each.value, "nat_gateway_key", null) != null ? aws_nat_gateway.this[each.value.nat_gateway_key].id : null
}

resource "aws_route_table_association" "this" {
  for_each = var.subnet_associations
  subnet_id      = aws_subnet.this[each.value.subnet_key].id
  route_table_id = aws_route_table.this[each.value.route_table_key].id
}

./modules/vpc/variable.tf

variable "vpc_name" {
  description = "Name of the VPC"
  type        = string
}

variable "vpc_cidr" {
  description = "CIDR block for the VPC"
  type        = string
}

variable "create_igw" {
  description = "Whether to create an Internet Gateway"
  type        = bool
  default     = false
}

variable "subnets" {
  description = "Subnet definitions"
  type = map(object({
    name   = string
    cidr   = string
    az     = string
    public = bool
  }))
}

variable "nat_gateways" {
  description = "NAT Gateway definitions"
  type = map(object({
    name      = string
    subnet_id = string
  }))
  default = {}
}

variable "route_tables" {
  description = "Route Table definitions"
  type        = map(string)
}

variable "routes" {
  description = "Route definitions"
  type = map(object({
    rt_name         = string
    cidr            = string
    gateway_id      = optional(string)
    nat_gateway_key = optional(string)
  }))
  default = {}
}

variable "subnet_associations" {
  description = "Associations between subnets and route tables"
  type = map(object({
    subnet_key      = string
    route_table_key = string
  }))
}

./modules/vpc/output.tf

output "vpc_id" {
  value = aws_vpc.this.id
}

output "igw_id" {
  value = aws_internet_gateway.this[0].id
}

output "nat_gateway_ids" {
  value = { for key, nat in aws_nat_gateway.this : key => nat.id }
}

output "subnet_ids" {
  description = "Subnet IDs for all subnets"
  value = {
    for subnet_key, subnet in aws_subnet.this :
    subnet_key => subnet.id
  }
}

main.tf

# VPC Management

module "vpc_db" {
  source     = "./modules/vpc"
  vpc_name   = "ncsc-db-vpc"
  vpc_cidr   = "10.0.0.0/16"
  create_igw = false
  subnets = {
    "ncsc-db-subnet-a" = { name = "ncsc-db-subnet-a", cidr = "10.0.0.0/24", az = "ap-northeast-2a", public = false }
    "ncsc-db-subnet-b" = { name = "ncsc-db-subnet-b", cidr = "10.0.1.0/24", az = "ap-northeast-2b", public = false }
  }
  nat_gateways = {}
  route_tables = {
    "ncsc-db-rt-a" = "ncsc-db-rt-a"
    "ncsc-db-rt-b" = "ncsc-db-rt-b"
  }
  routes = {}
  subnet_associations = {
    "ncsc-db-subnet-a" = { subnet_key = "ncsc-db-subnet-a", route_table_key = "ncsc-db-rt-a" }
    "ncsc-db-subnet-b" = { subnet_key = "ncsc-db-subnet-b", route_table_key = "ncsc-db-rt-b" }
  }
}

module "vpc_app" {
  source     = "./modules/vpc"
  vpc_name   = "ncsc-app-vpc"
  vpc_cidr   = "172.16.0.0/16"
  create_igw = false
  subnets = {
    "ncsc-app-subnet-a" = { name = "ncsc-app-subnet-a", cidr = "172.16.0.0/24", az = "ap-northeast-2a", public = false }
    "ncsc-app-subnet-b" = { name = "ncsc-app-subnet-b", cidr = "172.16.1.0/24", az = "ap-northeast-2b", public = false }
  }
  nat_gateways = {}
  route_tables = {
    "ncsc-app-rt-a" = "ncsc-app-rt-a"
    "ncsc-app-rt-b" = "ncsc-app-rt-b"
  }
  routes = {}
  subnet_associations = {
    "ncsc-app-subnet-a" = { subnet_key = "ncsc-app-subnet-a", route_table_key = "ncsc-app-rt-a" }
    "ncsc-app-subnet-b" = { subnet_key = "ncsc-app-subnet-b", route_table_key = "ncsc-app-rt-b" }
  }
}

module "vpc_man" {
  source     = "./modules/vpc"
  vpc_name   = "ncsc-man-vpc"
  vpc_cidr   = "192.168.0.0/16"
  create_igw = true
  subnets = {
    "ncsc-tgw-subnet-a"    = { name = "ncsc-tgw-subnet-a", cidr = "192.168.0.0/24", az = "ap-northeast-2a", public = false }
    "ncsc-tgw-subnet-b"    = { name = "ncsc-tgw-subnet-b", cidr = "192.168.1.0/24", az = "ap-northeast-2b", public = false }
    "ncsc-public-subnet-a" = { name = "ncsc-public-subnet-a", cidr = "192.168.2.0/24", az = "ap-northeast-2a", public = true }
    "ncsc-public-subnet-b" = { name = "ncsc-public-subnet-b", cidr = "192.168.3.0/24", az = "ap-northeast-2b", public = true }
  }
  nat_gateways = {
    "ncsc-natgw-a" = { name = "ncsc-natgw-a", subnet_id = "ncsc-tgw-subnet-a" }
    "ncsc-natgw-b" = { name = "ncsc-natgw-b", subnet_id = "ncsc-tgw-subnet-b" }
  }
  route_tables = {
    "ncsc-tgw-rt-a"    = "ncsc-tgw-rt-a"
    "ncsc-tgw-rt-b"    = "ncsc-tgw-rt-b"
    "ncsc-public-rt-a" = "ncsc-public-rt-a"
    "ncsc-public-rt-b" = "ncsc-public-rt-b"
  }
  routes = {
    "tgw-a" = { rt_name = "ncsc-tgw-rt-a", cidr = "0.0.0.0/0", nat_gateway_key = "ncsc-natgw-a" }
    "tgw-b" = { rt_name = "ncsc-tgw-rt-b", cidr = "0.0.0.0/0", nat_gateway_key = "ncsc-natgw-b" }
    "public-a" = { rt_name = "ncsc-public-rt-a", cidr = "0.0.0.0/0", gateway_id = module.vpc_man.igw_id }
    "public-b" = { rt_name = "ncsc-public-rt-b", cidr = "0.0.0.0/0", gateway_id = module.vpc_man.igw_id }
  }
  subnet_associations = {
    "ncsc-tgw-subnet-a"    = { subnet_key = "ncsc-tgw-subnet-a", route_table_key = "ncsc-tgw-rt-a" }
    "ncsc-tgw-subnet-b"    = { subnet_key = "ncsc-tgw-subnet-b", route_table_key = "ncsc-tgw-rt-b" }
    "ncsc-public-subnet-a" = { subnet_key = "ncsc-public-subnet-a", route_table_key = "ncsc-public-rt-a" }
    "ncsc-public-subnet-b" = { subnet_key = "ncsc-public-subnet-b", route_table_key = "ncsc-public-rt-b" }
  }
}