서버pc에 있는 이미지에 접근해 해당 이미지를 추론하고 추론 이미지 생성 & 추론 data를 DB에 담아주면
나는 이미지랑 data를 가져다 쓰는 방식으로 진행했다.
난 파일에 접근 가능하니까 업로드도 가능한줄 알았다 (웨 그렇게 생각하셨죠?? -> 나도 모름, 진짜 모름)
기존에 사용하는 이미지가 많아 서버 PC에 이미지를 저장하고 외부에서 접근 가능하게 해놓은 상태여서
(port & 포트포워딩)
외부 인력와서 추론 알고리즘 pc에 설치해줄때도 파일 시스템에 접근이 되는 거니까 업로드도 가능한건가 보다~ 하고 할일 하고 있었다
아래는 예시 백엔드 코드
const express = require('express');
const path = require('path');
const cors = require('cors');
const app = express();
const PORT = 3000;
// CORS 설정: 모든 도메인 허용, GET과 POST 메서드만 허용
app.use(cors({
methods: ['GET', 'POST']
}));
app.use(express.json());
// 'public/image' 폴더 경로 설정
const folderPath = path.join(__dirname, 'public', 'image');
// 정적 파일 제공
app.use('/images', express.static(folderPath));
// 서버 시작
app.listen(PORT, () => {
console.log(`이미지 server 실행`);
});
근데 작업하시다가 음 405 에러 나는데 왜그러징.. 하는걸 한참 뒤에 들었다 서로 다른 공간에서 작업하니까 작업하는 분은 본인이 잘못해서 그런갑다 하고 이것저것 해보고있었는데 공유한 url로 파일 시스템에 접근해서 이미지 다운로드는 되는데 업로드가 안되니까 본인이 잘못 한건줄 알고 계속 시도해보고 있었던것.. (안타깝게도 외부 인력도 나도 주니어여서 귀책사유를 명확히 알지 못했음)
결론부터 말하면 왜 안됐냐면...
그야.....
업로드 api가 없으니 업로드가 안되지!!
정말 부끄러운 이유로 에러가 나고있었고 "405 에러 나는데용?" 라는 말을 듣고 GPT 답변을 이것저것 읽어보고 생각했다.
(와 나 뭐함..?)
호다닥 GPT 도움을 받아 코드를 수정했고 다행히 바로 업로드가 됐다
예시 코드
const multer = require('multer');
// multer 설정: 파일 저장 경로 및 파일 이름 설정
const storage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, YOUR/PATH); // YOUR/PATH 에 업로드 할 경로 입력
},
filename: (req, file, cb) => {
cb(null, file.originalname); // 원래 파일 이름으로 저장
}
});
const upload = multer({ storage: storage });
// 파일 업로드 api를 만들어줘야 업로드가 되는 지극히 당연한 사실!!
app.post('/api/upload', upload.single('file'), (req, res) => {
if (!req.file) {
return res.status(400).json({ message: '파일이 업로드되지 않았습니다.' });
}
res.json({
message: '파일이 성공적으로 업로드되었습니다.',
file: req.file
});
});
multer 분명 공부할때 썼었는데..
경험해보지 않으면 실전에선 절대 생각이 안나는듯..?
*multer는 주로 파일 업로드에 사용하고 미들웨어로 에러 같은거 나면 next에 처리를 위임해줘서 사용하기 좋다
회사에서 진행하는 프로젝트가 1인 프로젝트 치고 규모도 좀 있고 경력도 거의 프론트만 1년 정도 한게 다여서 나름 부담감에 MongoDB 강의도 듣고 React deep dive 도 하고 코테도 깔짝깔짝 풀고 있었는데 이번 일 겪은 후로 다 치우고 백엔드 위주로 사이드 프로젝트 하면서 공부 중이다..
이것저것 하고있긴한데 교류하고있는 개발자 커뮤니티가 없으니 가끔 헤매고 있는거 같아 좀 불안허네
첫 회사에선 일렉트론으로 데스크탑 애플리케이션 만들다보니 node.js도 어찌어찌 작성했었는데
db 안쓰는 프로젝트고 api 통신도 아닌것이 뭔가 애매해서 백엔드 코드는 대충대충 했던 기억이 난다.
근데 지금회사에선 좀 본격적으로 백엔드 개발도 해야돼서 복습겸 회고하려고 한다.
프론트엔드 역량에 더 집중하고 싶기도한데 지금 회사에 필요한 건 이것저것 할 줄 아는 개발자인듯 하고 이렇게 역량 늘리는 것도 나쁘지 않긴하다.
기왕하는거 즐깁시다.
내가 생각하는 백엔드
프론트에서 필요한게 있으면 서버로 요청하고 서버는 응답한다.
백엔드는 응답하는 로직을 담당하는 부분이라고 생각한다
간단한 비즈니스 로직부터 db 조작까지해주는 정도?
근데 비즈니스 로직도 프론트엔드에서 private 하게 다룰수 있고 (feat. class 문법)
Next.js 13부터 서버 컴포넌트에서 바로 db CRUD가 가능해져서 프론트와 백엔드 경계가 모호하다고 느끼고있긴하다.
그래도 기본은 중요한거니까 기초를 다져봅시다.
어떻게 공부할까 하다가 전에 사둔 [리액트를 다루는 기술] 책에 백엔드 프로그래밍 부분이 있어서 진도를 따라가고 있다.
책에 수록된 스택은 Koa(기존 Express 팀이 개발한 더욱 가벼운 프레임워크) + Javascript + mongoose 인데,
Express + Typescript + mongoose 로 공부하고 싶어서 해당 스택으로 진행했다.
환경설정
1) express 설치
$ npm init
$ npm install express --save
2) Typescript 관련 설치
npm i -D typescript // typescript 설치 (-D 는 개발모드로)
npm i ts-node // 아래 후술
npm i @types/node
npm i @types/express
<ts-node> - TypeScript를 JavaScript로 변환하여 사전 컴파일 없이 Node.js에서 TypeScript를 직접 실행할 수 있도록 합니다(문서 발췌) 이거 없으면 ts 파일 하나당 컴파일 된js 파일 하나 만들어지고 디버깅도 컴파일된 js 파일에서 해야돼서 매우 피곤함
<types/node>
- 이 패키지에는 노드에 대한 유형 정의가 포함되어 있습니다. (문서 발췌)
없으면 ts 파일에서 Node.js의 내장 모듈(예: fs, http, path 등)을 사용할 때 Type 에러남.
// 코드 몇줄 딸깍으로 서버를 시작할 수 있다
const express = require('express')
const app = express()
const port = 3000
app.get('/', (req, res) => {
res.send('Hello World!')
})
app.listen(port, () => {
console.log(`Example app listening on port ${port}`)
})
2) 기본 라우팅
// metods를 구분해 하나의 route에 4개의 요청과 응답이 가능하다
// postman을 사용해 작성한 api를 test 해보자
app.get('/', function (req, res) {
res.send('Hello World!');
});
app.post('/', function (req, res) {
res.send('Got a POST request');
});
app.put('/', function (req, res) {
res.send('Got a PUT request');
});
app.delete('/', function (req, res) {
res.send('Got a DELETE request');
});
mongoDB
몽고DB는 크로스 플랫폼 도큐먼트 지향 데이터베이스 시스템이다. NoSQL 데이터베이스로 분류되는 몽고DB는 JSON과 같은 동적 스키마형 도큐먼트들을 선호함에 따라 전통적인 테이블 기반 관계형 데이터베이스 구조의 사용을 삼간다
(나무 위키 발췌)
음.. 그냥 처음 db 써보기 좋은 친구.
처음 용어도 좀 헷갈렸는데 몽고DB에서 Document는 JSON 객체라고 보면 될듯하다
const dummy = [
{name: "철수"},
{name: "영희"},
];
위 dummy 배열을 몽고DB에 넣는다고 하면
1번 Document에는 {name: "철수"} 가 2번Document에는 {name: "영희"} 가 들어가는 느낌?
모델은 스키마를 사용해 만드는 인스턴스로, 데이터베이스에서 실제 작업을 처리할 수 있는 함수들을 가진 객체.
모델을 사용하려면 아래와 같이 사전에 스키마를 만들어주어야됨.
import mongoose from "mongoose";
const { Schema } = mongoose;
// post
const PostSchema = new Schema({
title: String,
body: String,
});
const Post = mongoose.model("Post", PostSchema);
export default Post; // 이 Post 모델 객체를 사용해 db 조작이 이루어진다
3) 모델(model) 사용
import { Post } from "./models/post"; // 만들어준 Post 사용
app.post("/post", async (req, res) => {
const { title, body } = req.body;
const post = new Post({ // 인스턴스를 만들어 사용
title: title,
body: body,
});
try {
await post.save();
res.send("db 저장 성공!", JSON.stringify(post));
} catch (err) {
console.error(err);
res.status(500).send("db 저장 실패!");
}
});
Typescript
express도 mongoose 도 공식문서가 친절해서 참 좋다.
그중 어려웠던 mongoose 의 인스턴스 메서드와 스태틱 메서드에 대해서 작성하겠다
1) 스키마 생성
const userSchema = new Schema({
userName: String,
hashedPassword: String,
});
const User = mongoose.model("User", userSchema);
export default User;
2) 인스턴스 메서드
// 인스턴스 메서드 정의
userSchema.methods.hello = function () {
return'hello!!';
};
// 인스턴스를 만들어 사용
const user = new User({ userName: 'jack' });
console.log(user.hello()); // "hello!!"
3) 스태틱 메서드
// 스태틱 메서드 정의
userSchema.statics.findByUserName = function (userName: string) {
return this.findOne({ userName });
};
// User 모델에 바로 접근해서 사용
User.findByUserName("jack").then(name => {
console.log(name); // "jack", "jack" 이름을 가진 user 출력
});