dependencies : 어플리케이션이 실행될 때 실제로 필요한 패키지들을 명시. 이 패키지들은 프로덕션 환경에서도 사용되며, 빌드 결과물에 포함될 수 있다.
devDependencies : 개발중에만 필요한 패키지들을 명시. 예를 들어, 빌드 도구(Webpack), TypeScript 관련 도구(@typescript-eslint)등이 여기에 포함된다. 이 패키지들은 프로덕션 환경에서는 필요하지 않으며, 빌드 결과물에는 포함되지 않는다.
번들링 도구는 어플리케이션의 의존성을 분석하여 하나의 파일로 묶어준다. 이 과정에서 어플리케이션에 필요한 파일들만 포함되도록 최적화를 수행해야 한다. dependencies에 포함된 패키지는 프로덕션에서 동작하기 위해 실제 필요하기 때문에 어플리케이션의 번들에 포함될 가능성이 높다. devDependencies에 포함된 패키지는 개발 과정에서만 필요하며, 최종 번들 파일에 포함되지 않는다. 예를 들어, TypeScript 컴파일러 등은 개발 중에만 사용되기 때문에 번들링 도구가 이를 최종 결과물에서 제외한다.
@로 시작하는 패키지들은 일반적으로 TypeScript 관련 도구나 ESLint 플러그인 등이다. 이러한 도구들은 개발 시에만 필요하며, 프로덕션 환경에서는 필요하지 않기 때문에 devDependencies에 넣는 것이 일반적이다.
@로 시작하는 패키지(@typescript-eslint, @types/node)를 devDependencies에 포함시키면 빌드 과정에서 번들에 포함되지 않으며, 불필요한 개발 도구들이 포함되지 않아 번들 파일 크기가 줄어든다.
백엔드 : 데이터 관리, 웹 어플리케이션 프레임워크
백엔드 웹 개발은 클라이언트가 필요로하는 데이터를 반환할 수 있어야 한다.
이때 클라이언트가 원하는 데이터를 어떻게, 잘 반환할 지를 고려해야 한다.
01. 백엔드 = 데이터 관리
이런 번거로움 때문에 백엔드 프레임워크를 이용하는 것이 편하다.
#1. 직렬화 / 역직렬화
직렬화/역직렬화는 웹서버 기준 외부 데이터 형태와 내부 데이터 형태 사이의 변환하는 과정을 의미한다.
02. 웹 어플리케이션 프레임워크 등장
웹 어플리케이션 프레임워크는 매우 간편하게 웹 어플리케이션 서버를 개발할 수 있도록 돕는 프레임워크이다.
#1. 웹 어플리케이션 프레임워크가 제공하는 기능
#2. 인터페이스(Interface)
💡 인터페이스(추상)
사용자 입장에서 어떻게 사용하는지를 말한다.
인터페이스를 통해 시스템, 프로그램 등을 사용하며, 내부 복잡한 원리나 과정은 알 필요가 없다.
즉, 사용자는 시스템, 프로그램의 구체적인 구현을 알 필요없이, 오직 인터페이스만을 사용해 원하는 결과를 얻으면 된다.
💡 구체적인 구현(원리)
시스템이 실제로 어떻게 작동하는지 설명하는 것이다.
시스템 내부의 작동 원리, 세부 과정에 해당하여 일반 사용자는 신경쓰지 않아도 된다.
내부 구현은 언제든지 바뀔 수 있다.
#3. API(Application Programming Interface)
API는 어플리케이션, 웹 서버에서 어떤 요청을 보내면 어떤 응답을 받을 수 있는지에 대한 스펙이다.
즉, 인터페이스의 일종으로 사용자는 API를 통해 프로그램, 서버와 상호작용 하게 된다.
💡 추상 = 사용 스펙
사용 방법에 집중하여, 사용자가 어떤 요청 보내야 어떤 응답 받을 수 있는지 이해하는 것이 중요하다.
과정이 내부에서 어떻게 이루어지는지는 신경쓰지 않아도 된다.
💡 구체 = 상세 로직
요청을 보냈을 때 응답을 반환하기 위한 방법은 다양하지만 사용자는 신경쓰지 않아도 된다.
API가 실제로 어떻게 작동하는지에 대한 구체적인 내부 로직은 사용자가 알 필요가 없다.
예를 들어, Postman에서 어떤 요청 시 어떤 응답을 반환하는지 여부가 API라 볼 수 있다.
실제로 API의 내부 구현이 어떻게 구성되어 있고 동작하는지 사용자는 신경 쓸 필요없이 원하는 응답 등만 얻어가면 된다.
03. 웹 어플리케이션 프레임워크 동작 원리
#1. Package Manager : 라이브러리 버전 관리
웹 어플리케이션 프레임워크는 다수의 라이브러리, 인터페이스를 제공한다.
많은 수의 라이르러리가 필요하기 때문에 어떤 라이브러리를 사용하고, 어떤 버전을 사용할지 관리가 필요하다.
◼︎ JavaScript의 npm
🎯 package.json에서 dependencies와 devDependencies 차이 🎯
번들링 도구는 어플리케이션의 의존성을 분석하여 하나의 파일로 묶어준다. 이 과정에서 어플리케이션에 필요한 파일들만 포함되도록 최적화를 수행해야 한다. dependencies에 포함된 패키지는 프로덕션에서 동작하기 위해 실제 필요하기 때문에 어플리케이션의 번들에 포함될 가능성이 높다. devDependencies에 포함된 패키지는 개발 과정에서만 필요하며, 최종 번들 파일에 포함되지 않는다. 예를 들어, TypeScript 컴파일러 등은 개발 중에만 사용되기 때문에 번들링 도구가 이를 최종 결과물에서 제외한다.
@로 시작하는 패키지들은 일반적으로 TypeScript 관련 도구나 ESLint 플러그인 등이다. 이러한 도구들은 개발 시에만 필요하며, 프로덕션 환경에서는 필요하지 않기 때문에 devDependencies에 넣는 것이 일반적이다.
@로 시작하는 패키지(@typescript-eslint, @types/node)를 devDependencies에 포함시키면 빌드 과정에서 번들에 포함되지 않으며, 불필요한 개발 도구들이 포함되지 않아 번들 파일 크기가 줄어든다.
위와 같이 package.json에서 dependencies와 devDependencies를 분리해서 작성할 수 있다.
이런 과정을 통해 어플리케이션이 더 작은 크기의 파일로 배포되도록 도와주어 성능 향상에 긍정적인 영향을 미친다.
◼︎ Java의 Maven/Gradle 사용
#2. Database : 데이터 조회 및 조작
💡 CRUD와 데이터 식별
CRUD는 데이터베이스에서 가장 기본적인 데이터 조작 작업이며, 데이터 식별 시 ID를 사용해야 한다.
데이터가 변경되더라도 고유한 식별자로써 일관성을 유지할 수 있기 때문에 ID를 사용해야 한다.
예를 들어, 사용자의 이름이 바뀌어도 사용자의 ID는 변경되지 않는다. 따라서 ID를 사용하면 데이터의 식별 및 조회가 안정적으로 이루어진다. 하지만 이름으로 식별할 경우, 이름이 변경되면 데이터 조회에 실패할 수 있다.
💡 ID 생성 방법
◼︎ Auto Increment ID
자동으로 증가하는 숫자로 된 ID로, 데이터베이스가 지원하는 최대 숫자를 초과할 수 없다.
공격자가 ID를 기반으로 다른 자원에 접근 가능하며, 작은 앱에서는 문제 되지 않지만 대규모 시스템에서는 성능 저하가 발생할 수 있다.
◼︎ UUID(Universally/Globally Unique Identifier)
128비트로 구성된 고유 식별자로, 사실상 무한한 수의 ID 표현이 가능하다.
유사 난수로 생성되므로 충돌 가능성이 매우 낮으며, 생성 순서를 보장하지 않아 순서 기반 작업에 문제될 수 있다.
길이가 길어 인덱싱과 검색 성능에 영향을 미친다.
◼︎ CUID(Collision-Resistant Unique Identifier)
분산 시스템에서 사용하기에 적합한 고유 식별자이다.
생성 순서가 보장되며, UUID보다 충돌 가능성이 낮다.
◼︎ NanoID
짧은 길이의 고유 식별자로, CUID보다 짦으며, 순서 보장이 필요 없는 경우에 적합하다.
◼︎ Snowflake
트위터와 같은 대규모 시스템에서 사용되는 ID 생성 방식이다.
#3. Transaction : 대량 트래픽이나 다수 요청이 데이터베이스에 접근 -> 동시성 제어
대량 트래픽이 발생하는 상황에서 여러 웹서버가 동시에 하나의 데이터베이스에 접근할 때 데이터베이스에서 충돌이 발생할 수 있다.
이런 문제를 해결하기 위해 트랜잭션이 사용된다.
트랜잭션은 여러 사용자가 동시에 데이터베이스에 접근할 때 발생할 수 있는 문제를 해결하는데 중요한 기법으로, 단일 데이터베이스에 다수 접근이 충돌나지 않게 번호표를 추가 순서대로 처리한다.
'ASAC > 웹 기초 프로그래밍' 카테고리의 다른 글