vertical-alignの使い方と別の実装方法について
こんにちは、エンジニアの井戸田です。
先日 vertical-align
ではまり、検索してみると予測変換で vertical-aling 効かない
と出てくるので、結構皆さんもはまっているんだなと感じました。
なので今回は僕もはまったcssのプロパティである、 vertical-align
の値・使い方や、垂直方向の調整の別の実装方法を紹介したいと思います。
コードについて、htmlはslim、cssはscssを使用しているので注意してください。
vertical-alignの説明
vertical-align
は行内のテキスト、画像の垂直方向の揃え位置を指定するプロパティです。
vertical-align
は適用できるのが、 inline要素
と テーブルセル
です。なので divタグ
や pタグ
などの ブロック要素
に対して vertical-align
を指定してもうまくいきません。
divタグ
や pタグ
に vertical-align
を指定したい時は diplay: inline
や, display: table-cell
, diplay: inline-block
を指定し、要素自体を変更する必要があります。
値 | 説明 |
---|---|
baseline | 適当した要素のベースラインを親要素のベースラインに合わせる(初期値) |
top | 適用した要素の上端を、行ボックスの上端に合わせる |
middle | 適用した要素の中心を、親要素の中心に揃える |
bottom | 適用した要素の下端を、行ボックスの下端に合わせる |
text-top | 適用した要素の上端を、親要素の文字の上端に合わせる (テーブルセルへの指定はできない) |
text-bottom | 適用した要素の上端を、親要素の文字の下端に合わせる (テーブルセルへの指定はできない) |
super | 上付き文字 (テーブルセルへの指定はできない) |
sub | 下付き文字 (テーブルセルへの指定はできない) |
pxなどの単位 | px, emなどの単位を使用しての指定(ベースラインが揃った状態を0、正の値は上方向、負の値はした方向になる) |
- 初期値が
baseline
なのですが、画像などはbaseline
を持たないため、下端が親要素のベースラインに揃えられます。 - middleとは、フォントの場合
0.5ex
。小文字の「x」の半分高さです。
top
と text-top
、 bottom
と text-bottom
、 baseline
と text-bottom
の違いについて、勘違いしやすいので下記にまとめておきます。
top と text-topの違い
.verticalAlign.verticalAlign-top span.example | Example span.parent | parent span.child | top .verticalAlign.verticalAlign-textTop span.example | Example span.parent | parent span.child | text-top
.verticalAlign { margin: 0 0 8px 0; background-color: #f93; &-top { .child { vertical-align: top; } } &-textTop { .child { vertical-align: text-top; } } } .example { background-color: #fd7c79; font-size: 5rem; } .parent { background-color: #33cfff; font-size: 2.5rem; } .child { background-color: #24ff18; font-size: 1rem; }
上が top
で 下が text-top
になります。
text-top
は親要素の文字の上端(一番高い場所)を基準とします。なので上端を基準として配置することが可能です。
又 top
は適用した要素の上端を、行ボックスの上端に合わせるため上記のような表示になります。
bottom と text-bottomの違い
.verticalAlign.verticalAlign-bottom span.example | Example span.parent | parent span.child | bottom .verticalAlign.verticalAlign-textBottom span.example | Example span.parent | parent span.child | text-bottom
.verticalAlign { margin: 0 0 8px 0; background-color: #f93; &-bottom { .child { vertical-align: bottom; } } &-textTop { .child { vertical-align: text-bottom; } } } // 省略 以下はtopとtext-topと指定の仕方は同じです。
上が bottom
で下が text-bottom
になります。
text-bottom
は親要素の文字の下端(ディセンター文字の下端)を基準として配置することが可能です。
また bottom
は適用した要素の下端を、行ボックスの下端に合わせるため上記のような表示になります。
baseline と text-bottom
次は baseline
と bottom-text
に対してどのような違いがあるのか、説明します。
.verticalAlign.verticalAlign-baseline span.example | Example span.parent | parent span.child | baseline .verticalAlign.verticalAlign-textBottom span.example | Example span.parent | parent span.child | text-bottom
.verticalAlign { margin: 0 0 8px 0; background-color: #f93; &-baseline { .child { vertical-align: baseline; } } &-textBottom { .child { vertical-align: text-bottom; } } } // 省略 以下はtopとtext-topと指定の仕方は同じです。
上記を見てみるとどのような違いがあるのか迷うと思うのですが、親要素( .parent
)を対して line-height
を入れてみると違いが良く分かります。
.verticalAlign.verticalAlign-baseline span.example | Example span.parent | parent span.child | baseline .verticalAlign.verticalAlign-textBottom span.example | Example span.parent | parent span.child | text-bottom
.verticalAlign { margin: 0 0 8px 0; background-color: #f93; &-baseline { .child { vertical-align: baseline; } } &-textBottom { .child { vertical-align: text-bottom; } } } .example { background-color: #fd7c79; font-size: 5rem; } .parent { background-color: #33cfff; font-size: 2.5rem; line-height: 2; // ← 追加 } .child { background-color: #24ff18; font-size: 1rem; }
.parent
に対して line-height: 2;
を指定すると、 baseline
は親のフォントのベースライン(基準線)に合わせるので、ズレは生じません。ただ text-bottom
は親の要素の文字の下端に合わせるので、ズレが生じてしまいます。
上記の例の様に親の要素で line-height
(や height
などの縦幅調整をするプロパティ)を指定している時は注意が必要です。
(実際に実装する時には 初期値が baseline
なので、 vertical-aling: baseline;
の指定は必要ありません。)
ブロック要素への対応
テーブルセルとdisplay: table-cellの使い方
テーブルセルとは tableタグ
で使用する tdタグ
, thタグ
のことです。こちらの要素に対しても vertical-align
を使用すことができます。但し text-top
, text-bottom
, super
, sub
は指定することができません。
display: table-cell
での実装方法は下記の様になります。下記の例では .block
を垂直方向に中央揃えにしています。
.tableCell .block | block
.tableCell { display: table-cell; height: 100px; background-color: #f93; vertical-align: middle; }
block要素
に対して vertical-align
を使用する場合には、垂直方向の調整をしたいタグの親要素に対して display: table-cell
, vertical-align: ◯◯
を指定することで、使用することができます。
ただ表に関係ない要素に display: table-cell
を指定するのはバットな気がしますね。
display: inline-block
display: table-cell
を使用しないで display: inline-block
を使用する方法もあります。inline-block要素
とは inline要素
と block要素
を兼ね備えた要素です。下記の例では2つの inline-block要素
を垂直方向に中央揃えにしています。
.block .inlineBlock1 | inlineBlock1 .inlineBlock2 | inlineBlock2
.inlineBlock1 { display: inline-block; height: 8rem; background-color: #fd7c79; font-size: 2rem; vertical-align: middle; } .inlineBlock2 { display: inline-block; background-color: #33cfff; font-size: 2rem; vertical-align: middle; }
block要素
に対して display: inline-block
、 vertical-align: ◯◯
を指定することで、使用することができます。
inline-block要素
と inline要素
で異なるのが、 inline-block要素
の場合は横幅・縦幅が指定が可能なので、その分 inline要素
より使い易いかも知れません。
block
inline
inline-block
の違いについては、また別の機会に詳しく話したいと思います!
vertical-alingを使用しないで垂直方向を調整する方法として
- line-height
line-height
を使用して、親要素のheightに調整する。なんとなくバットな調整方法だと思います・・・。 - position
親のblock要素に対してposition: relative
、子要素に対してpostion: absolute
を指定する。
ただ垂直方向の中央揃えにしたいと思っていても、postion:absolute
は指定した要素の本来の位置からの相対位置なのでtop: 50%
という指定をしていても、その要素の上端が真ん中にきてしまうので、top: 50%
ではなく調整する必要があります。
上記2つを挙げましたが、それぞれ調整が難しいと思います。そこで僕個人がおすすめしたいのが FlexBox
を使用する方法です。
FlexBoxを使用し垂直方向を調整する
FlexBox
とは「Flexible Box Layout Module(フレキシブルボックスレイアウトモジュール)」のことで、要素をFlexコンテナというボックス内にフレキシブルで簡単に整列する方法です。
FlexBoxに対応しているブラウザは下記のようになります。
参考) Can I use... Support tables for HTML5, CSS3, etc
- IE11から正式対応。
- safariには
-webkit-
のベンダープレフィックス必要のようです。
垂直方向の調整をするために align-items
又は align-self
というプロパティを使用します。
align-items と align-self
- align-items
flexコンテナに対して指定することで、コンテナ内のすべてflexアイテム(子要素)に対して、同じ位置に調整します。 - align-self
flexアイテムに対して指定することで、個別に位置を調整します。
値 | 説明 |
---|---|
baseline | flexアイテム内の文字のベースラインを揃える。 最初のflexアイテムのbaselineに揃うようです。 |
flex-start | flexアイテムの上端を揃える( flex-direction が column や column-reverse の場合は右側を揃える) |
flex-end | flexアイテムの下端を揃える( flex-direction が column や column-reverse の場合は右側を揃える) |
center | 適用した要素の中心を、親要素の中心に揃える( flex-direction が column や column-reverse の場合は横幅の中央を揃える) |
stretch | フレックスアイテムの高さを揃える( flex-direction が column や column-reverse の場合は横幅を揃える) |
下記の例では、 align-items: center
を使用して実装してます。
.flexBox .flexItem1 | flexItem1 .flexItem2 | flexItem2 span.flexItem3 | flexItem3
.flexBox { display: flex; align-items: center; } .flexItem1 { background-color: #fd7c79; height: 200px; } .flexItem2 { background-color: #33cfff; height: 80px; } .flexItem3 { background-color: #24ff18; height: 160px; }
.flexBox
に対して display: flex
, align-items: center
を指定することで、flexコンテナ内の全てのflexアイテムが垂直方向に中央揃えになります。
このように簡単に垂直方向を調整することができるので、ブラウザの対応に気をつけなければいけませんが、 FlexBox
はとても便利です。
もし vertical-align
での調整が難しい場合には、 FlexBox
の導入をぜひ検討してみてください。弊社が運用しているmamanokoでも flex
を多用してます。
余談
株式会社Cluexではエンジニアの方を探しています!
GeocoderとGeokitを使用して、現在地周辺検索を行う機能を実装してみた
こんにちは、エンジニアの神山です。最近大豆製品ばっかり食べています。
今回はWebサービスでよく見かける、現在地周辺検索を行う機能の実装について書きました。
例えば現在地から半径2km内にあるレストランを検索したり、現在地より最寄りの駅を探したりできる機能です。
今回使用したGemは、 geocoder と geokit-rails です。
まずこの2つのGemにフォーカスして話を進めていきます。
GeocoderとGeokit
これらのGemは住所から緯度経度を割り出したり、緯度経度を用いた検索ロジックを提供しております。
具体的には以下の様な事ができます。
- 住所から緯度経度を割り出す
- 緯度経度から住所を割り出す
- IPアドレスから緯度経度を割り出す
- 指定したオブジェクトまたは緯度経度を中心に、指定した距離内や範囲(ex: 2km~5km)にある施設を検索する
- 2点間の距離を算出する
- あるオブジェクトに対して指定したオブジェクトが位置する方角を示す
- 指定したオブジェクトまたは緯度経度を中心に、長方形状に指定した範囲内ある検索する
住所から緯度経度を割り出すとは、「東京都中央区◯◯」という文字列を判別し、北緯35度、東経139度というように緯度経度に直すことです。
GeocoderとGeokitの比較
Geocoderの利点
Geocoderを使うメリットは、住所から緯度経度を割り出す機能が優秀という点です。
GeocoderはGeokitより多くのAPIを網羅しております。
GeokitはGoogle・Yahoo・Bing・FCC・MapQuest・Mapbox・OpenCageの7つに対して、 Geocoderは上のFCCを除いたものに加えて、Google Maps API for Work・Google Maps API for Work・Nominatim・Yandex・Geocoder.ca・Geocoder.us・Ovi/Nokia・Here/Nokia・ESRI・Mapzen・Pelias・Data Science Toolkit・Geocodio・SmartyStreets・OKF Geocoder・Geoportail.lu・PostcodeAnywhere Uk・LatLon.ioの25個網羅しています。
使用できるAPIの数が多いほうが、最適なものを選べるので使い勝手がいいですね。
Geokitの利点
一方、Geokitを使うメリットは、オブジェクトを絞るメソッドを使用する際メソッドチェーンが使えるという点です。
Geocoderだと可能な場合と不可能な場合があるようです。
例えば、Geokitのメソッドであるwithin
を使うとき、
prefecure_id = 1 shop_type = restaurant latitude = 33.33 longitude = 140.44 Shop.within(2, [latitude, longitude]).tap do |scoped| scoped.where!(prefecure_id: prefecure_id) if prefecure_id scoped.where!(shop_type: shop_type) if shop_type end
のようなことが出来ます。 例えば絞込を行う等、メソッドチェーンを使用したい場面を想定するとGeokitのほうが使い勝手が良いですね。
上記の理由により今回は、
- Geocoder: 緯度経度の割り出しを行う
- Geokit: 現在地周辺検索を行う
の様な使い分けをしました。
ちなみにgeocoder
とgeokit
の人気を比較しているサイトがあったので載せておきます。
Geocoderの使い方
住所から緯度経度を割り出すことを geocoding
といいます。
geocoding
を行いたいカラムがあるモデルに以下のように記述します。
geocoded_by :address after_validation :geocode, if: :address_changed?
geocoded_by
はgeocoding
を行いたいカラムを指定します。
address
というカラムに住所(ex: 東京都港区〇〇)が入っており、その住所を基に検索を行いたいような場面です。
after_validation
は geocoding
するタイミングを指定します。
上のように書くと、address
カラムに変更があった際に、自動でgeocoding
されるようになります。
Geokitの使い方
緯度経度を使って出来ることを、GitHubより抜粋しました。
# 指定した緯度経度から半径5km内のオブジェクトを検索 Shop.within(5, origin: [33.33, 140.33]) # 指定した緯度経度から半径5km外のオブジェクトを検索 Shop.beyond(5, origin: [33.33, 140.33]) # 指定した緯度経度から2km~5km内のオブジェクトを検索 Shop.in_range(2..5, origin: [33.33, 140.33]) # 緯度が30.33~35.55内でかつ、経度が135.55度~145.55度内にあるオブジェクトを検索 Shop.in_bound([[30.33, 135.55], [35.55, 145.55]]) # 指定した緯度経度から一番近いオブジェクトを検索 Shop.closest(origin: [33.33, 140.33])
様々な検索方法がありますね。 因みにGeocoderでも同じようなこと検索は可能です。
現在地の検索機能
では、現在地より半径2km以内にある店を検索する機能を実装していきます。 「現在地から探す」ボタンを押した時に、上記の条件で検索が行われるような実装です。
「現在地から探す」ボタン押下後の挙動としては、 Javascriptを用いて現在地の緯度経度情報を取得→Geokitのメソッドを用いて緯度経度付近にある施設を検索して、Viewに表示させる という流れになります。
Model
Shopモデルのaddress
カラムをgeocodingします。
- models/shop.rb
geocoded_by :address after_validation :geocode, if: :address_changed?
address_changed?
というメソッドはActiveRecord::Dirtyの機能です。
{column_name}_changed?で該当するカラムが変更された時に
true`を返します。
詳しくは下記を御覧ください。
Controller
Geokitのwithin
メソッドを用いることにより、現在地から2km以内の店が@placesに渡されます。
- shops_controller
def search latitude = params[:latitude] longitude = params[:longitude] @places = Shop.all.within(2, origin: [latitude, longitude]) end
View
- shops/index
「現在地から探す」ボタン部分になります。
.currentLocation = button_tag ‘現在地から探す’, type: ‘button’
Javascript
現在地の取得には、HTML5のGeolocation API
を使用します。
以下の様なコードになります。
class @CurrentLocations @getCurrentLocation: -> $('.currentLocation').on 'click', -> if navigator.geolocation navigator.geolocation.getCurrentPosition(successGetPosition, failGetPosition, options) else message = 'ご使用中のブラウザは現在地検索に対応されておりません。' Alert.set('warning', message) successGetPosition = (position) -> window.location.href = "/shops/searches?latitude=#{position.coords.latitude}&longitude=#{position.coords.longitude}" options = enableHighAccuracy: true failGetPosition = (error) -> switch error.code when 1 message = '位置情報の提供を許可してください。' when 2 message = '位置情報の取得に失敗しました。' Alert.set('warning', message)
では上から見ていきます。
@getCurrentLocation: -> $('.currentLocation').on 'click', -> if navigator.geolocation navigator.geolocation.getCurrentPosition(successGetPosition, failGetPosition, options) else message = 'ご使用中のブラウザは現在地検索に対応されておりません。' Alert.set('warning', message)
@getCurrentLocation
が現在地を取得する関数です。
navigator
はブラウザの情報を取得するオブジェクトです。
そして.geolocation
でブラウザが Geolocation API
に対応しているか調べています。
対応していないブラウザもあるので注意して下さい。(IE8.0など)
ブラウザが Geolocation API
に対応している時、 geoCurrentPosition
で現在地の取得を試みます。
geoCurrentPosition
の第一引数は現在地の取得に成功した時に実行され、第二引数は失敗した時に実行されます。
第三引数は現在地の取得の際のオプション設定をしております。
ちなみにブラウザが Geolocation API
に対応していてもユーザーが位置情報の提供を許可していない状況も考えられます。
そのような場合、 geoCurrentPosition
が呼ばれると自動で許可するか否かのポップアップが出るようになっております。これまた便利ですね。
ブラウザが Geolocation API
に未対応である場合は、 else
の部分が実行されます。
ここでは「対応していません」というアラートを出すようにしています。
successGetPosition = (position) -> window.location.href = "/places/searches?latitude=#{position.coords.latitude}&longitude=#{position.coords.longitude}"
successGetPosition
は現在地の取得に成功した時の関数です。
position
オブジェクトに現在地の情報が入っており、position.coords
で様々な情報を取り出せます。
例えば、 position.coords.latitude
で緯度を取得できたり、 position.coords.logitude
で経度を取得できます。
そして現在地の取得に成功した時に、現在地周辺の店の一覧ページに移動します。 またControllerに緯度経度の値を渡しております。
options = enableHighAccuracy: true
options
はその名のとおり、現在地取得の際のオプション設定です。
enableHighAccuracy
はGPSなどを使った高精度な現在地の取得を可能にします。
他にもタイムアウト設定やキャッシュの設定なども可能です。
failGetPosition = (error) -> switch error.code when 1 message = '位置情報の提供を許可してください。' when 2 message = '位置情報の取得に失敗しました。' Alert.set('warning', message)
failGetPosition
は現在地の取得に失敗した時に実行される関数です。
error
というオブジェクトに失敗の原因が入っております。
今回は、エラーの原因ごとに別々のアラートを出したいので、 error.code
ごとに条件分岐をしております。
error.code = 1
はユーザーが位置情報の許可をしていない時を指しております。
error.code = 2
は現在地の取得に失敗した時を指しております。
Geolocation API
の詳しい情報は以下のリンク先にも書かれているので参考にしてみてください。
以上が現在地周辺の施設を検索する機能の解説でした。 非常に便利なGemですね。
改良点等アドバイスいただけたら大変幸いです。
参考
今のうちに見直しておきたいnginx設定集 【セキュリティ編】
こんにちは、Cluexの高橋です。
先日EC2サーバーのOSを新しいものにしまして、その時にサーバーのテストを簡単に行ってくれるQualys SSL Labsで移行前のサーバーをテストしてみたところ、C判定が出てしまったので、nginxの設定も全体的に見直してみました。
イメージはこんな感じです
テストしたのはこちら「Qualys SSL Labs」 www.ssllabs.com
ということで今回はnginxの設定に関してセキュリティ関連でやっておくべき設定集をまとめました。
nginxのバージョン情報を隠す
nginxのバーション情報を隠蔽します。
server { # ~~ server_tokens off; # ~~ }
SSL通信に使用するプロトコルを指定する
SSLv2やSSLv3はダウングレード攻撃やPOODLEなどへの脆弱性があるのでTLSのみ許可します。
server { # ~~ ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # ~~ }
暗号化スイートの設定
SSLの暗号化にする暗号化スイートを明示的に指定し、クライアントサイドで指定した暗号化をしないようにすることで、通信をよりセキュアにすることができます。 ちなみにssl_ciphersの設定方法としては、「:」をデリミタとして使用し、「!」をプレフィックスでつけることで除外対象となります。
詳細な暗号化スイートの設定内容はこちらのサイトを参考にさせていただきました。
Strong SSL Security on nginx - Raymii.org
おすすめの設定がこちら。
server { # ~~ ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH'; # ~~ }
IE6/WinXP などにも対応したいと言う方にはこちらの設定がおすすめとのことですが、SSL3.0などを使用できない設定にしているので今回は特にIE6を気にする必要はないかと思います。
server { # ~~ ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:ECDHE-RSA-AES128-GCM-SHA256:AES256+EECDH:DHE-RSA-AES128-GCM-SHA256:AES256+EDH:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4"; # ~~ }
サーバーの暗号化設定の優先
先ほどのサーバー側で指定した暗号化スイートを優先して使用するようにします。
server { # ~~ ssl_prefer_server_ciphers on; # ~~ }
Http Strinct Transport Security(HSTS)ヘッダの追加
サーバーからStrict Transport Securityヘッダを返すことで常にHTTPSで通信を行うようにし、中間者攻撃を防ぎます。これを使用するには Nginxのngx_http_headers_moduleが必要になります。
add_header Strict-Transport-Security 'max-age=31536000; includeSubDomains;';
ちなみにpreloadオプションを使用したい場合は、こちらでドメインを登録しておくと宜しいかと思います。
こちらに登録するには下記の要件を満たす必要があります。
Submission Requirements
If a site sends the preload directive in an HSTS header, it is considered be requesting inclusion in the preload list and may be submitted via the form on this site.
In order to be accepted to the HSTS preload list through this form, your site must satisfy the following set of requirements:
Serve a valid certificate.
Redirect from HTTP to HTTPS on the same host.
Serve all subdomains over HTTPS.
・In particular, you must support HTTPS for the www subdomain if a DNS record for that subdomain exists.
- Serve an HSTS header on the base domain for HTTPS requests:
・The max-age must be at least eighteen weeks (10886400 seconds).
・The includeSubDomains directive must be specified.
・The preload directive must be specified.
If you are serving an additional redirect from your HTTPS site, that redirect must still have the HSTS header (rather than the page it redirects to).
preloadを指定する場合はこんな感じです。
add_header Strict-Transport-Security 'max-age=31536000; includeSubDomains;preload';
DH鍵交換時のKeyの強化
TLSプロトコルで採用されているDiffie-Hellman鍵交換は512bitもしくは1024bit以下のDHパラメータにおいてLogjam攻撃を受ける可能性があり、これを防ぐにはDHパラメータに2048bitのものを使用することが望ましいとされています。
Diffie-Hellman鍵交換による暗号化時にnginxのデフォルトでは1024ビットの鍵を使用しますが、Google ChromeやMozilla Firefoxなどの主要なブラウザでは「最低でも」1024ビット以上のものを使用するよう推奨しており、できれば2048bitのものを独自生成して使用するのが好ましいかと思います。
一般的なwebサイトでは2048bitもしくは4096bitでpemを作っておくといいようです。
まずはpemファイルの作成
$ cd /etc/ssl/certs $ openssl dhparam -out dhparam.pem 4096
こちらがnginxのconfファイルに追加する内容。
server { # ~~ ssl_dhparam /etc/ssl/certs/dhparam.pem; # ~~ }
OCSPステープリング(OCSP Stapling)の設定
OCSP(Online Certificate Status Protocol)はSSL/TLS通信の時に証明書が失効していないかを確認するために使用されています。 通常はSSL通信を行う際はクライアント側がこのOSCPを使用してサーバー証明書の正当性を確認する必要がありますが、サーバー側で事前にこの処理を行うことでクライアント側で行う必要がなくなるのでHTTPS通信の開始を高速化できます。
具体的にはOCSPステープリングによってクライアント側ではなくサーバー側でOCSPによるサーバー署名書の確認を行い、その結果をクライアントへのレスポンスと一緒に送るようにすることで、これを実現しています。
ssl_stapling on; ssl_stapling_verify on; ssl_trusted_certificate /etc/nginx/cert/trustchain.crt; resolver 8.8.8.8 8.8.4.4 valid=300s
ssl_staplingを使用するにはDNSリゾルバを resolverディレクティブにて指定する必要があります。googleのパブリックDNSサーバーが使用されることが多いようです。
X-Frame-Options
レスポンスヘッダにX-Frame-Optionsを設定することでブラウザがiframeなどの内部に自身のサイトを表示を許可するかを設定できます。DENYもしくはSAMEORIGINを指定することで自分のサイトのコンテンツが他のサイトに埋め込まれないように設定でき、クリックジャッキング攻撃を防ぐことができます。
add_header X-Frame-Options SAMEORIGIN;
X-XSS-Protection
XSSに対するフィルタ機能を有効化
add_header X-XSS-Protection "1; mode=block";
X-Content-Type-Options
Content-Typeに一致しない処理は行わないようにさせることでXSSなどを防ぎます。
add_header X-Content-Type-Options nosniff;
これが設定されていない場合、例えば Content-type="text/plain"
のファイルでも、その中にjavascriptのソースがあるとブラウザによって実行される可能性があります。
再度テストした結果は・・・
当時の設定では上記の幾つかはまだ設定していないものもあるのでA+の評価をとることができなかったので、今回あげたものも含めてさらにサーバー周りを強化していきたいなと思います。
ちなみにMozilla Foundationが公開しているwebサーバーのConfig Generatorがあるので、そちらで基本的な設定を確認できるので、気になる方はお使いになってみるいいかと思います。
Generate Mozilla Security Recommended Web Server Configuration Files
余談)Cluexではエンジニアの方を探しています!
See more at cluex.co.jp
assets on S3の導入
こんにちは。エンジニアの志村です。 最近暑くて参りますね…。アイスばっかり食べてます。
さて今回ですが、Assets on S3を導入しましたのでその際のメモです。
結構この形でassetsを配信しているサービスは多いですよね。
今回は、Cloudfront+S3 / asset_sync+capistranoという定番のパターンで実装しております。
assets on S3とは
デプロイ時にassetsファイルをS3に配置し、CDN経由で配信する方法です。
通常であればnginxやApache等のWebサーバーを介して静的ファイルは配信されています。
assets on S3はassetsファイルをS3に配置し、CloudfrontやAkamai等のCDN経由で配信します。
Webサーバー負担軽減やCDNを噛ませることによる高速化を目的として用いられることが多いかと思います。
仕組み
下記のような流れになります。
- デプロイ時に
rake assets:precompile
を走らせる。その際にasset_syncを使用し、S3にassetsファイルをアップロードする。 - manifestファイルをEC2にアップロードする。
rake assets:precompile
時に作成されるassetファイルを削除する(public/assetsに格納されている)
こんな感じでしょうか。 他にもCloudfrontやS3の設定があるので、下記に記していきます。
Rails側の設定
ではまずasset_syncを導入し、bundle install
をします。
asset_syncの導入
gem 'asset_sync'
次にasset_syncのconfigファイルを生成します。
$ rails g asset_sync:install --provider=AWS
今回はAWSを使用するのでproviderオプションにはAWSを設定します。
そうするとasset_sync.rb
という設定ファイルが生成されます。
- config/initializers/asset_sync.rb
AssetSync.configure do |config| # fogを使用するサービス config.fog_provider = 'AWS' # S3の存在するリージョン config.fog_region = 'ap-northeast-1' # S3のバケット名 config.fog_directory = 'assets' # IAMのアクセスキー config.aws_access_key_id = 'xxxx' # IAMのシークレットアクセスキー config.aws_secret_access_key = 'xxxx' # 既にS3上に存在しているファイルの扱い keep, delete, ignoreから選択 config.existing_remote_files = 'keep' # gzip圧縮をするかどうか config.gzip_compression = true end if defined?(AssetSync)
上記で使用してるIAMに関しては、次の章のS3の部分で説明します。 これでasset_sync自体の設定は完了しました!
assetsのURLをCloudfrontにする
assetsファイルはCloudfrontより配信されます。
通常の設定では、http://domain/assets/
配下のファイルが配信されますが、これをhttps://Cloudfrontのエンドポイント/assets
に変更し、Cloudfrontから配信するように設定します。
- config/environments/production.rb
〜中略〜 # Enable serving of images, stylesheets, and JavaScripts from an asset server. config.action_controller.asset_host = '//xxxxx.cloudfront.net' 〜中略〜
これでassetsファイルがCloudfrontより配信されるようになりました!
次はcapistranoの設定を行います
capistranoの設定
流れとして、
cap 〜 deploy
コマンドを叩いた時に、ローカルにてrake assets:precompile
を走らせる(asset_syncが自動的にS3にアップロードしてくれる)- manifestファイルをサーバの
public/assets
ディレクトリに転送する - ローカルで生成されたpublic/assetsディレクトリを消去する
この中で特に大切なのは2.かと思います。
railsは、productionにデプロイされる際にprecompileを行います。
その際にdigestを付与してファイル名-digest.scss
のようなファイル名に変更します。
このdigestはprecompile時にランダムに設定されるのでrails側で管理が必要になります。
そのファイル名を管理するのがmanifestファイルです。これが存在しないと、railsはassetのパスを正しく指定出来ません。
ではcapistranoの設定に移っていきます。 こちらのコードを参考にさせて頂きました。
- config/deploy.rb
〜中略〜 namespace :deploy do # rake db:assets:precompileを実行する task :asset_sync do run_locally do Bundler.with_clean_env do execute :rake, 'assets:precompile' end end end # manifestファイルをアップロードする task :upload_manifest do on roles(:app) do |host| if test "[ ! -d #{release_path}/public/assets ]" execute "mkdir -p #{release_path}/public/assets" end file_path = Dir::glob('public/assets/.sprockets-manifest*').first upload!(file_path, "#{release_path}/public/assets") end end # ローカルに残されたprecompile後のassetsファイルを削除する task :assets_cleanup do run_locally do Bundler.with_clean_env do execute :rake, 'assets:clobber' end end end task :restart do invoke 'unicorn:restart' end end before 'deploy:starting', 'deploy:asset_sync' after 'deploy:publishing', 'deploy:upload_manifest' after 'deploy:publishing', 'deploy:assets_cleanup' after 'deploy:publishing', 'deploy:restart' 〜中略〜
上記のようになります。
rakeタスクに関しては新しくファイルに切り分けても良いかと思いますが、そんなにデプロイスクリプトが多いわけでも無かったので僕はそのままdeploy.rbに書いてしまっています。
release_path
の部分はそれぞれの環境に合わせたpathを指定すればOKです。
developmentではsprocketsを使用しているのでそれをそのままuploadしております。
AWS側の設定
S3の設定
S3はバケットを作成し、CORSの設定を行います。 CORSの設定をしないと、Font Awesomeが正しく表示されません。 詳しくは
を御覧ください。
AWSコンソールの「S3」を選択
「バケットの作成」を選択
バケット名、リージョンを設定
作成したバケットを選択し、「プロパティ」→「アクセス許可」→「CORS設定の編集」を選択
ここに下記のコードを貼り付け、「保存」をします 下記のコードを使用させて頂きました。
<?xml version="1.0" encoding="UTF-8"?> <CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/"> <CORSRule> <AllowedOrigin>*</AllowedOrigin> <AllowedMethod>GET</AllowedMethod> <MaxAgeSeconds>3000</MaxAgeSeconds> <AllowedHeader>Authorization</AllowedHeader> </CORSRule> </CORSConfiguration>
Cloudfrontの設定
基本設定
assets用のディストリビューションを作成します。
AWSコンソールの「Cloudfront」を選択
「Web」を選択
Origin Settingsを入力する
項目 | 設定 | 説明 |
---|---|---|
Origin Domain Name | 先ほど作成したS3バケット名 | オブジェクトの取得先 |
Origin Path | 空のまま | S3のルートディレクトリの設定 |
Origin-ID | 分かりやすい名前 | オリジンを区別する一意のID |
Restrict Bucket Access | Yes | CloudfrontのURLからのみS3のオブジェクトにアクセス出来る |
Comment | 分かりやすい名前 | identityを区別するIDのようなもの |
Grant Read Permissions on Bucket | Yes | バケット内のオブジェクトの読み取り許可 |
Origin Custom Headers | 空のまま | リクエストをオリジンに転送する際にカスタムヘッダーを含めるかどうか |
※ Default Cache Behavior Settings, Distribution Settingsに関しては環境に応じて入力して下さい。今回は特にいじらずに行きます。
「Create Distributions」を選択するとCloudfrontのDistributionが作成されます。
Behaviorの設定
さて、Behaviorの設定を行っていきましょう。
Behaviorは振り分けのルールです。
例えば、
https://xxxx.cloudfront.net/assets
にリクエストが来た場合にはassetsバケットに転送https://xxxx.cloudfront.net/images
にリクエストが来た場合にはimagesバケットに転送
のようなことが可能になります。
「Behavior」タブの「Create Behavior」を選択
Settingsを入力
項目 | 設定 | 説明 |
---|---|---|
Path Pattern | /assets/* | 振り分けパターン。今回は/assets配下のオブジェクト全てをS3から配信したいので/assets/*とする |
Origin | 先ほど設定したOrigin-ID | どのオリジンからオブジェクトを取得するかを選択 |
Viewer Protocol Policy | 環境によって選択 | アクセスする際のプロトコルの選択 |
Allowed HTTP Methods | GET, HEAD | オリジンに転送するHTTPメソッド。今回は取得のみなのでGET, HEADを選択 |
Forward Headers | Whitelist -> Origin | どのヘッダを転送するか 今回CORSの設定を行っているので、OriginをAddする |
Grant Read Permissions on Bucket | Yes | バケット内のオブジェクトの読み取り許可 |
Object Caching | Use Origin Cache Headers | MaximumTTL等を変更しないのであればUse Origin Cache Headersのままで良い |
「Create」を選択すると、このBehaviorが有効になります。
設定の反映までは10分〜20分ぐらいかかるので気長に待ちましょう!
以上です。 asset_syncのおかげでそこまで多くの手順を踏むこと無く、assets on S3の導入が出来ました。 次回はLambdaを使用してInvalidationを走らせる処理について書きたいと思います。
インターン生の村田です!
はじめまして、慶應義塾大学2(3)年の村田正之です。
2016年4月から株式会社Cluexでエンジニアとしてインターンをしております。 よろしくお願いします。あと、上のカッコはあまり気にしないでください。
株式会社Cluexで働く前
Cluexにジョインするまでは所属していた学生団体の活動に多くの時間を割いていました。大学と深い関係もありその歴史は10年以上という、学生団体としては比較的しっかりとした方だったと思います。そこではビジネスコンテストの運営、もう少し堅い言葉を使ってしまうとインキュベーション活動をしておりまして、最終的にはその代の副代表も務めておりました。
当時はあまり意識していなかったですが、その学生団体では本当にたくさんのことを勉強させていただきました。 リーンスタートアップやデザイン思考といったアイデアやビジネスの創造においての基本的な概念を学ぶことができましたし、僅かではありますが、マネジメントや組織の形成の仕方、ファシリテーションと言った汎用的な能力も身につけることができました。 ファシリテーションなどの能力はエンジニアと無縁に見えることもあるかもしれませんが、チームで開発をしていく上では非常に大切な能力の一つであり、現在でも活かされている場面が多いと思います。 そのようなことを学ばせていただけたという意味で、現在でもその学生団体には感謝を忘れることはできません。 しかし活動期間がありましたので、活動終了後は特別に打ち込むものもなく普通の学生生活を送っていました。
株式会社Cluexのインターンに応募したきっかけ
その学生団体のビジネスコンテストを運営していく中で、ものづくりができる人の強さを目の当たりにしてきました。 特に能力の高いエンジニアを抱えているチームはアイデアにとどまらず素早く行動に移すことができるため、短期間でピボットを繰り返していることがとても衝撃的でした。
実はそのあたりから密かに、「エンジニアってかっこいいなあ」という憧れを抱き始めました。
そこで密かにプログラミングの本を購入して独学で勉強を始めました。 ただ、自分はエンジニアのコミュニティに属していなかったので、チャレンジしても誰にも相談できないまま解決できないということが何度か続き、結局挫折してしまいました。 そうしている中で、「もしプログラミングを学ぶなら優秀なエンジニアがいてスピード感のある環境に身を置きたい」と思いインターンを探していたところCluexというスタートアップを発見して応募しました。
当時は初心者でも受け入れてくれたので面接の応募をしたのですが、面接に行った際にサービスとプログラミングが大好きな人たちが働いている様子を見て、「ここでエンジニアとして働きたい!!」と感化されてしまいました。
いまやっていることと将来やりたいこと
Cluexでは2つのチームに分かれて開発を進めております。 1つがWebAppTeam、もう1つがNativeAppTeam(iOS)です。 私は前者のWebAppTeamでRubyonRailsを使って開発を進めています。 インフラ周りはまだほとんど触っていませんが、フロントエンドとバックエンドについてガリガリ書いています。
休みの日は業務以外のプログラミングを楽しんでいます。 最近はRubyのメタプログラミングを勉強してるので、今週の日曜日は有名なgemの中身を読んでみようと思ってます。
今後はもっとミドルウェア周りを色々遊んでみたり、サーバーもいじっていきたいです。 あとハードにも興味があるので将来的にはソフトだけではなくて、ハード側も勉強したいと思っています。 ただ今から他の言語に浮気してもうまくいきそうにはないので、まずは我慢してじっくりRubyとRailsに慣れていこうと思います。
Cluexではエンジニアの方を募集しています!
エンジニアリングと同時にビジネスマンとして成長したい、スタートアップで働いてみたい、もうレガシーな環境で余計な苦労しをたくないといった方など、 興味がある方はご連絡下さい。 https://www.wantedly.com/projects/60136
規律あるcssを運営するにあたって
こんにちは、エンジニアの井戸田です。
弊社ではmamanokoという子育てママさんのための情報サイトを運営しており、Ruby on Railsで実装しています。 今回はmamanokoで実装されているのcssの構成についてお話ししたいと思います。 mamanokoではSMACSSというcssの設計手法や、BEMというフロントエンド設計手法を弊社なりにカスタマイズして使用しています。
フロント面の開発環境は下記のようになっております。
SCSS Slim CoffeeScript
まずは本来のSMACSS、BEMについて説明します。
SMACSS
SMACSSとは、 Scalable and Modular Architecture CSS の略で スマックス
と読みます。CSSの設計手法で1つであり、 Base(ベース)
、 Layout(レイアウト)
、 Module(モジュール)
、 State(ステート)
、 Theme(テーマ)
の5つのルールに分け、それぞれのルールや記述規約が決められているのが特徴です。
smacssで設計する目的
SMACSSを導入することによって、コードの量が減り、CSSの弱点であった下記のことが解決されます。
- 保守性を高める
- メンテナンス性を高める
- デザインを統一することで、ユーザー体験の一貫性を高める
5つのルール
Base - ベースルール
要素そのもののスタイルを定義します。 セレクタを使ってスタイルを変更する場所であるので、idやclassは使用できません。
body { background-color: #fff; color: #000; } a { &:hover { color: inherit; } }
Layout - レイアウトルール
ページのエリア分けを定義します。
header
, footer
などよく id
指定するユニークな要素がLayoutに該当すると思います。
Module
や state
との区別のため l-
というprefixをつけるのが特徴です。このようにすることで、他のルールと区別ができ、管理がしやすくなります。
.l-header { height: 48px; background-color: #fff; } .l-footer { background-color: #fff; border-top: 1px solid #000; }
Module - モジュールルール
その名前の通り再利用可能なスタイルを定義します。 ページデザインのcssを書くにあたって、ほとんどがここに定義されると思います。 どこにおいても再利用できるように独立させておきます。
またクラスの書き方は モジュール名-サブクラス
の順番で書きます。
.article p.article-title タイトル
. article { background-color: #fff; border: 1px solid #000; &-title { color: #000; } }
State - ステートルール
状態によってデザインを上書きする時に定義します。
!important
を使用してのデザインの変更は避けましょう。 !important
を使用することで醜いコードになってしまいます。
ステートルールはモジュール名を付けてあげると、クラス名で被ることはないと思います。
.is-item-active .is-item-hidden
Theme - テーマルール
テーマルールを使用する機会は少ないです。
他言語対応時、英語や中国語など言語で標準のフォントサイズでは小さい場合があるので、そのような場合にテーマルールを使用することもあります。
theme-
というprefixをつけるのが特徴です。
BEM
BEMとは Block
, Element
, Modifier
の頭文字を取ったもので、 ベム
と読みます。
コンポーネント化のためのclss命名規則です。
BEMで設計する目的
BEMを導入することによって、パーツごとにclass名を完全に独立したものとできるので、下記のことが解決されます。
- 再利用性を高める
- 拡張性を高める
- 開発の生産性とメンテナンス性を高める
BEMの規約
- Block
- 文字通りブロック(塊)。構成のルートとなる要素です。
- Element
- Blockに所属する子要素。必ずBlockの中でのみ存在し、単体では使用してはいけません。
- Modifier
- 元となるBlock又はElementから変化した状態を示すものです。
上記の元に下記の規約が定められています。
- BlockやElementで2つ以上の単語の場合はハイフン1つ(-)
- Modifierで2つ以上の単語の場合はアンダースコア1つ(_)
- BockとElementはアンダースコアを2個(__)
- Block又はElementとModifierはハイフンを2個(--)
.articles-list .articles-list__item .artiles-list__item__title | タイトル .articles-list__item--state_small ・ ・ ・
弊社のSMACSSとBEMの構成
まず弊社ではマルチクラス設計を採用しています。 マルチクラス設計とは、HTMLに複数のclassを書いて、スタイルを当てる設計のことです。 マルチクラスを採用することにより、冗長な記述が減り、保守性の向上につながります。
例) ピンクのボタン(.button-pink)と、緑(.button-green)のボタンを定義
/ good .button { padding: 12px 20px; background-color: #fd8280; border: 1px solid #fd6360; border-radius: 2px; color: #fff; &-pink { background-color: #fd8280; border: 1px solid #fd6360; } &-green { background-color: #3de933; border: 1px solid #0ce400; } } / bad .button { &-pink { padding: 12px 20px; background-color: #fd8280; border: 1px solid #fd6360; border-radius: 2px; color: #fff; } &-green { padding: 12px 20px; background-color: #3de933; border: 1px solid #0ce400; border-radius: 2px; color: #fff; } }
SMACSS
本来では5つのルールに分けるのですが、弊社では7つのルールに分けて使用しています。
smacssでは、ほとんどのスタイルが module
に定義されると思うのですが、 module
をもっと細かいルールに分けることによって、fatになってしまいがちの module
を防いでいます。
- Base
本来のSMACSSと同じで、要素そのもののスタイルを定義します。
セレクタを使ってスタイルを変更する場所であるので、idやclassは使用できません。
a { color: #000; }
- Component
component
に書くものなのですが、見出し
部分やボタン
など、どこのページでも使い回す要素をここで定義します。そのため、グローバルなクラス名を付ける必要があります。
現在のmamanokoでは見出し部分のクラス名は.heading
、ボタン部分のクラス名は.button
と付けています。
.heading { border-bottom: 1px solid #000; padding: 0 8px; margin: 0 0 10px }
- Module
moduleも使い回す要素を定義します。componentとの違いとして、グローバルなclass名をつけない要素を定義するということです。主にグローバルなクラス名ではない要素のほどんどが、ここに定義されます。
ユーザページのアバター画像及び、ユーザーネームを表示するヘッダーのcssを作成する場合
.userHeader { padding: 20px; background-color: #fff; &_image { width: 80px; height: 80px; } &_name { font-size: 80%; } }
Layout
本来のSMACSSと同じで、header
,footer
などよくid
指定するユニークな要素のものを記述し、l-
というprefixを付けて他のルールと区別するようにしています。Patch
使い回しをしない、特定のcssを定義するルールです。現在ではcontroller名ごとにファイルを分けをしており、ファイル内ではactionごとにcssを変更するようにしています。このようにすることによって、特定のページだけcssが変更することができるのを加えて、componentやmoduleのcssを打ち消すことができます。 但しpatch
を使いすぎると、醜いコードになってしまうので注意が必要です。
.users_controller { .edit_action { .heading { font-size: 80%; } } }
- Lib
mixinなどの関数や、colorコードを変数で定義するルールです。
mixinなどの関数を1ファイルにまとめておくことで、保守性を高め、メンテナンスがしやすくなると思います。 またcolorコードを変数で定義することにより、他のルールでcolorコードを設定する場合に、定義した変数を使うので、保守性、メンテナンス性を高めるのはもちろん、ユーザー体験の一貫性を高める効果があると思います。
現在mamanokoではここに定義されたcolorコードの変数を使い、色を濃くするにはscssの関数である darken
や、色を薄くするには独自に関数を作成したものを使用しています。
@mixin rounded-s { border-radius: 2px; } @mixin rounded-m { border-radius: 4px; }
$base-color: #000; $primary-color: #ff828c;
- Vendor
外部ライブラリのcssを書き換えるルールです。現在mamanokoではBootstrapを使用しているのですが、デフォルトでcssが定義されており、うちのサイトにあったデザインにするためcssを書き換えています。
BEM
本来のBEMでは上記でも書いたようなルールがあります。
- BlockやElementで2つ以上の単語の場合はハイフン1つ(-) - Modifierで2つ以上の単語の場合はアンダースコア1つ(_) - BockとElementはアンダースコアを2個(__) - Block又はElementとModifierはハイフンを2個(--)
BEMの本来の形のまま実行してしまうと、下記のようなデメリットがあります。
- クラス名が冗長になってしまうので、コーディング量が増える
- 深くネストした要素はクラス名が複雑になってしまう
このデメリットを防ぐために、弊社では独自のルールを制定しています。
弊社のルール
- BlockとElement又はModiferとElementの区切りはアンダースコアを1つ(
_
)
/ good .block_element .block-modifier_element / bad .block__element .block--modifier__element
- BlockとModifier又はElementとModifierの区切りはハイフンを1つ(
_
)
/ good .block-modifier .block_element-modifier / bad .block--modifier .block__element--modifier
- BlockやElement, Modifierが2つ以上の単語で表す場合キャメルケースを使用する
/ good .articlesList .articlesList_container / bad .articles-list .articles-list__container
- ElementのElementは記述しなくて良い
/ good .articlesList .articlesList_container .articlesList_title / bad .articlesList .articlesList_container .articlesList_container_title
いかがでしょうか? SMACSSのルールをより細分化、BEMを冗長性を防ぐためハイフンや、アンダースコアを省略することで、より使いやすくなると思います。 最初は慣れないと思いますが、慣れてこれば簡単に要素のcssを検索することができるのではないでしょうか。
最後まで読んでいただきありがとうございました。
はじめまして、エンジニアの神山です!!
はじめまして、神山奎吾です。2016年4月から株式会社Cluexでエンジニアとして働いております。よろしくお願いします。
株式会社Cluexで働く前
2016年4月に私は新卒としてCluexにジョインしたのですが、それまでは別の会社で営業をしておりました。そこは大学4年次の4月に内定を頂いたところで、それから大学生ながらも働かせて頂きました。会社規模はCluexとほとんど変わらないスタートアップ企業でした。なぜ営業を選んだのかというと、当時からエンジニアに興味を持っていたのですが、「知識・経験がゼロの状態から始めるのなら営業でいいや」という安易な考えでした。またエンジニアを志した理由もただ興味があるだけで、そもそも将来にやりたいことすら曖昧でした。自分でやりたいと思った事業を創ること、また自分で引っ張る、時に起業できるぐらいの実力者になれたらいいなといった感じでした。
入社して最初の1,2か月はテレアポで新規クライアントの開拓をしてました。毎日200件近く電話をしておりました。しかも最初の2週間くらいはまったくアポが取れずすべて断られ続け、精神的にとても辛く苦しい思いをしました。あまりにもできなかったのが悔しく、休みを利用してテレアポの派遣に登録しテレアポのプロたちの会話術を必死に聞いて真似しておりました。そしてようやくその次の日からアポが取れるようになりました。アポが取れた時に同僚の方々に拍手喝采して頂き、このときの嬉しさは今でも忘れることが出来ません。 今振り返るとこのとき逃げずに挑戦し続けた経験が自分を精神的にかなり強くしてくれたと思います。またダメだった状態から50件に1件ぐらいの割合でアポがとれるようになると仕事がとても好きになり、強い自信を持つことができました。
テレアポの次は実際に広告を運用しており、当月の売り上げを先月の1.25倍にするというノルマのもと働いておりました。この仕事で毎月に一定額以上の利益を出す大変さを学ぶとともに、有限な時間をいかに有効的に使うかを意識して働いておりました。この仕事もハードでしたが、なんとかノルマを達成し続けることができました。このときに努力と根性と少しのクレバーさがあれば人間何でもできると気づきました。
株式会社Cluexに入社したきっかけ
入社して半年ぐらいしたときに、自分は将来何がしたいのか、どのような働き方をしたいのか考えるようになりました。そもそもなぜスタートアップ企業で働いているのかというと、爆速で実力をつけられる一番の環境だったからであり、なぜ実力を付けたいのかというと、実力があれば仕事に困ることもないどころか多種多様な仕事を良い条件でできる、本当の意味での安定が手に入る、また自分の好きな仕事を好きなようにできる、時に旅に出たりなど自由気ままに生きていけると考えていたからでした。 またなぜエンジニアに興味を持ったのかというと、昔から自分はものづくりが好きであり、仕事を楽しみたいとしたらエンジニアが一番なのかなと思ったことでした。欲を言えば自分の代名詞となる世界的なサービスを作りたいと思っておりました。またパソコンやインターネットに興味があり、FacebookやAppleに憧れておりました。理想は自分が0の状態からコードを書いたものを、事業として大きくスケールアップさせ、そのサービスが語られるときに自分の名前もセットで語られることです。
そして当時働いていた会社が上場を考えており、もし本当に究極のなりたい自分になるのなら、今エンジニアを目指すべきだと考え、会社をやめることにしました。社会人の基礎や営業のやり方を学ばせて頂き、公私共に大変お世話になっていたので、自己都合で辞めたことは大変申し訳なく感じております。
その後、2月の終盤ごろにCluexに声をかけて頂きました。最初は社歴がとても短く人数もごく少数の会社なので、未経験のエンジニアとして採用されたとして自分の希望通りに働けるのか、未経験を育てるだけの余裕や教育方針があるのか、悪い意味での何でも屋になるのではないかという不安もありました。しかし話を聞いてみると、エンジニアのリーダーが私と同じく営業上がりで未経験ながらもエンジニアに転職した方であったり、そもそもエンジニアとして経験が豊富な方がいらっしゃったりして、当初の不安は感じませんでした。また人と人の距離がとても近く団結力があり、しかも全員がやる気に満ちており凄く魅力的な会社だなと思いました。 それから何回かCluexに足を運んでいたのですが、メンバー全員が毎日朝から晩まで働いていて、しかもそれを当たり前のように笑って仕事をしているという環境がとても羨ましく、自分もここで働きたい、ここなら爆速で実力を付けられると思い、Cluexで働きたいと強く思うようになりました。また社員の皆さんにも歓迎していただけまして、3月中旬にジョインが決まりました。
いまやっていることと将来やりたいこと
現在、Ruby on Railsにて開発しております。4月1日にRoRのチュートリアルを始めたので3ヶ月と少し経ちます。当時は何もかもがわからない状態でした。プログラミング自体が初めてで、ターミナルって何?どうやって動いているの?みたいな状態でした。 入社してからはいままで休むことなくパソコンのキーを叩いております。というのも寝てる時間以外常に仕事のことを考えております。仕事が楽しくて楽しくて仕方がない状態です。現在入社して3ヶ月目ですが、出来ることが格段に広がりました(勿論、知識が足りてないところは大いにありますが…)。最近はReactをガシガシ書いており、Reactを書いている時間が日々の楽しみになっております。 また、最近はWebアプリケーションチームとして、少人数のチームが構成され、チームを意識した働き方をしております。この会社に入って個々人で開発していた日々から、本格的にチームとして動くようになり、この先、皆で何かを成し遂げたいと思うようになりました。また会社的にもまず上場をさせるという目標があるので、その時が楽しみでなりません。その場面に立ち会ったときには、自分も会社の重要な軸になっているようにより一層の努力を重ねるつもりです。
将来的には、全世界の人々に楽しんで頂けるようなサービスを作りたいと考えています。年齢や性別、言語や文化関係なく、その時一瞬でも幸せを感じて頂けるサービスを作りたいと考えております。自分は大学時代ずっとマジックをやっており、その時にマジックは全世界の人に平等に驚き、またちょっとした幸せを与えられることを知りました。それをITサービスにできたら、上記の目標に一歩近づけるかなと思います。 私の好きな言葉に、「無駄とユーモアが人を幸せにする」という言葉があります。例えば、カロリーが高いけど、美味しいケーキを食べたとき、またしょうもないジョークにも関わらず、なんか疲れが吹き飛んだ時とか、一見あまり価値のなさそうなことに人は幸せを感じ、それらが積み重なってその人の大きな幸せになっていくのだと強く感じます。もし自分が世界の人々を少しでも幸せにできたら、それだけで自分の生きた意味になるのかなと思います。
Cluexではエンジニアの方を募集しています!
エンジニアリングと同時にビジネスマンとして成長したい、スタートアップで働いてみたい、もうレガシーな環境で余計な苦労しをたくないといった方など、 興味がある方はご連絡下さい。 https://www.wantedly.com/projects/60136