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 에서 디렉토리에 대한 경로를 먼저 막아준다음, 세부 경로를 허용해주어 해결
Loading Comments...