반응형
reduce(callbackFn, initialValue)
  • initiallValue없으면? If initialValue is not specified, previousValue is initialized to the first value in the array, and currentValue is initialized to the second value in the array.
  • initialValue없고 대상array내 값이 1개뿐이라면?
    • 뭘해도 [A] -> reduce(...) -> A 형태로 결과가 나옴, 즉 1개 있던 value가 array를 빠져나오게됨

 

reduce((previousValue, currentValue, currentIndex, array) => { /* … */ }, initialValue)
  • previousValue: accumulated values until now
반응형
반응형

frontend

image upload시 서버 전송 하기 전에 frontend 로직진행하는 부분

<input
        accept="image/*"
        id={`input_${type}`}
        type="file"
        className="logo_preview_input"
        onChange={e => {
          if (e.target.files && e.target.files.length >= 1) {
            const reader = new FileReader();
            const img = e.target.files[0];
            reader.readAsDataURL(img);
            reader.onload = e2 => {
              setImg(e2.target.result);
              setImgName(img.name);
            };
          }
        }}
      />
      <label htmlFor={`input_${type}`} className="btn_logo_preview">
        <Button component="span" className="btn_color4">
          Select File
        </Button>
      </label>
      <p className="file_name">{imgName}</p>

 

업로드된 파일을 서버전송할 때 new FormData()를 써서 이안에 image file이랑 다른 string이랑 같이넣어줌

        const bgImg = document.getElementById('input_bg').files[0];//undefined if not uploaded
        //if (!bgImg) alert('Please select a background image file to update !');
        const previewImg = document.getElementById('input_preview').files[0];//undefined if not uploaded
        //if (!previewImg) alert('Please select a preview image file to update !');
        const buttonImg = document.getElementById('input_button').files[0];
        requestBody = new FormData();
        requestBody.append('tabName', content.tabName);
        requestBody.append('tabOrder', content.tabOrder);
        requestBody.append('themeApply', content.themeApply ? 'Y' : 'N');
        if (bgImg) requestBody.append('bgImg', bgImg);
        if (previewImg) requestBody.append('previewImg', previewImg);
        if (buttonImg) requestBody.append('buttonImg', buttonImg);

전송시 header는 보통 multipart/form-data를 사용하는 것 같은데 왜인지 이렇게 보내면 에러가 났고 아예 설정안하고 보내니 정상동작하였음

//const headers = new Headers({ 'Content-Type': 'application/json' });
//const headers = new Headers({ 'Content-Type': 'multipart/form-data' });

backend

  • formData로 보낸 것들도 url?q=형식으로 get으로 보낸것을 받는 것처럼 @RequestParam으로 받음
  • 그 중 이미지는 org.springframework.web.multipart.MultipartFile로 받음
  • 이미지외에 string으로 보낸 것들은 Map<String, Object>로 몽땅 받음
  • 만약 이름은 bgImg, previewImg이렇게 맞춰서 보냈는데 실제로는 파일이 아니라 string을 보내면 null로 받아짐
@PatchMapping("tab_withImg/{tabId}")
  public Tab updateTabWithImg(@CurrentUser UserPrincipal currentUser, @PathVariable String tabId,
      @RequestParam Map<String, Object> data, @RequestParam(required = false) MultipartFile bgImg,
      @RequestParam(required = false) MultipartFile previewImg, @RequestParam(required = false) MultipartFile buttonImg)
      throws Exception {
    logger.info("#updateTab_WithImg|currentUser=" + currentUser.getProvider());
    return homeAppAdminService.updateTab(tabId, data, bgImg, previewImg, buttonImg);
  }

 

  • multipart file을 받아서 로컬내 저장하고 처리하는 부분
  • 일반적으로 File쓰는 방법으로 저장하면 에러가 나서 java.nio.file.Path/Paths 써서 처리했었던듯
import java.io.File;
import java.nio.file.Path;
import java.nio.file.Paths;
import org.springframework.web.multipart.MultipartFile;


  private String uploadFile(String type, MultipartFile multipartFile) throws Exception {
    String uploadDirStr = UPLOAD_DIR == null ? "/engn001/tomcat/8.5/servers/portal_8180/uploads" : UPLOAD_DIR;
    File uploadDir = new File(uploadDirStr);
    if (!uploadDir.exists() && !uploadDir.mkdirs())
      throw new Exception("uploadDir mkdir Fail!");
    File uploadFile = new File(uploadDirStr + "/" + multipartFile.getOriginalFilename());
    if (!uploadFile.getAbsolutePath().equals(uploadFile.getCanonicalPath()))
      throw new Exception("파일경로 및 파일명을 확인하십시오.");

    Path path = Paths.get(uploadDirStr + "/" + multipartFile.getOriginalFilename()).toAbsolutePath();
    multipartFile.transferTo(path.toFile());
    // multipartFile.transferTo(uploadFile);//file not found error
    String resultGftsUrl = uploadGfts(type, "KIC", uploadFile);
    uploadGfts(type, "AIC", uploadFile);
    uploadGfts(type, "EIC", uploadFile);
    uploadFile.delete();
    return resultGftsUrl.replaceFirst("http://kic-", "");
  }

 

