Skip to content

๐Ÿ’ป next / node / mySQL / AWS ๋ฅผ ์ด์šฉํ•œ CRUD ์‚ฌ์ดํŠธ ์ œ์ž‘

Notifications You must be signed in to change notification settings

junh0328/nextjs-aws-service

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 
ย 
ย 
ย 
ย 

Repository files navigation

nextjs-aws-project


๐Ÿ‘‰๐Ÿผ ํ”„๋กœ์ ํŠธ ์†Œ๊ฐœ

  • Next.js / MySQL / AWS ์Šคํƒ์„ ์‚ฌ์šฉํ•˜์—ฌ ์‚ฌ์šฉํ•œ SNS ์„œ๋น„์Šค์˜ ์ผ๋ถ€ ์„œ๋น„์Šค๋ฅผ ์ œ๊ณต ์‚ฌ์ดํŠธ

๐Ÿ‘‰๐Ÿผ ํ”„๋กœ์ ํŠธ ๊ธฐ๊ฐ„

  • 2021-01-29 ~ 2021-03-02 (์„ธ๋ถ€ UI๋ฐ ๊ธฐ๋Šฅ ์ˆ˜์ • ์ง„ํ–‰ ์ค‘)

๐Ÿ‘‰๐Ÿผ ์ฃผ์š” ๊ธฐ์ˆ  & ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ

ํ”„๋ก ํŠธ์—”๋“œ ๋ถ€๋ถ„

  • Next.js (Create-next-app)
  • antd (CSS ํ”„๋ ˆ์ž„์›Œํฌ)
  • styled-componenets (CSS ์Šคํƒ€์ผ ๊ด€๋ฆฌ)
  • axios (์„œ๋ฒ„๊ฐ„ ๋ฐ์ดํ„ฐ ์†ก์ˆ˜์‹ )
  • immer (๋ฐ์ดํ„ฐ ๋ถˆ๋ณ€์„ฑ ๊ด€๋ฆฌ)
  • moment (๋‚ ์งœ ๊ด€๋ฆฌ)
  • react-slick (์ด๋ฏธ์ง€ ์บ๋ฃจ์…€)
  • swr (์ƒํƒœ ๊ด€๋ฆฌ)
  • redux (๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ)
  • redux-saga (๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ +)
  • redux-devtools-extension (ํฌ๋กฌ ๋ธŒ๋ผ์šฐ์ € ์™ธ๋ถ€ ์„œ๋น„์Šค ์‚ฌ์šฉํ•˜์—ฌ ์ƒํƒœ ๊ด€๋ฆฌ, ์ถ”์ )

๋ฐฑ์—”๋“œ ๋ถ€๋ถ„

  • node.js
  • nodemon
  • express
  • express-session
  • sequelize
  • mysql2
  • multer
  • cors
  • cookie-parser
  • passport

aws ๋ถ€๋ถ„

  • multer-s3
  • hpp
  • helmet

๊ณตํ†ต ์ƒํƒœ ๊ด€๋ฆฌ

  • cross-env
  • dotenv
  • pm2

๐Ÿ‘‰๐Ÿผ ํ”„๋กœ์ ํŠธ ๊ตฌํ˜„

  1. SSR๊ณผ ๋ฆฌ๋•์Šค-์‚ฌ๊ฐ€๋ฅผ ์ด์šฉํ•œ ๋น„๋™๊ธฐ์ฒ˜๋ฆฌ

    ์ฒ˜์Œ ๋นˆ ๊ฒŒ์‹œ๋ฌผ์—์„œ SSR์„ ํ†ตํ•ด ์„œ๋ฒ„์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›์•„ ์ฑ„์›Œ๋†“๋Š”๋‹ค.

