728x90
반응형

문제 상황

  1. cloudinary client를 다운받고, .ts파일을 만들어 돌리려는데 Webpack 5 어쩌고 에러가 남
    1. 문제를 해결했지만, fs module을 찾지 못했다는 에러가 계속 남

해결 방법

1번 문제

나도 문제가 생겼었는데, 문제를 해결하고 스크린샷을 찍으려 하니 이제 더 이상 문제가 생기지 않아 대신 같은 문제의 다른 사진으로 대체한다..

 

  1. webpack.config.js를 연다 (위치 - node_modules/react-scripts/config/webpack.config.js)
  2. plugin 부분에 밑에 github 답변대로 new webpack.ProvidePlugin... 부분을 넣는다.
  3. 그 아래 resolve 안에 fallback 부분을 추가하고, 필요한 모듈을 넣는다.
    https://webpack.kr/configuration/resolve/#resolvefallback
  4. 추가한 모듈들을 모두 npm install한다. 설치하지 않으면 계속 오류가 나게 된다.
  5. 실행하고 잘 돌아가는지를 확인한다.

각 모듈별 resolve 하는 방법은 다음 링크에 나와 있다. - https://webpack.kr/configuration/resolve/#resolvefallback
해당 링크는 webpack5에서 더 이상 자동으로 polyfill 하지 않는 모듈들 리스트이다.
즉, 다음 모듈들이 import되지 않아 문제가 생기므로 다음 모듈들을 다운로드하여 간다면 문제가 없어야 한다.

Webpack 5는 더 이상 Node.js의 핵심 모듈을 자동으로 폴리필하지 않습니다. 즉, 브라우저 등에서 실행되는 코드에서 사용하는 경우 npm에서 호환되는 모듈을 설치하고 직접 포함해야 합니다. 다음은 webpack 5 이전에 사용한 폴리필 목록입니다.

module.exports = {
  //...
  resolve: {
    fallback: {
      assert: require.resolve('assert'),
      buffer: require.resolve('buffer'),
      console: require.resolve('console-browserify'),
      constants: require.resolve('constants-browserify'),
      crypto: require.resolve('crypto-browserify'),
      domain: require.resolve('domain-browser'),
      events: require.resolve('events'),
      http: require.resolve('stream-http'),
      https: require.resolve('https-browserify'),
      os: require.resolve('os-browserify/browser'),
      path: require.resolve('path-browserify'),
      punycode: require.resolve('punycode'),
      process: require.resolve('process/browser'),
      querystring: require.resolve('querystring-es3'),
      stream: require.resolve('stream-browserify'),
      string_decoder: require.resolve('string_decoder'),
      sys: require.resolve('util'),
      timers: require.resolve('timers-browserify'),
      tty: require.resolve('tty-browserify'),
      url: require.resolve('url'),
      util: require.resolve('util'),
      vm: require.resolve('vm-browserify'),
      zlib: require.resolve('browserify-zlib'),
    },
  },
};

또는, 다음과 같은 방법으로도 해결 가능한 것 같다.
https://sooknise.tistory.com/169

2번 문제

일단 원인은 fs모듈이 node.js 모듈인데, 브라우저에 들어가지 못해서 나는 문제인 것 같다.
next.js를 사용하는 사람들도 해당 문제에 대해 많이 질문했는데, 대부분 next.config.js에서 fs:false로 설정하는 방식으로 문제를 해결했다.

나도 그렇게 하면 해결이 될까 싶어 따라해봤다.
위의 fallback에 fs: false,를 추가했더니 성공이다.

참고 자료

1번 문제 관련

https://github.com/web3/web3.js/issues/4090
ㄴ여기 northhub 님 답변대로 하니까 빌드됨

npm i buffer process stream-browserify os-browserify stream-http https-browserify url

node_modules/react-scripts/config/webpack.config.js 파일 수정

const webpack = require("webpack")
...

module.exports = {
  ...
  plugins: [
    new webpack.ProvidePlugin({
      Buffer: ["buffer", "Buffer"],
      process: "process/browser",
    }),
  ],
  resolve: {
    fallback: {
      http: require.resolve("stream-http"),
      https: require.resolve("https-browserify"),
      crypto: require.resolve("crypto-browserify"),
      stream: require.resolve("stream-browserify"),
      os: require.resolve("os-browserify/browser"),
      url: require.resolve("url"),
      assert: require.resolve("assert"),
    },
  },
};

https://webpack.kr/configuration/resolve/#resolvefallback

2번 문제 관련

https://github.com/JuyeolRyu/NodeSNS/issues/3

일단 해당 글에서 제일 잘 나와있다.

https://github.com/vercel/next.js/issues/1501

ㄴ여기서도

