Node.js Express 설치방법


1. node.js 설치


https://nodejs.org/ko/ 접속하여 node.js 설치한다.


2. Visual studio code 나 atom, subprimetext를 이용하여 프로젝트를 생성한다.


(visual studio code)


3. Terminal 에서 npm init 명령어를 입력하여 package.json 파일을 만든다.


npm init


4. Terminal 에서 npm install express --save 명령어를 입력하여 node_modules를 설치한다.

npm install express --save

5. 설치후 server.js 파일을 생성하고 아래와 같이 입력한다.


server.js

var express = require('express');
var app = express();

app.get('/', function (req, res) {
  res.send('Hello World!');
});

app.listen(3000, function () {
  console.log('Example app listening on port 3000!');
});


6. Terminal 에 node server.js 를 입력한다.


node server.js


7. localhost:3000 에 접속하여 Hello World!를 확인한다.



참고 : https://expressjs.com/ko/


Spring boot 에서  Invisible reCAPTCHA 설정하는 방법이다.



reCAPTHA 는 쉽게 말해 봇이 접근을 시도하는 것으로부터 보호하여 스팸글 등록 및 자동 글 작성 자동 회원가입을 막는 것이다.


현재는 v3까지 나왔으며 여러버전이 있는 데, Invisible reCAPTCHA는 말그대로 보이지 않는다. 버튼 체크나, 그림 맞추기 등을 하지 않아도 됨.

원리는 구글측에서 공개하지는 않았지만 구글측에서 사용자의 패턴을 분석해서 방지한다는 정도로 알고있다.



1.  https://www.google.com/recaptcha/intro/v3.html 사이트에 접속한다.


우측 상단의 My reCAPTCHA에 접속한다.



2.  접속한 뒤 새로 만든다.


Label 에는 제목을 입력한다. 이 제목은 말그대로 그냥 제목이다 파일 이름 짓듯이, 프로젝트 생성하듯이 지으면 된다.

그리고 아래와 같이 기입한 후 생성한다. Send alerts to owner는 체크해도 되고 안해도된다. 그리고 만들고나서도 수정 가능하니 신경을 크게 안써도 된다.



3.  생성된 것을 확인

아래와 같이 Site key와 Secret key를 받게 된다.

Step1에는 사용방법이 간단하게 나와 있으며 

Step2에는 Invisible reCAPTCHA API에 사용에 필요한 요청과 응답이 나와 있다.


4.   https://developers.google.com/recaptcha/docs/invisible 옆의 주소에 들어간다.

구글에서 아래와 같이 기본적인 예제를 올려 놓았다. 

이것을 복사를 한다.



5. 복사를 했으면 Spring boot의 static 폴더 아래에 아래와 같이 만든다

굳이 여기가 아니더라도 프론트엔드를 따로 사용하시는 분들이라면 그 쪽에 만들어서 사용하면 된다.


data-siteKey는 3번에서 받은 Site-key를 입력한다. 그리고 action에는 reCAPTCHA에 사용할 API주소를 입력한다. 


6. action에 사용할  reCAPTCHA를 사용할 Controller를 만든다.

하지만 그 전에 reCAPTCHAP에 응답받을 DTO를 생성한다. 이 작업은 굳이 안해도 되고 String으로 바로 받아도 되지만

깔끔함을 위해 작성했다.

구글 API에 아래와 같이 나와있다. 

위를 바탕으로 DTO를 작성한다.

public class reCAPTCHA_DTO {
	private boolean success;
	private Integer number;
	private String action;
	private String challenge_ts;
	private String hostname;
	private String error_codes;
	
	
	public reCAPTCHA_DTO() {
		super();
	}


	public reCAPTCHA_DTO(boolean success, Integer number, String action, String challenge_ts, String hostname,
			String error_codes) {
		super();
		this.success = success;
		this.number = number;
		this.action = action;
		this.challenge_ts = challenge_ts;
		this.hostname = hostname;
		this.error_codes = error_codes;
	}


	public boolean isSuccess() {
		return success;
	}


	public void setSuccess(boolean success) {
		this.success = success;
	}


	public Integer getNumber() {
		return number;
	}


	public void setNumber(Integer number) {
		this.number = number;
	}


	public String getAction() {
		return action;
	}


