728x90

보통 "반응형", "모바일 사이트" 하면 나오는

 

키워드 두가지가 있다

 

Viewport와 Media 쿼리

 

 

 

둘 중 누구도 없어서는 안되면 필수적인 요소다.

 

media 쿼리는 웹 프론트를 만져본 사람이라면 기본적인 사용법은 익히들 알고있다.

 

물론 이것도 공부하려면 할것들이 제법 많지만

 

필요할때 구글링하면서 쓰면 될만한 내용이라

 

미리부터 공부할 필요는 없을것 같다

 

 

 

그런데 Viewport가 오늘 신선한 충격으로 다가왔다.

 

<meta name='viewport' content='width=device-width, initial-width=1.0' />

그냥 헤더에 이거 한 줄 넣는것.

 

이 이상으로 이것이 무슨 의미를 갖는지 정확히 어떤 역할을 하는지 관심갖지 못했었다.

 

그냥 넣으면 대부분 만사 오케이니까

 

더이상 건드릴 이유도 공부할 이유도 없었다. (몇가지 옵션 정도는 쓰고있지만..)

 

 

 

그런데 재밌는 부분이 있다.

 

내 데스크탑 기준의 css를 태블릿에서도 비율에 맞게 유지하려면 어떻게 하면좋을까?

 

media query로 일일히 퍼센트에 맞게 조정해준다?

 

물론 이거도 노력하면 비슷한 효과를 볼수있다.

 

지금 내가 말하려고 하는것은 물리적/논리적 해상도의 차이에 대해서다.

 

(지금부터, 아래의 내용은 다소 비 전문적이거나 부정확할 수 있습니다.)

 

 

 

 

물리적은 실제 디바이스의 너비이고

 

논리적은 제품사양에 명시된 스펙에 나온 해상도라고 생각하면 될것같다...

 

 

 

자, 먼저 Viewport를 제외하고 생각하면 media 쿼리는 물리적 해상도를 기준으로 

 

컴포넌트/태그 들의 크기를 일정하게 조정해 주는 역할을 한다고 보면 될것같다

 

 

그런데, Viewport를 잘 이용하면 특정 값을 기준으로 논리적 해상도를 기준으로 css를 적용할수있다. (내가 오늘 이해한 바로는)

 

간단히는 이렇게 볼수있다.

 

<meta name='viewport' content='width=1190' />

이렇게 설정해둔다면

 

디바이스의 크기에 상관없이 

 

css의 width: 100%를 1190px로 보게한다.

 

이미 작성해둔 css들은 걱정하지 않아도, 이를 기준으로해서 알맞게 조정한 크기를 보여주게된다.

 

viewport는 정말 어마무시한 친구다.

 

위의 설정을 누가 이용하는지 아는가?

 

바로, 우리가 매일 보고 사용하고 있는 "네이버"다

 

 

 

네이버를 데스크탑에서 열고 개발자 도구를 보면 viewport가 위와 같이 설정되어있다.

 

그런데, 화면의 크기를 모바일 사이즈정도로 작게하고

 

화면을 다시 로드하면 m.naver.com으로 리디렉션하며 

 

해당 페이지에서 개발자 도구를 보면 viewport는

 

<meta name='viewport' content='width=device-width, initial-width=1.0' />

과 같은 우리가 흔히 아는 내용으로 작성되어있다.

 

정말 놀라운 viewport의 세계다.

 

 

 

 

현재 내가 운영중인 서비스에서는 네이버처럼 m.을 분리하여 운영할 여력은 없어서

 

javascript를 이용해 디바이스 크기에 따라 로드 시점에 viewport를 다르게 주도록 설정해보았다.

728x90
반응형
728x90

늘 하듯 AWS, GCP등을 다루다가

 

오랜만에 웹호스팅 문의를 받게되었다.

 

근데 이게 웬걸..? 오랜만에 하려니 어떻게 하면 좋을지 감을 잃었다.

 

솔직히 벙쪘다.

 

 

 

주어진건 가비아 계정과 구매된 도메인

 

요청사항은 HTML파일을 줄테니 호스팅 해달라는것.

 

호스팅 비용은 무료로.

 

 

 

어떻게 해야할까

 

내가 어떻게 했었을까

 

도메인은 원래 있던 사이트에서 어떻게 호스팅 쪽으로 가져올것인가\

 

SSL은 어떻게 붙이지?

 

 

 

늘 하던 작업들이지만, AWS, GCP등 클라우드 서버를 잃은 나는 무언가 무기력했다.

 