반응형
반응형

[a tag]

<a href={questionModalSrc} download="88a2f203a144c233726b8ffcdccc9ed8.png">

href 주소의 Type이 이미지나 파일이어야만 다운로드가능,

  • download='img.png'에서 img.png는 변경가능
  • 확장자 안쓰면 알아서 다운로드시 Type에 해당하는 확장자 붙여줌,
  • img.htm이런식으로 확장자 잘못 붙여도 다운로드 가능

 

 <a href={`/board/viewimage?file=${encodeURIComponent(questionModalSrc)}`}>

Type이 document (html문서)라면 다운로드 에러남
href가 file Type이 아니면 이런식으로 다운로드 에러남, 이 때 img.htm의 확장자 htm은 저절로 알아서 붙은것

 

 

 

 

 

[모든 element에 적용가능한 방법] 클릭시 임시로 a tag생성하고 클릭되도록

onClick={() => { const link = document.createElement('a');  
                link.href = \`/common/files/01. CDP Admin Operation Policy.docx\`;  
                link.target = '\_blank';//링크클릭시 새창에서 열도록, 링크여는목적 아니므로 없어도 될듯  
                link.download = '다운로드될 파일명'; 이 부분이 없으면 자동다운로드 안됨
                document.body.appendChild(link);  
                link.click();  
                document.body.removeChild(link);  
              }}

 

 

 

 

 

외부에 있는 자원을 다운로드

API 구현부분

  • 테스트해보니 요청하는 헤더내의 content_type: application/json이지만 응답헤더의 Content-Type: application/octet-stream
    Content-Disposition: attachement; filename="RBSPOT.json"로 응답함
  • 참고로 다른 요청->응답은 아래와 같았음
    • 일반적인 json Fetch/XHR request -> response
      • content-type: application/json -> Content-Type: application/json;charset=UTF-8
    • 파일을 자동으로 다운로드되도록 하는 request -> response
      • content-type: application/json -> Content-Type: application/octet-stream
        Content-Disposition: attachement; filename="RBSPOT.json"
    • 파일을 서버로 업로드하는 request -> response
      • Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryCr6S7zpBWkWbkGAB ->
@Description("MetaDataFile Download from Admin.")
@GetMapping
@PreAuthorize("hasRole('ADMIN')")
@RequestMapping("/api/admin/apiCallLog/{apiCallLogId}/file")
public ResponseEntity<?> getMetaDataFile(@CurrentUser UserPrincipal currentUser,
    @PathVariable Long apiCallLogId) {

  Map<String, Object> resultMap = new HashMap<String, Object>();
  URL url = new URL(...어찌어찌해서 얻어옴);
  InputStreamResource resource = new InputStreamResource(url.openStream());
  resultMap.put("fileName", apiCallInfo.getFileName());
  resultMap.put("resource", resource);

  return ResponseEntity.ok().contentType(MediaType.parseMediaType("application/octet-stream"))
      .header(HttpHeaders.CONTENT_DISPOSITION,
          "attachement; filename=\"" + resultMap.get("fileName") + "\"")
      .body(resultMap.get("resource"));
}

구현된 API call하는 부분

export async function getFileDownload(requestPath, requestMethod, rowData) {
  await fetch(API_BASE_URL + requestPath, {
    method: 'GET',
    headers: getHeaders(),
  })
    .then(response => {
      return response.blob();
    })
    .then(blob => {
      const url = window.URL.createObjectURL(
        new Blob([blob]),
      );
      const link = document.createElement('a');
      link.href = url;
      link.setAttribute(
        'download',
        rowData.fileName,
      );//filename to be downloaded, it can be used as link.download=fileName
      //link.style='display:none'; //OK it is not given
      document.body.appendChild(link);
      link.click();
      link.parentNode.removeChild(link);
    })
    .catch(err => {
      alert('error')
    });
}

서버 내부 자원(public공간내 file) 다운로드

<button
                  type="button"
                  className="quick_link link1"
                  onClick={() => {
                    const link = document.createElement('a');
                    link.href = `/common/files/01. CDP Admin Operation Policy_(ENG)20210428.docx`;
                    link.target = '_blank';
                    link.download = '01. CDP Admin Operation Policy_(ENG)20210428.docx';
                    document.body.appendChild(link);
                    link.click();
                    document.body.removeChild(link);
                  }}>

서버응답을 받아 파일을 내려주거나 내부소스 파일을 내려주거나 다운로드 하는 부분의 공통점

const link = document.createElement('a');
link.href = `/common/files/01. CDP Admin Operation Policy_(ENG)20210428.docx`;//여기에서 차이남
//link.target = '_blank'; //없어도됨
link.download = '01. CDP Admin Operation Policy_(ENG)20210428.docx'; //link.setAttribute('download', 파일명)과 동일
document.body.appendChild(link);
link.click();
document.body.removeChild(link);//link.remove(); link.parentNode.removeChild(link);와 동일

서버응답을 받아 파일생성하는 부분

new Blob([arrayContetns], options) options는 생략가능

new Blob([response], {type" res.headers[content-type]})

Blob을 URL로 변환

window.URL.createObjectURL(blob)

URL.revokeObjectURL( window.URL.createObjectURL(blob) ) 여기서 window.URL=URL인듯

반응형
반응형
반응형
반응형
import useMediaQuery from '@material-ui/core/useMediaQuery';
const isMobile = useMediaQuery(theme.breakpoints.down('sm'));
반응형
반응형

클립보드 붙여넣기까지만 됨

  • [print screen]: 전체화면
  • [alt] + [print screen]: 선택한 창만
  • [window] + [shift] + [s]: 영역선택하면 복사됨

 

PrtScn 버튼만으로 화면캡처 크기를 조절하려면

[window]버튼클릭 > 설정버튼 클릭 > 접근성 > 상호작용 > 키보드 > [PrtScn 단추를 사용하여 화면 캡처 열기] 설정

 

붙여넣기 한 클립보드 확인

  • [window] + [v] 클릭하면 저장된 클립보드중 선택해서 사용가능

 

chrome debug tool 사용: 이미지가 저절로 저장됨

ctrl + shift + p : run command 나오면 capture로 search

  • capture area screenshot: 원하는 영역을 선택하면 자동다운로드됨
  • capture full size screenshot: scroll까지포함해서 전체다 자동다운로드됨
  • capture node screenshot: html문서에서 선택한 부분만 자동다운로드됨
  • capture screenshot: 딱 현재 화면만 자동다운로드됨

-> 단점은 브라우저 내부영역만 가능, 주소창(혹은 주소표시줄, addressBar), bookmarkBar등은 포함못함

반응형
반응형

an XML-based markup language for describing two-dimensional based vector graphics

반응형
반응형

 

https://marketing.istockphoto.com/blog/aspect-ratio/

 

What Are Common Aspect Ratios for Images?

Learn what at aspect ratio is, why it's important, and how to find the right aspect ratio for Facebook, Instagram, Snapchat, and YouTube, and other design projects.

marketing.istockphoto.com

 

Here are some common digital image sizes and their corresponding aspect ratios.

  • 1080 x 1080 pixels = 1:1 aspect ratio
  • 1080 x 720 pixels = 3:2 aspect ratio
  • 1024 x 768 pixels = 4:3 aspect ratio
  • 1920 x 1080 pixels = 16:9 aspect ratio
반응형
반응형

 

CSV는 결국 delimeter로 구분된 string

 

const Papa = require('papaparse/papaparse.min.js');

Papa.unparse(내용에 들어갈 array-[{a,b},{a2,b2},...]);

let blob = new Blob(['\ufeff' + bodyData]), url = window.URL.createObjectURL(blob);
let a = document.createElement('a');
document.body.appendChild(a);
a.style = 'display: none';
a.href = url;
a.download = 'exportEventLogs.csv';
a.click();
window.URL.revokeObjectURL(url);//revokeObjectURL: URL.createObjectURL()로 생성한 객체 URL해제
//참고로 revoke는 re + voke(vocal 과 같은 어원, 부르다) 다시 불러들이다 -> 취소/해제하다

let blob = new Blob(['\ufeff' + csvData]),

여기서 \ufeff 붙이는 이유는? 

  • /ufeff는 해당 file이 어떤 문자열로 코딩되었는지를 의미하는 일종의 식별자입니다. “이 문서의 인코딩 방식은 뭐에요”라는 걸 알려주는 메타 정보인 것이죠. 보통 이러한 방식은 해당 파일의 맨 앞에 집어넣곤 합니다.
  • --> 이런걸 unicode BOM(Byte Order Mark)라고 하나봄

https://frhyme.github.io/python-basic/py_eff_byte_order_mark/

 

python에서 \ufeff가 읽힐 때 해결방법.

1-line summary

frhyme.github.io

 

BOM이란 문서 맨 앞에 눈에 보이지 않는 특정 바이트(byte)를 넣은 다음 이것을 해석해서 정확히 어떤 인코딩 방식이 사용되었는지 알아내는 방법을 나타냅니다. 자세하게 유니코드가 little-endian 인지 big-endian 인지 아니면 UTF-8 인지 쉽게 알 수 있도록, 유니코드 파일이 시작되는 첫부분에 보이지 않게, 2~3바이트의 문자열을 추가하는데 이것을 BOM이라고 합니다. BOM은 텍스트 에디터 화면에서는 보이지 않고, 헥사 에디터(Hex Editor)*로 열었을 때만 보입니다.

https://brownbears.tistory.com/124

 

유니코드 BOM(Byte Order Mark)

BOM이란 BOM이란 문서 맨 앞에 눈에 보이지 않는 특정 바이트(byte)를 넣은 다음 이것을 해석해서 정확히 어떤 인코딩 방식이 사용되었는지 알아내는 방법을 나타냅니다. 자세하게 유니코드가 litt

brownbears.tistory.com

 

 


function extractBodyFieldKey(body, timeType, intl) {
 let addUpDay = body.reduce( (acc, cur) => {
  return acc.concat(cur);
 });
 addUpDay = sortByTimestamp(addUpDay);
 return Papa.unparse(addUpDay.map(log => {
  let eventTime = getTimeZoneTime(log, timeType);
  let event =  intl.formatMessage({id:  util.eventLogMessageByCode(log.code)});
  let userId = log.userKey;
  let userName = log.userName;
  let deviceDisplayName = log.deviceName;
  return {eventTime, event, userId, userName, deviceDisplayName}
 }))
}

[07-22 오전 11:30] 구본관: 저희 모카키도 그렇고 에어팝 포털도 그렇고 CSV 내보내기 할 때 대량으로 생성하게 되면 block 걸리는 경우가 발생합니다. 위에 이번에 변경된 UI도 파일작업을 할 때 동작을 멈추게 됩니다. addUpDay.map 이나 Papa.unparse 부분에서 시간이 굉장히 오래 걸리게 되는데 이때 렌더링이 멈추게 됩니다 대량으로 데이터를 처리할때는 비동기 방식으로 처리할 필요가 있습니다. 저희가 사용하는 papaparse 라이브러리를 보면 step 이나 chunk 같은 옵션들이 있습니다. 이번에 수정하려고 하는 것은 아니고 추후 개발에 참고하시면 좋겠습니다

-> 시간이 오래 걸려서 렌더링 멈춤? 상관없고 대량 데이터를 array로 한번에 처리해서 outOfMemory날뿐, 잘라서 처리해주면됨

 

반응형

'js' 카테고리의 다른 글

Difference between fetch, ajax, and xhr  (0) 2024.01.19
변수의 true/false를 이용한 react 조건부 rendering (0 error case)  (0) 2022.08.31
개발환경에 따른 console.log 분리  (0) 2022.08.17
js array 중복제거  (0) 2022.08.08
moment  (0) 2022.07.25
반응형

.env.[localhost|development|production] 파일로 분리되어 각각의 파일안에 정의하고

REACT_APP_SERVER_LOCATION="DEV"

package.json에서 --config webpack.[localhost|development|production].js 를 설정하면

{
  "name": "asc_portal",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "start:webapp:local": "curl -X POST localhost:8090/language/info > src/language.json | npx --max_old_space_size=4096 webpack serve --mode development --env PRODUCT=portal TITLE=\"# LOCAL\" --config webpack.localhost.js",
    "build:webapp:development": "curl -X POST https://csportaltest.lge.com/api/language/info > src/language.json | npx webpack --mode development --env PRODUCT=portal TITLE=\"# DEV\" --config webpack.development.js",
    "build:webapp:production": "curl -X POST https://csportaltest.lge.com/api/language/info > src/language.json | npx webpack --mode production --env PRODUCT=portal TITLE=\"LG CS Portal\" --config webpack.production.js",
    "start": "react-scripts start",
    "build": "npx webpack --mode production --env PRODUCT=portal TITLE=\"LG CS Portal\" --config webpack.production.js",
    "build:dev": "env-cmd -f .env.test react-scripts build",
    "build:2nd": "env-cmd -f .env.test.2nd react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },

.env.[개발환경]안에 정의한 변수명 process.env.REACT_APP_SERVER_LOCATION 으로 사용가능


[mocaKey] package.json안에서 set REACT_APP_VERSION=dev 지정하면 process.env.REACT_APP_VERSION변수로 사용

"scripts": {
  "start": "set HTTPS=true&&react-scripts start",
  "start:beta": "set HTTPS=true&&set REACT_APP_VERSION=beta&&react-scripts start",
  "start:dev": "set HTTPS=true&&set REACT_APP_VERSION=dev&&react-scripts start",
  "hot": "react-app-rewired start",
  "build": "react-scripts build",
  "build:beta": "set REACT_APP_VERSION=beta&&react-scripts build",
  "build:dev": "set REACT_APP_VERSION=dev&&react-scripts build",
  "test": "react-scripts test --watchAll=false",
  "test:verbose": "react-scripts test --verbose",
  "test:report": "react-scripts test --verbose 2> report.txt",
  "test:coverage": "react-scripts test --coverage --watchAll=false",
  "eject": "react-scripts eject",
  "cypress:open": "cypress open",
  "cypress": "cypress run --browser=chrome",
  "cypress:test": "set START_SERVER_AND_TEST_INSECURE=1&&start-server-and-test start:dev https-get://localhost:3000 cypress"
},
let LEVEL = process.env.REACT_APP_VERSION;
LEVEL = LEVEL || dev;

if (LEVEL !== dev) {
  console.log = function() {};
  console.warn = function() {};
  console.debug = function() {};
}

 

반응형
반응형
  • ES6
    • Set (가장 빠름)
      • [...new Set(arr)]
      • Array.from( new Set(arr) )
    • filter
      • arr.filter( (item,idx)=>arr.indexOf(item) === idx )
    • reduce
      • arr.reduce( (acc,curr)=>acc.includes(curr)? acc : [...acc,curr], [] )

https://dongmin-jang.medium.com/javascript-array-%EC%A4%91%EB%B3%B5-%EC%A0%9C%EA%B1%B0%ED%95%98%EB%8A%94-%EB%B0%A9%EB%B2%95-es6-b5b9075361f9

  •  ES 6사용못할때
    • reduce, indexOf사용
      • arr.reduce(function(acc,curr,index){
            acc.indexOf(curr) > -1 ? acc : acc.push(curr);
            return acc;
        },[]);
    • filter, indexOf사용
      • arr.filter(function(a, i, self){
        	return self.indexOf(a) === i;
        });
반응형
반응형

반응형
반응형
  • display: block, 설정안하면 width는 부모로부터 받은 넓이를 다 사용, height는 자식꺼(height:100%일때)? 
    • full width available -> stretches out to the left & right as far as it can
    • starts on a new line -> vertical, 시작지점은 바로 앞 형제가 끝나고 바로 시작, 형제 안에 자식이 길거나 해도 무시함
      <div style="height:100px;">
      	<div style="height:500px;">
          </div>
      </div>
      <div>... -> 100px 끝나고 시작, 내부 자식이 500px짜리 있지만 무시함​​
       
    • example
      • <div>
      • <p> paragraph
      • <h1>~<h6> heading
      • <form>
      • <ol> ordered list
      • <ul> unordered list
      • <header><main><nav><footer>
      • <table>
  • display: inline, width/height설정할수 없고 설정해도 효과없음, color/fontweight등은 설정가능
    • for text
    • horizontal
    • example
      • <span>
      • <a>
      • <img>
      • <button>
      • <input>
      • ...
  • display: inline-block, inline이지만 width/height만 설정가능
  • display: table
  • display:flex

 

block level element와 inline level element의 차이에 대해 설명되어 있음

https://inpa.tistory.com/entry/HTML-%F0%9F%93%9A-p-div-span-%ED%83%9C%EA%B7%B8-%EC%A0%95%EB%A6%AC

 

🏷️ 비슷해 보이는 <p> <div> <span> 태그 차이점

태그 ​ ​ : div 태그는 body 문서 안에서 각 영역의 세션을 구분 정의 한다. : 구역을 나누는 태그. 가로줄 전체를 다 차지. 너비가 100% Layout 구조 틀을 만들고 CSS를 통해 위치 및 layer을 구분등 HTML

inpa.tistory.com

 

 

반응형
반응형
  • visible
    • default, not clipped(안 자르고 다 보여줌)
  • hidden
    • clipped - 넘치는 부분 잘라냄
    • 내부에 있는 애들이 빠져나가지 못하게 가둠(자기 자신이 더 커짐으로 해서라도)
  • scroll
    • clipped
    • 넘치지 않아도 scroll이 기본으로 생김 (넘치치 않으면 위 아래로 이동은 안되고 자리만 차지하는 scroll생김)
  • auto
    • clipped
    • scroll과 비슷하지만 넘치지 않으면 scroll없고 넘칠때만 생성
    • 만약 height가 고정이 아니라면 scroll생성안해도 되도록 height를 자동으로 늘이는듯(최대한 scroll없이 해결하고 정 안되면 scroll)

 

overflow-x, overflow-y로 방향지정 가능

 

반응형
반응형

<input> width:0으로 해도 변화가 없음 -> <input>의 기본 display:inline이라서 그런줄 알았으나 display:block이었음 -> input의 부모가 display:flex이고 선택된 tab들을 flex형태로 보여주는 데 이 경우 뭔가 제약이 있는 것 같음

반응형
반응형

TextField

Select

Autocomplete

Input

OutlinedInput

반응형
반응형

react node

<FormattedMessage> 사용하려면 IntlProvider를 윗단에서 아래와 같이 제공해줘야 함

import { IntlProvider } from "react-intl";
import enUsMsg from "./lang/en-US.json";
import koMsg from "./lang/ko.json";
import Page from "./Page";

const locale = localStorage.getItem("locale") ?? "ko";
const messages = { "en-US": enUsMsg, ko: koMsg }[locale];

function App() {
  return (
    <IntlProvider locale={locale} messages={messages}>
      <Page />
    </IntlProvider>
  );
}
import { FormattedMessage } from 'react-intl';

<FormattedMessage id={'user.table.tool.total'}/> //총 사용자 : {total}
<FormattedMessage id={'user.table.tool.total'} values={{total: 1000}}/> //총 사용자 : 1000, values는 넘겨주는 변수지정
<FormattedMessage id={'user.table.tool.total'} defaultMessage='notFound' /> //id에 해당하는 번역어 없을때, defaultMessage나옴 defaultMessage없으면 id가 나옴

ui에 나타날때  padding 위아래 10 차지함 

String

String으로 쓰려면 useIntl이나 ingetIntl로 intl객체를 props로 받아와서 intl.formatMessage({id:...}) 형태로 사용해야함

import {injectIntl} from "react-intl";

const title = intl.formatMessage({id: 'index.portal.title'});

export injectIntl(...);
반응형
반응형

포커스 안가지만 커서가져가면 (/)표시나오지는 않고 회색-점선라인이 되지 않음 - 딱보면 비활성회된지 모르고 커서가져가야 할수 있음

<input readOnly={true} 작동함(포커스불가)O

<input readOnly='true'  작동함(포커스불가)O

<input readOnly='false'  작동함(포커스불가)O

<input readOnly  작동안함X -> 다시해보니 작동하는듯, 그리고 readonly가 맞는듯

포커스 안가고 커서가져가면 (/)표시나오고 회색-점선라인이 됨 - 딱봐도 비활성화되보임

<input disabled 작동함(포커스불가, 비활성화)O

<input disabled='true' 작동함(포커스불가, 비활성화)O

<input disabled='false' 작동함(포커스불가, 비활성화)O

 

 

 

document.getElementById('control_EMAIL').readOnly = true;//(o) 대소문자 주의
document.getElementById('control_EMAIL').readonly = true;//(x) 대소문자 주의


document.getElementById('control_EMAIL').setAttribute('readonly') //소문자는 setAttribute로 하니까 됨

 

.print {
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  user-select: none;      // 테스트 안해봐서 모름    
}

 

반응형
반응형

moment -> string

console.log('st 1642820725061?',moment(1642820725061).format("MM/DD hh:mm"));
반응형
반응형

npm install

npm uninstall

npm list: 설치된 패키지 목록 확인하기

-g global

--depth 0 옵션을 사용하지 않으면 전체 트리구조로 의존성 있는 모든 모듈이 나옴

npm WARN config global `--global`, `--local` are deprecated. Use `--location=global` instead.

 npm install material-table@1.X

 

  • npm install --save-dev --save-exact prettier
  • npm install --global prettier

npm install --save-dev redux-devtools-extension

 

 

반응형

'js > node, npm' 카테고리의 다른 글

nodejs를 이용한 mock server 구성  (0) 2022.06.14
반응형

git 사용법 알아내기 - git help [알고싶은 명령어]

반응형
반응형

mergeCommit을 revert했더니 에러가 나면서 안됨 (error: commit 247ce0130b0aab7c244e7dcecc7be0fc57083bbe is a merge but no -m option was given.)

-m 옵션을 붙이라는 것 같아서 붙여서 했는데 그래도 안됨.. (error: option `mainline' expects a number greater than zero)

 

왜 에러가 나냐면 어느 부모로 돌아갈지 옵션을 붙여주지 않았기 때문, merge하는 것 자체가 부모가 2개인건데 둘중 어느 부모로 돌아갈지를 지정해줘야함

 

git revert HEAD -m 1 첫번째 부모로 돌아감

git revert HEAD -m 2 두번째 부모로 돌아감

 

첫번째 부모/두번째 부모가 뭔지 알아내는 방법: git cat-file -p [commitHash]

 

 

반응형
반응형
  • commit message로 검색
    • git log --grep='searchKeyword'
    • 만약 검색결과가 많아서 한 화면에 너무 많이 나온다면 --oneline을 붙여서 한줄씩만 보자
      • git log --grep='searchKeyword' --oneline
  • commit번호 (commitHash, commitID)를 알고 있다면
    • git show commitHash

 

반응형
반응형
  intelliJ/webStorm eclipse
특정line으로 이동 ctrl + g ctrl + l
찾은다음 바꾸기 ctrl + r  
찾기 ctrl + shift + f  
패턴으로 찾기?    
소스찾기 shift + shift  
optimize import ctrl + alt + o  
Settings/Preferences  바로가기 ctrl + alt + s  
reformat ctrl + alt + l  

prettier적용하려면 webStorm plugin에서 설치하거나, node로 설치하거나 둘 중 하나만 하면 되는듯

적용방법: Settings(ctrl+alt+s) -> prettier검색 -> check Box로 설정

모든 소스 한번에 적용하려면 디렉토리로 가서 ctrl + alt + l

https://www.jetbrains.com/help/webstorm/prettier.html#ws_prettier_install

반응형
반응형

 

material UI에서는 disabled 속성을 주면 됨

  • <Button disabled>
  • <Checkbox disabled>
  • <Switch disabled>
  • <Slider diabled>
  • ...

div를 포함한 하위 component를 모두 막고 싶은 경우

  • </div style={this.props.disable?{color:'#777777', pointerevents: 'none'}:{}}>

 

 

반응형
반응형

한글의 인코딩

  • 조합형
    • 초성, 중성, 종성의 조합으로 표현
    • 다른 문자체계들과 호환안되는 단점
  • 완성형
    • 한글자를 독립적으로 보고 각 글자에 코드를 부여
    • 조합형의 단점때문에 완성형이 표준으로 채택
    • EUC-KR
      • KS C 5601(완성형, 이후 KS X 1001로 개칭됨)이라는 코드에 기반함
      • 사용빈도가 높은 2350자만 지원해서 한계가 있음
    • CP(Code Page) 949
      • 한국어판 Microsoft Windows의 기본 코드 페이지로 EUC-KR의 2350 + 8822자를 더 추가함
      • 통합완성형, 확장완성형, MS에서 개발했기 때문에 ms949, windows-949등으로도 불림
    • unicode
      • unicode1.0
        • KS C 5601에 포함된 완성형 2,350자 한글을 지원
      • unicode 1.1
        • KS C 5657(이후 KS X 1002)에 포함된 1,930자 및 중국에서 요청한 6글자를 포함한 2,376자를 추가해 총 6,656자가 수록
        • 한 번에 일괄적으로 추가되지 않았고 빠진 글자들이 단계별로 추가되었기 때문에 배열 순서가 엉망이고 지원하는 플랫폼도 별로 없어 잘 사용되지 못함
      • unicode2.0
        • 완성형 11,172자(가, 각, 갂, 갃, …, 힠, 힡, 힢, 힣)와 조합형 한글 낱자가 모두 수록되어 있어 현대 한글과 옛한글 모두 완벽하게 표현가능
        • 기존1.1에 있던 한글을 삭제후,가나다순으로 새 영역에 배당, but 한글 재배당 때문에 unicode 1과 2는 호환이 안됨

unicode

  • 전 세계의 모든 문자를 다루도록 설계된 표준 문자 전산 처리 방식
  • 유니코드 문자의 경우 해당 글자의 코드를 표기할 때 U+(16진수 숫자, 주로 4자리)라고 쓴다. 예를 들면 한글 '가' 자는 유니코드에서 16진수로 AC00(10진수의 44032)라는 코드 넘버를 가지는데, 이것을 U+AC00이라고 적음

unicode의 encoding

  • 유니코드는 각 글자에 숫자를 배당하는 방식, 규격이고 인코딩은 유니코드 숫자를 저장하는 방식, 표현
  • UTF-8
    • 가장 많이 사용되는 가변 길이 유니코드 인코딩
    • https://namu.wiki/w/UTF-8
    • UTF-8로 표현 가능한 길이는 최대 6바이트지만 다른 인코딩과의 호환을 위해 4바이트까지만 사용한다. 그래서 한 글자가 1~4바이트 중 하나로 인코딩될 수 있으며, 1바이트 영역은 아스키 코드와 하위 호환성을 가진다. 아스키 코드의 0~127까지는 UTF-8로 완전히 동일하게 기록된다. 어차피 유니코드는 U+10FFFF까지만(10진법으로는 1,114,111) 이용하는데, UTF-8은 아래에 나와 있듯이 가변 바이트 길이를 선언하기 위해 꽤 많은 비트를 잡아먹고도 2,097,151까지 인코딩할 수 있기 때문에 4바이트만으로도 충분하고도 남는다.
 

UTF-8 - 나무위키

이 저작물은 CC BY-NC-SA 2.0 KR에 따라 이용할 수 있습니다. (단, 라이선스가 명시된 일부 문서 및 삽화 제외) 기여하신 문서의 저작권은 각 기여자에게 있으며, 각 기여자는 기여하신 부분의 저작권

namu.wiki

 

반응형

'etc' 카테고리의 다른 글

504 gateway time-out 에러 해결방법  (0) 2022.09.08
proxy/reverse proxy, web server, load balancer 개념  (0) 2022.09.08
app-ads.txt  (0) 2022.05.04
헷갈리는 것들  (0) 2019.03.15
Web Application Architecture 교육 (2019/03/11~03/15)  (0) 2019.03.11
반응형

 

  • array===[] (X)
  • array && array.length===0 (O)
  • array && !array.length (O)

 

반응형
반응형

Autocomplete 개념정리

  • options: input화면 클릭하여 나오는, 선택가능한 dropdown list들에 보여주기 위한 array
  • value: options중에서 선택된 값, multiple일 경우에는 array가 됨
  • tag: 선택된 value가 input란에 이미 선택되었음을 보여주는 것...? multiple일 때 의미가 있을 듯
import Autocomplete from '@material-ui/lab/Autocomplete';//mui 4.x버젼에는 lab에포함됨
import Autocomplete from '@mui/material/Autocomplete';//mui 5.x버젼이후에는 정식포함됨

<Autocomplete
    multiple
    open={open}//항상 false로 하면  생략된 tags는 펼쳐지고 dropdownOptionMenu나오는것만 방지할 수 있음,
    disabled={disabled}
    limitTags={1}//limit the number of displayed options when not focused
    id="searchAndMultiSelect"
    options={this.props.options||[]}//display될 option array
    value={this.props.value}//option중에 선택된 value
    disableCloseOnSelect//option에 focus가는동안은 선택했더라도 close하지않고 계속option노출하기
    onChange={(e,v)=>{this.props.onChange(e,v,this.props.selectType);}}//select할때마다 호출됨, dropdownOption에서 클릭안하고 선택된 tab의 X(delete)버튼이나 전체 X(delete)버튼 클릭시에도 호출됨
    getOptionLabel={(option) => this.props.getOptionLabel(option, this.props.selectType)}//option array에서 노출할 속성지정, renderOption주더라도 없으면에러남
    getOptionDisabled={(option) => this.props.getOptionDisabled(option)}//어떤 option을 선택못하게 할 것인지
    noOptionsText={intl.formatMessage({id: noOptionsText})}//장치가 존재하지 않습니다
    getOptionSelected={(option, value) => option.id ? option.id === value.id : option===value}//option에서 value를 뽑아내어 selected:true/false를 결정할 때 어떤 기준으로 결정할지
    renderInput={(params) =>
        <TextField
            className={classes.textField}
            { ...params }
            //placeholder={isEmpty(value) ? intl.formatMessage({id: placeholder}) : undefined}
            onFocus={() => this.handleFocus()}
            onBlur={() => this.handleBlur()}
            label={this.props.selectType&&intl.formatMessage({id: this.props.selectType})}
        />
    }
    renderOption={(option, {selected}) => {
        //2nd argument is {selected:true/false, inputValue:''}
        return this.props.renderOption(option, {selected}, this.props.selectType);
    }}
    //renderTags={(tagValue, getTagProps) =>tagValue.map((option, index) => (//Input에 선택된 tag를 보여주는 형태결정
    //         <Chip key={index} label={option.name||option.deviceGroupName}
	//             {...getTagProps({ index })} disabled={disabled} />// Set disable explicitly after getTagProps
    //filterOptions={fieldTypeList => fieldTypeList.filter(opt => opt.fieldType)}//option에서 filter된것만 노출함, 모두filtering해도 noOptions항목노출됨
    //onOpen = {()=>{}}//selector click해서 열렸을때 동작정의
    //readOnly //작동안함, 4.x버전에서는 안되는듯
    
/>
반응형
반응형
axios
fetch


써드파티 라이브러리로 설치가 필요
현대 브라우저에 빌트인이라 설치 필요 없음


XSRF 보호를 해준다.
별도 보호 없음


data 속성을 사용
body 속성을 사용


data는 object를 포함한다
body는 문자열화 되어있다


status가 200이고 statusText가 ‘OK’이면 성공이다
응답객체가 ok 속성을 포함하면 성공이다


자동으로 JSON데이터 형식으로 변환된다
.json()메서드를 사용해야 한다.


요청을 취소할 수 있고 타임아웃을 걸 수 있다.
해당 기능 존재 하지않음


HTTP 요청을 가로챌수 있음
기본적으로 제공하지 않음


download진행에 대해 기본적인 지원을 함
지원하지 않음


좀더 많은 브라우저에 지원됨
Chrome 42+, Firefox 39+, Edge 14+, and Safari 10.1+이상에 지원

출처: https://inpa.tistory.com/entry/AXIOS-📚-설치-사용#axios란 [👨‍💻 Dev Scroll:티스토리]

반응형
반응형

범용적인 목적으로 js를 사용하기 위한 선결조건: 모듈화

  • CommonJS
    • 브라우저 이외의 곳에서 JS를 사용하기 위한 모듈 시스템
    • 노드에서 많이 사용됨
    • CommonJS의 Common은 js를 브라우저만이 아닌 일반적인 범용언어로 사용살 수 있게 하겠다는 것
    • 필요한 파일이 모두 로컬디스크게 있어 바로 불러쓸 수 있는 상황 즉 서버사이드에서는 CommonJS가 AMD방식보다 간결함
  • AMD(Asynchronous Module Definition)
    • ES6가 나오기 전에 많이 사용됨
    • 주요특징
      • 모듈(자바스크립트)의 비동기 로딩 (html에서 script태그를 통해서 관리하는게 아닌 js로 script태그를 append하여서 로딩함
      • 클로저를 통한 전역관리
      • CommonJS에 비해 사용법 간단
    • AMD방식을 사용하는 대표적인 오픈소스가 RequireJS
    • 필요한 파일을 네트워크를 통해 내려받아야 하는 브라우저와 같은 환경에서는 AMD가 CommonJS보다 더 유연한 방법을 제공
  • ES6(2015)
    • 브라우저(frontend)에서는 요즘 거의 이것 사용
    • 그대로 쓰기보다 webpack/rollup 같은 번들러를 통해서 많이 사용됨

 

참고자료

https://isa-dev.tistory.com/217?category=994397

https://d2.naver.com/helloworld/12864

반응형

+ Recent posts