프로젝트

개인별 프로젝트를 작성하여 발표, 제출함으로 기말 시험을 대체합니다.

개요

  • 웹 크롤링 및 데이터베이스 이용

준비

다양한 방법으로 프로젝트를 생성할 수 있습니다. 기본적인 것은 자바 프로젝트이고 그외에 메이븐(maven), 그레이들(gradle) 프로젝트를 이용할 수 있습니다. 메이븐, 그레이들은 자동화 빌드 도구들입니다.

  • 이클립스 프로젝트 만들기(그레이들 이용)

  • 외부 패키지 추가(jsoup, sellinium, sqlite)

  • 빌드 및 jar 파일 만들기

자바 프로젝트

자바 프로젝트를 생성할 때 기본적으로 쓰입니다. File > New > Java Project를 선택하면 됩니다.

외부 라이브러리 이용

외부 라이브러리를 사용할 수 있는 여러 가지 방법들이 있습니다.

내부 jar 파일

프로젝트 안에 jar 파일들을 이용하는 방법입니다.

  1. 프로젝트 이름 위에서 오른쪽 클릭 > New > Folder를 클릭하여 libs 폴더를 만듭니다.

  2. 필요한 라이브러리들을 인터넷을 통해 다운받아 libs 폴더에 저장합니다.

  3. 프로젝트 이름 오른쪽 클릭 > Build Path > Configure Build Path를 선택합니다.

  4. Libraries > Add JARs 클릭하여 위에서 만든 libs 폴더를 선택하여 필요한 jar 파일들을 추가합니다. 만일 libs 폴더에 jar 파일들이 없으면 libs 폴더가 나타나지 않을 수 있습니다.

외부 jar 파일

프로젝트 밖에 있는 jar 파일들을 이용하는 방법입니다.

  1. 프로젝트 이름 위에서 오른쪽 클릭 > Build Path > Add External Archives 클릭합니다.

  2. 원하는 폴더와 그 안에 있는 필요한 jar 파일들을 선택합니다.

  3. 프로젝트 밑에 Referenced Libraries 항목에 추가한 jar 파일들을 볼 수 있습니다.

다른 방법으로는 다음과 같이 할 수 있습니다.

  1. 프로젝트 이름 위에서 오른쪽 클릭 > Build Path > Configure Build Path 클릭합니다.

  2. Libraries 탭을 선택하고 Add External JARs를 선택합니다.

  3. 원하는 폴더와 그 안에 있는 필요한 jar 파일들을 선택합니다.

  4. 프로젝트 밑에 Referenced Libraries 항목에 추가한 jar 파일들을 볼 수 있습니다.

jar 파일 만들기

프로젝트 이름 위에서 오른쪽 클릭 > Export > Java > Runnable JAR file 또는 Jar file을 선택합니다.

gradle 프로젝트

File > New > Project를 클릭하여 Gradle 항목에서 Gradle Project를 선택합니다. Finish를 누르면 자동으로 필요한 패키지를 설치합니다. 약간의 시간이 걸릴 수 있습니다.

외부 패키지 추가

  1. jsoup 패키지를 프로젝트에서 사용하고 싶으면 build.gradle 파일을 열어 dependencies 부분에 다음을 추가합니다.

    implementation 'org.jsoup:jsoup:1.11.3'
    
  2. 프로젝트 창에서 프로젝트를 오른쪽 클릭하여 Gradle > Refresh Gradle Project를 클릭하여 jsoup 패키지를 다운받는다.

  3. Project and External Dependencies에 보면 jsoup-1.11.3.jar 파일이 보일 것입니다.

  4. 자동으로 패키지를 인식하게 하려면, 메뉴 Window > Preferences > Gradle (> Configure Workspace Settings)를 클릭하여 Automatic Project Synchronization을 선택하면 됩니다.

빌드 실행

그레이들 빌드를 실행하기 위해서는 Gradle Tasks 항목에 build 를 오른쪽 클릭하여 실행을 누르면 됩니다.

패키지 만들기

프로젝트 위에서 오른쪽 클릭을 하여 New > Package를 누른 후 적당한 이름을 입력합니다. 이름은 도메인이 큰 곳에서 작은 곳으로 입력합니다. 예를 들어 kr.koreauniv.imath.pkgtest와 같이 입력합니다.

프로젝트 배포

