반응형

🔍 ArchUnit란 무엇인가?

소프트웨어 개발에서 아키텍처는 시스템의 핵심 구조를 정의합니다. 그러나 규모가 커질수록 아키텍처 규칙을 준수하기 어려워집니다.

여기서 ArchUnit이 등장합니다. ArchUnit은 Java 기반의 아키텍처 테스트 라이브러리로, 코드 내 구조적 규칙을 설정하고 이를 자동으로 검증할 수 있게 합니다. 이를 통해 프로젝트 내 아키텍처가 의도대로 유지되며, 유지보수성을 높이는 데 큰 기여를 합니다.

이번 글에서는 ArchUnit을 사용한 단위 테스트 설정 및 주요 사용법을 살펴보고, 실제 프로젝트에서 적용하는 방법을 단계별로 설명하겠습니다.

Java ArchUnit를 이용한 단위 테스트

 

 

📝 ArchUnit의 기본 원리와 장점

ArchUnit의 주요 장점은 코드와 아키텍처 간의 일관성을 유지하고, 이를 통해 코드 품질을 높일 수 있다는 점입니다. 규칙을 코드화하여 프로젝트 전체의 코드 구조가 요구 사항과 일치하는지 확인할 수 있습니다.

ArchUnit 특징 설명
코드 기반 규칙 정의 Java 또는 Kotlin 코드로 아키텍처 규칙을 정의하여 유지 보수성을 높입니다.
자동 검증 규칙을 정의한 후 자동으로 실행되어 일관성을 유지합니다.
테스트 통합 JUnit과 같은 기존의 테스트 프레임워크와 통합이 용이합니다.
유연한 규칙 설정 패키지 구조, 클래스 의존성, 접근 수준 등 다양한 규칙을 설정할 수 있습니다.

 

 

🛠 ArchUnit 설치 및 기본 설정

ArchUnit은 Maven과 Gradle 프로젝트에서 쉽게 설정할 수 있습니다. 아래 예시는 Maven과 Gradle 프로젝트에 ArchUnit을 설정하는 방법입니다.

Maven 설정

<dependency>
    <groupId>com.tngtech.archunit</groupId>
    <artifactId>archunit-junit5-api</artifactId>
    <version>0.23.1</version>
    <scope>test</scope>
</dependency>

Gradle 설정

testImplementation 'com.tngtech.archunit:archunit-junit5-api:0.23.1'

위 설정을 통해 ArchUnit의 JUnit5 지원 모듈을 추가할 수 있습니다.

 

 

🚀 ArchUnit의 핵심 기능: 단위 테스트 작성하기

ArchUnit을 활용해 규칙을 정의하고 이를 테스트할 수 있습니다. 단위 테스트를 작성하여 코드 구조가 의도한 대로 유지되는지 검증할 수 있습니다. 주요 기능에는 패키지 의존성 규칙, 클래스 계층 구조 규칙, 접근 제한 규칙 등이 있습니다.

1. 패키지 의존성 규칙

패키지 간의 의존성을 정의하여 특정 패키지가 다른 패키지에 접근하지 못하게 규정할 수 있습니다.

import com.tngtech.archunit.core.domain.JavaClasses;
import com.tngtech.archunit.core.importer.ClassFileImporter;
import com.tngtech.archunit.lang.ArchRule;
import com.tngtech.archunit.library.dependencies.SlicesRuleDefinition;
import org.junit.jupiter.api.Test;

class PackageDependencyTest {
    @Test
    void 패키지_순환_의존성_검증() {
        JavaClasses importedClasses = new ClassFileImporter().importPackages("com.example");

        ArchRule rule = SlicesRuleDefinition.slices()
            .matching("com.example.(*)..")
            .should().beFreeOfCycles();

        rule.check(importedClasses);
    }
}

위 코드는 com.example 패키지 내에서 순환 의존성이 발생하지 않도록 테스트합니다.

 

2. 클래스 계층 구조 규칙

특정 클래스가 반드시 특정 인터페이스를 구현하거나 부모 클래스를 상속하도록 강제할 수 있습니다.

import com.tngtech.archunit.core.domain.JavaClasses;
import com.tngtech.archunit.core.importer.ClassFileImporter;
import com.tngtech.archunit.lang.ArchRule;
import com.tngtech.archunit.lang.syntax.ArchRuleDefinition;
import org.junit.jupiter.api.Test;

