졸려서 귀찮지만
그래도 생각난 김에
 
미디엄에서 글을 보다가
아래와 같은 코드를 봤다.
 

public boolean isOdd(int num) {
	return (num & 1) != 0;
}

 
홀수를 판정할 때 나머지 연산자보다 위와 같이 비트 연산자를 사용하면 더 빠르다는 내용이었다.
 
왜 더 빠르고
얼마나 더 빠를까?
 
복습할겸 정리해봤다.
 

왜 더 빠른가?

알다시피 1을 이진법으로 나타내면 00000001 이다.
9를 이진법으로 나타내면 00001001 이다. 
 
* 왜 앞에 0이 여러개 붙는지 모르는 사람들을 위해
컴퓨터에서 일반적으로 제일 작은 단위는 1비트이며, 1비트는 2진수 한 자리값, 즉 0 혹은 1의 값을 갖는데 이걸 8개 붙여서 8비트가 되면 우리가 아는 1Byte가 된다. 따라서 위는 숫자 1과 9를 8비트로 저장한 형태이다.
 
&(AND) 비트 연산자는 각 비트를 비교하여 둘 다 1인 경우에만 결과 비트가 1이 되고, 그 외에는 0이 된다.
 
그럼 9와 1을 &연산으로 비교해보면
1      : 00000001
9      : 00001001
결과 : 00000001
가 나온다. 
 
홀수는 일반적으로 맨 오른쪽 비트가 1의 값을 갖고 짝수는 0을 갖기 때문에 
& 연산을 거쳐서 결과로 나온 값이 1이면 홀수, 아니면 짝수라고 볼 수 있다.
 
(왜 홀수의 맨 오른쪽 비트는 1이고 짝수는 0인지 이해가 안되면 직접 숫자를 이진법으로 1부터 쭉 나열해보면 규칙성을 알 수 있다.)
 
이러한 연산 과정은 나머지 연산보다 간단하며, 비트 연산자는 컴퓨터의 비트 단위 논리 연산 기능을 사용하여 매우 효율적으로 구현되어 있고 이러한 구현은 하드웨어 수준에서 최적화되어 있기 때문에 빠른 실행 속도를 제공한다.
 

얼마나 빠른가?

얼마나 빠른지 어떻게 알 수 있을까.
찾아보니 자바에서는 JMH(Java Microbenchmark Harness) 라는 것을 사용해 성능을 측정할 수 있었다.

 

음... 사실 이 글에서 JMH를 이용해 나머지 연산자와 비트 연산자 방식의 성능 차이를 직접 보려고 했는데

막상 해보니까 그렇게 유의미한 차이가 나지 않았다.

 

어쩌면 내가 성능 테스트 설정을 잘못한 걸수도 있고, 또 검색해보니 하드웨어나 컴파일러마다 차이가 있을 수 있다고 해서 이건 조금도 자세히 알아보고 나서 다른 포스팅으로 올릴 예정이다.

'JAVA' 카테고리의 다른 글

Thread-Safe한 Singleton 패턴  (1) 2022.08.25

우선 사전 지식 복습!

영속성(Persistence)

객체가 생성된 후에도 해당 객체의 상태를 유지하고, 다시 로드하여 사용할 있는 것을 의미한다. 

즉, 객체의 상태를 저장하고, 필요할 때 다시 불러와 사용할 수 있도록 해야한다.

그렇게 하기 위해 더 나아가서 우리는 데이터를 생성한 프로그램의 실행이 종료되더라도 사라지지 않는 데이터가 필요하다.

이를 위해 데이터베이스 같은 저장소에 저장하고 객체 정보를 다시 불러와 사용할 수 있도록 지원하는 과정들이 필요하다.

 

JDBC

Java에서 DB와 연결되어 데이터를 주고 받을 수 있도록 하기 위해 제공하는 표준 API이다. Java에서 DB와 연결하는 기술은 모두 내부적으로 JDBC API를 사용하게 된다. (JPA, MyBatis 등) 이를 통해 DBMS의 종류에 상관없이 JDBC를 이용해 쉽게 연결할 수 있다.

 

