AWSにおけるLAMP環境構築(事前準備編)

こんにちは!issaです。

クラウドサーバー、便利ですよね。昔はサーバーを構築する時には筐体選びに始まりデータセンター契約したり、ラック構成を考えたりと大変でしたが、今やボタン一つでできる時代。素晴らしいの一言ですね!今回は、そんな便利なクラウドの中でも無料期間が長く、これからサーバーを勉強しよう!とか、この構成で大丈夫か?みたいな検証を行う際に便利なAWS(Amazon Web Services)の紹介です。AWSを利用したLAMP環境の作成を例にして説明していきます。

今回は、なるべく無料の範囲内での検証環境作成を前提として構築します。初めてAWSにふれる方でも分かるように記載していきますので、これを機にTryしてみてはいかがでしょうか。逆にサーバー環境はいいから、とにかく開発環境が欲しい!といった方は「Cloud9」というAWSサービスもありますので、そちらを利用してみてください。いつか時間があれば、ご紹介させていただきます。

本記事は2回に分けて、下記流れにて説明を行います。

〇事前準備編

〇構築編

  • WEBサーバー (EC2インスタンス) 作成
  • DBサーバー (RDSインスタンス) 作成
  • WEBサーバーからDBサーバーへの接続

AWSは便利な反面、リスクも

AWSは非常に便利で何でもできる印象がありますが、それは裏をかえせば不正アクセス等で利用された場合に大変なリスクを抱えることになります。「aws 不正利用」で検索するととても怖い記事が・・・そうならないためにも、まずは事前準備をしっかりと!

アカウント作成までの流れは、オフィシャルが丁寧に記載してくれていますのでそちらをご参照ください。アカウント作成のリンクもそちらから遷移可能です。

まずは上記URLよりAWSアカウントを取得していただき、終わりましたら次章「アカウント保護」から始めていきましょう!

アカウント保護

適切に保護されていないアカウントを不正に利用されると、犯罪に利用されたり予想もしない請求がきてしまったりと不測の事態が発生する可能性があります。そんな事態にならないためにも事前の設定で備えておきます。

ここでは、下記の流れにて設定をおこなっていきます。

それでは早速アカウントを保護するため「IAM(Identity and Access Management)」の設定をしていきましょう!

ルートアカウントのMFA有効化

MFA(Multi-Factor Authentication)とは、日本語にすると多要素認証となります。
IDとパスワードのみよりも、強力にアカウントを守る事ができますので必ず設定するようにしてください。

①「すべてのサービス」をクリックし全てのサービスを表示してください。
②「セキュリティ、アイデンティティ、コンプライアンス」の中にある「IAM」をクリック。

①「ルートアカウントのMFAを有効化」をクリック。

①MFAの管理をクリック。

①有効にするMFAデバイスを選択します。

※個人的な検証環境等でしたら、スマートフォンがあれば可能な仮想MFAデバイス。
より強固にしたい、もしくは会社等共有の環境であればハードウェアMFAデバイスが良いでしょう。
こちらに、設定が可能なMFAデバイスの説明があります。
 

②有効にするデバイスを選択したら「次のステップ」ボタンをクリック。
今回は個人の検証環境を想定していますので、仮想MFAデバイスを選択しています。


①ここでは、仮想MFAデバイスに関しての注意文が表示されています。
オフィシャルの情報によると、互換性のあるアプリとしては「Google Authenticator」「Authy」というものが利用できます。

※Authyは、クラウドに情報を保存することにより複数の端末間で共有することが可能です。
携帯の紛失時等に復旧できるのも、非常に有難いですね。
そのため、個人で設定する際にはこちらの方が便利かと思います。
会社等での利用の場合、個人端末外で利用される恐れがありますので利用しない方が無難です。

②再度メッセージが不要な場合は「チェックボックス」にチェックを入れてください。
③「次のステップ」ボタンをクリック。

①仮想MFAデバイスで利用するアプリより、QRコードを読み込んでください。
②30秒で数値が更新されますので、連続2回、認証コード1,2と続けて入力してください。
③入力ができましたら「仮想MFAの有効化」ボタンをクリック。

①「完了」ボタンをクリックで、ルートアカウントのMFA有効化が完了です。

①ステータス画面でも、ルートアカウントのMFAを有効化の欄が警告マークではなくなったのが確認できます。