class ClassHierarchyTest {
    @Test
    void 서비스_클래스_규칙_검증() {
        JavaClasses importedClasses = new ClassFileImporter().importPackages("com.example.service");

        ArchRule rule = ArchRuleDefinition.classes()
            .that().resideInAPackage("..service..")
            .should().implement(ServiceInterface.class);

        rule.check(importedClasses);
    }
}

이 테스트는 service 패키지에 속한 클래스들이 ServiceInterface 인터페이스를 구현하도록 강제합니다.

 

3. 접근 제한 규칙

특정 패키지의 클래스나 메서드에 대한 접근 제한을 설정할 수 있습니다.

import com.tngtech.archunit.core.domain.JavaClasses;
import com.tngtech.archunit.core.importer.ClassFileImporter;
import com.tngtech.archunit.lang.ArchRule;
import com.tngtech.archunit.lang.syntax.ArchRuleDefinition;
import org.junit.jupiter.api.Test;

class AccessControlTest {
    @Test
    void 컨트롤러_접근_규칙_검증() {
        JavaClasses importedClasses = new ClassFileImporter().importPackages("com.example");

        ArchRule rule = ArchRuleDefinition.noClasses()
            .that().resideInAPackage("com.example.controller")
            .should().accessClassesThat().resideInAPackage("com.example.repository");

        rule.check(importedClasses);
    }
}

위 테스트는 Controller 계층이 Repository 계층에 직접 접근하지 않도록 규정합니다.

 

 

📊 ArchUnit의 규칙 설정과 활용 사례

현업에서 자주 사용되는 규칙 설정과 ArchUnit의 실제 활용 예시를 소개합니다. 이와 같은 규칙 설정을 통해 개발팀 전체의 코드 품질을 향상할 수 있습니다.

규칙 설정 설명
레이어드 아키텍처 규칙 특정 계층 간 접근 제한을 설정하여 MVC 패턴을 따르도록 강제합니다.
순환 의존성 제거 패키지 내 클래스가 순환 참조되지 않도록 설정합니다.
특정 클래스 금지 보안 문제나 다른 이유로 특정 클래스의 사용을 금지합니다.
패키지 명명 규칙 패키지 이름을 명명 규칙에 맞게 유지하도록 설정합니다.

 

 

🧩 ArchUnit을 통해 아키텍처 유지 보수하기

ArchUnit의 규칙을 사용하면 아키텍처 준수 여부를 지속적으로 확인할 수 있습니다. 팀원들이 코드를 수정할 때마다 ArchUnit 테스트가 자동으로 실행되므로, 실수로 아키텍처가 깨지거나 규칙이 무시되는 일을 방지할 수 있습니다. 이를 통해 코드의 일관성과 유지 보수성을 향상시킬 수 있습니다.

ArchUnit을 활용한 CI/CD 통합

ArchUnit 테스트는 CI/CD 파이프라인에 쉽게 통합될 수 있습니다. 테스트 자동화를 통해 배포 전 아키텍처 규칙을 항상 검증할 수 있습니다. 예를 들어, GitHub Actions 또는 Jenkins와 같은 툴에서 ArchUnit 테스트를 포함한 빌드 파이프라인을 구성하면 코드 품질을 지속적으로 유지할 수 있습니다.

 

 

✅ ArchUnit 활용의 Best Practices

ArchUnit을 효과적으로 사용하기 위한 몇 가지 팁을 정리했습니다.

  • 테스트 코드 리뷰: ArchUnit 규칙은 테스트 코드로 작성되므로 리뷰를 통해 추가 개선이 가능합니다.
  • 점진적 적용: 기존 프로젝트에 ArchUnit을 적용할 때는 주요 규칙부터 점진적으로 추가하는 것이 좋습니다.
  • 문서화 및 공유: 정의한 규칙을 문서화하고, 팀 내에서 공유하여 모든 팀원이 이해하도록 합니다.
  • 커스텀 규칙 작성: 기본 제공되는 규칙 외에도 프로젝트에 맞는 커스텀 규칙을 작성하여 일관성을 높입니다.

 

 

❓ 자주 묻는 질문 (Q&A)

Q1. ArchUnit을 어떤 프로젝트에 적용하면 좋을까요?