jar 파일을 만들어 배포합니다. gradle의 태스크 중에서 jar 태스크를 실행하면 build/libs에 jar 파일이 생성 됩니다.

실행 가능한 jar

실행 가능한 jar 파일을 만들려면 jar 부분 manifest의 속성으로 Main-Class에 시작 가능한 main 메소드가 있는 클래스를 지정해야 합니다.

jar {
  manifest {
    attributes "Main-Class": "kr.koreauniv.imath.pkgtest.Main"
  }

  from {
    configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
  }
}

위에서 from은 gradle의 테스크인 Jar의 메소드로서 복사할 파일의 위치를 지정합니다.

gradle jar 테스크를 실행하면 /build/libs에 jar 파일이 만들어진다. 이것을 실행하기 위해서는 다음과 같이 합니다.

java -jar 프로젝트.jar

외부 패키지 포함한 실행가능한 jar

하지만 외부 패키지가 포함되어 있으면 실행할 때 패키지가 없다고 에러를 낸다. 이 에러를 해결하는 방법은 두 가지로 생각해 볼 수 있습니다.

첫번째는 외부패키지가 모두 포함된 jar 파일을 만드는 것입니다. 이러한 jar파일을 뚱뚱한 jar(fat-jar)라고 부른다. 이것은 shadow 플러그인을 사용할 수 있습니다. build.gradle 파일 안에 다음과 같이 삽입합니다.

apply plugin: 'com.github.johnrengelman.shadow'

buildscript {
  repositories {
    jcenter()
  }

  dependencies {
    classpath 'com.github.jengelman.gradle.plugins:shadow:4.0.2'
  }
}

jar {
  finalizedBy shadowJar // 이부분이 자동으로 fat-jar를 만들어 준다.

  manifest {
    attributes 'Main-Class': 'com.dowellware.dyoon.pkgtest1.GradleTest'
  }
}

라이브러리 클래스 경로에 추가

두번째로는 jar 파일을 실행할 때 클래스 경로를 직접 지정해서 실행하는 방법이 있습니다. 이것이 작동하려면 종속 패키지들이 모두 다운받아 있어야 합니다. 가령 jsoup-1.11.3.jar 파일이 종속되어 있는 mypackage.jar 안의 kr.koreauniv.imath.MyMain 클래스를 실행하려면 다음과 같이해야 합니다.

java -cp ./jsoup-1.11.3.jar;./mypackage.jar kr.koreauniv.imath.MyMain

jsoup와 mypackage jar 파일이 현재 디렉토리에 있다는 가정입니다.

한글 인코딩 문제

패키지를 배포할 때 한글이 있는 코드는 다른 곳에서 사용할 때 깨져서 나올 수 있습니다. 이럴 때는 build.gradle 파일에 다음을 삽입해서 그레이들이 빌드할 때 문제가 생기지 않도록 합니다.

buildscript {
  tasks.withType(JavaCompile) {
    options.encoding = "UTF-8"
  }
}

gradle 이전 버전을 사용할 때는 다음을 build.gradle 파일 안에 적습니다.

compileJava.options.encoding = "UTF-8"
compileTestJava.options.encoding = "UTF-8"

이클립스 디버깅

디버깅(debugging) 또는 디버그(debug)는 컴퓨터 프로그램의 논리적인 오류(버그)를 검출하여 제거하는 과정을 뜻합니다. 자바 디버깅은 이클립스를 이용하여 쉽게 할 수 있습니다.

이클립스에서 설명을 합니다.

  1. 디버깅 하려는 파일의 원하는 라인 왼쪽 부분에 마우스 오른쪽 클릭을 하여 Toggle Breakpoint를 선택합니다. 그러면 작은 원이 표시가 됩니다. 이것이 중단점(breakpooint)입니다.

  2. 메뉴 아이콘 부분에 벌레 모양의 아이콘을 누르면 방화벽과 외관을 변경(switch)할 것이냐고 물으면 모두 허락을 누릅니다.

  3. 그러면 잠시후 앞에서 설정했던 중단점까지 프로그램을 실행한 후 기다리고 있는 것을 알 수 있습니다.

  4. 오른쪽 변수(variables) 확인 창에서 변수들을 확인할 수 있습니다.

  5. 다음 라인으로 진행하려면 메뉴 아이콘 중에서 Step Over(F6)를 누르면 됩니다.

  6. 다음 중단점까지 실행하려면 초록색 직사각형 삼각형(Resume)을 누르면 됩니다.

  7. 하단 Debug Shell을 이용하면 직접 코드를 실행할 수 있습니다.

