mythinkg

ignocide's blog


  • 홈

  • 아카이브

  • 태그

css의 색상 표기법(색상값)

작성일 2018-08-30 | In css |

개요

웹을 만들 면서 색상을 표시하는 방법을 정리합니다. 정리라고 쓰고 이 글의 내맘대로 번역이라고 한다.
웹에서 스타일에 대한 부분을 처리하는 css는 현재(2018년) level3(이하 css3)의 상태(완벽하진 않지만..)에 있습니다.
css에서는 color 속성를 표기하는 방법으로서 크게 3가지가 있으며 아래와 같습니다.

  • 키워드
  • rgb(rgba, 16진수 표기법)
  • hsl(hsla)

  • 기타
    • transparent
    • currentColor

이제부터 3가지 방식에 대해서 하나씩 정리하겠습니다.

키워드 표기법

Once upon a time 초창기(CSS1)에는 당연히 그 당시의 컴퓨터에 맞게 작성되었고 구식의 컴퓨터에서는 VGA 그래픽카드로부터 받아 표현 할 수 있는 색상 16개를 사용하여 작성되었다고 합니다.
표시는 white, black 과 같이 그 색상를 직접 작성하여 표기하는 아주 직관적이고 단순한 방법입니다.

color: black;

CSS버전이 올라가면서 rgb를 이용한 컬러값을 표현할 수 있게 되었습니다.
X윈도우 시스템인 X11에서는 더욱 많은 색을 표현하기 위해 많은 이름의 색상들을 사용하였습니다.
CSS3에서는 충돌되는 부분을 수정하여 124개의 색상이 추가가된 140색상이 작성하였습니다.
몇몇의 브라우저에서는 추가의 키워드가 있지만 CSS3의 표준은 140개입니다.

rgb(rgba), 16진수 표기법

16진수 표기법(Hexadecimal notation)

#와 16진수의 6자리 숫자로 이루어져 있습니다.

Hex Triplet라고 불리기도 하는 표기법입니다. 이 이름에서 처럼 두자리씩 3개로 끊어서 각각 빨간색, 녹색, 파란색의 값들이 들어가게 됩니다.

#[RR][GG][BB]

흔히 초등학교 때 배우는 색의 3원색(가산혼합)을 이용한 표현 방법입니다.
이 방식를 이용해 표현범위는 24bit(16^6 === 2^24)를 이용해 표현할 수 있는 색상 범위를 말하는 true color를 표현할 수 있습니다. 갯수로는 16진수의 6제곱인 16,777,216가지의 색을 표현 할 수 있습니다.

16진수 표기법은 각각의 두자리를 한자리로 줄여 짧게 줄여서 표기할 수 있습니다. 각각의 색상의 서로 다른 자릿수가 같으면 줄여 작성합니다. 예를 들어 #0cf는 #00ccff와 같습니다. 당연히 표현범위는 4096개로 좁아지게 됩니다.

#[R][G][B]

위의 6자리 숫자에 2자리를 더해 알파(Alpha)값을 표현 할 수 있습니다.
알파값은 투명 정도라고 이해하시면 됩니다.

#[RR][GG][BB][AA]

알파값을 포함한 8자리의 표기법 또한 위와 같은 방법으로 4자리로 줄여 표시 할 수 있습니다.

rgb(rgba) 표기법

rgb 는 각각 Red, Green, Blue의 약자로서 위의 16진수 표기법을 함수식 표기법(functional notation)을 사용하여 표현하게 됩니다.

rgb(R, G, B)

각각의 값들은 0~255사이의 10진수 또는 백분률로 표기할 수 있습니다. 예) rgb(210,35,2) rgb(10%,10%,10%)

rgba는 추가로 alpha값을 사용하는 함수 표기법으로서 alpha값은 0~1 사이의 값이나 백분률로 표시 할 수 있습니다.

rgba(R, G, B, A)

예) rgba(210,35,2,0.1) rgba(10%,10%,10%,10%)

hsl(hsla) 표기법

hsl(Hue, Saturation, Lightness)

Hue, Saturation, Lightness는 각각 색상,채도,명도 뜻합니다.
색상, 채도, 명도의 이름에서 알다 싶이 위 rgb에서의 색의 3원색과는 다른 관점으로 색의 3요소를 가지고 표현합니다.
즉, 색상과 짙은 정도(채도), 밝음 정도(명도)를 조합하여 색상을 표현합니다.

Hue에 해당 하는 값은 한국말로는 색상환 이라고 불리는 color circle에서 색을 선택하는 식이기 때문에 css에서 angle를 표현하는 deg,grad,rad와 같은 변수들을 인자로 사용합니다.
Saturation와 Lightness는 백분율이 들어 갈 수 있습니다.

