깊은바다거북
개발 공부 기록
깊은바다거북
전체 방문자
오늘
어제
  • 분류 전체보기 (219)
    • JAVA (9)
    • JavaScript (15)
    • 스파르타코딩클럽 (11)
      • [내일배움단] 웹개발 종합반 개발일지 (5)
      • [내일배움캠프] 프로젝트와 트러블 슈팅 (6)
    • SQL | NoSQL (4)
    • CS 등등 (0)
    • TIL | WIL (173)
    • 기타 에러 해결 (3)
    • 내 살 길 궁리 (4)

인기 글

최근 글

최근 댓글

태그

  • 자잘한 에러 해결
  • 최소 힙(Min Heap)
  • 자료 구조
  • 팀 프로젝트
  • 재귀 함수
  • Til
  • BST(이진 탐색 트리)
  • 혼자 공부하는 자바스크립트
  • TypeScript
  • TIT (Today I Troubleshot)
  • leetcode-cli
  • 프로그래머스
  • Preorder Traversal(전위 순회)
  • 최대 힙(Max Heap)
  • Trie
  • 01. 미니 프로젝트
  • POST / GET 요청
  • 자바스크립트 기초 문법
  • 점화식(Recurrence Relation)
  • Backtracking(백트래킹)
  • Linked List
  • Inorder Traversal(중위 순회)
  • tree
  • 시간 복잡도
  • BFS(너비우선탐색)
  • 코딩테스트 연습문제
  • DFS(깊이우선탐색)
  • Leetcode
  • 트러블 슈팅 Troubleshooting
  • Binary Tree(이진 트리)
hELLO · Designed By 정상우.
깊은바다거북

개발 공부 기록

TIL | WIL

2/14 화 (표류하고 있음) TIL

2023. 2. 14. 23:26

(막간 보충 공부중)

어제 오늘은 이론을 배우고 정리하기보다 코드를 직접 써보는 일에 집중했다. 직전 프로젝트 때의 다른 팀들의 코드를 보면서 연구하고 우리 팀 프로젝트 코드에 적용해보았다.

사실은 집중이 잘 안 됐다. 이론상으로 작동되어야 하는 코드가 계속해서 턱턱 막히니 진도가 굼벵이보다도 느린 느낌이었고 이렇게 계속해도 되는가 의문이 들었다.

저녁에는 그래서 자바스크립트 문법을 공부하며 환기했다. 여태 코딩과 구글링을 하며 스치기라도 한 개념들이 한가득 쌓여있는 상태라 그런지, 아니면 죽치고 안 풀리는 문제가 아닌 다른 걸 보는 것만으로도 살 판이 난 건지, 꽤 심화 문법에 관한 책이었는데도 재밌게 읽었다.

언제나 같은 딜레마와 의문이긴 하지만… 지식을 읽고 배워서 어떻게 해야 코드를 한 줄이라도 써서 적용하고 내 걸로 만들어볼 수 있을까? 결국 맹렬한 속도로 까먹을 거라지만, 그래도 어떻게 해야 불씨라도 잘 보존시켜놓을 수 있을지. 이런 고민에 언제나 정답같이 들려오는 소리처럼, 고민할 시간에 무작정 한 줄이라도 써보는 게 맞는 걸까. 하지만 그 무작정 한 줄을 어떻게 쓰냐고. 뭔가 커다랗게 돌아가는 소프트웨어적인 맥락에서 어떻게 쓰이고 어떨 때를 위해 어떻게 만들어서 저장해놔야 하는지를 알고 싶다.

나는 예시를 알고 싶다. 진짜 이게 어디에 왜 쓰이는 것인지. 그래서 왜 필요한 건지를 알고 싶다... 너무 이상적이기만 한 생각인지도. 그래도 예시 코드에 중점을 두고 수집해 나가는 것도 나쁘지 않은 전략일 것 같다. 내 검색 능력이 떨어져서 그런지 몰라도, 생각보다 내가 궁금해하는 그 상황에 알맞은 예제 코드가 별로 없다. 검색하고, 나오는 코드마다 읽고 가치가 있는지 판단하고 취합하고 정리하고 하는 데 시간이 많이 걸릴 것이다. 시간이 좀 걸려도, 미래의 나를 위해 그런 예시들을 모으는 것이 더 나을까?


Express의 req.path와 req.route.path

http://localhost:3000/api/admin/user/:email 이라는 URI가 있을 때

// app.js
const router = require('./routes');
app.user('/api', router);

// routes/index.js
const router = express.Router();
const adminRouter = require('./amin.routes');
router.use('/admin', adminRouter);
module.exports = router;

