728x90
반응형

Tomcat 서버 하나에 여러개의 war 파일을 배포하여 사용하며 각 application 별로 Spring의 DBCP 를 이용하여 Connection Pooling 을 한다.

 문제점 

  - db 접속 정보(id/pw) 를 한곳에서 관리할 수 없다.

  - db 접속 정보가 변경되면 각 war 별로 참조하는 파일의 내용을 변경해 줘야 한다. ( ex 암호화 되어 있는 properties 파일 )

  - 개별 connection pooling 의 경우 실수가 발생할 가능성이 높으며 불필요한 서버 리소스가 낭비 된다.


[방안]

  - WAS 에서 제공하는 connection pooling 을 사용 한다.

  - 각 war 에서는 JNDI 로 Lookup 하여 연결 한다.

  - 주의사항 : 접속 하는 데이터베이스는 하나가 된다.

         ex) aaa.war 에서는 test 라는 데이터베이스안에 있는 테이블만 사용

             bbb.war 에서는 real 이라는 데이터베이스 안에 있는 테이블만 사용

             위와 같은 경우 query 에 반드시 aaa.tableName 으로 처리 해줘야 한다.

             이전 처럼 개별로 connection 을 관리할 경우에는 connection 자체를 aaa 또는 bbb 로 하기 때문에 table name 만 써도

             문제되지 않았지만 이부분은 수정이 되어야 한다.


[처리 방법 정리]

1. Tomcat 설정

   server.xml 의 GlobalNameingResource 에 JNDI 내용 추가

 <GlobalNamingResources>

    <Resource name="jdbc/testJNDI"

          factory="com.yhkim.global.datasource.CustomDataSource"

          auth="Container"

          type="javax.sql.DataSource"

          maxActive="100"

          maxIdle="30"

          maxWait="10000"

          username=""

          password=""

          driverClassName="com.mysql.jdbc.Driver"

          url="jdbc:mysql://127.0.0.1:3306/databaseName?zeroDateTimeBehavior=convertToNull"/>

  </GlobalNamingResources>

  노란색 부분을 눈여겨 보자.

  일반적인 JNDI 이용 시 factory 부분은 org.apache.tomcat.jdbc.pool.DataSourceFactory 를 사용한다.

  하지만 그럴 경우 username 과 password 부분을 암호화 해서 사용할 수 없다. 

  따라서 custom factory class 를 작성하여 username 와 password 를 복호화 할 수 있도로 한다.


