# 콘솔창

10월 17, 2021 2:02:10 오전 org.junit.platform.launcher.core.EngineDiscoveryOrchestrator lambda$logTestDescriptorExclusionReasons$7

정보: 0 containers and 3 tests were Method or class mismatch

 

인텔리J 로 테스트케이스를 작성하는데 자꾸 나오는 문구!!

그렇다고 테스트 케이스가 실패나거나 안되는건 아닌데,

콘솔에 자꾸 빨간색으로 나오니 신경쓰여서 찾아보았다

 

 

원인

 

이 오류는 여러개의 테스트케이스를 작성해놓고

인텔리J 편의기능으로 하나의 테스트만 눌러서 실행했을 때 발생하는 것을 확인했다.

 

정확하게 확신은 없지만.. (댓글로 설명해주시면 수정할게요! ㅎㅎ)

 

인텔리J 편의 기능을 사용해서 하나의 테스트만

콕 집어서 테스트케이스를 실행하면

어쨌든 빌드는 해야하는데 전체 빌드하는 것도 아니고 하니

인텔리J가 자체의 빌드기능으로 빌드를 해서 실행해주는 것 같다.

 

내 설정의 기본 빌드툴은 Gradle인데 

갑자기 다른 빌드툴로 빌드를 하니

Method가 Missmatch 났다고 알려주는 것같다.

 

 

참고 : https://www.inflearn.com/questions/157200

 

 

 

 

 

 

 

 

 

해결방법

빌드툴을 그냥 인텔리J 꺼로 쓰라고 변경해주면

이런 MissMatch가 없어지는 것 같다.

 

위의 설정을 아래와 같이 변경하면 된다.

 

 

 

 

도움이 되는 글이었다면

로그인이 필요없는 공감 버튼 꾹 눌러주세요! 

 

 

 

 

 

 

 

 

 

[SPRING/Mybatis] POI를 이용한 대용량 데이터 추출 (엑셀 다운) -1

오랜만에 티스토리에 개발관련 기록을 남기는 것같다. 디비의 값을 엑셀로 다운로드을 수 있도록 해달라는 요청이 있었다. (요즘은 Android를 파는 중이지만...) 요청은 하나의 대상 테이블에 대한

kyome.tistory.com

 

이전 게시글에 이어서,

이제 ResultHandler 를 작성한다.

 

0. ResultHandler (ExcelHandler.java)

 

ResultHandler는 handleResult라는 메서드를

Override 하기만 하면 쉽게 사용할 수 있다.

handleResult는 데이터가 들어오는대로

건마다 호출되는 걸로 보인다.

 

 

1. 변수 및 생성자 선언

 

ResultHandler는 Generic으로 선언할 수 있고 

내가 만들 ExcelHandler는 Map으로 받아져야하기 때문에 

Generic 변수 T는 Map을 상속받는 변수야한다는 조건을 걸었다.

 

ResultHandler를 통해 다운로드를 받을 수 있도록 할 계획이기 때문에

생성자로 Response를 받으며 파일명이나

컬럼 순서를 받을 수 있도록 생성자를 추가했다.

 

import ...

public class ExcelHandler<T extends Map<String,Object>> implements ResultHandler<T> {
	public static final Logger LOGGER = LoggerFactory.getLogger(ExcelHandler.class);
	
	private T result;
	private String title;
	private String filename;
	private SXSSFWorkbook  workbook;
	private SXSSFSheet  sheet;
	private HttpServletResponse response;
	private ResultContext<? extends T> context;
	private List<String> columnTitleList;
	private int rownum;
	
	final int TITLE = 0;
	final int BODY = 1;

	
	private ExcelHandler() {
		super();
		rownum = 0;
	}
	
	public ExcelHandler(HttpServletResponse response, String filename) {
		this();
		this.response = response;
		this.title = filename;
		try {
			this.filename = URLEncoder.encode(filename.replace(" ", "_"),"UTF-8");
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		};
		workbook = new SXSSFWorkbook(10000);
		sheet = workbook.createSheet(title);
	}
	
