Devlog/Web

[Heroku+ClearDB] CORS error & 'PROTOCOL_CONNECTION_LOST' code H10 "App crashed"

FATKITTY 2022. 3. 21. 17:20
반응형

내 웹사이트가 문제없이 항상 잘 작동되고 있는 줄 알았다.

매번 deploy 작업 직후 잘 동작하는지 체크해보면 빠릿빠릿 잘 돌아가길래

'음 잘 되네' 하고 뿌듯해하며 내버려뒀음.

근데 내가 안 볼 때면 심심할 때마다 네트워크 에러를 띄운다는 사실을 며칠 전에 알게 됨.

콘솔을 확인해보니 "Access to XMLHttpRequest has been blocked by CORS policy"에

"Error: Request failed with status code 503" 어쩌구가 시뻘겋게 떠있었음 🤬

 

그렇게 CORS 에러를 해결하기 위해 밤을 지새웠다...

여러 해결 방법들을 적용해봐도 deploy 직후에는 잘 되는듯 했으나,

몇분만 지나면 갑자기

2022-03-20T13:02:52.922283+00:00 app[web.1]: /app/node_modules/newrelic/lib/shim/shim.js:1320
2022-03-20T13:02:52.922294+00:00 app[web.1]: throw error // Re-throwing application error, this is not an agent error.
2022-03-20T13:02:52.922295+00:00 app[web.1]: ^
2022-03-20T13:02:52.922296+00:00 app[web.1]:
2022-03-20T13:02:52.922296+00:00 app[web.1]: Error: Connection lost: The server closed the connection.
2022-03-20T13:02:52.922297+00:00 app[web.1]: at Protocol.end (/app/node_modules/mysql/lib/protocol/Protocol.js:112:13)
2022-03-20T13:02:52.922297+00:00 app[web.1]: at Socket.<anonymous> (/app/node_modules/mysql/lib/Connection.js:94:28)
2022-03-20T13:02:52.922298+00:00 app[web.1]: at Socket.<anonymous> (/app/node_modules/mysql/lib/Connection.js:526:10)
2022-03-20T13:02:52.922299+00:00 app[web.1]: at Socket.emit (node:events:538:35)
2022-03-20T13:02:52.922299+00:00 app[web.1]: at /app/node_modules/newrelic/lib/shim/shim.js:1314:22
2022-03-20T13:02:52.922300+00:00 app[web.1]: at LegacyContextManager.runInContext (/app/node_modules/newrelic/lib/context-manager/legacy-context-manager.js:59:23)
2022-03-20T13:02:52.922300+00:00 app[web.1]: at Shim.applySegment (/app/node_modules/newrelic/lib/shim/shim.js:1304:25)
2022-03-20T13:02:52.922301+00:00 app[web.1]: at Socket.wrapper (/app/node_modules/newrelic/lib/shim/shim.js:1916:17)
2022-03-20T13:02:52.922301+00:00 app[web.1]: at /app/node_modules/newrelic/lib/shim/shim.js:1314:22
2022-03-20T13:02:52.922301+00:00 app[web.1]: at LegacyContextManager.runInContext (/app/node_modules/newrelic/lib/context-manager/legacy-context-manager.js:59:23)
2022-03-20T13:02:52.922302+00:00 app[web.1]: Emitted 'error' event on Connection instance at:
2022-03-20T13:02:52.922303+00:00 app[web.1]: at Connection._handleProtocolError (/app/node_modules/mysql/lib/Connection.js:423:8)
2022-03-20T13:02:52.922303+00:00 app[web.1]: at Protocol.emit (node:events:526:28)
2022-03-20T13:02:52.922303+00:00 app[web.1]: at Protocol._delegateError (/app/node_modules/mysql/lib/protocol/Protocol.js:398:10)
2022-03-20T13:02:52.922304+00:00 app[web.1]: at Protocol.end (/app/node_modules/mysql/lib/protocol/Protocol.js:116:8)
2022-03-20T13:02:52.922304+00:00 app[web.1]: at Socket.<anonymous> (/app/node_modules/mysql/lib/Connection.js:94:28)
2022-03-20T13:02:52.922304+00:00 app[web.1]: at Shim.applySegment (/app/node_modules/newrelic/lib/shim/shim.js:1304:25) {
2022-03-20T13:02:52.922305+00:00 app[web.1]: fatal: true,
2022-03-20T13:02:52.922305+00:00 app[web.1]: code: 'PROTOCOL_CONNECTION_LOST'
2022-03-20T13:02:52.922305+00:00 app[web.1]: }
2022-03-20T13:02:53.100632+00:00 heroku[web.1]: Process exited with status 1
2022-03-20T13:02:53.167497+00:00 heroku[web.1]: State changed from up to crashed
2022-03-20T13:09:27.609089+00:00 heroku[router]: at=error code=H10 desc="App crashed" method=OPTIONS path=...