export const getServerSideProps = wrapper.getServerSideProps(
  async (context) => {
    const cookie = context.req ? context.req.headers.cookie : "";
    axios.defaults.headers.Cookie = "";
    if (context.req && cookie) {
      axios.defaults.headers.Cookie = cookie;
    }
    context.store.dispatch({
      type: LOAD_POSTS_REQUEST,
    });
    context.store.dispatch(END);
    await context.store.sagaTask.toPromise();
  }
);
  1. useDispatch() ํ›… ํ•จ์ˆ˜๋ฅผ ํ™œ์šฉํ•ด LOAD_POSTS_REQUEST์™€ ๊ฐ™์€ ์•ก์…˜์ด ํ˜ธ์ถœ๋˜๋ฉด ๋ฆฌ๋•์Šค-์‚ฌ๊ฐ€์—์„œ ์ด๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ณ  ๊ฒฐ๊ณผ๊ฐ’์„ LOAD_POSTS_SUCCESS / LOAD_POSTS_FAILURE ๋กœ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
unction loadPostsAPI(lastId) {
  return axios.get(`/posts?lastId=${lastId || 0}`);
}

function* loadPosts(action) {
  try {
    const result = yield call(loadPostsAPI, action.lastId);
    yield put({
      type: LOAD_POSTS_SUCCESS,
      data: result.data,
    });
  } catch (err) {
    console.error(err);
    yield put({
      type: LOAD_POSTS_FAILURE,
      error: err.response.data,
    });
  }
}

function* watchloadPosts() {
  yield takeLatest(LOAD_POSTS_REQUEST, loadPosts);
}

export default function* postSaga() {
  yield all([
    fork(watchloadPosts),
    ....
  ])
}
  1. ๋ฆฌ๋•์Šค-์‚ฌ๊ฐ€์—์„œ ์–ป์€ ์ •๋ณด๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ ๋ฆฌ๋“€์„œ์—์„œ ์ฒ˜๋ฆฌ
const reducer = (state = initialState, action) => {
  return produce(state, (draft) => {
    switch (action.type) {
      case LOAD_POSTS_REQUEST:
        draft.loadPostsLoading = true;
        draft.loadPostsDone = false;
        draft.loadPostsError = null;
        break;
      case LOAD_POSTS_SUCCESS:
        draft.loadPostsLoading = false;
        draft.loadPostsDone = true;
        draft.mainPosts = draft.mainPosts.concat(action.data);
        draft.hasMorePosts = action.data.length === 10;
        break;
      case LOAD_POSTS_FAILURE:
        draft.loadPostsLoading = false;
        draft.loadPostsError = action.error;
        break;
        ...
      default:
      break;
    }
  });
};
  1. ๋ฆฌ๋“€์„œ์—์„œ ์ฒ˜๋ฆฌ๋œ ๊ฐ’์„ ๋ฐ”ํƒ•์œผ๋กœ Virtual DOM์ด ์ด๋ฅผ ๋น„๊ตํ•˜๊ต ๋ Œ๋”๋งํ•œ๋‹ค. ํ›„์— ์ƒํ™ฉ์€ ์•„๋ž˜ ๊ฒฐ๊ณผ๋ฅผ ์ฐธ์กฐ

๐Ÿ‘‰๐Ÿผ ํ”„๋กœ์ ํŠธ ๊ฒฐ๊ณผ

๊ฒฐ๊ณผ๋ฌผ ๋ฐ”๋กœ๊ฐ€๊ธฐ

๋ฉ”์ธ๊ธฐ๋Šฅ

main gif

๋‹ค์ด๋‚˜๋ฏน ๋ผ์šฐํŒ…

main gif


๐Ÿ‘‰๐Ÿผ ๋ณด์™„ํ•  ์  ๋ฐ ๋Š๋‚€ ์ 

1. ๋น„๋™๊ธฐ ๊ตฌ์กฐ๋ฐ ์ฒ˜๋ฆฌ ๊ณผ์ •

