[React] onKeyDown 이벤트 한글 마지막 글자 한번 더 입력 오류

이미지
  예전에 프로젝트하면서 해쉬태그 관련 컴포넌트를 만들었던적이 있어서 그대로 가져와서 이번 프로젝트에서 사용하려했는데 onKeyPress 이벤트가 Deprecated 되었다고 나와서 MDN 가이드대로 keydown 으로 수정해보았다. 여기서 문제가 발생했는데 onKeyPress 이벤트에서는 아무 문제가 없는데 onKeyDown 이벤트를 사용했을때 동영상에서 처럼 마지막 글자가 한번더 출력되는 문제가 발생했다. 내가 작성한 setState와 관련한 비동기적인 동작 순서를 내가 잘못생각해서 발생되는 문제인줄 알았는데 찾아보니 해당 문제는 크롬 브라우저에서 한글을 입력하는 경우만 해당 문제가 발생하는것을 알게됐다. 키보드 이벤트 발생시 이벤트 핸들러가 두번 호출되는 문제였다. 한글의 경우 자음과 모음의 조합으로 한 음절이 만들어지는 조합 문자이기 때문에 글자가 조합중인지, 조합이 끝난 상태인지를 알 수 없기 때문에 발생하는 문제였다. 해당 문제는 isComposing 이라는 값을 체크해 해결할 수 있었다. 그런데 여기서 또 하나의 문제 event.isComposing 또는 event.target.isComposing을 사용하려고해도 해당 메소드가 없다고 나왔다. 예전에 React 공식 문서에서 브라우저 고유 이벤트가 필요하다면 nativeEvent 어트리뷰트를 참조하라는 글을 본적이 있었다. 아래 링크를 첨부했다. 아래처럼 코드를 작성하면 아래 동영상처럼 해결이 된다. 문제 해결 완료! 참고하면 좋을만한 링크 https://levelup.gitconnected.com/javascript-events-handlers-keyboard-and-load-events-1b3e46a6b0c3 https://ko.reactjs.org/docs/events.html#overview

Nodemailer 설정하기 (보안 수준이 낮은 앱의 액세스 기능 지원 중단)

이미지
개인프로젝트를 진행하면서 사용자 이메일 인증, 임시 비밀번호 발급 등을 위해 Nodemailer 라이브러리를 사용했다.  나의 경우 google Gmail 이메일 계정을 사용하여 Nodemailer를 사용했다. 예전에는 Nodemailer 공식 문서와 같이 코드를 작성하고 구글 계정에서 보안 수준이 낮은 앱의 액세스 기능을 키기만 하면 됐었다. 하지만 정책이 변경되어 다르게 설정이 필요해서 이와 관련해서 작성해보려한다. 1. 자신의 프로필 -> [Google 계정 관리] -> 보안 페이지 -> [Google에 로그인] 중 [2단계 인증]을 클릭 후 자신의 모바일 또는 sms 인증이 가능한 기기를 이용하여 2단계 인증을 완료시킨다. 2. 2단계 인증을 완료하고 바로 아래 앱 비밀번호를 클릭하여 비밀번호를 발급받는다. 해당 비밀번호는 창을 닫으면 다시는 확인할 수 없다. 따로 저장해두거나 새로 발급받아야 한다. 앱 선택은 기타를 선택해도 되고 아무거나 선택해도 된다. 3. 발급받은 번호를 기존의 Nodemailer 설정의 pass에 입력해주면 설정이 끝이난다. 추가적으로 Gmail 고객센터에서 제공하는 문서이다.  * 변경된 정책 확인 https://support.google.com/accounts/answer/6010255?hl=ko * 메일이 스팸으로 분류되는것을 방지하기 https://support.google.com/mail/answer/81126?hl=ko

[TypeORM] database update시 save() 메서드를 사용하면 주의할점

#  Updating in the database Now let's load a single photo from the database, update it and save it: import { Photo } from "./entity/Photo" import { AppDataSource } from "./index" const photoRepository = AppDataSource . getRepository ( Photo ) const photoToUpdate = await photoRepository . findOneBy ( { id : 1 , } ) photoToUpdate . name = "Me, my friends and polar bears" await photoRepository . save ( photoToUpdate ) Now photo with   id = 1   will be updated in the database.   공식 문서를 보면 위와 같이 사용자 정보를 최초로 저장할때가 아닌 업데이트 시에도 사용자 객체를 가져와 참조 값을 변경하고 save() 메서드를 사용해서 사용자 정보를 업데이트하도록 나와있다. 공식문서 첫페이지에 나와있는 방법이기에 그대로 그냥 사용했었다. 그런데 프로젝트 진행중 알 수 없는 문제가 발생했다. 데이터를 업데이트하는데 업데이트 되지않고 값이 추가적으로 insert 되는 상황이 발생했다. MySQL Workbench를 보면 값 업데이트가아닌 추가 되었는데 다시 해당 오류를 재현해보려했지만 동일한 오류를 재현하지 못했다. typeorm 처음 공부할때 공식문서와 여러 블로그를 봤는데 save() 메서드를 주의해서 사용해야 한다는 내용이있었다. 다시 찾아보니 TypeORM에서 save() 메서드는 entity에 작성되어있는 연결되어있는 모든 PK값을 WHERE 절에 함께 담아 SELECT 쿼리를 실행하