이와 같은 구조로서 추론 할 수 있는 것은 흰색과 검은색과 같은 무채색들은 색상의 값이 무의미되는 특징이 있습니다.
hsl(0,0%,100%)의 값은 hsl(100deg,0%,100%)와 같은 흰색으로 표현 할 수 있습니다.
예) hsl(100deg,20%,50%) hsl(3rad,10%,10%)

hsla(Hue, Saturation, Lightness, Alpha)

hsla 또한 위와 같은 패턴으로 Alpha값을 추가로 지정 할 수 있습니다.

기타 값들

color의 값으로서 위에서 정리한 3가지 방식말고 들어갈 수 있는 다른 값들이 있습니다.

transparent

이것은 색상을 투명하게 합니다. rgba(0,0,0,0) 과 같습니다.

currentColor

.red {
  color: red;
  border-color: currentColor; // 1번 부분
}

.red > .child {
  color: currentColor;
  border-color: currentColor;
}
<div class='red'>
  색상은 빨간색, 테두리는 색상의 색을 받아 빨간색
  <div class='child'>
    색과 테두리색이 없기 때문에 지정된 색이 없기 때문에 상속받은 색인 빨간색을 사용,
  </div>
</div>

currentColor는 색상 속성을 사용하고 없다면 부모로부터 색상을 상속받아 색상을 표현 합니다.
red class의 색상을 빨간색으로 지정하였기 때문에 1번부분에서의 currentColor는 빨간색으로 사용되게 됩니다.

자식 엘리먼트에서는 지정된 색상이 없기 때문에 부모로부터 상속받은 빨간색을 사용하게 됩니다.

더 읽어보기 »

내 월급 내가 보겠다는데 이리 힘들 줄이야

작성일 2018-04-12 | In javascript |

전말

짜증의 시작

글쓰는게 미숙하여 글마다 어투가 다르지만 이번글은 일상이기 때문에 구어체로 작성된다.

스타트업에 다니는 나는 회사에서 따로 회계사를 두지 않아 외부 회계사로부터 급여명세서를 받아본다. 사건의 시작은 평소와는 다른 이상하리 만큼 빠른 시기에 급상여명세서가 빨리 온 4월의 어느 월급날 전에 벌어졌다.

급여명세서나 카드 이용내역서는 생년월일을 비밀번호로 하여 암호화 되어 html파일로 즉 기본적인 웹 기반으로 되어 있다는 것이다.
마찬가지로 첨부되어 있는 파일을 여니 생년월일이 비밀번호로 되어 있다는 문구와 함꺠 하나의 페이지가 열렸고 생년월일을 입력하였지만 비밀번호는 맞지 않다는 문구만 볼 수 있었다.

파일이 잘못됬다는 3번의 문의와 다시 만들어 보낸다는 3변의 답장을 받았지만 열수 없다는 반복되는 화면만 보게 되는 상황이 짜증을 불러오고 결국 내가 직접 열기를 시도했고 그 과정을 기록했다.

알아보자

앞서 말한대로 파일은 html 단일 파일로 되어있었다.
헤더부분에는 스타일 스크립트와 자바스크립트 코드들이 있는 것을 볼 수 있었고, 암호화된 코드로 보이는 것은 hidden타입의 input 태그에 담겨져 있다.
열어보면 역시 당연하게도 파일을 열어보면 여타 다른 html와 같은 구조를 가지고 있고, 특징이 있다면 난독화는 되어있지 않고 개행문자 정도만 제거되어 있는 minify 정도만 되어았다는 점이다.
덕분에? 나는 내 월급을 열어볼 수 있었다.

흔하디 흔한 pretty view 사이트를 통해 복호화 코드를 얻을 수 있었다.

암보 비교 구문


  if (Math.abs(pwd << pwd) != unescape('\x31\x37\x34\x34\x38\x33\x30\x34\x36\x34')) {
      alert('비밀번호가 일치하지 않습니다.');
      return;
  }

처음 이 코드를 봤을 때 Math.abs(pwd << pwd) 이 부분이 이해가 잘 안 됬다.
물논 암호를 암호만큼 쉬프트 연산을 한 다음 절대값을 취한 다는 것은 알지만 이것이 무슨 의미를 가지는 지는 모르겠다.
위의 숫자를 다음 1744830464와 비교한다.

unescape(‘\x31\x37\x34\x34\x38\x33\x30\x34\x36\x34’)