์ฑ…์„ ํ†ตํ•ด ์ฒ˜์Œ javascript๋ฅผ ๋ฐฐ์šธ ๋•Œ promise๋‚˜, async await์™€ ๊ฐ™์€ ๋น„๋™๊ธฐ ๋ฌธ๋ฒ•๋“ค์€ ๋‹จ์ง€ ์ฑ…์†์˜ ๋ฌธ์ž๋“ค๋กœ๋งŒ ๋‚˜์—ด๋˜์–ด์žˆ์–ด์„œ ์‰ฝ๊ฒŒ ์™€๋‹ซ์ง€ ์•Š์•˜๋‹ค. ํ•˜์ง€๋งŒ, ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๋ฉด์„œ ์‹ค์ œ๋กœ ๊ฒฝํ—˜ํ•ด๋ณด๋‹ˆ ๋ฐ์ดํ„ฐ ์†ก์ˆ˜์‹ ์— ์žˆ์–ด์„œ ๋น„๋™๊ธฐ์ฒ˜๋ฆฌ๊ฐ€ ์ ˆ๋Œ€ ๋น ์ง€๋ฉด ์•ˆ๋œ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ๊ฒŒ ๋˜์—ˆ๋‹ค. ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ๊ฐ€ ์—†๋‹ค๋ฉด, ๋ฐฑ์—”๋“œ ์„œ๋ฒ„์™€์˜ ์†Œํ†ต์ด ์ผ๋ฐฉํ–ฅ์ ์œผ๋กœ ์ „๋‹ฌ๋˜๊ณ  ๊ฒฐ๊ณผ๊ฐ’ ๋˜๋Š” ์—๋Ÿฌ๊ฐ’์„ ๋งˆ์Œ๋Œ€๋กœ ๋ฝ‘์•„์˜ฌ์ง€๋„ ๋ชจ๋ฅธ๋‹ค.(๋ฆฌํ„ด์„ ์ œ๋Œ€๋กœ ๋ฐ›์ง€ ๋ชป ํ•  ๊ฒƒ์ด๋‹ค.) ์™„๋ฒฝํ•˜์ง„ ์•Š์ง€๋งŒ, ๋‹ค๋ฅธ ํ† ์ดํ”„๋กœ์ ํŠธ๋ฅผ ๋” ์ง„ํ–‰ํ•˜๋ฉด์„œ redux, redux-saga์˜ ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ ํ•จ์ˆ˜ ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ js์˜ ๊ธฐ๋ณธ ๋ฌธ๋ฒ•์—์„œ ์ œ๊ณตํ•˜๋Š” ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ ํ•จ์ˆ˜์— ๋Œ€ํ•ด ๊ณต๋ถ€ํ•ด์•ผ๊ฒ ๋‹ค

2. CORS ์ •์ฑ…์œผ๋กœ ์ƒ๊ธฐ๋Š” ์˜ค๋ฅ˜๋“ค ์ฐพ๊ธฐ

ํ’€์Šคํƒ์œผ๋กœ ๊ฐ•์˜๋ฅผ ๋“ค์œผ๋ฉฐ ๋‹ค์‹œ ๋งŒ๋“ค์–ด๋ณด๋ฉด์„œ, CORS ๋ฌธ์ œ๋ฅผ ๋„ˆ๋ฌด ๋งŽ์ด ๊ฒช์—ˆ๋‹ค. ์•„๋งˆ์กด ์›น ์„œ๋น„์Šค์— ๋ฐฐํฌ๋ฅผ ํ•˜๋Š” ๊ณผ์ •์—์„œ๋„ ๋ฆฌ๋ˆ…์Šค ๋ช…๋ น์–ด๋ฅผ ํ†ตํ•ด ๋ฆฌ๋ˆ…์Šค ์„œ๋ฒ„์—์„œ ์ƒˆ๋กญ๊ฒŒ pull ์„ ํ•ด์•ผ ํ•˜๊ณ , axios๋กœ ์‚ฌ์šฉ์ž ์š”์ฒญ์„ ๋ฐฑ์—”๋“œ ์„œ๋ฒ„์— ๋„˜๊ฒจ์ค„ ๋•Œ๋„ ์ž˜๋ชป ์„ค์ •ํ•œ๋‹ค๋ฉด CORS ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•˜๊ธฐ ๋‹ค๋ฐ˜์‚ฌ์˜€๋‹ค. (์ปค๋ฐ‹ ํ‘ธ์‰ฌ์™€ ํ’€์˜ ๋ฌดํ•œ ๋ฐ˜๋ณต...) ์ƒ๋Œ€์ ์œผ๋กœ ํ”„๋ก ํŠธ์—์„œ๋Š” ์„ค์ •ํ•ด์•ผํ•  ๊ฒƒ์ด ์ ์ง€๋งŒ, ๋‚ด๊ฐ€ ์ฒ˜๋ฆฌํ•ด ๋ณธ ์‚ฌํ•ญ ์™ธ์—๋„ ๋ฐœ์ƒํ•  ์˜ค๋ฅ˜๋“ค์— ๋Œ€๋น„ํ•ด ์กฐ๊ธˆ ๋” ๋”ฅํ•œ ๊ณต๋ถ€์˜ ํ•„์š”์„ฑ์„ ๋Š๊ผˆ๋‹ค.