고려대 세종 캠퍼스 셔틀버스 시간표

목표

고려대 세종 캠퍼스 셔틀 버스 시간표를 파싱하여 sqlite 데이터베이스에 저장하고 출력하는 프로그램을 작성합니다.

클래스 설명

셔틀 시간표를 파싱하여 데이터베이스에 저장하고 출력하는데 필요한 클래스들입니다. 과제를 할 때 적어도 아래에 있는 클래스와 메소드들을 작성해야 합니다.

ShuttleMain

메인 메소드를 이용해서 실행합니다. 메인에서는 웹페이지 셔틀 버스를 파싱하여 디비에 저장하고 출력하는 프로그램을 작성합니다.

ShuttleCrawl

세종 홈페이지에 접속해서 셔틀 시간표를 파싱

메소드

설명

public ArrayList<ShuttleDto> getShuttleTable()

페이지를 파싱하여 ArrayList<ShuttleDto>을 반환합니다.

public void addShuttleTableToDb(ArrayList<ShuttleDto>)

데이터베이스 테이블에 삽입을 합니다.

ShuttleDto

데이터 전송 객체(Data Transfer Object)로 데이터베이스 테이블에 자료를 넘기기 위한 클래스입니다.

필드

설명

no

번호

station

조치원역

school

학교

note

비고

메소드

설명

getXxx()

필드에 해당하는 get 메소드들입니다.

setXxx()

필드에 해당하는 set 메소드들입니다.

ShuttleDao

데이터베이스 접근 객체(Data Access Object)로 데이터베이스 연결, 추가, 변경, 선택 관련 메소드들을 구현하는 클래스입니다.

메소드

설명

public Connection getConnection()

데이터베이스 연결

public void close()

데이터베이스 연결 해제

public ShuttleDto getByNo(int no)

no에 해당하는 ShuttleDto 반환

public void add(ShuttleDto dto)

ShuttleDto 객체가 가지고 있는 정보를 데이터베이스에 저장

public ArrayList<ShuttleDto> getAllList()

데이터베이스 테이블의 모든 정보를 반환

public void update(ShuttleDto dto)

ShuttleDto 객체의 정보를 업데이트

public void deleteByNo(int no)

no에 해당하는 레코드를 삭제

농수산물 가격 정보

농수산물 유통정보 사이트(KAMIS)에서 월간 가격정보에 대한 모든 경우를 선택하는 프로그램을 작성합니다.

KamisCrawl 클래스에 구현할 필드는 다음과 같습니다.

필드

설명

WebDriver driver

driver는 전역으로 설정하고 생성자 메소드에서 ChromeDriver로 초기화합니다.

KamisCrawl 클래스에 구현할 메소드는 다음과 같습니다.

메소드

설명

public KamisCrawl()

생성자 메소드로 크롬드라이버 시스템 설정 및 웹드라이버를 초기화합니다.

public void selectPeriod()

페이지에서 기간을 설정합니다. Scanner를 이용해서 키보드로부터 년도와 기간을 입력받습니다.

public void selectCounty()

지역을 차례로 클릭하도록 합니다.

public void selectCategory()

부류를 차례로 클릭하는 메소드입니다.

public void selectItem()

품목을 차례로 클릭하는 메소드입니다.

public void selectKind()

품종을 차례로 클릭하는 메소드입니다.

public void selectRank()

등급을 차례로 클릭하는 메소드입니다.

public void close()

웹드라이버를 종료하여 웹 브라우저를 닫습니다.

public static void main(String[] args)

KamisCrawl 객체를 생성하고 selectPeriod 메소드를 호출하여 년도와 기간을 입력받은 후에 selectCounty 메소드를 호출하여 모든 경우에 대한 클릭을 수행하도록 합니다. 마지막으로 close 메소드를 호출하여 브라우저를 종료합니다.

  • 예외(Exception)가 발생할 것을 대비해 모든 selectXxx 메소드는 적절한 예외를 던지는(throws) 문장을 구현해야합니다.

요리법 파싱

12월 4일 과제

