• 카테고리

    질문 & 답변
  • 세부 분야

    풀스택

  • 해결 여부

    해결됨

프론트 ec2 빌드 시 JavaScript heap out of memory 오류가 납니다

20.12.17 16:49 작성 조회수 3.77k

0

배포하는데 세 가지 문제가 발생해 도움이 필요합니다ㅜㅠ

1. 우선 프론트 서버 문제입니다.

ec2 프론트 서버에 빌드 시 힙메모리가 누수되고 있는 것 같은데

로컬에서 build 된 client chunk 용량이 1.72MB 정도 입니다..

그런데 ec2 instance에 연결해 ubuntu에 npm run build를 하면 메모리 힙에서 문제가 생기는 것 같습니다.

backend server는 pm2로 켜놓은 상태입니다.

어디서 메모리가 누수되고 있는지 확인할 수 있는지 추전해주실 만한 방법이 있을까요?

2. 백서버의 경우 탄력적 ip로 ip주소를 고정해놓고 도메인을 등록한 상태입나다. 

이를 인스턴스 퍼블릭 IPv4로는 접근이 되는데 

 http://api.ymillonga.com로 접근하면  사이트에 연결이 안됩니다. 

hsts 해제도 확인했습니다.

제가 도메인을 산 곳에서 네임서버 수정한 후에 어느 정도 시간이 걸려서 생기는 문제인지 아니면 제가 놓치고 있는 부분이 있는지 조언 부탁드립니다!

로컬 빌드 시 프론트 용량

C:\Users\HOME\Documents\ymillonga\front>npm run build

> front@1.0.0 build C:\Users\HOME\Documents\ymillonga\front
> cross-env ANALYZE=true NODE_ENV=true next build

warn  - You are using a non-standard "NODE_ENV" value in your environment. This creates inconsistencies in the project and is strongly advised against. Read more: https://err.sh/next.js/non-standard-node-env
Warning: Built-in CSS support is being disabled due to custom CSS configuration being detected.
See here for more info: https://err.sh/next.js/built-in-css-disabled

info  - Using external babel configuration from C:\Users\HOME\Documents\ymillonga\front\.babelrc
Webpack Bundle Analyzer saved report to C:\Users\HOME\Documents\ymillonga\front\.next\analyze\server.html
Webpack Bundle Analyzer saved report to C:\Users\HOME\Documents\ymillonga\front\.next\analyze\client.html
info  - Creating an optimized production build  
info  - Compiled successfully
info  - Collecting page data
info  - Finalizing page optimization

Page                                                           Size     First Load JS
┌ λ /                                                          1.43 kB         500 kB
├   /_app                                                      0 B             105 kB
├ ○ /404                                                       262 B           106 kB
├ λ /hashtag/[tag]                                             784 B           496 kB
├ λ /login                                                     10.2 kB         485 kB
├ λ /post/[id]                                                 687 B           496 kB
├ λ /posts/related                                             1.09 kB         499 kB
├ λ /profile                                                   8.9 kB          484 kB
├ λ /signup                                                    1.33 kB         476 kB
└ λ /user/[id]                                                 1.27 kB         496 kB
+ First Load JS shared by all                                  105 kB
  ├ chunks/033f869c0cc364627d93bd7d05534baade1e7634.cc8305.js  5.03 kB
  ├ chunks/6b7903cd2497917111f687055581f790035a2aa9.c4f564.js  15.6 kB
  ├ chunks/777c2cca.558465.js                                  77 B
  ├ chunks/b6451bfa71415e1eb6b699247070fee6c4d97f38.fee3f6.js  11.5 kB
  ├ chunks/commons.7aac71.js                                   8.79 kB
  ├ chunks/framework.9d2e16.js                                 42.1 kB
  ├ chunks/main.5b6e30.js                                      7.06 kB
  ├ chunks/pages/_app.c0b4a3.js                                14.3 kB
  ├ chunks/styles.f4dce8.js                                    99 B
  ├ chunks/webpack.470e21.js                                   752 B
  └ css/777c2cca.81a3d2c1.chunk.css                            65.7 kB