3. CSS FRAMEWORK

CSS ํ”„๋ ˆ์ž„์›Œํฌ๋Š” ์ •๋ง ๋…์ด ๋“  ์„ฑ๋ฐฐ์ด๋‹ค. ์ง€๊ธˆ ๋ฆฌ์•กํŠธ์™€ ๋„ฅ์ŠคํŠธ์—์„œ๋Š” ํ•จ์ˆ˜ํ˜• ์ปดํฌ๋„ŒํŠธ๋ฅผ ํ†ตํ•ด ์ž‘์„ฑํ•˜์ง€๋งŒ, CSS FRAMEWORK์˜ ์˜ˆ์ œ๋“ค์„ ํด๋ž˜์Šคํ˜• ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์•„์ง๋„ ๋งŽ์ด ์กด์žฌํ•œ๋‹ค. ๋‹ค์‹œ ๋ฐ”๊ฟ”์„œ ์‚ฌ์šฉํ•˜๋Š” ๋ฒ•๋„ ๊ณต๋ถ€๋ฅผ ํ•ด์•ผ ํ–ˆ๊ณ , 'antd'์˜ ๊ธ€๋กœ๋ฒŒ ์Šคํƒ€์ผ๋ง ๋“ฑ ์„ธ๋ถ€์ ์œผ๋กœ ์ ‘๊ทผํ•˜์—ฌ ์š”์†Œ์— ์Šคํƒ€์ผ๋ง์„ ์ฃผ๊ธฐ๊ฐ€ ๋งค์šฐ ๊นŒ๋‹ค๋กœ์› ๋‹ค. (๋ชจ๋ฐ”์ผ ๋ฒ„์ „์„ ์œ„ํ•ด ๋ฏธ๋””์–ด ์ฟผ๋ฆฌ๋ฅผ ์“ฐ๋Š” ๋ถ€๋ถ„์€ ์•„์ง ๋งค์šฐ ๋งŽ์ด ๋ถ€์กฑํ•œ๋“ฏ ํ•˜๋‹ค...) ๊ฐ„ํŽธํ•˜๊ฒŒ ์ปดํฌ๋„ŒํŠธ ui๋ฅผ ์ œ๊ณต๋ฐ›๋Š” ์ž…์žฅ์ด๊ธฐ ๋•Œ๋ฌธ์— ํ”„๋ก ํŠธ ๊ฐœ๋ฐœ์ž ์ž…์žฅ์—์„œ๋„ ๋†“์น˜๋ฉด ์•ˆ๋˜๋Š” ๋ถ€๋ถ„์ธ ๊ฒƒ ๊ฐ™๋‹ค.

4. javascript ๋ฌธ๋ฒ•

