728x90

쿠버를 세팅 하면서 생긴 이슈이다.

 

sudo apt-get update

후에 생긴 에러다

 

해결법

sudo mkdir -p /etc/apt/keyrings

 

echo "deb [signed-by=/etc/apt/keyrings/kubernetes.gpg] https://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee /etc/apt/sources.list.d/kubernetes.list

 

curl -fsSL https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes.gpg

 

 

참고

https://github.com/kubernetes/release/issues/2862#issuecomment-1533888814

728x90

회사에서 테스트를 하면서 URL 클래스를 모킹해야 하는 일이 생겼다.

 

해당 클래스는 final 클래스였다. 

 

해당 클래스를 모킹하기 위해서는 mockito-inline 의존성을 추가 해야했다. (아래 pom.xml 에 추가)

<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-inline</artifactId>
    <version>버전</version>
    <scope>test</scope>
</dependency>

 

그런데 해당 의존성을 추가 했는데,

java.lang.ExceptionInInitializerError
    at org.mockito.internal.exceptions.stacktrace.ConditionalStackTraceFilter.<init>(ConditionalStackTraceFilter.java:17)

이런 오류가 발생하였다.

초기화 과정에서 발생한 에러인 것 같다.

 

해당 오류를 해결하기 위해 열심히 찾아본 결과 mockito의 버전 문제였다.

 

해당 프로젝트 에서는 mockito 1.xx대를 사용하고 있었다. 그래서 4.xx 버전으로 올렸더니 정상실행 되었다.

 

import 문에서 모키토 버전마다 아래와 같이 다른점이 있다고 한다. (더 많겠지만 대표적인 것들만 추려냄)

mockito 1.xx 버전 mockito 4.xx 버전
import static org.mockito.Matchers
import org.mockito.runners.MockitoJUnitRunner
import static org.mockito.ArgumentMatchers
import org.mockito.junit.MockitoJUnitRunner

 

 

 

결론: mockito 버전 올려서 mockito-inline 의존성을 추가 하였더니 됐다

728x90

<?> 는 와일드카드 타입이다. 즉 모든 타입을 의미한다. 주로 타입 인자를 알지 못할 때 쓰인다.

그러면 그냥 List와 List<?>의 차이는 무엇일까?

List<?> 를 매개변수로 사용하는 메서드는 List의 원소를 읽는 것은 가능하지만, 쓰는 것은 불가능하다.

 

읽기

List, List<?> 둘 다 파라메터로 받아 와서 읽는 것은 가능하다.

 

 

쓰기

코드상에서 바로 에러를 잡을 수 있다.(컴파일 전 타입체크)

List<?>는 write를 하지 못한다는 것을 알 수 있다.

728x90

멘토링을 시작한 계기

2022년 3월 부터 6월 까지 인턴을 하였고 인턴이 끝나가는 6월 말쯤 고민이 많아졌다. “인턴을 하던 회사에서 정규직으로 제안이 오면 계속 회사에 남을지”, “공부하는 시간을 가질지” 선택 사항을 두고 고민이 많았다.

 

인턴을 하며 개발이 쉽게만 생각했던 나는, 현업에서의 개발은 절실히 공부의 필요성을 느끼게 했다. 처음에는 현업에서 나 정도면 그냥 하면 되겠지 라는 안일한 생각을 하며 입사를 했었지만, 현업을 몸소 느껴보니 호락호락하지 않았다. 특히 기술적으로 부족함을 많이 느껴 공부할 시간이 필요하다고 생각했다. 그리고 학부때 배운 지식이 파편화되어, 파편 조각들을 모으는 작업이 필요했다.

 

정말 고맙게도 인턴을 하던 회사에서 정규직 제안을 나에게 해주었다. 이미 나의 마음속에 답은 정해져 있었지만, 막상 제안이 들어오니 다시 한번 고민하게 되었다. 그렇지만 앞으로 긴 시간을 따로 내어서 공부할 수 있는 시간이 많지 않다고 생각했다. 이번 기회에 혼자 공부 하는 시간을 가지고 싶었다. 그리고 무엇보다, 개발자로서 자기 주도 학습을 할 수 있는 힘을 스스로 키우고싶었다. 그래야 앞으로 개발자의 길에서 스스로 성장할 수 있는 힘이 생길 것 같다고 생각했다.

 

