최근 Service 개발에서 반복적인 Account 생성이 필요한 테스트 케이스가 있어서 작업 중 Remote Server에서 주민등록번호 Validation 을 하는 바람에 급히 검색하여 다음과 같은 내용을 알아내었다.

예를 들어 640713-1018433 이 주민번호를 예로 들어보죠
우선 주민등록번호 마지막자리수만 제외하고,
각각의 자리수마다 다음과 같은 수를 곱하여 전체를 더한다.

6 4 0 7 1 3 1 0 1 8 4 3
x x x x x x x x x x x x
2 3 4 5 6 7 8 9 2 3 4 5
-----------------------
+ + + + + + + + + + + +

즉, (6*2)+(4*3)+(0*4)+(7*5)+(1*6)+(3*7)+(1*8)+(0*9)+(1*2)
+(8*3)+(4*4)+(3*5) = 151

그러면 151 이란 수가 나온다. 이 151을 매직키인 11로 나누어 나머지만 취한다.

151 / 11 = 몫: 13 <-- 버림

나머지: 8

마지막 단계로 매직키인 11에서 나머지 8을 빼면 3이란 수가 나오
는데, 이숫자가 주민등록번호 마지막 자리의 숫자와 일치하면 대한민국 국민이다.

11 - 8 = 3 --> 정상적인 주민등록번호임 
출처 : http://blog.naver.com/foenix/40040223161

이 내용을 다음과 같은 메서드로 만들어 보았다.


	public static String getSSN() {
		Random rand = new Random();
		Calendar cal = Calendar.getInstance();
		cal.setTimeInMillis(rand.nextLong());
		String s1 = new SimpleDateFormat("yyMMdd").format(cal.getTime());
		String s2 = null;
		
		while(s2 == null || s2.length() < 6) {
			s2 = Integer.toString(rand.nextInt(299999));
		}
		int sum = 0;
		for (int i = 0; i < s1.length(); i++) {
			sum += Integer.parseInt(String.valueOf(s1.charAt(i))) * (i + 2);
			int j = i < 2 ? i + 8 : i;
			sum += Integer.parseInt(String.valueOf(s2.charAt(i))) * j;
		}
		int bit = 11 - (sum % 11);

		return s1 + "-" + s2 + (bit == 10 ? 0 : bit);
	}
TAG java, TDD

댓글을 달아 주세요

  1. 벤또사마 2009/06/17 09:46  댓글주소  수정/삭제  댓글쓰기

    2000년생 이후도 동작하면 대박.

  2. 프로채터 2009/06/19 19:01  댓글주소  수정/삭제  댓글쓰기

    3번 4번 있고 외국인은 5번 6번 있는데... 쩝...

  3. 강성희 2009/08/31 17:41  댓글주소  수정/삭제  댓글쓰기

    비슷한 문제인 신용카드 인증 문제가 문득 기억나네요.
    2차 P-camp때 김창준님이 자신의 세션에서 신용카드 문제를 TDD로 해결하는 방법을 보여주셨는데, 당시 TDD 초보였던지라 너무 감동을 받았던-_- 기억이...

Tomcat 등의 Servlet Container를 사용하여, 웹애플리케이션을 개발할 때, DataSource를 Servlet Container의 Context 에 JNDI Resource로 bind 하여 사용하는 경우가 많다.

test case를 실행하기 위해 JNDI remote provider 를 제공하는 application server (glassfish, jboss 등)를 사용할 수도 있으나, 이러한 것은 test의 원자성을 저해하기 때문에 test 환경 자체에서 JNDI resource를 생성할 수 있는 방법을 생각해 보았다.

Sun에서 제공하는 File System Service Provider를 이용하는 것이다. 사용법은 매우 간단하다. 단순히 naming context의 initail context factory 를 com.sun.jndi.fscontext.RefFSContextFactory 로 지정하기만 하면 된다.

다음은 간단히 만들어 본 class 이다. 이 class는 context xml 파일을 읽어서 JNDI resource를 loading해 주는 역할을 한다. test를 수행하기 전에 JNDILoader.init()을 실행 해주면 다른 작업 없이 test case를 실행시킬 수 있을 것이다.

package com.fguy.test;

import java.io.File;
import java.io.IOException;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.naming.Reference;
import javax.naming.StringRefAddr;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.apache.log4j.Logger;
import org.w3c.dom.DOMException;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

public class JNDILoader {
	private static final Logger LOG = Logger.getLogger(JNDILoader.class);