A1. ArchUnit은 규모가 크거나, 구조적 일관성이 중요한 프로젝트에 유용합니다. 특히 레이어드 아키텍처를 사용하는 프로젝트에서 효과적입니다.

Q2. ArchUnit 규칙을 변경하면 기존 코드에 문제가 생기나요?

A2. 새 규칙 추가 시 기존 코드와의 충돌이 있을 수 있습니다. 이때 테스트 결과를 검토하며 규칙을 조정하거나 코드를 리팩터링하는 것이 좋습니다.

Q3. ArchUnit의 성능에 대한 우려가 있나요?

A3. 테스트의 양이 많아질 경우 빌드 시간이 길어질 수 있으므로, 중요한 규칙을 위주로 적용하고 불필요한 테스트는 지양합니다.


Java ArchUnit은 코드와 아키텍처가 일치하는지 지속적으로 확인할 수 있는 강력한 도구입니다. 이를 통해 개발팀은 코드의 일관성을 유지하며 유지 보수성을 높일 수 있습니다. ArchUnit을 처음 사용해보는 분이라면, 이 글을 참고하여 프로젝트에 적용해 보시길 추천드립니다! 😊

 

 

ArchUnit 공식 가이드 링크

https://www.archunit.org/userguide/html/000_Index.html

반응형
반응형

현대의 웹과 모바일 애플리케이션 개발에서 데이터 관리는 중요한 측면 중 하나입니다. 

 

전통적인 RESTful API는 오랫동안 데이터를 요청하고 전송하는 표준 방식이었습니다. 

하지만, RESTful API는 여러 엔드포인트에 대한 복잡한 요청, 데이터 오버페칭 및 언더페칭과 같은 문제를 내포하고 있습니다. 

 

이러한 한계를 극복하기 위해 Facebook은 2015년 GraphQL을 공개했습니다. 

 

GraphQL은 데이터 요청과 응답 과정을 더 효율적이고 유연하게 만들어 개발자의 생산성을 크게 향상시킵니다.

 


GraphQL 소개

GraphQL은 클라이언트가 필요한 데이터의 구조를 명확하게 요청할 수 있게 하고, 서버는 정확히 그 요청에 맞는 데이터만 반환합니다. 이는 데이터 오버페칭과 언더페칭을 방지하고, 애플리케이션의 성능을 최적화합니다.

예를 들어, 사용자 정보와 그 사용자의 게시글 제목만을 요청하는 GraphQL 쿼리는 다음과 같이 간단합니다

query {
  user(id: "1") {
    name
    email
    posts {
      title
    }
  }
}

이 쿼리는 사용자의 이름, 이메일, 그리고 게시글 제목만을 반환합니다. 이러한 단순성과 명확성은 GraphQL의 주요 장점 중 하나입니다.

 


주요 개념과 용어

 

GraphQL을 이해하기 위해서는 몇 가지 핵심 개념을 알아야 합니다

  • Schema: 데이터의 모델을 정의하며, 특정 쿼리에 대해 반환되어야 하는 데이터 타입을 명시합니다.
  • Query: 데이터를 읽을 때 사용되며, REST API의 GET 요청과 유사합니다.
  • Mutation: 데이터를 생성, 수정, 삭제할 때 사용됩니다.
  • Resolver: 쿼리나 뮤테이션을 실제 데이터로 해석하는 함수입니다.

예를 들어, 사용자 스키마는 다음과 같이 정의될 수 있습니다

type User {
  id: ID!
  name: String!
  email: String!
  posts: [Post!]
}

 

그리고 사용자의 정보를 요청하는 쿼리는 이렇게 간단해집니다

query {
  user(id: "1") {
    name
    email
  }
}

 


 

GraphQL의 장점

GraphQL의 주요 장점은 데이터 오버페칭과 언더페칭을 방지하며, 애플리케이션의 네트워크 성능을 최적화한다는 점입니다. 

클라이언트는 필요한 데이터만 정확히 요청할 수 있으며, 서버는 요청된 데이터만 반환합니다. 

이는 특히 복잡한 시스템과 모바일 애플리케이션에서 매우 유용합니다.

또한, GraphQL은 타입 시스템을 사용하여 API를 더욱 견고하게 만듭니다. 

개발자는 API를 통해 어떤 데이터를 기대할 수 있는지 명확하게 알 수 있으며, 이는 개발 과정에서의 오류를 줄여줍니다.

 


 

