기존에 main브런치에서 작업 후 dev나 prod브런치로 pr시 배포하게끔 설정했으나
개발서버, 운영서버를 별도로 할 필요가 없어 프론트와 백 전부 main 브런치를 배포브런치로 변경했다.
깃 워크플로의 브런치만 변경하여 배포했고 액션이 성공하길래 잘 되는줄 알았으나
- name: Extract metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=ref,event=branch
여기서 대상 브런치로태그를 넣고있어서 이미지 갱신이 안되고있더라;;
type=ref,value=dev
태그는 쓰던대로 dev로 푸시하게 다시 수정하니 잘 반영됬다.
우선 배포환경을 만들어둿으니 이제 내용물
서버 구조는

routes에서 경로 설정하고
토큰을 검증하는 걸로
const { verifyToken } = require('../utils/jwt');
const { errorResponse } = require('../utils/response');
const authenticateToken = (req, res, next) => {
const authHeader = req.headers['authorization'];
const token = authHeader && authHeader.split(' ')[1];
if (!token) {
const error = errorResponse('Access token is required', 401);
return res.status(401).json(error);
}
try {
const decoded = verifyToken(token);
req.user = {
idx: decoded.idx,
userId: decoded.user_id,
};
next();
} catch (error) {
console.error('JWT verification error:', error.message);
let statusCode = 403;
let message = error.message;
let object = error.code;
console.log(
'error.code',
error.code,
'error.name',
error.name,
'error.message',
error.message)
if (error.code === -1001) {
statusCode = 401;
message = 'Token expired';
}
const errorRes = errorResponse(message, statusCode);
errorRes.object = object;
return res.status(statusCode).json(errorRes);
}
};
const optionalAuth = (req, res, next) => {
const authHeader = req.headers['authorization'];
const token = authHeader && authHeader.split(' ')[1];
if (!token) {
req.user = null;
return next();
}
try {
const decoded = verifyToken(token);
req.user = {
idx: decoded.idx,
userId: decoded.user_id,
};
next();
} catch (error) {
console.error('JWT verification error:', error.message);
let statusCode = 403;
let message = error.message;
let object = error.code;
if (error.code === -1001) {
statusCode = 401;
message = 'Token expired';
}
const errorRes = errorResponse(message, statusCode);
errorRes.object = object;
return res.status(statusCode).json(errorRes);
}
};
module.exports = {
authenticateToken,
optionalAuth
};
auth.js
router.get('/cyphers', optionalAuth, gameController.getCyphers);
토큰이 있어도되고 없어도되는경우
router.post('/favorites', authenticateToken, gameController.mergeFavorites)
무조건 있어야되는경우
로 체크하고 컨트롤러 진입 후 필요한 서비스 호출.
먼저 사이퍼즈로
api호출은
const axios = require('axios');
const createApiClient = (baseURL, options = {}) => {
const client = axios.create({
baseURL,
timeout: options.timeout || 10000,
headers: {
'User-Agent': 'board-server/1.0.0',
'Content-Type': 'application/json',
...options.headers
}
});
client.interceptors.request.use(
(config) => {
console.log(`API Request: ${config.method?.toUpperCase()} ${config.baseURL}${config.url}`);
return config;
},
(error) => {
return Promise.reject(error);
}
);
client.interceptors.response.use(
(response) => {
return response;
},
(error) => {
console.error(`API Error (${error.config?.baseURL}):`, error.message);
console.error('Request config:', {
method: error.config?.method,
url: error.config?.url,
params: error.config?.params,
data: error.config?.data
});
return Promise.reject(error);
}
);
return client;
};
module.exports = {
createApiClient,
};
httpClient.js 만들고
constructor() {
this.neopleApiClient = createApiClient('https://api.neople.co.kr');
}
서비스에서 선언뒤에
let response = await this.neopleApiClient.get('/cy/players', { params });
이런식으로 호출했다.
다행히 문서대로 하니까 정상호출.
계정 기본정보를 위해
/cy/players
에서 playerId를 가져와
/cy/players/${playerId}
로 보다 자세한 정보를 가져와 응답.

검색화면은 간단한 정보만.
상세에서는
/cy/players/${playerId}/matches
로 30일치 전적만 우선 가져오기로 하고

라디오 선택시 공식, 일반 기록을 불러온다.