본문 바로가기
서버/AWS

[AWS]18. Lambda 프록시 통합과 비프록시 통합의 간단한 차이점

by jamong1014 2024. 3. 29.
반응형

프로젝트를 진행하던 중 PHP 클라이언트에서 API Gateway URL(POST)로 데이터를 전송해야 하는 작업을 하고 있었는데 계속 오류가 반환되어 몇 시간 동안 헤매었었다.

 

오류라고 하기도 좀 그런 게 코드 자체는 정상적으로 돌아가지만 DynamoDB에 데이터가 저장되면 값이 None, null 형식으로 저장되는 것이다.

 

그래서 항상 그렇듯이 무조건 데이터 형 변환 또는 인코딩 등에 대한 문제로 파악이 되어 여러 뻘짓을 몇 시간 동안 했었다.

  response = table.put_item(
           Item={
                'idx': body['idx'],  ------------------> str( body['idx'] ),
                'score': body['score']
            }
        )

저런 식으로 문자열로 바꿔보기도 하고 뭐 이것저것 다 해보았지만 결과는 똑같았다.

 

GPT의 도움을 빌려 새로운 코드를 몇 번이나 생성했지만 조금의 방식만 다를 뿐 결국 같은 동작을 하는 코드이다.

import json
import boto3

dynamodb = boto3.resource('dynamodb')

def lambda_handler(event, context):
    try:
        # 'body' 필드의 존재 여부 확인 및 JSON으로 파싱
        if 'body' in event:
            body = json.loads(event['body'])
        else:
            # 'body' 필드가 없는 경우, 에러 메시지 반환
            return {
                'statusCode': 400,
                'body': json.dumps('No body in the event')
            }

        table = dynamodb.Table('study_test')
        
        # DynamoDB에 데이터 삽입
        response = table.put_item(
           Item={
                'idx': body['idx'],

                'score': body['score']
            }
        )
        
        # 성공 응답 반환
        return {
            'statusCode': 200,
            'body': json.dumps('Data inserted successfully!')
        }
    except Exception as e:
        # 예외 발생 시, 에러 메시지 반환
        return {
            'statusCode': 500,
            'body': json.dumps(str(e))
        }

이 코드 또한 많은 시도로 생성한 코드인데 어느 정도 문제점을 파악하기 시작한 시점이다.

 

 # 'body' 필드의 존재 여부 확인 및 JSON으로 파싱
        if 'body' in event:
            body = json.loads(event['body'])
        else:
            # 'body' 필드가 없는 경우, 에러 메시지 반환
            return {
                'statusCode': 400,
                'body': json.dumps('No body in the event')
            }

 

여기서 Body라는 필드가 없다면 에러 반환을 하도록 짜여져 있다.

그럼 대체 event의 body 필드는 무엇인가?

 

람다 함수에 대한 AWS 문서를 보면 알겠지만 API Gateway가 Lambda 프록시 통합으로 보내는 이벤트의 구조에서 나오는 필드 중 하나이다.

 

API Gateway는 HTTP 요청을 받아 그 내용을 Lambda 함수로 전달하는데 이때 전달되는 event 객체 내에서 body 필드는 HTTP 요청의 본문(body) 부분을 담고 있는 것이다.

 

즉 Lambda에서는 event 객체에서 직접 접근하여 처리할 수 있다는 소리인데, HTTP에 대한 요청값을 아무런 작업도 하지 않고 그대로 Lambda로 보내는 것이다.

이러한 기능을 하는 통합 프록시를 활성화를 해야만 위의 body 필드가 사용된 코드가 작동이 되는 것이다.

 

통합 프록시 기능을 활성화하지 않고 "body라는 필드에 데이터가 들어가있으니 사용하면 되겠지?.."

라는 생각으로 계속 시도했으니 값이 정상적으로 들어가지 않았던 것이다.

 

그럼 프록시 통합 기능을 비활성화한 상태는 무엇이나?

비프록시 통합은 말그대로 프록시 통합 기능을 비활성화한 상태인데 이 상태에서 프록시 통합과 비슷한 형태로 구현할려면은 Api Gateway에서 매핑 템플릿이라는걸 통해 요청과 응답 데이터를 변환하여 처리해야 한다.

 

매핑 템플릿은 백엔드에서 처리하기 쉬운 형태로 응답 데이터의 구조를 변환하는 설정이라고 보면 된다.

통합 프록시와는 반대로 Lambda 함수에서 처리할 수 있는 형태로 변환을 하는 것이다.

 

예를 들어 idx, score라는 json body(본문)에서 추출해서

{
  "idx": "$input.json('$.idx')",
  "score": "$input.json('$.score')"
}

이런 구조화된 형태를 Lambda 함수로 보내는 것이다.

 

하지만 무조건 매핑 템플릿을 사용해야하는건 아니다.

밑에 코드처럼 event 객체 내에서 키 값을 통해 데이터에 접근하는 경우 event.get('') 형식으로 간단히 불러올 수 있다.

import json
import boto3

dynamodb = boto3.resource('dynamodb')

def lambda_handler(event, context):
    try:
      

        table = dynamodb.Table('study_test')
        
        # DynamoDB에 데이터 삽입
        response = table.put_item(
           Item={
                'idx': event.get('idx'),

                'score': event.get('score')
            }
        )
        
        # 성공 응답 반환
        return {
            'statusCode': 200,
            'body': json.dumps('Data inserted successfully!')
        }
    except Exception as e:
        # 예외 발생 시, 에러 메시지 반환
        return {
            'statusCode': 500,
            'body': json.dumps(str(e))
        }

body에 직접 접근할 필요가 없는 구조이다.

 


PHP CURL(Method POST)

<?php
// API Gateway URL
$url = 'endpoint url';

// 전송할 데이터
$data = array('idx' => 'qwe542', 'score' => 'qwe');
$data_json = json_encode($data);

// cURL을 사용한 POST 요청
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type:application/json'));
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data_json);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

$result = curl_exec($ch);
curl_close($ch);

echo $result;
?>
반응형

댓글