사용 사례

GraphQL은 전 세계 수많은 기업에서 성공적으로 도입되어 사용되고 있습니다. 

예를 들어, GitHub, Shopify, Twitter 등의 기업은 자신들의 API에 GraphQL을 채택하여 개발자 경험을 향상시키고 있습니다. 

이러한 기업들은 GraphQL을 통해 데이터 관리의 복잡성을 줄이고, 개발 효율성을 높이는 데 성공했습니다.

 


 

기본 GraphQL 서버 구축

GraphQL 서버를 구축하는 것은 생각보다 간단합니다. 

예를 들어, Node.js와 Apollo Server를 사용하여 간단한 GraphQL 서버를 설정할 수 있습니다

const { ApolloServer, gql } = require('apollo-server');

const typeDefs = gql`
  type Query {
    hello: String
  }
`;

const resolvers = {
  Query: {
    hello: () => 'Hello, world!',
  },
};

const server = new ApolloServer({ typeDefs, resolvers });

server.listen().then(({ url }) => {
  console.log(`🚀 Server ready at ${url}`);
});

 

이 예제는 매우 간단한 GraphQL 서버를 보여줍니다. 

여기서는 하나의 쿼리만 있지만, 실제 애플리케이션에서는 사용자 정의 타입, 복잡한 쿼리 및 뮤테이션 등을 추가할 수 있습니다.

 


 

GraphQL 도구 및 리소스

GraphQL을 시작하는 데 있어 도움이 될 수 있는 다양한 도구와 리소스가 있습니다. 

Apollo Client는 클라이언트 사이드에서 GraphQL을 쉽게 사용할 수 있게 해주며, GraphQL Playground는 쿼리를 테스트하고 문서화하는 데 유용합니다. 

또한, 공식 GraphQL 웹사이트와 GitHub에서는 풍부한 학습 자료와 커뮤니티를 제공하고 있어, GraphQL에 대한 깊은 이해를 돕습니다.

 


 

최신 동향과 자원

  • GraphQL 공식 웹사이트 - GraphQL에 대한 공식 문서와 자습서, 스펙 등이 포함된 웹사이트
  • Apollo GraphQL - GraphQL 개발에 도움이 되는 도구와 자료가 제공되는 공식 웹사이트
  • GitHub GraphQL API - GitHub에서 사용하는 GraphQL API에 대한 문서와 예제
  • GraphQL Weekly Newsletter - GraphQL과 관련된 주간 소식과 리소스를 제공하는 뉴스레터
  • GraphQL Summit - GraphQL 커뮤니티 및 개발자와의 연결 기회를 제공하는 행사 정보

 

GraphQL은 현대 애플리케이션 개발에서 데이터를 관리하는 새로운 방식을 제시합니다. 

그것은 개발자에게 더 큰 유연성과 효율성을 제공하며, 애플리케이션의 성능을 개선합니다. 

GraphQL의 커뮤니티는 지속적으로 성장하고 있으며, 이 기술은 앞으로도 많은 발전을 이룰 것으로 기대됩니다. 

반응형
반응형

public static bool CheckCpIdenti(string cpIdenti)
{
            cpIdenti = cpIdenti.Replace("-", "");

            if (cpIdenti.Length != 10)
            {
                return false;
            }

            int sum = 0;
            string checkNo = "137137135";

            // 1. 각각의 자리에 1 3 7 1 3 7 1 3 5 를 곱한 합을 구한다.
            for (int i = 0; i < checkNo.Length; i++)
                sum += (int)Char.GetNumericValue(cpIdenti[i]) * (int)Char.GetNumericValue(checkNo[i]);

 

            // 2. 마지막에서 두번째 숫자에 5를 곱하고 10으로 나누어 나온 몫을 더한다.
            sum += (int)Char.GetNumericValue(cpIdenti[8]) * 5 / 10;

 

            // 3. 매직키인 10로 나누어 나머지만 취한다.
            sum %= 10;

 

            // 4. 매직키인 10에서 나머지를 뺀다. (단 나머지가 0이 아닐경우)
            if(sum != 0)

     sum = 10 - sum;

 

            // 5. 이숫자가 사업자등록번호 마지막 자리의 숫자와 일치하면 정상적인 사업자등록번호이다.
            if (sum != (int)Char.GetNumericValue(cpIdenti[9]))
                return false;
            else
                return true;
}