	public ExcelHandler(HttpServletResponse response, 
    	String filename,List<String> orderedColumnTitleList) {
		this(response,filename);
		this.columnTitleList = orderedColumnTitleList;
	}

	...
    

 

 

 

 

 

 

 

 

2.  엑셀에 쓰기 메서드 구현

 

DB 에서 조회한 결과의 Column이 몇 개이고 이름이 무엇이든 상관없이

독립적으로 실행이 되어야 재사용이 가능해지기 때문에 

 

엑셀에 입력하는 기능에만 집중했고 

나머지는 파라미터로 받도록 했다.

 

private void write(int type,int currentRow,CellStyle style) {
		
	if (columnTitleList == null) {
		columnTitleList = new ArrayList<String>(context.getResultObject().keySet());
	}
	SXSSFRow row = sheet.createRow(currentRow);
	
	if(columnTitleList.size() == 0 ) {
		return;
	}
	
	for(int i = 0 ; i < columnTitleList.size() ; i++) {
		SXSSFCell cell = row.createCell(i);
		String tempValue = "";
		
		switch (type) {
			case TITLE:
				tempValue = columnTitleList.get(i);
				break;
			case BODY:
				if(context.getResultObject().containsKey(columnTitleList.get(i))) {
					tempValue = context.getResultObject().get(columnTitleList.get(i)).toString();
				}
				
				break;
		}
//		스타일 객체가 없다면 기본으로
		if(style != null) {
			cell.setCellStyle(style);
		}
		cell.setCellValue(tempValue);	
	}
}
	

 

 

 

3. handleResult Override

 

데이터가(한개의 행이) 호출 될 때마다 workbook에 입력해주고

현재의 행을 나타내는 변수를 ++ 해준다.

 

헤더전용 CellStyle 과 내용전용 CellStyle을 

미리 선언해두어서 write에 마지막 파라미터로 넣어주면

필요에 따라 셀스타일을 변경하면서 입력할 수도 있다.

 

	...

@Override
public void handleResult(ResultContext<? extends T> resultContext) {
	if(resultContext.getResultObject() == null) {
		return;
	}
	this.context = resultContext;
	result =  context.getResultObject();
	
	
	Font headerFont = workbook.createFont();
	headerFont.setFontName("맑은 고딕");
	headerFont.setBold(true);
       
	CellStyle headerStyle = workbook.createCellStyle();
	headerStyle.setBorderTop(BorderStyle.THIN);
	headerStyle.setBorderBottom(BorderStyle.THIN);
	headerStyle.setBorderLeft(BorderStyle.THIN);
	headerStyle.setBorderRight(BorderStyle.THIN);
        
	headerStyle.setAlignment(HorizontalAlignment.CENTER);
	headerStyle.setVerticalAlignment(VerticalAlignment.CENTER);
	headerStyle.setFillForegroundColor(IndexedColors.LIGHT_CORNFLOWER_BLUE.getIndex());
	headerStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
	headerStyle.setFont(headerFont);

	Font bodyFont = workbook.createFont();
	bodyFont.setFontName("맑은 고딕");
        
	CellStyle bodyStyle= workbook.createCellStyle();
	bodyStyle.setBorderTop(BorderStyle.THIN);
	bodyStyle.setBorderBottom(BorderStyle.THIN);
	bodyStyle.setBorderLeft(BorderStyle.THIN);
	bodyStyle.setBorderRight(BorderStyle.THIN);
        
	bodyStyle.setAlignment(HorizontalAlignment.LEFT);
	bodyStyle.setFont(bodyFont);
		
	if(rownum == 0 ) {			
		write(TITLE, rownum,headerStyle);
		write(BODY, rownum+1,bodyStyle);
	}else {
		write(BODY, rownum+1,bodyStyle);
	}
	rownum++;
}

...

 

 

 

 

 

 

4. 엑셀 다운로드

 

생성자로 Response 객체를 받는 이유는 여기에 있다.

Response 객체의 헤더에 첨부파일을 넣어서 

OutStream으로 파일을 내보낸다.

 

파일 처리는 항상 그렇듯 예외처리를 성실하게 해줘야하고

종료시에 close 를 호출해줘야한다.

 

