반응형
해당 게시글에서는 지도 화면이 아닌 JSON 데이터를 받는 방법입니다!
이번에는 lambda 함수를 먼저 작성하고 테스트 해보자

 

이전에는 Flutter + rest api 통신 문제로 인해 통신하지 못했지만, javascript에서는 가능했다. 때문에 AWS Web Service를 활용하여 서버에 코드를 등록하고 호출하는 방식을 사용해보고자 한다. 

 


 

 

클라우드 서비스 | 클라우드 컴퓨팅 솔루션| Amazon Web Services

필요한 만큼 이용할 수 있는 것은 물론 필요에 따라 몇 분 만에 확장 또는 축소할 수 있습니다. 자세히 알아보세요.

aws.amazon.com

 

우리가 사용할 것은 코드를 등록하여 사용할 Lambda, Flutter와 통신할 매개체인 API GateWay다.
각각 월 100만건 무료로 그 이상 호출 시 사용한만큼에 따라 가입한 정책에 따라 요금이 부과된다.

 

 

때문에 가입 후 카드 등록이 필수다. 카드 등록시 1$를 결제한 후 바로 취소해 준다고 써져 있다.

( 카드 결제 정보가 맞는지 확인차 하는 것으로 보이며 저는 100원 결제되었다가 바로 취소되었습니다. )

가입 후 카드정보를 다음과 같이 입력하면 된다.

 



1. 가입이 완료되었다면 콘솔로 이동해 주자

2. 콘솔 상단의 검색에 lambda를 검색 후 이동해 주자

 

3. lambda 함수를 생성 해주자

 

4. 사용할 함수명과 함께 함수를 만들어 주자

 

코드를 등록하기 때문에 내장함수가 아니면 라이브러리를 다운받아서 같이 올려줘야 한다.

때문에 Node.js 가 익숙하다면 Node.js를 사용하고 나는 Python으로 진행하였다.

런타임에서 Node.js 가 아닌 Python을 선택하면 된다.

( 저는 Test(함수 이름), Python 3.12 version(런 타임 환경) 을 사용했습니다. )

 

생성 후 다음과 같은 화면을 볼 수 있는데

코드 작성 후 Deploy(배포)를 통해 저장한다고 생각하면 되고 Test를 통해 코드 테스트를 해 볼 수 있다.

다른 언어의 main함수와 같이 lambda_function 이름을 가진 코드를 실행하기 때문에 이름 변경에 주의하자.

 


이제 코드를 작성하자.

기존의 DartNode.js에서 작성했던 코드를 Python으로 변환하고

x, y를 매개변수로 받는 함수로 작성해보자

 

 

 

1. 먼저 원하는 위치에 빈디렉토리 생성 후 lambda_fuction.py 파일을 만들어 주자.

 

2. Aws lambda에 쓸 카카오와 Rest API 통신하는 코드를 작성한다.

import json
import requests

def make_api_call(x, y):
   
    params = {
        'query': '카카오 프렌즈',
        'y': y,
        'x': x,
        'radius': '20000'
    }

    headers = {
        'Authorization': 'KakaoAK 발급받은_Rest_API_KEY'
    }

    response = requests.get(url, params=params, headers=headers)
    response_data = response.json()
   
    return response_data

def lambda_handler(event, context):
    x = event['x']
    y = event['y']
   
    try:
        data = make_api_call(x, y)
        return {
            'statusCode': 200,
            'body': json.dumps(data)
        }
    except Exception as e:
        return {
            'statusCode': 500,
            'body': json.dumps({'error': str(e)})
        }

 

3. 해당 파일 경로에 이동하여 requests 라이브러리를 추가해주자.

cmd 창에 다음과 같이 입력한다.

3-1. >cd ~파일경로/Test

3-2. >pip install requests -t

 

4. 해당 Test 파일을 압축 후 업로드 한다.

 

업로드 후 저장해 준다.

 

여기서 주의할 점이 lambda 함수 페이지에서 root 하위 파일들로 위치해 있어야 한다.

 

5. 이제 Test 해보자

 

Test 버튼 클릭 후 이름과 임의의 경도와 위도 값을 넣으면 된다.

다시 테스트 버튼을 클릭하면 다음과 같은 결과를 얻을 수 있다.

 

 

마치며...
메모리 사용량 시간 등을 알려주며 한글은 변환되어 \\uc11c\\uc6b8(서울)로 표현된다.
다음은 API GATEWAY를 사용하여 lambda와 연결하고
Flutter에서 URL에 POST 요청을 통해 처리할 수 있도록 하겠다 

 