	public void setAction(String action) {
		this.action = action;
	}


	public String getChallenge_ts() {
		return challenge_ts;
	}


	public void setChallenge_ts(String challenge_ts) {
		this.challenge_ts = challenge_ts;
	}


	public String getHostname() {
		return hostname;
	}


	public void setHostname(String hostname) {
		this.hostname = hostname;
	}


	public String getError_codes() {
		return error_codes;
	}


	public void setError_codes(String error_codes) {
		this.error_codes = error_codes;
	}
}

7. 이제 controller를 작성한다.


params 의 seceret에서는 3번의 seceret_key를 적는다.

3번에의 요청에서 봤듯이 ip가 필요하기 때문에 ip를 받아온다. (ip받아오는 방법은 서버마다 다르기 때문에 굳이 이렇게 안해도 됨.)

g-recaptha-response역시 3번에 나와 있듯이 구글측에서 주는 것이기 때문에 RequsetParam으로 받아 그대로 사용하면 된다.

그리고 아래와 같이 작성해서 post를 날리면 된다.


@PostMapping() public reCAPTCHA_DTO reCAPTCHA_TEST(@RequestParam(name="g-recaptcha-response") String recaptchaResponse , HttpServletRequest request) { String ip = request.getRemoteAddr(); String url = "https://www.google.com/recaptcha/api/siteverify"; String params="?secret=6LcwQYIUAAA******************&response="+recaptchaResponse; RestTemplate restTemplate = new RestTemplate(); reCAPTCHA_DTO re = restTemplate.exchange(url+params, HttpMethod.POST, null, reCAPTCHA_DTO.class).getBody(); if(re.isSuccess()) { System.out.println("성공"); } else { System.out.println("실패"); } return re; }

8. 결과


아래 사진과 같이 맨 오른쪽 하단에 reCAPTCHA 표시가 나타나며 submit을 누르면 결과가나온다.

결과



Invisible reCAPTCHA말고도 다른 reCAPTCHA사용하는 방법 역시 위와 크게 다르지 않기 때문에 아래의 레퍼런스에서 확인하여 때에 맞게 사용하면 된다.



참고 -  https://developers.google.com/recaptcha/intro


먼저 이 글을 보기 전에 알고 있으면 더 좋은 글입니다.


1번. MySQL JSON DATA TYPE

2018/11/30 - [Develop/MySQL] - [MySQL] MySQL JSON - MySQL 5.7 JSON Functions



2번. MySQL에서의 '일반' 값을 JSON형식으로 가져오기

2018/10/28 - [Develop/Spring Boot] - Spring boot JPA EntityManager를 이용한 Map형식으로 mapping하기

2018/10/24 - [Develop/Spring Boot] - Spring boot jpa map, hashmap, JSON형식


3번. JSON PARSING

2018/11/13 - [Develop/Spring Boot] - Spring Boot Json, hashmap to json , JsonObject 만들기- JSON 마지막

2018/11/12 - [Develop/Spring Boot] - Spring Boot Deserialization Json, Deserialization JsonString to JsonObject - Json 4편

2018/11/09 - [Develop/Spring Boot] - Spring Boot Json, Jackson을 이용한 JsonParsing - Json 3편

2018/11/07 - [Develop/Spring Boot] - Spring Boot Json, Gson을 이용한 JsonObject to String, String to JsonObject- JSON 2편

2018/11/06 - [Develop/Spring Boot] - Spring Boot Json, JsonObject로 만들기 - JSON 1편



나도 SPRING BOOT 에서 어떻게 가져오는지 많이 검색해봤으나. 자료가 거의 없어서 열심히 삽질했던 것 같다.

수 많은 삽질 끝에 알아내서 필요한 곳에 사용중이다.


이번 글은 MySQL에서 SELECT시 일반 DATA 형식이 아닌 JSON DATA TYPE을 SPRING BOOT 에 SELECT하는 내용이다.

우선 일반 DATA형식은 그냥 말그대로 SELECT id, name FROM test 해서 가져오는 내용들이고

JSON DATA TYPE 형식은 위의 1번 링크에서 확인할 수 있다.



1. 우선 이번에 사용할 예제 테이블 및 데이터이다. 1번링크에서 확인 가능하다.