뭐 이런 에러가 나면서 웹사이트의 기능들이 제 기능을 못 했다.

계속 삽질을 하다가 결국 딴데서 원인이 있었음을 알아냄.

 

 

✅ Solution

초반에 설정해놓았던 CORS options의 문제가 아니었다.

알고보니 ClearDB와의 접속이 자꾸 끊어져서 생긴 문제였던 것.

생각치도 못했던 원인 ㄴㅇㄱ

 

DB connection 설정하는 코드에서 

// 기존 코드
mysql.createConnection({
	host: process.env.DB_HOST,
    	user: process.env.DB_USER,
    	password: process.env.DB_PASSWORD,
    	database: process.env.DB_DATABASE,
    	charset: "utf8mb4",
 });

 

createConnection ➡ createPool

// 수정된 코드
mysql.createPool({
	host: process.env.DB_HOST,
    	user: process.env.DB_USER,
    	password: process.env.DB_PASSWORD,
    	database: process.env.DB_DATABASE,
    	charset: "utf8mb4",
 });

 

이렇게 바꿔줬더니 바로 해결됐다!!

 

createConnection과 createPool의 차이점이 뭐길래?

궁극적인 목적은 DB connection을 만드려는 것으로 동일하다. 동작 방식이 다를뿐.

createConnection : connection을 한 번 생성하면 커넥션을 직접 종료하거나, mysql 서버가 커넥션을 끊을 때까지 그 하나의 커넥션만 존재. 그 커넥션을 다른 곳에서 참조할 수도, 재사용할 수도 있음.

createPool : 여러 connection들이 저장되는 공간. 이 pool에 커넥션을 요청하면 아무도 쓰고 있지 않아 놀고 있는(?) 상태의 커넥션을 받는다. 요청한 시점에 pool에 놀고 있는 커넥션이 아예 없다면 새로 생성된 커넥션을 받게 된다. 새로운 커넥션 생성을 더 이상 할 수 없는 지경에 다다르면, 기존의 것들 중 사용 가능한 상태의 커넥션이 생길 때까지 기다려야한다. 이 커넥션들은 open된 상태로 유지 가능하며, 쉽게 재사용이 가능하다.

⬆ 제가 직접 번역했는데 아무래도 좀 어설프네요...

참고자료에 첨부한 원문을 읽으시면 확실하게 이해되실겁니다 ㅜㅜ

 

한 줄만 바꿔줬을 뿐인데 지긋지긋했던 CORS 관련된 문제가 더는 안 생기고,

heroku logs에 App crashed라면서 뜨던 에러 로그도 더 이상 안 보이니 신기하다 ㅎㅎ

 

 

참고자료

https://superuser.com/questions/1455182/cleardb-database-on-heroku-closing-connection-after-1-min-of-inactivity/1550226#1550226?newreg=7897fa5144af412a812be78f44b801e3 

https://stackoverflow.com/questions/26432178/what-is-the-difference-between-mysql-createconnection-and-mysql-createpool-in-no

 

 

  ❤와 댓글은 큰 힘이 됩니다. 감사합니다 :-)  

반응형