RAKSUL TechBlog

ラクスルグループのエンジニアが技術トピックを発信するブログです

RでSnowflakeに接続する

この記事はRAKSUL Advent Calendar 2022の17日目の記事です。

こんにちは、ノバセル株式会社 データサイエンティストの松村です。 この記事ではRとSnowflakeに関する小ネタを紹介したいと思います。

RとSnowflake

ノバセルではDWH(データウェアハウス)としてSnowflakeを使っており、データ分析の際はSnowflake上のデータを使うことが非常に多いです。 また、自分を含めデータサイエンティスト職の人はPythonを使うことが多いですが、案件によってはRも普通に使います。 SnowflakeにはSnowsightというWeb UIがあるため、そこでSQLを書いて結果を取得、csvでダウンロードといったことができまるので、そのcsvをPythonやRで読み込めば分析はできます。 しかし、PythonやRのコード上でデータの取得まで完結すると、他のメンバーにコードを共有したり、GitHubにコードをアップした際に他の人が同じコードで同じ結果を再現することが容易になります。

Pythonの場合、Snowflakeに接続してデータを取得する専用のコネクタが存在するのですが、Rは自分が探した限りでは専用のパッケージ等がありません。そこで、この記事ではRからSnowflakeに接続しデータを取得する方法について、2通りの方法を紹介をします。

1. SQL文を書いてODBC経由で実行する

ODBCはMicrosoft社が定めた、アプリケーションからデータベースにアクセスするための仕組みです。Snowflakeはこの規格に対応しており、ODBCドライバーが提供されています。

docs.snowflake.com

このようなODBCドライバーをRから操作するものとして、odbcパッケージがあります。

ODBCドライバーや依存ライブラリのインストール

以下では、macOSなどUnix系のOSでの方法に絞って説明をします。

まず、Snowflake用のODBCドライバーをインストールします。

macOS用 ODBC ドライバーのインストールと構成 — Snowflake Documentation

そして、Rなどのプログラミング言語からODBCを操作するために必要な unixodbc をインストールします。 macOSであれば、ターミナルからbrew install unixodbcでインストールできます。

Rパッケージのインストール

次に、必要なRパッケージをインストールします。Rコンソール上で、以下のコマンドでインストールができます。

install.packages(c("odbc", "DBI"))

DBIパッケージは、ODBCとは別で、Rから何らかのデータベースに接続するとき必要なパッケージです。

Snowflakeに接続してクエリを投げる

準備が整ったので、実際にSnowflakeに接続をします。

まず、Snowflakeへの接続情報を作成します。

# Snowflakeへの接続情報を作成
conn <- DBI::dbConnect(odbc::odbc(),
                       Driver = "Snowflake",
                       Server = "<Account Name>.snowflakecomputing.com",
                       UID = "<User Name>",
                       PWD = "<Password>"
  )

この接続情報を作る時点で、以下のようにデータベース名やスキーマ名を指定することもできます。