MFAに関しては、金融系サイト等でも利用されていますのでご存知の方も多かったのではないでしょうか?AWSだとここで設定可能だったんですね!

次は、更にセキュリティレベルを上げるため、IP制限をかけるポリシーを作成します。
固定IP環境ではない方は、こちらの手順は飛ばしてください。

IP制限ポリシーの作成

①「ポリシー」をクリック。
②「ポリシーの作成」ボタンをクリック。

①設定内容を、直接記述するために「JSON」タブをクリック。

①今回のコードは「アクセス元が特定のIP以外だった場合、全てのアクションを拒否する」というものになります。
コンソールへのログインを直接防ぐことは、現状のAWSの仕様上できませんが、仮に不正アクセスされたとしても特定のIP以外はほとんどの操作が不可能となります。

IPアドレスはCIDR表記にて記載してください。
※CIDRとは下記SourceIpに記載しているようなIPアドレスの範囲をまとめて記載する記法です。

詳細はこちら


{
    "Version": "2012-10-17",
    "Statement": {
        "Effect": "Deny",
        "Action": "*",
        "Resource": "*",
        "Condition": {
            "NotIpAddress": {
                "aws:SourceIp": [
                    "xxx.xxx.xxx.xxx/32",
                    "yyy.yyy.yyy.yyy/28"
                ]
            }
        }
    }
}

②コードの記載が終わったら「Review policy」ボタンをクリック。

①適当な名前を設定してください。今回は「SourceIPRestriction」としました。
②「明示的な拒否」が全サービスに対しておこなわれているのが確認できます。
③「Create policy」ボタンをクリック。

図のように完了メッセージがでれば、IP制限のポリシー作成が完了です。

環境によっては、この設定は不要な場合もあるかと思います。しかし、次の設定は各個人の権限に関わる所となりますので読み飛ばしは厳禁ですよ!

IAMグループの作成

個々のユーザー毎にポリシーを設定していくと、大変手間がかかります。
そのため、ある程度のポリシーをまとめるためのグループを作っておきます。
各ユーザーをこのグループに所属させることにより、一括して管理が可能です。

用途によって、グループは様々作成する必要があると思いますが
今回は管理者グループと、一般開発者グループの2つを用意します。

①「グループ」をクリック。
②「新しいグループの作成」ボタンをクリック。

①管理者用グループ名を入力。ここでは「Administrators」とします。
②「次のステップ」ボタンをクリック。

①検索ボックスに「Admin」と記入。
②検索結果から「AdministratorAccess」のチェックボックスをクリック。
複数ポリシーを選択しますので、まだ「次のステップ」ボタンは押さないでください。

①検索ボックスに先ほど作成したポリシー名「SourceIPRestriction」を入力。
②先ほどと同様に「チェックボックス」をクリック。

①先ほどチェックしたポリシーが表示されていることを確認してください。
②問題なければ「グループの作成」ボタンをクリックして、管理者グループの作成は完了です。

続いて、一般開発グループを作成します。
今回はEC2とRDSの全ての機能を操作することが可能な権限を与えていますが、
実際の運用時には必要最小限の権限のみを与えることをおススメします。

①開発用グループ名を入力。ここでは「Developers」とします。
②「次のステップ」ボタンをクリック。

①検索ボックスに「ec2」と記入。
②検索結果から「AmazonEC2FullAccess」のチェックボックスをクリック。

①検索ボックスに「RDSFull」と記入。
②検索結果から「AmazonRDSFullAccess」のチェックボックスをクリック。

①検索ボックスに先ほど作成したポリシー名「SourceIPRestriction」を入力。
②先ほどと同様に「チェックボックス」をクリック。
③「次のステップ」ボタンをクリック。

①先ほどチェックしたポリシーが表示されていることを確認してください。
②問題なければ「グループの作成」ボタンをクリックして、一般開発グループの作成も完了です。

グループの作成ができましたので続いてユーザーを作成していきます。
まだまだ序章なのでついてきてくださいね!

IAMユーザーの作成

グループの作成ができましたので、続いてログイン用のIAMユーザーを作成します。
ユーザーもグループと同様、管理者および一般開発者をそれぞれ作成していきます。

①メニューから「ユーザー」をクリック。
②「ユーザーを追加」ボタンをクリック。