	...
    
public void download() throws IOException{
	LOGGER.debug("## start excel download : "+filename);
	response.setHeader("Content-Disposition", "attachment; filename=" 
        				+ filename.replaceAll(" ", "_") + ".xlsx;");
	response.setCharacterEncoding(Constants.ENCODING);
		
	ServletOutputStream stream = response.getOutputStream();
	OutputStream out = new BufferedOutputStream(stream);
	
	try {
		response.resetBuffer();
		response.setBufferSize(1024 * 4);
		workbook.write(out);
		
	} catch (Exception e) {
		out.flush();
		out.close();
		stream.close();
	} finally {
		out.flush();
		out.close();
		stream.close();
	}
	
	if (workbook != null) {
		try {
			workbook.dispose();
		} catch (Exception e) {
			workbook.close();
		} finally {
			workbook.close();
		}
	}
	workbook.close();
}

public void close() {
	workbook.dispose();
	try {
		workbook.close();
	} catch (IOException e) {
		e.printStackTrace();
	}
}

...

 

 

 

 

 

도움이 되었다면

로그인이 필요 없는 공감 버튼 꾹 눌러주세요! 

 

 

 

 

오랜만에 티스토리에 개발관련 기록을 남기는 것같다.

디비의 값을 엑셀로 다운로드을 수 있도록 해달라는 요청이 있었다.

(요즘은 Android를 파는 중이지만...)

 

요청은 하나의 대상 테이블에 대한 엑셀 다운로드 구현이지만

어차피 개발할 거라면 재사용할 수 있도록 개발했다.

 

 

 

 

 

 

 

 

 

 

0. 의존성 추가 (pom.xml)

 


...
		<!-- excel -->
		<dependency>
		    <groupId>org.apache.poi</groupId>
		    <artifactId>poi</artifactId>
		    <version>4.1.1</version>
		</dependency>
		
		<dependency>
		    <groupId>org.apache.poi</groupId>
		    <artifactId>poi-ooxml</artifactId>
		    <version>4.1.1</version>
		</dependency>
...

 

 

 

 

1. SQL (ExcelMapper.xml)

 

엑셀 다운로드용 쿼리를 모아둘 목적으로 XML 파일을 생성했다.

 

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="kr.co.excel.dao.ExcelMapper">
	<resultMap id="excelListDownloadMap" type="java.util.HashMap" >
    	<result column="CONTENT_NO"     	property="번호"    	jdbcType="INTEGER" />
    	<result column="CONTENT_TITLE"     	property="제목"    	jdbcType="VARCHAR" />
    </resultMap>

    <select id="contentListDownload" resultMap="excelListDownloadMap">
		<![CDATA[
			SELECT CONTENT_NO ,CONTENT_TITLE
			FROM TB_CONTENT
			WHERE CONTENT_NO < 100
		]]>
	</select>
</mapper>

 

 

 

2.  DAO (ExcelMapper.java)

 

현재 개발환경에서는 Mapper 를 사용하기 때문에

interface로 간단하게 DAO를 선언할 수 있다.

반환값을 void, 파라미터를 ResultHandler로 선언하면

Mybatis에서 조회되는 값을 바로 핸들링할 수 있다.

 

(ResultHandler 클래스를 잘 짜놓는다면...ㅎㅎㅎ)

ResultHandler는 너무 길어지니 이어지는 게시글에 자세히 적는걸로!

 

import java.util.Map;

import org.apache.ibatis.session.ResultHandler;
import org.springframework.stereotype.Repository;

@Repository
public interface ExcelMapper {
	public void contentListDownload(ResultHandler<Map<String,Object>> ExcelHander);
}

 

 

 

 

 

 

3. Service (ExcelService.java)

 

난 서비스를 ResultHandler과 DAO의 매핑 공간으로 사용했다.

매핑을 해놓으면 해당 메서드를 호출할때

ExcelHandler에 조회 결과가 매핑되는 걸로 보인다.

난 이 ResultHandler를 통해 다운로드 받을 엑셀 형식을 정의하고

다운로드 로직을 ResultHandler 에 넣어놓았다. (excelHandler.download())

 

import java.io.IOException;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import kr.co.excel.dao.ExcelMapper;

@Service
public class ExcelService {
	@Autowired
	private ExcelMapper excelMapper;
	
