(김유선) 개인프로젝트 SSR로 처음부터 끝까지 진행하기 - 페이지 제작(3)

2024. 5. 13. 17:52프로젝트 일지

어제 확인해보니까 카테고리 창은 다른 ejs 파일에 렌더링해야 했다.

그래서 어제의 문제는 사실 해결하지 않고 넘겨도 되지만

문제가 발생한 이상 원인은 알아야겠다.

 

<카테고리 창>

오류 코드를 보니

 

length의 타입에러인 것 같았다.

그래서 구글링해보다

 

[Javascript] 빈배열인지 확인하는법 && TypeError: Cannot read property 'length' of undefined 에러 해결방법

React로 작업도중 TypeError: Cannot read property 'length' of undefined 에러가 발생했다!데이터 송신되기전에 빈배열이 랜더링이 발생해버리는 문제였다!방식으로 문제를 해결했다먼저 배열이 맞는가 아닌

velog.io

이걸 확인했는데, 나랑 같은 케이스인 것 같았다.

 

app.get('/category/:where', async(요청,응답)=>{
  let text = 요청.params.where
  let data = {}
  data.name = '<'+text+"> 카테고리"
  data.user = 요청.user
  if(text=='식당'){
    data.market = await db.collection('market').find({$or : [{업종 : '한식_일반' },
      {업종 : '한식_한정식' }, {업종 : '한식_면류' }, {업종 : '한식_육류' }, {업종 : '한식_찌개류' },
      {업종 : '한식_해산물' }, {업종 : '한식_분식' }, {업종 : '한식_기타' }, {업종 : '일식' },
      {업종 : '양식' }, {업종 : '중식' }]}).toArray()
    응답.render('search.ejs', { data : data })
  }
  else if(text=='카페'){
    data.market = await db.collection('market').find({$or : [{업종 : '기타서비스업' }, {업종 : '기타양식'}]}).toArray()
    응답.render('search.ejs', { data : data })
  }
  else if(text=='미용실'){
    data.market = await db.collection('market').find({업종 : '이미용업' }).toArray()
    응답.render('search.ejs', { data : data })
  }
  else if(text=='기타서비스'){
    data.market = await db.collection('market').find({$or : [{업종 : '세탁업' }, {업종 : '목욕업'}, {업종 : '숙박업'}]}).toArray()
    응답.render('search.ejs', { data : data })
    }
  else{
    응답.send('올바른 경로로 접속하지 않았습니다.')
  }
})

원래는 응답을 전체의 아래에 해줬는데 경우마다 따로 응답을 하는 걸로 수정했다.

그랬더니 오류 코드는 사라졌는데

글씨체랑 이미지 문제는 그대로였다.

 

내 생각엔 params나 get 요청에서 문제가 발생한 것 같다.

그래서 get 요청을 post 요청으로 바꿔봤다.