①管理者名を入力
②ログインが可能なユーザーとするため「AWS マネジメントコンソールへのアクセス」にチェック。
③「次のステップ:アクセス権限」ボタンをクリック。

①今回は管理者のユーザーですので、先ほど作成した「Administrator」グループへ所属させます。
②「次のステップ:確認」ボタンをクリック。

①Administratorグループに所属していることを確認し「ユーザーの作成」ボタンをクリック。

①三か所に同じ番号がありますが、このどこかでパスワードを確認しておいてください。
これ以降、同じパスワードを確認するすべがなくなりますので注意してください。
②パスワードの確認が完了したら「閉じる」ボタンをクリックし、ユーザーの作成は完了です。
同様の手順で、一般開発ユーザーも作成します。選択するグループを「Administrator」から「Developers」へ変えること以外同じですので、ここでの説明は割愛します。

先ほどまでの項目で、ユーザーの作成が完了しました。
ルートアカウントと同様に、IAMユーザーへもMFAを適用します。

①MFAが有効でないことが確認できます。
②「ユーザー名」をクリックします。

①「認証情報」タブをクリック。
②「ペンの画像」をクリック。
ここからは、ルートアカウントの時と同様の手順でMFAを対象のMFAデバイスに紐づけてください。

ここまでの作業で、アカウントの保護に関する設定ができました。
続いて請求関連の設定をおこなっていきます。

請求関連設定

AWSの特徴でもある従量課金。
少ない金額で運用が可能ですが、間違った運用をおこなってしまうと大変な請求が来ることもありえます。
計画的な利用のためのサービスが、既に用意されていますのでそちらを利用していきます。

ここでは、下記の流れにて設定をおこなっていきます。

予算設定

一か月の運用に対する予算を設定していきます。
ここでは、あまりコストをかけない想定で10ドルを予算額にしていきます。


※このサービスは、あくまで予算アラートです。設定金額を超えたからと言っていきなりサービスが停止するわけではないのでご注意ください。
また、予算を超えているかのチェックはリアルタイムにおこなわれるわけではなく、定期的なチェック時に超えていたらアラートメールが飛ぶという形になりますので
多額の料金がかかるサービスを利用する場合、それに応じた予算の設定が必要になります。

①画面右上のアカウント名をクリックし、メニューを表示させます。
②メニュー内より「請求ダッシュボード」をクリック。

①ダッシュボードが表示されたら、メニューより「予算」をクリック。
②AWS Budgets(予算)ページへ遷移したら「予算を作成」ボタンをクリック。

①予算に名前を付けます。
※複数アカウントを所持する予定がある方は、ここで付ける名前には全てのアカウントで一意になる名前を付けることをおススメします。
アラートメールには、この予算名のみが記載されるため
1つのアドレスで複数アカウントの通知を受け取っていた場合は
どのアカウントからのアラートなのか分からなくなってしまいます。

②予算額をドル単位で記載します。
③どのタイミングで通知を受け取るかを設定します。
 今回は予算の50%。5ドルを超えたら通知されるように設定しています。
④通知先のアドレスを設定します。
 即座に気づけるように、今回は携帯アドレスを設定しました。
⑤全ての入力が終わったら「作成」ボタンをクリック。

これで、予算の作成が完了です。

請求設定

定期的に請求ダッシュボードのチェックは必要ですが、
請求書に関してはメールでも受信できるようにしておきます。

①メニューより「設定」をクリック。
②「電子メールで PDF 版請求書を受け取る」をチェック。
③予算の設定はしていますが「無料利用枠の使用のアラートの受信」にもチェックを付けてより確実にしておきましょう。
④アラート受信のアドレスを設定。
⑤「設定の保存」ボタンをクリック。
画面上部に「設定を保存しました」とメッセージが表示されたら設定完了です。

IAMユーザーへの請求情報閲覧権限付与

このままですと、ルートアカウントでなければ請求関連の参照ができません。
そこで、先ほど作ったAdministratorグループに所属したユーザーには参照権限を与えるようにします。

①画面右上の「アカウント名」をクリック。
②メニューから「アカウント」をクリック。

①初期状態では、IAMユーザーが請求情報へアクセスできないようになっています。
②「編集」をクリック

①「IAM アクセスのアクティブ化」にチェック。
②「更新」ボタンをクリック。