conn_db <- DBI::dbConnect(odbc::odbc(),
                          Driver = "Snowflake",
                          Server = "<Account Name>.snowflakecomputing.com",
                          Database = "<Database Name>",
                          SCHEMA = "<Schema Name>"
                          UID = "<User Name>",
                          PWD = "<Password>"

SnowflakeでMFA(多要素認証)を利用している場合は、このコードを実行した時点で、モバイルへのプッシュ通知送信などが行われます。 作成した接続情報を使えば、DBI::dbGetQuery()関数で任意のクエリに対して結果をデータフレームの形で取得することができます。

# SQL文を書いてデータを取得
query <- "
select
  column1, column2
from
  tbl_name
where
  some conditions
"
df <- DBI::dbGetQuery(conn_db, query)

データ取得や分析が終わったら、作成した接続情報は解除しておくと安全です。

# Snowflake接続解除
DBI::dbDisconnect(conn)
DBI::dbDisconnect(conn_db)

2. dbplyrパッケージでデータを操作する

Rユーザーであれば、SQLを書くよりもtidyverse(特にdplyrパッケージによう列選択や行の絞り込み、集計処理など)を使ってデータ操作をしたいと思う方もいるかも知れません。

kazutan.github.io

dbplyrパッケージ(パッケージ名にbがついてることに注意)はデータベース上のデータに対してSQLを書かずにdplyrの文法でデータ操作が行える機能を提供しています。 この場合もデータベースへは接続するので、接続情報を作るのは同じです。

library(dbplyr)
library(magrittr) # パイプ演算子のため

# Snowflakeへの接続情報を作成
conn_db <- DBI::dbConnect(odbc::odbc(),
                          Driver = "Snowflake",
                          Server = "<Account Name>.snowflakecomputing.com",
                          Database = "<Database Name>",
                          SCHEMA = "<Schema Name>"
                          UID = "<User Name>",
                          PWD = "<Password>"

# Rオブジェクト上にテーブルへの接続を作る
source_table <- dplyr::tbl(conn_db, "<tbl_name>")

# dplyr の文法でデータを取得
garapon_genres13 <- source_table %>%
  # 列の選択
  dplyr::select(column1,
                column2) %>%
  # 条件に依る行の絞り込み
  dplyr::filter(some condition) %>%
  # データベースから結果の出力
  dplyr::collect()

このように、Rユーザーであれば慣れ親しんだ文法でSnowflake上のデータを取得することができます。

おまけ: ユーザー名やパスワードをコードに残したくない

さて、Snowflakeへの接続やデータ操作ができることは分かったのですが、どのパッケージを使うにしてもユーザー名やパスワードを使って接続情報を作る必要がありました。 ユーザー名やパスワードなどの認証情報、特にパスワードは他の人に知られるてはならず、GitHubなどのホスティングサービス上には決して置いてはいけないものです。 Rでコーディングするとき、このような場面で、コード上に認証情報を直接書かなくても良くなる方法を2つ紹介します。

rstudioapiパッケージでインタラクティブに入力

1つ目はIDE(統合開発環境)としてRStudioを用いている場合に限定されますが、インタラクティブに認証情報を入力するものです。先程のSnowflakeへの認証情報を作成する部分で、認証情報に当たる部分を以下のように書き換えます。

conn <- DBI::dbConnect(odbc::odbc(),
                       Driver = "Snowflake",
                       Server = "<Account Name>.snowflakecomputing.com",
                       # ユーザー名、パスワードはインタラクティブに入力
                       UID = rstudioapi::askForPassword("Database user"),
                       PWD = rstudioapi::askForPassword("Database password")
  )

このコードを実行すると、以下のようなポップアップが出現し、ユーザー名を入力することができます(ユーザー名の入力が終わるとパスワードの入力ポップアップが開きます)。

keyringパッケージを使う

もう一つ、keyringパッケージを使う方法があります。これは、macOSならキーチェーン、WindowsならCredential StoreといったOS側の仕組みを使って認証情報を管理する方法を提供するパッケージです。 こちらは、コード上に認証情報を書かなくても良いですが、実行環境のOSに依存してしまうため、他の人とコードを共有する目的のときは使いづらいかもしれません。そのため、参考記事の紹介に留めます。バックエンドとしてOSのkeyringだけではなく.envファイルを使った環境変数の読み込みにも対応しているので、個人での開発の際は使ってみると良いかもしれません。

qiita.com

おわりに

本記事では、RからSnowflakeに接続してデータを取得する方法や、コード上に認証情報を残さない工夫について書きました。R×Snowflakeのユーザーはあまり多くないかもしれませんが、そんな方々への参考になれば幸いです。

PMとベトナムチームの開発体制のご紹介!

はじめに

こんにちは!ラクスルの印刷事業部でPMをしています。
ラクスルアドベントカレンダー16日目を担当します。

本題に入る前に、まずは自己紹介です。
私はラクスルが2社目で、前職はERPシステムを提供する企業でエンジニアをしており、要件定義・実装・保守運用などに携わっておりました。
ラクスルに入社したタイミングで、エンジニアからPMと職種が変わり、最初はチラシや名刺など主に紙の印刷物を取り扱っているプロダクトのPMとして前任者に伴走していただきながら1人前のPMになるべく業務をしておりました。
その後はトートバッグやタオルなど紙以外のモノを取り扱うラクスルノベルティ、次に作業着やコックコートなど企業の方が業務で使用する衣類を取り扱うアパレル・ユニフォームに携わってきました。

ラクスルの印刷事業部はフェーズが異なる事業が複数存在する点が非常に魅力的だと思っております。

ラクスル価値創造レポート2022 P.20


そんなラクスルで働くPM業務の一部をノベルティ事業部を事例としてお伝えしたいと思います。

 

ラクスルノベルティのご紹介

まずはラクスルノベルティの説明を簡単にさせてください。
ラクスルはチラシや名刺など紙の印刷物をメインに取り扱っていましたが、以下の考えにもとづき事業拡張をしております。

ラクスル価値創造レポート2022 P.25

ラクスルノベルティは上記の図の中で左側に位置しており、2019年にリリースをしました。
リリース以来順調に成長を続け、今ではたくさんのお客様がトートバッグやタオル、ボールペンなどモノの印刷物を求めてくださいます。
そんなラクスルノベルティ事業のプロダクトはベトナムのエンジニアが開発をしています。
2020年にベトナム法人を設立し、ワンチームで開発をしています。
リリース当初は日本人エンジニアも開発しておりましたが、数年前から全員ベトナム支社のエンジニアになっております。

ラクスルの印刷事業部でPM採用をする中で何度か質問があったので、ベトナムのエンジニアとの開発体制についてお伝えしようと思います。
ベトナムの開発チームと働くPMの雰囲気が伝われば幸いです。
(ラクスル全体での決まりではなく、あくまでノベルティ事業部のプロダクト開発に関わるチームの事例になります)

開発体制のご紹介

[役割分担]

プロダクトのロードマップや要件定義は主に日本側で行っており、それをこれから記載するMTGで共有しています。
共有したロードマップや要件を元にしてリリースするまではベトナムのエンジニアやPMがメインになるので、バトンタッチをするイメージです。
実装前の開発タスクへの落とし込みや実装中の進捗管理、実装後の受け入れ(= テスト)も主にベトナムのエンジニアやPMが行っています。
無事にリリースができたら渡したバトンが再び返ってくるイメージで、リリースしたプロダクトによってどんなアウトカムがうまれたのかを主に日本側で検証/測定しています。


[コミュニケーション方法]

ベトナム側に日本語を話せるPMがいるので、大枠はベトナムのPMに伝えています。
頻度はそれほど多くはないですが、プロダクトや事業の現状共有やプレゼンを英語ですることもあります。
またSlackでは仕様やリリース内容について英語でコミュニケーションを取っています。
ベトナムのエンジニア同士でのコミュニケーションはベトナム語でも行うため、開発用のSlackチャンネルでは、日本語・英語・ベトナム語と3ヶ国語でやりとりがされています。

初めはコミュニケーションのミスで、認識の齟齬が発生することもありましたが、一定フローが固まってくるとそのようなことはほぼなくなりました。
より開発工数が少なくて済む仕様や顧客価値につながる仕様の提案をしてくれるなど、技術力以外の面でも積極的に関わっています。
その他以下に記載の定期MTG以外にも、仕様の確認をしたいなどはGoogle meetでクイックに会話するなど気軽にコミュニケーションをとっています。


[MTG]

ラクスル全体では厳格な決まりはなく、ノベルティ事業部に関わるPMとエンジニアが行っている事例になります。ノベルティ事業部ではスクラム開発をしており、金曜始まりで木曜終わりの1週間スプリントにしています。

  • デイリー スクラム(Daily Scrum)では、日々の開発の進捗や開発以外のタスクについてベトナム側のPMと認識を合わせています。
  • リリース内容の共有(≒スプリント レビュー(Sprint Review))を火曜日に行っています。リリースする機能を各ステークホルダーに共有して問題がないかを確認しています。
  • プロダクト バックログ リファインメント(Product Backlog Refinement)は水曜日に行っています。ロードマップの確認、直近の開発進捗の確認、開発の優先順位の見直し、PRDの内容の共有やレビューなど開発に関する様々なコミュニケーションをとるMTGにしています。細かい仕様のやりとりについてはSlackでも行いますが、主な開発関連の話はこのMTGで行うようにしています。
  • スプリント プランニング(Sprint Planning)は木曜日にベトナム側のみで行っていて、次スプリントの開発計画を立てています。
  • スプリント レトロスペクティブ(Sprint Retrospective)はベトナム側と日本側で分けて実施していて、日本側では金曜日に主にコミュニケーションのための時間として使っています。

まとめ

この記事を通して、少しでもベトナムのエンジニアと働くPMのリアルな姿を知っていただけたら嬉しいです!
ラクスルではPMの採用をしています。より詳細を知りたいという方がいましたら、ぜひ以下のリンクからご連絡ください!

あとがき

この記事を読んでラクスルに少しでも興味を持っていただいた方に向けて(勝手に)TO DOリストを用意しました。

▼すぐにラクスルに応募したい方
・レジュメをアップデートする
応募する

▼転職を検討するタイミングで応募したい方
タレントプールに登録する
 ご希望のポジションで募集を開始する際に採用担当からご連絡いたします
・レジュメをアップデートしておく

みなさまのアクションをお待ちしています!

 

AWS CDKにおけるコンフィギュレーション管理のベストプラクティス

この記事は ラクスルの2022年アドベントカレンダー14日目の記事です。

はじめまして!ノバセル事業部 NA(Novasell Analytics)開発チーム、サーバーサイドエンジニアの浅田です。昨日の記事では、23新卒内定者インターン中のメンバーが、ラクスルグループ(ラクスル・ノバセル・ハコベル)の各サービスでどんなことをしているのかを紹介してくれました。

今日は、AWS CDKにおけるコンフィギュレーション管理のベストプラクティスに関する記事を書いていきます。よろしくお願いします!

前提

まず、前提として、CDKでAWSのインフラを構築する際には、コンストラクトに多くのプロパティを設定する必要があります。

例えば、以下の簡単な例では、account, region, vpcId, instanceTypeというプロパティを渡しているのがわかります。

import { App } from 'aws-cdk-lib';
import { InstanceClass, InstanceSize, InstanceType } from 'aws-cdk-lib/aws-ec2';
import { DbStack } from './DbStack';

const devEnv = {
  account: process.env.CDK_DEFAULT_ACCOUNT,
  region: process.env.CDK_DEFAULT_REGION,
};

const prodEnv = {
  account: process.env.CDK_DEFAULT_ACCOUNT,
  region: process.env.CDK_DEFAULT_REGION,
};

const app = new App();

// 開発環境のRDSインスタンスを作成
new DbStack(app, 'DevDb', {
    env: devEnv,
    vpcId: 'vpc-2f09a348',
    instanceType: 't3.micro',
});

// 本番環境のRDSインスタンスを作成
new DbStack(app, 'ProdDb', {
    env: prodEnv,
    vpcId: 'vpc-abcd0123',
    instanceType: 'r5.xlarge',
});

app.synth();

プロパティの数が少ないうちは、上記のように値を直書きでもいいかもしれませんが、一般的に、時間が経過するにつれて管理しなくてはいけない値は増えてくるので、別の管理アプローチが必要になります。

これらの値を定義し、時間の経過とともに維持する方法が、コンフィギュレーション管理です。

この管理手法には大きく分けて2つのやり方があります。Static Management、Dynamic Managementの2つです。以下ではそれぞれの概要を述べた上で、コンフィギュレーション管理のベストプラクティスを検討していきます。

Static Management(静的構成管理)

コンフィギュレーション管理の最も一般的な手法が、このStatic Management(静的管理)です。

この手法が優れているところは、同じ入力が与えられた場合、常に同じ出力を生成する点です。この特徴は、後述するDynamic Managementの箇所でも非常に効果を発揮します。この決定論的であるという特徴はcdkにおいて最も重要なことです。なぜならcdkが扱っているのはインフラストラクチャであり、これが予期せず変更されてしまうことは非常に危険なことだからです。

このStatic Managementにはいくつか方法があります。

一つが、先述したように値を直書きする方法です。ただし、この方法は、値が増えてきた時に管理、維持が大変になるのでやめておいた方が良いでしょう。

幸い、CDKは汎用プログラミング言語を使用しているため、この設定を管理するためにさまざまな方法を活用できます。以下では、さらに3つのアプローチを見ていきます。

1. Context Variables(コンテキスト変数)

1つ目は、コンテキスト変数を利用する方法です。

コンテキスト変数に関しては以下の記事参照。

docs.aws.amazon.com

まず、コンテキスト変数の設定ですが、いくつかやり方があります。

コマンドラインからcontext変数を設定する方法

以下のようにcdkコマンド実行時にオプションでcontext変数に値をセットする方法です。ただし、この方法は、複数の値を設定するには不向きでしょう。

cdk synth -c dev-vpc-id=vpc-4321abcd -c prod-vpc-id=vpc-9876edcb
cdk.jsonファイル内で設定

cdkプロジェクト内にデフォルトで置かれているcdk.jsonファイル内でcontext変数に値をセットするやり方もあります。これが最も一般的な方法かもしれません。

{
  "app": "npx ts-node --prefer-ts-exts src/main.ts",
  "context": {
    "dev-vpc-id": "vpc-4321abcd",
    "prod-vpc-id": "vpc-9876edcb"
  }
}



さらに、設定したコンテキスト変数は、以下のようにtryGetContextメソッドを用いて簡単に取得できます。

const devVpcId = app.node.tryGetContext('dev-vpc-id') ?? 'vpc-2f09a348';
const prodVpcId = app.node.tryGetContext('prod-vpc-id') ?? 'vpc-abcd0123';



このコンテキスト変数を利用する方法は、最もシンプルですが、うまくスケーリングしないという欠点があります。

例えば、cdk.json配下でより深い構造を表現したい場合は、次のような命名規則が必要になります。

{
  "app": "npx ts-node --prefer-ts-exts src/main.ts",
  "context": {
    "dev_vpc-id": "vpc-4321abcd",
    "dev_app_security-group": "sg-012345678'",
    "prod_vpc-id": "vpc-9876edcb",
    "prod_app_security-group": "sg-abcd01234'"
  }
}

確かに可能ではありますが、小さなタイプミスや間違いが後で整合性の問題につながることもあります。

また、全ての環境の全てのプロパティをひとつのファイルで管理しているので、時間経過につれて肥大化し、管理しにくくなってしまいます。

コンテキスト変数は少量の設定であればうまく機能しますが、多くの設定を扱うのであれば、移動したほうがよいでしょう。

2. Static Files

Static Managementのアプローチの2つ目は、静的ファイルを利用する方法です。

ここでも汎用言語を使用している恩恵に預かれます。つまり、その言語がサポートする場所であれば、データを移動したり保存したりできるということです。

先述した例では、cdk.jsonに全てのプロパティを設定していました。まずはこれらすべてを別のファイルにリファクタリングし、そしてそのファイルを読み込んで、そのプロパティをスタックに渡します。

const devProperties = require('./env/dev.json');
const prodProperties = require('./env/prod.json');

// DEV RDSインスタンスを作成する
new DbStack(app, 'DevDb', {
    env: devEnv,
    ...devProperties,
});

// prod RDSインスタンスを作成する
new DbStack(app, 'ProdDb', {
    env: prodEnv,
    ...prodProperties
});

dev.json

{
  "vpcId": "vpc-2f09a348",
  "instanceType": "t3.micro"
}

prod.json

{
  "vpcId": "vpc-abcd0123",
  "instanceType": "r5.xlarge"
}
  • 上では、特定の環境のすべての設定は、環境ごとに1つのファイルにあります。
    • すべてを1つの場所に置くことで、環境で何かを変える場所を知ることは非常に明確かつ簡単になります。
    • ただし、このアプローチにも課題があります。
      • この場合、instanceTypeは文字列「t3.micro」「r5.xlarge」で設定されています。
      • このような文字列値は、誤入力しやすく、間違って「t3, micro」を入力してしまった場合、エラーにつながります。
      • また、このようなエラーは非常に見つけにくいです。
      • 静的ファイルは、コピー/貼り付けているだけ、または間違えにくい文字列がたくさんある場合に最適だといえるでしょう。

3. Less Static-y Files

先ほど見たように、静的.jsonファイルでは、InstanceTypeクラスのようなより複雑な型を指定できません。代わりに以下のような.tsファイルの使用に変更すると、ある種の安全性を得られます。

prod.ts

import { InstanceClass, InstanceSize, InstanceType } from 'aws-cdk-lib/aws-ec2';
export const config = {
    vpcId: 'vpc-abcd0123',
    instanceType: InstanceType.of(InstanceClass.R5, InstanceSize.XLARGE),
};



ここでのもうひとつの利点は、dev.tsとprod.tsファイルがより複雑なロジックで、jsonファイルよりも複雑な型を表せることです。

たとえば、これらの値の一部を環境変数からオーバーライドしたいときには、以下のようにすることで対応できます。

prod.ts

import { InstanceClass, InstanceSize, InstanceType } from 'aws-cdk-lib/aws-ec2';
export const config = {
    vpcId: process.env.DEV_VPC ?? 'vpc-abcd0123',
    instanceType: InstanceType.of(InstanceClass.R5, InstanceSize.XLARGE),
};



ここで、注意するべきことは、コンテキスト変数や環境変数などについては、以下のように適切に検証する必要があるということです。

const vpcId = process.env.VPC_ID;
if (!vpcId || !isValidVpcId(vpcId)) {
    throw new Error("Please provide a valid VPC_ID environment variable");
}
  • もし、パイプラインの変更によりvpcIdが誤って変更された場合、スタックが失敗する可能性があるからです。
    • 先述したように、cdkのコードは常に決定論的になるように配慮することが最も重要なことです。
    • この点に関して言えばcdk.jsonなどで静的に管理するアプローチの方が優れています。
    • 基本はtsファイルで管理しつつ、コンテキスト変数や環境変数などの入力に対して適切にチェックするという手法がベストでしょう。

Dynamic Management

コードの設定を取得するためのよりダイナミックな方法もあります。設定値をサードパーティのサービスに置いて、実行時に動的に取得する方法です。

RDSインスタンスの設定がJSONファイルに保存されている例に戻りましょう。

{
  "vpcId": "vpc-2f09a348",
  "instanceType": "t3.micro"
}



JSONは、データ転送に移植性が高く、頻繁に使用される形式です。必要に応じて、このデータはローカルファイルではなくサービスから取得できます。

axios.get('https://someconfig.novasell.com/dev')
    .then(devConfig => {
        const app = new App();
        const stack = new DbStack(app, 'DevDb', results);
        app.synth();
    });
  • ここでは、シンプルなHTTPクライアントであるサードパーティのaxiosライブラリが、何らかのconfigサーバーを呼び出してconfig情報を取得し、dev DB Stackを作成します。

    • これは非常に強力な方法ですが、非常に危険な方法でもあります。
      • なぜなら、このコードが実行されるたびに、https://someconfig.novasell.com/devへの要求の結果が同じ結果を返すという保証はない、つまり決定論的ではないからです。
      • 入力が異なる場合、予期せぬタイミングでスタックが変容してしまう恐れがあります。
      • このアプローチをより決定論的にするためのステップとして、以下のようなアプローチがあります。

  • まず取得したデータをファイルに保存するように変更します。

axios.get('https://someconfig.novasell/dev')
    .then(devConfig => {
        fs.readFileSync('./env/dev.json', devConfig);
    });
  • そうすると、先述したような静的ファイルの読み込みというアプローチに帰着します。
const devProperties = require('./env/dev.json');

// Create our DEV RDS instance
new DbStack(app, 'DevDb', {
    env: devEnv,
    ...devProperties,
});
  • 上のようなアプローチをとることで、データの取得は2つの別々のステップになり、最初のステップで結果をキャッシュに書き込み、2番目のステップで使用するようになりました。
    • このように2つのステップに分けることで、予期せぬ変更が起こる可能性を減らせます。
    • なぜなら、コードを合成すると、静的な設定から再び駆動されるため、常に同じ出力になるからです。

ベストプラクティス

これまで、コンフィギュレーション管理の様々なアプローチを概観してきました。

まとめると、以下のように分類できます。

Static Management

  • contextで渡す

  • configの値をファイルに分ける(json)

  • configの値をファイルに分ける(ts)

Dynamic Management

  • サードパーティのサービスに置いて、実行時に動的に取得する



cdk.jsonに書いていく方法は、肥大化しがちです。

jsonファイルに分ける方法もありですが、例えばInstanceTypeのような複雑な型を指定するようなケースには不向きです。

実行時に動的に取得する方法は、configで制御するものが少ない場合、用意する手間と見合わないかもしれないので、動的に取得することによって得られる利益と用意する手間とを比較衡量して判断するようにしましょう。

以上をまとめると、最初はtsのファイルに分ける方法で、値が増えてきたら、実行時に動的に取得する方法に切り替えるのがいいでしょう。ただし、この方法を採用する場合は、コードが決定論的になるように、コンテキスト変数や環境変数などについては、適切に検証する必要があります。

おわりに

今回は、AWS CDKにおけるコンフィギュレーション管理の種々のアプローチを概観し、その中のベストプラクティスを検討してきました。

CDKは非常に奥が深いかつ非常に強力なツールなので、今後も継続してこの分野のインプット・アウトプットしていきます!

ラクスルの2022年アドベントカレンダーはまだまだ続きます!

ラクスルの内定者インターンって何してるの?23新卒エンジニアに聞いてみました

この記事は ラクスルの2022年アドベントカレンダー14日目の記事です。

はじめまして!ラクスル事業部 PBU(Printing Business Unit)開発チームで内定者インターンをしている23新卒の杉山です。今日の記事では、ラクスルグループ(ラクスル・ノバセル・ハコベル)の各サービスで内定者インターンをしている23新卒のメンバーにどんなことをしているのかを聞いてみました。

続きを読む

「オンラインでも社内ハッカソンを盛り上げたい!」オンライン配信の裏ワザ

こんにちは。ラクスルで技術広報を務める松本です。 今日は 『オンラインでも社内ハッカソンを盛り上げるために、ZoomとMeetを駆使して、匿名コメントを登壇画面に流しこむ』ための裏ワザをご紹介します

  • ラクスルアドベントカレンダーを運営しています。 qiita.com

-技術広報アドベントカレンダー13日目を担当しています。

Hackweekとは

ラクスルでは、年に1度「エンジニア起因でプロダクト開発を行うハッカソン”HACKWEEK”」を開催しています。コロナ禍でも、オンラインにてチームが集って開催を続けてきて、今年で5回目の開催となります。

「技術的チャレンジ・学び」「イノベーションの創出」「事業部間/エンジニア間での知見の共有」を行うことを目的として、エンジニアが開発に打ちこむわけですが・・毎年期間が限られたHackweek中にエンジニアの皆さんがプロダクトやアイディアの種を生み出すこのお祭り。たった3日間でこんなものを作ってしまうのか!と毎年驚かされる個人的にも大好きなお祭りです。

期間中の盛り上がりは、こちらをご覧ください

recruit.raksul.com

内容

以前は、対面で全員で集合して盛り上がっていたこのイベントも、2020年以来オンラインでの開催を余儀なくされています。

オンラインでもなんとか盛り上がって臨場感を出したい!という想いから運営チームであつまって与件を洗い出します。

◆実現したかったこと

  • オンラインでも盛り上がっている感をだすため、コメントやスタンプを画面に流したい
  • 匿名で気軽に参加できるコメントスクリーンを使いたい
  • オンラインでも盛り上がっている感をだすため、効果音を入れ込みたい
  • 司会(2人)が写っている間は、全画面ピン止めしたい、かつ、コメントを流したい

◆与件

  • 登壇者がたくさん(ベトナムからの参加含む全22組)いるので、ウェビナーでの開催は難しい
  • ギリギリまで登壇資料/VTRなど作成しているため、直前の変更に対応しなければならない
  • コメントスクリーンはDLしたPCで全画面共有しないと、作動しない(ぱっと教えても、うまくいかないことが多い)
  • 通訳いれるのでZoomはMUST
  • 予算はほとんどない

しかし、登壇者がたくさんいる状況でコメントを画面上に流しこむのは、なかなか難しい仕様。コメントのために、ヘルプデスクに申請して全員のPCにDLしてもらうのは・・難しそう。さてどうやったらできるのか・・とOBSやYOUTUBE、匿名をやめてSlackと併用するか・・など試行錯誤し、運営リハを重ね実現した方法がこちら。

配信詳細

①ウェビナーを使わずに、司会(2人)が写っている間は、全画面ピン止めしたいという要望を叶えるために、ZoomでMeetをモニターを全画面共有。これでコメントが流れます

②登壇者はZoomに入り、声だけでプレゼン。これによって、プレゼン中のスライドにもコメント流すことが可能になります

③どうしても自分で資料めくりたい!というメンバー向けに 別室でのプレゼン用PCをセットし別室でプレゼン

④通訳はアフリカから参加

⑤ZoomとMeet両方に入っていると、音声が片方しか聞こえない仕様になっているので携帯別のアカウントからZoomに入り、現地の音声を拾っていました。

という、かなり複雑な状態での運営となりました!イベントにトラブルはつきもの。 幾つかのトラブルはありましたが、なんとか無事に終了!!

ZoomとMeetを駆使

失敗談

ちなみに失敗した案を書き留めておくと・・・

A:PC2でモニターを使わない

コメントスクリーンの特性上、全画面共有モニターなしだと次の投影資料準備ができずスムーズな進行とはならないため×

B:Meet×Meetでの配信

  • Meetはタブ共有でしか、音声が入らない
  • コメントスクリーンは全画面共有でしか、コメントが表示されない
  • つまり、相性悪くて×

C:Zoom×Zoomでの配信

  • 1つのPCで2つのZoomには入れない。シークレットウィンドウ使って、ブラウザでZoom入ってみたけれど音声や画面切り替えがうまくいかなかった

余談

Hackweek本番当日は、筆者本人はコロナ感染療養中のため、PC2のコントロールを担っていたにも関わらず、自宅からの参加となりました。 打ち上げのお弁当食べたかったな。

また、Hackweek中に取り組んだプロダクト開発についても幾つかBlogがでているまとまっているのでぜひご覧ください!

techblog.raksul.com

techblog.raksul.com

techblog.raksul.com

きっと、もっと簡単簡単に全ての要件をかなえられるのかもしれませんが・・・ よい方法があったらこっそり教えてください!

最近リリースした、ラクスルのエンジニアサイトもみてね!

raksulinc.notion.site