반응형
반응형
해당 게시글에서는 지도 화면이 아닌 JSON 데이터를 받는 방법입니다!

 

Flutter에서 지도를 가져와 쓰고 싶을 때 물론 flutter 개발사인 구글 지도도 좋지만, 친근한 네이버 지도, 카카오 지도가 더 좋지 않을까? 해서 사용해보려고 한다. 

 

 

 

 

 

 

카카오 지도 API 문서네이버 지도 API 문서를 뒤적거리다.
내가 해보고 싶은건 지도도 지도지만 검색해서 나오는 마커표시들이다.

 

찾아보니 네이버 지도 API  압도적으로 많다. ( 그 이유는 하다보니 알게 되었다. )
일단 네이버가 설명이 개인적으로 잘 되어 있는 편이다. 근데 둘다 설명은 개인적으로 2% 부족한 편

( 내가 못찾은건가 싶기도 하다 )

 


 

일단 우리는 위 화면과 같은 목표로 개발하기 위해서 첫번 째로

네이버가 아닌 카카오 지도 API  중 하나인 Rest API ( 키워드로 검색하기 )를 사용해보려고 한다.

( 찾아보니 네이버 지도에는 키워드 검색하기가 20년도쯤에 종료된 것으로 안다. )

 

오늘은 요청하고 데이터를 받기만 하기 때문에 UI적 요소는 크게 필요 없다.


 

https://developers.kakao.com/

 

Kakao Developers

카카오 API를 활용하여 다양한 어플리케이션을 개발해보세요. 카카오 로그인, 메시지 보내기, 친구 API, 인공지능 API 등을 제공합니다.

developers.kakao.com

  위 사이트에서 다음과 같이 진행하면 된다.

내 애플리케이션 클릭
추가하기 클릭

 

다음과 같이 기재

 

Flutter의 경우 앱 이름은 보통  com.example.${해당 프로젝트 이름으로 구성된다}
위치는 프로젝트 안에 android/app/build.gradle에 해당 형식으로 적혀져 있다.

보통 manifest에 package명으로 기재되어 있음.

우리는 Rest  API 이기 때문에 해당하는 부분을 사용하면 된다.

(아직은 플랫폼을 등록 안해도 된다.)

 


 

https://developers.kakao.com/docs/latest/ko/local/dev-guide

 

Kakao Developers

카카오 API를 활용하여 다양한 어플리케이션을 개발해보세요. 카카오 로그인, 메시지 보내기, 친구 API, 인공지능 API 등을 제공합니다.

developers.kakao.com

 

이제 Rest API 문서를 확인해 보자

 

 

우리는 이 중에서 키워드로 장소 검색하기를 사용할 것이다!

 

요청시 Authorization 헤더와 쿼리 파라미터 query필수인 것을 알 수 있다.

 

curl -v -G GET "https://dapi.kakao.com/v2/local/search/keyword.json?y=37.514322572335935&x=127.06283102249932&radius=20000" -H "Authorization: KakaoAK ${REST_API_KEY}" --data-urlencode "query=카카오 프렌즈"

 

 

예시 코드를 cmd에서 시험해 보면 다음과 같은 결과를 알 수 있다.

 

그렇다면 우리는 이 결과를 통해 document가 List형식을 띄는 것을 알 수 있고 형식은 다음과 같다


그렇다면 우리의 위치를 기점으로 20km의 "카카오 프렌즈"  를 검색하고자 한다.


 

1-1. 우리의 위치를 찾기 위해 geolocator를 추가해 준다.

 

1-2. 안드로이드 manifest.xml에 위치(geolactor)와 인터넷(http 통신)을 추가해준다.

    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.INTERNET" />

 

1-3. 다음과 같은 코드로 사용할 수 있다.

    // 현재의 위도 경도 위치를 가져옴
    Position position = await Geolocator.getCurrentPosition(
        desiredAccuracy: LocationAccuracy.high);

    position.latitude;  // 위도 y
    position.longitude; // 경도 x

 

 

2-1. 동일하게 .yaml file에 해당 dependencie를 추가해 줍니다.

dependencies:
  http: ^1.2.1

 