①有効になっていたら、アクセスが可能になります。
※今回はAdministratorグループへ「AdministratorAccess」権限を付与しているため、その他操作は不要でした。
「AdministratorAccess」権限を持たないユーザーへ個別に設定する場合には、別途下記URLを参考に設定する必要があります。

事前準備完了

これで事前準備は完了です。
事前準備めんどくさーい!と思った方もいらっしゃるかもしれませんが、何事も自己防衛大事です。後悔してからでは遅いのです!

次回は「AWSにおけるLAMP環境構築入門(構築編)」です。

いよいよインスタンスの作成に入っていきます!
インスタンスとは「AWS クラウドにある仮想サーバー」を意味します。
ようやく本題って感じですね!
接続できるところまで記載していきますので、お楽しみに!!

【インタビュー】カタリストのインターンシップ紹介

ボンジュール!飲み会の度に、体重が2キロくらい増えるコウダインテだよ!
今回は、カタリストで採用しているインターンシップについての記事です。

絶賛募集中のインターンシップですが、「実際どんなことするの?難しくないの?」
と、インターンシップの応募に二の足を踏んでいる現役大学生のあなた!
そこのあなたのために、現在活躍中の現役インターンシップ生へのインタビューを通して
「カタリストでのインターンシップ体験」を紹介します。


<続きを読む>

iOS アーキテクチャ Redux + ApplicationCoordinator

はじめまして。今回がエンジニアブログ初投稿で、カタリストシステム最年少のホンダです!
今回は、新規プロダクト開発時に悩み抜いて選定したアーキテクチャについて書きます。
今までは、iOSの基本的な設計思想であるApple’s MVCを使って、iOSアプリを開発していました。

しかし、開発が進むにつれて以下のような問題が発生しました。

  • ViewControllerが肥大化する
  • 画面遷移が複雑化する
  • データの引き渡しがやりづらい

上記の問題を解決するために、今回新たに開発する新規プロダクトでは、Redux(ReSwift) + ApplicationCoordinator を使った、データの同期と遷移の共通化を実装しています。
本記事では、まず概要を説明し、記事の後半で実際のコードをご紹介致します。

Reduxとは

ReSwiftの根本には、Reduxの思想があります。
Reduxは、UIのstate(状態)を管理をするためのフレームワークです。stateでデータフロー管理する実装にFluxが提案されていますが、ReduxはFluxの概念を拡張してより扱いやすく設計されています。
Reduxのデータフローは以下になります。

  • Action 「何をする」という情報を持ったオブジェクトです。
  • Store アプリケーションの状態(state)を保持している場所です。最大で1つです。
  • State アプリケーションでの状態を表します。
  • Reducer ActionとStateを使ってStore内のStateを更新します。

Reduxの3原則

Reduxの基本設計は以下の3つの原則に基づいて設計されています。
上記のデータフローはこの原則に則っていることがよく分かると思います。

  1. Single source of truth
    アプリケーション内でStoreは1つのみとし、Stateは単独のオブジェクトとしてStoreに保持される。
  2. State is read-only
    Stateを直接変更することはできず、actionをStoreへdispatchすることでしかStateは変更できない。
  3. Mutations are written as pure functions
    Stateを変更する関数(Reducer)は純粋な関数にする。


ReSwift

今回、ReduxのSwift実装の


を使用して実装しています。
Redux原則を元にデータフローを制御することで、変更の反映漏れやデータの引き回しの不要になります。

ApplicationCoordinator

ライブラリに頼らない遷移管理パターンで、AppDelegate内でUIWindowを継承して初期化することで、遷移関連を統一した1ファイルで管理することが可能です。
ViewController内のDelegateの宣言が前提の為、一時的に渡したい変数等は簡単に引き継ぐことが可能です。

サンプル

今回はサンプルとして以下のような簡単な実装をReSwift + ApplicationCoordinatorで構築したサンプルコードを紹介します。
入力ボタンで入力専用画面へ遷移されて、入力した内容が最初の画面に反映されています。

実行環境

  • mac OS Sierra 10.12.6
  • Xcode 9.2
  • Swift 4
  • ReSwift 4.0.0

ReSwiftは、Cocoapodsで導入しています。

pod 'ReSwift'

Storyboard

Storyboardには簡単なUIコンポーネントを配置しています。

Model

最初にReSwiftの登場するState、Action、Reducerを定義します。
状態は、AppStateの中にツリー構造で定義します。Reducerは、MainStateのextensionで宣言することで、名前空間を制御しています。

