GDSC 토이프로젝트 개발 노트
📅 22-12-26
📌 로그인 API 구현
- 어차피 2주차에 JWT 붙이면서 또 수정 들어갈테니 DB 접근만 우선 구현하기로 했다.
- ChatGPT에게 코드를 내놓으라고 협박했다.
- ✅ 해당 코드를 읽어보면 대강 이런식으로 하는구나, 하고 감이 빨리 잡힌다.
- ⚠️ 매번 이러면 안되고 생산성이 우선일 때 추천한다.
📌 프리즈마 연결
sequelize
쓰려다가prisma
를 추천받음 -> 매우 간결해진 코드mysql
로 ORM 없는 쌩 쿼리도 연습 차 작성해보았다.
가독성 끝내주는 쌩쿼리 보기
connection.query(
'INSERT INTO Users (nickname, name, studentId, department, status) values (?, ?, ?, ?, ?);',
[nickname, name, studentId, department, status],
(error, results) => {
if (error) {
console.error(error);
res.status(500).send({error: 'An error occurred while saving..'});
} else {
// Query the database for the name
const query = 'SELECT nickname, name FROM users WHERE name = ?';
connection.query(query, [name], (error, results) => {
if (error) {
console.error(error);
res.sendStatus(500);
} else {
res.send(results);
}
});
}
}
);
📅 23-01-01
📌 Cloud Functions 배포
- 일반적으로 Functions는 한 개 당 하나의 로직을 의도했다고 한다.
- 하지만 난 하나의 Functions에 전체 API를 연결했다.
- CJS에서 ESM으로 변경, 모듈 분리하여 배포
- ESM으로 갈아탄 이유는 리액트 부작용이다.
- 원래 Functions는 CJS만 지원했는데 수요가 많아 21년도부터 ESM도 지원하기 시작했다. [참고]
- prisma 때문에 커스텀 빌드 커맨드를 넣어야 했다. 이걸 참고했다.
📌 호출 테러? 디도스?
Functions를 보며 들었던 의문이다. 누군가 악의적으로 이 함수를 엄청 많이 호출한다면?
물론 공격자에게 금전적 이득이 없으니 세상에 어떤 관종이 그러겠나 싶겠지만, 세상은 넓고 관종은 많다.
인터뷰에 따르면 rate limit 밖에 별다른 뾰족한 수가 없는 듯 싶다.
해당 사건은 Azure에서 처리해줬다 들었고, AWS의 선례 덕분인지 전반적으로 클라우드 업계에서 비정상 트래픽은 봐주는 관행이 보인다. 하지만 애초에 문제가 안터지는 것이 좋지 않을까?
rate limit을 걸어도 호출 자체가 곧 과금이니, 과연 서버리스가 웹 백엔드로써의 좋은 '상품'인지는 좀 의구심이 든다. (기술 자체는 흥미롭고 좋다.)
📅 23-01-06
📌 파일 업로드 기능 구현
- GCP Cloud storage 연결 및 업로드
- 아래 두 레퍼런스를 적당히 짬뽕해서 구현
[그리고 아무도 안적어놓은 key 설명]
- 아래 두 레퍼런스를 적당히 짬뽕해서 구현
'Cloud Storage 사용' GCP 문서와 그 문서를 93.5% 따라한 글
- BE에서 FE로부터 날라온 이미지 파일 받기
multer
로 multipart 받아서 처리
- Postman에서 multipart를 쏘는 법은 다음과 같다.
- 그런데 json을 text가 아닌 형태로 보낼 수 있을지 알아보아야 한다.
- 저 쩜쩜쩜을 누르면 Content Type이 있던데 이걸
application/json
으로 설정하면..? (내심 기대중)
- BE 인증 미들웨어에서
Authorization
헤더를 못잡길래 로그 찍었더니authorization
으로 되어있다.- 범인은 express였다.
- RFC에 의거하면 HTTP 헤더 필드는 case insensitive라 여기까진 ok..이다.
- 그런데 express에서 제공하는 메소드의 네이밍에 낚였다. 하단 참고.
📌 header와 headers의 차이
이 답변에 따르면, 다음과 같다고 한다.
req.header
(=req.get
): case-insensitive한 서치req.headers
: case-sensitive, JS 객체의 프로퍼티 서치
다시말해
req.header('aUtHoRiZaTiOn') // ok
req.header('Authorization') // ok
req.header('authorization') // ok
req.headers['authorization'] // ok
req.headers['Authorization'] // ERROR
이렇다는 것이다.
그런데 headers
의 s가 더 광범위한 서치를 의미하는 줄 알고 바꿔쓴 것이 원인이었다. express가 모든걸 lowercase로 눌러버리는데 대문자 들은 것을 찾으라 했으니😑
📅 23-01-13
📌 이메일 인증 기능 구현
nodemailer
를 이용한 이메일 발송NODEMAILER_USER
와NODEMAILER_PASS
라는 2가지 환경변수가 들어간다.
- 인증코드 방식: 보안을 위해 정수코드는 피하기로 하였다. 지금도 좀 허술한 것 같지만..
ejs
로 메일 내용 렌더링- 프로젝트 이메일은 gmail을 선택
- 환경변수에 로그인하듯 계정 아이디/비번을 넣으니 Bad Credential이라고 한다.
- 찾아보니 less secure sign-in을 쓰면 된다는데, 더 알아보니 이 방법은 outdated였다.
- 22년 5월부터 구글 정책이 바뀌어서 2-step verification 설정 후 app password를 발급해야 한다. [참고]
- app password도 보안 상 좋지는 않다고 한다. 근데 env 푸시하는 바보짓만 안하면 될듯?
- regex로 특정 학교 이메일인지 검사
- RegExp로 test하면 boolean result를 반환한다.
// 학교 이메일이 asdf.edu일 경우
const emailRegExp = new RegExp("^[a-zA-Z0-9._%+-][email protected]$");
console.log(emailRegExp.test('[email protected]'));
- 인증코드 일치 검사
- 인증 이메일 발송 성공하면 Redis에 '이메일-코드' 형식으로 저장 (exp: 5분)
/auth/user/email/code
에서 POST로 받아서 Redis 데이터와 일치하는지 검사- 잘못된 이메일을 받을때 500으로 주고 있어서 해당 부분 보수가 필요하다.