Skip to content

Commit

Permalink
Merge pull request #42 from inje-megabrain/develop
Browse files Browse the repository at this point in the history
Develop
  • Loading branch information
narinn-star committed Aug 27, 2023
2 parents 1f0e640 + e19d638 commit 47a4d99
Show file tree
Hide file tree
Showing 68 changed files with 10,803 additions and 811 deletions.
43 changes: 23 additions & 20 deletions .eslintrc.json
Original file line number Diff line number Diff line change
@@ -1,21 +1,24 @@
{
"root": true,
"parser": "@typescript-eslint/parser",
"env": {
"browser": true,
"node": true
},
"parserOptions": {
"project": ["./tsconfig.json"]
},
"plugins":["@typescript-eslint", "prettier"],
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/recommended",
"plugin:@typescript-eslint/recommended-requiring-type-checking",
"plugin:react/recommended",
"plugin:react/jsx-runtime",
"plugin:react-hooks/recommended",
"prettier"
]
}
"root": true,
"parser": "@typescript-eslint/parser",
"env": {
"browser": true,
"node": true
},
"parserOptions": {
"project": ["./tsconfig.json"]
},
"plugins": ["@typescript-eslint", "prettier"],
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/recommended",
"plugin:@typescript-eslint/recommended-requiring-type-checking",
"plugin:react/recommended",
"plugin:react/jsx-runtime",
"plugin:react-hooks/recommended",
"prettier"
],
"rules": {
//"react/react-in-jsx-scope": "off"
}
}
67 changes: 67 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
#main.yml
name: master

on:
push:
branches: [develop]

env:
AWS_REGION: ap-northeast-2
S3_BUCKET_NAME: pick-read-me-actions-s3-bucket
CODE_DEPLOY_APPLICATION_NAME: pick-read-me-codedeploy-app
CODE_DEPLOY_DEPLOYMENT_GROUP_NAME: pick-read-me-codedeploy-group-front

jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout source code
uses: actions/checkout@v2

- name: Cache node modules
uses: actions/cache@v1
with:
path: node_modules
key: ${{ runner.OS }}-master-build-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
${{ runner.OS }}-build-
${{ runner.OS }}-
- name: Install Dependencies
run: yarn

- name: Build
run: yarn build

- name: appspec.yml
run: mv ./appspec.yml ./build

- name: Include Scripts
run: mv ./deploy.sh ./build

# AWS 인증 (IAM 사용자 Access Key, Secret Key 활용)
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ env.AWS_REGION }}

# (5) 빌드 결과물을 S3 버킷에 업로드 /fe폴더내에
- name: Upload to AWS S3
run: |
aws deploy push \
--application-name ${{ env.CODE_DEPLOY_APPLICATION_NAME }} \
--ignore-hidden-files \
--s3-location s3://$S3_BUCKET_NAME/fe/$GITHUB_SHA.zip \
--source ./build
# S3 버킷에 있는 파일을 대상으로 CodeDeploy 실행
- name: Deploy to AWS EC2 from S3
run: |
aws deploy create-deployment \
--application-name ${{ env.CODE_DEPLOY_APPLICATION_NAME }} \
--deployment-config-name CodeDeployDefault.AllAtOnce \
--deployment-group-name ${{ env.CODE_DEPLOY_DEPLOYMENT_GROUP_NAME }} \
--s3-location bucket=$S3_BUCKET_NAME,key=fe/$GITHUB_SHA.zip,bundleType=zip
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
.DS_Store
node_modules
node_modules/
build/
19 changes: 19 additions & 0 deletions appspec.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
version: 0.0
os: linux

files:
- source: /
destination: /home/ubuntu/front
overwrite: yes

permissions:
- object: /home/ubuntu/front
pattern: "**"
owner: ubuntu
group: ubuntu

hooks:
AfterInstall:
- location: deploy.sh
timeout: 60
runas: ubuntu
11 changes: 11 additions & 0 deletions deploy.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
echo "> [$(date +%y-%m-%d/%H:%M)] Deploy React" >> /home/ubuntu/front/deploy.sh

pm2 kill
pm2 serve /home/ubuntu/front/build 3000 --spa --name front
# REPOSITORY=/home/ubuntu/front

# cd $REPOSITORY

# sudo yarn install

