이 포스팅은 자바스크립트 문법을 어느정도 알고 있다는 가정하에 쓰여진 포스팅입니다
만일 자바스크립트 문법을 모르시면 자바스크립트에 대한 공부를 한 후 오시는 것을 추천드립니다
추천) 생활코딩 - Javascript : https://www.opentutorials.org/course/3085
누가 가져갔는지는 모르겠는데 아무튼 누가 액자를 가져가서 댕댕이들에게 액자가 없다
그럼 원인이 뭘까? 우선 F12를 눌러 개발자 도구를 열어보자. 그리고 네트워크 탭을 선택해보자
개발자 도구의 네트워크를 통해 보니 일단 CSS 파일은 제대로 날아왔다. 근데 왜 적용이 안됐을까?
소스 탭을 열어보자
여기서도 일단 서버로부터 CSS 파일을 받았다고는 나와있다
그럼 대충 추측하자면 서버로부터 CSS 파일을 받아오긴 했지만 서버에서 받아와서 로컬에 저장한 파일이 아닌 계속해서 서버를 계속 참조하려 해서 일어나는 일이라고 추측해볼 수 있다
그럼 어떻게 하면 좋을까?
바로 우리 댕댕이들 사진에 관한 문제이다. 멀쩡하게 출력되는데 무슨 개소리냐고?
예를 들어서 생각해보자. 지금이야 우리 댕댕이들 사진이 한장 뿐이라 그냥 서버에서 /Dog 주소로 요청을 받는 함수를 하나 더 붙여서 해결을 했다. 근데 이 사진들이 한 100장쯤 된다고 가정해보자
그럼 사진 요청을 받는 함수를 무려 100개를 만들어야 하는 미친 상황이 벌어지게 된다!!
상상만해도 머리가 아프고 비효율적일 것이라는 감이 온다
그냥 파일을 보내주는 함수를 만들지 말고 실제 이미지나 파일은 서버에 있더라도 html에는 마치 로컬에 있는 것 처럼 작성해도 이미지가 출력되게 하는 방식으로 작성하면 안될까?
서버에 존재하는 정적인 파일(static file)을 한 번 서빙해보자
우리가 식당가서 생각하는 그 서빙과 비슷하니 개념 자체는 어렵지 않을 것이라 본다
우리가 쓰는 익스프레스에는 이미 훌륭한 파일 서빙 시스템이 포함되어 있다. 별다른 라이브러리 설치 없이 아래와 같이 해주면 파일을 서빙해줄 수 있다
app.use(express.static('서빙할 폴더 이름'))
이렇게 서버 프로그램이 파일을 클라이언트에게 서빙하도록 해줄 수 있다
express.static 함수의 인자로는 서빙할 파일들이 있는 위치를 문자열로 주면 된다
예를 들어서 express.static('image')
라고 해주면 image 폴더에 있는 파일들을 클라이언트가 요청하면 서빙을 해주게 되는 것이다
우선 코드를 바꾸기 전에 우리가 만드는 프로젝트의 구조를 살펴보자
NodeTutorial
┣ Dog.jpg
┣ a.html
┣ app.js
┣ package-lock.json
┣ package.json
┗ style.css
별 다른 폴더를 만들거나 하지 않았기 때문에 아마 대부분이 위와 같이 되어있을 것이다. 다른 점이라면 파일 이름이 다를 수도 있다는 점과 프로젝트 폴더의 이름이 NodeTutorial이 아닐 수도 있다는 점 정도밖에 없을 것이다
이제 해당 프로젝트 폴더에 public이란 이름의 폴더를 만들어 주고 Dog.jpg를 public 폴더 내부로 옮겨주자 그럼 이런 구조가 만들어질 것이다. (보통 이런식으로 클라이언트에게 제공할 정적 파일들은 public 폴더 내부에 모아둔다)
NodeTutorial
┣ public
┃ ┣ Dog.jpg
┃ ┗ style.css
┣ a.html
┣ app.js
┣ package-lock.json
┗ package.json
위와 같은 구조를 띠면 된다.
코드를 아래와 같이 바꾸고 Dog 연결을 담당하는 함수를 지워주자
import express from 'express'
import { readFile } from 'fs'
const app = express()
app.use(express.static('public'))
app.get('/', (request, response) => {
readFile('a.html', (err, data) => {
if(err) { response.send('No Such File of Directory') }
res.send(data)
}
})
html 파일도 아래와 같이 바꿔주자
<!DOCTYPE html>
<html>
<head>
<title>:D</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<h1>Dog</h1>
<img id="DogFrame" src="Dog.jpg" style="width: 720px;">
</body>
</html>
위와 같이 js 파일과 html 파일을 수정한 뒤 저장을 하고 서버를 다시 가동시킨 후 다시 로컬호스트 서버로 접속하자
이제 액자도 정상적으로 출력된다
그렇다 깔끔하게 정리를 하고 싶어서 이미지는 이미지대로, CSS 파일은 CSS 파일대로 모아놓고 정리를 해서 아래와 같이 프로젝트 폴더를 구성해서 쓸 수도 있을 것이다
┣ public
┃ ┣ css
┃ ┃ ┗ style.css
┃ ┗ images
┃ ┃ ┗ Dog.jpg
┣ a.html
┣ app.js
┣ package-lock.json
┗ package.json
폴더구조를 이렇게 바꿔놓고 그대로 다시 새로고침을 하면 아래와 같이 화면이 뜬다
잘 나오던 댕댕이들 사진과 액자가 안나온다. 그도 그럴 것이 폴더를 위와 같이 정리하면 사진과 css 파일은 public 폴더에 있는게 아니라 그 아래에 있는 서브 폴더에 존재하기 때문에 서버가 파일을 찾을 수 없어서 파일을 서빙하지 않는 것이다
이 문제를 해결하기 위해서는 어떻게 할 수 있을까?
사실 답은 간단한데 html 파일을 아래와 같이 바꿔주면 된다
<!DOCTYPE html>
<html>
<head>
<title>:D</title>
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<h1>Dog</h1>
<img id="DogFrame" src="images/Dog.jpg" style="width: 720px;">
</body>
</html>
그럼 서버가 public 폴더 내부에 위치한 서브 폴더인 css 폴더 안까지 가서 css 파일을 찾아서 서빙해준다. 이미지도 마찬가지다
html 파일을 바꿔주니 다시 정상적으로 출력이 된다
아니면 html 파일이 아니라 js 파일을 수정하는 방법도 있다. js 파일을 수정하겠다면 코드를 아래와 같이 바꿔주면 된다
import express from 'express'
import { readFile } from 'fs'
const app = express()
app.use(express.static('public/css'))
app.use(express.static('public/images'))
app.get('/', (request, response) => {
readFile('a.html', (err, data) => {
if(err) { response.send('No Such File of Directory') }
res.send(data)
}
})
이렇게 해도 파일이 정상적으로 출력될 것이다
일장일단이 있는데, html 파일에 어느정도 파일이 위치한 경로를 명시해두면 이름 중복 때문에 서버가 어떤 파일을 보내야 될 지 혼란해하는 일이 일어나지 않고, 코드가 간결해진다는 장점이 있다
그러나 html 파일에 저렇게 자세한 경로를 적어두게 되면 서버의 구조를 간접적으로나마 알려주는 것이 된다. 그럴 일이 잘 없더라도 서버의 구조를 알려주는게 딱히 좋은 일도 아니고...
여러개의 static 함수를 쓰면 서버의 구조를 자세하게 알려주지 않아도 되니 보안성이 좋다는 장점이 있지만, 만일 우연히 동일한 이름의 파일이 존재하게 되면 서버가 어떤 파일을 보내줘야될 지 몰라서 혼란에 빠질 것이다
그러니까 뭐가 더 좋다 나쁘다는 없고 상황에 맞게 적당히 골라서 쓰면 되는 것이다
진짜 다른 사이트에서 글 뒤져봐도 이해 하나도 안 갔는데 덕분에 업무가 돌아갔어요 ㅜㅜ 감사합니다