You can't use cloudinary because I hope it's a server side file issue.

라고 한다.

https://github.com/facebook/create-react-app/issues/11756#issuecomment-994680220

ㄴ브라우저에서 사용하면 안 된다는 글

https://stackoverflow.com/questions/78917930/why-i-am-getting-error-cant-resolve-fs-when-i-am-using-cloudinary-in-next-js

ㄴnext.js에서도 false로 사용을 해제한다

728x90
반응형
LIST

'Web Dev > React.js' 카테고리의 다른 글

[REACT] react-router-dom 및 module.css 사용 중 이슈  (0) 2024.08.15
728x90
반응형

개요

react-router-dom을 이용해 nav바를 만들어 routing을 제어하고, activeclassname 속성을 활용하여 nav바에서 선택된 이름을 표시하는 기능을 구현했었다.

<div className={styles['nav-center']}>
    <NavLink to='/' className={styles.navlink} activeclassname={styles.active}><span>Home</span></NavLink>
    <NavLink to='/category' className={styles.navlink} activeclassname={styles.active}><span>Category</span></NavLink>
    <NavLink to='/tags' className={styles.navlink} activeclassname={styles.active}><span>Tags</span></NavLink>
    <NavLink to='/about' className={styles.navlink} activeclassname={styles.active}><span>About</span></NavLink>
    <SearchBar />
</div>

문제상황

그런데 css modules을 이용하면서 문제가 생겼었는데, css modules에선 className 및 일부 요소들만 뒤에 hash를 붙여서 고유하게 되기 때문에 activeclassname으로 지정한 .active 클래스 이름이 적용되는 과정에서 문제가 생겼다.

activeclassname으로 지정한 .active 클래스가 (해당 path일때 클래스가 추가됨) 분명 styles.을 붙여서 넣었는데도 뒤에 해시가 붙지 않고 들어가는 문제가 생긴 것이다.

해결 1

이 문제를 해결하는데엔 다양한 해결 방법이 있다.

  1. :global()을 사용해 선택자를 global화 시킨다.
  2. 따로 .css파일을 만들어 그쪽으로 해당 부분을 옮긴다.
  3. 따로 className에 js를 이용해 현재 path를 기반으로 class를 넣어준다.

여기서 1.과 2.는 해당 className이 전역화된다는 문제가 있어 css Modules를 쓰는 의미가 없어진다고 생각했다.

따라서 3.의 방법을 사용해 현재 path일 시에만 따로 .active클래스를 넣어 주었다.

해결된 코드는 다음과 같다.

// 이렇게 되면 굳이 NavLink를 쓸 필요가 
<div className={styles['nav-center']}>
    <Link to='/' className={`${styles.navlink} ${path === '/' ? styles.active : ''}`} ><span>Home</span></Link>
    <Link to='/category' className={`${styles.navlink} ${path === '/category' ? styles.active : ''}`} ><span>Category</span></Link>
    <Link to='/tags' className={`${styles.navlink} ${path === '/tags' ? styles.active : ''}`} ><span>Tags</span></Link>
    <Link to='/about' className={`${styles.navlink} ${path === '/about' ? styles.active : ''}`} ><span>About</span></Link>
    <SearchBar />
</div>

해결한 사진

쓰다보니 반복되는 부분이 많아 다음과 같이 코드를 간결하게 작성할 수 있었다.

// 따로 navItems 배열 생성
const navItems = [
    {
        name: 'Home',
        path: '/',
    },
    ...

/// nav 부분
<div className={styles['nav-center']}>
    {navItems.map((item, index) => (
        <Link key={`nav-${index}`} to={item.path} className={`${styles.navlink} ${path === item.path ? styles.active : ''}`} ><span>{item.name}</span></Link>
        ))}
    </div>
))}

해결 2

글을 쓰는중에 다른 해결법을 찾았다.
claude가 준 답변중에 힌트가 있었는데 여기서 찾지는 못했었다.

  1. css 선택자중 속성 선택자는 암호화되지 않는다는 점을 이동한다.

수정한 코드

// js
<div className={styles['nav-center']}>
    {navItems.map((item, index) => (
        <NavLink key={`nav-${index}`} to={item.path} className={styles.navlink} activeclassname={styles.active} ><span>{item.name}</span></NavLink>
    ))}
</div>

//css
.navlink[class*="active"]>span {
    color: white;
}

참고 자료

https://stackoverflow.com/questions/57179705/i-was-unable-to-style-the-active-route-in-react-using-react-router

  • 해당 자료에는 (isActive)=>{~~} 이렇게 쓰는 내용과
  • activeClassName={styles.active} 이렇게 해결할 수 있다는 답변이 달려 있지만 실제로 해보면 둘 다 되진 않는다.
  • 심지어 activeClassName으로 쓰면 react에서 activeclassname으로 쓰라고 경고가 뜬다.