3. 그렇다면 이제 다음과 같이 uri과 params, header를 통해 통신할 수 있습니다.

    const String apiKey = 'KaKaoAK ${Rest key}';

    final Map<String, String> queryParams = {
      'y': '${position.latitude}',
      'x': '${position.longitude}',
      'radius': '20000',
      'query': '카카오 프렌즈'
    };

    final uri = Uri.parse(url).replace(queryParameters: queryParams);

    final response = await http.get(
      uri,
      headers: {
        'Authorization': apiKey,
      },
    );

    if (response.statusCode == 200) {
      final data = jsonDecode(response.body);
      log('Response data: $data');
    } else {
      log('Request failed with status: ${response.statusCode}.');
    }
  }

 

통신의 결과 log를 확인해보자

 

결과

[log] Request failed with status: 401.

 

... ??

 

Flutter Code로 실행한 결과 권한이 없음 이였다. 하지만 이는 domain과 params가 잘못된 경우도 포함되므로 다음과 같은 시도를 하였다. ( javascript로 추가 검증시에 발견 )

1. url = https://dapi.kakao.com/v2/local/search/keyword
2. parms를 필수 param인 query만 두고 작성
3. --data-urlencode를 위한 Uri.encodeComponent(keyword)
4. Kakao문서의 SDK 추가
5. 네이트비 앱 키 등록
6. Admin 키 사용
7. 보낸 domain, header, params 재 확인 ( 텍스트 비교기로 확인 )

 

( 혹시나 RestApi + Flutter http 로 되는 사람이 있으면 댓글 부탁드립니다. )

 

때문에 이 코드를 JavaScript로 변환시켜 Node.js로 실행시켜보니 200(Ok)의 결과와 함께 데이터가 왔다..

 

전체 코드 ( Flutter )

import 'dart:convert';
import 'dart:developer';
import 'package:flutter/material.dart';
import 'package:geolocator/geolocator.dart';
import 'package:http/http.dart' as http;

class TestPage extends StatefulWidget {
  const TestPage({super.key});

  @override
  State<TestPage> createState() => _TestPageState();
}

class _TestPageState extends State<TestPage> {
  Future<void> fetch() async {
    // 현재의 위도 경도 위치를 가져옴
    Position position = await Geolocator.getCurrentPosition(
        desiredAccuracy: LocationAccuracy.high);

    const String apiKey = 'KaKaoAK ${Rest key}';

    final Map<String, String> queryParams = {
      'y': '${position.latitude}',
      'x': '${position.longitude}',
      'radius': '20000',
      'query': '카카오 프렌즈'
    };

    final uri = Uri.parse(url).replace(queryParameters: queryParams);

    final response = await http.get(
      uri,
      headers: {
        'Authorization': apiKey,
      },
    );

    if (response.statusCode == 200) {
      final data = jsonDecode(response.body);
      log('Response data: $data');
    } else {
      log('Request failed with status: ${response.statusCode}.');
    }
  }

  @override
  void initState() {
    super.initState();
    fetch();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("테스트 페이지"),
      ),
      body: const Center(
        child: Text("지도 api 테스트중 입니다."),
      ),
    );
  }
}
마치며..

이 문제도 문제인데, KEY 의 보안 문제 때문에 클라우드 서비스를 통해 데이터를 전달 받는 방식으로 다음 포스팅을 하려고 한다. 다음에는 AWS를 활용하여 데이터를 전달받고 지도에 마커를 등록하는 글로 찾아오겠습니다.

 

반응형
반응형
간혹 가다 코드 작성시 한칸씩 띄어쓰기 되어서 보여지는 경우가 있습니다.
이를 반자, 전자라고 하는데요.
간격이 벌어지는 경우 전자
붙어서 타이핑 되는 경우 반자라고 합니다.

 

 

 

윈도우의 경우 다음과 같이 아래쪽에 마우스 오른쪽 클릭을 통해 변경하실 수 있습니다.

 

그래도 안된다고 하시는 경우가 있습니다!

 

그럴 땐 ALT + = (백스페이스 왼쪽) 을 하시면 됩니다.

반응형
반응형

문제

JLabel을 활용하여 "Love Java"를 출력하고, "Love Java" 글자 위에 마우스를 올려 마우스 휠을 위로 굴리면 글자가 작아지고, 아래로 굴리면 글자가 커지도록 프로그램을 작성하라. 폰트 크기는 한 번에 5픽셀씩 작아지거나 커지도록 하고, 5픽셀 이하로 작아지지 않도록 해라.

 

