프로젝트 중 겪은 트러블 슈팅 (CORS, 소셜 로그인 등)
Description: magic promt라는 프로젝트를 만들면서 겪었던 서비스 구성시 환경설정, 풀스택 동작 등에 관한 트러블슈팅 기록입니다. 1.12소셜로그인까지 다루고있습니다.
현재 노트: KR-110.40 a 프로젝트 중 겪은 트러블 슈팅 (CORS, 소셜 로그인 등)
상위 분류: KR-110.40 생성형 AI를 이용한 개인 창작 마법 프로젝트
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');
결과
현재 접속한 user의 username 으로 표기하기
문제: 로그인 후 접속한 유저의 이름을 표기해야하는데 기본값인 Guest로 표기됨
트위터 구글 소셜로그인
목적
AI가 갑자기 만들어줘서 대략적으로 흐름 파악후 구현.
현재 아이디생성, 게스트로그인 만 있는데 높은 접근성을 위해서는 요즘과 같이 네이버,구글,트위터 등의 아이디를 사용하는 경우가 구현되는게 좋겠다고 생각하고 있었음
흐름
- 사용자라 소셜 로그인 시도 -> 프론트엔드가 트위터나 구글에 요청 Client ID포함
- 사용자 권한 인증동의
- 구글이나 트위터에서 인증코드를 프론트엔드로 전달. 프론트엔드는 해당 값을 백엔드로전달
예시
{
"code": "4/0000000000000000000000000000000000000",
"scope": "email profile"
}
- 백엔드는 Client ID, Client Secret(비밀키), 인증 코드를 통해 구글이나 트위터에 액세스토큰 요청
- 구글이나 트위터가 액세스 토큰과 함께 사용자 정보를 송신. 이후 이 액세스토큰으로 API요청시 사용되며, 굴이나 트위터 정보 액세스가능
- 백엔드는 해당 액세스 토큰기반으로 JWT 토큰 생성 후 프론트엔드에 전달
- 클라이언트가 JWT로 API요청
환경변수
여기서 중요한 변수확인
Google 로그인(Google Cloud Console)
GOOGLE_CLIENT_ID
및 GOOGLE_CLIENT_SECRET
Twitter 로그인(트위터 개발자 사이트)
TWITTER_CONSUMER_KEY
및 TWITTER_CONSUMER_SECRET
해당 변수들은 내 개발자 계정을 통해 발급받으며 위의 환경변수들을 통해 내 애플리케이션이 해당 플랫폼과 상호작용함
그래서 발급받을때 보면 해당 엔드포인트의 무료 월간 횟수, 최대 어플리케이션 개수등 제한사항도많음. 하지만 기본적으로 웬만하면 소규모는 무료범위 내에서 해결가능
소셜 로그인 트러블 슈팅
환경변수 설정 후 클릭시 403 및 oob 에러
구글 로그인은 클릭시 403에러, 트위터 로그인은 oob에러
트위터 로그인 에러문구
Desktop applications only support the oauth_callback value 'oob'
Client ID및 secret 변경과, callback URL twitter developer사이트에서 설정
이후 oob에러에서 다음의 에러문구로 변환
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
승인페이지까지는 확인 완료
인증 후 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에게 질문
-
비밀번호 필드 비활성화: 소셜 로그인 사용자에 대해 비밀번호 필드를 비활성화하거나
nullable
로 설정합니다. 이런 경우 비밀번호를 따로 저장하지 않고, 로그인 시 소셜 인증만으로 사용자 신원을 확인합니다. -
더미 비밀번호 생성: 소셜 로그인 사용자에게 임의의 더미 비밀번호를 생성하여 저장하지만, 이 비밀번호는 실제로 사용되지 않으며, 소셜 인증을 통해서만 로그인 가능합니다.
-
비밀번호 없는 계정 처리: 소셜 로그인 계정에 대해 비밀번호를 요구하지 않고 소셜 프로필 정보만으로 사용자 인증을 진행합니다. 이 방식에서는 비밀번호가 전혀 필요하지 않습니다.
결론
비밀번호 없는 계정 처리가 가장 운영 및 관리 측면에서 효율적
- 운영관리 편함
- 보안성 강화
- 기존시스템과 호환
해결
sql 쿼리를 통해 기존 password NOT NULL
제약 삭제
ALTER TABLE public.users ALTER COLUMN password DROP NOT NULL;
트위터 소셜 로그인 구현
(pgadmin으로 연결된 DB에서 row 생성 확인)
세션 데이터 암호화
AI가 세션만들면서 생성한 내용. 따로 SESSION_SECRET
라는 환경변수로 관리 필요
사용 용도는 일반적으로 사람마다 로그인하면 그 사람과의 세션이 유지돼야하고 고유하게 유지돼야하기 때문에 세션관리가 필요한데 이 때 사용하는 값
Error fetching user mana
guest 로그인시만 발생
원인 추정: 유저가 만들어지면서 기본마나 10이 제공돼야하는데, guest로그인은 그게 아닌거 같음
내가 직접 만든 유저나 소셜로그인은 기본마나 10이 설정돼있음.
생각해볼점
guest 로그인 유저 어떻게 관리할까? 세션ID를 사용해서 임시로 만들고 사라지게할까?
-> 다른 프로그램들의 경우를 찾아봄
실제 구현 사례
기본 register의 방식과 같지만 , 임의의 정보를 생성해서 만든다. 예를 들어 username을 uuid기반으로 만든다던가. 그리고 이 정보들의 기기의 로컬 DB등에 저장된다고한다.
해결방법
guest login시 기존의 유저등록방식 활용 단 username은 uuid기반으로 guest_${uuidv4().substring(0, 8)}
와 같이 uuid앞 8자리 활용
비밀번호는 일단 하드코딩형태로. 추후 고도화