// routes/admin.routes.js
const router = express.Router();
const adminController = new require('../controllers/admin.controller)();
router.get('/user/:email', adminController.searchUser);
module.exports = router;
  • req.route.path === ‘/user/:email’ 이런 용례와
  • req.path === ‘/api/admin/user’ 이런 용례로 사용할 수 있다.

1. 관리자가 아닐 시 페이지 렌더링 막기

페이지에 가서 로그인 상태인지, 관리자인지를 체크하지 말고, (그러기 전에 이미 서버에서 다 렌더링 해서 줘버린 상태일 것이므로 좋지 않다…) 아예 렌더링을 담당하는 서버 계층에서 html을 보내줄 것인지 말 것인지를 결정하도록 하자.

DON’T

이렇게 하지 말고 :

// views/admin_orders.ejs
<script>
    // 페이지 진입 시
    if(localStorage.getItem('is_admin')!=='1'){
        alert('관리자 권한이 없습니다.')
        location.href='/'
    }
    // 페이지 로딩 완료 시
    $(document).ready(function () {
        me()
        showOrderTables();
    });
</script>

⇒ 렌더링 완료된 페이지가 살짝 보이는 것을 막을 수 없음.

DO

이렇게 하자:

// pages.routes.js
router.get('/admin/orders', authMiddleware, (req, res, next) => {
  try {
      // 로그인을 하지 않은 경우
      에러 던지기

      // 로그인을 했지만 관리자가 아닌 경우
      에러 던지기

      // 관리자인 경우
      res.render('admin_orders.ejs', { components: 'orderManagement' });
  } catch (error) {
			// 던져진 에러를 받아서 next로 넘김
      next(error);
  }
});

⇒ route 단계에서 try-catch 문으로 갈랐다.

2. 모든 request-response 사이클에서 던진 에러 받아 처리하기

위의 예시처럼

} catch (error) {
	// 던져진 에러를 받아서 next로 넘김
  next(error);
}

이렇게 next(error)로 넘긴 모든 에러에 대한 처리는, 도입된 미들웨어들이 ‘위에서부터 순차적으로 처리된다’는 Express의 원리를 이용해 에러 처리 미들웨어를 가장 밑에 붙여두면 된다.

  1. 에러 처리 미들웨어를 만들고:
// middleware/error-handler.js
module.exports = (err, req, res, next) => {
	/* 페이지 렌더링 처리 */
  if (err.message === '로그인이 필요합니다') {
      return res.render('modal.ejs', { message: err.message, href: '/login'});
  }
  if (err.message === '관리자 권한이 필요합니다') {
      return res.render('modal.ejs', { message: err.message, href: '/'});
  }
	// ...
}

  1. Express app이 거치는 가장 마지막 미들웨어가 되도록 위치시킨다:
// app.js
const pageRouter = require('./routes/pages.routes');
const errorHandler = require('./middleware/error-handler');

/* ... 각종 app.use()들 ... */
app.use(pageRouter); // --> 페이지를 렌더링하는 라우터
app.use(errorHandler); // --> 각종 에러가 이 끝 미들웨어 함수로 모이게 됨. 

  • 그런데 같은 이름의 에러가 여러 곳에서 발생한다고 할 때, errorhandle.js 상단에서 이미 res.render()로 모든 ‘로그인이 필요합니다’ 에러에 대한 응답을 반환해버리는데, 따로 어떻게 또 res.json() 등의 예외 처리 케이스까지 도달하게 하지..?

3. 문제 발견

기존의 auth-middleware에서

module.exports = (req, res, next) => {
  const { authorization } = req.headers;
  const [authType, authToken] = (authorization || '').split(' ');

  if (!authToken || authType !== 'Bearer') {
    res.status(401).send({
      errorMessage: '로그인이 필요한 기능입니다.',
    });
    return;
  }
	
	try {
		const { user_id } = jwt.verify(...)
	}...

이런 방식은 반드시 HTTP 요청이 발생했을 때만 사용자 인증이 가능하다는 문제를 발견했다. 프론트에서 Ajax 요청을 보내지 않는 단순한 페이지 이동일 시, res.locals.users에 유저 확인 정보를 담는 이 방식으로는 계속해서 ‘로그인이 필요한 기능입니다’라고만 페이지를 띄울 뿐이다. 프론트 쪽에서 페이지 로딩이 될 때마다 /users/me를 호출하게 만드는 방식으로 해결할 수 있지만, 이는 서버쪽에서의 해결이 아니다.

location.href = ‘/admin_index’를 활성화하는 시점에 /users/me를 호출하게 하거나 Authorization header를 넣어주거나 하는 방법은 없을까?

페이지가 로딩되는 시점에 일단 me()를 호출하고, 바로 이어서 페이지 자체를 렌더링해주는 api를 또 호출하게 하는 식은 안될까?


Uploaded by N2T

    'TIL | WIL' 카테고리의 다른 글
    • 2/16 목 (코드를 실컷 작성하니 단축키가 손에 붙는다) TIL
    • 2/15 수 (Ajax를 안 거치고 로그인이 필요한 페이지에 접근하려면 cookie밖에 답이 없다) TIL, TIT
    • 2/13 월 (첫 TDD 코딩 문제 풀이 - Bowling Game Kata) TIL
    • 2/10 금 (Nest.js로 DB없는 게시판을 만들어 보다) TIL
    깊은바다거북
    깊은바다거북

    티스토리툴바