์—ฌํƒœ๊นŒ์ง€์˜ ๊ณต๋ถ€ ๋ฐฉํ–ฅ์ด javascript์˜ event Listener, DOM, BOM ์œ„์ฃผ๋กœ ๊ณต๋ถ€๋ฅผ ํ•˜๊ณ  ๋ฆฌ์•กํŠธ์—์„œ ๋„ฅ์ŠคํŠธ๋กœ ๋„˜์–ด์™”๋‹ค. ๊ทธ๋ž˜์„œ ์ธ์ง€, ๋ฐฐ์—ด์˜ ํ”„๋กœํ† ํƒ€์ž… ํ•จ์ˆ˜๋“ค(push, filter, concat, find) ๋“ฑ ์“ฐ๊ณ  ์‹ถ์„ ๋•Œ ์ œ๋Œ€๋กœ ๋ชป์“ฐ๋Š” ์ƒํ™ฉ์ด ๋ฐœ์ƒํ–ˆ๋‹ค. ๋‚ด๊ฐ€ ์ƒ๊ฐํ•˜๋Š” ํ”„๋ก ํŠธ ๊ฐœ๋ฐœ์ž์˜ ๊ฐ€์žฅ ํฐ ๋•๋ชฉ์€ '๋จธ๋ฆฟ์†์œผ๋กœ ๊ตฌํ˜„ํ•œ ๋กœ์ง์„ ์ฝ”๋“œ๋ฅผ ํ†ตํ•ด ๋‚˜ํƒ€๋‚ผ ์ˆ˜ ์žˆ๋Š๋ƒ'์ธ ๊ฒƒ ๊ฐ™๋‹ค. react์™€ next๋ฅผ ํ†ตํ•ด ํ† ์ดํ”„๋กœ์ ํŠธ๋ฅผ ์ง„ํ–‰ํ•˜๊ธฐ ์ „์—, js์— ๋Œ€ํ•œ ์ข€ ๋” ํƒ„ํƒ„ํ•œ ์‹ค๋ ฅ์„ ๊ฐ–์ถ˜ ํ›„์— ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ๊ณต๋ถ€ํ•œ๋‹ค๋ฉด ํ›จ์”ฌ ๋” ๊ฐ„๊ฒฐํ•˜๊ณ  ๊ฐ€๋…์„ฑ ์ข‹์€ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ์ด๋‹ค.

5. AWS

