프로젝트 중 겪은 트러블 슈팅 (CORS, 소셜 로그인 등)

Description: magic promt라는 프로젝트를 만들면서 겪었던 서비스 구성시 환경설정, 풀스택 동작 등에 관한 트러블슈팅 기록입니다. 1.12소셜로그인까지 다루고있습니다.

현재 노트: KR-110.40 a 프로젝트 중 겪은 트러블 슈팅 (CORS, 소셜 로그인 등)
상위 분류: KR-110.40 생성형 AI를 이용한 개인 창작 마법 프로젝트

#개인프로젝트 #프로젝트경험 #magic_prompt

500 Error인데 동작한경우

/api/auth/register
요구되는 json 입력시 반환값은 500 에러인데, 제대로 생성된 경우

상태확인

일단 정상작동은 함. users를 통해 데이터 확인.

추론

코드 분석결과 생성이후 -> jwt Sign ->201 상태인데 임 jwt sign에서 에러발생으로 추청

jwt secret 환경 불러와지는지 확인 -> undefined
기존동작하던 PORT 변수 불러와지는 확인 -> undefined
문법 확인->이상없음

해결

replit secrets라는 replit에서 배포할경우에 사용하는 변수라는 개념 학습
replit secret 생성후 테스트-> 인식못함 확인 ->문법결과 이상없음-> 기존 require("dotenv").config(); 코드 삭제-> 환경변수 제대로 인식되는거 확인 해결

frontend에서 register 등록시 network error.

처음에 cors에러로 추정 cors 추가 -> 안됨
REAC_API_URL 인거 같아 일단 하드코딩된 replit에서 생성된 긴 url로 수정
자체웹브라우저에서 디쇠 CORS policy 문구 확인
app.js cors 설정 추가, 그리고 app.use(cors(corsOptions)); 적용빼먹지말기

DB 기존 테이블에 column 추가 및 업데이트

기존 테이블에 새로운 컬럼 추가

기존 유저데이터에 소지하고 있는 마나라는 데이터를 추가할려고함. 즉 기존 테이블에 새로운 컬럼 생성하기. 간단하게 sql로동작
ALTER TABLE users ADD COLUMN mana INTEGER DEFAULT 100;

기존 테이블의 컬럼 default값 변경

100은 너무큰거같아서 default 값 10으로변경하려고 같은 명령어 시도

같은 명령어 사용시 이미 존재하는 관계라며 에러 발생
쿼리를 통해 일괄적용. 만약 특정조건시 where문 사용
ALTER TABLE users ALTER COLUMN mana SET DEFAULT 10;

Node 메모리 누수

증상

잘되던 React에서 다음의 에러 발생

Starting the development server...


<--- Last few GCs --->

[5830:0x453d830]     8410 ms: Mark-Compact (reduce) 127.3 (132.4) -> 124.8 (129.4) MB, 15.02 / 0.00 ms  (+ 10.8 ms in 26 steps since start of marking, biggest step 4.0 ms, walltime since start of marking 48 ms) (average mu = 0.732, current mu = 0.615) all[5830:0x453d830]     8471 ms: Mark-Compact (reduce) 127.5 (130.9) -> 126.3 (131.2) MB, 38.73 / 0.00 ms  (average mu = 0.587, current mu = 0.374) allocation failure; scavenge might not succeed


<--- JS stacktrace --->

FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory
----- Native stack trace -----

원인분석

확인

node가 사용하는 힙용량 확인
node -e 'console.log(v8.getHeapStatistics().heap_size_limit/(1024*1024))'

전체적인 node 메모리 사용량 확인
node -e 'console.log(v8.getHeapStatistics())'

해결

아마 수정과정에서 메모리사용 변수가 바뀐거같음.
package.json에서 start시 파라미터로 최대 메모리 설정해줘서 해결
... --max-old-space-size=4096 start

JWT Secret key값이 바뀐후 세션에러문제

갑자기 세션로그인에러 발생
Your session has expired. Please log in again.

추측 및 확인

탭들 전부 닫았다 다시 해봐도 문제. AI문의 JWT문제인거같음.
로그로 확인. backend쪽 인증

Received token: Token present
Token verification failed: secret or public key must be provided

jwt BEFORE라는 키값으로 만들어졌는데 어디에서 수정되면서 로그인시 AFTER라는 값을 사용하는거 같음.

해결

일단 원래쓰던 JWT_SECRET 환경변수를 사용하겠끔 전부 사용하겠금 바꾸고 || "BEFORE" 처럼 기본값 추가. 이후 로그도 확인
console.log('JWT_SECRET used:', process.env.JWT_SECRET ? 'Environment variable' : 'Fallback key');

결과
Pasted image 20240928021139.png

현재 접속한 user의 username 으로 표기하기

문제: 로그인 후 접속한 유저의 이름을 표기해야하는데 기본값인 Guest로 표기됨

트위터 구글 소셜로그인

목적

AI가 갑자기 만들어줘서 대략적으로 흐름 파악후 구현.
현재 아이디생성, 게스트로그인 만 있는데 높은 접근성을 위해서는 요즘과 같이 네이버,구글,트위터 등의 아이디를 사용하는 경우가 구현되는게 좋겠다고 생각하고 있었음