일단 뭐부터 공부해야할지 감이 오지 않았기 때문에 혼자는 무리가 있었다. 그래서 검색을 통해 나의 요구사항에 맞는 교육과정을 찾았다. 나의 요구사항은 간단했다. “기초부터 탄탄히 하고, 답을 알려주지 않고 스스로 성장할 수 있는 힘을 가질 수 있는 곳”이었다. F-lab이 나의 요구사항에 딱 드러맞았다.

 

정규직을 제안을 해오시던 사수님께 “저는 공부할 시간이 필요할 거같다” 라고 말씀 드렸다. 사수님이 “혼자 어떻게 할건지 구체적인 목표가 있냐, 없으면 회사에 남아 일하면서 공부할 시간을 주겠다”며 정말 감사하게도 이렇게 말씀해주셨다. F-lab 멘토링 과정에 참여할 예정이라고 말씀 드리니, F-lab 이라면 놓아주겠다고 하셨다. 왜냐하면 F-lab에 대한 사수님의 평이 정말 좋았었기 때문이다. 그렇게 인턴 생활을 했던 회사와 좋은 인연으로 남게되었다.

 

 

F-lab 멘토링의 시작

2022년 8월부터 자바 백앤드 코스를 시작했다. 처음에는 부담되는 가격이었다. 인턴 생활을 하며 저축한 돈과 주식으로 번 돈을 모두 나의 미래에 투자했다. “처음에는 이게 맞을까?” 라는 생각과 함께 불안감을 떨칠 수 없었다. 그러나 그 불안감은 멘토님을 만나고 더이상 느끼지 않았다. 뭔지 모를 확신이 들었다. 그렇게 Carrey 멘토님과 인연이 시작되며 6개월의 시간동안 매주 한번씩 만나게 되었다.

 

 

자바 기초 공부

처음 6주는 자바의 신 1, 2권을 읽고 토론하는 시간을 가졌다. 나는 그때까지는 언어를 사용하면서 그 언어를 기초부터 제대로 공부하지 않고 그 언어를 사용해 왔는데, 멘토링을 하면서 기초부터 제대로 배우는 느낌이 들었다. 그리고 실무에서 꼭 필요한 지식과 개념들을 알려주신 점도 알 수 있었다. 앞으로 실무를 하며 이런 개념들을 어떻게 사용되는지 상상이 되어서 좋았다. 그렇게 6주라는 시간이 흐르고 프로젝트를 하기 시작했다.

 

 

프로젝트 시작

처음에는 프로젝트 주제를 정하고 유즈케이스를 만드는 시간을 가졌다. 나는 당시에 스터디 카페를 즐겨 다녀서 스터디 카페 시스템을 만들어보고 싶어서 프로젝트 주제를 스터디카페로 정했다. 그 다음 마일스톤브렌치 전략, 프로토타입을 만들고 개발을 시작했다.

처음 멘토님의 코드리뷰를 받으며 개발을 할 때 멘토님은 객체지향을 강조하셨다. 이론적으로 객체지향을 배웠지만 실제 코드로는 아직 익숙하지 않았다. 그러한 점들은 코드 리뷰를 통해 배워나갔다. 여러가지 기술들을 적용 하려고 노력 하였고, 여러 트러블 슈팅 겪으며 한층 더 성장한 계기가 되었다.

 

개발한 애플리케이션을 배포를 하는 단계에서 CI/CD 부터 Auto scaling, Load balancer, pinpoint 등을 구축하는 경험이 처음이라 나에게 생소하게 다가왔다. 나의 사전에는 불가능이 없기 때문에 계속 문서를 읽고 하다보니 모두 구축할 수 있었다. 이제는 NCP를 자유자재로 다룰 수 있다고 말하고 다닐 수 있을 거같다 😏. 그리고 NCP를 사용하며 정리해둔 블로그 글들이 NCP 공식 블로그에 개제되는 기쁨도 얻을 수 있었다.

 

그리고 API 개발과 인프라 구성이 끝나고 이 API를 사용하고 싶어서 프론트도 개발을 해서 사용해보았다.

 

 

마치며

멘토링을 하지 않았다면 등골이 오싹한 정도라고 표현하고싶다. 스스로 공부하는 힘을 길러주었고, 어떤 개발자가 좋은 개발자인지 스스로 정의를 내려보고 생각해볼 수 있는 힘이 생겼다고 말하고싶다. 무엇보다 자기주도 학습이 가능하다고 생각이 되어서 너무 기쁘고 무엇보다 정말 좋은 멘토님을 만나서 많이 배운거같다. 앞으로 계속 좋은 인연으로 남고싶다.

