[{"data":1,"prerenderedAt":1156},["ShallowReactive",2],{"article-private-develop-released":3},{"id":4,"title":5,"body":6,"category":1141,"createdAt":1143,"description":1144,"extension":1145,"index":1146,"meta":1147,"navigation":1148,"path":1149,"publish":1148,"seo":1150,"series":1146,"seriesTitle":1146,"stem":1151,"tag":1152,"thumbnail":1154,"updatedAt":1146,"__hash__":1155},"articles\u002Farticles\u002Fprivate-develop-released.md","リリースまで進み続けるんだ！これはお前が始めた個人開発だろ？",{"type":7,"value":8,"toc":1096},"minimark",[9,21,35,41,44,47,51,54,57,76,79,90,93,96,100,104,112,115,118,135,138,141,144,148,162,170,173,176,187,190,193,210,213,216,219,222,225,311,315,321,326,329,332,335,346,349,358,369,372,376,379,382,385,389,392,395,398,412,415,418,421,435,438,452,455,469,472,475,478,481,504,512,535,538,541],[10,11,12,13,20],"p",{},"この記事は",[14,15,19],"a",{"href":16,"rel":17},"https:\u002F\u002Fqiita.com\u002Fadvent-calendar\u002F2022\u002Findividual-developers",[18],"nofollow","Qiita 個人開発 Advent Calendar 2022の12\u002F11の記事","になります。",[10,22,23,24,29,30],{},"こんにちはjunです。2022年の11月に",[14,25,28],{"href":26,"rel":27},"https:\u002F\u002Froute-share.net",[18],"RouteShare","というユーザー投稿型webサービスをリリースしました。地図に情報を入力し、ワードプレスの様に記事を作成し、いろんな道や場所の魅力を投稿できます。ユーザーが自由に地図に情報を入力して地図を見ながら記事を読めること、地図（地理情報）を中心としたコンテンツです。ツーリスト、サイクリスト、ライダーなど、いろんな場所に旅行したり地理情報をまとめる人向けになっています。ぜひご興味ありましたらご利用ください。メールアドレスかGoogleアカウントで登録が可能です。",[14,31,34],{"href":32,"rel":33},"https:\u002F\u002Froute-share.net\u002Fabout",[18],"RouteShareについてより知りたい方はこちら",[36,37],"image-render",{":src":38,":width":39,":center":40,":current":40},"'large_logo.png'","'300px'","true",[10,42,43],{},"さて、宣伝はここまでにしておきます。このサービスは企画、設計、デザイン、実装、デプロイ、支払い全てに至って自分で行った、個人開発プロダクトです。途中、友人にコンセプトや使い心地のレビューはもらいましたが基本的には一人で開発しました。開発開始から９ヶ月で作り上げたサービスで、これからは運営や改善を繋げながら収益化を目指そうと思っています。",[10,45,46],{},"今回の記事ではリリースに至るまでの、企画、設計、デザイン、実装、デプロイ、支払いなど実務的な内容を書こうと思います。結構長くなると思いますが、個人開発をしてみたい人の参考になればと思います。適宜、好きなセクションに飛ばしてみてみてください。",[48,49,50],"h2",{"id":50},"ここでいいう個人開発とサービス種別について",[10,52,53],{},"人によっては「個人開発」の意味合いやどこまでやるかという感覚が異なると思いますので、あらかじめここで解説する「個人開発」というものを定義しておきます。",[10,55,56],{},"ここでいう個人開発は",[58,59,60,64,67,70,73],"ul",{},[61,62,63],"li",{},"公開され、第三者が利用することができる。",[61,65,66],{},"誰かの役に立つ、得になるもの。",[61,68,69],{},"最終的に事業として収益化を目指すもの。",[61,71,72],{},"一人または少人数で法人格がない人がつくるもの、開発に関して給与が発生しない。",[61,74,75],{},"会社に勤務していたり、学生だったり何かしらの別の所属を持っている中、個人的に開発するもの",[10,77,78],{},"としておきます。そのため",[58,80,81,84,87],{},[61,82,83],{},"収益化を目的としない、趣味的・実験的な内容",[61,85,86],{},"オープンソース開発、活動",[61,88,89],{},"法人格を持って運営する。大人数で金の力でなんとかする",[10,91,92],{},"といったことではないとしておきます。まあ「法人格を持って運営する」あたりは「事業として収益化を目指すもの」とぶつかったりするので、あくまで「こんぐらいのレベル感なんだなー」と思ってください。",[10,94,95],{},"また、作成するサービス種別はwebサービスとしておきます。ただしある程度のセクションはネイティブ開発など他種別の個人開発にも応用できると思います。",[48,97,99],{"id":98},"作成した個人開発の開発技術的概要","作成した個人開発の開発・技術的概要",[101,102,103],"h3",{"id":103},"開発概要",[58,105,106,109],{},[61,107,108],{},"作成期間:9ヶ月",[61,110,111],{},"実作成人月:3人月ぐらい？",[10,113,114],{},"2022年の2月から同年11月にリリースしました。退勤後や土日を使用して作成したので、期間は9ヶ月かかりました。アプリケーションの構成自体はそれほど複雑でないので、実際は3人月ぐらいでできそうな規模です。",[10,116,117],{},"内訳としては",[58,119,120,123,126,129,132],{},[61,121,122],{},"2~3月: 設計と企画、技術検証",[61,124,125],{},"3~4.5月: ボイラーテンプレート的な開発",[61,127,128],{},"4.5~8月: 基幹機能開発",[61,130,131],{},"9~10月: レスポンシブや細かい機能、調整",[61,133,134],{},"11月: 最終確認、デプロイ作業",[10,136,137],{},"という感じです。構想自体は結構前から練っていたのでそれほど時間はとりませんでした。",[101,139,140],{"id":140},"技術概要",[10,142,143],{},"公開サービスなのでセキュリティ上可能限りで紹介します。",[145,146,147],"h4",{"id":147},"フロントエンド",[58,149,150,153,156,159],{},[61,151,152],{},"Nuxt.js（SSR）",[61,154,155],{},"Google Map API",[61,157,158],{},"Editor.js",[61,160,161],{},"Bootstrap-vue",[10,163,164,165,169],{},"フロントエンドは得意なNuxt.jsを使用して構築しました。基本的なUIはNuxt.jsにて記述し、Google Map を用いた地図操作・レンダリングは別途、JSでクラスを作成しNuxtと連携しました。また、記事の作成の際には",[14,166,158],{"href":167,"rel":168},"https:\u002F\u002Feditorjs.io\u002F",[18],"というブロックベースのエディタを採用しました。",[10,171,172],{},"デザインは正直得意ではないので、デザインの４原則とブランドカラーを決めてBootstrapをカスタマイズして実装しました。またモーダルなどUIを作るのが面倒だったという理由もあります。",[145,174,175],{"id":175},"バックエンド",[58,177,178,181,184],{},[61,179,180],{},"Laravel（フレームワーク）",[61,182,183],{},"mysql（DB）",[61,185,186],{},"apache（Webサーバ）",[10,188,189],{},"バックエンドは得意なLaravelを使用しました。",[145,191,192],{"id":192},"その他",[58,194,195,198,201,204,207],{},[61,196,197],{},"Git",[61,199,200],{},"Google App engine (フロントエンドサーバ)",[61,202,203],{},"Google Domains",[61,205,206],{},"Github actions",[61,208,209],{},"Docker （仮想化）",[10,211,212],{},"フロントではNode.jsを動かせるGoogle App engineを使用しています。理由は後述します。",[10,214,215],{},"以降のセッションでは開発に関する細かい内容を解説していきます。",[48,217,218],{"id":218},"詳細なリリースまでの流れ",[101,220,221],{"id":221},"とりあえずこの記事で伝えたいこと",[10,223,224],{},"結構長くなるので、重要なことを箇条書きしました。それぞれアンカーを張っていますので気になるとこを見てみてください。",[58,226,227,233,239,245,251,257,263,269,275,281,287,293,299,305],{},[61,228,229],{},[14,230,232],{"href":231},"#%E3%81%BE%E3%81%9A%E3%81%AF%E8%87%AA%E5%88%86%E3%81%8C%E3%81%82%E3%82%8B%E3%81%A8%E3%81%84%E3%81%84%E3%81%AA%E3%81%A8%E6%80%9D%E3%81%A3%E3%81%9F%E3%81%93%E3%81%A8%E3%82%92%E5%A4%A7%E5%88%87%E3%81%AB","まずは自分があるといいなと思ったことを大切に",[61,234,235],{},[14,236,238],{"href":237},"#%E4%BC%81%E7%94%BB%E6%99%82%E3%81%AF%E3%82%A2%E3%82%B8%E3%83%A3%E3%82%A4%E3%83%AB%E3%82%B5%E3%83%A0%E3%83%A9%E3%82%A4%E3%82%92%E8%AA%AD%E3%82%82%E3%81%86","企画時はアジャイルサムライを読もう",[61,240,241],{},[14,242,244],{"href":243},"#%E7%AB%B6%E5%90%88%E3%82%92%E8%AA%BF%E3%81%B9%E3%81%A6%E9%9C%80%E8%A6%81%E3%82%92%E8%AA%BF%E3%81%B9%E3%82%8B","競合を調べて需要を調べる",[61,246,247],{},[14,248,250],{"href":249},"#%E3%81%97%E3%81%A3%E3%81%8B%E3%82%8A%E5%85%B7%E7%8F%BE%E5%8C%96%E3%81%99%E3%82%8B","しっかり具現化する",[61,252,253],{},[14,254,256],{"href":255},"#%E3%82%84%E3%82%89%E3%81%AA%E3%81%84%E3%81%93%E3%81%A8%E3%82%92%E6%B1%BA%E3%82%81%E3%82%8B%E3%81%AE%E3%81%AF%E9%87%8D%E8%A6%81","やらないことを決めるのは重要",[61,258,259],{},[14,260,262],{"href":261},"#%E5%8F%8E%E7%9B%8A%E5%8C%96%E3%81%AF%E8%A6%96%E9%87%8E%E3%81%AB%E5%85%A5%E3%82%8D%E3%81%86","収益化は視野に入ろう",[61,264,265],{},[14,266,268],{"href":267},"#%E6%94%AF%E5%87%BA%E3%81%AF%E3%81%A8%E3%81%AB%E3%81%8B%E3%81%8F%E3%82%B1%E3%83%81%E3%82%8C","支出はとにかくケチれ",[61,270,271],{},[14,272,274],{"href":273},"#%E3%83%87%E3%82%B6%E3%82%A4%E3%83%B3%E3%81%AF%E3%82%B7%E3%83%B3%E3%83%97%E3%83%AB%E3%81%AB%E8%80%83%E3%81%88%E3%82%8B","デザインはシンプルに考える",[61,276,277],{},[14,278,280],{"href":279},"#%E6%8A%80%E8%A1%93%E3%81%AF%E8%87%AA%E5%88%86%E3%81%8C%E5%BE%97%E6%84%8F%E3%81%AA%E3%82%82%E3%81%AE%E3%82%92","技術は自分が得意なものを",[61,282,283],{},[14,284,286],{"href":285},"#%E5%AE%8C%E7%92%A7%E3%82%92%E7%9B%AE%E6%8C%87%E3%81%95%E3%81%AA%E3%81%84","完璧を目指さない",[61,288,289],{},[14,290,292],{"href":291},"#%E3%83%86%E3%82%B9%E3%83%88%E3%80%81Git%E3%81%AF%E3%81%A7%E3%81%8D%E3%82%8B%E3%82%88%E3%81%86%E3%81%AB","テスト、Gitはできるように",[61,294,295],{},[14,296,298],{"href":297},"#%E7%9B%AE%E6%A8%99%E6%97%A5%E3%82%92%E6%B1%BA%E3%82%81%E3%82%8B","目標日を決める",[61,300,301],{},[14,302,304],{"href":303},"#%E7%B6%99%E7%B6%9A%E7%9A%84%E3%81%AA%E9%81%8B%E5%96%B6%E3%81%A8%E9%96%8B%E7%99%BA%E3%82%92%E3%82%81%E3%81%96%E3%81%99","継続的な運営と開発をめざす",[61,306,307],{},[14,308,310],{"href":309},"#%E5%A4%96%E9%83%A8%E3%82%B5%E3%83%BC%E3%83%93%E3%82%B9%E5%88%A9%E7%94%A8%E6%99%82%E3%81%AF%E8%A6%8F%E7%B4%84%E3%82%92%E3%81%97%E3%81%A3%E3%81%8B%E3%82%8A%E8%AA%AD%E3%82%80","外部サービス利用時は規約をしっかり読む",[101,312,314],{"id":313},"企画構想","企画、構想",[10,316,317,320],{},[318,319,314],"em",{},"では、プロジェクトの基礎となる部分です。頭の中にある曖昧なアイデアや目的を言語化し、はっきりさせることで実際に作りたいサービスがわかってきます。設計を行うことでアイデアを実現させる、ソフトウェア構成を考えようやく開発に至ります。",[10,322,323],{},[324,325],"span",{"id":232},[145,327,328],{"id":328},"開発に至る経緯",[36,330],{":src":331,":width":39,":center":40,":current":40},"'process.svg'",[10,333,334],{},"RouteShareを作成する経緯としては私がサイクリストで、色んなとこにツーリングを行く経験が元になっています。その際、ルートを作るときにGoogle My Mapを使用していました。どんなルートにしようかを考えるとき他人のブログやストリートビューを見たりしていました。しかし、",[58,336,337,340,343],{},[61,338,339],{},"もっと総合的にまとめられているサイトがないこと",[61,341,342],{},"住所名や写真だと「実際にそこはどのへんなの？」と地図を見ながら情報を掲載したい",[61,344,345],{},"地図の埋め込みや表示を行っているサイトがない",[10,347,348],{},"とルートの共有できるサービスってあんまないのでは？と思う様になりました。",[10,350,351,352,357],{},"またツーリング友達が",[14,353,356],{"href":354,"rel":355},"https:\u002F\u002Fwww.itmedia.co.jp\u002Fnews\u002Farticles\u002F1907\u002F03\u002Fnews096.html",[18],"ルートラボ","というサービスがなくなり、ルートの共有に困っているということも聞きました。",[58,359,360,363,366],{},[61,361,362],{},"ユーザーが手軽に地図に情報を掲載できる",[61,364,365],{},"地図や文章を共有できる",[61,367,368],{},"公開されて無料でできるサービス",[10,370,371],{},"というサービスが無いかを考えました。ともあれ最初の構想においてはまず自分の体験や、必要だなと思うこと、あるといいなと思うサービスを思うかべたり、既存アプリの欠点を探すといいです。",[10,373,374],{},[324,375],{"id":238},[145,377,378],{"id":378},"企画の時に役に立つアジャイルサムライ",[10,380,381],{},"ちょっと脱線しますが、企画の段階には「アジャイルサムライ」という名著が役に立ちます。チームでのアジャイル開発に関する内容がメインですが、プロジェクトの立案や管理に関する具体的な方法に関してのTipsが多いです。チームだけでなく個人開発でも十分利用できることが書いてあります。ぼっち開発なので第４章の「全体像を捉える」以降が特に役に立ちます。以降の内容でもアジャイルサムライで出てくる内容がちょくちょく出てきます。",[10,383,384],{},"個人開発を行うときはアジャイルサムライを購入してみたり、他にも企画やプロジェクト管理に関する著書を買ってみてもいいでしょう。",[10,386,387],{},[324,388],{"id":244},[145,390,391],{"id":391},"競合調査",[36,393],{":src":394,":width":39,":center":40,":current":40},"'search.svg'",[10,396,397],{},"競合調査をする理由は、",[58,399,400,403,406,409],{},[61,401,402],{},"機能がダダ被りであった場合、例えリリースしても「ユーザーがこのアプリを使うメリット」が見つからない状態となるのを防ぐ。",[61,404,405],{},"自分が知らない機能を探し出す。",[61,407,408],{},"なぜ収益化できているのか、人気なのかの理由を知る。",[61,410,411],{},"差別化できることを探す。",[10,413,414],{},"単純なコピーアプリでなく「ユーザーがこのアプリを使うメリット」を出せる様にします。上記で「案外無いんじゃないのかな？」と書きましたが、案外あったりします笑。車輪の再発明にならない様にまず落ち着いて、ググってみます。",[10,416,417],{},"RouteShareの場合、まずGoogle Map、Strava、Ride with GPSを調査しました。いくつかのアプリは有料機能の無料期間があったので、サブスク購入して調査しました。また、自分が知らないアプリがあるかもしれないため、「ルート　共有　アプリ」とか「ツーリング　おすすめ　アプリ」と素人気分になって調べたり、友人に聞き取りをおこないました。",[10,419,420],{},"競合調査の結果、一部のアプリには",[58,422,423,426,429,432],{},[61,424,425],{},"地図に情報入力ができる",[61,427,428],{},"記事を作成できる",[61,430,431],{},"ナビゲーション機能がある",[61,433,434],{},"自動トラッキング記録機能がある",[10,436,437],{},"といった考えていた機能とかぶるとこ、思いつかなかった機能がありました。各種サービスごとに",[58,439,440,443,446,449],{},[61,441,442],{},"特徴的な機能",[61,444,445],{},"ターゲット",[61,447,448],{},"何ができて、どんなユーザーのニーズを満たすか",[61,450,451],{},"何が足りないか",[10,453,454],{},"をリストアップしていきます。「何が足りないか」は「開発に至る経緯」で思った欲しい機能で比較すると良いです。そうすると",[58,456,457,460,463,466],{},[61,458,459],{},"Google Map は地図入力のUIと情報量は群を抜いているが、StravaやRide with GPSのような他のユーザーと情報を共有しにくい。コミュニティー機能がない。",[61,461,462],{},"Stravaはアスリート向けで、どちらかというとトレーニング記録サービスという感じ。有料機能でルート作成機能はあるが、一つのラインしか描画できない。",[61,464,465],{},"Ride with GPSは作りたい内容と似ていて、地図機能や記事作成機能がそれなりにある。しかしサイクリスト向けであり、一つのラインしか描画できない（無料の場合）。記事のUIが微妙。",[61,467,468],{},"YAMAPは登山者向け。トラッキング記録機能やオフライン地図保存がある。情報の共有機能もあるがリッチな入力は難しい。",[10,470,471],{},"などアプリごとの欠点・あった方がいいなと思うとこもありました。既存のサービスを調査したら次は、開発するプロジェクトをはっきりさせていきます。",[145,473,474],{"id":474},"エレベータピッチ",[36,476],{":src":477,":width":39,":center":40,":current":40},"'undraw_presentation_re_sxof.svg'",[10,479,480],{},"競合調査を行い意外と被っていたり、何を作ればいいかなどアイデアが曖昧な状態であることが多いです。アジャイルサムライである「全体像を捉える」を行います。特にエレベーターピッチと呼ばれる",[58,482,483,486,489,492,495,498,501],{},[61,484,485],{},"「潜在的なニーズを満たしたり、抱えている課題を解決したり」したい",[61,487,488],{},"「対象顧客」向けの",[61,490,491],{},"「プロダクト名」というプロダクトは",[61,493,494],{},"「プロダクトのカテゴリー」である。",[61,496,497],{},"これは「重要な利点、対価に見合う説得力のある理由」ができ、",[61,499,500],{},"「代替手段の最右翼」とは違って、",[61,502,503],{},"「差別化の決定的な特徴」が備わっている。",[10,505,506,507,511],{},"以上のテンプレートを使って個人開発で",[508,509,510],"strong",{},"作るプロダクトが具体的になんであり、誰のものなのかということ","をはっきりさせます。RouteShareでは以下の様になりました。",[58,513,514,517,520,523,526,529,532],{},[61,515,516],{},"「自身の旅程や訪れた道、場所の感想・写真を共有」したい",[61,518,519],{},"「旅行者、ドライバー、ライダー、サイクリスト、街歩き」向けの",[61,521,522],{},"「Route Share」というプロダクトは",[61,524,525],{},"「地図と記事を用いる地図型SNSサービス」である。",[61,527,528],{},"これは「旅程や地理情報の共有し、地域や場所、道の魅力を発信する」ことができ",[61,530,531],{},"「StravaとGoogle Map」とは違って",[61,533,534],{},"「地図上の描画とレポート機能による共有とコミュニティ機能」が備わっている",[10,536,537],{},"となりました。自分がサイクリストだったこともあり、ターゲットを限定的にしていましたが「旅行者、ドライバー、ライダー、サイクリスト、街歩き」など「ツーリスト」全体にターゲットを広げました。",[10,539,540],{},"他に自分がなぜ旅行が好きなのかを深掘りして、「地域や場所、道の魅力を発信する」という「個人の記録」にとどまらない使い方ができるサービスを作りたいという方向性が定まりました。",[542,543,544,547,550,553,556,567,570,576,584,589,594,599,619,624,629,634,639,642,645,649,653,656,659,663,666,669,672,675,687,690,693,696,699,701,704,707,711,714,717,720,723,726,729,732,735,761,764,767,770,773,776,779,782,785,788,791,794,797,800,803,806,809,812,815,819,822,825,829,832,835,838,852,855,857,860,862,865,879,882,885,888,902,905,907,916,919,922,925,929,932,935,938,941,944,947,951,954,957,960,963,966,969,972,975,979,982,985,993,996,999,1002,1006,1009,1012,1019,1022,1033,1036,1040,1043,1046,1049,1052,1055,1059,1062,1065,1077,1080,1083,1086,1093],"sapn",{"id":250},[145,545,546],{"id":546},"パッケージリスト",[10,548,549],{},"大まかなプロダクトの方向性が定まり、次はパッケージリストというものを作ります。これは本の表紙の様なもので、１枚の紙にプロダクトのイメージ図、特徴機能、キャッチコピーを掲載します。ただこの中では特徴機能が重要な気がします。",[10,551,552],{},"この「特徴機能」は最初にいくつか候補を挙げておきます。それらの候補から最終的に３つに絞ってパッケージに載せます。しかしここで重要なのは「このプロダクトで何ができるのか」をはっきりさせることです。",[10,554,555],{},"この際、アジャイルサムライでは「フィーチャーでなく効能をつたえる」ことを重視しています。フィーチャーとは一言ですむ特徴や機能名のことです。RouteShareの場合、地図機能、記事機能、SNSサービスといった用語が当てはまります。しかしこれらの「特徴」や「機能名」を言ったとこでユーザーからしてみれば、「で、それらは一体何がいいの？」となっていまいます。これらの「特徴」や「機能名」でユーザーの",[58,557,558,561,564],{},[61,559,560],{},"どんなニーズを満たすのか",[61,562,563],{},"どんな役に立つことやメリットがあるのか",[61,565,566],{},"何ができるようになるのか",[10,568,569],{},"を具体的に言える様にしましょう。アジャイルサムライでは上記３つのことを「効能」と言っています。RouteShareでは以下の様になりました。",[571,572,573],"blockquote",{},[10,574,575],{},"地図にルートの描画、スポットの設置ができる。",[58,577,578,581],{},[61,579,580],{},"わかりやすいルートを作ることができる。どこの情報かわかりやすい。",[61,582,583],{},"地図でどこに何があるかを直ぐに把握できる。",[571,585,586],{},[10,587,588],{},"地図のルートスポットから記事にリンクをはれる。",[58,590,591],{},[61,592,593],{},"地図と記事の関連性がわかりやすいので、楽に内容を共有できる。",[571,595,596],{},[10,597,598],{},"地図＋記事の投稿を作成できる。",[58,600,601,604,607,610,613,616],{},[61,602,603],{},"自分が行った旅先の情報を他人に共有できる。",[61,605,606],{},"プランナーとして利用でき、仲間とルートや旅程を共有しやすい。",[61,608,609],{},"道路情報や気をつけることなど、実際に行かないとわからない様な詳細な情報を共有でき、取得できる。",[61,611,612],{},"自分たちの町などのおすすめの回り方を発信できる。",[61,614,615],{},"写真も投稿できるのでダイアリーとして、旅の思い出を残すことができる。",[61,617,618],{},"直感的に場所を把握することができる。",[571,620,621],{},[10,622,623],{},"設定したパスやスポットからどこに行ったかのデータを取得される",[58,625,626],{},[61,627,628],{},"検索で場所、ルートから投稿を検索できる様になる。自分がいきたいと思っている、知りたいと思っている場所の情報を地図から探すことができる。",[571,630,631],{},[10,632,633],{},"投稿にタグを貼ることができる。",[58,635,636],{},[61,637,638],{},"都道府県、地名、やりたいことから目的のルートを探ることができる。",[10,640,641],{},"まずは「〜ができる」「〜する」という特徴を書いたら、「それによってユーザーにとってどう役に立つのか」を箇条書きで書きます。",[10,643,644],{},"パッケージは作っても作らなくてもいいですが、作った方がやる気は上がる気がします笑。",[10,646,647],{},[324,648],{"id":256},[145,650,652],{"id":651},"やることやらないこと","やること、やらないこと",[10,654,655],{},"方向性が決まり、実装したい機能が定まってきたら選定を行いましょう。RouteShareも開発していくとわかってきた技術的難点やコストの問題で端折った機能がたくさんあります。個人開発ではスコープ管理が自由な分、「こーした方がユーザーにとっていいのでは..」と考えることが多くなります。やること、やらないことを決めないと実装したい機能が後からどんどん湧いて、リリースが先延ばしになってしまい、最終的に途中で頓挫することが多いです。",[10,657,658],{},"正直言うとそのサービスが需要があるか、ニーズにマッチしているかは市場に出して使ってみてもらわないと効果測定ができません。後々の設計や技術選定、開発を行いながら「やらないこと（あとでやる）」と「やること」を選定していくといいです。経験的に「やらないこと」に振れないかと第一に考えるとスコープが無限増殖しません。",[10,660,661],{},[324,662],{"id":262},[145,664,665],{"id":665},"収益化構想",[36,667],{":src":668,":width":39,":center":40,":current":40},"'undraw_investing_re_bov7.svg'",[10,670,671],{},"このサービスでは収益化を考えています。私自身は無料のサービスには限界があり、最終的には何らかの形で有料化・収益化することでより良いサービスになると考えています。使用ユーザーが増えることはその分、サーバスペックも要求されるようになりますし、当初のニーズに対する答え合わせもできるようになってきます。より安定的に、素早くビジネスとサービス品質を加速させるためにはマネタイズは重要になります。",[10,673,674],{},"RouteShareも一大プラットフォームになるべく、収益化の構想は考えています。ただし、正直言うとここは自分でも曖昧で「取らぬ狸の皮算用」をしているのでは？と感じているとこがあります。RouteShareでは以下の方法での収益化パターンを考えています。",[676,677,678,681,684],"ol",{},[61,679,680],{},"広告添付",[61,682,683],{},"有料機能、サブスク化",[61,685,686],{},"法人掲載枠を設ける",[688,689,680],"h5",{"id":680},[10,691,692],{},"Google Adsenseなどのサービスを利用して広告を添付します。シンプルで導入はしやすいです。しかし広告添付は収益化のためには非常に多くのユーザーが必要であり、また不安定です。",[688,694,683],{"id":695},"有料機能サブスク化",[10,697,698],{},"一部機能に制限をつけ利用したい場合は有料会員としてサブスクを求める方法です。使用しているユーザーや料金、収益状況が把握しやすく収益が安定しやすいです。しかし有料で買いたいほどのニーズの解決や無料枠との差別化が必要であり、収益は単価を多く取るか少なくするかによって必要なユーザー数に依存するようになります。",[688,700,686],{"id":686},[10,702,703],{},"私は最終的にはこの方法での収益化を目指しています。法人と契約して優先的に掲載できる枠を設けたり、法人のみが使用できる機能を提供、企画を立案してプロモーションを行うことです。サービスにそれなりにユーザーがいて、法人に対してそれなりの利益を提供するまでサービスの成熟と営業が必要なりますが、toCな収益形態よりも安定的で発展性のある収益化形態です。",[10,705,706],{},"収益化方法は色々とありますが、少なくともどのように収益を確保するかの構想は初期の設計段階でも考えておくといいです。",[10,708,709],{},[324,710],{"id":268},[145,712,713],{"id":713},"支出はシビアに感覚で判断しない",[10,715,716],{},"いきなり企画の段階でいうのも何ですが、個人の広報力やブランドがない状態でデプロイしても正直ユーザーは来てくれません。個人開発のツイートがバズってたくさん！というのは偶に見ますが非常に稀です。",[10,718,719],{},"正直大方のサービスは運営していき、少しずつユーザーを増やしていきます。サービスがいつバズって収益化まで繋がるかは「サービスがどれほどの期間運営しているか」に依存します。下手すると年単位になることもあります。",[10,721,722],{},"その時、支出の存在はリリース後の悩みの種になりますのでサーバ代は必ず計算して、いかにケチれるようにすることが重要です。",[10,724,725],{},"私の場合Laravelを使用するAPIサーバのためにVPSを新規に借りようとしましたが、計算しても月2000円は追加の出になるため、実は別のブログで運用しているレンタルサーバに導入しています笑",[10,727,728],{},"フロントに関してはGoogle App Engineを使用して必要な時に稼働するようにしました。とにかく支出はケチれるようにして、かかる費用は毎月監視するようにしましょう。",[145,730,731],{"id":731},"リスク",[10,733,734],{},"ここまではどんな機能を実装しようか、サービスがどうなるのかワクワクしながら進めたと思います。しかし機能を実装するで上にどんなリスクが生じるのかを考えましょう。実際に企画初期段階では以下のように考えていました。",[58,736,737,740,743,746,749,752,755,758],{},[61,738,739],{},"ユーザーが本当に何を望んでいるかわからない",[61,741,742],{},"Stravaなどの強い競合からどうユーザーを引き込むか",[61,744,745],{},"最初の広報とユーザーに広めるか",[61,747,748],{},"ルートパスからの検索の実装方法",[61,750,751],{},"検索コスト",[61,753,754],{},"リッチテキストの実装",[61,756,757],{},"Google API のリクエストコスト",[61,759,760],{},"本当に開発しきれるか",[10,762,763],{},"この時さまざまなリスクが思い浮かびますが、そのリスクが「自分が制御できるか」で対応すべきかを決めましょう。例えば「このサービスは受けるだろうか」「ユーザーのニーズをあてているか」は正直考えるだけ無駄なリスクです。なぜなら「その答えはユーザーのみが知っていて、そもそも市場に出さないとわからない」からです。もちろん競合調査などをして可能な限りリスクを下げることが必要ですが、自分がどれほどそのリスクに対して対策を取れるか、制御できるかを念頭にしておくことが大切です。",[10,765,766],{},"リスクをよく考えることで早い段階で課題を明らかにでき、プロジェクトが進んでから爆弾が爆発するのを防ぐことができます。あと気持ちがすっきりします笑",[145,768,769],{"id":769},"プロジェクトの管理",[10,771,772],{},"プロジェクトの管理はGoogle ドキュメントとスプレッドシートで行いました。企画書などはドキュメントにまとめ、スコープ、実装機能表などをスプレッドシートで管理しました。",[10,774,775],{},"個人開発であればJiraやBacklogよりもスプレッドシートぐらいで十分です。チームでも2,3人ぐらいまでなら大丈夫そうです。これらの記録は後で見返したりする時に便利ですし、課題管理はプロジェクトがどれほど進んでいるかの指標になるので作成しておくといいです。",[10,777,778],{},"また設計に関しては基本的にスプレッドシート、図などはDiagrams.netを使用しました。",[101,780,781],{"id":781},"設計",[36,783],{":src":784,":width":39,":center":40,":current":40},"'undraw_dev_productivity_re_fylf.svg'",[10,786,787],{},"企画・構想が決まったら設計を行います。ここからようやくエンジニアっぽいことをやっていきます。",[145,789,790],{"id":790},"サイトマップと画面イメージを作成する",[10,792,793],{},"機能については企画の段階でまとめました。サービスではユーザーが画面上のUIを通じてデータの更新・閲覧を行います。すなわち「どんな画面が表示され、そこで何ができて、どう遷移するのか」を把握します。",[10,795,796],{},"いきなり画面図を書くのは大変なので最初はサイトマップというものを作成して「どんなページ（画面）」があれば良いのか？を決定します。webサービスの場合はURLのパスも決めてしましましょう。",[36,798],{":src":799,":center":40,":current":40},"'sitemap.png'",[10,801,802],{},"サイトマップは名称、パス、タイトル、用途を記述し、認証や特定のミドルウェア的な制御を行う場合は追加で記入しておきます。",[10,804,805],{},"サイトマップを作成したらワイヤーフレームを作成します。ワイヤーフレームはページにどんなパーツを表示させ、どんな要素（データなど）を表示するのかを整理することができます。フロント部分で表示する要素を整理することで、実際にどんなテーブル構成にすればいいかを知ることができるようになります。",[145,807,808],{"id":808},"ワークフロー図を作る",[10,810,811],{},"次はワークフロー図を作成します。ここでいうワークフロー図はプログラム的な処理のフローです。例えばGoogle連携についてのフローは以下のような画像で表現しました。",[36,813],{":src":814,":center":40,":current":40},"'wf.png'",[145,816,818],{"id":817},"er図を作る","ER図を作る",[10,820,821],{},"ER図にてテーブル設計を行います。フロント・バック内でのフローや要素を整理するとER図はすんなりとできることが多いです。",[36,823],{":src":824,":center":40,":current":40},"'er.png'",[10,826,827],{},[324,828],{"id":274},[145,830,831],{"id":831},"デザインを作る",[10,833,834],{},"エンジニアで一番大変なのはこのデザインの部分です。ワイヤーフレームをもとにして実際のデザインを作成します。私はAdobe XDを使用して画面ごとのデザイン、UI、パーツを作成しました。ここはFigmaでもXDでも大丈夫ですが、コンポーネントやレイヤー分けできるツールを使用した方がいいです。",[10,836,837],{},"デザインセンスがないと感じる場合",[58,839,840,843,846,849],{},[61,841,842],{},"他のサイトを参考にする",[61,844,845],{},"デザインの4原則を守る",[61,847,848],{},"ブランドカラーを決める",[61,850,851],{},"CSSフレームワークを使用する",[10,853,854],{},"以上４点を意識します。",[688,856,842],{"id":842},[10,858,859],{},"RouteShareはTwitter、Qiita、Stravaを参考にしてそれらを混ぜ込んだ形にしました。よく見ると似ている箇所があります。もちろん完全にパクるのは良くないですが、デザイン・UIの参考として作成した方が、少なくともダサいデザインにはならないと思います。",[688,861,845],{"id":845},[10,863,864],{},"これを守るだけでなんかいい感じになります。デザインの4原則とは",[676,866,867,870,873,876],{},[61,868,869],{},"近接",[61,871,872],{},"整列",[61,874,875],{},"強弱",[61,877,878],{},"反復",[10,880,881],{},"の4点です。",[36,883],{":src":884,":center":40,":current":40},"'list.png'",[10,886,887],{},"例えば上記は登録された投稿一覧ですが、",[58,889,890,893,896,899],{},[61,891,892],{},"タイトルと投稿場所、サマリーとユーザー情報はある程度マージンをとる。",[61,894,895],{},"それぞれの要素のパディングを同じにして開始位置を揃える。",[61,897,898],{},"背景色を利用して強弱、領域の区別をできるようにする",[61,900,901],{},"下のボタンなど似ている要素は似たレイアウトと感じで表示する",[10,903,904],{},"この4点を意識していくと結構いい感じになります。",[688,906,848],{"id":848},[10,908,909,910,915],{},"ブランドを決めます。RouteShareは道路の新型青看板の青色をもとにしています。その色を起点にして",[14,911,914],{"href":912,"rel":913},"https:\u002F\u002Fwww.colorhexa.com\u002F",[18],"ColorHexa","などで輝度方向のパターンの色を使用するといいです。基本的にはブランドカラーはこのようにし決定して、色々とカラフルにしない方がいいです。しかしUIではキャンセル、確認といった箇所では赤・緑・黄色などを使用してしても問題ありません。",[36,917],{":src":918,":center":40,":current":40},"'bar.png'",[688,920,851],{"id":921},"cssフレームワークを使用する",[10,923,924],{},"デザインとCSS・UI系の工数を省きたい場合はCSSフレームワークを使用した方がいいです。RouteShareはBootstrap-vueを使用しています。フレームワークは好きなものを使用して大丈夫ですが、上記のブランドカラーなどを適用したりプロパティーを変更できるフレームワークを使用した方がいいです。",[10,926,927],{},[324,928],{"id":280},[145,930,931],{"id":931},"技術選定",[10,933,934],{},"設計やデザインを作成して技術選定を行います。リリースを重視し、個人開発であればあなたの得意なスタックで大丈夫です。正直いうと、ユーザーにとってみればバックエンドに何を使っていようが、動いていればまずいいのです。あとはあなたの開発効率の問題になります。個人開発ではモチベーションや初版リリースまで辿り着けるかが第一の関門となっています。",[10,936,937],{},"そのため技術的な勉強という要素を入れてしまうと、途中で挫折しかねません。もちろん選定したスタックによってはコストがかかってしまうものもあります。しかしその中でもコストと開発難易度がちょうど良くなるスタックを選択した方がいいです。",[10,939,940],{},"一番最初のことろはサーバーレス環境で全部おさめてやりたいとも思いましたが、デプロイの設定やFireBaseなどは初めてだったこともありやめました。LaravelとフロントエンドはVue.jsという構成も考えましたが、フロントの構築は１つのフレームワークで行った方が自分的にはかなり楽だったので、LaravelをバックにフロントはNuxt.jsという構成を取りました。",[10,942,943],{},"APIサーバとフロントサーバを用意する必要がありましたが、Google App engineの無料枠を利用できる様にしたり、APIサーバーも構成を工夫することで費用を抑えることができました。",[10,945,946],{},"１番の悩みの種はGoogle Map APIの課金ですが解決方法は見つけ、まずはリリースを優先するために地図表示はGoogle Mapにまずは任せることにしました。",[10,948,949],{},[324,950],{"id":310},[145,952,953],{"id":953},"外部サービスの利用時は規約をしっかり理解する",[10,955,956],{},"もし外部サービスのAPIなどを使用する時は規約を読んでおきましょう。公開して、収益を求めるサービスなので規約違反はNGです。",[10,958,959],{},"RouteShareの場合はGoogle Map APIで規約違反をしてしまう機能を開発しそうになった時がありました。RouteShareは地図にセットしたラインやスポットを計算して、周辺地図の画像をサムネイルとして設定できる機能があります。↓",[36,961],{":src":962,":width":39,":center":40,":current":40},"'sample_card.png'",[10,964,965],{},"このとき当初はGoogle Map static image apiを使用しており、バックエンドで画像のURLにリクエストしてレスポンスの画像をこちらのサーバに置いておくという方法をとっていました。しかしこの方法は規約違反であり、必ずブラウザからstatic image apiのURLを記載することとの規約がありました。",[10,967,968],{},"現在は地図サービスのAPIを別途契約して、タイル画像を取得して生成するようにしました。知らぬ間に規約違反することもあるので、規約は難しいですが一読しておくことをお勧めします。",[101,970,971],{"id":971},"開発",[10,973,974],{},"設計、技術選定、デザインがある程度完成したら早速開発を始めましょう。正直のこの開発時期が一番、挫折しやすいと思います。ここでは開発時に大切なことを書いておく程度にします。",[10,976,977],{},[324,978],{"id":286},[145,980,981],{"id":981},"とにかく作り上げること",[10,983,984],{},"個人開発の完成は自身のモチベに依存するため",[58,986,987,990],{},[61,988,989],{},"Better than Nothing",[61,991,992],{},"Done is better than perfect",[10,994,995],{},"の気持ちを常に持っていた方がいいです。開発をしている際に一部の設計を見直したり、機能を追加・変更することがあると思いますがスケジュールとスコープがオーバーしないようにしましょう。",[10,997,998],{},"私も開発をしている時に「こうした方がいいのでは？」「もっと最適な方法があるのでは？」と思って思うように開発が進まないことがありました。",[10,1000,1001],{},"もちろん期限内に最善を尽くすの良いですが、完璧を求めようとするとズルズルと起源と対応すべきコストが増大します。途中で色々面倒になったり、仕事が忙しくなり放置..ということになります。今の自分が持っている技術スタックの最善を尽くして開発を進めてください。",[10,1003,1004],{},[324,1005],{"id":292},[145,1007,1008],{"id":1008},"保守性とテスト性は重要",[10,1010,1011],{},"作り上げることは重要ですが、品質を犠牲にするわけではありません。リリースはゴールではなく、マイルストーンであり経過点です。むしろサービスはリリースしてから始まりますので、リリース後の保守や改善のことも考えなければなりません。",[10,1013,1014,1015,1018],{},"その際に",[318,1016,1017],{},"作り上げることを言い訳に","自分ですらコードの内容を把握できないものや、保守性の低いものはリリース後のモチベを下げる要員になります。",[10,1020,1021],{},"継続的な開発のために",[58,1023,1024,1027,1030],{},[61,1025,1026],{},"保守性を高める記述を心がける",[61,1028,1029],{},"可能な限りテストコードを書いて、改善コードをデプロイしやすくする",[61,1031,1032],{},"バージョン管理は必ず導入する",[10,1034,1035],{},"以上のことはやっておいて損はありません。",[10,1037,1038],{},[324,1039],{"id":298},[145,1041,1042],{"id":1042},"毎日コツコツやること",[10,1044,1045],{},"あとはもう時間をかけるのみです。個人開発は睡眠時間を削ったり土日を使うことで捻出しました。仕事が終わったら直ぐに個人開発の環境を立ち上げておきます。",[10,1047,1048],{},"まとまった休みにやるよりも、毎日ちょっとずつの方が結果的にリリース達成の確率は上がります。",[10,1050,1051],{},"ここはもう、何とか時間を作ってください。心の中に「リリースまで進み続けるんだ！これはお前が始めた個人開発だろ？」と問いかけるようにしてください。",[10,1053,1054],{},"そしてリリース日やマイルストーンなど明確な目標期限を定めてください。個人開発は管理が自由な分、開発時間などを伸ばしがちです。期限を定めることでダラダラと続けることを防げますし、スコープが増大することも防げます。",[10,1056,1057],{},[324,1058],{"id":304},[101,1060,1061],{"id":1061},"リリース構成",[10,1063,1064],{},"開発進み完成してきたらリリースの準備を行います。リリース方法は使用している開発構成によってまちまちですが、基本的にはgitを用いてリリースを管理できるようにしたほうがいです。可能な限り、手動での反映を少なくできるようにした方がいいです。",[10,1066,1067,1068,1072,1073,1076],{},"RouteShareではgithub上で",[1069,1070,1071],"code",{},"release",",",[1069,1074,1075],{},"test","といったブランチを作成して、本番環境もそれらのブランチからプルするようにしています。フロントエンドはGoogle App engineを使用しており、ビルドからサーバへのデプロイはgithub actionsで自動的に行えるようにしています。",[10,1078,1079],{},"ドメインの設定やSSLなどやることが多いですが、この辺はリリース時に1回で済むので頑張って調べてください。（私もそのうち書きます..）",[10,1081,1082],{},"今後の機能リリースではできる限り本番へのデプロイが楽になるような構成を最初に心掛けた方がいいです。",[48,1084,1085],{"id":1085},"個人開発のススメ",[10,1087,1088,1089,1092],{},"色々端折ってしまった所がありますが、内容は以上となります。本記事では開発したRouteShareの詳細はお伝えしませんでしたが、また違う記事で機能について開発面で細かく解説した記事でも書こうと思います。ぜひ旅行好きな方は",[14,1090,28],{"href":26,"rel":1091},[18],"を使ってみてください！",[10,1094,1095],{},"デプロイから1ヶ月たち、まだユーザー数やトラフィックも少ないですが今後は運用に注力したり、リリースまでに間に合わなかった機能を実装しようと思います。エンジニアであればこのように製品を自ら開発してビジネスを始めることができます。ディベロッパー的な視点や技術だけでなく、経営や運営、企画の力も付きます。総合的な力をつけたいエンジニアはサービスの大小あれど、色々な人に使ってもらえるアプリケーションを開発してみるといいと思います！",{"title":1097,"searchDepth":1098,"depth":1098,"links":1099},"",3,[1100,1102,1111,1140],{"id":50,"depth":1101,"text":50},2,{"id":98,"depth":1101,"text":99,"children":1103},[1104,1105],{"id":103,"depth":1098,"text":103},{"id":140,"depth":1098,"text":140,"children":1106},[1107,1109,1110],{"id":147,"depth":1108,"text":147},4,{"id":175,"depth":1108,"text":175},{"id":192,"depth":1108,"text":192},{"id":218,"depth":1101,"text":218,"children":1112},[1113,1114,1126,1134,1139],{"id":221,"depth":1098,"text":221},{"id":313,"depth":1098,"text":314,"children":1115},[1116,1117,1118,1119,1120,1121,1122,1123,1124,1125],{"id":328,"depth":1108,"text":328},{"id":378,"depth":1108,"text":378},{"id":391,"depth":1108,"text":391},{"id":474,"depth":1108,"text":474},{"id":546,"depth":1108,"text":546},{"id":651,"depth":1108,"text":652},{"id":665,"depth":1108,"text":665},{"id":713,"depth":1108,"text":713},{"id":731,"depth":1108,"text":731},{"id":769,"depth":1108,"text":769},{"id":781,"depth":1098,"text":781,"children":1127},[1128,1129,1130,1131,1132,1133],{"id":790,"depth":1108,"text":790},{"id":808,"depth":1108,"text":808},{"id":817,"depth":1108,"text":818},{"id":831,"depth":1108,"text":831},{"id":931,"depth":1108,"text":931},{"id":953,"depth":1108,"text":953},{"id":971,"depth":1098,"text":971,"children":1135},[1136,1137,1138],{"id":981,"depth":1108,"text":981},{"id":1008,"depth":1108,"text":1008},{"id":1042,"depth":1108,"text":1042},{"id":1061,"depth":1098,"text":1061},{"id":1085,"depth":1101,"text":1085},[1142],"learning","2022-12-11","ユーザー投稿型webサービスの個人開発をリリースするまでの道のり","md",null,{},true,"\u002Farticles\u002Fprivate-develop-released",{"title":5,"description":1144},"articles\u002Fprivate-develop-released",[1153],"dev_exp","private-develop-released\u002Fthumbnail.jpeg","nztFX4zrPEZhku2rJ4fzSsXPLzjLH78Rqjadot2TAvk",1780987141499]