//
//  AppState.swift
// AppDelgateで初期化し、全体のStateを管理する構造体です。
//
import Foundation
import ReSwift

struct AppState: StateType {
    var main = MainState()
}
//
//  MainState.swift
//  子State
//
import Foundation
import ReSwift

struct MainState: StateType {
    var text: String?
}
//
//  InputAction.swift
//  Actionの構造体です。変更したいStateの値を宣言しています。
//
import Foundation
import ReSwift

struct InputAction: Action {
    var text: String
}

//
//  AppReducer.swift
//  大本のReducerです。
//
import Foundation
import ReSwift

func AppReducer(action: Action, state: AppState?) -> AppState {
    return AppState(
        main: MainState.MainReducer(action: action, state: state?.main)
    )
}
//
//  MainReducer.swift
//  子のReducerで、今回は、InputAction構造体に反応して新しいStateを生成して返す処理をしています。
//
import Foundation
import ReSwift

extension MainState {
    static func MainReducer(action: Action, state: MainState?) -> MainState {
        let state = state ?? MainState(text: "")
        var newState = state
        var mainState = state
        switch action {
        case _ as InputAction:
            mainState = MainState(text: (action as! InputAction).text)
        default:
            break
        }
        newState = mainState
        return newState
    }
}

ApplicationCoordinator

本クラスで各ViewController上で定義した、protocolを使用して遷移を管理します。
AppDelgateで初期化する為、UIWindowをイニシャライザに持ちます。
ViewControllerのprotocolは、extensionで定義するのがオススメです。

//
//  ApplicationCoordinator.swift
//
import UIKit

final class ApplicationCoordinator {
    
    private let window: UIWindow
    
    init(window: UIWindow) {
        self.window = window
    }
    
    public func start() {
        guard let vc = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "VC") as? ViewController else {
            return
        }
        vc.transitionDelegate = self
        self.window.rootViewController = UINavigationController(rootViewController: vc)
        self.window.makeKeyAndVisible()
    }
}

extension ApplicationCoordinator: ViewControllerTransitionDelegate {
    func push() {
        guard let vc = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "SecondVC") as? SecondViewController  else {
            return
        }
        (self.window.rootViewController as? UINavigationController)?.pushViewController(vc, animated: true)
    }
}

AppDelegate

Storeの初期化とApplicationCoordinatorの初期化をします。


//
//  AppDelegate.swift
//

import UIKit
import ReSwift

// NOTE: アプリで1つのStoreを作成生成する
let mainStore = Store(
    reducer: AppReducer,
    state: nil
)

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?
    // NOTE: lazyで定義して、始めて使用されるタイミングでApplicationCoordinatorを初期化しています。
    lazy var applicationCoordinator: ApplicationCoordinator = {
        return ApplicationCoordinator(window: self.window!)
    }()

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        self.window = UIWindow(frame: UIScreen.main.bounds)
        self.applicationCoordinator.start()
        return true
    }
...

Controller

//
//  ViewController.swift
//
import UIKit
import ReSwift

protocol ViewControllerTransitionDelegate: class {
    func push()
}

final class ViewController: UIViewController {
    weak var transitionDelegate: ViewControllerTransitionDelegate?
    
    @IBOutlet weak var label: UILabel!
    
    override func viewDidLoad() {
        super.viewDidLoad()
    }
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        // 監視作成
        // NOTE: 特定の状態のみ監視し、同じ値の場合はSkipする
        mainStore.subscribe(self) {
            $0.select {
                $0.main
                }.skipRepeats {
                    $0.text == $1.text
            }
        }
    }
    
    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        // 監視削除
        mainStore.unsubscribe(self)
    }
    
    @IBAction func event(_ sender: Any) {
        self.transitionDelegate?.push()
    }
}

extension ViewController: StoreSubscriber {
    typealias StoreSubscriberStateType = MainState
    // NOTE: 監視しているの値が変更されてた場合に呼ばれる
    func newState(state: MainState) {
        self.label.text = state.text ?? ""
    }
}


//
//  SecondViewController.swift
//
import UIKit
import ReSwift

final class SecondViewController: UIViewController {
    
    @IBOutlet weak var textField: UITextField!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        self.textField.text = mainStore.state.main.text
    }
}

