

これは AWS CDK v2 デベロッパーガイドです。旧版の CDK v1 は 2022 年 6 月 1 日にメンテナンスを開始し、2023 年 6 月 1 日にサポートを終了しました。

翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。

# 識別子と AWS CDK
<a name="identifiers"></a>

 AWS Cloud Development Kit (AWS CDK) アプリケーションを構築するときは、さまざまなタイプの識別子と名前を使用します。 AWS CDK を効果的に使用し、エラーを回避するには、識別子のタイプを理解することが重要です。

識別子は、作成された範囲内で一意である必要があります。 AWS CDK アプリケーションでグローバルに一意である必要はありません。

同じスコープ内で同じ値を持つ識別子を作成しようとすると、 AWS CDK は例外をスローします。

## コンストラクト ID
<a name="identifiers-construct-ids"></a>

最も一般的な識別子の `id` は、コンストラクトオブジェクトをインスタンス化するときに 2 番目の引数として渡される識別子です。この識別子は、すべての識別子と同様に、作成先の範囲内でのみ一意である必要があり、コンストラクトオブジェクトをインスタンス化するときの最初の引数です。

**注記**  
スタックの `id` は、[AWS CDK CLI リファレンス](cli.md)で参照するために使用する識別子でもあります。

アプリで `MyBucket` 識別子を持つ 2 つのコンストラクトがある例を見てみましょう。1 つ目は、`Stack1` 識別子を持つスタックのスコープで定義されます。2 番目は、`Stack2` 識別子を持つスタックのスコープで定義されます。これらは異なるスコープで定義されているため、競合を引き起こすことはなく、問題なく同じアプリに共存できます。

**Example**  

```
import { App, Stack, StackProps } from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as s3 from 'aws-cdk-lib/aws-s3';

class MyStack extends Stack {
  constructor(scope: Construct, id: string, props: StackProps = {}) {
    super(scope, id, props);

    new s3.Bucket(this, 'MyBucket');
  }
}

const app = new App();
new MyStack(app, 'Stack1');
new MyStack(app, 'Stack2');
```

```
const { App , Stack } = require('aws-cdk-lib');
const s3 = require('aws-cdk-lib/aws-s3');

class MyStack extends Stack {
  constructor(scope, id, props = {}) {
    super(scope, id, props);

    new s3.Bucket(this, 'MyBucket');
  }
}

const app = new App();
new MyStack(app, 'Stack1');
new MyStack(app, 'Stack2');
```

```
from aws_cdk import App, Construct, Stack, StackProps
from constructs import Construct
from aws_cdk import aws_s3 as s3

class MyStack(Stack):

    def __init__(self, scope: Construct, id: str, **kwargs):

        super().__init__(scope, id, **kwargs)
        s3.Bucket(self, "MyBucket")

app = App()
MyStack(app, 'Stack1')
MyStack(app, 'Stack2')
```

```
// MyStack.java
package com.myorg;

import software.amazon.awscdk.App;
import software.amazon.awscdk.Stack;
import software.amazon.awscdk.StackProps;
import software.constructs.Construct;
import software.amazon.awscdk.services.s3.Bucket;

public class MyStack extends Stack {
    public MyStack(final Construct scope, final String id) {
        this(scope, id, null);
    }

    public MyStack(final Construct scope, final String id, final StackProps props) {
        super(scope, id, props);
        new Bucket(this, "MyBucket");
    }
}

// Main.java
package com.myorg;

import software.amazon.awscdk.App;

public class Main {
    public static void main(String[] args) {
        App app = new App();
        new MyStack(app, "Stack1");
        new MyStack(app, "Stack2");
    }
}
```

```
using Amazon.CDK;
using constructs;
using Amazon.CDK.AWS.S3;

public class MyStack : Stack
{
    public MyStack(Construct scope, string id, IStackProps props) : base(scope, id, props)
    {
        new Bucket(this, "MyBucket");
    }
}

class Program
{
    static void Main(string[] args)
    {
        var app = new App();
        new MyStack(app, "Stack1");
        new MyStack(app, "Stack2");
    }
}
```