https://stackoverflow.com/questions/68783262/react-css-modules-some-css-is-not-applied-for-active-class-set-by-navlink-c

  • 여기 자료를 참고해서 activeclassname속성으로 다시 바꿨다.

참고 - css modules에서 암호화되는 선택자들 - claude.ai에 물어본 결과

  1. CSS Modules에서 암호화되는 선택자들
클래스 이름:
기본적으로 모든 클래스 이름이 암호화됩니다.
예: .className은 .styles_className__1a2b3와 같이 변환될 수 있습니다.

.className {
  color: blue;
}


복합 선택자 내의 클래스 이름:
중첩된 선택자의 각 부분이 개별적으로 암호화됩니다.
예: .nested .element는 .styles_nested__1a2b3 .styles_element__4c5d6로 변환될 수 있습니다.

.nested .element {
  font-size: 16px;
}

composes로 생성된 클래스:
composes 키워드를 사용하여 다른 클래스의 스타일을 상속받은 클래스도 암호화됩니다.
결과적으로 여러 암호화된 클래스 이름이 적용됩니다.

.composeExample {
  composes: className;
  background: yellow;
}


:local 선택자로 감싼 클래스:
:local(.className)과 같이 명시적으로 지역 범위로 선언된 클래스도 암호화됩니다.

:local(.localScoped) {
  border: 1px solid black;
}


미디어 쿼리 내의 클래스 이름:
미디어 쿼리 자체는 암호화되지 않지만, 그 안의 클래스 이름은 암호화됩니다.

@media (max-width: 600px) {
  .responsiveClass {
    font-size: 14px;
  }
}


애니메이션 이름:
@keyframes 규칙에서 사용되는 애니메이션 이름도 암호화될 수 있습니다.


CSS Modules의 확장 기능을 통해 정의된 변수나 믹스인:
일부 CSS Modules 구현에서는 변수나 믹스인도 지역화할 수 있습니다.
  1. CSS Modules에서 암호화(지역화)되지 않는 선택자들:
1. 요소 선택자: main, div, p 등과 같은 HTML 요소 선택자는 암호화되지 않습니다.
main {
  padding: 20px;
}

2. ID 선택자: #idSelector와 같은 ID 선택자도 암호화되지 않습니다.
#idSelector {
  font-size: 16px;
}

3. 속성 선택자: [data-attribute]와 같은 속성 선택자도 암호화되지 않습니다.
[data-attribute] {
  background: yellow;
}

4. 의사 클래스 및 의사 요소: :hover, ::before 등은 암호화되지 않습니다.
a:hover{
    ...
}

5. 전역 선택자: :global()로 래핑된 선택자는 암호화되지 않습니다.
:global(.globalClass) {
  border: 1px solid black;
}

6. 미디어 쿼리: 미디어 쿼리 자체는 암호화되지 않지만, 그 안의 클래스 이름은 암호화됩니다.
@media (...){
    ...
}

7. 키프레임 이름: @keyframes 규칙의 이름은 암호화되지 않습니다.
@keyframes(...){
    ...
}

8. CSS 변수 이름: --variable-name과 같은 CSS 변수 이름은 암호화되지 않습니다.
:root{
    --bg-default: #000000;
    ...
}
728x90
반응형
LIST
728x90
반응형

 

0. ubuntu 업데이트

apt update
apt upgrade

1. mysql 설치 및 설정

// 설치
sudo apt install mysql-server

// 설치 설정
sudo mysql_secure_installation

비밀번호 설정하기 -> 0~2 로 보안 강도 설정

Remove anonymous users - y

Disallow root login remotely - n

Remove test database and access to it - y

Reload privilege tables now? - y

 

-> 설정 완료

 

EC2에서 Mysql 접속

mysql -u root -p

+ 비밀번호 입력 -> mysql 접속 완료

 

php 설치

다음과 같은 명령어를 입력해 php를 설치한다.

sudo apt install php-fpm php-mysql

설치가 되었는지 확인하려면 다음과 같은 명령어를 치면 된다.

php -v

설치가 잘 되었다면 다음과 같은 결과가 나온다.

 

3. nginx - 파일 설정

default 파일 설정

먼저 다음과 경로로 접속한다

cd /etc/nginx/sites-available

그리고 폴더에 있는 default 파일을 편집한다.

sudo vi default

 

default 파일의 다음 부분을 주석 해제한다.

여기서 php 버전을 설치된 버전으로 바꿔준다.

필자는 7.2버전이 설치가 되었기 때문에 7.2로 내용을 바꿔 주었다.