2. CustomDataSource class 작성

   apache 의 common-dbcp 를 이용하였다. 

   아래 java project 에서 build-path 에 common-dbcp-x.x.jar 파일을 포함하고 

   아래 project 를 globalds.jar (이름은 마음데로) 파일로 export 하여 Tomcat/lib 에 포함시킨다. 

   ../conf/dbinfo.properties 는 즉 설치되는 Tomcat/conf/ 경로가 된다. 

   Tomcat/conf/에 dbinfo.properties 를 만들고 아래 내용을 넣는다. (테스트를 위해 암호화가 아닌 base64 encoding 을 해도 무관)

   username=암호화된아이디

   password=암호화된비밀번호

 public class CustomDataSource extends BasicDataSourceFactory {

public Object getObjectInstance(Object obj, Name name, Context nameCtx, 

                                          @SuppressWarnings("rawtypes") Hashtable environment) throws Exception

{

if(obj instanceof Reference)

{

setUsername((Reference)obj);

setPassword((Reference)obj);

}

return super.getObjectInstance(obj, name, nameCtx, environment);

}


private void setUsername(Reference ref)

throws Exception

{

findDecryptAndReplace("username", ref);

}


private void setPassword(Reference ref)

throws Exception

{

findDecryptAndReplace("password", ref);

}


private void findDecryptAndReplace(String refType, Reference ref)

throws Exception

{

int idx = find(refType, ref);

String decrypted = decrypt(refType);

replace(idx, refType, decrypted, ref);

}


private void replace(int idx, String refType, String newValue, Reference ref)

throws Exception

{

ref.remove(idx);

ref.add(idx, new StringRefAddr(refType, newValue));

}


private String decrypt(String key)throws Exception

{

return getDecViaSeed(getProperty(key));

}


private int find(String addrType, Reference ref)

{

try{

@SuppressWarnings("rawtypes")

Enumeration enu = ref.getAll();

for(int i = 0; enu.hasMoreElements(); i++)

{

RefAddr addr = (RefAddr)enu.nextElement();

if(addr.getType().compareTo(addrType) == 0)

return i;

}

}catch(Exception e){

e.printStackTrace();

}

return 0;

}

public String getDecViaSeed(String str) {

String strDecrypt = "";

try

{

// strDecrypt = 복호화 처리

                   // 실제 테스트를 위해서는 간단히 BASE64 정도로 테스트 해봐도 된다.

}

catch (UnsupportedEncodingException e) 

{

e.printStackTrace();

catch (Exception e) 

{

e.printStackTrace();

}

return strDecrypt;

}

public String getProperty(String key) {

String rtnStr = "";

try {

Properties prop = new Properties();

prop.load(new FileInputStream("../conf/dbinfo.properties"));

rtnStr = prop.getProperty(key);

} catch ( IOException ioe ) {

ioe.printStackTrace();

return null;

} catch ( Exception e ) {

e.printStackTrace();

}

return rtnStr;

}

}

 


3. Tomcat lib 에 필요한 jar 파일 추가

  2번에서 생성한 globalds.jar 과 

  commons-dbcp.jar

  commons-collections.jar

  commons-pool.jar 

  파일을 Tomcat/lib 경로에 포함한다.


4. Application 에서 JNDI 이용하기

web application은 Spring + MyBatis 로 구성되어 있으며 

jdbc 설정.xml 에 아래와 같이 datasource 및 transaction 부분을 설정 한다. (transaction 처리는 상황에 따라 다르게 처리 가능)

bold 처리된 부분만 보면 된다. jndiName 은 tomcat 의 server.xml 에 있는 이름과 동일 해야 한다.

      <beans:bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">

  <beans:property name="jndiName" value="jdbc/testNDI"/>

  <beans:property name="resourceRef" value="true"/>

  </beans:bean>

<beans:bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean" lazy-init="true">

<beans:property name="dataSource" ref="dataSource"/>

<beans:property name="configLocation" value="classpath:mybatis/mybatis-configuration.xml" />

<beans:property name="mapperLocations" value="classpath:mybatis/query.xml" />

<beans:property name="transactionFactory">

<beans:bean class="org.apache.ibatis.transaction.managed.ManagedTransactionFactory" />

</beans:property>

</beans:bean>

<beans:bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">

<beans:constructor-arg ref="sqlSessionFactory" />

</beans:bean>

 

<beans:bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">

<beans:property name="dataSource" ref="dataSource" />

</beans:bean>

<beans:bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">

<beans:property name="transactionManager" ref="transactionManager" />

</beans:bean>


5. Application 의 context.xml 설정

META-INF 폴더 밑에 context.xml 파일이 없다면 생성하고 있다면 아래 내용을 추가 한다.

 <?xml version="1.0" encoding="UTF-8"?>

<Context path="/applicationName">

    <WatchedResource>WEB-INF/web.xml</WatchedResource>

<ResourceLink global="jdbc/testJNDI" name="jdbc/testJNDI" type="javax.sql.DataSource"/>

</Context>



728x90
반응형

'Web Programming > server' 카테고리의 다른 글

톰캣 404  (0) 2018.09.04
A child container failed during start  (0) 2018.09.04
728x90
반응형



728x90
반응형

'끄적끄적..' 카테고리의 다른 글

하드디스크 파티션 나누기  (0) 2018.09.06
직장인 투잡으로 돈벌기  (0) 2018.09.05
구글 검색 원리  (0) 2018.09.04
스마트폰 배터리를 오래 사용하는 방법  (0) 2018.09.04
부업 / 투잡으로 용돈벌기  (1) 2018.09.04
728x90
반응형

TDD(Test-driven Development) 테스트 주도 개발방법론

각종 Community에서 개발 프로세스가 TDD가 언급이 되었고 예전에 소프트웨어 개발 프로세스 중에 배웠던 TDD에 대해 깊이 있게 몰랐기 때문에 명확하게 정의를 하고 앞으로 개발 방법을 TDD로 바꾸려고 노력하기 위해 Posting을 해보려고 한다.

1. TDD(Test-driven Development)이란?

  • 일반적인 개발 프로세스

    • 일반적으로 개발 절차는 먼저 어떻게 개발할지 디자인하고 디자인을 바탕으로 실제 코드를 작성하고 최종적으로 테스트를 작동시켜보면서 해보는 과정이었다.

No Image

  • TDD(Test-driven Development)

    • 정확한 프로그래밍 목적을 디자인 단계에서 반드시 미리 정의해야만 하고 또 무엇을 미리 정의해야한다.
    • RED : 실패하는 테스트를 만들기.
    • GREEN : 테스트에 통과할 만한 작은 코드를 작성하기.
    • REFACTOR : 반복되는 코드, 긴 메소드, 큰 클래스, 긴 매개변수 목록 등등 코드를 좀 더 효율적으로 바꾸기.

No Image

  • 개발하는 과정에서 Test Script를 작성하고 코드를 Refactoring 했다는 점이 중요하다.

2. TDD 따라하기 (JUnit)

목표 : Movie라는 클래스에 등급을 부여하고 Averaging Rate구하기

1) JUnit이란?