반응형
반응형

외부에서 사용할 API를 ASP.NET WebAPI로 구현을 했지만

자꾸 포맷이 이상하게 들어온다고 한다.

음 XML 포맷에 맞춰서 스트링으로 반환을 하고 있는데 뭐가 문제인지 알 수가 없었다.

 

Postman을 통해서 테스트를 하면서 응답 헤더 값을 확인 해보니 

Content-Type이 "application/json"으로 되어있었다.

 

혹시 해서 찾아보니 역시였다.

 

Content-Type을 "application/xml"로 맞춰서 아래 코드 형식대로 수정하니

정상적으로 파싱이 된다고 한다. ^_________________________^

 

너무 나태해졌으ㅋㅋㅋ

 

 

[HttpGet]

public HttpResponseMessage GetXml ()

{

string xmlString = "<? xml version='1.0' encoding='UTF-8'?><msg>TEST</msg>");

 

return new HttpResponseMessage() { Content = new StringContent(xmlString, Encoding.UTF8, "application/xml") };

 

}

반응형
반응형
반응형
반응형

 

ASP.NET Web API GET요청시 JSON 포맷으로 무조건 리턴 받게 하는 방식이다.

JsonMediaTypeFormatter를 이용해서 Employee 객체를 무조건 JSON으로 직렬화시켜서

응답으로 내보내게 된다.

 

public HttpResponseMessage Get(int id)
{
    var employee = list.FirstOrDefault(e => e.Id == id);
    return new HttpResponseMessage()
    {
        Content = new ObjectContent<Employee>(employee,
        Configuration.Formatters.JsonFormatter)
    };
}

반응형
반응형

C#에서 Excel파일을 생성하기 위해서 UTF-8로 지정을 해야지 파일이 깨지지 않는다

엑셀 dll을 사용하는 것이 아니라 XML 스프레드시트 형태로 만들어서 xls 확장자로

저장하는 형태이다.

string excel = header.ToString() + styles.ToString() + title.ToString() + content.ToString() + footer.ToString();
context
.Response.ContentType = "application/excel";
context
.Response.AddHeader("Content-disposition", "attachment; filename=\"report.xls\"");
HttpContext.Current.Response.BinaryWrite(UTF8Encoding.UTF8.GetBytes(excel));

반응형
반응형

IIS에서 웹 사이트를 새로 생성하고 파일 경로를 설정한 이후 부터 설명 하겠다.

자꾸 잊어버리네멍2


1. ASP.NET 4 사용 설정

.NET Framework 4를 설치하면, IIS의 Web Service Extensions 4가 등록 되어있지만 기본 값이 "금지(Prohibited")로 설정되어있다.


ASP.NET v4.0.30319 라인에서 우클릭을 하고 "허용(Allowed)"를 선택한다. 


2. 와일드카드 맵 추가

Web-Forms 어플리케이션을 구성한 다음에는 어플리케이션이 실행이 될 것이다.  하지만 MVC 어플리케이션으로 개발을 하였다면 마지막 한가지 단계가 더 해야한다. 추가한 어플리케이션을 위한 와일드카드 맵(Wildcard map)을 추가할 필요가 있다.

IIS로 돌아가서 웹 사이트에서 우클릭을 한 후 "속성" -> "홈 디렉토리" -> "구성" 을 선택한다.

아래 부분에 와일드카드 응용 프로그램 매핑(Wildcard Application maps) 설치된 리스트를 볼 수 있다. 그런데 비어 있을 것이다. 여기서 "삽입(Insert)" 버튼을 클릭한다.

응용 프로그램 확장 매핑 추가 / 편집 대화창이 나타난다. 실행파일(Excutable) 텍스트 입력 필드에 ".NET Framework 4.0 isapi-extension" 보통 c:\Windows\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll 경로를 입력한다. 그리고 파일이 있는지 확인("Verify that file exist") 체크 박스의 체크를 해제한다.

확인("OK") 버튼을 클릭하면 대화창이 닫힌다.

이제 MVC4 어플리케이션을 실행에 대한 설정은 모두 준비 되었다.


참조 블로그 : http://sde03.azurewebsites.net/?p=3101


반응형

+ Recent posts