Upgrade to Pro — share decks privately, control downloads, hide ads and more …

動き出したクックパッドのCtoCビジネス

1amageek
February 14, 2018

 動き出したクックパッドのCtoCビジネス

2017の春からクックパッドはCtoCビジネスを開始することを公言していました。本日は新規サービスを発表させて頂きます。

その名も「Komerco」(コメルコ)です。

Komercoはモノで毎日の料理を楽しくするプラットフォームです。Cookpadは毎日の料理を楽しみにすると言うミッションを掲げています。
Komercoはその中でも、モノで毎日の料理を楽しくすると言うポジションでサービスを展開します。

もので毎日の料理を楽しくするとはどう言うことでしょうか?
これはKomercoのプロダクトオーナーのInstagramです。

料理を美味しく作れる鍋、
美しく飾ることができる器
料理は楽しくなると考えました。

世界にはたくさんの素晴らしい作品にあふれています。
日本には素晴らしい作品を生み出すクリエーターがたくさんがいます。Komerco は素晴らしいモノを提供するクリエーターと
料理をする人を結びつけるサービスです。
Komercoではすでに素晴らしい作品を生みだす100人のクリエーターを獲得しています。

Komercoについてもう少しお話します。Komercoは三つの要素から構成されています。
EC・Media・cookpadの三つです。

Komercoはこの春リリースです。

さてKomercoの開発の裏側に話を進めていきましょう。
みなさん昨日のクックパッド のDevelopers Blogみていただけましたか?
今日はそのあたりの話をもう少ししようと思っています。

まずKomercoチームの紹介をします。
特に注目して頂きたいのがエンジニアに関してです。Komercoにはサーバーサイドエンジニアがいません。

Komercoはサーバーレスで開発されています。KomercoのバックエンドはFirebaseです。

なぜFirebaseなんでしょうか?

私がWEB興味をもち、最初にサービスを作り始めたのは2009年でした。Railsが普及し始めNode.jsが生まれた年です。当時は私は夢見がちな要件定義をたくさんしていました。
もちろん失敗しました。開発を行った事がない素人には夢見がちな要件は重すぎたからです。

次はチームを組んで開発を行うことにしました。
この頃はMEANという開発方法が登場し、Node.jsが普及し始めた頃です。

これも失敗しました。開発者の技術力の差によって、サーバーサイドとクライアントサイドの進捗に大きなズレが起こりました。その結果チームのモチベーションを維持できなくなっていました。

前の反省を生かしてmBaaSを導入することにしました。
Facebookが提供していたParseと言うサービスを利用していました。このときは、開発も順調に進みました。サーバーサイドのことを考える必要がなくなったため、開発が非常にシンプルになりました。この頃から私はREST APIを使うことがなくなりました。

しかし失敗しました。Facebookが突然、Parseをクローズさせたんです。そして2016年 Googleに買収されたFirebaseがとてつもなく素晴らしいものになってリリースされました。
このタイミングで私はFirebaseに飛びつきました。

そこからFirebaseの研究を進め、Komercoの開発に至りました。
Firebaseに到るまでに長い歴史があるんですねぇ。
そしてParseのようになるまいとGoolgeさんと仲良くさせてもらいながらコミュニティを盛り上げて行っています。

開発がうまくいかなかったのはなぜでしょうか?
エンジニアスキルですか?
納期ですか?
チームの結束ですか?

私が思うに全ては開発が遅いことだと言う思います。
開発が遅くなる原因はたくさんありました。しかし、逆説的にとにかく開発が早くなればあらゆることが解決されると考えました。

想像してみてください。
鉛筆で書いて消しゴムで消すように仕様変更ができて、想い描いたことを直ぐに形にできる開発ができればどうですか?
きっと未来は明るいんです。
私は現在存在するバックエンドのサービスの中でFirebaseがそれをもっとも近い存在だと考えています。

Firebaseの特徴を3つご紹介します。
・高速に開発できること
・簡単にセキュリテイを担保できること
・フルマネージドです。

FirebaseはクライアントからDBへ直接Writeを行います。
APIを通す必要がないのでAPIを開発する必要すらありません。
どのくらい簡単かお見せしましょう。

SwiftでUserを定義して保存、取得、更新を行なっています。
非常に簡単ですよね?
もう一つ例をお見せします。サービスを設計する上でDBを正規化することって辛くないですか?少なくとも私はRDBの設計をするのは結構辛いです。

