diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index 45f3df5..7584f0a 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -11,8 +11,8 @@ jobs:
build:
runs-on: ubuntu-20.04
env:
- REACT_APP_BASE_URL: ${{ secrets.REACT_APP_BASE_URL }}
- REACT_APP_SOCIAL_URL: ${{ secrets.REACT_APP_SOCIAL_URL }}
+ REACT_APP_KAKAO_CLIENT_ID: ${{ secrets.KAKAO_CLIENT_ID }}
+ REACT_APP_KAKAO_REDIRECT_URI: ${{ secrets.KAKAO_REDIRECT_URI }}
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
AWS_REGION: '${{ secrets.AWS_REGION }}'
@@ -41,8 +41,8 @@ jobs:
echo "REACT_APP_REGION=$REACT_APP_REGION" >> .env.production
env:
- REACT_APP_BASE_URL: ${{ secrets.REACT_APP_BASE_URL }}
- REACT_APP_SOCIAL_URL: ${{ secrets.REACT_APP_SOCIAL_URL }}
+ REACT_APP_KAKAO_CLIENT_ID: ${{ secrets.KAKAO_CLIENT_ID }}
+ REACT_APP_KAKAO_REDIRECT_URI: ${{ secrets.KAKAO_REDIRECT_URI }}
REACT_APP_ACCESS_KEY: ${{ secrets.AWS_ACCESS_KEY_ID }}
REACT_APP_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
REACT_APP_REGION: ${{ secrets.AWS_REGION }}
diff --git a/.gitignore b/.gitignore
index 8692cf6..475737c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -14,6 +14,7 @@
# misc
.DS_Store
.env
+.env.production
.env.local
.env.development.local
.env.test.local
diff --git a/.prettierrc.js b/.prettierrc.js
new file mode 100644
index 0000000..d3f19ed
--- /dev/null
+++ b/.prettierrc.js
@@ -0,0 +1,7 @@
+module.exports = {
+ arrowParens: 'always',
+ bracketSpacing: true,
+ jsxBracketSameLine: false,
+ singleQuote: true,
+ useTabs: false,
+};
diff --git a/package-lock.json b/package-lock.json
index 9c44440..585ca09 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -15,9 +15,15 @@
"@types/node": "^16.18.68",
"@types/react": "^18.2.43",
"@types/react-dom": "^18.2.17",
+ "axios": "^1.6.2",
+ "dayjs": "^1.11.10",
"react": "^18.2.0",
"react-dom": "^18.2.0",
+ "react-query": "^3.39.3",
+ "react-router-dom": "^6.20.1",
"react-scripts": "5.0.1",
+ "recoil": "^0.7.7",
+ "styled-components": "^6.1.1",
"typescript": "^4.9.5",
"web-vitals": "^2.1.4"
}
@@ -2290,6 +2296,24 @@
"postcss-selector-parser": "^6.0.10"
}
},
+ "node_modules/@emotion/is-prop-valid": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.2.1.tgz",
+ "integrity": "sha512-61Mf7Ufx4aDxx1xlDeOm8aFFigGHE4z+0sKCa+IHCeZKiyP9RLD0Mmx7m8b9/Cf37f7NAvQOOJAbQQGVr5uERw==",
+ "dependencies": {
+ "@emotion/memoize": "^0.8.1"
+ }
+ },
+ "node_modules/@emotion/memoize": {
+ "version": "0.8.1",
+ "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.1.tgz",
+ "integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA=="
+ },
+ "node_modules/@emotion/unitless": {
+ "version": "0.8.1",
+ "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.1.tgz",
+ "integrity": "sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ=="
+ },
"node_modules/@eslint-community/eslint-utils": {
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz",
@@ -3247,6 +3271,14 @@
}
}
},
+ "node_modules/@remix-run/router": {
+ "version": "1.13.1",
+ "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.13.1.tgz",
+ "integrity": "sha512-so+DHzZKsoOcoXrILB4rqDkMDy7NLMErRdOxvzvOKb507YINKUP4Di+shbTZDhSE/pBZ+vr7XGIpcOO0VLSA+Q==",
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
"node_modules/@rollup/plugin-babel": {
"version": "5.3.1",
"resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz",
@@ -4199,6 +4231,11 @@
"resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz",
"integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw=="
},
+ "node_modules/@types/stylis": {
+ "version": "4.2.4",
+ "resolved": "https://registry.npmjs.org/@types/stylis/-/stylis-4.2.4.tgz",
+ "integrity": "sha512-36ZrGJ8fgtBr6nwNnuJ9jXIj+bn/pF6UoqmrQT7+Y99+tFFeHHsoR54+194dHdyhPjgbeoNz3Qru0oRt0l6ASQ=="
+ },
"node_modules/@types/testing-library__jest-dom": {
"version": "5.14.9",
"resolved": "https://registry.npmjs.org/@types/testing-library__jest-dom/-/testing-library__jest-dom-5.14.9.tgz",
@@ -5078,6 +5115,29 @@
"node": ">=4"
}
},
+ "node_modules/axios": {
+ "version": "1.6.2",
+ "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.2.tgz",
+ "integrity": "sha512-7i24Ri4pmDRfJTR7LDBhsOTtcm+9kjX5WiY1X3wIisx6G9So3pfMkEiU7emUBe46oceVImccTEM3k6C5dbVW8A==",
+ "dependencies": {
+ "follow-redirects": "^1.15.0",
+ "form-data": "^4.0.0",
+ "proxy-from-env": "^1.1.0"
+ }
+ },
+ "node_modules/axios/node_modules/form-data": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
+ "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
+ "dependencies": {
+ "asynckit": "^0.4.0",
+ "combined-stream": "^1.0.8",
+ "mime-types": "^2.1.12"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
"node_modules/axobject-query": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.2.1.tgz",
@@ -5391,6 +5451,14 @@
"node": ">= 8.0.0"
}
},
+ "node_modules/big-integer": {
+ "version": "1.6.52",
+ "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.52.tgz",
+ "integrity": "sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==",
+ "engines": {
+ "node": ">=0.6"
+ }
+ },
"node_modules/big.js": {
"version": "5.2.2",
"resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz",
@@ -5503,6 +5571,21 @@
"node": ">=8"
}
},
+ "node_modules/broadcast-channel": {
+ "version": "3.7.0",
+ "resolved": "https://registry.npmjs.org/broadcast-channel/-/broadcast-channel-3.7.0.tgz",
+ "integrity": "sha512-cIAKJXAxGJceNZGTZSBzMxzyOn72cVgPnKx4dc6LRjQgbaJUQqhy5rzL3zbMxkMWsGKkv2hSFkPRMEXfoMZ2Mg==",
+ "dependencies": {
+ "@babel/runtime": "^7.7.2",
+ "detect-node": "^2.1.0",
+ "js-sha3": "0.8.0",
+ "microseconds": "0.2.0",
+ "nano-time": "1.0.0",
+ "oblivious-set": "1.0.0",
+ "rimraf": "3.0.2",
+ "unload": "2.2.0"
+ }
+ },
"node_modules/browser-process-hrtime": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz",
@@ -5620,6 +5703,14 @@
"node": ">= 6"
}
},
+ "node_modules/camelize": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.1.tgz",
+ "integrity": "sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ==",
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/caniuse-api": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz",
@@ -6055,6 +6146,14 @@
"postcss": "^8.4"
}
},
+ "node_modules/css-color-keywords": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/css-color-keywords/-/css-color-keywords-1.0.0.tgz",
+ "integrity": "sha512-FyyrDHZKEjXDpNJYvVsV960FiqQyXc/LlYmsxl2BcdMb2WPx0OGRVgTg55rPSyLSNMqP52R9r8geSp7apN3Ofg==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
"node_modules/css-declaration-sorter": {
"version": "6.4.1",
"resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-6.4.1.tgz",
@@ -6236,6 +6335,16 @@
"resolved": "https://registry.npmjs.org/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz",
"integrity": "sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w=="
},
+ "node_modules/css-to-react-native": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/css-to-react-native/-/css-to-react-native-3.2.0.tgz",
+ "integrity": "sha512-e8RKaLXMOFii+02mOlqwjbD00KSEKqblnpO9e++1aXS1fPQOpS1YoqdVHBqPjHNoxeF2mimzVqawm2KCbEdtHQ==",
+ "dependencies": {
+ "camelize": "^1.0.0",
+ "css-color-keywords": "^1.0.0",
+ "postcss-value-parser": "^4.0.2"
+ }
+ },
"node_modules/css-tree": {
"version": "1.0.0-alpha.37",
"resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.37.tgz",
@@ -6451,6 +6560,11 @@
"node": ">=10"
}
},
+ "node_modules/dayjs": {
+ "version": "1.11.10",
+ "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.10.tgz",
+ "integrity": "sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ=="
+ },
"node_modules/debug": {
"version": "4.3.4",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
@@ -8606,6 +8720,11 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/hamt_plus": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/hamt_plus/-/hamt_plus-1.0.2.tgz",
+ "integrity": "sha512-t2JXKaehnMb9paaYA7J0BX8QQAY8lwfQ9Gjf4pg/mk4krt+cmwmU652HOoWonf+7+EQV97ARPMhhVgU1ra2GhA=="
+ },
"node_modules/handle-thing": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz",
@@ -11606,6 +11725,11 @@
"jiti": "bin/jiti.js"
}
},
+ "node_modules/js-sha3": {
+ "version": "0.8.0",
+ "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz",
+ "integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q=="
+ },
"node_modules/js-tokens": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
@@ -11998,6 +12122,15 @@
"tmpl": "1.0.5"
}
},
+ "node_modules/match-sorter": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/match-sorter/-/match-sorter-6.3.1.tgz",
+ "integrity": "sha512-mxybbo3pPNuA+ZuCUhm5bwNkXrJTbsk5VWbR5wiwz/GC6LIiegBGn2w3O08UG/jdbYLinw51fSQ5xNU1U3MgBw==",
+ "dependencies": {
+ "@babel/runtime": "^7.12.5",
+ "remove-accents": "0.4.2"
+ }
+ },
"node_modules/mdn-data": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.4.tgz",
@@ -12060,6 +12193,11 @@
"node": ">=8.6"
}
},
+ "node_modules/microseconds": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/microseconds/-/microseconds-0.2.0.tgz",
+ "integrity": "sha512-n7DHHMjR1avBbSpsTBj6fmMGh2AGrifVV4e+WYc3Q9lO+xnSZ3NyhcBND3vzzatt05LFhoKFRxrIyklmLlUtyA=="
+ },
"node_modules/mime": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
@@ -12235,6 +12373,14 @@
"thenify-all": "^1.0.0"
}
},
+ "node_modules/nano-time": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/nano-time/-/nano-time-1.0.0.tgz",
+ "integrity": "sha512-flnngywOoQ0lLQOTRNexn2gGSNuM9bKj9RZAWSzhQ+UJYaAFG9bac4DW9VHjUAzrOaIcajHybCTHe/bkvozQqA==",
+ "dependencies": {
+ "big-integer": "^1.6.16"
+ }
+ },
"node_modules/nanoid": {
"version": "3.3.7",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz",
@@ -12506,6 +12652,11 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/oblivious-set": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/oblivious-set/-/oblivious-set-1.0.0.tgz",
+ "integrity": "sha512-z+pI07qxo4c2CulUHCDf9lcqDlMSo72N/4rLUpRXf6fu+q8vjt8y0xS+Tlf8NTJDdTXHbdeO1n3MlbctwEoXZw=="
+ },
"node_modules/obuf": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz",
@@ -14201,6 +14352,11 @@
"node": ">= 0.10"
}
},
+ "node_modules/proxy-from-env": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
+ "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
+ },
"node_modules/psl": {
"version": "1.9.0",
"resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz",
@@ -14489,6 +14645,31 @@
"resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
"integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w=="
},
+ "node_modules/react-query": {
+ "version": "3.39.3",
+ "resolved": "https://registry.npmjs.org/react-query/-/react-query-3.39.3.tgz",
+ "integrity": "sha512-nLfLz7GiohKTJDuT4us4X3h/8unOh+00MLb2yJoGTPjxKs2bc1iDhkNx2bd5MKklXnOD3NrVZ+J2UXujA5In4g==",
+ "dependencies": {
+ "@babel/runtime": "^7.5.5",
+ "broadcast-channel": "^3.4.1",
+ "match-sorter": "^6.0.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/tannerlinsley"
+ },
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0"
+ },
+ "peerDependenciesMeta": {
+ "react-dom": {
+ "optional": true
+ },
+ "react-native": {
+ "optional": true
+ }
+ }
+ },
"node_modules/react-refresh": {
"version": "0.11.0",
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.11.0.tgz",
@@ -14497,6 +14678,36 @@
"node": ">=0.10.0"
}
},
+ "node_modules/react-router": {
+ "version": "6.20.1",
+ "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.20.1.tgz",
+ "integrity": "sha512-ccvLrB4QeT5DlaxSFFYi/KR8UMQ4fcD8zBcR71Zp1kaYTC5oJKYAp1cbavzGrogwxca+ubjkd7XjFZKBW8CxPA==",
+ "dependencies": {
+ "@remix-run/router": "1.13.1"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ },
+ "peerDependencies": {
+ "react": ">=16.8"
+ }
+ },
+ "node_modules/react-router-dom": {
+ "version": "6.20.1",
+ "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.20.1.tgz",
+ "integrity": "sha512-npzfPWcxfQN35psS7rJgi/EW0Gx6EsNjfdJSAk73U/HqMEJZ2k/8puxfwHFgDQhBGmS3+sjnGbMdMSV45axPQw==",
+ "dependencies": {
+ "@remix-run/router": "1.13.1",
+ "react-router": "6.20.1"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ },
+ "peerDependencies": {
+ "react": ">=16.8",
+ "react-dom": ">=16.8"
+ }
+ },
"node_modules/react-scripts": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-5.0.1.tgz",
@@ -14601,6 +14812,25 @@
"node": ">=8.10.0"
}
},
+ "node_modules/recoil": {
+ "version": "0.7.7",
+ "resolved": "https://registry.npmjs.org/recoil/-/recoil-0.7.7.tgz",
+ "integrity": "sha512-8Og5KPQW9LwC577Vc7Ug2P0vQshkv1y3zG3tSSkWMqkWSwHmE+by06L8JtnGocjW6gcCvfwB3YtrJG6/tWivNQ==",
+ "dependencies": {
+ "hamt_plus": "1.0.2"
+ },
+ "peerDependencies": {
+ "react": ">=16.13.1"
+ },
+ "peerDependenciesMeta": {
+ "react-dom": {
+ "optional": true
+ },
+ "react-native": {
+ "optional": true
+ }
+ }
+ },
"node_modules/recursive-readdir": {
"version": "2.2.3",
"resolved": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.3.tgz",
@@ -14736,6 +14966,11 @@
"node": ">= 0.10"
}
},
+ "node_modules/remove-accents": {
+ "version": "0.4.2",
+ "resolved": "https://registry.npmjs.org/remove-accents/-/remove-accents-0.4.2.tgz",
+ "integrity": "sha512-7pXIJqJOq5tFgG1A2Zxti3Ht8jJF337m4sowbuHsW30ZnkQFnDzy9qBNhgzX8ZLW4+UBcXiiR7SwR6pokHsxiA=="
+ },
"node_modules/renderkid": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/renderkid/-/renderkid-3.0.0.tgz",
@@ -15344,6 +15579,11 @@
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
"integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="
},
+ "node_modules/shallowequal": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz",
+ "integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ=="
+ },
"node_modules/shebang-command": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
@@ -15840,6 +16080,33 @@
"webpack": "^5.0.0"
}
},
+ "node_modules/styled-components": {
+ "version": "6.1.1",
+ "resolved": "https://registry.npmjs.org/styled-components/-/styled-components-6.1.1.tgz",
+ "integrity": "sha512-cpZZP5RrKRIClBW5Eby4JM1wElLVP4NQrJbJ0h10TidTyJf4SIIwa3zLXOoPb4gJi8MsJ8mjq5mu2IrEhZIAcQ==",
+ "dependencies": {
+ "@emotion/is-prop-valid": "^1.2.1",
+ "@emotion/unitless": "^0.8.0",
+ "@types/stylis": "^4.0.2",
+ "css-to-react-native": "^3.2.0",
+ "csstype": "^3.1.2",
+ "postcss": "^8.4.31",
+ "shallowequal": "^1.1.0",
+ "stylis": "^4.3.0",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">= 16"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/styled-components"
+ },
+ "peerDependencies": {
+ "react": ">= 16.8.0",
+ "react-dom": ">= 16.8.0"
+ }
+ },
"node_modules/stylehacks": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-5.1.1.tgz",
@@ -15855,6 +16122,11 @@
"postcss": "^8.2.15"
}
},
+ "node_modules/stylis": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.0.tgz",
+ "integrity": "sha512-E87pIogpwUsUwXw7dNyU4QDjdgVMy52m+XEOPEKUn161cCzWjjhPSQhByfd1CcNvrOLnXQ6OnnZDwnJrz/Z4YQ=="
+ },
"node_modules/sucrase": {
"version": "3.34.0",
"resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.34.0.tgz",
@@ -16569,6 +16841,15 @@
"node": ">= 10.0.0"
}
},
+ "node_modules/unload": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/unload/-/unload-2.2.0.tgz",
+ "integrity": "sha512-B60uB5TNBLtN6/LsgAf3udH9saB5p7gqJwcFfbOEZ8BcBHnGwCf6G/TGiEqkRAxX7zAFIUtzdrXQSdL3Q/wqNA==",
+ "dependencies": {
+ "@babel/runtime": "^7.6.2",
+ "detect-node": "^2.0.4"
+ }
+ },
"node_modules/unpipe": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
diff --git a/package.json b/package.json
index 919ef0d..a82ac2b 100644
--- a/package.json
+++ b/package.json
@@ -10,9 +10,15 @@
"@types/node": "^16.18.68",
"@types/react": "^18.2.43",
"@types/react-dom": "^18.2.17",
+ "axios": "^1.6.2",
+ "dayjs": "^1.11.10",
"react": "^18.2.0",
"react-dom": "^18.2.0",
+ "react-query": "^3.39.3",
+ "react-router-dom": "^6.20.1",
"react-scripts": "5.0.1",
+ "recoil": "^0.7.7",
+ "styled-components": "^6.1.1",
"typescript": "^4.9.5",
"web-vitals": "^2.1.4"
},
diff --git a/src/asset/login/logo.png b/src/asset/login/logo.png
new file mode 100644
index 0000000..3b90810
Binary files /dev/null and b/src/asset/login/logo.png differ
diff --git a/src/component/home/KakaoOauth.tsx b/src/component/home/KakaoOauth.tsx
new file mode 100644
index 0000000..3b5a525
--- /dev/null
+++ b/src/component/home/KakaoOauth.tsx
@@ -0,0 +1,11 @@
+import { useLocation } from 'react-router';
+
+export default function KakaoOauth() {
+ const location = useLocation();
+ const urlParams = new URLSearchParams(location.search);
+ const codeValue = urlParams.get('code');
+
+ console.log(codeValue);
+
+ return <>카카오 리다이렉트 페이지>;
+}
diff --git a/src/index.tsx b/src/index.tsx
index 032464f..ff390b1 100644
--- a/src/index.tsx
+++ b/src/index.tsx
@@ -1,15 +1,32 @@
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
-import App from './App';
import reportWebVitals from './reportWebVitals';
+import { RouterProvider } from 'react-router-dom';
+import { router } from './routes/Router';
+import { QueryClient, QueryClientProvider } from 'react-query';
+import { RecoilRoot } from 'recoil';
+import { GlobalStyle } from 'styles/globalStyles';
+
+const queryClient = new QueryClient({
+ defaultOptions: {
+ queries: {
+ refetchOnWindowFocus: false,
+ },
+ },
+});
const root = ReactDOM.createRoot(
document.getElementById('root') as HTMLElement
);
root.render(
-
+
+
+
+
+
+
);
diff --git a/src/layout/DefaultLayout.tsx b/src/layout/DefaultLayout.tsx
new file mode 100644
index 0000000..09c9d63
--- /dev/null
+++ b/src/layout/DefaultLayout.tsx
@@ -0,0 +1,30 @@
+import { useEffect } from 'react';
+import { Outlet, useMatches, useNavigate } from 'react-router';
+import styled from 'styled-components';
+
+export default function DefaultLayout() {
+ const isLogin = localStorage.getItem('token');
+ const navigate = useNavigate();
+ const matches = useMatches();
+
+ useEffect(() => {
+ if (!isLogin && matches[1].pathname !== '/oauth') {
+ navigate('/login');
+ }
+ }, []);
+
+ return (
+
+
+
+ );
+}
+
+const DefaultLayoutContainer = styled.div`
+ max-width: 375px;
+ min-height: 100vh;
+ margin: auto;
+ padding: 0px 24px;
+
+ /* background-color: aliceblue; */
+`;
diff --git a/src/pages/Home.tsx b/src/pages/Home.tsx
new file mode 100644
index 0000000..02c907f
--- /dev/null
+++ b/src/pages/Home.tsx
@@ -0,0 +1,3 @@
+export default function Home() {
+ return <>Home>;
+}
diff --git a/src/pages/Login.tsx b/src/pages/Login.tsx
new file mode 100644
index 0000000..574f940
--- /dev/null
+++ b/src/pages/Login.tsx
@@ -0,0 +1,92 @@
+import styled from 'styled-components';
+import onBoardingLogo from 'asset/login/logo.png';
+
+export default function Login() {
+ const onClickKakaoLogin = () => {
+ window.location.href = kakaoLoginURL;
+ };
+
+ const kakaoClientId = process.env.REACT_APP_KAKAO_CLIENT_ID;
+ const kakaoRedirectURI = process.env.REACT_APP_KAKAO_REDIRECT_URI;
+ const kakaoLoginURL = `https://kauth.kakao.com/oauth/authorize?client_id=${kakaoClientId}&redirect_uri=${kakaoRedirectURI}&response_type=code`;
+
+ return (
+
+
+
+
+ AI가 감정을 분석하고
한 줄로 요약해요
+
+
+ 오늘 있었던 일을 자유롭게 적어보세요.
잘 알아차리지 못했던
+ 감정들을 AI가 찾아줄게요
+
+
+
+
+ 네이버로 로그인하기
+
+ 카카오톡으로 로그인하기
+
+
+
+ );
+}
+const LoginPageContainer = styled.div`
+ padding-top: 80px;
+`;
+
+const LoginLogo = styled.div`
+ height: 60px;
+ width: 277px;
+ background-size: cover;
+ background-image: url(${onBoardingLogo});
+ margin: auto;
+`;
+
+const LoginTitleContainer = styled.div`
+ display: flex;
+ flex-direction: column;
+ gap: 8px;
+ margin-bottom: 57px;
+ margin-top: 57px;
+`;
+
+const LoginTitle = styled.h1`
+ font-size: 1.5rem;
+ font-weight: 900;
+ word-break: keep-all;
+ text-align: center;
+ line-height: 1.8rem;
+`;
+
+const LoginSubtitle = styled.div`
+ word-break: keep-all;
+ text-align: center;
+ line-height: 1.2rem;
+`;
+
+const SocialLoginContainer = styled.div`
+ display: flex;
+ flex-direction: column;
+ gap: 12px;
+`;
+
+const SocialLoginBtn = styled.div`
+ width: 100%;
+ height: 56px;
+ border-radius: 10px;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ cursor: pointer;
+`;
+
+const KakaoLoginBtn = styled(SocialLoginBtn)`
+ background-color: #fee600;
+`;
+
+const NaverLoginBtn = styled(SocialLoginBtn)`
+ background-color: #00c300;
+ color: #fff;
+`;
diff --git a/src/routes/Router.tsx b/src/routes/Router.tsx
new file mode 100644
index 0000000..db62c52
--- /dev/null
+++ b/src/routes/Router.tsx
@@ -0,0 +1,22 @@
+import { createBrowserRouter } from 'react-router-dom';
+import DefaultLayout from 'layout/DefaultLayout';
+import Login from 'pages/Login';
+import Home from 'pages/Home';
+import KakaoOauth from 'component/home/KakaoOauth';
+
+export const router = createBrowserRouter([
+ {
+ element: ,
+ children: [
+ {
+ path: '/',
+ element: ,
+ },
+ { path: '/login', element: },
+ {
+ path: '/oauth',
+ children: [{ path: 'kakao', element: }],
+ },
+ ],
+ },
+]);
diff --git a/src/shared/axios.ts b/src/shared/axios.ts
new file mode 100644
index 0000000..27d283d
--- /dev/null
+++ b/src/shared/axios.ts
@@ -0,0 +1,68 @@
+import axios, { InternalAxiosRequestConfig } from 'axios';
+
+const token = localStorage.getItem('token');
+
+const baseURL = process.env.REACT_APP_BASE_URL;
+
+const instance = axios.create({ baseURL });
+
+const setToken = (
+ config: InternalAxiosRequestConfig
+): InternalAxiosRequestConfig => {
+ config.headers['Authorization'] = `Bearer ${token}`;
+ return config;
+};
+
+if (token) {
+ instance.interceptors.request.use(setToken);
+}
+
+instance.interceptors.response.use(
+ (response) => {
+ return response;
+ },
+ async (error) => {
+ const { response, config } = error;
+ const originalRequest = config;
+ if (response.status === 403 || response.status === 401) {
+ let refreshToken = localStorage.getItem('retoken');
+ let accessToken = localStorage.getItem('token');
+ let userId = localStorage.getItem('id');
+ const tokens = {
+ refreshToken,
+ accessToken,
+ userId,
+ };
+ // if (refreshToken) {
+ // const { data } = await checkToken(tokens);
+ // const access = data.data.accessToken;
+ // const refresh = data.data.refreshToken;
+ // localStorage.setItem('token', access);
+ // localStorage.setItem('retoken', refresh);
+ // window.location.reload();
+ // }
+ return axios(originalRequest);
+ }
+ if (response.status === 404) {
+ return window.location.replace('/notfound');
+ }
+ if (response.status === 504) {
+ return window.location.replace('/connectfail');
+ }
+ if (response.status === 400) {
+ return response;
+ }
+ return Promise.reject(error);
+ }
+);
+
+// const checkToken = async ({ accessToken, refreshToken, userId }) => {
+// const response = await axios.post(`${baseURL}/user/reissue`, {
+// accessToken,
+// refreshToken,
+// userId,
+// });
+// return response;
+// };
+
+export default instance;
diff --git a/src/styles/globalStyles.tsx b/src/styles/globalStyles.tsx
new file mode 100644
index 0000000..ea95d98
--- /dev/null
+++ b/src/styles/globalStyles.tsx
@@ -0,0 +1,71 @@
+import { createGlobalStyle } from 'styled-components';
+
+//전역 스타일링
+export const GlobalStyle = createGlobalStyle`
+
+ html, body, div, span, applet, object, iframe,
+ h1, h2, h3, h4, h5, h6, p, blockquote, pre,
+ a, abbr, acronym, address, big, cite, code,
+ del, dfn, em, img, ins, kbd, q, s, samp,
+ small, strike, strong, sub, sup, tt, var,
+ b, u, i, center,
+ dl, dt, dd, menu, ol, ul, li,
+ fieldset, form, label, legend,
+ table, caption, tbody, tfoot, thead, tr, th, td,
+ article, aside, canvas, details, embed,
+ figure, figcaption, footer, header, hgroup,
+ main, menu, nav, output, ruby, section, summary,
+ time, mark, audio, video {
+ margin: 0;
+ padding: 0;
+ border: 0;
+ font-size: 100%;
+ font: inherit;
+ vertical-align: baseline;
+ box-sizing: border-box;
+ }
+
+ /* HTML5 display-role reset for older browsers */
+ article, aside, details, figcaption, figure,
+ footer, header, hgroup, main, menu, nav, section {
+ display: block;
+ }
+
+ /* HTML5 hidden-attribute fix for newer browsers */
+ *[hidden] {
+ display: none;
+ }
+
+ * {
+ box-sizing: border-box;
+ }
+
+ html {
+ width: 100%;
+ height: 100%;
+ -webkit-user-select:none;
+ -moz-user-select:none;
+ -ms-user-select:none;
+ user-select:none
+ }
+
+ body {
+ line-height: 1;
+ overflow-x: hidden;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+ }
+
+ /* h1, h2, h3, h4, h5, h6 {
+ font-family:"SpoqaMedium"
+ } */
+
+ a {
+ text-decoration: none;
+ }
+
+ button {
+ cursor: pointer;
+ }
+`;
diff --git a/tsconfig.json b/tsconfig.json
index a273b0c..181a58d 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -1,11 +1,8 @@
{
"compilerOptions": {
"target": "es5",
- "lib": [
- "dom",
- "dom.iterable",
- "esnext"
- ],
+ "baseUrl": "./src",
+ "lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"esModuleInterop": true,
@@ -20,7 +17,5 @@
"noEmit": true,
"jsx": "react-jsx"
},
- "include": [
- "src"
- ]
+ "include": ["src"]
}