★ 프리티어
- printWidth - 줄 바꿈 할 폭 길이 / tabWidth - 탭 너비 / singleQuote - single 쿼테이션 사용 여부 / trailingComma - 여러 줄 사용 시, 후행 콤마 사용 방식 / jsxBracketSameLine - JSX의 마지막 '>'를 다음 줄로 내릴지 여부 / semi - 세미콜론 붙일지 여부 / arrawParens - Arrow 함수의 파라메터 부분에 괄호 붙일지 여부
- Prettier와 ESLint 차이 : 프리티어는 Formatter이고 ESLint는 Linter, Linter는 코드를 정적으로 분석해 프로그램을 실행하지 않고도 코딩 컨벤션에 위배되는 코드 or 안티 패턴을 자동으로 검출해주는 역할(코드 포맷팅 기능도 포함)
=> ESLint는 주로 코드 에러를 잡아내고 코드 문법을 강제하는 등의 코드 품질 개선에 중점이고 Prettier는 코드 서식을 통일시키고 정돈해주기 위해 중점을 두었음(코드 에러 & 정적 탐지 시 ESLint / 포맷팅 시 Prettier)
★ 소켓
☆ TCP
- 서버와 클라이언트 간 신뢰성 있는 데이터 송수신을 위해 만들어진 프로토콜(연결 지향성 프로토콜)
- 데이터를 나눠 보내는 게 가능하고 받는쪽에서 나눠 받은 데이터를 재조립(누락 시, 데이터가 존재하면 다시 요청해 완성)
- TCP로 서버/클라이언트 간 연결이 된 경우 데이터를 양방향으로 주고 받을 수 있음
- 데이터의 순서가 뒤바뀌는 일 없이 안정적이라 신뢰가 가능
- UDP에 비해 데이터 송수신 비용 부담이 큼(연결 지향성이므로), UDP보다 전송속도가 느림
☆ UDP
- 비연결성 프로토콜로 데이터를 보내고 제대로 받았는지 확인하지 않아 제대로 도착했는지에 대한 보장이 없어 신뢰도가 비교적으로 낮음
- 데이터를 순차적으로 보내게 되더라도 받는 쪽에서는 다른 순서로 전달 받을 수 있음
- 데이터를 보내기만 하고 다른 처리를 하지 않기에 TCP에 비해 비용 부담이 적음 & 전송속도가 빠름
☆ 소켓
- 네트워크에서의 소켓 : 데이터를 송수신하기 위해 반드시 거쳐야 하는 연결부
- 대표적으로 TCP/UDP 프로토콜을 사용하는 소켓이 있는데, 일반적으로는 안정적인 데이터 송수신을 위한 TCP 소켓 사용이 대부분이지만, 일부 패킷이 손실이 되더라도 빠른 전송속도가 필요한 경우 UDP소켓 사용
- 패킷 : 소켓을 통해 송수신하는 데이터 덩어리 하나가 한개의 패킷이라 표현
- 웹소켓 : 실시간 웹 서비스를 제공하기 위해 만들어진 소켓, 모든 브라우저에서 전부 다 동작하지 않음
- socket.io : JS로 웹소켓 사용하려 할 때 많이 사용하는 라이브러리, 주의!! 이 라이브러리는 순수한 웹 소켓의 기술만을 이용하지 않음(웹소켓이 동작하지 못하는 브라우저 경우 서버에서 데이터를 일정 간격마다 받아오는 polling 기능으로 실시간 기능 구현이 가능하도록 해줌)
=> 즉 socket.io는 웹소켓을 포함해 웹소켓을 사용하지 못하는 환경에서도 비슷하게 사용 가능하게 구현한 라이브러리!
★ Access Token, Refresh Token
- Access Token : 사용자의 권한이 확인(로그인 등) 되었을 때 해당 사용자를 인증하는 용도, 인증 요청 시 비밀키로 인증을 하기에 복잡한 설계 없이 구현 가능 & 여러 분기 거치지 않아도 되는 장점, Stateless(무상태)로 서버가 죽었다 살아나도 동일한 동작을 함
- Access Token 문제점 : 이 토큰은 사용자를 인증하는 모든 정보를 담고 있고 인증 여부는 확인이 가능하나 처음 발급한 사용자가 본인인지 확인이 불가능, 이로 인해 토큰 만료시간이 길면 길 수록 탈취되었을 때의 피해가 커짐(탈취되어도 탈취된 토큰인지 알 수 없고 고의적으로 만료 시킬수 없을 것이기에 언제든 탈취될 수 있고 피해를 최소화 할 수 있는 방향으로 개발해야 함)
- Refresh Token : 특정 사용자가 Access Token을 발급받기 위한 용도로만 사용, 사용자가 인증정보를 가지고 있는 것이 아닌 서버에서 해당 사용자 정보를 저장소/별도의 DB에 저장해 관리함, 그렇기에 특정 Token만료가 필요한 경우 저장된 Token을 삭제 해 사용자 인증 여부를 제어가 가능하다는 장점이 있음, 사용자에게 발급한 Token이 탈취당했을 시 피해 최소화를 위해 사용
=> 프로젝트를 빠르게 구현하거나 사용자 요청에 대한 인증 최소화 시, Access Token만을 사용 / 보안성을 중요시하고 서버를 탄탄하게 구성해야 할 시 Refresh Token 사용
★ 트랜잭션
- 작업의 완전성 보장을 위해 사용되는 개념, 특정 작업을 전부 처리하거나 전부 실패하게 만들어 데이터의 일관성을 보장해줌, 작업 단위가 하나의 쿼리에 종속되는 것이 아닌 여러 개의 쿼리를 묶어 그룹화 해 처리
☆ 트랜잭션 특징
- 1. 원자성(Atomicity) : 트랜잭션 내에서 실행되는 명령들을 하나의 묶음으로 처리해 내부에서 실행된 명령들은 전부 성공해야 하거나 전부 실패해야 함
- 2. 일관성(Consistency) : 내부에서 처리되는 데이터는 데이터의 일관성을 유지해야 함, 에러가 발생해도 데이터의 문제가 발생하면 안됨
- 3. 격리성(Isolation) : 트랜잭션 실행 전/후의 데이터를 외부에서 참조가 가능하나 수행하는 중간 상태를 보거나 변경할 수 없도록 구성(MySQL에서는 DB Object에 락을 걸어 구현)
- 4. 지속성(Durability) : 트랜잭션 성공적으로 수행 시 수정된 데이터를 시스템에 영구적으로 적용함, 트랜잭션의 중간 결과가 아니라 완성된 결과만을 저장해 DB에 이상이 생겨도 자동으로 복구가능한 특성
☆ Lock
- Lock : 동시성 제어를 위해 사용하는 기능, 데이터를 점유해 다른 트랜잭션의 접근을 막아 동시성 및 일관성의 균형을 맞추기 위해 사용
- Lock종류 : Shared Locks(READ Locks) - 다른 트랜잭션이 데이터 읽는 건 허용하지만 수정하는 건 금지, READ 전용 락이라 불리며 해당 락을 사용하는 트랜잭션이 모든 작업 수행 시, 공유락 해제 / Exclusive Locks(WRITE Locks) - 다른 트랜잭션이 읽기, 쓰기 모두 금지, WRITE 전용 락이라 불리며 트랜잭션이 해당하는 데이터를 점유 후 다른 트랜잭션이 데이터에 접근 할 수 없도록 만듬
- Locking Level - 1) Global Locks(Databasse Locks) : DB의 모든 테이블에 락을 걸어 현재 트랜잭션을 제외한 나머지 트랜잭션들이 모든 테이블 사용 못하게 함(가장 높은 수준의 락, 가장 큰 범위)
- 2) Table Locks : 다른 사용자가 작업중인 테이블을 동시에 수정하지 못하도록 함
- 3) Named Locks : 테이블이나 테이블의 행과 같은 DB오브젝트가 아닌 특정한 문자열을 점유함
- 4) Metadata Locks : 다른 사용자가 작업중인 테이블의 동일한 행 및 동일 DB의 객체를 동시에 수정하지 못하도록 함
- Dead Lock : 여러 테이블에 락을 적용해 다른 작업이 처리되지 못하게 점유하고 있는 작업이 있을 때, 다른 작업이 끝나는 것을 무한정 기다리는 것(적재적소에 필요한 락의 수준을 설정해 트랜잭션을 구성해야 발생되지 않음)
- Transaction Isolation Level - 1) READ UNCOMMITTED : 가장 낮은 격리 수준으로 락을 걸지 않아 동시성이 높지만 일관성이 쉽게 깨질 수 있음
- 2) READ COMMITTED : 다른 트랜잭션이 데이터 수정 중에는 데이터를 읽을 수 없어 커밋되지 않은 읽기 현상이 발생하지 않음
- 3) REPEATABLE READ : 읽기를 마치더라도 공유락을 풀지 않으며 트랜잭션이 완전히 종료될 때까지 락을 유지하는 수준, 공유락이 걸린 상태에서 수정은 불가능하나 삽입이 가능해져 팬텀읽기 발생 가능한 문제점이 있음
- 4) SERIALIZABLE : 데이터를 읽는 동안 다른 트랜잭션이 읽거나 삽입할 수 없고 새로운 데이터 추가 또한 불가능한 수준, 가장 높은 수준의 격리 수준이나 동시성이 떨어지는 문제점이 있음
- Uncommitted Read : 다른 트랜잭션에 의해 작업중인 데이터를 읽게 되는 것, 발생 될 경우 의도치 않은 데이터를 참조하게 되어 데이터의 일관성이 깨지는 상황이 발생
- Phantom Read : 트랜잭션을 수행하던 중 다른 트랜잭션에 의해 삭제된 데이터를 팬텀행이라고 하는데, 이 팬텀행에 해당하는 데이터를 읽는 것을 팬텀 읽기라 부름
★ 객체 지향
- SW의 핵심을 기능이 아닌 객체로 삼아 객체를 도출하고 각각의 역할을 정의하는 것에 초점을 맞추는 것, 책임과 권한을 가진 객체들이 서로 메시지를 주고받으며 협력해 필요한 기능을 수행하도록 시스템을 개발하는 것, 객체지향으로 크고 복잡한 시스템을 효과적으로 분해하고 구성할 수 있고 손쉽게 이해하고 효율적으로 다룰 수 있게 도와주는 방법으로 인정받아 가장 인기 있는 프로그래밍 패러다임으로 자리 잡음
☆ 객체 지향 특징
- 캡슐화(Encapsulation) : 개념적/물리적으로 객체 내부의 세부적 사항을 감추는 것(정보은닉 목적), 캡슐화의 목적은 변경하기 쉬운 객체를 만드는 것(객체 내부의 접근을 제한 시, 객체간의 결합도를 낮출 수 있기에 설계를 좀 더 쉽게 변경할 수 있음) => JS의 클래스는 멤버 변수를 숨길 수 없음(Type Script 사용해야 함)
- 상속(Inheritance) : 상위 클래스의 특징을 하위 클래스에서 물려받아 코드 중복을 제거하고 코드 재사용성을 증대, 즉 하나의 클래스가 가진 특징(함수, 변수, 데이터 등)을 다른 클래스가 물려 받는 것, 개별 클래스를 상속 관계로 묶음으로 클래스 간 체계화 된 구조를 파악하기 쉬워짐, 데이터 및 메소드 변경 시 상위 클래스만 변경 해 전체적인 일관성 유지가 가능함.
- 추상화(Abstraction) : 객체에서 공통된 부분을 모아 상위 개념으로 새롭게 선언하는 것, 즉 불필요한 부분을 생략하고 객체 속성 중 공통적이고 중요한 것에만 중점을 두어 모델화 하는 것(공통적인 특성을 파악해 필요없는 특성을 제거하는 과정), 복잡한 내부 구현에 신경쓰지 않고 외부에 노출되어 있는 인터페이스만을 이용해 코드 작성이 가능(인터페이스란 클래스 정의 시, 메소드와 속성만을 정의해 인터페이스에 선언된 프로퍼티 또는 메소드의 구현을 강제 해 코드의 일관성을 유지할 수 있도록 만듬 - 인터페이스도 TS만 지원)
- 다형성(Polymorphism) : 객체가 연산 수행 시 하나의 행위에 대해 각 객체가 가지고 있는 고유한 특성으로 다른 여러 형태로 재구성 되는 것을 의미, 즉 동일한 메소드의 이름을 사용하나 메소드에 대해 클래스마다 다르게 구현되는 개념(Overriding - 상속 관계에 있는 부모 클래스에서 이미 정의된 메소드를 자식 클래스에서 같은 시그니쳐를 갖는 메소드로 다시 정의하는 것(부모 메소드를 재정의) <=> Overloading - 같은 이름의 메소드를 중복해 정의하는 것(매개변수의 개수나 타입을 다르게 해서))
- 의존성(Dependency) : 객체들이 협력하는 과정 속에서 해당 객체들이 다른 객체를 의존하는 정도, 어떤 객체가 변경 될 때 그 객채에 의존하는 다른 객체도 또한 변경이 이루어짐
- 결합도(Coupling) : 의존성의 정도를 나타내며 다른 모듈에 대해 얼마나 많은 의존성을 가지고 있는지(의존성이 과한 경우 결합도가 높다고 말함 <-> 합리적 수준으로 의존 시, 결합도가 낮다고 함), 결합도가 높을수록 함께 변경될 확률도 높아지기에 변경하기가 어려워지므로 결합도를 낮춰 변경이 용이한 설계를 만드는 것이 목표
- 응집도(Cohesion) : 모듈에 포함된 내부 요소들이 각각 연관되어 있는 관계의 정도(밀접하게 연관된 작업만 수행하고 연관성 없는 작업은 다른 객체에 위임하는 경우 응집도가 높다고 함), 1개의 메소드가 내부에서 변수를 많이 사용할 수록 해당 메소드와 클래스는 응집도가 높아짐, 자신의 데이터를 스스로 처리하는 자율적 객체를 만들면 결합도를 낮출수 있고 응집도를 높일 수 있다(응집도를 높이기 위해선 스스로 자신의 데이터를 책임져야 함)
☆ 프로그래밍 패러다임
- 프로그래밍 패러다임은 무엇을 해야 할지 보다는 무엇을 해서 안되는지를 말해 줌
- 대표적으로 구조적 프로그래밍, 객제 지향 프로그래밍, 함수형 프로그래밍이 있음
- 1) Structured Programming : 제어 흐름의 직접적인 전환에 대한 규칙 제시, 기능을 중심적으로 개발하고 프로그래밍 기술이 시작되며 가장 처음 적용
- 2) Object-Oriented Programming : 제어흐름의 간접적인 전환에 대한 규칙 제시, 프로그래밍 처리단위가 객체이며 "현실 세계를 모델링"하는 패러다임으로 데이터와 프로세스가 동일한 모듈 내부에 위치하도록 프로그래밍하는 방식, 코드를 추상화해 직관적으로 사고할 수 있음, 현실 세계의 객체를 유연하게 표현할 수 있고 각 객체는 어떠한 특성을 가지고 있고 특정 기능 수행이 가능
- 3) Functional Programming : 할당문에 대한 규칙을 제시, 함수를 중심적으로 개발 진행
☆ 객체 지향 프로그래밍
- 장점 : 의존성을 효율적으로 통제할 수 있는 다양한 방법을 제공해 요구사항 변경에 좀 더 수월하게 대응 가능성을 높여줌, 데이터를 중심으로 프로그래밍하기에 코드가 많아져도 일관성 유지가 좋음, 자신의 문제를 스스로 처리해야 하는 우리의 예상을 만족시켜주기에 이해가 쉽고 객체 내부 변경이 외부에 파급되지 않도록 제어가 가능해 변경이 수월
- 객체 지향 설계 5원칙 : SOLID라 하며 다섯가지 기본 원칙의 앞단어를 하나씩 가져옴, 시간이 지나도 유지 보수와 확장이 쉬운 시스템을 만들고자 할 때 사용
- 1) SRP(Single Responsibility Principle) : 하나의 객체는 하나의 책임만 가져야 함(클래스나 모듈을 변경할 이유가 단 하나 뿐이여야 한다라는 원칙), SRP는 책임이라는 개념을 정의하며 적절한 클래스의 크기를 제시
- 2) OCP(Open-Closed Principle) : SW 개체의 행위는 확장될 수 있어야 하지만 개체를 변경해서는 안된다(확장에는 열려있으나 변경에는 닫혀 있어야 함), 즉 기존 코드에 영향을 주지 않고 SW의 새로운 기능이나 구성 요소를 추가 할 수 있어야 한다는 것(만약 요구사항을 조금 확장하는 데, SW를 엄청 수정해야 한다면 개발 코스트 또한 증가하므로)
- 3) LSP(Liskov Substitution Principle) : 객체는 프로그램의 정확성을 깨뜨리지 않으며 하위 타입의 인스턴스로 바꿀 수 있어야 함, 즉 부모 클래스와 자식 클래스를 서로 바꾸더라도 해당 프로그램에서 잘못된 결과를 도출하지 않는 것
- 4) ISP(Interface Segregation Principle) : 특정 클라이언트를 위한 인터페이스의 여러 개가 범용 인터페이스 하나보다 낫다, 즉 필요하지 않는 기능을 가진 인터페이스에 의존하지 않도록 최대한 인터페이스를 작게 유지해야 함
- 5) DIP(Dependency Inversion Principle) : 구체화에 의존하면 안되고 추상화에 의존해야 한다, 즉 높은 계층의 모듈이 저수준의 모듈에 의존해서는 안된다
★ Layered Architecture Pattern
- Domain : 개발자는 비지니스 프로세스를 개선하거나 자동화하기 위해 일하는데, 도메인은 이런 프로세스가 지원하는 활동을 의미함(SW로 해결하고자 하는 문제의 영역), 한 도메인은 다시 하위 도메인으로 나뉠 수 있음(하위 도메인 구성 여부는 상황에 따라 달라짐, B2B / B2C)
- Domain Model : 유용한 특성을 포함하는 프로세스나 현상의 지도, 즉 특정 도메인을 개념적으로 정리한 모델로 사용할 개체를 기억하기 쉬운 식별자로 부여해 대상을 쉽게 공유, 모델링 종류 : 엔티티, 값 객체, 도메인 서비스
- Entity : 실제 DB 테이블과 연관되어 있는 핵심 클래스로 이 기준으로 테이블이 생성되고 DB스키마가 변경, 엔티티를 요청이나 응답값으로 전달하는 클래스로 사용하면 안됨!, 내부 속성이 변경되어도 동일한 엔티티로 남아있고 시간에 따라 변하는 속성이 포함 될 수 있음, 어떤 요소가 엔티티를 유일하게 식별하는지 정의하는 것 또한 중요
- Architecture Pattern : SW의 구조를 구성하기 위한 가장 기본적 토대를 제시, 각각의 시스템들과 그 역할이 정의되어 있고 여러 시스템 사이의 관계와 규칙이 포함되어 있음, 검증된 구조로 안정적 개발이 가능, 도메인이 복잡할 수록 모델이나 코드를 더 쉽게 변경할 수 있음
- 대표적 패턴 : Repository pattern(영속적 저장소에 대한 추상화), Service layer pattern(유스케이스의 시작과 끝을 명확하게 정의하기 위함), Unit of work pattern(원자적 연산을 제공), Aggregate pattern(데이터 정합성을 강화하기 위함)
- 아키텍쳐 패턴 도입 전 고려사항 : 이 패턴이 주는 이익과 비용에 대한 확실한 이유가 있어야 함, 해당 패턴을 채택 시 어떤 장단점이 존재하는지 명확히 인지해야 함, 노력과 시간을 투자할 만한 가치가 있을 정도로 애플리케이션과 도메인이 복잡한 경우에만 도입해야 함
- Layered Architecture Pattern : 계층을 분리해 관리하는 패턴으로 대중적이며 비용이 적어 표준 아키텍쳐로 불림(어떤 패턴 도입할지에 대한 확신이 없을 때 좋은 선택지), 각 계층이 자신의 바로 아래 계층에만 의존하게 만드는 것이 목표로 계층화의 핵심은 각 계층은 응집도가 높으면서 다른 계층과는 낮은 결합도를 가져야 함, 상위 계층은 하위 계층을 사용할 수 있어야 하지만 하위 계층은 상위 계층에 누가 있는지 알 수 없고 사용할 수 조차 없도록 구성해야 함
- 계층형 아키텍쳐의 장점 : 관심사를 분리해 구현하려는 코드를 명확히 인지할 수 있음, 계층별 의존성이 낮아 모듈 교체해도 코드 수정이 용이, 계층별 단위 테스트를 작성할 수 있어 테스트 코드를 용이하게 구성이 가능함
- 3-Layered Architecture Pattern : Controller(애플리케이션의 가장 바깥으로 요청/응답을 처리 - 클라이언트의 요청을 처리 후 서버에서 처리된 결과를 반환해주는 역할) / Service(애플리케이션의 중간 부분으로 아키텍쳐의 핵심적인 비즈니스 로직이 수행되는 부분, 현업에서는 이 부분이 계속 비대해짐) / Repository(애플리케이션의 가장 안쪽으로 실제 DB의 데이터를 사용하는 계층)
- 3-Layered 로직 수행 플로우 : 클라이언트가 요청을 보냄 - 요청을 URL에 알맞은 컨트롤러가 수신을 받음 - 컨트롤러는 넘어온 요청을 처리하기 위해 서비스 호출 - 서비스는 필요한 데이터를 가져오기 위해 저장소에게 데이터 요청 - 서비스는 저장소에서 가져온 데이터를 가공해 컨트롤러에게 데이터를 넘김 - 컨트롤러는 서비스의 결과물을 클라이언트에게 전달
- Controller : 3-Layered에서는 Presentation Layer라고 표현되는데 대표적으로 컨트롤러 사용, 서버에 요청 시 가장 먼저 만나게 됨, 하위 계층에서 발생하는 예외를 처리함, 클라이언트가 전달한 데이터에 대해 유효성을 검증하는 기능을 수행, 요청 처리 후 서버에 처리된 결과를 반환
- Service : Business logic layer라고도 불리며 아키텍처의 가장 핵심적인 비지니스 로직을 수행하고 실제 사용자가 원하는 요구사항을 구현하는 계층, Presentation Layer와 Data Access Layer 사이의 중간 다리 역할을 하며 두 계층이 직접적인 통신을 하지 않도록 만들어 줌, 데이터 필요 시 저장소에게 데이터를 요청함, 애플리케이션의 규모가 커질수록 서비스의 역할 및 코드 또한 커지게 됨(핵심적 비지니스 로직을 수행해 클라이언트들의 요구사항을 반영해 원하는 결과를 컨트롤러에게 반환해주는 계층)
- 서비스 계층의 장/단점 : 장점 - 유스케이스와 워크플로우를 명확히 정의하는 데 도움(저장소에게 얻어야 할 데이터가 무엇인지 이해 가능, 어떤 사전 검사와 현재 상태 검증을 해야하는지 이해 가능, 어떤 내용 저장해야 하는지 이해 가능, API뒤에 감췄기 때문에 자유롭게 리팩토링 가능함, Repository Pattern 및 Fake Repository와 조합 시 높은 수준의 테스트를 작성 할 수 있음) / 단점 - 다른 추상화 계층에 불과하므로 너무 많은 기능을 넣으면 빈약한 도메인 모델과 같은 안티 패턴이 생길 수 있음
- Repository : Data Access Layer라 불리며 DB와 관련된 작업을 수행하는 계층, 모든 데이터가 메모리상에 존재하는 것처럼 가정 해 데이터 접근과 관련된 세부 사항을 감춤, 저장소 계층 구현 시 데이터를 저장하는 방법을 더 쉽게 변경할 수 있고 Fake 저장소를 제공하기가 더 쉬워짐, 애플리케이션의 다른 계층에서는 세부 사항이 어떤 방식으로 구현되어 있더라고 영향 받지 않음(데이터 저장소를 간단히 추상화 한 것으로 모델 계층과 데이터 계층을 분리할 수 있음)
- 저장소 계층의 장/단점 : 장점 - 모델과 인프라에 대한 사항을 완전 분리했기에 단위 테스트를 위한 Fake 저장소를 쉽게 만들 수 있음, 도메인 모델 미리 작성 시, 처리해야 할 비지니스 문제에 더 잘 집중할 수 있음, 접근 방식을 바꾸려 할 때, 외래키/마이그레이션 등을 염려하지 않고 모델에 반영이 가능, 객체를 테이블에 매핑하는 과정을 원하는대로 제어가 가능 해 DB스키마를 단순화 할 수 있음, ORM을 저장소 계층에서 사용 시, DB를 MySQL과 Postgres와 같이 서로 바꾸는 게 쉬워짐 / 단점 - ORM매핑을 수동으로 할 시에 개발 코스트가 더욱 소모(Sequelize와 같은 라이브러리), 저장소 계층이 없더라도 ORM이 모델과 저장소의 결합을 어느 정도 완화 시켜줄 수 있음
'JS > Node.js' 카테고리의 다른 글
| Node.js의 유용한 13가지 라이브러리 (0) | 2023.11.09 |
|---|---|
| TIL(2023.06.27) (0) | 2023.06.29 |
| Node.js 숙련 (0) | 2023.06.25 |
| TIL(23.06.23) refreshToken을 활용한 유저 계정 전환 기능 (0) | 2023.06.24 |
| TIL(23.06.22) .env 설정 / refreshToken 생성 (0) | 2023.06.24 |