이 가이드는 클래스룸 부가기능 둘러보기 시리즈의 첫 번째 둘러보기입니다.
이 둘러보기에서는 웹 애플리케이션을 개발하고 이를 클래스룸 부가기능으로 게시하기 위한 기반을 닦습니다. 이후 둘러보기 단계에서는 이 앱을 확장합니다.
이 둘러보기에서는 다음 작업을 완료합니다.
- 웹 앱의 새 Google Cloud 프로젝트를 만듭니다.
- 자리표시자 로그인 버튼이 있는 스켈레톤 웹 앱을 만듭니다.
- 웹 앱의 비공개 Google Workspace Marketplace (GWM) 스토어 등록정보를 게시합니다.
완료되면 부가기능을 설치하고 클래스룸 부가기능 iframe에서 로드할 수 있습니다.
기본 요건
아래에서 언어를 선택하여 적절한 기본 요건을 확인하세요.
Python
Python 예에서는 Flask 프레임워크를 사용합니다.
개요 페이지에서 모든 둘러보기의 전체 소스 코드를 다운로드할 수 있습니다. 이 특정 둘러보기의 코드는 /flask/01-basic-app/
디렉터리에서 찾을 수 있습니다.
필요한 경우 Python 3.7 이상을 설치하고 pip
를 사용할 수 있는지 확인합니다.
python -m ensurepip --upgrade
또한 새 Python 가상 환경을 설정하고 활성화하는 것이 좋습니다.
python3 -m venv .classroom-addon-env
source .classroom-addon-env/bin/activate
다운로드한 예시의 각 둘러보기 하위 디렉터리에는 requirements.txt
가 포함되어 있습니다. pip
를 사용하여 필요한 라이브러리를 빠르게 설치할 수 있습니다. 다음을 사용하여 이 둘러보기에 필요한 라이브러리를 설치합니다.
cd flask/01-basic-app
pip install -r requirements.txt
Node.js
Node.js 예에서는 Express 프레임워크를 사용합니다. 개요 페이지에서 모든 둘러보기의 전체 소스 코드를 다운로드할 수 있습니다.
필요한 경우 NodeJS v16.13+를 설치합니다.
npm
를 사용하여 필수 노드 모듈을 설치합니다.
npm install
Java
자바 예에서는 Spring Boot 프레임워크를 사용합니다. 개요 페이지에서 모든 둘러보기의 전체 소스 코드를 다운로드할 수 있습니다.
자바 11+가 머신에 아직 설치되어 있지 않으면 설치합니다.
Spring Boot 애플리케이션은 Gradle 또는 Maven을 사용하여 빌드를 처리하고 종속 항목을 관리할 수 있습니다. 이 예에는 Maven 자체를 설치하지 않고도 성공적인 빌드를 보장하는 Maven 래퍼가 포함되어 있습니다.
제공된 예를 실행하려면 프로젝트를 다운로드한 디렉터리에서 다음 명령어를 실행하여 프로젝트를 실행하기 위한 기본 요건을 갖추었는지 확인하세요.
java --version
./mvnw --version
또는 Windows에서는 다음 스크립트를 실행합니다.
java -version
mvnw.cmd --version
Google Cloud 프로젝트 설정
Classroom API에 대한 액세스 및 필수 인증 방법은 Google Cloud 프로젝트에서 제어합니다. 다음 안내에서는 부가기능과 함께 사용할 새 프로젝트를 만들고 구성하는 최소 단계를 안내합니다.
프로젝트 만들기
프로젝트 만들기 페이지로 이동하여 새 Google Cloud 프로젝트를 만듭니다. 새 프로젝트의 이름을 지정할 수 있습니다. 만들기를 클릭합니다.
새 프로젝트가 완전히 생성되는 데 몇 분 정도 걸립니다. 완료되면 프로젝트를 선택해야 합니다. 화면 상단의 프로젝트 선택기 드롭다운 메뉴에서 프로젝트를 선택하거나 오른쪽 상단의 알림 메뉴에서 프로젝트 선택을 클릭할 수 있습니다.
GWM SDK를 Google Cloud 프로젝트에 연결하기
API 라이브러리 브라우저로 이동합니다. Google Workspace Marketplace SDK
를 검색합니다. 결과 목록에 SDK가 표시됩니다.
Google Workspace Marketplace SDK 카드를 선택한 다음 사용 설정을 클릭합니다.
GWM SDK 구성하기
GWM에서는 사용자와 관리자가 부가기능을 설치할 수 있는 목록을 제공합니다. 계속하려면 OAuth 동의 화면과 GWM SDK의 앱 구성과 스토어 등록정보를 구성하세요.
OAuth 동의 화면
사용자가 앱을 처음 승인할 때 OAuth 동의 화면이 표시됩니다. 사용 설정한 범위에 따라 앱에서 개인 정보 및 계정 정보에 액세스하도록 허용하라는 메시지가 사용자에게 표시됩니다.
OAuth 동의 화면 만들기 페이지로 이동합니다. 다음 정보를 입력합니다.
- 사용자 유형을 외부로 설정합니다. 만들기를 클릭합니다.
- 다음 페이지에서 필요한 앱 세부정보와 연락처 정보를 입력합니다. 승인된 도메인에서 앱을 호스팅하는 도메인을 제공합니다. 저장하고 계속하기를 클릭합니다.
웹 앱에 필요한 OAuth 범위를 추가합니다. 범위와 그 목적에 관한 자세한 설명은 OAuth 구성 가이드를 참고하세요.
Google에서
login_hint
쿼리 매개변수를 전송하려면 다음 범위 중 하나 이상을 요청해야 합니다. 이 동작에 대한 자세한 설명은 OAuth 구성 가이드를 참조하세요.https://www.googleapis.com/auth/userinfo.email
(이미 포함됨)https://www.googleapis.com/auth/userinfo.profile
(이미 포함됨)
다음 범위는 클래스룸 부가기능에만 적용됩니다.
https://www.googleapis.com/auth/classroom.addons.teacher
https://www.googleapis.com/auth/classroom.addons.student
또한 앱에서 최종 사용자에게 요구하는 다른 모든 Google API 범위를 포함합니다.
저장 후 계속을 클릭합니다.
테스트 사용자 페이지에 테스트 계정의 이메일 주소를 나열합니다. 저장하고 계속하기를 클릭합니다.
설정이 올바른지 확인한 다음 대시보드로 돌아갑니다.
앱 구성
GWM SDK의 앱 구성 페이지로 이동합니다. 다음 정보를 입력합니다.
앱 공개 상태를
Private
로 설정합니다. 이 설정은 테스트 및 개발 목적으로 적합하며 이 둘러보기에 적합합니다. 일반 대중이 부가기능을 사용할 준비가 된 경우에만Public
를 선택하세요.설치를 도메인 관리자로 제한하려면 Installation Settings를
Admin Only install
로 설정합니다.앱 통합에서 클래스룸 부가기능을 선택합니다. 보안 연결 설정 URI를 입력하라는 메시지가 표시됩니다. 이 URL은 사용자가 부가기능을 열 때 로드될 것으로 예상되는 URL입니다. 이 둘러보기에서는
https://<your domain>/addon-discovery
여야 합니다.허용된 연결 URI 프리픽스는
courses.*.addOnAttachments.create
및courses.*.addOnAttachments.patch
메서드를 사용하여AddOnAttachment
에 설정된 URI를 검증하는 데 사용됩니다. 유효성 검사는 리터럴 문자열 프리픽스 일치 항목이며 현재 와일드카드 사용을 허용하지 않습니다. 지금은 비워 둘 수 있습니다.이전 단계의 OAuth 동의 화면에 표시된 것과 동일한 OAuth 범위를 추가합니다.
개발자 링크에서 조직에 맞게 필드를 작성합니다.
스토어 등록정보
GWM SDK의 스토어 등록정보 페이지로 이동합니다. 다음 정보를 입력합니다.
- 앱 세부정보에서 언어를 추가하거나 이미 나열된 언어 옆의 드롭다운을 펼칩니다. 부가기능의 GWM 스토어 등록정보 페이지에 표시됩니다. 완료를 클릭하여 저장합니다.
- 부가기능의 카테고리를 선택합니다.
- 그래픽 저작물에서 필수 입력란에 이미지를 제공합니다. 나중에 변경할 수 있으며 이전 단계에서 앱 공개 상태를 비공개로 설정한 경우 자리표시자일 수 있습니다.
- 지원 링크에 요청된 URL을 제공합니다. 이전 단계에서 앱 공개 상태를 비공개로 설정한 경우 이러한 URL은 자리표시자가 될 수 있습니다.
게시를 클릭하여 설정을 저장합니다. 이전 단계에서 앱 공개 상태를 비공개로 설정하면 앱을 즉시 설치할 수 있습니다. 앱 공개 상태를 공개로 설정하면 GWM팀의 검토를 위해 앱을 보낸 후 앱을 설치할 수 있게 됩니다.
부가기능 설치하기
이제 GWM SDK의 스토어 등록정보 페이지 상단에 있는 링크를 사용하여 부가기능을 설치할 수 있습니다. 페이지 상단의 앱 URL을 클릭하여 등록정보를 본 다음 설치를 선택합니다.
기본 웹 앱 빌드
두 경로가 있는 스켈레톤 웹 애플리케이션을 설정합니다. 향후 둘러보기 단계를 통해 이 애플리케이션이 확장되므로 지금은 부가기능 /addon-discovery
의 방문 페이지와 '회사 사이트'의 모의 색인 페이지 /
을 만듭니다.
다음 두 엔드포인트를 구현합니다.
/
: 환영 메시지와 현재 탭과 부가기능 iframe을 모두 닫는 버튼을 표시합니다./addon-discovery
: 환영 메시지와 함께 부가기능 iframe을 닫는 버튼과 새 탭에서 웹사이트를 여는 버튼을 표시합니다.
창이나 iframe을 만들고 닫는 버튼을 추가합니다. 이는 다음 둘러보기에서 승인을 위해 사용자를 새 탭으로 안전하게 표시하는 방법을 보여줍니다.
유틸리티 스크립트 만들기
static/scripts
디렉터리를 만듭니다. 새 파일 addon-utils.js
를 만듭니다. 다음 두 함수를 추가합니다.
/**
* Opens a given destination route in a new window. This function uses
* window.open() so as to force window.opener to retain a reference to the
* iframe from which it was called.
* @param {string} destinationURL The endpoint to open, or "/" if none is
* provided.
*/
function openWebsiteInNewTab(destinationURL = '/') {
window.open(destinationURL, '_blank');
}
/**
* Close the iframe by calling postMessage() in the host Classroom page. This
* function can be called directly when in a Classroom add-on iframe.
*
* Alternatively, it can be used to close an add-on iframe in another window.
* For example, if an add-on iframe in Window 1 opens a link in a new Window 2
* using the openWebsiteInNewTab function above, you can call
* window.opener.closeAddonIframe() from Window 2 to close the iframe in Window
* 1.
*/
function closeAddonIframe() {
window.parent.postMessage({
type: 'Classroom',
action: 'closeIframe',
}, '*');
};
경로 만들기
/addon-discovery
및 /
엔드포인트를 구현합니다.
Python
애플리케이션 디렉터리 설정하기
이 예에서는 애플리케이션 로직을 Python 모듈로 구조화합니다. 제공된 예에서 webapp
디렉터리입니다.
서버 모듈의 디렉터리(예: webapp
)를 만듭니다. static
디렉터리를 모듈 디렉터리로 이동합니다. 모듈 디렉터리에도 template
디렉터리를 만듭니다. HTML 파일은 여기에 있습니다.
서버 모듈 빌드*
모듈 디렉터리에 __init__.py
파일을 만들고 다음과 같은 가져오기 및 선언을 추가합니다.
from flask import Flask
import config
app = Flask(__name__)
app.config.from_object(config.Config)
# Load other module script files. This import statement refers to the
# 'routes.py' file described below.
from webapp import routes
그런 다음 웹 앱의 경로를 처리할 파일을 만듭니다. 제공된 예에서 webapp/routes.py
입니다. 이 파일에 두 경로를 구현합니다.
from webapp import app
import flask
@app.route("/")
def index():
return flask.render_template("index.html",
message="You've reached the index page.")
@app.route("/classroom-addon")
def classroom_addon():
return flask.render_template(
"addon-discovery.html",
message="You've reached the addon discovery page.")
두 경로 모두 각 Jinja 템플릿에 message
변수를 전달합니다. 이는 사용자가 도달한 페이지를 식별하는 데 유용합니다.
구성 만들기 및 파일 실행
애플리케이션의 루트 디렉터리에서 main.py
및 config.py
파일을 만듭니다. config.py
에서 보안 비밀 키를 구성하세요.
import os
class Config(object):
# Note: A secret key is included in the sample so that it works.
# If you use this code in your application, replace this with a truly secret
# key. See https://flask.palletsprojects.com/quickstart/#sessions.
SECRET_KEY = os.environ.get(
'SECRET_KEY') or "REPLACE ME - this value is here as a placeholder."
main.py
파일에서 모듈을 가져오고 Flask 서버를 시작합니다.
from webapp import app
if __name__ == "__main__":
# Run the application over HTTPs with a locally stored certificate and key.
# Defaults to https://localhost:5000.
app.run(
host="localhost",
ssl_context=("localhost.pem", "localhost-key.pem"),
debug=True)
Node.js
경로는 다음 줄과 함께 app.js
파일에 등록됩니다.
const websiteRouter = require('./routes/index');
const addonRouter = require('./routes/classroom-addon');
app.use('/', websiteRouter);
app.use('/addon-discovery', addonRouter);
/01-basic-app/routes/index.js
를 열고 코드를 검토합니다. 최종 사용자가 회사 웹사이트를 방문하면 이 경로에 연결됩니다. 경로는 index
Handlebars 템플릿을 사용하여 응답을 렌더링하고 템플릿에 title
및 message
변수가 포함된 데이터 객체를 전달합니다.
router.get('/', function (req, res, next) {
res.render('index', {
title: 'Education Technology',
message: 'Welcome to our website!'
});
});
두 번째 경로 /01-basic-app/routes/classroom-addon.js
를 열고 코드를 검토합니다. 최종 사용자 방문 시 부가기능이 이 경로에 연결됩니다. 이 경로는 discovery
Handlebars 템플릿과 추가로 addon.hbs
레이아웃을 사용하여 회사 웹사이트와 다르게 페이지를 렌더링합니다.
router.get('/', function (req, res, next) {
res.render('discovery', {
layout: 'addon.hbs',
title: 'Education Technology Classroom add-on',
message: `Welcome.`
});
});
Java
자바 코드 예에서는 모듈을 사용하여 순차적 둘러보기 단계를 패키징합니다. 첫 번째 둘러보기이므로 코드는 step_01_basic_app
모듈에 있습니다. 모듈을 사용하여 프로젝트를 구현하지 않아도 됩니다. 둘러보기의 각 단계를 진행하면서 단일 프로젝트로 빌드하는 것이 좋습니다.
이 프로젝트 예에서는 컨트롤러 클래스 Controller.java
를 만들어 엔드포인트를 정의합니다. 이 파일의 spring-boot-starter-web
종속 항목에서 @GetMapping
주석을 가져옵니다.
import org.springframework.web.bind.annotation.GetMapping;
클래스 정의 위에 Spring Framework 컨트롤러 주석을 포함하여 클래스의 목적을 나타냅니다.
@org.springframework.stereotype.Controller
public class Controller {
그런 다음 오류 처리를 위한 두 개의 경로와 추가 경로를 구현합니다.
/** Returns the index page that will be displayed when the add-on opens in a
* new tab.
* @param model the Model interface to pass error information that's
* displayed on the error page.
* @return the index page template if successful, or the onError method to
* handle and display the error message.
*/
@GetMapping(value = {"/"})
public String index(Model model) {
try {
return "index";
} catch (Exception e) {
return onError(e.getMessage(), model);
}
}
/** Returns the add-on discovery page that will be displayed when the iframe
* is first opened in Classroom.
* @param model the Model interface to pass error information that's
* displayed on the error page.
* @return the addon-discovery page.
*/
@GetMapping(value = {"/addon-discovery"})
public String addon_discovery(Model model) {
try {
return "addon-discovery";
} catch (Exception e) {
return onError(e.getMessage(), model);
}
}
/** Handles application errors.
* @param errorMessage message to be displayed on the error page.
* @param model the Model interface to pass error information to display on
* the error page.
* @return the error page.
*/
@GetMapping(value = {"/error"})
public String onError(String errorMessage, Model model) {
model.addAttribute("error", errorMessage);
return "error";
}
부가기능 테스트
서버를 시작합니다. 그런 다음 교사 테스트 사용자 중 하나로 Google 클래스룸에 로그인합니다. 수업 과제 탭으로 이동하여 새 과제를 만듭니다. 텍스트 영역 아래의 부가기능 버튼을 클릭한 다음 부가기능을 선택합니다. iframe이 열리고 부가기능이 GWM SDK의 앱 구성 페이지에서 지정한 첨부파일 설정 URI를 로드합니다.
수고하셨습니다 다음 단계인 Google SSO로 사용자 로그인을 진행할 준비가 되었습니다.