소스 코드

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class Main7 extends JFrame{
	public Main7() {
		setTitle("마우스 휠을 굴려 폰트 크기 조절");
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		
		Container c = getContentPane();
		c.setLayout(new FlowLayout());
		
		JLabel la = new JLabel("Love Java");
		la.addMouseWheelListener(new MouseWheelListener() {
			public void mouseWheelMoved(MouseWheelEvent e) {
				int n = e.getWheelRotation();
				int size = la.getFont().getSize();
				if(n<0&&size>5) {
					la.setFont(new Font("Arial",Font.PLAIN,size-5));			
				}
				else {
					la.setFont(new Font("Arial",Font.PLAIN,size+5));
				}
			}
		});
		c.add(la);
		setSize(500,500);
		setVisible(true);
	}
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		new Main7();
	}

}
반응형
반응형

문제

클릭 연습용 스윙 응용프로그램을 작성하라. "C"를 출력하는 JLabel을 하나 만들고 초기 위치를 (100, 100)으로 하고, "C"를 클릭할 때마다 컨텐트팬 내에 랸덤한 위치로 움직이게 하라.

 

소스 코드

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class Main6 extends JFrame{
	public Main6() {
		setTitle("클릭 연습 용 응용프로그램");
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		
		Container c = getContentPane();
		
		c.setLayout(null);
		
		JLabel l = new JLabel("C");
		l.setSize(10,10);
		l.setLocation(100, 100);
		
		c.add(l);
		
		l.addMouseListener(new MouseAdapter() {
			public void mouseClicked(MouseEvent e) {
				int x = (int)(Math.random()*250);
				int y = (int)(Math.random()*250);
				l.setLocation(x, y);
			}
		});
		
		setSize(300,300);
		setVisible(true);
	}
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		new Main6();
	}

}
반응형
반응형

문제

JLabel 컴포넌트로 "Love Java"를 출력하고, 키 리스너를 작성하여 + 키를 치면 폰트 크기를 5픽셀씩 키우고, - 키를 치면 폰트 크기를 5픽셀씩 줄이는 스윙 응용프로그램을 작성하라. 5픽셀 이하로 작아지지 않도록 하라.

 

소스 코드

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Main5 extends JFrame{
	public Main5() {
		setTitle("+,-키로 폰트 크기 조절");
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		
		Container c = getContentPane();
		
		JLabel label = new JLabel("Love Java");
		label.setFont(new Font("Arial",Font.PLAIN,10)); // Arial 폰트로 10픽섹 크기
		Font f = label.getFont();

		c.setLayout(new FlowLayout());
		
		c.addKeyListener(new KeyAdapter() {
			public void keyPressed(KeyEvent e) {
				int size = f.getSize();
				if(e.getKeyCode() == KeyEvent.VK_ADD || e.getKeyCode()==KeyEvent.VK_EQUALS) { // 전자는 숫자패드의 + 후자는 Shift와 함께쓰는 버튼입니다.
					label.setFont(new Font("Arial",Font.PLAIN,size+5));
				}
				// 플러스와 동일
				else if((e.getKeyCode() == KeyEvent.VK_MINUS || e.getKeyCode() == KeyEvent.VK_SUBTRACT) && size > 5) {
					label.setFont(new Font("Arial",Font.PLAIN,size-5));
				}
			}
		});
		
		c.add(label);
		
		setSize(300,200);
		setVisible(true);
		
		c.setFocusable(true);
		c.requestFocus();
	}
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		new Main5();
	}

}
반응형
반응형

문제

JLabel을 활용하여 "Love Java"를 출력하고 왼쪽 화살표 키(<Left> 키)를 입력할때마다 "ove JavaL", "ve JavaLo", "e JavaLov"와 같이 한 문자씩 왼쪽으로 회전하는 프로그램을 작성하라.

 

소스 코드

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class Main4 extends JFrame{
	public Main4() {
		setTitle("Left 키로 문자열 이동");
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		
		Container c = getContentPane();
		
		JLabel label = new JLabel("Love Java"); 
		c.setLayout(new FlowLayout());
		
		c.addKeyListener(new KeyAdapter() {
			public void keyPressed(KeyEvent e) {
				if(e.getKeyCode() == KeyEvent.VK_LEFT) {  
					label.setText(label.getText().substring(1) + label.getText().charAt(0));
				}		
			}
		});
		
		c.add(label);
		
		setSize(300,100);
		setVisible(true);
		
		c.setFocusable(true);
		c.requestFocus();
	}
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		new Main4();
	}

}
반응형
반응형

문제

JLabel을 활용하여 "Love Java"를 출력하고 왼쪽 화살표 키(<Left> 키)를 입력할 때마다 "avaJ evoL"와 "Love Java"를 번갈아 출력하는 스윙 프로그램을 작성하라

 