어떻게 위 작업을 해낼수 있을것인가...

 

고민끝에 떠올린 방법은

 

Netlify로 호스팅하고 가비아에서 도메인의 네임서버를 Netlify 네임서버로 변경해주는것

 

 

 

먼저, 건네받은 Html이 포함된 폴더를 통째로 Netlify에 올렸다.

 

그리고  차례로 절차를 밟아나갔다.

 

Netlify의 네임서버 사용.

 

그리고 Netlify의 1~4 네임서버를 복사해 가비아의 도메인 네임서버에 덮어씌우기

 

 

 

그렇게 약 6시간이 지난후 정상적으로 호스팅에 성공했다.

 

* 참고로 도메인은 무료가 아닙니다. 

728x90
반응형
728x90

React기반인 서비스를 운영중인 회사의 서비스 페이지에 Fullpage.js + aos를 적용해보았습니다.

아주 쉽고 빠르게 잘 붙었지만

이게 웬걸...

 

로딩만 했다하면 도저히 원인 파악이 어려울 정도의 상황이 발생했습니다.

스크롤 위치가 이상한데 잡히면서 컴포넌트들이 나타나지 않았습니다.

 

aos가 나타나는 trigger에 문제가 있다고 짐작할뿐 대체 왜 이런 현상이 계속되는가...

를 3시간을 추적에 추적을했습니다.

 

그러다 Lazy loading이라는 키워드를 발견했고

서비스페이지만 Lazy loading을 제거했습니다.

 

와우 너무나도 정상적으로 동작..?!

 

이렇게 간단한 이슈인것을 몇시간을 헤맸네요.

Lazy loading을 했을때 왜 해당 이슈가 발생하는지 근본적인 원인에 대해 탐구하는 포스팅을 다음 글에서 이어가도록 하겠습니다.

 

728x90
반응형
728x90

mongo를 쓰다보면,

list내에서 특정 값 혹은 document를 제거해야되는 경우가 굉장히많다.

 

이때는, 원본 자료를 불러와 해당 값을 제거한뒤 업데이트 시키는 방법 (덮어씌우기)을 주로 이용했다.

 

그런데, 자료를 불러올 필요가 없는 상황에서 해당 값만 바로 제거할수는 없을까? 하는 생각이 들었다.

찾아보니, 이때는  $pull 키워드로 해당 작업이 가능하다.

늘상 써오던 $set과 크게 다르지 않다

 

간단한 예제와 함께 포스팅을 마무리하기겠다.

// collection 이름이 Orders인 경우

Orders = [ 
  {
    _id: ...,
    menus: ['coffee', 'tea'],
  },
  {
    _id: ...,
    menus: ['bread', 'tea'],
  },
  {
    _id: ObjectId('abc'),
    menus: ['coffee', 'fruit'],
  },
];

// 특정 대상에 대한 처리 - ObjectId('abc')의 fruit을 제거할때
db.Orders.findOneAndUpdate({ _id: ObjectId('abc') }, { $pull: { menus: { $in: ['fruit']} }  })

// 전체 대상에서 fruit을 제거
db.Orders.updateMany({}, { $pull: { menus: { $in: ['fruit'] } } })


menu가 document형태로 들어가있을 경우?
Orders = [ 
  {
    _id: ...,
    menus: [
      {
        _id: ...,
        name: 'coffee',
        price: 100,
      },
      {
        _id: ...,
        name: 'tea',
        price: 200,
      }
    ],
  },
  {
    _id: ...,
    menus: [
      {
        _id: ...,
        name: 'bread',
        price: 150,
      },
      {
        _id: ...,
        name: 'tea',
        price: 200,
      }
    ],
  },
  {
    _id: ObjectId('abc'),
    menus: [
      {
        _id: ...,
        name: 'coffee',
        price: 100,
      },
      {
        _id: ...,
        name: 'fruit',
        price: 500,
      }
    ],
  },
];

// 특정 대상에 대한 처리 - ObjectId('abc')의 fruit을 제거할때
db.Orders.findOneAndUpdate({ _id: ObjectId('abc') }, { $pull: { menus: { name: 'fruit' } }  })

// 전체 대상에서 fruit을 제거
db.Orders.updateMany({}, { $pull: { menus: { name: 'fruit' } } })

 

 

[참고자료]

docs.mongodb.com/manual/reference/operator/update/pull/

728x90
반응형
728x90

오랜만에 포스팅을 합니다.

 

운영중인 프로그램이 대규모 업데이트가 연속적으로 이루어지고있어

 

