유데미 웹개발 챌린지

50일차 - 연결된 웹사이트에 스타일 적용, form 데이터 저장 및 추출

창고관리장 2023. 4. 28. 22:49

 

익스프레스JS로 서버에 연결한 웹사이트에 스타일 입히기

 

오늘은 어제 서버에 연결한 웹사이트에 생략되었던 css 스타일을 적용해보았다.

정적파일 제공 코드

이를 위해 메인 자바스크립트 파일인 App.js 파일에 위 이미지와 같은 코드를 추가해주었다. use 메서드는 익스프레스JS 내의 미들웨어 함수를 사용하기 위해 사용하는 메서드이며, express.static은 사용자에게 정적 파일을 제공하는 역할을 하게 된다.

 

이 코드를 사용하면 public 폴더 내에 있는 파일들에 대한 정적 파일 서비스를 설정할 수 있는데, 만약 public 폴더 내에 css 파일이 있다면 이 파일들이 제공되는 것이다. 참고로 스타일 관련 파일과 자바스크립트 파일은 모두 public이라 이름지은 폴더에 보관하며 사용한다고 한다. public이라는 뜻이 '대중의'라는 뜻이므로, 코드의 역할과도 부합한다.

💡 정적 파일을 제공할 때, 파일 경로를 지정하는 방법에는 위 이미지와 같은 상대 경로를 이용하는 방법과 절대 경로를 이용하는 방법이 있다. 정적 파일을 서비스할 때는 보안상 이유로 경로 조작 공격을 방지하는 것이 중요한데, 경로 조작 공격은 사용자에서 서버로 전송되는 파일 경로에 대해 변조를 가해 의도하지 않은 파일에 접근하는 것이다. 익스프레스JS는 이를 방지하기 위해 파일 경로에 대한 검사를 수행하므로, 기본적으로 '../'과 같은 경로 조작 문자열이 포함된 경로는 서비스하지 않는다. 그래서 안전하게 정적 파일을 제공할 수 있게 된다.

정적 파일이 제공된 웹사이트

이렇게 해서 기본 HTML 내용만 보였던 웹사이트가 스타일이 씌워져서 사용자에게 다시 나타나게 되었다. 

 

form 데이터 저장 및 추출하기

웹사이트 내에 있는 양식

이 연습용 웹사이트에는 위 이미지와 같은 양식페이지가 따로 있다. 여기서 사용자가 마음에 들었던 레스토랑의 정보를 입력하여 제출하면 이 웹사이트에 자신이 적었던 레스토랑의 정보가 특정 구역에 계속 나타나 있게 된다. 

 

오늘은 그 기능을 구현해 보았는데, 해당 코드는 아래 이미지와 같다.

사용자로부터 양식의 데이터를 받을 코드

우선 사용자로부터 데이터를 받아야하므로 post 메서드를 사용했고, 매개변수에 양식이 위치하는 웹사이트 내 경로와 함수를 넣어주었다. 함수에서는 사용자로부터 받은 post 요청이 오면 req.body에 담겨진 json 데이터를 가져와야 하는데, 이를 restaurant 상수에 저장해주었다. 

 

그 다음으로 json 파일이 위치한 경로를 filePath 상수에 저장했고, 파일 시스템인 fs에서 readFileSync 메서드를 사용하여 해당 json 파일의 데이터를 가져오고 JSON.parse 메서드를 사용하여 그 데이터를 객체 형태로 파싱하여 결과를 storedRestaurants에 저장해주었다.

 

이후 사용자의 추가 데이터를 json 파일의 배열 내 맨 끝에 계속 업데이트하기 위해 결과에 push 메서드를 사용했고, writeFileSync 메서드를 사용하여 해당 파일에 storedRestaurants의 배열을 문자열로 변환한 값을 사용하도록 했다. 

 

마지막 코드로 사용자가 제출버튼을 누르면 데이터가 전송되면서 잘 전달되었다는 문구가 있는 confirm 페이지로 이동하도록 redirect 메서드를 사용했다. 아래 이미지가 해당 페이지이다.

양식 제출 후 이동하는 페이지의 내용

오늘은 여기서 끝나지 않고 EJS 엔진을 사용하여 사용자에게 맞춘 동적인 웹페이지를 구현해보았다. 우선 결과부터 보면 아래 이미지와 같다.

동적 웹페이지 구성

위 이미지가 뜨는 위치는 웹사이트 내 restaurants 페이지인데, 사용자가 제출한 레스토랑이 즐겨찾기처럼 저장되어 있으며, 상단의 'we found 3 restaurants' 단락의 숫자가 사용자가 저장한만큼 바뀌도록 구성했다.

EJS 엔진의 사용