λ  (Server)  server-side renders at runtime (uses getInitialProps or getServerSideProps)
○  (Static)  automatically rendered as static HTML (uses no initial props)
●  (SSG)     automatically generated as static HTML + JSON (uses getStaticProps)
   (ISR)     incremental static regeneration (uses revalidate in getStaticProps)

[==  ] info  - Generating static pages (0/1)

우분투 빌드시 오류코드

ubuntu@ip-172-31-45-132:~/ymillonga-sns/front$ npm run build   

> front@1.0.0 build /home/ubuntu/ymillonga-sns/front
> cross-env ANALYZE=true NODE_ENV=true next build

warn  - You are using a non-standard "NODE_ENV" value in your environment. This creates inconsistencies in the project and is 
strongly advised against. Read more: https://err.sh/next.js/non-standard-node-env
Warning: Built-in CSS support is being disabled due to custom CSS configuration being detected.
See here for more info: https://err.sh/next.js/built-in-css-disabled

info  - Using external babel configuration from /home/ubuntu/ymillonga-sns/front/.babelrc
Webpack Bundle Analyzer saved report to /home/ubuntu/ymillonga-sns/front/.next/analyze/server.html
info  - Creating an optimized production build ..
<--- Last few GCs --->

[17547:0x630efc0]    20581 ms: Scavenge 477.9 (490.8) -> 477.4 
(490.8) MB, 16.3 / 0.0 ms  (average mu = 0.604, current mu = 0.531) allocation failure
[17547:0x630efc0]    20601 ms: Scavenge 478.8 (494.8) -> 478.3 
(494.8) MB, 17.0 / 0.0 ms  (average mu = 0.604, current mu = 0.531) allocation failure
[17547:0x630efc0]    21501 ms: Mark-sweep 481.5 (494.8) -> 477.8 (497.3) MB, 866.5 / 0.0 ms  (average mu = 0.393, current mu = 0.116) allocation failure scavenge might not succeed


<--- JS stacktrace --->

FATAL ERROR: MarkCompactCollector: young object promotion failed Allocation failed - JavaScript heap out of memory
 1: 0xa04200 node::Abort() [node]
 2: 0x94e4e9 node::FatalError(char const*, char const*) [node] 
 3: 0xb7860e v8::Utils::ReportOOMFailure(v8::internal::Isolate*, char const*, bool) [node]
 4: 0xb78987 v8::internal::V8::FatalProcessOutOfMemory(v8::internal::Isolate*, char const*, bool) [node]
 5: 0xd33215  [node]
 6: 0xd63dae v8::internal::EvacuateNewSpaceVisitor::Visit(v8::internal::HeapObject, int) [node]
 7: 0xd6fde6 v8::internal::FullEvacuator::RawEvacuatePage(v8::internal::MemoryChunk*, long*) [node]
 8: 0xd5bfcf v8::internal::Evacuator::EvacuatePage(v8::internal::MemoryChunk*) [node]
 9: 0xd5c248 v8::internal::PageEvacuationTask::RunInParallel(v8::internal::ItemParallelJob::Task::Runner) [node]
