[NodeJs] url 경로 조립시 주의할 것

Ywoosang·2024년 2월 3일
0

Node.js

목록 보기
1/1

NestJS 로 블로그를 만들던 도중 백엔드에서 사용자 엔티티를 업데이트하기 위해 이미지파일 경로를 조립후 클라이언트에 전송해야 할 일이 생겼다.

파일 서비스에서 이를 처리하도록 구현했고 configService 에서 가져온 백엔드 도메인과 /static/images 를 조립해 정상적인 경로를 반환할것이라 생각했다.

@Injectable()
export class FilesService {
    private readonly baseDir: string;
    private readonly tempPath: string;
    private readonly staticPath: string;

    constructor(private readonly configService: ConfigService<AllConfigType>) {
        this.baseDir = this.configService.get('app.workingDirectory', { infer: true });
        this.tempPath = path.join(this.baseDir, 'public', 'temp');
        this.staticPath = path.join(
            this.configService.get('app.backendDomain', { infer: true }),
            'static',
            'images',
        );
    }
	...

임시 경로에서 파일을 옮긴 후 생성된 staticPath 를 이용해 UsersService 에서 사용자 엔티티를 save 할 수 있을 것이다.

// files.service.ts
async uploadUserProfileImage(filename: string) {
  const destination = path.join(this.baseDir, 'public', 'images', 'users');
  
  if (!fs.existsSync(destination)) {
    fs.mkdirSync(destination, { recursive: true });
  }
  
  const tempFilePath = path.join(this.tempPath, filename);
  const filePath = path.join(destination, filename);
  await fs.promises.rename(tempFilePath, filePath);
  
  return path.join(
    this.staticPath,
    'users',
    filename
  );
}

서버를 키고 이미지가 적용되었는지 확인해보니 404 에러가 떴다. 500이 아닌 404 라면

  1. 파일업로드할때 image 를 첨부하지 않은 경우 (서버단에서 설정해놓음)
  2. static file serve 가 되지 않은 경우

둘중 하나일텐데

Failed to load resource: the server responded with a status of 404 (Not Found)

프론트단 axios 에서 formData 에 파일을 제대로 넣었기 때문에 아무리 봐도 후자인 듯 싶어서 url 을 확인해봤다.

실패한 요청을 보니 프론트 url 과 백엔드 url 이 같이 붙어있다.

https://ywoosang-blog-front.run.goorm.io/ywoosang-blog.run.goorm.io/static/images/users/6ef8af70-b1f6-42f4-8c08-69dbb4878f46.jpeg 

분명히 백엔드도메인으로 조립해 보냈는데 요청이 저렇게 들어간게 좀 이상했다. 바로 이미지 태그를 확인했다.

<img data-v-54003fcc="" src="https:/ywoosang-blog.run.goorm.io/static/images/users/6ef8af70-b1f6-42f4-8c08-69dbb4878f46.jpeg" alt="User Avatar">

자세히 보다보니 https:// 가 한 개 있는걸 찾았다. 찾는데 좀 오래걸렸다.
백엔드 .env.dev 에서 백엔드도메인을 잘못 붙인줄 알고 확인해봤는데 이것도 제대로 들어가 있었다.

마지막으로 path.join 을 의심해봤는데, 문제는 이거였다.

stackoverflow 를 찾아봤고 결론은 'path.join 을 url 조립에 사용하지 않아야한다' 였다.

https://stackoverflow.com/questions/16301503/can-i-use-requirepath-join-to-safely-concatenate-urls

단순히 이미지 경로만 필요하므로, 아래처럼 protocol&domain name + extension 으로 나눠서 해결했다.

const extention = path.join(
  this.staticPath,
  'users',
  filename
);
return `${this.backendDomain}/${extention}`;
profile
백엔드와 인프라에 관심이 많은 개발자 입니다

0개의 댓글