더 자세히 설명하자면, DBMS 회사들이 자신들의 데이터베이스 시스템에 접근할 수 있도록 표준 JDBC 인터페이스에 명시된 메소드들을 구현한 것을 JDBC 드라이버라고 한다. 따라서 자바 어플리케이션에서 JDBC를 사용하면 JDBC 드라이버를 제공하는 어떤 종류의 관계형 DBMS에도 접근이 가능하고, 사용자들은 특정 회사의 데이터베이스의 정확한 사용 방법을 몰라도 JDBC API만 알면 데이터베이스 조작이 가능하게 되는 것이다. JPA와 MyBatis도 내부적으로 JDBC를 사용하기 때문에 간편하게 DB 설정을 바꿀 수 있는 것.

 

JDBC 이전에는 MySQL과 Oracle 같은 DBMS들은 각자의 DB Driver를 가지고 있고 개발자는 각각 그에 맞게 개발해야했고 한다. 하지만 JDBC를 사용하면 Oracle에서 MySQL로 DB를 바꾼다고 하면 JDBC 설정만 바꿔주면 되게 되었으니 엄청 편해진 것.

 

JPA란?

Java Persistence API 

JPA는 자바 진영에서 제공하는 ORM(Object Relational Mapping) 기술에 대한 표준 API 이다.

객체와 관계형 데이터베이스의 데이터를 매핑하여 개발자가 손쉽게 데이터베이스를 다룰 수 있도록 도와준다.

Java 애플리케이션과 JDBC 사이에서 동작한다. 개발자가 JPA를 사용하면, JPA 내부에서 JDBC API를 사용해 SQL을 호출하여 DB와 통신한다. 

 

애플리케이션 개발자가 객체를 데이터베이스에 저장하고 조회할 때 발생하는 많은 문제를 해결해준다.

예를 들어 객체와 테이블 간의 매핑, 데이터베이스 연동 코드 작성, SQL 작성 등의 작업을 JPA가 대신 처리해주기 때문에

개발자는 그러한 작업에 집중하지 않고 비즈니스 로직 구현에 집중할 수 있다. 

 

JPA는 Hibernate, EclipseLInk, OpenJPA 등 다양한 구현체가 있으며 스프링 등의 다양한 자바 프레임워크에서 사용된다.

 

ORM이 뭔데?

ORM은 Object-Relational-Mapping 이라는 이름 그대로 객체 지향 프로그래밍 언어와 관계형 데이터베이스 간의 데이터를 변환해주는 기술이다. 

 

ORM은 객체 지향 프로그래밍 언어에서 사용하는 클래스, 객체, 상속 등의 개념을 관계형 데이터베이스에서 사용하는 테이블, 레코드, 외래키 등의 개념으로 변환하여 데이터를 저장하고 조회한다. 

 

ORM을 사용하면 개발자는 SQL을 직접 작성하는 대신 객체 지향적인 코드로 데이터베이스를 다룰 수 있다.

이에 따라 객체 지향적인 코드를 작성하여 코드의 가독성 향상, 생산성 향상, 유지보수성과 확장성이 좋아지는 장점이 따라온다.

 

다만, 복잡한 통계성 쿼리 작업에는 적합하지 않고 실시간 처리용 쿼리에 적합하다!!

왜냐하면 ORM은 객체 지향적인 관점에서 데이터베이스에 접근하는데, 이 때 단순한 쿼리를 통해 개발자가 정의한 객체와 데이터 베이스 테이블을 매핑하기 때문에 복잡한 로직을 포함하는 쿼리나 통계적인 연산은 SQL을 직접 작성하는 것이 더 효율적이다.
또한 ORM 기술은 자동으로 데이터베이스와 매핑 작업을 거치기 때문에 데이터베이스에 직접 쿼리를 작성하는 것보다 상대적으로 느릴 수 있으며 복잡한 쿼리에 대한 최적화 작업이 쉽지 않을 수 있다. 

 

그치만 복잡한 서비스를 운영하는 대기업들이 JPA로 잘만 하고 있는걸 보면 쓰는 사람 나름인거같다 ㅎ 

 

MyBatis는 ORM은 아닌거 같은데 그럼 뭐지

MyBatis는 SQL Mapper 로 분류 된다.