2) pom.xml JUnit & hamcrest 추가 코드

<dependencies>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.8.2</version>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.hamcrest</groupId>
			<artifactId>hamcrest-all</artifactId>
			<version>1.1</version>
			<scope>test</scope>
		</dependency>
</dependencies>

3) JUnit 실행

package movie;

import org.junit.Test;

/**
 * Created by NESOY on 2017-01-31.
 */
public class MovieTest {
    @Test
    public void foo(){

    }
}

Test 결과화면

No Image

4) Failing Test 코드 작성

/**
 * Created by NESOY on 2017-01-31.
 */
public class MovieTest {
    @Test
    public void canCreateMovie(){
        Movie movie = new Movie();
    }
}

5) Test를 통과하기 위한 소량의 코드 추가

package movie;

/**
 * Created by NESOY on 2017-01-31.
 */
public class Movie {
}

Test 결과화면

No Image

6) Averaging Rating Test Case만들기 - 가장 초기 모델이므로 Rate점수가 없다. -> 0점.

package movie;

import org.junit.Test;

import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertThat;

/**
 * Created by NESOY on 2017-01-31.
 */
public class MovieTest {
    @Test
    public void canCreateMovie(){
        Movie movie = new Movie();
        assertThat(movie.averageRationg(),is(0));
    }
}

7) Test를 통과하기 위한 소량의 코드 추가

package movie;

/**
 * Created by NESOY on 2017-01-31.
 */
public class Movie {
    public Integer averageRationg() {
        return 0;
    }
}

Test 결과화면

No Image

8) Refactoring하기 - Method 이름 바꾸기

package movie;

import org.junit.Test;

import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertThat;

/**
 * Created by NESOY on 2017-01-31.
 */
public class MovieTest {
    @Test
    public void should_return_0_when_just_created(){
        Movie movie = new Movie();
        assertThat(movie.averageRationg(),is(0));
    }
}

9) Averaging Rating Test Case만들기 -> 1을 주었을때 Average Rate가 1이 나와야한다.

package movie;

import org.junit.Test;

import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertThat;

/**
 * Created by NESOY on 2017-01-31.
 */
public class MovieTest {
    @Test
    public void should_return_0_when_just_created(){
        Movie movie = new Movie();
        assertThat(movie.averageRationg(),is(0));
    }

    @Test
    public void should_return_1_when_was_rated(){
        Movie movie = new Movie();
        movie.rate(1);
        assertThat(movie.averageRationg(),is(1));
    }
}

10) Compile 통과하기 위한 소량의 코드 추가

package movie;

/**
 * Created by NESOY on 2017-01-31.
 */
public class Movie {
    public Integer averageRationg() {
        return 0;
    }

    public void rate(int rate) {

    }
}

Test 결과화면

No Image

averageRationg Return 값이 어떠한 상황에서도 0이다. 고쳐서 Test를 통과시키자.

package movie;

/**
 * Created by NESOY on 2017-01-31.
 */
public class Movie {
    private int sumOfRate = 0;
    private int countOfRate = 0;

    public Integer averageRationg() {
        return sumOfRate/ countOfRate;
    }

    public void rate(int rate) {
        this.sumOfRate += rate;
        this.countOfRate++;
    }
}

Test 결과화면

No Image

countOfRate가 0일 경우에 0으로 나누었을 경우 Exception 발생 -> 0일때 예외처리

package movie;

/**
 * Created by NESOY on 2017-01-31.
 */
public class Movie {
    private int sumOfRate = 0;
    private int countOfRate = 0;

    public Integer averageRationg() {
        return countOfRate == 0 ? 0 : sumOfRate/ countOfRate;
    }

