210524 기록과 지속적인 학습의 관계

Google Search Console

요즘 공부하면서 느끼지만, 개발에 쓰이는 기술들은 트렌드가 정말 빠르게 바뀌는 것 같다. 기존에 사용했던 기술의 단점이 보완되서 더 나은 새로운 기술들이 등장하고, 그렇게 되면서 자연스럽게 학습해야 되는 양도 자연스럽게 늘어가는 것 같다.
물론 그 근간이 되는 기본 지식을 탄탄하게 쌓는다면, 그 변화의 물살을 타고 서핑하는 기분으로 배움의 즐거움을 느낄 수 있을 것이다.

이번 포스팅에서는 내가 작업한 것들을 종합해서 정리하기 위한 목적의 웹 페이지를 만들면서 자연스럽게 내가 여지까지 만들었던 깃허브 레포지토리와 블로그의 글들을 전체적으로 보았는데, 그때 느낀점들을 위주로 글을 남겨보려고 한다.

지식의 생명주기와 기록

개발관련 공부를 하면서 항상 느끼는 점은 공부해야 되는 양과 범위가 방대하다는 것이다. 저번주에 학습했던 내용이 몇 일이 지나면 새롭게 느껴지고, 몇 달 전에 학습했던 내용에 대해서는 더욱 더 새롭게 느껴진다. 그래서 공부했던 내용은 주기적으로 반복학습이 필요하다.

이번에 블로그와 깃허브 저장소들을 전체적으로 살펴보면서 내가 어떤 것들을 학습하고 기록했는지 살펴보았다. 다행히 깃허브 저장소의 README에 꼼꼼하게 작업한 내용들과 목적, 그리고 내가 포스팅한 블로그 글의 링크도 첨부해두어서 마치 이전 학습을 진행했을때로 잠시 돌아가서 금방 학습했던 내용들을 복습할 수 있었다.

만약 내가 이런 기록들을 남기지 않았더라면, 아마도 또 다시 그 때와 비슷한 시간을 투자해서 다시 학습을 해야하는 상황이 벌어졌을지도 모른다.

인터넷에 검색을 하면 정말 내가 작성한 블로그 글과는 비교가 안 될 정도로 잘 정리된 블로그 글들이 많다. 하지만 아무리 잘 작성되어있는 글이라고 하더라도 내가 작성했던 글만큼 잘 읽히지 않는다. 그리고 내가 직접 글을 작성해보면 덤으로 다른 사람에게 설명하는 연습이 되기도 한다.

그래서 나만의 언어로 정제를 해서 글을 쓰는 작업은 정말 중요한 것 같다.

뭔가 나만의 노트에 필기를 하게 되면 나만 보는 것이기 때문에 막 적게 되는데, public한 블로그와 같은 곳에 블로그 글을 포스팅하게 되면 여러 번 글을 다듬게 되는 것 같다. 그 과정을 통해 자연스럽게 작성한 글을 여러번 읽고 복습하게 되는 좋은 부수효과도 얻게 되는 것 같다.

내가 블로그 포스팅을 하는데 있어 가장 좋은 동기부여는 Google Search Console이었던 것 같다.
내 블로그의 검색엔진을 최적화(SEO)하고, 네이버와 구글의 Search console에 블로그를 등록해서 내 블로그가 어떤 검색어로 노출이 많이 되고 사람들이 방문을 하는지 알 수 있도록 하였다.

Read More

210517 React with NextJS TIL - Next Redux Wrapper, HYDRATE, redux-thunk, 제너레이터 함수에 대한 이해, redux-saga

2021/05/17 - redux-thunk 내용추가

ReactJS with NextJS

Next Redux Wrapper

일반적으로 React에 Redux를 붙일 때에는 하나의 Redux store만 존재하기 때문에 어렵지 않다.
하지만 Next.js에서 Redux를 사용하게 되면 여러 개의 Redux store가 생성된다.
그 이유는 Next.js에서는 User가 Request를 보낼때마다 Redux store를 새로 생성하기 때문이다. 그리고 Next.js에서 제공하는 getInitialProps와 getServerSideProps에서도 Redux store에 접근이 가능하도록 해야되기 때문에 NextJS에서 Redux를 붙일때 꽤나 복잡하다. 하지만 이를 간편하게 해주는 라이브러리가 있는데 바로 Next Redux Wrapper이다.

next redux wrapper 설치

/store/configureStore.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import { createWrapper } from 'next-redux-wrapper';
import { createStore } from 'redux';
import reducer from '../reducers';

const configureStore = () => {
const store = createStore(reducer);
return store;
};

const wrapper = createWrapper(configureStore, {
debug: process.env.NODE_ENV === 'development'
});

export default wrapper;

Read More