extension SecondViewController: UITextFieldDelegate {
    func textFieldDidEndEditing(_ textField: UITextField, reason: UITextFieldDidEndEditingReason) {
        // NOTE: dispatch関数を使用して、Actionを送信する。対応するReduserが検知し、新たなStateが作成され更新されます。
        mainStore.dispatch(InputAction(text: textField.text ?? ""))
    }
}

まとめ

iOS開発の課題を全て解決しているわけではありませんが、状態変化が起きた際の処理を一箇所にまとめるこで、可読性が改善し、処理が散らばらないのでデバッグしやすいと感じています。
興味のある方は実際に触ってみると面白いと思います。
ReSwiftの表面的な使い方やアーキテクチャ選定のお役に立てれば幸いです。
ここまでお読みいただきまして、ありがとうございました。


次回は社員インタビュー(若手編)を記事にさせていただく予定です。乞うご期待ください!

【2018年】ヒト・モノ・カネの時代からヒト・ヒト・ヒトの時代へ【新年のご挨拶】

2018年、新年あけましておめでとうございます!
代表の大井田です。昨年、弊社は、様々な変化を迎え、新たな発見の多い1年となりました。
月並みですが、新年第一回目ということで、昨年の振り返りと僕なりのIT業界の時流を受けた今後の展望など、ご挨拶として投稿させていただきたいと思います。

昨年(2017年)の印象的だった出来事、振り返り

自社スタッフによる開発ブログのスタート、オウンドメディアの立ち上げなど、外部への発信を強化。その中で、素敵な出会いもありました。一方、手放したものも。現在取り組み中の、自社サービス開発の経緯なども合わせて紹介させていただきます。

「Developer’s Blog | カタリストシステム開発者ブログ」のスタート

スタッフによる、開発者ブログを立ち上げました。(今ご覧いただいているブログです)

導入の理由としては、

  • 弊社に興味を持っていただいた方へ、どんな会社かを知っていただくため
  • 弊社エンジニアのアウトプットする訓練の場

という目的のもと、実験的な導入でしたが、じわじわと PV数も増えていっており、外に配信することの重要性を感じる機会となりました。
弊社のエンジニアも、みんなブツブツ言いながらもそれなりに楽しんで記事を書いてくれているようなので、本当に感謝です(この場でお礼を言います。協力してくれて本当にありがとう。)。
そしてみんな普通に文章を書くのが上手かった、という良きことが発見できました。

オウンドメディア「TeamHackers」運営の開始

現在開発中の自社サービス・ローンチに向けた準備として、
「TeamHackers ~最高のチームを作り上げるアイデアハック~」
という働き方についての情報をまとめたオウンドメディアの運営を始めました。

僕たちのようなIT業界(特に、弊社のようなベンチャー)では、常に変化する時流に柔軟に対応し、いかにメンバーの能力を生かし、生産性を向上させられるかが鍵を握ります。
現在、それを達成することを根底から支えるサービスを開発中です。その分野にお悩みの方と出会うため、このようなメディアの方向性を決め運用をスタートしました。

メディア立ち上げに当たって、人づてに紹介していただいた、メディア運営の責任者として元リクルート出身のコンサルタントNさん、グロースハック・デザイナーのHさんとご縁をいただき、出会いに恵まれて運営を実現することができました。インターンで運営のアシスタントをしてくれているMくんもめちゃくちゃ優秀と絶賛です。とても優秀な方々なので、全幅の信頼を寄せてオウンドメディア運営をお任せしています。

弊社としても、投稿されていく記事を読む中で、働き方というものに自然と目を向ける機会となっています。運営側の僕が言うのもなんですが、かなり面白い記事が揃っていますので、ぜひ見ていただけると幸いです。

大きな決断、飲食事業の譲渡

僕は、弊社(株式会社カタリストシステム)とは別に株式会社ソラーレという飲食事業を運営していました。様々な事情があり、こちらは別の法人様へ事業譲渡することになりました。(ソラーレ社員の名誉のためにも一応言っておきますが、赤字で撤退したという理由ではありません。現場のスタッフが本当に頑張ってくれていたので、しっかり利益は出ていました。)

飲食事業を始めると決めて、人探し、物件探しから始まって店舗開業、そして事業譲渡まで丸5年運営していました。大変な苦労もあり、現場の思いもあり、そして楽しさもあり、普通では味わえない良い経験と知見を得ることができました。関係者には感謝しかありません。本当にどうもありがとうございました。