난독화도 안해 놓고 이런식으로 넣을 것이라면 왜 escape된 문자열로 넣는지 모르겠다. 이정도로 코드를 뜯어볼 개발자라면 저정도는 해석이 될텐데..
그냥 1744830464를 넣어누지;

Math.abs(pwd « pwd)

거~~~~~~~~~~~대한 비트연산인 만큼 잘려나가는 비트들이 생길테고 마지막에 절대값 처리까지한다.
즉, 연산결과가 1744830464가 나오는 암호값이 유일한 값이 아닐 수 있다고 생각했다.

for(let pwd = 0 ; pwd<999999; pwd++){
  if(Math.abs(pwd << pwd) === 1744830464){
    console.log(pwd)
  }
}

역시 단순 무식하게 돌려보면 비밀번호로 사용 가능한 어마무시한 숫자들이 나오게 된다.

물론 이중에 암호화 정보를 복화화 할 수 있는 키는 하나 뿐이다.

복호화 구문


  var bin = unescape(cliperText).split(',');
  var text = '';
  var strKey = pwd;
  for (var i = 0; i < bin.length; i++) {
      text = text + String.fromCharCode(Number(bin[i]) + strKey.charCodeAt(i % strKey.length));
  }
  document.write(text);

var bin = unescape(cliperText).split(‘,’);

금여명세서 파일에 담겨있는 암호화된 문자열을 대입하여 실행해보면 숫자로된 배열을 얻을 수 있다.