소스 코드

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class Main3 extends JFrame{
	public Main3() {
		setTitle("Left 키로 문자열 교체");
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		
		Container c = getContentPane();
		
		JLabel label = new JLabel("Love Java"); 
		c.setLayout(new FlowLayout());
		
		c.addKeyListener(new KeyAdapter() {
			public void keyPressed(KeyEvent e) {
				if(e.getKeyCode() == KeyEvent.VK_LEFT) {  
					if(label.getText().equals("Love Java")) {
						label.setText("avaJ evoL");
					}
					else if(label.getText().equals("avaJ evoL")) {
						label.setText("Love Java");	
					}
				}		
			}
		});
		
		c.add(label);
		
		setSize(300,100);
		setVisible(true);
		
		c.setFocusable(true);
		c.requestFocus();
	}
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		new Main3();
	}

}
반응형
반응형

문제

컨텐트팬의 배경색은 초록색으로 하고 마우스를 드래깅하는 동안만 노란색으로 유지하는 스윙 응용프로그램을 작성하라.

 

소스 코드

import javax.swing.*;
import java.awt.event.*;
import java.awt.*;

public class Main2 extends JFrame{
	public Main2() {
		setTitle("드래깅동안 YELLOW...");
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		
		Container c = getContentPane();
		Panel p = new Panel();
		p.setBackground(Color.green);
		
		p.addMouseMotionListener(new MouseAdapter() {
			public void mouseDragged(MouseEvent e) {
				p.setBackground(Color.yellow);
			}
		});
		p.addMouseListener(new MouseAdapter() {
			public void mouseReleased(MouseEvent e) {
				p.setBackground(Color.green);
			}
		});
		c.add(p);
		
		setSize(300,200);
		setVisible(true);
	}
	public static void main(String[] args) {
		new Main2();
		
	}

}

 

반응형
반응형

문제

문제 13을 확장하여 다음 명령을 추가하라.

 

명령 사용 예시

>>rename phone txt p.txt //phone.txt를 p.txt로 변경. 파일과 디렉터리 이름 변경
>>mkdir xxx // 현재 디렉터리 밑에 xxx 디렉터리 생성

 

소스 코드 ( 실습문제 13번 디렉터리 이동 부분 NullPointerException 오류도 수정 하였습니다. )

import java.io.*;
import java.util.*;

public class Main13 {
	public static void ListFile(File f) {
		File[]subFiles = f.listFiles();
		for(int i = 0;i<subFiles.length;i++) {
			File file = subFiles[i];
			
			// 파일 종류
			if(file.isDirectory())
				System.out.print("dir\t");
			else if(file.isFile())
				System.out.print("file\t");
			
			System.out.printf(file.length()+"바이트"); // 파일 크기
			System.out.println("   \t"+file.getName()); // 파일이름
		}
	}
	public static void main(String[] args) throws IOException {
		// TODO Auto-generated method stub
		File f = new File("C:\\");
		Scanner s = new Scanner(System.in);
		System.out.println("***** 파일 탐색기입니다. *****");
		System.out.println("\t["+f.getPath()+"]");
		ListFile(f);
		while(true) {
			
			System.out.print(">>");
			String search = s.next();
			if(search.equals("그만")) {
				break;
			}
			else if(search.equals("..")) {
				File temp = new File(f.getParent());
				f = temp;
			}
			else if(search.equals("rename")) {
				String Changename = s.nextLine();
				try {
					StringTokenizer st = new StringTokenizer(Changename," ");
					while(st.hasMoreTokens())
					{
						File temp = new File(f.getPath()+"\\"+st.nextToken());
						File renameFile = new File(f.getPath()+"\\"+st.nextToken());
						temp.renameTo(renameFile);
					}
				}catch(NoSuchElementException e) {
					System.out.println("두 개의 파일명이 주어지지 않았습니다.!");
					continue;
				}
			}
			
			else if(search.equals("mkdir")) {
				String name = s.nextLine();
				File fout = new File(f.getPath()+"\\"+name);
				if(!fout.exists()) {
					System.out.println(fout.getName()+ " 디렉터리를 생성하였습니다.");
					fout.mkdir();
				}
				else {
					System.out.println("이미 존재하는 파일입니다.");
					continue;
				}
				
			}
			else {
					File temp = new File(f.getPath()+"\\"+search);	
					f = temp;		
			}
			try {
				System.out.println("\t["+f.getPath()+"]");
				ListFile(f);
			}catch(NullPointerException e) {
				System.out.println("없는 파일입니다.");
				continue;
			}
		}
		s.close();
	}
}
반응형

+ Recent posts