	ExcelHandler<Map<String,Object>> excelHandler;
	
	public void contentListDownload(
			HttpServletRequest request,
			HttpServletResponse response){
		excelHandler = new ExcelHandler<>(response,"테스트");
		excelMapper.contentListDownload(excelHandler);
		
		try {
			excelHandler.download();
		} catch (IOException e) {
			e.printStackTrace();
			excelHandler.close();
		}
	}
}

 

 

 

 

 

4. Controller (ExcelController.java)

 

View페이지가 별도로 필요없는 RestController를 선언했다. 

엑셀 다운로드시 Response 객체가

필요하기 때문에 파라미터로 선언해놓았다.

Request 객체는 추후에 필요할 듯 싶어서

넣어 놓았을 뿐 당장은 필요없다.

 

import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import kr.co.excel.service.ExcelService;

@RestController
public class ExcelController {
	
	@Autowired
	ExcelService excelService;
	
	@RequestMapping(value = "/contentListDown.do")
	public void contentListDownload(
			HttpServletRequest request,
			HttpServletResponse response){
		excelService.contentListDownload(request,response);
	}
}

 

 

 

 

도움이 되었다면

로그인이 필요 없는 공감 버튼 꾹 눌러주세요! 

 

 

 

 

 


 

[SPRING/Mybatis] POI를 이용한 대용량 데이터 추출 (엑셀 다운) -2

 

[SPRING/Mybatis] POI를 이용한 대용량 데이터 추출 (엑셀 다운) -2

[SPRING/Mybatis] POI를 이용한 대용량 데이터 추출 (엑셀 다운) -1 오랜만에 티스토리에 개발관련 기록을 남기는 것같다. 디비의 값을 엑셀로 다운로드을 수 있도록 해달라는 요청이 있었다. (요즘은 A

kyome.tistory.com


 

 

 

 

JUnit을 적용하기 시작하면서 제일 처음 마주한 에러였다.

야심 차게 TDD 적용을 꿈꾸며

@Test 애노테이션을 넣고 실행했는데

다음과 같은 에러가 발생했다.

 

 

 

 

 

 

 

에러 로그

java.lang.ExceptionInInitializerError
	at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
	at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
	at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
	at org.junit.internal.builders.AnnotatedBuilder.buildRunner(AnnotatedBuilder.java:31)
	at org.junit.internal.builders.AnnotatedBuilder.runnerForClass(AnnotatedBuilder.java:24)
	at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:57)
	at org.junit.internal.builders.AllDefaultPossibilitiesBuilder.runnerForClass(AllDefaultPossibilitiesBuilder.java:29)
	at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:57)
	at org.junit.internal.requests.ClassRequest.getRunner(ClassRequest.java:24)
	at org.eclipse.jdt.internal.junit4.runner.JUnit4TestLoader.createUnfilteredTest(JUnit4TestLoader.java:87)
	at org.eclipse.jdt.internal.junit4.runner.JUnit4TestLoader.createTest(JUnit4TestLoader.java:73)
	at org.eclipse.jdt.internal.junit4.runner.JUnit4TestLoader.loadTests(JUnit4TestLoader.java:46)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:522)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:760)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:460)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:206)
Caused by: java.lang.IllegalStateException: Failed to find class [org.junit.runners.model.MultipleFailureException]: SpringJUnit4ClassRunner requires JUnit 4.9 or higher.
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.<clinit>(SpringJUnit4ClassRunner.java:102)
	... 17 more

 

 

ExceptionInInitExceptionInInitializerError 라는

생소한 에러를 마주하니

당황스러웠다..

전혀 감이 안잡혔다.

 

그렇지만 차분하게 읽어보니

아주 아주 친절하게 해결방법이 

적혀있었다.

 

 

 

 

 

 

 

 

해결

 

 

에러 로그를 자세히 보니

SpringJUnit4ClassRunner requires JUnit 4.9 or higher.라는