bin = [“3”, “52”, “67”, “59”, “60”, “6”, “3”, “52”, “52”, “47”, “52”, “6”, “-25”, “8”, “67”, “55”, “68”, “52”, “44”, “10”, “9”, “8”, “-16”, “44497”, “49288”, “50616”, …

아래 한줄이 복호화의 모든 과정이 담긴 코드이다.

text = text + String.fromCharCode(Number(bin[i]) + strKey.charCodeAt(i % strKey.length));

눈 여겨 봐야 할 코드는 String.fromCharCode와 charCodeAt 이란 두가지 함수 이다. 두가지 함수는 ascii코드를 문자로, 해당 위치의 문자(char)를 아스키 코드로 변환하여 변환하는 역활을 한다.

위의 코드를 해석하면 이러한 과정을 반복하여 복호화를 한다.

  1. 암호6자리를 순서대로 반복하여 아스키 코드로 변환하여 키값으로 사용한다.
  2. 암호화된 문자열(위의 bin 변수)의 값과 키값을 합친다.
  3. 합친 값을 다시 문자열로 바꿔 저장한다.
  • 끝나게 되면 복호화된 문자열을 document.write(text);를 통하여 화면에 뿌려주게 된다.

해독하기

위의 두가지 과정을 통해 알 수 있었것을 통해 알 수 있는 생각보다 별로 없었다.

암호를 6개의 숫자를 돌아가며 키값으로 쓰고(6개 단위로 반복되는 패턴) 있다는 것이다.

영화 이미테이션 게임에 보면 암호무전에 매번 같은 문자를 시작으로 하는 문자를 보고 암호를 푸는 장면이 나오게 된다. 결과적으로는 나도 그런식으로 암호를 풀게 되었다.

1,2,3월달의 암호를 치고 들어갔을 경우의 값(복호화된 결과값)을 비교했다.
html 문서인 만큼 시작값은 언제나 <html> 이였다.

….. 다 풀없다.

복호화 하였을 경우 처음 6글자가 <html>인 6개의 숫자만 대입하여 찾으면 되는 것이다. 암호가 될수 있는 값들 중에 100000부터 시작했을 경우 처음 후보인 100058일 경우 값은

4dskq>4dd_i>8sgyl....

벌써 하나가 풀리기 시작했다. 처음 6자리가 4dskq> 인것을 봤을 때 <html>을 비교해봤을 때 비밀번호 마지막 자리는 8일 것이다.
몇번 반복하고 난뒤 금방 비밀번호를 알 수 있었고 비밀번호는 941208이였다.

누구냐 넌…

941208로 풀어 보면 예상대로 <html><head> <titl로 시작하는 문자열을 얻을 수 있었고 뒤의 문자도 깔끔하게 복호화 됨을 볼 수 있었다.

남들은 자신의 생년월일 6숫자치고 보는걸 난 본의아니게 이렇게 보게 되었다.
끝.

후기

내 월급 내가 보겠다는게 겁나 힘드네

더 읽어보기 »

[hackerrank solution] Super Reduced String

작성일 2018-01-28 | In hackerrank |

solution

function super_reduced_string (s) {
    // Complete this function
  let chars = s.split('')
  let diff = null
  while (diff !== 0) {
    let beforeLength = chars.length

    let newChars = []
    for (let idx = 0; idx <= chars.length; idx++) {
      if (chars[idx] === chars[idx + 1]) {
        idx++
      } else {
        newChars.push(chars[idx])
      }
    }

    chars = newChars

    let afterLength = chars.length

    diff = beforeLength - afterLength
  }

  return chars.join('') || 'Empty String'
}
더 읽어보기 »

React HOC(High Order Component)

작성일 2018-01-15 | In react |

HOC(High Order Component)

개요

High Order Component의 약자로서 React가 제공해주는 api가 아닌 React를 이용한 응용 기술, 디자인패턴 입니다.
HOC는 React에서 UI Component로서가 아닌 컴포넌트 로직을 재사용하기 위한 컴포넌트 입니다.
즉, 다른 Component취해 새로운 Component를 반환하여 사용하게끔 해줍니다.
React 공식홈페이지에서 가이드를 해줍니다.
이미 react-redux나 react-router를 통하여 알게 모르게 사용되는 기술입니다.

react-redux를 예로 들자면

import react from 'react'
import { connect } from 'react-redux'
// Class Comp extends react.Component {.....

Comp = connect(mapStateToProps, mapDispatchToProps)(Comp)

에서와 같이 Comp에서 react-redux의 cennect란 함수를 이용하여 redux로부터 state를 연결하여 값들을 사용하고 있습니다.

심지어 내부에서 connectHOC란 함수명으로 사용합니다.
return connectHOC(selectorFactory, _extends{methodName: ‘connect’…

이를 응용하면 아래 데이터호출, 인증처리와 같은 비지니스 로직을 분리한다건가, react-redux, react-router와 같이 필요한 값들을 부여하거나 반대로 제한하는 등의 여러가지 일들을 할 수 있습니다.

사용해보기

SPA(Single Page Application)에서는 각각의 페이지를 동적으로 받아 페이지 전환을 하게 됩니다.
페이지마다 title를 바꿔주기위해서

import React, { Component } from 'react'

class Page extends Component {
  componentDidMount(){
      document.title = "PageTitle"
  }

  componentWillDidMount(){
      document.title = "default title"
  }

  render() {
    return <div>페이지 컴포넌트</div>
  }
}

위와 같은 코드들을 페이지로서 사용하는 Component에 작성을 하게 됩니다. 바로 HOC를 만들어 적용하게 되면, title를 작성하기 사용되는 비지니스로직을 분리함과 동시에 중복되는 코드를 줄일 수 있게 됩니다.

import React, { Component } from 'react'

class Page extends Component {
  render() {
    return <div>페이지 컴포넌트</div>
  }
}

function withTitle(title){
  return function(WrappedComponent){
    Class TitleComponent extends Component {
      componentDidMount(){
          document.title = title
      }

      componentWillDidMount(){
          document.title = "default title"
      }

      render(){
        <WrappedComponent {...this.props} />;
      }
    }

    return TitleComponent
  }
}

withTitle(‘PageTitle’)(Page)

위에 작성된 withTitle은 HOC로서 작성되어 받아낸 Component만을 랜더링 함으로서 UI적으로는 영향을 끼치지 않고 title만을 조작하는 로직을 처리합니다.
Page컴포넌트는 title에 대해서는 신경쓰지 않고 랜더링하는 부분만 남게 되었습니다. 이로서 title을 조작하는 로직이 분리 되었습니다.

이와같이 HOC는 AOP스럽게 사용함으로서 코드 재사용성을 늘리고 분리합니다. 이러한 HOC작성 함로서 인증처리와 같은 문제나 로깅등에 대한 것도 분리할수 있게 됩니다.

단점

HOC는 Component를 Component가 감싸는 형식이기 때문에 그에 따른 단점도 생기게 됩니다.
대표적인 문제로

  1. displayName이 덮어씌워지는 문제
  2. refs가 전달이 안되는 문제

위와 같은 문제는 HOC 코드 작성하는 부분에서 극복이 가능합니다. 번거로움 +1

Class TitleComponent extends Component {
  static displayName = `TitleComponent(${getDisplayName(WrappedComponent)})`;
  // ...

남발하게 될 경우 디버깅이 힘들어지는 등의 당연한 문제점들이 발생하게 됩니다.

Etc..

decorator와 같이 사용하게 된다면

@withTItle("PageTitle")
class Page extends Component {
  render() {
    return <div>페이지 컴포넌트</div>
  }
}

이런식으로도 사용가능합니다.

decorator는 es7문법으로서 현재는 babel-plugin-transform-decorators-legacy 플러그인을 설치해야 사용가능하며
babel 7버전부터는 포함되게 된다고 합니다.
사용법은 여기.

참고페이지 여기.

더 읽어보기 »

[hackerrank solution] Day of the Programmer

작성일 2018-01-07 | In hackerrank |

solution

function divisible (i, j) {
  return !(i % j)
}

function solve (year) {
    // Complete this function
  let date = [13, '09', year]

  if (year === 1918) {
    date[0] = 26
  } else if (year > 1918) {
    if (divisible(year, 400) || (divisible(year, 4) && !divisible(year, 100))) {
      date[0]--
    }
  } else if (divisible(year, 4)) {
    date[0]--
  }
  return date.join('.')
}

function main () {
  var year = parseInt(readLine())
  var result = solve(year)
  process.stdout.write('' + result + '\n')
}

더 읽어보기 »

[hackerrank solution] Migratory Birds

작성일 2018-01-07 | In hackerrank |

solution

function migratoryBirds (n, ar) {
    // Complete this function
  let most = 0
  let map = ar.reduce(function (ac, v, index) {
    ac[v]++
    return ac
  }, {
    1: 0, 2: 0, 3: 0, 4: 0, 5: 0
  })

  let resultSet = [5, 4, 3, 2, 1].reduce(function (ac, v, index) {
    if (map[v] >= ac.frequency) {
      ac.result = v
      ac.frequency = map[v]
    }

    return ac
  }, {
    result: 5,
    frequency: map[5]
  })

  return resultSet.result
}

function main () {
  var n = parseInt(readLine())
  ar = readLine().split(' ')
  ar = ar.map(Number)
  var result = migratoryBirds(n, ar)
  process.stdout.write('' + result + '\n')
}
더 읽어보기 »

[hackerrank solution] Divisible Sum Pairs

작성일 2018-01-07 | In hackerrank |

solution

function divisibleSumPairs (n, k, ar) {
    // Complete this function
  let result = 0
  while (ar.length !== 0) {
    let i = ar.shift()
    for (let j of ar) {
      if (!((i + j) % k)) {
        result++
      }
    }
  }

  return result
}

function main () {
  var n_temp = readLine().split(' ')
  var n = parseInt(n_temp[0])
  var k = parseInt(n_temp[1])
  ar = readLine().split(' ')
  ar = ar.map(Number)
  var result = divisibleSumPairs(n, k, ar)
  process.stdout.write('' + result + '\n')
}
더 읽어보기 »

[hackerrank solution] Breaking the Records

작성일 2018-01-01 | In hackerrank |

solution

function breakingRecords (score) {
  let lowest, highest
  let result = [0, 0]
  lowest = highest = score.shift()
  for (let record of score) {
    if (record < lowest) {
      lowest = record
      result[1]++
    } else if (record > highest) {
      highest = record
      result[0]++
    }
  }

  return result
}

function main () {
  var n = parseInt(readLine())
  score = readLine().split(' ')
  score = score.map(Number)
  var result = breakingRecords(score)
  console.log(result.join(' '))
}
더 읽어보기 »

[hackerrank solution] Apple and Orange

작성일 2018-01-01 | In hackerrank |

solution


function appleAndOrange (s, t, a, b, apple, orange) {
    // Complete this function
  let result = [0, 0]
  for (let item1 of apple) {
    let point1 = item1 + a
    if (s <= point1 && point1 <= t) {
      result[0]++
    }
  }

  for (let item2 of orange) {
    let point2 = item2 + b
    if (s <= point2 && point2 <= t) {
      result[1]++
    }
  }

  return result
}

function main () {
  var s_temp = readLine().split(' ')
  var s = parseInt(s_temp[0])
  var t = parseInt(s_temp[1])
  var a_temp = readLine().split(' ')
  var a = parseInt(a_temp[0])
  var b = parseInt(a_temp[1])
  var m_temp = readLine().split(' ')
  var m = parseInt(m_temp[0])
  var n = parseInt(m_temp[1])
  apple = readLine().split(' ')
  apple = apple.map(Number)
  orange = readLine().split(' ')
  orange = orange.map(Number)
  var result = appleAndOrange(s, t, a, b, apple, orange)
  console.log(result.join('\n'))
}
더 읽어보기 »

스크롤 부드럽게 하기

작성일 2017-11-28 | In web |

개요

스크롤

해결방안

-webkit-overflow-scrolling

더 읽어보기 »
1 2 3
ignocide

ignocide

web developr

22 포스트
8 카테고리
11 태그
RSS
© 2018 ignocide
Powered by Jekyll
Theme - NexT.Muse