10: 0xd4eb29 v8::internal::ItemParallelJob::Run() [node]       
11: 0xd71d40 void v8::internal::MarkCompactCollectorBase::CreateAndExecuteEvacuationTasks<v8::internal::FullEvacuator, v8::internal::MarkCompactCollector>(v8::internal::MarkCompactCollector*, v8::internal::ItemParallelJob*, v8::internal::MigrationObserver*, long) [node]
12: 0xd725dc v8::internal::MarkCompactCollector::EvacuatePagesInParallel() [node]
13: 0xd727a5 v8::internal::MarkCompactCollector::Evacuate() [node]
14: 0xd84791 v8::internal::MarkCompactCollector::CollectGarbage() [node]
15: 0xd40ab8 v8::internal::Heap::MarkCompact() [node]
16: 0xd425a8 v8::internal::Heap::CollectGarbage(v8::internal::AllocationSpace, v8::internal::GarbageCollectionReason, v8::GCCallbackFlags) [node]
17: 0xd459ec v8::internal::Heap::AllocateRawWithRetryOrFailSlowPath(int, v8::internal::AllocationType, v8::internal::AllocationOrigin, v8::internal::AllocationAlignment) [node]
18: 0xd0b2f2 v8::internal::Factory::AllocateRaw(int, v8::internal::AllocationType, v8::internal::AllocationAlignment) [node]  
19: 0xd07542 v8::internal::FactoryBase<v8::internal::Factory>::AllocateRawArray(int, v8::internal::AllocationType) [node]     
20: 0xd075f4 v8::internal::FactoryBase<v8::internal::Factory>::NewFixedArrayWithFiller(v8::internal::Handle<v8::internal::Map>, int, v8::internal::Handle<v8::internal::Oddball>, v8::internal::AllocationType) [node]
21: 0xf3d8ce v8::internal::Handle<v8::internal::NameDictionary> v8::internal::HashTable<v8::internal::NameDictionary, v8::internal::NameDictionaryShape>::New<v8::internal::Isolate>(v8::internal::Isolate*, int, v8::internal::AllocationType, v8::internal::MinimumCapacity) [node]
22: 0xf3db26 v8::internal::Handle<v8::internal::NameDictionary> v8::internal::HashTable<v8::internal::NameDictionary, v8::internal::NameDictionaryShape>::EnsureCapacity<v8::internal::Isolate>(v8::internal::Isolate*, v8::internal::Handle<v8::internal::NameDictionary>, int, v8::internal::AllocationType) [node]      
23: 0xf3e33a v8::internal::Handle<v8::internal::NameDictionary> v8::internal::Dictionary<v8::internal::NameDictionary, v8::internal::NameDictionaryShape>::Add<v8::internal::Isolate>(v8::internal::Isolate*, v8::internal::Handle<v8::internal::NameDictionary>, v8::internal::Handle<v8::internal::Name>, v8::internal::Handle<v8::internal::Object>, v8::internal::PropertyDetails, v8::internal::InternalIndex*) [node]
24: 0xf49dba v8::internal::BaseNameDictionary<v8::internal::NameDictionary, v8::internal::NameDictionaryShape>::Add(v8::internal::Isolate*, v8::internal::Handle<v8::internal::NameDictionary>, v8::internal::Handle<v8::internal::Name>, v8::internal::Handle<v8::internal::Object>, v8::internal::PropertyDetails, v8::internal::InternalIndex*) [node]
25: 0x106f4ff v8::internal::Runtime_AddDictionaryProperty(int, 
unsigned long*, v8::internal::Isolate*) [node]
26: 0x1400039  [node]
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! front@1.0.0 build: `cross-env ANALYZE=true NODE_ENV=true next build`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the front@1.0.0 build script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR!     /home/ubuntu/.npm/_logs/2020-12-17T07_21_00_369Z-debug.log

클라이언드 용량

front/config/config.js

export const backUrl = process.env.NODE_ENV === 'production' ? "http://15.165.249.3" :
 "http://localhost:3051";


export const callbackUrl = process.env.NODE_ENV === 'production' ? 
"http://15.165.249.3/user/google/callback" : "http://localhost:3051/user/google/callback";

back/ app.js

const express = require('express');
const dotenv = require('dotenv');
const passport = require('passport');
const db = require('./models');
const morgan = require('morgan');
const path = require('path');
const userRouter = require('./routes/user');
const postRouter = require('./routes/post');
const postsRouter = require('./routes/posts');
const hashtagRouter = require('./routes/hashtag');

const cookieParser = require('cookie-parser');
const session = require('express-session');
const passportConfig = require('./passport');
const cors = require('cors');
const hpp = require('hpp');
const helmet = require('helmet');//hpp, helmet:production모드일 때 보안에 필요한 필수 패키지들
const app = express();
dotenv.config();
passportConfig();
const prod = process.env.NODE_ENV === 'production';
const frontUrl = prod ? "http://ymillonga.com" : "http://localhost:3050";