Firebaseではこんな分にリレーションを表現できます。
ここではUserとGroupの二つを定義しました。

UserがGroupsをもちGroupがUsersをもち
お互いに参照を持つ事ができるようになっています。

ここでは三つのインスタンスの関係性を表しています。
相互参照して、最後に保存します。これだけです。非常にシンプルですね。

次にセキュリティについて紹介します。
Firebaseのセキュリティはルールファイルを定義する事で行います。

これがルールファイルです。
このルールでは、UserがReadできるのはAuthを持っていることクライアントである事、またWriteできるのは自分だけと言うことを表しています。

最後にインフラについてですが、Firebaseはオートスケールします。インフラの監視に悩まされることはありません。
Firebaseを例えるなら、開発における鉛筆と消しゴムと無限のキャンバスです。速そうな気がしませんか?

でもまだまだ加速できる
車輪の再発明を可能な限り少なくしていきましょう。

私たちはオープンソースを利用しています。みなさんもサービスを作るときはお世話になっているんじゃないでしょうか?
もちろんKomercoでもOpenSourceを利用しています。

そして私たちは、利用するだけじゃありません。作り出して公開しています。

なぜOpenSourceを提供するんでしょうか?
それは、少人数で品質を担保するためです。

OpenSourceにすることで品質が向上します。
エンジニアは、外部に出すことを考え始めた瞬間に依存性を考えるようになり、自ずと疎結合な設計がされていきます。
自分のチームでしか使わない頭になった瞬間コードはへの妥協は必ず増えていきます。心理的なことですが、非常に効果があります。

この後、私がちが作ったOpenSourceを紹介しますが、そのOpenSourceはすでに、海外のスタートアップでも利用されています。
バグ報告もたくさんもらいます。
OpenSourceにすることでチーム以外の人が自分たちの開発を手伝ってくれるんです。

そして、再利用ができる。
これこそGive and Takeです。私たちが作ったOpenSourceは社内の他のチームでも利用されています。
こうすることで他のチームはさらに高速な開発ができるようになります。

Komercoの技術を公開しています。のぞいてみてください。

今日は特に次の二つをご紹介します。
PringとOrderableです。

高速に開発できそうじゃないですか?

高速化した先に何があるんでしょうか?
ただ早く作ることになんの意味があるのか?

開発が高速化されることで
大胆な戦略を取る事ができるんです。

複数回の仕様変更ドンとこい。Komercoでも要件の漏れや、仕様の拡張を何回行いました。高速化していない状態で、4人でECを立ち上げようとしていたら複数回の仕様変更はかなりの痛手だと思います。

消耗しないは言い過ぎですが、想い描いたことを直ぐに実現できる環境は非常に精神的なストレスを軽減します。

要件が多くあっても仕様で衝突したり悩む事が劇的に少なくなります。

最後にこれは非常に重要です。
たくさん試す事ができるようになります。
サービスの設計をするとき、感覚的意見な衝突で悩むことはありませんか?このUIの方が、こっちのUIの方が、あれの方が
あると思います。

しかし残念ながら、いくら議論しても時間の無駄です。
結論は市場しか知らないんです市場に聞きましょう。

たくさん試しましょう。想い描いたことをとにかく試して事実を確立していきましょう。
そうする事で、少しづつですがサービスは確実に成長していきます。

最後にまとめさせていただきます。

Komercoは今年の春にリリースします!

KomercoはFirebaseで開発されています。

Komercoで使われいるテクノロジーを公開しています。

クックパッドを新しいサービスを高速で開発して行きます。

最後に動きだしたクックパッドのビジネスにご注目ください。

1amageek

February 14, 2018
Tweet

More Decks by 1amageek

Other Decks in Technology