    public void rate(int rate) {
        this.sumOfRate += rate;
        this.countOfRate++;
    }
}

Test 결과화면

No Image

11) Refactoring - TestCase의 중복되는 부분 제거하기

package movie;

import org.junit.Test;

import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertThat;

/**
 * Created by NESOY on 2017-01-31.
 */
public class MovieTest {
    @Test
    public void should_return_0_when_just_created(){
        Movie movie = new Movie(); // 중복
        assertThat(movie.averageRationg(),is(0));
    }

    @Test
    public void should_return_1_when_was_rated(){
        Movie movie = new Movie(); // 중복
        movie.rate(1);
        assertThat(movie.averageRationg(),is(1));
    }
}

Tips : Intellj Refactor - Field - Setup Method 자동으로 해준다.

No Image

package movie;

import org.junit.Before;
import org.junit.Test;

import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertThat;

/**
 * Created by NESOY on 2017-01-31.
 */
public class MovieTest {

    private Movie movie;

    @Before
    public void setUp() throws Exception {
        movie = new Movie();
    }

    @Test
    public void should_return_0_when_just_created(){
        Movie movie = this.movie; // 불필요하므로 제거한다.
        assertThat(movie.averageRationg(),is(0));
    }

    @Test
    public void should_return_1_when_was_rated(){
        Movie movie = this.movie; // 불필요하므로 제거한다.
        movie.rate(1);
        assertThat(movie.averageRationg(),is(1));
    }
}

12) Averaging Rating Test Case만들기 -> 3,5을 주었을때 Average Rate가 4이 나와야한다.

@Test
   public void should_return_4_when_3_and_5_were_rated(){
       movie.rate(3);
       movie.rate(5);
       assertThat(movie.averageRationg(),is(4));
   }

Test 결과화면

No Image

728x90
반응형

'Web Programming > java-jsp' 카테고리의 다른 글

람다 아키텍처  (0) 2018.09.05
java Generic  (0) 2018.09.05
클래스 정보 가져오기 - 리플렉션  (0) 2018.09.04
JSTL에서 LIST Size  (0) 2018.09.04
For input string: ""  (0) 2018.09.04
728x90
반응형
리플렉션(reflection)은 기본적으로 Java에서 클래스의 정보를 효율적으로
얻기 위해 개발된 기법입니다. 클래스의 정보를 얻는 방법부터 알아 
보겠습니다. 다음의 예제들을 살펴보겠습니다.


▶ 클래스 정보를 관리하는 도구의 종류

/* 클래스 정보를 다루는 도구 얻기 */
public class Test01 {

  public static void main(String[] args) throws Exception {
    // 1) 인스턴스를 통해서 얻기
    String obj = new String("Hello");
    Class<?> c1 = obj.getClass(); // <?> : 어떤 종류의 클래스든 다 얻어올 수 있다는 의미
    // => 인스턴스만 있으면 그 인스턴스가 어떤 클래스의 객체인지 쉽게 알아낼 수 있다.
    
    
    // 2) class.forName() 메서드를 통해서 얻기
    Class<?> c2 = Class.forName("java.lang.String"); 
    // => 아규먼트가 가리키는 문자열이 없을 수 있기 때문에 예외처리가 필요하다.
    // => 클래스 이름을 문자열로 받을 수 있기 때문에 유지보수가 쉽다.
        
    // 3) 모든 클래스에 내장된 "class" 스태틱 변수를 통해서 얻기
    Class<?> c3 = String.class;
    // => 코딩이 간편하다. 그러나 클래스 이름을 코드로 명시하기 때문에 유지보수가 어렵다.
  }

}


▶ Class 도구를 이용해 클래스의 이름 알아내기


/* Class 도구 사용법 : 클래스 이름 알아내기 */
public class Test02 {

  public static void main(String[] args) throws Exception {
    Class<?> c1 = String.class;
    
    System.out.println(c1.getName());
    System.out.println(c1.getSimpleName());
    System.out.println(c1.getCanonicalName());
  }
}

실행 결과 : java.lang.String String java.lang.String



▶ Class 도구를 이용해 특정 메서드의 리턴 타입 알아내기


/* Class 도구 사용법 : 메서드의 리턴 타입 알아내기 */
import java.lang.reflect.Method;
public class Test05 {