내용이 친절하게 나와있다.

JUnit4를 사용하고 싶다면 4.9 이상의

버전으로 세팅되어 있어야 한다.

 

 

<dependency>
	<groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.9</version>
    <scope>test</scope>
</dependency>

 

위의 내용과 같이 

4.9 버전으로 세팅을 다시 해주니 

정상적으로 잘 작동하는 것을 확인할 수 있었다!

 

 

JUnit은 버전도 다양하고 호환성에

아주 예민한 패키지인 것 같다.

 

 


 

 

도움이 되었다면

로그인이 필요 없는 공감 버튼 꾹 눌러주세요! 

 

 

 

SpringJUnit4ClassRunner.class의 빨간 줄

 

Spring에 JUnit을 적용하기 위해서는 찾아보던 중

적용하기 위해서는 

RunWith(SpringJUnit4ClassRunner.class)

애노테이션을 클래스 위에 

선언해주어야 한다길래 

그대로 했더니 아래 캡처와 같이 빨간 줄이 떴다..

 

 

그리고 빨간줄이 없어지질 않는다!! ㅠㅠ

 

 

저렇게 이클립스상에 빨간 줄로 표시되는 경우는 보통

필요로 하는 내용과 다른 정보를 넣었거나

존재하지 않은 내용을 넣었거나..

어쨌든 무언가 틀렸다는 내용이다.

 

 

 

 

 

 

 

해결

 

관련해서 찾아보니

시스템이 정상적으로 돌아갈 정도로 

spring 프레임워크 환경을 구축했다고 해서 

JUnit을 사용할 수 있는 게 아니었다.

 

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-test</artifactId>
    <version>4.2.9.RELEASE</version>
</dependency>

 

JUnit을 사용하기 위해서는 

spring-test라는 이름의 의존성을 주입해주어야 한다.

 

 

나는 지금까지 JUnit을 고려하지 않았기 때문에

특별히 큰 문제없이 개발했을 뿐 

JUnit을 사용하기 위해서는 spring-test이 꼭 필요하다.

 

 


 

 

포스팅이 도움이 되었다면

로그인이 필요 없는 공감 버튼 꾹 눌러주세요! 

 

 

개발하고 있는 서버에 JUnit을 적용하고

Mock 클래스를 사용해서 MVC에 대한

테스트 환경을 구축하였더니

다음과 같은 에러가 발생하였다.

 

 

에러 콘솔 캡처

 

 

 

에러 로그

java.lang.NoClassDefFoundError: javax/servlet/SessionCookieConfig

…

Caused by: java.lang.ClassNotFoundException: javax.servlet.SessionCookieConfig
	at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
	at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
	... 32 more

 

 

에러만 해석해보자면

JSP를 사용하기 위해 필요한 패키지인 servlet 안에

SessionCookieConfig 클래스가 없어서 나는 에러이다.

 

이런 문제는 보통 버전에서 오는 경우가 많은 것 같아서 

찾아보니 역시 버전 호환성의 문제였다.

 

 

 

 

 

 

 

나는 현재 servlet-api 2.5버전을 사용하고 있었는데 

너무 옛버전이라서 불가능하다고 한다.

 

 

Junit 사용 불가 버전

 

 

 

MockHttpSession을 사용하기 위해서는

최소 3.1.0 버전을 사용해야 한다.

 

메이븐에서 검색해보니 

dependency 작성 규칙도 바뀌어 있었다

2.5 버전은 확실히 너무 옛 버전인 것 같다...

 

 

 

해결

 

<dependency>
	<groupId>javax.servlet</groupId>
	<artifactId>javax.servlet-api</artifactId>
	<version>3.1.0</version>
    <scope>provided</scope>
</dependency>

 

상위 버전으로 의존성만 변경하니 

문제없이 잘 작동한다.

 

 


 

 

 

 

포스팅이 도움이 되었다면

로그인이 필요 없는 공감 버튼 꾹 눌러주세요! 

 

 

 

 

자바 개발을 하다보면 날짜 형태에 

맞추어 String으로 저장된 값에 