## パス
<a name="identifiers-paths"></a>

 AWS CDK アプリケーションのコンストラクトは、 `App` クラスにルートされた階層を形成します。特定のコンストラクト、その親コンストラクト、その祖父母などの ID のコレクションを、*パス*としてコンストラクトツリーのルートに参照します。

 AWS CDK は通常、テンプレート内のパスを文字列として表示します。レベルからの ID は、通常はスタックであるルート `App` インスタンスのすぐ下のノードから始まるスラッシュで区切られます。例えば、前のコード例にある 2 つの Amazon S3 バケットリソースのパスは `Stack1/MyBucket` および `Stack2/MyBucket` です。

次の例で示すように、プログラムですべてのコンストラクトのパスにアクセスできます。これは `myConstruct` (Python デベロッパーは `my_construct` と記述します) のパスを取得します。IDs は作成されるスコープ内で一意である必要があるため、パスは常に AWS CDK アプリケーション内で一意です。

**Example**  

```
const path: string = myConstruct.node.path;
```

```
const path = myConstruct.node.path;
```

```
path = my_construct.node.path
```

```
String path = myConstruct.getNode().getPath();
```

```
string path = myConstruct.Node.Path;
```

## 一意の ID
<a name="identifiers-unique-ids"></a>

 AWS CloudFormation では、テンプレート内のすべての論理 IDs が一意である必要があります。このため、 AWS CDK はアプリケーション内のコンストラクトごとに一意の識別子を生成できる必要があります。リソースには、グローバルに一意のパス (スタックから特定のリソースへの範囲で、すべてのスコープの名前) があります。したがって、 AWS CDK はパスの要素を連結し、8 桁のハッシュを追加することで、必要な一意の識別子を生成します。(ハッシュは、同じ AWS CloudFormation 識別子になる `A/B/C`や などの個別のパスを区別するために必要です。 AWS CloudFormation 識別子は英数字であり`A/BC`、スラッシュやその他の区切り文字を含めることはできません）。 AWS CDK はこの文字列をコンストラクトの*一意の ID* と呼び出します。

一般的に、 AWS CDK アプリは一意の IDs について知る必要はありません。ただし、次の例で示すように、任意のコンストラクトの一意の ID にプログラムでアクセスできます。

**Example**  

```
const uid: string = Names.uniqueId(myConstruct);
```

```
const uid = Names.uniqueId(myConstruct);
```

```
uid = Names.unique_id(my_construct)
```

```
String uid = Names.uniqueId(myConstruct);
```

```
string uid = Names.Uniqueid(myConstruct);
```

*アドレス*は、CDK リソースを一意に区別する別な種類の一意の識別子です。パスの SHA-1 ハッシュから派生し、人間が読み取れません。ただし、定数で比較的に短い長さ (常に 42 個の 16 進数文字) は、「従来」の一意の ID が長すぎる状況で役立ちます。一部のコンストラクトでは、一意の ID の代わりに合成された AWS CloudFormation テンプレートのアドレスを使用する場合があります。繰り返しになりますが、アプリは一般的にコンストラクトのアドレスを知る必要はありませんが、次のようにコンストラクトのアドレスを取得できます。

**Example**  

```
const addr: string = myConstruct.node.addr;
```

```
const addr = myConstruct.node.addr;
```

```
addr = my_construct.node.addr
```

```
String addr = myConstruct.getNode().getAddr();
```

```
string addr = myConstruct.Node.Addr;
```

## 論理 ID
<a name="identifiers-logical-ids"></a>

 AWS CDK がアプリケーションを AWS CloudFormation テンプレートに合成すると、リソースごとに*論理 ID* が生成されます。 AWS CloudFormation は論理 IDs を使用してテンプレート内のリソースを識別し、デプロイ間でリソースを追跡します。論理 IDs の生成方法を理解することで、CDK コードをリファクタリングする際の意図しないリソースの置き換えを回避できます。

### 論理 IDs の生成方法
<a name="identifiers-logical-id-generation"></a>

 AWS CDK は、次のアルゴリズムを使用してコンストラクトパスから論理 IDs を生成します。

1. スタック自体を除き、コンストラクトツリーからパスコンポーネントを連結します。

1. ヒューリスティックを適用して読みやすさを向上させます ([「論理 ID パスコンポーネントのヒューリスティック](#identifiers-logical-id-heuristics)」を参照）。

1. 一意性を確保するために、フルパスの 8 文字のハッシュを追加します。

結果の形式は次のとおりです。

```
<human-readable-portion><8-character-hash>
```

たとえば、VPC プライベートサブネットルートテーブルは論理 ID を生成する場合があります`VPCPrivateSubnet2RouteTable0A19E10E`。

論理 ID の生成には、次のルールが適用されます。
+ 最大長は 255 文字です。人間が読める部分は 240 文字に制限されています。
+ 8 文字のハッシュにより、同じ文字列に連結する `A/B/C`や `A/BC` などのパスが異なる論理 IDs を生成するようになります。
+ スタックの直接の子であるリソース (単一コンポーネントパス) は、名前が 255 文字以下であれば、ハッシュなしで直接名前を使用します。

### 論理 ID パスコンポーネントのヒューリスティック
<a name="identifiers-logical-id-heuristics"></a>

 AWS CDK は、論理 IDs。

 `Default` — 完全に削除  
パスコンポーネントが の場合`Default`、CDK は人間が読み取り可能な部分とハッシュ入力の両方からそのコンポーネントを削除します。つまり、既存のコンストラクトを新しいコンストラクト内にラップし、内部コンストラクトに名前を付けると、元のラップされていないコンストラクトとまったく同じ論理 ID `Default`が生成されます。これは、デプロイされたリソース ID を変更せずにフラットコードを上位レベルのコンストラクトに安全にリファクタリングするための重要なメカニズムです。

 `Resource` — 人間が読み取り可能な部分からのみ非表示  
パスコンポーネントが の場合`Resource`、CDK はそれを人間が読み取り可能な部分から省略しますが、ハッシュ計算に含めます。L1 (CloudFormation) コンストラクトは、規則によってコンストラクト ID `Resource`として を使用します。これにより、一意性を失うことなく論理 IDs短くすることができます。

重複する連続コンポーネント — 重複排除  
上記のパスコンポーネント名が現在のコンポーネント名で終わると、CDK は現在のコンポーネントをスキップします。これにより、論理 IDs。

### リファクタリング時に論理 IDs を保持するには、 `Default`を使用します。
<a name="identifiers-logical-id-refactoring"></a>

フラットスタックを上位レベルのコンストラクトにリファクタリングする場合、プライマリリソースのコンストラクト ID `Default`として を使用して論理 ID を保持できます。これにより、 AWS CloudFormation はデプロイ中にリソースを置き換えることができません。

次の例は、リソースが直接定義されているスタックを示しています。

**Example**  

```
export class MyStack extends cdk.Stack {
  constructor(scope: Construct, id: string) {
    super(scope, id);
    new s3.Bucket(this, 'DataBucket');
    new lambda.Function(this, 'ProcessFunction', { /* ... */ });
  }
}
```

```
class MyStack extends cdk.Stack {
  constructor(scope, id) {
    super(scope, id);
    new s3.Bucket(this, 'DataBucket');
    new lambda.Function(this, 'ProcessFunction', { /* ... */ });
  }
}
```

```
from aws_cdk import (
    Stack,
    aws_s3 as s3,
    aws_lambda as _lambda,
)
from constructs import Construct

class MyStack(Stack):
    def __init__(self, scope: Construct, id: str, **kwargs) -> None:
        super().__init__(scope, id, **kwargs)
        s3.Bucket(self, "DataBucket")
        _lambda.Function(self, "ProcessFunction", # ...
        )
```

```
package com.myorg;

import software.constructs.Construct;
import software.amazon.awscdk.Stack;
import software.amazon.awscdk.StackProps;
import software.amazon.awscdk.services.s3.Bucket;
import software.amazon.awscdk.services.lambda.Function;

public class MyStack extends Stack {
    public MyStack(final Construct scope, final String id) {
        this(scope, id, null);
    }

    public MyStack(final Construct scope, final String id, final StackProps props) {
        super(scope, id, props);
        new Bucket(this, "DataBucket");
        Function.Builder.create(this, "ProcessFunction")
            // ...
            .build();
    }
}
```

```
using Amazon.CDK;
using Constructs;
using Amazon.CDK.AWS.S3;
using Amazon.CDK.AWS.Lambda;

namespace MyApp
{
    public class MyStack : Stack
    {
        public MyStack(Construct scope, string id, StackProps props = null) : base(scope, id, props)
        {
            new Bucket(this, "DataBucket");
            new Function(this, "ProcessFunction", new FunctionProps
            {
                // ...
            });
        }
    }
}
```

```
package main

import (
	"github.com/aws/aws-cdk-go/awscdk/v2"
	"github.com/aws/aws-cdk-go/awscdk/v2/awslambda"
	"github.com/aws/aws-cdk-go/awscdk/v2/awss3"
	"github.com/aws/constructs-go/constructs/v10"
	"github.com/aws/jsii-runtime-go"
)

type MyStackProps struct {
	awscdk.StackProps
}

func NewMyStack(scope constructs.Construct, id string, props *MyStackProps) awscdk.Stack {
	stack := awscdk.NewStack(scope, &id, &props.StackProps)

	awss3.NewBucket(stack, jsii.String("DataBucket"), &awss3.BucketProps{})
	awslambda.NewFunction(stack, jsii.String("ProcessFunction"), &awslambda.FunctionProps{
		// ...
	})

	return stack
}
```

バケットのパスは で`MyStack/DataBucket/Resource`、論理 ID は になります`DataBucket<hash>`。

バケットを上位レベルのコンストラクトに抽出し、内部コンストラクト に名前を付けることで同じ論理 ID を保持できます`Default`。

**Example**  

```
class DataPipeline extends Construct {
  constructor(scope: Construct, id: string) {
    super(scope, id);
    new s3.Bucket(this, 'Default');  // 'Default' is hidden from logical ID
    new lambda.Function(this, 'ProcessFunction', { /* ... */ });
  }
}

export class MyStack extends cdk.Stack {
  constructor(scope: Construct, id: string) {
    super(scope, id);
    new DataPipeline(this, 'DataBucket');
  }
}
```

```
class DataPipeline extends Construct {
  constructor(scope, id) {
    super(scope, id);
    new s3.Bucket(this, 'Default');  // 'Default' is hidden from logical ID
    new lambda.Function(this, 'ProcessFunction', { /* ... */ });
  }
}

class MyStack extends cdk.Stack {
  constructor(scope, id) {
    super(scope, id);
    new DataPipeline(this, 'DataBucket');
  }
}
```

```
from aws_cdk import (
    Stack,
    aws_s3 as s3,
    aws_lambda as _lambda,
)
from constructs import Construct

class DataPipeline(Construct):
    def __init__(self, scope: Construct, id: str) -> None:
        super().__init__(scope, id)
        s3.Bucket(self, "Default")  # 'Default' is hidden from logical ID
        _lambda.Function(self, "ProcessFunction", # ...
        )

class MyStack(Stack):
    def __init__(self, scope: Construct, id: str, **kwargs) -> None:
        super().__init__(scope, id, **kwargs)
        DataPipeline(self, "DataBucket")
```

```
package com.myorg;

import software.constructs.Construct;
import software.amazon.awscdk.Stack;
import software.amazon.awscdk.StackProps;
import software.amazon.awscdk.services.s3.Bucket;
import software.amazon.awscdk.services.lambda.Function;

public class DataPipeline extends Construct {
    public DataPipeline(final Construct scope, final String id) {
        super(scope, id);
        new Bucket(this, "Default");  // 'Default' is hidden from logical ID
        Function.Builder.create(this, "ProcessFunction")
            // ...
            .build();
    }
}

public class MyStack extends Stack {
    public MyStack(final Construct scope, final String id) {
        this(scope, id, null);
    }

    public MyStack(final Construct scope, final String id, final StackProps props) {
        super(scope, id, props);
        new DataPipeline(this, "DataBucket");
    }
}
```

```
using Amazon.CDK;
using Constructs;
using Amazon.CDK.AWS.S3;
using Amazon.CDK.AWS.Lambda;

namespace MyApp
{
    public class DataPipeline : Construct
    {
        public DataPipeline(Construct scope, string id) : base(scope, id)
        {
            new Bucket(this, "Default");  // 'Default' is hidden from logical ID
            new Function(this, "ProcessFunction", new FunctionProps
            {
                // ...
            });
        }
    }

    public class MyStack : Stack
    {
        public MyStack(Construct scope, string id, StackProps props = null) : base(scope, id, props)
        {
            new DataPipeline(this, "DataBucket");
        }
    }
}
```

```
package main

import (
	"github.com/aws/aws-cdk-go/awscdk/v2"
	"github.com/aws/aws-cdk-go/awscdk/v2/awslambda"
	"github.com/aws/aws-cdk-go/awscdk/v2/awss3"
	"github.com/aws/constructs-go/constructs/v10"
	"github.com/aws/jsii-runtime-go"
)

type DataPipeline struct {
	constructs.Construct
}

func NewDataPipeline(scope constructs.Construct, id string) constructs.Construct {
	this := constructs.NewConstruct(scope, &id)

	// 'Default' is hidden from logical ID
	awss3.NewBucket(this, jsii.String("Default"), &awss3.BucketProps{})
	awslambda.NewFunction(this, jsii.String("ProcessFunction"), &awslambda.FunctionProps{
		// ...
	})

	return this
}

type MyStackProps struct {
	awscdk.StackProps
}

func NewMyStack(scope constructs.Construct, id string, props *MyStackProps) awscdk.Stack {
	stack := awscdk.NewStack(scope, &id, &props.StackProps)

	NewDataPipeline(stack, "DataBucket")

	return stack
}
```

バケットのパスは になりました`MyStack/DataBucket/Default/Resource`。`Default` は人間が読み取り可能な部分とハッシュ入力の両方から削除されるため、論理 ID は元の ID `DataBucket<hash>` と同じままになります。

**重要**  
コンストラクトスコープ`Default`ごとに ID を持つ子を 1 つだけ持つことができます。同じレベルで複数のリソースが必要な場合は、わかりやすい IDsを指定します。この`Default`パターンは、1 つのプライマリリソースを持つ単一責任構造に最適です。

### 制約事項と考慮事項
<a name="identifiers-logical-id-considerations"></a>

論理 IDs を使用する場合は、次の点に注意してください。
+ `Default` コンストラクト ID は、スコープごとに 1 つの子のみを割り当てることができます。
+ デプロイ後にコンストラクト ID を変更すると、論理 ID が変更され、 AWS CloudFormation がリソースを置き換えます。デプロイする前に`cdk diff`、 を使用して変更を確認します。
+ 論理 IDs がすでに変更されている場合は、 `cdk refactor` コマンドを使用して古い論理 ID を新しい論理 IDs にマッピングできます。詳細については、「[CDK コードのリファクタリング時にデプロイされたリソースを保持する](refactor.md)」を参照してください。
+ 合成されたテンプレートに論理 IDs がどのように表示されるかの詳細については、[AWS CloudFormation テンプレートのIDs](configure-synth.md#how-synth-default-logical-ids)」を参照してください。

### 論理 ID の安定性
<a name="identifiers-logical-id-stability"></a>

リソースの作成後に論理 ID を変更しないでください。 AWS CloudFormation はリソースを論理 ID で識別します。したがって、リソースの論理 ID を変更すると、 AWS CloudFormation は新しい論理 ID を使用して新しいリソースを作成し、 は既存のリソースを削除します。リソースのタイプによっては、サービスの中断、データ損失、その両方が発生する場合があります。