  public static void main(String[] args) throws Exception {
    Class<?> clazz = Math.class;
    
    Method m = clazz.getMethod("sin", double.class);
    System.out.println(m);
    
    Class<?> returnType = m.getReturnType();
    System.out.println(returnType.getName());
  }
}

/*
실행 결과 : 
public static double java.lang.Math.sin(double)
double
*/



▶ Class 도구를 이용해 특정 메서드의 파라미터 타입 알아내기


/* Class 도구 사용법 : 메서드의 파라미터 타입 알아내기 */
import java.lang.reflect.Method;
public class Test06 {

  public static void main(String[] args) throws Exception {
    Class<?> clazz = Math.class;
    
    Method[] methodList = clazz.getMethods();
    for (Method m : methodList) {
      System.out.printf("%s\n", m.getName());
      Class<?>[] paramTypes = m.getParameterTypes();
      for (Class<?> paramType : paramTypes) {
        System.out.printf("--> %s \n", paramType.getName());
      }
      System.out.println();
    }
  }
}



▶ Class 도구를 이용해 메서드 호출하기


/* Class 도구 사용법 : 메서드 호출하기 import java.lang.reflect.Method; public class Test07 { public static void main(String[] args) throws Exception { // 1) 인스턴스 메서드 호출하기 String str = new String("Hello"); Class<?> clazz = String.class; Method m = clazz.getMethod("replace", char.class, char.class); Object returnValue = m.invoke(str, 'l', 'x'); System.out.println(returnValue); // 2) 클래스 메서드 호출하기 clazz = Math.class; m = clazz.getMethod("abs", int.class); returnValue = m.invoke(null, -100); // 스태틱 메서드를 호출할 때는 인스턴스를 null로 설정하라 System.out.println(returnValue); } }



▶ Class 도구를 이용해 인스턴스 생성하기

/* Class 도구 사용법 : 인스턴스 생성하기 */
import java.lang.reflect.Method;
import java.util.Date;
public class Test08 {

  public static void main(String[] args) throws Exception {
    // Class<?> clazz = Date.class;
    Class<?> clazz = Class.forName("java.util.Date");
    Date obj = (Date)clazz.newInstance();
    System.out.println(obj);
  }
}


▶ Class 도구를 이용해 nested class 로딩하기

/* Class 도구 사용법 : nested class 로딩 */
import java.lang.reflect.Method;
import java.util.Date;
public class Test09 {

  static class My {}
  
  public static void main(String[] args) throws Exception {
    Class<?> c1 = My.class;
    Class<?> c2 = step26.Test09.My.class;
    Class<?> c3 = Class.forName("step26.Test09$My");
    
    System.out.println(c1);
    System.out.println(c2);
    System.out.println(c3);
  }
}

/*
실행 결과 :
class step26.Test09$My
class step26.Test09$My
*/


Step 1. MySuper 클래스를 정의하기

──────────────────────────────────────

public class MySuper {
  public int superPublicVar;
  String superDefaulttVar;
  protected boolean superProtectedVar;
  private float superPrivateVar;
  
  public void superPublicM() {}
  void superDefaultM() {}
  protected void superProtectedM() {}
  private void superPrivateM() {}
}



Step 2. MySuper 클래스를 상속한 MyClass 클래스 정의하기

──────────────────────────────────────

public class MyClass extends MySuper {
  public int publicVar;
  String defaultVar;
  protected boolean protectedVar;
  private float privateVar;
  
  public MyClass() {}
  public MyClass(int p1) {}
  public MyClass(String p1, int p2) {}
  
  public void publicM() {}
  void defaultM() {}
  protected void protectedM() {}
  private void privateM() {}
  
  public void m1() {}
  public void m2(int v1) {}
  public void m3(String p1, int p2) {}
}




Step 3. MyClass 클래스의 메서드를 알아내기

──────────────────────────────────────

* Class 도구 사용법 : 클래스의 메서드 알아내기 */
import java.lang.reflect.Method;
public class Test03 {

  public static void main(String[] args) throws Exception {
  // static 환경에서는 this가 없다.  
  test1();
  test2();  
  }
  
  private static void test1() throws Exception {
    Class<?> clazz = MyClass.class;
    
    Method[] methodList = clazz.getMethods(); 
    // 상속 받은 메서드를 포함하여 모든 public 메서드만 추출한다.
    for (Method m : methodList) {
      System.out.println(m.getName());
    }
  }
  
