AWS

[WriterSide] Publishing and Access Control

kahnco 2024. 4. 24. 20:30

개요

 개발 중이던 프로젝트의 규모가 비대해지면서 문서화의 절실함을 느끼게 되었습니다. 그에 따라 다양한 문서 툴을 비교해보게 되었고, 실제로 사용해보면서 제가 느낀 각각의 특징은 다음과 같습니다.


1. Notion

 어찌보면 가장 보편적이고 강력한 문서툴이라고 할 수 있습니다. 기본적으로 제공해주는 다양한 템플렛들이 존재하고, 은둔고수들이 잘 정리해놓은 무료 템플렛 또한 여럿 존재하기 때문에 가장 먼저 후보에 올려놓은 문서툴이었습니다. 또한, 프로젝트 단위로 프라이빗한 공간에 작성하고 이를 한정된 사용자만 볼 수 있기 때문에 여러 팀원들과의 커뮤니케이션이 원활하였습니다.

 허나, 한글을 사용하면 마지막 글자가 씹힌다거나, 네트워크 상태가 조금이라도 좋지 못하면 그 사이에 작성했던 문서들이 통으로 날아가버리는 크리티컬한 문제가 있었습니다. 글자가 씹히는 문제는 인내심을 가진다면 상관없는 문제였지만, 공들여 작성한 문서들이 사라져버리는 문제는 치명적이기 때문에 노션을 폐기하게 되었습니다.

2. Confluence

 이슈 및 프로젝트 추적 툴로써 Jira를 사용하고 있던 터라, Jira와 좋은 연동성을 자랑하는 Confluence 또한 자연스러 후보에 오르게 되었습니다. 스프린트 리뷰 페이지를 Jira에서 Confluence로 자동 생성해주는 기능은 특히나 유용했습니다.

 하지만, 문서의 트리 구조가 가시적이지 못한 문제와 사용 가능한 문서 템플렛의 적은 개수로 인해서 폐기되었습니다.

3. Microsoft Loop

 거의 프리뷰 수준에 노션을 카피한 문서툴이었지만, Microsoft Office 제품을 사용하고 있던 차에 괜찮은 선택지라 생각되었습니다. 노션의 기능들을 대부분 사용할 수 있을 뿐만 아니라, 파일까지 참조 가능하다는 점 만큼은 노션보다 나은 퍼포먼스를 보여주었습니다.

 하지만, 정말 크리티컬한 문제로 네트워크 상태가 문제가 없음에도 불구하고 작성하였던 문서의 양식이 깨져버린다던가, 문서 자체가 없어져버리는 일이 빈번하게 발생하였습니다. 심지어 노션보다 훨씬 빈번하게 발생했기 때문에 최단 기간 폐기라는 불명예를 안으며 퇴장하였습니다. 

4. Jetbrains WriterSide

 마지막으로, Jetbrains에서 제공하는 WriterSide 가 후보에 올랐습니다. 토픽이라는 개념을 파일 계층 구조로 쌓아내려가는 형식이기 때문에 히스토리 추적에 굉장히 용이했고, 마크다운과 XML 키워드 모두 지원했기 때문에 개발자가 금방 적응해서 사용할 수 있었습니다. (Mermaid까지!!)

 하지만, 이 역시 단점이 존재했습니다. 얼리 억세스로 나온 제품이라, 퍼블리싱에 굉장한 제약 조건들이 존재했고 토픽과 파일 간에 달리 적용되는 네이밍 룰을 따라가기가 조금 어려웠습니다.


하지만...

 그럼에도 불구하고, 다음과 같은 이유들로 WriterSide는 저에게 너무 매력적인 문서툴이었습니다.

  1. 네트워크 상태에 전혀 영향을 받지 않습니다
  2. 버전 관리를 사용할 수 있기 때문에 히스토리 추적이 용이했습니다.
  3. 동일한 문서를 여러 사람이 수정한다 하더라도, 브랜치 전략을 통해 충돌을 비교적 쉽게 해결할 수 있습니다.
  4. 개발자에게 친숙한 마크다운, XML 키워드를 그대로 쓸 수 있습니다.

 위의 내용들은 지금까지 거쳐왔던 문서툴들의 단점을 그대로 극복할 수 있는 장점들이기 때문에 WriterSide를 최종 선택하게 되었습니다.


이제 문제는...

 최대의 고비인 퍼블리싱 단계가 남았습니다. 그나마 Docker 빌드를 공식 지원하지만, Non-Latin Language인 한국어에게 최악인 단점이 존재했습니다. 그것은 바로... 토픽 파일과 토픽 타이틀에 Non-Latin Language가 존재하면 해당 토픽은 퍼블리싱된 이후에 접근 불가한 페이지(Oops, Sorry its our fault)가 되거나 새로고침 시 404 에러가 발생하는 문제였습니다. Dockerfile에서 커스텀해보려고 했으나 얻는 이득에 비해서 공수가 너무 많이 투입될 것 같아 일찌감치 포기하고, 작성된 토픽들에서 한글을 빼는 것으로 타협보았습니다.


퍼블리싱 시작

 일단 공식 지원되는 Dockerfile 을 통해서 Docker Image를 뽑아내보겠습니다. Dockerfile 내용은 다음과 같습니다.

FROM registry.jetbrains.team/p/writerside/builder/writerside-builder:241.15989 as build

ARG INSTANCE=Writerside/hi

RUN mkdir /opt/sources

WORKDIR /opt/sources

ADD Writerside ./Writerside