위 사이트 https://www.haemukja.com/recipes 에 있는 요리법을 해먹지수순으로 정렬한 후에 2개의 요리법에 대해서, 아래 데이터베이스 필드에 나오는 내용들을 출력하는 프로그램을 작성하시면 됩니다. 블로거 아이디(bloggerId)는 나중에 설명할테니 생략해도 됩니다.

마지막 과제

아래 주어진 조건에 맞도록 프로그램을 해서 100개 이상의 요리법을 디비에 저장하고 RecipeMain에 주어진 메소드에 맞게 출력하면 됩니다. 아래에 각 클래스에 주어진 메소드들은 반드시 구현해야하고 필요한 것이 있으면 더 구현해도 됩니다.

데이터베이스

  • 테이블 이름: recipe

필드

타입

설명

id

INTEGER

레코드 아이디

title

TEXT

요리 제목

bloggerName

TEXT

블로거 이름

bloggerId

TEXT

블로거 아이디 번호

cookTime

INTEGER

요리 시간

scrap

INTEGER

스크랩 수

calory

REAL

칼로리

site

TEXT

블로거 사이트(블로거 이름 아래에 나옵니다. 블로거에 따라 없을 수도 있습니다.)

ingredients

TEXT

재료 리스트

nutrition

TEXT

영양 정보

tag

TEXT

태그

instruction

TEXT

요리법

image

BLOB

사진(선택 사항)

클래스

RecipeMain, RecipeCrawl, RecipeDto, RecipeDao 클래스들을 작성합니다.

클래스

설명

RecipeMain

과제를 수행하는 메소드와 메인을 포함하는 클래스입니다.

RecipeCrawl

사이트를 파싱하고 디비에 저장하는 클래스입니다.

RecipeDto

디비에 주어진 필드에 대응하는 필드들을 생성하고 get, set 메소드를 만듭니다.

RecipeDao

디비와 관련된 메소드들을 포함하는 클래스입니다.

RecipeMain 클래스

RecipeMain 클래스에 구현할 메소드는 다음과 같습니다.

메소드

설명

public void printSearch(String text)

요리법 설명(디비에서 instruction 필드에 해당) 중에 문자열 text를 포함하는 요리법 리스트를 디비에서 가져와 출력합니다.

public void printSortByBloggerRecipes()

블로거들이 올린 요리법의 갯수에 대한 내림차순으로 정렬된 결과를 디비에서 가져와 bloggerName: count 쌍으로 출력합니다.

public void printRecipes(String bloggerName)

bloggerName이 작성한 모든 요리법들을 디비에서 가져와 출력합니다.

public static void main(String[] args)

RecipeCrawlparseAndSave() 메소드를 실행해서 디비에 파싱 결과를 디비에 저장합니다.

RecipeDao 클래스

RecipeDao 클래스에 구현할 메소드는 다음과 같습니다.

메소드

설명

public List<RecipeDto> search(String text)

요리법 설명(디비에서 instruction 필드에 해당) 중에 문자열 text를 포함하는 요리법 리스트를 반환합니다.

public List<RecipeDto> getRecipes(String bloggerName)

bloggerName이 작성한 모든 요리법들을 반환합니다.

public HashMap<String, Integer> sortByBloggerRecipes()

블로거들이 올린 요리법의 갯수에 대한 내림차순으로 정렬하여 <bloggerName, count> 쌍으로 된 HashMap을 반환합니다. 여기서 countbloggerName에 해당하는 요리법의 갯수입니다.

RecipeCrawl 클래스

RecipeCrawl 클래스에 구현할 필드는 다음과 같습니다.

필드

설명

WebDriver driver

driver는 전역으로 설정하고 생성자 메소드에서 ChromeDriver로 초기화합니다.

RecipeCrawl 클래스에 구현할 메소드는 다음과 같습니다.

메소드

설명

public RecipeCrawl()

생성자 메소드로 크롬드라이버 시스템 설정 및 웹드라이버를 초기화합니다.

public void parseAndSave()

사이트를 파싱하여 100개 이상의 요리법을 디비에 저장합니다.

public String getNumber(String text, String pattern)

text 문자열과 정규표현식 pattern을 입력하면 문자열 text 안에 있는 패턴에 맞는 숫자를 문자열로 반환합니다.

public void close()

웹드라이버를 종료하여 웹 브라우저를 닫습니다.

public static void main(String[] args)

RecipeCrawl 객체를 생성하고 메소드를 호출하여 …, 마지막으로 close 메소드를 호출하여 브라우저를 종료합니다.