	private static final boolean initialized = false;
	private static final String CONTEXT_XML = "WebContent/META-INF/context.xml";

	private JNDILoader() {

	}

	public static final void init() throws ParserConfigurationException,
			SAXException, IOException, DOMException, NamingException {

		if (!initialized) {
			Context context = getNamingContext();

			List resourceNames = new ArrayList();
			Map> references = new HashMap>();

			NodeList contextResourceNodeList = getContextResourceNodeList();
			for (int i = 0; i < contextResourceNodeList.getLength(); i++) {
				Node item = contextResourceNodeList.item(i);
				// print comment;
				if (LOG.isDebugEnabled()
						&& item.getNodeType() == Node.COMMENT_NODE
						&& item != null) {
					LOG.debug(item.getNodeValue());
				}

				// register to JNDI
				if ("resource".equalsIgnoreCase(item.getNodeName())
						&& "javax.sql.DataSource".equals(item.getAttributes()
								.getNamedItem("type").getNodeValue())) {
					NamedNodeMap attributes = item.getAttributes();
					String name = attributes.getNamedItem("name")
							.getNodeValue();
					Map reference = references.get(name);

					if (reference == null) {
						reference = new HashMap();
					}

					for (int j = 0; j < attributes.getLength(); j++) {
						String n = attributes.item(j).getNodeName();
						String v = attributes.item(j).getNodeValue();
						if (!"name".equals(n)) {
							reference.put(n, v);
						}
						LOG.debug(attributes.item(j));
					}

					resourceNames.add(name);
					references.put(name, reference);
				}

				if ("resourceparams".equalsIgnoreCase(item.getNodeName())) {
					NodeList parameters = item.getChildNodes();
					String name = item.getAttributes().getNamedItem("name")
							.getNodeValue();
					Map reference = references.get(name);

					if (reference == null) {
						reference = new HashMap();
					}

					for (int j = 0; j < parameters.getLength(); j++) {
						Node paramItem = parameters.item(j);
						if ("parameter".equalsIgnoreCase(paramItem
								.getNodeName())) {
							NodeList children = paramItem.getChildNodes();
							String n = null;
							String v = null;
							for (int k = 0; k < children.getLength(); k++) {
								Node child = children.item(k);
								if ("name"
										.equalsIgnoreCase(child.getNodeName())) {
									n = child.getNodeValue();
								} else if ("value".equalsIgnoreCase(child
										.getNodeName())) {
									v = child.getNodeValue();
								}
								LOG.debug(child);
							}
							reference.put(n, v);
						}
					}
					references.put(name, reference);
				}
			}
			for (String name : resourceNames) {
				Reference reference = new Reference("javax.sql.DataSource",
						"org.apache.commons.dbcp.BasicDataSourceFactory", null);
				Map referenceMap = references.get(name);

				for (String key : referenceMap.keySet()) {
					reference
							.add(new StringRefAddr(key, referenceMap.get(key)));
				}

				context.rebind("java:comp/env/".concat(name), reference);
			}
		}
	}

	private static final NodeList getContextResourceNodeList()
			throws ParserConfigurationException, SAXException, IOException {
		DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory
				.newInstance();
		DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
		Document doc = docBuilder.parse(new File(CONTEXT_XML));
		return doc.getFirstChild().getChildNodes();
	}

	private static final Context getNamingContext() throws NamingException {
		System.setProperty(Context.INITIAL_CONTEXT_FACTORY,
				"com.sun.jndi.fscontext.RefFSContextFactory");
		System.setProperty(Context.PROVIDER_URL, "file:///tmp");

		return new InitialContext();
	}
}

댓글을 달아 주세요

	public static final boolean isPhoneNumber(String string) {
		return string.matches("(0(\\d|\\d{2}|\\d{3})-)?(\\d{3}|\\d{4})-\\d{4}");
	}

지역 정보 검색에 활용하기 위해 작성한 메서드

(사실은 코드가 잘 나오는 지 확인해보기 위해 포스팅...)
TAG code, java

댓글을 달아 주세요

  1. 선환 2007/10/24 02:33  댓글주소  수정/삭제  댓글쓰기

    흠.. 자바인가요.. 생소하네..

    (0(\\d|\\d{2}|\\d{3})-)?(\\d{3}|\\d{4})-\\d{4}
    (0(\\d{2,3})-)?(\\d{3,4})-\\d{4}

    이렇게 하면은 안 되나요?