RUN export DISPLAY=:99 && \
Xvfb :99 & \
/opt/builder/bin/idea.sh helpbuilderinspect -source-dir /opt/sources --product $INSTANCE --runner other --output-dir /opt/wrs-output/

WORKDIR /opt/wrs-output

RUN unzip webHelpHI2-all.zip -d /opt/wrs-output/unzipped-artifact

FROM httpd:2.4 as http-server

COPY --from=build /opt/wrs-output/unzipped-artifact/ /usr/local/apache2/htdocs/

  

다행히 빌드는 문제없이 진행되었습니다. 이제 이를 퍼블리싱 해보겠습니다.

기존에 돌아가고 있던 K8S 클러스터가 있었기에, ArgoCD + HelmChart 의 조합으로 Namespace, Pod, Service를 생성해주었습니다. 사용된 커맨드 및 파일들은 다음과 같습니다.

kubectl create namespace document
apiVersion: apps/v1
kind: Deployment
metadata:
  name: document-pod
  labels:
    app: document-pod
  namespace: document
spec:
  replicas: 1
  selector:
    matchLabels:
      app: document-pod
  strategy:
    rollingUpdate:
      maxSurge: 30%
      maxUnavailable: 30%
    type: RollingUpdate
  template:
    metadata:
      labels:
        app: document-pod
    spec:
      containers:
        - name: document-pod
          image: "{Docker Image 저장된 곳}:{{ .Values.image_tag }}"
          imagePullPolicy: Always
          ports:
            - containerPort: 80
              protocol: TCP
apiVersion: v1
kind: Service
metadata:
  namespace: document
  name: document-svc
spec:
  selector:
    app: document-pod
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80

 

 이렇게 작성해두고, ArgoCD 에서 Application 생성 이후에 해당 파일들이 있는 경로를 타겟시켜주면 퍼블리싱 준비가 끝납니다. 이제 러닝 중인 SVC를 외부에서 접근 가능하도록 빼보겠습니다.

 

 K8S 에 ALB ingress controller 를 세팅하여 Ingress 생성 시에 ALB가 같이 생성되도록 세팅해두었습니다. 사용한 Ingress 설정 내용은 다음과 같습니다.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: "document-ingress"
  namespace: document
  annotations:
    alb.ingress.kubernetes.io/scheme: internet-facing
    alb.ingress.kubernetes.io/target-type: ip
    alb.ingress.kubernetes.io/group.name: documents-ingress-group
    alb.ingress.kubernetes.io/group.order: '1'
    alb.ingress.kubernetes.io/listen-ports: '[{"HTTP": 80}, {"HTTPS":443}]'
    alb.ingress.kubernetes.io/certificate-arn: {발급 받은 인증서 ARN}
    alb.ingress.kubernetes.io/actions.ssl-redirect: '{"Type": "redirect", "RedirectConfig": { "Protocol": "HTTPS", "Port": "443", "StatusCode": "HTTP_301"}}'
    alb.ingress.kubernetes.io/idle-timeout: '300'
spec:
  ingressClassName: alb
  rules:
    - http:
        paths:
          - path: "/"
            pathType: Prefix
            backend:
              service:
                name: "document-svc"
                port:
                  number: 80

 

이 단계까지 진행하면 ALB가 생성되는데, 해당 ALB의 DNS 주소를 통해 퍼블리싱된 WriterSide 페이지를 구경할 수 있습니다.

감격의 순간

 

해당 ALB의 DNS 주소를 Route53에서 레코드 생성을 통해 https 프로토콜 적용시켜주면 좀더 깔끔합니다.


접근 제한

 이제 퍼블리싱까지 완료했으니 끝!인줄 알았지만, 프로젝트에 사용되는 문서가 구글에 떠돌아다니는 꼴을 볼 수 없으니 간단한(?)  인증 단계를 넣어보겠습니다.

 저는 ALB를 선택해서 괜한 삽질을 했지만, 여러분은 꼭! Nginx Ingress 를 사용하시기 바랍니다... ALB는 Basic Auth 같이 간단하게 구현 가능한 인증 방식이 없고 무조건 OIDC, Cognito를 활용한 인증만 가능하게 되어있습니다.

 

 그래서 일단 간단하게 Cognito를 생성해주었는데, 신경쓸 부분들은 다음과 같습니다.

  • 호스팅 UI 설정 및 OAuth 2.0 엔드포인트를 Cognito 자동 모드로 생성하기 -> 사용자 지정 도메인으로 설정하면 해당 도메인의 인증서를 버지니아 지역밖에 참조 못하기 때문에 상당히 골치아파집니다.

  • 앱 클라이언트를 기밀 클라이언트 설정으로 생성하고, 보안 키는 꼭 생성하기 -> 보안 키가 없으면 Ingress Auth 구성 시에 Ingress 배포에 실패합니다.
  • OAuth grant 유형을 ` 권한 부여 코드 부여`로 설정하기
  • 호스팅 UI의 허용된 콜백 URL를 다음 포맷으로 설정하기
https://{아까 생성한 ALB의 DNS 주소}/oauth2/idpresponse
혹은
https://{ALB DNS 주소가 매핑된 Rounte53 레코드 주소}/oauth2/idpresponse

 

이렇게 진행하고나서 아까의 문서 페이지에 다시 접속하면...

암호를 대시오

 

위 그림과 같이 Cognito 로그인 화면이 뜨는 것을 확인할 수 있습니다.

반응형

'AWS' 카테고리의 다른 글

Make a Scheduler With AWS EventBridge  (0) 2023.11.21
Deploy Selenium to the AWS Machine  (0) 2023.11.18
AWS CDK - API Gateway Fix Note 1  (0) 2023.11.07