| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | |||||
| 3 | 4 | 5 | 6 | 7 | 8 | 9 |
| 10 | 11 | 12 | 13 | 14 | 15 | 16 |
| 17 | 18 | 19 | 20 | 21 | 22 | 23 |
| 24 | 25 | 26 | 27 | 28 | 29 | 30 |
| 31 |
- 위드굿즈
- 카카오뷰 탭이동
- 엑셀 프린트하기
- 이석증
- HTML
- 원씽
- 30일 글쓰기
- 성공에 대한 거짓말
- CSS
- 책 원씽
- 웹기초
- Git 팀 작업
- 실시간 통신
- 카카오뷰N잡
- 카뷰 수익 인증
- 카카오뷰 성장
- Axios 라이브러리
- 카카오뷰 부업
- 위드굿즈 굿즈샵
- 카카오뷰 온라인 수익화
- 도서 원씽
- 엑셀 기초 함수
- express.js 환경 셋팅
- 카카오뷰 초보
- ppt 다이어그램
- 카카오뷰 수익
- git 협업하기
- 성공비법
- 자기관리
- ppt 도형 색
- Today
- Total
김데이의 개발공부
[ TIL ] Day 32 - 개인 프로젝트 미션 3 : 모범답안 훓어보기 본문
[ TIL ] Day 32 - 개인 프로젝트 미션 3 : 모범답안 훓어보기
theday365 2025. 11. 10. 19:05🗓️ 수업 일자 : 2025.11.10
✨ 오늘의 수업 평가 : [ REVIEW ] 🌀📝 리마인드 데이 🌀📝
다른 팀원분들이 애써주셔서 팀 프로젝트는 무난하게 진행되고 있어서,
나름 팀 작업에 도움이 될까 싶어서 Sweggar(https://swagger.io/)에 대해 공부해봤는데
멘토님 말대로 그냥 쉽게 쓸 수 있는 툴이 아니어서 일단 보류 했다 ㅎㅎ
오후에는 개인 프로젝트에 대한 모범답안이 나와서 내 코드와 비교하며 다른 점에 대해 확인 하는 시간을 가졌다.
멘토님과 고민했던 Comment 모델링에 대해 주강사님과도 논의 했는데,
다행이도 그냥 내가 작업한 대로 가져가도 문제는 없을 것 같다고 해 주셔서 뚝심있게 밀어보기로 결심 했다~
(나중에 가서 안되면, 다시 뒤엎으면 되지~ 그땐 또 그때대로 뭔갈 또 배우지 않을까 싶다ㅎㅎ)
👩💻 [개인 / 팀 프로젝트] 오늘 작업 내용 💻
- 팀 프로젝트 작업 : Sweggar(https://swagger.io/) 공부하기 맛보기
- 개인 프로젝트 : 모범 답안과 비교하기
📝 오늘 배운 내용
- Prisma Client 단일 선언 방식
- Struct 심화 사용법 : 검증 & 변환하기
- Multer 파일 포맷 / 규격 설정하기
1. Prisma Client 단일 선언 방식
- Prisma 에서는 Prisma Client를 사용할 때마다 매번 불러오는 것이 아닌, 작업 전체에서 한번만 불러온 뒤 재사용을 권장
- 해당 방식의 장점
- 단일 인스턴스 사용 : APP의 성능과 안정성을 위해 하나만 생성
- 중앙 집중식 관리 : lib 폴더 안에 prisma.ts 또는 prismaClient.js 처럼 하나의 파일에서 인스턴스를 관리
- 참고 문헌 : 프리즈마 공식 문서 https://www.prisma.io/docs/orm/more/help-and-troubleshooting/nextjs-help
Comprehensive Guide to Using Prisma ORM with Next.js | Prisma Documentation
Learn best practices, monorepo strategies, and dynamic usage techniques for Prisma ORM in Next.js applications.
www.prisma.io
[기존] 모든 비지니스 로직 파일(controller.js)의 상단에 선언

[변경] Prisma Client 인스턴스 파일을 생성하고, controller.js 파일에서는 해당 인스턴스를 불러와 사용

2. Struct 심화 사용법 : 검증 & 변환하기
- 기존 : Superstruct를 사용하여 데이터 검증 방식만 사용
- 심화 : 데이터를 검증하며, 유효성 검사를 통과 시키기 위해 DB의 규정에 맞는 데이터로 변환 진행
[예시]
1. 문자열로 받은 숫자에 대해 "형변환" 진행
[struct.js]
import { coerce, number, string } from 'superstruct';
// coerce : "문자 -> 숫자" 같이 변환 규칙을 정의할 때 사용하는 메서드'
// coerce(targetType, sourceType, transformFunction)
// (변환 후 타입, 변환 전 타입, 변환 로직)
// number : "숫자" 타입 구조 정의(숫자가 아니면 값 사용 불가)
// string : "문자" 타입 구조 정의
export const MyNumber = coerce(number(), string(), (value) => parseFloat(value));
// 문자형으로 받은 값을 숫자형으로 변환하되, 소숫점까지 있는 숫자로 변환
// === 실제 사용 ===
[controller.js]
import { create } from 'superstruct';
import { MyNumber } from '../lib/struct.js';
create("42.5", MyNumber); // 문자열 "42.5"를 숫자형 42.5로 변환
create(true, MyNumber); // 입력 값 자체가 문자열이 아니라 검증 자체를 안하고 에러 반환
create("hello", MyNumber); // 문자열이 들어왔지만, 숫자형 변환이 되지 않는(NaN)이라 타입 에러 발생
2. 문자열로 받은 내용을 모두 대문자로 변환
[struct.js]
import { coerce, string } from 'superstruct';
// coerce : "문자 -> 숫자" 같이 변환 규칙을 정의할 때 사용하는 메서드'
// coerce(targetType, sourceType, transformFunction)
// (변환 후 타입, 변환 전 타입, 변환 로직)
// string : "문자" 타입 구조 정의
export const ToUpperString = coerce(string(), string(), (val) => v.toUpperCase());
// 문자형으로 받은 값을 문자형으로 변환하되, 소문자를 모두 대문자로 반환
// === 실제 사용 ===
[controller.js]
import { create } from 'superstruct';
import { ToUpperString } from '../lib/struct.js';
create("hello", ToUpperString); // HELLO 로 반환하여 값 사용
create(123, ToUpperString); // 형 타입이 맞지 않아, 에러를 내보내고 변환 안함
참고 문헌
1. Superstruct 데이터 검증 방식 : Validating Data - https://docs.superstructjs.org/guides/02-validating-data
Validating Data | Superstruct
Superstruct is designed to let you validate any data, ensuring that it matches a specific schema. In this guide we'll show you some of the possibilities. The simplest structs are ones that validate "primitive" values, like strings, numbers or booleans. For
docs.superstructjs.org
2. Superstruct 데이터 변환(강제) 방식 : Coercing Data - https://docs.superstructjs.org/guides/02-validating-data
Validating Data | Superstruct
Superstruct is designed to let you validate any data, ensuring that it matches a specific schema. In this guide we'll show you some of the possibilities. The simplest structs are ones that validate "primitive" values, like strings, numbers or booleans. For
docs.superstructjs.org
3. Multer 파일 포맷 / 규격 설정하기
1. 파일 저장 용량 설정하기
limits : 선택적 설정 값, 파일의 크기 제한을 지정하는 객체
| 속성 | 설명 | 기본값 |
| fieldNameSize | 업로드할 때 name="something" 이런 필드 이름의 최대 길이 | 100 bytes |
| fieldSize | 파일이 아닌 일반 텍스트 필드 값의 최대 크기 (예: input text) | 1MB |
| fields | 파일이 아닌 일반 필드의 최대 개수 | 무제한 |
| fileSize | 한 개 파일의 최대 크기 (byte 단위) | 무제한 |
| files | 업로드 가능한 파일 필드의 최대 개수 | 무제한 |
| parts | multipart 폼 전체에서 필드 + 파일 합친 최대 개수 | 무제한 |
| headerPairs | multipart 요청에서 파싱 가능한 헤더 key=value 쌍의 최대 개수 | 2000 |
export const upload = multer({
limits: {
fileSize: 5 * 1024 * 1024, // 파일 1개당 5MB를 넘지 않는 파일
files: 3, // 파일 최대 3개까지 가능
fields: 10, // 일반 텍스트 필드는 최대 10개 가능
},
});
+ 파일이 아닌 일반 텍스트에 제한을 두는 이유
- 보안 : 누군가 악의적으로 POST 요청에 엄청 긴 문자열을 넣는 경우, 서버 메모리를 소진해버림 ( ⇒ DoS 방지용 )
- 서버 안정성 : 일반 사용자의 경우에도 예상치 못한 텍스트가 들어 올 경우, 서버의 성능이 저하 될 수 있으므로 방지
- 정상적인 요청 구분 : 이름 / 주소 / 설명 같은 경우 일반적인 용량이 있으므로, 잘못 된 접근을 사전에 방지
2. 파일 이름 커스텀 하기
diskStorage : 파일을 디스크에 저장 할 때 사용자가 커스텀 할 수 있도록 도와주는 객체
const storage = multer.diskStorage({
// 저장할 파일 경로 지정
destination: function (req, file, cb) {
cb(null, '/tmp/my-uploads')
},
// 파일 이름 설정 : 아래 여러 방식 참고
filename: function (req, file, cb) {
cb(null, fileFN)
}
})
const upload = multer({ storage: storage })
// === 파일의 이름 지정 방식 ===
// 1. 저장 시 설정 값 & 시간 이용하기
filename: function (req, file, cb) {
cb(null, file.fieldname + '-' + Date.now())
}
// 2. UUID 사용하기
filename: function(req, file, cb) {
const ext = path.extname(file.originalname);
const filename = ${uuidv4()}${ext};
cb(null, filename);
},
3. 파일 포맷 설정 후 잘못된 파일 걸러내기
// 사용할 확장자명을 img와 document로 나눠서 관리
const FILE_TYPE_WHITELIST = {
image: ['image/png', 'image/jpeg', 'image/jpg'],
document: ['application/pdf'],
};
// 입력 된 파일을 새로운 변수에 Set()객체로 생성
const ALLOWED_IMAGE_TYPES = new Set([
...FILE_TYPE_WHITELIST.image,
...FILE_TYPE_WHITELIST.document,
]);
export const upload = multer({
fileFilter(req, file, cb) {
const isValidType = ALLOWED_IMAGE_TYPES.has(file.mimetype);
// 현재 파일의 확장자가 객체에 있는지 없는지 확인하는 변수
// 만약 확장자가 없는 경우
if (!isValidType) {
return cb(
new BadRequestError(`지원하지 않는 파일 형식입니다: ${file.mimetype}`)
);
}
// 확장자가 올바르게 지정 되었다면
cb(null, true);
},
});
📃 내일은 뭘 배울까 🤔
- 팀 작업 중간 점검 발표 🚀
'코드잇 Node.js(BE) 부트 캠프 > TIL (Today I Learn) 📑' 카테고리의 다른 글
| [ TIL ] Day 34 - Swagger 전격 분석하기! 📋🖊️ (0) | 2025.11.12 |
|---|---|
| [ TIL ] Day 33 - 에러 처리 흐름과 종류 ⚠️🚨 (0) | 2025.11.11 |
| [ TIL ] Day 31 - 팀 초급 프로젝트(실습) : 팀 API 작업 검토 & PR 보내기 (0) | 2025.11.07 |
| [ TIL ] Day 30 - 팀 초급 프로젝트(실습) : 협업 추가 셋팅(Git rebase) & 팀 API 작업 (0) | 2025.11.06 |
| [ TIL ] Day 29 - 팀 초급 프로젝트(실습) : 협업 셋팅(Git clone, 코드 작성 규칙 숙지) & 개별 API 작업 (0) | 2025.11.06 |