210516 ReactJS TIL - 컴포넌트 폴더 구조, 해쉬태그 구현을 위한 정규표현식

React

컴포넌트 폴더 구조

컴포넌트를 작성할때 각각의 개별 컴포넌트를 하나의 개별 폴더로 분리해서 작성해주는 것이 좋다.
그 이유는 styled-components로 만든 컴포넌트들을 하나의 파일에 같이 작성을 해주게 되면 가독성에 좋지 않기 때문에 하나의 컴포넌트 폴더 내부에 index.jsstyles.js로 분리해서 styles.js 파일 내에는 styled-components로 작성해준 컴포넌트들만 따로 분리해서 작성해주도록 한다.

ex)
/components/ImagesZoom/index.js
/components/ImagesZoom/styles.js

해쉬 태그를 위한 정규 표현식

참고 사이트 : https://regexr.com/

(1) //g : g는 여러개 요소를 찾는 옵션
(2) /#./g : .은 # 뒤에 한 개 문자까지 선택
(3) /#../g : ..은 # 뒤에 두 개 문자까지 선택
(4) /#.+/g : .+는 # 뒤의 모든 문자들을 선택
(5) /#[^\s#]+/g : 공백(\s)을 제거하고 다음 해쉬 태그 기준으로 끊기

split 메서드와 함께 사용하는 경우에는 아래와 같이 정규표현의 조건부를 괄호로 감싸줘야 한다.

