๐ณ : ๊ถ์์ง
๐น : ๊น๋์ฐ
๐ : ์ค์์ฐ
- reduce๋ฅผ ํ์ฉํ์ฌ ํ๋ก๋ฐ์ด๋๊ฐ ์ฌ๋ฌ ๊ฐ์ผ ๊ฒฝ์ฐ, ํฉ์ณ์ฃผ๋ IssueProvider๋ฅผ ๊ตฌํํ์ต๋๋ค.
const IssueProvider = ({ contexts, children }) => contexts.reduce( (prev, context) => createElement(context, { children: prev, }), children );
- Issue ํ์ด์ง์ Store๋ฅผ ์ ์ฉํ์ฌ ์ด์ ์์ฑ / ๋ฆฌ์คํธ / ์ด์ ๋ฆฌ์คํธ ํค๋ ๋ฑ์์ ๋ชจ๋ ์ํ๊ด๋ฆฌ๊ฐ ๊ฐ๋ฅํ๋๋ก ๋ฆฌํฉํ ๋งํ์์ต๋๋ค.
- ์์ฑ์ ์ถ๊ฐ ํํฐ ์ต์ ์ ํ ์ ํ์ ์ฐฝ์ผ๋ก ๋ชฉ๋ก์ ๋์ฐ๊ฒ ๊ตฌํํ๋ค.
- ์ด ๋,
import { Dropdown } from 'semantic-ui-react'
๋ฅผ ์ฌ์ฉํด๋ดค๋๋ฐ ํด๋์ค๋ฅผ ๋ ๋ฐ๋ก ๋ง๋ค์ด์ ๋์์ธ์ ์ก์์ค์ผํด์ ๋ถํธํจ๋ ์์๋ค.
- Reducer๋ฅผ ์ฌ์ฉํ์ฌ issueDetail Store์ isOpen ๊ฐ์ ๋ณ๊ฒฝํด์ฃผ์๋ค.
- reducer ํจ์์์ ์๋ก์ด ์ํ๋ฅผ ๋ง๋ค ๋์๋ ๋ถ๋ณ์ฑ์ ์ง์ผ์ฃผ์ด์ผ ํ๊ธฐ ๋๋ฌธ์ spread ์ฐ์ฐ์๋ฅผ ์ฌ์ฉ reducer ๋ด๋ถ์์ ์คํ๋ ๋ ์ฐ์ฐ์๋ฅผ ์ฌ์ฉํ์๋ค.
- useContext์ useReducer๋ฅผ ์ฌ์ฉํ์ฌ ๊ตฌํํ์๋ค.
- Label ํ์ด์ง์์ ๋น์ทํ๊ฒ ๊ตฌํ์ ํ๋ ๋ด์ฉ์ด๋ผ ์ด์ ๋ณด๋ค๋ ๊นจ๋ํ๊ฒ ์ฝ๋๋ฅผ ์์ฑํ ์ ์์๋ค. ํ์ง๋ง ์์ง๋ ๊ฐ์ ํ ์ ์ด ๋ง์ด ๋จ์ ๊ฒ ๊ฐ๋ค.
@primer/octicons-react ์ค์น
import {
IssueOpenedIcon,
MilestoneIcon,
IssueClosedIcon,
} from '@primer/octicons-react';
- label ์์ฑ๊ณผ ์ ๊ฑฐ์ label ๋ชฉ๋ก์ ๋์ ์ผ๋ก ๊ด๋ฆฌํด์ผํ๋๋ฐ ๊ฐ๊ธฐ ๋ค๋ฅธ ํ์ผ(componenet)์์ ์ํ๋ฅผ ๊ด๋ฆฌํ๋ ๊ฒ์ด ์ด๋ ค์ ๋ค. useReducer์ dispatch ๋ฅผ ํ์ฉํ์ฌ ์ํ๋ฅผ ์ฝ๊ฒ ๊ด๋ฆฌํ ์ ์์์ ์๊ฒ ๋์๋ค.
export const labelReducer = (labels, { type, payload }) => {
switch (type) {
case 'SET_INIT_DATA':
return payload;
case 'PUT_LABEL':
return labels.map((label) => {
if (label.id === payload.id) {
label = payload;
}
return label;
});
case 'DELETE_LABEL':
return labels.filter((label) => label.id !== payload);
case 'NEW_LABEL_ADD':
return [...labels, payload];
default:
break;
}
};
- ์์ ๋ง์ฐฌ๊ฐ์ง๋ก ๋์ ์ผ๋ก ํญ์ด ์ด๋ฆฌ๊ณ ๋ซํ ํ์๊ฐ ์์๊ณ ์ด๋ฅผ reducer๋ฅผ ํตํด ํ์ฉํ ์ ์์๋ค. ๊ฐ๊ฐ์ ์ํฉ์ ๋ฐ๋ฅธ ๊ฐ์ ์ ์ํด์ฃผ์ด ํญ์ ์ํ๋ฅผ ๊ด๋ฆฌํ์๋ค.
export const newReducer = (isClickNew, { type }) => {
switch (type) {
case 'NEW_LABEL_TAB_OPEN':
return true;
case 'NEW_LABEL_TAB_CLOSE':
return false;
case 'NEW_LABEL_ADD':
return false;
default:
break;
}
};
- useState๋ฅผ ์ฌ์ฉํ์ฌ ํ ์ ๋ง๋ค์ด์ ํ์ด์ง๊ฐ ๋ ๋๋ง ๋ ๋ useEffect๋ก ํ๋ฒ๋ง fetchํ์ฌ ํ์ํ ์ด์์์ฑ์ ์ ๋ณด๋ฅผ ๊ฐ์ ธ์์ ๋์ ํ ๋นํ์๋ค. match๋ ๊ฐ URL์ ๋ค์ด๊ฐ๋ issueId๋ฅผ ๊ฐ์ ธ์๋ค.
- Open, Close์ ์ํ์ ๋ฐ๋ผ UI๋ฅผ ์กฐ๊ฑด๋ถ ๋ ๋๋ง ํ์ฌ ๋ค๋ฅด๊ฒ ๋ํ๋ด์๋ค.
export default function IssueDetailPage({ match, location }) {
const [issueAuthorInfo, setIssueAuthorInfo] = useState('');
const [issueId, setIssueId] = useState(1);
const userId = localStorage.getItem('userId');
const getIssueAuthorInfo = async () => {
const id = match.params.issueId;
setIssueId(id);
const options = getOptions();
const response = await fetch(GET_ISSUE(id), options);
const responseJSON = await response.json();
setIssueAuthorInfo(responseJSON.data[0]);
};
useEffect(() => {
getIssueAuthorInfo();
}, []);
๐ [FE] ์ฝ๋ฉํธ ์ ๋ ฅ ์ ์ฝ๋ฉํธ ์์ฑ ๋ฒํผ ํ์ฑํ ์ ๋ ฅ์ด ์๋์ด ์์ ์ ๋นํ์ฑํ
- onChange์ Ref, useState ๋ฅผ ์ด์ฉํด์ ๋ณ๊ฒฝ์ฌํญ์ ๋ฐ๋ก ๋ฐ์ํด์ฃผ๋ Handling ํจ์๋ฅผ ๋ง๋ค์ด ๋ฒํผ ํ์ฑํ๋ฅผ ๋์์์ผฐ๋ค.
const IssueCommentForm = ({ issueId, userId }) => {
const history = useHistory();
const commentRef = useRef(false);
const [comment, setComment] = useState('');
const [userImage, setUserImage] = useState('');
const createCommentData = () => {
if (commentRef.current.value === '') {
return;
}
const comment = {
userId: userId,
issueId: issueId,
content: commentRef.current.value,
};
- ์ปดํฌ๋ํธ ํด๋์ ๊ด๋ฆฌํ ํ์ผ๋ค์ด ๋ง์์ ธ ํ์๋ฅผ ํตํด ํด๋ ๊ตฌ์กฐ๋ฅผ ๊ตฌ์ฒดํํ์๋ค.
- ํด๋ ๊ตฌ์กฐ ์์
/components ใด /issue ใด /milestone ใด MilestoneHeader.jsx ใด Milestone.jsx ใด /shared ใด /button ใด /container ใด MainContainer.jsx ใด HeaderContainer.jsx
- ์ฌ๋ฌ item์์ ์ฌ์ฌ์ฉ์ด ๊ฐ๋ฅํ ์ปดํฌ๋ํธ๋ค์
shared
์ ๋ฃ๊ณ ๊ทธ ์ธ component๋ค์ ์์ ์ด ์ํitem(ex. milestone, issue)
ํด๋์ ๋ฃ๊ธฐ๋ก ๊ฒฐ์ ํ์๋ค.
- ํด๋ ๊ตฌ์กฐ ์์
- useState๋ฅผ ํ์ฉํด์ ๊ธ์ ์๊ฐ ๋ณ๊ฒฝ๋ ๋๋ง๋ค setTimeiot์ ํ์ฉํด์ 0.5์ด๋ง๋ค ๊ธ์ ์ ์ฒดํน์ ํ๋ค.
- useState๋ฅผ ํตํด ๋์ ์ผ๋ก ํ๋ฉด์ ๋ณํ์ํค๋ ๋ฐฉ์์ ๊ณต๋ถํ ์ ์์๋ค.
- ์ด์๋ฅผ ๋ณด์ฌ์ค ๋, ํ์ฌ ํ๋ฉด์ด ๋ ๋๋ง๋ ์๊ฐ๊ณผ ์ด์๊ฐ ์์ฑ๋ ์๊ฐ์ ์ฐจ๋ฅผ ๊ณ์ฐํ์ฌ ํ๋ฉด์ ๋ณด์ด๊ธฐ ์ํด ํจ์๋ฅผ ๊ตฌํํ๋ค.
- 60์ด ์ดํ๋ผ๋ฉด -> ์ด ๋จ์๋ก ํํ (seconds ago)
- 60๋ถ ์ดํ๋ผ๋ฉด -> ๋ถ ๋จ์๋ก ํํ (minutes ago)
- 60์๊ฐ ์ดํ๋ผ๋ฉด -> ์๊ฐ ๋จ์๋ก ํํ (hours ago)
- ๊ทธ ์ด์์ด๋ผ๋ฉด -> days ago๋ก ํํ
const result = (redValue * 0.299 + greenValue * 0.587 + blueValue * 0.114) / 255;
- ์๊น ๊ฐ์์ R, G, B ๊ฐ์ ๋ฝ์๋ด ์ ์์ ์ ์ฉํ์๋ค.
- ๊ฒฐ๊ณผ ๊ฐ์ด 0.5 ๋ณด๋ค ํฌ๋ฉด ๊ฒ์ ๊ธ์จ๋ฅผ 0.5 ๋ณด๋ค ์์ผ๋ฉด ํฐ์ ๊ธ์จ๋ฅผ ๋ฐํํด์ฃผ์๋ค.
- ์ด๋ฆ์ด
use
๋ก ์์ํ๊ณ , ์์์ ๋ค๋ฅธ Hook์ ํธ์ถํจ์ ํตํด custom hook์ ์ค๊ณํ ์ ์๋ค. - get ์์ฒญ์ ๋ณด๋ด ๋ฐ์ดํฐ๋ฅผ ๋ฐ๊ธฐ ์ ๊น์ง loading์ ๋์ฐ๋ ๋ถ๋ถ์ ์ฌํ์ฉํ ์ ์์ ๊ฒ ๊ฐ์ custom hook ์ผ๋ก ๋ถ๋ฆฌํ์๋ค.
- ์ป์ ์ ์ ์ ๋ณด๋ก JWT Token ์์ฑํ ํ๋ก ํธ๋ก ๋ฐํ
- ๋ฐํ ์ json ํํ๋ก ๋ฆฌํดํด์ค์ผ ํ๋ค.
- axios.post ๋ฐํ์ .then(res) ํ์์ผ๋ก ๋ฐ์์ฃผ์ด์ผ not found(404) Error๋ฅผ ํด๊ฒฐํ ์ ์๋ค.
- ๋ฐํ๋ ํ ํฐ์ ํ๋ก ํธ์ localstorage ์ ์ฅ.
res.json(๊ฐ)
์์ ๊ฐ ๋ถ๋ถ์ด ์๋ชป๋์ด๋ ์๋ฒ์์ ๋ณ๋ค๋ฅธ ์ค๋ฅ๋ฅผ return ํ์ง ์์์ ์๊ฒ ๋์๋ค.
- Header Link ์ถ๊ฐ
- babel-polyfill ์ ์ฉ
- runtime์ babel ๋ฌธ๋ฒ ๋ณํ์ด ์ผ์ด๋๋๋ก babel-polyfill์ ์ ์ฉ
- babel-polyfill์ ์ ์ฉํ์ง ์๋ ๊ฒฝ์ฐ, chrome์์ regeneratorRuntime ์๋ฌ๊ฐ ๋ฐ์ํ์ฌ ์ ์ฉ
- ์ด์ ๋ด์ฉ ์์ฑ ์ ํ์ฌ ์
๋ ฅ๋ ๊ธ์ ์ ํํ ๊ธฐ๋ฅ ๊ตฌํ
- ์๊ตฌ์ฌํญ์ 2์ด ๊ฐ๊ฒฉ์ด์์ง๋ง, ํ ์ด ๋๋ฌด ๊ธด ๊ฒ ๊ฐ์ 0.5์ด ๊ฐ๊ฒฉ์ผ๋ก ๊ธ์ ์๋ฅผ ์ฒดํนํ๋๋ก ๊ตฌํ
- React์์ useEffectํจ์๋ฅผ ์ฌ์ฉํ์ฌ ๊นํ OAuth์ CallBack URL์ ๊ฐ๋ ์ปดํฌ๋ํธ๋ฅผ ๋ง๋ค์ด์ URL์ code๋ฅผ parsing ํ์ฌ ๋ฐฑ์๋๋ก ์์ฒญ์ ๋ณด๋ด๊ฒ ์ค๊ณ.
- ๋ฐฑ์๋์์ ์ด๋ฅผ ๋ฐ์ access_token์ ์ป๊ณ , ์ ์ ์ ๋ณด๋ฅผ ์ป์.
- [FE] Client ํ๋ก์ ํธ ๊ตฌ์ถ
- [AS-IS] github ๋ก๊ทธ์ธ ํ์ด์ง, Main ํ์ด์ง, ์ด์ ์์ธ ํ์ด์ง, ์ด์ ๋ฑ๋ก ๊ธฐ๋ฅ ๊ฐ๋ฅ
- [BE] API Cors ์ค์ ์ ์ฉ
- [BE] API ๊ธฐ๋ฅ ์ถ๊ฐ ๋ฐ ๊ฐ์
- [AS-IS] Issue & Comment Assignee ์ ๋ณด ์ถ๊ฐ ๋ฐํ
- [AS-IS] status๊ฐ fail์ธ ๊ฒฝ์ฐ status ๊ฐ๋ง ๋๊ธฐ๋๋ก ์์
- [AS-IS] Github ๊ฐ์ ์ ์๋ก์ด user ์์ฑ์ imageURL ๋ฌธ์ ์์
- [AS-IS] ๋ชจ๋ ์ฌ์ฉ์(Assignee)๋ฅผ ๋ฐํํด์ฃผ๋ API ์ถ๊ฐ
- [AS-IS] Milestone ์ ๋ณด ๋ฐํ API ์ถ๊ฐ
- [AS-IS] Issue ์ญ์ API ์ถ๊ฐ
- [AS-IS] ๋ก๊ทธ์ธ ์ฌ๋ถ ๋ฐํํ๋ API ์ถ๊ฐ
- [AS-IS] label get API ์ถ๊ฐ
- ์ฐธ๊ณ ์ฝ๋:
/shared/App.jsx
- ๋ด vscode์์ prettier๊ฐ ์๋ ๊ฒฝ์ฐ ์๋ ์ฌ์ดํธ๋ฅผ ์ฐธ๊ณ ํด์ฃผ์ธ์
- Prettier๋ก Default Formatter ์ค์ ๋ฐฉ๋ฒ
vscode -> [ํ์ผ] -> [๊ธฐ๋ณธ์ค์ ] -> [์ค์ ] -> editor.default formatter ๋ณ๊ฒฝ
- src ๋๋ ํ ๋ฆฌ ๋ฐ์ ํ์ผ ์์ฑํด์ฃผ๊ธฐ
export const BASE_URL = 'http://118.67.131.96:3000/';
๊ตฌํ ๋ด์ฉ ๋ฐ ์์ ํ๋ ๋ด์ญ
- [Backend] ์ด์์ ํ ๋น๋ Assignee ์ด๋ฆ ์ธ์ ์ถ๊ฐ ์ ๋ณด ๋ฐํํด์ฃผ๊ธฐ
- userId, imageUrl ์ ๋ณด๋ฅผ ์ถ๊ฐํด์คฌ์ต๋๋ค.
- [Backend] ์ด์์ Comment ์ฌ์ฉ์์ ์ด๋ฆ ์ธ์ ์ด๋ฏธ์ง url, id ์ถ๊ฐ ๋ฐํํด์ฃผ๊ธฐ
- [Backend] ๋ชจ๋ ์ฌ์ฉ์(Assignee) ๋ฐํํด์ฃผ๋ API ์ ์ํ๊ธฐ
- [Backend] milestone get API ์์ ํ๊ธฐ
- [Backend] status -> fail์ธ ๊ฒฝ์ฐ status ๊ฐ๋ง ๋๊ธฐ๊ธฐ
- ๋ชจ๋ API ์ ๋ถ ๋ค ๊ณ ์น๊ธฐ
- [Backend] ์ด์ ์ญ์ ํ๊ธฐ
- [Backend] Github ๊ฐ์ ์ ์๋ก์ด user ์์ฑ์ imageURL ๋ฌธ์ ๊ณ ์น๊ธฐ
- [Backend] ๋ก๊ทธ์ธ ์ฌ๋ถ ๋ฐํํ๋ API ๋ง๋ค๊ธฐ
- [Backend] label get API ๋ง๋ค๊ธฐ
- fetch ์์ฒญ ์, cors ์ต์ ์ถ๊ฐํด์คฌ์
- Backend app.js cors ์ค์ ์ถ๊ฐํด์คฌ์
react-router-dom
์ ์น์์ ์ฐ์ด๋ ์ปดํฌ๋ํธ์ด๊ณ ,react-router-native
๋ react-native๋ฅผ ํ์ฉํ ์ฑ๊ฐ๋ฐ์ ์ฐ์ด๋ ์ปดํฌ๋ํธ๋ฅผ ํฌํจํ๊ณ ์๋ค.react-router
๋ ์ด ๋์ ํฉ์น ํจํค์ง์ด๋ค.- https://velopert.com/3417 ๋ฅผ ์ฐธ๊ณ ํ์ฌ ์งํํ์๋ค.
react-router-dom
๋ง ์ค์นํ๊ธฐ๋ก ํ๋ค.
npm install -d react-router-dom
- ๋๋ ํ ๋ฆฌ ๊ตฌ์กฐ ์ค๊ณ
-
๊ธฐ์กด
- src/components: ์ปดํฌ๋ํธ๋ค์ด ์์นํ๋ ๋๋ ํ ๋ฆฌ
- src/pages: ๊ฐ ๋ผ์ฐํธ๋ค์ด ์์นํ๋ ๋๋ ํ ๋ฆฌ
-
์ถ๊ฐ๋ ๋๋ ํ ๋ฆฌ
- src/utils: ์์ฃผ ์ฌ์ฉ๋๋ ํจ์๋ค์ ๋ชจ์๋์ ๋๋ ํ ๋ฆฌ
- src/shared: ์๋ฒ์ ํด๋ผ์ด์ธํธ์์ ๊ณต์ฉ์ผ๋ก ์ฌ์ฉ๋๋ ์ปดํฌ๋ํธ App.js ๊ฐ ์ฌ๊ธฐ์ ์์นํจ
- src/client: ๋ธ๋ผ์ฐ์ ์ธก์์ ์ฌ์ฉํ ์ต์์ ์ปดํฌ๋ํธ
-
- url๋ก ์ง์ router์ ์ ๊ทผํ๋ ๋์ํ์ง ์๊ณ 404 error๊ฐ ๋ฐ์ํ๋ค.๐ฅ
- ๋ฒํผ(Link)์ ํด๋ฆญํด์ ๋์ด๊ฐ๋ ๋ผ์ฐํ ์ด๋ฒคํธ๋ ๋ฌด์ฌํ ๋์ํ์๋ค.
- pages๋ผ๋ ๋๋ ํ ๋ฆฌ ๋ค์ด๋ฐ๋ ์์ง ์๋ฟ์ง ์๊ณ (views ๋ง์ด ์ผ์๋๋ฐ,,) shared๋,, client๋.. ์ง์ง ์์ํ ๊ฒ ๋ง์์ ๋ฆฌ์กํธ์ ์์ง ์ ์ด ์๊ฐ๋๋ค ^^7
- ๊ณผ์ ์๊ตฌ์ฌํญ์ ์ฝ์ด๋ณด๋ CSS-in-JS๋ฅผ ์ ์ฉํด์ผํจ์ ์๊ฒ ๋์ด ์์ ํ์๋ค.
npm install -d styled-components
- SCSS๋ก ์ ์ฉํ๊ณ ์ถ์๋๋ฐ ๋๋ฌด ์์ฝ๋ค์ 8ใ 8๐
- ๊ตฌํํ OAuth Login์ ๊ฒฐ๊ณผ ๊ฐ์ ์ด๋ป๊ฒ FE์ iOS์ ์ ๋ฌํ ์ ์์์ง ๋ง์ ๊ณ ๋ฏผ์ ํ์๋ค. ๐ค
- redirect์ url๋ก token์ ๋๊ฒจ์ฃผ๋ ๋ฐฉ๋ฒ์ ์๋ ๊ฒ ๊ฐ๊ณ ...
- githubOAuth๋ก ๋ก๊ทธ์ธํ๋ฉด ๋ฐ๊ธ๋๋ code์ client_id, client_secret์ ์ด์ฉํ์ฌ post์์ฒญ์ผ๋ก access_token์ ๋ฐ๊ธํ๋ ค๊ณ ํ ์ ์๋ ๋ชจ๋ ๋ฐฉ๋ฒ์ ์๋ํด ๋ณด์์ผ๋ ๋ฌด์จ ์ด์ ์์์ธ์ง ์๋ฌ๊ฐ ๋ฐ์ํ๋ค.. ๋์ค์ ๋ค์ ์๋ํด์ผ๊ฒ ๋ค. ์ฐธ์กฐ๋งํฌ
- ์๋ฒ์์ npm ๋ช ๋ น์ด๋ฅผ ์ณค์ ๋ command not found ์กฐ์ฐจ ๋จ์ง ์์๋ค.
- ์๋ฒ๋ฅผ ์ฌ๋ถํ ํ๋ค. ์ฌ๋ถํ ํ๋๊น npm ๋ช ๋ น์ด๊ฐ ์๋๋ ์ค๋ฅ๊ฐ ํด๊ฒฐ๋์๋ค.
- ์๋ก cloneํ๊ณ npm๊ณผ node, pm2๋ฅผ ์ฌ์ค์นํ๋ค.
- ๋ง์ ์๋ฃ๋ ์๋ฒ...
- ํ๋ก ํธ์์๋ .env ๋์ src ์๋์ config.js ํ์ผ์ ์์ฑํ์ฌ ํ๊ฒฝ๋ณ์๋ฅผ ์ค์ ํ์๋ค. ์ฐธ์กฐ๋งํฌ
- scssํ์ผ ์ฌ์ฌ์ฉ์ ์ํด Client ์๋์ scssํด๋๋ฅผ ๋ง๋ค๊ณ _color.js ์ ๊ฐ์ด ๋ง๋ค์ด์ ๋ค๋ฅธ scss์์ importํด์ ์ฌ์ฉ ํ๊ธฐ๋ก ๊ฒฐ์ ํ์๋ค. ์ฐธ์กฐ๋งํฌ
- _color.js์์ ์์ฃผ ์ฐ๋ ์๊น์ ๋ณ์์ฒ๋ผ ๋ค์ด๋ฐํ์ฌ ์ฌ์ฉํ๊ธฐ๋ก ํ์๋ค.
$gray-100: #f8f9fa !default; // $์๊น-์ซ์๊ฐ: #์์๊ฐ // ๊ธฐ๋ณธ ์์์ ๋ธ๋ฃจ๋ 500์ ๊ฐ๋๋ค. // ๋ฎ์ ์ซ์์ผ์๋ก ์ฐํ ์์ด๊ณ ๋์ ์ซ์์ผ์๋ก ์ด๋์ด ์์ ์๋ฏธํ๋ค.
- 100 ~ 999 ์ฌ์ด์ ์ซ์๋ฅผ ์๊น ๋ค์ ๋ถ์ฌ ์ฌ์ฉํ๊ธฐ๋ก ํ๋ค.
- create react app ์์ด ํ๋ก์ ํธ๋ฅผ ์์ฑํ๋ค.
- react์ ๋ฅ์ํ ์ฌ๋์ด ์์ด ํ์ ๋ชจ๋ zoom์ ์ ์ํ์ฌ ํจ๊ป ์ฐพ์๋ณด๋ฉฐ ๊ฒฐ์ ํ์๋ค.
- js์ jsx๋ ๊ธฐ๋ฅ์ ๋์ผํ์ง๋ง React์์ ๊ถ์ฅํ๋ jsx๋ฅผ ์ฌ์ฉํ๊ธฐ๋ก ํ์๋ค.
- React ํ๋ก์ ํธ์ ํด๋ ๊ตฌ์กฐ๋ฅผ ์ค๊ณํ์๋ค. ๐๐
- ex) Routes.jsx ๊ฐ ๋ชจ๋ ๊ฒฝ๋ก๋ฅผ ๊ฐ๊ณ ์๋ค.
ใด /Client App.jsx App.scss ใด /src ใด /components ใด Routes.jsx ใด /navbar ใด Navbar.jsx ใด Navbar.scss ใด /form ใด IssueAddForm.jsx ใด IssueAddForm.scss ใด /pages ใด /login ใด LoginPage.jsx ใด LoginPage.scss
- ex) Routes.jsx ๊ฐ ๋ชจ๋ ๊ฒฝ๋ก๋ฅผ ๊ฐ๊ณ ์๋ค.
- ์ต์ ๋ฒ์ ์ webpack-dev-server/webpack-cli๋ฅผ ์ฌ์ฉํ๋ webpack-dev-server๋ฅผ ์คํ ์ ์๋ฌ๊ฐ ๋ฐ์ํ๋ค.
- ์์กด์ฑ์ด ํ์ธ๋ ๋ฒ์ ์ ์ฐพ์ ๋ณ๊ฒฝ ํ, ์ฌ์คํ์ ์งํํ๋๋ ์๋ฌ๋ฅผ ํด๊ฒฐํ ์ ์์๋ค.
- ๋ฒ์ ๊ด๋ฆฌ์ ์ค์์ฑ์ ๋ค์ ํ ๋ฒ ๋๊ผ๋ค.
- dev-server <- feat-issue-api merge
- dev-server <- feat-milestone-api merge
- dev-server <- Feat signin api Merge
์ถฉ๋์ ์ด๋ป๊ฒ ํด๊ฒฐํ๋ ๊ฒ ๊ฐ์ฅ ์ข์๊น?
- ํ์๋ค์ด ๊ฐ์ด ์์ผ๋ฉด์ ์ฝ๋๋ฅผ ๋ณธ๋ค.
fork
๋ฑ์ github GUI ํด์ ์ฌ์ฉํ์ฌ ๋ธ๋์น์ ์ ์ฅ์ ๊ด๋ฆฌ์ ๋์์ ๋ฐ์ผ๋ฉด ๋ ์ฝ๋ค.- ์ถฉ๋์ด ํฌ์ง ์๋ค๋ฉด github web ํธ์ง์ผ๋ก ์ฝ๊ฒ mergeํ ์ ์๋ค.
sub query
GET_OPEN_ISSUES:
`SELECT issue.id as issueId, < 3๋ฒ : issue.id๋ฅผ ๊ฐ์ ธ์์ issueID๋ผ ์ ์
(SELECT user.email FROM user WHERE user.id = issue.userId) as email, < 4๋ฒ : where์ด ์ฑ๋ฆฝํ ๋ ์ ์ ์ email ๊ฐ์ ธ์์ email์ด๋ผ ์ ์ ์ดํ ๋๋ฌธ
(SELECT user.name FROM user WHERE user.id = issue.userId) as name,
(SELECT milestone.title FROM milestone WHERE issue.milestoneID = milestone.id) as milestone,
issue.title, issue.content, issue.isOpen, issue.createAt, issue.closeAt
FROM issue < 1๋ฒ : ์ด์๋ก๋ถํฐ
WHERE issue.isOpen = 1`, < 2๋ฒ : issue์ isOpen์ด true์ผ ๋
makeIssueTemplate: async (results) => {
const issueList = [...results.data[0]];
for (let issue of issueList) {
const labelList = await requestQuery(query.GET_LABELS_BY_ISSUE_ID, [
issue.issueId,
]);
const assigneeResults = await requestQuery(
query.GET_ASSIGNEES_BY_ISSUE_ID,
[issue.issueId]
);
const assigneeList = [];
for (let assign of assigneeResults.data[0]) {
assigneeList.push(assign.name);
}
issue.label = labelList.data[0];
issue.assign = assigneeList;
}
return issueList;
},
{
"status": "success",
"data": [
{
"issueId": 1,
"email": "[email protected]",
"name": "test",
"milestone": "FE",
"title": "ViewCreate",
"content": "we develop",
"isOpen": 1,
"createAt": "2020-01-02T15:00:00.000Z",
"closeAt": "2020-01-02T15:00:00.000Z",
"label": [
{
"labelName": "web",
"labelColor": "#121212",
"labelDescription": "fighting"
},
{
"labelName": "FE",
"labelColor": "#243412",
"labelDescription": "fighting"
}
],
"assign": [
"test",
"reality"
]
},
]
}
-
ํ๋ฉด์์ content๊ฐ ๋น์ด์์ ๊ฒฝ์ฐ
no description provided
๋ฉ์ธ์ง๋ฅผ ๋ค๋ฅธ ๊ธ์จ๋ก ๋์์ฃผ๊ธฐ ์ํด์null
๋ก content๋ก ์ค์ ๊ฐ๋ฅํ๊ฒ ํ์๋ค.- NOT NULL ์ ๊ฑฐ
ALTER TABLE issue modify content text NULL;
- ์ฟผ๋ฆฌ๋ฌธ์ DDL, DML์ ๋๋ฌธ์๋ก ๋๋จธ์ง๋ ์๋ฌธ์๋ก, ๋ง์ง๋ง์๋ ์ธ๋ฏธ์ฝ๋ก ์๋ถ์ด๊ธฐ
- ๋ผ์ฐํฐ ์ฝ๋ ์์
- get -> post -> put -> delete ๋ณ๋ก ์ฝ๋๋ฅผ ๋์์ฐ๊ธฐ๋ก ํ์๋ค.
- ํจ์๋ช ์ ๊ฐ get, create, update, delete ์ ๋จ์ด๋ฅผ ์จ์ ์์ฑํ๊ธฐ๋ก ๊ฒฐ์ ํ์๋ค.
- put๊ณผ patch ์ค put ์ฌ์ฉ์ผ๋ก ํต์ผํ๊ธฐ๋ก ๊ฒฐ์ ํ์๋ค.
- ์ฝ๋ฉ์ปจ๋ฒค์ ์์ ๊ฒฐ๊ณผ ๐
- TOAST์ Google์ ์ฝ๋ฉ ์ปจ๋ฒค์ ์ ๊ธฐ๋ฐ์ผ๋ก ์ฝ๋ฉ ์ปจ๋ฒค์ ์ ๊ฒฐ์ ํ์๋ค.
- ๊ด๋ จ PR :
#81
- ์์ ์คํ์ผ์ ๋ง์ถ๊ธฐ ์ํด ์ฒซ API๋ ํ๋ฉด์ ๊ณต์ ํ๋ฉฐ ํ์ ์ ์์ด ์ฐธ์ฌํ์ฌ ๊ฐ๋ฐํ์๋ค.
- ๊ด๋ จ issue :
#15
- user ํ
์ด๋ธ
email
์ปฌ๋ผ ์ถ๊ฐ- ๊ธฐ์กด์ user ํ
์ด๋ธ์์ ์ฌ์ฉ์ ๋ก๊ทธ์ธ ์ ๋ณด์์
name
๋ง ์ ์ฅํ๋๋ก ํ๋๋ฐ, API๋ฅผ ๊ตฌํํ๋ฉด์email
์ ๋ณด๋ ์ถ๊ฐ๋ก ํ์ํจ์ ๋๊ปด ์ถ๊ฐํ์๋ค.
- ๊ธฐ์กด์ user ํ
์ด๋ธ์์ ์ฌ์ฉ์ ๋ก๊ทธ์ธ ์ ๋ณด์์
- milestone ํ
์ด๋ธ ์ปฌ๋ผ ์ผ๋ถ ์์
- ์ด์ open, close ๊ด๋ฆฌํ๋ ์ปฌ๋ผ์ ์ญ์ ํ์๋ค.
- ๋งค issue ๋ณ๊ฒฝ ์๋ง๋ค ํธ๋ฆฌ๊ฑฐ๋ก ๊ด๋ฆฌํ๋ ํ์๋ณด๋ค, milestone ํ์ด์ง์ ์ฌ์ฉ์๊ฐ ๋ค์ด์์ ๋ issue ๊ฐ์๋ฅผ ํ์ธํ๋ ํ์๊ฐ ์ ์ ๊ฒ์ผ๋ก ํ๋จํด์ ๋ณ๊ฒฝํ์๋ค.
- issue_label table ์์
- ์ฐ๊ฒฐ์ด user table์ ์๋ชป ์ฐ๊ฒฐ ๋์ด ์์ด์ ์ฌ๋ฐ๋ฅด๊ฒ ์์
- eslint, prettier์ ์ค์ ์ ํ์ ๋ชจ๋ ๋์ผํ๊ฒ ์ค์ ํ์๋ค.
- eslint ์คํ์ด์ค 2์นธ, ; ์์ฑ