diff --git a/.DS_Store b/.DS_Store
new file mode 100644
index 0000000..9216d95
Binary files /dev/null and b/.DS_Store differ
diff --git a/.eslintrc.base.json b/.eslintrc.base.json
new file mode 100644
index 0000000..4f292a2
--- /dev/null
+++ b/.eslintrc.base.json
@@ -0,0 +1,89 @@
+{
+ "extends": [
+ "eslint:recommended",
+ "plugin:@typescript-eslint/recommended",
+ "plugin:prettier/recommended",
+ "plugin:import/recommended",
+ "plugin:import/typescript"
+ ],
+ "plugins": [
+ "@typescript-eslint",
+ "prettier",
+ "import"
+ ],
+ "rules": {
+ "prettier/prettier": [
+ "error",
+ {
+ "useTabs": true
+ }
+ ],
+ "quotes": [
+ "error",
+ "single"
+ ],
+ "jsx-quotes": [
+ "error",
+ "prefer-single"
+ ],
+ "@typescript-eslint/no-unused-vars": "error",
+ "@typescript-eslint/no-explicit-any": "warn",
+ "no-console": [
+ "warn",
+ {
+ "allow": [
+ "warn",
+ "error"
+ ]
+ }
+ ],
+ "import/order": [
+ "error",
+ {
+ "groups": [
+ "builtin",
+ "external",
+ "internal",
+ [
+ "sibling",
+ "parent"
+ ],
+ "index",
+ "type"
+ ],
+ "pathGroups": [
+ {
+ "pattern": "@/**",
+ "group": "internal",
+ "position": "after"
+ }
+ ],
+ "newlines-between": "always",
+ "alphabetize": {
+ "order": "asc",
+ "caseInsensitive": true
+ }
+ }
+ ],
+ "import/no-duplicates": "warn",
+ "no-multiple-empty-lines": [
+ "error",
+ {
+ "max": 1,
+ "maxBOF": 0,
+ "maxEOF": 0
+ }
+ ],
+ "import/newline-after-import": [
+ "error",
+ {
+ "count": 1
+ }
+ ]
+ },
+ "parser": "@typescript-eslint/parser",
+ "parserOptions": {
+ "ecmaVersion": 2020,
+ "sourceType": "module"
+ }
+}
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index c6bba59..5f31252 100644
--- a/.gitignore
+++ b/.gitignore
@@ -122,9 +122,17 @@ dist
# Stores VSCode versions used for testing VSCode extensions
.vscode-test
-# yarn v2
-.yarn/cache
-.yarn/unplugged
-.yarn/build-state.yml
-.yarn/install-state.gz
+# Yarn
+.yarn/*
.pnp.*
+
+# pnpm
+.pnpm-store/
+pnpm-lock.yaml
+
+# Turbo
+.turbo
+
+# DS_Store files
+**/.DS_Store
+.DS_Store
\ No newline at end of file
diff --git a/.prettierrc.base.json b/.prettierrc.base.json
new file mode 100644
index 0000000..a315ece
--- /dev/null
+++ b/.prettierrc.base.json
@@ -0,0 +1,10 @@
+{
+ "singleQuote": false,
+ "jsxSingleQuote": true,
+ "trailingComma": "es5",
+ "tabWidth": 2,
+ "useTabs": true,
+ "semi": true,
+ "printWidth": 100,
+ "bracketSpacing": true
+}
\ No newline at end of file
diff --git a/.vscode/extensions.json b/.vscode/extensions.json
new file mode 100644
index 0000000..c99c624
--- /dev/null
+++ b/.vscode/extensions.json
@@ -0,0 +1,6 @@
+{
+ "recommendations": [
+ "dbaeumer.vscode-eslint",
+ "esbenp.prettier-vscode"
+ ]
+}
\ No newline at end of file
diff --git a/.vscode/setting.json b/.vscode/setting.json
new file mode 100644
index 0000000..1e2ae19
--- /dev/null
+++ b/.vscode/setting.json
@@ -0,0 +1,22 @@
+{
+ "editor.formatOnSave": true,
+ "editor.codeActionsOnSave": {
+ "source.fixAll.eslint": "explicit"
+ },
+ "editor.defaultFormatter": "esbenp.prettier-vscode",
+ "[typescript]": {
+ "editor.defaultFormatter": "esbenp.prettier-vscode"
+ },
+ "[javascript]": {
+ "editor.defaultFormatter": "esbenp.prettier-vscode"
+ },
+ "[json]": {
+ "editor.defaultFormatter": "esbenp.prettier-vscode"
+ },
+ "[html]": {
+ "editor.defaultFormatter": "esbenp.prettier-vscode"
+ },
+ "[css]": {
+ "editor.defaultFormatter": "esbenp.prettier-vscode"
+ }
+}
\ No newline at end of file
diff --git a/README.md b/README.md
index 1878f3d..09e56ad 100644
--- a/README.md
+++ b/README.md
@@ -1,59 +1,130 @@
-# Freedivah
-**Freedivah** is a global community platform where freedivers from around the world come together to connect, share their passion, and inspire each other. The name **Freedivah** blends 'freediving' with the name of the developer, a devoted freediving enthusiast, capturing her deep love for the sport in every detail.
-## MVP FEATURES
-### TRACK & ANALYZE
+# Freedivah: Project Overview
+**“From Dive Tracking to Social Sharing”**
+Freedivah is an interactive platform that allows freedivers to mark and share their dive locations on a global map using national flag icons.
+
+The name 'Freedivah' combines 'freediving' with my identity as a developer, reflecting both my passion for underwater exploration and my journey.
+
+## Key Features
+
+- **Personalized Dive Map**: Pin and save your dive locations on a global map.
+- **Sharing and Connecting**: Share your dive experiences and connect with divers worldwide.
+- **Tracking and Documentation**: Log and track your dives across different countries to monitor your progress.
+
+## Documentation
+For more detailed information, refer to the following:
+- [Technology Choices Rationale, API Specification, Functional Specification, Route Design etc](https://jiah827.notion.site/Project-Freedivah-10f4ef50e633807387d4c9307d622bdb?pvs=74)
+- [Optimizing Freedivah’s Architecture with Feature-Sliced Design(FSD)](https://www.notion.so/jiah827/Optimizing-Freedivah-s-Architecture-with-Feature-Sliced-Design-1134ef50e63380b1b47bea0cc16f5f64)
+- [Managing Shared Libraries: API Strategy with Exports and Aliases](https://www.notion.so/jiah827/exports-alias-API-1434ef50e63380a3aacad6eb9b7fec3b)
+- [Why Vanilla Extract CSS?](https://www.notion.so/jiah827/CSS-1424ef50e633802ab39cec3730fe2d74)
+
+## Development Considerations
+
+### Flexible and Scalable Architecture
+ - Single-direction dependencies and modularity.
+ - Loosely coupled systems through separation and abstraction of business logic, UI, and side effects.
+
+## Architecture
+### System Overview
+```mermaid
+graph TB
+subgraph "Frontend (Next.js)"
+Web[Web Application]
+subgraph "FSD Architecture"
+App[Application Layer]
+Pages[Pages Layer]
+Widgets[Widgets Layer]
+Entities[Entities Layer]
+Shared_FE[Shared Layer]
+end
+end
+subgraph "Backend (Express.js)"
+API[API Server]
+subgraph "API Layers"
+Routes[Routes]
+Controllers[Controllers]
+Services[Services]
+Models[Models]
+end
+end
+subgraph "Shared Package"
+Types[Types]
+Utils[Utils]
+end
+Web --> Types
+Web --> Utils
+API --> Types
+API --> Utils
+subgraph "External Services"
+Supabase[(Supabase)]
+end
+API --> Supabase
+```
+### Package Dependencies
+```mermaid
+graph TD
+A[packages/web]
+B[packages/api]
+C[packages/shared]
+A --> C
+B --> C
+style A fill:#eb6b56,stroke:#333,stroke-width:2px
+style B fill:#2196F3,stroke:#333,stroke-width:2px
+style C fill:#47b39d,stroke:#333,stroke-width:2px
+```
+### Build Flow
+```mermaid
+graph LR
+A[Build Shared] --> B[Build Web & API]
+B --> C[Run Services]
+style A fill:#47b39d,stroke:#333,stroke-width:2px
+style B fill:#2196F3,stroke:#333,stroke-width:2px
+style C fill:#eb6b56,stroke:#333,stroke-width:2px
+```
+### Package Overview
+- `@freedivah/shared`: Core utilities and types
+- `@freedivah/web`: Next.js frontend application
+- `@freedivah/api`: Express backend server
+
+## Technologies Used
+ - **Frontend**: Next.js, TypeScript, Vanilla Extract
+ - **Backend**: Node.js, Express.js, Supabase
+ - **Testing**: Jest
+ - **DevOps**: Github Actions, Docker, AWS
+
+## How to Run
+### Prerequisites
+- Node.js 18+
+- PNPM 9.14.1+
+
+### Installation & Development
+1. Clone the repository
+ ```
+ git clone https://github.com/f-lab-edu/Freedivah.git
+ cd Freedivah
+ ```
+2. Install dependencies
+ ```
+ pnpm install
+ ```
+3. Start development
+ ```
+ pnpm dev
+ ```
+### Testing
+ ```
+ yarn test
+ ```
+### Build
+ ```
+ yarn build
+ ```
+
+## Design
+
-- **My Dive Map**: Mark your dive locations on a global map with flag badges. Input methods include GPS, device integration, and direct entry.
-### SHARE & CONNECT
-- **Profile**: Earn and showcase freediving certification badges.
-- **Export & Share**: Export and share your dive map files.
-- **Feed**:
- - Upload and comment on photos and videos.
- - Share your current location with a map image featuring a flag badge.
- - Posts are automatically translated into English.
-## TECH STACKS
-#### Mono Repo / PNPM
-- **Mono Repo**: Manages multiple packages within a single repository, streamlining development and version control.
-- **PNPM**: Provides efficient package management with fast installation and reduced disk space usage. Chosen for its superior compatibility with widely used tools, despite Yarn Berry’s Zero-install advantages.
-#### Front-End Technologies
-- **Vanilla JavaScript** and **TypeScript**: Core languages selected to deepen our understanding of fundamental JavaScript principles.
-- **Vanilla Extract**: Used for styling and UI development. Preferred over TailwindCSS and Styled Components for its static CSS extraction, type safety, and lack of runtime overhead, enhancing performance and maintainability.
-
-#### Backend Framework
-
-- **Node.js** with **Express.js**: Manages server-side logic and API endpoints.
-
-#### Data Storage
-
-- **Firebase Realtime Database**: Handles and stores dive data and user profiles.
-
-#### Authentication
-
-- **Firebase Authentication**: Manages user authentication and profiles, seamlessly integrating with Google Authentication.
-- **Google Authentication**: Enabled through Firebase Authentication, offering a smooth and effortless login experience with Google accounts.
-
-
-## EXTERNAL APIS
-
-#### Map Integration & Visualization
-
-- **Google Maps JavaScript API**: Displays dive locations with flag badges on a map.
-
-#### Location Services
-
-- **Geolocation API**: Retrieves the user's current location for precise dive tracking.
-- **OpenCage Geocoding API**: Converts coordinates into country information. Selected for its cost-effectiveness and broad coverage compared to Google Maps Geocoding API.
-
-#### Data Export
-
-- **JSZip**: Exports dive maps and data as downloadable files.
-
-#### Flag Icons
-
-- **FlagsAPI**: Provides high-quality flag icons in SVG format with various sizes and styles.
diff --git a/docs/images/Freedivah_Design.webp b/docs/images/Freedivah_Design.webp
new file mode 100644
index 0000000..7e4be00
Binary files /dev/null and b/docs/images/Freedivah_Design.webp differ
diff --git a/jest.config.base.js b/jest.config.base.js
new file mode 100644
index 0000000..f31782c
--- /dev/null
+++ b/jest.config.base.js
@@ -0,0 +1,14 @@
+module.exports = {
+ preset: 'ts-jest',
+ testEnvironment: 'node',
+ moduleNameMapper: {
+ '^@/(.*)$': '/src/$1',
+ },
+ setupFilesAfterEnv: ['/jest.setup.ts'],
+ testMatch: ['**/__tests__/**/*.test.ts?(x)'],
+ collectCoverageFrom: [
+ 'src/**/*.{ts,tsx}',
+ '!src/**/*.d.ts',
+ '!src/**/*.stories.{ts,tsx}',
+ ],
+};
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..7b7f79d
--- /dev/null
+++ b/package.json
@@ -0,0 +1,37 @@
+{
+ "name": "freedivah",
+ "version": "1.0.0",
+ "main": "index.js",
+ "repository": "https://github.com/f-lab-edu/Freedivah.git",
+ "author": "jiaah <25231717+jiaah@users.noreply.github.com>",
+ "license": "MIT",
+ "packageManager": "pnpm@9.14.1",
+ "workspaces": [
+ "packages/*"
+ ],
+ "scripts": {
+ "build": "turbo run build",
+ "dev": "turbo run dev",
+ "test": "turbo run test",
+ "test:watch:filter": "turbo run test:watch --filter=@freedivah/*#",
+ "clean": "turbo run clean && rm -rf node_modules",
+ "lint": "turbo run lint",
+ "format": "prettier --write \"**/*.{ts,tsx,md}\""
+ },
+ "devDependencies": {
+ "@testing-library/jest-dom": "^6.6.3",
+ "@types/jest": "^29.5.14",
+ "@types/node": "^20",
+ "@typescript-eslint/eslint-plugin": "^8.14.0",
+ "@typescript-eslint/parser": "^8.14.0",
+ "eslint": "^9.15.0",
+ "eslint-config-prettier": "^9.1.0",
+ "eslint-import-resolver-typescript": "^3.6.1",
+ "eslint-plugin-import": "^2.29.1",
+ "eslint-plugin-prettier": "^5.2.1",
+ "jest": "^29.7.0",
+ "prettier": "^3.3.3",
+ "turbo": "^2.3.0",
+ "typescript": "^5"
+ }
+}
\ No newline at end of file
diff --git a/packages/api/.eslintrc.json b/packages/api/.eslintrc.json
new file mode 100644
index 0000000..3056c8c
--- /dev/null
+++ b/packages/api/.eslintrc.json
@@ -0,0 +1,8 @@
+{
+ "extends": [
+ "../../.eslintrc.base.json"
+ ],
+ "env": {
+ "node": true
+ }
+}
\ No newline at end of file
diff --git a/packages/api/.prettierrc.json b/packages/api/.prettierrc.json
new file mode 100644
index 0000000..32e9d12
--- /dev/null
+++ b/packages/api/.prettierrc.json
@@ -0,0 +1,5 @@
+{
+ "extends": [
+ "../../.prettierrc.base.json"
+ ]
+}
\ No newline at end of file
diff --git a/packages/api/jest.config.js b/packages/api/jest.config.js
new file mode 100644
index 0000000..c4661a2
--- /dev/null
+++ b/packages/api/jest.config.js
@@ -0,0 +1,4 @@
+module.exports = {
+ ...require('../../jest.config.base'),
+ testEnvironment: 'node',
+};
\ No newline at end of file
diff --git a/packages/api/jest.setup.ts b/packages/api/jest.setup.ts
new file mode 100644
index 0000000..5cd4fbd
--- /dev/null
+++ b/packages/api/jest.setup.ts
@@ -0,0 +1,3 @@
+import '@testing-library/jest-dom';
+
+// 전역 설정이나 모킹이 필요한 경우 여기에 추가
diff --git a/packages/api/nodemon.json b/packages/api/nodemon.json
new file mode 100644
index 0000000..a075834
--- /dev/null
+++ b/packages/api/nodemon.json
@@ -0,0 +1,6 @@
+{
+ "watch": ["src"],
+ "ext": ".ts,.js",
+ "ignore": [],
+ "exec": "ts-node -r tsconfig-paths/register ./src/index.ts"
+}
\ No newline at end of file
diff --git a/packages/api/package.json b/packages/api/package.json
new file mode 100644
index 0000000..d38bfbb
--- /dev/null
+++ b/packages/api/package.json
@@ -0,0 +1,25 @@
+{
+ "name": "@freedivah/api",
+ "version": "0.1.0",
+ "private": true,
+ "scripts": {
+ "build": "tsc",
+ "dev": "nodemon",
+ "start": "node dist/index.js",
+ "test": "jest",
+ "test:watch": "jest --watch",
+ "test:coverage": "jest --coverage"
+ },
+ "dependencies": {
+ "@freedivah/shared": "workspace:*",
+ "@supabase/supabase-js": "^2.39.0",
+ "dotenv": "^16.3.1",
+ "express": "^4.18.2"
+ },
+ "devDependencies": {
+ "@types/express": "^4.17.21",
+ "nodemon": "^3.0.1",
+ "ts-node": "^10.9.1",
+ "tsconfig-paths": "^4.2.0"
+ }
+}
\ No newline at end of file
diff --git a/packages/api/src/index.ts b/packages/api/src/index.ts
new file mode 100644
index 0000000..d2b8dbe
--- /dev/null
+++ b/packages/api/src/index.ts
@@ -0,0 +1,5 @@
+import { logger } from '@shared/utils';
+
+logger('Shared is connected', {
+ state: 'ON',
+});
\ No newline at end of file
diff --git a/packages/api/tsconfig.json b/packages/api/tsconfig.json
new file mode 100644
index 0000000..1bfb308
--- /dev/null
+++ b/packages/api/tsconfig.json
@@ -0,0 +1,22 @@
+{
+ "extends": "../../tsconfig.base.json",
+ "compilerOptions": {
+ "outDir": "./dist",
+ "rootDir": "./src",
+ "module": "commonjs",
+ "noEmit": false,
+ "baseUrl": ".",
+ "paths": {
+ "@shared/*": [
+ "../../node_modules/@freedivah/shared/*"
+ ]
+ },
+ },
+ "include": [
+ "src/**/*.ts"
+ ],
+ "exclude": [
+ "node_modules",
+ "dist"
+ ]
+}
\ No newline at end of file
diff --git a/packages/shared/.eslintrc.json b/packages/shared/.eslintrc.json
new file mode 100644
index 0000000..e376f66
--- /dev/null
+++ b/packages/shared/.eslintrc.json
@@ -0,0 +1,5 @@
+{
+ "extends": [
+ "../../.eslintrc.base.json"
+ ]
+}
\ No newline at end of file
diff --git a/packages/shared/.prettierrc.json b/packages/shared/.prettierrc.json
new file mode 100644
index 0000000..32e9d12
--- /dev/null
+++ b/packages/shared/.prettierrc.json
@@ -0,0 +1,5 @@
+{
+ "extends": [
+ "../../.prettierrc.base.json"
+ ]
+}
\ No newline at end of file
diff --git a/packages/shared/jest.config.js b/packages/shared/jest.config.js
new file mode 100644
index 0000000..80e81b1
--- /dev/null
+++ b/packages/shared/jest.config.js
@@ -0,0 +1,3 @@
+module.exports = {
+ ...require('../../jest.config.base'),
+};
diff --git a/packages/shared/jest.setup.ts b/packages/shared/jest.setup.ts
new file mode 100644
index 0000000..1fdec5d
--- /dev/null
+++ b/packages/shared/jest.setup.ts
@@ -0,0 +1,3 @@
+import '@testing-library/jest-dom';
+
+// 전역 설정이나 모킹이 필요한 경우 여기에 추가
\ No newline at end of file
diff --git a/packages/shared/package.json b/packages/shared/package.json
new file mode 100644
index 0000000..44d6d06
--- /dev/null
+++ b/packages/shared/package.json
@@ -0,0 +1,23 @@
+{
+ "name": "@freedivah/shared",
+ "version": "0.0.0",
+ "private": true,
+ "scripts": {
+ "build": "tsc",
+ "dev": "tsc --watch",
+ "test": "jest",
+ "test:watch": "jest --watch",
+ "test:coverage": "jest --coverage"
+ },
+ "exports": {
+ "./utils": {
+ "default": "./dist/utils/index.js"
+ },
+ "./types": {
+ "default": "./dist/types/index.js"
+ }
+ },
+ "devDependencies": {
+ "ts-jest": "^29.2.5"
+ }
+}
\ No newline at end of file
diff --git a/packages/shared/tsconfig.json b/packages/shared/tsconfig.json
new file mode 100644
index 0000000..dabeeb1
--- /dev/null
+++ b/packages/shared/tsconfig.json
@@ -0,0 +1,17 @@
+{
+ "extends": "../../tsconfig.base.json",
+ "compilerOptions": {
+ "composite": true,
+ "outDir": "./dist",
+ "rootDir": ".",
+ "baseUrl": ".",
+ },
+ "include": [
+ "**/*.ts",
+ "utils/index.ts"
+ ],
+ "exclude": [
+ "node_modules",
+ "dist"
+ ]
+}
\ No newline at end of file
diff --git a/packages/shared/utils/__tests__/index.test.ts b/packages/shared/utils/__tests__/index.test.ts
new file mode 100644
index 0000000..f3cbe49
--- /dev/null
+++ b/packages/shared/utils/__tests__/index.test.ts
@@ -0,0 +1,40 @@
+import { logger } from '../index';
+
+describe('logger', () => {
+ let consoleLogSpy: jest.SpyInstance;
+
+ beforeEach(() => {
+ // console.log를 모킹하여 실제 콘솔 출력을 방지
+ consoleLogSpy = jest.spyOn(console, 'log').mockImplementation();
+ });
+
+ afterEach(() => {
+ // 각 테스트 후 모킹 초기화
+ consoleLogSpy.mockRestore();
+ });
+
+ it('should log message with correct format', () => {
+ logger('Test message');
+ expect(consoleLogSpy).toHaveBeenCalledWith('[Logger] Test message', '');
+ });
+
+ it('should log message with data when provided', () => {
+ const testData = { count: 1, text: 'hello' };
+ logger('Test message', testData);
+ expect(consoleLogSpy).toHaveBeenCalledWith('[Logger] Test message', testData);
+ });
+
+ it('should handle undefined data correctly', () => {
+ logger('Test message', undefined);
+ expect(consoleLogSpy).toHaveBeenCalledWith('[Logger] Test message', '');
+ });
+
+ it('should handle multiple calls correctly', () => {
+ logger('First message');
+ logger('Second message', { value: 123 });
+
+ expect(consoleLogSpy).toHaveBeenCalledTimes(2);
+ expect(consoleLogSpy).toHaveBeenNthCalledWith(1, '[Logger] First message', '');
+ expect(consoleLogSpy).toHaveBeenNthCalledWith(2, '[Logger] Second message', { value: 123 });
+ });
+});
\ No newline at end of file
diff --git a/packages/shared/utils/index.ts b/packages/shared/utils/index.ts
new file mode 100644
index 0000000..7cb7308
--- /dev/null
+++ b/packages/shared/utils/index.ts
@@ -0,0 +1,10 @@
+interface LogData {
+ [key: string]: any;
+}
+
+const logger = (message: string, data?: LogData) => {
+ const logMessage = `[Logger] ${message}`;
+ console.log(logMessage, data || '');
+};
+
+export { logger };
diff --git a/packages/web/.eslintrc.json b/packages/web/.eslintrc.json
new file mode 100644
index 0000000..601292a
--- /dev/null
+++ b/packages/web/.eslintrc.json
@@ -0,0 +1,39 @@
+{
+ "extends": [
+ "../../.eslintrc.base.json",
+ "next/core-web-vitals"
+ ],
+ "parserOptions": {
+ "ecmaFeatures": {
+ "jsx": true
+ }
+ },
+ "rules": {
+ "import/order": [
+ "error",
+ {
+ "pathGroups": [
+ {
+ "pattern": "react",
+ "group": "external",
+ "position": "before"
+ },
+ {
+ "pattern": "next/**",
+ "group": "external",
+ "position": "after"
+ },
+ {
+ "pattern": "@/**",
+ "group": "internal",
+ "position": "after"
+ }
+ ],
+ "pathGroupsExcludedImportTypes": [
+ "react",
+ "next"
+ ],
+ }
+ ],
+ }
+}
\ No newline at end of file
diff --git a/packages/web/.gitignore b/packages/web/.gitignore
new file mode 100644
index 0000000..d32cc78
--- /dev/null
+++ b/packages/web/.gitignore
@@ -0,0 +1,40 @@
+# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
+
+# dependencies
+/node_modules
+/.pnp
+.pnp.*
+.yarn/*
+!.yarn/patches
+!.yarn/plugins
+!.yarn/releases
+!.yarn/versions
+
+# testing
+/coverage
+
+# next.js
+/.next/
+/out/
+
+# production
+/build
+
+# misc
+.DS_Store
+*.pem
+
+# debug
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+
+# env files (can opt-in for committing if needed)
+.env*
+
+# vercel
+.vercel
+
+# typescript
+*.tsbuildinfo
+next-env.d.ts
diff --git a/packages/web/.prettierrc.json b/packages/web/.prettierrc.json
new file mode 100644
index 0000000..32e9d12
--- /dev/null
+++ b/packages/web/.prettierrc.json
@@ -0,0 +1,5 @@
+{
+ "extends": [
+ "../../.prettierrc.base.json"
+ ]
+}
\ No newline at end of file
diff --git a/packages/web/README.md b/packages/web/README.md
new file mode 100644
index 0000000..e215bc4
--- /dev/null
+++ b/packages/web/README.md
@@ -0,0 +1,36 @@
+This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app).
+
+## Getting Started
+
+First, run the development server:
+
+```bash
+npm run dev
+# or
+yarn dev
+# or
+pnpm dev
+# or
+bun dev
+```
+
+Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
+
+You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.
+
+This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel.
+
+## Learn More
+
+To learn more about Next.js, take a look at the following resources:
+
+- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
+- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
+
+You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome!
+
+## Deploy on Vercel
+
+The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
+
+Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details.
diff --git a/packages/web/app/(routes)/login/page.tsx b/packages/web/app/(routes)/login/page.tsx
new file mode 100644
index 0000000..867dde3
--- /dev/null
+++ b/packages/web/app/(routes)/login/page.tsx
@@ -0,0 +1,7 @@
+export default function LoginPage() {
+ return (
+
+ Login Page
+
+ )
+}
\ No newline at end of file
diff --git a/packages/web/app/(routes)/map/page.tsx b/packages/web/app/(routes)/map/page.tsx
new file mode 100644
index 0000000..db1f749
--- /dev/null
+++ b/packages/web/app/(routes)/map/page.tsx
@@ -0,0 +1,7 @@
+export default function MapPage() {
+ return (
+
+ Map Page
+
+ )
+}
\ No newline at end of file
diff --git a/packages/web/app/layout.tsx b/packages/web/app/layout.tsx
new file mode 100644
index 0000000..4108414
--- /dev/null
+++ b/packages/web/app/layout.tsx
@@ -0,0 +1,33 @@
+
+import type { Metadata } from 'next';
+import localFont from 'next/font/local';
+
+const geistSans = localFont({
+ src: "../public/assets/fonts/GeistVF.woff",
+ variable: "--font-geist-sans",
+ weight: "100 900",
+});
+const geistMono = localFont({
+ src: "../public/assets/fonts/GeistMonoVF.woff",
+ variable: "--font-geist-mono",
+ weight: "100 900",
+});
+
+export const metadata: Metadata = {
+ title: "Create Next App",
+ description: "Generated by create next app",
+};
+
+export default function RootLayout({
+ children,
+}: Readonly<{
+ children: React.ReactNode;
+}>) {
+ return (
+
+
+ {children}
+
+
+ );
+}
diff --git a/packages/web/app/page.tsx b/packages/web/app/page.tsx
new file mode 100644
index 0000000..e80f736
--- /dev/null
+++ b/packages/web/app/page.tsx
@@ -0,0 +1,13 @@
+import { logger } from "@shared/utils";
+
+logger('Shared is connected', {
+ state: 'ON',
+});
+
+export default function Home() {
+ return (
+
+ Hello Freedivah
+
+ );
+}
diff --git a/packages/web/next.config.ts b/packages/web/next.config.ts
new file mode 100644
index 0000000..94a0639
--- /dev/null
+++ b/packages/web/next.config.ts
@@ -0,0 +1,16 @@
+import { createVanillaExtractPlugin } from '@vanilla-extract/next-plugin';
+import type { NextConfig } from 'next';
+
+const withVanillaExtract = createVanillaExtractPlugin();
+
+const nextConfig: NextConfig = {
+ webpack: (config, { isServer }) => {
+ config.resolve.alias = {
+ ...config.resolve.alias,
+ '@shared': '@freedivah/shared'
+ };
+ return config;
+ }
+};
+
+module.exports = withVanillaExtract(nextConfig);
diff --git a/packages/web/package.json b/packages/web/package.json
new file mode 100644
index 0000000..72ba32e
--- /dev/null
+++ b/packages/web/package.json
@@ -0,0 +1,28 @@
+{
+ "name": "@freedivah/web",
+ "version": "0.1.0",
+ "private": true,
+ "scripts": {
+ "build": "next build",
+ "dev": "next dev",
+ "start": "next start",
+ "test": "jest",
+ "test:watch": "jest --watch",
+ "test:coverage": "jest --coverage"
+ },
+ "dependencies": {
+ "@freedivah/shared": "workspace:*",
+ "@vanilla-extract/css": "^1.16.0",
+ "next": "15.0.3",
+ "react": "19.0.0-rc-66855b96-20241106",
+ "react-dom": "19.0.0-rc-66855b96-20241106"
+ },
+ "devDependencies": {
+ "@testing-library/react": "^16.0.1",
+ "@types/react": "^18",
+ "@types/react-dom": "^18",
+ "@vanilla-extract/next-plugin": "^2.4.6",
+ "eslint-config-next": "15.0.3",
+ "jest-environment-jsdom": "^29.7.0"
+ }
+}
\ No newline at end of file
diff --git a/packages/web/public/assets/fonts/GeistMonoVF.woff b/packages/web/public/assets/fonts/GeistMonoVF.woff
new file mode 100644
index 0000000..f2ae185
Binary files /dev/null and b/packages/web/public/assets/fonts/GeistMonoVF.woff differ
diff --git a/packages/web/public/assets/fonts/GeistVF.woff b/packages/web/public/assets/fonts/GeistVF.woff
new file mode 100644
index 0000000..1b62daa
Binary files /dev/null and b/packages/web/public/assets/fonts/GeistVF.woff differ
diff --git a/packages/web/public/assets/images/favicon.ico b/packages/web/public/assets/images/favicon.ico
new file mode 100644
index 0000000..718d6fe
Binary files /dev/null and b/packages/web/public/assets/images/favicon.ico differ
diff --git a/packages/web/src/application/styles/global.css.ts b/packages/web/src/application/styles/global.css.ts
new file mode 100644
index 0000000..5f6a72b
--- /dev/null
+++ b/packages/web/src/application/styles/global.css.ts
@@ -0,0 +1,26 @@
+import { globalStyle } from '@vanilla-extract/css';
+import { colors } from './theme/colors.css';
+
+globalStyle('html, body', {
+ maxWidth: '100vw',
+ overflowX: 'hidden'
+});
+
+globalStyle('body', {
+ color: colors.foreground,
+ background: colors.background,
+ fontFamily: 'Arial, Helvetica, sans-serif',
+ WebkitFontSmoothing: 'antialiased',
+ MozOsxFontSmoothing: 'grayscale'
+});
+
+globalStyle('*', {
+ boxSizing: 'border-box',
+ padding: 0,
+ margin: 0
+});
+
+globalStyle('a', {
+ color: 'inherit',
+ textDecoration: 'none'
+});
\ No newline at end of file
diff --git a/packages/web/src/application/styles/index.ts b/packages/web/src/application/styles/index.ts
new file mode 100644
index 0000000..232feb8
--- /dev/null
+++ b/packages/web/src/application/styles/index.ts
@@ -0,0 +1,4 @@
+import './global.css';
+import { colors } from './theme/colors.css';
+
+export { colors };
diff --git a/packages/web/src/application/styles/theme/colors.css.ts b/packages/web/src/application/styles/theme/colors.css.ts
new file mode 100644
index 0000000..99e5841
--- /dev/null
+++ b/packages/web/src/application/styles/theme/colors.css.ts
@@ -0,0 +1,8 @@
+import { createGlobalTheme } from '@vanilla-extract/css';
+
+export const colors = createGlobalTheme(':root', {
+ background: '#ffffff',
+ foreground: '#171717',
+ backgroundDark: '#0a0a0a',
+ foregroundDark: '#ededed',
+});
diff --git a/packages/web/src/application/styles/theme/index.ts b/packages/web/src/application/styles/theme/index.ts
new file mode 100644
index 0000000..899aa90
--- /dev/null
+++ b/packages/web/src/application/styles/theme/index.ts
@@ -0,0 +1,3 @@
+import { colors } from './colors.css';
+
+export { colors };
diff --git a/packages/web/tsconfig.json b/packages/web/tsconfig.json
new file mode 100644
index 0000000..e8927b4
--- /dev/null
+++ b/packages/web/tsconfig.json
@@ -0,0 +1,40 @@
+{
+ "extends": "../../tsconfig.base.json",
+ "compilerOptions": {
+ "baseUrl": ".",
+ "paths": {
+ "@/*": [
+ "./src/*"
+ ],
+ "@shared/*": [
+ "../../node_modules/@freedivah/shared/*"
+ ],
+ "@styles/*": [
+ "./src/styles/*"
+ ],
+ "@assets/*": [
+ "./public/assets/*"
+ ]
+ },
+ "plugins": [
+ {
+ "name": "next" // Next.js 플러그인 활성화
+ }
+ ],
+ "noEmit": true,
+ "module": "esnext",
+ "moduleResolution": "node",
+ "resolveJsonModule": true
+ },
+ "include": [
+ "next-env.d.ts",
+ "**/*.ts",
+ "**/*.tsx",
+ ".next/types/**/*.ts",
+ ".next/types/app/(routes)/page.tsx",
+ ".next/types/app/(routes)/layout.tsx"
+ ],
+ "exclude": [
+ "node_modules"
+ ]
+}
\ No newline at end of file
diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml
new file mode 100644
index 0000000..dee51e9
--- /dev/null
+++ b/pnpm-workspace.yaml
@@ -0,0 +1,2 @@
+packages:
+ - "packages/*"
diff --git a/tsconfig.base.json b/tsconfig.base.json
new file mode 100644
index 0000000..b186fec
--- /dev/null
+++ b/tsconfig.base.json
@@ -0,0 +1,20 @@
+{
+ "compilerOptions": {
+ "target": "es2020",
+ "lib": [
+ "dom",
+ "dom.iterable",
+ "esnext"
+ ],
+ "allowJs": true,
+ "skipLibCheck": true,
+ "strict": true,
+ "esModuleInterop": true,
+ "isolatedModules": true,
+ "jsx": "preserve",
+ "incremental": true,
+ },
+ "exclude": [
+ "node_modules"
+ ]
+}
\ No newline at end of file
diff --git a/turbo.json b/turbo.json
new file mode 100644
index 0000000..e6d2cc0
--- /dev/null
+++ b/turbo.json
@@ -0,0 +1,34 @@
+{
+ "$schema": "https://turbo.build/schema.json",
+ "globalDependencies": [
+ "**/.env.*local"
+ ],
+ "tasks": {
+ "build": {
+ "dependsOn": [
+ "^build"
+ ],
+ "outputs": [
+ ".next/**",
+ "!.next/cache/**",
+ "dist/**"
+ ]
+ },
+ "lint": {},
+ "dev": {
+ "cache": false,
+ "persistent": true
+ },
+ "test": {
+ "dependsOn": [
+ "build"
+ ],
+ "outputs": [
+ "coverage/**"
+ ]
+ },
+ "clean": {
+ "cache": false
+ }
+ }
+}
\ No newline at end of file