포스팅할 시간이 없네요.

 

대규모 업데이트를 하다본니, 이것만큼은 꼭 공유해주고 싶다! 라고 생각이 든 파트가 있어 포스팅하게되었습니다.

 

바로 로깅 시스템인데요.

 

 

다양한 라이브러리에서 로깅시스템을 지원해주지만,

내가 만들어 자유자재로 쓰는 가벼운 로깅시스템은 디버깅에서 최고의 효율은 발휘해주는것 같습니다.

 

예를들어, try/catch구문에서  해당 코드의 디렉토리 위치부터 에러발생 시간, 에러 내용을 모두 표시해준다면
에러복구에 정말 유용하겠죠?

따라서, fs시스템을 이용해 간단한 로깅메서드를 만들어 해당 시스템을 구축해 보도록 하겠습니다.

 

# 순서

1. 로깅 메서드 만들기

2. 활용 예제

3. 응용 예제

 

 


 

1. 로깅 메서드 만들기

const fs = require('fs');
const moment = require('moment');

export const logging = log => {
  const today = moment().format('YYYYMMDD');
  const date = moment().format('YYYY.MM.DD HH:mm:ss');

  const file = `./log/${today}_server.log`;
  const newLine = `[${date}] - ${log}`;

  fs.readFile(file, (err, data) => {
    if (err) {
      return console.error('read log err: ', err);
    }
    
    fs.writeFile(file, data + '\n' + newLine, err => {
      if (err) {
        return console.error('write log err: ', err);
      }
    });
  });
  
};

# 예제 키워드: fs, moment, 백틱

파일을 읽어오고 줄을 바꿔 내용을 덧붙이는 예제입니다.
writeFile은 해당 파일이 존재하지 않으면 기본적으로 create & write하게 되어있습니다.

 

(추가적으로, 해당 옵션은 flag옵션으로 변경가능합니다.)


2. 활용 예제

const { logging } = require('./util');

try {
  // something ...
  
} catch(error) {
  console.log('check system error log: ', error); // 콘솔에서 에러 확인 (개발에 활용)
  logging(error); // 로그파일에 기록 (나중에 확인하기 위함)
  return 'error;
}

 

우리의 logging 예제코드가 util파일에 있다고 가정했을때의 예제입니다.

이렇게, logging(error) 한줄 추가해주는것만으로

" [날짜] - 에러내용 "

 

구조의 에러 리포트를 누적해둘수있습니다.

예외처리에 빠짐없이 잘 써둔다면 디버깅에서 아주 유용하게 쓰일것으로 보입니다.

 

좀더 실용적이고 쓸만한 메서드로 개선해볼까요

 

 

3. 응용예제

# util
const fs = require('fs');
const moment = require('moment');

export const logging = (log, dir) => {
  const today = moment().format('YYYYMMDD');
  const date = moment().format('YYYY.MM.DD HH:mm:ss');

  const file = `./log/${today}_server.log`;
  const newLine = `[${date}] - ${log} ${ dir ? '\n'+ 'directory: ' + dir : ''}`;

  fs.readFile(file, (err, data) => {
    if (err) {
      return console.error('read log err: ', err);
    }
    
    fs.writeFile(file, data + '\n' + newLine, err => {
      if (err) {
        return console.error('write log err: ', err);
      }
    });
  });
  
};


# server
const { logging } = require('./util');

try {
  // something ...
  
} catch(error) {
  console.log('check system error log: ', error); // 콘솔에서 에러 확인 (개발에 활용)
  logging(error, __filename); // 로그파일에 기록 (나중에 확인하기 위함)
  return 'error;
}

# 예제 키워드: __filename

 

 

이렇게 간단한 수정만으로 파일의 디렉토리까지 남겨가며 모든 에러를 추적하게됩니다.

 

728x90
반응형
728x90

모바일 반응형의 기본인 viewport메타태그

 

<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, user-scalable=yes" />

maximum-scale을 포함해 다양한 옵션이 존재한다.

 

이중에서 user-scaleable이 yes 상태이면

input창을 focus했을떄 자동으로 화면이 줌인된다.

user-scalable=0 으로 설정하면 해당 이슈는 해결된다

 

다양한 사용자들에게 접근성을 제공하는 옵션이기도하니 서비스의 특성에 맞게 설정하도록하자.

728x90
반응형
728x90

Input에서 한글입력을 막는 방법에는

여러가지 접근 방법이 있다.

 

절대적인 방법을 발견하여 메모해둔다.

 