# sudo npx pm2 reload all
15 changes: 15 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,32 @@
"name": "PickreadMe",
"version": "1.0.0",
"main": "./index.js",
"homepage": "http://pickreadme.site",
"license": "MIT",
"proxy": "http://52.78.80.150:9000",
"dependencies": {
"@babel/preset-react": "^7.18.6",
"@babel/preset-typescript": "^7.21.5",
"@types/file-saver": "^2.0.5",
"@types/node": "^20.5.6",
"@types/react-router-dom": "^5.3.3",
"@typescript-eslint/eslint-plugin": "^5.59.2",
"@typescript-eslint/parser": "^5.59.2",
"@uiw/react-md-editor": "^3.23.3",
"axios": "^1.4.0",
"daisyui": "^2.51.6",
"dom-to-image": "^2.6.0",
"eslint": "^8.40.0",
"eslint-plugin-react": "^7.32.2",
"eslint-plugin-react-hooks": "^4.6.0",
"file-loader": "^6.2.0",
"file-saver": "^2.0.5",
"framer-motion": "^10.12.16",
"html2canvas": "^1.4.1",
"react": "^18.2.0",
"react-cookie": "^4.1.1",
"react-dom": "^18.2.0",
"react-icons": "^4.9.0",
"react-query": "^3.39.3",
"react-router-dom": "^6.11.1",
"typescript": "^5.0.4",
Expand All @@ -27,6 +41,7 @@
"devDependencies": {
"@babel/core": "^7.21.8",
"@babel/preset-env": "^7.21.5",
"@types/dom-to-image": "^2.6.4",
"@types/react": "^18.2.6",
"@types/react-dom": "^18.2.4",
"autoprefixer": "^10.4.14",
Expand Down
13 changes: 8 additions & 5 deletions public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,17 @@
<html lang="en">

<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>PickReadMe</title>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- <meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests"> -->
<title>PickReadMe</title>
<script src="/build/bundle.js"></script>
<link rel="shortcut icon" href="#">
</head>

<body>
<div id="root"></div>
<div id="root"></div>
</body>

</html>
1 change: 1 addition & 0 deletions src/Api/ constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const BASE_URL = 'http://52.78.80.150:9000';
20 changes: 20 additions & 0 deletions src/Api/Cookies.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { Cookies } from 'react-cookie';

const cookies = new Cookies();

// export const setCookie = (...args: Parameters<(typeof cookies)['set']>) => {
// console.log('+', ...args);
// return cookies.set(...args);
// };

export const setCookie = (name: string, value: string, option?: any) => {
return cookies.set(name, value, { ...option });
};

export const getCookie = (name: string) => {
return cookies.get(name);
};

export const removeCookie = (name: string) => {
return cookies.remove(name);
};
115 changes: 115 additions & 0 deletions src/Api/client.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
import axios from 'axios';
import { getCookie, removeCookie, setCookie } from './Cookies';
import { BASE_URL } from './ constants';
import logout from './logout';
import fetchAccess from './fetchAccess';

const ACCESS_HEADER_KEY = 'accessToken';
const REFRESH_HEADER_KEY = 'refreshToken';
const TOKEN_TYPE = 'Bearer';

const client = axios.create({
baseURL: BASE_URL,
withCredentials: true,
});

client.interceptors.request.use((req) => {
return req;
});

client.interceptors.response.use(
(res) => {
if (res.status === 200 && res.data) {
const token = res.data as { accessToken?: string; refreshToken?: string };
if (token.accessToken) {
setAccessToken(token.accessToken);
}
if (token.refreshToken) {
setRefreshToken(token.refreshToken);
}
}
return res;
},
async (error) => {
//console.log(error);
if (error.response.status === 401) {
if (error.response.data.includes('refresh')) {
// refresh 토큰 만료, refresh 토큰 없음
logout()
.then(() => {
console.log('로그아웃');
removeCookie('refreshToken');
})
.then(() => {
window.location.href = '/';
console.log(
'RefreshToken 만료로 로그아웃 합니다. 다시 로그인해주세요.'
);
});
}
if (error.response.data.includes('access')) {
// 엑세스 토큰 만료, 없음
await fetchAccess()
.then(async (v) => {
error.config.headers = {
'Content-Type': 'application/json',
accessToken: v.data,
};
localStorage.setItem('accessToken', v.data);
const response = await axios.request(error.config);
return response;
})
.then(() => {
window.location.reload();
});
}
if (error.response.data.includes('IP')) {
logout()
.then(() => {
console.log('등록된 IP가 있어 로그아웃합니다.');
removeCookie('refreshToken');
})
.then(() => {
window.location.href = '/';
});
}
}

return Promise.reject(error);
}
);

export const setRefreshToken = (token: string) => {
if (token) {
client.defaults.headers.common[
REFRESH_HEADER_KEY
] = `${TOKEN_TYPE} ${token}`;
//쿠키 저장
setCookie('refreshToken', `${token}`, {
path: 'http://52.78.80.150:9000',
//path: '/',
//httpOnly: true,
maxAge: 14 * 24 * 60 * 60,
//maxAge: 180,
sameSite: 'none',
secure: true,
});
} else {
delete client.defaults.headers.common[REFRESH_HEADER_KEY];
}
};

export const setAccessToken = (token: string) => {
if (token) {
client.defaults.headers.common[
ACCESS_HEADER_KEY
] = `${TOKEN_TYPE} ${token}`;
//LocalStorage 저장
localStorage.setItem('accessToken', token);
console.log('저장 완료');
} else {
delete client.defaults.headers.common[ACCESS_HEADER_KEY];
}
};

export default client;
20 changes: 20 additions & 0 deletions src/Api/createLike.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import client from './client';
import { getCookie } from './Cookies';

export default function createLike(postId: number) {
return new Promise((resolve) => {
client
.post(`/api/like/posts?post_id=${postId}`, {
headers: {
accessToken: localStorage.getItem('accessToken'),
refreshToken: getCookie('refreshToken'),
},
})
.then((v) => {
resolve(v);
})
.catch((error) => {
console.log('createLike 에러 ' + error);
});
});
}
12 changes: 12 additions & 0 deletions src/Api/deletePost.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import client from './client';

const deletePost = async (postId: number) => {
try {
const res = await client.delete(`/api/delete/posts?post_id=${postId}`, {});
if (res) console.log('삭제 완료');
} catch (error) {
console.log('deletePost 에러 ', error);
}
};

export default deletePost;
Loading

0 comments on commit 47a4d99

Please sign in to comment.