Google App Engine 문서 원본 보기
←
Google App Engine
둘러보기로 가기
검색하러 가기
문서 편집 권한이 없습니다. 다음 이유를 확인해주세요:
요청한 명령은 다음 권한을 가진 사용자에게 제한됩니다:
사용자
.
이 문서는 편집하거나 다른 명령을 할 수 없도록 보호되어 있습니다.
문서의 원본을 보거나 복사할 수 있습니다.
Google App Engine(GAE)을 정리 한다. *홈페이지 : https://appengine.google.com/ :*http://code.google.com/p/googleappengine/ :*http://code.google.com/intl/en/appengine/ :*http://groups.google.com/group/google-appengine-java/ *Java Doc :*[http://code.google.com/intl/en/appengine/docs/java/javadoc/ GAE Java Docs] :*[http://code.google.com/intl/de/appengine/docs/java/datastore/ The Datastore Java API] *다운로드 : *라이선스 : *플랫폼 : Google App Engine, Java/Python == 개요 == LXC (LinuX Container)를 대체하는 Google의 Container에서 동작 [https://cloud.google.com/developers/articles/unleashing-appengine-scalability AppEngine 아케텍처] *2008년 4월 : GAE/P (Google App Engine for Python) 서비스 개시 *2009년 4월 : GAE/J (Google App Engine for Java) 서비스 개시 *가격 정책 :*500MB storage 무료 :*월 5백만 page view는 무료 :*계정당 10개의 애플리케이션 등록 가능 :*추가 용량에 따른 과금 정책 :*[http://code.google.com/intl/ko-KR/appengine/docs/quotas.html Understanding Application Quotas with Google App Engine] *서비스 운영 유형 :*appspot.com 도메인을 사용하여 애플리케이션 서비스 ::*예, [https://jopenbusiness.appspot.com/ https://jopenbusiness.appspot.com/] :*Google Apps에서 애플리케이션 서비스 ::*자신의 도메인으로 서비스가 가능함 ==GAE 제약 사항== *[http://code.google.com/intl/de/appengine/docs/quotas.html Google App Engine Quotas] : GAE의 Quotas가 모두 정리되어 있다. *Time-Out에 빠지지 않도록 GAE 내의 애플리케이션을 가볍게 작성 한다. *Blobstore는 GAE/J에 대해서 과금을 할 경우에만 사용할 수 있다. com.google.apphosting.api.ApiProxy$FeatureNotEnabledException: The Blobstore API will be enabled for this application once billing has been enabled in the admin console. *Socket을 사용할 수 없다. ==GAE for Python 개발 환경== 2008년 4월 GAE의 개발 환경을 Python 개발자에게도 공개, 현재 Python 2.5 지원 ==GAE for Java 개발 환경== *[[Google App Engine - Java 개발 환경 설정]] ==GAE for Java의 주요 기능== *appengine-api-1.0-sdk-1.3.6.jar 사용 ===Google App Engine for Java 개요=== *Java 개발 환경 (JavaScript, Ruby), Python 개발 환경 :*Google App Engine SDK 1.3.1 for Java :*Google App Engine SDK 1.3.1 for Python :*Google Plugin for Eclipse : Google App Engine, Google WebToolkit 1.7 :*Database : A set of properties (key-value) ::*JDO (Java Data Object), JPA (Java Persistence API) :*App Engine Service : URL Fetch(java.net), Mail(JavaMail), Memcache, Image Manipulation :*Scheduled Tasks and Task Queues *GAE 개발 환경 :*GAE (Google App Engine) 기반 개발 ::*GAE 1.3.2 ::*GAE에서 지원하는 Java Technologies :::*[http://groups.google.com/group/google-appengine-java/web/will-it-play-in-app-engine?pli=1 Will it play in App Engine ] :*GWT (Google Web Toolkit) 기반 개발 ::*GAE에 적용된 버전 : GWT 2.0.3, 2010.4 ::*주의 : GWT를 사용하여 Eclipse에서 테스트하기 위해서는 브라우저에 GWT 개발 도구(plugin)이 설치되어야 한다. *표준 Java API :*Java 6 VM :*Servlet 2.5 Container :*javax.net.URLConnection for URLFetch API :*javax.mail for Mail API :*JSR 107 for Memcache API : Key-value pair mapping *Application Service :*사용자 인증 및 권한 부여 : ServletFilter, Spring Security에서 활용 가능 :*Cron :*데이터 가져오기/내보내기 : [http://labs.google.com/papers/bigtable.html Google Bigtable 기반 Database] ::*참조: [http://www.datanucleus.org/products/accessplatform/appengine/support.html DataNucleus's Google Bigtable] :*방화벽 데이터에 대한 액세스 *기타 환경 :*HTTP Session support :*JDO/JPA for Database API : GQL (Google Query Language) *제약 사항 :*Only 1000 files per application :*A web request must respond in 30 senconds otherwise GAE throw DeadlineExceededException ===Memcache=== package com.jopenbusiness.gae.sample; import java.util.HashMap; import javax.cache.Cache; import javax.cache.CacheException; import javax.cache.CacheFactory; import javax.cache.CacheManager; public class Memcache { private static Cache cache = null; @SuppressWarnings("unchecked") public Memcache() { CacheFactory factory = null; try { factory = CacheManager.getInstance().getCacheFactory(); cache = factory.createCache(new HashMap<String, Object>()); cache.put("name", "value"); cache.get("name"); } catch (CacheException e) { e.printStackTrace(); } } } ===Blobstore=== *Blobstore는 GAE/J에 대해서 과금을 할 경우에만 사용할 수 있다. com.google.apphosting.api.ApiProxy$FeatureNotEnabledException: The Blobstore API will be enabled for this application once billing has been enabled in the admin console. ===Persistence=== GAE for Java는 데이터 관리를 위해 JDO(Java Data Objects)와 JPA(Java Persistence API)를 지원한다. User 데이터 관리를 예제로 하여 이를 확인해 보자. *User.java :*저장할 데이터를 어노테이션을 사용하여 식별한다. package com.jopenbusiness.gae.client; import java.io.Serializable; import javax.jdo.annotations.IdGeneratorStrategy; import javax.jdo.annotations.IdentityType; import javax.jdo.annotations.PersistenceCapable; import javax.jdo.annotations.Persistent; import javax.jdo.annotations.PrimaryKey; '''@PersistenceCapable(identityType = IdentityType.APPLICATION)''' public class User implements Serializable { private static final long serialVersionUID = 3438684493254005858L; '''@PrimaryKey''' '''@Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)''' private long id = 0l; '''@Persistent''' private String name = null; '''@Persistent''' private String username = null; '''@Persistent''' private String password = null; '''@Persistent''' private String email = null; public long getId() { return id; } public void setId(long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } } *UserDAO.java package com.jopenbusiness.gae.server; import java.util.ArrayList; import com.jopenbusiness.gae.client.User; public interface UserDAO { void insertUser(User user); void updateUser(User user); void deleteUser(User user); ArrayList<User> selectUsers(); } *UserDAOJdo.java :*PersistenceManager를 사용하여 데이터를 관리 한다. package com.jopenbusiness.gae.server; import java.util.ArrayList; import javax.jdo.PersistenceManager; import com.jopenbusiness.gae.client.User; import com.jopenbusiness.gae.server.PMF; public class UserDAOJdo implements UserDAO { @Override public void insertUser(User user) { PersistenceManager pm = null; try { pm = PMF.getPersistenceManager(); pm.makePersistent(user); } finally { pm.close(); } } @Override public void updateUser(User user) { PersistenceManager pm = null; User tmpUser = null; try { pm = PMF.getPersistenceManager(); pm.currentTransaction().begin(); tmpUser = pm.getObjectById(User.class, user.getId()); tmpUser.setName(user.getName()); tmpUser.setUsername(user.getUsername()); tmpUser.setPassword(user.getPassword()); tmpUser.setEmail(user.getEmail()); pm.makePersistent(tmpUser); pm.currentTransaction().commit(); } catch (Exception ex) { pm.currentTransaction().rollback(); throw new RuntimeException(ex); } finally { pm.close(); } } @Override public void deleteUser(User user) { PersistenceManager pm = null; try { pm = PMF.getPersistenceManager(); pm.currentTransaction().begin(); user = pm.getObjectById(User.class, user.getId()); pm.deletePersistent(user); pm.currentTransaction().commit(); } catch (Exception ex) { pm.currentTransaction().rollback(); throw new RuntimeException(ex); } finally { pm.close(); } } @Override @SuppressWarnings("unchecked") public ArrayList<User> selectUsers() { PersistenceManager pm = null; String query = null; pm = PMF.getPersistenceManager(); query = "select from " + User.class.getName(); return (ArrayList<User>) pm.newQuery(query).execute(); } } *PMF.java :*PersistenceManagerFactory가 자원을 많이 차지하므로 유일하게 관리 한다. package com.jopenbusiness.gae.server; import javax.jdo.JDOHelper; import javax.jdo.PersistenceManager; import javax.jdo.PersistenceManagerFactory; public class PMF { private static final PersistenceManagerFactory pmfInstance = JDOHelper.getPersistenceManagerFactory("transactions-optional"); private PMF() { } public static PersistenceManagerFactory get() { return pmfInstance; } public static PersistenceManager getPersistenceManager() { return pmfInstance.getPersistenceManager(); } } */src/META-INF/jdoconfig.xml :*persistence-manager-factory를 정의 한다. <?xml version="1.0" encoding="utf-8"?> <jdoconfig xmlns="http://java.sun.com/xml/ns/jdo/jdoconfig" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://java.sun.com/xml/ns/jdo/jdoconfig"> <persistence-manager-factory name="transactions-optional"> <property name="javax.jdo.PersistenceManagerFactoryClass" value="org.datanucleus.store.appengine.jdo.DatastoreJDOPersistenceManagerFactory"/> <property name="javax.jdo.option.ConnectionURL" value="appengine"/> <property name="javax.jdo.option.NontransactionalRead" value="true"/> <property name="javax.jdo.option.NontransactionalWrite" value="true"/> <property name="javax.jdo.option.RetainValues" value="true"/> <property name="datanucleus.appengine.autoCreateDatastoreTxns" value="true"/> </persistence-manager-factory> </jdoconfig> ===Logging=== import java.util.logging.Level; import java.util.logging.Logger; private final static Logger log = Logger.getLogger(Memcache.class.getName()); log.log(Level.WARNING, "Start Memcache"); ==SSO with Google Apps== *사용자가 접속할 때 보여줄 첫 화면 :*index.jsp <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <%@ page pageEncoding="UTF-8" contentType="text/html; charset=UTF-8" language="java"%> <%@ page import="com.google.appengine.api.users.User" %> <%@ page import="com.google.appengine.api.users.UserService" %> <%@ page import="com.google.appengine.api.users.UserServiceFactory" %> <% UserService userService = null; User user = null; String domain = "jopenbusiness.co.kr"; String service = "http://www.jopenbusiness.co.kr/"; userService = UserServiceFactory.getUserService(); if (!userService.isUserLoggedIn()) { out.print("<script type=\"text/javascript\">"); out.print("window.document.location.href = \"" + userService.createLoginURL(request.getRequestURI()) + "\";"); out.print("</script>"); return; } user = userService.getCurrentUser(); //user = (User) request.getAttribute("user"); if ((user == null) || (!user.getAuthDomain().equals(domain))) { out.print("<script type=\"text/javascript\">"); out.print("window.document.location.href = \"" + userService.createLoginURL(request.getRequestURI()) + "\";"); out.print("</script>"); return; } out.print("<script type=\"text/javascript\">"); out.print("window.document.location.href = \"" + service + "\";"); out.print("</script>"); %> *로그인된 사용자의 정보를 반환하는 화면 :*Google Apps의 각각의 서비스에서 로그아웃을 하면 Google Apps만 로그아웃됨 :*userService.createLogoutURL(loginURL)이 생성하는 URL로 로그아웃 요청을 하면 전체 서비스가 로그아웃됨 :*checkSSO.jsp <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <%@ page pageEncoding="UTF-8" contentType="text/html; charset=UTF-8" language="java"%> <%@ page import="com.google.appengine.api.users.User" %> <%@ page import="com.google.appengine.api.users.UserService" %> <%@ page import="com.google.appengine.api.users.UserServiceFactory" %> <% UserService userService = null; User user = null; String domain = "jopenbusiness.co.kr"; String service = "http://www.jopenbusiness.co.kr/"; String loginURL = "http://www.jopenbusiness.co.kr/index.jsp"; userService = UserServiceFactory.getUserService(); if (!userService.isUserLoggedIn()) { out.print("{"); out.print("errorCode:\"-1\","); out.print("errorMessage:\"Error: not login.\""); out.print("}"); return; } user = userService.getCurrentUser(); //user = (User) request.getAttribute("user"); if ((user == null) || (!user.getAuthDomain().equals(domain))) { out.print("{"); out.print("errorCode:\"-2\","); out.print("errorMessage:\"Error: authDomain not match.\""); out.print("}"); return; } out.print("{"); out.print("errorCode:\"0\","); out.print("errorMessage:\"OK\","); out.print("authDomain:\"" + user.getAuthDomain() + "\","); out.print("email:\"" + user.getEmail() + "\","); out.print("userId:\"" + user.getUserId() + "\","); out.print("nickname:\"" + user.getNickname() + "\","); out.print("loginURL:\"" + userService.createLoginURL(loginURL) + "\","); out.print("logoutURL:\"" + userService.createLogoutURL(loginURL) + "\""); out.print("}"); %> ==GAE for Biz== *기업용 Google App Engine :*SQL을 지원하는 Database 제공 예정 *비용 :*1인당 월 $8, 최대 $1000 ==Google Web Toolkit== GWT는 Java를 JavaScript로 컴파일 하여 브라우저에서 실행(AJAX Application)할 수 있도록 하는 도구로 성능적인 부분에서 최적화되어 있다. *주의 : GWT를 사용하여 Eclipse에서 테스트하기 위해서는 브라우저에 GWT 개발 도구(plugin)이 설치되어야 한다. *참고 문헌 :*[http://visualhhk.blogspot.com/2009/11/google-web-toolkit-eclipse-galileo.html Google Web Toolkit과 Eclipse Galileo를 이용한 고성능 웹 개발, 2009.11] ==개발자 매뉴얼== ===Query=== */war/WEB-INF/datastore-indexes.xml <?xml version="1.0" encoding="utf-8"?> <!-- http://code.google.com/intl/ko-KR/appengine/docs/java/datastore/queries.html#Introduction_to_Indexes --> <datastore-indexes autoGenerate="true"> <datastore-index kind="ContactVO" ancestor="false"> <property name="cloudName" direction="asc" /> <property name="updateDatetime" direction="asc" /> </datastore-index> </datastore-indexes> *참고 문헌 :*[http://blog.naver.com/PostView.nhn?blogId=hwang8125&logNo=90102652739 google app engine(GAE)에서의 쿼리 사용법, 2010.12] == 참고 문헌 == *[http://googleappengine.blogspot.com/ Google App Engine Blog] *[http://appengine-cookbook.appspot.com/ Google Cookbook - Google App Engine] *[http://code.google.com/status/appengine Google App Engine - System Status] *[http://groups.google.com/group/google-appengine-java GAE - Google Groups] : 오류 사항을 검색할 수 있음 *[http://code.google.com/p/blobdb/ BlobDB] *[http://http://gaejexperiments.wordpress.com/ Google App Engine Java Experiments] : GAE/J 용 책을 편 사람의 블로그 :*[http://mumbaihealth.appspot.com/ Mumbai Health Tracker] *[http://appgallery.appspot.com/results?topapps=true Application Gallery Search Results - Top Apps] *Manual :*[http://code.google.com/intl/de/appengine/docs/java/datastore/ http://code.google.com/intl/de/appengine/docs/java/datastore/] :*[http://code.google.com/intl/de/appengine/docs/java/javadoc/ http://code.google.com/intl/de/appengine/docs/java/javadoc/] :*[http://jpql.com//api/java/jdo http://jpql.com//api/java/jdo] *[[Design pattern|Design pattern]] *[http://www.moreagile.net/2014/05/ContainersAtScale.html http://www.moreagile.net/2014/05/ContainersAtScale.html] *http://www.slideshare.net/curioe_/lezhincomics-google-appengine-30453946 [[Category:Google|Category:Google]]<br/>[[Category:Cloud|Category:Cloud]]<br/>[[Category:Java|Category:Java]]
Google App Engine
문서로 돌아갑니다.
둘러보기 메뉴
개인 도구
로그인
이름공간
문서
토론
변수
보기
읽기
원본 보기
역사 보기
더 보기
검색
주요 메뉴
오픈소스 컨설팅
오픈소스
오픈소스 라이선스
오픈소스 커뮤니티
오픈소스 종류
오픈소스 현황
오픈소스 한글화
문자셋과 인코딩
Storage
Network
보안
고가용성
모니터링
오픈 API
오픈 서비스
Cloud
BigData
Android
산사랑 노트
둘러보기
인기 문서
최근 수정 문서
모든 문서
모든 분류
임의 문서
위키 사용법
자매 사이트
CMS
오비컨 홈페이지
오비컨 CMS
블로그
데모 - SuiteCRM
산사랑의 Twitter
산사랑의 Facebook
친구 사이트
공개SW 포털
OLIS
한국공개소프트웨어협회
AppCenter 지원본부
OLC
PSEG
개발자 블로그
블로터
개인 메뉴
메뉴 수정
양식함
도구
여기를 가리키는 문서
가리키는 글의 최근 바뀜
특수 문서 목록
문서 정보