728x90

문제사항 제시

이러한 에러를 맞이했다. Boolean 타입과 Timestamp은 비교대상이 안된다고 한다.

 

 

해결책 모색

나의 코드에서 Boolean 타입 혹은 Timestamp을 비교하고 있는 로직을 찾아보았다.

이 부분이 뭔가 잘못된 것 같다. 논리적으로 잘못된 것이 없어보이는데 아마 추측으로 '&&' 부분이 잘못된 것 같았다. 그래서 찾아보니 '&&'는 'AND'의 약어이고 같은 기능을 하지만 'AND'는 SQL 표준 연산자로 모든 데이터베이스 시스템에서 지원된다고 한다. (이식성이 좋은 것 같다.) 그래서 'AND'로 적용해보았다.

 

 

적용

 

 

결과

결과적으로 이제 해당 에러는 해결되었다. ㅎㅎ

 

728x90

문제사항 제시

오버부킹 이슈를 해결하려고 PESSIMISTIC_WRITE 락을 분명 걸었는데 락 적용이 되지 않았다. 

 

코드로 예시를 들어보겠다.

 

Customer 엔티티 코드이다.

@Entity
@Table(name = "customer")
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@ToString
@Getter
public class CustomerEntity extends BaseEntity {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;

    private String name;
    private String email;
    private String password;
    private String tel;

    @OneToMany(mappedBy = "customer", cascade = CascadeType.ALL, orphanRemoval = true)
    private List<ScheduleEntity> schedules = new ArrayList<>();

    ...

 

Schedule 엔티티 코드이다.

@Entity(name = "schedule")
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Getter
@ToString(exclude = {"studySeat", "customer"})
@Where(clause = "state = 'RESERVED' && started_time >= NOW()")
public class ScheduleEntity {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;

    @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.REFRESH)
    @JoinColumn(name = "customer_id", referencedColumnName = "id")
    private CustomerEntity customer;

    @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.REFRESH)
    @JoinColumn(name = "study_seat_id", referencedColumnName = "id")
    private StudySeatEntity studySeat;

    @Column(name = "started_time")
    @DateTimeFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss")
    private LocalDateTime startedTime;

    @Column(name = "end_time")
    @DateTimeFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss")
    private LocalDateTime endTime;

    @Enumerated(value = EnumType.STRING)
    private ScheduleState state;
    
    ...

 

StudySeat 엔티티 코드이다.

@Entity
@Table(name = "study_seat")
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@ToString
@Getter
public class StudySeatEntity {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;
    private String seatNumber;
    private boolean occupied;

    @OneToMany(mappedBy = "studySeat", cascade = CascadeType.ALL, orphanRemoval = true)
    private List<ScheduleEntity> schedules = new ArrayList<>();
    
    ...

 

StudySeatService 코드이다.

    public CommandReserveSeatResponse reserveSeat(final ReserveSeatRequest command, final long studySeatId) {
        Customer customer = findByCustomerId(command.getCustomerId());
        StudySeat studySeat = findByStudySeatId(studySeatId);

        check(studySeat.isReservable(command.getStartedTime(), command.getEndTime())
            , INVALID_SCHEDULE_RESERVATION_ALREADY_OCCUPIED)
        ;

        studySeat.reserve(
            customer, studySeat,
            command.getStartedTime(), command.getEndTime()
        );

        studySeatRepository.save(studySeat);

        return new CommandReserveSeatResponse(success, studySeatId);
    }

 

 

Customer, StudySeat은 Schedule과 1:M 관계이다. DDD 구조상 StudySeat 과 Schedule로 하나의 aggregate로 묶여져 있고 StudySeat이 Schedule을 제어하는 역할을 한다.

 

그래서 이와 같은 파일 구조를 가진다.

 

그래서 결론은 StudySeat의 Repository에 findById에 Lock을 걸었는데 적용되지 않았다.

여러개의 쓰레드를 만들어서 한꺼번에 실행 시키는 테스트 코드를 실행시켰는데, 콘솔에 찍히는 query문을 여러번 눈을 씻고 찾아봐도 select for update가 계속 찍혔는데도 내가 원했던 결과가 나오지 않았다.

 

 

해결책 모색

생각 해보니 Service 코드를 보면 Customer 부터 찾아오는 것을 확인할 수 있었다.