์ •๋ง ์• ์ฆ์˜ ์•„๋งˆ์กด ์›น ์„œ๋น„์Šค์ด๋‹ค. ํ”„๋ก ํŠธ๋งŒ ๊ฐ€์ง€๊ณ  ํœ˜๋ฐœ๋˜๋Š” ๋ฉ”๋ชจ๋ฆฌ๋„ ์ข‹์ง€๋งŒ, DB๋ฅผ ํฌํ•จํ•˜์—ฌ ์กฐ๊ธˆ ๋” ์™„์„ฑ๋œ ํ”„๋กœ์ ํŠธ๋ฅผ ๋‹ค๋ฅธ ์‚ฌ๋žŒ๋“ค์—๊ฒŒ ๋ณด์—ฌ์ฃผ๊ณ  ์‹ถ์–ด์„œ ์–ด๋–ป๊ฒŒ ๋๊นŒ์ง€ ๋†“์ง€ ์•Š๊ณ  AWS๋ฅผ ํ†ตํ•ด ๋ฐฐํฌํ•˜์˜€๋‹ค. ๊ธฐ์กด ๊ฐ•์˜๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ ๋”ฐ๋ผ๋งŒ ์น˜๋Š”๋ฐ๋„, ๊ฐ•์˜์™€๋Š” ๋‹ค๋ฅด๊ฒŒ ํ„ฐ๋ฏธ๋„์—์„œ ๋˜๋‹ค๋ฅธ ์š”๋ฅ˜๋“ค์ด ๋ฐœ์ƒํ•˜๊ธฐ๋„ ํ•˜์˜€๊ณ , ๊ทธ ์˜ค๋ฅ˜๋“ค์„ ๊ตฌ๊ธ€๋งํ•˜๋Š”๋ฐ๋งŒ ํ•ด๋„ ๋ฉฐ์น ์„ ์Ÿ์•„ ๋ถ€์€ ๊ฒƒ ๊ฐ™์ง€๋งŒ, ํ•ด๋†“๊ณ  ๋ณด๋‹ˆ ๋งค์šฐ ๋ฟŒ๋“ฏํ–ˆ๋‹ค. ์ด๋ ‡๋‹ค ํ•  ๊ฒฐ๊ณผ๋ฌผ์„ ๋‚ด ๋ณธ ์  ์—†์ด, ๊ณ„์† ์ธํ„ฐ๋„ท ๊ฐ•์˜๋“ค์˜ course๋“ค์„ ํ†ตํ•ด์„œ ๊ณต๋ถ€ํ•˜๋‹ค๊ฐ€ ์ด๋ฒˆ์—์•ผ ๋ง๋กœ ํฐ ํ”„๋กœ์ ํŠธ๋ฅผ ๋งŒ๋“ค๊ฒŒ ๋˜์—ˆ๋‹ค. ํ”„๋ก ํŠธ์™€ ๋ฐฑ์—”๋“œ๋ฅผ ๋ชจ๋‘ ๋‹ค๋ค„ ๋ณด๋ฉด์„œ, ํ•œ ๊ณณ์—๋งŒ ํŽธํ–ฅ๋  ์ˆ˜ ์žˆ๋Š” ์‹œ์•ผ๋ฅผ ์–ด๋Š์ •๋„ ๋ฒ—์–ด๋‚ฌ๋‹ค๊ณ  ์ƒ๊ฐํ•œ๋‹ค. ๋ฐฑ์—”๋“œ ํ”„๋กœ๊ทธ๋ž˜๋จธ์™€ ์†Œํ†ตํ•˜๊ธฐ ์œ„ํ•ด api ์ฒ˜๋ฆฌ๋ฅผ ์–ด๋–ป๊ฒŒ RestFulํ•˜๊ฒŒ ์ฒ˜๋ฆฌํ•  ์ง€, ๋˜๋Š” DB๋ฅผ ๋งŒ๋“ค ๋•Œ ์–ด๋–ค ๊ด€๊ณ„๋กœ ๋งŒ๋“ค์–ด์•ผ ํ”„๋ก ํŠธ๋‚˜ ๋ฐฑ์—์„œ ์†Œํ†ตํ•  ๋•Œ ํŽธํ•  ์ง€์— ๋Œ€ํ•œ ๊ณ ๋ฏผ์ด ๋งŽ์ด ๋“ค์–ด ๊ฐ„ ๊ฒƒ ๊ฐ™๋‹ค.

๋„๋ฉ”์ธ์„ ์‚ฌ์„œ ์—ฐ๊ฒฐํ•˜๊ณ , lambda ์ฒ˜๋ฆฌ๋ฅผ ํ†ตํ•ด ์ด๋ฏธ์ง€๋ฅผ ๋ฆฌ์‚ฌ์ด์ง•ํ•˜๊ณ , ํƒ„๋ ฅ์  IP๋ฅผ ๋ฐ›์•„์„œ ๋„๋ฉ”์ธ์— ์—ฐ๊ฒฐํ•˜๋Š” ์ž‘์—…๋“ค์ด ๋„ˆ๋ฌด ์ƒˆ๋กญ๊ณ  ์žฌ๋ฐŒ์—ˆ๋‹ค. ์ด๋Ÿฐ ๋‹ค์–‘ํ•œ ๊ฒฝํ—˜๋“ค์ด ๋‚˜์ค‘์— ๋‚˜์˜ ๋ฐœ์ „์— ํฐ ๋ฌด๊ธฐ๊ฐ€ ๋˜๋ฆฌ๋ผ ๋ฏฟ์–ด ์˜์‹ฌ์น˜ ์•Š๋Š”๋‹ค.


About

๐Ÿ’ป next / node / mySQL / AWS ๋ฅผ ์ด์šฉํ•œ CRUD ์‚ฌ์ดํŠธ ์ œ์ž‘

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published