날짜를 더하거나 빼야할 때가 많다.

 

처음부터 String 형태로 DB에 

저장하는 경우도 많고

 

Controller에서 DB값을 받았을 때, 

이미 SQL로 TO_CHAR( )을 적용한 값을 

받게되는 경우도 있기 때문에 

 

String 으로 Date를 만드는 

방법을 익혀두는게 

마음 편하다.

 

 

 

 


 

" String to Date "

 

 

 

1. DateFormat 선언하기

 

날짜 문자열이 "2020.10.01" 형태로 

들어온다고 가정할 때,

날짜데이터를 잘 구분할 수있도록

형태에 맞추어 DateFormat을

미리 지정해 주어야 한다.

 


DateFormat dateFormat = new SimpleDateFormat ("yyyy.MM.dd"); 

 

 

 

 

 

 

2. Date 형태로 변환하기

 

이제 DateFormat이 제공하는

parse 메소드를 사용해서

Date 인스턴스를 생성한다.

 

파라미터로 String 데이터를 넣으면

그 형태에 맞는 Date 인스턴스를 반환한다.

 


Date endDate = dateFormat.parse("2020.10.01"); 

 

Date를 다룬다고 생각하고

마음편하게 사용하면 된다.

 

 

 

 

 

html의 공간에서 layout 잡는 방법은 정말 다양하다. 

flexbox를 사용해서 layout을 잡고 정렬을 하기도 하고  
극단적으로는 table로 잡기도한다. 

오늘은 html 페이지에서 가로 영역을 균등하게 

나누는  간단한 방법을 알아보자

 

다음과 같이 body 내에 존재하는 div박스 3개를

CSS를 이용하여 가로로 균등하게 채울 것이다. 

 

No.1
No.2
No.3
body

 

위의 3개의 박스를 가로로 채우기 위해서는 

다음과 같이 영역별로 sytle의 display 속성 값을 지정해주어야 한다.

 

최상위에 table

    그 하위에 table-row

        그 하위에 table-cell

 

이렇게 하면 cell은 상위의 row 영역을 cell 개수만큼 나눠 가진다.

 

 

 

 

 

 

적용 코드

 

 

 

코드는 다음과 같다.

 

<div style=“display:table;”> 최상위 div <!-- 테이블 영역 -->
    <div style=“display:table-row;”> <!-- 한 줄 영역 -->
        <div style=“display:table-cell;”> cell-1 <!-- 한 칸 영역 -->
            <div> No.1 </div>
        </div>
        <div style=“display:table-cell;”> cell-2 <!-- 한 칸 영역 -->
            <div> No.2 </div>
        </div>
        <div style=“display:table-cell;”> cell-3 <!-- 한 칸 영역 -->
            <div> No.3 </div>
        </div>
    </div>
<div>

 

기본적으로 table-cell안의 내용은 가운데 정렬이 된다. (table 태그의 상태와 유사하다.) 

 

 

div의 내용이 영역을 넘어가면 div의 width는 자동으로 늘어나는데

이를 막기 위해서는 table-cell의 style에

table-layout : fixed; 를 추가해주면 된다.

 

 

이렇게 하면 layout 은 고정되는데 내용은

자동 줄 바꿈이 되지 않아서 내용이 layout을 넘어간다.

 

자동 줄 바꿈을 설정해주어야 하는데 

table-cell의 style에 

word-break: break-all; 을 추가해주면 된다.

 

 





실제 코드

위의 이미지로 보여진 예제의

실제 코드는 다음과 같다.

 

참고하면 좋을 것 같다.

 

