[回顧録]グーグー~?Kukkaクローンプロジェクトレビュー(1)
*クローンプロジェクトの場合は、チームメンバーとコミュニケーションし、DBモデリング設計からセンター機能の実装まで、コードを直接作成してください.
1. Why Kukka?
バナーとメインリストカードスライドを実現 登録時にNavバックエンドとの通信でユーザ名とカート数を受信する機能 .スクロールY値によるNav処理
5.新しい試みと深い学習
1. Why Kukka?
Guccaを選んだ理由は、初めてサイトに登録したときに感じた「清潔」な印象.
余計な画面は学習開発の立場で、必要な機能しか体現できません!という考えが生まれた.
バナースライド、カードコンポーネント、詳細ページ計算ロジック、カート機能を表示します.
今まで学んだことを応用しながら、少し高い機能を体現できると確信しています.
最初のプロジェクトなので、欲張るよりも、勉強のポイントを考え直すことに重点を置いたほうがいいです.
2.チームミーティング
意外にも1人足りず、4人で種目を始めたため、一丸となった.
毎日のように日常的な打ち合わせやスプレーの打ち合わせをするときに、お互いの進捗状況を共有するのが1位です.
本当に間違いなく、コミュニケーションの面では、他のチームは自分がよくやったことを認めています.
様々なクラス名や変数名をどのように表現するかを決める会議も重要ですが、このプロジェクトを通じてそれぞれどの部分を学び、改善したいのか、進捗状況をどのように共有したいのかなど、チーム間で会話を行い、スタートすれば、より良いコミュニケーションができます.
3.デモビデオ
4.技術スタック/機能分担
テクノロジースタック
フロントエンド:React、Router、Sass
バックエンド:Node.js Express, My SQL, Prisma, Bycrypt, JWT
API Document : https://documenter.getpostman.com/view/15514335/Uyr4Jegx
役割と機能の分担
最初のプロジェクトに入る前に、バックエンドにもっと興味を持っている私はバックエンドを重点にしたいと思っています.
そのため、バックエンドでカートを担当するC.R.U.D API.
フロントはホームページ全体を作成することを決定し、フロントが実現する代表的な機能は以下の通りである.
userefとuserefectを使用して
意外にも1人足りず、4人で種目を始めたため、一丸となった.
毎日のように日常的な打ち合わせやスプレーの打ち合わせをするときに、お互いの進捗状況を共有するのが1位です.
本当に間違いなく、コミュニケーションの面では、他のチームは自分がよくやったことを認めています.
様々なクラス名や変数名をどのように表現するかを決める会議も重要ですが、このプロジェクトを通じてそれぞれどの部分を学び、改善したいのか、進捗状況をどのように共有したいのかなど、チーム間で会話を行い、スタートすれば、より良いコミュニケーションができます.
3.デモビデオ
4.技術スタック/機能分担
テクノロジースタック
フロントエンド:React、Router、Sass
バックエンド:Node.js Express, My SQL, Prisma, Bycrypt, JWT
API Document : https://documenter.getpostman.com/view/15514335/Uyr4Jegx
役割と機能の分担
最初のプロジェクトに入る前に、バックエンドにもっと興味を持っている私はバックエンドを重点にしたいと思っています.
そのため、バックエンドでカートを担当するC.R.U.D API.
フロントはホームページ全体を作成することを決定し、フロントが実現する代表的な機能は以下の通りである.
userefとuserefectを使用して
テクノロジースタック
フロントエンド:React、Router、Sass
バックエンド:Node.js Express, My SQL, Prisma, Bycrypt, JWT
API Document : https://documenter.getpostman.com/view/15514335/Uyr4Jegx
役割と機能の分担
最初のプロジェクトに入る前に、バックエンドにもっと興味を持っている私はバックエンドを重点にしたいと思っています.
そのため、バックエンドでカートを担当するC.R.U.D API.
フロントはホームページ全体を作成することを決定し、フロントが実現する代表的な機能は以下の通りである.
userefとuserefectを使用して
5.新しい試みと深い学習
最初のプロジェクトを行い、新しい学習、感じ、経験がたくさんあります.
まず、私が学んだことを再応用するコードと新しい理解の概念を紹介したいと思います.
5-1. Frontend[ホーム]
これは、リストページで使用するリストカードコンポーネントを組み合わせて、ホームページで再利用するコードです.
最初はオーバーラップ部分をハードコーディングして書きましたが,学習反応の観点からは非効率なコードでした.
コードを個別のコンポーネントとして削除する必要はないが,コードの再利用性とメンテナンス性の向上が開発者のタスクと宿命であると考え,再コンポーネント化を行った.
最も重要なのは,propsでパラメータを伝達する論理を明確に理解していないため,より自分でやりたい仕事であり,幸い期待通り,この過程をよりよく理解できることである.# Main.js
const [lists, setLists] = useState({ productList: [],});
//GET API로 받은 리스트 데이터 필터링 후 메인 리스트카드로 props 넘겨줌
const filtered_subscriptrion_list = lists.productList.filter(
list => list.id > 9 && list.id <= 11);
const filtered_bouquet_list = lists.productList.filter(list => list.id <= 10);
<MainListCard
key={filtered_bouquet_list.id}
lists={filtered_bouquet_list}
bgColor="#fafafa"
title="꽃이 필요한 순간,"
subTitle="꾸까 꽃다발"
text="더보기"
linkTo={goToLink}
/>
# MainListCard.js
//리스트 페이지에서 쓰이는 리스트카드 컴포넌트 재활용
function MainListCard({lists, bgColor, containerMargin, title, subTitle, text, linkTo, hide,}){
return(
<section className={styles.mainContainer}
style={{backgroundColor: bgColor, margin: containerMargin}}>
<div className={styles.flowerList} ref={cardRef}>
{lists.map(list => (<ListCard key={list.id} list={list} />))}
</div>
<button
type="button"
className={styles.turn_list_card_btn}
onClick={nextListCard}
style={{ display: hide }}
> 〉 </button>
</section>
);
5-2. Backend[ショッピングバスケットAPI]
プロジェクトをするときに一番知りたい部分はバックエンドAPIの使用位置です.
だからショッピングバスケットAPIはすべてのC.R.U.Dを作ることができるので、必ず担当して成功する機能を担当しなければなりません!
単純に頭の中で論理を考えるのは難しく、スプレッドシートで記入すると、思想も整理され、理解度も向上します.
APIを作成する際には、フロントが要求する値、バックエンドが応答するデータを明確にすることが重要です.
Backend(1):ミドルウェアトークン検証コード
わがチームのショッピングバスケットは会員しか使えない機能なので、関連する大規模な検証プログラムが必要です.
コードを書くときに悩むのは,毎回トークン検証コードを作成するかどうかを疑うためである.
バックグラウンドセッションで学習するミドルウェア関数という概念を思いつき、応用したいと思っていました.
スタックオーバーフローとjwtハブを参照して、対応するミドルウェアを作成し、postmanとして、POST APIが正常に動作しているのを見て、私の喜びは本当に理不尽です.//토큰 검증을 통해 유저 ID를 얻는 미들웨어
const jwt = require("jsonwebtoken");
const getUserIdByVerifyToken = async (req, res, next) => {
const token = req.headers.token;
if (token) {
jwt.verify(token, process.env.SECRET_KEY, (err, decoded) => {
if (err) {
res.status(400).json({ message: err.message });
} else {
req.userId = decoded.id;
next();
}
});
} else {
res.status(403).json({ message: "token is not provided" });
}
};
module.exports = { getUserIdByVerifyToken };
Backend(2):カートGET APIのCartDao構造
これは、フロントから受信したデータを非同期でデータベースの各行に格納するコードです.
順番の並び方を使うように感じましたが、どこに書くのか分からず悩んでしまいました.
何度も検索した結果,Prisma公式ハブのDiscussionコードからヒントを得た.
結局、ある論理で書く感覚と執着感が問題解決の鍵になっているようだ.//디테일 페이지에서 담은 상품을 DB의 product_carts 테이블에 담는 cartDao.js
const createUserCart = async (userId, productId, addOptionId, quantity, totalPrice) => {
return addOptionId.forEach (
async (optionId) =>
await prisma.$queryRaw`
INSERT INTO product_carts
(user_id, product_id, add_option_id, quantity, totalPrice, order_status) VALUES
(${userId}, ${productId}, ${optionId}, ${quantity}, ${totalPrice}, "주문 전")`
);
};
6.再包装が必要なコード
これは私たちがグーグーページのNav-barです.
ログイン後、トークンがローカルストレージに入ると、お会いできて嬉しいです. {userName}
!ターゲットは、直接レンダリングされた部分とカートの数で入力された部分です.
ただし、stateとして管理すべきトークンをconstと宣言したため、再レンダリングが発生しないという問題が発生した.
リノベーション期間中にこの部分を修復したいのですが、チーム内で優先的に解決すべき問題が発生したため、まだ修復されていません.context APIを使用して修復中で、再構築後のコードをアップロードすべきことが解決しました!// 리팩토리전 Nav 코드
const token = localStorage.getItem('token');
const [counter, setCounter] = useState(0);
const [isLogIn, setIsLogIn] = useState(false);
useEffect(() => {
fetch('/carts', {
headers: {
'Content-Type': 'application/json',
token: token,
},
})
.then(res => res.json())
.then(data => {
setCounter(data.userCart.length);
});
}, [isLogIn]);
useEffect(() => {
if (token) {
setIsLogIn(true);
} else {
setIsLogIn(false);
}
}, []);
7.耳を傾ける
プロジェクトをするとき、思いがけない問題にぶつかるたびに、新しい問題がないと感じます.
前回出会った問題や、すでに経験した問題があるので、いくつかの応用能力で解決できる問題がたくさんあります.
そのため、同じ過程を経験した人からアドバイスを聞くことは、開発者に必要な品格の一つです.
7-1. 予定工期*10
プロジェクトが始まると、指導者はみんなに一言言った.
つまり、予定された勤務期間にさらに0を加算します.
この言葉は私たちが機能を貪るたびにお互いにコントロールする魔法の単語になった.
そこで,リストレイアウトが完了し,データをロードするAPIが完了すると,早々にフロントエンド−バックエンドを貼り付けた.
プロジェクトの4日目だけです.これは一緒に振り返ったときに、これが一番いい選択だと思わせる良い決定であり、アドバイスをよく吸収した例でもあります.**
7-2. データ構造の重要性
バックグラウンドからフロントにデータを渡す場合,フロントの立場を考慮して1つの配列にデータを置いたことがある.しかし,3つの配列を地図に変換して支柱としてサブアセンブリに渡す過程で地図が多く用いられる.
この点に対する助けと提案から,データ構造を深く考慮していないクエリー文を記述したことに気づいた.
オブジェクトと配列を含むデータの違いは考えられなかった…!
配列は、オブジェクトを表す異なる属性を含む類似の属性の集合です.
8.実施エラー
地獄のGit Revert
以下は、表示されないGitリストアログです.
事件の経緯は私たちの楽屋のmainが詰まっていない状況で、私はうっかりPRをホームページに送ってしまいました.
誰も気づいていない中、PR承認後に合併してスタートしました.
幸いなことに、mainを以前の状態に戻す方法を知り、あるチームメンバーがPR対象をDevelopに変更すべきかどうかの意見を出しました.
ダイヤルバック命令の原理を正しく認識できず、ダイヤルバックをmain以外のdevelopmentに誤って置き、このように私たちは遠い川を越えた.
revertとの戦闘から1時間後、revertを行うと、以前にコミットした内容を含むrevertブランチが生成され、PR対象に上書きされることに気づいた.
git命令が知らずに乱用したのではないかという教訓を得た.のみ
改めて感じましたが、ダウンジャケットでのコラボレーションでは、経路をしっかり確認し、どこにとどめるべきかを考え続けましょう!
このように問題を解決した後、解決方法を正しく理解すれば、その経験の価値は大いに異彩を放つ.ギリバート、、疲れていますが、価値のある経験です.
最初のプロジェクトなので、本当に振り返ることがたくさんあります.
そのため、私のもっと深い物語を含む回顧録は第2弾で行われます:)
Reference
この問題について([回顧録]グーグー~?Kukkaクローンプロジェクトレビュー(1)), 我々は、より多くの情報をここで見つけました
https://velog.io/@songyi7091/회고록-꾸꾸까까-Kukka-클론-프로젝트-회고-1
テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol
# Main.js
const [lists, setLists] = useState({ productList: [],});
//GET API로 받은 리스트 데이터 필터링 후 메인 리스트카드로 props 넘겨줌
const filtered_subscriptrion_list = lists.productList.filter(
list => list.id > 9 && list.id <= 11);
const filtered_bouquet_list = lists.productList.filter(list => list.id <= 10);
<MainListCard
key={filtered_bouquet_list.id}
lists={filtered_bouquet_list}
bgColor="#fafafa"
title="꽃이 필요한 순간,"
subTitle="꾸까 꽃다발"
text="더보기"
linkTo={goToLink}
/>
# MainListCard.js
//리스트 페이지에서 쓰이는 리스트카드 컴포넌트 재활용
function MainListCard({lists, bgColor, containerMargin, title, subTitle, text, linkTo, hide,}){
return(
<section className={styles.mainContainer}
style={{backgroundColor: bgColor, margin: containerMargin}}>
<div className={styles.flowerList} ref={cardRef}>
{lists.map(list => (<ListCard key={list.id} list={list} />))}
</div>
<button
type="button"
className={styles.turn_list_card_btn}
onClick={nextListCard}
style={{ display: hide }}
> 〉 </button>
</section>
);
//토큰 검증을 통해 유저 ID를 얻는 미들웨어
const jwt = require("jsonwebtoken");
const getUserIdByVerifyToken = async (req, res, next) => {
const token = req.headers.token;
if (token) {
jwt.verify(token, process.env.SECRET_KEY, (err, decoded) => {
if (err) {
res.status(400).json({ message: err.message });
} else {
req.userId = decoded.id;
next();
}
});
} else {
res.status(403).json({ message: "token is not provided" });
}
};
module.exports = { getUserIdByVerifyToken };
//디테일 페이지에서 담은 상품을 DB의 product_carts 테이블에 담는 cartDao.js
const createUserCart = async (userId, productId, addOptionId, quantity, totalPrice) => {
return addOptionId.forEach (
async (optionId) =>
await prisma.$queryRaw`
INSERT INTO product_carts
(user_id, product_id, add_option_id, quantity, totalPrice, order_status) VALUES
(${userId}, ${productId}, ${optionId}, ${quantity}, ${totalPrice}, "주문 전")`
);
};
これは私たちがグーグーページのNav-barです.
ログイン後、トークンがローカルストレージに入ると、お会いできて嬉しいです.
{userName}
!ターゲットは、直接レンダリングされた部分とカートの数で入力された部分です.ただし、stateとして管理すべきトークンをconstと宣言したため、再レンダリングが発生しないという問題が発生した.
リノベーション期間中にこの部分を修復したいのですが、チーム内で優先的に解決すべき問題が発生したため、まだ修復されていません.context APIを使用して修復中で、再構築後のコードをアップロードすべきことが解決しました!
// 리팩토리전 Nav 코드
const token = localStorage.getItem('token');
const [counter, setCounter] = useState(0);
const [isLogIn, setIsLogIn] = useState(false);
useEffect(() => {
fetch('/carts', {
headers: {
'Content-Type': 'application/json',
token: token,
},
})
.then(res => res.json())
.then(data => {
setCounter(data.userCart.length);
});
}, [isLogIn]);
useEffect(() => {
if (token) {
setIsLogIn(true);
} else {
setIsLogIn(false);
}
}, []);
7.耳を傾ける
プロジェクトをするとき、思いがけない問題にぶつかるたびに、新しい問題がないと感じます.
前回出会った問題や、すでに経験した問題があるので、いくつかの応用能力で解決できる問題がたくさんあります.
そのため、同じ過程を経験した人からアドバイスを聞くことは、開発者に必要な品格の一つです.
7-1. 予定工期*10
プロジェクトが始まると、指導者はみんなに一言言った.
つまり、予定された勤務期間にさらに0を加算します.
この言葉は私たちが機能を貪るたびにお互いにコントロールする魔法の単語になった.
そこで,リストレイアウトが完了し,データをロードするAPIが完了すると,早々にフロントエンド−バックエンドを貼り付けた.
プロジェクトの4日目だけです.これは一緒に振り返ったときに、これが一番いい選択だと思わせる良い決定であり、アドバイスをよく吸収した例でもあります.**
7-2. データ構造の重要性
バックグラウンドからフロントにデータを渡す場合,フロントの立場を考慮して1つの配列にデータを置いたことがある.しかし,3つの配列を地図に変換して支柱としてサブアセンブリに渡す過程で地図が多く用いられる.
この点に対する助けと提案から,データ構造を深く考慮していないクエリー文を記述したことに気づいた.
オブジェクトと配列を含むデータの違いは考えられなかった…!
配列は、オブジェクトを表す異なる属性を含む類似の属性の集合です.
8.実施エラー
地獄のGit Revert
以下は、表示されないGitリストアログです.
事件の経緯は私たちの楽屋のmainが詰まっていない状況で、私はうっかりPRをホームページに送ってしまいました.
誰も気づいていない中、PR承認後に合併してスタートしました.
幸いなことに、mainを以前の状態に戻す方法を知り、あるチームメンバーがPR対象をDevelopに変更すべきかどうかの意見を出しました.
ダイヤルバック命令の原理を正しく認識できず、ダイヤルバックをmain以外のdevelopmentに誤って置き、このように私たちは遠い川を越えた.
revertとの戦闘から1時間後、revertを行うと、以前にコミットした内容を含むrevertブランチが生成され、PR対象に上書きされることに気づいた.
git命令が知らずに乱用したのではないかという教訓を得た.のみ
改めて感じましたが、ダウンジャケットでのコラボレーションでは、経路をしっかり確認し、どこにとどめるべきかを考え続けましょう!
このように問題を解決した後、解決方法を正しく理解すれば、その経験の価値は大いに異彩を放つ.ギリバート、、疲れていますが、価値のある経験です.
最初のプロジェクトなので、本当に振り返ることがたくさんあります.
そのため、私のもっと深い物語を含む回顧録は第2弾で行われます:)
Reference
この問題について([回顧録]グーグー~?Kukkaクローンプロジェクトレビュー(1)), 我々は、より多くの情報をここで見つけました
https://velog.io/@songyi7091/회고록-꾸꾸까까-Kukka-클론-프로젝트-회고-1
テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol
地獄のGit Revert
以下は、表示されないGitリストアログです.
事件の経緯は私たちの楽屋のmainが詰まっていない状況で、私はうっかりPRをホームページに送ってしまいました.
誰も気づいていない中、PR承認後に合併してスタートしました.
幸いなことに、mainを以前の状態に戻す方法を知り、あるチームメンバーがPR対象をDevelopに変更すべきかどうかの意見を出しました.
ダイヤルバック命令の原理を正しく認識できず、ダイヤルバックをmain以外のdevelopmentに誤って置き、このように私たちは遠い川を越えた.
revertとの戦闘から1時間後、revertを行うと、以前にコミットした内容を含むrevertブランチが生成され、PR対象に上書きされることに気づいた.
git命令が知らずに乱用したのではないかという教訓を得た.のみ
改めて感じましたが、ダウンジャケットでのコラボレーションでは、経路をしっかり確認し、どこにとどめるべきかを考え続けましょう!
このように問題を解決した後、解決方法を正しく理解すれば、その経験の価値は大いに異彩を放つ.ギリバート、、疲れていますが、価値のある経験です.
最初のプロジェクトなので、本当に振り返ることがたくさんあります.
そのため、私のもっと深い物語を含む回顧録は第2弾で行われます:)
Reference
この問題について([回顧録]グーグー~?Kukkaクローンプロジェクトレビュー(1)), 我々は、より多くの情報をここで見つけました https://velog.io/@songyi7091/회고록-꾸꾸까까-Kukka-클론-프로젝트-회고-1テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol