인프런 커뮤니티 질문&답변

양동선님의 프로필 이미지
양동선

작성한 질문수

Slack 클론 코딩[실시간 채팅 with React]

폴더 구조와 리액트 라우터

http://localhost:3090/을 실행하면 Cannot GET 이렇게 뜹니다..

작성

·

440

·

수정됨

0

client.js 라우터 설정하고

import React from 'react';
import { render } from 'react-dom';
import { BrowserRouter } from 'react-router-dom';
import App from '@layouts/App';

render(
  <BrowserRouter>
    <App />
  </BrowserRouter>,
  document.querySelector('#app'),
);

App.tsx 도 라우터 설정하고

import React from "react";
import { Switch, Route, Redirect } from 'react-router-dom';
import LogIn from '@pages/LogIn';
import SignUp from '@pages/SignUp';


const App = () => {
  return (
    <Switch>
      <Redirect exact path="/" to="/login" />
      <Route path="/login" component={LogIn} />
      <Route path="/signup" component={SignUp} />
    </Switch>
  );
};

export default App;

이렇게 했는데

ㅁㅁㅁ.png렌더링이 안되고 에러도 안생기고.. 깃허브 보면서 코드확인했는데 다른게 없는거 같은데 안되요...

답변 4

0

양동선님의 프로필 이미지
양동선
질문자

다시 실행하니까 됩니다... 계속 너무 질문을 많이 하는거 같아서 죄송하고 감사합니다!!

제가 궁금해서 그런데 보통 제가 리엑트 할때는 라우터를 파일을 만들어서 거기에서 전체적으로 경로를 관리하게 했는데 지금은

client.tsx와 App.tsx 두곳에 분리해서 관리하는데 제가 했던것과는 달라서 그런데 보통 이런식으로 관리하게 되나요 현업에서는??

제로초(조현영)님의 프로필 이미지
제로초(조현영)
지식공유자

따로 파일을 둬서 관리도 가능합니다만 주소 정도 관리 가능하고 결국에는 각각의 컴포넌트 안에서 Route를 쓸 수밖에 없습니다.

0

양동선님의 프로필 이미지
양동선
질문자

네 같은 폴더안에 있어요~무경로제.png

제로초(조현영)님의 프로필 이미지
제로초(조현영)
지식공유자

image

여기서 Console 탭 오른쪽에 빨간색 15 있는데 그거 눌러서 무슨무슨 에러 있는지 봐보세요

제로초(조현영)님의 프로필 이미지
제로초(조현영)
지식공유자

에러들이 숨겨져있습니다(31 hidden)

0

양동선님의 프로필 이미지
양동선
질문자

같은 경로에 index.html도 있는 게 맞죠? 이거 어떻게 확인하는지 잘모르겟어요..

 

제로초(조현영)님의 프로필 이미지
제로초(조현영)
지식공유자

pacakge.json이랑 index.html이랑 webpack.config.ts가 같은 폴더 안에 있어야합니다.

0

제로초(조현영)님의 프로필 이미지
제로초(조현영)
지식공유자

웹팩 설정 한 번 보여주세요. 같은 경로에 index.html도 있는 게 맞죠?

양동선님의 프로필 이미지
양동선
질문자

import path from 'path';
import ReactRefreshWebpackPlugin from '@pmmmwh/react-refresh-webpack-plugin';
import webpack, { Configuration as WebpackConfiguration } from "webpack";
import { Configuration as WebpackDevServerConfiguration } from "webpack-dev-server";
import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer';
import ForkTsCheckerWebpackPlugin from 'fork-ts-checker-webpack-plugin';

interface Configuration extends WebpackConfiguration {
  devServer?: WebpackDevServerConfiguration;
}

const isDevelopment = process.env.NODE_ENV !== 'production';

const config: Configuration = {
  name: 'sleact',
  mode: isDevelopment ? 'development' : 'production',
  devtool: !isDevelopment ? 'hidden-source-map' : 'eval',
  resolve: {
    extensions: ['.js', '.jsx', '.ts', '.tsx', '.json'],
    alias: {
      '@hooks': path.resolve(__dirname, 'hooks'),
      '@components': path.resolve(__dirname, 'components'),
      '@layouts': path.resolve(__dirname, 'layouts'),
      '@pages': path.resolve(__dirname, 'pages'),
      '@utils': path.resolve(__dirname, 'utils'),
      '@typings': path.resolve(__dirname, 'typings'),
    },
  },
  entry: {
    app: './client',
  },
  module: {
    rules: [
      {
        test: /\.tsx?$/,
        loader: 'babel-loader',
        options: {
          presets: [
            [
              '@babel/preset-env',
              {
                targets: { browsers: ['IE 10'] },
                debug: isDevelopment,
              },
            ],
            '@babel/preset-react',
            '@babel/preset-typescript',
          ],
          env: {
            development: {
              plugins: [require.resolve('react-refresh/babel')],
            },
          },
        },
        exclude: path.join(__dirname, 'node_modules'),
      },
      {
        test: /\.css?$/,
        use: ['style-loader', 'css-loader'],
      },
    ],
  },
  plugins: [
    new ForkTsCheckerWebpackPlugin({
      async: false,
      // eslint: {
      //   files: "./src/**/*",
      // },
    }),
    new webpack.EnvironmentPlugin({ NODE_ENV: isDevelopment ? 'development' : 'production' }),
  ],
  output: {
    path: path.join(__dirname, 'dist'),
    filename: '[name].js',
    publicPath: '/dist/',
  },
  devServer: {
    historyApiFallback: true, // react router
    port: 3090,
    devMiddleware: { publicPath: '/dist/' },
    static: { directory: path.resolve(__dirname) },
    // proxy: {
    //   '/api/': {
    //     target: 'http://localhost:3095',
    //     changeOrigin: true,
    //   },
    // },
  },
};

if (isDevelopment && config.plugins) {
  config.plugins.push(new webpack.HotModuleReplacementPlugin());
  config.plugins.push(new ReactRefreshWebpackPlugin());
  config.plugins.push(new BundleAnalyzerPlugin({ analyzerMode: 'server', openAnalyzer: true }));
}
if (!isDevelopment && config.plugins) {
  config.plugins.push(new webpack.LoaderOptionsPlugin({ minimize: true }));
  config.plugins.push(new BundleAnalyzerPlugin({ analyzerMode: 'static' }));
}

export default config;

index.html

<html>

<head>
    <meta charset="UTF-8">
    <meta name="viewport"
        content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>슬리액</title>
    <style>
        html,
        body {
            margin: 0;
            padding: 0;
            overflow: initial !important;
        }

        body {
            font-size: 15px;
            line-height: 1.46668;
            font-weight: 400;
            font-variant-ligatures: common-ligatures;
            -moz-osx-font-smoothing: grayscale;
            -webkit-font-smoothing: antialiased;
        }

        * {
            box-sizing: border-box;
        }
    </style>
    <link rel="stylesheet"
        href="https://a.slack-edge.com/bv1-9/client-boot-styles.dc0a11f.css?cacheKey=gantry-1613184053"
        crossorigin="anonymous" />
    <link rel="shortcut icon" href="https://a.slack-edge.com/cebaa/img/ico/favicon.ico" />
    <link href="https://a.slack-edge.com/bv1-9/slack-icons-v2-16ca3a7.woff2" rel="preload" as="font"
        crossorigin="anonymous" />
</head>

<body>
    <div id="app">

    </div>
    <script src="/dist/app.js"></script>
</body>

</html>
양동선님의 프로필 이미지
양동선

작성한 질문수

질문하기