1
2
3
/(#[^\s#]+)/g;

'첫 번째 게시글 #해시태그 #익스프레스'.split(/(#[^\s#]+)/g);

210515 React with NextJS TIL - Next.js에서 styled-components를 사용하기 위한 설정

ReactJS with NextJS

참고 : https://github.com/vercel/next.js/tree/master/examples/with-styled-components

Next.js에서 styled-components 사용하기

Next.js에서 styled-components를 사용하려면 몇 가지 설정이 필요하다.

(1) babel-plugin-styled-components 설치하기

이 패키지를 설치하는 이유는 Next에서 최초로 SSR이 된 이후에 내부 라우팅을 통해 페이지가 이동하면서 CSR을 하게 되는데, className의 해시값이 서버에서 생성되는 값과 브라우저에서 생성되는 값이 불일치하게 되면서 에러가 발생하기 때문에 설치해줘야 한다.

1
npm i -D babel-plugin-styled-components

(2) .babelrc 파일 생성하기

1
2
3
4
{
"presets": ["next/babel"],
"plugins": [["styled-components", { "ssr": true }]]
}

(3) pages 폴더 아래에 _document.js 파일 생성하기

참고: https://nextjs.org/docs/advanced-features/custom-document

Read More

210514 Redux vs Mobx vs ContextAPI

React
Redux Mobx ContextAPI
원리가 간단하다. 어플리케이션이 별로 크지 않은 경우에 사용하도록 한다.
에러에 대한 추적이 가능하다. 에러에 대한 추적이 불가능하다.
코드의 양이 많다. 코드의 양이 적다.(생산성이 높다)

비동기 요청을 했을때에는 요청에 대한 실패에 대비를 해야 되기 때문에 이런 처리부분에 대해 해당 상태관리 라이브러리가 제공하는지에 대해 고려해서 사용해야 한다.(대기, 성공, 실패) 이 부분에 대해 Redux와 Mobx는 제공이 되지만, ContextAPI의 경우에는 직접구현을 해야한다.

210514 React TIL - ContextAPI의 사용, Custom Hook(useContext + React.createContext), Strict mode, action 객체와 reducer 함수의 작성, React에서 상태관리의 위치

20210418 Update - Custom hooks - context.js
20210514 Update - Custom hooks(input)

React

본 포스팅 내용은 과거에 개인적으로 공부할때 정리했던 ReactJS의 내용을 복습의 목적으로 다시 정리하는 포스팅입니다.

실습 Repository : https://github.com/LeeHyungi0622/react-basic-projects/blob/master/sidebar-modal/src/context.js

ContextAPI의 사용 & Custom Hook(useContext + React.createContext)

여지까지 ContextAPI를 모든 하위 컴포넌트들의 상위 컴포넌트에서 정의해서 사용했었는데, 이 ContextAPI부분을 별도의 파일로 정의를 해서 사용할 수 있다.
이렇게 별도의 context.js파일로 작성해서 관리를 하면 코드를 좀 더 가독성 좋게 만들 수 있는 것 같다.

그리고 ContextAPI에서 전달하는 값을 사용하는 하위 컴포넌트들에서는 매번 useContext를 import해서 인자로 React.createContext() 객체를 인자로 넣어서 값을 호출해서 사용하였는데 이 부분은 별도의 custom Hook으로 정의해서 사용을 할 수도 있다.

(custom Hook을 만들어서 사용할때에는 함수의 이름에 접두사 use를 꼭 붙여줘야 한다.)

context.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
import React, { useState, useContext } from 'react';

const AppContext = React.createContext();

const AppProvider = ({ children }) => {
// modal, sidebar state
const [isSidebarOpen, setIsSidebarOpen] = useState(false);
const [isModalOpen, setIsModalOpen] = useState(false);

const openSidebar = () => {
setIsSidebarOpen(true);
};

const closeSidebar = () => {
setIsSidebarOpen(false);
};

const openModal = () => {
setIsModalOpen(true);
};

const closeModal = () => {
setIsModalOpen(false);
};

return (
<AppContext.Provider
value={{
isModalOpen,
isSidebarOpen,
openModal,
openSidebar,
closeModal,
closeSidebar
}}
>
{children}
</AppContext.Provider>
);
};

// Custom Hook(useContext + AppContext)
export const useGlobalContext = () => {
return useContext(AppContext);
};

// index.js에서 최상위 App.js를 감싸주기 위해 AppProvider를 export해준다. (index.js)
export { AppProvider };

Read More

210511 Node.js TDD Practice 다섯번째 이야기 - 통합 테스트 (Integration Test) 코드 작성

Nodejs Mocking Http Request

통합 테스트(Integration Test)

모듈을 통합하는 단계에서 수행하는 테스트로, 단위 테스트를 통해서 모듈들이 모두 잘 작동하는 것을 확인한 뒤에 모듈들을 서로 연동하여 테스트를 수행하는 것을 말한다.

Supertest

단위 테스트에서 jest 모듈을 사용해서 테스트를 했다면, 통합 테스트는 supertest라는 모듈을 이용해서 구현을 한다.

단위 테스트에서는 MongoDB 부분은 문제가 없다는 가정하에 mock 함수로 처리를 했는데 통합 테스트에서는 supertest를 사용해서 실제로 요청을 보내서 테스트를 진행한다.

통합 테스트 코드 작성

통합 테스트 코드는 실제 작성한 코드의 로직을 기반으로 작성한다.

예를들어 아래와 같이 MongoDB에 req.body를 통해 넘겨받은 데이터를 새로 추가하고 추가된 데이터를 별도의 변수에 담아 response의 status code가 201인 경우에 json 데이터로 함께 전달하고 있다.

1
2
3
4
5
6
7
8
9
exports.createProduct = async (req, res, next) => {
try {
const newProduct = await productModel.create(req.body);
console.log('createProduct', newProduct);
res.status(201).json(newProduct);
} catch (error) {
next(error);
}
};

위의 코드를 통합 테스트 코드로 작성을 하면, 아래와 같이 통합테스트 코드를 구현할 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
const request = require('supertest');
const app = require('../../server');
const newProduct = require('../data/new-data.json');

test('POST /api/products', async () => {
// 실제 코드와 같이 요청을 보내고 함께 보낸 데이터를 response 변수에 담는다.
const response = await request(app).post('/api/products').send(newProduct);
// 위의 response 객체의 상태코드를 확인
expect(response.statusCode).toBe(201);
// response의 body(json) 데이터를 확인을 한다.
expect(response.body.name).toBe(newProduct.name);
expect(response.body.description).toBe(newProduct.description);
});

Read More

210510 anchor 태그에서 target="_blank" 속성의 보안적 문제

Security issue

anchor 태그에서 target=”_blank” 속성의 보안적 문제

anchor 태그에 연결되어있는 페이지를 새로운 창에 열고자 할때 속성에 target=”_blank”를 넣어주는데, 보안적으로 문제가 있다. 바로 Tabnabbing이라는 공격의 위험성이 있다는 것이다.
Tabnabbing이란 HTML 문서 내에서 링크를 클릭했을때 새롭게 열린 탭이나 페이지에서 기존 문서의 location을 피싱 사이트로 변경해서 정보를 탈취하는 공격기술을 말한다.
이 공격은 이메일이나 커뮤니티에서 쉽게 사용될 수 있기 때문에 주의해야 한다.
따라서 anchor 태그에 target=”_blank” 속성을 넣어 줄 때에는 반드시 rel="noreferrer noopener"라는 속성을 같이 넣어서 취약점을 보완해야 한다.

210510 Node.js TDD Practice 네번째 이야기 - 비동기 요청 에러에 대한 테스트 코드 작성

Nodejs Mocking Http Request

Error handling

이번 포스팅에서는 req.body로부터 넘겨받은 데이터를 MongoDB에 저장할때 발생할 수 있는 에러 케이스에 대해 에러 처리를 하기 위한 테스트 코드 작성에 대한 내용을 작성해보려고 한다.

현재 테스트에 있어서 프론트단이 별도로 개발되어있지 않기 때문에 Postman을 이용해서 임의로 만든 API를 테스트 할 것이다. Postman을 사용하면 API 개발의 생산성을 높여 줄 수 있으며, Request를 임의로 전달해서 테스트를 할 수 있다.

Postman

Postman의 사용은 위의 캡처와 같이 우선 테스트할 Request의 method를 선택을 하고, Endpoints를 작성해준다. 요청시에 Body에 별도로 데이터를 담아서 전달해야되는 경우에는 Body 옵션을 선택해서 전송하고자하는 데이터의 타입을 지정해서 데이터를 작성해주면 된다.

모든 설정이 끝난뒤에 Send버튼을 클릭해주면, 앞서 endpoint에 작성해준 URL과 mapping되는 router의 callback 함수(controller)가 앞서 Postman에서 설정한 내용을 기반으로 실행이 된다.
(Body에 별도의 데이터를 담아서 전달한 경우에는 callback 함수(controller)의 req.body를 통해 전달이 된다.)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
app.use('/api/products', productRoutes);

router.post('/', productController.createProduct);

// 비동기 요청에서 발생되는 에러에 대한 예외처리
exports.createProduct = async (req, res, next) => {
try {
const newProduct = await productModel.create(req.body);
console.log('createProduct', newProduct);
res.status(201).json(newProduct);
} catch (error) {
next(error);
}
};

Read More

210510 TTV, TTI, SSG의 개념


이번 포스팅에서는 개발자라면 상식으로 알고 있어야 하는 TTV(Time To View), TTI(Time To Interact), SSG(Static Site Generation)의 개념에 대해서 정리해보려고 한다.

우선 앞의 세 가지 개념에 대해서 정리를 하기 전에 간단하게 웹의 변천사에 대해서 살펴보자.

1990년 중반까지의 웹 사이트는 static sites로, 서버에서 이미 만들어진 HTML 파일들을 받아오는 형태로 동작한다. 이 static sites의 단점은 주소를 요청할때마다 다시 서버로부터 새로운 html 파일을 받아서 re-rendering을 하기 때문에 화면이 blinking되어 사용감에 불편함을 준다.

이러한 전체 화면이 re-rendering이 되는 것을 개선하고자 1996년부터 html 문서 내에 또 다른 문서를 포함시킬 수 있는 <iframe>태그가 도입이 되었고, 이때부터는 페이지 내에서 부분적으로 문서를 받아와서 업데이트를 할 수 있게 되었다.

1998년이후부터는 현재 비동기 요청시에 사용되는 fetch API의 원조격인 XMLHttpRequest API가 등장을 하게 되는데, 이때부터 JSON 포멧으로 서버로부터 필요한 데이터만 받아 올 수 있게 되었다. 받아 온 데이터는 자바스크립트로 동적으로 HTML element를 생성해서 페이지에 로딩할 수 있게 되었다.

위의 방식이 2005년부터 공식적으로 ajax라는 이름으로 불려지면서, SPA의 방식이 본격적으로 도입이 되기 시작했다.
하나의 웹 페이지에서 필요한 부분의 일부만 렌더링하기 때문에 사용자에게 앱을 사용하는 것과 같은 사용감을 주기 때문에 웹 앱이라고 불리기 시작했다.

SSR과 CSR의 개념에 대해서는 이전에 별도로 블로그 포스팅을 해뒀기 때문에 아래 링크의 포스팅을 참고하도록 하자.

https://leehyungi0622.github.io/2021/04/26/202104/210426-SSR_and_CSR/

CSR의 문제를 보안하기 위한 SSR

CSR방식은 처음에는 서버로부터 빈 화면만 받아오게 되고, 이후에 서버로부터 필요한 자바스크립트 파일과 필요한 각종 라이브러리 및 소스코드를 받아오게 되는데 사이즈가 크기 때문에 초기의 긴 로딩 시간검색엔진 최적화(SEO) 문제라는 두 가지 문제점을 가지고 있다.
이러한 이유 때문에 1990년 중반부터 사용된 static sites에서 영감을 받은 SSR방식이 도입되었다.
하지만 SSR 방식의 도입이 앞의 두 가지 문제점은 어느정도 개선을 할 수 있었지만, 완벽한 솔루션이 되지는 못했다. 그 이유는 첫 페이지 로딩시에 blinking issue서버 과부화라는 두 가지 문제점 때문이었다. 또한 초기에 화면이 빠르게 로딩되더라도 사용자와 interact하기 위한 대기시간이 필요(화면이 로딩되어 클릭을 했는데 아무런 반응이 일어나지 않는 경우)했고, 이 부분을 이해하기 위해서는 이번 포스팅에서 다룰 TTV(Time To View)와 TTI(Time To Interact)의 개념에 대해서 알고 있어야 한다.

Read More