네이버 메일 수신 여부(읽었는지) 확인하는 방법
네이버 메일은 기본적으로 수신 여부를 알려줍니다. 물론 G-Mail의 Streak처럼 매우 정밀하게 언제 몇 번 읽었는지 등은 알려주지 않지만, 수신 여부만 알면 될 때 유용하게 사용할 수 있습니다.
바로 메일을 작성한 뒤에 [보내기] 버튼을 눌러서 메일을 보내보겠습니다.
보낸 이후에는 [보낸 메일함] 옆에 있는 [수신확인] 버튼을 눌러 자신이 보낸 메일에 대한 [수신확인]을 할 수 있습니다.
그러면 바로 오른쪽에 [읽지 않음] 혹은 언제 일었는지 나오게 됩니다.
(+ 참고 사항 )
참고로 그냥 [보낸 메일함]에 있는 [읽음] 표시는 자기 자신이 읽었는지에 대한 여부입니다. 우리가 보낸 메일의 상대방이 읽었는지 확인하기 위해서는 [수신확인]에서 확인하셔야 해요!
'기타' 카테고리의 다른 글
Gmail Streak을 이용하여 보낸 메일 수신 여부 확인하기! (내가 보낸 메일을 상대방이 읽었는지) (0) | 2019.05.08 |
---|---|
지금 당장 멀리 있는 곳에 서류, 선물, 물건 등을 보내야 할 때 (0) | 2019.05.06 |
PHP에서 Error Log 남기는 법 (0) | 2019.04.29 |
PHP 서버에서 안드로이드 인 앱 결제(IAP) 여부를 검증하는 API 개발하는 방법 (1) | 2019.04.29 |
the requested PHP extension simplexml is missing from your system. 오류 해결 방법 (0) | 2019.04.16 |
운영체제: 컴퓨터 리소스를 효율적으로 관리할 수 있도록 도와주는 시스템 소프트웨어입니다. 좋은 운영체제란 신뢰성이 높고, 사용이 편하며, 빠르게 처리될 수 있어야 합니다. 운영체제의 대표적인 종류로는 윈도우, 리눅스(Linux), Mac OS 등이 있습니다. 운영체제는 크게 4가지 목차로 구성됩니다.
[ 목차 ]
1) 프로세스 관리: 실행 중인 프로그램들을 효율적으로 관리
- 스케줄링
- 문맥 교환(Context Switch)
- 스레드(Thread)
- 프로세스 동기화
- 상호배제와 임계영역
- 세마포어
2) 메모리 관리: 주기억장치의 쓰임을 효율적으로 관리
3) I/O 관리: 입출력 장치를 효율적으로 관리
4) File 관리: 컴퓨터의 파일을 효율적으로 관리
일반적으로 시험이나 면접에서는 프로세스 관리에 대해서 물어보는 경우가 제일 많습니다.
'운영체제' 카테고리의 다른 글
운영체제가 컴퓨터를 작동 시키는 과정을 알아보자! (0) | 2017.04.23 |
---|---|
다양한 컴퓨터 시스템을 소개합니다! (0) | 2017.04.22 |
컴퓨터 시스템의 발전 양상을 살펴보자! (0) | 2017.04.22 |
운영체제란 무엇일까? (0) | 2017.04.22 |
PHP에서 Error Log 남기는 법
PHP에서 에러 로그(Log)를 남기는 방법은 간단합니다. 다음과 같은 코드를 이용하면 됩니다. 두 번째 파라미터인 3의 의미는 파일의 뒤쪽에 이어서 내용을 작성하겠다는 의미입니다. 그리고 세 번째 파라미터에는 로그 파일의 위치가 들어갑니다.
error_log ('{남기고자 하는 로그 메시지}', 3, "/var/log/apache2/php_error.log");
자세한 내용은 다음의 경로에서 확인할 수 있습니다.
https://www.php.net/manual/en/function.error-log.php
또한 경우에 따라서는 permission denied 오류가 발생하면서 로그를 기록하지 못할 수도 있습니다. 그럴 때는 권한 설정을 진행하면 됩니다. 좋은 방법은 아니지만, 대충 무조건 허용해도 괜찮을 때는 777 권한을 주면 됩니다.
그래서 결과적으로는 다음과 같은 형태로 로그를 남길 수 있습니다.
또한 실시간으로 로그를 테스트 하는 경우 다음과 같이 실시간 출력이 가능합니다.
tail -f {파일 이름}
'기타' 카테고리의 다른 글
지금 당장 멀리 있는 곳에 서류, 선물, 물건 등을 보내야 할 때 (0) | 2019.05.06 |
---|---|
네이버 메일 수신 여부(읽었는지) 확인하는 방법 (1) | 2019.05.05 |
PHP 서버에서 안드로이드 인 앱 결제(IAP) 여부를 검증하는 API 개발하는 방법 (1) | 2019.04.29 |
the requested PHP extension simplexml is missing from your system. 오류 해결 방법 (0) | 2019.04.16 |
PHP Composer에서 Cannot allocate memory 오류 해결 방법 (0) | 2019.04.16 |
PHP 서버에서 안드로이드 인 앱 결제(IAP) 여부를 검증하는 API 개발하는 방법
일반적으로 안드로이드 어플리케이션을 개발할 때에는 인 앱 결제(IAP) 기능을 구현해야 할 때가 많습니다. 다만 이러한 인 앱 결제 기능을 구현할 때 알아 두어야 할 점이 있습니다. 그것은 바로 클라이언트가 제대로 카드 결제를 수행했는지의 여부입니다. 실제로 카드 결제를 하지 않고, 서버로 API만 호출하는 방식의 해킹 기법이 존재하기 때문입니다.
따라서 서버는 클라이언트로부터 상품 ID(Product ID)와 구매 토큰(Purchase Token)을 전달 받도록 개발을 해야 합니다. 그래서 그 구매 토큰이 유효한지 여부를 확인하여, 구매 토큰이 유효할 때만 해당 구매자의 캐시를 증가시키는 등의 작업을 수행해야 합니다. 구매 토큰은 실제로 결제 처리를 했을 때 클라이언트가 발급 받을 수 있으므로, 서버 측에서 이러한 구매 토큰을 이용해 구글 구매 보고서 API에 접근해 해당 사용자의 결제가 사실인지 확인하는 것입니다.
구매 토큰이 유효한지 여부를 확인하는 과정이 없으면, 실제로 카드 결제를 하지 않은 악성 사용자가 의도적으로 API를 호출하여 부당한 이득을 취할 수 있으므로 유의하셔야 합니다.
결과적으로, 서버 API를 개발할 때는 구글 개발자 권한으로 결제 보고서에 접근할 수 있어야 합니다. 이를 위해 결제 보고서를 가져오는 Google API를 이용합니다. 따라서 사전에 개발자 콘솔에서 설정을 해야 할 필요가 있습니다.
PHP에서의 예제 소스코드는 다음과 같습니다. Google API를 위한 SDK가 설치되어 있어야 합니다.
$client = new Google_Client();
$client->setAuthConfig('/home/ubuntu/IAP.json'); // 구글 개발자 인증 설정
$client->addScope('https://www.googleapis.com/auth/androidpublisher');
$service = new Google_Service_AndroidPublisher($client);
$package_name = "{어플리케이션 패키지 이름}";
$product_id = $this->input_check('product_id');
$purchase_token = $this->input_check('purchase_token');
if($product_id == "" || $purchase_token == "") {
// 상품 ID와 구매 토큰은 반드시 전달 받아야 합니다.
exit;
}
try {
$list = $service->inappproducts->listInappproducts($package_name);
$amount = -1;
$purchased_price = -1;
foreach ($list as $key => $value) {
// 상품 ID를 기준으로 검색하여 상품을 얼마에 구매했는지 확인
if($list[$key]['sku'] == $product_id) {
$str = $list[$key]['listings']['en-US']['title'];
$purchased_price = $list[$key]['defaultPrice']['priceMicros'];
$amount = preg_replace("/[^0-9]*/s", "", $str);
break;
}
}
if($amount == null || $purchased_price == null) {
// "구글 개발자 콘솔 오류입니다. 관리자에게 문의하세요."
exit;
}
// 구매 가격은 Micro가 기준
$purchased_price /= 1000000;
// 구글 API 레퍼런스: https://developers.google.com/android-publisher/api-ref/purchases/products
$purchase = $service->purchases_products->get($package_name, $product_id, $purchase_token);
// 해당 주문의 구매 상태와 구매 타입을 확인
$purchase_state = $purchase->getPurchaseState();
$purchase_type = $purchase->getPurchaseType();
$order_id = $purchase->getOrderId();
if($purchase_state == '1') {
// 결제 취소 된 주문 내역입니다.
exit;
}
// 이전에 처리 된 토큰인지 확인
$data['order_no'] = $order_id;
result= $this->model_member->check_buy($data); // 포인트 구매 내역 DB 쿼리를 요청합니다.
if($result != 0) {
$this->output->set_status_header(403); // 이미 처리 된 주문 내역입니다.
exit;
}
// 이전에 처리 된 적 없는 토큰인 경우 결제 완료
if($purchase_type == '0') { // 테스트 결제일 때는 purchase_type 값이 0임.
// 테스트 결제 완료
}
else if($purchase_type == null) { // 진짜 결제일 때는 purchase_type 값이 전달되지 않음.
// 진짜 결제 완료
}
} catch (Exception $e) {
$this->output->set_status_header(505); // 상품 ID 혹은 구매 토큰 값이 바르지 않습니다.
exit;
}
유의할 점은 실제 배포 때와 테스트 때의 구매 타입(Purchase Type)의 값이 다르다는 것입니다. 테스트(Test) 환경에서 결제를 할 때는 purchaseType의 값이 0으로 날아오지만, 실제 배포 환경에서는 purchaseType의 값이 null입니다. 따라서 일반적인 일회성 결제인 경우 purchaseType이 0인지, null인지에 따라서 다르게 처리해주시면 됩니다.
'기타' 카테고리의 다른 글
네이버 메일 수신 여부(읽었는지) 확인하는 방법 (1) | 2019.05.05 |
---|---|
PHP에서 Error Log 남기는 법 (0) | 2019.04.29 |
the requested PHP extension simplexml is missing from your system. 오류 해결 방법 (0) | 2019.04.16 |
PHP Composer에서 Cannot allocate memory 오류 해결 방법 (0) | 2019.04.16 |
재직 증명서(국민연금 가입 증명서) 인터넷 발급(PDF 파일로 저장) 방법 (0) | 2019.04.16 |
AWS API Gateway와 Lambda를 활용해 REST API 구축하기 ①
AWS에서 API Gateway와 Lambda를 활용해 REST API를 구축해보는 시간을 가져보도록 하겠습니다. 초기 설정부터 차근차근 개발하게 되므로 Lambda Function부터 만들어야 합니다. [Create Function] 버튼을 누릅니다.
가장 기본적인 형태인 Node.js 함수로 만들겠습니다. 또한 사용자 관련 API라는 의미에서 다음과 같이 함수 이름도 지어 보았습니다.
실제로 사용자 API를 DB 연동까지 하려면 귀찮은 작업이 될 것입니다. 따라서 다음과 같이 클라이언트의 메소드(Method)의 종류에 따라서 단순히 응답하는 함수를 만들었습니다. GET 방식과 POST 방식에 대해서만 작업했습니다.
exports.handler = (event, context, callback) => {
const operation = event.httpMethod;
switch (operation) {
case 'POST':
callback(null, {
'statusCode': 200
});
break;
case 'GET':
data = {
'id': 1,
'name': '나동빈'
}
callback(null, {
'statusCode': 200,
'headers': {},
'body': JSON.stringify(data)
});
break;
default:
callback(new Error(`Unrecognized operation "${operation}"`));
}
};
다음과 같이 람다 함수를 작성한 뒤에 [Save]를 꼭 해주셔야 적용됩니다.
이제 이러한 람다 함수를 실행할 수 있도록 API Gateway 페이지에서 [Create API]로 API를 만들겠습니다.
우리가 만들 API는 REST API이므로 [REST]를 선택하고, 이름을 설정하여 만들어 주시면 됩니다.
이제 API 프로젝트가 만들어지면, 바로 [Create Resource] 버튼을 눌러서 리소스(Resource)를 만들 수 있습니다.
이후에 다음과 같이 user라는 이름의 리소스를 생성하겠습니다. 일반적으로 REST API에서는 실제 데이터의 종류에 따라서 리소스를 만들게 됩니다. 다시 말해 사용자에 대한 처리를 위해 user라는 리소스를 정의하는 식입니다.
이제 [Create Method]를 눌러서 실제로 해당 user 리소스에 대한 메소드를 설정합니다.
GET 방식의 메소드를 만든 뒤에 Lambda Function을 선택하여 함수 이름을 적습니다. 또한 [Use Lambda Proxy Integration]에 체크합니다.
이제 [Deploy API]를 누르면 실제로 API Gateway가 동작합니다.
일반적으로 API를 개발할 때는 버전별로 API를 관리합니다. API Gateway는 그러한 기능을 지원하고 있습니다. 따라서 저는 다음과 같이 오늘 날짜인 2019-04-24라는 이름으로 API 배포를 진행하겠습니다.
배포 이후에 AWS Lambda 페이지로 이동해 보시면, 실제로 API 게이트웨이가 람다 함수 앞에 붙게 됩니다. 이제 해당 URL로 접속해 보도록 하겠습니다.
저는 다음과 같이 Restlet 확장 프로그램을 이용하여 접속해보았습니다. 그 결과 정상적으로 내용이 출력됩니다.
만약 메소드(Method)를 PUT 방식으로 설정하는 등, API Gateway에서 지정하지 않은 방식을 이용하려고 하면 오류가 발생합니다.
이제 POST 방식의 메소드 또한 추가하겠습니다.
마찬가지로 람다 함수를 적용하고, [Use Lambda Proxy Integration]에 체크합니다.
이후에 배포까지 진행합니다.
POST 메소드 적용 이후에는 다음과 같이 [POST] 방식으로 요청을 보냈더니 정상적으로 응답이 돌아옵니다.
그렇다면 자바 스크립트 등의 웹에서 해당 API를 이용하려면 어떻게 하면 될까요? 간단히 다음과 같은 HTML 소스코드를 작성해서 테스트 해보도록 하겠습니다.
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
</head>
<body>
<input type="button" value="GET" onClick="get()"/>
<script>
const API_URL = 'URL';
function get() {
fetch(API_URL, {
headers: {
'Accept': 'application/json'
}
}).then(res => res.json())
.then(data => console.log(data))
.catch(err => console.error(err));
}
</script>
</body>
</html>
실행 결과 다음과 같이 [GET] 버튼을 누르면 CORS 관련 오류가 발생합니다.
따라서 GET 메소드에서 [Enable CORS]를 눌러서 CORS를 활성화 해주시면 됩니다.
기본 설정 그대로 CORS 설정을 진행하시면 됩니다.
이후에 다시 [Deploy API]를 눌러서 배포하시면 됩니다.
이제 최종적으로 Lambda 함수에서 응답 헤더(Header)에 Access-Control-Allow-Origin을 추가하시면 됩니다.
case 'GET':
data = {
'id': 1,
'name': '나동빈'
}
callback(null, {
'statusCode': 200,
'headers': {'Access-Control-Allow-Origin': '*'},
'body': JSON.stringify(data)
});
break;
이제 다시 버튼을 누르면 매우 정상적으로 동작합니다.
'AWS' 카테고리의 다른 글
AWS API Gateway와 Lambda를 활용해 REST API 구축하기 ③ (2) | 2019.05.28 |
---|---|
AWS API Gateway와 Lambda를 활용해 REST API 구축하기 ② (0) | 2019.05.21 |
AWS Lambda(Node.js)와 AWS DynamoDB 연동 예제 (2) | 2019.04.24 |
AWS 람다(Lambda)로 Python 서버 API 구현하기 ③ Lambda Layers를 이용해 공통 라이브러리 관리하기 (1) | 2019.04.23 |
AWS 문자 메시지(SMS) 발송 로그(Log) 관리하기 (0) | 2019.04.22 |
AWS Lambda(Node.js)와 AWS DynamoDB 연동 예제
이번 시간에는 AWS Lambda(Node.js)와 AWS DynamoDB를 연동하는 예제를 다루어 보도록 하겠습니다. DynamoDB는 NoSQL 데이터베이스로, 종합 관리(Fully Managed)된다는 특징이 있습니다. 또한 데이터는 자동으로 복제되기 때문에 상대적으로 안전합니다. 그리고 배포와 확장이 단순하다는 장점이 있습니다.
DynamoDB는 간단한 모바일 API를 구축하기 위한 목적으로 이용하면 효과적입니다. 간단히 실습을 해봅시다. 바로 AWS Lambda 서비스 화면으로 이동하여 하나의 함수(Function)을 만듭시다.
저는 Node.js로 기본 람다 함수를 만들었습니다.
이후에 [API Gateway]를 하나 선택해서 달아줍니다. 그러면 자동으로 해당 람다 함수에 접근할 수 있는 API URL이 생성되고, 이를 관리할 수 있게 됩니다.
설정은 다음과 같이 [Open with API Key]를 선택해서, 클라이언트가 API Key를 이용해 람다 함수에 접근할 수 있도록 합니다.
[Add] 버튼을 누른 이후에는 [Save]를 해주셔야 합니다. 그러면 다음과 같이 API에 접근할 수 있는 URL이 생성됩니다. 또한 우리는 API Key를 이용해 접근하도록 설정하여, API Key 또한 출력됩니다.
이제 다음과 같이 REST API 테스트 도구를 이용하여 테스트할 수 있습니다. 저는 Restlet을 이용했습니다. API Key를 보낼 때에는 HTTP Header에 x-api-key라는 이름으로 키 값을 보내주어야 합니다.
※ DynamoDB와 연동하기 ※
이제 DynamoDB와 연동하기 위해서 DynamoDB에서 하나의 테이블을 생성해보도록 합시다.
간단히 사용자 정보가 담기는 테이블을 만들어 보겠습니다. 테이블 이름은 User, 기본키로는 id를 넣어줍니다.
이후에 실습을 위해 하나의 아이템(Item)을 넣어주겠습니다. [Create Item] 버튼을 누릅니다.
저는 다음과 같이 하나의 사용자 데이터를 넣어보았습니다.
이제 AWS Lambda 소스코드를 수정합니다. 기본 테스트 양식은 다음과 같습니다. dynamodb-doc이라는 라이브러리를 이용하면 간단히 DynamoDB와 통신할 수 있습니다. 기본적으로 GET 방식으로 사용자가 접근했을 때, User 테이블에 있는 모든 정보를 그대로 JSON 형식으로 출력하도록 만들었습니다.
const doc = require('dynamodb-doc');
const dynamo = new doc.DynamoDB();
exports.handler = (event, context, callback) => {
const operation = event.httpMethod;
const payload = {
TableName: '{테이블 이름}'
}
switch (operation) {
case 'POST':
dynamo.putItem(payload, callback);
break;
case 'PATCH':
dynamo.updateItem(payload, callback);
break;
case 'DELETE':
dynamo.deleteItem(payload, callback);
break;
case 'GET':
dynamo.scan(payload, (err, data) => {
callback(null, {
'statusCode': 200,
'headers': {},
'body': JSON.stringify(data)
});
});
break;
default:
callback(new Error(`Unrecognized operation "${operation}"`));
}
};
[Save] 버튼을 눌러 저장한 뒤에, 한 단계만 더 거치면 테스트할 수 있습니다.
우리가 거칠 단계는 AWS Lambda의 권한입니다. 기본적으로 AWS Lambda에서는 DynamoDB에 접근할 권한이 없습니다. 그렇기 때문에 [Execution role] 탭에서 권한 설정을 확인해야 합니다.
다음과 같이 정책 부분에서 [Edit Policy] 버튼을 눌러서 정책을 수정할 수 있습니다.
다음과 같이 [Add additional permissions] 탭을 눌러서 DynamoDB 접근 권한을 추가할 수 있도록 합니다.
저는 다음과 같이 DynamoDB에 대한 모든 권한을 허용했습니다.
이후에 저장까지 잘 해주시면 됩니다. 이제 아까와 동일한 요청을 다시 하게 되면 다음과 같이 나옵니다.
'AWS' 카테고리의 다른 글
AWS API Gateway와 Lambda를 활용해 REST API 구축하기 ② (0) | 2019.05.21 |
---|---|
AWS API Gateway와 Lambda를 활용해 REST API 구축하기 ① (0) | 2019.04.24 |
AWS 람다(Lambda)로 Python 서버 API 구현하기 ③ Lambda Layers를 이용해 공통 라이브러리 관리하기 (1) | 2019.04.23 |
AWS 문자 메시지(SMS) 발송 로그(Log) 관리하기 (0) | 2019.04.22 |
AWS 서비스 한도 증가 요청하는 방법 (AWS 문자 메시지 한도 늘이기) (0) | 2019.04.22 |
AWS 람다(Lambda)로 Python 서버 API 구현하기 ③ Lambda Layers를 이용해 공통 라이브러리 관리하기
하나의 람다 함수(Lambda Function)에서 특정한 라이브러리를 이용하는 경우, 라이브러리를 포함하는 압축 파일(.ZIP) 통째로 람다 함수로 업로드를 하면 라이브러리를 손쉽게 이용할 수 있습니다. 하지만 라이브러리를 포함하여 업로드하는 경우 3MB를 넘어가기 때문에 AWS Lambda 사이트에서 직접 소스코드를 수정하는 것은 불가능했습니다. 소스코드를 변경해야 할 일이 생기면 소스코드를 수정한 뒤에 다시 압축해서 Lambda에 업로드해야 했습니다.
더군다나 하지만 여러 개의 람다 함수에서, 공통된 라이브러리를 이용하는 경우에는 매 번 라이브러리를 압축해서 올려야 한다는 단점이 있습니다. 여러 개의 람다 함수가 공통적으로 사용하는 라이브러리를 일괄적으로 관리할 수 있다면 더욱 편리하겠죠.
2018년 12월부터는 Lambda Layers 기능이 지원되기 때문에 공통된 라이브러리를 Lambda Layers에 올리고, Lambda Function에서는 이를 단순히 불러와 사용할 수 있게 되었습니다. (2018년 12월 이전에는 얼마나 불편했을지 상상이 안 가네요.) 말 그대로 의존성을 효과적으로 관리할 수 있게 되었습니다.
실습을 위해 하나의 Lambda Function을 생성합니다. 예제 코드는 Python으로 작성하겠습니다. 예제 함수에서는 간단한 크롤링 프로그램을 구현할 것입니다. 크롤링을 위해서는 b4라는 라이브러리가 필요합니다.
일단 API Gateway를 붙여서 API 테스트를 해보겠습니다.
다음과 같이 [Open]으로 보안 설정을 해서 누구든지 API에 접근할 수 있도록 합니다.
이후에 [Save]를 눌러 적용합니다. 그리고 API Gateway의 URL을 확인하여 접속합니다.
접속 결과, Lambda의 기본 코드에 의해서 다음과 같이 출력됩니다.
이제 Lambda Function의 코드를 다음과 같이 바꿉니다. bs4라는 라이브러리를 이용해서 크롤링을 수행합니다.
import json
import urllib.request
from bs4 import BeautifulSoup
def lambda_handler(event, context):
url = "https://www.google.com"
soup = BeautifulSoup(urllib.request.urlopen(url).read(), "html.parser")
a_tags = soup.find_all("a")
result_list = []
for i in a_tags:
result_list.append(i.get_text())
return {
'statusCode': 200,
'body': json.dumps(result_list)
}
이제 코드를 [Save]하여 URL에 접속해 봅시다.
당연히 라이브러리가 없으니 오류가 발생합니다. 따라서 로컬에서 pip3 명령을 이용해 bs4를 설치합니다. -t 옵션을 이용하면 특정한 경로에 bs4 라이브러리를 다운로드 할 수 있습니다.
라이브러리 다운로드가 완료되면 이를 하나의 폴더에 담아주어야 합니다.
python이라는 이름의 폴더를 만들어, 모든 라이브러리 폴더를 python 폴더 안으로 넣습니다. 폴더 이름이 python이어야 AWS Lambda에서 이를 성공적으로 인식할 수 있습니다.
이후에 이 python 폴더를 포함하는 폴더를 압축합니다. 다시 말해, 압축 파일의 상위 폴더가 python이 되어야 합니다. 저는 다음과 같이 bs4.zip라는 이름의 압축 파일로 압축했습니다.
이제 압축된 파일을 확인해 보시면, 상위 폴더 이름이 python인 것을 확인할 수 있습니다.
이제 AWS Lambda 서비스의 [Layers] 탭으로 가서 [Create Layer]로 레이어를 생성합니다.
다음과 같이 레이어 이름을 설정하여 생성합니다.
이제 람다 함수의 Layer로, 방금 생성한 Layer를 넣습니다.
다음과 같이 설정합니다.
이후에 람다 함수의 [Save]를 진행하면, 이제 API에 접속했을 때 성공적으로 크롤링 된 결과가 출력됩니다.
'AWS' 카테고리의 다른 글
AWS API Gateway와 Lambda를 활용해 REST API 구축하기 ① (0) | 2019.04.24 |
---|---|
AWS Lambda(Node.js)와 AWS DynamoDB 연동 예제 (2) | 2019.04.24 |
AWS 문자 메시지(SMS) 발송 로그(Log) 관리하기 (0) | 2019.04.22 |
AWS 서비스 한도 증가 요청하는 방법 (AWS 문자 메시지 한도 늘이기) (0) | 2019.04.22 |
AWS 람다(Lambda)에서 AWS S3 서비스 이용하기 (0) | 2019.04.17 |
AWS 문자 메시지(SMS) 발송 로그(Log) 관리하기
AWS SNS의 문자 메시지(SMS) 전송 기능을 이용하다 보면, 때때로 다양한 문제에 직면할 수 있습니다. 그러한 문제에 적절히 대응하기 위해서는 AWS SMS 기능에 대한 로그(Log) 관리가 필요합니다. 로그 관리는 Text messaging (SMS) 탭에서 [Edit] 버튼을 눌러서 수행할 수 있습니다.
여기에서는 가장 먼저 Amazon SNS가 CloudWatch Logs에 로그를 작성할 SMS 전송 성공 비율을 지정합니다. 예를 들어, 전송 실패에 대한 로그만 작성하려면 이 값을 0으로 설정합니다. 전송 성공의 10%에 대한 로그를 작성하려면 이 값을 10으로 설정합니다. 비율을 지정하지 않으면 Amazon SNS는 모든 전송 성공에 대한 로그를 작성합니다.
저는 100%으로 설정했으므로 모든 문자 메시지(SMS) 전송에 대해서 로그에 기록합니다. 그리고 [Create new service role] 탭을 클릭하고 [Create new roles] 버튼을 눌러 새롭게 규칙을 설정할 수 있습니다.
다음과 같이 SNSSuccessFeedback 규칙 이름 그대로 생성합니다.
이제 다음과 같이 IAM 규칙(Role)이 설정이 되어서 이제 CloudWatch의 로그(Log)가 쌓이게 됩니다.
※ S3 로그 저장 ※
AWS 문자 메시지(SMS) 로그는 S3에 저장할 수도 있습니다. 이를 위해서 AWS S3 서비스에서 [Create Bucket]을 눌러서 하나의 새로운 버킷(Bucket)을 만들 수 있습니다.
버킷의 이름을 설정해 생성합니다.
이후에 [Edit Text Messaging Preferences] 탭에서 해당 AWS S3 버킷을 Report 전송용으로 설정하면 됩니다. 그러면 매일매일의 SMS 사용량 Report가 S3에 전송된다는 특징이 있습니다.
다만 이 경우 AWS SNS가 해당 버킷(Bucket)에 쓰기 권한이 있어야 하기 때문에, 간단히 S3의 [Bucket Policy]를 설정해보도록 하겠습니다. [Policy Generator]를 눌러서 정책을 생성합니다.
먼저 자신의 AWS Bucket의 경로(ARN)에 Put Object 액션(Action)을 부여합니다.
이후에 자신의 AWS Bucket의 경로(ARN)에 GetBucketLocation 액션(Action)을 부여합니다.
그리고 [Generate Policy] 버튼을 눌러서 정책 명령어를 생성할 수 있습니다.
이제 다시 AWS S3의 [Permissions] 탭에서 버킷 정책(Bucket Policy)을 바꿀 수 있도록 설정합니다.
이제 [Bucket Policy] 탭에 정책 내용을 붙여넣기 하여 적용하면 됩니다.
'AWS' 카테고리의 다른 글
AWS Lambda(Node.js)와 AWS DynamoDB 연동 예제 (2) | 2019.04.24 |
---|---|
AWS 람다(Lambda)로 Python 서버 API 구현하기 ③ Lambda Layers를 이용해 공통 라이브러리 관리하기 (1) | 2019.04.23 |
AWS 서비스 한도 증가 요청하는 방법 (AWS 문자 메시지 한도 늘이기) (0) | 2019.04.22 |
AWS 람다(Lambda)에서 AWS S3 서비스 이용하기 (0) | 2019.04.17 |
AWS SNS로 문자 메시지(SMS) 전송하기 (PHP 구현) (1) | 2019.04.16 |
AWS 서비스 한도 증가 요청하는 방법 (AWS 문자 메시지 한도 늘이기)
AWS에서 몇몇 서비스는 의도치 않은 과금을 막기 위해 서비스 한도가 정해져 있습니다. 대표적으로 AWS SNS의 문자 메시지(SMS) 전송 서비스는 기본적으로 한 달에 1달러($) 어치만 사용할 수 있도록 제한되어 있습니다. 그래서 아무 의심 없이 AWS SMS 기능을 구현해 놓았는데, 기본 한도인 1달러를 초과하여 앱 사용자에게 문자 메시지가 가지 않아서 낭패를 보는 경우가 있습니다.
이럴 때는 AWS 지원 센터에 방문해서 특정한 서비스의 한도를 증가하겠다고 요청 문서를 작성하시면 됩니다.
▶ AWS 지원 센터(Support Center): https://console.aws.amazon.com/support/home
AWS 지원 센터에서 [Create Case] 버튼을 눌러서 요청 글을 작성할 수 있습니다.
이후에 [Service Limit Increase] 탭을 누르고, 원하는 서비스를 선택할 수 있습니다. 저는 AWS [SMS Text Messaging] 서비스의 한도를 높이고자 합니다.
이후에 [General Limits]를 선택한 뒤에 한계 값(Limit Value)을 설정할 수 있습니다. 일반적으로 이 값은 늘리고자 하는 수치를 의미합니다. 저는 AWS SMS를 한 달에 400 달러까지 사용할 수 있다고 적은 것입니다.
이후에 [Case Description] 탭에서는 어떻게 서비스를 사용할 것인지, 한도를 증가시키는 이유는 무엇인지 등에 대한 정보를 적으면 됩니다.
일반적으로 다음과 같은 형태로 영어 문장을 작성해서 보내시면 됩니다. 제가 실제로 사용했던 문장 양식입니다.
"We require an SMS limit increase of {금액} USD per month to make sure of the serviceability of our application ({웹 사이트 주소}) The app provides a {제공하는 서비스} service that uses SMS messaging for a one-time password verification. Users are required to submit and verify their mobile numbers upon the sign-up process. Our customers are located in worldwide countries such as Korea, United States, Singapore, India, etc. We’re expecting up to {사용량} SMS to be sent out everyday."
이후에 [Contact Options] 탭에서 회신을 받을 언어 등을 설정해서 [Submit]을 진행하시면 됩니다.
(+ 추가)
위 문장 양식으로 SMS 한도 증가 요청을 보냈더니 AWS 측에서 [사용하고자 하는 API 지역(Region)], [고객에게 보낼 문자 메시지 템플릿(Template)]을 추가 정보로 요청했습니다. 따라서 다음과 같은 두 가지 정보를 추가적으로 적어서 보내시면 좋을 것 같습니다.
1) Which AWS region will the user be calling our API/service from: Tokyo
2) Message templates for this country:
"Welcome to {서비스 이름}, your verification code is ({번호})."
일반적으로 국내에서 AWS SMS 기능을 이용하시는 분은 Tokyo를 설정합니다. 그래서 위와 같이 추가적인 내용도 함께 보내시면 좋을 것 같습니다. 보내지 않으시면 AWS 서포트 센터 측에서 추가적인 정보를 요청하고, 이에 대해 응답하는 과정에서 5일 정도 시간이 소요될 수 있으므로 미리 보내시면 좋습니다. (AWS의 서포트 센터는 그렇게 빠르게 응답을 해주지 않습니다. 따라서, 가능하면 한 번에 끝낼 수 있도록 AWS가 필요해 할 만한 모든 정보를 기입하면 좋아요.)
아무튼 AWS SMS 지출 한도 승인을 완료되었을 때는 다음과 같이 AWS에서 연락이 옵니다. (저는 400달러로 한도를 설정했습니다.)
이후에 다음과 같이 AWS SMS 탭으로 이동하여 한도를 늘여 주시면 됩니다.
또한 설정 이후에 문자 메시지 기능이 즉시 동작하지는 않을 수 있습니다. 저는 한 10분 이상 보내지지 않았습니다. 그 당시에 "No quota left for account"라는 로그 메시지가 출력되었다가, 시간이 지나니까 정상적으로 문자 메시지가 보내지더군요.
'AWS' 카테고리의 다른 글
AWS 람다(Lambda)로 Python 서버 API 구현하기 ③ Lambda Layers를 이용해 공통 라이브러리 관리하기 (1) | 2019.04.23 |
---|---|
AWS 문자 메시지(SMS) 발송 로그(Log) 관리하기 (0) | 2019.04.22 |
AWS 람다(Lambda)에서 AWS S3 서비스 이용하기 (0) | 2019.04.17 |
AWS SNS로 문자 메시지(SMS) 전송하기 (PHP 구현) (1) | 2019.04.16 |
Python boto3을 이용하여 AWS S3과 연동하기 (1) | 2019.04.10 |
왜 C언어의 캐릭터(char) 배열은 1칸 적게 입력을 받아야 할까?
Q. 10칸이 들어갈 수 있는 char 배열을 만든 뒤에, 그 안에 정확히 10개의 문자를 넣었어요. 그런데 오류가 발생했어요. 왜 그런거죠? 캐릭터 배열은 원래 1자 적게 입력을 받아야 하나요?
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
int main(void) {
char a[10];
scanf("%s", &a);
printf("%s", a);
system("pause");
return 0;
}
A. 위 소스코드를 실행하면 실제로, 프로그램이 실행이 되긴 하는 것을 알 수 있습니다. 하지만 메모리를 벗어났기 때문에 런타임 오류가 발생할 수 있습니다.
이러한 결과가 나오는 이유는 우리가 scanf() 함수에 의해서 "0123456789"라는 문자열을 입력하면, 실제로는 문자열 뒤에 널(Null) 값이 붙어서 11자가 입력되는 것입니다. 그렇기 때문에 10자라는 캐릭터 배열의 범위를 벗어나서 오류가 발생하는 것입니다.
사실 char 배열로 10칸을 만들어도 정확히 10칸까지의 데이터를 넣을 수 있습니다. 하지만 이건 개발자가 억지로 10칸의 데이터를 넣는 것에 가깝습니다. 왜냐하면 printf("%s", 변수); 형태는 null을 만날 때까지 출력합니다. 따라서 null 값을 넣지 않게 되면, null 값을 만날 때까지 쓰레기 값이 왕창 출력될 수 있습니다.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
int main(void) {
char a[10] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };
printf("%s", a);
system("pause");
return 0;
}
위 소스코드를 실행해 보시면, 0부터 9까지 가득 채워 정확히 10자 만큼의 char 배열을 초기화했기 때문에 null 값이 배열에 들어가지 못합니다. 그래서 0부터 9까지의 문자 뿐만 아니라 쓰레기 값까지 한꺼번에 출력될 확률이 높습니다.
이러한 결과는 컴퓨터 시스템에 따라서 다를 수 있습니다. 우연히 그 뒤 메모리가 null로 채워져 있을 수 있다면, 정확히 0부터 9까지만 출력이 될 수도 있습니다. 맞습니다. 기본적으로 우리의 컴퓨터 시스템은 문자열을 초기화 하거나, 입력을 받을 때 자동으로 null 값을 뒤쪽에 채워넣게 됩니다.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
int main(void) {
char a[] = "0123456789";
printf("크기: %d\n", sizeof(a));
system("pause");
return 0;
}
위 소스코드를 실행해 보시면 a의 배열의 크기는 실제로 10 바이트가 아닌, 11 바이트인 것을 알 수 있습니다. 다시 말해서 1칸 이상의 여유 공간이 없도록 입력을 받는 경우에는 캐릭터 배열을 초기화할 때는 런타임 에러가 발생할 수 있는 것입니다.
이러한 상황에서는 우리의 컴퓨터 메모리 상에 문제가 발생하여, 오류가 발생할 수 있습니다. 하지만 특정 시스템에서는 그러한 문제가 발생한 상태에서 강제 종료가 되지는 않고 그대로 실행이 될 수 있습니다. 이러한 형태는 위험합니다. 프로그램을 실행하는 공격자가 임의로 악용할 수 있기 때문이죠.
그래서 gets_s()와 같이 메모리 오버플로우 공격을 방어할 수 있는 함수를 이용해야 합니다. 이러한 함수는 메모리 오류를 바로 체크해주기 때문에, 메모리 오버플로우가 발생한 위치에서 오류 메시지를 띄우게 됩니다. 그래서 버퍼 오버플로우 공격 등을 방어할 수 있습니다.