このように昨年は、新たに始めたこともあり、長い時を経て終わったこともあり、僕の中では昨年末で1つの区切りがついたように思います。ひとえに思うのは、ブログやメディアの運営しかり、飲食事業しかり、人との出会いがあってこそのものだと強く実感しています。今年、新たな一歩を踏み始めるに当たって僕の中で「ヒト」というのが、大きなキーワードになっていきました。

2018年 自社サービスへ挑戦への想い

そして、2017年、最も大きなウェイトを占めたのが、自社サービス開発への挑戦でした。受託開発の波に乗り成長してきた弊社が、さらに次のステップへ向かうため始めた取り組みですが、とても難しいチャレンジだと感じています。今まではクライアントありきのシステム構築のため、クライアント様に「何をやりたいのか?」を聞いて、それをシステムとして実現させてあげることができれば良かったのです。しかし今回は自社サービス。「なにをやりたいのか?」を自分で考えなければなりません。

何をやりたいか? 時流と課題

これがまた難しいお題でした。やはりIT業界にいる身としては、最近の流行っている時流に乗りたい気持ちが満載です。

例えば、

  • AI
  • ディープラーニング
  • IoT
  • VR,AR,MR
  • 自動運転
  • 電気自動車

等があります。しかしながら、皆さんそこに向かっていち早くサービス化するために邁進している状況を肌で感じています。そのため、僕は敢えてそちらの方向には進みませんでした。というか進めませんでした…。最近の技術の進歩はとても速くなっています。そして、そんな時流に乗った分野へ本音を言えば行きたいのですが、どうしても資本がある大手には勝ちづらいことは目に見えています。小資本の弊社が行くべきではない。圧倒的な技術力があれば巨人に勝つことも可能かもしれませんが、これらの時流の分野で圧倒的な技術力は、残念ながら弊社にはありません…。

であれば、どこを目指すべきか。「勝てないのでやらない」では、あまりにもネガティブな話で終わってしまうので、弊社だからこそ勝負ができる分野を徹底的に考えました。

ヒト・モノ・カネの時代からヒト・ヒト・ヒトの時代へ

少し話は変わりますが、よく経営の大事な資源として「ヒト、モノ、カネ」と言われます。しかし時代は変わって21世紀は「ヒト、ヒト、ヒト」だ、という方も現れました。確かにこの考え方は納得しています。前述した内容でも述べましたが、開発者ブログ、メディアの運営、飲食事業、何をやるにしても大事なのはやっぱり「人」です。それは間違いありません。

それならば「人」をベースに考えてみよう。

開発会社の経営をしていると、「人」について本当によく考えます。それは本当に面白いもので、例えば1人が10の働きをしたとして、では単純に3人集まれば30の働きになるかというとそんなことはないのです。なぜか5の働きに低下する場合もあるし、逆に50の働きができるケースもあります。それは何故起きるのか?非常に興味を惹かれました。

僕たちは社会で生きる以上、人との関係性の外で生きることはできません。とりわけ、開発はチームで行います。人と人の関係性が大きくプロジェクトへ影響を与えます。チームで働くことを前提としたサービス。この分野ならば弊社とも親和性があり、また多くの人が日々課題解決を目指している分野です。ここなら勝負ができるかもしれないと感じました。

それからは、この分野のどこに課題や問題があるのか?を探して、それを解決するサービスを目指しました。ローンチ前なので詳しくは語れませんが、エンジニア集団が作るからには、システムにはこだわり抜こう!と、エンジニア魂が燃え上がるようなシステム設計になっています。

2018年に向けて抱負

まずは前述した現在開発中の「チームの課題を解決するサービス」のローンチを何としてでも行いたいと思っています。そして、そこから始まり、ご縁のある皆様に対して価値あるものを提供していきたいと思います。また「ヒト、モノ、カネ」ではなく「ヒト、ヒト、ヒト」を指針に、今まで以上に、人との関係性を大切にする会社を目指していきたいと思っています。自社サービスを作り上げることの難しさを本当に噛みしめる日々ですが、そんな至らない自分を助けてくれる会社の皆に本当に感謝しています。この場を借りて、お礼を言いたいです。「いつもありがとう」、と。

最後になりましたが、どうぞ、今年も何卒よろしくお願いします。