error TS2339: Property 'id' does not exist on type 'User'.

이미지
  express.js, passport.js, typescript 를 사용해서 로그인 기능을 구현했다. passport local 로그인 동작 순서는 아래와 같다. passport-local -> passport.authenticate -> local strategy -> req.login -> passport.serializeUser -> response 각 순서에서 작업을 수행하고 각 단계에서 callback 함수와 함께 다음 함수에서 필요한 값을 넘겨주게 된다.  error TS2339: Property 'id' does not exist on type 'User'. 해당 에러는 아래 코드에서 발생되었다. passport . serializeUser (( user , done ) => { done ( null , user . id ); }); 아래 코드처럼 req.login으로 user 정보를 넘겨passport.serializeUser에서 해당 유저 정보를 받는데 return req . login ( user , async ( err ) => { if ( err ) { console . error ( err ); return next ( err ); } if ( typeof user === 'object' && user !== null ) { if ( user ) { return res . status ( 200 ). json ({ success : true , message : 'login success' , user : { email : user . email , nickname : u

[TypeORM] Error during Data Source initialization: DataTypeNotSupportedError: Data type "Object" in "User.google" is not supported by "mysql" database.

이미지
오류 사진 import { Entity , PrimaryGeneratedColumn , Column , OneToMany } from 'typeorm' ; import { Post } from './Post' ; @ Entity () export class User { @ PrimaryGeneratedColumn () id : number ; @ Column ({ unique : true , length : 50 }) email : string ; @ Column ({ unique : true , nullable : true }) google : string | null ; @ Column ({ length : 10 }) nickname : string ; @ Column ({ length : 200 }) password : string ; @ Column () createdAt : Date ; @ OneToMany (() => Post , ( post ) => post . user ) posts : Post []; } - 수정 전 - 구글 로그인으로 가입한 사용자 정보를 받는 컬럼에서 오류가 발생했다. Object 데이터 타입을 받을 수 없다는것인데 찾아보니 유니언 타입(Union type)으로 작성하면 데이터 타입을 Object로 인식하기 때문에 위에서 google: string | null 과 같이 작성하면 안된다고 한다. import { Entity , PrimaryGeneratedColumn , Column , OneToMany } from 'typeorm' ; import { Post } from './Post' ; @ Entity () export class User { @ PrimaryGeneratedColumn () id : number ; @ Column ({

포트(port) 번호 사용방법

TCP/UDP 통신에서는 포트 번호를 이용해서 컴퓨터 안의 어떤 프로그램에게 데이터를 전달할지 식별한다. 포트 번호는 0 ~ 65525까지의 16비트 범위의 숫자로 구성되어 있다. - 포트번호: 0 ~ 1023 잘 알려진 포트(Well-Known Port) 라고 부르며, 웹 서버나 메일 서버 등의 일반적인 프로그램들이 사용한다. 일반적으로 잘 알려진 포트 번호 21/TCP- FTP 22/TCP- SSH 23/TCP- Telnt 25/tcp- SMTP (Simple Mail Transfer Protocol) 53/udp- DNS (Domain Name Syetem) 69/udp- TFTP 80/tcp- HTTP (HyperText Transfer Protocol) - 웹 페이지 전송 110/tcp- POP3 (Post Office Protocol version 3) - 전자우편 가져오기에 사용 161/udp- SNMP (Simple Network Management Protocol) 443/tcp- HTTPS - HTTP over SSL ( 암호화 전송 ) - 포트번호: 1024 ~ 49151 등록된 포트(Registered Port) 라고 부르며, 주로 서버 소켓으로 사용하는 영역이다. - 포트번호: 49152 ~ 65535 동적 포트(Dynamic Port) 라고 부르며, 수시로 변경되는 포트를 의미하며 인터넷이나 시스템에서 사용할 때 동적으로 할당하는 포트를 의미한다.  *동적 포트 영역은 서버 소켓 포트로 사용을 금지한다.

vscode에서 control + space 자동완성 안될때

이미지
vscode에서 코드를 작성할때 자동완성 기능 단축키로 control + space를 사용했는데  맥 초기화 및 업데이트 이후부터 자동완성 기능이 fn + control + space를 눌러야만 동작했다. 사진처럼 vscode에 shortcuts을 확인해봐도 control + space 인데 말이다. vscode trigger suggest 해결 방법은 아래와 같다. 1. Go to system preferences -> keyboard -> input sources 2. add a new input source (I did english ABC)  3. Go to shortcuts tab (inside of keyboard settings) 4. Click on input sources on the left 5. disable the "select previous input source" shortcut 참고자료: https://github.com/microsoft/vscode/issues/103855#issuecomment-671062294  

[React] dangerouslySetInnerHTML 사용하여 문자열 html 출력하기

이미지
태그와 문자열이 함께 저장되어있는 JSON 데이터를 받아와 화면에 출력하려고 했다. HTML 태그와 문자열을 포함하는 json 데이터 컴포넌트에 json 데이터 출력 json 데이터 출력 결과 우리가 상상하는것과 다르게 태그가 문자열 그대로 출력된다. React 공식 문서에 따르면 일반적인 코드에 HTML 코드를 삽입하는것은 Cross-Site Scripting(XSS)에 취약하다고 한다. 사용자가 임의로 웹페이지에 스크립트를 적용할 수 있어 이러한 문제점을 차단하기위해 무조건 텍스트로만 출력되게 설정되어있다고 한다. 그래서 우리가 상상하던데로 출력되지않고 문자열 그대로 태그가 출력 되는것이었다. React 공식 문서에 따르면 DOM에 innerHTML을 사용하려면 즉, 태그를 포함한 문자열 데이터를 태그가 적용되어 출력되게 하기위해서는 대체 방법인 dangerouslySetInnerHTML 을 사용하라고 나와있다. dangerouslySetInnerHTML 속성명을 보면 알 수 있듯이 개발자에게 위험하다는것을 한번더 상기시키기 위해서  dangerously라는 단어가 포함되어있는  dangerouslySetInnerHTML을 사용해서 출력하게 한다는것이다. 사진과 같이 __html을 객체의 키로 전달하고 value값으로 태그가 포함된 문자열 데이터를 전달하면 우리가 상상하던것과 같이 출력된다. dangerouslySetInnerHTML  출력 결과  

웹뷰(WebView) 모바일 가상 키보드 inputmode

이미지
  input 태그에 type 속성과는 별개로 inputmode 속성 값을 작성하면 모바일 웹뷰에서 속성값에 따라 특화된 가상 키보드가 활성화 된다.   none 가상 키보드를 사용하지 않는다. 가상 키보드를 직접 구현하는 경우 사용한다.       text (기본값) 사용자의 현재 위치에 맞는 표준 가상 키보드를 제공한다.       decimal 사용자의 위치에 따라 소숫점( , 또는 . )을 제공하는 숫자형 가상 키보드를 제공한다. 사용자의 장치에 따라 음의 부호( - )를 제공할 수도 있고 안할 수도 있다.     numeric 숫자형 가상 키보드를 제공한다. 소숫점은 없으며 사용자의 장치에 따라 음의 부호( - )를 제공할 수도 있고 안할 수도 있다.   tel 전화번호 가상 키보드를 제공한다. 숫자 0 ~ 9, +, *, # 를 포함한다.    search 검색 입력에 최적화된 가상 키보드를 보여준다. 사용자의 장치에 따라 Enter / 제출 키가 검색 아이콘이나 레이블을 가질 수 있다. email 이메일 입력에 최적화된 가상 키보드를 보여준다. @ 키를 제공한다. url URL 입력에 최적화된 가상 키보드를 제공한다.  / 와 .com 과 같은 키를 제공한다.

VSCode 설정 동기화하기

이미지
예전에 컴퓨터를 새로 구매하면서 VSCode 설정을 동기화 해본 경험이 있다. 하지만 최근 주니어 개발자로 취업하고 회사에서 업무용으로 지급받은 맥에도  VSCode 설정도 동기화 해야했는데 자주하는 경험이 아니다보니 또다시 찾아보게되어 추후에도 쉽게 찾아볼 수 있도록 블로그에 작성하게 되었다. VSCode 설정을 동기화 하는 방법은 2가지가 있다.  1. VSCode에 내장되어있는 Syncs 기능 사용하기 2. VSCode Extensions에 있는 Settings Sync 사용하기 나의 경우 회사에서는 개인적으로 사용하는 계정을 일체 사용하지 않을것이기 때문에 2번 방법을 사용했다. 1번 방법의 경우 동일한 github 계정을 사용해여야 동기화가 가능하다. 1번. Settings Sync 익스텐션 설치하기 https://marketplace.visualstudio.com/items?itemName=Shan.code-settings-sync 2번. Github에서 Personal Access Token 생성하기 Settings -> Developer Settings -> Personal access tokens -> Generate new token -> Note(식별 내용 작성) -> Expriration 설정하기(원하는 만료기간 설정) -> gist 체크 박스 체크 -> Generate token 클릭 주황색으로 가려진 토큰은 복사해서 보관해둬야 한다. 발급된 토큰은 한번만 확인할 수 있다. 새로 고침시 비공개처리 된다. 3번. gist 접속해서 Create sercret gist 생성하기 구글에 gist 글 검색한다. 들어가서 생성버튼을 누르고 제목, 내용? 양식은 없으며 본인이 알아볼 수 있는 식별 내용 작성하고 Create sercret gist 클릭 생성한 gist를 눌러보면 URL Params 끝에 Gist Id 가 작성되어있다.  4번. VScode에서 Shift + Option + U를 눌러 설정 업로드하