SQL Mapper 는 개발자가 쿼리를 직접 작성하고, 쿼리와 자바 객체간의 매핑을 XML 등의 설정 파일을 통해 정의한다. 

 

MyBatis도 자바 객체와 데이터베이스 간의 매핑을 처리하는 기능을  일부 지원한다는 점에서 ORM의 역할을 어느정도 수행하지만,

다른 ORM들과의 큰 차이점은 다른 ORM 프레임워크들이 코드 기반을 강조하는 것과 달리 개발자가 직접 SQL을 작성하도록 한다는 것이다.

 

'백엔드' 카테고리의 다른 글

HTTPS 동작 방식  (0) 2022.06.29
JAR 와 WAR  (2) 2022.06.20
리액티브 프로그래밍 (Reactive Programming)  (1) 2022.06.13
도커(docker)에 톰캣(tomcat) 설치하기  (0) 2022.06.08


드디어 앵그리박스 프론트 작업이 막바지에 이르렀다. ㅜㅜ
프론트 팀원분이 계속 개인 사정이 생기셔서 상당히 오래 기다렸지만.. 결국 책임감을 갖고 작업해주셔서 감사하게 생각하고 있다.

프론트 작업이 80% 정도 완료 되어서 백엔드 쪽에서도 기능 확인을 위해 한 번 전체적인 체크를 하려고 사이트에 접속해서 이것 저것 해보았다. 근데 하다보니 사이트가 뭘 할 때마다 로딩 속도가 상당히 느렸다. 아니 굉장히 느렸다.... 왜 이러지? 하고 프론트 쪽이랑 같이 얘기해보니까 아마도 API 서버가 응답 속도가 오래 걸리는 것 같다고 결론이 났다. API 에 요청을 보내지 않는 화면은 굉장히 빠르게 로딩이 끝났기 때문이다.

그렇다면... API 응답 속도를 향상 시켜야지!
다른 백엔드 팀원과 둘이서 머리를 맞대고 생각해보았고 원인은 아마 아래의 이유로 추정되었다.

AWS 리전이 캘리포니아에 있어서 물리적으로 거리가 머니까 응답 속도가 느린 것 같다!
→ 그렇다면 서울 리전으로 옮기자!

한국에 살면서 멀쩡한 서울 리전 냅두고 왜 캘리포니아에 만들었냐고 물어본다면...
사실 AWS에 모든 셋팅을 끝내고 나서 서울 리전이 아니라 캘리포니아 리전이라는 것을 알아버렸고 그 당시에는 다시 셋팅할 필요까지는 없다고 생각하고 넘어 갔었다. 하하... 실수였다...

리전 이동 과정을 간략히 정리하면 아래와 같다.

  1. 캘리포니아에 있는 ec2의 이미지 생성
  2. 서울 리전에서 이미지를 사용하여 인스턴스 생성
  3. Route53에서 기존에 설정되어 있던 A, CNAME 레코드 삭제
  4. AWS Certificate Manager에서 SSL 인증서 발급 (발급 요청 후 CNAME을 복사하여 Route53에 CNAME 새로 생성)
  5. 로드밸런서 생성 (타겟 그룹도 같이 생성하고 인스턴스 연결)
  6. Route53에서 A레코드 추가하여 로드밸런서와 연결 (별칭 on 해야 해당 옵션 선택 가능)
  7. 로드밸런서에 타겟 그룹 연결
  8. 그 외 설정은 기존의 ec2에 되어있었고 이미지로 복사해왔기 때문에 바로 완료~~!

리전을 옮긴다 쳐도 얼마나 개선되었는지 수치로 확인하고 싶었기에 Jmeter를 사용하여 간략하게 성능 테스트를 함께 진행 했다.

프로필 조회 리전 이동 후

프로필 조회 리전 이동 전


솔직히 테스트툴 안쓰고 사이트에만 접속해봐도 바로 체감이 느껴질 정도로 차이가 나게 좋아졌다.

사이트만 보면 더 이상 손을 쓰지 않아도 될 정도로 좋아지긴 했지만..
공부 차원에서 다음에는 DB 쿼리를 살펴보고 더 최적화해서 응답 속도를 더 향상 시킬 수 있는지 확인해볼 예정이다.






 

