News Habit 프로젝트 정리
News Habit 프로젝트 정리

News Habit 프로젝트 정리

Created
Feb 5, 2024 10:21 AM
Last edited time
Last updated April 8, 2024
Tags
Backend
Spring
Crawling
Language
Java
Python
URL

Intro::

뉴스 해빗 프로젝트 관련 글들을 정리하고 모아놓은 글입니다.

크롤링

Naver Open API 검색

💡
입력한 query 에 대한 검색결과를 json 도는 xml 로 반환해준다.
뉴스 기사의 경우 기사의 전체 내용을 가져다 주지는 않기 때문에 직접 크롤링을 해야한다. 하지만 검색어와 관련된 뉴스 기사를 가져다 주기 때문에 키워드와 잘 결합하면 좋은 데이터를 쉽게 가져올 수 있다.
 

BeautifulSoup

from bs4 import BeautifulSoup
💡
간단하게 설명하면 html 파일에서 원하는 부분을 추출해오는 파싱 라이브러리이다.
soup = BeautifulSoup(html.text, "lxml") # a 태그중 attr 조건에 맞춰서 가져와 준다. headline_tag = soup.find_all('a', attrs={"class": "sa_text_title", "data-clk" : "airscont"})
크롤링 하고 싶은 페이지가 있다면 개발자 도구를 사용하여 html에서 가져오고 싶은 데이터의 태그를 찾아서 조건에 맞춰 가져오면 된다.
해당 데이터를 사용할때는 이용약관을 참고하자.
 

외부에 노출되면 안되는 정보 관리

💡
naver open api 에서 제공하는 id 와 secret key 값과 같은 개인 정보들을 사용해야하는 경우 json 파일을 활용하여 관리할 수 있다.
#config.json { "naver_api" : { "clientId" : "clientId12345", "clientSecret" : "password" }, "mysql" : { "user_id" : "user", "user_password" : "userpassword", "table" : "project" } }
 
💡
python 활용 예시
import json # 네이버 api 사용자 정보 가져오는 함수 def getConfigData(data): try: with open("./config.json", 'r') as f : jsonData = json.load(f) except Exception as e : print(e) exit(1) return jsonData[data]
 

Logging

💡
로깅을 구현할때 다음 블로그가 도움이 되었다.
 

Crontab

0 * * * * /opt/homebrew/bin/python3 /Users/{유저}/Desktop/projects/NewsHabit_Backend/crawling/src/main.py >> /Users/{유저}/Desktop/projects/NewsHabit_Backend/crawling/logs/crontab.log 2>&1
 

Spring

초기 설정

💡
스프링부트 이니셜라이저로 초기 설정을 하였다.
// application.yml dependencies { implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-validation' implementation 'org.springframework.boot:spring-boot-starter-web' implementation 'org.flywaydb:flyway-core' implementation 'org.flywaydb:flyway-mysql' implementation 'org.modelmapper:modelmapper:2.4.4' compileOnly 'org.projectlombok:lombok' developmentOnly 'org.springframework.boot:spring-boot-devtools' runtimeOnly 'com.mysql:mysql-connector-j' annotationProcessor 'org.projectlombok:lombok' testImplementation 'org.springframework.boot:spring-boot-starter-test' }

로깅

application.yml
💡
SLF4J(Simple Logging Facade for Java) 자체는 로깅 구현체가 아니라, 다양한 로깅 프레임워크에 대한 단순화된 추상 레이어를 제공한다. 따라서, 로그 파일 관리(예: 로그 파일 회전, 로그 파일 보관 기간 설정)는 SLF4J를 사용하는 구체적인 로깅 프레임워크(예: Logback, log4j2 등)의 설정을 통해 이루어진다.
💡
trace > debug > info > warn > error 순으로 단계가 구성된다.
logging: file: name: ${user.dir}/log/test.log level: root: debug logback: rollingpolicy: max-history: 30 max-file-size: 20MB
code
log.trace("trace"); log.debug("debug"); log.info("info"); log.warn("warn"); log.error("error"); // 이런 방식으로 로깅 가능

Exception Handler

💡
로깅과 함께 사용하면 에러 처리에 대한 처리를 강력하게 할 수 있다.
💡
ErrorCode 를 enum 으로 구현하고 ErrorResponse 를 사용해 활용한다면 Exception Handler에서 유용하게 사용 할 수 있다.
@ControllerAdvice 를 사용하여 global handler를 만들면 모든 @Controller 에서 발생하는 에러를 전역적으로 핸들링 할 수 있다.
GlobalExceptionHandler
@Slf4j @ControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler({BindException.class}) public ResponseEntity<ErrorResponse> validException(BindException ex) { log.error("bind error", ex.getBindingResult().getAllErrors().get(0)); ErrorCode ec = ErrorCode.VALID_FAILED; ec.setMessage(ex.getBindingResult().getAllErrors().get(0).getDefaultMessage()); ErrorResponse response = new ErrorResponse(ec); return new ResponseEntity<>(response, HttpStatus.BAD_REQUEST); } }
ErrorCode
public enum ErrorCode { /** Common **/ BAD_REQUEST(400, "CM001", "BAD REQUEST"), VALID_FAILED(400, "CM002", "Valid Test Failed."), BAD_ARGUMENT(400, "CM003", "Wrong Argument"), NOT_FOUND(404, "CM004", "NOT FOUND"), METHOD_NOT_ALLOWED(405, "CM005", "METHOD NOT ALLOWED"), NULL_POINT(500, "CM0006", "NULL POINT EXCEPTION"), INTERNAL_SERVER_ERR(500, "CM007", "INTERNAL SERVER ERROR"); private final int status; private final String errCode; private String message; public void setMessage(String msg) { this.message = msg; } }
ErrorResponse
public class ErrorResponse { private int status; private String message; private String code; public ErrorResponse(ErrorCode errorCode) { this.status = errorCode.getStatus(); this.message = errorCode.getMessage(); this.code = errorCode.getErrCode(); } }
 

Spring Security

💡
요청에 대한 조건 처리를 해줄 수 있다.

AWS 와 도커를 통한 배포환경 구축

궁금증

앱에서 요청을 보낼때 어떻게 보내는 건가?? 도메인이 없으면???
💡
aws를 통해 배정받은? IP 를 통해 요청받고 응답한다고 생각하면 된다. 도메인은 굳이 필요없다.
 

에러 대응

Error parsing HTTP request header 에러 오류
  • cloudfront 에서 ec2에 http 변환을 하는 과정에서 문제가 발생하는지 확인
    • 오리진 요청 파라미터 정책 변경 후 확인중 → 해결 X
    • 방법 찾는중….
정적 리소스 접근에 대한 요청이 Spring Security로 안막힘
Spring Security가 요청을 거부하기 전에, 요청이 정적 리소스 핸들러에 도달하고 거기서 처리되고 있음
  • WebMvcConfigurer 인터페이스 구현 → 해결 X
  • Spring Security 에서 디렉토리에 대한 경로를 먼저 막아준다음, 세부 경로를 허용해주어 해결

References::

Loading Comments...