1. Input타입이 text인 경우에는 정규식을 통해 체크하여 원하는 문자열 입력방지를 실시할수있다.

예를들어, 숫자만 입력받고싶다면

 

const regExp = /[a-z|ㄱ-ㅎ|ㅏ-ㅣ|가-힣]/g;

 

이런식의 정규식으로 입력값을 체크해서 입력을 방지하면 된다.

그리고 실제로 가능한 방법이다.

 

 

그러나,  우리는 사용자의 입력 편의성을 위하여 input타입을 number로 잡아줘야한다.

그때는 숫자외 다른 입력값을 입력했을때 정규식이 바보가된다.

인지를 못한다.

 

왜 그런가하고 타겟의 값을 콘솔에 찍어보았다.

console.log(e.target.value)

결과: 

분명히 실제로는 "123ㄱ"라고 화면에 나타나 있지만 결과에는 빈값이 출력되었다.

그러니 정규식이 캐치할래야 할수가 없는 상황이었다.

 

2. 정규식이 안먹히면 어떻게하지? 키코드를 사용해야하나?

원하는게 안먹히면 우리들은 발상의 전환을 시도한다.

하지만, 헛탕일 켤뿐 안된다는것을 미리 밝히는 바이다.

 

3. 그래서 어떻게 해야되는가?

input태그에  onchange이벤트를 걸었다면 아래와 같은 방법으로

숫자입력만 받는 방법이 가능하다.

const isNotNumber = () => {
  const regExp = /[a-z|ㄱ-ㅎ|ㅏ-ㅣ|가-힣]/g;
  return regExp.test(value);
}

<input 
  type='text'
  onchange={e => {
    if (e.nativeEvent.data && isNotNumber(e.nativeEvent.data) {
      e.preventDefault();
      return null;
    }
    
    ...something
  }}
/>

 

매우 아름다운 방법으로 생각된다.

e.nativeEvent.data에는 놀랍게도 내가 지금 입력한 그 키값이 나타난다.

3이라면 3, t라면 t가 말이다.

backspace는 null이 나타난다. 따라서 null인 경우에는 허용을 해줘야한다.

 

 

사실 그동안 숫자만 입력받는 코드를 짜뒀다고 했는데

자꾸 한글이 입력된다는 리포트를 받아서 당황스러웠던적이 있다.

코드는 거짓말을 하지않는다...

나의 실책일뿐~~ ㅎㅎ

 

이 방법이 유효하지 않다거나 더 좋은방법이 있다면 댓글을 달아주시면 정말 감사하겠습니다.

728x90
반응형
728x90

여기다가

사용중인 정규식을 하나하나 저장하고 업데이트 하고자한다.

매번 새로 짤 필요도 없고...

 

1. 이메일

/^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,5})+$/

 

2. 휴대폰

/^01(?:0|1|[6-9])[0-9]{4}[0-9]{4}$/

728x90
반응형
728x90

EC2와 NGINX만 쓸때는 너무나도 자연스러웠던것이

LoadBalancer를 쓰면서 추가적인 조치가 필요해졌다

 

EC2 + NGINX 구성에서는 늘 사용자 요청의 대문역할은 NGINX였고,

NGINX에 HTTP -> HTTPS Redirect 설정을 해두면 자연스럽게 처리되었다.

 

다만, 이번에 사용자의 증가로 Load Balancer를 적용한 이후로는 해당 코드는 무효했었다.

대문이 NGINX가 아니라 Load Balancer가 되어버린것이다.

따라서,  HTTP -> HTTPS Redirect설정을 Load Balancer에서 해주었다.

 

너무나도 간단하고 친절하게 되어있으므로 겁먹을 필요없다.

1. EC2 -> 로드밸런서 -> 대상 클릭 -> 하단에 탭중 리스너 -> HTTP 내용중 "규칙 보기/편집"을 클릭하여 해당화면으로 진입.

2. 연필탭 클릭 -> 왼쪽에 뜬 연필 한번 더 클릭 -> 기본 설정 지우고 "리다이렉션 설정" -> HTTPS / 443


참고자료
stackoverflow.com/questions/24603620/redirecting-ec2-elastic-load-balancer-from-http-to-https

728x90
반응형
728x90

[초기설정]

1. key파일을 이용해 root 계정으로 로그인

2. sudo passwd 입력

3. 새 암호 입력

4. 새 암호 확인

 

[변경]

1. root 계정으로 로그인

2. passwd 입력

3. 새 암호 입력

4. 새 암호 확인

 

끝...

728x90
반응형