흐름

  1. 사용자라 소셜 로그인 시도 -> 프론트엔드가 트위터나 구글에 요청 Client ID포함
  2. 사용자 권한 인증동의
  3. 구글이나 트위터에서 인증코드를 프론트엔드로 전달. 프론트엔드는 해당 값을 백엔드로전달
    예시
{
  "code": "4/0000000000000000000000000000000000000",
  "scope": "email profile"
}
  1. 백엔드는 Client ID, Client Secret(비밀키), 인증 코드를 통해 구글이나 트위터에 액세스토큰 요청
  2. 구글이나 트위터가 액세스 토큰과 함께 사용자 정보를 송신. 이후 이 액세스토큰으로 API요청시 사용되며, 굴이나 트위터 정보 액세스가능
  3. 백엔드는 해당 액세스 토큰기반으로 JWT 토큰 생성 후 프론트엔드에 전달
  4. 클라이언트가 JWT로 API요청

환경변수

여기서 중요한 변수확인
Google 로그인(Google Cloud Console)
GOOGLE_CLIENT_IDGOOGLE_CLIENT_SECRET

Twitter 로그인(트위터 개발자 사이트)
TWITTER_CONSUMER_KEYTWITTER_CONSUMER_SECRET

해당 변수들은 내 개발자 계정을 통해 발급받으며 위의 환경변수들을 통해 내 애플리케이션이 해당 플랫폼과 상호작용함

그래서 발급받을때 보면 해당 엔드포인트의 무료 월간 횟수, 최대 어플리케이션 개수등 제한사항도많음. 하지만 기본적으로 웬만하면 소규모는 무료범위 내에서 해결가능

소셜 로그인 트러블 슈팅

환경변수 설정 후 클릭시 403 및 oob 에러

구글 로그인은 클릭시 403에러, 트위터 로그인은 oob에러

트위터 로그인 에러문구
Desktop applications only support the oauth_callback value 'oob'

Client ID및 secret 변경과, callback URL twitter developer사이트에서 설정

이후 oob에러에서 다음의 에러문구로 변환

Pasted image 20240928180040.png
ENV 정리 후 다시 체크. Consumer Key값인데 Client ID값과 Secret을 넣은 부분을 확인. 트위터 Dev 환경을 처음사용하기에 생긴거라 추론.
이후 해당 변수로 수정후 다시 로그인 시도

CallBack URL error 발생

X developer에서 어플리케이션에서 callback url을 설정하는 부분이 있는데 다시 확인해봄
https://2121424-1421421-11f.picard.replit.dev:3000/api/auth/twitter/callback 인데 앞의 api를 빼넣고 넣었음. 정확히 수정후 save

승인페이지까지는 확인 완료

Pasted image 20240928183649.png

인증 후 column값이 없다는 에러발생

추측

원하는 동작은 소셜 로그인후, 해당 정보 기반으로 유저가 없다면 생성을, 이미 존재하는 유저라면 로그인을 수행하는게 목적임. 근데 현재 기능상 소셜로그인후까지 밖에 안 됐기떄문이라 예상.
해당 로그의 경우 DB접근해서 twitter_id 라는 column기준으로 user 존재여부 확인하려는데 해당값이 없어서 그런듯

error: column "twitter_id" does not exist
    at /home/runner/MagicPromptGame/node_modules/pg-pool/index.js:45:11
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async Strategy._verify (/home/runner/MagicPromptGame/backend/src/config/passport.js:63:22)

근거

passort.js 63번쨰 줄 쿼리
let user = await pool.query('SELECT * FROM users WHERE twitter_id = $1', [profile.id]);

해결 해당 column 테이블에 추가

ALTER TABLE users
ADD COLUMN IF NOT EXISTS twitter_id TEXT UNIQUE;

pass word null relation constraints

소셜 로그인시 아마 기본적으로 비밀번호는 따로 입력안하는데 그래서 null값으로 넣으려다보니 정책위반으로 안되는 거같음

증상

The error indicates that a null value was attempted to be inserted into the password column of the users table, which violates the not-null constraint.

생각

소셜로그인시 기본 password값은 어떻게 처리할것인가? 일단 AI에게 질문

결론

비밀번호 없는 계정 처리가 가장 운영 및 관리 측면에서 효율적

해결

sql 쿼리를 통해 기존 password NOT NULL 제약 삭제
ALTER TABLE public.users ALTER COLUMN password DROP NOT NULL;

트위터 소셜 로그인 구현
(pgadmin으로 연결된 DB에서 row 생성 확인)
Pasted image 20240928194530.png

세션 데이터 암호화

AI가 세션만들면서 생성한 내용. 따로 SESSION_SECRET라는 환경변수로 관리 필요

사용 용도는 일반적으로 사람마다 로그인하면 그 사람과의 세션이 유지돼야하고 고유하게 유지돼야하기 때문에 세션관리가 필요한데 이 때 사용하는 값

Error fetching user mana

Pasted image 20241014145256.png

guest 로그인시만 발생
원인 추정: 유저가 만들어지면서 기본마나 10이 제공돼야하는데, guest로그인은 그게 아닌거 같음
내가 직접 만든 유저나 소셜로그인은 기본마나 10이 설정돼있음.

생각해볼점
guest 로그인 유저 어떻게 관리할까? 세션ID를 사용해서 임시로 만들고 사라지게할까?
-> 다른 프로그램들의 경우를 찾아봄

실제 구현 사례
기본 register의 방식과 같지만 , 임의의 정보를 생성해서 만든다. 예를 들어 username을 uuid기반으로 만든다던가. 그리고 이 정보들의 기기의 로컬 DB등에 저장된다고한다.

해결방법
guest login시 기존의 유저등록방식 활용 단 username은 uuid기반으로 guest_${uuidv4().substring(0, 8)} 와 같이 uuid앞 8자리 활용
비밀번호는 일단 하드코딩형태로. 추후 고도화