    public CommandReserveSeatResponse reserveSeat(final ReserveSeatRequest command, final long studySeatId) {
        Customer customer = findByCustomerId(command.getCustomerId());
        StudySeat studySeat = findByStudySeatId(studySeatId);

이 순서대로면 CustomerRepository에 락을 적용해야 원하는 결과가 나온다.

 

왜냐하면 Customer와 Schedule도 1:M으로 매핑되어 있기 때문에 Customer먼저 찾으면 

 

이런꼴이 되기 때문에 isReservable 메소드(예약이 가능한지 검증하는 메소드)에 들어가면 schedule이 비어 있어서 모두 통과가 되는 것이다. 그러면 락이 걸리는 StudySeat 부터 검색하게 하면 해결이 된다.

 

 

적용

    public CommandReserveSeatResponse reserveSeat(final ReserveSeatRequest command, final long studySeatId) {
        StudySeat studySeat = findByStudySeatId(studySeatId);
        Customer customer = findByCustomerId(command.getCustomerId());

 

결과

Customer를 먼저 찾아오게 되면 여러개 쓰레드 모두가 매핑된 Schedule이 비어있다고 인식된다. 그래서 락이 걸리는 StudySeat 객체 부터 찾아오게 하면서 이 문제를 해결했다. 락을 걸 때 순서 또한 중요하다고 느꼈다.

728x90

문제사항 제시

나는 테스트 환경에서 h2 in-memory db를 사용하고 있었다. 통합 테스트를 하려고 했는데 에러가 몇시간 동안 발목을 잡았다.

 

ddl-auto: validate를 해놓은 상태이고 엔티티와 디비가 맞는지만 확인했다.

 

그런데 Flyway가 실제 디비에 어떻게 적용시켰는지를 알아야 엔티티를 디비에 맞추든, 디비를 엔티티에 맞추든 할 수 있었다.

(사실 엔티티를 디비에 맞추면 OCP 위반이기 때문에 엔티티를 디비에 맞추어야했다.)

 

그렇게 하려면 디비의 상황을 알아야 했는데 아무리 h2.console.enabled=true 로 해놓아도 http://localhost:8080/h2 가 열리지 않았다.

 

 

해결책 모색

애초에 나는 application-test.yml, application.yml을 나눠놓았다.

 

그래서 application.yml 에서

 

spring:
  profiles:
    active: test

 

를 하고 애플리케이션을 실행시켜서 h2 console에 들어갈 수 있었다.

 

그 결과, 실제 어떻게 Flyway가 디비에 적용시켰는지, 왜 jpa가 매핑을 못시키고 있었는지 원인을 알 수 있었다.

 

 

원인

테이블들이 기본적으로 uppercase로 적용 되어 있었다.

 

적용

원인을 해결하기 위해 

 

datasource:
  url: jdbc:h2:mem:skka-for-test;MODE=MYSQL;DB_CLOSE_DELAY=-1;DATABASE_TO_LOWER=TRUE

 

결과

 

맨 뒤에

;DATABASE_TO_LOWER=TRUE

을 추가 해주니까 됐다.

728x90

오버부킹(Overbooking) 이란

오버부킹 이슈는 여러명의 사용자가 동시에 같은 자원을 예약하려고할 때 발생한다.

문제상황 제시

현재 SKKA프로젝트 도메인에서 오버부킹 이슈가 발생할 수 있는 가능성이 많다고 생각된다.
대표적으로 특정해 몇월 몇일에 스케줄을 예약하려고 하는데, 마침 그 날이 수요가 많은 날일 때 예약하려고 하는 요청들이 몰릴 것이다.
그렇게 된다면 처음에 해당 날짜에 예약을 요청한 사용자가 예약에 성공 해야 공정하고 투명한 시스템이 될 것 같다.

 


< 예시 >

[현재 테이블 상황]

id customer_id study_seat_id started_time              end_time                   
1 1 1 2023-12-01 11:12:00 2023-12-01 13:12:00
2 2 2 2023-12-01 14:12:00 2023-12-01 16:12:00
3 3 3 2023-12-01 18:12:00 2023-12-01 20:12:00

 

[1번 요청]

POST /seats/1 {
  "customerId" : 1,
  "startedTime" : "2023-12-01T09:00:00",
  "endTime" : "2023-01-10T11:00:00"
}

 

[2번 요청]

POST /seats/1 {
  "customerId" : 2,
  "startedTime" : "2023-12-01T09:00:00",
  "endTime" : "2023-01-10T11:00:00"
}

 

[3번 요청]

POST /seats/1 {
  "customerId" : 3,
  "startedTime" : "2023-12-01T09:00:00",
  "endTime" : "2023-01-10T11:00:00"
}

 

1, 2, 3번 요청이 한꺼번에 요청이 쏟아졌을 때 제일 먼저 온 요청만 처리 해야하고 나머지는 이미 차지 되었다는 에러를 던져야한다.


해결방안 모색

  • lock
    • ORM (jpa)
    • ORM 레이어에서 락을 사용하면 더 높은 추상화 수준을 제공해서 락 로직을 데이터베이스 대신 애플리케이션 코드에서 처리할 수 있다.
      그러면 개발 프로세스가 간소화될 것 같고, 특히 동시 트랜잭션이 많은 애플리케이션에서 성능이 향상될 수 있을 것 같다.
      그러나 덜 견고하거나 확장 가능하지 않을 수 있으며 일관성을 유지하고 교착 상태를 피하기 위해 추가적인 관리가 필요할 수 있을 것 같다.
    • DB
    • 데이터베이스(DB) 레이어의 락은 데이터베이스 수준에서 구현되므로 애플리케이션 코드와 독립적이므로 더 신뢰성이 높고 견고하다.
      여기서 신뢰성이 높고 견고하다는 의미는 네트워크 장애, 하드웨어 오류, 잘못된 애플리케이션 사용 등 예기치 못한 상황에서도 데이터베이스는 올바르게 작동 하고 오류 없이 기능한다는 것을 보장하는 것을 말한다.
      그리고 복잡한 데이터 관계나 여러 애플리케이션이 동일한 데이터베이스에 액세스하는 경우 특히 효과적이다. 그러나
      구현과 관리가 더 복잡할 수 있고, 성능에 더 큰 영향을 미칠 수 있다.
  • ORM 레이어의 락과 데이터베이스 레이어의 락 중 어떤 것이 나은지는 애플리케이션의 특정 요구 사항에 따라 다를 것 같다.

찾은 해결방안 적용

ORM lock은 애플리케이션 레밸에서 구현이 되고, 데이터의 lock을 얻고, 해제 하는 행위를 ORM에 의존을 해야한다.
그리고 ORM lock은 데이터베이스 lock과 유사한 기능을 제공하지만, 데이터를 먼저 데이터베이스에서 검색한 다음 잠금을 획득해야 하기 때문에 성능이나 신뢰성이 부족하다.
이와 같은 추가적인 프로세스는 overhead를 추가하고 race condition을 야기하기 때문에 ORM lock은 오버부킹을 해결하는데 적합하지 않다.

결과

결국은 exclusive lock을 사용하면 된다.

그러므로

    @Lock(value = LockModeType.PESSIMISTIC_WRITE)

을 사용해주면 되겠다.

728x90

최근에 프로젝트를 하고 있는데 배포를할 때 NCP(네이버 클라우드 플랫폼)에서 진행했다. 

네이버 클라우드에서 여러가지 기술을 사용해보았다. 그 중에서 기록 해놓고 싶은 것들을 "적용기"로 기록해두었다. 그 글들을 네이버 클라우드 공식 블로그에서 인용을 했다. 정말 뿌듯했다 🥹 

 

https://m.blog.naver.com/n_cloudplatform/223006590728
https://m.blog.naver.com/n_cloudplatform/223013853228

 

728x90

프로젝트 내용 및 결과물

https://github.com/f-lab-edu/SSKA

 

GitHub - f-lab-edu/SSKA: 스터디 카페 운영 서비스 입니다.

스터디 카페 운영 서비스 입니다. Contribute to f-lab-edu/SSKA development by creating an account on GitHub.

github.com

 

사용한 NCP 서비스

  • SourceCommit
  • SourceBuild
  • SourceDeploy
  • SourcePipeline
  • Cloud DB for MySQL
  • Pinpoint Cloud
  • Auto Scaling
  • Load Balancer
  • Server
  • Object Storage
  • FileSafer

 

Ncloud 사용 중 느낀 점 (좋았던 점, 바라는 점 등)

처음에 제공된 크레딧으로 많은 기능들을 사용해 볼 수 있었다. 아마 2년 전쯤 AWS로 간단하게 배포한 경험이 있었는데 그때의 기억을 되새겨 보면 AWS는 UI가 투박스럽다고 느낀 기억이 있다. 네이버 클라우드는 내가 한국인이라 네이버를 많이 애용해서 그런지 모르겠으나 친근한 UI이고 UX또한 좋아서 이것저것 설정하는데 한결 편했다.

 

그리고 공식문서가 너무 잘 되어 있어서 꼼꼼히 잘 읽으면서 필요한 기능들을 설정하니 모든 기능들을 잘 적용할 수 있었다. 이번에 NCP 클라우드 환경 설정을 하면서 블로그를 거의 찾아보지 않았던 것 같다.

 

그러나 깜짝 놀랬던점은 FileSafer라는 기능이 있는데 이 기능에서 약 하루만에 9만8천원이 나가버렸다ㅠㅠ SourceCommit에 푸시한 코드들이 바이러스가 없는지 검사해주는 기능이어서 좋아보여서 설정을 해두었는데 돈이 너무 많이나가 버렸다. 피같은 내 돈...아무리 크레딧이지만 나한테는 정말 귀했다.. 10만원, 30만원 크레딧이 있었는데 10만원 크레딧이 다 소진 되었다고 아침에 문자가 와서 어안이 벙벙하여 NCP 크레딧 현황을 봤는데 너무 허무했다. 그치만 9만8천원에 인생공부 했다고 생각했다. 개발도 인생에 포함이 되니 인생 공부라고 하겠다.

MySQL 서버를 띄었는데 돈이 너무너무 많이 나갔다. 하루에 거의 2만원쯤 나갔나..? 기억이 안난다. 그래서 바로 디비 인스턴스를 내린 기억이 있다. 지금도 핀포인트랑 디비 성능 테스트할 때만 디비 인스턴스 올려서 테스트 하고있다.

 

 

프로젝트를 진행하며 재밌었던 점

이번 SKKA 프로젝트를 하며 다양하게 로직을 구현 해보기도 하고, Restful 하게 API도 만들어보고 객체지향을 빡세게 적용 시켜보기도 하고 클라우드 환경 구성과 CI/CD 적용을 하는 등 정말 다양하게 많이 해보았다. 특히 재미있었던 부분이 객체지향적인 설계였다. 코딩을 하면서 "집청소"하는 느낌이 든 적은 이번이 처음이었다. 난잡하고 가독성이 떨어지면서 객체들의 역할을 생각하며 코딩을 했다. 처음에 Service 코드에 로직을 구성하고 리팩토링 작업을 시작하면서 각각의 도메인 객체가 맡은 역할을 생각하여 비즈니스 로직으로 집어 넣는 작업들이 재미있었다. 마치 어릴 때 좋아했고 지금도 좋아하지만 하지 못하고 직업을 갖고 하려고 하는 레고조립 같았다.

 

 

프로젝트를 진행하며 어려웠던 점

스터디카페 예약 시스템을 구축하는 단계에서 검증 해야 하는 케이스가 생각 할수록 계속 나왔다. 그래서 총 9가지가 나왔었다. 이것을 검증하려고 몇일을 고민했던 것 같다.

프로젝트 wiki에 트러블슈팅들은 써 놓았다.(https://github.com/f-lab-edu/SSKA/wiki/04.-Trouble-Shooting)

 

 

프로젝트를 진행하며 아쉬웠던 점

작년 인턴 생활을 했을 때 알람 도메인을 맡아서 개발한 경험을 살려 푸시알람도 멋있게 개발해보고싶다는 아쉬움이 남았다.. 추후 붙여볼 예정이다.

 

 

사용한 기술 스택

 

 

앞으로 Ncloud를 어떻게 활용할지

앞으로 많은 프로젝트에서도 많이 사용될 것 같다. 특히 좀 더 전문적으로 핀포인트를 사용해서 애플리케이션을 더 개선해보고싶은 마음이 많다. 그리고 이번에는 VPC 환경이었다면 다음에는 classic 모드로 클라우드 환경을 조성해 볼 예정이다.

+ Recent posts