**블록 내 3번째 줄 (주석 제외) 코드는 오류가 나서 주석 처리로 놔둔다.

 

nginx.conf 설정

그리고 /etc/nginx 폴더로 가서 nginx.conf 파일의 다음 내용을 편집해준다.

cd /etc/nginx
sudo vi nginx.conf

server_names_hash_bucket_size 64부분의 주석을 해제해 준다.

 

nginx 설정이 끝나면, 꼭 test와 restart 를 해주어야 한다.

sudo nginx -t
sudo service nginx restart

 

 

다음 글에서는 도메인을 연결하고, 서브도메인 및 리다이렉션을 설정하는 방법을 소개하겠다.

728x90
반응형
LIST

'Web Dev > BackEnd' 카테고리의 다른 글

[UMC] APM 실습 #1주차  (0) 2022.03.18
728x90
반응형

 

Node.js는 크롬의 v8엔진 기반 javascript 런타임이다.

Node.js에서 제공하는 라이브러리인 express.js를 사용하면 웹 서버를 쉽게 구축할 수 있다.

node.js 프레임워크를 배우며 공부한 내용을 정리하고, 관련 지식을 찾는 사람에게도 내용을 공유하기 위해 해당 주제에 대해 작성해보기로 했다.

1. 폴더 및 package.json 설정

Node.js 프로젝트를 시작하려면 먼저 폴더를 만들고, 거기에 사용할 라이브러리(모듈)을 설치해야 한다.

-> BackEnd Study 폴더를 만들어 주고, 거기에 npm init 명령어를 입력해준다.

 

npm init 명령어를 입력하면 cmd창에 이것저것 이름을 설정해주라는 항목이 뜨는데, 

일단 특별한 설정을 해주지 않을 거면 전부 enter 키를 눌러주면 된다.

그럼 다음과 같이 폴더 아래 파일이 생성된다.

필자는 이미 express 라이브러리를 설치해서 package-lock.json 등의 파일이 있다.

2. localhost로 서버 열어보기

폴더에 app.js 파일을 만들어 다음과 같은 코드를 입력해준다.

// app.js
const express = require("express");
const app = express();

app.set('port', process.env.PORT || 3000);

app.get('/', (req, res) => {
    res.send("hello, express");
});

app.listen(app.get('port'), () => {
    console.log(app.get('port'), "번 포트에서 대기 중");
});

그리고 cmd 창에서 경로를 BackEnd Study로 맞춰준 다음, node app.js를 입력해 준다.

그럼 다음과 같은 로그가 뜨면서 localhost에서 서버가 열린다.

localhost의 3000번 포트로 접속하면 (http://localhost:3000) 다음과 같이 사이트가 열린다.

 

이제 html 파일을 응답으로 전달해 보겠다.

폴더 안에 html 파일을 추가해주고 경로를 설정해 줄 것이다.

그리고 아까의 코드에서 res.send() 부분을 res.sendFile()로 바꿔 주기만 하면 된다.

 

먼저 코드는 다음과 같다.

// app.js
const express = require("express");
const path = require("path");

const app = express();

app.set('port', process.env.PORT || 3000);

app.get('/', (req, res) => {
    res.sendFile(path.join(__dirname, '/index.html'));
});

app.listen(app.get('port'), () => {
    console.log(app.get('port'), "번 포트에서 대기 중");
});
// index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Express Server</title>
</head>
<body>
    <h1>Welcome To Express</h1>
    <p>2. html 응답으로 보내기</p>
</body>
</html>

폴더 안에 index.html을 추가해 주고, path 라이브러리를 이용해 경로를 지정해 준다.

그리고 app.js 파일 내용을 다음과 같이 설정해준다. (sendFile(), path.join() 메소드 이용)

 

그리고 서버를 다시 시작해주면 (node app.js) 다음과 같이 결과가 나온다.

일단 이것으로 우리는 사용자의 요청에 html 파일 및 적절한 응답을 보내줄 수 있는 법을 배웠다.

다음 시간에는 다양한 uri에 적절한 응답을 보내는 방법, 미들웨어를 추가하는 방법 등을 배워 보겠다.

 

+) 배우면서 개인적으로 궁금했던 점들

  1. http 모듈로도 서버를 구축할 수 있다는데, express 모듈과의 차이점은 무엇일까? - (https://quark21.tistory.com/331) 참고
  2. port를 설정해 줄때, app.set 메소드를 이용하는 대신, const port = 3000;으로 변수에 값을 넣어주고, app.listen() 메소드의 app.get('port') 부분에 변수를 넣어 줘도 되는데 둘의 차이는 무엇일까?
728x90
반응형
LIST

+ Recent posts