

기계 번역으로 제공되는 번역입니다. 제공된 번역과 원본 영어의 내용이 상충하는 경우에는 영어 버전이 우선합니다.

# Amazon RDS에 대한AWS AppSync JavaScript 해석기 함수 참조
<a name="resolver-reference-rds-js"></a>

 AWS AppSync RDS 함수 및 해석기를 사용하면 개발자가 RDS 데이터 API를 사용하여 Amazon Aurora 클러스터 데이터베이스에 SQL 쿼리를 보내고 이러한 쿼리의 결과를 다시 가져올 수 있습니다. AWS AppSync의 `rds` 모듈에 `sql`태그가 지정된 템플릿을 사용하거나 `rds` 모듈의 `select`, `update`, 및 `remove`헬퍼 함수를 사용하여 데이터 API로 전송되는 SQL 문을 작성할 수 있습니다. `insert`는 RDS Data Service의 [https://docs.aws.amazon.com//rdsdataservice/latest/APIReference/API_ExecuteStatement.html](https://docs.aws.amazon.com//rdsdataservice/latest/APIReference/API_ExecuteStatement.html) 작업을 AWS AppSync 사용하여 데이터베이스에 대해 SQL 문을 실행합니다.

**주제**
+ [SQL 태그가 지정된 템플릿](#sql-tagged-templates)
+ [문 생성](#creating-statements)
+ [데이터 불러오기](#retrieving-data)
+ [유틸리티 함수](#utility-functions)
+ [SQL Select](#utility-functions-select)
+ [SQL Insert](#utility-functions-insert)
+ [SQL Update](#utility-functions-update)
+ [SQL Delete](#utility-functions-delete)
+ [캐스팅](#casting)

## SQL 태그가 지정된 템플릿
<a name="sql-tagged-templates"></a>

AWS AppSync의 `sql` 태그가 지정된 템플릿을 사용하면 템플릿 표현식을 사용하여 런타임에 동적 값을 수신할 수 있는 정적 문을 생성할 수 있습니다.는 표현식 값에서 변수 맵을 AWS AppSync 빌드하여 Amazon Aurora Serverless Data API로 전송되는 [https://docs.aws.amazon.com//rdsdataservice/latest/APIReference/API_SqlParameter.html](https://docs.aws.amazon.com//rdsdataservice/latest/APIReference/API_SqlParameter.html) 쿼리를 구성합니다. 이 방법을 사용하면 런타임에 전달된 동적 값이 원래 문을 수정할 수 없으며, 이로 인해 의도하지 않은 실행이 발생할 수 있습니다. 모든 동적 값은 파라미터로 전달되며 원래 문을 수정할 수 없으며 데이터베이스에서 실행되지 않습니다. 이렇게 하면 쿼리가 SQL 삽입 공격에 덜 취약해집니다.

**참고**  
모든 경우에 SQL 문을 작성할 때는 입력으로 받는 데이터를 적절하게 처리하기 위한 보안 지침을 따라야 합니다.

**참고**  
`sql` 태그가 지정된 템플릿은 변수 값 전달만 지원합니다. 표현식을 사용하여 열 또는 테이블 이름을 동적으로 지정할 수 없습니다. 그러나 유틸리티 함수를 사용하여 다음 작업을 수행할 수도 있습니다.

다음 예시에서는 런타임 중 GraphQL 쿼리에 동적으로 설정된 `col` 인수 값을 기반으로 필터링하는 쿼리를 만듭니다. 해당 값은 태그 표현식을 사용해서만 문에 추가할 수 있습니다.

```
import { sql, createMySQLStatement } from '@aws-appsync/utils/rds';

export function request(ctx) {
  const query = sql`
SELECT * FROM table 
WHERE column = ${ctx.args.col}`
  ;
  return createMySQLStatement(query);
}
```

변수 맵을 통해 모든 동적 값을 전달함으로써 데이터베이스 엔진을 사용하여 값을 안전하게 처리하고 삭제합니다.

## 문 생성
<a name="creating-statements"></a>

함수 및 해석기는 MySQL 및 PostgreSQL 데이터베이스와 상호 작용할 수 있습니다. 문을 작성할 때는 각각 `createMySQLStatement` 및 `createPgStatement`를 사용합니다. 예를 들어, `createMySQLStatement`는 MySQL 쿼리를 생성할 수 있습니다. 이러한 함수는 두 개까지의 문을 허용하므로 요청이 결과를 즉시 검색해야 할 때 유용합니다. MySQL으로 다음을 할 수 있습니다.

```
import { sql, createMySQLStatement } from '@aws-appsync/utils/rds';

export function request(ctx) {
    const { id, text } = ctx.args;
    const s1 = sql`insert into Post(id, text) values(${id}, ${text})`;
    const s2 = sql`select * from Post where id = ${id}`;
    return createMySQLStatement(s1, s2);
}
```

**참고**  
`createPgStatement` 및 `createMySQLStatement`는 `sql` 태그가 지정된 템플릿으로 작성된 문을 이스케이프 처리하거나 인용하지 않습니다.

## 데이터 불러오기
<a name="retrieving-data"></a>

실행된 SQL 문의 결과는 `context.result` 객체의 응답 핸들러에서 확인할 수 있습니다. 결과는 `ExecuteStatement` 작업의 [응답 요소](https://docs.aws.amazon.com//rdsdataservice/latest/APIReference/API_ExecuteStatement.html#API_ExecuteStatement_ResponseElements)가 포함된 JSON 문자열입니다. 파싱 시 결과는 다음 형태를 가집니다.

```
type SQLStatementResults = {
    sqlStatementResults: {
        records: any[];
        columnMetadata: any[];
        numberOfRecordsUpdated: number;
        generatedFields?: any[]
    }[]
}
```

반환된 행을 나타내는 JSON 객체 목록으로 `toJsonObject` 유틸리티를 사용하여 결과를 변환할 수 있습니다. 예제:

```
import { toJsonObject } from '@aws-appsync/utils/rds';

export function response(ctx) {
    const { error, result } = ctx;
    if (error) {
        return util.appendError(
            error.message,
            error.type,
            result
        )
    }
    return toJsonObject(result)[1][0]
}
```

단, `toJsonObject`는 문 결과 배열을 반환합니다. 문 하나를 제공한 경우 배열 길이는 `1`입니다. 문 두 개를 제공한 경우 배열 길이는 `2`입니다. 배열의 각 결과에는 `0` 이상의 행이 포함됩니다. 결과 값이 유효하지 않거나 예상치 못한 경우 `toJsonObject`는 `null`을 반환합니다.

## 유틸리티 함수
<a name="utility-functions"></a>

 AWS AppSync RDS 모듈의 유틸리티 헬퍼를 사용하여 데이터베이스와 상호 작용할 수 있습니다.

### SQL Select
<a name="utility-functions-select"></a>

`select` 유틸리티는 관계형 데이터베이스를 쿼리하기 위한 `SELECT` 문을 생성합니다.

**기본 사용**

기본 형식에서 쿼리하려는 테이블을 지정할 수 있습니다.

```
import { select, createPgStatement } from '@aws-appsync/utils/rds';

export function request(ctx) {

    // Generates statement: 
    // "SELECT * FROM "persons"
    return createPgStatement(select({table: 'persons'}));
}
```

테이블 식별자에 스키마를 지정할 수도 있습니다.

```
import { select, createPgStatement } from '@aws-appsync/utils/rds';

export function request(ctx) {

    // Generates statement:
    // SELECT * FROM "private"."persons"
    return createPgStatement(select({table: 'private.persons'}));
}
```

**열 지정**

`columns` 속성을 사용하여 열을 지정할 수 있습니다. 값으로 설정되지 않은 경우 기본값은 `*`입니다.

```
export function request(ctx) {

    // Generates statement:
    // SELECT "id", "name"
    // FROM "persons"
    return createPgStatement(select({
        table: 'persons',
        columns: ['id', 'name']
    }));
}
```

열 테이블도 지정할 수 있습니다.

```
export function request(ctx) {

    // Generates statement: 
    // SELECT "id", "persons"."name"
    // FROM "persons"
    return createPgStatement(select({
        table: 'persons',
        columns: ['id', 'persons.name']
    }));
}
```

**제한 및 오프셋**

쿼리에 `limit` 및 `offset`을 적용할 수 있습니다.

```
export function request(ctx) {

    // Generates statement: 
    // SELECT "id", "name"
    // FROM "persons"
    // LIMIT :limit
    // OFFSET :offset
    return createPgStatement(select({
        table: 'persons',
        columns: ['id', 'name'],
        limit: 10,
        offset: 40
    }));
}
```

**순서 기준**

`orderBy` 속성을 기준으로 결과를 정렬할 수 있습니다. 열을 지정하는 객체 배열과 선택적 `dir` 속성을 제공하십시오.

```
export function request(ctx) {

    // Generates statement: 
    // SELECT "id", "name" FROM "persons"
    // ORDER BY "name", "id" DESC
    return createPgStatement(select({
        table: 'persons',
        columns: ['id', 'name'],
        orderBy: [{column: 'name'}, {column: 'id', dir: 'DESC'}]
    }));
}
```

**필터**

특수 조건 객체를 사용하여 필터를 구축할 수 있습니다.

```
export function request(ctx) {

    // Generates statement:
    // SELECT "id", "name"
    // FROM "persons"
    // WHERE "name" = :NAME
    return createPgStatement(select({
        table: 'persons',
        columns: ['id', 'name'],
        where: {name: {eq: 'Stephane'}}
    }));
}
```

필터를 결합할 수도 있습니다.

```
export function request(ctx) {

    // Generates statement:
    // SELECT "id", "name"
    // FROM "persons"
    // WHERE "name" = :NAME and "id" > :ID
    return createPgStatement(select({
        table: 'persons',
        columns: ['id', 'name'],
        where: {name: {eq: 'Stephane'}, id: {gt: 10}}
    }));
}
```

`OR` 문을 작성할 수 있습니다.

```
export function request(ctx) {

    // Generates statement:
    // SELECT "id", "name"
    // FROM "persons"
    // WHERE "name" = :NAME OR "id" > :ID
    return createPgStatement(select({
        table: 'persons',
        columns: ['id', 'name'],
        where: { or: [
            { name: { eq: 'Stephane'} },
            { id: { gt: 10 } }
        ]}
    }));
}
```

`not`으로 조건을 무효화할 수도 있습니다.

```
export function request(ctx) {

    // Generates statement:
    // SELECT "id", "name"
    // FROM "persons"
    // WHERE NOT ("name" = :NAME AND "id" > :ID)
    return createPgStatement(select({
        table: 'persons',
        columns: ['id', 'name'],
        where: { not: [
            { name: { eq: 'Stephane'} },
            { id: { gt: 10 } }
        ]}
    }));
}
```

다음 작업을 사용하여 값을 비교할 수도 있습니다.


| 
| 
| 연산자 | 설명 | 가능한 값 유형 | 
| --- |--- |--- |
| eq | Equal | number, string, boolean | 
| ne | Not equal | number, string, boolean | 
| le | Less than or equal | number, string | 
| lt | Less than | number, string | 
| ge | Greater than or equal | number, string | 
| gt | Greater than | number, string | 
| contains | Like | string | 
| notContains | Not like | string | 
| beginsWith | Starts with prefix | string | 
| between | Between two values | number, string | 
| attributeExists | The attribute is not null | number, string, boolean | 
| size | checks the length of the element | string | 

### SQL Insert
<a name="utility-functions-insert"></a>

이 `insert` 유틸리티는 `INSERT` 작업과 함께 데이터베이스에 단일 행 항목을 삽입하는 간단한 방법을 제공합니다.

**단일 항목 삽입**

항목을 삽입하려면 테이블을 지정한 다음 값 객체를 전달하십시오. 객체 키는 테이블 열에 매핑됩니다. 열 이름은 자동으로 이스케이프 처리되고 변수 맵을 사용하여 값이 데이터베이스로 전송됩니다.

```
import { insert, createMySQLStatement } from '@aws-appsync/utils/rds';

export function request(ctx) {
    const { input: values } = ctx.args;
    const insertStatement = insert({ table: 'persons', values });
    
    // Generates statement:
    // INSERT INTO `persons`(`name`)
    // VALUES(:NAME)
    return createMySQLStatement(insertStatement)
}
```

**MySQL 사용 사례**

`select`가 뒤따르는 `insert`를 결합하여 삽입된 행을 검색할 수 있습니다.

```
import { insert, select, createMySQLStatement } from '@aws-appsync/utils/rds';

export function request(ctx) {
    const { input: values } = ctx.args;
    const insertStatement = insert({  table: 'persons', values });
    const selectStatement = select({
        table: 'persons',
        columns: '*',
        where: { id: { eq: values.id } },
        limit: 1,
    });
    
    // Generates statement:
    // INSERT INTO `persons`(`name`)
    // VALUES(:NAME)
    // and
    // SELECT *
    // FROM `persons`
    // WHERE `id` = :ID
    return createMySQLStatement(insertStatement, selectStatement)
}
```

**Postgres 사용 사례**

Postgres를 사용하면 삽입한 행에서 데이터를 가져오는 데 [https://www.postgresql.org/docs/current/dml-returning.html](https://www.postgresql.org/docs/current/dml-returning.html)을 사용할 수 있습니다. `*` 또는 열 이름 배열을 받아들입니다.

```
import { insert, createPgStatement } from '@aws-appsync/utils/rds';

export function request(ctx) {
    const { input: values } = ctx.args;
    const insertStatement = insert({
        table: 'persons',
        values,
        returning: '*'
    });

    // Generates statement:
    // INSERT INTO "persons"("name")
    // VALUES(:NAME)
    // RETURNING *
    return createPgStatement(insertStatement)
}
```

### SQL Update
<a name="utility-functions-update"></a>

`update` 유틸리티를 사용하여 기존 행을 업데이트할 수 있습니다. 조건 객체를 사용하여 조건을 충족하는 모든 행의 지정된 열에 변경 내용을 적용할 수 있습니다. 예를 들어 이러한 변형을 만들 수 있는 스키마가 있다고 가정해 보겠습니다. 해당 `2000` 연도부터 인식(`known_since`)하게 된 경우에만 `Person`의`name`을 `3`의 `id` 값으로 업데이트하려고 합니다.

```
mutation Update {
    updatePerson(
        input: {id: 3, name: "Jon"},
        condition: {known_since: {ge: "2000"}}
    ) {
    id
    name
  }
}
```

업데이트 해석기는 다음과 같이 생겼습니다.

```
import { update, createPgStatement } from '@aws-appsync/utils/rds';

export function request(ctx) {
    const { input: { id, ...values }, condition } = ctx.args;
    const where = {
        ...condition,
        id: { eq: id },
    };
    const updateStatement = update({
        table: 'persons',
        values,
        where,
        returning: ['id', 'name'],
    });

    // Generates statement:
    // UPDATE "persons"
    // SET "name" = :NAME, "birthday" = :BDAY, "country" = :COUNTRY
    // WHERE "id" = :ID
    // RETURNING "id", "name"
    return createPgStatement(updateStatement)
}
```

조건에 검사를 추가하여 `3`와 동등한 프라이머리 키 `id`를 가진 행만 업데이트되도록 할 수 있습니다. 마찬가지로 Postgres `inserts`의 경우 수정된 데이터를 반환하는 데 `returning`을 사용할 수 있습니다.

### SQL Delete
<a name="utility-functions-delete"></a>

`remove` 유틸리티를 사용하여 기존 행을 제거할 수 있습니다. 조건을 충족하는 모든 행에서 조건 객체를 사용할 수 있습니다. 참고로 `delete`는 JavaScript에서 예약된 키워드입니다. 대신 `remove`를 사용해야 합니다.

```
import { remove, createPgStatement } from '@aws-appsync/utils/rds';

export function request(ctx) {
    const { input: { id }, condition } = ctx.args;
    const where = { ...condition, id: { eq: id } };
    const deleteStatement = remove({
        table: 'persons',
        where,
        returning: ['id', 'name'],
    });

    // Generates statement:
    // DELETE "persons"
    // WHERE "id" = :ID
    // RETURNING "id", "name"
    return createPgStatement(updateStatement)
}
```

## 캐스팅
<a name="casting"></a>

올바른 객체 유형을 더 구체적으로 지정하여 문에 사용하려는 경우가 있을 수 있습니다. 제공된 유형 힌트를 사용하여 파라미터 유형을 지정할 수 있습니다.는 데이터 API와 [동일한 유형 힌트](https://docs.aws.amazon.com//rdsdataservice/latest/APIReference/API_SqlParameter.html#rdsdtataservice-Type-SqlParameter-typeHint)를 AWS AppSync 지원합니다. 모듈의 `typeHint` 함수를 사용하여 파라미터를 캐스팅할 AWS AppSync `rds` 수 있습니다.

다음 예시에서는 JSON 객체로 캐스팅된 값으로 배열을 보낼 수 있습니다. `->` 연산자를 사용하여 JSON 배열의 `index` `2`에서 요소를 검색합니다.

```
import { sql, createPgStatement, toJsonObject, typeHint } from '@aws-appsync/utils/rds';

export function request(ctx) {
    const arr = ctx.args.list_of_ids
    const statement = sql`select ${typeHint.JSON(arr)}->2 as value`
    return createPgStatement(statement)
}

export function response(ctx) {
    return toJsonObject(ctx.result)[0][0].value
}
```

캐스팅은 `DATE`, `TIME` 및 `TIMESTAMP` 등을 처리하고 비교할 때도 유용합니다.

```
import { select, createPgStatement, typeHint } from '@aws-appsync/utils/rds';

export function request(ctx) {
    const when = ctx.args.when
    const statement = select({
        table: 'persons',
        where: { createdAt : { gt: typeHint.DATETIME(when) } }
    })
    return createPgStatement(statement)
}
```

다음에서는 현재 날짜와 시간을 보낼 수 있는 방법을 보여줍니다.

```
import { sql, createPgStatement, typeHint } from '@aws-appsync/utils/rds';

export function request(ctx) {
    const now = util.time.nowFormatted('YYYY-MM-dd HH:mm:ss')
    return createPgStatement(sql`select ${typeHint.TIMESTAMP(now)}`)
}
```

**사용 가능한 유형 힌트**
+ `typeHint.DATE` – 해당 파라미터는 `DATE` 유형의 객체로 데이터베이스에 전송됩니다. 승인된 형식은 `YYYY-MM-DD`입니다.
+ `typeHint.DECIMAL` – 해당 파라미터는 `DECIMAL` 유형의 객체로 데이터베이스에 전송됩니다.
+ `typeHint.JSON` – 해당 파라미터는 `JSON` 유형의 객체로 데이터베이스에 전송됩니다.
+ `typeHint.TIME` – 해당 문자열 파라미터 값은 `TIME` 유형의 객체로 데이터베이스에 전송됩니다. 승인된 형식은 `HH:MM:SS[.FFF]`입니다.
+ `typeHint.TIMESTAMP` – 해당 문자열 파라미터 값은 `TIMESTAMP` 유형의 객체로 데이터베이스에 전송됩니다. 승인된 형식은 `YYYY-MM-DD HH:MM:SS[.FFF]`입니다.
+ `typeHint.UUID` – 해당 문자열 파라미터 값은 `UUID` 유형의 객체로 데이터베이스에 전송됩니다.