2. 먼저 JSON DATA TYPE을 불러올 코드를 작성한다.


아래의 코드를 보면 CONCAT_WS('\\\\',  부분이 있다.


사실 JSON DATA TYPE을 가져올 때 JSON_OBJECT를 사용하면 가져올 수 있으나. 사용하는 이유는


SPRING BOOT에서 CONCAT_WS('\\\\',  를 사용하지 않으면 MySQL에서 값을 불러올때 쌍따옴표를 지워버린다. 


그래서 만약 CONCAT_WS를 사용하지않고 JSON_OBJECT만을 이용하여 SELECT하면


ex) {"ID": 1, "NAME": "TEST", "PASSWORD": "1234", "PHONE_NUM": "010-1111-1111"} 이렇게 불러와야할 값이

     {"    이렇게 나오고 뒤의 내용은 다 짤려버린다.


그래서 CONCAT_WS 함수를 이용하여 쌍따옴표가 안짤리고 SELECT하기 위해 앞에 역슬래쉬를 붙인다. 


4개 붙이는 이유는 두개 붙이니까 SPRING BOOT단에서 짤려버리더라...... 그래서 4개 붙인다.


그리고 CONCAT_WS를 사용하면 값을 Byte로 불러온다.  그래서 String 형식이나 기타 외의 데이터로는 불러오지 못하므로


항상 Object 데이터 형식을 사용해서 불러와야 한다. 그 후 Object를 Byte로 변환 그리고 Byte를  String으로 변환하는 방법 등을 사용 해야 한다.


아래의 코드에서도 우선 List로 결과를 불러오고 Object를 통해 Byte로 변환 그리고 Byte를 다시 String으로 변환한다.


@GetMapping("/test")
	public void test() {
		Query query = entityManager.createNativeQuery("SELECT " + "concat_ws('\\\\', "
				+ "json_object('id', t.id, 'password', t.password, 'name', t.name, 'phone_num', t.phone_num)) "
				+ "as TEST " + "FROM " + "test t");

		List r = query.getResultList();
		for (Object obj : r) {
			byte[] b = (byte[]) obj;
			String value = new String(b, StandardCharsets.UTF_8);
			System.out.println(value);
		}
}


위 코드를 실행하면 아래와 같은 JSON 타입의 내용을 Spring Boot에서 불러올 수 있다.




3.  이 Json String을 JsonObject로 만들어보자 


3번 링크의 Gson이나 Jackson, JsonObject 등등 을 이용하여 만들 수 있다.


Jackson을 이용하여 한번 만들어 보겠다.


먼저 TestDTO 클래스를 하나 만든다 

3번링크의 Json 1편의 DTO에서 password와 phone_num 변수를 추가한다.


만든 후 현재 데이터를 2개가 불러오기 때문에 객체 배열로 생성하였다.

그 후 각 클래스 배열마다 Jackson의 objectmapper를 사용하여 Json String을 Json Object로 변환시켜주었다.


Query query = entityManager.createNativeQuery("SELECT " + "concat_ws('\\\\', "
				+ "json_object('id', t.id, 'password', t.password, 'name', t.name, 'phone_num', t.phone_num)) "
				+ "as TEST " + "FROM " + "test t");


		List r = query.getResultList();
		
		ObjectMapper objectMapper = new ObjectMapper();
		TestDTO t[] = new TestDTO[r.size()];
		int i=0;
		
		for (Object obj : r) {
			byte[] b = (byte[]) obj;
			String value = new String(b, StandardCharsets.UTF_8);
			try {
				
				t[i]= objectMapper.readValue(value, TestDTO.class);
				i++;
			}
			catch (IOException e) {
				e.printStackTrace();
			}
		}
		for(TestDTO test : t) {
			System.out.println(test.getId());
			System.out.println(test.getPassword());
			System.out.println(test.getName());
			System.out.println(test.getPhone_num());
			System.out.println();
		}

아래와 같이 결과가 나온다


이것을 많은 형식을 이용하여 불러 올 수있다 2번링크를 사용하여 애초에  Map으로 불러와서 mapping시키거나 할 수 있다.


Map으로 불러와서 mapping할 경우 문제점은 정규식을 통해 파싱해줘야 하는 단점이있다.


왜냐하면 Json값이 { "id" : 1 } 이렇다면 Map으로 불러올경우 "{ "id" : 1 }" 이렇게 중괄호에 쌍따옴표가 붙어버린다.


그래서 정규식을 통해 중괄호의 쌍따옴표만 지워야 하는 단점이 있다. 하지만 나는 이러한 단점에도 불구하고도 


JSON_TYPE과 함께 일반 데이터까지 가지의 값을 가져 와야하기 때문에 자주 사용한다.


MySQL 5.7.8 VER 부터 JSON TYPE을 지원해준다. 

그래서 MySQL에서 JSON TYPE을 위한 많은 함수를 제공해준다.


MySQL에서는  JSON Functions의 레퍼런스를 상세히 제공해준다.


MySQL 5.7 : https://dev.mysql.com/doc/refman/5.7/en/json-functions.html
MySQL 8 : https://dev.mysql.com/doc/refman/8.0/en/json.html

아주 기본적인 예만 한번 해본다.

1.TEST라는 이름을 가진 테이블안에 아래와 같은 2개의 데이터가 들어가 있다.


2.  MySQL 레퍼런스에서 제공해주는 JSON_OBJECT라는 Function을 사용하면

아래와 같은 결과를 얻을 수 있다.



{
    "ID":  1,
     "NAME":  "TEST",
     "PASSWORD":  "1234",
     "PHONE_NUM":  "010-1111-1111"
}{
    "ID":  2,
     "NAME":  "HI",
     "PASSWORD":  "5555",
     "PHONE_NUM":  "010-2222-2222"
}



파이썬 말고 Spring boot(Java)에서 슬랙 웹훅을 사용해 볼 것이다.



- 파이썬으로 Slack 통신하기

1. 2018/11/03 - [Develop/Python] - Python Slack WebHook (파이썬 슬랙 웹훅) 만들기

2. 2018/11/03 - [Develop/Python] - Python Slack Bot (파이썬 슬랙 봇) - slackclient

3. 2018/11/03 - [Develop/Python] - Python Slack Bot (파이썬 슬랙 봇) - slacker

4. 2018/11/08 - [Develop/Python] - Python Slack Lunch Bot - 점심 알리미 봇

5. 2019/05/03 - [Develop/Node.js] - [Node.js] Node.js Slack WebHooks (슬랙 웹훅)



1. 먼저 아래의 경로에 들어가서 슬랙 웹훅 추가하는 법을 보고 온다.

2018/11/03 - [Develop/Python] - Python Slack WebHook (파이썬 슬랙 웹훅) 만들기


2. 아래의 dependency를 추가한다.



  net.gpedro.integrations.slack
  slack-webhook
  1.4.0

3. 아래와 같이 연습해본다.


@GetMapping("/test")
	public void webHook() {
		
		SlackApi api = new SlackApi("https://hooks.slack.com/services/");    //웹훅URL
		api.call(new SlackMessage("#general", "TEST-WEBHOOK", "연습~~~~"));
		
	}

4. 결과





슬랙 자체에서 Java API를 많이 제공해준다
https://api.slack.com/community  - 여기에 들어가면 확인할 수 있다.

이 글에서 사용한 API는 
이것이다.



Spring boot에서 AWS S3 파일업로드 하는 방법이다.




Spring boot AWS 배포 방법

2018/10/26 - [Develop/Spring Boot] - Spring Boot AWS Elastic BeanStalk을 이용한 배포


AWS Python Lambda 사용방법

2018/11/16 - [Develop/Python] - AWS Python Lambda (CloudWatch Lambda) 사용하기



1. S3에서 버킷을 하나 생성한다.




버킷을 생성할 때 주의할 점은 이름에 대문자가 들어가면 안되고 특수문자가 들어가면안된다. 또한, 이 버킷의 이름은 AWS S3의 전체 버킷 이름들과 중복이 되면 안된다. 예를들어 test라는 버킷을 한 경우 누군가 test라는 버킷을 사용중이라면 test라는 이름으로 버킷을 생성할 수 없다.


이름을 정한 후 옵션이나 권한 설정은 필요하면 설정을 하시고 그 외 그냥 다음을 눌러 생성한다. 어차피 옵션이나 권한은 S3를 생성하고 다시 설정을 할 수 있다.




2. Spring boot pom.xml에 dependency를 추가한다.


s3 dependency를 추가한다.



    com.amazonaws
    aws-java-sdk-s3
    1.11.452


그리고 Multipartfile 을 사용할 것이기 때문에 Multipartfile dependency를 추가한다.



    commons-fileupload
    commons-fileupload
    1.3.3


3. appliaction.properties 파일 설정.


리전 정보는 옆의 링크에서 확인할 수 있다.- https://docs.aws.amazon.com/ko_kr/general/latest/gr/rande.html 

cloud.aws.credentials.accessKey=IAM USER에서 확인
cloud.aws.credentials.secretKey=IAM USER에서 확인
cloud.aws.s3.bucket=buckettestgogo
cloud.aws.region.static=ap-northeast-2

추가로 Mutlipartfile의 파일 크기 범위를 정하고 싶으면 application.properties에 아래와 같이 추가한다.


spring.http.multipart.max-file-size=10MB
spring.http.multipart.max-request-size=10MB

4. 파일업로드


AmazonS3 의존성을 주입하고. bucket이름을 가져온다 굳이 @Value로 안가져와도 되고 buckettestgogo를 선언해도 된다.


ObjectMetadata를 통해 ContentType을 설정할 수 있다.

그리고 CloudFront를 사용하시는 분들이라면 metadata에 setCacheControl로 Cache설정이 가능하다.

또한. 파일의 권한을 지정할 수 있다. 아래 소스에는 읽기를 Public으로 설정하였다.

	@Autowired
	private AmazonS3 amazonS3;

	@Value("${cloud.aws.s3.bucket}")
	private String bucket;

	public void s3Test(MultipartFile file, String fname) {
		TransferManager tm = TransferManagerBuilder.standard().withS3Client(amazonS3).build();


		PutObjectRequest request;
		try {
	
			ObjectMetadata metadata = new ObjectMetadata();
			metadata.setCacheControl("604800"); // 60*60*24*7 일주일
			metadata.setContentType("image/png");
			request = new PutObjectRequest(bucket, fname, file.getInputStream(), metadata)
					.withCannedAcl(CannedAccessControlList.PublicRead);
			// amazonS3.putObject(request);
			Upload upload = tm.upload(request);

			upload.waitForCompletion();

		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (AmazonServiceException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (AmazonClientException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
       }


기본적인 예제를 활용하여 만들어 보았다 그 외에는 AWS에서 상세히 잘 설명되어 있다.

AWS 객체업로드 - https://docs.aws.amazon.com/ko_kr/AmazonS3/latest/dev/HLuploadFileJava.html

AWS 리전정보 - https://docs.aws.amazon.com/ko_kr/general/latest/gr/rande.html


Expo에서 안드로이드 사용시 could not install *smartsocket* listener: cannot bind to 127.0.0.1:5037 

가끔 Expo 말고 순수 React Native로 실행 했다가 다시 Expo를 실행 할 때 이런 에러가 떴다.


인터넷에 아무리 뒤져봐도 adb.exe를 실행하여 adb kill-server 하라고만 하지 전혀 해결되지 않았다. 수많은 삽질끝에 해결을 하였다.

해결하기 진짜 힘들었다. 


ㄹㅇ 끔찍한 사진.


1. React Native 했다가 Expo 실행 시 에러 났을 경우 에뮬레이터에 앱을 보면 React Native 앱이 깔려 있다. 이것을 일단 지우자.(사실 안지워도 될 수 도있음??) 그리고 혹시 모르니 일단 Expo앱도 지웠다.


2. 그리고 2개의 adb.exe를 찾아야한다. 

1개가 아니다. 2개가 있다. 이러니 삽질할 수 밖에.


나의 PC같은 경우는(Windows 사용)

하나는 아래의 경로에

1. C:\Users\      \AppData\Local\Android\Sdk\platform-tools

나머지 하나는 아래의 경로에 있다.

2. C:\Users\      \AppData\Roaming\npm\node_modules\expo-cli\node_modules\xdl\binaries\windows\adb


그리고 각각 실행해서

adb -version을 찍어보면 두개가 버전이 다르다. 

1번 adb가 버전이 더 높다 그러므로 2번 adb에 1번 adb로 복사 붙여넣기하여 바꾼다.

그리고 두개의 adb를 실행하여 adb kill-server를 각각 해주고

에뮬레이터와 안드로이드 스튜디오를 종료하고 새로 키고

expo start android를 하면

다음부터 에러없이 정상적으로 작동한다.



 

AWS의 Lambda 서비스와 Cloudwatch 이용하면 Batch job 역할을 할 수 있다.

덧 붙여 Python Lambda Python Package 배포 하는 방법을 해보자.



AWS ElasticBeanStalk을 이용한 배포(Spring boot) 바로가기

1. 2018/10/26 - [Develop/Spring Boot] - Spring Boot AWS Elastic BeanStalk을 이용한 배포




1. 먼저 AWS Lambda서비스를 생성합니다.






2. 그리고 AWS CloudWatch 서비스의 규칙에서 규칙생성을 합니다.




3. 이벤트 소스의 일정에 들어가 고정비율 또는 Cron식을 이용하여 시간을 선택합니다.

그리고 대상에서 아까 만든 Lambda 함수를 선택하고 생성을 합니다.


(저의 크론식은 Batchjob을 위해 매일 하루 자정마다 실행을 하는 것입니다.)

Cron식은 아래 링크의 AWS CloudWatch 레퍼런스에서 확인 할 수 있습니다. 

https://docs.aws.amazon.com/ko_kr/lambda/latest/dg/tutorial-scheduled-events-schedule-expressions.html



 


4. 다시 Lambda로 들어와  아까만든 것의 편집합니다.

왼쪽 Designer 창에서 CloudWatch Events를 클릭하고

트리거 구성에 방금 만든 CloudWatch 규칙을 입력하고 추가합니다.




5. 규칙을 추가하였다면 생성한 함수의 이름을 클릭하여 함수코드 적는 란으로 돌아옵니다.




6. 직접 코드를 입력할 수도 있고, zip파일로 추가와 s3에 있는 것을 사용할 수 있습니다. 저는 .zip파일을 추가해보겠습니다.


.zip 파일을 업로드하고 저장을 하면




아래와 같이 Find not found 경고와 코드편집기가 나옵니다. 이 경고 메세지는 실행할 수 있는 핸들러(파이썬 메소드) 이름을 못찾아서 입니다. 이제 곧 수정할 예정입니다.


7. 저의 프로젝트 같은 경우는 app.py에서 실행하므로 app.py에 클릭합니다.

또한 저는 def main 메소드에서 프로그램이 실행됩니다.


이제 핸들러 정보에서 핸들러(파이썬 메소드)를 입력합니다. 

먼저 실행할 메인 파이썬파일의 이름을 적고 뒤엔 실행할 메소드 이름을 적습니다

(ex app.py 의 main() 메소드를 실행한다면 app.main 이라고 적음)

그리고 가장 중요한 실행하는 메인 메소드의 인자에 (event, context)라고 적어주어야 합니다. 

Lambda 레퍼런스에 따르면  아래와 같습니다.

  • event - AWS Lambda는 이 파라미터를 사용하여 이벤트 데이터를 핸들러에 전달합니다. 이 파라미터는 일반적인 Python dict 유형입니다. 또한 liststrintfloat 또는 NoneType 유형이 될 수 있습니다.

  • context - AWS Lambda는 이 파라미터를 사용하여 실행 시간 정보를 핸들러에 제공합니다. 이 파라미터는 LambdaContext 유형입니다.




8. 그리고 가장중요한 Python Package 추가하는 방법입니다. 

저는 사진에 이미 위 사진들에 추가가 되어있습니다.(pymysql)


저는 venv를 사용하기 때문에.

윈도우 기준

 %VIRTUAL_ENV%\Lib\site-packages


리눅스/mac 기준

$VIRTUAL_ENV/lib/python3.6/site-packages


site-packages 안에 있는 패키지 폴더들을 전부 복사하여 최상위 폴더에 붙여넣습니다. 그리고 배포할땐 압축파일에 venv파일을 제외하면 됩니다.

저 같은 경우는 mysql패키지만 사용하므로 site-packages안에 있는 mysql패키지(pymysql, PyMySQL-0.8.0.dist-info, pip-10.0.1-py3.7.egg)를 아래와 같이 최상위 폴더에 붙여놓고 venv폴더를 제외하고 .zip파일로 압축을 하였습니다.



9. 환경 변수 설정. (필요하신 분들만 사용안하시는 분들은 그냥 저장하셔도 무관함.)

저의 config.py 파이썬 파일입니다.



아래와 추가하시면 됩니다.



10. 위의 설정을 다 하셨으면 저장하시면 끝이납니다.

그리고 CloudWatch의 로그에서 필터에 아래와 같이 검색하시면 로그가 나옵니다. 그 로그를 보고 지정한 시각에 실행이 정상적으로 되었는지 확인하시면됩니다.




마지막으로. 파이썬파일에 외부 파일을 저장하는 소스가 있으면 READ_ONLY에러가 나오면서 되지않습니다. 예를 들어 log를 파일로 남기기 위해 파일 저장하는 소스가 있는데. 이는 Lambda에서 파일 저장을 제공하지 않으므로 에러가 발생합니다. 

사실 Lambda의 /tmp폴더에 경로를 지정하여 저장되게 하면, 저장되나 /tmp폴더를 확인할 수 있는 방법이 없습니다. 물론 S3를 이용하여 확인 할 수 는 있습니다.

그러므로 로그를 많이 확인하셔야 한다면 로그파일이 S3에 저장되게 할 수 있습니다. 물론 여기선 다루지 않습니다.(레퍼런스에서 확인)


또한, Lambda의 IP가 동적이므로 데이터베이스에서 IP 허용제한을 걸어 뒀을 경우. Lambda 파이썬 프로젝트에서 데이터베이스에 접근할 경우 동적ip로 인해 접근이 안 될 수 도있습니다. 그럴경우 VPC라는 것을 통해 허용할 수있습니다. 이것 또한 여기서 다루진 않습니다.(레퍼런스에서 확인)



참고

파이썬배포- https://docs.aws.amazon.com/ko_kr/lambda/latest/dg/python-programming-model-handler-types.html

파이썬배포 - https://docs.aws.amazon.com/ko_kr/batch/latest/userguide/batch_cwet.html

파이썬배포 - https://docs.aws.amazon.com/ko_kr/lambda/latest/dg/lambda-python-how-to-create-deployment-package.html

파이썬배포 - https://docs.aws.amazon.com/ko_kr/lambda/latest/dg/with-s3-example-deployment-pkg.html#with-s3-example-deployment-pkg-python

CRON 시간 -https://docs.aws.amazon.com/ko_kr/lambda/latest/dg/tutorial-scheduled-events-schedule-expressions.html

VPC구성- https://docs.aws.amazon.com/ko_kr/AmazonCloudWatch/latest/logs/DocumentHistory_cwl.html

VPC구성 - https://docs.aws.amazon.com/ko_kr/lambda/latest/dg/vpc.html

S3로그 - https://docs.aws.amazon.com/ko_kr/AmazonCloudWatch/latest/logs/S3ExportTasksConsole.html

S3로그 - https://docs.aws.amazon.com/ko_kr/AmazonCloudWatch/latest/logs/S3ExportTasks.html



MySQL  Workbench 에서 프로시저에서 CUSOR 사용시 잘못 된 CUSOR이름을 사용하면 아래와 같은 에러가 발생한다.



Error 1324: Undefined CURSOR: CUR_TEST SQL Statement

이유는 혹시 CUSOR이름을 아래와 같은 형식으로 지을 경우 발생한다.



CUSOR_TEST 의 CUSOR라는 단어가 MYSQL WORKBENCH에서 예약어로 사용되기 때문인 듯 하다.

그러므로 CUR_TEST라는 형식이든 에러가 안나도록 바꾸면 된다.

MySQL  Workbench 에서 프로시저에서 DELIMITER 사용시 아래와 같은 에러가 발생한다.


 Syntax error: unexpected 'DELIMITER'




이유는 Workbench에서 프로시저 작성할 때 이미 DELIMITER를 눈에 보이진 않지만 자동으로 제공해주기 때문이다.

아래와 같이 다시 DELIMITER를 지우고 APPLY를 한번 눌러보면 DELIMITER가 자동으로 제공해주는 것을 볼 수 있다.



따라서 Workbench에서 DELIMITER를 선언할 필요가 없다.

+ Recent posts