Transcript

  1. Norikazu Muramoto
    Komercoࣄۀ෦
    ಈ͖ग़ͨ͠ΫοΫύουͷ
    CtoCϏδωε

    View Slide

  2. CtoCϏδωε

    View Slide

  3. View Slide

  4. View Slide

  5. ϞϊͰຖ೔ͷྉཧΛָ͘͢͠ΔϓϥοτϑΥʔϜ

    View Slide

  6. ϞϊͰຖ೔ͷྉཧΛָ͘͢͠Δ
    ຖ೔ͷྉཧΛָ͠Έʹ͢Δ

    View Slide

  7. ϞϊͰຖ೔ͷྉཧΛָ͘͢͠Δʁ

    View Slide

  8. View Slide

  9. View Slide

  10. View Slide

  11. View Slide

  12. ΫϦΤʔλʔ

    View Slide

  13. View Slide

  14. View Slide

  15. EC

    View Slide

  16. EC Media

    View Slide

  17. EC Media cookpad

    View Slide

  18. EC Media cookpad
    Product

    View Slide

  19. EC Media cookpad
    Product Story

    View Slide

  20. EC Media cookpad
    Product Story Recipe

    View Slide

  21. ͜ͷय़ϦϦʔε

    View Slide

  22. Komercoͷ։ൃʹ࿩ΛਐΊ·͠ΐ͏

    View Slide

  23. iOS Engineer
    Product owner
    Director
    1
    1
    4
    4
    Designer 1
    Our team
    Customer support 2
    Creator scout

    View Slide

  24. iOS Engineer
    Product owner
    Creator scout
    Director
    1
    1
    4
    4
    Designer 1
    Our team
    Customer support 2
    αʔόʔαΠυͷΤϯδχΞ͕͍·ͤΜ

    View Slide

  25. Serverless

    View Slide

  26. View Slide

  27. Why Firebase?

    View Slide

  28. Why Firebase?
    ࢲͷਓੜͷࣦഊஊͱڞʹ͝આ໌͠·͢ɻ

    View Slide

  29. 2009
    Node.js
    Rails
    ເΈ͕ͪͳཁ݅ఆٛ

    View Slide

  30. 2009
    Node.js
    Rails
    ເΈ͕ͪͳཁ݅ఆٛ

    View Slide

  31. 2009
    Node.js
    MEAN
    2013
    Rails
    ເΈ͕ͪͳཁ݅ఆٛ
    νʔϜϏϧσΟϯά։࢝

    View Slide

  32. 2009
    Node.js
    MEAN
    2013
    Rails
    ເΈ͕ͪͳཁ݅ఆٛ
    νʔϜϏϧσΟϯά։࢝


    View Slide

  33. 2009
    Node.js
    MEAN
    2013
    2015
    Parse
    Rails
    ເΈ͕ͪͳཁ݅ఆٛ
    νʔϜϏϧσΟϯά։࢝
    mBaaSΛಋೖ
    REST APIͱܾผ


    View Slide

  34. 2009
    Node.js
    MEAN
    2013
    2015
    Parse
    Rails
    ເΈ͕ͪͳཁ݅ఆٛ
    νʔϜϏϧσΟϯά։࢝


    mBaaSΛಋೖ
    REST APIͱܾผ

    View Slide

  35. 2009
    Node.js
    MEAN
    2013
    2015
    Parse
    Rails
    2016
    Firebase
    ເΈ͕ͪͳཁ݅ఆٛ
    νʔϜϏϧσΟϯά։࢝
    Firebaseಋೖ


    mBaaSΛಋೖ
    REST APIͱܾผ

    View Slide

  36. 2009
    Node.js
    MEAN
    2013
    2015
    Parse
    Rails
    2016
    Firebase
    ເΈ͕ͪͳཁ݅ఆٛ
    νʔϜϏϧσΟϯά։࢝




    2018
    Komerco
    mBaaSΛಋೖ
    REST APIͱܾผ
    Firebaseಋೖ

    View Slide

  37. View Slide

  38. ։ൃ͕͏·͍͔͘ͳ͍ͷ͸ͳͥʁ

    View Slide

  39. ։ൃ͕஗͍͜ͱ
    ॾѱͷࠜݯ

    View Slide

  40. ԖචͰॻ͍ͯ
    ফ͠ΰϜͰফ͢
    ૝͍ඳ͍ͨ͜ͱΛ͙͢ܗʹͰ͖Δ։ൃ

    View Slide

  41. Full Managed
    Secure
    Quick
    Why Firebase?

    View Slide

  42. Quick
    Firestore
    Cloud Functions
    App
    Read / Write
    Firebase

    View Slide

  43. // SAVE
    let user: User = User()
    user.name = "1amageek"
    user.save()
    // GET
    User.get("user_id") { user, error in
    if let error = error {
    print(error)
    return
    }
    print(user)
    // UPDATE
    user?.name = "Norikazu Muramoto"
    user?.update()
    }
    @objcMembers
    class User: Object {
    dynamic var name: String?
    }

    View Slide

  44. @objcMembers
    class User: Object, UserProtocol {
    dynamic var name: String?
    let groups: ReferenceCollection = []
    }
    @objcMembers
    class Group: Object, UserProtocol {
    dynamic var name: String?
    let users: ReferenceCollection = []
    }

    View Slide

  45. @objcMembers
    class User: Object, UserProtocol {
    dynamic var name: String?
    let groups: ReferenceCollection = []
    }
    @objcMembers
    class Group: Object, UserProtocol {
    dynamic var name: String?
    let users: ReferenceCollection = []
    }

    View Slide

  46. let user0: User = User()
    let user1: User = User()
    let group: Group = Group()
    // ૬ޓࢀর͢Δ
    user0.groups.insert(group)
    user1.groups.insert(group)
    group.users.insert(user0)
    group.users.insert(user1)
    // อଘ͢Δ
    group.save()

    View Slide

  47. Secure
    Document
    Document
    App
    Firebase

    View Slide

  48. service cloud.firestore {
    match /databases/{database}/documents {
    // user
    match /user/{userID} {
    allow read: if request.auth != null;
    allow write: if request.auth.uid == userID;
    }
    }
    }

    View Slide

  49. service cloud.firestore {
    match /databases/{database}/documents {
    // user
    match /user/{userID} {
    allow read: if request.auth != null;
    allow write: if request.auth.uid == userID;
    }
    }
    }

    View Slide

  50. Full Managed
    Auto Scale

    View Slide

  51. ·ͩ·ͩՃ଎Ͱ͖Δ

    View Slide

  52. OpenSource

    View Slide

  53. Give and Take

    View Slide

  54. ͳͥOpenSourceʁ
    গਓ਺Ͱ඼࣭Λ୲อ͢ΔͨΊ
    ɾOpenSourceʹ͢Δͱ඼࣭͕޲্͢Δɻ
    ɾ֎෦ͷਓ͕ɺνʔϜͷϦιʔεʹͳΔɻ
    ɾ࠶ར༻Ͱ͖Δɻ

    View Slide

  55. ͳͥOpenSourceʁ
    গਓ਺Ͱ඼࣭Λ୲อ͢ΔͨΊ
    ɾOpenSourceʹ͢Δͱ඼࣭͕޲্͢Δɻ
    ɾ֎෦ͷਓ͕ɺνʔϜͷϦιʔεʹͳΔɻ
    ɾ࠶ར༻Ͱ͖Δɻ

    View Slide

  56. ͳͥOpenSourceʁ
    গਓ਺Ͱ඼࣭Λ୲อ͢ΔͨΊ
    ɾOpenSourceʹ͢Δͱ඼࣭͕޲্͢Δɻ
    ɾ֎෦ͷਓ͕ɺνʔϜͷϦιʔεʹͳΔɻ
    ɾ࠶ར༻Ͱ͖Δɻ

    View Slide

  57. ͳͥOpenSourceʁ
    ɾOpenSourceʹ͢Δͱ඼࣭͕޲্͢Δɻ
    ɾ֎෦ͷਓ͕ɺνʔϜͷϦιʔεʹͳΔɻ
    ɾ࠶ར༻Ͱ͖Δɻ
    গਓ਺Ͱ඼࣭Λ୲อ͢ΔͨΊ

    View Slide

  58. OpenSource
    Komercoͷٕज़Λެ։͍ͯ͠·͢
    https://github.com/1amageek/Pring
    https://github.com/1amageek/pring.ts
    https://github.com/sgr-ksmt/Alertift
    https://github.com/sgr-ksmt/Lobster
    https://github.com/miuP/Algent
    https://github.com/miuP/Tsuchi
    https://github.com/starhoshi/Orderable
    https://github.com/starhoshi/Orderable.ts

    View Slide

  59. Pring Orderable

    View Slide

  60. Pring
    Firestore model framework
    ɾFirestoreͰεΩʔϚΛఆٛ
    ɾϦϨʔγϣϯγοϓΛఆٛ
    ɾෳ਺ϊʔυͷಉ࣌ߋ৽

    View Slide

  61. // Shop
    let shop = Shop()
    shop.name = "͏ͭΘγϣοϓ"
    // Product
    let product = Product()
    product.name = "࣫ృΓͷث"
    product.hashtags = ["ث", "࣫ృΓͷث"]
    // SKU
    let sku = SKU()
    sku.stock = 10
    sku.price = 2000
    sku.shop.set(shop)
    sku.product.set(product)
    shop.products.insert(product)
    product.shop.set(shop)
    product.skus.insert(sku)
    shop.save()

    View Slide

  62. Orderable
    Order processing framework
    ɾࡏݿΛ֬ೝɺมߋ
    ɾܾࡁػೳͱ࿈ܞ
    ɾܾࡁཤྺͷ࡞੒Λอଘ
    ɾϦτϥΠ

    View Slide

  63. ߴ଎ʹ։ൃͰ͖ͦ͏͡Όͳ͍Ͱ͔͢ʁ

    View Slide

  64. ։ൃΛߴ଎Խͨ͠ઌʹ
    ͨͩૣ͘࡞Δ͜ͱʹҙຯ͕͋Δͷ͔

    View Slide

  65. ։ൃ͕ߴ଎Խ͞ΕΔ͜ͱͰ
    େ୾ͳઓུΛऔΕΔΑ͏ʹͳΓ·͢
    ɾෳ਺ճͷ࢓༷มߋʹ΋ରԠͰ͖Δ
    ɾΤϯδχΞ͕ফ໣͠ͳ͍
    ɾίϛχϡέʔγϣϯίετ͕͔͔Βͳ͍
    ɾͨ͘͞Μࢼ͢͜ͱ͕Ͱ͖Δ

    View Slide

  66. ։ൃ͕ߴ଎Խ͞ΕΔ͜ͱͰ
    େ୾ͳઓུΛऔΕΔΑ͏ʹͳΓ·͢
    ɾෳ਺ճͷ࢓༷มߋʹ΋ରԠͰ͖Δ
    ɾΤϯδχΞ͕ফ໣͠ͳ͍
    ɾίϛχϡέʔγϣϯίετ͕͔͔Βͳ͍
    ɾͨ͘͞Μࢼ͢͜ͱ͕Ͱ͖Δ

    View Slide

  67. ։ൃ͕ߴ଎Խ͞ΕΔ͜ͱͰ
    େ୾ͳઓུΛऔΕΔΑ͏ʹͳΓ·͢
    ɾෳ਺ճͷ࢓༷มߋʹ΋ରԠͰ͖Δ
    ɾΤϯδχΞ͕ফ໣͠ͳ͍
    ɾίϛχϡέʔγϣϯίετ͕͔͔Βͳ͍
    ɾͨ͘͞Μࢼ͢͜ͱ͕Ͱ͖Δ

    View Slide

  68. ։ൃ͕ߴ଎Խ͞ΕΔ͜ͱͰ
    େ୾ͳઓུΛऔΕΔΑ͏ʹͳΓ·͢
    ɾෳ਺ճͷ࢓༷มߋʹ΋ରԠͰ͖Δ
    ɾΤϯδχΞ͕ফ໣͠ͳ͍
    ɾίϛχϡέʔγϣϯίετ͕͔͔Βͳ͍
    ɾͨ͘͞Μࢼ͢͜ͱ͕Ͱ͖Δ

    View Slide

  69. ։ൃ͕ߴ଎Խ͞ΕΔ͜ͱͰ
    ɾෳ਺ճͷ࢓༷มߋʹ΋ରԠͰ͖Δ
    ɾΤϯδχΞ͕ফ໣͠ͳ͍
    ɾίϛχϡέʔγϣϯίετ͕͔͔Βͳ͍
    ɾͨ͘͞Μࢼ͢͜ͱ͕Ͱ͖Δ
    େ୾ͳઓུΛऔΕΔΑ͏ʹͳΓ·͢

    View Slide

  70. ࣄ࣮͸զʑͷதʹͳ͍

    View Slide

  71. ͨ͘͞Μࢼ͢
    ࢼͨ͠ճ਺෼αʔϏε͸੒௕͍ͯ͘͠

    View Slide

  72. ·ͱΊ

    View Slide

  73. ࠓ೥ͷय़ϦϦʔε༧ఆ

    View Slide

  74. FirebaseͰ։ൃ͞Ε͍ͯ·͢

    View Slide

  75. ςΫϊϩδʔΛެ։͍ͯ͠·͢

    View Slide

  76. ৽αʔϏεΛߴ଎Ͱ։ൃ͍͖ͯ͠·͢ɻ

    View Slide

  77. ಈ͖ग़ͨ͠ΫοΫύουͷ
    Ϗδωεʹ͝஫໨͍ͩ͘͞

    View Slide

  78. Thank you.

    View Slide