๐ฅ๏ธ Front-End
โ ํ๋ก์ ํธ์ ์ฌ์ฉ๋๋ babel-preset-react-app์ด @babel/plugin-proposal-private-property-in-object ํจํค์ง๋ฅผ ์์กด์ฑ์ผ๋ก ์ ์ธํ์ง ์๊ณ ์ฌ์ฉํ๊ณ ์์ด์ ๊ฒฝ๊ณ ๋ฐ์
// ์ค์น๋ก ํด๊ฒฐ
yarn add --dev @babel/plugin-proposal-private-property-in-object
โ Promise๊ฐ state์ ๋ค์ด๊ฐ ์์ด์ ์๊ธด ์ฑ๋ํก ์ค๋ฅ. Redux state์๋ ๋น๋๊ธฐ ์์ ๋๋ Promise์ ๊ฐ์ ๊ฐ์ด ํฌํจ๋์ด์๋ ์ ๋๊ธฐ ๋๋ฌธ.
// ์ค๋ฅ ๋ฉ์์ง
serializableStateInvariantMiddleware.ts:212 A non-serializable value was detected in the state, in the path: `channelTalk`. Value: Promise
Take a look at the reducer(s) handling this action type: channelTalk/bootChannelTalk.
(See https://redux.js.org/faq/organizing-state#can-i-put-functions-promises-or-other-non-serializable-items-in-my-store-state)
โ redux-thunk๋ฅผ ์ฌ์ฉํ์ฌ ๋น๋๊ธฐ ์์ ์ ์ฒ๋ฆฌํจ.
import { createSlice } from "@reduxjs/toolkit";
import * as ChannelService from "@channel.io/channel-web-sdk-loader";
// ๋น๋๊ธฐ ์์
์ ์ฒ๋ฆฌํ๊ธฐ ์ํด thunk๋ฅผ ์ฌ์ฉํ๋ ์ก์
์์ฑ์
export const bootChannelTalk = () => async (dispatch) => {
const { REACT_APP_CHANNEL_PLUGIN_KEY } = process.env;
// ์คํฌ๋ฆฝํธ ๋ก๋ ํ ์ต๋ช
์ผ๋ก ๋ถํธ
ChannelService.loadScript();
ChannelService.boot({
pluginKey: REACT_APP_CHANNEL_PLUGIN_KEY,
});
// ๋น๋๊ธฐ ์์
์ด ์๋ฃ๋๋ฉด ๋๊ธฐ์ ์ธ ์ก์
์ ๋์คํจ์น
dispatch(channelTalkSlice.actions.bootChannelTalkSuccess());
};
const channelTalkSlice = createSlice({
name: "channelTalk",
initialState: {},
reducers: {
bootChannelTalkSuccess: (state, action) => {
// ๋ถํธ ์ฑ๊ณต ํ ์ํ๋ฅผ ๋ณ๊ฒฝํ๋ ๋ก์ง ์์ฑ
},
// ... ๋ค๋ฅธ ์ก์
๋ฐ ๋ฆฌ๋์๋ค
},
});
export const { bootChannelTalkSuccess } = channelTalkSlice.actions;
export default channelTalkSlice.reducer;
โ styled-components์์ props๋ฅผ ์ฌ์ฉํ ๋ ๋ฌ ๊ฒฝ๊ณ
styled-components: it looks like an unknown prop "pt" is being sent through to the DOM, which will likely trigger a React console error. If you would like automatic filtering of unknown props, you can opt-into that behavior via `<StyleSheetManager shouldForwardProp={...}>` (connect an API like `@emotion/is-prop-valid`) or consider using transient props (`$` prefix for automatic filtering.)
index.js์์ StyleSheetManager๋ก App ์ปดํฌ๋ํธ๋ฅผ ๊ฐ์ธ์ค ๋ค์ shouldForwardProp์์ฑ์ true๋ฅผ ๋ฐํํ๋๋ก ์ถ๊ฐ. ์์ props์ฒ๋ผ ๋์ํ๊ฒ ํด์ค.
root.render(
<React.StrictMode>
<Provider store={store}>
<ThemeProvider theme={theme}>
<StyleSheetManager shouldForwardProp={() => true}> {/* ์ถ๊ฐ */}
<GlobalStyle />
<App />
</StyleSheetManager>
</ThemeProvider>
</Provider>
</React.StrictMode>
);
โ FE&BE ๊ฐ Cookie ์ ๋ฌ ์ด์ (localhost:3000์์ ํ ํฐ์ด %25๊ฐ ๋ถ์ด์ ๋์ค๋ ๋ฌธ์ )
- ํ๋ก ํธ์๋๋ localhost:3000์ผ๋ก ์๋ฒ๋ฅผ ๊ตฌ๋ํ๊ณ , ๋ฐฑ์๋ ์๋ฒ๋ IP ์ฃผ์์ด๊ธฐ ๋๋ฌธ์ ๋๋ฉ์ธ ๋ถ์ผ์น ๋ฌธ์ ๊ฐ ์๊ฒผ๋ค. ์ค์ ๋ก same-origin policy์ ์ด๊ธ๋๊ฒ ์ ๊ทผ์ ํ๋ฉด, ๋คํธ์ํฌ ํญ set-cookie ๋ถ๋ถ ํ ํฐ ๊ฐ ์์ ! ๊ฒฝ๊ณ ์ฌ์ธ์ด ๋ด๋ค.
- ๋๋ฉ์ธ์ ๋ง์ถ๊ธฐ ์ํด ์ด๋ฏธ ๋ฐฐํฌ๋ ํ๋ก ํธ์๋ ์ฌ์ดํธ์์ ์์ ํ๋ ํ ํฐ์ด ์ ์์ ์ผ๋ก ์๊ฒผ๋ค.
โ Redux์์ ๋ก๊ทธ์ธ ์ํ๋ฅผ ์ ์งํ๊ธฐ ์ํด redux-persist๋ฅผ ์ ์ฉํ๋ค๊ฐ Uncaught TypeError: baseReducer is not a function ์๋ฌ ๋ฐ์
- ์ฃผ์ด์ง ์ฝ๋์์ "baseReducer"๋ผ๋ ๋ณ์ ๋๋ ํจ์๊ฐ ๊ธฐ๋ํ ํ์์ด ์๋๋ผ๋ ์๋ฌ์๋ค.
๐ฅ ํด๊ฒฐ๋ฐฉ๋ฒ
- redux-persist๋ฅผ ์ฌ์ฉํ ๋๋ configureStore์ ์ ๋ฌ๋๋ reducer๋ ํจ์์ฌ์ผ ํ๋ค.
- authslice.js ํ์ผ์์ authslice → authReducer๋ก ๋ณ๊ฒฝํ๋ค.
- ์ถ๊ฐ๋ก rootReducer ๊ฐ์ฒด๋ฅผ ํจ์๋ก ๋ณํํด์ผ ํ๋ค. store.js ํ์ผ์์ combinedReducers ํจ์๋ฅผ ์ฌ์ฉํ๋ค.
๐ฅ redux-persist ์ ์ฉ์ด ์๋ฃ๋์์ผ๋ non-serializable ์๋ฌ ๋ฐ์
- ์ด ์ค๋ฅ๋ Redux์ serializable action์ ์ ์งํ๋ ์์น์ ์ด๊ธ๋๋ ๋น์ง๋ ฌํ ๊ฐ๋ฅํ์ง ์์(non-serializable) ๊ฐ์ด ์ก์ ์ ํฌํจ๋์ด ์๋ค๋ ๊ฒ์ ๋ํ๋ธ๋ค.
ํด๊ฒฐ๋ฐฉ๋ฒ
- ์ค์๋ฅผ ๋ฐฉ์งํ๊ธฐ ์ํด middleware๊ฐ ์คํ๋๋๋ก ํ๋ ๊ฒ์ด ๊ถ๊ณ ์ฌํญ์ด์ง๋ง, ๋๋ ๋ฐฉ๋ฒ๋ redux toolkit ๊ณต์๋ฌธ์์์ ์๋ ค์ค๋ค.
- store.js ํ์ผ์์ serializableCheck๋ฅผ false๋ก ์ง์ ํ๋ค.
const store = configureStore({
reducer: persistedReducer,
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware({
// Serializable ์ฒดํฌ๋ฅผ ๋นํ์ฑํํ์ฌ non-serialization ๊ฐ๋ฅํ ๊ฐ ์ฌ์ฉ ํ์ฉ
// ํน๋ณํ ์ํฉ์์๋ง ์ฌ์ฉํด์ผ ํ๋ฉฐ, ์ฃผ์๊ฐ ํ์ํ ์ค์
serializableCheck: false,
}),
});
โ [Violation] Avoid using document.write() ๊ฒฝ๊ณ
์์ฝํ์๋ฉด document.write()๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ ๊ถ์ฅ๋์ง ์๋๋ค.
ํด๊ฒฐ์ฑ : ์ฑ๋ํก์ ์ฌ์ฉํ์ง ์์ผ๋ฉด ๊ฒฝ๊ณ ๊ฐ ์๊ธฐ์ง ์๋๋ค. ์ฑ๋ํก์ ์ฌ์ฉํ๊ณ ์ถ์ผ๋ฉด ๊ฒฝ๊ณ ๋ ๋จ๊ฒจ๋์ด์ผ ํ๋ค.
์ฑ๋ํก์ ์ฌ์ฉํ๊ณ ์ถ๊ธฐ ๋๋ฌธ์ ๊ฒฝ๊ณ ์ฐฝ์ ๋ด๋ฒ๋ ค ๋๊ธฐ๋ก ํ๋ค.
- ์ฑ๋ํก์์ ์ฌ์ฉํ๋ document.write() ๋ถ๋ถ
var t = document.getElementById("ch-plugin-script-iframe"),
r = !1,
o = function () {
var e = t.contentDocument || t.contentWindow.document;
e.open(),
e.write(
'<!DOCTYPE html><script async type="text/javascript" src="https://cdn.channel.io/plugin/ch-plugin-core.446b7109.vendor.js" charset="UTF-8"></script>'
),
e.write(
'<script async type="text/javascript" src="https://cdn.channel.io/plugin/ch-plugin-core-20240205163803.js" charset="UTF-8"></script>'
),
e.write(
'<html lang="en"><head><meta charset="utf-8"></head><body><div id="main"></div></body></html>'
),
e.close(),
(r = !0);
};
t.onload || o(),
(t.onload = function () {
r || o();
});
'Web_Project' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
Front-End Convention (0) | 2024.03.10 |
---|---|
์ ์ ํ ์คํธ ํผ๋๋ฐฑ ๋ฐ์ (0) | 2024.03.10 |
[ํ๋ก์ ํธ ๋ธ๋ก์ ] Giftipie ํ๋ก์ ํธ ์์ธ์ค๋ช (0) | 2024.03.06 |
[ํ๋ก์ ํธ ์๊ฐ] Giftipie ์ ๋ฌผํ๋ฉ ์๋น์ค (0) | 2024.03.06 |
์์ฑ-์์ -์์ธ-ํ์์-๊ฒฐ์ ํ์ด์ง (0) | 2024.02.23 |