app.post('/category/:where', async(요청,응답)=>{
  let text = 요청.params.where
  console.log(text)
  let data = {}
  data.name = '<'+text+"> 카테고리"
  data.user = 요청.user
  if(text=='식당'){
    data.market = await db.collection('market').find({$or : [{업종 : '한식_일반' },
      {업종 : '한식_한정식' }, {업종 : '한식_면류' }, {업종 : '한식_육류' }, {업종 : '한식_찌개류' },
      {업종 : '한식_해산물' }, {업종 : '한식_분식' }, {업종 : '한식_기타' }, {업종 : '일식' },
      {업종 : '양식' }, {업종 : '중식' }]}).toArray()
    응답.render('search.ejs', { data : data })
  }
<form action="/category/식당" method="post">
                        <input type="submit">
                            <p class="hover">식당</p>
                    </form>

이렇게

그런데도 같은 문제가 발생한다. get 요청인 게 문제가 아닌가보다.

그럼 어제 업소 상세페이지랑 겹치는 params가 문제인 것 같다.

(어제 요청.params.num을 인식하지 못했으니)

 

그래서 뤼튼에게 물어봤다.

나 : "서버에서 요청.params 값을 사용하는데 문제가 생기는 건 어떤 경우야?"

뤼튼 : "

네, 서버에서 요청.params 값을 사용할 때 문제가 생길 수 있는 경우에 대해 자세히 살펴보겠습니다.

1. HTTP 메서드 사용 문제

  • GET 요청에서는 요청.params 값을 사용하는 것이 적절합니다.
  • POST, PUT, PATCH 등의 요청에서는 요청.body 값을 사용하는 것이 더 적절합니다.
  • 요청.params는 URL 경로에 포함된 값이므로, 데이터 변경이나 생성 시에는 요청.body를 사용하는 것이 더 안전합니다. [res_idx]

2. 파라미터 유효성 검사 문제

  • 요청.params 값은 URL 경로에 포함되므로, 클라이언트가 임의로 변경할 수 있습니다.
  • 따라서 서버에서 요청.params 값에 대한 유효성 검사를 철저히 해야 합니다.
  • 유효성 검사를 하지 않으면 보안 문제가 발생할 수 있습니다.

3. 프레임워크/미들웨어 호환성 문제

  • 일부 프레임워크나 미들웨어에서는 요청.params 값을 지원하지 않을 수 있습니다.
  • 예를 들어 Parse Server와 같은 Express.js 기반 미들웨어에서는 요청.params 값이 제대로 동작하지 않을 수 있습니다. [res_idx]

4. 캐싱 및 로깅 문제

  • 요청.params 값은 URL 경로에 포함되므로, 캐싱이나 로깅 등의 처리 시 문제가 발생할 수 있습니다.
  • 예를 들어 요청.params 값이 변경되면 캐싱된 데이터가 유효하지 않게 될 수 있습니다.

따라서 서버에서 요청.params 값을 사용할 때는 이러한 문제점들을 고려해야 합니다. 가능하다면 요청.body나 요청.query 등을 사용하는 것이 더 안전할 수 있습니다. 궁금한 점이 더 있다면 언제든 말씀해 주세요.

"

 

여기서 3번이 내가 처한 문제인 것 같다.

" 예를 들어 Parse Server와 같은 Express.js 기반 미들웨어에서는 요청.params 값이 제대로 동작하지 않을 수 있습니다." <- 내가 지금 사용중인 것은 express.js다.

이걸 어떻게 해결해야 할까...

 

<상세페이지 창>

ㅋㅋㅋㅋㅋㅋㅋㅋ 이거 해결됐음

// 업소 상세페이지 보기
app.get('/detail/:num', async(요청,응답)=>{
  let data = {}
  let num = parseInt(요청.params.num)
  console.log(typeof 요청.params.num)
  data.user = 요청.user
  data.market = await db.collection('market').findOne({번호 : num})
  응답.render('detail.ejs',{data : data})
})

어제 데이터 타입이 달라서 그런가 해서 typeof로 봤었는데  요청.params.num 이 string이라 될 줄 알았다. 

근데 오늘 뤼튼한테 물어보니까

이렇게 떠서 다시 한번 시도했다.

console.log(typeof 요청.params.num)
  console.log(typeof 59)

이렇게 하니까

string, number이 나왔다.

아니 어젠 왜 같은 걸로 알고 있었지ㅠㅠㅠ

그냥 내가 데이터 타입들을 잘 모르나보다

어 그럼 카테고리 창에서도 파라미터가 문제가 아니라 타입이 문제인 걸까...

그건 아닌 것 같다.

얘도 잘 뜨긴 뜨는데 이미지가 안 보인다ㅠㅠㅠㅠㅠㅠ

암만 봐도 css는 잘 적용되어있고 경로 문제인 것 같은데...

경로도 잘 입력한 것 같음...

심지어 search에서 post 요청할 때는 잘 작동하던 페이지가 이러는 거라

경로가 다르지가 않을텐데,,,

암만 봐도 경로 문제인가보다ㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠ

근데 서버에는 이런 에러가 뜬다.

서버에러의 원인은 알겠다.

data.market =await db.collection('market').findOne({번호 : num})

이렇게 코드를 작성하고 여기서 data.market를 콘솔했는데

왜인지 모르게 null이 같이 나온다. 그래서 서버에서 저런 에러가 떴나보다.

뭔가 이상해서

data.market =await db.collection('market').findOne({번호 : 4})

이렇게 해봤는데

?????? 왜 두 개 나옴

 

console.log(typeof num)

얘도 두 개 나온다

요청.params.num

얘 자체가 문제인 듯

그래서 콘솔해보니까

 

4
UhBeeHanByeol.woff

 

이렇게 출력됨

이게 글씨체랑도 연관이 있는 것 같다.

저길 어떻게 이동했나 찾아봤더니

$('.detailbtn').click(function(){
        location.href='/detail/'+$(this).parent().data('num')
    })

이렇게 되어있었다.

어미 요소에

data-num=<%=data.market[i].번호%>

이렇게 번호를 숨겨뒀었는데 이 글씨체가 같이 데이터로 전송이 된 것 같다.

(본 김에 어미 말고 본인에게 데이터 숨겨둠)

console.log($(this).data('num'))

클라이언트에서 이렇게 출력하면 숫자만 잘 출력되는데

console.log(요청.params)

서버에서 이렇게 출력해보니까

{ num: '59' }
{ num: 'UhBeeHanByeol.woff' }

이렇게 출력된다.

서버로 보내는 순간 데이터에 폰트도 따로 보내주나보다.

이해는 안되지만 이해하려고 하니까 너무 어려워져서 나중에 다시 알아보기로 하고

데이터셋 말고 다른 방식으로 해결해봐야겠다.

 

헐 보니까 얘도 똑같음

<button class="btn" onclick="location.href='/category/기타서비스'">
                        <img src="./img/icon-service.png" alt="">
                        <p class="hover">기타 서비스</p>
                    </button>
app.get('/category/:where', async(요청,응답)=>{
  let text = 요청.params.where
  let data = {}
  data.name = '<'+text+"> 카테고리"
  data.user = 요청.user
  console.log(text)

요청.params.where를 출력하니까

기타서비스
UhBeeHanByeol.woff

이렇게 출력됐다.

데이터셋 문제가 아닌 듯

파라미터 자체가 문제인 것 같은데

대체 왜....이지