ํ๋ก์ ํธ GOALDDAE ํ๋ก ํธ์๋ ๋ ํผ์งํ ๋ฆฌ
3
stars
0
forks
source link
Project Detail
1. ๋์ ํ
์ด๋ธ
์ ํฌ๋ ์ ์ ํ
์ด๋ธ๊ณผ ๋์ ํ
์ด๋ธ์ ๋ชจ๋ ํ์ฉํ์ฌ DB๋ฅผ ๊ตฌ์ฑํ์ต๋๋ค.
๋์ ํ
์ด๋ธ์ ์ฌ์ฉํ ์ด์
๊ฒ์ํ์ ์๋ก ๋ค์ด ๊ฐ ๊ฒ์๊ธ๋ณ ๋๊ธ์ ํ๋ฒ์ ์ ์ฅํ ๊ฒฝ์ฐ ํ๋์ ๊ธ์ ๋๊ธ์ ์กฐํํด์ผ ํ ๋ ์ ์ ํ
์ด๋ธ๋ก ๋ชจ๋ ๋๊ธ์ ํ๋ฒ์ ์ ์ฅ ์ ์กฐํ ์ฒ๋ฆฌ์ ์๊ฐ์ด ๊ฑธ๋ฆด ์ ์์ต๋๋ค.
๊ทธ๋ ๊ธฐ ๋๋ฌธ์ ๊ฐ ๊ฒ์๊ธ๋ณ๋ก ๋๊ธ ๋์ ํ
์ด๋ธ์ ๊ตฌ์ฑํด ์กฐํ ์๊ฐ์ ๋จ์ถํ๊ธฐ ์ํด ๋์ ํ
์ด๋ธ์ ์ฌ์ฉํ์ต๋๋ค.
๋ํ, ๋์ ํ
์ด๋ธ ์ฌ์ฉ์ MyBatis๋ฅผ ์ด์ฉํ๊ฒ ๋๋๋ฐ ์ด๋ SQL Injection ๋ฌธ์ ๋ฅผ ๋ณด์ํ๊ธฐ ์ํด
`
$
`
๋์
`
#
`
์ ์ฌ์ฉํด ์ฌ์ฉ์๊ฐ ์ฟผ๋ฆฌ๋ฅผ ๋ ๋ฆฌ๋๋ผ๋ ๋ฌธ์ ๊ฐ ๋ฐ์ํ์ง ์๋๋ก ์ฒ๋ฆฌํ์ต๋๋ค.
2. Spring Security
JWT ํ ํฐ์ ์ด์ฉํด ์ฌ์ฉ์๊ฐ ๋ก๊ทธ์ธ ํ์ ๋ ํด๋น ์ฌ์ฉ์์ ๊ถํ์ด ๋ด๊ฒจ ์๋ JWT ํ ํฐ์ ๋ฐ๊ธํด ๊ถํ์ ๋ฐ๋ผ ์๋น์ค ์ด์ฉ ์ ํ
๋ํ, ํด๋น JWT ํ ํฐ์ ์ฟ ํค์ HTTPOnly๋ก ์ ์ฅํด XSS ๊ณต๊ฒฉ์ ๋๋นํ์ต๋๋ค.
Cookie cookie = new Cookie("token", token);
cookie.setHttpOnly(true);
cookie.setPath("/"); // ๋ชจ๋ ํ์ด์ง์์ ์ ๊ทผ ๊ฐ๋ฅ
Refresh Token ์ฌ์ฉ
Access Token์ ์ ํจ๊ธฐ๊ฐ์ ์งง๊ฒ ๋์ด Access Token์ ํ์ทจ๋ฅผ ์ต์ํํ์ต๋๋ค. Access Token์ด ๋ง๋ฃ๋์์ ๊ฒฝ์ฐ ์ฌ์ฉ์์ ์ฌ๋ก๊ทธ์ธ์ ์ต์ํ ํ๊ธฐ ์ํด
Refresh Token์ DB์ ์ ์ฅํด ๋๊ณ ๋ง๋ฃ ์ Refresh Token์ ํตํด Access Token์ ์ฌ๋ฐ๊ธํด์ฃผ๋๋ก ์ค์ ํ์ต๋๋ค.
if(!token.equals("")) {
if (tokenProvider.validToken(token)) {
Authentication authentication = tokenProvider.getAuthentication(token);
SecurityContextHolder.getContext().setAuthentication(authentication);
} else {
if(!refreshToken.equals("")){
Long userId = tokenProvider.getUserId(refreshToken);
RefreshToken refreshTokenEntity = refreshTokenService.findByUserId(userId);
boolean validRefreshToken = tokenProvider.validToken(refreshTokenEntity.getRefreshToken());
if (validRefreshToken && refreshToken.equals(refreshTokenEntity.getRefreshToken())) {
User user = userJPARepository.findById(userId).get();
String newAccessToken = tokenProvider.generateToken(user, ACCESS_TOKEN_DURATION);
String newRefreshToken = tokenProvider.generateToken(user, REFRESH_TOKEN_DURATION);
refreshTokenService.saveRefreshToken(userId, newRefreshToken);
CookieUtil.addCookie(response, ACCESS_TOKEN_COOKIE_NAME, newAccessToken);
CookieUtil.addCookie(response, REFRESH_TOKEN_COOKIE_NAME, newRefreshToken);
Authentication authentication = tokenProvider.getAuthentication(newAccessToken);
SecurityContextHolder.getContext().setAuthentication(authentication);
}
}
}
}
3. WebSocket
์ฑํ
๋ฐ ์น๊ตฌ ๊ธฐ๋ฅ ์ฌ์ฉ์ ์ค์๊ฐ ๋ฐ์์ ์ํด WebSocket์ ์ฌ์ฉํ์ต๋๋ค. ํด๋น ๊ธฐ๋ฅ๋ค์ 1๋1 ํต์ ์ด๊ธฐ ๋๋ฌธ์ queue ๋ฐฉ์์ ์ด์ฉํด ๊ตฌํํ์ต๋๋ค.
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/friend").setAllowedOrigins("http://localhost:3000").withSockJS();
}
@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
registry.enableSimpleBroker("/queue");
registry.setApplicationDestinationPrefixes("/app");
}
}
---
@RestController
public class FriendWebSocketController {
private static Set userList = new HashSet<>();
private SimpMessagingTemplate simpMessagingTemplate;
@Autowired
public FriendWebSocketController(SimpMessagingTemplate simpMessagingTemplate){
this.simpMessagingTemplate = simpMessagingTemplate;
}
@MessageMapping("/friend/{id}")
public void sendMessage(@Payload FriendSocketMsgDTO friendSocketMsgDTO, @DestinationVariable Integer id){
this.simpMessagingTemplate.convertAndSend("/queue/FriendRequestToClient/"+ id, friendSocketMsgDTO);
}
@MessageMapping("/friend/join")
public void joinUser(@Payload Integer userId){
userList.add(userId);
}
}
EndPoint๋ฅผ ์ง์ ํด ํด๋น EndPoint๋ก ์์ฒญ์ ๋ฐ์ต๋๋ค.
`
join
`
์ ํตํด Socket ์๋ฒ์ ์ฐ๊ฒฐํ ํ ์ฐ๊ฒฐ๋ ์ฌ์ฉ์๋ก ๋ถํฐ ๋ฉ์์ง๋ฅผ ๋ฐ์ ์๋ต์ ๋ฐ์ ์ฌ์ฉ์์๊ฒ ๋ฉ์์ง๋ฅผ ์ ์กํฉ๋๋ค.
4. Crawling
์ ํฌ๋ ๋ค์ด๋ฒ ํด์ธ ์ถ๊ตฌ ๊ธฐ์ฌ๋ฅผ ํฌ๋กค๋งํด ์ฌ์ฉ์์๊ฒ ํ์ฌ์ ํซ์ด์๋ฅผ ๋ณด์ฌ์ฃผ๊ณ ์ ํ์์ต๋๋ค.
์ฌ์ฉ์๋ ๊ธฐ์ฌ๋ฅผ 5๊ฐ์ฉ ๋ณผ ์ ์์ผ๋ฉฐ, 15์ด ๋ง๋ค ์๋์ผ๋ก ๋์ด๊ฐ๋ฉฐ ์ด 25๊ฐ์ ๊ธฐ์ฌ๋ฅผ ๋ณด์ฌ์ค๋๋ค.
๋ฐ์ดํฐ๋ 3์ผ ์ด์์ด ๋๋ฉด ์๋์ผ๋ก ์ญ์ ๋๊ฒ๋ ํ์๊ณ , ์ค์ ์ ์ผ๋ก ์๊ฐํ ๋ถ๋ถ์ ์ถ๊ตฌ๋ ์ต์ ๊ธฐ์ฌ์ ๋ฏผ๊ฐํ๋ฏ๋ก
`
@Scheduled
`
์ ์ด์ฉํ์ฌ ํ๋ฃจ์ 4๋ฒ 6์, 12์, 18์, 24์ ํฌ๋กค๋ง๋๊ฒ๋ ์ ์ฉํ์์ต๋๋ค. ๊ทธ๋ฆฌ๊ณ DB์๋ ์์ฑ ์ผ์ ๋ด๋ฆผ์ฐจ์์ผ๋ก ์ ์ฅ๋๋ฉฐ, ๋ด๋ฆผ์ฐจ์์ผ๋ก ๋
ธ์ถ๋๊ฒ ๊ตฌํํ์ต๋๋ค.
5. CI/CD
Jenkins์ Docker๋ฅผ ์ด์ฉํด ๋ฐฐํฌ๋ฅผ ์งํํ์ต๋๋ค.
๊นํ๋ธ๋ฅผ ํตํด ์ด๋ฒคํธ๊ฐ ๋ฐ์ํ๊ฒ ๋๋ฉด ์นํ
์ ํตํด Jenkins์์ ์์ฒญ์ ์บ์นํด ๋์ปค ์ด๋ฏธ์ง๋ฅผ ๋น๋ํฉ๋๋ค. ๋น๋๊ฐ ์๋ฃ๋๋ฉด ๋น๋๋ ์ด๋ฏธ์ง๋ฅผ DockerHub๋ก pushํด ๊ฐ ์๋ฒ์์ ํด๋น ์ด๋ฏธ์ง๋ฅผ pull ๋ฐ์ ์๋ฒ๋ฅผ ์คํํฉ๋๋ค.
์ฌ์ฉ์์ ์์ฒญ์ด ๋ค์ด์์๋ ๋ฐ๋ก ์๋ฒ๋ก ์์ฒญ์ ๋ณด๋ด๋ ๊ฒ์ด ์๋ nginx๋ฅผ ๊ฑฐ์ณ ํฌ์ค ์ฒดํฌ๋ฅผ ํตํด ๋ก๋๋ฐธ๋ฐ์ฑ ์ฒ๋ฆฌํ์ฌ ํธ๋ํฝ์ ๋ถ์ฐ ์์ผฐ์ต๋๋ค.
๋ํ, ๋ฒ์ ์
์ผ๋ก ์ธํด ์๋กญ๊ฒ ๋ฐฐํฌ๋ฅผ ์งํํด์ผ ํ ๋ ์๋ฒ์ ์ค๋จ์ ๋ง๊ธฐ ์ํด ๋กค๋ง ๋ฐฉ์์ ๋์
ํด ๋ฌด์ค๋จ ๋ฐฐํฌ๋ฅผ ์ํํ์ต๋๋ค.