싱글톤은 인스턴스를 1개만 생성하기 위해 사용하는 디자인 패턴이다.

 

소켓이랑 스레드 공부하다가 싱글톤은 스레드 세이프하지 않을거 같다는 생각이 들어서 찾아보다가 나중에도 까먹으면 다시 보려고 정리. (사실 더 여러 개 있는데 몇 개는 생략..)

 

1. 기본적인 싱글톤

public class Singleton {
    private static Singleton instance;
    public static Singleton getInstance() {
        if(instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

Thread-safe 하지 않다.

멀티 스레드 환경에서 if(instance == null) 을 여러 개의 스레드가 동시에 실행한다면 인스턴스가 여러 개 생성될 수 있다.

 

2. Synchronized 메소드 적용

public class Singleton {
    private static Singleton instance;

    public static synchronized Singleton getInstance() {
        if(instance == null){
            instance = new Singleton();
        }
        return instance;
    }
}

Thread-safe는 보장된다.

하지만 성능 문제가 있다. 싱글톤을 최초로 생성하는 경우에만 Lock을 걸면 되는데, 이 경우는 싱글톤 인스턴스를 가져올때 마다 Lock을 걸기 때문이다.

 

3. 클래스 로드와 동시에 초기화

public class Singleton {
    private static Singleton instance = new Singleton();

    private Singleton(){

    }

    public static Singleton getInstance() {
        return instance;
    }

}

클래스가 로드될 때 한 번만 초기화가 되기 때문에 Thread-safe는 보장된다.

하지만 해당 싱글톤이 한 번도 사용되지 않아도 인스턴스가 생성되는 것이기 때문에 성능상 좋지는 않다.

 

4. LazyHolder 기법

public class Singleton {

    private Singleton() {
    }

    public static Singleton getInstance() {
        return LazyHolder.instance;
    }

    private static class LazyHolder {
        private static final Singleton instance = new Singleton();
    }
}

자바 진영에서 가장 많이 사용되는 기법이라고 한다. 

sychronized 나 volatile 같은 키워드도 필요 없고 JAVA 버전도 상관없이 Thread-safe 를 보장한다.

내가 이해한 동작 방식은 아래와 같다..

- Singleton 클래스에는 LazyHolder 클래스의 변수가 없기 때문에 클래스 로딩 시 LazyHolder 클래스를 초기화하지 않음.

- getInstance() 호출 시 LazyHolder 클래스가 초기화되는데, 클래스가 로딩 되고 초기화되는 시점은 Thread-safe가 보장되므로 LazyHolder 안에 선언된 static instance 변수를 클래스 초기화 시점에 딱 한번만 생성되게 된다. 더불어 final 변수이므로 다시 instace가 할당되는 것 또한 막을 수 있다.

 

여기서 잠깐,

JVM은 static을 맨처음에 다 메모리에 올리는걸로 알고 있는데 LazyHolder가 왜 getInstance 호출 시점에 초기화 된다는건지 이해가 안된다면? 아래 블로그를 참고하자.

 

https://kdhyo98.tistory.com/70

 

[Java] static inner class 는 언제 로드가 될까? 로드와 초기화?

😣서론 최근 싱글톤을 직접 구현하여 사용하게 되었고, 스레드 세이프를 하기 위해서 static inner class를 사용하게 되었다. public class LottoTicketBooth { private LottoTicketBooth() { } private static cl..

kdhyo98.tistory.com

요약하자면, static Inner 클래스는 처음에 로드되어 메모리에 올라가는 것은 맞지만 Outer 클래스에서 호출하기 전까지는 클래스가 초기화 되지는 않는다는 것.

 

 

references

https://injae-kim.github.io/dev/2020/08/06/singleton-pattern-usage.html

 

'JAVA' 카테고리의 다른 글

비트연산자로 홀수판정이 더 빠르다 왜  (1) 2023.05.17

이클립스에서 생성한 스프링 레거시 프로젝트를 인텔리제이로 열어볼 일이 있었다.

 

하나씩 설정 고쳐가면서 하고 있는데 DB에서 불러온 한글 데이터는 괜찮은데 코드에서 직접 넣은 한글이 자꾸 깨졌다..

 

당연히 인코딩 문제이겠거니 하고 검색했는데 생각보다 여러 개를 만져야 하길래 정리.

 

 

File Encoding 설정

1. File - Settings 로 이동

2. Editor - File Encodings 에서 인코딩 관련 설정 모두 변경

 

 

VM Options 설정

1. Help - Edit Custom VM Options 클릭

2. idea64.exe.vmoptions 파일이 열리면 아래 2줄의 인코딩 설정을 붙여넣고 인텔리제이 껐다 킴

-Dfile.encoding=UTF-8
-Dconsole.encoding=UTF-8

 

(Gradle인 경우) build.gradle에 인코딩 설정 추가

build.gradle에 아래 코드를 넣고 빌드

compileJava.options.encoding = 'UTF-8'
tasks.withType(JavaCompile) {
    options.encoding = 'UTF-8'
}

 

1. Gradle 에 junit, spring-test 추가 (spring-test는 사용 중인 spring 버전과 맞춰줘야함)

testImplementation 'junit:junit:4.12'
testImplementation 'org.springframework:spring-test:5.0.2.RELEASE'

 

2. Test 클래스 설정

@RunWith(SpringJUnit4ClassRunner.class) // spring-test dependency 넣을 때 사용 중인 Spring과 꼭 버전 맞추기
@WebAppConfiguration
//@ContextConfiguration("file:src/main/webapp/WEB-INF/spring/root-context.xml") //xml로 설정했을 때.....
@ContextConfiguration(classes= {ControllerConfig.class})
@Transactional // transactinalManager 빈을 설정해줘야함
public class SpringMvcGradleTest {

	@Autowired
	UserDao userDao;

	@Test
	public void testInsertUser() {
		// 테스트 내용
    }
}

 

 

+ transactionalManager 

@Bean
    public PlatformTransactionManager transactionManager() {
        final DataSourceTransactionManager transactionManager = new DataSourceTransactionManager(dataSource);
        return transactionManager;
    }

 

 

이렇게 간단한데... 

이거 때문에 1시간 30분 동안 씨름.... !!! (레거시 잘 몰라서 config.java랑 root-context 섞어 쓰고 있었음...)

ㅠㅠ

'백엔드 > 스프링' 카테고리의 다른 글

Spring Rest Docs 적용 (Maven)  (0) 2022.06.25

HTTP

- Hypertext Transfer Protocol

- 클라이언트와 서버 사이에 이루어지는 요청/응답 프로토콜

- 암호화되지 않은 방법으로 데이터를 전송하여 안전하지 않다. 

 

HTTPS

- Hypertext Transfer Protocol Over Secure Socket Layer

- 요청과 응답 데이터는 네트워크로 보내지기 전에 암호화된다.

- HTTPS 는 HTTP 하부에 SSL 같은 보안 계층을 제공한다.

 

SSL (Secure Sockets Layer)

- 암호화 기반 인터넷 보안 프로토콜- 인터넷 통신의 암호화, 인증, 데이터 무결성을 보장하기 위해 개발됨.- 웹에서 전송되는 데이터를 암호화한다. - TLS 암호화의 전신이다.- 1996년 SSL 3.0 이후 업데이트 되지 않았으며, 앞으로 사라지게될 것으로 여겨지고 있다. SSL 프로토콜에는 알려진 취약성이 여러가지 있으며 보안 전문가들은 SSL 사용을 중단하라고 권장한다. 실제로 최신 웹 브라우저는 대부분 이제 SSL을 지원하지 않으며, SSL을 제공하는 업체는 사실상 TLS보호를 제공하는 것이다. 

 

암호화 : 제 3자로부터 전송되는 데이터를 숨김

인증 : 정보를 교환하는 당사자가 요청된 당사자임을 보장

무결성 : 데이터가 위조되거나 변조되지 않았는지 확인

 

암호화 방식

대칭키

  • 암호화 · 복호화할 때 사용하는 키가 동일한 방식
  • 키가 한 개 뿐이므로 유출되어선 안됨
  • 비대칭키보다 속도가 빠르다. 

비대칭키(공개키)

  • 암호화 · 복호화할 때 사용하는 키가 서로 다른 방식
  • Private Key와 Public Key가 함께 존재한다.
  • Private Key로 암호화한 데이터는 Public Key로 복호화할 수 있고, Public Key로 암호화한 데이터는 Private키로 복호화할 수 있다.

CA 기관 (Certificate Authority, 인증기관)

브라우저가 접속하고자 하는 서버의 SSL 인증서를 받으면 이것이 진짜인지 가짜인지 검증해주는 기관이다. 

클라이언트와 서버 둘 다 신뢰하는 기관.

 

SSL 인증서(TLS 인증서)

인증서는 개인이 만드는 사설 인증서와 CA기관에서 발급한 공인 인증서가 있다. 

  1. 웹브라우저는 CA 기관들의 Public Key를 이미 알고 있다. 
  2. 서버에서 CA 기관에 서버 정보와 자신의 Public Key를 담아 SSL 인증서 발급 요청을 한다.
  3. CA 기관은 서버의 SSL 인증서를 발급한다. 
    1. SSL 인증서에 서버의 도메인을 비롯한 서버를 인증해주는 정보들을 담고
    2. Private Key와 Public Key 한쌍을 새로 생성하여 담아준다.
    3. 인증기관의 Private Key로 암호화하여 서버에 전달한다. 
  4. 서버와 브라우저가 통신하려고 하면 서버는 브라우저에게 SSL 인증서를 전달한다. 
  5. 브라우저는 SSL 인증서를 검증하기 위해 CA 기관의 Public Key로 SSL 인증서를 복호화한다.
  6. 복호화에 성공하면 SSL 인증서가 진짜라는 것이고, 복호화에 실패하면 진짜가 아니거나 CA기관에서 발급한 인증서가 아니라는 뜻이다. (주소창에 빨간색으로 신뢰할 수 없는 사이트라고 뜨는 경우)
  7. 복호화한 SSL 인증서에서 서버의 Public Key를 얻었고, 웹브라우저는 이제 서버를 신뢰한다. 이제 서버의 공개키로 실제 데이터 암호화에 사용할 대칭키를 암호화하여 서버에게 전송한다. 
  8. 서버는 웹브라우저가 자신의 Public Key로 암호화하여 전달한 대칭키를 자신의 Private Key로 복호화한다. 
  9. 이제부터 서버와 브라우저는 대칭키 방식으로 암호화 통신을 할 수 있다.

HTTPS를 써도 성능이 떨어지지 않는 이유는 최종적으로 대칭키 방식으로 동작하기 때문이다. 

 

 

Reference

https://www.cloudflare.com/ko-kr/learning/ssl/what-is-ssl/

https://aws-hyoh.tistory.com/59

 

HTTPS 통신과정 쉽게 이해하기 #5(CA, 인증기관)

지난 #1, #2, #3, #4 문서에서 서버가 보유한 SSL 인증서를 인증기관(CA)이 발급한다고 설명했습니다. 그렇다면 도대체 이 인증기관(CA)은 무엇일까요? 그리고 내가 사용하는 브라우저는 접속하는 웹

aws-hyoh.tistory.com

 

'백엔드' 카테고리의 다른 글

JPA 개념  (2) 2023.04.29
JAR 와 WAR  (2) 2022.06.20
리액티브 프로그래밍 (Reactive Programming)  (1) 2022.06.13
도커(docker)에 톰캣(tomcat) 설치하기  (0) 2022.06.08

처음 Musicat 프로젝트를 진행할 때는 Rest API 서버를 구축하면서 왜 써야하는지 모르고 갖다 쓴 것도 많았다.

 

대표적인 예가 Swagger-UI 그리고 RestDocs 였다.

 

우리가 처음 REST API 서버를 개발하게된 것은 좀 갑작스러웠는데, 학원에서 계속 MVC 구조로만 개발하다가 마지막에 갑자기 각 조마다 REST API 서버로도 개발하는 기능이 있는 것이 좋겠다고 하셔서 급하게 공부해서 추가하게 되었다.

 

그 때 학원에서 요구한 스펙 중 하나가 바로 문서 자동화였는데, 처음에는 적용하기 쉬운 Swagger-UI를 제안하셨고 우리는 '문서 제공겸 테스트도 제공하는 툴' 정도로만 이해하고 우선 적용했었다.

 

하지만 사실 우리는 백엔드-프론트 모두 우리가 개발했기 때문에..

자기가 맡은 API 스펙은 자기 머릿 속에 들어있어서 사실상 Swagger-UI는 전혀 필요하지가 않았다.  (API 테스트는 Postman이 더 편해서 테스트할 때도 필요가 없었다.)

 

플젝이 다 끝나고 나서 Swagger-UI 말고 RestDocs를 적용해보는 것이 어떠냐고 하셔서 또 부랴부랴 알아보았고,

비즈니스 코드를 깔끔하게 유지할 수 있고 테스트 코드 기반으로 돌아간다는 점이 확실히 더 나아보여서 적용했었다.

 

그러나 그 때도 그저 적용해보는 것에 끝났고 실제 사용자에게 노출될 화면이라던가 이런 것까지는 잘 고려하지 않았었다. 

API 문서에 대해 이론적으로는 알았지만 그 필요성에 대해 몸소 느껴보지 못했기에 '이정도면 됐지' 라고 생각했던 것이다.

 

하지만 Angry-Bank를 진행하면서 프론트/백엔드 파트를 나눠서 프론트 개발자분들과 협업하며 API문서를 노션에 직접 작성해주는 방식으로 진행했는데, 아주 많은 것을 느낄 수 있었다.

 

그 중 가장 크게 느낀 것은 두 가지였는데,

 

1. API문서는 생각보다 자세하게 써야한다... 자세하면 자세할수록 좋다...! (대충 쓰면 프론트쪽에서 문의가 많이 들어오거나 프론트분들이 작업하실 때 불편하다.) 

 

2. 코드를 고치고나서 API 문서를 수정해주는 것을 까먹는다면 그것은 누군가에게 작업 시간 피해로 돌아간다! (그치만 새벽에 졸면서 작업을 하고나면 높은 확률로 까먹어버린다.)

 

결론 : API 문서는 모자란 정보 없이 적고, 자주 수정해줘야한다.

 

이전에 문서 자동화에 대해 공부할 때 여러 번 읽었던 내용이었다. 하지만 직접 해보니 정말 왜 자동화를 해야하는지에 대해 뼈저리게 느낄 수 있었다. 

 

그래서!

오랜만에 musicat-audio REST 서버에 적용했던 문서를 다시 들춰보았을 때 깜짝 놀라고 말았다. 

테스트 코드를 작성하고 스펙을 뽑는 것까진 해놨지만, 실제 API 문서를 출력해주는 화면은 만들지 않고 있었던 것이다. 

 

변명을 하자면... 당시의 우리는 문서를 보는 입장이 되어본 적도, 문서를 보여주는 입장이 되어본 적도 없었던지라 '오, 테스트 코드도 잘 돌아가고 스펙도 adoc 파일로 잘 나왔네.' 까지만 생각하고 말았던 것 같다... ^^;;;

 

이제라도 알게 되어서 다행이다... 라고 생각하며 부랴부랴 API 문서 출력 화면(html)을 만들었다.

RestDocs 적용법 정리 : https://fidget278.tistory.com/54

 

Spring Rest Docs 적용 (Maven)

Spring Rest Docs란? Rest API 서버를 개발하다보면 같이 협업하는 사람들에게 API 문서를 제공해야할 일이 생긴다. 이 때 직접 문서를 정리하게 되면 코드와 항상 맞춰주기가 힘들다. 코드를 변경하면

fidget278.tistory.com

 

html 까지는 순조롭게 만들었는데, 실제로 배포했을 때 docs/index.html 로 접근하지 못하는 문제가 있었다.

우리는 war로 패키징하여 외장 톰캣으로 배포하는데 아마도 외장 톰캣과 경로가 겹쳐서 그런 것 같았다.

docs/index.html 로 접근하던 것을 restdocs/restdocs-index.hmtl 로 고쳐주니 잘 되었다. 

 

이제 테스트 코드로 뽑은 문서들은 전부 html 파일에 담아주는 작업을 해야한다.

문서 수정을 까먹는 일은 없어지겠지만 사실 이런 셋팅 해주는건 좀 시간도 많이 걸리고 불편하긴 하다... 역시나 100% 편한 일은 없는 것 같다..

+ Recent posts