캐럿브라우징을 포스팅하게 된 이유는 개발을 하는 과정에서 live-server로 띄운 웹페이지의 텍스트영역에 지속적으로 커서가 생기는 현상에 당황스러웠고 처음에는 코드의 문제로 버그가 발생하는 줄 알고 몇분간 삽질을 한 경험이있었다. 이 후 키보드가 잘못 눌렸을 때 문제가 발생했고 해당 브라우저에서 띄운 모든 페이지가 커서를 띄우는 것을 확인 후 캐럿 브라우징에 대해 알게되었다... 혹시 캐럿브라우징 기능이 필요할 수도 있고 같은 실수를 했을 때 당황하지 않고 대처하기 위해 포스팅했고 앞으로도 경험해야 할 문제들도 발단부터 검증하면 분명 해결할 수 있을 것이라는 믿음이 더 강해졌다.
코드를 축소하여 최적화하고 사용하지 않는 코드를 제거하여 빌드하는 방식으로 성능을 최적화할 수 있다.
CSS가 아닌 SASS 혹은 stylus, Typescript 사용 시 컴파일 과정에서 필요 플러그인을 추가하고 번들러를 실행해준다.
종속성 문제의 해결
Webpack의 단점
일부 패키지들을 loader를 통해 매번 추가해주어야 하며 추가하고자 하는 자원의 타입에 따라 추가해 주어야 하는 loader가 다를 수 있기 때문에 러닝커브가 다소 있는 편이다.
Install
# 웹팩, 개발자 서버 인스톨
npm i -D webpack webpack-dev-server
# 필요한 플러그인 및 로더 설치 (css, sass, static copy plugin, env 등)
npm i -D html-webpack-plugin dotenv-webpack css-loader copy-webpack-plugin cross-env source-map-loader sass-loader clean-webpack-plugin
웹팩(개발자 서버 포함)과 필요한 로더와 플러그인을 설치한다.
webpack.config.js 분리
html / css / vanillaJS 구성으로 웹팩 적용하였으며 config 작성할 때 common, dev, prod로
나누어 빌드환경에 맞춰 별도로 관리해주었다.
webpack.common.js
공통으로 적용 될 config를 작성한다.
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const DotEnv = require('dotenv-webpack');
module.exports = {
entry: {
main: path.resolve(__dirname, '../src/script.js'),
},
output: {
path: path.resolve(__dirname, '../public'),
filename: '[name].min.js'
},
// target: ['web', 'es5'], // es5 환경 작업 시 사용
module: {
rules: [
{
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules/
},
{
test: /\.js$/,
enforce: 'pre',
use: ['source-map-loader'],
},
{
test: /\.s?css$/,
use: [
'style-loader',
'css-loader',
'sass-loader'
]
},
{
test: /\.(glb|gltf)$/,
use: ['file-loader']
},
]
},
plugins: [
new HtmlWebpackPlugin({
template: path.resolve(__dirname, '../src/index.html'),
filename: 'index.html',
minify: true,
}),
// origin 그대로 복사할 파일을 지정
new CopyWebpackPlugin({
// 빌드 시 public 폴더에 자동 생성(patterns 경로에 해당 파일이 없으면 에러발생)
patterns: [
{ from: path.resolve(__dirname, '../static') },
{ from: path.resolve(__dirname, '../src/style.css') },
]
}),
// dotenv-webpack패키지를 통한 환경변수(env) 사용
new DotEnv({ path: '.env' }),
]
};
다수의 Mesh, Light, Group, Object3D, Camera로 이루어진 트리 구조이다.
배경색, 안개, 다수의 오브젝트, 빛, 질감 등을 표현하는 화면이다.
Scene은 최상위 노드이기 때문에 객체의 위치와 방향이 부모(Scene)기준이다.
Camera
Camera는 다른 구성 객체와는 달리 Scene 그래프에 포함되지 않으며
Scene객체를 촬영하여 어떻게 보여줄 것인가를 결정하는 역할을 한다.
Light
여러 종류의 광원을 말하며 이는 즉 조명을 뜻한다.
AmbientLight, SpotLight, DirectionalLight 등 다양한 광원을 활용하여
Scene에 존재하는 다양한 3D요소들을 3D 공간 공간에서 볼 수 있다.
Geometry
3D요소의 모양을 정의할 수 있으며 내장객체 또는 파일을 통해 형상을 만들 수 있다.
Material
질감을 뜻하며 표면의 색상, 투명도, 질감을 나타낼 수 있다.
Mesh(Object3D)
Mesh는 특정 Material의 속성을 가진 Geometry를 그리는 객체이다.
Mesh는 3D공간 상의 위치와 특정 기준 축 회전 등을 결정할 수 있으며
Material과 Geometry는 재사용이 가능하여 여러 Mesh가 특정
Material, Geometry를 동시 참조 가능한 특징이 있다.
마치며...
오늘은 Three.js의 기본 구성과 개념에 대한 포스팅만을 진행했지만 현재 Three.js를 사용한 프로젝트가 완성에 가까워졌고 완성된이후에Three.js에 대한 추가 포스팅을 진행할 예정이다. 언제나 개발을 통해 기능을 구현하는 것도 중요하지만 가장 중요한 것은 사용한 기술에 대한 개념, 원리를 명확히 이해하고 있는 것이라 생각하고 있고 나에게는 하나의 원칙이기도 하다. 앞으로도근거 있는기술의 사용과 검증 가능한 코드를 지속하기 위해 더 나은 노력할 것이다.
Import Git Repository에서 git계정을 연결하여 저장소의 프로젝트들을 가져온다.
Import를 눌러 deploy(publishing)를 진행한다.
위와 같이 프로젝트 이름을 설정하고 프레임워크를 동일하게 설정해준다.
유의사항
프로젝트를 진행할때 특정 API-key를 사용해서 통신을 해야하는 경우가 아주 많다.
그러한 API-key는 분명 유출시 위험성이 있기 때문에 .env파일에 환경변수로 사용했을 것이고
Github에도 업로드 되지 않게 했을 것이다.vercel에서 파일을 배포할때 Github의 레포지토리를
기준으로 배포하기 때문에 vercel은 환경변수를 알 수 있는 방법이 없다. 그렇기 때문에 반드시
Environment Variables 텝을 눌러 개발환경과 동일한 변수명과 동일한 API-key를 넣어주어야 한다.
만약 API-key와 같은 환경변수의 값이 입력되지 않는다면 배포가 성공해도 status 500 에러가 발생한다.
환경변수를 모두 Add를 눌러 추가하고 마지막으로 Deploy를 눌러주면 배포가 완료된다.
마치며...
유의사항이라고 큼직하게 환경변수 적용에 대해 적어 두었지만 사실 너무나 당연한 것이다. 나는 환경변수에 대해서 떠올리지 못했고 500에러를 마주하며 좌절했었다. 너무 당연하게 개발환경에서 많은 시간을 투자해서 개발을 하다보니 익숙하지 않은 환경에서 무언가를 시도한다는 것은 그런 당연한 것을 쉽게 망각하기도 하는 것 같다. 역시 경험은 성장에서 빼놓을 수 없는 중요한 요소인 것을 다시금 깨닫는 시간이었다.
getServerSideProps를 사용할땐 반드시 해당페이지의 메인 컴포넌트 파일(index.tsx)에서만 사용가능하다.
마치며...
처음에 ssr기능이 그저 next.js프레임워크를 사용하기만하면 되는 줄 알았는데 전혀 아니였다. 항상 새로운 프레임워크를 사용할땐 공식페이지에서 Document를 꼭 정독하고 프레임워크가 지향하는 개발의 자연스러운 방향과 기능들에 대해 인지하고 적재적소에 사용할 수 있도록 준비해두는 것이 개발자로서 더 올바른 자세라는 것을 깨달았다.
접두사 합(Prefix Sum): 배열 가장 앞부터 특정하는 위치까지 각 누적합을 미리 구해놓은 것이다.
접두사 합을 활용하여 알고리즘을 을 아래와 같이 만들 수 있다. 위치 각각에 대한 접두사 합을 계산하여 P에 저장한다. 매번 특정 수 만큼의 쿼리정보를 확인할때 구간 합은 P[right] - P[left - 1] 이다.
주어진 배열
Index
1
2
3
4
5
6
7
8
Value
3
2
4
1
2
2
1
5
접두사 합 배열
Index
0
1
2
3
4
5
6
7
8
Value
0
3
5
9
10
12
14
15
20
이에 [주어진 배열]에서 각 인덱스별로 누적합을 구한 것이 [접두사 합 배열 (p)]이다.
누적합 알고리즘에서 주어지는 공식 P[right] - P[left - 1] 를 생각했을때 아래의 예시를 확인해보자.
[주어진 배열]에서 1부터 3번째 인덱스가 가진 value의 누적합을 구해야 하는 문제이다.
[1, 3] => p[3] - p[0] = 9
< [주어진 배열]을 확인하면 3 + 2 + 4 이기 때문에 결과는 9가 되는 것을 확인 할 수 있다. >
[주어진 배열]에서 1부터 3번째 인덱스가 가진 value의 누적합을 구해야 하는 문제이다.
[3, 5] => p[5] - p[2] = 7
< [주어진 배열]을 확인하면 4 + 1 + 2 이기 때문에 결과는7이 되는 것을 확인 할 수 있다. >
누적합 알고리즘을 활용한 예시문제
데이터의 개수 N이 8로 주어진다.
찾고자 하는 데이터 4번째 부터 8번째의 값의 누적합을 구해야 한다. (left = 4, right = 8)
let n = 8;
let arr = [3, 2, 4, 1, 2, 2, 1, 5];
// 접두사 합 배열
let sumValue = 0;
let prefixSum = [0];
for (let i of arr) {
sumValue += i;
prefixSum.push(sumValue);
}
// 네 번째 수부터 여덟 번째 수까지
let left = 4;
let right = 8;
console.log(prefixSum[right] - prefixSum[left - 1]);
마치며...
누적합 알고리즘은 내가 생각했던 것 보다 훨씬 효율적으로 특정 범위의 누적합을 구하는 방식이었던 것 같다. 알고리즘을 공부하면서 컴퓨터 공학과 수학은 뗄레야 뗄 수가 없는 관계인 것을 다시금 느꼈다.
리스트에서 순차적으로 기록하며 처리할 때 두가지 위치(점: point)를지정하여 처리하는 알고리즘이다.
예를 들어 [1, 2, 3, 4, 5, 6, 7, 8, 9] 리스트에서 4, 5, 6, 7, 8 을 말할때 "4에서 8까지의 수" 라고 말한다.
위 예시에서 처럼 4~8까지의 수를 "시작점 4"와 "끝점 8"로 2개의 점으로 데이터의 범위를 특정하여
문제를 처리하는 알고리즘을 뜻한다.
투 포인터를 활용하기
부분 연속 수열찾기 문제에서 투 포인터 알고리즘을 활용하여 문제를 해결할 수 있다.
시작점과 끝점이 첫 인덱스 0을 가리키도록 만든다.
[현재 부분의 합 S]가 [찾아야할 값 M]과 같다면 카운트에 추가해준다.
S가 M보다 작거나 같으면 끝점을 1 증가시켜준다.
S가 M보다 크면 시작점을 1증가시킨다.
모든 경우를 2번~ 5번까지의 과정을 반복하며 값을 얻는다.
투 포인터를 활용한 예시문제
데이터의 갯수 N이 8로 주어진다.
찾고자하는 부분 합 M이 5로 주어진다.
주어지는 수열은 [3, 2, 1, 4, 2, 1, 1, 5] 이다.
부분 수열의 합이 M이되는 경우의 개수를 출력하시오.
let n = 8;
let m = 5;
let data = [3, 2, 1, 4, 2, 1, 1, 5];
let cnt = 0;
let intervalSum = 0;
let end = 0;
// start를 순차적으로 증가시키며 반복한다.
for (let start = 0; start < n; start++) {
// end를 조건에 맞는경우 가능한 만큼 이동시키기
while (intervalSum < m && end < n) {
intervalSum += data[end];
end += 1;
}
// 부분합이 m일 때 카운트++
if (intervalSum == m) cnt += 1;
intervalSum -= data[start];
}
console.log(cnt); // output: 3
마치며...
평소에 코딩테스트를 한번씩 풀어보는데 나도 모르는 사이에 투포인터 알고리즘을 사용하는 경우가 종종 있었던 것 같다. 확실히 용어를 알고 원리를 제대로 파악하니 좀 더 전략적으로 코드를 작성할 수 있게 된 것 같아 뿌듯했다.