TIL

250101

GoJay 2025. 1. 1. 18:00
  • Udemy <The Web Developer 부트캠프 2024>
    • 하나의 파일에서 Express의 모든 라우트 경로에 대한 미들웨어를 처리할 수 있지만, 서비스가 커질수록 하나의 파일에서 모든 라우팅 로직을 처리하는 건 유지보수를 더 어렵게 만드는 원인이 된다.
    • 이런 문제 때문에, 어느 정도 규모 있는 서비스를 만들 땐 보통 라우팅 경로에 따라 모듈을 쪼개서 관리하는 것이 일반적이다.
    • 이때 express.Router 메서드가 사용된다. express.Ruouterrouter 객체를 반환하며, router 객체가 제공하는 get post put patch delete 등 메서드를 통해 라우팅 로직을 처리할 수 있다.
    • 보통은 routes와 같은 이름으로 디렉토리를 만든 후 라우터들을 목적에 따라 구분하고, 각 모듈에서 정의한 라우팅 로직을 module.exports = router 방식으로 정의해둔 라우터 객체를 외부에 노출한다. 그리고, 실제 앱 부분에서 노출된 라우터를 require로 불러와 해당 라우터를 app.use로 연결해준다.
    • app.use('/shelters', shelterRouter) 방식으로 사용하면 shelterRouter로 정의한 모든 라우팅 경로 앞에 prefix로 /shelter가 붙는다. shelterRouterrouter.get('/:id', (req, res) => {})로 정의한 라우터가 있다면 실제로는 /shelter/:id 경로일 때 라우팅 로직이 실행되는 것이다.
    • 라우터를 모듈로 쪼개둔다면, 특정 진입점이 있는 라우터에서만 적용하고 싶은 미들웨어도 쉽게 쪼개서 관리할 수 있다. 예를 들어 /admin 경로 뒤에 오는 모든 라우터들에서 권한이 인증된 유저인지 확인하는 미들웨어를 먼저 실행하고 처리하고 싶다면 routes/admin.js 모듈에서 정의한 router 객체에 router.use(isAdmin)처럼 미리 정의한 로직을 미들웨어로 전달해 주고, 미들웨어에서 조건에 맞는 경우만 next()를 호출해 주고, 그렇지 않을 경우 next(err)로 바로 에러 핸들링을 처리해 줄 수 있다.
    • 라우터를 모듈로 잘 쪼개면 유지보수가 수월해주고, 프로젝트의 비즈니스 로직을 한눈에 파악하기 쉽도록 관리할 수 있다. 결국, 어디에서 어떤 라우터 모듈로 쪼개서 어떻게 관리할지는 개발자의 판단의 영역이다. 해당 부분에서 좋은 판단을 하기 위해선 역시 다양한 경험이 중요하겠다.
    • 쿠키에 대해서도 공부했다. http 통신은 무상태성(Stateless)이라는 특징을 갖는다. 풀어보면, 기본적으로 http 통신에선 어떠한 데이터가 저장되지 않는다는 뜻이다. 각 요청과 응답은 독립적이며, 이전 요청과 다음 요청 사이엔 어떠한 상태가 공유되지 않는다.
    • 하지만, 경우에 따라선 http 통신을 위한 '기억된 상태'가 필요한 경우가 있다. 이런 경우에 사용되는 게 '쿠키'다.
    • 쿠키는 http request에 사용할 어떠한 상태(데이터, 정보)를 저장해 두는 저장소이다. 주로 브라우저에 저장되어 있다가, 클라이언트에서 서버로 요청이 갈 때 브라우저에 저장된 쿠키가 같이 서버로 전달된다.
    • Express는 미들웨어의 res 객체에 res.cookie라는 메서드가 있다. 해당 메서드는 두 개의 매개변수를 받으며, 첫 번째 매개 변수는 쿠키에 저장될 값의 키, 두 번째 매개 변수는 저장 될 값을 나타낸다(쿠키는 객체 형태로 데이터를 관리해 준다).
    • 서버에서 정의해 준 쿠키는 해당 라우팅 경로로 접속 시 브라우저에 저장된다. 그 상태에서 브라우저에서 서버로 요청이 전달되면 req.cookies에 브라우저에서 관리되던 쿠키가 전달된다.
    • 쿠키를 사용하면 다양한 처리를 해줄 수 있다. 예를 들어서, 어떤 사람이 서비스를 이용할 때 다크 모드를 선호하는지 라이트 모드를 선호하는지에 대한 정보를 쿠키로 관리한 후, 서버에서 쿠키의 mode 정보를 활용해 필요한 값들을 내려주도록 할 수 있다. 흔히 사용되는 로그인 인증-인가 시 '이 요청이 인증된 사람으로부터 온 요청이다'라는 걸 식별하는 과정에서도 쿠기를 활용할 수 있다.
    • 서버에서 쿠키에 서명 처리를 할 수 있다. app.use(cookieParser('secret'))와 같이, cookieParser를 설정할 때 특정 값을 전달해 주면 해당 값으로 쿠키의 값이 서명 처리된다(서명을 위한 키도 보안이 필요하기 때문에, 실제 코드에 하드 코딩해서 넣진 않는다. 주로 .env에 값을 저장해 둔 다음 불러와서 넣어준다).
    • '서명'은 '보안'의 개념은 아니다. 서명을 하더라도 클라이언트에 쿠키의 값이 내려갔을 때 원본 값을 확인할 수는 있다.
    • 대신, 서명을 하면 서버에서 내려준 쿠키가 임의로 변경됐는지, 다른 값으로 들어오진 않았는지를 파악할 수 있다. 만약에 클라이언트에서 별도로 쿠키의 값을 조정해서 서버로 보냈으면 이는 의도하지 않은 동작일 수 있다. 이런 경우에 서명을 통해 쿠키의 값 변경 여부를 파악한 다음 서버에서 내려준 쿠키와 일치할 때에만 필요한 로직을 처리하도록 해줄 수 있다.
    • 쿠키는 클라이언트에서 저장되고 관리되기 때문에, 서버에서 특정 브라우저의 접근에 대한 데이터를 누적해서 관리하기 어렵다. 이러한 니즈가 있을 경우 세션을 사용할 수 있다.
    • 세션은 서버에서 관리된다. 보통은 세션을 위한 별도의 데이터베이스를 두고, 해당 DB에 무상태성인 http 통신 과정에서 저장하고 관리해야 하는 정보를 추출해 저장해 두는 식으로 관리한다.
    • 데브 환경에서는 별도의 DB를 두지 않고, PC의 메모리에 세션 데이터를 저장하고 관리할 수 있다. 단, 해당 경우엔 브라우저를 새로고침 해주면 기존 세션 정보가 날아간다는 단점이 있다.
    • 세션을 사용하면, http 통신 과정에서 쿠키에 세션 아이디(sid)가 클라이언트로 전달된다. 그리고, 해당 클라이언트에서 어떠한 요청이 전달되면 쿠키에 있는 세션 아이디를 key로 해서 세션 DB에 저장된 필요한 정보를 탐색하고 활용할 수 있다.
    • 쿠키로 클라이언트와 통신을 할 땐 많은 숫자의 데이터를 주고받기에 부담이 될 수 있다. 따라서, 세션을 활용해 데이터를 저장하고, 클라이언트와의 통신 과정에선 쿠키에 비교적 크기가 작은 세션 아이디 정보만 담아 주고받는 게 훨씬 더 경제적이다.
    • 뿐만 아니라, 쿠키에 많은 정보를 담아 통신에 사용하면 통신 내용이 탈취됐을 경우 중요한 정보가 외부에 노출될 우려가 생기고, 보안 상 취약점이 발생할 우려가 있다. 세션은 서버에서 데이터를 저장하고, 필요한 것들만 추출해서 로직 처리 후 내려줄 수 있기 때문에, 조금 더 안정적인 활용이 가능하다.

'TIL' 카테고리의 다른 글

241230 TIL  (0) 2024.12.30
241225 TIL  (0) 2024.12.26
241223 TIL  (0) 2024.12.25
241222 TIL  (0) 2024.12.23
241221 TIL  (0) 2024.12.21