db.sequelize.sync()
    .then(() => {
        console.log('db연결 성공');
    })
    .catch(console.error);
app.use(morgan('dev'));

if (prod) {
    app.use(morgan('combined'));
    app.use(hpp());
    app.use(helmet({ contentSecurityPolicy: false }));
    app.use(cors({
        origin: [frontUrl'http://3.36.18.214'],
        credentials: true,
    }))
else {
    app.use(morgan('dev'));
    app.use(cors({
        origin: true,
        credentials: true,
    }));
}

app.use(express.json());
app.use(express.urlencoded({ extended: true }));

app.use('/'express.static(path.join(__dirname'uploads')));
app.use(cookieParser(process.env.COOKIE_SECRET));
app.use(session({
    saveUninitialized: false,
    resave: false,
    secret: process.env.COOKIE_SECRET,
    proxy: prod,
    cookie: {
        httpOnly: true,
        secure: false,
        //process.env.NODE_ENV === 'production',//https일 때 true
        domain: process.env.NODE_ENV === 'production' && '.ymillonga.com'
    },
}));
app.use(passport.initialize());
app.use(passport.session());

app.use('/user'userRouter);
app.use('/post'postRouter);
app.use('/posts'postsRouter);
app.use('/hashtag'hashtagRouter);


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


app.use((reqresnext=> {
    const error = new Error(`${req.method} ${req.url} 라우터가 없습니다.`);
    error.status = 404;
    next(error);
});
app.use((errreqresnext=> {
    res.locals.message = err.message;
    res.locals.error = process.env.NODE_ENV !== 'production' ? err : {};
    res.status(err.status || 500);
    res.render('error');
});

app.listen(3051, () => {
    console.log(`3051에서 대기 중`);
});

답변 7

·

답변을 작성해보세요.

1

네 xyz로 만드셔야 합니다.

1

ping 결과는 아직도 안 나오나요? 그리고 네임서버 ip 적으셨는데 네임서버 ip는 어떻게 알고 적으셨나요?

1

ping ymillonga.com 하셨을 때 아직 나오지 않는 거죠? 호스팅 쪽 설정에서 name server를 aws로 바꾸셨나요? 바꾸고 나신 후에는 route53에서 A 레코드 설정을 하셔야 합니다.

cors쪽은 origin에 http://54.78.17.63 으로 http까지 적어보세요.

1

1. ec2가 t2.micro라서 메모리 용량이 부족한 것 같습니다. 더 큰 것을 사용하면 되지만 요금이 청구될 수 있으므로 로컬에서 빌드한 후 .next 파일을 커밋하여 서버에서 스타트하면 됩니다.

2. 터미널에서 ping 도메인주소 해보세요. 그리고 route53에서 등록한 아이피가 뜨는지 봐보세요.

0

maliethy님의 프로필

maliethy

질문자

2020.12.18

네임서버 아이피는 호스티케이알 페이지에서 'ip check'라는 버튼을 클릭하면 자동으로 값이 채워지더라구요

그리고 ping에 검색인 안 되었던 건 제가 산 도메인이 .com 이 아니고 .xyz 인데 

Route53에도 호스팅 영역이름을 ymillonga.xyz 로 만들어야 되는 거였더라구요

도메인 연결됩니다!!!!!

제로초님 덕분에  오늘 밤은 편한 마음으로 숙면할 수 있겠어요ㅜㅠ 진짜 눈물날 것 같습니다

감사합니당(꾸벅*100000)

0

maliethy님의 프로필

maliethy

질문자

2020.12.18

1.  http://를 적으니 cors문제 해결되었습니다!!

2.  호스팅 쪽 설정에서 name server를 aws로 바꿨고 route53에서 A 레코드 설정을 했습니다.

그런데도 호스트를 찾을 수 없다고 나옵니다.

이렇게 도메인 연결을 하지 않으면 google OAuth에서도 cookie문제 때문에 400 승인오류가 나오는 건가요?

0

maliethy님의 프로필

maliethy

질문자

2020.12.18

1. front에 빌드 파일을 가져온 후 start하기까지 성공했습니다!

그런데 front 서버를 시작해보니  바로 isAxiosError가 뜹니다

back서버와 연결을 제대로 하지 않아서 이런 에러가 뜨는 걸까요?

front에서는 back ip 54.180.73.165를 아래와 같이 설정해놓고

export const backUrl = process.env.NODE_ENV === 'production' ? 
"//54.180.73.165" : "http://localhost:3051";


export const callbackUrl = process.env.NODE_ENV === 'production' ? 

"//54.180.73.165/user/google/callback" : "//localhost:3051/user/google/callback"; 

back에서는 front ip 52.78.17.63을 아래와 같이 설정했습니다

const frontUrl = prod ? "//ymillonga.com" : "http://localhost:3050";

db.sequelize.sync()
    .then(() => {
        console.log('db연결 성공');
    })
    .catch(console.error);
app.use(morgan('dev'));

if (prod) {
    // app.enable('trust proxy');
    app.use(morgan('combined'));
    app.use(hpp());
    app.use(helmet({ contentSecurityPolicy: false }));
    app.use(cors({
        origin: [frontUrl'//52.78.17.63'],
        credentials: true,
   }))

그래서인지 회원가입을 해보면 cors에러도 뜨고 있습니다..

이 에러는 어떤 식으로 해결할 수 있을지요?

2. ping으로 도메인주소를 검색하니 등록되지 않은 도메인으로 나옵니다..

아직 제가 도메인을 등록한 호스팅케이알 쪽에서 처리가 안 된 건가봐요

ubuntu@ip-172-31-39-192:~/ymillonga-sns/front$ sudo npx pm2 logs 
[TAILING] Tailing last 15 lines for [all] processes (change the value with --lines option)
/home/ubuntu/.pm2/pm2.log last 15 lines:
PM2        | 2020-12-18T04:52:13: PM2 log: BUS socket file      : /home/ubuntu/.pm2/pub.sock 
PM2        | 2020-12-18T04:52:13: PM2 log: Application log path : /home/ubuntu/.pm2/logs     
PM2        | 2020-12-18T04:52:13: PM2 log: Worker Interval      : 30000
PM2        | 2020-12-18T04:52:13: PM2 log: Process dump file    : /home/ubuntu/.pm2/dump.pm2 
PM2        | 2020-12-18T04:52:13: PM2 log: Concurrent actions   : 2
PM2        | 2020-12-18T04:52:13: PM2 log: SIGTERM timeout      : 1600
PM2        | 2020-12-18T04:52:13: PM2 log: ===============================================================================
PM2        | 2020-12-18T04:52:13: PM2 log: App [npm:0] starting in -fork mode-
PM2        | 2020-12-18T04:52:13: PM2 log: App [npm:0] online
PM2        | 2020-12-18T04:58:34: PM2 log: Process 0 in a stopped status, starting it        
PM2        | 2020-12-18T04:58:34: PM2 log: Stopping app:npm id:0
PM2        | 2020-12-18T04:58:34: PM2 log: App [npm:0] exited with code [0] via signal [SIGINT]
PM2        | 2020-12-18T04:58:34: PM2 log: pid=20254 msg=process killed
PM2        | 2020-12-18T04:58:34: PM2 log: App [npm:0] starting in -fork mode-
PM2        | 2020-12-18T04:58:34: PM2 log: App [npm:0] online

/home/ubuntu/.pm2/logs/npm-out.log last 15 lines:
0|npm      | 
0|npm      | 
0|npm      | > front@1.0.0 start /home/ubuntu/ymillonga-sns/front
0|npm      | > cross-env NODE_ENV=production next start -p 80
0|npm      | 
0|npm      | 
0|npm      | > front@1.0.0 start /home/ubuntu/ymillonga-sns/front
0|npm      | > cross-env NODE_ENV=production next start -p 80
0|npm      | 
0|npm      | ready - started server on http://localhost:80
0|npm      | 
0|npm      | > front@1.0.0 start /home/ubuntu/ymillonga-sns/front
0|npm      | > cross-env NODE_ENV=production next start -p 80
0|npm      | 
0|npm      | ready - started server on http://localhost:80

/home/ubuntu/.pm2/logs/npm-error.log last 15 lines:
0|npm      | /_next/static/chunks/main-5b6e30e4e4c4041b19a2.js" as="script"/><link rel="preload" href="/_next/static/chunks/webpack-470e211b0deae0421d43.js" as="script"/><link rel="preload" href="/_next/static/chunks/framework.9d2e166d997d65d161ee.js" as="script"/><link rel="preload" href="/_next/static/chunks/777c2cca.558465dbb6a4aca39df7.js" as="script"/><link rel="preload" href="/_next/static/chunks/commons.7aac711c79de39919a5b.js" as="script"/><link rel="preload" href="/_next/static/chunks/b6451bfa71415e1eb6b699247070fee6c4d97f38.fee3f687a48eedf1e073.js" as="script"/><link rel="preload" href="/_next/static/chunks/6b7903cd2497917111f687055581f790035a2aa9.c4f56485172857df9218.js" as="script"/><link rel="preload" href="/_next/static/chunks/033f869c0cc364627d93bd7d05534baade1e7634.bed2edbffebc819ad35a.js" as="script"/><link rel="preload" href="/_next/static/chunks/styles.f4dce837bc041dd8f3be.js" as="script"/><link rel="preload" href="/_next/static/chunks/pages/_app-c0b4a3006b3626b82503.js" as="script"/><link rel="preload" href="/_next/static/chunks/pages/404-81081bd27f51e63ffb3a.js" as="script"/></head><body><div id="__next"><h1>404 - Page Not Found</h1></div><script src="https://polyfill.io/v3/polyfill.min.js?features=es6,es7,es8,es9,NodeList.prototype.forEach&amp;flags=gated"></script><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{}},"page":"/404","query":{},"buildId":"5f5Z50zcbRY5M349vwBzm","nextExport":true,"autoExport":true,"isFallback":false,"head":[["meta",{"name":"viewport","content":"width=device-width"}],["meta",{"charSet":"utf-8"}],["title",{"children":"Ymillonga"}]]}</script><script nomodule="" src="/_next/static/chunks/polyfills-d2b931b66816b47c9329.js"></script><script src="/_next/static/chunks/main-5b6e30e4e4c4041b19a2.js" async=""></script><script src="/_next/static/chunks/webpack-470e211b0deae0421d43.js" async=""></script><script src="/_next/static/chunks/framework.9d2e166d997d65d161ee.js" async=""></script><script src="/_next/static/chunks/777c2cca.558465dbb6a4aca39df7.js" async=""></script><script src="/_next/static/chunks/commons.7aac711c79de39919a5b.js" async=""></script><script src="/_next/static/chunks/b6451bfa71415e1eb6b699247070fee6c4d97f38.fee3f687a48eedf1e073.js" async=""></script><script src="/_next/static/chunks/6b7903cd2497917111f687055581f790035a2aa9.c4f56485172857df9218.js" async=""></script><script src="/_next/static/chunks/033f869c0cc364627d93bd7d05534baade1e7634.bed2edbffebc819ad35a.js" async=""></script><script src="/_next/static/chunks/styles.f4dce837bc041dd8f3be.js" async=""></script><script src="/_next/static/chunks/pages/_app-c0b4a3006b3626b82503.js" async=""></script><script src="/_next/static/chunks/pages/404-81081bd27f51e63ffb3a.js" async=""></script><script src="/_next/static/5f5Z50zcbRY5M349vwBzm/_buildManifest.js" async=""></script><script src="/_next/static/5f5Z50zcbRY5M349vwBzm/_ssgManifest.js" async=""></script></body></html>'
0|npm      |   },
0|npm      |   isAxiosError: true,
0|npm      |   toJSON: [Function: toJSON]
0|npm      | }