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"] }