  private static void test2() throws Exception {
    Class<?> clazz = MyClass.class;
    
    Method[] methodList = clazz.getDeclaredMethods(); 
    // 해당 클래스에 선언된 모든 메서드를 추출한다. 
    for (Method m : methodList) {
      System.out.println(m.getName());
    }
  }
  
}




Step 4. MyClass 클래스의 특정 메서드만 추출하기

──────────────────────────────────────


/* Class 도구 사용법 : 클래스의 특정 메서드만 추출하기 */
import java.lang.reflect.Method;
public class Test04 {

  public static void main(String[] args) throws Exception {
    Class<?> clazz = MyClass.class;
    
    Method m = clazz.getMethod("m1");
    System.out.println(m.getName());
    
    // 일치하는 메서드를 찾지 못했을 때? null을 리턴하는 것이 아니라 예외가 발생한다.
    // m = clazz.getMethod("m1", String.class);
    // System.out.println(m);
    
    Method m2 = clazz.getMethod("m2", int.class);
    System.out.println(m2);
    
    Method m3 = clazz.getMethod("m3", String.class, int.class);
    System.out.println(m3);
  }
}
/*
실행 결과 : 
m1
public void step26.MyClass.m2(int)
public void step26.MyClass.m3(java.lang.String,int)
*/


728x90
반응형

'Web Programming > java-jsp' 카테고리의 다른 글

java Generic  (0) 2018.09.05
TDD 테스트 주도 개발방법론  (0) 2018.09.04
JSTL에서 LIST Size  (0) 2018.09.04
For input string: ""  (0) 2018.09.04
Jsoup parser 크롤링  (0) 2018.08.30
728x90
반응형

strlen 함수

PHP 함수인 strlen 함수에 대해 php.net 에서는 아래와 같이 설명하고 있습니다.

문자열 길이를 얻습니다. 

그렇지만, 해당 함수는 영문 문자열이 몇 바이트(Byte)인지를 가져오는 함수입니다.
영문은 1 Byte로 계산하지만,
UTF-8 문서에 경우 각 문자를 1~4Byte까지 사용하므로, 한글은 한 글자당 1~4Byte에 길이가 반환되어 정확한 문자열의 길이를 알 수 없습니다.
그렇기 때문에 우리는 이를 해결 할 수 있는 함수인 mb_strlen 에 대해서도 함께 알아보겠습니다.

mb_strlen 함수

PHP 함수인 mb_strlen 은 php.net 에서 strlen과 동일한 설명을 가지고 있습니다.

문자열 길이를 얻습니다. 

그러면 무엇이 틀린 걸까요?
그건 바로 사용하는 인수 값이 틀립니다.

strlen은 문자열 하나만을 인수로 사용하지만,
mb_strlen은 문자열과 현재 파일의 인코딩(= 문자셋 혹은 charset )을 인수로 사용합니다.
mb_strlen 함수를 이용하면 한글 문자열 길이도 문제없이 가져올 수 있습니다.

▶사용법


강조 처리된 부분만 필수 입력 사항입니다.

strlen( 문자열 )


mb_strlen( 문자열 ,   인코딩 =  mb_internal_encoding() )


* 인코딩 : 값을 입력하지 않으면, 기본 문자 인코딩에서 사용되는 문자 인코딩을 가져옵니다. [참고 ]


▶strlen 함수 예제



코드

1
2
3
4
<?php
echo "영어 : ". strlen("Edward").'<br/>';
echo "한글 : ". strlen("반갑수");
?>


결과

영어 : 6
한글 : 9


▶mb_strlen 함수 예제


파일 인코딩이 UTF-8인 경우에 대한 예제입니다. (다른 인코딩이면 어딜 변경해야할지 아실거라 생각합니다.)

코드

1
2
3
4
<?php
echo "영어 : ". mb_strlen("Edward", "UTF-8").'<br/>';
echo "한글 : ". mb_strlen("반갑수", "UTF-8");
?>


결과

영어 : 6
한글 : 3



출처: http://extbrain.tistory.com/entry/PHP-문자열-길이-가져오기-strlen-mbstrlen-함수 [확장형 뇌 저장소]

728x90
반응형

'Web Programming > php' 카테고리의 다른 글

php $_GET $_POST  (0) 2018.09.05
php new line to br nl2br()  (0) 2018.09.05
php data types  (0) 2018.09.04
php include, require  (0) 2018.09.03
php 배열  (0) 2018.09.03

+ Recent posts