이를 위해 우선 EJS 엔진을 npm을 통해 설치하여 사용할 준비를 끝내고 app.set 메서드를 사용하여 익스프레스JS가 적용된 프로젝트의 HTML파일들이 저장되어 있는 views 폴더를 명시하고 해당 폴더의 경로를 설정해주었다. 그리고 views 폴더 내의 파일들을 렌더링할 때 사용할 엔진을 ejs로 지정해주었다.

💡 EJS 엔진: EJS는 HTML과 유사한 구문을 사용하여 서버 측에서 동적 웹페이지를 생성하는 데 사용되는 자바스크립트 템플릿 엔진이다. 이 엔진은 크게 네 가지의 장점이 있다.
첫째, EJS는 HTML과 자바스크립트를 쉽게 혼합하여 사용할 수 있기 때문에 코드가 더욱 읽기 쉬워진다. HTML 코드와 자바스크립트 코드가 같은 파일 안에서 존재하기에 HTML 코드와 자바스크립트 코드 사이를 왔다갔다 할 필요가 없어진다.
둘째, EJS를 사용하면 템플릿을 만들어서 재사용할 수 있다. 따라서 반복되는 HTML 코드를 템플릿으로 만들어두면 코드 중복도 피하고 유지보수성을 높일 수 있다.
셋째, EJS는 서버 측에서 동적으로 HTML 코드를 생성할 수 있다. 서버에서 데이터를 가져와서 템플릿에 적용할 수 있기 때문에 사용자에게 맞는 동적 콘텐츠를 생성할 수 있다.
넷째, EJS는 노드JS와 함께 사용되어서 다양한 영역에서 사용할 수 있다. 브라우저에서 사용되는 자바스크립트와는 다르게, 노드JS와 함께 사용되면 서버 측에서 동적인 웹페이지를 생성할 수 있다. 또한, EJS는 다른 템플릿 엔진과도 호환성이 높아서 프로젝트의 요구사항에 따라 유연하게 사용할 수 있다.

HTML파일 내에서의 EJS 엔진 코드의 사용

위 이미지는 HTML 파일 내에 EJS 엔진의 코드를 사용한 모습이다. <%로 열고 %>로 닫는다. 또한, 해당 변수나 표현식의 값을 HTML에 출력할 때는 <%=를 사용하며, 출력이 아닌 코드 블록을 실행하려면 =을 뗀 <%을 사용한다.

 

사용자가 저장한 레스토랑을 보여주는 페이지에서는 if 조건문을 사용하였는데, 사용자가 입력한 데이터가 0일 때와 0이 아닐 때로 나누었으며, 특히 0이 아닐 때는 we found 다음의 숫자부분을 저장된 수에 맞추기 위해 numberOfRestaurants 변수를 만들었다.

또, 이 경우 저장된 레스토랑 정보가 담긴 박스를 페이지에 계속 나타내기 위해 for of 반복문을 사용하여 목록 부분을 반복문 안에 넣어주었다.

 

또한, article 태그 내의 h2 태그, 단락 태그들, 앵커 태그 부분은 form의 해당하는 각 부분의 name 속성명을 상수 restaurant과 연결시켜 놓았다. 이렇게 하면 name 속성에 저장된 값들이 해당하는 위치에 나타나게 된다. 여기서 EJS의 스크립트 코드가 사용되는 위치는 자유롭다는 것을 알 수 있다.

EJS 확장명으로 변경

그리고 익스프레스JS 파일에 적용하기 전에 EJS 코드의 적용을 위해 모든 HTML 파일의 확장명을 ejs로 변경해주었다. 

위 이미지는 해당 페이지에 사용자의 요청에 대해 응답을 하는 코드인데, 상수 filePath와 fileData, storedRestaurants는 사용자로부터의 요청을 받아 json 파일에 저장하는 다른 코드에서 그대로 따왔다. 경로 및 파싱할 데이터가 동일하기 때문이다. 

 

그 다음 동적 웹페이지를 생성하기 위해 res.render 메서드를 사용했다. 이 render 메서드는 익스프레스JS에서 제공하는 템플릿 엔진을 사용하여 템플릿 파일을 렌더링하는 메서드이다. 첫 번째 인수로 렌더링할 탬플릿 파일의 이름(Restaurants)를 받고, 두 번째 인수로 템플릿 엔진에 전달할 데이터를 객체 형태로 입력받는다.

 

위 코드에서는 ejs 파일에서 선언했던 변수 numberOfRestaurants에 storedRestaurants 배열의 길이가 나타나도록 했고, for of 반복문의 restaurants에는 storedRestaurants 배열 전체가 저장되도록 했다. 이렇게 전달된 데이터는 Restaurants 템플릿에서 사용할 수 있다.