<!-- 테이블 방식으로 가운데 정렬하는 방법 -->
<div class="test_body" style ="width:230px; height:180px;background:skyblue;">
<div class="test_content" style="width:50px; height:50px; background:green;" >No.1</div>
<div class="test_content" style="width:50px; height:50px; background:red;" >No.2</div>
<div class="test_content" style="width:50px; height:50px; background:yellow;" >No.3</div>
body
</div>
<br>
<br>
<br>
<div class="test_body" style ="display:table;table-layout:fixed; word-break:break-all; width:230px; height:180px;background:skyblue">
  <div style="display:table-row; ">
    <div align=center style="display:table-cell; background:violet;" >
      <div class="test_content" style="width:50px; height:50px; background:green" >No.1</div>
      cell-1
    </div>
    <div align=center style="display:table-cell; background:orange;" >
      <div class="test_content" style=" width:50px; height:50px; background:red" >No.2</div>
      cell-2
    </div>
    <div align=center style="display:table-cell; background:pink;" >
      <div class="test_content" style="width:50px; height:50px; background:yellow" >No.3</div>
      cell-3
    </div>
  </div>
body
</div>

'Web 개발 > HTML & CSS' 카테고리의 다른 글

jQuery로 움직이는 배너 만들기  (0) 2019.07.26
CSS의 position으로 배너 추가하기  (0) 2019.07.17

배너를 움직이게 하기위해서는 

페이지가 열린 후에도 동적으로 Element의 속성을 변경되어야한다.

 

이를 위해서는 당연히 javaScript가 필요한데, 

javascript를 통해서 HTML의 window 객체의 정보를 얻어서 동적으로 움직이게 하면 된다.

그렇지만 순수 JavaScript로 모든 것을 구현하기엔 애니메이션과 같은 너무 복잡한 부분들이 존재한다.

 

이러한 어려움은 JQuery를 통해 간단하게 해결하여 움직이는 배너를 구현할 수 있다.

 

 

1. 움직이는 기준 : 스크롤 이동

스크롤이 이동할 때마다 배너의 위치를 바꾸어 주어야 한다.

이를 위해선 가장 먼저 스크롤이 이동했는지 알려주고, 이동할 때마다 특정한 행동(함수)를 하게 만들어야한다.

이러한 기능을 가지는 JQuery 함수가 바로 $(window).scroll() 이다.

 

$(window).scroll(function(){ /* 실행할 함수 */ });

 

2. 멈추는 기준 : 스크롤 기준 일정 거리

스크롤을 기준으로 하기 때문에 현재 스크롤이 위에서부터 몇이나 떨어져있는지 알 수 있어야한다.

이러한 기능을 하는 것 역시 JQuery 함수  $(window).scrollTop() 이다.

현재 스크롤이 페이지 맨위에서 얼마만큼 떨어져있는지를 계산해준다.

즉, 여기서 나오는 값은 현재 보고 있는 페이지에서 제일 꼭대기라고 생각하면 편하다.

보통 배너는 페이지 중간쯤 나오기 때문에 나는 여기에 35를 더해서 변수에 저장해 둘 것이다.

 

var position = $(window).scrollTop()+35;

 

3. 움직이는 효과 : 부드럽게 이동해서 멈추는 효과

움직이기 시작하는 기준과 멈추는 지점을 선언했으니 이제 부드럽게 이동하게 만들면 된다.

이를 위해선 $(‘#banner’).stop().animate({속성명 :속성값},이동시간)를 사용한다.

배너 div의 속성이 지정해준 속성값까지 이동시간안에 변하도록 한다.

이동시간은 ms이며 1000가 1초이다.

 

4. 조립

이제 이 모든 내용을 합치면 다음과 같다

  $(window).scroll(function( ){
        var position = $(window).scrollTop()+35;
      $( "#banner" ).stop().animate({top:position+"px"}, 800);
   });

 

ASP자체가 익숙하지 않다 ㅠㅠ 

 

JSP만 접하다 보니 APS문법 자체가 어색해보이기까지 하다

보통 <!-- --> 모양새는 주석에 쓰이는데

앞에 #을 붙여 ASP에서 사용하는 문법으로 사용된다.

 

 

 

옵션

virtual과 file이 있는데 

file은 상대 경로를 말하며

virtual은 서버에서의 가상디렉토리를 말한다.

( www.example.com/inc/banner.asp로 페이지를 로드할 수 있다면,

/inc/banner.asp를 값으로 넣어주면 된다.) 

 

 

 

  <!--#include virtual = "/inc/banner.asp"-->

 

 

 

 

 

+ Recent posts

"여기"를 클릭하면 광고 제거.